r10656: BIG merge from trunk. Features not copied over
authorGerald Carter <jerry@samba.org>
Fri, 30 Sep 2005 17:13:37 +0000 (17:13 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 16:04:48 +0000 (11:04 -0500)
* \PIPE\unixinfo
* winbindd's {group,alias}membership new functions
* winbindd's lookupsids() functionality
* swat (trunk changes to be reverted as per discussion with Deryck)
(This used to be commit 939c3cb5d78e3a2236209b296aa8aba8bdce32d3)

261 files changed:
examples/LDAP/samba.schema
source3/Makefile.in
source3/auth/auth.c
source3/auth/auth_domain.c
source3/auth/auth_ntlmssp.c
source3/auth/auth_util.c
source3/auth/auth_winbind.c
source3/client/mount.cifs.c
source3/client/smbspool.c
source3/configure.in
source3/groupdb/mapping.c
source3/include/ads.h
source3/include/asn_1.h
source3/include/authdata.h
source3/include/client.h
source3/include/dlinklist.h
source3/include/doserr.h
source3/include/includes.h
source3/include/messages.h
source3/include/module.h
source3/include/ntdomain.h
source3/include/ntlmssp.h
source3/include/passdb.h
source3/include/printing.h
source3/include/rpc_client.h
source3/include/rpc_dce.h
source3/include/rpc_dfs.h
source3/include/rpc_ds.h
source3/include/rpc_eventlog.h
source3/include/rpc_lsa.h
source3/include/rpc_misc.h
source3/include/rpc_netlogon.h
source3/include/rpc_ntsvcs.h [new file with mode: 0644]
source3/include/rpc_perfcount.h [new file with mode: 0644]
source3/include/rpc_perfcount_defs.h [new file with mode: 0644]
source3/include/rpc_reg.h
source3/include/rpc_samr.h
source3/include/rpc_secdes.h
source3/include/rpc_svcctl.h
source3/include/smb.h
source3/include/smb_ldap.h [new file with mode: 0644]
source3/include/smb_share_modes.h
source3/include/smbldap.h
source3/include/spnego.h
source3/include/srvstr.h
source3/lib/account_pol.c
source3/lib/arc4.c [new file with mode: 0644]
source3/lib/data_blob.c
source3/lib/debug.c
source3/lib/dmallocmsg.c
source3/lib/gencache.c
source3/lib/genrand.c
source3/lib/messages.c
source3/lib/module.c
source3/lib/pidfile.c
source3/lib/privileges.c
source3/lib/smbldap.c
source3/lib/smbldap_util.c
source3/lib/smbrun.c
source3/lib/tallocmsg.c
source3/lib/time.c
source3/lib/util.c
source3/libads/authdata.c
source3/libads/kerberos_verify.c
source3/libads/ldap.c
source3/libads/ldap_printer.c
source3/libads/sasl.c
source3/libsmb/cliconnect.c
source3/libsmb/clidgram.c
source3/libsmb/clientgen.c
source3/libsmb/clierror.c
source3/libsmb/clikrb5.c
source3/libsmb/clireadwrite.c
source3/libsmb/clispnego.c
source3/libsmb/clitrans.c
source3/libsmb/credentials.c
source3/libsmb/errormap.c
source3/libsmb/libsmb_compat.c
source3/libsmb/libsmbclient.c
source3/libsmb/ntlmssp.c
source3/libsmb/ntlmssp_parse.c
source3/libsmb/ntlmssp_sign.c
source3/libsmb/passchange.c
source3/libsmb/pwd_cache.c
source3/libsmb/smb_share_modes.c
source3/libsmb/smbdes.c
source3/libsmb/smbencrypt.c
source3/libsmb/smberr.c
source3/libsmb/spnego.c
source3/libsmb/trusts_util.c
source3/locking/brlock.c
source3/locking/locking.c
source3/modules/weird.c
source3/nmbd/asyncdns.c
source3/nmbd/nmbd.c
source3/nmbd/nmbd_elections.c
source3/nmbd/nmbd_packets.c
source3/nmbd/nmbd_synclists.c
source3/nmbd/nmbd_winsserver.c
source3/nsswitch/wb_common.c
source3/nsswitch/wbinfo.c
source3/nsswitch/winbindd.c
source3/nsswitch/winbindd.h
source3/nsswitch/winbindd_ads.c
source3/nsswitch/winbindd_async.c
source3/nsswitch/winbindd_cache.c
source3/nsswitch/winbindd_cm.c
source3/nsswitch/winbindd_dual.c
source3/nsswitch/winbindd_group.c
source3/nsswitch/winbindd_misc.c
source3/nsswitch/winbindd_nss.h
source3/nsswitch/winbindd_pam.c
source3/pam_smbpass/pam_smb_auth.c
source3/param/loadparm.c
source3/passdb/lookup_sid.c
source3/passdb/passdb.c
source3/passdb/pdb_get_set.c
source3/passdb/pdb_interface.c
source3/passdb/pdb_ldap.c
source3/passdb/pdb_nds.c
source3/passdb/pdb_smbpasswd.c
source3/passdb/secrets.c
source3/passdb/util_sam_sid.c
source3/printing/notify.c
source3/printing/print_cups.c
source3/printing/print_generic.c
source3/printing/print_iprint.c
source3/printing/printing.c
source3/printing/printing_db.c
source3/profile/profile.c
source3/registry/reg_db.c
source3/registry/reg_dynamic.c
source3/registry/reg_eventlog.c
source3/registry/reg_frontend.c
source3/registry/reg_objects.c
source3/registry/reg_perfcount.c [new file with mode: 0644]
source3/registry/reg_printing.c
source3/registry/reg_util.c
source3/registry/regfio.c
source3/rpc_client/cli_dfs.c
source3/rpc_client/cli_ds.c
source3/rpc_client/cli_echo.c
source3/rpc_client/cli_lsarpc.c
source3/rpc_client/cli_netlogon.c
source3/rpc_client/cli_pipe.c
source3/rpc_client/cli_reg.c
source3/rpc_client/cli_samr.c
source3/rpc_client/cli_shutdown.c
source3/rpc_client/cli_spoolss.c
source3/rpc_client/cli_spoolss_notify.c
source3/rpc_client/cli_srvsvc.c
source3/rpc_client/cli_svcctl.c
source3/rpc_client/cli_wkssvc.c
source3/rpc_parse/parse_buffer.c
source3/rpc_parse/parse_dfs.c
source3/rpc_parse/parse_ds.c
source3/rpc_parse/parse_echo.c
source3/rpc_parse/parse_eventlog.c
source3/rpc_parse/parse_misc.c
source3/rpc_parse/parse_net.c
source3/rpc_parse/parse_ntsvcs.c [new file with mode: 0644]
source3/rpc_parse/parse_prs.c
source3/rpc_parse/parse_reg.c
source3/rpc_parse/parse_rpc.c
source3/rpc_parse/parse_samr.c
source3/rpc_parse/parse_svcctl.c
source3/rpc_server/srv_eventlog.c
source3/rpc_server/srv_eventlog_nt.c
source3/rpc_server/srv_lsa_hnd.c
source3/rpc_server/srv_lsa_nt.c
source3/rpc_server/srv_netlog_nt.c
source3/rpc_server/srv_ntsvcs.c [new file with mode: 0644]
source3/rpc_server/srv_ntsvcs_nt.c [new file with mode: 0644]
source3/rpc_server/srv_pipe.c
source3/rpc_server/srv_pipe_hnd.c
source3/rpc_server/srv_reg.c
source3/rpc_server/srv_reg_nt.c
source3/rpc_server/srv_samr_nt.c
source3/rpc_server/srv_samr_util.c
source3/rpc_server/srv_spoolss_nt.c
source3/rpc_server/srv_srvsvc_nt.c
source3/rpc_server/srv_svcctl.c
source3/rpc_server/srv_svcctl_nt.c
source3/rpcclient/cmd_dfs.c
source3/rpcclient/cmd_ds.c
source3/rpcclient/cmd_echo.c
source3/rpcclient/cmd_lsarpc.c
source3/rpcclient/cmd_netlogon.c
source3/rpcclient/cmd_samr.c
source3/rpcclient/cmd_spoolss.c
source3/rpcclient/cmd_srvsvc.c
source3/rpcclient/cmd_test.c [new file with mode: 0644]
source3/rpcclient/cmd_wkssvc.c
source3/rpcclient/rpcclient.c
source3/rpcclient/rpcclient.h
source3/sam/idmap_rid.c
source3/sam/idmap_smbldap.c [new file with mode: 0644]
source3/script/installman.sh
source3/script/installswat.sh
source3/script/mkproto.awk
source3/script/tests/functions
source3/script/tests/t_001.sh
source3/services/services_db.c
source3/services/svc_netlogon.c [new file with mode: 0644]
source3/services/svc_rcinit.c
source3/services/svc_spoolss.c
source3/services/svc_winreg.c [new file with mode: 0644]
source3/smbd/blocking.c
source3/smbd/change_trust_pw.c
source3/smbd/chgpasswd.c
source3/smbd/close.c
source3/smbd/conn.c
source3/smbd/connection.c
source3/smbd/error.c
source3/smbd/files.c
source3/smbd/mangle_hash2.c
source3/smbd/message.c
source3/smbd/nttrans.c
source3/smbd/open.c
source3/smbd/oplock.c
source3/smbd/oplock_irix.c
source3/smbd/oplock_linux.c
source3/smbd/process.c
source3/smbd/reply.c
source3/smbd/server.c
source3/smbd/sesssetup.c
source3/smbd/trans2.c
source3/tdb/tdbdump.c
source3/tdb/tdbtool.c
source3/tdb/tdbutil.c
source3/torture/locktest2.c
source3/torture/mangle_test.c
source3/torture/msgtest.c
source3/torture/t_asn1.c [new file with mode: 0644]
source3/torture/t_strappend.c [new file with mode: 0644]
source3/torture/torture.c
source3/torture/vfstest.c
source3/utils/log2pcaphex.c
source3/utils/net.c
source3/utils/net.h
source3/utils/net_ads.c
source3/utils/net_rpc.c
source3/utils/net_rpc_join.c
source3/utils/net_rpc_printer.c
source3/utils/net_rpc_registry.c
source3/utils/net_rpc_rights.c
source3/utils/net_rpc_samsync.c
source3/utils/net_rpc_service.c
source3/utils/net_status.c
source3/utils/ntlm_auth.c
source3/utils/pdbedit.c
source3/utils/smbcacls.c
source3/utils/smbcontrol.c
source3/utils/smbcquotas.c
source3/utils/status.c
source3/utils/testparm.c
source3/web/diagnose.c
source3/web/neg_lang.c
source3/web/startstop.c
source3/web/statuspage.c
source3/web/swat.c

index 2205c17309510238aeb36aa6f5c87ef558f01c93..daf4588ead5383b0a8217dc5f56b7ff2d860df57 100644 (file)
@@ -389,16 +389,68 @@ attributetype ( 1.3.6.1.4.1.7165.2.1.53 NAME 'sambaTrustFlags'
        EQUALITY caseIgnoreIA5Match
        SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
 
-attributetype ( 1.3.6.1.4.1.7165.2.1.56 NAME 'sambaAccountPolicyName'
-       DESC 'Account Policy Name'
-       EQUALITY caseIgnoreMatch
-       SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{255} SINGLE-VALUE )
+# "min password length"
+attributetype ( 1.3.6.1.4.1.7165.2.1.58 NAME 'sambaMinPwdLength'
+       DESC 'Minimal password length (default: 5)'
+       EQUALITY integerMatch
+       SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
 
-attributetype ( 1.3.6.1.4.1.7165.2.1.57 NAME 'sambaAccountPolicyValue'
-       DESC 'Account Policy Value'
+# "password history"
+attributetype ( 1.3.6.1.4.1.7165.2.1.59 NAME 'sambaPwdHistoryLength'
+       DESC 'Length of Password History Entries (default: 0 => off)'
        EQUALITY integerMatch
        SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
 
+# "user must logon to change password"
+attributetype ( 1.3.6.1.4.1.7165.2.1.60 NAME 'sambaLogonToChgPwd'
+       DESC 'Force Users to logon for password change (default: 0 => off, 2 => on)'
+       EQUALITY integerMatch
+       SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+# "maximum password age"
+attributetype ( 1.3.6.1.4.1.7165.2.1.61 NAME 'sambaMaxPwdAge'
+       DESC 'Maximum password age, in seconds (default: -1 => never expire passwords)'
+       EQUALITY integerMatch
+       SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+# "minimum password age"
+attributetype ( 1.3.6.1.4.1.7165.2.1.62 NAME 'sambaMinPwdAge'
+       DESC 'Minimum password age, in seconds (default: 0 => allow immediate password change)'
+       EQUALITY integerMatch
+       SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+# "lockout duration"
+attributetype ( 1.3.6.1.4.1.7165.2.1.63 NAME 'sambaLockoutDuration'
+       DESC 'Lockout duration in minutes (default: 30, -1 => forever)'
+       EQUALITY integerMatch
+       SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+# "reset count minutes"
+attributetype ( 1.3.6.1.4.1.7165.2.1.64 NAME 'sambaLockoutObservationWindow'
+       DESC 'Reset time after lockout in minutes (default: 30)'
+       EQUALITY integerMatch
+       SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+# "bad lockout attempt"
+attributetype ( 1.3.6.1.4.1.7165.2.1.65 NAME 'sambaLockoutThreshold'
+       DESC 'Lockout users after bad logon attempts (default: 0 => off)'
+       EQUALITY integerMatch
+       SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+# "disconnect time"
+attributetype ( 1.3.6.1.4.1.7165.2.1.66 NAME 'sambaForceLogoff'
+       DESC 'Disconnect Users outside logon hours (default: -1 => off, 0 => on)'
+       EQUALITY integerMatch
+       SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+# "refuse machine password change"
+attributetype ( 1.3.6.1.4.1.7165.2.1.67 NAME 'sambaRefuseMachinePwdChange'
+       DESC 'Allow Machine Password changes (default: 0 => off)'
+       EQUALITY integerMatch
+       SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+
+
 
 #######################################################################
 ##              objectClasses used by Samba 3.0 schema               ##
@@ -448,7 +500,11 @@ objectclass ( 1.3.6.1.4.1.7165.2.2.5 NAME 'sambaDomain' SUP top STRUCTURAL
        MUST ( sambaDomainName $ 
               sambaSID ) 
        MAY ( sambaNextRid $ sambaNextGroupRid $ sambaNextUserRid $
-             sambaAlgorithmicRidBase ) )
+             sambaAlgorithmicRidBase $ 
+             sambaMinPwdLength $ sambaPwdHistoryLength $ sambaLogonToChgPwd $
+             sambaMaxPwdAge $ sambaMinPwdAge $
+             sambaLockoutDuration $ sambaLockoutObservationWindow $ sambaLockoutThreshold $
+             sambaForceLogoff $ sambaRefuseMachinePwdChange ))
 
 ##
 ## used for idmap_ldap module
@@ -488,9 +544,3 @@ objectclass ( 1.3.6.1.4.1.7165.2.2.12 NAME 'sambaConfigOption' SUP top STRUCTURA
 ##     DESC 'Samba Privilege'
 ##     MUST ( sambaSID )
 ##     MAY ( sambaPrivilegeList ) )
-
-objectclass ( 1.3.6.1.4.1.7165.2.2.15 NAME 'sambaAccountPolicy' SUP top STRUCTURAL
-       DESC 'Samba Account Policy'
-       MUST ( sambaAccountPolicyName $ sambaAccountPolicyValue )
-       MAY ( description ) )
-
index 95457758a650eb88de1f6324b2d1bf26fb11fc67..07c348bd84e598f34177c145737a7914d7489550 100644 (file)
@@ -63,6 +63,7 @@ RPCLIBDIR = $(LIBDIR)/rpc
 IDMAPLIBDIR = $(LIBDIR)/idmap
 CHARSETLIBDIR = $(LIBDIR)/charset
 AUTHLIBDIR = $(LIBDIR)/auth
+CONFIGLIBDIR = $(LIBDIR)/config
 CONFIGDIR = @configdir@
 VARDIR = @localstatedir@
 MANDIR = @mandir@
@@ -101,8 +102,7 @@ LIBSMBSHAREMODES=bin/libsmbsharemodes.a @LIBSMBSHAREMODES_SHARED@
 LIBSMBSHAREMODES_MAJOR=0
 LIBSMBSHAREMODES_MINOR=1
 
-
-FLAGS1 = $(CFLAGS) @FLAGS1@ -Iinclude -I$(srcdir)/include -I$(srcdir)/ubiqx @SMBWRAP_INC@ -I. $(CPPFLAGS) -I$(srcdir) -I$(srcdir)/tdb
+FLAGS1 = $(CFLAGS) @FLAGS1@ -Iinclude -I$(srcdir)/include -I$(srcdir)/ubiqx -I$(srcdir)/tdb @SMBWRAP_INC@ -I. $(CPPFLAGS) -I$(srcdir)
 FLAGS2 = 
 FLAGS3 = 
 FLAGS4 = 
@@ -199,12 +199,12 @@ LIB_OBJ = $(VERSION_OBJ) lib/charcnv.o lib/debug.o lib/fault.o \
          lib/talloc.o lib/substitute.o lib/fsusage.o \
          lib/ms_fnmatch.o lib/select.o lib/messages.o \
          lib/tallocmsg.o lib/dmallocmsg.o libsmb/smb_signing.o \
-         lib/md5.o lib/hmacmd5.o lib/iconv.o \
+         lib/md5.o lib/hmacmd5.o lib/arc4.o lib/iconv.o \
          nsswitch/wb_client.o $(WBCOMMON_OBJ) \
-         lib/pam_errors.o intl/lang_tdb.o lib/account_pol.o \
+         lib/pam_errors.o intl/lang_tdb.o \
          lib/adt_tree.o lib/gencache.o $(TDB_OBJ) \
          lib/module.o lib/ldap_escape.o @CHARSET_STATIC@ \
-         lib/privileges.o lib/secdesc.o lib/secace.o lib/secacl.o @SOCKWRAP@
+         lib/secdesc.o lib/secace.o lib/secacl.o @SOCKWRAP@
 
 LIB_DUMMY_OBJ = lib/dummysmbd.o lib/dummyroot.o
 LIB_NONSMBD_OBJ = $(LIB_OBJ) $(LIB_DUMMY_OBJ)
@@ -256,13 +256,13 @@ LIBMSRPC_OBJ = rpc_client/cli_lsarpc.o rpc_client/cli_samr.o \
               rpc_client/cli_reg.o $(RPC_CLIENT_OBJ) \
               rpc_client/cli_spoolss.o rpc_client/cli_spoolss_notify.o  \
               rpc_client/cli_ds.o rpc_client/cli_echo.o \
-              rpc_client/cli_shutdown.o rpc_client/cli_svcctl.o
+              rpc_client/cli_shutdown.o rpc_client/cli_svcctl.o 
 
 REGOBJS_OBJ = registry/reg_objects.o
 
 REGISTRY_OBJ = registry/reg_frontend.o registry/reg_cachehook.o registry/reg_printing.o \
                registry/reg_db.o registry/reg_eventlog.o registry/reg_shares.o \
-               registry/reg_util.o registry/reg_dynamic.o
+               registry/reg_util.o registry/reg_dynamic.o registry/reg_perfcount.o
 
 RPC_LSA_OBJ = rpc_server/srv_lsa.o rpc_server/srv_lsa_nt.o
 
@@ -282,7 +282,10 @@ RPC_SVC_OBJ = rpc_server/srv_srvsvc.o rpc_server/srv_srvsvc_nt.o
 RPC_WKS_OBJ =  rpc_server/srv_wkssvc.o rpc_server/srv_wkssvc_nt.o
 
 RPC_SVCCTL_OBJ =  rpc_server/srv_svcctl.o rpc_server/srv_svcctl_nt.o \
-                  services/svc_spoolss.o services/svc_rcinit.o services/services_db.o
+                  services/svc_spoolss.o services/svc_rcinit.o services/services_db.o \
+                  services/svc_netlogon.o services/svc_winreg.o
+
+RPC_NTSVCS_OBJ = rpc_server/srv_ntsvcs.o rpc_server/srv_ntsvcs_nt.o
 
 RPC_DFS_OBJ =  rpc_server/srv_dfs.o rpc_server/srv_dfs_nt.o
 
@@ -308,7 +311,8 @@ RPC_PARSE_OBJ = rpc_parse/parse_lsa.o rpc_parse/parse_net.o \
                rpc_parse/parse_spoolss.o rpc_parse/parse_dfs.o \
                rpc_parse/parse_echo.o rpc_parse/parse_shutdown.o \
                rpc_parse/parse_svcctl.o \
-               rpc_parse/parse_eventlog.o rpc_parse/parse_buffer.o $(REGOBJS_OBJ)
+               rpc_parse/parse_eventlog.o rpc_parse/parse_buffer.o \
+                rpc_parse/parse_ntsvcs.o $(REGOBJS_OBJ)
 
 RPC_CLIENT_OBJ = rpc_client/cli_pipe.o
 
@@ -320,7 +324,7 @@ PASSDB_OBJ = $(PASSDB_GET_SET_OBJ) passdb/passdb.o passdb/pdb_interface.o \
                passdb/util_sam_sid.o passdb/pdb_compat.o \
                passdb/lookup_sid.o \
                passdb/login_cache.o @PDB_STATIC@ passdb/pdb_sql.o \
-               lib/system_smbd.o
+               lib/system_smbd.o lib/account_pol.o lib/privileges.o
 
 XML_OBJ = passdb/pdb_xml.o
 MYSQL_OBJ = passdb/pdb_mysql.o
@@ -414,8 +418,7 @@ PRINTING_OBJ = printing/pcap.o printing/print_svid.o printing/print_aix.o \
                printing/print_iprint.o
 
 PRINTBASE_OBJ = printing/notify.o printing/printing_db.o
-
-PRINTBACKEND_OBJ = printing/printing.o printing/nt_printing.o $(PRINTBASE_OBJ)
+PRINTBACKEND_OBJ = printing/printing.o printing/nt_printing.o $(PRINTBASE_OBJ) 
 
 SMBD_OBJ = $(SMBD_OBJ_BASE) $(SMBD_OBJ_MAIN)
 NMBD_OBJ1 = nmbd/asyncdns.o nmbd/nmbd.o nmbd/nmbd_become_dmb.o \
@@ -432,7 +435,7 @@ NMBD_OBJ1 = nmbd/asyncdns.o nmbd/nmbd.o nmbd/nmbd_become_dmb.o \
             nmbd/nmbd_workgroupdb.o nmbd/nmbd_synclists.o
 
 NMBD_OBJ = $(NMBD_OBJ1) $(PARAM_OBJ) $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) $(UBIQX_OBJ) \
-           $(PROFILE_OBJ) $(LIB_NONSMBD_OBJ) $(SECRETS_OBJ) $(POPT_LIB_OBJ) 
+           $(PROFILE_OBJ) $(LIB_NONSMBD_OBJ) $(SECRETS_OBJ) $(POPT_LIB_OBJ)
 
 WREPL_OBJ1 = wrepld/server.o wrepld/process.o wrepld/parser.o wrepld/socket.o \
              wrepld/partners.o
@@ -487,7 +490,8 @@ RPCCLIENT_OBJ1 = rpcclient/rpcclient.o rpcclient/cmd_lsarpc.o \
                 rpcclient/cmd_netlogon.o rpcclient/cmd_srvsvc.o \
                 rpcclient/cmd_dfs.o rpcclient/cmd_reg.o \
                 rpcclient/display_sec.o rpcclient/cmd_ds.o \
-                rpcclient/cmd_echo.o rpcclient/cmd_shutdown.o
+                rpcclient/cmd_echo.o rpcclient/cmd_shutdown.o \
+                rpcclient/cmd_test.o 
 
 RPCCLIENT_OBJ = $(RPCCLIENT_OBJ1) \
              $(PARAM_OBJ) $(LIBSMB_OBJ) $(LIB_NONSMBD_OBJ) \
@@ -521,11 +525,6 @@ LIBSMBCLIENT_OBJ = libsmb/libsmbclient.o libsmb/libsmb_compat.o \
 
 LIBSMBSHAREMODES_OBJ = libsmb/smb_share_modes.o tdb/tdb.o tdb/spinlock.o
 
-CAC_OBJ = $(LIBSMBCLIENT_OBJ) \
-          libmsrpc/libmsrpc.o libmsrpc/libmsrpc_internal.o \
-          libmsrpc/cac_lsarpc.o libmsrpc/cac_winreg.o libmsrpc/cac_samr.o \
-          libmsrpc/cac_svcctl.o
-
 # This shared library is intended for linking with unit test programs
 # to test Samba internals.  It's called libbigballofmud.so to
 # discourage casual usage.
@@ -561,7 +560,7 @@ NET_OBJ = $(NET_OBJ1) $(PARAM_OBJ) $(SECRETS_OBJ) $(LIBSMB_OBJ) \
          $(LIBMSRPC_OBJ) $(IDMAP_OBJ) \
          $(LIBADS_OBJ) $(LIBADS_SERVER_OBJ) $(POPT_LIB_OBJ) \
          $(SMBLDAP_OBJ) $(DCUTIL_OBJ) $(SERVER_MUTEX_OBJ) \
-         $(AFS_OBJ) $(AFS_SETTOKEN_OBJ) $(PRINTERDB_OBJ) $(REGFIO_OBJ)
+         $(AFS_OBJ) $(AFS_SETTOKEN_OBJ) $(REGFIO_OBJ)
 
 CUPS_OBJ = client/smbspool.o $(PARAM_OBJ) $(LIBSMB_OBJ) \
          $(LIB_NONSMBD_OBJ) $(KRBCLIENT_OBJ) $(SECRETS_OBJ)
@@ -644,7 +643,8 @@ PROTO_OBJ = $(SMBD_OBJ_MAIN) \
            $(RPC_LSA_OBJ) $(RPC_NETLOG_OBJ) $(RPC_SAMR_OBJ) $(RPC_REG_OBJ) $(RPC_LSA_DS_OBJ) \
            $(RPC_SVC_OBJ) $(RPC_WKS_OBJ) $(RPC_DFS_OBJ) $(RPC_SPOOLSS_OBJ) \
            $(RPC_ECHO_OBJ) $(RPC_SVCCTL_OBJ) $(RPC_EVENTLOG_OBJ) $(SMBLDAP_OBJ) \
-            $(IDMAP_OBJ) libsmb/spnego.o $(PASSCHANGE_OBJ)
+            $(IDMAP_OBJ) libsmb/spnego.o $(PASSCHANGE_OBJ) \
+            $(RPC_NTSVCS_OBJ)
 
 WINBIND_WINS_NSS_OBJ = nsswitch/wins.o $(PARAM_OBJ) \
        $(LIBSMB_OBJ) $(LIB_NONSMBD_OBJ) $(NSSWINS_OBJ) $(KRBCLIENT_OBJ)
@@ -655,8 +655,6 @@ PICOBJS = $(SMBWRAPPER_OBJ:.o=.@PICSUFFIX@)
 LIBSMBCLIENT_PICOBJS = $(LIBSMBCLIENT_OBJ:.o=.@PICSUFFIX@)
 LIBSMBSHAREMODES_PICOBJS = $(LIBSMBSHAREMODES_OBJ:.o=.@PICSUFFIX@)
 
-CAC_PICOBJS = $(CAC_OBJ:.o=.@PICSUFFIX@)
-
 PAM_SMBPASS_OBJ_0 = pam_smbpass/pam_smb_auth.o pam_smbpass/pam_smb_passwd.o \
                pam_smbpass/pam_smb_acct.o pam_smbpass/support.o \
                $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) $(PASSDB_OBJ) $(GROUPDB_OBJ) \
@@ -715,7 +713,7 @@ NTLM_AUTH_OBJ = ${NTLM_AUTH_OBJ1} $(LIBSAMBA_OBJ) $(POPT_LIB_OBJ) \
                libsmb/asn1.o libsmb/spnego.o libsmb/clikrb5.o libads/kerberos.o \
                libads/kerberos_verify.o $(SECRETS_OBJ) $(SERVER_MUTEX_OBJ) \
                libads/authdata.o $(RPC_PARSE_OBJ0) $(PASSDB_OBJ) $(GROUPDB_OBJ) \
-               $(SMBLDAP_OBJ) $(DOSERR_OBJ)
+               $(SMBLDAP_OBJ) $(DOSERR_OBJ) rpc_parse/parse_net.o
 
 ######################################################################
 # now the rules...
@@ -760,9 +758,7 @@ wins : SHOWFLAGS @WINBIND_WINS_NSS@
 
 modules: SHOWFLAGS proto_exists $(MODULES)
 
-cac: SHOWFLAGS bin/libmsrpc.@SHLIBEXT@ bin/libmsrpc.a
-
-everything: all libsmbclient debug2html smbfilter talloctort modules torture cac \
+everything: all libsmbclient debug2html smbfilter talloctort modules torture \
        $(EVERYTHING_PROGS)
 
 .SUFFIXES:
@@ -1045,16 +1041,6 @@ bin/libsmbsharemodes.a: $(LIBSMBSHAREMODES_PICOBJS)
        @echo Linking libsmbsharemodes non-shared library $@
        @-$(AR) -rc $@ $(LIBSMBSHAREMODES_PICOBJS)
 
-bin/libmsrpc.@SHLIBEXT@: $(CAC_PICOBJS)
-       @echo Linking libmsrpc shared library $@
-       @$(SHLD) $(LDSHFLAGS) -o $@ $(CAC_PICOBJS) $(LDFLAGS) $(LIBS) \
-       @SONAMEFLAG@`basename $@`
-
-bin/libmsrpc.a: $(CAC_PICOBJS)
-       @echo Linking libmsrpc non-shared library $@
-       @-$(AR) -rc $@ $(CAC_PICOBJS)
-
-
 # This is probably wrong for anything other than the GNU linker. 
 bin/libbigballofmud.@SHLIBEXT@: $(LIBBIGBALLOFMUD_PICOBJS)
        @echo Linking bigballofmud shared library $@
@@ -1091,6 +1077,11 @@ bin/librpc_svcctl.@SHLIBEXT@: $(RPC_SVCCTL_OBJ)
        @$(SHLD) $(LDSHFLAGS) -o $@ $(RPC_SVCCTL_OBJ) -lc \
                @SONAMEFLAG@`basename $@`
 
+bin/librpc_ntsvcs.@SHLIBEXT@: $(RPC_NTSVCS_OBJ)
+       @echo "Linking $@"
+       @$(SHLD) $(LDSHFLAGS) -o $@ $(RPC_NTSVCS_OBJ) -lc \
+               @SONAMEFLAG@`basename $@`
+
 bin/librpc_wkssvc.@SHLIBEXT@: $(RPC_WKS_OBJ)
        @echo "Linking $@"
        @$(SHLD) $(LDSHFLAGS) -o $@ $(RPC_WKS_OBJ) -lc \
@@ -1328,6 +1319,9 @@ bin/pam_smbpass.@SHLIBEXT@: $(PAM_SMBPASS_PICOOBJ)
        @echo "Linking shared library $@"
        @$(SHLD) $(LDSHFLAGS) -o $@ $(PAM_SMBPASS_PICOOBJ) -lpam $(DYNEXP) $(LIBS) -lc $(LDAP_LIBS) $(KRB5LIBS)
 
+bin/libmsrpc.a: $(LIBMSRPC_PICOBJ)
+       @-$(AR) -rc $@ $(LIBMSRPC_PICOBJ) 
+
 bin/tdbbackup@EXEEXT@: $(TDBBACKUP_OBJ) bin/.dummy
        @echo Linking $@
        @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(LDFLAGS) $(DYNEXP) $(LIBS) $(TDBBACKUP_OBJ) @SOCKWRAP@
@@ -1346,6 +1340,9 @@ bin/t_strcmp@EXEEXT@: bin/libbigballofmud.@SHLIBEXT@ torture/t_strcmp.o
 bin/t_strstr@EXEEXT@: bin/libbigballofmud.@SHLIBEXT@ torture/t_strstr.o
        $(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(DYNEXP) $(LIBS) torture/t_strstr.o -L ./bin -lbigballofmud
 
+bin/t_strappend@EXEEXT@: bin/libbigballofmud.@SHLIBEXT@ torture/t_strappend.o
+       $(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(DYNEXP) $(LIBS) torture/t_strappend.o -L ./bin -lbigballofmud
+
 bin/t_stringoverflow@EXEEXT@: bin/libbigballofmud.@SHLIBEXT@ torture/t_stringoverflow.o
        $(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(DYNEXP) torture/t_stringoverflow.o -L./bin -lbigballofmud
 
@@ -1634,7 +1631,7 @@ Makefile: $(srcdir)/Makefile.in config.status
 # These are called by the test suite and need to be built before
 # running it.  For the time being we don't build all of BIN_PROGS,
 # because they're not all needed.
-check-programs: bin/t_strcmp bin/t_strstr bin/t_push_ucs2 bin/smbcontrol bin/t_snprintf
+# check-programs: bin/t_strcmp bin/t_strstr bin/t_push_ucs2 bin/smbcontrol bin/t_snprintf bin/t_asn1
 
 #test: all
 #      @if test -z "$(SMB4TORTURE)"; then \
index 9886526cf96328fea79ee806e3c0984ac95a89cb..92c90b62410577c615b5daf007a9fafd5a4d2c97 100644 (file)
@@ -235,7 +235,7 @@ static NTSTATUS check_ntlm_password(const struct auth_context *auth_context,
 
 #ifdef DEBUG_PASSWORD
        DEBUG(100, ("user_info has passwords of length %d and %d\n", 
-                   user_info->lm_resp.length, user_info->nt_resp.length));
+                   (int)user_info->lm_resp.length, (int)user_info->nt_resp.length));
        DEBUG(100, ("lm:\n"));
        dump_data(100, user_info->lm_resp.data, user_info->lm_resp.length);
        DEBUG(100, ("nt:\n"));
index cdf87adebb980c23b57695288ab93e6cb4e3e5d4..4abc6c6656044e31863e138a099007789f9d4ead 100644 (file)
@@ -40,15 +40,17 @@ extern BOOL global_machine_password_needs_changing;
  *
  **/
 
-static NTSTATUS connect_to_domain_password_server(struct cli_state **cli, 
-                                                 const char *domain, const char *dc_name,
-                                                 struct in_addr dc_ip, 
-                                                 const char *setup_creds_as,
-                                                 uint16 sec_chan,
-                                                 const unsigned char *trust_passwd,
-                                                 BOOL *retry)
+static NTSTATUS connect_to_domain_password_server(struct cli_state **cli,
+                                               const char *domain,
+                                               const char *dc_name,
+                                               struct in_addr dc_ip, 
+                                               struct rpc_pipe_client **pipe_ret,
+                                               BOOL *retry)
 {
         NTSTATUS result;
+       struct rpc_pipe_client *netlogon_pipe = NULL;
+
+       *pipe_ret = NULL;
 
        /* TODO: Send a SAMLOGON request to determine whether this is a valid
           logonserver.  We can avoid a 30-second timeout if the DC is down
@@ -64,8 +66,9 @@ static NTSTATUS connect_to_domain_password_server(struct cli_state **cli,
         * ACCESS_DENIED errors if 2 auths are done from the same machine. JRA.
         */
 
-       if (!grab_server_mutex(dc_name))
+       if (!grab_server_mutex(dc_name)) {
                return NT_STATUS_NO_LOGON_SERVERS;
+       }
        
        /* Attempt connection */
        *retry = True;
@@ -95,36 +98,65 @@ static NTSTATUS connect_to_domain_password_server(struct cli_state **cli,
         * into account also. This patch from "Bjart Kvarme" <bjart.kvarme@usit.uio.no>.
         */
 
-       if(cli_nt_session_open(*cli, PI_NETLOGON) == False) {
+       /* open the netlogon pipe. */
+       if (lp_client_schannel()) {
+               /* We also setup the creds chain in the open_schannel call. */
+               netlogon_pipe = cli_rpc_pipe_open_schannel(*cli, PI_NETLOGON,
+                                       PIPE_AUTH_LEVEL_PRIVACY, domain, &result);
+       } else {
+               netlogon_pipe = cli_rpc_pipe_open_noauth(*cli, PI_NETLOGON, &result);
+       }
+
+       if(!netlogon_pipe) {
                DEBUG(0,("connect_to_domain_password_server: unable to open the domain client session to \
-machine %s. Error was : %s.\n", dc_name, cli_errstr(*cli)));
-               cli_nt_session_close(*cli);
-               cli_ulogoff(*cli);
+machine %s. Error was : %s.\n", dc_name, nt_errstr(result)));
                cli_shutdown(*cli);
                release_server_mutex();
-               return NT_STATUS_NO_LOGON_SERVERS;
+               return result;
        }
 
-       fstr_sprintf((*cli)->mach_acct, "%s$", setup_creds_as);
-
-       /* This must be the remote domain (not ours) for schannel */
-
-       fstrcpy( (*cli)->domain, domain ); 
+       if (!lp_client_schannel()) {
+               /* We need to set up a creds chain on an unauthenticated netlogon pipe. */
+               uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS;
+               uint32 sec_chan_type = 0;
+               char machine_pwd[16];
+
+               if (!get_trust_pw(domain, machine_pwd, &sec_chan_type)) {
+                       DEBUG(0, ("connect_to_domain_password_server: could not fetch "
+                       "trust account password for domain '%s'\n",
+                               domain));
+                       cli_shutdown(*cli);
+                       release_server_mutex();
+                       return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
+               }
 
-       result = cli_nt_establish_netlogon(*cli, sec_chan, trust_passwd);
+               result = rpccli_netlogon_setup_creds(netlogon_pipe,
+                                       dc_name,
+                                       domain,
+                                       global_myname(),
+                                       machine_pwd,
+                                       sec_chan_type,
+                                       &neg_flags);
+
+               if (!NT_STATUS_IS_OK(result)) {
+                       cli_shutdown(*cli);
+                       release_server_mutex();
+                       return result;
+               }
+       }
 
-        if (!NT_STATUS_IS_OK(result)) {
-               DEBUG(0,("connect_to_domain_password_server: unable to setup the NETLOGON credentials to machine \
-%s. Error was : %s.\n", dc_name, nt_errstr(result)));
-               cli_nt_session_close(*cli);
-               cli_ulogoff(*cli);
+       if(!netlogon_pipe) {
+               DEBUG(0,("connect_to_domain_password_server: unable to open the domain client session to \
+machine %s. Error was : %s.\n", dc_name, cli_errstr(*cli)));
                cli_shutdown(*cli);
                release_server_mutex();
-               return result;
+               return NT_STATUS_NO_LOGON_SERVERS;
        }
 
        /* We exit here with the mutex *locked*. JRA */
 
+       *pipe_ret = netlogon_pipe;
+
        return NT_STATUS_OK;
 }
 
@@ -135,18 +167,17 @@ machine %s. Error was : %s.\n", dc_name, cli_errstr(*cli)));
 ************************************************************************/
 
 static NTSTATUS domain_client_validate(TALLOC_CTX *mem_ctx,
-                                      const auth_usersupplied_info *user_info, 
-                                      const char *domain,
-                                      uchar chal[8],
-                                      auth_serversupplied_info **server_info, 
-                                      const char *dc_name, struct in_addr dc_ip,
-                                      const char *setup_creds_as,
-                                      uint16 sec_chan,
-                                      unsigned char trust_passwd[16],
-                                      time_t last_change_time)
+                                       const auth_usersupplied_info *user_info, 
+                                       const char *domain,
+                                       uchar chal[8],
+                                       auth_serversupplied_info **server_info, 
+                                       const char *dc_name,
+                                       struct in_addr dc_ip)
+
 {
        NET_USER_INFO_3 info3;
        struct cli_state *cli = NULL;
+       struct rpc_pipe_client *netlogon_pipe = NULL;
        NTSTATUS nt_status = NT_STATUS_NO_LOGON_SERVERS;
        int i;
        BOOL retry = True;
@@ -162,8 +193,12 @@ static NTSTATUS domain_client_validate(TALLOC_CTX *mem_ctx,
        /* rety loop for robustness */
        
        for (i = 0; !NT_STATUS_IS_OK(nt_status) && retry && (i < 3); i++) {
-               nt_status = connect_to_domain_password_server(&cli, domain, dc_name, 
-                       dc_ip, setup_creds_as, sec_chan, trust_passwd, &retry);
+               nt_status = connect_to_domain_password_server(&cli,
+                                                       domain,
+                                                       dc_name,
+                                                       dc_ip,
+                                                       &netlogon_pipe,
+                                                       &retry);
        }
 
        if ( !NT_STATUS_IS_OK(nt_status) ) {
@@ -181,13 +216,19 @@ static NTSTATUS domain_client_validate(TALLOC_CTX *mem_ctx,
          * in the info3 structure.  
          */
 
-       nt_status = cli_netlogon_sam_network_logon(cli, mem_ctx,
-               NULL, user_info->smb_name.str, user_info->domain.str, 
-               user_info->wksta_name.str, chal, user_info->lm_resp, 
-               user_info->nt_resp, &info3);
-        
-       /* let go as soon as possible so we avoid any potential deadlocks
-          with winbind lookup up users or groups */
+       nt_status = rpccli_netlogon_sam_network_logon(netlogon_pipe,
+                                       mem_ctx,
+                                       dc_name,                   /* server name */
+                                       user_info->smb_name.str,   /* user name logging on. */
+                                       user_info->domain.str,     /* domain name */
+                                       user_info->wksta_name.str, /* workstation name */
+                                       chal,                      /* 8 byte challenge. */
+                                       user_info->lm_resp,        /* lanman 24 byte response */
+                                       user_info->nt_resp,        /* nt 24 byte response */
+                                       &info3);                   /* info3 out */
+
+       /* Let go as soon as possible so we avoid any potential deadlocks
+          with winbind lookup up users or groups. */
           
        release_server_mutex();
 
@@ -195,7 +236,7 @@ static NTSTATUS domain_client_validate(TALLOC_CTX *mem_ctx,
                DEBUG(0,("domain_client_validate: unable to validate password "
                          "for user %s in domain %s to Domain controller %s. "
                          "Error was %s.\n", user_info->smb_name.str,
-                         user_info->domain.str, cli->srv_name_slash
+                         user_info->domain.str, dc_name
                          nt_errstr(nt_status)));
 
                /* map to something more useful */
@@ -203,32 +244,18 @@ static NTSTATUS domain_client_validate(TALLOC_CTX *mem_ctx,
                        nt_status = NT_STATUS_NO_LOGON_SERVERS;
                }
        } else {
-               nt_status = make_server_info_info3(mem_ctx, user_info->internal_username.str, 
-                                                  user_info->smb_name.str, domain, server_info, &info3);
+               nt_status = make_server_info_info3(mem_ctx,
+                                               user_info->internal_username.str, 
+                                               user_info->smb_name.str,
+                                               domain,
+                                               server_info,
+                                               &info3);
        }
 
-#if 0
-       /* 
-        * We don't actually need to do this - plus it fails currently with
-        * NT_STATUS_INVALID_INFO_CLASS - we need to know *exactly* what to
-        * send here. JRA.
-        */
-
-       if (NT_STATUS_IS_OK(status)) {
-               if(cli_nt_logoff(&cli, &ctr) == False) {
-                       DEBUG(0,("domain_client_validate: unable to log off user %s in domain \
-%s to Domain controller %s. Error was %s.\n", user, domain, dc_name, cli_errstr(&cli)));        
-                       nt_status = NT_STATUS_LOGON_FAILURE;
-               }
-       }
-#endif /* 0 */
-
        /* Note - once the cli stream is shutdown the mem_ctx used
           to allocate the other_sids and gids structures has been deleted - so
           these pointers are no longer valid..... */
 
-       cli_nt_session_close(cli);
-       cli_ulogoff(cli);
        cli_shutdown(cli);
        return nt_status;
 }
@@ -244,10 +271,7 @@ static NTSTATUS check_ntdomain_security(const struct auth_context *auth_context,
                                        auth_serversupplied_info **server_info)
 {
        NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE;
-       unsigned char trust_passwd[16];
-       time_t last_change_time;
        const char *domain = lp_workgroup();
-       uint32 sec_channel_type = 0;
        fstring dc_name;
        struct in_addr dc_ip;
 
@@ -273,26 +297,6 @@ static NTSTATUS check_ntdomain_security(const struct auth_context *auth_context,
                return NT_STATUS_NOT_IMPLEMENTED;
        }
 
-       /*
-        * Get the machine account password for our primary domain
-        * No need to become_root() as secrets_init() is done at startup.
-        */
-
-       if (!secrets_fetch_trust_account_password(domain, trust_passwd, &last_change_time, &sec_channel_type))
-       {
-               DEBUG(0, ("check_ntdomain_security: could not fetch trust account password for domain '%s'\n", domain));
-               return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
-       }
-
-       /* Test if machine password has expired and needs to be changed */
-       if (lp_machine_password_timeout()) {
-               if (last_change_time > 0 && 
-                   time(NULL) > (last_change_time + 
-                                 lp_machine_password_timeout())) {
-                       global_machine_password_needs_changing = True;
-               }
-       }
-
        /* we need our DC to send the net_sam_logon() request to */
 
        if ( !get_dc_name(domain, NULL, dc_name, &dc_ip) ) {
@@ -301,9 +305,13 @@ static NTSTATUS check_ntdomain_security(const struct auth_context *auth_context,
                return NT_STATUS_NO_LOGON_SERVERS;
        }
        
-       nt_status = domain_client_validate(mem_ctx, user_info, domain,
-               (uchar *)auth_context->challenge.data, server_info, dc_name, dc_ip,
-               global_myname(), sec_channel_type,trust_passwd, last_change_time);
+       nt_status = domain_client_validate(mem_ctx,
+                                       user_info,
+                                       domain,
+                                       (uchar *)auth_context->challenge.data,
+                                       server_info,
+                                       dc_name,
+                                       dc_ip);
                
        return nt_status;
 }
@@ -357,7 +365,7 @@ static NTSTATUS check_trustdomain_security(const struct auth_context *auth_conte
        /* No point is bothering if this is not a trusted domain.
           This return makes "map to guest = bad user" work again.
           The logic is that if we know nothing about the domain, that
-          user is known to us and does not exist */
+          user is not known to us and does not exist */
        
        if ( !is_trusted_domain( user_info->domain.str ) )
                return NT_STATUS_NOT_IMPLEMENTED;
@@ -367,8 +375,8 @@ static NTSTATUS check_trustdomain_security(const struct auth_context *auth_conte
         * No need to become_root() as secrets_init() is done at startup.
         */
 
-       if (!secrets_fetch_trusted_domain_password(user_info->domain.str, &trust_password, &sid, &last_change_time))
-       {
+       if (!secrets_fetch_trusted_domain_password(user_info->domain.str, &trust_password,
+                               &sid, &last_change_time)) {
                DEBUG(0, ("check_trustdomain_security: could not fetch trust account password for domain %s\n", user_info->domain.str));
                return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
        }
@@ -396,9 +404,13 @@ static NTSTATUS check_trustdomain_security(const struct auth_context *auth_conte
                return NT_STATUS_NO_LOGON_SERVERS;
        }
        
-       nt_status = domain_client_validate(mem_ctx, user_info, user_info->domain.str,
-               (uchar *)auth_context->challenge.data, server_info, dc_name, dc_ip,
-               lp_workgroup(), SEC_CHAN_DOMAIN, trust_md4_password, last_change_time);
+       nt_status = domain_client_validate(mem_ctx,
+                                       user_info,
+                                       user_info->domain.str,
+                                       (uchar *)auth_context->challenge.data,
+                                       server_info,
+                                       dc_name,
+                                       dc_ip);
 
        return nt_status;
 }
index 11d9aa09c4c4992ca8b47199b841fa82f438533a..738af73f49691d3287c36c9135d48cabee1901cf 100644 (file)
@@ -114,13 +114,15 @@ static NTSTATUS auth_ntlmssp_check_password(struct ntlmssp_state *ntlmssp_state,
                return nt_status;
        }
        if (auth_ntlmssp_state->server_info->user_session_key.length) {
-               DEBUG(10, ("Got NT session key of length %u\n", auth_ntlmssp_state->server_info->user_session_key.length));
+               DEBUG(10, ("Got NT session key of length %u\n",
+                       (unsigned int)auth_ntlmssp_state->server_info->user_session_key.length));
                *user_session_key = data_blob_talloc(auth_ntlmssp_state->mem_ctx, 
                                                   auth_ntlmssp_state->server_info->user_session_key.data,
                                                   auth_ntlmssp_state->server_info->user_session_key.length);
        }
        if (auth_ntlmssp_state->server_info->lm_session_key.length) {
-               DEBUG(10, ("Got LM session key of length %u\n", auth_ntlmssp_state->server_info->lm_session_key.length));
+               DEBUG(10, ("Got LM session key of length %u\n",
+                       (unsigned int)auth_ntlmssp_state->server_info->lm_session_key.length));
                *lm_session_key = data_blob_talloc(auth_ntlmssp_state->mem_ctx, 
                                                   auth_ntlmssp_state->server_info->lm_session_key.data,
                                                   auth_ntlmssp_state->server_info->lm_session_key.length);
index 6624631b53dd5c5df1153abb787d55c779212d2c..194a1ad532da432dd8a917e9363eca49ff89104f 100644 (file)
@@ -372,7 +372,7 @@ BOOL make_user_info_for_reply(auth_usersupplied_info **user_info,
                unsigned char local_lm_response[24];
                
 #ifdef DEBUG_PASSWORD
-               DEBUG(10,("Unencrypted password (len %d):\n",plaintext_password.length));
+               DEBUG(10,("Unencrypted password (len %d):\n",(int)plaintext_password.length));
                dump_data(100, plaintext_password.data, plaintext_password.length);
 #endif
 
@@ -640,6 +640,44 @@ NT_USER_TOKEN *create_nt_token(uid_t uid, gid_t gid, int ngroups, gid_t *groups,
        return token;
 }
 
+/******************************************************************************
+ Create a token for the root user to be used internally by smbd.
+ This is similar to running under the context of the LOCAL_SYSTEM account
+ in Windows.  This is a read-only token.  Do not modify it or free() it.
+ Create a copy if your need to change it.
+******************************************************************************/
+
+NT_USER_TOKEN *get_root_nt_token( void )
+{
+       static NT_USER_TOKEN *token = NULL;
+       DOM_SID u_sid, g_sid;
+       DOM_SID g_sids[1];
+       struct passwd *pw;
+       NTSTATUS result;
+       
+       if ( token )
+               return token;
+               
+       if ( !(pw = getpwnam( "root" )) ) {
+               DEBUG(0,("create_root_nt_token: getpwnam\"root\") failed!\n"));
+               return NULL;
+       }
+       
+       /* get the user and primary group SIDs; although the 
+          BUILTIN\Administrators SId is really the one that matters here */
+          
+       if ( !NT_STATUS_IS_OK(uid_to_sid(&u_sid, pw->pw_uid)) )
+               return NULL;
+       if ( !NT_STATUS_IS_OK(gid_to_sid(&g_sid, pw->pw_gid)) )
+               return NULL;
+               
+       sid_copy( &g_sids[0], &global_sid_Builtin_Administrators );
+       
+       result = create_nt_user_token( &u_sid, &g_sid, 1, g_sids, False, &token);
+       
+       return NT_STATUS_IS_OK(result) ? token : NULL;
+}
+
 /******************************************************************************
  * this function returns the groups (SIDs) of the local SAM the user is in.
  * If this samba server is a DC of the domain the user belongs to, it returns 
@@ -831,6 +869,61 @@ NTSTATUS make_server_info_sam(auth_serversupplied_info **server_info,
        return nt_status;
 }
 
+/***************************************************************************
+ Make (and fill) a user_info struct from a Kerberos PAC logon_info by conversion 
+ to a SAM_ACCOUNT
+***************************************************************************/
+
+NTSTATUS make_server_info_pac(auth_serversupplied_info **server_info, 
+                             char *unix_username,
+                             struct passwd *pwd,
+                             PAC_LOGON_INFO *logon_info)
+{
+       NTSTATUS nt_status;
+       SAM_ACCOUNT *sampass = NULL;
+       DOM_SID user_sid, group_sid;
+       fstring dom_name;
+
+       if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam_pw(&sampass, pwd))) {             
+               return nt_status;
+       }
+       if (!NT_STATUS_IS_OK(nt_status = make_server_info(server_info))) {
+               return nt_status;
+       }
+
+       /* only copy user_sid, group_sid and domain name out of the PAC for
+        * now, we will benefit from more later - Guenther */
+
+       sid_copy(&user_sid, &logon_info->info3.dom_sid.sid);
+       sid_append_rid(&user_sid, logon_info->info3.user_rid);
+       pdb_set_user_sid(sampass, &user_sid, PDB_SET);
+       
+       sid_copy(&group_sid, &logon_info->info3.dom_sid.sid);
+       sid_append_rid(&group_sid, logon_info->info3.group_rid);
+       pdb_set_group_sid(sampass, &group_sid, PDB_SET);
+
+       unistr2_to_ascii(dom_name, &logon_info->info3.uni_logon_dom, -1);
+       pdb_set_domain(sampass, dom_name, PDB_SET);
+
+       pdb_set_logon_count(sampass, logon_info->info3.logon_count, PDB_SET);
+
+       (*server_info)->sam_account    = sampass;
+
+       if (!NT_STATUS_IS_OK(nt_status = add_user_groups(server_info, unix_username,
+               sampass, pwd->pw_uid, pwd->pw_gid))) 
+       {
+               return nt_status;
+       }
+
+       (*server_info)->unix_name = smb_xstrdup(unix_username);
+
+       (*server_info)->sam_fill_level = SAM_FILL_ALL;
+       (*server_info)->uid = pwd->pw_uid;
+       (*server_info)->gid = pwd->pw_gid;
+       return nt_status;
+}
+
+
 /***************************************************************************
  Make (and fill) a user_info struct from a 'struct passwd' by conversion 
  to a SAM_ACCOUNT
index 3a81cba626d7655acc5f3a46cf89a6d77c53d314..0c263b6ab31bc60ef42a545727dbadbd65ae1b29 100644 (file)
@@ -38,7 +38,7 @@ static NTSTATUS get_info3_from_ndr(TALLOC_CTX *mem_ctx, struct winbindd_response
                }
                prs_copy_data_in(&ps, (char *)info3_ndr, len);
                prs_set_offset(&ps,0);
-               if (!net_io_user_info3("", info3, &ps, 1, 3)) {
+               if (!net_io_user_info3("", info3, &ps, 1, 3, False)) {
                        DEBUG(2, ("get_info3_from_ndr: could not parse info3 struct!\n"));
                        return NT_STATUS_UNSUCCESSFUL;
                }
index a6136a9e2c26cfb7f558db36f0f361c093a6180b..5750deb31ca82bf482743a78360645a891878719 100755 (executable)
@@ -39,7 +39,7 @@
 #include <fcntl.h>
 
 #define MOUNT_CIFS_VERSION_MAJOR "1"
-#define MOUNT_CIFS_VERSION_MINOR "9"
+#define MOUNT_CIFS_VERSION_MINOR "8"
 
 #ifndef MOUNT_CIFS_VENDOR_SUFFIX
 #define MOUNT_CIFS_VENDOR_SUFFIX ""
@@ -127,10 +127,8 @@ static int open_cred_file(char * file_name)
        if(fs == NULL)
                return errno;
        line_buf = malloc(4096);
-       if(line_buf == NULL) {
-               fclose(fs);
+       if(line_buf == NULL)
                return -ENOMEM;
-       }
 
        while(fgets(line_buf,4096,fs)) {
                /* parse line from credential file */
@@ -506,8 +504,6 @@ static int parse_options(char * options, int * filesys_flags)
                        *filesys_flags &= ~MS_NOSUID;
                } else if (strncmp(data, "nodev", 5) == 0) {
                        *filesys_flags |= MS_NODEV;
-               } else if (strncmp(data, "nobrl", 5) == 0) {
-                       *filesys_flags &= ~MS_MANDLOCK;
                } else if (strncmp(data, "dev", 3) == 0) {
                        *filesys_flags &= ~MS_NODEV;
                } else if (strncmp(data, "noexec", 6) == 0) {
@@ -574,15 +570,13 @@ static void check_for_comma(char ** ppasswrd)
        char *pass;
        int i,j;
        int number_of_commas = 0;
-       int len;
+       int len = strlen(*ppasswrd);
 
        if(ppasswrd == NULL)
                return;
        else 
                (pass = *ppasswrd);
 
-       len = strlen(pass);
-
        for(i=0;i<len;i++)  {
                if(pass[i] == ',')
                        number_of_commas++;
@@ -696,8 +690,9 @@ static char * parse_server(char ** punc_name)
        int length = strnlen(unc_name,1024);
        char * share;
        char * ipaddress_string = NULL;
-       struct hostent * host_entry;
+       struct hostent * host_entry = NULL;
        struct in_addr server_ipaddr;
+       int rc;
 
        if(length > 1023) {
                printf("mount error: UNC name too long");
@@ -720,13 +715,6 @@ static char * parse_server(char ** punc_name)
                        if(share) {
                                free_share_name = 1;
                                *punc_name = malloc(length+3);
-                               if(*punc_name == NULL) {
-                                       /* put the original string back  if 
-                                          no memory left */
-                                       *punc_name = unc_name;
-                                       return NULL;
-                               }
-                                       
                                *share = '/';
                                strncpy((*punc_name)+2,unc_name,length);
                                unc_name = *punc_name;
@@ -756,7 +744,8 @@ continue_unc_parsing:
                                        return NULL;
                                }
                                if(host_entry == NULL) {
-                                       printf("mount error: could not find target server. TCP name %s not found\n", unc_name);
+                                       printf("mount error: could not find target server. TCP name %s not found ", unc_name);
+                                       printf(" rc = %d\n",rc);
                                        return NULL;
                                } else {
                                        /* BB should we pass an alternate version of the share name as Unicode */
@@ -1029,9 +1018,6 @@ mount_retry:
                optlen = 0;
        if(share_name)
                optlen += strlen(share_name) + 4;
-       else {
-               printf("No server share name specified\n");
-       }
        if(user_name)
                optlen += strlen(user_name) + 6;
        if(ipaddr)
@@ -1140,6 +1126,8 @@ mount_retry:
                                        strcat(mountent.mnt_opts,"rw");
                                if(flags & MS_MANDLOCK)
                                        strcat(mountent.mnt_opts,",mand");
+                               else
+                                       strcat(mountent.mnt_opts,",nomand");
                                if(flags & MS_NOEXEC)
                                        strcat(mountent.mnt_opts,",noexec");
                                if(flags & MS_NOSUID)
index d13ae39416f45994677ee1e0247d72ff04c5726a..da517297f71b01b74c229b67685f3c8f4f02a90c 100644 (file)
@@ -70,6 +70,9 @@ static int            smb_print(struct cli_state *, char *, FILE *);
   FILE         *fp;            /* File to print */
   int          status=0;               /* Status of LPD job */
   struct cli_state *cli;       /* SMB interface */
+  char null_str[1];
+
+  null_str[0] = '\0';
 
   /* we expect the URI in argv[0]. Detect the case where it is in argv[1] and cope */
   if (argc > 2 && strncmp(argv[0],"smb://", 6) && !strncmp(argv[1],"smb://", 6)) {
@@ -158,12 +161,12 @@ static int                smb_print(struct cli_state *, char *, FILE *);
     if ((password = strchr_m(username, ':')) != NULL)
       *password++ = '\0';
     else
-      password = "";
+      password = null_str;
   }
   else
   {
-    username = "";
-    password = "";
+    username = null_str;
+    password = null_str;
     server   = uri + 6;
   }
 
@@ -335,10 +338,8 @@ char * get_ticket_cache( uid_t uid )
 
   if ( ticket_file == NULL )
   {
-#ifdef DEVELOPER
     /* no ticket cache found */
     fprintf(stderr, "ERROR: No ticket cache found for userid=%d\n", uid);
-#endif
     return NULL;
   }
 
index aeb3dd5d47992eb745a24eff2ffba323d08af420..deeab5886fea98154d0a1f953d510ed05e337fe5 100644 (file)
@@ -235,6 +235,7 @@ AC_SUBST(SMBWRAP_INC)
 AC_SUBST(EXTRA_BIN_PROGS)
 AC_SUBST(EXTRA_SBIN_PROGS)
 AC_SUBST(EXTRA_ALL_TARGETS)
+AC_SUBST(CONFIG_LIBS)
 
 # Set defaults
 PIE_CFLAGS=""
@@ -359,9 +360,9 @@ if test "$ac_cv_prog_gnu_ld" = "yes"; then
        changequote([,])dnl
        AC_MSG_RESULT(${ac_cv_gnu_ld_date})
         if test -n "$ac_cv_gnu_ld_date"; then
-           if test "$ac_cv_gnu_ld_date" -lt 20030217; then
-              ac_cv_gnu_ld_no_default_allow_shlib_undefined=yes
-           fi
+       if test "$ac_cv_gnu_ld_date" -lt 20030217; then
+               ac_cv_gnu_ld_no_default_allow_shlib_undefined=yes
+       fi
         else
            AC_MSG_CHECKING(GNU ld release version)
            changequote(,)dnl
@@ -457,10 +458,10 @@ DYNEXP=
 
 dnl Add modules that have to be built by default here
 dnl These have to be built static:
-default_static_modules="pdb_smbpasswd pdb_tdbsam rpc_lsa rpc_samr rpc_reg rpc_lsa_ds rpc_wks rpc_svcctl rpc_net rpc_dfs rpc_srv rpc_spoolss rpc_eventlog auth_rhosts auth_sam auth_unix auth_winbind auth_server auth_domain auth_builtin printerdb_file"
+default_static_modules="pdb_smbpasswd pdb_tdbsam rpc_lsa rpc_samr rpc_reg rpc_lsa_ds rpc_wks rpc_svcctl rpc_ntsvcs rpc_net rpc_dfs rpc_srv rpc_spoolss rpc_eventlog auth_rhosts auth_sam auth_unix auth_winbind auth_server auth_domain auth_builtin"
 
 dnl These are preferably build shared, and static if dlopen() is not available
-default_shared_modules="vfs_recycle vfs_audit vfs_extd_audit vfs_full_audit vfs_netatalk vfs_fake_perms vfs_default_quota vfs_readonly vfs_cap vfs_expand_msdfs vfs_shadow_copy charset_CP850 charset_CP437 auth_script"
+default_shared_modules="vfs_recycle vfs_audit vfs_extd_audit vfs_netatalk vfs_fake_perms vfs_default_quota vfs_readonly vfs_cap vfs_expand_msdfs vfs_shadow_copy charset_CP850 charset_CP437 auth_script"
 
 if test "x$developer" = xyes; then
    default_static_modules="$default_static_modules rpc_echo"
@@ -1990,14 +1991,14 @@ dnl For IA64 HPUX systems, the libs are located in lib/hpux32 instead of lib.
     for l in "lib32" "lib" "lib/hpux32"; do
         if test -d "$i/$l" ; then
                 LDFLAGS="$save_LDFLAGS -L$i/$l"
-                LIBS=
-                export LDFLAGS LIBS CPPFLAGS
+        LIBS=
+        export LDFLAGS LIBS CPPFLAGS
 dnl Try to find iconv(3)
                 jm_ICONV($i/$l)
                 if test x"$ICONV_FOUND" = "xyes" ; then
-                    libext="$l"
-                    break;
-                fi
+            libext="$l"
+            break;
+        fi
         fi
     done
 
@@ -2005,7 +2006,7 @@ dnl Try to find iconv(3)
        LDFLAGS=$save_LDFLAGS
         LIB_ADD_DIR(LDFLAGS, "$i/$libext")
         CFLAGS_ADD_DIR(CPPFLAGS, "$i/include")
-        LIBS="$save_LIBS"
+       LIBS="$save_LIBS"
         ICONV_LOCATION=$i
         export LDFLAGS LIBS CPPFLAGS
 dnl Now, check for a working iconv ... we want to do it here because
@@ -2820,6 +2821,7 @@ if test x"$with_ldap_support" != x"no"; then
   if test x"$ac_cv_lib_ext_ldap_ldap_init" = x"yes" -a x"$ac_cv_func_ext_ldap_domain2hostlist" = x"yes"; then
     AC_DEFINE(HAVE_LDAP,1,[Whether ldap is available])
     default_static_modules="$default_static_modules pdb_ldap idmap_ldap";
+    default_shared_modules="$default_shared_modules";
     SMBLDAP="lib/smbldap.o"
     SMBLDAPUTIL="lib/smbldap_util.o"
     with_ldap_support=yes
@@ -3048,9 +3050,77 @@ if test x"$with_ads_support" != x"no"; then
   AC_CHECK_FUNC_EXT(krb5_krbhst_get_addrinfo, $KRB5_LIBS)
   AC_CHECK_FUNC_EXT(krb5_c_enctype_compare, $KRB5_LIBS)
   AC_CHECK_FUNC_EXT(krb5_enctypes_compatible_keys, $KRB5_LIBS)
+  AC_CHECK_FUNC_EXT(krb5_crypto_init, $KRB5_LIBS)
+  AC_CHECK_FUNC_EXT(krb5_crypto_destroy, $KRB5_LIBS)
+  AC_CHECK_FUNC_EXT(krb5_decode_ap_req, $KRB5_LIBS)
+  AC_CHECK_FUNC_EXT(decode_krb5_ap_req, $KRB5_LIBS)
+  AC_CHECK_FUNC_EXT(krb5_free_ap_req, $KRB5_LIBS)
+  AC_CHECK_FUNC_EXT(free_AP_REQ, $KRB5_LIBS)
+  AC_CHECK_FUNC_EXT(krb5_c_verify_checksum, $KRB5_LIBS)
+  AC_CHECK_FUNC_EXT(krb5_principal_compare_any_realm, $KRB5_LIBS)
+  AC_CHECK_FUNC_EXT(krb5_parse_name_norealm, $KRB5_LIBS)
+  AC_CHECK_FUNC_EXT(krb5_princ_size, $KRB5_LIBS)
 
   LIBS="$KRB5_LIBS $LIBS"
-  
+
+  AC_CACHE_CHECK(whether krb5_verify_checksum takes 7 arguments, smb_krb5_verify_checksum, [
+    AC_TRY_COMPILE([
+       #include <krb5.h>], 
+       [krb5_verify_checksum(0, 0, 0, 0, 0, 0, 0);], 
+       [smb_krb5_verify_checksum=7], 
+       [smb_krb5_verify_checksum=6], 
+    ) 
+  ])
+  AC_DEFINE_UNQUOTED(KRB5_VERIFY_CHECKSUM_ARGS, $smb_krb5_verify_checksum, [Number of arguments to krb5_verify_checksum])
+
+  AC_CACHE_CHECK([for checksum in krb5_checksum],
+                samba_cv_HAVE_CHECKSUM_IN_KRB5_CHECKSUM,[
+    AC_TRY_COMPILE([#include <krb5.h>],
+      [krb5_checksum cksum; cksum.checksum.length = 0;],
+      samba_cv_HAVE_CHECKSUM_IN_KRB5_CHECKSUM=yes,
+      samba_cv_HAVE_CHECKSUM_IN_KRB5_CHECKSUM=no)])
+
+  if test x"$samba_cv_HAVE_CHECKSUM_IN_KRB5_CHECKSUM" = x"yes"; then
+    AC_DEFINE(HAVE_CHECKSUM_IN_KRB5_CHECKSUM,1,
+               [Whether the krb5_checksum struct has a checksum property])
+  fi
+
+  AC_CACHE_CHECK([for etype in EncryptedData],
+                samba_cv_HAVE_ETYPE_IN_ENCRYPTEDDATA,[
+    AC_TRY_COMPILE([#include <krb5.h>],
+      [EncryptedData edata; edata.etype = 0;],
+      samba_cv_HAVE_ETYPE_IN_ENCRYPTEDDATA=yes,
+      samba_cv_HAVE_ETYPE_IN_ENCRYPTEDDATA=no)])
+
+  if test x"$samba_cv_HAVE_ETYPE_IN_ENCRYPTEDDATA" = x"yes"; then
+    AC_DEFINE(HAVE_ETYPE_IN_ENCRYPTEDDATA,1,
+               [Whether the EncryptedData struct has a etype property])
+  fi
+
+  AC_CACHE_CHECK([for ticket pointer in krb5_ap_req],
+                samba_cv_HAVE_TICKET_POINTER_IN_KRB5_AP_REQ,[
+    AC_TRY_COMPILE([#include <krb5.h>],
+      [krb5_ap_req *ap_req; ap_req->ticket = NULL;],
+      samba_cv_HAVE_TICKET_POINTER_IN_KRB5_AP_REQ=yes,
+      samba_cv_HAVE_TICKET_POINTER_IN_KRB5_AP_REQ=no)])
+
+  if test x"$samba_cv_HAVE_TICKET_POINTER_IN_KRB5_AP_REQ" = x"yes"; then
+    AC_DEFINE(HAVE_TICKET_POINTER_IN_KRB5_AP_REQ,1,
+               [Whether the krb5_ap_req struct has a ticket pointer])
+  fi
+
+  AC_CACHE_CHECK([for krb5_crypto type],
+                samba_cv_HAVE_KRB5_CRYPTO,[
+    AC_TRY_COMPILE([#include <krb5.h>],
+      [krb5_crypto crypto;],
+      samba_cv_HAVE_KRB5_CRYPTO=yes,
+      samba_cv_HAVE_KRB5_CRYPTO=no)])
+
+  if test x"$samba_cv_HAVE_KRB5_CRYPTO" = x"yes"; then
+    AC_DEFINE(HAVE_KRB5_CRYPTO,1,
+               [Whether the type krb5_crypto exists])
+  fi
+
   AC_CACHE_CHECK([for krb5_encrypt_block type],
                 samba_cv_HAVE_KRB5_ENCRYPT_BLOCK,[
     AC_TRY_COMPILE([#include <krb5.h>],
@@ -3178,6 +3248,30 @@ if test x"$with_ads_support" != x"no"; then
              [Whether the KV5M_KEYTAB option is available])
   fi
 
+  AC_CACHE_CHECK([for KRB5_KU_OTHER_CKSUM],
+                 samba_cv_HAVE_KRB5_KU_OTHER_CKSUM,[
+    AC_TRY_COMPILE([#include <krb5.h>],
+      [krb5_keyusage usage = KRB5_KU_OTHER_CKSUM;],
+      samba_cv_HAVE_KRB5_KU_OTHER_CKSUM=yes,
+      samba_cv_HAVE_KRB5_KU_OTHER_CKSUM=no)])
+
+  if test x"$samba_cv_HAVE_KRB5_KU_OTHER_CKSUM" = x"yes"; then
+    AC_DEFINE(HAVE_KRB5_KU_OTHER_CKSUM,1,
+              [Whether KRB5_KU_OTHER_CKSUM is available])
+  fi
+  
+  AC_CACHE_CHECK([for KRB5_KEYUSAGE_APP_DATA_CKSUM],
+                 samba_cv_HAVE_KRB5_KEYUSAGE_APP_DATA_CKSUM,[
+    AC_TRY_COMPILE([#include <krb5.h>],
+      [krb5_keyusage usage = KRB5_KEYUSAGE_APP_DATA_CKSUM;],
+      samba_cv_HAVE_KRB5_KEYUSAGE_APP_DATA_CKSUM=yes,
+      samba_cv_HAVE_KRB5_KEYUSAGE_APP_DATA_CKSUM=no)])
+
+  if test x"$samba_cv_HAVE_KRB5_KEYUSAGE_APP_DATA_CKSUM" = x"yes"; then
+    AC_DEFINE(HAVE_KRB5_KEYUSAGE_APP_DATA_CKSUM,1,
+              [Whether KRB5_KEYUSAGE_APP_DATA_CKSUM is available])
+  fi
+
   AC_CACHE_CHECK([for the krb5_princ_component macro],
                 samba_cv_HAVE_KRB5_PRINC_COMPONENT,[
     AC_TRY_LINK([#include <krb5.h>],
@@ -3915,7 +4009,6 @@ AC_ARG_WITH(libsmbclient,
   INSTALLCLIENT=installclientlib
 )
 
-
 INSTALLCLIENTCMD_SH=:
 INSTALLCLIENTCMD_A=:
 INSTALLCLIENT=
@@ -3925,19 +4018,19 @@ AC_MSG_CHECKING(whether to build the libsmbsharemodes shared library)
 AC_ARG_WITH(libsmbsharemodes,
 [  --with-libsmbsharemodes     Build the libsmbsharemodes shared library (default=yes if shared libs supported)],
 [ case "$withval" in
-  no) 
+  no)
      AC_MSG_RESULT(no)
      ;;
   *)
      if test $BLDSHARED = true; then
         INSTALLCLIENTCMD_SH="\$(INSTALLCMD)"
-       ## build the static version of libsmbsharemodes as well
-       INSTALLCLIENTCMD_A="\$(INSTALLCMD)"
+        ## build the static version of libsmbsharemodes as well
+        INSTALLCLIENTCMD_A="\$(INSTALLCMD)"
         LIBSMBSHAREMODES_SHARED=bin/libsmbsharemodes.$SHLIBEXT
         LIBSMBSHAREMODES=libsmbsharemodes
         AC_MSG_RESULT(yes)
      else
-       enable_static=yes
+        enable_static=yes
         AC_MSG_RESULT(no shared library support -- will supply static library)
      fi
      if test $enable_static = yes; then
@@ -3965,7 +4058,6 @@ AC_ARG_WITH(libsmbsharemodes,
   INSTALLCLIENT=installclientlib
 )
 
-
 #################################################
 # these tests are taken from the GNU fileutils package
 AC_CHECKING(how to get filesystem space usage)
@@ -4951,11 +5043,13 @@ SMB_MODULE(pdb_tdbsam, passdb/pdb_tdb.o, "bin/tdbsam.$SHLIBEXT", PDB)
 SMB_MODULE(pdb_guest, passdb/pdb_guest.o, "bin/guest.$SHLIBEXT", PDB)
 SMB_SUBSYSTEM(PDB,passdb/pdb_interface.o)
 
+
 SMB_MODULE(rpc_lsa, \$(RPC_LSA_OBJ), "bin/librpc_lsarpc.$SHLIBEXT", RPC)
 SMB_MODULE(rpc_reg, \$(RPC_REG_OBJ), "bin/librpc_winreg.$SHLIBEXT", RPC)
 SMB_MODULE(rpc_lsa_ds, \$(RPC_LSA_DS_OBJ), "bin/librpc_lsa_ds.$SHLIBEXT", RPC)
 SMB_MODULE(rpc_wks, \$(RPC_WKS_OBJ), "bin/librpc_wkssvc.$SHLIBEXT", RPC)
 SMB_MODULE(rpc_svcctl, \$(RPC_SVCCTL_OBJ), "bin/librpc_svcctl.$SHLIBEXT", RPC)
+SMB_MODULE(rpc_ntsvcs, \$(RPC_NTSVCS_OBJ), "bin/librpc_ntsvcs.$SHLIBEXT", RPC)
 SMB_MODULE(rpc_net, \$(RPC_NETLOG_OBJ), "bin/librpc_NETLOGON.$SHLIBEXT", RPC)
 SMB_MODULE(rpc_dfs, \$(RPC_DFS_OBJ), "bin/librpc_netdfs.$SHLIBEXT", RPC)
 SMB_MODULE(rpc_srv, \$(RPC_SVC_OBJ), "bin/librpc_srvsvc.$SHLIBEXT", RPC)
index a30e8eed784c7be4f4f7f7997ac5a3ec90a649d5..3ca074581c13440abc9ffdb5731afbc1475fb953 100644 (file)
@@ -2,7 +2,7 @@
  *  Unix SMB/CIFS implementation.
  *  RPC Pipe client / server routines
  *  Copyright (C) Andrew Tridgell              1992-2000,
- *  Copyright (C) Jean François Micouleau      1998-2001.
+ *  Copyright (C) Jean François Micouleau      1998-2001.
  *  
  *  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
@@ -365,7 +365,7 @@ static BOOL get_group_map_from_ntname(const char *name, GROUP_MAP *map)
  Remove a group mapping entry.
 ****************************************************************************/
 
-static BOOL group_map_remove(DOM_SID sid)
+static BOOL group_map_remove(const DOM_SID *sid)
 {
        TDB_DATA kbuf, dbuf;
        pstring key;
@@ -378,7 +378,7 @@ static BOOL group_map_remove(DOM_SID sid)
 
        /* the key is the SID, retrieving is direct */
 
-       sid_to_string(string_sid, &sid);
+       sid_to_string(string_sid, sid);
        slprintf(key, sizeof(key), "%s%s", GROUP_PREFIX, string_sid);
 
        kbuf.dptr = key;
@@ -954,7 +954,6 @@ BOOL get_group_from_gid(gid_t gid, GROUP_MAP *map)
        return True;
 }
 
-
 /****************************************************************************
  Create a UNIX group on demand.
 ****************************************************************************/
@@ -988,8 +987,8 @@ int smb_create_group(char *unix_group, gid_t *new_gid)
                        close(fd);
                }
 
-       } 
-       
+       }
+
        if (*new_gid == 0) {
                struct group *grp = getgrnam(unix_group);
 
@@ -1018,7 +1017,7 @@ int smb_delete_group(char *unix_group)
                DEBUG(ret ? 0 : 3,("smb_delete_group: Running the command `%s' gave %d\n",del_script,ret));
                return ret;
        }
-
+               
        return -1;
 }
 
@@ -1131,7 +1130,7 @@ NTSTATUS pdb_default_update_group_mapping_entry(struct pdb_methods *methods,
 NTSTATUS pdb_default_delete_group_mapping_entry(struct pdb_methods *methods,
                                                   DOM_SID sid)
 {
-       return group_map_remove(sid) ?
+       return group_map_remove(&sid) ?
                NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
 }
 
@@ -1173,18 +1172,12 @@ NTSTATUS pdb_default_create_alias(struct pdb_methods *methods,
        if (lookup_name(get_global_sam_name(), name, &sid, &type))
                return NT_STATUS_ALIAS_EXISTS;
 
-       if (!winbind_allocate_rid(&new_rid))
+       if (!winbind_allocate_rid_and_gid(&new_rid, &gid))
                return NT_STATUS_ACCESS_DENIED;
 
        sid_copy(&sid, get_global_sam_sid());
        sid_append_rid(&sid, new_rid);
 
-       /* Here we allocate the gid */
-       if (!winbind_sid_to_gid(&gid, &sid)) {
-               DEBUG(0, ("Could not get gid for new RID\n"));
-               return NT_STATUS_ACCESS_DENIED;
-       }
-
        map.gid = gid;
        sid_copy(&map.sid, &sid);
        map.sid_name_use = SID_NAME_ALIAS;
@@ -1282,7 +1275,7 @@ NTSTATUS pdb_default_alias_memberships(struct pdb_methods *methods,
                return result;
 
        *alias_rids = TALLOC_ARRAY(mem_ctx, uint32, num_alias_sids);
-       if ((alias_sids != 0) && (*alias_rids == NULL))
+       if (*alias_rids == NULL)
                return NT_STATUS_NO_MEMORY;
 
        *num_alias_rids = 0;
@@ -1347,3 +1340,38 @@ NTSTATUS pdb_nop_enum_group_mapping(struct pdb_methods *methods,
        return NT_STATUS_UNSUCCESSFUL;
 }
 
+/****************************************************************************
+ These need to be redirected through pdb_interface.c
+****************************************************************************/
+BOOL pdb_get_dom_grp_info(const DOM_SID *sid, struct acct_info *info)
+{
+       GROUP_MAP map;
+       BOOL res;
+
+       become_root();
+       res = get_domain_group_from_sid(*sid, &map);
+       unbecome_root();
+
+       if (!res)
+               return False;
+
+       fstrcpy(info->acct_name, map.nt_name);
+       fstrcpy(info->acct_desc, map.comment);
+       sid_peek_rid(sid, &info->rid);
+       return True;
+}
+
+BOOL pdb_set_dom_grp_info(const DOM_SID *sid, const struct acct_info *info)
+{
+       GROUP_MAP map;
+
+       if (!get_domain_group_from_sid(*sid, &map))
+               return False;
+
+       fstrcpy(map.nt_name, info->acct_name);
+       fstrcpy(map.comment, info->acct_desc);
+
+       return pdb_update_group_mapping_entry(&map);
+}
+
+
index 8f6cc6e582b4b8e2cbe3b41bce20ca27c197974e..d2eeaab4d8488ad94ca88d6362585e50efc57568 100644 (file)
@@ -130,7 +130,7 @@ typedef void **ADS_MODLIST;
 #define UF_UNUSED_5                            0x00800000
 
 #define UF_UNUSED_6                            0x01000000
-#define UF_UNUSED_7                            0x02000000
+#define UF_NO_AUTH_DATA_REQUIRED               0x02000000
 #define UF_UNUSED_8                            0x04000000
 #define UF_UNUSED_9                            0x08000000
 
index 796c8bb7404e94e9127936f5406847451cf1bd88..63a18c4923041c2a1d0b8e5ffaa43c8199c2d2f6 100644 (file)
@@ -27,7 +27,7 @@ struct nesting {
        struct nesting *next;
 };
 
-typedef struct {
+typedef struct asn1_data {
        uint8 *data;
        size_t length;
        off_t ofs;
@@ -37,13 +37,16 @@ typedef struct {
 
 
 #define ASN1_APPLICATION(x) ((x)+0x60)
+#define ASN1_APPLICATION_SIMPLE(x) ((x)+0x40)
 #define ASN1_SEQUENCE(x) ((x)+0x30)
 #define ASN1_CONTEXT(x) ((x)+0xa0)
+#define ASN1_CONTEXT_SIMPLE(x) ((x)+0x80)
 #define ASN1_GENERAL_STRING 0x1b
 #define ASN1_OCTET_STRING 0x4
 #define ASN1_OID 0x6
 #define ASN1_BOOLEAN 0x1
 #define ASN1_INTEGER 0x2
+#define ASN1_BITFIELD 0x3
 #define ASN1_ENUMERATED 0xa
 #define ASN1_SET 0x31
 
index 1be127aaac6b543011a52e0246216e30e7885164..194429ab673c446c19d261dfb7b6e962f95ebc20 100644 (file)
 #define _AUTHDATA_H 
 
 #include "rpc_misc.h"
+#include "rpc_netlogon.h"
 
 #define PAC_TYPE_LOGON_INFO 1
 #define PAC_TYPE_SERVER_CHECKSUM 6
 #define PAC_TYPE_PRIVSVR_CHECKSUM 7
 #define PAC_TYPE_LOGON_NAME 10
 
+#ifndef KRB5_AUTHDATA_WIN2K_PAC
+#define KRB5_AUTHDATA_WIN2K_PAC 128
+#endif
+
+#ifndef KRB5_AUTHDATA_IF_RELEVANT
+#define KRB5_AUTHDATA_IF_RELEVANT 1
+#endif
+
+
 typedef struct pac_logon_name {
        NTTIME logon_time;
        uint16 len;
@@ -37,7 +47,7 @@ typedef struct pac_logon_name {
 
 typedef struct pac_signature_data {
        uint32 type;
-       uint8 *signature;
+       RPC_DATA_BLOB signature; /* this not the on-wire-format (!) */
 } PAC_SIGNATURE_DATA;
 
 typedef struct group_membership {
@@ -50,6 +60,8 @@ typedef struct group_membership_array {
        GROUP_MEMBERSHIP *group_membership;
 } GROUP_MEMBERSHIP_ARRAY;
 
+#if 0 /* Unused, replaced by NET_USER_INFO_3 - Guenther */
+
 typedef struct krb_sid_and_attrs {
        uint32 sid_ptr;
        uint32 attrs;
@@ -82,7 +94,7 @@ typedef struct pac_logon_info {
        UNIHDR hdr_dir_drive;   
 
        uint16 logon_count; /* number of times user has logged onto domain */
-       uint16 reserved12;
+       uint16 bad_password_count;      /* samba4 idl */
 
        uint32 user_rid;
        uint32 group_rid;
@@ -90,15 +102,15 @@ typedef struct pac_logon_info {
        uint32 group_membership_ptr;
        uint32 user_flags;
 
-       uint32 reserved13[4];
+       uint8 session_key[16];          /* samba4 idl */
        UNIHDR hdr_dom_controller;
        UNIHDR hdr_dom_name;
 
        uint32 ptr_dom_sid;
-       
-       uint32 reserved16[2];
-       uint32 reserved17;      /* looks like it may be acb_info */
-       uint32 reserved18[7];
+
+       uint8 lm_session_key[8];        /* samba4 idl */
+       uint32 acct_flags;              /* samba4 idl */
+       uint32 unknown[7];
 
        uint32 sid_count;
        uint32 ptr_extra_sids;
@@ -121,6 +133,14 @@ typedef struct pac_logon_info {
        DOM_SID2 res_group_dom_sid;
        GROUP_MEMBERSHIP_ARRAY res_groups;
 
+} PAC_LOGON_INFO;
+#endif
+
+typedef struct pac_logon_info {        
+       NET_USER_INFO_3 info3;
+       DOM_SID2 res_group_dom_sid;
+       GROUP_MEMBERSHIP_ARRAY res_groups;
+
 } PAC_LOGON_INFO;
 
 typedef struct pac_info_ctr
@@ -134,18 +154,19 @@ typedef struct pac_info_ctr
        } pac;
 } PAC_INFO_CTR;
 
-typedef struct pac_info_hdr {
+typedef struct pac_buffer {
        uint32 type;
        uint32 size;
        uint32 offset;
        uint32 offsethi;
        PAC_INFO_CTR *ctr;
-} PAC_INFO_HDR;
+       uint32 pad;
+} PAC_BUFFER;
 
 typedef struct pac_data {
        uint32 num_buffers;
        uint32 version;
-       PAC_INFO_HDR *pac_info_hdr_ptr;
+       PAC_BUFFER *pac_buffer;
 } PAC_DATA;
 
 
index e9d40c3b7c9480eea1a631bd89df57b65da1cc7f..df52e227f0c55d611bf89eec96f1b7216e9dd759 100644 (file)
@@ -57,25 +57,39 @@ struct print_job_info
        time_t t;
 };
 
+struct cli_pipe_auth_data {
+       enum pipe_auth_type auth_type; /* switch for the union below. Defined in ntdomain.h */
+       enum pipe_auth_level auth_level; /* defined in ntdomain.h */
+       union {
+               struct schannel_auth_struct *schannel_auth;
+               NTLMSSP_STATE *ntlmssp_state;
+               struct kerberos_auth_struct *kerberos_auth;
+       } a_u;
+       void (*cli_auth_data_free_func)(struct cli_pipe_auth_data *);
+};
+
 struct rpc_pipe_client {
+       struct rpc_pipe_client *prev, *next;
+
        TALLOC_CTX *mem_ctx;
 
        struct cli_state *cli;
 
        int pipe_idx;
+       const char *pipe_name;
        uint16 fnum;
 
-       int pipe_auth_flags;
-
-       NTLMSSP_STATE *ntlmssp_pipe_state;
-       const char *user_name;
        const char *domain;
+       const char *user_name;
        struct pwd_info pwd;
 
-       struct netsec_auth_struct auth_info;
-
        uint16 max_xmit_frag;
        uint16 max_recv_frag;
+
+       struct cli_pipe_auth_data auth;
+
+       /* The following is only non-null on a netlogon pipe. */
+       struct dcinfo *dc;
 };
 
 struct cli_state {
@@ -92,8 +106,11 @@ struct cli_state {
        int privileges;
 
        fstring desthost;
-       fstring user_name;
+
+       /* The credentials used to open the cli_state connection. */
        fstring domain;
+       fstring user_name;
+       struct pwd_info pwd;
 
        /*
         * The following strings are the
@@ -111,7 +128,6 @@ struct cli_state {
        fstring full_dest_host_name;
        struct in_addr dest_ip;
 
-       struct pwd_info pwd;
        DATA_BLOB secblob; /* cryptkey or negTokenInit */
        uint32 sesskey;
        int serverzone;
@@ -137,27 +153,8 @@ struct cli_state {
           any per-pipe authenticaion */
        DATA_BLOB user_session_key;
 
-       /*
-        * Only used in NT domain calls.
-        */
-
-       int pipe_idx;                      /* Index (into list of known pipes) 
-                                             of the pipe we're talking to, 
-                                             if any */
-
-       struct rpc_pipe_client pipes[PI_MAX_PIPES];
-
-       /* Secure pipe parameters */
-       int pipe_auth_flags;
-
-       struct rpc_pipe_client netlogon_pipe;  /* The "first" pipe to get
-                                                 the session key for the
-                                                 schannel. */
-       unsigned char sess_key[16];        /* Current session key. */
-       DOM_CRED clnt_cred;                /* Client credential. */
-       fstring mach_acct;                 /* MYNAME$. */
-       fstring srv_name_slash;            /* \\remote server. */
-       fstring clnt_name_slash;           /* \\local client. */
+       /* The list of pipes currently open on this connection. */
+       struct rpc_pipe_client *pipe_list;
 
        BOOL use_kerberos;
        BOOL fallback_after_kerberos;
@@ -175,9 +172,6 @@ struct cli_state {
        /* was this structure allocated by cli_initialise? If so, then
            free in cli_shutdown() */
        BOOL allocated;
-
-       /* Name of the pipe we're talking to, if any */
-       fstring pipe_name;
 };
 
 #define CLI_FULL_CONNECTION_DONT_SPNEGO 0x0001
index 794aea757662845bfee1bccf06f3b71470162064..c856aaa7625794dc20d2305ec66e4099c502e2e9 100644 (file)
                } \
 }
 
+/* insert 'p' after the given element 'el' in a list. If el is NULL then
+   this is the same as a DLIST_ADD() */
+#define DLIST_ADD_AFTER(list, p, el) \
+do { \
+        if (!(list) || !(el)) { \
+               DLIST_ADD(list, p); \
+       } else { \
+               p->prev = el; \
+               p->next = el->next; \
+               el->next = p; \
+               if (p->next) p->next->prev = p; \
+       }\
+} while (0)
+
 /* demote an element to the top of the list, needs a tmp pointer */
 #define DLIST_DEMOTE(list, p, tmp) \
 { \
index 7c98171250c1602c8393ea647a9cd7316e6ff1df..593d5d99eef62cb6af4a7c34b5720b477737c895 100644 (file)
@@ -5,6 +5,7 @@
    Copyright (C) John H Terpstra              1996-2000
    Copyright (C) Luke Kenneth Casson Leighton 1996-2000
    Copyright (C) Paul Ashton                  1998-2000
+   Copyright (C) Gerald (Jerry) Carter        2005
    
    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
 #define WERR_NOMEM W_ERROR(8)
 #define WERR_GENERAL_FAILURE W_ERROR(31)
 #define WERR_NOT_SUPPORTED W_ERROR(50)
+#define WERR_DEVICE_NOT_EXIST W_ERROR(55)
 #define WERR_PRINTQ_FULL W_ERROR(61)
 #define WERR_NO_SPOOL_SPACE W_ERROR(62)
 #define WERR_NO_SUCH_SHARE W_ERROR(67)
 #define WERR_PRINT_MONITOR_IN_USE W_ERROR(ERRprintmonitorinuse)
 #define WERR_PRINTER_HAS_JOBS_QUEUED W_ERROR(ERRprinterhasjobsqueued)
 
+/* Configuration Manager Errors */
+/* Basically Win32 errors meanings are specific to the \ntsvcs pipe */
+
+#define WERR_CM_NO_MORE_HW_PROFILES W_ERROR(35)
+#define WERR_CM_NO_SUCH_VALUE W_ERROR(37)
+
 
 /* DFS errors */
 
index 51aa218ac6c6eca212b75c939a76f06f2724e92e..573982903b8727904ed80825a6ae0b50b5d97e50 100644 (file)
@@ -27,7 +27,8 @@
 
 #ifndef __cplusplus
 #define class #error DONT_USE_CPLUSPLUS_RESERVED_NAMES
-#define private #error DONT_USE_CPLUSPLUS_RESERVED_NAMES
+/* allow to build with newer heimdal releases */
+/* #define private #error DONT_USE_CPLUSPLUS_RESERVED_NAMES */
 #define public #error DONT_USE_CPLUSPLUS_RESERVED_NAMES
 #define protected #error DONT_USE_CPLUSPLUS_RESERVED_NAMES
 #define template #error DONT_USE_CPLUSPLUS_RESERVED_NAMES
 #include <net/if.h>
 #endif
 
+
 #ifdef HAVE_SYS_MOUNT_H
 #include <sys/mount.h>
 #endif
@@ -896,19 +898,17 @@ extern int errno;
 
 #include "privileges.h"
 
-#include "rpc_creds.h"
+#include "rpc_misc.h"
+
+#include "rpc_dce.h"
 
 #include "mapping.h"
 
 #include "passdb.h"
 
-#include "ntdomain.h"
-
-#include "rpc_misc.h"
-
 #include "rpc_secdes.h"
 
-#include "nt_printing.h"
+#include "authdata.h"
 
 #include "msdfs.h"
 
@@ -923,6 +923,29 @@ extern int errno;
 
 #include "auth.h"
 
+#include "ntdomain.h"
+
+#include "rpc_svcctl.h"
+#include "rpc_ntsvcs.h"
+#include "rpc_lsa.h"
+#include "rpc_netlogon.h"
+#include "reg_objects.h"
+#include "rpc_reg.h"
+#include "rpc_samr.h"
+#include "rpc_srvsvc.h"
+#include "rpc_wkssvc.h"
+#include "rpc_spoolss.h"
+#include "rpc_eventlog.h"
+#include "rpc_dfs.h"
+#include "rpc_ds.h"
+#include "rpc_echo.h"
+#include "rpc_shutdown.h"
+#include "rpc_unixinfo.h"
+#include "rpc_perfcount.h"
+#include "rpc_perfcount_defs.h"
+
+#include "nt_printing.h"
+
 #include "idmap.h"
 
 #include "client.h"
@@ -945,6 +968,8 @@ extern int errno;
 
 #include "spnego.h"
 
+#include "rpc_client.h"
+
 /*
  * Type for wide character dirent structure.
  * Only d_name is defined by POSIX.
@@ -995,6 +1020,8 @@ struct smb_ldap_privates;
 
 #include "smbldap.h"
 
+#include "smb_ldap.h"
+
 /***** automatically generated prototypes *****/
 #ifndef NO_PROTO_H
 #include "proto.h"
@@ -1414,7 +1441,7 @@ void krb5_free_unparsed_name(krb5_context ctx, char *val);
 void setup_kaddr( krb5_address *pkaddr, struct sockaddr *paddr);
 int create_kerberos_key_from_string(krb5_context context, krb5_principal host_princ, krb5_data *password, krb5_keyblock *key, krb5_enctype enctype);
 int create_kerberos_key_from_string_direct(krb5_context context, krb5_principal host_princ, krb5_data *password, krb5_keyblock *key, krb5_enctype enctype);
-void get_auth_data_from_tkt(DATA_BLOB *auth_data, krb5_ticket *tkt);
+BOOL get_auth_data_from_tkt(TALLOC_CTX *mem_ctx, DATA_BLOB *auth_data, krb5_ticket *tkt);
 krb5_const_principal get_principal_from_tkt(krb5_ticket *tkt);
 krb5_error_code krb5_locate_kdc(krb5_context ctx, const krb5_data *realm, struct sockaddr **addr_pp, int *naddrs, int get_masters);
 krb5_error_code get_kerberos_allowed_etypes(krb5_context context, krb5_enctype **enctypes);
index 1039e0d9a7074d31a85461418a9b5c30b3844f44..abe219374ed57eb59387625821a474aedc17cde1 100644 (file)
 #define MSG_SMB_SAM_SYNC     3003
 #define MSG_SMB_SAM_REPL     3004
 #define MSG_SMB_UNLOCK       3005
+#define MSG_SMB_BREAK_REQUEST 3006
+#define MSG_SMB_BREAK_RESPONSE 3007
+#define MSG_SMB_ASYNC_LEVEL2_BREAK 3008
+#define MSG_SMB_OPEN_RETRY   3009
+#define MSG_SMB_KERNEL_BREAK 3010
 
 /* winbind messages */
 #define MSG_WINBIND_FINISHED     4001
@@ -77,4 +82,8 @@
 #define FLAG_MSG_PRINT_NOTIFY  0x0008
 #define FLAG_MSG_PRINT_GENERAL 0x0010
 
+struct process_id {
+       pid_t pid;
+};
+
 #endif
index c41310c7f7536043f143d039ad6e0baed23bdacd..8b317a9d59df253405e78d69bcc329cb1325be5f 100644 (file)
@@ -33,6 +33,4 @@ typedef int smb_event_id_t;
 
 typedef void (smb_idle_event_fn)(void **data,time_t *interval,time_t now);
 
-typedef void (smb_exit_event_fn)(void **data);
-
 #endif /* _MODULE_H */
index 87fac492db39124aafff55692318f4b6eb4565fd..967aac2bb5f06fe9f4ea36e6fc089f2fa6a66d7f 100644 (file)
 #ifndef _NT_DOMAIN_H /* _NT_DOMAIN_H */
 #define _NT_DOMAIN_H 
 
-struct uuid {
-       uint32 time_low;
-       uint16 time_mid;
-       uint16 time_hi_and_version;
-       uint8  clock_seq[2];
-       uint8  node[6];
-};
-#define UUID_SIZE 16
-
-#define UUID_FLAT_SIZE 16
-typedef struct uuid_flat {
-       uint8 info[UUID_FLAT_SIZE];
-} UUID_FLAT;
-
-/* dce/rpc support */
-#include "rpc_dce.h"
-
-/* miscellaneous structures / defines */
-#include "rpc_misc.h"
-
-#include "rpc_creds.h"
-
-#include "talloc.h"
-
 /*
  * A bunch of stuff that was put into smb.h
  * in the NTDOM branch - it didn't belong there.
@@ -67,6 +43,7 @@ typedef struct _prs_struct {
        uint32 grow_size; /* size requested via prs_grow() calls */
        char *data_p; /* The buffer itself. */
        TALLOC_CTX *mem_ctx; /* When unmarshalling, use this.... */
+       const char *sess_key; /* If we have to do encrypt/decrypt on the fly. */
 } prs_struct;
 
 /*
@@ -97,7 +74,7 @@ typedef struct _output_data {
         * The current PDU being returned. This inclues
         * headers, data and authentication footer.
         */
-       unsigned char current_pdu[MAX_PDU_FRAG_LEN];
+       unsigned char current_pdu[RPC_MAX_PDU_FRAG_LEN];
 
        /* The amount of data in the current_pdu buffer. */
        uint32 current_pdu_len;
@@ -111,9 +88,9 @@ typedef struct _input_data {
         * This is the current incoming pdu. The data here
         * is collected via multiple writes until a complete
         * pdu is seen, then the data is copied into the in_data
-        * structure. The maximum size of this is 0x1630 (MAX_PDU_FRAG_LEN).
+        * structure. The maximum size of this is 0x1630 (RPC_MAX_PDU_FRAG_LEN).
         */
-       unsigned char current_in_pdu[MAX_PDU_FRAG_LEN];
+       unsigned char current_in_pdu[RPC_MAX_PDU_FRAG_LEN];
 
        /*
         * The amount of data needed to complete the in_pdu.
@@ -158,22 +135,22 @@ struct handle_list {
 
 /* Domain controller authentication protocol info */
 struct dcinfo {
-       DOM_CHAL clnt_chal; /* Initial challenge received from client */
-       DOM_CHAL srv_chal;  /* Initial server challenge */
-       DOM_CRED clnt_cred; /* Last client credential */
-       DOM_CRED srv_cred;  /* Last server credential */
+       uint32 sequence; /* "timestamp" from client. */
+       DOM_CHAL seed_chal; 
+       DOM_CHAL clnt_chal; /* Client credential */
+       DOM_CHAL srv_chal;  /* Server credential */
  
        uchar  sess_key[8]; /* Session key */
-       uchar  md4pw[16];   /* md4(machine password) */
+       uchar  mach_pw[16];   /* md4(machine password) */
 
        fstring mach_acct;  /* Machine name we've authenticated. */
 
        fstring remote_machine;  /* Machine name we've authenticated. */
+       fstring domain;
 
        BOOL challenge_sent;
        BOOL got_session_key;
        BOOL authenticated;
-
 };
 
 typedef struct pipe_rpc_fns {
@@ -188,6 +165,46 @@ typedef struct pipe_rpc_fns {
        
 } PIPE_RPC_FNS;
 
+/*
+ * Different auth types we support.
+ * Can't keep in sync with wire values as spnego wraps different auth methods.
+ */
+
+enum pipe_auth_type { PIPE_AUTH_TYPE_NONE = 0, PIPE_AUTH_TYPE_NTLMSSP, PIPE_AUTH_TYPE_SCHANNEL,
+                       PIPE_AUTH_TYPE_SPNEGO_NTLMSSP, PIPE_AUTH_TYPE_KRB5, PIPE_AUTH_TYPE_SPNEGO_KRB5 };
+
+/* Possible auth levels - keep these in sync with the wire values. */
+enum pipe_auth_level { PIPE_AUTH_LEVEL_NONE = 0,
+                       PIPE_AUTH_LEVEL_CONNECT = 1,    /* We treat as NONE. */
+                       PIPE_AUTH_LEVEL_INTEGRITY = 5,  /* Sign. */
+                       PIPE_AUTH_LEVEL_PRIVACY = 6     /* Seal. */
+};
+
+/* auth state for krb5. */
+struct kerberos_auth_struct {
+       const char *service_principal;
+       DATA_BLOB session_key;
+};
+
+/* auth state for schannel. */
+struct schannel_auth_struct {
+       uchar sess_key[16];
+       uint32 seq_num;
+};
+
+/* auth state for all bind types. */
+
+struct pipe_auth_data {
+       enum pipe_auth_type auth_type; /* switch for union below. */
+       enum pipe_auth_level auth_level;
+       union {
+               struct schannel_auth_struct *schannel_auth;
+               AUTH_NTLMSSP_STATE *auth_ntlmssp_state;
+/*             struct kerberos_auth_struct *kerberos_auth; TO BE ADDED... */
+       } a_u;
+       void (*auth_data_free_func)(struct pipe_auth_data *);
+};
+
 /*
  * DCE/RPC-specific samba-internal-specific handling of data on
  * NamedPipes.
@@ -210,20 +227,12 @@ typedef struct pipes_struct {
        RPC_HDR hdr; /* Incoming RPC header. */
        RPC_HDR_REQ hdr_req; /* Incoming request header. */
 
-       uint32 ntlmssp_chal_flags; /* Client challenge flags. */
-       BOOL ntlmssp_auth_requested; /* If the client wanted authenticated rpc. */
-       BOOL ntlmssp_auth_validated; /* If the client *got* authenticated rpc. */
-       unsigned char challenge[8];
-       unsigned char ntlmssp_hash[258];
-       uint32 ntlmssp_seq_num;
-       struct dcinfo dc; /* Keeps the creds data. */
+       /* This context is used for pipe state storage and is freed when the pipe is closed. */
+       TALLOC_CTX *pipe_state_mem_ctx;
 
-        /* Hmm. In my understanding the authentication happens
-           implicitly later, so there are no two stages for
-           schannel. */
+       struct pipe_auth_data auth;
 
-       BOOL netsec_auth_validated;
-       struct netsec_auth_struct netsec_auth;
+       struct dcinfo *dc; /* Keeps the creds data from netlogon. */
 
        /*
         * Windows user info.
@@ -233,14 +242,13 @@ typedef struct pipes_struct {
        fstring wks;
 
        /*
-        * Unix user name and credentials.
+        * Unix user name and credentials used when a pipe is authenticated.
         */
 
        fstring pipe_user_name;
        struct current_user pipe_user;
-
        DATA_BLOB session_key;
-
        /*
         * Set to true when an RPC bind has been done on this pipe.
         */
@@ -277,7 +285,8 @@ typedef struct pipes_struct {
 
        output_data out_data;
 
-       /* talloc context to use when allocating memory on this pipe. */
+       /* This context is used for PUD data and is freed between each pdu.
+               Don't use for pipe state storage. */
        TALLOC_CTX *mem_ctx;
 
        /* handle database to use on this pipe. */
@@ -383,27 +392,11 @@ typedef struct {
 
 /* end higher order functions */
 
-
-/* security descriptor structures */
-#include "rpc_secdes.h"
-
-/* pac */
-#include "authdata.h"
-
-/* different dce/rpc pipes */
-#include "rpc_buffer.h"
-#include "rpc_lsa.h"
-#include "rpc_netlogon.h"
-#include "rpc_reg.h"
-#include "rpc_samr.h"
-#include "rpc_srvsvc.h"
-#include "rpc_wkssvc.h"
-#include "rpc_svcctl.h"
-#include "rpc_spoolss.h"
-#include "rpc_eventlog.h"
-#include "rpc_dfs.h"
-#include "rpc_ds.h"
-#include "rpc_echo.h"
-#include "rpc_shutdown.h"
+typedef struct {
+       uint32 size;
+       prs_struct prs;
+       uint32 struct_start;
+       uint32 string_at_end;
+} RPC_BUFFER;
 
 #endif /* _NT_DOMAIN_H */
index 267779c434d462334e40a9673fb40edc00edd4ae..30a37e06c3ef2e9dcef94988248eccada2de71ca 100644 (file)
@@ -34,7 +34,8 @@ enum NTLM_MESSAGE_TYPE
        NTLMSSP_NEGOTIATE = 1,
        NTLMSSP_CHALLENGE = 2,
        NTLMSSP_AUTH      = 3,
-       NTLMSSP_UNKNOWN   = 4
+       NTLMSSP_UNKNOWN   = 4,
+       NTLMSSP_DONE      = 5 /* samba final state */
 };
 
 /* NTLMSSP negotiation flags */
@@ -61,13 +62,15 @@ enum NTLM_MESSAGE_TYPE
 #define NTLMSSP_CHAL_TARGET_INFO           0x00800000
 #define NTLMSSP_NEGOTIATE_128              0x20000000 /* 128-bit encryption */
 #define NTLMSSP_NEGOTIATE_KEY_EXCH         0x40000000
-#define NTLMSSP_NEGOTIATE_080000000        0x80000000
+#define NTLMSSP_NEGOTIATE_56               0x80000000
 
 #define NTLMSSP_NAME_TYPE_SERVER      0x01
 #define NTLMSSP_NAME_TYPE_DOMAIN      0x02
 #define NTLMSSP_NAME_TYPE_SERVER_DNS  0x03
 #define NTLMSSP_NAME_TYPE_DOMAIN_DNS  0x04
 
+#define NTLMSSP_SIG_SIZE 16
+
 typedef struct ntlmssp_state 
 {
        TALLOC_CTX *mem_ctx;
@@ -142,23 +145,22 @@ typedef struct ntlmssp_state
        const char *(*get_global_myname)(void);
        const char *(*get_domain)(void);
 
-       /* SMB Signing */
-       
-       uint32 ntlmssp_seq_num;
-
        /* ntlmv2 */
-       unsigned char send_sign_const[16];
-       unsigned char send_seal_const[16];
-       unsigned char recv_sign_const[16];
-       unsigned char recv_seal_const[16];
 
-       unsigned char send_sign_hash[258];
-       unsigned char send_seal_hash[258];
-       unsigned char recv_sign_hash[258];
-       unsigned char recv_seal_hash[258];
+       unsigned char send_sign_key[16];
+       unsigned char send_seal_key[16];
+       unsigned char recv_sign_key[16];
+       unsigned char recv_seal_key[16];
+
+       unsigned char send_seal_arc4_state[258];
+       unsigned char recv_seal_arc4_state[258];
+
+       uint32 ntlm2_send_seq_num;
+       uint32 ntlm2_recv_seq_num;
 
        /* ntlmv1 */
-       unsigned char ntlmssp_hash[258];
+       unsigned char ntlmv1_arc4_state[258];
+       uint32 ntlmv1_seq_num;
 
        /* it turns out that we don't always get the
           response in at the time we want to process it.
@@ -166,4 +168,3 @@ typedef struct ntlmssp_state
        DATA_BLOB stored_response; 
        
 } NTLMSSP_STATE;
-
index 114585346e16a97d6388d31fdc47cc648d664945..e985ab582dcbe666fd5b2a66563165d949ecd9af 100644 (file)
@@ -233,6 +233,7 @@ struct acct_info
 };
 
 struct samr_displayentry {
+       uint32 idx;
        uint32 rid;
        uint16 acct_flags;
        const char *account_name;
@@ -268,7 +269,7 @@ struct pdb_search {
  * this SAMBA will load. Increment this if *ANY* changes are made to the interface. 
  */
 
-#define PASSDB_INTERFACE_VERSION 8
+#define PASSDB_INTERFACE_VERSION 9
 
 typedef struct pdb_context 
 {
@@ -373,6 +374,14 @@ typedef struct pdb_context
                                    const char ***names,
                                    uint32 **attrs);
 
+       NTSTATUS (*pdb_get_account_policy)(struct pdb_context *context,
+                                          int policy_index, uint32 *value);
+
+       NTSTATUS (*pdb_set_account_policy)(struct pdb_context *context,
+                                          int policy_index, uint32 value);
+
+       NTSTATUS (*pdb_get_seq_num)(struct pdb_context *context, time_t *seq_num);
+
        BOOL (*pdb_search_users)(struct pdb_context *context,
                                 struct pdb_search *search,
                                 uint16 acct_flags);
@@ -478,6 +487,7 @@ typedef struct pdb_methods
                                           int num_members,
                                           uint32 **alias_rids,
                                           int *num_alias_rids);
+
        NTSTATUS (*lookup_rids)(struct pdb_methods *methods,
                                TALLOC_CTX *mem_ctx,
                                const DOM_SID *domain_sid,
@@ -486,6 +496,14 @@ typedef struct pdb_methods
                                const char ***names,
                                uint32 **attrs);
 
+       NTSTATUS (*get_account_policy)(struct pdb_methods *methods,
+                                      int policy_index, uint32 *value);
+
+       NTSTATUS (*set_account_policy)(struct pdb_methods *methods,
+                                      int policy_index, uint32 value);
+
+       NTSTATUS (*get_seq_num)(struct pdb_methods *methods, time_t *seq_num);
+
        BOOL (*search_users)(struct pdb_methods *methods,
                             struct pdb_search *search,
                             uint16 acct_flags);
index 220fd08ef1e2ee0b3063dbfde309b91707d806d4..54f32d5954c3d0d975616e199856470fb98db58b 100644 (file)
@@ -57,7 +57,7 @@ struct printif
                    print_status_struct *status);
   int (*queue_pause)(int snum);
   int (*queue_resume)(int snum);
-  int (*job_delete)(int snum, struct printjob *pjob);
+  int (*job_delete)(const char *sharename, const char *lprm_command, struct printjob *pjob);
   int (*job_pause)(int snum, struct printjob *pjob);
   int (*job_resume)(int snum, struct printjob *pjob);
   int (*job_submit)(int snum, struct printjob *pjob);
index 9ca2d5aa8c9f78108b14edb3b69f8995d3d21ba4..8a83c0f8ae87fc9c18e9b93977b55b989b9788ef 100644 (file)
 #define _RPC_CLIENT_H
 
 /* macro to expand cookie-cutter code in cli_xxx() using rpc_api_pipe_req() */
-                  
-#define CLI_DO_RPC( pcli, ctx, pipe_num, opnum, q_in, r_out, \
+
+#define CLI_DO_RPC( pcli, ctx, p_idx, opnum, q_in, r_out, \
                              q_ps, r_ps, q_io_fn, r_io_fn, default_error ) \
-{      r_out.status = default_error;\
-       prs_init( &q_ps, MAX_PDU_FRAG_LEN, ctx, MARSHALL ); \
-       prs_init( &r_ps, 0, ctx, UNMARSHALL );\
+{\
+       SMB_ASSERT(pcli->pipe_idx == p_idx); \
+       if (!prs_init( &q_ps, RPC_MAX_PDU_FRAG_LEN, ctx, MARSHALL )) { \
+               return NT_STATUS_NO_MEMORY;\
+       }\
+       if (!prs_init( &r_ps, 0, ctx, UNMARSHALL )) {\
+               prs_mem_free( &q_ps );\
+               return NT_STATUS_NO_MEMORY;\
+       }\
        if ( q_io_fn("", &q_in, &q_ps, 0) ) {\
-               if ( rpc_api_pipe_req(pcli, pipe_num, opnum, &q_ps, &r_ps) ) {\
-                       if (!r_io_fn("", &r_out, &r_ps, 0)) {\
-                               r_out.status = default_error;\
-                       }\
+               NTSTATUS _smb_pipe_stat_ = rpc_api_pipe_req(pcli, opnum, &q_ps, &r_ps); \
+               if (!NT_STATUS_IS_OK(_smb_pipe_stat_)) {\
+                       prs_mem_free( &q_ps );\
+                       prs_mem_free( &r_ps );\
+                       return _smb_pipe_stat_;\
+               }\
+               if (!r_io_fn("", &r_out, &r_ps, 0)) {\
+                       prs_mem_free( &q_ps );\
+                       prs_mem_free( &r_ps );\
+                       return default_error;\
                }\
+       } else {\
+               prs_mem_free( &q_ps );\
+               prs_mem_free( &r_ps );\
+               return default_error;\
        }\
        prs_mem_free( &q_ps );\
        prs_mem_free( &r_ps );\
 }
 
-/* macro to expand cookie-cutter code in cli_xxx() using rpc_api_pipe_req_int() */
+/* Arrrgg. Same but with WERRORS. Needed for registry code. */
 
-#define CLI_DO_RPC_EX( pcli, ctx, pipe_num, opnum, q_in, r_out, \
+#define CLI_DO_RPC_WERR( pcli, ctx, p_idx, opnum, q_in, r_out, \
                              q_ps, r_ps, q_io_fn, r_io_fn, default_error ) \
-{      r_out.status = default_error;\
-       prs_init( &q_ps, MAX_PDU_FRAG_LEN, ctx, MARSHALL ); \
-       prs_init( &r_ps, 0, ctx, UNMARSHALL );\
+{\
+       SMB_ASSERT(pcli->pipe_idx == p_idx); \
+       if (!prs_init( &q_ps, RPC_MAX_PDU_FRAG_LEN, ctx, MARSHALL )) { \
+               return WERR_NOMEM;\
+       }\
+       if (!prs_init( &r_ps, 0, ctx, UNMARSHALL )) {\
+               prs_mem_free( &q_ps );\
+               return WERR_NOMEM;\
+       }\
        if ( q_io_fn("", &q_in, &q_ps, 0) ) {\
-               if ( rpc_api_pipe_req_int(pcli, opnum, &q_ps, &r_ps) ) {\
-                       if (!r_io_fn("", &r_out, &r_ps, 0)) {\
-                               r_out.status = default_error;\
-                       }\
+               NTSTATUS _smb_pipe_stat_ = rpc_api_pipe_req(pcli, opnum, &q_ps, &r_ps); \
+               if (!NT_STATUS_IS_OK(_smb_pipe_stat_)) {\
+                       prs_mem_free( &q_ps );\
+                       prs_mem_free( &r_ps );\
+                       return ntstatus_to_werror(_smb_pipe_stat_);\
+               }\
+               if (!r_io_fn("", &r_out, &r_ps, 0)) {\
+                       prs_mem_free( &q_ps );\
+                       prs_mem_free( &r_ps );\
+                       return default_error;\
                }\
+       } else {\
+               prs_mem_free( &q_ps );\
+               prs_mem_free( &r_ps );\
+               return default_error;\
        }\
        prs_mem_free( &q_ps );\
        prs_mem_free( &r_ps );\
index 88b8380870e3d0e4a9d11a8c2b96fc8aa66b0e60..3de4d2b691e71abdcb0865b5c61709d54d036549 100644 (file)
@@ -23,9 +23,6 @@
 #ifndef _DCE_RPC_H /* _DCE_RPC_H */
 #define _DCE_RPC_H 
 
-#include "rpc_misc.h"  /* this only pulls in STRHDR */
-
-
 /* DCE/RPC packet types */
 
 enum RPC_PKT_TYPE {
@@ -37,7 +34,7 @@ enum RPC_PKT_TYPE {
        RPC_BINDNACK = 0x0D,
        RPC_ALTCONT  = 0x0E,
        RPC_ALTCONTRESP = 0x0F,
-       RPC_BINDRESP = 0x10 /* not the real name!  this is undocumented! */
+       RPC_AUTH3 = 0x10 /* not the real name!  this is undocumented! */
 };
 
 /* DCE/RPC flags */
@@ -45,29 +42,41 @@ enum RPC_PKT_TYPE {
 #define RPC_FLG_LAST  0x02
 #define RPC_FLG_NOCALL 0x20
 
+
 #define SMBD_NTLMSSP_NEG_FLAGS 0x000082b1 /* ALWAYS_SIGN|NEG_NTLM|NEG_LM|NEG_SEAL|NEG_SIGN|NEG_UNICODE */
 
 /* NTLMSSP signature version */
 #define NTLMSSP_SIGN_VERSION 0x01
 
-/* NTLMSSP auth type */
-#define NTLMSSP_AUTH_TYPE 0xa
+/* DCE RPC auth types - extended by Microsoft. */
+#define RPC_ANONYMOUS_AUTH_TYPE    0
+#define RPC_AUTH_TYPE_KRB5_1      1
+#define RPC_SPNEGO_AUTH_TYPE       9 
+#define RPC_NTLMSSP_AUTH_TYPE     10
+#define RPC_KRB5_AUTH_TYPE        16 /* Not yet implemented. */ 
+#define RPC_SCHANNEL_AUTH_TYPE    68 /* 0x44 */
 
 /* DCE-RPC standard identifiers to indicate 
    signing or sealing of an RPC pipe */
+#define RPC_AUTH_LEVEL_NONE      1
+#define RPC_AUTH_LEVEL_CONNECT   2
+#define RPC_AUTH_LEVEL_CALL      3
+#define RPC_AUTH_LEVEL_PACKET    4
+#define RPC_AUTH_LEVEL_INTEGRITY 5
+#define RPC_AUTH_LEVEL_PRIVACY   6
+
+#if 0
 #define RPC_PIPE_AUTH_SIGN_LEVEL 0x5
 #define RPC_PIPE_AUTH_SEAL_LEVEL 0x6
+#endif
 
 /* Netlogon schannel auth type and level */
-#define NETSEC_AUTH_TYPE 0x44
-#define NETSEC_SIGN_SIGNATURE { 0x77, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00 }
-#define NETSEC_SEAL_SIGNATURE { 0x77, 0x00, 0x7a, 0x00, 0xff, 0xff, 0x00, 0x00 }
+#define SCHANNEL_SIGN_SIGNATURE { 0x77, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00 }
+#define SCHANNEL_SEAL_SIGNATURE { 0x77, 0x00, 0x7a, 0x00, 0xff, 0xff, 0x00, 0x00 }
 
-#define RPC_AUTH_NETSEC_SIGN_OR_SEAL_CHK_LEN   0x20
-#define RPC_AUTH_NETSEC_SIGN_ONLY_CHK_LEN      0x18
+#define RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN         0x20
+#define RPC_AUTH_SCHANNEL_SIGN_ONLY_CHK_LEN    0x18
 
-/* SPNEGO auth type. */
-#define SPNEGO_AUTH_TYPE 0x9
 
 /* The 7 here seems to be required to get Win2k not to downgrade us
    to NT4.  Actually, anything other than 1ff would seem to do... */
@@ -76,20 +85,17 @@ enum RPC_PKT_TYPE {
 #define NETLOGON_NEG_SCHANNEL                  0x40000000
 #define NETLOGON_NEG_DOMAIN_TRUST_ACCOUNT      0x2010b000
 
-enum netsec_direction {
+enum schannel_direction {
        SENDER_IS_INITIATOR,
        SENDER_IS_ACCEPTOR
 };
 
-/* Internal Flags to indicate what type of authentication on the pipe */
-#define AUTH_PIPE_SIGN    0x0001
-#define AUTH_PIPE_SEAL    0x0002
-#define AUTH_PIPE_NTLMSSP 0x0004
-#define AUTH_PIPE_NETSEC  0x0008
+/* Maximum size of the signing data in a fragment. */
+#define RPC_MAX_SIGN_SIZE 0x20 /* 32 */
 
 /* Maximum PDU fragment size. */
 /* #define MAX_PDU_FRAG_LEN 0x1630             this is what wnt sets */
-#define MAX_PDU_FRAG_LEN 0x10b8                        /* this is what w2k sets */
+#define RPC_MAX_PDU_FRAG_LEN 0x10b8                    /* this is what w2k sets */
 
 /* RPC_IFACE */
 typedef struct rpc_iface_info {
@@ -163,7 +169,7 @@ typedef struct rpc_addr_info {
        fstring str; /* the string above in single byte, null terminated form */
 } RPC_ADDR_STR;
 
-/* RPC_HDR_BBA */
+/* RPC_HDR_BBA - bind acknowledge, and alter context response. */
 typedef struct rpc_hdr_bba_info {
        uint16 max_tsize;       /* maximum transmission fragment size (0x1630) */
        uint16 max_rsize;       /* max receive fragment size (0x1630) */
@@ -183,39 +189,24 @@ typedef struct rpc_hdr_auth_info {
 
 #define RPC_HDR_AUTH_LEN 8
 
-/* RPC_HDR_AUTHA */
-typedef struct rpc_hdr_autha_info {
-       uint16 max_tsize;       /* maximum transmission fragment size (0x1630) */
-       uint16 max_rsize;       /* max receive fragment size (0x1630) */
-       RPC_HDR_AUTH auth;
-} RPC_HDR_AUTHA;
-
-#define RPC_HDR_AUTHA_LEN (RPC_HDR_AUTH_LEN+4)
-
 /* this is TEMPORARILY coded up as a specific structure */
 /* this structure comes after the bind request */
-/* RPC_AUTH_NETSEC_NEG */
-typedef struct rpc_auth_netsec_neg_info {
+/* RPC_AUTH_SCHANNEL_NEG */
+typedef struct rpc_auth_schannel_neg_info {
        uint32 type1;   /* Always zero ? */
        uint32 type2;   /* Types 0x3 and 0x13 seen. Check AcquireSecurityContext() docs.... */
        fstring domain; /* calling workstations's domain */
        fstring myname; /* calling workstation's name */
-} RPC_AUTH_NETSEC_NEG;
+} RPC_AUTH_SCHANNEL_NEG;
 
 /* attached to the end of encrypted rpc requests and responses */
-/* RPC_AUTH_NETSEC_CHK */
-typedef struct rpc_auth_netsec_chk_info {
+/* RPC_AUTH_SCHANNEL_CHK */
+typedef struct rpc_auth_schannel_chk_info {
        uint8 sig  [8]; /* 77 00 7a 00 ff ff 00 00 */
        uint8 packet_digest[8]; /* checksum over the packet, MD5'ed with session key */
        uint8 seq_num[8]; /* verifier, seq num */
        uint8 confounder[8]; /* random 8-byte nonce */
-} RPC_AUTH_NETSEC_CHK;
-
-struct netsec_auth_struct {
-       uchar sess_key[16];
-       uint32 seq_num;
-       int auth_flags;
-};
+} RPC_AUTH_SCHANNEL_CHK;
 
 typedef struct rpc_context {
        uint16 context_id;              /* presentation context identifier. */
@@ -268,60 +259,4 @@ typedef struct rpc_auth_verif_info {
        uint32  msg_type; /* NTLMSSP_MESSAGE_TYPE (1,2,3) and 5 for schannel */
 } RPC_AUTH_VERIFIER;
 
-/* this is TEMPORARILY coded up as a specific structure */
-/* this structure comes after the bind request */
-/* RPC_AUTH_NTLMSSP_NEG */
-
-typedef struct rpc_auth_ntlmssp_neg_info {
-       uint32  neg_flgs; /* 0x0000 b2b3 */
-
-       STRHDR hdr_myname; /* offset is against START of this structure */
-       STRHDR hdr_domain; /* offset is against START of this structure */
-
-       fstring myname; /* calling workstation's name */
-       fstring domain; /* calling workstations's domain */
-} RPC_AUTH_NTLMSSP_NEG;
-
-/* this is TEMPORARILY coded up as a specific structure */
-/* this structure comes after the bind acknowledgement */
-/* RPC_AUTH_NTLMSSP_CHAL */
-typedef struct rpc_auth_ntlmssp_chal_info {
-       uint32 unknown_1; /* 0x0000 0000 */
-       uint32 unknown_2; /* 0x0000 0028 */
-       uint32 neg_flags; /* 0x0000 82b1 */
-
-       uint8 challenge[8]; /* ntlm challenge */
-       uint8 reserved [8]; /* zeros */
-} RPC_AUTH_NTLMSSP_CHAL;
-
-
-/* RPC_AUTH_NTLMSSP_RESP */
-typedef struct rpc_auth_ntlmssp_resp_info {
-       STRHDR hdr_lm_resp; /* 24 byte response */
-       STRHDR hdr_nt_resp; /* 24 byte response */
-       STRHDR hdr_domain;
-       STRHDR hdr_usr;
-       STRHDR hdr_wks;
-       STRHDR hdr_sess_key; /* NULL unless negotiated */
-       uint32 neg_flags; /* 0x0000 82b1 */
-
-       fstring sess_key;
-       fstring wks;
-       fstring user;
-       fstring domain;
-       fstring nt_resp;
-       fstring lm_resp;
-} RPC_AUTH_NTLMSSP_RESP;
-
-/* attached to the end of encrypted rpc requests and responses */
-/* RPC_AUTH_NTLMSSP_CHK */
-typedef struct rpc_auth_ntlmssp_chk_info {
-       uint32 ver; /* 0x0000 0001 */
-       uint32 reserved;
-       uint32 crc32; /* checksum using 0xEDB8 8320 as a polynomial */
-       uint32 seq_num;
-} RPC_AUTH_NTLMSSP_CHK;
-
-#define RPC_AUTH_NTLMSSP_CHK_LEN 16
-
 #endif /* _DCE_RPC_H */
index 39316a5d5410de3a881b633fb0a63c2a8f88b306..7aee208c14b0fa3d8c333b8a3054e0054375ae5f 100644 (file)
 #define DFSFLAG_ADD_VOLUME           0x00000001
 #define DFSFLAG_RESTORE_VOLUME       0x00000002
 
-typedef struct dfs_q_dfs_exist
-{
-  uint32 dummy;
-}
-DFS_Q_DFS_EXIST;
+typedef struct dfs_q_dfs_exist {
+       uint32 dummy;
+} DFS_Q_DFS_EXIST;
 
 /* status == 1 if dfs exists. */
-typedef struct dfs_r_dfs_exist
-{
+typedef struct dfs_r_dfs_exist {
        uint32 status;          /* Not a WERROR or NTSTATUS code */
-}
-DFS_R_DFS_EXIST;
-
-typedef struct dfs_q_dfs_add
-{
-  uint32 ptr_DfsEntryPath;
-  UNISTR2 DfsEntryPath;
-  uint32 ptr_ServerName;
-  UNISTR2 ServerName;
-  uint32 ptr_ShareName;
-  UNISTR2 ShareName;
-  uint32 ptr_Comment;
-  UNISTR2 Comment;
-  uint32 Flags;
-}
-DFS_Q_DFS_ADD;
-
-typedef struct dfs_r_dfs_add
-{
-  WERROR status;
-}
-DFS_R_DFS_ADD;
+} DFS_R_DFS_EXIST;
+
+typedef struct dfs_q_dfs_add {
+       uint32 ptr_DfsEntryPath;
+       UNISTR2 DfsEntryPath;
+       uint32 ptr_ServerName;
+       UNISTR2 ServerName;
+       uint32 ptr_ShareName;
+       UNISTR2 ShareName;
+       uint32 ptr_Comment;
+       UNISTR2 Comment;
+       uint32 Flags;
+} DFS_Q_DFS_ADD;
+
+typedef struct dfs_r_dfs_add {
+       WERROR status;
+} DFS_R_DFS_ADD;
 
 /********************************************/
-typedef struct dfs_q_dfs_remove
-{
-  UNISTR2 DfsEntryPath;
-  uint32 ptr_ServerName;
-  UNISTR2 ServerName;
-  uint32 ptr_ShareName;
-  UNISTR2 ShareName;
-}
-DFS_Q_DFS_REMOVE;
-
-typedef struct dfs_r_dfs_remove
-{
-  WERROR status;
-}
-DFS_R_DFS_REMOVE;
+typedef struct dfs_q_dfs_remove {
+       UNISTR2 DfsEntryPath;
+       uint32 ptr_ServerName;
+       UNISTR2 ServerName;
+       uint32 ptr_ShareName;
+       UNISTR2 ShareName;
+} DFS_Q_DFS_REMOVE;
+
+typedef struct dfs_r_dfs_remove {
+       WERROR status;
+} DFS_R_DFS_REMOVE;
 
 /********************************************/
-typedef struct dfs_info_1
-{
-  uint32 ptr_entrypath;
-  UNISTR2 entrypath;
-}
-DFS_INFO_1;
-
-typedef struct dfs_info_2
-{
-  uint32 ptr_entrypath;
-  UNISTR2 entrypath;
-  uint32 ptr_comment;
-  UNISTR2 comment;
-  uint32 state;
-  uint32 num_storages;
-}
-DFS_INFO_2;
-
-typedef struct dfs_storage_info
-{
-  uint32 state;
-  uint32 ptr_servername;
-  UNISTR2 servername;
-  uint32 ptr_sharename;
-  UNISTR2 sharename;
-}
-DFS_STORAGE_INFO;
-
-typedef struct dfs_info_3
-{
-  uint32 ptr_entrypath;
-  UNISTR2 entrypath;
-  uint32 ptr_comment;
-  UNISTR2 comment;
-  uint32 state;
-  uint32 num_storages;
-  uint32 ptr_storages;
-  uint32 num_storage_infos;
-  DFS_STORAGE_INFO* storages;
-}
-DFS_INFO_3;
-
-typedef struct dfs_info_ctr
-{
+typedef struct dfs_info_1 {
+       uint32 ptr_entrypath;
+       UNISTR2 entrypath;
+} DFS_INFO_1;
+
+typedef struct dfs_info_2 {
+       uint32 ptr_entrypath;
+       UNISTR2 entrypath;
+       uint32 ptr_comment;
+       UNISTR2 comment;
+       uint32 state;
+       uint32 num_storages;
+} DFS_INFO_2;
+
+typedef struct dfs_storage_info {
+       uint32 state;
+       uint32 ptr_servername;
+       UNISTR2 servername;
+       uint32 ptr_sharename;
+       UNISTR2 sharename;
+} DFS_STORAGE_INFO;
+
+typedef struct dfs_info_3 {
+       uint32 ptr_entrypath;
+       UNISTR2 entrypath;
+       uint32 ptr_comment;
+       UNISTR2 comment;
+       uint32 state;
+       uint32 num_storages;
+       uint32 ptr_storages;
+       uint32 num_storage_infos;
+       DFS_STORAGE_INFO* storages;
+} DFS_INFO_3;
+
+typedef struct dfs_info_ctr {
+       uint32 switch_value;
+       uint32 num_entries;
+       uint32 ptr_dfs_ctr; /* pointer to dfs info union */
+       union {
+               DFS_INFO_1 *info1;
+               DFS_INFO_2 *info2;
+               DFS_INFO_3 *info3;
+       } dfs;
+} DFS_INFO_CTR;
+
+typedef struct dfs_q_dfs_get_info {
+       UNISTR2 uni_path;
   
-  uint32 switch_value;
-  uint32 num_entries;
-  uint32 ptr_dfs_ctr; /* pointer to dfs info union */
-  union
-  {
-    DFS_INFO_1 *info1;
-    DFS_INFO_2 *info2;
-    DFS_INFO_3 *info3;
-  } dfs;
-}
-DFS_INFO_CTR;
-
-typedef struct dfs_q_dfs_get_info
-{
-  UNISTR2 uni_path;
-  
-  uint32 ptr_server;
-  UNISTR2 uni_server;
+       uint32 ptr_server;
+       UNISTR2 uni_server;
 
-  uint32 ptr_share;
-  UNISTR2 uni_share;
+       uint32 ptr_share;
+       UNISTR2 uni_share;
   
-  uint32 level;
-}
-DFS_Q_DFS_GET_INFO;
-
-typedef struct dfs_r_dfs_get_info
-{
-  uint32 level;
-  uint32 ptr_ctr;
-  DFS_INFO_CTR ctr;
-  WERROR status;
-}
-DFS_R_DFS_GET_INFO;
-
-typedef struct dfs_q_dfs_enum
-{
-  uint32 level;
-  uint32 maxpreflen;
-  uint32 ptr_buffer;
-  uint32 level2;
-  uint32 ptr_num_entries;
-  uint32 num_entries;
-  uint32 ptr_num_entries2;
-  uint32 num_entries2;
-  ENUM_HND reshnd;
-}
-DFS_Q_DFS_ENUM;
-
-typedef struct dfs_r_dfs_enum
-{
-  DFS_INFO_CTR *ctr;
-  uint32 ptr_buffer;
-  uint32 level;
-  uint32 level2;
-  uint32 ptr_num_entries;
-  uint32 num_entries;
-  uint32 ptr_num_entries2;
-  uint32 num_entries2;
-  ENUM_HND reshnd;
-  WERROR status;
-}
-DFS_R_DFS_ENUM;
-
+       uint32 level;
+} DFS_Q_DFS_GET_INFO;
+
+typedef struct dfs_r_dfs_get_info {
+       uint32 level;
+       uint32 ptr_ctr;
+       DFS_INFO_CTR ctr;
+       WERROR status;
+} DFS_R_DFS_GET_INFO;
+
+typedef struct dfs_q_dfs_enum {
+       uint32 level;
+       uint32 maxpreflen;
+       uint32 ptr_buffer;
+       uint32 level2;
+       uint32 ptr_num_entries;
+       uint32 num_entries;
+       uint32 ptr_num_entries2;
+       uint32 num_entries2;
+       ENUM_HND reshnd;
+} DFS_Q_DFS_ENUM;
+
+typedef struct dfs_r_dfs_enum {
+       DFS_INFO_CTR *ctr;
+       uint32 ptr_buffer;
+       uint32 level;
+       uint32 level2;
+       uint32 ptr_num_entries;
+       uint32 num_entries;
+       uint32 ptr_num_entries2;
+       uint32 num_entries2;
+       ENUM_HND reshnd;
+       WERROR status;
+} DFS_R_DFS_ENUM;
 #endif  
index e06918730a4d437d916bab33273644167f2ed06c..24bf1e948a36b33744169a4b642a183e9724c5df 100644 (file)
@@ -21,9 +21,6 @@
 #ifndef _RPC_DS_H /* _RPC_LSA_H */
 #define _RPC_DS_H 
 
-#include "rpc_misc.h"
-
-
 /* Opcodes available on PIPE_LSARPC_DS */
 
 #define DS_GETPRIMDOMINFO      0x00
index b692a762257a1dcbd4ddb71c17fd7e6ee239a09f..7ce1199b213ac9577887400e50478000f6bebe20 100644 (file)
 #define EVENTLOG_AUDIT_FAILURE        0x0010
 
 
-typedef struct eventlog_q_open_eventlog
-{
-       uint32 unknown1;
+/***********************************/
+
+typedef struct {
+       uint16 unknown1;
        uint16 unknown2;
-       uint16 unknown3;
-       uint16 sourcename_length;
-       uint16 sourcename_size;
-       uint32 sourcename_ptr;
-       UNISTR2 sourcename;
-       uint32 servername_ptr;
-       UNISTR2 servername;
-}
-EVENTLOG_Q_OPEN_EVENTLOG;
-
-typedef struct eventlog_r_open_eventlog
-{
+} EVENTLOG_OPEN_UNKNOWN0;
+
+typedef struct {
+       EVENTLOG_OPEN_UNKNOWN0 *unknown0;
+       UNISTR4 logname;
+       UNISTR4 servername;
+       uint32 unknown1;
+       uint32 unknown2;
+} EVENTLOG_Q_OPEN_EVENTLOG;
+
+typedef struct {
        POLICY_HND handle;
        WERROR status;
-}
-EVENTLOG_R_OPEN_EVENTLOG;
+} EVENTLOG_R_OPEN_EVENTLOG;
 
-typedef struct eventlog_q_close_eventlog
-{
+
+/***********************************/
+
+typedef struct {
        POLICY_HND handle;
-}
-EVENTLOG_Q_CLOSE_EVENTLOG;
+} EVENTLOG_Q_CLOSE_EVENTLOG;
 
-typedef struct eventlog_r_close_eventlog
-{
+typedef struct {
        POLICY_HND handle;
        WERROR status;
-} 
-EVENTLOG_R_CLOSE_EVENTLOG;
+} EVENTLOG_R_CLOSE_EVENTLOG;
 
-typedef struct eventlog_q_get_num_records
-{
+
+/***********************************/
+
+typedef struct {
        POLICY_HND handle;
-} 
-EVENTLOG_Q_GET_NUM_RECORDS;
+} EVENTLOG_Q_GET_NUM_RECORDS;
 
-typedef struct eventlog_r_get_num_records
-{
+typedef struct {
        uint32 num_records;
        WERROR status;
-}
-EVENTLOG_R_GET_NUM_RECORDS;
+} EVENTLOG_R_GET_NUM_RECORDS;
 
-typedef struct eventlog_q_get_oldest_entry
-{
+
+/***********************************/
+
+typedef struct {
        POLICY_HND handle;
-}
-EVENTLOG_Q_GET_OLDEST_ENTRY;
+} EVENTLOG_Q_GET_OLDEST_ENTRY;
 
-typedef struct eventlog_r_get_oldest_entry
-{
+typedef struct {
        uint32 oldest_entry;
        WERROR status;
-}
-EVENTLOG_R_GET_OLDEST_ENTRY;
+} EVENTLOG_R_GET_OLDEST_ENTRY;
+
 
-typedef struct eventlog_q_read_eventlog
+/***********************************/
+
+typedef struct 
 {
        POLICY_HND handle;
        uint32 flags;
        uint32 offset;
        uint32 max_read_size;
-}
-EVENTLOG_Q_READ_EVENTLOG;
+} EVENTLOG_Q_READ_EVENTLOG;
 
-typedef struct eventlog_record
-{
+typedef struct {
        uint32 length;
        uint32 reserved1;
        uint32 record_number;
@@ -136,8 +133,7 @@ typedef struct eventlog_record
        uint32 data_offset;
 } Eventlog_record;
 
-typedef struct eventlog_data_record
-{
+typedef struct {
        uint32 source_name_len;
        wpstring source_name;
        uint32 computer_name_len;
@@ -151,8 +147,7 @@ typedef struct eventlog_data_record
        uint32 data_padding;
 } Eventlog_data_record;
 
-typedef struct eventlog_entry
-{
+typedef struct eventlog_entry {
        Eventlog_record record;
        Eventlog_data_record data_record;
        uint8 *data;
@@ -160,8 +155,7 @@ typedef struct eventlog_entry
        struct eventlog_entry *next;
 } Eventlog_entry;
  
-typedef struct eventlog_r_read_eventlog
-{
+typedef struct {
        uint32 num_bytes_in_resp;
        uint32 bytes_in_next_record;
        uint32 num_records;
@@ -170,24 +164,18 @@ typedef struct eventlog_r_read_eventlog
        uint32 sent_size;
        uint32 real_size;
        WERROR status;
-}
-EVENTLOG_R_READ_EVENTLOG;
+} EVENTLOG_R_READ_EVENTLOG;
 
-typedef struct eventlog_q_clear_eventlog
-{
+
+/***********************************/
+
+typedef struct {
        POLICY_HND handle;
-       uint32 unknown1;
-       uint16 backup_file_length;
-       uint16 backup_file_size;
-       uint32 backup_file_ptr;
-       UNISTR2 backup_file;
-}
-EVENTLOG_Q_CLEAR_EVENTLOG;
-
-typedef struct eventlog_r_clear_eventlog
-{
+       UNISTR4 backupfile;
+} EVENTLOG_Q_CLEAR_EVENTLOG;
+
+typedef struct {
        WERROR status;
-}
-EVENTLOG_R_CLEAR_EVENTLOG;
+} EVENTLOG_R_CLEAR_EVENTLOG;
 
 #endif /* _RPC_EVENTLOG_H */
index 053a23b218508dee8cee55290d8ecda6e6996731..dd255c28d5d5e3b52166db8fe0a5375bb45c7d23 100644 (file)
@@ -24,8 +24,6 @@
 #ifndef _RPC_LSA_H /* _RPC_LSA_H */
 #define _RPC_LSA_H 
 
-#include "rpc_misc.h"
-
 /* Opcodes available on PIPE_LSARPC */
 
 #if 0  /* UNIMPLEMENTED */
index 9f35450d952a40d254b97f1cc028662e8b4197da..e5d91c1b6300750911fbb895981f7be3798e18ef 100644 (file)
@@ -21,9 +21,6 @@
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-#include "ntdomain.h"
-#include "rpc_dce.h"
-
 #ifndef _RPC_MISC_H /* _RPC_MISC_H */
 #define _RPC_MISC_H 
 
@@ -302,8 +299,7 @@ typedef struct {
  **********************************************************************/
 
 /* DOM_CLNT_SRV - client / server names */
-typedef struct clnt_srv_info
-{
+typedef struct clnt_srv_info {
        uint32  undoc_buffer; /* undocumented 32 bit buffer pointer */
        UNISTR2 uni_logon_srv; /* logon server name */
        uint32  undoc_buffer2; /* undocumented 32 bit buffer pointer */
@@ -311,8 +307,7 @@ typedef struct clnt_srv_info
 } DOM_CLNT_SRV;
 
 /* DOM_LOG_INFO - login info */
-typedef struct log_info
-{
+typedef struct log_info {
        uint32  undoc_buffer; /* undocumented 32 bit buffer pointer */
        UNISTR2 uni_logon_srv; /* logon server name */
        UNISTR2 uni_acct_name; /* account name */
@@ -321,89 +316,44 @@ typedef struct log_info
 } DOM_LOG_INFO;
 
 /* DOM_CHAL - challenge info */
-typedef struct chal_info
-{
+typedef struct chal_info {
        uchar data[8]; /* credentials */
 } DOM_CHAL;
  
 /* DOM_CREDs - timestamped client or server credentials */
-typedef struct cred_info
-{
+typedef struct cred_info {
        DOM_CHAL challenge; /* credentials */
        UTIME timestamp;    /* credential time-stamp */
 } DOM_CRED;
 
 /* DOM_CLNT_INFO - client info */
-typedef struct clnt_info
-{
+typedef struct clnt_info {
        DOM_LOG_INFO login;
        DOM_CRED     cred;
 } DOM_CLNT_INFO;
 
 /* DOM_CLNT_INFO2 - client info */
-typedef struct clnt_info2
-{
+typedef struct clnt_info2 {
        DOM_CLNT_SRV login;
        uint32        ptr_cred;
        DOM_CRED      cred;
 } DOM_CLNT_INFO2;
 
 /* DOM_LOGON_ID - logon id */
-typedef struct logon_info
-{
+typedef struct logon_info {
        uint32 low;
        uint32 high;
 } DOM_LOGON_ID;
 
 /* OWF INFO */
-typedef struct owf_info
-{
+typedef struct owf_info {
        uint8 data[16];
 } OWF_INFO;
 
-
-
-
-
-/*
- * A client connection's state, pipe name, 
- * user credentials, etc...
- */
-typedef struct _cli_auth_fns cli_auth_fns;
-struct user_creds;
-struct cli_connection {
-
-        char                    *srv_name;
-        char                    *pipe_name;
-        struct user_creds       usr_creds;
-
-        struct cli_state        *pCli_state;
-
-        cli_auth_fns            *auth;
-
-        void                    *auth_info;
-        void                    *auth_creds;
-};
-
-
-/* 
- * Associate a POLICY_HND with a cli_connection
- */
-typedef struct rpc_hnd_node {
-
-       POLICY_HND              hnd;
-       struct cli_connection   *cli;
-
-} RPC_HND_NODE;
-
 typedef struct uint64_s
 {
        uint32 low;
        uint32 high;
 } UINT64_S;
 
-
-
-
-
 #endif /* _RPC_MISC_H */
index b3fe16ba2b32fda89dd4ec943a200ead6e1155b4..b004e26397ed673514de8c131a560384b3c48429 100644 (file)
 #define NL_CTRL_REPL_IN_PROGRESS 0x0002
 #define NL_CTRL_FULL_SYNC        0x0004
 
+#define LOGON_EXTRA_SIDS             0x0020
+#define LOGON_RESOURCE_GROUPS        0x0200 
+
+#define SE_GROUP_MANDATORY             0x00000001
+#define SE_GROUP_ENABLED_BY_DEFAULT    0x00000002
+#define SE_GROUP_ENABLED               0x00000004
+#define SE_GROUP_OWNER                         0x00000008
+#define SE_GROUP_USE_FOR_DENY_ONLY     0x00000010
+#define SE_GROUP_LOGON_ID              0xC0000000
+#define SE_GROUP_RESOURCE              0x20000000
+
+
 #if 0
 /* I think this is correct - it's what gets parsed on the wire. JRA. */
 /* NET_USER_INFO_2 */
-typedef struct net_user_info_2
-{
+typedef struct net_user_info_2 {
        uint32 ptr_user_info;
 
        NTTIME logon_time;            /* logon time */
@@ -145,8 +156,7 @@ typedef struct net_user_info_2
 #endif
 
 /* NET_USER_INFO_3 */
-typedef struct net_user_info_3
-{
+typedef struct net_user_info_3 {
        uint32 ptr_user_info;
 
        NTTIME logon_time;            /* logon time */
@@ -186,6 +196,13 @@ typedef struct net_user_info_3
        uint32 num_other_sids; /* number of foreign/trusted domain sids */
        uint32 buffer_other_sids;
        
+       /* The next three uint32 are not really part of user_info_3 but here
+        * for parsing convenience.  They are only valid in Kerberos PAC
+        * parsing - Guenther */
+       uint32 ptr_res_group_dom_sid;
+       uint32 res_group_count;
+       uint32 ptr_res_groups;
+
        UNISTR2 uni_user_name;    /* username unicode string */
        UNISTR2 uni_full_name;    /* user's full name unicode string */
        UNISTR2 uni_logon_script; /* logon script unicode string */
@@ -203,32 +220,26 @@ typedef struct net_user_info_3
 
        DOM_SID2 *other_sids; /* foreign/trusted domain SIDs */
        uint32 *other_sids_attrib;
-
 } NET_USER_INFO_3;
 
 
 /* NETLOGON_INFO_1 - pdc status info, i presume */
-typedef struct netlogon_1_info
-{
+typedef struct netlogon_1_info {
        uint32 flags;            /* 0x0 - undocumented */
        uint32 pdc_status;       /* 0x0 - undocumented */
-
 } NETLOGON_INFO_1;
 
 /* NETLOGON_INFO_2 - pdc status info, plus trusted domain info */
-typedef struct netlogon_2_info
-{
+typedef struct netlogon_2_info {
        uint32  flags;            /* 0x0 - undocumented */
        uint32  pdc_status;       /* 0x0 - undocumented */
        uint32  ptr_trusted_dc_name; /* pointer to trusted domain controller name */
        uint32  tc_status;           
        UNISTR2 uni_trusted_dc_name; /* unicode string - trusted dc name */
-
 } NETLOGON_INFO_2;
 
 /* NETLOGON_INFO_3 - logon status info, i presume */
-typedef struct netlogon_3_info
-{
+typedef struct netlogon_3_info {
        uint32 flags;            /* 0x0 - undocumented */
        uint32 logon_attempts;   /* number of logon attempts */
        uint32 reserved_1;       /* 0x0 - undocumented */
@@ -236,7 +247,6 @@ typedef struct netlogon_3_info
        uint32 reserved_3;       /* 0x0 - undocumented */
        uint32 reserved_4;       /* 0x0 - undocumented */
        uint32 reserved_5;       /* 0x0 - undocumented */
-
 } NETLOGON_INFO_3;
 
 /********************************************************
@@ -250,8 +260,7 @@ typedef struct netlogon_3_info
 
 /* NET_Q_LOGON_CTRL - LSA Netr Logon Control */
 
-typedef struct net_q_logon_ctrl_info
-{
+typedef struct net_q_logon_ctrl_info {
        uint32 ptr;
        UNISTR2 uni_server_name;
        uint32 function_code;
@@ -260,8 +269,7 @@ typedef struct net_q_logon_ctrl_info
 
 /* NET_R_LOGON_CTRL - LSA Netr Logon Control */
 
-typedef struct net_r_logon_ctrl_info
-{
+typedef struct net_r_logon_ctrl_info {
        uint32 switch_value;
        uint32 ptr;
 
@@ -273,22 +281,18 @@ typedef struct net_r_logon_ctrl_info
 } NET_R_LOGON_CTRL;
 
 
-typedef struct ctrl_data_info_5
-{
+typedef struct ctrl_data_info_5 {
        uint32          function_code;
        
        uint32          ptr_domain;
        UNISTR2         domain;
-       
 } CTRL_DATA_INFO_5;
 
-typedef struct ctrl_data_info_6
-{
+typedef struct ctrl_data_info_6 {
        uint32          function_code;
        
        uint32          ptr_domain;
        UNISTR2         domain;
-       
 } CTRL_DATA_INFO_6;
 
 
@@ -301,8 +305,7 @@ typedef struct ctrl_data_info_6
  ********************************************************/
 
 /* NET_Q_LOGON_CTRL2 - LSA Netr Logon Control 2 */
-typedef struct net_q_logon_ctrl2_info
-{
+typedef struct net_q_logon_ctrl2_info {
        uint32          ptr;             /* undocumented buffer pointer */
        UNISTR2         uni_server_name; /* server name, starting with two '\'s */
        
@@ -312,7 +315,6 @@ typedef struct net_q_logon_ctrl2_info
                CTRL_DATA_INFO_5 info5;
                CTRL_DATA_INFO_6 info6;
        } info;
-       
 } NET_Q_LOGON_CTRL2;
 
 /*******************************************************
@@ -322,8 +324,7 @@ typedef struct net_q_logon_ctrl2_info
  *******************************************************/
 
 /* NET_R_LOGON_CTRL2 - response to LSA Logon Control2 */
-typedef struct net_r_logon_ctrl2_info
-{
+typedef struct net_r_logon_ctrl2_info {
        uint32       switch_value;  /* 0x1, 0x3 */
        uint32       ptr;
 
@@ -336,13 +337,11 @@ typedef struct net_r_logon_ctrl2_info
        } logon;
 
        NTSTATUS status; /* return code */
-
 } NET_R_LOGON_CTRL2;
 
 /* NET_Q_GETDCNAME - Ask a DC for a trusted DC name */
 
-typedef struct net_q_getdcname
-{
+typedef struct net_q_getdcname {
        uint32  ptr_logon_server;
        UNISTR2 uni_logon_server;
        uint32  ptr_domainname;
@@ -351,103 +350,86 @@ typedef struct net_q_getdcname
 
 /* NET_R_GETDCNAME - Ask a DC for a trusted DC name */
 
-typedef struct net_r_getdcname
-{
+typedef struct net_r_getdcname {
        uint32  ptr_dcname;
        UNISTR2 uni_dcname;
        NTSTATUS status;
 } NET_R_GETDCNAME;
 
 /* NET_Q_TRUST_DOM_LIST - LSA Query Trusted Domains */
-typedef struct net_q_trust_dom_info
-{
+typedef struct net_q_trust_dom_info {
        uint32       ptr;             /* undocumented buffer pointer */
        UNISTR2      uni_server_name; /* server name, starting with two '\'s */
-
 } NET_Q_TRUST_DOM_LIST;
 
 #define MAX_TRUST_DOMS 1
 
 /* NET_R_TRUST_DOM_LIST - response to LSA Trusted Domains */
-typedef struct net_r_trust_dom_info
-{
+typedef struct net_r_trust_dom_info {
        UNISTR2 uni_trust_dom_name[MAX_TRUST_DOMS];
 
        NTSTATUS status; /* return code */
-
 } NET_R_TRUST_DOM_LIST;
 
 
 /* NEG_FLAGS */
-typedef struct neg_flags_info
-{
-    uint32 neg_flags; /* negotiated flags */
-
+typedef struct neg_flags_info {
+       uint32 neg_flags; /* negotiated flags */
 } NEG_FLAGS;
 
 
 /* NET_Q_REQ_CHAL */
-typedef struct net_q_req_chal_info
-{
-    uint32  undoc_buffer; /* undocumented buffer pointer */
-    UNISTR2 uni_logon_srv; /* logon server unicode string */
-    UNISTR2 uni_logon_clnt; /* logon client unicode string */
-    DOM_CHAL clnt_chal; /* client challenge */
-
+typedef struct net_q_req_chal_info {
+       uint32  undoc_buffer; /* undocumented buffer pointer */
+       UNISTR2 uni_logon_srv; /* logon server unicode string */
+       UNISTR2 uni_logon_clnt; /* logon client unicode string */
+       DOM_CHAL clnt_chal; /* client challenge */
 } NET_Q_REQ_CHAL;
 
 
 /* NET_R_REQ_CHAL */
-typedef struct net_r_req_chal_info
-{
+typedef struct net_r_req_chal_info {
        DOM_CHAL srv_chal; /* server challenge */
        NTSTATUS status; /* return code */
 } NET_R_REQ_CHAL;
 
 /* NET_Q_AUTH */
-typedef struct net_q_auth_info
-{
+typedef struct net_q_auth_info {
        DOM_LOG_INFO clnt_id; /* client identification info */
        DOM_CHAL clnt_chal;     /* client-calculated credentials */
 } NET_Q_AUTH;
 
 /* NET_R_AUTH */
-typedef struct net_r_auth_info
-{
+typedef struct net_r_auth_info {
        DOM_CHAL srv_chal;     /* server-calculated credentials */
        NTSTATUS status; /* return code */
 } NET_R_AUTH;
 
 /* NET_Q_AUTH_2 */
-typedef struct net_q_auth2_info
-{
-    DOM_LOG_INFO clnt_id; /* client identification info */
-    DOM_CHAL clnt_chal;     /* client-calculated credentials */
-
-    NEG_FLAGS clnt_flgs; /* usually 0x0000 01ff */
+typedef struct net_q_auth2_info {
+       DOM_LOG_INFO clnt_id; /* client identification info */
+       DOM_CHAL clnt_chal;     /* client-calculated credentials */
 
+       NEG_FLAGS clnt_flgs; /* usually 0x0000 01ff */
 } NET_Q_AUTH_2;
 
 
 /* NET_R_AUTH_2 */
-typedef struct net_r_auth2_info
-{
+typedef struct net_r_auth2_info {
        DOM_CHAL srv_chal;     /* server-calculated credentials */
        NEG_FLAGS srv_flgs; /* usually 0x0000 01ff */
        NTSTATUS status; /* return code */
 } NET_R_AUTH_2;
 
 /* NET_Q_AUTH_3 */
-typedef struct net_q_auth3_info
-{
-    DOM_LOG_INFO clnt_id;      /* client identification info */
-    DOM_CHAL clnt_chal;                /* client-calculated credentials */
-    NEG_FLAGS clnt_flgs;       /* usually 0x6007 ffff */
+typedef struct net_q_auth3_info {
+       DOM_LOG_INFO clnt_id;   /* client identification info */
+       DOM_CHAL clnt_chal;             /* client-calculated credentials */
+       NEG_FLAGS clnt_flgs;    /* usually 0x6007 ffff */
 } NET_Q_AUTH_3;
 
 /* NET_R_AUTH_3 */
-typedef struct net_r_auth3_info
-{
+typedef struct net_r_auth3_info {
        DOM_CHAL srv_chal;      /* server-calculated credentials */
        NEG_FLAGS srv_flgs;     /* usually 0x6007 ffff */
        uint32 unknown;         /* 0x0000045b */
@@ -456,25 +438,20 @@ typedef struct net_r_auth3_info
 
 
 /* NET_Q_SRV_PWSET */
-typedef struct net_q_srv_pwset_info
-{
-    DOM_CLNT_INFO clnt_id; /* client identification/authentication info */
-    uint8 pwd[16]; /* new password - undocumented. */
-
+typedef struct net_q_srv_pwset_info {
+       DOM_CLNT_INFO clnt_id; /* client identification/authentication info */
+       uint8 pwd[16]; /* new password - undocumented. */
 } NET_Q_SRV_PWSET;
     
 /* NET_R_SRV_PWSET */
-typedef struct net_r_srv_pwset_info
-{
-    DOM_CRED srv_cred;     /* server-calculated credentials */
-
-  NTSTATUS status; /* return code */
+typedef struct net_r_srv_pwset_info {
+       DOM_CRED srv_cred;     /* server-calculated credentials */
 
+       NTSTATUS status; /* return code */
 } NET_R_SRV_PWSET;
 
 /* NET_ID_INFO_2 */
-typedef struct net_network_info_2
-{
+typedef struct net_network_info_2 {
        uint32            ptr_id_info2;        /* pointer to id_info_2 */
        UNIHDR            hdr_domain_name;     /* domain name unicode header */
        uint32            param_ctrl;          /* param control (0x2) */
@@ -490,12 +467,10 @@ typedef struct net_network_info_2
        UNISTR2           uni_wksta_name;      /* workgroup name unicode string */
        STRING2           nt_chal_resp;        /* nt challenge response */
        STRING2           lm_chal_resp;        /* lm challenge response */
-
 } NET_ID_INFO_2;
 
 /* NET_ID_INFO_1 */
-typedef struct id_info_1
-{
+typedef struct id_info_1 {
        uint32            ptr_id_info1;        /* pointer to id_info_1 */
        UNIHDR            hdr_domain_name;     /* domain name unicode header */
        uint32            param_ctrl;          /* param control */
@@ -507,81 +482,64 @@ typedef struct id_info_1
        UNISTR2           uni_domain_name;     /* domain name unicode string */
        UNISTR2           uni_user_name;       /* user name unicode string */
        UNISTR2           uni_wksta_name;      /* workgroup name unicode string */
-
 } NET_ID_INFO_1;
 
 #define INTERACTIVE_LOGON_TYPE 1
 #define NET_LOGON_TYPE 2
 
 /* NET_ID_INFO_CTR */
-typedef struct net_id_info_ctr_info
-{
-  uint16         switch_value;
-  
-  union
-  {
-    NET_ID_INFO_1 id1; /* auth-level 1 - interactive user login */
-    NET_ID_INFO_2 id2; /* auth-level 2 - workstation referred login */
-
-  } auth;
+typedef struct net_id_info_ctr_info {
+       uint16         switch_value;
   
+       union {
+               NET_ID_INFO_1 id1; /* auth-level 1 - interactive user login */
+               NET_ID_INFO_2 id2; /* auth-level 2 - workstation referred login */
+       } auth;
 } NET_ID_INFO_CTR;
 
 /* SAM_INFO - sam logon/off id structure */
-typedef struct sam_info
-{
-  DOM_CLNT_INFO2  client;
-  uint32          ptr_rtn_cred; /* pointer to return credentials */
-  DOM_CRED        rtn_cred; /* return credentials */
-  uint16          logon_level;
-  NET_ID_INFO_CTR *ctr;
-
+typedef struct sam_info {
+       DOM_CLNT_INFO2  client;
+       uint32          ptr_rtn_cred; /* pointer to return credentials */
+       DOM_CRED        rtn_cred; /* return credentials */
+       uint16          logon_level;
+       NET_ID_INFO_CTR *ctr;
 } DOM_SAM_INFO;
 
 /* NET_Q_SAM_LOGON */
-typedef struct net_q_sam_logon_info
-{
-    DOM_SAM_INFO sam_id;
+typedef struct net_q_sam_logon_info {
+       DOM_SAM_INFO sam_id;
        uint16          validation_level;
-
 } NET_Q_SAM_LOGON;
 
 /* NET_R_SAM_LOGON */
-typedef struct net_r_sam_logon_info
-{
-    uint32 buffer_creds; /* undocumented buffer pointer */
-    DOM_CRED srv_creds; /* server credentials.  server time stamp appears to be ignored. */
+typedef struct net_r_sam_logon_info {
+       uint32 buffer_creds; /* undocumented buffer pointer */
+       DOM_CRED srv_creds; /* server credentials.  server time stamp appears to be ignored. */
     
        uint16 switch_value; /* 3 - indicates type of USER INFO */
-    NET_USER_INFO_3 *user;
-
-    uint32 auth_resp; /* 1 - Authoritative response; 0 - Non-Auth? */
+       NET_USER_INFO_3 *user;
 
-  NTSTATUS status; /* return code */
+       uint32 auth_resp; /* 1 - Authoritative response; 0 - Non-Auth? */
 
+       NTSTATUS status; /* return code */
 } NET_R_SAM_LOGON;
 
 
 /* NET_Q_SAM_LOGOFF */
-typedef struct net_q_sam_logoff_info
-{
-    DOM_SAM_INFO sam_id;
-
+typedef struct net_q_sam_logoff_info {
+       DOM_SAM_INFO sam_id;
 } NET_Q_SAM_LOGOFF;
 
 /* NET_R_SAM_LOGOFF */
-typedef struct net_r_sam_logoff_info
-{
-    uint32 buffer_creds; /* undocumented buffer pointer */
-    DOM_CRED srv_creds; /* server credentials.  server time stamp appears to be ignored. */
-    
-  NTSTATUS status; /* return code */
-
+typedef struct net_r_sam_logoff_info {
+       uint32 buffer_creds; /* undocumented buffer pointer */
+       DOM_CRED srv_creds; /* server credentials.  server time stamp appears to be ignored. */
+       NTSTATUS status; /* return code */
 } NET_R_SAM_LOGOFF;
 
 /* NET_Q_SAM_SYNC */
-typedef struct net_q_sam_sync_info
-{
+typedef struct net_q_sam_sync_info {
        UNISTR2 uni_srv_name; /* \\PDC */
        UNISTR2 uni_cli_name; /* BDC */
        DOM_CRED cli_creds;
@@ -592,19 +550,16 @@ typedef struct net_q_sam_sync_info
        uint32 sync_context;
 
        uint32 max_size;       /* preferred maximum length */
-
 } NET_Q_SAM_SYNC;
 
 /* SAM_DELTA_HDR */
-typedef struct sam_delta_hdr_info
-{
+typedef struct sam_delta_hdr_info {
        uint16 type;  /* type of structure attached */
        uint16 type2;
        uint32 target_rid;
 
        uint32 type3;
        uint32 ptr_delta;
-
 } SAM_DELTA_HDR;
 
 /* LOCKOUT_STRING */
@@ -617,7 +572,6 @@ typedef struct account_lockout_string {
        UINT64_S reset_count;
        uint32 bad_attempt_lockout;
        uint32 dummy;
-
 } LOCKOUT_STRING;
 
 /* HDR_LOCKOUT_STRING */
@@ -625,12 +579,10 @@ typedef struct hdr_account_lockout_string {
        uint16 size;
        uint16 length;
        uint32 buffer;
-
 } HDR_LOCKOUT_STRING;
 
 /* SAM_DOMAIN_INFO (0x1) */
-typedef struct sam_domain_info_info
-{
+typedef struct sam_domain_info_info {
        UNIHDR hdr_dom_name;
        UNIHDR hdr_oem_info;
 
@@ -666,13 +618,10 @@ typedef struct sam_domain_info_info
        uint32 unknown6;
        uint32 unknown7;
        uint32 unknown8;
-
-
 } SAM_DOMAIN_INFO;
 
 /* SAM_GROUP_INFO (0x2) */
-typedef struct sam_group_info_info
-{
+typedef struct sam_group_info_info {
        UNIHDR hdr_grp_name;
        DOM_GID gid;
        UNIHDR hdr_grp_desc;
@@ -682,12 +631,10 @@ typedef struct sam_group_info_info
        UNISTR2 uni_grp_name;
        UNISTR2 uni_grp_desc;
        RPC_DATA_BLOB buf_sec_desc;
-
 } SAM_GROUP_INFO;
 
 /* SAM_PWD */
-typedef struct sam_passwd_info
-{
+typedef struct sam_passwd_info {
        /* this structure probably contains password history */
        /* this is probably a count of lm/nt pairs */
        uint32 unk_0; /* 0x0000 0002 */
@@ -700,12 +647,10 @@ typedef struct sam_passwd_info
 
        UNIHDR hdr_empty_lm;
        UNIHDR hdr_empty_nt;
-
 } SAM_PWD;
 
 /* SAM_ACCOUNT_INFO (0x5) */
-typedef struct sam_account_info_info
-{
+typedef struct sam_account_info_info {
        UNIHDR hdr_acct_name;
        UNIHDR hdr_full_name;
 
@@ -765,12 +710,10 @@ typedef struct sam_account_info_info
        SAM_PWD pass;
        RPC_DATA_BLOB buf_sec_desc;
        UNISTR2 uni_profile;
-
 } SAM_ACCOUNT_INFO;
 
 /* SAM_GROUP_MEM_INFO (0x8) */
-typedef struct sam_group_mem_info_info
-{
+typedef struct sam_group_mem_info_info {
        uint32 ptr_rids;
        uint32 ptr_attribs;
        uint32 num_members;
@@ -785,8 +728,7 @@ typedef struct sam_group_mem_info_info
 } SAM_GROUP_MEM_INFO;
 
 /* SAM_ALIAS_INFO (0x9) */
-typedef struct sam_alias_info_info
-{
+typedef struct sam_alias_info_info {
        UNIHDR hdr_als_name;
        uint32 als_rid;
        BUFHDR2 hdr_sec_desc;  /* security descriptor */
@@ -796,12 +738,10 @@ typedef struct sam_alias_info_info
        UNISTR2 uni_als_name;
        RPC_DATA_BLOB buf_sec_desc;
        UNISTR2 uni_als_desc;
-
 } SAM_ALIAS_INFO;
 
 /* SAM_ALIAS_MEM_INFO (0xC) */
-typedef struct sam_alias_mem_info_info
-{
+typedef struct sam_alias_mem_info_info {
        uint32 num_members;
        uint32 ptr_members;
        uint8 unknown[16];
@@ -809,13 +749,11 @@ typedef struct sam_alias_mem_info_info
        uint32 num_sids;
        uint32 *ptr_sids;
        DOM_SID2 *sids;
-
 } SAM_ALIAS_MEM_INFO;
 
 
 /* SAM_DELTA_POLICY (0x0D) */
-typedef struct
-{
+typedef struct {
        uint32   max_log_size; /* 0x5000 */
        UINT64_S audit_retention_period; /* 0 */
        uint32   auditing_mode; /* 0 */
@@ -844,8 +782,7 @@ typedef struct
 } SAM_DELTA_POLICY;
 
 /* SAM_DELTA_TRUST_DOMS */
-typedef struct
-{
+typedef struct {
        uint32 buf_size;
        SEC_DESC *sec_desc;
        DOM_SID2 sid;
@@ -860,12 +797,10 @@ typedef struct
 
        uint32 unknown3;
        UNISTR2 domain;
-
 } SAM_DELTA_TRUSTDOMS;
 
 /* SAM_DELTA_PRIVS (0x10) */
-typedef struct
-{
+typedef struct {
        DOM_SID2 sid;
 
        uint32 priv_count;
@@ -896,8 +831,7 @@ typedef struct
 } SAM_DELTA_PRIVS;
 
 /* SAM_DELTA_SECRET */
-typedef struct
-{
+typedef struct {
        uint32 buf_size;
        SEC_DESC *sec_desc;
        UNISTR2 secret;
@@ -928,19 +862,16 @@ typedef struct
 
        uint32 buf_size3;
        SEC_DESC *sec_desc2;
-
 } SAM_DELTA_SECRET;
 
 /* SAM_DELTA_MOD_COUNT (0x16) */
-typedef struct
-{
+typedef struct {
         uint32 seqnum;
         uint32 dom_mod_count_ptr;
        UINT64_S dom_mod_count;  /* domain mod count at last sync */
 } SAM_DELTA_MOD_COUNT;
 
-typedef union sam_delta_ctr_info
-{
+typedef union sam_delta_ctr_info {
        SAM_DOMAIN_INFO    domain_info ;
        SAM_GROUP_INFO     group_info  ;
        SAM_ACCOUNT_INFO   account_info;
@@ -955,8 +886,7 @@ typedef union sam_delta_ctr_info
 } SAM_DELTA_CTR;
 
 /* NET_R_SAM_SYNC */
-typedef struct net_r_sam_sync_info
-{
+typedef struct net_r_sam_sync_info {
        DOM_CRED srv_creds;
 
        uint32 sync_context;
@@ -973,8 +903,7 @@ typedef struct net_r_sam_sync_info
 } NET_R_SAM_SYNC;
 
 /* NET_Q_SAM_DELTAS */
-typedef struct net_q_sam_deltas_info
-{
+typedef struct net_q_sam_deltas_info {
        UNISTR2 uni_srv_name;
        UNISTR2 uni_cli_name;
        DOM_CRED cli_creds;
@@ -984,12 +913,10 @@ typedef struct net_q_sam_deltas_info
        UINT64_S dom_mod_count;  /* domain mod count at last sync */
 
        uint32 max_size;       /* preferred maximum length */
-
 } NET_Q_SAM_DELTAS;
 
 /* NET_R_SAM_DELTAS */
-typedef struct net_r_sam_deltas_info
-{
+typedef struct net_r_sam_deltas_info {
        DOM_CRED srv_creds;
 
        UINT64_S dom_mod_count;   /* new domain mod count */
diff --git a/source3/include/rpc_ntsvcs.h b/source3/include/rpc_ntsvcs.h
new file mode 100644 (file)
index 0000000..947794b
--- /dev/null
@@ -0,0 +1,147 @@
+/* 
+   Unix SMB/CIFS implementation.
+   SMB parameters and setup
+   Copyright (C) Gerald (Jerry) Carter        2005
+   
+   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.
+*/
+
+#ifndef _RPC_NTSVCS_H /* _RPC_NTSVCS_H */
+#define _RPC_NTSVCS_H
+
+/* ntsvcs pipe */
+
+#define NTSVCS_GET_VERSION             0x02
+#define NTSVCS_VALIDATE_DEVICE_INSTANCE        0x06
+#define NTSVCS_GET_ROOT_DEVICE_INSTANCE        0x07
+#define NTSVCS_GET_DEVICE_LIST         0x0a
+#define NTSVCS_GET_DEVICE_LIST_SIZE    0x0b
+#define NTSVCS_GET_DEVICE_REG_PROPERTY 0x0d
+#define NTSVCS_HW_PROFILE_FLAGS                0x28
+#define NTSVCS_GET_HW_PROFILE_INFO     0x29
+#define NTSVCS_GET_VERSION_INTERNAL    0x3e
+
+
+/**************************/
+
+typedef struct {
+       /* nothing in the request */
+       uint32 dummy;
+} NTSVCS_Q_GET_VERSION;
+
+typedef struct {
+       uint32 version;
+       WERROR status;
+} NTSVCS_R_GET_VERSION;
+
+
+/**************************/
+
+typedef struct {
+       UNISTR2 *devicename;
+       uint32 flags;
+} NTSVCS_Q_GET_DEVICE_LIST_SIZE;
+
+typedef struct {
+       uint32 size;
+       WERROR status;
+} NTSVCS_R_GET_DEVICE_LIST_SIZE;
+
+
+/**************************/
+
+typedef struct {
+       UNISTR2 *devicename;
+       uint32 buffer_size;
+       uint32 flags;
+} NTSVCS_Q_GET_DEVICE_LIST;
+
+typedef struct {
+       UNISTR2 devicepath;
+       uint32 needed;
+       WERROR status;
+} NTSVCS_R_GET_DEVICE_LIST;
+
+/**************************/
+
+typedef struct {
+       UNISTR2 devicepath;
+       uint32 flags;
+} NTSVCS_Q_VALIDATE_DEVICE_INSTANCE;
+
+typedef struct {
+       WERROR status;
+} NTSVCS_R_VALIDATE_DEVICE_INSTANCE;
+
+/**************************/
+
+#define DEV_REGPROP_DESC       1
+
+typedef struct {
+       UNISTR2 devicepath;
+       uint32 property;
+       uint32 unknown2;
+       uint32 buffer_size1;
+       uint32 buffer_size2;
+       uint32 unknown5;
+} NTSVCS_Q_GET_DEVICE_REG_PROPERTY;
+
+typedef struct {
+       uint32 unknown1;
+       REGVAL_BUFFER value;
+       uint32 size;
+       uint32 needed;
+       WERROR status;
+} NTSVCS_R_GET_DEVICE_REG_PROPERTY;
+
+
+/**************************/
+
+typedef struct {
+       uint32 index;
+       uint8 *buffer;
+       uint32 buffer_size;
+       uint32 unknown1;
+} NTSVCS_Q_GET_HW_PROFILE_INFO;
+
+typedef struct {
+       uint32 buffer_size;     /* the size (not included in the reply) 
+                                  if just matched from the request */
+       uint8 *buffer;
+       WERROR status;
+} NTSVCS_R_GET_HW_PROFILE_INFO;
+
+
+/**************************/
+
+typedef struct {
+       uint32 unknown1;
+       UNISTR2 devicepath;
+       uint32 unknown2;
+       uint32 unknown3;
+       uint32 unknown4;
+       uint32 unknown5;
+       uint32 unknown6;
+       uint32 unknown7;
+} NTSVCS_Q_HW_PROFILE_FLAGS;
+
+typedef struct {
+       uint32 unknown1;
+       uint32 unknown2;
+       uint32 unknown3;
+       WERROR status;
+} NTSVCS_R_HW_PROFILE_FLAGS;
+
+#endif /* _RPC_NTSVCS_H */
diff --git a/source3/include/rpc_perfcount.h b/source3/include/rpc_perfcount.h
new file mode 100644 (file)
index 0000000..0e3a6eb
--- /dev/null
@@ -0,0 +1,106 @@
+#ifndef _RPC_PERFCOUNT_H
+#define _RPC_PERFCOUNT_H
+
+typedef struct perf_counter_definition
+{
+       /* sizeof(PERF_COUNTER_DEFINITION) */
+       uint32 ByteLength;
+       uint32 CounterNameTitleIndex;
+       uint32 CounterNameTitlePointer;
+       uint32 CounterHelpTitleIndex;
+       uint32 CounterHelpTitlePointer;
+       uint32 DefaultScale;
+       uint32 DetailLevel;
+       uint32 CounterType;
+       uint32 CounterSize;
+       uint32 CounterOffset;
+}
+PERF_COUNTER_DEFINITION;
+
+typedef struct perf_counter_block
+{
+       /* Total size of the data block, including all data plus this header */
+       uint32 ByteLength;
+       uint8 *data;
+}
+PERF_COUNTER_BLOCK;
+
+typedef struct perf_instance_definition
+{
+       /* Total size of the instance definition, including the length of the terminated Name string */
+       uint32 ByteLength;
+       uint32 ParentObjectTitleIndex;
+       uint32 ParentObjectTitlePointer;
+       uint32 UniqueID;
+       /* From the start of the PERF_INSTANCE_DEFINITION, the byte offset to the start of the Name string */
+       uint32 NameOffset;
+       uint32 NameLength;
+       /* Unicode string containing the name for the instance */
+       uint8 *data;
+       PERF_COUNTER_BLOCK counter_data;
+}
+PERF_INSTANCE_DEFINITION;
+
+typedef struct perf_object_type
+{
+       /* Total size of the object block, including all PERF_INSTANCE_DEFINITIONs,
+          PERF_COUNTER_DEFINITIONs and PERF_COUNTER_BLOCKs in bytes */
+       uint32 TotalByteLength;
+       /* Size of this PERF_OBJECT_TYPE plus all PERF_COUNTER_DEFINITIONs in bytes */
+       uint32 DefinitionLength;
+       /* Size of this PERF_OBJECT_TYPE */
+       uint32 HeaderLength;
+       uint32 ObjectNameTitleIndex;
+       uint32 ObjectNameTitlePointer;
+       uint32 ObjectHelpTitleIndex;
+       uint32 ObjectHelpTitlePointer;
+       uint32 DetailLevel;
+       uint32 NumCounters;
+       uint32 DefaultCounter;
+       uint32 NumInstances;
+       uint32 CodePage;
+       UINT64_S PerfTime;
+       UINT64_S PerfFreq;
+       PERF_COUNTER_DEFINITION *counters;
+       PERF_INSTANCE_DEFINITION *instances;
+       PERF_COUNTER_BLOCK counter_data;
+}
+PERF_OBJECT_TYPE;
+
+/* PerfCounter Inner Buffer structs */
+typedef struct perf_data_block
+{
+       /* hardcoded to read "P.E.R.F" */
+       uint16 Signature[4];
+       uint32 LittleEndian;
+       /* both currently hardcoded to 1 */
+       uint32 Version;
+       uint32 Revision;
+       /* bytes of PERF_OBJECT_TYPE data, does NOT include the PERF_DATA_BLOCK */
+       uint32 TotalByteLength;
+       /* size of PERF_DATA_BLOCK including the uint8 *data */
+       uint32 HeaderLength;
+       /* number of PERF_OBJECT_TYPE structures encoded */
+       uint32 NumObjectTypes;
+       uint32 DefaultObject;
+       SYSTEMTIME SystemTime;
+       /* This will guarantee that we're on a 64-bit boundary before we encode
+          PerfTime, and having it there will make my offset math much easier. */
+       uint32 Padding;
+       /* Now when I'm marshalling this, I'll need to call prs_align_uint64() 
+          before I start encodint the UINT64_S structs */
+       /* clock rate * seconds uptime */
+       UINT64_S PerfTime;
+       /* The clock rate of the CPU */
+       UINT64_S PerfFreq; 
+       /* used for high-res timers -- for now PerfTime * 10e7 */
+       UINT64_S PerfTime100nSec;
+       uint32 SystemNameLength;
+       uint32 SystemNameOffset;
+       /* The SystemName, in unicode, terminated */
+       uint8* data;
+       PERF_OBJECT_TYPE *objects;
+} 
+PERF_DATA_BLOCK;
+
+#endif /* _RPC_PERFCOUNT_H */
diff --git a/source3/include/rpc_perfcount_defs.h b/source3/include/rpc_perfcount_defs.h
new file mode 100644 (file)
index 0000000..3999a68
--- /dev/null
@@ -0,0 +1,73 @@
+#ifndef _RPC_PERFCOUNT_DEFS_H
+#define _RPC_PERFCOUNT_DEFS_H
+
+/*
+ * The following #defines match what is in winperf.h. 
+ * See that include file for more details, or look up
+ * "Performance Data Format" on MSDN
+ * 
+ * Rather than including them in rpc_perfcount.h, they
+ * were broken out into a separate .h file so that they
+ * can be included by other programs that need this info
+ * without pulling in everything else samba-related.
+ */
+
+#define PERF_NO_INSTANCES             -1
+#define PERF_NO_UNIQUE_ID            -1
+
+/* These determine the data size */
+#define PERF_SIZE_DWORD               0x00000000
+#define PERF_SIZE_LARGE               0x00000100
+#define PERF_SIZE_ZERO                0x00000200
+#define PERF_SIZE_VARIABLE_LEN        0x00000300
+
+/* These determine the usage of the counter */
+#define PERF_TYPE_NUMBER              0x00000000
+#define PERF_TYPE_COUNTER             0x00000400
+#define PERF_TYPE_TEXT                0x00000800
+#define PERF_TYPE_ZERO                0x00000C00
+
+/* If PERF_TYPE_NUMBER was selected, these provide display information */
+#define PERF_NUMBER_HEX               0x00000000
+#define PERF_NUMBER_DECIMAL           0x00010000
+#define PERF_NUMBER_DEC_1000          0x00020000
+
+/* If PERF_TYPE_COUNTER was selected, these provide display information */
+#define PERF_COUNTER_VALUE            0x00000000
+#define PERF_COUNTER_RATE             0x00010000
+#define PERF_COUNTER_FRACTION         0x00020000
+#define PERF_COUNTER_BASE             0x00030000
+#define PERF_COUNTER_ELAPSED          0x00040000
+#define PERF_COUNTER_QUEUELEN         0x00050000
+#define PERF_COUNTER_HISTOGRAM        0x00060000
+#define PERF_COUNTER_PRECISION        0x00070000
+
+/* If PERF_TYPE_TEXT was selected, these provide display information */
+#define PERF_TEXT_UNICODE             0x00000000
+#define PERF_TEXT_ASCII               0x00010000
+
+/* These provide information for which tick count to use when computing elapsed interval */
+#define PERF_TIMER_TICK               0x00000000
+#define PERF_TIMER_100NS              0x00100000
+#define PERF_OBJECT_TIMER             0x00200000
+
+/* These affect how the data is manipulated prior to being displayed */
+#define PERF_DELTA_COUNTER            0x00400000
+#define PERF_DELTA_BASE               0x00800000
+#define PERF_INVERSE_COUNTER          0x01000000
+#define PERF_MULTI_COUNTER            0x02000000
+
+/* These determine if any text gets added when the value is displayed */
+#define PERF_DISPLAY_NO_SUFFIX        0x00000000
+#define PERF_DISPLAY_PER_SEC          0x10000000
+#define PERF_DISPLAY_PERCENT          0x20000000
+#define PERF_DISPLAY_SECONDS          0x30000000
+#define PERF_DISPLAY_NOSHOW           0x40000000
+
+/* These determine the DetailLevel of the counter */
+#define PERF_DETAIL_NOVICE            100
+#define PERF_DETAIL_ADVANCED          200
+#define PERF_DETAIL_EXPERT            300
+#define PERF_DETAIL_WIZARD            400
+
+#endif /* _RPC_PERFCOUNT_DEFS_H */
index f6ddf5b9adffda5f11ac0d8ca4105ae0b1d364b3..b24b640237fec10d1ecf0a9fd0598293a7d4aa01 100644 (file)
@@ -25,8 +25,6 @@
 #ifndef _RPC_REG_H /* _RPC_REG_H */
 #define _RPC_REG_H 
 
-#include "reg_objects.h"
-
 /* RPC opnum */
 
 #define REG_OPEN_HKCR          0x00
@@ -50,6 +48,7 @@
 #define REG_SET_VALUE          0x16
 #define REG_SHUTDOWN           0x18
 #define REG_ABORT_SHUTDOWN     0x19
+#define REG_OPEN_HKPT          0x20
 #define REG_GETVERSION         0x1a
 #define REG_SHUTDOWN_EX                0x1e
 
@@ -63,6 +62,9 @@
 #define KEY_HKLM               "HKLM"
 #define KEY_HKU                        "HKU"
 #define KEY_HKCR               "HKCR"
+#define KEY_HKPD               "HKPD"
+#define KEY_HKPT               "HKPT"
+#define KEY_SERVICES           "HKLM\\SYSTEM\\CurrentControlSet\\Services"
 #define KEY_PRINTING           "HKLM\\SYSTEM\\CurrentControlSet\\Control\\Print"
 #define KEY_PRINTING_2K                "HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Print\\Printers"
 #define KEY_PRINTING_PORTS     "HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Ports"
 #define REG_FULL_RESOURCE_DESCRIPTOR   9
 #define REG_RESOURCE_REQUIREMENTS_LIST 10
 
+/*
+ * Registry key types
+ *     Most keys are going to be GENERIC -- may need a better name?
+ *     HKPD and HKPT are used by reg_perfcount.c
+ *             they are special keys that congtain performance data
+ */
+#define REG_KEY_GENERIC                0
+#define REG_KEY_HKPD           1
+#define REG_KEY_HKPT           2
+
 /* 
  * container for function pointers to enumeration routines
  * for vitural registry view 
@@ -108,9 +120,8 @@ typedef struct {
 /* structure to store the registry handles */
 
 typedef struct _RegistryKey {
-       struct _RegistryKey *prev, *next;
-
-       pstring         name;           /* full name of registry key */
+       uint32          type;
+       char            *name;          /* full name of registry key */
        uint32          access_granted;
        REGISTRY_HOOK   *hook;  
 } REGISTRY_KEY;
index fb829558d442e61ee499ac0cc4e2e2881ac33f81..6067587654e123c202ed16809d45b39521739775 100644 (file)
@@ -26,8 +26,6 @@
 #ifndef _RPC_SAMR_H /* _RPC_SAMR_H */
 #define _RPC_SAMR_H 
 
-#include "rpc_misc.h"
-
 /*******************************************************************
  the following information comes from a QuickView on samsrv.dll,
  and gives an idea of exactly what is needed:
index b2b97e391e00842812abc65eb15dd9ae785f3f7e..c385e41fd30954ad128bce8f392d458b1b7ee108 100644 (file)
@@ -481,13 +481,16 @@ typedef struct standard_mapping {
          SC_RIGHT_MGR_ENUMERATE_SERVICE        | \
          SC_RIGHT_MGR_QUERY_LOCK_STATUS )
 
-#define SC_MANAGER_ALL_ACCESS \
+#define SC_MANAGER_EXECUTE_ACCESS SC_MANAGER_READ_ACCESS
+
+#define SC_MANAGER_WRITE_ACCESS \
        ( STANDARD_RIGHTS_REQUIRED_ACCESS       | \
          SC_MANAGER_READ_ACCESS                | \
          SC_RIGHT_MGR_CREATE_SERVICE           | \
          SC_RIGHT_MGR_LOCK                     | \
          SC_RIGHT_MGR_MODIFY_BOOT_CONFIG )
 
+#define SC_MANAGER_ALL_ACCESS SC_MANAGER_WRITE_ACCESS
 
 /* Service Object Bits */ 
 
@@ -515,12 +518,14 @@ typedef struct standard_mapping {
          SC_RIGHT_SVC_STOP                     | \
          SC_RIGHT_SVC_PAUSE_CONTINUE )
 
-#define SERVICE_ALL_ACCESS \
+#define SERVICE_WRITE_ACCESS \
        ( STANDARD_RIGHTS_REQUIRED_ACCESS       | \
          SERVICE_READ_ACCESS                   | \
          SERVICE_EXECUTE_ACCESS                | \
          SC_RIGHT_SVC_CHANGE_CONFIG )
 
+#define SERVICE_ALL_ACCESS SERVICE_WRITE_ACCESS
+
           
 
 /*
index 77dd004fed40a4156b3909c88ed5b6c2529d761f..443a6588a661ab4a01bc79454a60765017810393 100644 (file)
 #ifndef _RPC_SVCCTL_H /* _RPC_SVCCTL_H */
 #define _RPC_SVCCTL_H 
 
-
 /* svcctl pipe */
 
 #define SVCCTL_CLOSE_SERVICE                   0x00
 #define SVCCTL_CONTROL_SERVICE                 0x01
+#define SVCCTL_LOCK_SERVICE_DB                 0x03
+#define SVCCTL_QUERY_SERVICE_SEC               0x04    /* not impmenented */
+#define SVCCTL_SET_SEVICE_SEC                  0x05    /* not implemented */
 #define SVCCTL_QUERY_STATUS                    0x06
+#define SVCCTL_UNLOCK_SERVICE_DB               0x08
 #define SVCCTL_ENUM_DEPENDENT_SERVICES_W       0x0d
 #define SVCCTL_ENUM_SERVICES_STATUS_W          0x0e
 #define SVCCTL_OPEN_SCMANAGER_W                        0x0f
 #define SVCCTL_CONTROL_STOP                    0x00000001
 #define SVCCTL_CONTROL_PAUSE                   0x00000002
 #define SVCCTL_CONTROL_CONTINUE                        0x00000003
-#define SVCCTL_CONTROL_SHUTDOWN                 0x00000004
+#define SVCCTL_CONTROL_INTERROGATE             0x00000004
+#define SVCCTL_CONTROL_SHUTDOWN                 0x00000005
 
 #define SVC_HANDLE_IS_SCM                      0x0000001
 #define SVC_HANDLE_IS_SERVICE                  0x0000002
+#define SVC_HANDLE_IS_DBLOCK                   0x0000003
 
-#define SVC_STATUS_PROCESS_INFO                 0x00000001
+#define SVC_STATUS_PROCESS_INFO                 0x00000000
 
-#define SVCCTL_SCRIPT_DIR  "/svcctl/"
+/* where we assume the location of the service control scripts */
+#define SVCCTL_SCRIPT_DIR  "svcctl"
 
 /* utility structures for RPCs */
 
@@ -127,13 +133,7 @@ typedef struct {
 } SERVICE_STATUS;
 
 typedef struct {
-       uint32 type;
-       uint32 state;
-       uint32 controls_accepted;
-       uint32 win32_exit_code;
-       uint32 service_exit_code;
-       uint32 check_point;
-       uint32 wait_hint;
+       SERVICE_STATUS status;
        uint32 process_id;
        uint32 service_flags;
 } SERVICE_STATUS_PROCESS;
@@ -158,7 +158,8 @@ typedef struct {
 } SERVICE_CONFIG;
 
 typedef struct {
-        UNISTR2 *description;
+       uint32 unknown; 
+        UNISTR description;
 } SERVICE_DESCRIPTION;
 
 typedef struct {
@@ -168,20 +169,12 @@ typedef struct {
 
 typedef struct {
         uint32 reset_period;
-        UNISTR2 *rebootmsg;
+        UNISTR2 *rebootmsg;    /* i have no idea if these are UNISTR2's.  I can't get a good trace */
         UNISTR2 *command;
-        uint32  nActions;
-        SC_ACTION *saActions;
-        UNISTR2 *description;
+        uint32  num_actions;
+        SC_ACTION *actions;
 } SERVICE_FAILURE_ACTIONS;
 
-
-typedef struct SCM_info_struct {
-       uint32  type;                    /* should be SVC_HANDLE_IS_SCM */
-       pstring target_server_name;      /* name of the server on which the operation is taking place */
-       pstring target_db_name;          /* name of the database that we're opening */
-} SCM_info;
-
 typedef struct Service_info_struct {
        uint32  type;           /* should be SVC_HANDLE_IS_SERVICE */
        pstring servicename;    /* the name of the service */
@@ -205,9 +198,9 @@ typedef struct Service_info_struct {
  
 typedef struct {
        /* functions for enumerating subkeys and values */      
-       WERROR  (*stop_service)( SERVICE_STATUS *status );
-       WERROR  (*start_service) ( void );
-       WERROR  (*service_status)( SERVICE_STATUS *status );
+       WERROR  (*stop_service)( const char *service, SERVICE_STATUS *status );
+       WERROR  (*start_service) ( const char *service );
+       WERROR  (*service_status)( const char *service, SERVICE_STATUS *status );
 } SERVICE_CONTROL_OPS;
 
 /* structure to store the service handle information  */
@@ -341,6 +334,7 @@ typedef struct {
        WERROR status;
 } SVCCTL_R_ENUM_DEPENDENT_SERVICES;
 
+
 /**************************/
 
 typedef struct {
@@ -354,32 +348,58 @@ typedef struct {
        WERROR status;
 } SVCCTL_R_QUERY_SERVICE_CONFIG;
 
+
+/**************************/
+
 typedef struct {
        POLICY_HND handle;
-        uint32 info_level;
+       uint32 level;
        uint32 buffer_size;
 } SVCCTL_Q_QUERY_SERVICE_CONFIG2;
 
 typedef struct {
-       UNISTR2 *description;
-        uint32 returned;
+       RPC_BUFFER buffer;
        uint32 needed;
-        uint32 offset;
        WERROR status;
 } SVCCTL_R_QUERY_SERVICE_CONFIG2;
 
+
+/**************************/
+
 typedef struct {
        POLICY_HND handle;
-        uint32 info_level;
+        uint32 level;
        uint32 buffer_size;
 } SVCCTL_Q_QUERY_SERVICE_STATUSEX;
 
 typedef struct {
        RPC_BUFFER buffer;
-        uint32 returned;
        uint32 needed;
        WERROR status;
 } SVCCTL_R_QUERY_SERVICE_STATUSEX;
 
+
+/**************************/
+
+typedef struct {
+       POLICY_HND handle;
+} SVCCTL_Q_LOCK_SERVICE_DB;
+
+typedef struct {
+       POLICY_HND h_lock;
+       WERROR status;
+} SVCCTL_R_LOCK_SERVICE_DB;
+
+
+/**************************/
+
+typedef struct {
+       POLICY_HND h_lock;
+} SVCCTL_Q_UNLOCK_SERVICE_DB;
+
+typedef struct {
+       WERROR status;
+} SVCCTL_R_UNLOCK_SERVICE_DB;
+
 #endif /* _RPC_SVCCTL_H */
 
index c0778383c652b7983bda1735fe7cc095c1554d72..61d2237b2dd638ee28bbf1449097ae7e991dcda7 100644 (file)
@@ -206,13 +206,13 @@ typedef smb_ucs2_t wfstring[FSTRING_LEN];
 #define PI_SHUTDOWN            10
 #define PI_SVCCTL              11
 #define PI_EVENTLOG            12
-#define PI_MAX_PIPES           13
+#define PI_NTSVCS              13
+#define PI_MAX_PIPES           14
 
 /* 64 bit time (100usec) since ????? - cifs6.txt, section 3.5, page 30 */
-typedef struct nttime_info
-{
-  uint32 low;
-  uint32 high;
+typedef struct nttime_info {
+       uint32 low;
+       uint32 high;
 } NTTIME;
 
 
@@ -414,6 +414,10 @@ struct fd_handle {
                                 */
 };
 
+struct timed_event;
+struct idle_event;
+struct share_mode_entry;
+
 typedef struct files_struct {
        struct files_struct *next, *prev;
        int fnum;
@@ -437,6 +441,11 @@ typedef struct files_struct {
        time_t last_write_time;
        int oplock_type;
        int sent_oplock_break;
+       struct timed_event *oplock_timeout;
+
+       struct share_mode_entry *pending_break_messages;
+       int num_pending_break_messages;
+
        unsigned long file_id;
        BOOL can_lock;
        BOOL can_read;
@@ -564,6 +573,7 @@ struct current_user
 #define NO_BREAK_SENT 0
 #define BREAK_TO_NONE_SENT 1
 #define LEVEL_II_BREAK_SENT 2
+#define ASYNC_LEVEL_II_BREAK_SENT 3
 
 typedef struct {
        fstring smb_name; /* user name from the client */
@@ -619,28 +629,19 @@ struct interface
        struct in_addr nmask;
 };
 
-/* struct used by share mode violation error processing */
-typedef struct {
-       pid_t pid;
-       uint16 mid;
-       struct timeval time;
-       SMB_DEV_T dev;
-       SMB_INO_T inode;
-       uint16 port;
-} deferred_open_entry;
-
 /* Internal message queue for deferred opens. */
 struct pending_message_list {
        struct pending_message_list *next, *prev;
-       struct timeval msg_time; /* The timeout time */
+       struct timeval request_time; /* When was this first issued? */
+       struct timeval end_time; /* When does this time out? */
        DATA_BLOB buf;
        DATA_BLOB private_data;
 };
 
 /* struct returned by get_share_modes */
-typedef struct {
-       pid_t pid;
-       uint16 op_port;
+struct share_mode_entry {
+       struct process_id pid;
+       uint16 op_mid;
        uint16 op_type;
        uint32 access_mask;             /* NTCreateX access bits (FILE_READ_DATA etc.) */
        uint32 share_access;            /* NTCreateX share constants (FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE). */
@@ -652,14 +653,18 @@ typedef struct {
        SMB_DEV_T dev;
        SMB_INO_T inode;
        unsigned long share_file_id;
-} share_mode_entry;
-
-
-#define SHAREMODE_FN_CAST() \
-       void (*)(share_mode_entry *, char*)
+};
 
-#define SHAREMODE_FN(fn) \
-       void (*fn)(share_mode_entry *, char*)
+struct share_mode_lock {
+       const char *filename;
+       SMB_DEV_T dev;
+       SMB_INO_T ino;
+       int num_share_modes;
+       struct share_mode_entry *share_modes;
+       BOOL delete_on_close;
+       BOOL fresh;
+       BOOL modified;
+};
 
 #define NT_HASH_LEN 16
 #define LM_HASH_LEN 16
@@ -700,14 +705,14 @@ typedef struct {
 
 /* key and data in the connections database - used in smbstatus and smbd */
 struct connections_key {
-       pid_t pid;
+       struct process_id pid;
        int cnum;
        fstring name;
 };
 
 struct connections_data {
        int magic;
-       pid_t pid;
+       struct process_id pid;
        int cnum;
        uid_t uid;
        gid_t gid;
@@ -719,12 +724,6 @@ struct connections_data {
 };
 
 
-/* key and data records in the tdb locking database */
-struct locking_key {
-       SMB_DEV_T dev;
-       SMB_INO_T inode;
-};
-
 /* the following are used by loadparm for option lists */
 typedef enum {
        P_BOOL,P_BOOLREV,P_CHAR,P_INTEGER,P_OCTAL,P_LIST,
@@ -744,11 +743,11 @@ struct enum_list {
 };
 
 #define BRLOCK_FN_CAST() \
-       void (*)(SMB_DEV_T dev, SMB_INO_T ino, int pid, \
+       void (*)(SMB_DEV_T dev, SMB_INO_T ino, struct process_id pid, \
                                 enum brl_type lock_type, \
                                 br_off start, br_off size)
 #define BRLOCK_FN(fn) \
-       void (*fn)(SMB_DEV_T dev, SMB_INO_T ino, int pid, \
+       void (*fn)(SMB_DEV_T dev, SMB_INO_T ino, struct process_id pid, \
                                 enum brl_type lock_type, \
                                 br_off start, br_off size)
 struct parm_struct
@@ -1462,10 +1461,29 @@ extern int chain_size;
 #define BATCH_OPLOCK 2
 #define LEVEL_II_OPLOCK 4
 #define INTERNAL_OPEN_ONLY 8
+#define FAKE_LEVEL_II_OPLOCK 16        /* Client requested no_oplock, but we have to
+                                * inform potential level2 holders on
+                                * write. */
+#define DEFERRED_OPEN_ENTRY 32
+#define UNUSED_SHARE_MODE_ENTRY 64
 
 #define EXCLUSIVE_OPLOCK_TYPE(lck) ((lck) & ((unsigned int)EXCLUSIVE_OPLOCK|(unsigned int)BATCH_OPLOCK))
 #define BATCH_OPLOCK_TYPE(lck) ((lck) & (unsigned int)BATCH_OPLOCK)
-#define LEVEL_II_OPLOCK_TYPE(lck) ((lck) & (unsigned int)LEVEL_II_OPLOCK)
+#define LEVEL_II_OPLOCK_TYPE(lck) ((lck) & ((unsigned int)LEVEL_II_OPLOCK|(unsigned int)FAKE_LEVEL_II_OPLOCK))
+
+struct inform_level2_message {
+       SMB_DEV_T dev;
+       SMB_INO_T inode;
+       uint16 mid;
+       unsigned long target_file_id;
+       unsigned long source_file_id;
+};
+
+struct kernel_oplock_message {
+       SMB_DEV_T dev;
+       SMB_INO_T inode;
+       unsigned long file_id;
+};
 
 /*
  * On the wire return values for oplock types.
@@ -1483,95 +1501,23 @@ extern int chain_size;
 #define OPLOCKLEVEL_NONE 0
 #define OPLOCKLEVEL_II 1
 
-/*
- * Loopback command offsets.
- */
-
-#define OPBRK_CMD_LEN_OFFSET 0
-#define OPBRK_CMD_PORT_OFFSET 4
-#define OPBRK_CMD_HEADER_LEN 6
-
-#define OPBRK_MESSAGE_CMD_OFFSET 0
-
-/*
- * Oplock break command code to send over the udp socket.
- * The same message is sent for both exlusive and level II breaks. 
- * 
- * The form of this is :
- *
- *  0     2       2+pid   2+pid+dev 2+pid+dev+ino
- *  +----+--------+-------+--------+---------+
- *  | cmd| pid    | dev   |  inode | fileid  |
- *  +----+--------+-------+--------+---------+
- */
-
-#define OPLOCK_BREAK_PID_OFFSET 2
-#define OPLOCK_BREAK_DEV_OFFSET (OPLOCK_BREAK_PID_OFFSET + sizeof(pid_t))
-#define OPLOCK_BREAK_INODE_OFFSET (OPLOCK_BREAK_DEV_OFFSET + sizeof(SMB_DEV_T))
-#define OPLOCK_BREAK_FILEID_OFFSET (OPLOCK_BREAK_INODE_OFFSET + sizeof(SMB_INO_T))
-#define OPLOCK_BREAK_MSG_LEN (OPLOCK_BREAK_FILEID_OFFSET + sizeof(unsigned long))
-
-/* Message types */
-#define OPLOCK_BREAK_CMD 0x1
-#define KERNEL_OPLOCK_BREAK_CMD 0x2
-#define LEVEL_II_OPLOCK_BREAK_CMD 0x3
-#define ASYNC_LEVEL_II_OPLOCK_BREAK_CMD 0x4
-
-/* Add the "deferred open" message. */
-#define RETRY_DEFERRED_OPEN_CMD 0x5
-
-/*
- * And the message format for it. Keep the same message length.
- *
- *  0     2       2+pid   2+pid+dev 2+pid+dev+ino
- *  +----+--------+-------+--------+---------+
- *  | cmd| pid    | dev   |  inode | mid     |
- *  +----+--------+-------+--------+---------+
- */
-
-#define DEFERRED_OPEN_CMD_OFFSET 0
-#define DEFERRED_OPEN_PID_OFFSET 2 /* pid we're *sending* from. */
-#define DEFERRED_OPEN_DEV_OFFSET (DEFERRED_OPEN_PID_OFFSET + sizeof(pid_t))
-#define DEFERRED_OPEN_INODE_OFFSET (DEFERRED_OPEN_DEV_OFFSET + sizeof(SMB_DEV_T))
-#define DEFERRED_OPEN_MID_OFFSET (DEFERRED_OPEN_INODE_OFFSET + sizeof(SMB_INO_T))
-#define DEFERRED_OPEN_MSG_LEN OPLOCK_BREAK_MSG_LEN
-
 /*
  * Capabilities abstracted for different systems.
  */
 
 #define KERNEL_OPLOCK_CAPABILITY 0x1
 
-/*
- * Oplock break command code sent via the kernel interface (if it exists).
- *
- * Form of this is :
- *
- *  0     2       2+devsize 2+devsize+inodesize
- *  +----+--------+--------+----------+
- *  | cmd| dev    |  inode |  fileid  |
- *  +----+--------+--------+----------+
- */
-#define KERNEL_OPLOCK_BREAK_DEV_OFFSET 2
-#define KERNEL_OPLOCK_BREAK_INODE_OFFSET (KERNEL_OPLOCK_BREAK_DEV_OFFSET + sizeof(SMB_DEV_T))
-#define KERNEL_OPLOCK_BREAK_FILEID_OFFSET (KERNEL_OPLOCK_BREAK_INODE_OFFSET + sizeof(SMB_INO_T))
-#define KERNEL_OPLOCK_BREAK_MSG_LEN (KERNEL_OPLOCK_BREAK_FILEID_OFFSET + sizeof(unsigned long))
-
-
 /* if a kernel does support oplocks then a structure of the following
    typee is used to describe how to interact with the kernel */
 struct kernel_oplocks {
-       BOOL (*receive_message)(fd_set *fds, char *buffer, int buffer_len);
+       files_struct * (*receive_message)(fd_set *fds);
        BOOL (*set_oplock)(files_struct *fsp, int oplock_type);
        void (*release_oplock)(files_struct *fsp);
-       BOOL (*parse_message)(char *msg_start, int msg_len, SMB_INO_T *inode, SMB_DEV_T *dev, unsigned long *file_id);
        BOOL (*msg_waiting)(fd_set *fds);
        int notification_fd;
 };
 
 
-#define CMD_REPLY 0x8000
-
 /* this structure defines the functions for doing change notify in
    various implementations */
 struct cnotify_fns {
@@ -1759,4 +1705,18 @@ struct ea_list {
 /* EA to use for DOS attributes */
 #define SAMBA_XATTR_DOS_ATTRIB "user.DOSATTRIB"
 
+struct uuid {
+       uint32 time_low;
+       uint16 time_mid;
+       uint16 time_hi_and_version;
+       uint8  clock_seq[2];
+       uint8  node[6];
+};
+#define UUID_SIZE 16
+
+#define UUID_FLAT_SIZE 16
+typedef struct uuid_flat {
+       uint8 info[UUID_FLAT_SIZE];
+} UUID_FLAT;
+
 #endif /* _SMB_H */
diff --git a/source3/include/smb_ldap.h b/source3/include/smb_ldap.h
new file mode 100644 (file)
index 0000000..144317c
--- /dev/null
@@ -0,0 +1,256 @@
+/* 
+   Unix SMB/CIFS Implementation.
+   LDAP protocol helper functions for SAMBA
+   Copyright (C) Volker Lendecke 2004
+    
+   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.
+   
+*/
+
+#ifndef _SMB_LDAP_H
+#define _SMB_LDAP_H
+
+enum ldap_request_tag {
+       LDAP_TAG_BindRequest = 0,
+       LDAP_TAG_BindResponse = 1,
+       LDAP_TAG_UnbindRequest = 2,
+       LDAP_TAG_SearchRequest = 3,
+       LDAP_TAG_SearchResultEntry = 4,
+       LDAP_TAG_SearchResultDone = 5,
+       LDAP_TAG_ModifyRequest = 6,
+       LDAP_TAG_ModifyResponse = 7,
+       LDAP_TAG_AddRequest = 8,
+       LDAP_TAG_AddResponse = 9,
+       LDAP_TAG_DelRequest = 10,
+       LDAP_TAG_DelResponse = 11,
+       LDAP_TAG_ModifyDNRequest = 12,
+       LDAP_TAG_ModifyDNResponse = 13,
+       LDAP_TAG_CompareRequest = 14,
+       LDAP_TAG_CompareResponse = 15,
+       LDAP_TAG_AbandonRequest = 16,
+       LDAP_TAG_SearchResultReference = 19,
+       LDAP_TAG_ExtendedRequest = 23,
+       LDAP_TAG_ExtendedResponse = 24
+};
+
+enum ldap_auth_mechanism {
+       LDAP_AUTH_MECH_SIMPLE = 0,
+       LDAP_AUTH_MECH_SASL = 3
+};
+
+#ifndef LDAP_SUCCESS
+enum ldap_result_code {
+       LDAP_SUCCESS = 0,
+       LDAP_SASL_BIND_IN_PROGRESS = 0x0e,
+       LDAP_INVALID_CREDENTIALS = 0x31,
+       LDAP_OTHER = 0x50
+};
+#endif /* LDAP_SUCCESS */
+
+struct ldap_Result {
+       int resultcode;
+       const char *dn;
+       const char *errormessage;
+       const char *referral;
+};
+
+struct ldap_attribute {
+       const char *name;
+       int num_values;
+       DATA_BLOB *values;
+};
+
+struct ldap_BindRequest {
+       int version;
+       const char *dn;
+       enum ldap_auth_mechanism mechanism;
+       union {
+               const char *password;
+               struct {
+                       const char *mechanism;
+                       DATA_BLOB secblob;
+               } SASL;
+       } creds;
+};
+
+struct ldap_BindResponse {
+       struct ldap_Result response;
+       union {
+               DATA_BLOB secblob;
+       } SASL;
+};
+
+struct ldap_UnbindRequest {
+       uint8 __dummy;
+};
+
+enum ldap_scope {
+       LDAP_SEARCH_SCOPE_BASE = 0,
+       LDAP_SEARCH_SCOPE_SINGLE = 1,
+       LDAP_SEARCH_SCOPE_SUB = 2
+};
+
+enum ldap_deref {
+       LDAP_DEREFERENCE_NEVER = 0,
+       LDAP_DEREFERENCE_IN_SEARCHING = 1,
+       LDAP_DEREFERENCE_FINDING_BASE = 2,
+       LDAP_DEREFERENCE_ALWAYS
+};
+
+struct ldap_SearchRequest {
+       const char *basedn;
+       enum ldap_scope scope;
+       enum ldap_deref deref;
+       uint32 timelimit;
+       uint32 sizelimit;
+       BOOL attributesonly;
+       char *filter;
+       int num_attributes;
+       const char **attributes;
+};
+
+struct ldap_SearchResEntry {
+       const char *dn;
+       int num_attributes;
+       struct ldap_attribute *attributes;
+};
+
+struct ldap_SearchResRef {
+       int num_referrals;
+       const char **referrals;
+};
+
+enum ldap_modify_type {
+       LDAP_MODIFY_NONE = -1,
+       LDAP_MODIFY_ADD = 0,
+       LDAP_MODIFY_DELETE = 1,
+       LDAP_MODIFY_REPLACE = 2
+};
+
+struct ldap_mod {
+       enum ldap_modify_type type;
+       struct ldap_attribute attrib;
+};
+
+struct ldap_ModifyRequest {
+       const char *dn;
+       int num_mods;
+       struct ldap_mod *mods;
+};
+
+struct ldap_AddRequest {
+       const char *dn;
+       int num_attributes;
+       struct ldap_attribute *attributes;
+};
+
+struct ldap_DelRequest {
+       const char *dn;
+};
+
+struct ldap_ModifyDNRequest {
+       const char *dn;
+       const char *newrdn;
+       BOOL deleteolddn;
+       const char *newsuperior;
+};
+
+struct ldap_CompareRequest {
+       const char *dn;
+       const char *attribute;
+       const char *value;
+};
+
+struct ldap_AbandonRequest {
+       uint32 messageid;
+};
+
+struct ldap_ExtendedRequest {
+       const char *oid;
+       DATA_BLOB value;
+};
+
+struct ldap_ExtendedResponse {
+       struct ldap_Result response;
+       const char *name;
+       DATA_BLOB value;
+};
+
+union ldap_Request {
+       struct ldap_BindRequest         BindRequest;
+       struct ldap_BindResponse        BindResponse;
+       struct ldap_UnbindRequest       UnbindRequest;
+       struct ldap_SearchRequest       SearchRequest;
+       struct ldap_SearchResEntry      SearchResultEntry;
+       struct ldap_Result              SearchResultDone;
+       struct ldap_SearchResRef        SearchResultReference;
+       struct ldap_ModifyRequest       ModifyRequest;
+       struct ldap_Result              ModifyResponse;
+       struct ldap_AddRequest          AddRequest;
+       struct ldap_Result              AddResponse;
+       struct ldap_DelRequest          DelRequest;
+       struct ldap_Result              DelResponse;
+       struct ldap_ModifyDNRequest     ModifyDNRequest;
+       struct ldap_Result              ModifyDNResponse;
+       struct ldap_CompareRequest      CompareRequest;
+       struct ldap_Result              CompareResponse;
+       struct ldap_AbandonRequest      AbandonRequest;
+       struct ldap_ExtendedRequest     ExtendedRequest;
+       struct ldap_ExtendedResponse    ExtendedResponse;
+};
+
+struct ldap_Control {
+       const char *oid;
+       BOOL        critical;
+       DATA_BLOB   value;
+};
+
+struct ldap_message {
+       TALLOC_CTX             *mem_ctx;
+       uint32                  messageid;
+       uint8                   type;
+       union  ldap_Request     r;
+       int                     num_controls;
+       struct ldap_Control    *controls;
+};
+
+struct ldap_queue_entry {
+       struct ldap_queue_entry *next, *prev;
+       int msgid;
+       struct ldap_message *msg;
+};
+
+struct ldap_connection {
+       TALLOC_CTX *mem_ctx;
+       int sock;
+       int next_msgid;
+       char *host;
+       uint16 port;
+       BOOL ldaps;
+
+       const char *auth_dn;
+       const char *simple_pw;
+
+       /* Current outstanding search entry */
+       int searchid;
+
+       /* List for incoming search entries */
+       struct ldap_queue_entry *search_entries;
+
+       /* Outstanding LDAP requests that have not yet been replied to */
+       struct ldap_queue_entry *outstanding;
+};
+
+#endif
index f61ba624c696d662b318c9b5479575c966728483..1e04ea496de2ca5ef4f4fd62c2746844e792c752 100644 (file)
@@ -55,7 +55,7 @@ struct smb_share_mode_entry {
        uint32_t access_mask;
        struct timeval open_time;
        uint32_t file_id;
-       pid_t pid;
+       struct process_id pid;
 };
 
 /*
index df56f60bf39cdc1a8342d19dbdbe93158c4fe6ca..bea1a6d84a36c54dd3eec4bf6a4aa93009f64dfe 100644 (file)
@@ -1,5 +1,5 @@
 /* 
-   Unix SMB/CIFS implementation.
+   Unix SMB/CIFS mplementation.
    LDAP protocol helper functions for SAMBA
    Copyright (C) Gerald Carter                 2001-2003
     
@@ -40,6 +40,7 @@ struct smbldap_state;
 #define LDAP_OBJ_IDPOOL                        "sambaUnixIdPool"
 #define LDAP_OBJ_IDMAP_ENTRY           "sambaIdmapEntry"
 #define LDAP_OBJ_SID_ENTRY             "sambaSidEntry"
+#define LDAP_OBJ_TRUST_PASSWORD         "sambaTrustPassword"
 
 #define LDAP_OBJ_ACCOUNT               "account"
 #define LDAP_OBJ_POSIXACCOUNT          "posixAccount"
@@ -95,10 +96,12 @@ struct smbldap_state;
 #define LDAP_ATTR_LOGON_COUNT          36
 #define LDAP_ATTR_MUNGED_DIAL          37
 #define LDAP_ATTR_BAD_PASSWORD_TIME    38
-#define LDAP_ATTR_PWD_HISTORY          39
+#define LDAP_ATTR_PWD_HISTORY           39
 #define LDAP_ATTR_SID_LIST             40
-#define LDAP_ATTR_MOD_TIMESTAMP                41
-#define LDAP_ATTR_LOGON_HOURS          42
+#define LDAP_ATTR_MOD_TIMESTAMP         41
+#define LDAP_ATTR_LOGON_HOURS          42 
+#define LDAP_ATTR_TRUST_PASSWD_FLAGS    43
+
 
 typedef struct _attrib_map_entry {
        int             attrib;
@@ -117,6 +120,8 @@ extern ATTRIB_MAP_ENTRY groupmap_attr_list[];
 extern ATTRIB_MAP_ENTRY groupmap_attr_list_to_delete[];
 extern ATTRIB_MAP_ENTRY idpool_attr_list[];
 extern ATTRIB_MAP_ENTRY sidmap_attr_list[];
+extern ATTRIB_MAP_ENTRY trustpw_attr_list[];
+
 
 /* Function declarations -- not included in proto.h so we don't
    have to worry about LDAP structure types */
index 8bb13bd354a3942641bbdc523727fdfe4b458770..66abe317053a7e268ac233738b96b62e8f2f1f2f 100644 (file)
@@ -43,7 +43,7 @@ typedef enum _spnego_negResult {
 } negResult_t;
 
 typedef struct spnego_negTokenInit {
-       char **mechTypes;
+       const char **mechTypes;
        int reqFlags;
        DATA_BLOB mechToken;
        DATA_BLOB mechListMIC;
index 04db59cf012859f60013ebb01a5e25c2083a8d26..1029df53aee8f53bd8e27340bea837f0374ca3d7 100644 (file)
@@ -18,8 +18,6 @@
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-#include "includes.h"
-
 #define srvstr_pull(base_ptr, dest, src, dest_len, src_len, flags) \
     pull_string(base_ptr, dest, src, dest_len, src_len, flags)
 
index 423dc1675a6d9b9cba04145de964586b0aa46e2a..b02edc5b40102e0f8fc64db1447d5986e6511043 100644 (file)
@@ -3,6 +3,7 @@
  *  account policy storage
  *  Copyright (C) Jean François Micouleau      1998-2001.
  *  Copyright (C) Andrew Bartlett              2002
+ *  Copyright (C) Guenther Deschner            2004-2005
  *  
  *  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
 #include "includes.h"
 static TDB_CONTEXT *tdb; 
 
-#define DATABASE_VERSION 2
+/* cache all entries for 60 seconds for to save ldap-queries (cache is updated
+ * after this period if admins do not use pdbedit or usermanager but manipulate
+ * ldap directly) - gd */
 
-/****************************************************************************
- Set default for a field if it is empty
-****************************************************************************/
-
-static void set_default_on_empty(int field, uint32 value)
-{
-       if (account_policy_get(field, NULL))
-               return;
-       account_policy_set(field, value);
-       return;
-}
+#define DATABASE_VERSION       3
+#define AP_LASTSET             "LAST_CACHE_UPDATE"
+#define AP_TTL                 60
 
-/****************************************************************************
- Open the account policy tdb.
-****************************************************************************/
 
-BOOL init_account_policy(void)
-{
-       const char *vstring = "INFO/version";
-       uint32 version;
+struct ap_table {
+       int field;
+       const char *string;
+       uint32 default_val;
+       const char *description;
+       const char *ldap_attr;
+};
 
-       if (tdb)
-               return True;
-       tdb = tdb_open_log(lock_path("account_policy.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
-       if (!tdb) {
-               DEBUG(0,("Failed to open account policy database\n"));
-               return False;
-       }
+static const struct ap_table account_policy_names[] = {
+       {AP_MIN_PASSWORD_LEN, "min password length", MINPASSWDLENGTH, 
+               "Minimal password length (default: 5)", 
+               "sambaMinPwdLength" },
 
-       /* handle a Samba upgrade */
-       tdb_lock_bystring(tdb, vstring,0);
-       if (!tdb_fetch_uint32(tdb, vstring, &version) || version != DATABASE_VERSION) {
-               tdb_store_uint32(tdb, vstring, DATABASE_VERSION);
+       {AP_PASSWORD_HISTORY, "password history", 0,
+               "Length of Password History Entries (default: 0 => off)", 
+               "sambaPwdHistoryLength" },
                
-               set_default_on_empty(
-                       AP_MIN_PASSWORD_LEN, 
-                       MINPASSWDLENGTH);/* 5 chars minimum             */
-               set_default_on_empty(
-                       AP_PASSWORD_HISTORY, 
-                       0);             /* don't keep any old password  */
-               set_default_on_empty(
-                       AP_USER_MUST_LOGON_TO_CHG_PASS, 
-                       0);             /* don't force user to logon    */
-               set_default_on_empty(
-                       AP_MAX_PASSWORD_AGE, 
-                       (uint32)-1);    /* don't expire                 */
-               set_default_on_empty(
-                       AP_MIN_PASSWORD_AGE, 
-                       0);             /* 0 days                      */
-               set_default_on_empty(
-                       AP_LOCK_ACCOUNT_DURATION, 
-                       30);            /* lockout for 30 minutes      */
-               set_default_on_empty(
-                       AP_RESET_COUNT_TIME, 
-                       30);            /* reset after 30 minutes      */
-               set_default_on_empty(
-                       AP_BAD_ATTEMPT_LOCKOUT, 
-                       0);             /* don't lockout               */
-               set_default_on_empty(
-                       AP_TIME_TO_LOGOUT, 
-                       -1);            /* don't force logout          */
-               set_default_on_empty(
-                       AP_REFUSE_MACHINE_PW_CHANGE, 
-                       0);             /* allow machine pw changes    */
-       }
-       tdb_unlock_bystring(tdb, vstring);
-
-       /* These exist by default on NT4 in [HKLM\SECURITY\Policy\Accounts] */
-
-       privilege_create_account( &global_sid_World );
-       privilege_create_account( &global_sid_Builtin_Administrators );
-       privilege_create_account( &global_sid_Builtin_Account_Operators );
-       privilege_create_account( &global_sid_Builtin_Server_Operators );
-       privilege_create_account( &global_sid_Builtin_Print_Operators );
-       privilege_create_account( &global_sid_Builtin_Backup_Operators );
+       {AP_USER_MUST_LOGON_TO_CHG_PASS, "user must logon to change password", 0,
+               "Force Users to logon for password change (default: 0 => off, 2 => on)",
+               "sambaLogonToChgPwd" },
        
-       return True;
-}
-
-static const struct {
-       int field;
-       const char *string;
-} account_policy_names[] = {
-       {AP_MIN_PASSWORD_LEN, "min password length"},
-       {AP_PASSWORD_HISTORY, "password history"},
-       {AP_USER_MUST_LOGON_TO_CHG_PASS, "user must logon to change password"},
-       {AP_MAX_PASSWORD_AGE, "maximum password age"},
-       {AP_MIN_PASSWORD_AGE,"minimum password age"},
-       {AP_LOCK_ACCOUNT_DURATION, "lockout duration"},
-       {AP_RESET_COUNT_TIME, "reset count minutes"},
-       {AP_BAD_ATTEMPT_LOCKOUT, "bad lockout attempt"},
-       {AP_TIME_TO_LOGOUT, "disconnect time"},
-       {AP_REFUSE_MACHINE_PW_CHANGE, "refuse machine password change"},
-       {0, NULL}
+       {AP_MAX_PASSWORD_AGE, "maximum password age", (uint32) -1,
+               "Maximum password age, in seconds (default: -1 => never expire passwords)", 
+               "sambaMaxPwdAge" },
+               
+       {AP_MIN_PASSWORD_AGE,"minimum password age", 0,
+               "Minimal password age, in seconds (default: 0 => allow immediate password change)", 
+               "sambaMinPwdAge" },
+               
+       {AP_LOCK_ACCOUNT_DURATION, "lockout duration", 30,
+               "Lockout duration in minutes (default: 30, -1 => forever)",
+               "sambaLockoutDuration" },
+               
+       {AP_RESET_COUNT_TIME, "reset count minutes", 30,
+               "Reset time after lockout in minutes (default: 30)", 
+               "sambaLockoutObservationWindow" },
+               
+       {AP_BAD_ATTEMPT_LOCKOUT, "bad lockout attempt", 0,
+               "Lockout users after bad logon attempts (default: 0 => off)", 
+               "sambaLockoutThreshold" },
+               
+       {AP_TIME_TO_LOGOUT, "disconnect time", -1,
+               "Disconnect Users outside logon hours (default: -1 => off, 0 => on)", 
+               "sambaForceLogoff" }, 
+               
+       {AP_REFUSE_MACHINE_PW_CHANGE, "refuse machine password change", 0,
+               "Allow Machine Password changes (default: 0 => off)",
+               "sambaRefuseMachinePwdChange" },
+               
+       {0, NULL, 0, "", NULL}
 };
 
 char *account_policy_names_list(void)
@@ -148,7 +112,7 @@ char *account_policy_names_list(void)
 Get the account policy name as a string from its #define'ed number
 ****************************************************************************/
 
-static const char *decode_account_policy_name(int field)
+const char *decode_account_policy_name(int field)
 {
        int i;
        for (i=0; account_policy_names[i].string; i++) {
@@ -156,7 +120,34 @@ static const char *decode_account_policy_name(int field)
                        return account_policy_names[i].string;
        }
        return NULL;
+}
+
+/****************************************************************************
+Get the account policy LDAP attribute as a string from its #define'ed number
+****************************************************************************/
 
+const char *get_account_policy_attr(int field)
+{
+       int i;
+       for (i=0; account_policy_names[i].field; i++) {
+               if (field == account_policy_names[i].field)
+                       return account_policy_names[i].ldap_attr;
+       }
+       return NULL;
+}
+
+/****************************************************************************
+Get the account policy description as a string from its #define'ed number
+****************************************************************************/
+
+const char *account_policy_get_desc(int field)
+{
+       int i;
+       for (i=0; account_policy_names[i].string; i++) {
+               if (field == account_policy_names[i].field)
+                       return account_policy_names[i].description;
+       }
+       return NULL;
 }
 
 /****************************************************************************
@@ -171,18 +162,146 @@ int account_policy_name_to_fieldnum(const char *name)
                        return account_policy_names[i].field;
        }
        return 0;
+}
+
+/*****************************************************************************
+Update LAST-Set counter inside the cache
+*****************************************************************************/
+
+static BOOL account_policy_cache_timestamp(uint32 *value, BOOL update, 
+                                          const char *ap_name)
+{
+       pstring key;
+       uint32 val = 0;
+       time_t now;
+
+       if (ap_name == NULL)
+               return False;
+               
+       slprintf(key, sizeof(key)-1, "%s/%s", ap_name, AP_LASTSET);
+
+       if (!init_account_policy())
+               return False;
+
+       if (!tdb_fetch_uint32(tdb, key, &val) && !update) {
+               DEBUG(10,("failed to get last set timestamp of cache\n"));
+               return False;
+       }
+
+       *value = val;
+
+       DEBUG(10, ("account policy cache lastset was: %s\n", http_timestring(val)));
+
+       if (update) {
+
+               now = time(NULL);
 
+               if (!tdb_store_uint32(tdb, key, (uint32)now)) {
+                       DEBUG(1, ("tdb_store_uint32 failed for %s\n", key));
+                       return False;
+               }
+               DEBUG(10, ("account policy cache lastset now: %s\n", http_timestring(now)));
+               *value = now;
+       }
+
+       return True;
 }
 
-/****************************************************************************
-****************************************************************************/
+/*****************************************************************************
+Get default value for account policy
+*****************************************************************************/
+
+BOOL account_policy_get_default(int account_policy, uint32 *val)
+{
+       int i;
+       for (i=0; account_policy_names[i].field; i++) {
+               if (account_policy_names[i].field == account_policy) {
+                       *val = account_policy_names[i].default_val;
+                       return True;
+               }
+       }
+       DEBUG(0,("no default for account_policy index %d found. This should never happen\n", 
+               account_policy));
+       return False;
+}
+
+/*****************************************************************************
+ Set default for a field if it is empty
+*****************************************************************************/
+
+static BOOL account_policy_set_default_on_empty(int account_policy)
+{
+
+       uint32 value;
+
+       if (!account_policy_get(account_policy, &value) && 
+           !account_policy_get_default(account_policy, &value)) {
+               return False;
+       }
+
+       return account_policy_set(account_policy, value);
+}
+
+/*****************************************************************************
+ Open the account policy tdb.
+***`*************************************************************************/
+
+BOOL init_account_policy(void)
+{
+
+       const char *vstring = "INFO/version";
+       uint32 version;
+       int i;
+
+       if (tdb)
+               return True;
+
+       tdb = tdb_open_log(lock_path("account_policy.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
+       if (!tdb) {
+               DEBUG(0,("Failed to open account policy database\n"));
+               return False;
+       }
+
+       /* handle a Samba upgrade */
+       tdb_lock_bystring(tdb, vstring,0);
+       if (!tdb_fetch_uint32(tdb, vstring, &version) || version != DATABASE_VERSION) {
+
+               tdb_store_uint32(tdb, vstring, DATABASE_VERSION);
+
+               for (i=0; account_policy_names[i].field; i++) {
+
+                       if (!account_policy_set_default_on_empty(account_policy_names[i].field)) {
+                               DEBUG(0,("failed to set default value in account policy tdb\n"));
+                               return False;
+                       }
+               }
+       }
+
+       tdb_unlock_bystring(tdb, vstring);
+
+       /* These exist by default on NT4 in [HKLM\SECURITY\Policy\Accounts] */
+
+       privilege_create_account( &global_sid_World );
+       privilege_create_account( &global_sid_Builtin_Administrators );
+       privilege_create_account( &global_sid_Builtin_Account_Operators );
+       privilege_create_account( &global_sid_Builtin_Server_Operators );
+       privilege_create_account( &global_sid_Builtin_Print_Operators );
+       privilege_create_account( &global_sid_Builtin_Backup_Operators );
+
+       return True;
+}
+
+/*****************************************************************************
+Get an account policy (from tdb) 
+*****************************************************************************/
 
 BOOL account_policy_get(int field, uint32 *value)
 {
        fstring name;
        uint32 regval;
 
-       if(!init_account_policy())return False;
+       if (!init_account_policy())
+               return False;
 
        if (value)
                *value = 0;
@@ -199,18 +318,21 @@ BOOL account_policy_get(int field, uint32 *value)
        if (value)
                *value = regval;
 
-       DEBUG(10,("account_policy_get: %s:%d\n", name, regval));
+       DEBUG(10,("account_policy_get: name: %s, val: %d\n", name, regval));
        return True;
 }
 
 
 /****************************************************************************
+Set an account policy (in tdb) 
 ****************************************************************************/
+
 BOOL account_policy_set(int field, uint32 value)
 {
        fstring name;
 
-       if(!init_account_policy())return False;
+       if (!init_account_policy())
+               return False;
 
        fstrcpy(name, decode_account_policy_name(field));
        if (!*name) {
@@ -219,15 +341,71 @@ BOOL account_policy_set(int field, uint32 value)
        }
 
        if (!tdb_store_uint32(tdb, name, value)) {
-               DEBUG(1, ("tdb_store_uint32 failed for field %d (%s) on value %u", field, name, value));
+               DEBUG(1, ("tdb_store_uint32 failed for field %d (%s) on value %u\n", field, name, value));
                return False;
        }
 
-       DEBUG(10,("account_policy_set: %s:%d\n", name, value));
+       DEBUG(10,("account_policy_set: name: %s, value: %d\n", name, value));
        
        return True;
 }
 
+/****************************************************************************
+Set an account policy in the cache 
+****************************************************************************/
+
+BOOL cache_account_policy_set(int field, uint32 value)
+{
+       uint32 lastset;
+       const char *policy_name = NULL;
+
+       policy_name = decode_account_policy_name(field);
+       if (policy_name == NULL) {
+               DEBUG(0,("cache_account_policy_set: no policy found\n"));
+               return False;
+       }
+
+       DEBUG(10,("cache_account_policy_set: updating account pol cache\n"));
+
+       if (!account_policy_set(field, value)) {
+               return False;
+       }
+
+       if (!account_policy_cache_timestamp(&lastset, True, policy_name)) 
+       {
+               DEBUG(10,("cache_account_policy_set: failed to get lastest cache update timestamp\n"));
+               return False;
+       }
+
+       DEBUG(10,("cache_account_policy_set: cache valid until: %s\n", http_timestring(lastset+AP_TTL)));
+
+       return True;
+}
+
+/*****************************************************************************
+Get an account policy from the cache 
+*****************************************************************************/
+
+BOOL cache_account_policy_get(int field, uint32 *value)
+{
+       uint32 lastset;
+
+       if (!account_policy_cache_timestamp(&lastset, False, 
+                                           decode_account_policy_name(field))) 
+       {
+               DEBUG(10,("cache_account_policy_get: failed to get latest cache update timestamp\n"));
+               return False;
+       }
+
+       if ((lastset + AP_TTL) < (uint32)time(NULL) ) {
+               DEBUG(10,("cache_account_policy_get: no valid cache entry (cache expired)\n"));
+               return False;
+       } 
+
+       return account_policy_get(field, value);
+}
+
+
 /****************************************************************************
 ****************************************************************************/
 
diff --git a/source3/lib/arc4.c b/source3/lib/arc4.c
new file mode 100644 (file)
index 0000000..03ca54c
--- /dev/null
@@ -0,0 +1,80 @@
+/* 
+   Unix SMB/CIFS implementation.
+
+   An implementation of arc4.
+
+   Copyright (C) Jeremy Allison 2005.
+   
+   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"
+
+/*****************************************************************
+ Initialize state for an arc4 crypt/decrpyt.
+ arc4 state is 258 bytes - last 2 bytes are the index bytes.
+*****************************************************************/
+
+void smb_arc4_init(unsigned char arc4_state_out[258], const unsigned char *key, size_t keylen)
+{
+       size_t ind;
+       unsigned char j = 0;
+
+       for (ind = 0; ind < 256; ind++) {
+               arc4_state_out[ind] = (unsigned char)ind;
+       }
+
+       for( ind = 0; ind < 256; ind++) {
+               unsigned char tc;
+
+               j += (arc4_state_out[ind] + key[ind%keylen]);
+
+               tc = arc4_state_out[ind];
+               arc4_state_out[ind] = arc4_state_out[j];
+               arc4_state_out[j] = tc;
+       }
+       arc4_state_out[256] = 0;
+       arc4_state_out[257] = 0;
+}
+
+/*****************************************************************
+ Do the arc4 crypt/decrpyt.
+ arc4 state is 258 bytes - last 2 bytes are the index bytes.
+*****************************************************************/
+
+void smb_arc4_crypt(unsigned char arc4_state_inout[258], unsigned char *data, size_t len)
+{
+       unsigned char index_i = arc4_state_inout[256];
+       unsigned char index_j = arc4_state_inout[257];
+        size_t ind;
+
+       for( ind = 0; ind < len; ind++) {
+               unsigned char tc;
+               unsigned char t;
+
+               index_i++;
+               index_j += arc4_state_inout[index_i];
+
+               tc = arc4_state_inout[index_i];
+               arc4_state_inout[index_i] = arc4_state_inout[index_j];
+               arc4_state_inout[index_j] = tc;
+
+               t = arc4_state_inout[index_i] + arc4_state_inout[index_j];
+               data[ind] = data[ind] ^ arc4_state_inout[t];
+       }
+
+       arc4_state_inout[256] = index_i;
+       arc4_state_inout[257] = index_j;
+}
index 161f46a941723ffd439253b6089a79ca3ed52e32..ccd0d27f47b61a68e13ded9759df9e2b13fb36d1 100644 (file)
@@ -22,8 +22,9 @@
 #include "includes.h"
 
 /*******************************************************************
- free() a data blob
+ Free() a data blob.
 *******************************************************************/
+
 static void free_data_blob(DATA_BLOB *d)
 {
        if ((d) && (d->free)) {
@@ -32,8 +33,8 @@ static void free_data_blob(DATA_BLOB *d)
 }
 
 /*******************************************************************
- construct a data blob, must be freed with data_blob_free()
you can pass NULL for p and get a blank data blob
+ Construct a data blob, must be freed with data_blob_free().
You can pass NULL for p and get a blank data blob
 *******************************************************************/
 
 DATA_BLOB data_blob(const void *p, size_t length)
@@ -56,8 +57,9 @@ DATA_BLOB data_blob(const void *p, size_t length)
 }
 
 /*******************************************************************
- construct a data blob, using supplied TALLOC_CTX
+ Construct a data blob, using supplied TALLOC_CTX.
 *******************************************************************/
+
 DATA_BLOB data_blob_talloc(TALLOC_CTX *mem_ctx, const void *p, size_t length)
 {
        DATA_BLOB ret;
@@ -83,8 +85,9 @@ DATA_BLOB data_blob_talloc(TALLOC_CTX *mem_ctx, const void *p, size_t length)
 }
 
 /*******************************************************************
-free a data blob
+ Free a data blob.
 *******************************************************************/
+
 void data_blob_free(DATA_BLOB *d)
 {
        if (d) {
@@ -96,8 +99,9 @@ void data_blob_free(DATA_BLOB *d)
 }
 
 /*******************************************************************
-clear a DATA_BLOB's contents
+ Clear a DATA_BLOB's contents
 *******************************************************************/
+
 static void data_blob_clear(DATA_BLOB *d)
 {
        if (d->data) {
@@ -106,11 +110,11 @@ static void data_blob_clear(DATA_BLOB *d)
 }
 
 /*******************************************************************
-free a data blob and clear its contents
+ Free a data blob and clear its contents
 *******************************************************************/
+
 void data_blob_clear_free(DATA_BLOB *d)
 {
        data_blob_clear(d);
        data_blob_free(d);
 }
-
index f877d540fb456081d228be7033b258d38c6e0a68..f3676070dcb6d8bb2c8e59e3d36540f9100971d5 100644 (file)
@@ -448,19 +448,22 @@ BOOL debug_parse_levels(const char *params_str)
  Receive a "set debug level" message.
 ****************************************************************************/
 
-static void debug_message(int msg_type, pid_t src, void *buf, size_t len)
+static void debug_message(int msg_type, struct process_id src,
+                         void *buf, size_t len)
 {
        const char *params_str = buf;
 
        /* Check, it's a proper string! */
        if (params_str[len-1] != '\0') {
                DEBUG(1, ("Invalid debug message from pid %u to pid %u\n",
-                         (unsigned int)src, (unsigned int)getpid()));
+                         (unsigned int)procid_to_pid(&src),
+                         (unsigned int)getpid()));
                return;
        }
 
        DEBUG(3, ("INFO: Remote set of debug to `%s'  (pid %u from pid %u)\n",
-                 params_str, (unsigned int)getpid(), (unsigned int)src));
+                 params_str, (unsigned int)getpid(),
+                 (unsigned int)procid_to_pid(&src)));
 
        debug_parse_levels(params_str);
 }
@@ -473,7 +476,8 @@ void debug_message_send(pid_t pid, const char *params_str)
 {
        if (!params_str)
                return;
-       message_send_pid(pid, MSG_DEBUG, params_str, strlen(params_str) + 1,
+       message_send_pid(pid_to_procid(pid), MSG_DEBUG,
+                        params_str, strlen(params_str) + 1,
                         False);
 }
 
@@ -481,11 +485,13 @@ void debug_message_send(pid_t pid, const char *params_str)
  Return current debug level.
 ****************************************************************************/
 
-static void debuglevel_message(int msg_type, pid_t src, void *buf, size_t len)
+static void debuglevel_message(int msg_type, struct process_id src,
+                              void *buf, size_t len)
 {
        char *message = debug_list_class_names_and_levels();
 
-       DEBUG(1,("INFO: Received REQ_DEBUGLEVEL message from PID %u\n",(unsigned int)src));
+       DEBUG(1,("INFO: Received REQ_DEBUGLEVEL message from PID %u\n",
+                (unsigned int)procid_to_pid(&src)));
        message_send_pid(src, MSG_DEBUGLEVEL, message, strlen(message) + 1, True);
 
        SAFE_FREE(message);
index a83ed518d7cf50f3f2bc1443f4237588ee1766d3..1b2308ecba65307ea22f4f75aeb723c7b604b56d 100644 (file)
@@ -35,7 +35,7 @@ static unsigned long our_dm_mark = 0;
  * Respond to a POOL_USAGE message by sending back string form of memory
  * usage stats.
  **/
-static void msg_req_dmalloc_mark(int UNUSED(msg_type), pid_t UNUSED(src_pid),
+static void msg_req_dmalloc_mark(int UNUSED(msg_type), struct process_id UNUSED(src_pid),
                          void *UNUSED(buf), size_t UNUSED(len))
 {
 #ifdef ENABLE_DMALLOC
@@ -49,7 +49,7 @@ static void msg_req_dmalloc_mark(int UNUSED(msg_type), pid_t UNUSED(src_pid),
 
 
 static void msg_req_dmalloc_log_changed(int UNUSED(msg_type),
-                                       pid_t UNUSED(src_pid),
+                                       struct process_id UNUSED(src_pid),
                                        void *UNUSED(buf), size_t UNUSED(len))
 {
 #ifdef ENABLE_DMALLOC
index f2e267c9d4497d576881215d4b010f2879f4c100..85599c92d33725ed35c75a3809a2686006a93548 100644 (file)
@@ -251,11 +251,17 @@ BOOL gencache_get(const char *keystr, char **valstr, time_t *timeout)
                char* entry_buf = SMB_STRNDUP(databuf.dptr, databuf.dsize);
                char *v;
                time_t t;
+               unsigned u;
+               int status;
 
                v = SMB_MALLOC(databuf.dsize - TIMEOUT_LEN);
                                
                SAFE_FREE(databuf.dptr);
-               sscanf(entry_buf, CACHE_DATA_FMT, (int*)&t, v);
+               status = sscanf(entry_buf, CACHE_DATA_FMT, &u, v);
+               if ( status != 2 ) {
+                   DEBUG(0, ("gencache_get: Invalid return %d from sscanf\n", status ));
+               }
+               t = u;
                SAFE_FREE(entry_buf);
 
                DEBUG(10, ("Returning %s cache entry: key = %s, value = %s, "
@@ -307,6 +313,8 @@ void gencache_iterate(void (*fn)(const char* key, const char *value, time_t time
        TDB_DATA databuf;
        char *keystr = NULL, *valstr = NULL, *entry = NULL;
        time_t timeout = 0;
+       int status;
+       unsigned u;
 
        /* fail completely if get null pointers passed */
        SMB_ASSERT(fn && keystr_pattern);
@@ -335,7 +343,11 @@ void gencache_iterate(void (*fn)(const char* key, const char *value, time_t time
                entry = SMB_STRNDUP(databuf.dptr, databuf.dsize);
                SAFE_FREE(databuf.dptr);
                valstr = SMB_MALLOC(databuf.dsize - TIMEOUT_LEN);
-               sscanf(entry, CACHE_DATA_FMT, (int*)(&timeout), valstr);
+               status = sscanf(entry, CACHE_DATA_FMT, &u, valstr);
+               if ( status != 2 ) {
+                   DEBUG(0,("gencache_iterate: invalid return from sscanf %d\n",status));
+               }
+               timeout = u;
                
                DEBUG(10, ("Calling function with arguments (key = %s, value = %s, timeout = %s)\n",
                           keystr, valstr, ctime(&timeout)));
index 9ccddfa4c53776dca2c3c52716bd6917de226d0c..f37bbc9c2fd3b310e7971246d80aa2e5801af7c6 100644 (file)
@@ -22,7 +22,7 @@
 
 #include "includes.h"
 
-static unsigned char hash[258];
+static unsigned char smb_arc4_state[258];
 static uint32 counter;
 
 static BOOL done_reseed = False;
@@ -52,61 +52,6 @@ static void get_rand_reseed_data(int *reseed_data)
        }
 }
 
-/**************************************************************** 
- Setup the seed.
-*****************************************************************/
-
-static void seed_random_stream(unsigned char *seedval, size_t seedlen)
-{
-       unsigned char j = 0;
-       size_t ind;
-
-       for (ind = 0; ind < 256; ind++)
-               hash[ind] = (unsigned char)ind;
-
-       for( ind = 0; ind < 256; ind++) {
-               unsigned char tc;
-
-               j += (hash[ind] + seedval[ind%seedlen]);
-
-               tc = hash[ind];
-               hash[ind] = hash[j];
-               hash[j] = tc;
-       }
-
-       hash[256] = 0;
-       hash[257] = 0;
-}
-
-/**************************************************************** 
- Get datasize bytes worth of random data.
-*****************************************************************/
-
-static void get_random_stream(unsigned char *data, size_t datasize)
-{
-       unsigned char index_i = hash[256];
-       unsigned char index_j = hash[257];
-       size_t ind;
-
-       for( ind = 0; ind < datasize; ind++) {
-               unsigned char tc;
-               unsigned char t;
-
-               index_i++;
-               index_j += hash[index_i];
-
-               tc = hash[index_i];
-               hash[index_i] = hash[index_j];
-               hash[index_j] = tc;
-
-               t = hash[index_i] + hash[index_j];
-               data[ind] = hash[t];
-       }
-
-       hash[256] = index_i;
-       hash[257] = index_j;
-}
-
 /****************************************************************
  Get a 16 byte hash from the contents of a file.
  Note that the hash is not initialised.
@@ -202,7 +147,7 @@ static int do_reseed(BOOL use_fd, int fd)
                        seed_inbuf[i] ^= ((char *)(&reseed_data))[i % sizeof(reseed_data)];
        }
 
-       seed_random_stream(seed_inbuf, sizeof(seed_inbuf));
+       smb_arc4_init(smb_arc4_state, seed_inbuf, sizeof(seed_inbuf));
 
        return -1;
 }
@@ -246,7 +191,7 @@ void generate_random_buffer( unsigned char *out, int len)
        while(len > 0) {
                int copy_len = len > 16 ? 16 : len;
 
-               get_random_stream(md4_buf, sizeof(md4_buf));
+               smb_arc4_crypt(smb_arc4_state, md4_buf, sizeof(md4_buf));
                mdfour(tmp_buf, md4_buf, sizeof(md4_buf));
                memcpy(p, tmp_buf, copy_len);
                p += copy_len;
index 7d3addd86a4d401c685552dea2fa285451bf1fcc..058bbc99b0bcce105609c18af40a633096a95ad0 100644 (file)
@@ -57,8 +57,8 @@ static int received_signal;
 struct message_rec {
        int msg_version;
        int msg_type;
-       pid_t dest;
-       pid_t src;
+       struct process_id dest;
+       struct process_id src;
        size_t len;
 };
 
@@ -66,7 +66,7 @@ struct message_rec {
 static struct dispatch_fns {
        struct dispatch_fns *next, *prev;
        int msg_type;
-       void (*fn)(int msg_type, pid_t pid, void *buf, size_t len);
+       void (*fn)(int msg_type, struct process_id pid, void *buf, size_t len);
 } *dispatch_fns;
 
 /****************************************************************************
@@ -83,10 +83,12 @@ static void sig_usr1(void)
  A useful function for testing the message system.
 ****************************************************************************/
 
-static void ping_message(int msg_type, pid_t src, void *buf, size_t len)
+static void ping_message(int msg_type, struct process_id src,
+                        void *buf, size_t len)
 {
        const char *msg = buf ? buf : "none";
-       DEBUG(1,("INFO: Received PING message from PID %u [%s]\n",(unsigned int)src, msg));
+       DEBUG(1,("INFO: Received PING message from PID %s [%s]\n",
+                procid_str_static(&src), msg));
        message_send_pid(src, MSG_PONG, buf, len, True);
 }
 
@@ -123,12 +125,12 @@ BOOL message_init(void)
  Form a static tdb key from a pid.
 ******************************************************************/
 
-static TDB_DATA message_key_pid(pid_t pid)
+static TDB_DATA message_key_pid(struct process_id pid)
 {
        static char key[20];
        TDB_DATA kbuf;
 
-       slprintf(key, sizeof(key)-1, "PID/%d", (int)pid);
+       slprintf(key, sizeof(key)-1, "PID/%s", procid_str_static(&pid));
        
        kbuf.dptr = (char *)key;
        kbuf.dsize = strlen(key)+1;
@@ -140,8 +142,9 @@ static TDB_DATA message_key_pid(pid_t pid)
  then delete its record in the database.
 ****************************************************************************/
 
-static BOOL message_notify(pid_t pid)
+static BOOL message_notify(struct process_id procid)
 {
+       pid_t pid = procid.pid;
        /*
         * Doing kill with a non-positive pid causes messages to be
         * sent to places we don't want.
@@ -152,7 +155,7 @@ static BOOL message_notify(pid_t pid)
        if (kill(pid, SIGUSR1) == -1) {
                if (errno == ESRCH) {
                        DEBUG(2,("pid %d doesn't exist - deleting messages record\n", (int)pid));
-                       tdb_delete(tdb, message_key_pid(pid));
+                       tdb_delete(tdb, message_key_pid(procid));
                } else {
                        DEBUG(2,("message to process %d failed - %s\n", (int)pid, strerror(errno)));
                }
@@ -165,8 +168,10 @@ static BOOL message_notify(pid_t pid)
  Send a message to a particular pid.
 ****************************************************************************/
 
-static BOOL message_send_pid_internal(pid_t pid, int msg_type, const void *buf, size_t len,
-                     BOOL duplicates_allowed, unsigned int timeout)
+static BOOL message_send_pid_internal(struct process_id pid, int msg_type,
+                                     const void *buf, size_t len,
+                                     BOOL duplicates_allowed,
+                                     unsigned int timeout)
 {
        TDB_DATA kbuf;
        TDB_DATA dbuf;
@@ -180,12 +185,12 @@ static BOOL message_send_pid_internal(pid_t pid, int msg_type, const void *buf,
         * sent to places we don't want.
         */
 
-       SMB_ASSERT(pid > 0);
+       SMB_ASSERT(procid_to_pid(&pid) > 0);
 
        rec.msg_version = MESSAGE_VERSION;
        rec.msg_type = msg_type;
        rec.dest = pid;
-       rec.src = sys_getpid();
+       rec.src = procid_self();
        rec.len = len;
 
        kbuf = message_key_pid(pid);
@@ -288,7 +293,7 @@ static BOOL message_send_pid_internal(pid_t pid, int msg_type, const void *buf,
  Send a message to a particular pid - no timeout.
 ****************************************************************************/
 
-BOOL message_send_pid(pid_t pid, int msg_type, const void *buf, size_t len, BOOL duplicates_allowed)
+BOOL message_send_pid(struct process_id pid, int msg_type, const void *buf, size_t len, BOOL duplicates_allowed)
 {
        return message_send_pid_internal(pid, msg_type, buf, len, duplicates_allowed, 0);
 }
@@ -297,7 +302,7 @@ BOOL message_send_pid(pid_t pid, int msg_type, const void *buf, size_t len, BOOL
  Send a message to a particular pid, with timeout in seconds.
 ****************************************************************************/
 
-BOOL message_send_pid_with_timeout(pid_t pid, int msg_type, const void *buf, size_t len,
+BOOL message_send_pid_with_timeout(struct process_id pid, int msg_type, const void *buf, size_t len,
                BOOL duplicates_allowed, unsigned int timeout)
 {
        return message_send_pid_internal(pid, msg_type, buf, len, duplicates_allowed, timeout);
@@ -307,7 +312,7 @@ BOOL message_send_pid_with_timeout(pid_t pid, int msg_type, const void *buf, siz
  Count the messages pending for a particular pid. Expensive....
 ****************************************************************************/
 
-unsigned int messages_pending_for_pid(pid_t pid)
+unsigned int messages_pending_for_pid(struct process_id pid)
 {
        TDB_DATA kbuf;
        TDB_DATA dbuf;
@@ -349,7 +354,7 @@ static BOOL retrieve_all_messages(char **msgs_buf, size_t *total_len)
        *msgs_buf = NULL;
        *total_len = 0;
 
-       kbuf = message_key_pid(sys_getpid());
+       kbuf = message_key_pid(pid_to_procid(sys_getpid()));
 
        if (tdb_chainlock(tdb, kbuf) == -1)
                return False;
@@ -377,7 +382,8 @@ static BOOL retrieve_all_messages(char **msgs_buf, size_t *total_len)
  Parse out the next message for the current process.
 ****************************************************************************/
 
-static BOOL message_recv(char *msgs_buf, size_t total_len, int *msg_type, pid_t *src, char **buf, size_t *len)
+static BOOL message_recv(char *msgs_buf, size_t total_len, int *msg_type,
+                        struct process_id *src, char **buf, size_t *len)
 {
        struct message_rec rec;
        char *ret_buf = *buf;
@@ -420,7 +426,7 @@ static BOOL message_recv(char *msgs_buf, size_t total_len, int *msg_type, pid_t
 void message_dispatch(void)
 {
        int msg_type;
-       pid_t src;
+       struct process_id src;
        char *buf;
        char *msgs_buf;
        size_t len, total_len;
@@ -438,8 +444,9 @@ void message_dispatch(void)
                return;
 
        for (buf = msgs_buf; message_recv(msgs_buf, total_len, &msg_type, &src, &buf, &len); buf += len) {
-               DEBUG(10,("message_dispatch: received msg_type=%d src_pid=%u\n",
-                         msg_type, (unsigned int) src));
+               DEBUG(10,("message_dispatch: received msg_type=%d "
+                         "src_pid=%u\n", msg_type,
+                         (unsigned int) procid_to_pid(&src)));
                n_handled = 0;
                for (dfn = dispatch_fns; dfn; dfn = dfn->next) {
                        if (dfn->msg_type == msg_type) {
@@ -464,7 +471,8 @@ void message_dispatch(void)
 ****************************************************************************/
 
 void message_register(int msg_type, 
-                     void (*fn)(int msg_type, pid_t pid, void *buf, size_t len))
+                     void (*fn)(int msg_type, struct process_id pid,
+                                void *buf, size_t len))
 {
        struct dispatch_fns *dfn;
 
@@ -543,8 +551,9 @@ static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, void
                /* If the pid was not found delete the entry from connections.tdb */
 
                if (errno == ESRCH) {
-                       DEBUG(2,("pid %u doesn't exist - deleting connections %d [%s]\n",
-                                       (unsigned int)crec.pid, crec.cnum, crec.name));
+                       DEBUG(2,("pid %s doesn't exist - deleting connections %d [%s]\n",
+                                procid_str_static(&crec.pid),
+                                crec.cnum, crec.name));
                        tdb_delete(the_tdb, kbuf);
                }
        }
index 49121d12ca177d8617ad221be419200bc70972c3..885faf8d80e17afe2083a604eeb6af5087ff1024 100644 (file)
@@ -231,77 +231,3 @@ void smb_run_idle_events(time_t now)
 
        return;
 }
-
-/***************************************************************************
- * This Function registers a exit event
- *
- * the registered functions are run on exit()
- * and maybe shutdown idle connections (e.g. to an LDAP server)
- ***************************************************************************/
-
-struct smb_exit_list_ent {
-       struct smb_exit_list_ent *prev,*next;
-       smb_event_id_t id;
-       smb_exit_event_fn *fn;
-       void *data;
-};
-
-static struct smb_exit_list_ent *smb_exit_event_list = NULL;
-
-smb_event_id_t smb_register_exit_event(smb_exit_event_fn *fn, void *data)
-{
-       struct smb_exit_list_ent *event;
-       static smb_event_id_t smb_exit_event_id = 1;
-
-       if (!fn) {      
-               return SMB_EVENT_ID_INVALID;
-       }
-
-       event = SMB_MALLOC_P(struct smb_exit_list_ent);
-       if (!event) {
-               DEBUG(0,("malloc() failed!\n"));
-               return SMB_EVENT_ID_INVALID;
-       }
-       event->fn = fn;
-       event->data = data;
-       event->id = smb_exit_event_id++;
-
-       DLIST_ADD(smb_exit_event_list,event);
-
-       return event->id;
-}
-
-BOOL smb_unregister_exit_event(smb_event_id_t id)
-{
-       struct smb_exit_list_ent *event = smb_exit_event_list;
-       
-       while(event) {
-               if (event->id == id) {
-                       DLIST_REMOVE(smb_exit_event_list,event);
-                       SAFE_FREE(event);
-                       return True;
-               }
-               event = event->next;
-       }
-       
-       return False;
-}
-
-void smb_run_exit_events(void)
-{
-       struct smb_exit_list_ent *event = smb_exit_event_list;
-       struct smb_exit_list_ent *tmp = NULL;
-
-       while (event) {
-               event->fn(&event->data);
-               tmp = event;
-               event = event->next;
-               /* exit event should only run one time :-)*/
-               SAFE_FREE(tmp);
-       }
-
-       /* the list is empty now...*/
-       smb_exit_event_list = NULL;
-
-       return;
-}
index 20a8e82ce23e48df499a72e329dfdae365010ddb..b041eb7f1b2d5b1e2b300a0cff3b01c3661eb0c5 100644 (file)
@@ -57,7 +57,7 @@ pid_t pidfile_pid(const char *name)
                goto noproc;
        }
        
-       if (!process_exists((pid_t)ret)) {
+       if (!process_exists_by_pid(ret)) {
                goto noproc;
        }
 
index d95c1ba4c132b12e021b50ad8b62b7747a730423..ff0631b82f184c75cf42bcbb7ce8317698d91ccd 100644 (file)
@@ -397,6 +397,8 @@ static BOOL privilege_set_add(PRIVILEGE_SET *priv_set, LUID_ATTR set)
 
 /*********************************************************************
  Generate the LUID_ATTR structure based on a bitmask
+ The assumption here is that the privilege has already been validated
+ so we are guaranteed to find it in the list. 
 *********************************************************************/
 
 LUID_ATTR get_privilege_luid( SE_PRIV *mask )
@@ -404,8 +406,7 @@ LUID_ATTR get_privilege_luid( SE_PRIV *mask )
        LUID_ATTR priv_luid;
        int i;
 
-       priv_luid.attr = 0;
-       priv_luid.luid.high = 0;
+       ZERO_STRUCT( priv_luid );
        
        for ( i=0; !se_priv_equal(&privs[i].se_priv, &se_priv_end); i++ ) {
        
index cf7c8fc87f273f9aafe4b681ebbbca101357a0b6..f08a67a22c891f5cbc7c807458818ec1c5405734 100644 (file)
@@ -267,7 +267,11 @@ ATTRIB_MAP_ENTRY sidmap_attr_list[] = {
                return; 
 
        while ( list[i] ) {
-               SAFE_FREE( list[i] );
+               /* SAFE_FREE generates a warning here that can't be gotten rid
+                * of with CONST_DISCARD */
+               if (list[i] != NULL) {
+                       free(CONST_DISCARD(char *, list[i]));
+               }
                i+=1;
        }
 
index 798cb3fff74c17ca9a711b1a9bcc7dee3fbd6ae3..4679b864874a01115d5eb92f257691c5afd9bdc6 100644 (file)
 #include "includes.h"
 #include "smbldap.h"
 
+/**********************************************************************
+ Add the account-policies below the sambaDomain object to LDAP, 
+*********************************************************************/
+static NTSTATUS add_new_domain_account_policies(struct smbldap_state *ldap_state,
+                                               const char *domain_name)
+{
+       NTSTATUS ntstatus = NT_STATUS_UNSUCCESSFUL;
+       int i, rc;
+       uint32 policy_default;
+       const char *policy_attr = NULL;
+       pstring dn;
+       LDAPMod **mods = NULL;
+
+       DEBUG(3,("Adding new account policies for domain\n"));
+       
+       pstr_sprintf(dn, "%s=%s,%s", 
+               get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN),
+               domain_name, lp_ldap_suffix());
+
+       for (i=1; decode_account_policy_name(i) != NULL; i++) {
+
+               pstring val;
+
+               policy_attr = get_account_policy_attr(i);
+               if (!policy_attr) {
+                       DEBUG(0,("add_new_domain_account_policies: ops. no policy!\n"));
+                       continue;
+               }
+
+               if (!account_policy_get_default(i, &policy_default)) {
+                       DEBUG(0,("add_new_domain_account_policies: failed to get default account policy\n"));
+                       return ntstatus;
+               }
+
+               DEBUG(10,("add_new_domain_account_policies: adding \"%s\" with value: %d\n", policy_attr, policy_default));
+
+               pstr_sprintf(val, "%d", policy_default); 
+
+               smbldap_set_mod( &mods, LDAP_MOD_REPLACE, policy_attr, val);
+
+               rc = smbldap_modify(ldap_state, dn, mods);
+
+               if (rc!=LDAP_SUCCESS) {
+                       char *ld_error = NULL;
+                       ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error);
+                       DEBUG(1,("failed to add account policies to dn= %s with: %s\n\t%s\n",
+                               dn, ldap_err2string(rc),
+                               ld_error ? ld_error : "unknown"));
+                       SAFE_FREE(ld_error);
+                       ldap_mods_free(mods, True);
+                       return ntstatus;
+               }
+       }
+
+       ldap_mods_free(mods, True);
+
+       return NT_STATUS_OK;
+}
+
 /**********************************************************************
  Add the sambaDomain to LDAP, so we don't have to search for this stuff
  again.  This is a once-add operation for now.
@@ -200,6 +259,13 @@ NTSTATUS smbldap_search_domain_info(struct smbldap_state *ldap_state,
                        goto failed;
                }
                        
+               status = add_new_domain_account_policies(ldap_state, domain_name);
+               if (!NT_STATUS_IS_OK(status)) {
+                       DEBUG(0, ("Adding domain account policies for %s failed with %s\n", 
+                               domain_name, nt_errstr(status)));
+                       goto failed;
+               }
+
                return smbldap_search_domain_info(ldap_state, result, domain_name, False);
                
        } 
index 13e330dd97a9d59c81096d979a8dfa8eb50464f0..6d6d7817f1abbc13b01c25724cb51f3ee7e19f0a 100644 (file)
@@ -225,10 +225,16 @@ int smbrunsecret(const char *cmd, const char *secret)
                 */
                int status = 0;
                pid_t wpid;
+               size_t towrite;
+               ssize_t wrote;
                
                close(ifd[0]);
                /* send the secret */
-               write(ifd[1], secret, strlen(secret));
+               towrite = strlen(secret);
+               wrote = write(ifd[1], secret, towrite);
+               if ( wrote != towrite ) {
+                   DEBUG(0,("smbrunsecret: wrote %ld of %lu bytes\n",(long)wrote,(unsigned long)towrite));
+               }
                fsync(ifd[1]);
                close(ifd[1]);
 
index 8ee3c257f6b642723a795de60e36076aac946fd4..8f03fd66ff1888749bccb9cd26598a1d8660cb83 100644 (file)
@@ -30,7 +30,7 @@
  * Respond to a POOL_USAGE message by sending back string form of memory
  * usage stats.
  **/
-void msg_pool_usage(int msg_type, pid_t src_pid,
+void msg_pool_usage(int msg_type, struct process_id src_pid,
                    void *UNUSED(buf), size_t UNUSED(len))
 {
        off_t reply;
@@ -41,7 +41,7 @@ void msg_pool_usage(int msg_type, pid_t src_pid,
        DEBUG(2,("Got POOL_USAGE\n"));
 
        reply = talloc_total_size(NULL);
-       fstr_sprintf(reply_str, "%lld", reply);
+       fstr_sprintf(reply_str, "%ld", (long)reply);
        
        message_send_pid(src_pid, MSG_POOL_USAGE,
                         reply_str, strlen(reply_str)+1, True);
index 5e0f5646fca9eb3385f4bc6e9adc93ed67821b1e..385762e82c2e2fe4d04ccb702f5b13327d90244c 100644 (file)
@@ -782,6 +782,15 @@ BOOL nt_time_is_zero(NTTIME *nt)
        return False;
 }
 
+/****************************************************************************
+ Check if two NTTIMEs are the same.
+****************************************************************************/
+
+BOOL nt_time_equals(NTTIME *nt1, NTTIME *nt2)
+{
+       return (nt1->high == nt2->high && nt1->low == nt2->low);
+}
+
 /****************************************************************************
  Return a timeval difference in usec.
 ****************************************************************************/
@@ -792,6 +801,135 @@ SMB_BIG_INT usec_time_diff(const struct timeval *larget, const struct timeval *s
        return (sec_diff * 1000000) + (SMB_BIG_INT)(larget->tv_usec - smallt->tv_usec);
 }
 
+/*
+  return a timeval struct with the given elements
+*/
+struct timeval timeval_set(uint32_t secs, uint32_t usecs)
+{
+       struct timeval tv;
+       tv.tv_sec = secs;
+       tv.tv_usec = usecs;
+       return tv;
+}
+
+/*
+  return a zero timeval
+*/
+struct timeval timeval_zero(void)
+{
+       return timeval_set(0,0);
+}
+
+/*
+  return True if a timeval is zero
+*/
+BOOL timeval_is_zero(const struct timeval *tv)
+{
+       return tv->tv_sec == 0 && tv->tv_usec == 0;
+}
+
+/*
+  return a timeval for the current time
+*/
+struct timeval timeval_current(void)
+{
+       struct timeval tv;
+       GetTimeOfDay(&tv);
+       return tv;
+}
+
+/*
+  return a timeval ofs microseconds after tv
+*/
+struct timeval timeval_add(const struct timeval *tv,
+                          uint32_t secs, uint32_t usecs)
+{
+       struct timeval tv2 = *tv;
+       tv2.tv_sec += secs;
+       tv2.tv_usec += usecs;
+       tv2.tv_sec += tv2.tv_usec / 1000000;
+       tv2.tv_usec = tv2.tv_usec % 1000000;
+       return tv2;
+}
+
+/*
+  return the sum of two timeval structures
+*/
+struct timeval timeval_sum(const struct timeval *tv1,
+                          const struct timeval *tv2)
+{
+       return timeval_add(tv1, tv2->tv_sec, tv2->tv_usec);
+}
+
+/*
+  return a timeval secs/usecs into the future
+*/
+struct timeval timeval_current_ofs(uint32_t secs, uint32_t usecs)
+{
+       struct timeval tv = timeval_current();
+       return timeval_add(&tv, secs, usecs);
+}
+
+/*
+  compare two timeval structures. 
+  Return -1 if tv1 < tv2
+  Return 0 if tv1 == tv2
+  Return 1 if tv1 > tv2
+*/
+int timeval_compare(const struct timeval *tv1, const struct timeval *tv2)
+{
+       if (tv1->tv_sec  > tv2->tv_sec)  return 1;
+       if (tv1->tv_sec  < tv2->tv_sec)  return -1;
+       if (tv1->tv_usec > tv2->tv_usec) return 1;
+       if (tv1->tv_usec < tv2->tv_usec) return -1;
+       return 0;
+}
+
+/*
+  return the difference between two timevals as a timeval
+  if tv1 comes after tv2, then return a zero timeval
+  (this is *tv2 - *tv1)
+*/
+struct timeval timeval_until(const struct timeval *tv1,
+                            const struct timeval *tv2)
+{
+       struct timeval t;
+       if (timeval_compare(tv1, tv2) >= 0) {
+               return timeval_zero();
+       }
+       t.tv_sec = tv2->tv_sec - tv1->tv_sec;
+       if (tv1->tv_usec > tv2->tv_usec) {
+               t.tv_sec--;
+               t.tv_usec = 1000000 - (tv1->tv_usec - tv2->tv_usec);
+       } else {
+               t.tv_usec = tv2->tv_usec - tv1->tv_usec;
+       }
+       return t;
+}
+
+/*
+  return the lesser of two timevals
+*/
+struct timeval timeval_min(const struct timeval *tv1,
+                          const struct timeval *tv2)
+{
+       if (tv1->tv_sec < tv2->tv_sec) return *tv1;
+       if (tv1->tv_sec > tv2->tv_sec) return *tv2;
+       if (tv1->tv_usec < tv2->tv_usec) return *tv1;
+       return *tv2;
+}
+
+/*
+  return the greater of two timevals
+*/
+struct timeval timeval_max(const struct timeval *tv1,
+                          const struct timeval *tv2)
+{
+       if (tv1->tv_sec > tv2->tv_sec) return *tv1;
+       if (tv1->tv_sec < tv2->tv_sec) return *tv2;
+       if (tv1->tv_usec > tv2->tv_usec) return *tv1;
+       return *tv2;
+}
 
 /****************************************************************************
  convert ASN.1 GeneralizedTime string to unix-time
index 39938921968dc82dd74c49a53a3c154449f23b56..a5cfe95b660fd931b168bdee55db0a82862aa03e 100644 (file)
@@ -1404,12 +1404,22 @@ BOOL same_net(struct in_addr ip1,struct in_addr ip2,struct in_addr mask)
  Check if a process exists. Does this work on all unixes?
 ****************************************************************************/
 
-BOOL process_exists(pid_t pid)
+BOOL process_exists(const struct process_id pid)
 {
+       if (!procid_is_local(&pid)) {
+               /* This *SEVERELY* needs fixing. */
+               return True;
+       }
+
        /* Doing kill with a non-positive pid causes messages to be
         * sent to places we don't want. */
-       SMB_ASSERT(pid > 0);
-       return(kill(pid,0) == 0 || errno != ESRCH);
+       SMB_ASSERT(pid.pid > 0);
+       return(kill(pid.pid,0) == 0 || errno != ESRCH);
+}
+
+BOOL process_exists_by_pid(pid_t pid)
+{
+       return process_exists(pid_to_procid(pid));
 }
 
 /*******************************************************************
@@ -2756,3 +2766,57 @@ uint32 map_share_mode_to_deny_mode(uint32 share_access, uint32 private_options)
 
        return (uint32)-1;
 }
+
+pid_t procid_to_pid(const struct process_id *proc)
+{
+       return proc->pid;
+}
+
+struct process_id pid_to_procid(pid_t pid)
+{
+       struct process_id result;
+       result.pid = pid;
+       return result;
+}
+
+struct process_id procid_self(void)
+{
+       return pid_to_procid(sys_getpid());
+}
+
+BOOL procid_equal(const struct process_id *p1, const struct process_id *p2)
+{
+       return (p1->pid == p2->pid);
+}
+
+BOOL procid_is_me(const struct process_id *pid)
+{
+       return (pid->pid == sys_getpid());
+}
+
+struct process_id interpret_pid(const char *pid_string)
+{
+       return pid_to_procid(atoi(pid_string));
+}
+
+char *procid_str_static(const struct process_id *pid)
+{
+       static fstring str;
+       fstr_sprintf(str, "%d", pid->pid);
+       return str;
+}
+
+char *procid_str(TALLOC_CTX *mem_ctx, const struct process_id *pid)
+{
+       return talloc_strdup(mem_ctx, procid_str_static(pid));
+}
+
+BOOL procid_valid(const struct process_id *pid)
+{
+       return (pid->pid != -1);
+}
+
+BOOL procid_is_local(const struct process_id *pid)
+{
+       return True;
+}
index 2cc6c6ebae46c0325dbf553b538b88932a154064..2e7866c0559f314b91993e3279f34773727f49c7 100644 (file)
@@ -2,6 +2,11 @@
    Unix SMB/CIFS implementation.
    kerberos authorization data (PAC) utility library
    Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2003   
+   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005
+   Copyright (C) Andrew Tridgell 2001
+   Copyright (C) Luke Howard 2002-2003
+   Copyright (C) Stefan Metzmacher 2004-2005
+   Copyright (C) Guenther Deschner 2005
    
    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
 
 #ifdef HAVE_KRB5
 
-static DATA_BLOB unwrap_pac(DATA_BLOB *auth_data)
-{
-       DATA_BLOB pac_contents;
-       ASN1_DATA data;
-       int data_type;
-
-       asn1_load(&data, *auth_data);
-       asn1_start_tag(&data, ASN1_SEQUENCE(0));
-       asn1_start_tag(&data, ASN1_SEQUENCE(0));
-       asn1_start_tag(&data, ASN1_CONTEXT(0));
-       asn1_read_Integer(&data, &data_type);
-       asn1_end_tag(&data);
-       asn1_start_tag(&data, ASN1_CONTEXT(1));
-       asn1_read_OctetString(&data, &pac_contents);
-       asn1_end_tag(&data);
-       asn1_end_tag(&data);
-       asn1_end_tag(&data);
-       asn1_free(&data);
-       return pac_contents;
-}
-
 static BOOL pac_io_logon_name(const char *desc, PAC_LOGON_NAME *logon_name,
                              prs_struct *ps, int depth)
 {
@@ -75,6 +59,8 @@ static BOOL pac_io_logon_name(const char *desc, PAC_LOGON_NAME *logon_name,
 }
 
 
+
+#if 0 /* Unused (handled now in net_io_user_info3()) - Guenther */
 static BOOL pac_io_krb_sids(const char *desc, KRB_SID_AND_ATTRS *sid_and_attr,
                            prs_struct *ps, int depth)
 {
@@ -159,6 +145,7 @@ static BOOL pac_io_krb_sid_and_attr_array(const char *desc,
        return True;
 
 }
+#endif
 
 static BOOL pac_io_group_membership(const char *desc, 
                                    GROUP_MEMBERSHIP *membership,
@@ -216,27 +203,34 @@ static BOOL pac_io_group_membership_array(const char *desc,
 
 }
 
+#if 0 /* Unused, replaced using an expanded net_io_user_info3() now - Guenther */
 static BOOL pac_io_pac_logon_info(const char *desc, PAC_LOGON_INFO *info, 
                                  prs_struct *ps, int depth)
 {
-       uint32 garbage;
+       uint32 garbage, i;
+
        if (NULL == info)
                return False;
 
        prs_debug(ps, depth, desc, "pac_io_pac_logon_info");
        depth++;
 
-       if (!prs_uint32("unknown", ps, depth, &garbage))
+       if (!prs_align(ps))
                return False;
-       if (!prs_uint32("unknown", ps, depth, &garbage))
+       if (!prs_uint32("unknown", ps, depth, &garbage)) /* 00081001 */
+               return False;
+       if (!prs_uint32("unknown", ps, depth, &garbage)) /* cccccccc */
                return False;
        if (!prs_uint32("bufferlen", ps, depth, &garbage))
                return False;
-       if (!prs_uint32("bufferlenhi", ps, depth, &garbage))
+       if (!prs_uint32("bufferlenhi", ps, depth, &garbage)) /* 00000000 */
                return False;
+
        if (!prs_uint32("pointer", ps, depth, &garbage))
                return False;
 
+       if (!prs_align(ps))
+               return False;
        if (!smb_io_time("logon_time", &info->logon_time, ps, depth))
                return False;
        if (!smb_io_time("logoff_time", &info->logoff_time, ps, depth))
@@ -270,7 +264,7 @@ static BOOL pac_io_pac_logon_info(const char *desc, PAC_LOGON_INFO *info,
 
        if (!prs_uint16("logon_count", ps, depth, &info->logon_count))
                return False;
-       if (!prs_uint16("reserved12", ps, depth, &info->reserved12))
+       if (!prs_uint16("bad_password_count", ps, depth, &info->bad_password_count))
                return False;
        if (!prs_uint32("user_rid", ps, depth, &info->user_rid))
                return False;
@@ -287,13 +281,7 @@ static BOOL pac_io_pac_logon_info(const char *desc, PAC_LOGON_INFO *info,
        if (!prs_uint32("user_flags", ps, depth, &info->user_flags))
                return False;
 
-       if (!prs_uint32("reserved13.0", ps, depth, &info->reserved13[0]))
-               return False;
-       if (!prs_uint32("reserved13.1", ps, depth, &info->reserved13[1]))
-               return False;
-       if (!prs_uint32("reserved13.2", ps, depth, &info->reserved13[2]))
-               return False;
-       if (!prs_uint32("reserved13.3", ps, depth, &info->reserved13[3]))
+       if (!prs_uint8s(False, "session_key", ps, depth, info->session_key, 16)) 
                return False;
        
        if (!smb_io_unihdr("hdr_dom_controller", 
@@ -306,30 +294,17 @@ static BOOL pac_io_pac_logon_info(const char *desc, PAC_LOGON_INFO *info,
        if (!prs_uint32("ptr_dom_sid", ps, depth, &info->ptr_dom_sid))
                return False;
 
-       if (!prs_uint32("reserved16.0", ps, depth, &info->reserved16[0]))
-               return False;
-       if (!prs_uint32("reserved16.1", ps, depth, &info->reserved16[1]))
+       if (!prs_uint8s(False, "lm_session_key", ps, depth, info->lm_session_key, 8)) 
                return False;
 
-       /* might be acb_info */
-       if (!prs_uint32("reserved17", ps, depth, &info->reserved17))
+       if (!prs_uint32("acct_flags", ps, depth, &info->acct_flags))
                return False;
 
-
-       if (!prs_uint32("reserved18.0", ps, depth, &info->reserved18[0]))
-               return False;
-       if (!prs_uint32("reserved18.1", ps, depth, &info->reserved18[1]))
-               return False;
-       if (!prs_uint32("reserved18.2", ps, depth, &info->reserved18[2]))
-               return False;
-       if (!prs_uint32("reserved18.3", ps, depth, &info->reserved18[3]))
-               return False;
-       if (!prs_uint32("reserved18.4", ps, depth, &info->reserved18[4]))
-               return False;
-       if (!prs_uint32("reserved18.5", ps, depth, &info->reserved18[5]))
-               return False;
-       if (!prs_uint32("reserved18.6", ps, depth, &info->reserved18[6]))
-               return False;
+       for (i = 0; i < 7; i++)
+       {
+               if (!prs_uint32("unkown", ps, depth, &info->unknown[i])) /* unknown */
+                        return False;
+       }
 
        if (!prs_uint32("sid_count", ps, depth, &info->sid_count))
                return False;
@@ -395,44 +370,109 @@ static BOOL pac_io_pac_logon_info(const char *desc, PAC_LOGON_INFO *info,
                                     &info->res_group_dom_sid, ps, depth))
                        return False;
 
-       if (info->ptr_res_groups)
+       if (info->ptr_res_groups) {
+
+               if (!(info->user_flgs & LOGON_RESOURCE_GROUPS)) {
+                       DEBUG(0,("user_flgs attribute does not have LOGON_RESOURCE_GROUPS\n"));
+                       /* return False; */
+               }
+
                if (!pac_io_group_membership_array("res group membership",
                                                   &info->res_groups,
                                                   info->res_group_count,
                                                   ps, depth))
                        return False;
+       }
+
+       return True;
+}
+#endif
+
+static BOOL pac_io_pac_logon_info(const char *desc, PAC_LOGON_INFO *info, 
+                                 prs_struct *ps, int depth)
+{
+       uint32 garbage;
+       BOOL kerb_validation_info = True;
+
+       if (NULL == info)
+               return False;
+
+       prs_debug(ps, depth, desc, "pac_io_pac_logon_info");
+       depth++;
+
+       if (!prs_align(ps))
+               return False;
+       if (!prs_uint32("unknown", ps, depth, &garbage)) /* 00081001 */
+               return False;
+       if (!prs_uint32("unknown", ps, depth, &garbage)) /* cccccccc */
+               return False;
+       if (!prs_uint32("bufferlen", ps, depth, &garbage))
+               return False;
+       if (!prs_uint32("bufferlenhi", ps, depth, &garbage)) /* 00000000 */
+               return False;
+
+       if(!net_io_user_info3("", &info->info3, ps, depth, 3, kerb_validation_info))
+               return False;
+
+       if (info->info3.ptr_res_group_dom_sid) {
+               if (!smb_io_dom_sid2("res_group_dom_sid", 
+                                    &info->res_group_dom_sid, ps, depth))
+                       return False;
+       }
+
+       if (info->info3.ptr_res_groups) {
+
+               if (!(info->info3.user_flgs & LOGON_RESOURCE_GROUPS)) {
+                       DEBUG(0,("user_flgs attribute does not have LOGON_RESOURCE_GROUPS\n"));
+                       /* return False; */
+               }
+
+               if (!pac_io_group_membership_array("res group membership",
+                                                  &info->res_groups,
+                                                  info->info3.res_group_count,
+                                                  ps, depth))
+                       return False;
+       }
 
        return True;
 }
 
 
+
 static BOOL pac_io_pac_signature_data(const char *desc, 
                                      PAC_SIGNATURE_DATA *data, uint32 length,
                                      prs_struct *ps, int depth)
 {
        uint32 siglen = length - sizeof(uint32);
-       if (NULL == data)
-               return False;
-
        prs_debug(ps, depth, desc, "pac_io_pac_signature_data");
        depth++;
+       
+       if (data == NULL)
+               return False;
 
+       if (!prs_align(ps))
+               return False;
        if (!prs_uint32("type", ps, depth, &data->type))
                return False;
-       if (UNMARSHALLING(ps)) {
-               data->signature = PRS_ALLOC_MEM(ps, unsigned char, siglen);
-               if (!data->signature) {
+
+       if (UNMARSHALLING(ps) && length) {
+               data->signature.buffer = PRS_ALLOC_MEM(ps, uint8, siglen);
+               if (!data->signature.buffer) {
                        DEBUG(3, ("No memory available\n"));
                        return False;
                }
        }
-       if (!prs_uint8s(False, "signature", ps, depth, data->signature,siglen))
+
+       data->signature.buf_len = siglen;
+
+       if (!prs_uint8s(False, "signature", ps, depth, data->signature.buffer, data->signature.buf_len))
                return False;
 
+
        return True;
 }
 
-static BOOL pac_io_pac_info_hdr_ctr(const char *desc, PAC_INFO_HDR *hdr,
+static BOOL pac_io_pac_info_hdr_ctr(const char *desc, PAC_BUFFER *hdr,
                                    prs_struct *ps, int depth)
 {
        if (NULL == hdr)
@@ -445,8 +485,8 @@ static BOOL pac_io_pac_info_hdr_ctr(const char *desc, PAC_INFO_HDR *hdr,
                return False;
 
        if (hdr->offset != prs_offset(ps)) {
-               DEBUG(5, ("offset in header(x%x) and data(x%x) do not match\n",
-                         hdr->offset, prs_offset(ps)));
+               DEBUG(5,("offset in header(x%x) and data(x%x) do not match, correcting\n",
+                        hdr->offset, prs_offset(ps)));
                prs_set_offset(ps, hdr->offset);
        }
 
@@ -518,10 +558,15 @@ static BOOL pac_io_pac_info_hdr_ctr(const char *desc, PAC_INFO_HDR *hdr,
                prs_set_offset(ps, prs_offset(ps) + hdr->size);
        }
 
+#if 0
+       /* obscure pad */
+       if (!prs_uint32("pad", ps, depth, &hdr->pad))
+               return False;
+#endif
        return True;
 }
 
-static BOOL pac_io_pac_info_hdr(const char *desc, PAC_INFO_HDR *hdr, 
+static BOOL pac_io_pac_info_hdr(const char *desc, PAC_BUFFER *hdr, 
                                prs_struct *ps, int depth)
 {
        if (NULL == hdr)
@@ -563,19 +608,19 @@ static BOOL pac_io_pac_data(const char *desc, PAC_DATA *data,
                return False;
 
        if (UNMARSHALLING(ps) && data->num_buffers > 0) {
-               if ((data->pac_info_hdr_ptr = PRS_ALLOC_MEM(ps, PAC_INFO_HDR, data->num_buffers)) == NULL) {
+               if ((data->pac_buffer = PRS_ALLOC_MEM(ps, PAC_BUFFER, data->num_buffers)) == NULL) {
                        return False;
                }
        }
 
        for (i=0; i<data->num_buffers; i++) {
-               if (!pac_io_pac_info_hdr(desc, &data->pac_info_hdr_ptr[i], ps, 
+               if (!pac_io_pac_info_hdr(desc, &data->pac_buffer[i], ps, 
                                         depth))
                        return False;
        }
 
        for (i=0; i<data->num_buffers; i++) {
-               if (!pac_io_pac_info_hdr_ctr(desc, &data->pac_info_hdr_ptr[i],
+               if (!pac_io_pac_info_hdr_ctr(desc, &data->pac_buffer[i],
                                             ps, depth))
                        return False;
        }
@@ -583,25 +628,300 @@ static BOOL pac_io_pac_data(const char *desc, PAC_DATA *data,
        return True;
 }
 
-PAC_DATA *decode_pac_data(DATA_BLOB *auth_data, TALLOC_CTX *ctx)
+static NTSTATUS check_pac_checksum(TALLOC_CTX *mem_ctx, 
+                                  DATA_BLOB pac_data,
+                                  PAC_SIGNATURE_DATA *sig,
+                                  krb5_context context,
+                                  krb5_keyblock *keyblock)
+{
+       krb5_error_code ret;
+       krb5_checksum cksum;
+       krb5_keyusage usage = 0;
+
+       smb_krb5_checksum_from_pac_sig(&cksum, sig);
+
+#ifdef HAVE_KRB5_KU_OTHER_CKSUM /* Heimdal */
+       usage = KRB5_KU_OTHER_CKSUM;
+#elif defined(HAVE_KRB5_KEYUSAGE_APP_DATA_CKSUM) /* MIT */
+       usage = KRB5_KEYUSAGE_APP_DATA_CKSUM;
+#else
+#error UNKNOWN_KRB5_KEYUSAGE
+#endif
+
+       ret = smb_krb5_verify_checksum(context, 
+                                      keyblock, 
+                                      usage, 
+                                      &cksum,
+                                      pac_data.data, 
+                                      pac_data.length);
+
+       if (ret) {
+               DEBUG(2,("check_pac_checksum: PAC Verification failed: %s (%d)\n", 
+                       error_message(ret), ret));
+               return NT_STATUS_ACCESS_DENIED;
+       }
+
+       return NT_STATUS_OK;
+}
+
+static NTSTATUS parse_pac_data(TALLOC_CTX *mem_ctx, DATA_BLOB *pac_data_blob, PAC_DATA *pac_data)
 {
-       DATA_BLOB pac_data_blob = unwrap_pac(auth_data);
        prs_struct ps;
-       PAC_DATA *pac_data;
+       PAC_DATA *my_pac;
 
-       DEBUG(5,("dump_pac_data\n"));
-       prs_init(&ps, pac_data_blob.length, ctx, UNMARSHALL);
-       prs_copy_data_in(&ps, (char *)pac_data_blob.data, pac_data_blob.length);
-       prs_set_offset(&ps, 0);
+       if (!prs_init(&ps, pac_data_blob->length, mem_ctx, UNMARSHALL))
+               return NT_STATUS_NO_MEMORY;
 
-       data_blob_free(&pac_data_blob);
+       if (!prs_copy_data_in(&ps, (char *)pac_data_blob->data, pac_data_blob->length))
+               return NT_STATUS_INVALID_PARAMETER;
+
+       prs_set_offset(&ps, 0);
 
-       pac_data = TALLOC_ZERO_P(ctx, PAC_DATA);
-       pac_io_pac_data("pac data", pac_data, &ps, 0);
+       my_pac = TALLOC_ZERO_P(mem_ctx, PAC_DATA);
+       if (!pac_io_pac_data("pac data", my_pac, &ps, 0))
+               return NT_STATUS_INVALID_PARAMETER;
 
        prs_mem_free(&ps);
 
-       return pac_data;
+       *pac_data = *my_pac;
+
+       return NT_STATUS_OK;
+}
+
+/* just for debugging, will be removed later - Guenther */
+char *pac_group_attr_string(uint32 attr)
+{
+       fstring name = "";
+
+       if (!attr)
+               return NULL;
+
+       if (attr & SE_GROUP_MANDATORY)                  fstrcat(name, "SE_GROUP_MANDATORY ");
+       if (attr & SE_GROUP_ENABLED_BY_DEFAULT)         fstrcat(name, "SE_GROUP_ENABLED_BY_DEFAULT ");
+       if (attr & SE_GROUP_ENABLED)                    fstrcat(name, "SE_GROUP_ENABLED ");
+       if (attr & SE_GROUP_OWNER)                      fstrcat(name, "SE_GROUP_OWNER ");
+       if (attr & SE_GROUP_USE_FOR_DENY_ONLY)          fstrcat(name, "SE_GROUP_USE_FOR_DENY_ONLY ");
+       if (attr & SE_GROUP_LOGON_ID)                   fstrcat(name, "SE_GROUP_LOGON_ID ");
+       if (attr & SE_GROUP_RESOURCE)                   fstrcat(name, "SE_GROUP_RESOURCE ");
+
+       return SMB_STRDUP(name);
+}
+
+/* just for debugging, will be removed later - Guenther */
+static void dump_pac_logon_info(PAC_LOGON_INFO *logon_info) {
+
+       DOM_SID dom_sid, res_group_dom_sid;
+       int i;
+       char *attr_string;
+       uint32 user_flgs = logon_info->info3.user_flgs;
+
+       if (logon_info->info3.ptr_res_group_dom_sid) {
+               sid_copy(&res_group_dom_sid, &logon_info->res_group_dom_sid.sid);
+       }
+       sid_copy(&dom_sid, &logon_info->info3.dom_sid.sid);
+       
+       DEBUG(10,("The PAC:\n"));
+       
+       DEBUGADD(10,("\tUser Flags: 0x%x (%d)\n", user_flgs, user_flgs));
+       if (user_flgs & LOGON_EXTRA_SIDS)
+               DEBUGADD(10,("\tUser Flags: LOGON_EXTRA_SIDS 0x%x (%d)\n", LOGON_EXTRA_SIDS, LOGON_EXTRA_SIDS));
+       if (user_flgs & LOGON_RESOURCE_GROUPS)
+               DEBUGADD(10,("\tUser Flags: LOGON_RESOURCE_GROUPS 0x%x (%d)\n", LOGON_RESOURCE_GROUPS, LOGON_RESOURCE_GROUPS));
+       DEBUGADD(10,("\tUser SID: %s-%d\n", sid_string_static(&dom_sid), logon_info->info3.user_rid));
+       DEBUGADD(10,("\tGroup SID: %s-%d\n", sid_string_static(&dom_sid), logon_info->info3.group_rid));
+
+       DEBUGADD(10,("\tGroup Membership (Global and Universal Groups of own domain):\n"));
+       for (i = 0; i < logon_info->info3.num_groups; i++) {
+               attr_string = pac_group_attr_string(logon_info->info3.gids[i].attr);
+               DEBUGADD(10,("\t\t%d: sid: %s-%d\n\t\t   attr: 0x%x == %s\n", 
+                       i, sid_string_static(&dom_sid), 
+                       logon_info->info3.gids[i].g_rid,
+                       logon_info->info3.gids[i].attr,
+                       attr_string));
+               SAFE_FREE(attr_string);
+       }
+
+       DEBUGADD(10,("\tGroup Membership (Domain Local Groups and Groups from Trusted Domains):\n"));
+       for (i = 0; i < logon_info->info3.num_other_sids; i++) {
+               attr_string = pac_group_attr_string(logon_info->info3.other_sids_attrib[i]);
+               DEBUGADD(10,("\t\t%d: sid: %s\n\t\t   attr: 0x%x == %s\n", 
+                       i, sid_string_static(&logon_info->info3.other_sids[i].sid), 
+                       logon_info->info3.other_sids_attrib[i],
+                       attr_string));
+               SAFE_FREE(attr_string);
+       }
+
+       DEBUGADD(10,("\tGroup Membership (Ressource Groups (SID History ?)):\n"));
+       for (i = 0; i < logon_info->info3.res_group_count; i++) {
+               attr_string = pac_group_attr_string(logon_info->res_groups.group_membership[i].attrs);
+               DEBUGADD(10,("\t\t%d: sid: %s-%d\n\t\t   attr: 0x%x == %s\n", 
+                       i, sid_string_static(&res_group_dom_sid),
+                       logon_info->res_groups.group_membership[i].rid,
+                       logon_info->res_groups.group_membership[i].attrs,
+                       attr_string));
+               SAFE_FREE(attr_string);
+       }
+}
+
+NTSTATUS decode_pac_data(TALLOC_CTX *mem_ctx,
+                        DATA_BLOB *pac_data_blob,
+                        krb5_context context, 
+                        krb5_keyblock *service_keyblock,
+                        krb5_const_principal client_principal,
+                        time_t tgs_authtime,
+                        PAC_DATA **pac_data)
+                        
+{
+       DATA_BLOB modified_pac_blob;
+       PAC_DATA *my_pac;
+       NTSTATUS nt_status;
+       krb5_error_code ret;
+       PAC_SIGNATURE_DATA *srv_sig = NULL;
+       PAC_SIGNATURE_DATA *kdc_sig = NULL;
+       PAC_LOGON_NAME *logon_name = NULL;
+       PAC_LOGON_INFO *logon_info = NULL;
+       krb5_principal client_principal_pac;
+       NTTIME tgs_authtime_nttime;
+       int i, srv_sig_pos = 0, kdc_sig_pos = 0;
+       fstring username;
+
+       *pac_data = NULL;
+
+       my_pac = talloc(mem_ctx, PAC_DATA);
+       if (!my_pac) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       nt_status = parse_pac_data(mem_ctx, pac_data_blob, my_pac);
+       if (!NT_STATUS_IS_OK(nt_status)) {
+               DEBUG(0,("decode_pac_data: failed to parse PAC\n"));
+               return nt_status;
+       }
+
+       modified_pac_blob = data_blob_talloc(mem_ctx, pac_data_blob->data, pac_data_blob->length);
+
+       if (my_pac->num_buffers < 4) {
+               nt_status = NT_STATUS_INVALID_PARAMETER;
+               goto out;
+       }
+
+       /* store signatures */
+       for (i=0; i < my_pac->num_buffers; i++) {
+       
+               switch (my_pac->pac_buffer[i].type) {
+               
+                       case PAC_TYPE_SERVER_CHECKSUM:
+                               if (!my_pac->pac_buffer[i].ctr->pac.srv_cksum) {
+                                       break;
+                               }
+                               
+                               srv_sig = my_pac->pac_buffer[i].ctr->pac.srv_cksum;
+                               
+                               /* get position of signature buffer */
+                               srv_sig_pos = my_pac->pac_buffer[i].offset;
+                               srv_sig_pos += sizeof(uint32);
+                               
+                               break;
+                               
+                       case PAC_TYPE_PRIVSVR_CHECKSUM:
+                               if (!my_pac->pac_buffer[i].ctr->pac.privsrv_cksum) {
+                                       break;
+                               }
+
+                               kdc_sig = my_pac->pac_buffer[i].ctr->pac.privsrv_cksum;
+                               
+                               /* get position of signature buffer */
+                               kdc_sig_pos = my_pac->pac_buffer[i].offset;
+                               kdc_sig_pos += sizeof(uint32);
+                               
+                               break;
+                               
+                       case PAC_TYPE_LOGON_NAME:
+                               if (!my_pac->pac_buffer[i].ctr->pac.logon_name) {
+                                       break;
+                               }
+
+                               logon_name = my_pac->pac_buffer[i].ctr->pac.logon_name;
+                               break;
+
+                       case PAC_TYPE_LOGON_INFO:
+                               if (!my_pac->pac_buffer[i].ctr->pac.logon_info) {
+                                       break;
+                               }
+
+                               logon_info = my_pac->pac_buffer[i].ctr->pac.logon_info;
+                               break;
+                       }
+
+       }
+
+       if (!srv_sig || !kdc_sig || !logon_name || !logon_info) {
+               nt_status = NT_STATUS_INVALID_PARAMETER;
+               goto out;
+       }
+
+       /* zero PAC_SIGNATURE_DATA signature buffer */
+       memset(&modified_pac_blob.data[srv_sig_pos], '\0', srv_sig->signature.buf_len);
+       memset(&modified_pac_blob.data[kdc_sig_pos], '\0', kdc_sig->signature.buf_len);
+
+       /* check server signature */
+       nt_status = check_pac_checksum(mem_ctx, modified_pac_blob, srv_sig, context, service_keyblock);
+       if (!NT_STATUS_IS_OK(nt_status)) {
+               DEBUG(0,("decode_pac_data: failed to verify PAC server signature\n"));
+               goto out;
+       }
+
+       /* Convert to NT time, so as not to loose accuracy in comparison */
+       unix_to_nt_time(&tgs_authtime_nttime, tgs_authtime);
+
+       if (!nt_time_equals(&tgs_authtime_nttime, &logon_name->logon_time)) {
+       
+               DEBUG(2,("decode_pac_data: Logon time mismatch between ticket and PAC!\n"));
+               DEBUGADD(2, ("decode_pac_data: PAC: %s\n", 
+                       http_timestring(nt_time_to_unix(&logon_name->logon_time))));
+               DEBUGADD(2, ("decode_pac_data: Ticket: %s\n", 
+                       http_timestring(nt_time_to_unix(&tgs_authtime_nttime))));
+               
+               nt_status = NT_STATUS_ACCESS_DENIED;
+               goto out;
+       }
+
+       if (!logon_name->len) {
+               DEBUG(2,("decode_pac_data: No Logon Name available\n"));
+               nt_status = NT_STATUS_INVALID_PARAMETER;
+               goto out;
+       }
+       rpcstr_pull(username, logon_name->username, sizeof(username), -1, STR_TERMINATE);
+
+       ret = smb_krb5_parse_name_norealm(context, username, &client_principal_pac);
+       if (ret) {
+               DEBUG(2,("decode_pac_data: Could not parse name from incoming PAC: [%s]: %s\n", 
+                       username, error_message(ret)));
+               nt_status = NT_STATUS_INVALID_PARAMETER;
+               goto out;
+       }
+
+       if (!smb_krb5_principal_compare_any_realm(context, client_principal, client_principal_pac)) {
+               DEBUG(2,("decode_pac_data: Name in PAC [%s] does not match principal name in ticket\n", 
+                       username));
+               nt_status = NT_STATUS_ACCESS_DENIED;
+               goto out;
+       }
+
+       DEBUG(10,("Successfully validated Kerberos PAC\n"));
+
+       dump_pac_logon_info(logon_info);
+
+       *pac_data = my_pac;
+
+       nt_status = NT_STATUS_OK;
+
+out:
+       if (client_principal_pac) {
+               krb5_free_principal(context, client_principal_pac);
+       }
+
+       return nt_status;
 }
 
 #endif
index 770d129e5dafd62278e0fde88687a55aceac31b1..6a5c6b6a491ce1e82677866664f521defca13fa7 100644 (file)
@@ -4,8 +4,9 @@
    Copyright (C) Andrew Tridgell 2001
    Copyright (C) Remus Koos 2001
    Copyright (C) Luke Howard 2003   
-   Copyright (C) Guenther Deschner 2003
+   Copyright (C) Guenther Deschner 2003, 2005
    Copyright (C) Jim McDonough (jmcd@us.ibm.com) 2003
+   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005
    
    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
@@ -37,7 +38,8 @@ const krb5_data *krb5_princ_component(krb5_context, krb5_principal, int );
 ***********************************************************************************/
 
 static BOOL ads_keytab_verify_ticket(krb5_context context, krb5_auth_context auth_context,
-                       const DATA_BLOB *ticket, krb5_data *p_packet, krb5_ticket **pp_tkt)
+                       const DATA_BLOB *ticket, krb5_data *p_packet, krb5_ticket **pp_tkt, 
+                       krb5_keyblock **keyblock)
 {
        krb5_error_code ret = 0;
        BOOL auth_ok = False;
@@ -100,12 +102,18 @@ static BOOL ads_keytab_verify_ticket(krb5_context context, krb5_auth_context aut
                                        p_packet->length = ticket->length;
                                        p_packet->data = (krb5_pointer)ticket->data;
                                        *pp_tkt = NULL;
-                                       ret = krb5_rd_req(context, &auth_context, p_packet, kt_entry.principal, keytab, NULL, pp_tkt);
+
+                                       ret = krb5_rd_req_return_keyblock_from_keytab(context, &auth_context, p_packet,
+                                                                                     kt_entry.principal, keytab,
+                                                                                     NULL, pp_tkt, keyblock);
+
                                        if (ret) {
-                                               DEBUG(10, ("ads_keytab_verify_ticket: krb5_rd_req(%s) failed: %s\n",
+                                               DEBUG(10,("ads_keytab_verify_ticket: "
+                                                       "krb5_rd_req_return_keyblock_from_keytab(%s) failed: %s\n",
                                                        entry_princ_s, error_message(ret)));
                                        } else {
-                                               DEBUG(3,("ads_keytab_verify_ticket: krb5_rd_req succeeded for principal %s\n",
+                                               DEBUG(3,("ads_keytab_verify_ticket: "
+                                                       "krb5_rd_req_return_keyblock_from_keytab succeeded for principal %s\n",
                                                        entry_princ_s));
                                                auth_ok = True;
                                                break;
@@ -172,8 +180,9 @@ static BOOL ads_keytab_verify_ticket(krb5_context context, krb5_auth_context aut
 ***********************************************************************************/
 
 static BOOL ads_secrets_verify_ticket(krb5_context context, krb5_auth_context auth_context,
-                       krb5_principal host_princ,
-                       const DATA_BLOB *ticket, krb5_data *p_packet, krb5_ticket **pp_tkt)
+                                     krb5_principal host_princ,
+                                     const DATA_BLOB *ticket, krb5_data *p_packet, krb5_ticket **pp_tkt,
+                                     krb5_keyblock **keyblock)
 {
        krb5_error_code ret = 0;
        BOOL auth_ok = False;
@@ -182,6 +191,8 @@ static BOOL ads_secrets_verify_ticket(krb5_context context, krb5_auth_context au
        krb5_enctype *enctypes = NULL;
        int i;
 
+       ZERO_STRUCTP(keyblock);
+
        if (!secrets_init()) {
                DEBUG(1,("ads_secrets_verify_ticket: secrets_init failed\n"));
                return False;
@@ -222,20 +233,23 @@ static BOOL ads_secrets_verify_ticket(krb5_context context, krb5_auth_context au
 
                krb5_auth_con_setuseruserkey(context, auth_context, key);
 
-               krb5_free_keyblock(context, key);
-
                if (!(ret = krb5_rd_req(context, &auth_context, p_packet, 
                                        NULL,
                                        NULL, NULL, pp_tkt))) {
                        DEBUG(10,("ads_secrets_verify_ticket: enc type [%u] decrypted message !\n",
                                (unsigned int)enctypes[i] ));
                        auth_ok = True;
+                       krb5_copy_keyblock(context, key, keyblock);
+                       krb5_free_keyblock(context, key);
                        break;
                }
        
                DEBUG((ret != KRB5_BAD_ENCTYPE) ? 3 : 10,
                                ("ads_secrets_verify_ticket: enc type [%u] failed to decrypt with error %s\n",
                                (unsigned int)enctypes[i], error_message(ret)));
+
+               krb5_free_keyblock(context, key);
+
        }
 
  out:
@@ -251,27 +265,33 @@ static BOOL ads_secrets_verify_ticket(krb5_context context, krb5_auth_context au
  authorization_data if available.
 ***********************************************************************************/
 
-NTSTATUS ads_verify_ticket(const char *realm, const DATA_BLOB *ticket, 
-                          char **principal, DATA_BLOB *auth_data,
+NTSTATUS ads_verify_ticket(TALLOC_CTX *mem_ctx,
+                          const char *realm, const DATA_BLOB *ticket, 
+                          char **principal, PAC_DATA **pac_data,
                           DATA_BLOB *ap_rep,
                           DATA_BLOB *session_key)
 {
        NTSTATUS sret = NT_STATUS_LOGON_FAILURE;
+       DATA_BLOB auth_data;
        krb5_context context = NULL;
        krb5_auth_context auth_context = NULL;
        krb5_data packet;
        krb5_ticket *tkt = NULL;
        krb5_rcache rcache = NULL;
+       krb5_keyblock *keyblock = NULL;
+       time_t authtime;
        int ret;
 
        krb5_principal host_princ = NULL;
+       krb5_const_principal client_principal = NULL;
        char *host_princ_s = NULL;
        BOOL got_replay_mutex = False;
 
        BOOL auth_ok = False;
+       BOOL got_auth_data = False;
 
        ZERO_STRUCT(packet);
-       ZERO_STRUCTP(auth_data);
+       ZERO_STRUCT(auth_data);
        ZERO_STRUCTP(ap_rep);
        ZERO_STRUCTP(session_key);
 
@@ -335,20 +355,30 @@ NTSTATUS ads_verify_ticket(const char *realm, const DATA_BLOB *ticket,
        }
 
        if (lp_use_kerberos_keytab()) {
-               auth_ok = ads_keytab_verify_ticket(context, auth_context, ticket, &packet, &tkt);
+               auth_ok = ads_keytab_verify_ticket(context, auth_context, ticket, &packet, &tkt, &keyblock);
        }
        if (!auth_ok) {
                auth_ok = ads_secrets_verify_ticket(context, auth_context, host_princ,
-                                                       ticket, &packet, &tkt);
+                                                   ticket, &packet, &tkt, &keyblock);
        }
 
        release_server_mutex();
        got_replay_mutex = False;
 
+#if 0
+       /* Heimdal leaks here, if we fix the leak, MIT crashes */
+       if (rcache) {
+               krb5_rc_close(context, rcache);
+       }
+#endif
+
        if (!auth_ok) {
                DEBUG(3,("ads_verify_ticket: krb5_rd_req with auth failed (%s)\n", 
                         error_message(ret)));
                goto out;
+       } else {
+               authtime = get_authtime_from_tkt(tkt);
+               client_principal = get_principal_from_tkt(tkt);
        }
 
        ret = krb5_mk_rep(context, auth_context, &packet);
@@ -369,20 +399,40 @@ NTSTATUS ads_verify_ticket(const char *realm, const DATA_BLOB *ticket,
        file_save("/tmp/ticket.dat", ticket->data, ticket->length);
 #endif
 
-       get_auth_data_from_tkt(auth_data, tkt);
+       /* continue when no PAC is retrieved 
+          (like accounts that have the UF_NO_AUTH_DATA_REQUIRED flag set) */
 
-       {
-               TALLOC_CTX *ctx = talloc_init("pac data");
-               decode_pac_data(auth_data, ctx);
-               talloc_destroy(ctx);
+       got_auth_data = get_auth_data_from_tkt(mem_ctx, &auth_data, tkt);
+       if (!got_auth_data) {
+               DEBUG(3,("ads_verify_ticket: did not retrieve auth data. continuing without PAC\n"));
+       }
+
+       if (got_auth_data && pac_data != NULL) {
+
+               sret = decode_pac_data(mem_ctx, &auth_data, context, keyblock, client_principal, authtime, pac_data);
+               if (!NT_STATUS_IS_OK(sret)) {
+                       DEBUG(0,("ads_verify_ticket: failed to decode PAC_DATA: %s\n", nt_errstr(sret)));
+                       goto out;
+               }
+               data_blob_free(&auth_data);
        }
 
 #if 0
+#if defined(HAVE_KRB5_TKT_ENC_PART2)
+       /* MIT */
        if (tkt->enc_part2) {
                file_save("/tmp/authdata.dat",
                          tkt->enc_part2->authorization_data[0]->contents,
                          tkt->enc_part2->authorization_data[0]->length);
        }
+#else
+       /* Heimdal */
+       if (tkt->ticket.authorization_data) {
+               file_save("/tmp/authdata.dat",
+                         tkt->ticket.authorization_data->val->ad_data.data,
+                         tkt->ticket.authorization_data->val->ad_data.length);
+       }
+#endif
 #endif
 
        if ((ret = krb5_unparse_name(context, get_principal_from_tkt(tkt),
@@ -402,7 +452,7 @@ NTSTATUS ads_verify_ticket(const char *realm, const DATA_BLOB *ticket,
        }
 
        if (!NT_STATUS_IS_OK(sret)) {
-               data_blob_free(auth_data);
+               data_blob_free(&auth_data);
        }
 
        if (!NT_STATUS_IS_OK(sret)) {
@@ -413,6 +463,10 @@ NTSTATUS ads_verify_ticket(const char *realm, const DATA_BLOB *ticket,
                krb5_free_principal(context, host_princ);
        }
 
+       if (keyblock) {
+               krb5_free_keyblock(context, keyblock);
+       }
+
        if (tkt != NULL) {
                krb5_free_ticket(context, tkt);
        }
index 81afd7f49e3037ba235cef10fad9ef57a5b5dd2e..bf402b3499e27dafc3d74948579eb141e1bf5b07 100644 (file)
@@ -2104,7 +2104,7 @@ char **ads_pull_strings_range(ADS_STRUCT *ads,
        if ((*num_strings) != range_start) {
                DEBUG(1, ("ads_pull_strings_range: Range attribute (%s) doesn't start at %u, but at %lu"
                          " - aborting range retreival\n",
-                         range_attr, *num_strings + 1, range_start));
+                         range_attr, (unsigned int)(*num_strings) + 1, range_start));
                ldap_memfree(range_attr);
                *more_strings = False;
                return NULL;
@@ -2140,7 +2140,7 @@ char **ads_pull_strings_range(ADS_STRUCT *ads,
                *next_attribute = talloc_asprintf(mem_ctx,
                                                  "%s;range=%d-*", 
                                                  field,
-                                                 *num_strings);
+                                                 (int)*num_strings);
                
                if (!*next_attribute) {
                        DEBUG(1, ("talloc_asprintf for next attribute failed!\n"));
index db544fe2092589b34f840b0e9e10e6472128a768..d6ac09d22bda5db4404917d44f3ddc64eafb3291 100644 (file)
@@ -258,7 +258,7 @@ static void map_regval_to_ads(TALLOC_CTX *ctx, ADS_MODLIST *mods,
 }
 
 
-WERROR get_remote_printer_publishing_data(struct cli_state *cli, 
+WERROR get_remote_printer_publishing_data(struct rpc_pipe_client *cli, 
                                          TALLOC_CTX *mem_ctx,
                                          ADS_MODLIST *mods,
                                          const char *printer)
@@ -269,16 +269,16 @@ WERROR get_remote_printer_publishing_data(struct cli_state *cli,
        uint32 i;
        POLICY_HND pol;
 
-       asprintf(&servername, "\\\\%s", cli->desthost);
+       asprintf(&servername, "\\\\%s", cli->cli->desthost);
        asprintf(&printername, "%s\\%s", servername, printer);
        if (!servername || !printername) {
                DEBUG(3, ("Insufficient memory\n"));
                return WERR_NOMEM;
        }
        
-       result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, 
+       result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, 
                                             "", MAXIMUM_ALLOWED_ACCESS, 
-                                            servername, cli->user_name, &pol);
+                                            servername, cli->cli->user_name, &pol);
        if (!W_ERROR_IS_OK(result)) {
                DEBUG(3, ("Unable to open printer %s, error is %s.\n",
                          printername, dos_errstr(result)));
@@ -288,7 +288,7 @@ WERROR get_remote_printer_publishing_data(struct cli_state *cli,
        if ( !(dsdriver_ctr = TALLOC_ZERO_P( mem_ctx, REGVAL_CTR )) ) 
                return WERR_NOMEM;
 
-       result = cli_spoolss_enumprinterdataex(cli, mem_ctx, &pol, SPOOL_DSDRIVER_KEY, dsdriver_ctr);
+       result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx, &pol, SPOOL_DSDRIVER_KEY, dsdriver_ctr);
 
        if (!W_ERROR_IS_OK(result)) {
                DEBUG(3, ("Unable to do enumdataex on %s, error is %s.\n",
@@ -305,7 +305,7 @@ WERROR get_remote_printer_publishing_data(struct cli_state *cli,
        if ( !(dsspooler_ctr = TALLOC_ZERO_P( mem_ctx, REGVAL_CTR )) )
                return WERR_NOMEM;
 
-       result = cli_spoolss_enumprinterdataex(cli, mem_ctx, &pol, SPOOL_DSSPOOLER_KEY, dsspooler_ctr);
+       result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx, &pol, SPOOL_DSSPOOLER_KEY, dsspooler_ctr);
 
        if (!W_ERROR_IS_OK(result)) {
                DEBUG(3, ("Unable to do enumdataex on %s, error is %s.\n",
@@ -323,7 +323,7 @@ WERROR get_remote_printer_publishing_data(struct cli_state *cli,
        TALLOC_FREE( dsdriver_ctr );
        TALLOC_FREE( dsspooler_ctr );
 
-       cli_spoolss_close_printer(cli, mem_ctx, &pol);
+       rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
 
        return result;
 }
index 8fa62a5ade4e07d6ce0e18f36f4d9632df7c65e7..72cbf7264ec964bd22d74c06f546464ee2a29572 100644 (file)
@@ -142,7 +142,7 @@ static ADS_STATUS ads_sasl_spnego_krb5_bind(ADS_STRUCT *ads, const char *princip
        DATA_BLOB session_key = data_blob(NULL, 0);
        int rc;
 
-       rc = spnego_gen_negTokenTarg(principal, ads->auth.time_offset, &blob, &session_key);
+       rc = spnego_gen_negTokenTarg(principal, ads->auth.time_offset, &blob, &session_key, 0);
 
        if (rc) {
                return ADS_ERROR_KRB5(rc);
index 3d8e36c493a7911f3339e1f105a8078a92addab5..7ecc7695171e8c9b14773ed2e047b1863f203775 100644 (file)
@@ -532,7 +532,7 @@ static ADS_STATUS cli_session_setup_kerberos(struct cli_state *cli, const char *
        DEBUG(2,("Doing kerberos session setup\n"));
 
        /* generate the encapsulated kerberos5 ticket */
-       rc = spnego_gen_negTokenTarg(principal, 0, &negTokenTarg, &session_key_krb5);
+       rc = spnego_gen_negTokenTarg(principal, 0, &negTokenTarg, &session_key_krb5, 0);
 
        if (rc) {
                DEBUG(1, ("spnego_gen_negTokenTarg failed: %s\n", error_message(rc)));
@@ -600,7 +600,7 @@ static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli, const char *use
                nt_status = ntlmssp_update(ntlmssp_state, 
                                                  blob_in, &blob_out);
                data_blob_free(&blob_in);
-               if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
+               if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED) || NT_STATUS_IS_OK(nt_status)) {
                        if (turn == 1) {
                                /* and wrap it in a SPNEGO wrapper */
                                msg1 = gen_negTokenInit(OID_NTLMSSP, blob_out);
@@ -1337,25 +1337,6 @@ BOOL cli_connect(struct cli_state *cli, const char *host, struct in_addr *ip)
        return True;
 }
 
-/****************************************************************************
- Initialise client credentials for authenticated pipe access.
-****************************************************************************/
-
-void init_creds(struct ntuser_creds *creds, const char* username,
-                      const char* domain, const char* password)
-{
-       ZERO_STRUCTP(creds);
-
-       pwd_set_cleartext(&creds->pwd, password);
-
-       fstrcpy(creds->user_name, username);
-       fstrcpy(creds->domain, domain);
-
-       if (!*username) {
-               creds->pwd.null_pwd = True;
-       }
-}
-
 /**
    establishes a connection to after the negprot. 
    @param output_cli A fully initialised cli structure, non-null only on success
@@ -1474,7 +1455,6 @@ NTSTATUS cli_full_connection(struct cli_state **output_cli,
                             int signing_state,
                             BOOL *retry) 
 {
-       struct ntuser_creds creds;
        NTSTATUS nt_status;
        struct cli_state *cli = NULL;
 
@@ -1513,8 +1493,7 @@ NTSTATUS cli_full_connection(struct cli_state **output_cli,
                }
        }
 
-       init_creds(&creds, user, domain, password);
-       cli_init_creds(cli, &creds);
+       cli_init_creds(cli, user, domain, password);
 
        *output_cli = cli;
        return NT_STATUS_OK;
index 819616105edc9d274a76fd26bf0f4fb76d8a6ef9..dfb613238f60facfd6799e9b1732aae89536008a 100644 (file)
@@ -101,7 +101,7 @@ BOOL cli_send_mailslot(BOOL unique, const char *mailslot,
        DEBUGADD(4,("to %s IP %s\n", nmb_namestr(&dgram->dest_name),
                    inet_ntoa(dest_ip)));
 
-       return message_send_pid(nmbd_pid, MSG_SEND_PACKET, &p, sizeof(p),
+       return message_send_pid(pid_to_procid(nmbd_pid), MSG_SEND_PACKET, &p, sizeof(p),
                                False);
 }
 
index f1794ab5dc8d041f8b2efc9d096a04eb2307927f..bc64cc919b7705aa59f6aedbefdaf1b28a6f5ab1 100644 (file)
@@ -221,15 +221,16 @@ void cli_setup_bcc(struct cli_state *cli, void *p)
  Initialise credentials of a client structure.
 ****************************************************************************/
 
-void cli_init_creds(struct cli_state *cli, const struct ntuser_creds *usr)
+void cli_init_creds(struct cli_state *cli, const char *username, const char *domain, const char *password)
 {
-        /* copy_nt_creds(&cli->usr, usr); */
-       fstrcpy(cli->domain   , usr->domain);
-       fstrcpy(cli->user_name, usr->user_name);
-       memcpy(&cli->pwd, &usr->pwd, sizeof(usr->pwd));
+       fstrcpy(cli->domain, domain);
+       fstrcpy(cli->user_name, username);
+       pwd_set_cleartext(&cli->pwd, password);
+       if (!*username) {
+               cli->pwd.null_pwd = True;
+       }
 
-        DEBUG(10,("cli_init_creds: user %s domain %s\n",
-               cli->user_name, cli->domain));
+        DEBUG(10,("cli_init_creds: user %s domain %s\n", cli->user_name, cli->domain));
 }
 
 /****************************************************************************
@@ -260,7 +261,6 @@ void cli_setup_signing_state(struct cli_state *cli, int signing_state)
 struct cli_state *cli_initialise(struct cli_state *cli)
 {
         BOOL alloced_cli = False;
-       int i;
 
        /* Check the effective uid - make sure we are not setuid */
        if (is_setuid_root()) {
@@ -332,16 +332,9 @@ struct cli_state *cli_initialise(struct cli_state *cli)
        /* initialise signing */
        cli_null_set_signing(cli);
 
-       for (i=0; i<PI_MAX_PIPES; i++)
-               cli->pipes[i].fnum = 0;
-
-       cli->netlogon_pipe.fnum = 0;
-
        cli->initialised = 1;
        cli->allocated = alloced_cli;
 
-       cli->pipe_idx = -1;
-
        return cli;
 
         /* Clean up after malloc() error */
@@ -358,34 +351,42 @@ struct cli_state *cli_initialise(struct cli_state *cli)
 }
 
 /****************************************************************************
-close the session
-****************************************************************************/
+ External interface.
+ Close an open named pipe over SMB. Free any authentication data.
+ ****************************************************************************/
 
-void cli_nt_session_close(struct cli_state *cli)
+void cli_rpc_pipe_close(struct rpc_pipe_client *cli)
 {
-       int i;
-
-       for (i=0; i<PI_MAX_PIPES; i++) {
-               if (cli->pipes[i].pipe_auth_flags & AUTH_PIPE_NTLMSSP) {
-                       ntlmssp_end(&cli->pipes[i].ntlmssp_pipe_state);
-               }
+       if (!cli_close(cli->cli, cli->fnum)) {
+               DEBUG(0,("cli_rpc_pipe_close: cli_close failed on pipe %s "
+                       "to machine %s.  Error was %s\n",
+                       cli->pipe_name,
+                       cli->cli->desthost,
+                       cli_errstr(cli->cli)));
+       }
 
-               if (cli->pipes[i].fnum != 0)
-                       cli_close(cli, cli->pipes[i].fnum);
-               cli->pipes[i].fnum = 0;
+       if (cli->auth.cli_auth_data_free_func) {
+               (*cli->auth.cli_auth_data_free_func)(&cli->auth);
        }
-       cli->pipe_idx = -1;
+
+       DEBUG(10,("cli_rpc_pipe_close: closed pipe %s to machine %s\n",
+               cli->pipe_name, cli->cli->desthost ));
+
+       DLIST_REMOVE(cli->cli->pipe_list, cli);
+       talloc_destroy(cli->mem_ctx);
 }
 
 /****************************************************************************
-close the NETLOGON session holding the session key for NETSEC
+ Close all pipes open on this session.
 ****************************************************************************/
 
-void cli_nt_netlogon_netsec_session_close(struct cli_state *cli)
+void cli_nt_pipes_close(struct cli_state *cli)
 {
-       if (cli->netlogon_pipe.fnum != 0) {
-               cli_close(cli, cli->netlogon_pipe.fnum);
-               cli->netlogon_pipe.fnum = 0;
+       struct rpc_pipe_client *cp, *next;
+
+       for (cp = cli->pipe_list; cp; cp = next) {
+               next = cp->next;
+               cli_rpc_pipe_close(cp);
        }
 }
 
@@ -395,8 +396,7 @@ void cli_nt_netlogon_netsec_session_close(struct cli_state *cli)
 
 void cli_close_connection(struct cli_state *cli)
 {
-       cli_nt_session_close(cli);
-       cli_nt_netlogon_netsec_session_close(cli);
+       cli_nt_pipes_close(cli);
 
        /*
         * tell our peer to free his resources.  Wihtout this, when an
@@ -410,8 +410,9 @@ void cli_close_connection(struct cli_state *cli)
         * the only user for this so far is smbmount which passes opened connection
         * down to kernel's smbfs module.
         */
-       if ( (cli->cnum != (uint16)-1) && (cli->smb_rw_error != DO_NOT_DO_TDIS ) )
+       if ( (cli->cnum != (uint16)-1) && (cli->smb_rw_error != DO_NOT_DO_TDIS ) ) {
                cli_tdis(cli);
+       }
         
        SAFE_FREE(cli->outbuf);
        SAFE_FREE(cli->inbuf);
@@ -420,19 +421,16 @@ void cli_close_connection(struct cli_state *cli)
        data_blob_free(&cli->secblob);
        data_blob_free(&cli->user_session_key);
 
-       if (cli->pipes[cli->pipe_idx].pipe_auth_flags & AUTH_PIPE_NTLMSSP) 
-               ntlmssp_end(&cli->pipes[cli->pipe_idx].ntlmssp_pipe_state);
-
        if (cli->mem_ctx) {
                talloc_destroy(cli->mem_ctx);
                cli->mem_ctx = NULL;
        }
 
-       if (cli->fd != -1) 
+       if (cli->fd != -1) {
                close(cli->fd);
+       }
        cli->fd = -1;
        cli->smb_rw_error = 0;
-
 }
 
 /****************************************************************************
@@ -444,8 +442,9 @@ void cli_shutdown(struct cli_state *cli)
        BOOL allocated = cli->allocated;
        cli_close_connection(cli);
        ZERO_STRUCTP(cli);
-       if (allocated)
+       if (allocated) {
                free(cli);
+       }
 }
 
 /****************************************************************************
index 355a2adf34d998cd86689ace555073fcd3dabc37..6938702e1e04f3c32a06ae7e3c1544da117e4cd5 100644 (file)
@@ -404,3 +404,20 @@ BOOL cli_is_dos_error(struct cli_state *cli)
 
         return cli_is_error(cli) && !(flgs2 & FLAGS2_32_BIT_ERROR_CODES);
 }
+
+/* Return the last error always as an NTSTATUS. */
+
+NTSTATUS cli_get_nt_error(struct cli_state *cli)
+{
+       if (cli_is_nt_error(cli)) {
+               return cli_nt_error(cli);
+       } else if (cli_is_dos_error(cli)) {
+               uint32 ecode;
+               uint8 eclass;
+               cli_dos_error(cli, &eclass, &ecode);
+               return dos_to_ntstatus(eclass, ecode);
+       } else {
+               /* Something went wrong, we don't know what. */
+               return NT_STATUS_UNSUCCESSFUL;
+       }
+}
index 1741c1db3cdb703317de003f69ce2c2ec93ade07..e3ad5f17cb0b78018d3a3724a8e275a903c238d7 100644 (file)
@@ -3,6 +3,8 @@
    simple kerberos5 routines for active directory
    Copyright (C) Andrew Tridgell 2001
    Copyright (C) Luke Howard 2002-2003
+   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005
+   Copyright (C) Guenther Deschner 2005
    
    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
 }
 #endif
 
- void get_auth_data_from_tkt(DATA_BLOB *auth_data, krb5_ticket *tkt)
+BOOL unwrap_pac(TALLOC_CTX *mem_ctx, DATA_BLOB *auth_data, DATA_BLOB *unwrapped_pac_data)
 {
+       DATA_BLOB pac_contents;
+       ASN1_DATA data;
+       int data_type;
+
+       if (!auth_data->length) {
+               return False;
+       }
+
+       asn1_load(&data, *auth_data);
+       asn1_start_tag(&data, ASN1_SEQUENCE(0));
+       asn1_start_tag(&data, ASN1_SEQUENCE(0));
+       asn1_start_tag(&data, ASN1_CONTEXT(0));
+       asn1_read_Integer(&data, &data_type);
+       
+       if (data_type != KRB5_AUTHDATA_WIN2K_PAC ) {
+               DEBUG(10,("authorization data is not a Windows PAC (type: %d)\n", data_type));
+               asn1_free(&data);
+               return False;
+       }
+       
+       asn1_end_tag(&data);
+       asn1_start_tag(&data, ASN1_CONTEXT(1));
+       asn1_read_OctetString(&data, &pac_contents);
+       asn1_end_tag(&data);
+       asn1_end_tag(&data);
+       asn1_end_tag(&data);
+       asn1_free(&data);
+
+       *unwrapped_pac_data = data_blob_talloc(mem_ctx, pac_contents.data, pac_contents.length);
+
+       data_blob_free(&pac_contents);
+
+       return True;
+}
+
+ BOOL get_auth_data_from_tkt(TALLOC_CTX *mem_ctx, DATA_BLOB *auth_data, krb5_ticket *tkt)
+{
+       DATA_BLOB auth_data_wrapped;
+       BOOL got_auth_data_pac = False;
+       int i;
+       
 #if defined(HAVE_KRB5_TKT_ENC_PART2)
-       if (tkt->enc_part2 && tkt->enc_part2->authorization_data && tkt->enc_part2->authorization_data[0] && tkt->enc_part2->authorization_data[0]->length)
-               *auth_data = data_blob(tkt->enc_part2->authorization_data[0]->contents,
-                       tkt->enc_part2->authorization_data[0]->length);
+       if (tkt->enc_part2 && tkt->enc_part2->authorization_data && 
+           tkt->enc_part2->authorization_data[0] && 
+           tkt->enc_part2->authorization_data[0]->length)
+       {
+               for (i = 0; tkt->enc_part2->authorization_data[i] != NULL; i++) {
+               
+                       if (tkt->enc_part2->authorization_data[i]->ad_type != 
+                           KRB5_AUTHDATA_IF_RELEVANT) {
+                               DEBUG(10,("get_auth_data_from_tkt: ad_type is %d\n", 
+                                       tkt->enc_part2->authorization_data[i]->ad_type));
+                               continue;
+                       }
+
+                       auth_data_wrapped = data_blob(tkt->enc_part2->authorization_data[i]->contents,
+                                                     tkt->enc_part2->authorization_data[i]->length);
+
+                       /* check if it is a PAC */
+                       got_auth_data_pac = unwrap_pac(mem_ctx, &auth_data_wrapped, auth_data);
+                       data_blob_free(&auth_data_wrapped);
+                       
+                       if (!got_auth_data_pac) {
+                               continue;
+                       }
+               }
+
+               return got_auth_data_pac;
+       }
+               
 #else
-       if (tkt->ticket.authorization_data && tkt->ticket.authorization_data->len)
-               *auth_data = data_blob(tkt->ticket.authorization_data->val->ad_data.data,
-                       tkt->ticket.authorization_data->val->ad_data.length);
+       if (tkt->ticket.authorization_data && 
+           tkt->ticket.authorization_data->len)
+       {
+               for (i = 0; i < tkt->ticket.authorization_data->len; i++) {
+                       
+                       if (tkt->ticket.authorization_data->val[i].ad_type != 
+                           KRB5_AUTHDATA_IF_RELEVANT) {
+                               DEBUG(10,("get_auth_data_from_tkt: ad_type is %d\n", 
+                                       tkt->ticket.authorization_data->val[i].ad_type));
+                               continue;
+                       }
+
+                       auth_data_wrapped = data_blob(tkt->ticket.authorization_data->val[i].ad_data.data,
+                                                     tkt->ticket.authorization_data->val[i].ad_data.length);
+
+                       /* check if it is a PAC */
+                       got_auth_data_pac = unwrap_pac(mem_ctx, &auth_data_wrapped, auth_data);
+                       data_blob_free(&auth_data_wrapped);
+                       
+                       if (!got_auth_data_pac) {
+                               continue;
+                       }
+               }
+
+               return got_auth_data_pac;
+       }
 #endif
+       return False;
 }
 
  krb5_const_principal get_principal_from_tkt(krb5_ticket *tkt)
@@ -435,7 +527,7 @@ cleanup_princ:
   get a kerberos5 ticket for the given service 
 */
 int cli_krb5_get_ticket(const char *principal, time_t time_offset, 
-                       DATA_BLOB *ticket, DATA_BLOB *session_key_krb5)
+                       DATA_BLOB *ticket, DATA_BLOB *session_key_krb5, uint32 extra_ap_opts)
 {
        krb5_error_code retval;
        krb5_data packet;
@@ -475,7 +567,7 @@ int cli_krb5_get_ticket(const char *principal, time_t time_offset,
 
        if ((retval = ads_krb5_mk_req(context, 
                                        &auth_context, 
-                                       AP_OPTS_USE_SUBKEY
+                                       AP_OPTS_USE_SUBKEY | (krb5_flags)extra_ap_opts,
                                        principal,
                                        ccdef, &packet))) {
                goto failed;
@@ -550,10 +642,349 @@ failed:
 #endif
 }
 
+void smb_krb5_checksum_from_pac_sig(krb5_checksum *cksum, 
+                                   PAC_SIGNATURE_DATA *sig)
+{
+#ifdef HAVE_CHECKSUM_IN_KRB5_CHECKSUM
+       cksum->cksumtype        = (krb5_cksumtype)sig->type;
+       cksum->checksum.length  = sig->signature.buf_len;
+       cksum->checksum.data    = sig->signature.buffer;
+#else
+       cksum->checksum_type    = (krb5_cksumtype)sig->type;
+       cksum->length           = sig->signature.buf_len;
+       cksum->contents         = sig->signature.buffer;
+#endif
+}
+
+krb5_error_code smb_krb5_verify_checksum(krb5_context context,
+                                        krb5_keyblock *keyblock,
+                                        krb5_keyusage usage,
+                                        krb5_checksum *cksum,
+                                        uint8 *data,
+                                        size_t length)
+{
+       krb5_error_code ret;
+
+       /* verify the checksum */
+
+       /* welcome to the wonderful world of samba's kerberos abstraction layer:
+        * 
+        * function                     heimdal 0.6.1rc3        heimdal 0.7     MIT krb 1.4.2
+        * -----------------------------------------------------------------------------
+        * krb5_c_verify_checksum       -                       works           works
+        * krb5_verify_checksum         works (6 args)          works (6 args)  broken (7 args) 
+        */
+
+#if defined(HAVE_KRB5_C_VERIFY_CHECKSUM)
+       {
+               krb5_boolean checksum_valid = False;
+               krb5_data input;
+
+               input.data = (char *)data;
+               input.length = length;
+
+               ret = krb5_c_verify_checksum(context, 
+                                            keyblock, 
+                                            usage,
+                                            &input, 
+                                            cksum,
+                                            &checksum_valid);
+               if (!checksum_valid)
+                       ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
+       }
+
+#elif KRB5_VERIFY_CHECKSUM_ARGS == 6 && defined(HAVE_KRB5_CRYPTO_INIT) && defined(HAVE_KRB5_CRYPTO) && defined(HAVE_KRB5_CRYPTO_DESTROY)
+
+       /* Warning: MIT's krb5_verify_checksum cannot be used as it will use a key
+        * without enctype and it ignores any key_usage types - Guenther */
+
+       {
+
+               krb5_crypto crypto;
+               ret = krb5_crypto_init(context,
+                                      keyblock,
+                                      0,
+                                      &crypto);
+               if (ret) {
+                       DEBUG(0,("smb_krb5_verify_checksum: krb5_crypto_init() failed: %s\n", 
+                               error_message(ret)));
+                       return ret;
+               }
+
+               ret = krb5_verify_checksum(context,
+                                          crypto,
+                                          usage,
+                                          data,
+                                          length,
+                                          cksum);
+
+               krb5_crypto_destroy(context, crypto);
+       }
+
+#else
+#error UNKNOWN_KRB5_VERIFY_CHECKSUM_FUNCTION
+#endif
+
+       return ret;
+}
+
+time_t get_authtime_from_tkt(krb5_ticket *tkt)
+{
+#if defined(HAVE_KRB5_TKT_ENC_PART2)
+       return tkt->enc_part2->times.authtime;
+#else
+       return tkt->ticket.authtime;
+#endif
+}
+
+static int get_kvno_from_ap_req(krb5_ap_req *ap_req)
+{
+#ifdef HAVE_TICKET_POINTER_IN_KRB5_AP_REQ /* MIT */
+       if (ap_req->ticket->enc_part.kvno)
+               return ap_req->ticket->enc_part.kvno;
+#else /* Heimdal */
+       if (ap_req->ticket.enc_part.kvno) 
+               return *ap_req->ticket.enc_part.kvno;
+#endif
+       return 0;
+}
+
+static krb5_enctype get_enctype_from_ap_req(krb5_ap_req *ap_req)
+{
+#ifdef HAVE_ETYPE_IN_ENCRYPTEDDATA /* Heimdal */
+       return ap_req->ticket.enc_part.etype;
+#else /* MIT */
+       return ap_req->ticket->enc_part.enctype;
+#endif
+}
+
+static krb5_error_code
+get_key_from_keytab(krb5_context context,
+                   krb5_keytab keytab,
+                   krb5_const_principal server,
+                   krb5_enctype enctype,
+                   krb5_kvno kvno,
+                   krb5_keyblock **out_key)
+{
+       krb5_keytab_entry entry;
+       krb5_error_code ret;
+       krb5_keytab real_keytab;
+       char *name = NULL;
+
+       if (keytab == NULL) {
+               krb5_kt_default(context, &real_keytab);
+       } else {
+               real_keytab = keytab;
+       }
+
+       if ( DEBUGLEVEL >= 10 ) {
+               krb5_unparse_name(context, server, &name);
+               DEBUG(10,("get_key_from_keytab: will look for kvno %d, enctype %d and name: %s\n", 
+                       kvno, enctype, name));
+               krb5_free_unparsed_name(context, name);
+       }
+
+       ret = krb5_kt_get_entry(context,
+                               real_keytab,
+                               server,
+                               kvno,
+                               enctype,
+                               &entry);
+
+       if (ret) {
+               DEBUG(0,("get_key_from_keytab: failed to retrieve key: %s\n", error_message(ret)));
+               goto out;
+       }
+
+#ifdef HAVE_KRB5_KEYTAB_ENTRY_KEYBLOCK /* Heimdal */
+       ret = krb5_copy_keyblock(context, &entry.keyblock, out_key);
+#elif defined(HAVE_KRB5_KEYTAB_ENTRY_KEY) /* MIT */
+       ret = krb5_copy_keyblock(context, &entry.key, out_key);
+#else
+#error UNKNOWN_KRB5_KEYTAB_ENTRY_FORMAT
+#endif
+
+       if (ret) {
+               DEBUG(0,("get_key_from_keytab: failed to copy key: %s\n", error_message(ret)));
+               goto out;
+       }
+               
+       smb_krb5_kt_free_entry(context, &entry);
+       
+out:    
+       if (keytab == NULL) {
+               krb5_kt_close(context, real_keytab);
+       }
+               
+       return ret;
+}
+
+void smb_krb5_free_ap_req(krb5_context context, 
+                         krb5_ap_req *ap_req)
+{
+#ifdef HAVE_KRB5_FREE_AP_REQ /* MIT */
+       krb5_free_ap_req(context, ap_req);
+#elif defined(HAVE_FREE_AP_REQ) /* Heimdal */
+       free_AP_REQ(ap_req);
+#else
+#error UNKNOWN_KRB5_AP_REQ_FREE_FUNCTION
+#endif
+}
+
+/* Prototypes */
+#if defined(HAVE_DECODE_KRB5_AP_REQ) /* MIT */
+krb5_error_code decode_krb5_ap_req(const krb5_data *code, krb5_ap_req **rep);
+#endif
+
+krb5_error_code smb_krb5_get_keyinfo_from_ap_req(krb5_context context, 
+                                                const krb5_data *inbuf, 
+                                                krb5_kvno *kvno, 
+                                                krb5_enctype *enctype)
+{
+       krb5_error_code ret;
+#ifdef HAVE_KRB5_DECODE_AP_REQ /* Heimdal */
+       {
+               krb5_ap_req ap_req;
+               
+               ret = krb5_decode_ap_req(context, inbuf, &ap_req);
+               if (ret)
+                       return ret;
+
+               *kvno = get_kvno_from_ap_req(&ap_req);
+               *enctype = get_enctype_from_ap_req(&ap_req);
+
+               smb_krb5_free_ap_req(context, &ap_req);
+       }
+#elif defined(HAVE_DECODE_KRB5_AP_REQ) /* MIT */
+       {
+               krb5_ap_req *ap_req = NULL;
+
+               ret = decode_krb5_ap_req(inbuf, &ap_req);
+               if (ret)
+                       return ret;
+               
+               *kvno = get_kvno_from_ap_req(ap_req);
+               *enctype = get_enctype_from_ap_req(ap_req);
+
+               smb_krb5_free_ap_req(context, ap_req);
+       }
+#else
+#error UNKOWN_KRB5_AP_REQ_DECODING_FUNCTION
+#endif
+       return ret;
+}
+
+krb5_error_code krb5_rd_req_return_keyblock_from_keytab(krb5_context context,
+                                                       krb5_auth_context *auth_context,
+                                                       const krb5_data *inbuf,
+                                                       krb5_const_principal server,
+                                                       krb5_keytab keytab,
+                                                       krb5_flags *ap_req_options,
+                                                       krb5_ticket **ticket, 
+                                                       krb5_keyblock **keyblock)
+{
+       krb5_error_code ret;
+       krb5_ap_req *ap_req = NULL;
+       krb5_kvno kvno;
+       krb5_enctype enctype;
+       krb5_keyblock *local_keyblock;
+
+       ret = krb5_rd_req(context, 
+                         auth_context, 
+                         inbuf, 
+                         server, 
+                         keytab, 
+                         ap_req_options, 
+                         ticket);
+       if (ret) {
+               return ret;
+       }
+       
+       ret = smb_krb5_get_keyinfo_from_ap_req(context, inbuf, &kvno, &enctype);
+       if (ret) {
+               return ret;
+       }
+
+       ret = get_key_from_keytab(context, 
+                                 keytab,
+                                 server,
+                                 enctype,
+                                 kvno,
+                                 &local_keyblock);
+       if (ret) {
+               DEBUG(0,("krb5_rd_req_return_keyblock_from_keytab: failed to call get_key_from_keytab\n"));
+               goto out;
+       }
+
+out:
+       if (ap_req) {
+               smb_krb5_free_ap_req(context, ap_req);
+       }
+
+       if (ret && local_keyblock != NULL) {
+               krb5_free_keyblock(context, local_keyblock);
+       } else {
+               *keyblock = local_keyblock;
+       }
+
+       return ret;
+}
+
+krb5_error_code smb_krb5_parse_name_norealm(krb5_context context, 
+                                           const char *name, 
+                                           krb5_principal *principal)
+{
+#ifdef HAVE_KRB5_PARSE_NAME_NOREALM
+       return krb5_parse_name_norealm(context, name, principal);
+#endif
+
+       /* we are cheating here because parse_name will in fact set the realm.
+        * We don't care as the only caller of smb_krb5_parse_name_norealm
+        * ignores the realm anyway when calling
+        * smb_krb5_principal_compare_any_realm later - Guenther */
+
+       return krb5_parse_name(context, name, principal);
+}
+
+BOOL smb_krb5_principal_compare_any_realm(krb5_context context, 
+                                         krb5_const_principal princ1, 
+                                         krb5_const_principal princ2)
+{
+#ifdef HAVE_KRB5_PRINCIPAL_COMPARE_ANY_REALM
+
+       return krb5_principal_compare_any_realm(context, princ1, princ2);
+
+/* krb5_princ_size is a macro in MIT */
+#elif defined(HAVE_KRB5_PRINC_SIZE) || defined(krb5_princ_size)
+
+       int i, len1, len2;
+       const krb5_data *p1, *p2;
+
+       len1 = krb5_princ_size(context, princ1);
+       len2 = krb5_princ_size(context, princ2);
+
+       if (len1 != len2)
+               return False;
+
+       for (i = 0; i < len1; i++) {
+
+               p1 = krb5_princ_component(context, CONST_DISCARD(krb5_principal, princ1), i);
+               p2 = krb5_princ_component(context, CONST_DISCARD(krb5_principal, princ2), i);
+
+               if (p1->length != p2->length || memcmp(p1->data, p2->data, p1->length))
+                       return False;
+       }
+
+       return True;
+#else
+#error NO_SUITABLE_PRINCIPAL_COMPARE_FUNCTION
+#endif
+}
+
 #else /* HAVE_KRB5 */
  /* this saves a few linking headaches */
 int cli_krb5_get_ticket(const char *principal, time_t time_offset, 
-                       DATA_BLOB *ticket, DATA_BLOB *session_key_krb5) 
+                       DATA_BLOB *ticket, DATA_BLOB *session_key_krb5, uint32 extra_ap_opts
 {
         DEBUG(0,("NO KERBEROS SUPPORT\n"));
         return 1;
index 1220907629c368af5b41d31d4f2c0512020c6deb..55e36b646b9a67d5b1bd7a4a8184c9747516f541 100644 (file)
@@ -323,13 +323,13 @@ static BOOL cli_issue_write(struct cli_state *cli, int fnum, off_t offset,
               0x0008 start of message mode named pipe protocol
 ****************************************************************************/
 
-size_t cli_write(struct cli_state *cli,
+ssize_t cli_write(struct cli_state *cli,
                 int fnum, uint16 write_mode,
                 const char *buf, off_t offset, size_t size)
 {
-       int bwritten = 0;
-       int issued = 0;
-       int received = 0;
+       ssize_t bwritten = 0;
+       unsigned int issued = 0;
+       unsigned int received = 0;
        int mpx = 1;
        int block = cli->max_xmit - (smb_size+32);
        int blocks = (size + (block-1)) / block;
@@ -343,8 +343,8 @@ size_t cli_write(struct cli_state *cli,
        while (received < blocks) {
 
                while ((issued - received < mpx) && (issued < blocks)) {
-                       int bsent = issued * block;
-                       int size1 = MIN(block, size - bsent);
+                       ssize_t bsent = issued * block;
+                       ssize_t size1 = MIN(block, size - bsent);
 
                        if (!cli_issue_write(cli, fnum, offset + bsent,
                                        write_mode,
index 85b7bd9e1eec1f3cee0d87cf33bcbd2d43c01d71..33fc265f79847dda077707a9ed00a65b02b7789f 100644 (file)
@@ -325,14 +325,15 @@ BOOL spnego_parse_krb5_wrap(DATA_BLOB blob, DATA_BLOB *ticket, uint8 tok_id[2])
 */
 int spnego_gen_negTokenTarg(const char *principal, int time_offset, 
                            DATA_BLOB *targ, 
-                           DATA_BLOB *session_key_krb5)
+                           DATA_BLOB *session_key_krb5, uint32 extra_ap_opts)
 {
        int retval;
        DATA_BLOB tkt, tkt_wrapped;
        const char *krb_mechs[] = {OID_KERBEROS5_OLD, OID_NTLMSSP, NULL};
 
        /* get a kerberos ticket for the service and extract the session key */
-       retval = cli_krb5_get_ticket(principal, time_offset, &tkt, session_key_krb5);
+       retval = cli_krb5_get_ticket(principal, time_offset,
+                                       &tkt, session_key_krb5, extra_ap_opts);
 
        if (retval)
                return retval;
index c6b1d465ffed05ea8b15e209f6cf3efb968245e7..5d3710b92e260f055c87e66e95ae9546d37b3134 100644 (file)
@@ -464,8 +464,8 @@ BOOL cli_send_nt_trans(struct cli_state *cli,
 }
 
 /****************************************************************************
-  receive a SMB nttrans response allocating the necessary memory
-  ****************************************************************************/
+ Receive a SMB nttrans response allocating the necessary memory.
+****************************************************************************/
 
 BOOL cli_receive_nt_trans(struct cli_state *cli,
                          char **param, unsigned int *param_len,
@@ -503,7 +503,7 @@ BOOL cli_receive_nt_trans(struct cli_state *cli,
         */
        if (cli_is_dos_error(cli)) {
                 cli_dos_error(cli, &eclass, &ecode);
-               if (cli->pipes[cli->pipe_idx].fnum == 0 || !(eclass == ERRDOS && ecode == ERRmoredata)) {
+               if (!(eclass == ERRDOS && ecode == ERRmoredata)) {
                        cli_signing_trans_stop(cli);
                        return(False);
                }
@@ -637,11 +637,22 @@ BOOL cli_receive_nt_trans(struct cli_state *cli,
                }
                if (cli_is_dos_error(cli)) {
                         cli_dos_error(cli, &eclass, &ecode);
-                       if(cli->pipes[cli->pipe_idx].fnum == 0 || !(eclass == ERRDOS && ecode == ERRmoredata)) {
+                       if(!(eclass == ERRDOS && ecode == ERRmoredata)) {
+                               cli_signing_trans_stop(cli);
+                               return(False);
+                       }
+               }
+               /*
+                * Likewise for NT_STATUS_BUFFER_TOO_SMALL
+                */
+               if (cli_is_nt_error(cli)) {
+                       if (!NT_STATUS_EQUAL(cli_nt_error(cli),
+                                            NT_STATUS_BUFFER_TOO_SMALL)) {
                                cli_signing_trans_stop(cli);
                                return(False);
                        }
                }
+
                /* parse out the total lengths again - they can shrink! */
                if (SVAL(cli->inbuf,smb_ntr_TotalDataCount) < total_data)
                        total_data = SVAL(cli->inbuf,smb_ntr_TotalDataCount);
index 0d521bae8ac42c7421f6db043bee74a48c0e3217..3f2dcd850b33b887270d507146445abb3ae7bc26 100644 (file)
@@ -2,6 +2,7 @@
    Unix SMB/CIFS implementation.
    code to manipulate domain credentials
    Copyright (C) Andrew Tridgell 1997-1998
+   Largely rewritten by Jeremy Allison 2005.
    
    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
@@ -21,8 +22,9 @@
 #include "includes.h"
 
 /****************************************************************************
-represent a credential as a string
+ Represent a credential as a string.
 ****************************************************************************/
+
 char *credstr(const uchar *cred)
 {
        static fstring buf;
@@ -34,182 +36,243 @@ char *credstr(const uchar *cred)
 
 
 /****************************************************************************
 setup the session key. 
-Input: 8 byte challenge block
Setup the session key. 
+ Input: 8 byte challenge block
        8 byte server challenge block
       16 byte md4 encrypted password
-Output:
-      8 byte session key
+ Output:
+      16 byte session key (last 8 bytes zero).
 ****************************************************************************/
-void cred_session_key(const DOM_CHAL *clnt_chal, const DOM_CHAL *srv_chal, const uchar *pass, 
-                     uchar session_key[8])
+
+static void cred_create_session_key(const DOM_CHAL *clnt_chal_in,
+                       const DOM_CHAL *srv_chal_in,
+                       const uchar *pass_in, 
+                       uchar session_key_out[16])
 {
        uint32 sum[2];
        unsigned char sum2[8];
 
-       sum[0] = IVAL(clnt_chal->data, 0) + IVAL(srv_chal->data, 0);
-       sum[1] = IVAL(clnt_chal->data, 4) + IVAL(srv_chal->data, 4);
+       sum[0] = IVAL(clnt_chal_in->data, 0) + IVAL(srv_chal_in->data, 0);
+       sum[1] = IVAL(clnt_chal_in->data, 4) + IVAL(srv_chal_in->data, 4);
 
        SIVAL(sum2,0,sum[0]);
        SIVAL(sum2,4,sum[1]);
 
-       cred_hash1(session_key, sum2, pass);
+       cred_hash1(session_key_out, sum2, pass_in);
+       memset(&session_key_out[8], '\0', 8);
 
        /* debug output */
-       DEBUG(4,("cred_session_key\n"));
+       DEBUG(4,("cred_create_session_key\n"));
 
-       DEBUG(5,("      clnt_chal: %s\n", credstr(clnt_chal->data)));
-       DEBUG(5,("      srv_chal : %s\n", credstr(srv_chal->data)));
+       DEBUG(5,("      clnt_chal_in: %s\n", credstr(clnt_chal_in->data)));
+       DEBUG(5,("      srv_chal_in : %s\n", credstr(srv_chal_in->data)));
        DEBUG(5,("      clnt+srv : %s\n", credstr(sum2)));
-       DEBUG(5,("      sess_key : %s\n", credstr(session_key)));
+       DEBUG(5,("      sess_key_out : %s\n", credstr(session_key_out)));
 }
 
-
 /****************************************************************************
-create a credential
-
-Input:
-      8 byte sesssion key
-      8 byte stored credential
-      4 byte timestamp
-
-Output:
-      8 byte credential
+ Utility function to step credential chain one forward.
+ Deliberately doesn't update the seed. See reseed comment below.
 ****************************************************************************/
-void cred_create(uchar session_key[8], DOM_CHAL *stor_cred, UTIME timestamp, 
-                DOM_CHAL *cred)
+
+static void creds_step(struct dcinfo *dc)
 {
-       DOM_CHAL time_cred;
+       DOM_CHAL time_chal;
 
-       SIVAL(time_cred.data, 0, IVAL(stor_cred->data, 0) + timestamp.time);
-       SIVAL(time_cred.data, 4, IVAL(stor_cred->data, 4));
+       DEBUG(5,("\tsequence = 0x%x\n", (unsigned int)dc->sequence ));
 
-       cred_hash2(cred->data, time_cred.data, session_key);
+       DEBUG(5,("\tseed:        %s\n", credstr(dc->seed_chal.data) ));
 
-       /* debug output*/
-       DEBUG(4,("cred_create\n"));
+       SIVAL(time_chal.data, 0, IVAL(dc->seed_chal.data, 0) + dc->sequence);
+       SIVAL(time_chal.data, 4, IVAL(dc->seed_chal.data, 4));
+                                                                                                   
+       DEBUG(5,("\tseed+seq   %s\n", credstr(time_chal.data) ));
 
-       DEBUG(5,("      sess_key : %s\n", credstr(session_key)));
-       DEBUG(5,("      stor_cred: %s\n", credstr(stor_cred->data)));
-       DEBUG(5,("      timestamp: %x\n"    , timestamp.time));
-       DEBUG(5,("      timecred : %s\n", credstr(time_cred.data)));
-       DEBUG(5,("      calc_cred: %s\n", credstr(cred->data)));
-}
+       cred_hash2(dc->clnt_chal.data, time_chal.data, dc->sess_key);
 
+       DEBUG(5,("\tCLIENT      %s\n", credstr(dc->clnt_chal.data) ));
 
-/****************************************************************************
-  check a supplied credential
+       SIVAL(time_chal.data, 0, IVAL(dc->seed_chal.data, 0) + dc->sequence + 1);
+       SIVAL(time_chal.data, 4, IVAL(dc->seed_chal.data, 4));
+
+       DEBUG(5,("\tseed+seq+1   %s\n", credstr(time_chal.data) ));
 
-Input:
-      8 byte received credential
-      8 byte sesssion key
-      8 byte stored credential
-      4 byte timestamp
+       cred_hash2(dc->srv_chal.data, time_chal.data, dc->sess_key);
+
+       DEBUG(5,("\tSERVER      %s\n", credstr(dc->srv_chal.data) ));
+}
 
-Output:
-      returns 1 if computed credential matches received credential
-      returns 0 otherwise
+
+/****************************************************************************
+ Create a server credential struct.
 ****************************************************************************/
-int cred_assert(DOM_CHAL *cred, uchar session_key[8], DOM_CHAL *stored_cred,
-               UTIME timestamp)
+
+void creds_server_init(struct dcinfo *dc,
+                       DOM_CHAL *clnt_chal,
+                       DOM_CHAL *srv_chal,
+                       const char mach_pw[16],
+                       DOM_CHAL *init_chal_out)
 {
-       DOM_CHAL cred2;
+       DEBUG(10,("creds_server_init: client chal : %s\n", credstr(clnt_chal->data) ));
+       DEBUG(10,("creds_server_init: server chal : %s\n", credstr(srv_chal->data) ));
+       dump_data_pw("creds_server_init: machine pass", mach_pw, 16);
 
-       cred_create(session_key, stored_cred, timestamp, &cred2);
+       /* Just in case this isn't already there */
+       memcpy(dc->mach_pw, mach_pw, 16);
 
-       /* debug output*/
-       DEBUG(4,("cred_assert\n"));
+       /* Generate the session key. */
+       cred_create_session_key(clnt_chal,              /* Stored client challenge. */
+                               srv_chal,               /* Stored server challenge. */
+                               dc->mach_pw,              /* input machine password. */
+                               dc->sess_key);            /* output session key. */
 
-       DEBUG(5,("      challenge : %s\n", credstr(cred->data)));
-       DEBUG(5,("      calculated: %s\n", credstr(cred2.data)));
+       dump_data_pw("creds_server_init: session key", dc->sess_key, 16);
 
-       if (memcmp(cred->data, cred2.data, 8) == 0)
-       {
-               DEBUG(5, ("credentials check ok\n"));
-               return True;
-       }
-       else
-       {
-               DEBUG(5, ("credentials check wrong\n"));
+       /* Generate the next client and server creds. */
+       cred_hash2(dc->clnt_chal.data,                  /* output */
+                       clnt_chal->data,                /* input */
+                       dc->sess_key);                  /* input */
+
+       cred_hash2(dc->srv_chal.data,                   /* output */
+                       srv_chal->data,                 /* input */
+                       dc->sess_key);                  /* input */
+
+       /* Seed is the client chal. */
+       memcpy(dc->seed_chal.data, dc->clnt_chal.data, 8);
+
+       DEBUG(10,("creds_server_init: clnt : %s\n", credstr(dc->clnt_chal.data) ));
+       DEBUG(10,("creds_server_init: server : %s\n", credstr(dc->srv_chal.data) ));
+       DEBUG(10,("creds_server_init: seed : %s\n", credstr(dc->seed_chal.data) ));
+
+       memcpy(init_chal_out->data, dc->srv_chal.data, 8);
+}
+
+/****************************************************************************
+ Check a credential sent by the client.
+****************************************************************************/
+
+BOOL creds_server_check(const struct dcinfo *dc, const DOM_CHAL *rcv_cli_chal_in)
+{
+       if (memcmp(dc->clnt_chal.data, rcv_cli_chal_in->data, 8)) {
+               DEBUG(5,("creds_server_check: challenge : %s\n", credstr(rcv_cli_chal_in->data)));
+               DEBUG(5,("calculated: %s\n", credstr(dc->clnt_chal.data)));
+               DEBUG(0,("creds_server_check: credentials check failed.\n"));
                return False;
        }
+       DEBUG(10,("creds_server_check: credentials check OK.\n"));
+       return True;
 }
 
-
 /****************************************************************************
-  checks credentials; generates next step in the credential chain
+ Replace current seed chal. Internal function - due to split server step below.
 ****************************************************************************/
-BOOL clnt_deal_with_creds(uchar sess_key[8],
-                         DOM_CRED *sto_clnt_cred, DOM_CRED *rcv_srv_cred)
+
+static void creds_reseed(struct dcinfo *dc)
 {
-       UTIME new_clnt_time;
-       uint32 new_cred;
+       DOM_CHAL time_chal;
 
-       DEBUG(5,("clnt_deal_with_creds: %d\n", __LINE__));
+       SIVAL(time_chal.data, 0, IVAL(dc->seed_chal.data, 0) + dc->sequence + 1);
+       SIVAL(time_chal.data, 4, IVAL(dc->seed_chal.data, 4));
 
-       /* increment client time by one second */
-       new_clnt_time.time = sto_clnt_cred->timestamp.time + 1;
+       dc->seed_chal = time_chal;
 
-       /* check that the received server credentials are valid */
-       if (!cred_assert(&rcv_srv_cred->challenge, sess_key,
-                        &sto_clnt_cred->challenge, new_clnt_time))
-       {
-               return False;
-       }
+       DEBUG(5,("cred_reseed: seed %s\n", credstr(dc->seed_chal.data) ));
+}
 
-       /* first 4 bytes of the new seed is old client 4 bytes + clnt time + 1 */
-       new_cred = IVAL(sto_clnt_cred->challenge.data, 0);
-       new_cred += new_clnt_time.time;
+/****************************************************************************
+ Step the server credential chain one forward. 
+****************************************************************************/
 
-       /* store new seed in client credentials */
-       SIVAL(sto_clnt_cred->challenge.data, 0, new_cred);
+BOOL creds_server_step(struct dcinfo *dc, const DOM_CRED *received_cred, DOM_CRED *cred_out)
+{
+       dc->sequence = received_cred->timestamp.time;
 
-       DEBUG(5,("      new clnt cred: %s\n", credstr(sto_clnt_cred->challenge.data)));
-       return True;
-}
+       creds_step(dc);
+
+       /* Create the outgoing credentials */
+       cred_out->timestamp.time = dc->sequence + 1;
+       cred_out->challenge = dc->srv_chal;
 
+       creds_reseed(dc);
+
+       return creds_server_check(dc, &received_cred->challenge);
+}
 
 /****************************************************************************
-  checks credentials; generates next step in the credential chain
+ Create a client credential struct.
 ****************************************************************************/
-BOOL deal_with_creds(uchar sess_key[8],
-                    DOM_CRED *sto_clnt_cred, 
-                    DOM_CRED *rcv_clnt_cred, DOM_CRED *rtn_srv_cred)
+
+void creds_client_init(struct dcinfo *dc,
+                       DOM_CHAL *clnt_chal,
+                       DOM_CHAL *srv_chal,
+                       const char mach_pw[16],
+                       DOM_CHAL *init_chal_out)
 {
-       UTIME new_clnt_time;
-       uint32 new_cred;
+       dc->sequence = time(NULL);
 
-       DEBUG(5,("deal_with_creds: %d\n", __LINE__));
+       DEBUG(10,("creds_client_init: client chal : %s\n", credstr(clnt_chal->data) ));
+       DEBUG(10,("creds_client_init: server chal : %s\n", credstr(srv_chal->data) ));
+       dump_data_pw("creds_client_init: machine pass", mach_pw, 16);
 
-       /* check that the received client credentials are valid */
-       if (!cred_assert(&rcv_clnt_cred->challenge, sess_key,
-                    &sto_clnt_cred->challenge, rcv_clnt_cred->timestamp))
-       {
-               return False;
-       }
+       /* Just in case this isn't already there */
+       memcpy(dc->mach_pw, mach_pw, 16);
 
-       /* increment client time by one second */
-       new_clnt_time.time = rcv_clnt_cred->timestamp.time + 1;
+       /* Generate the session key. */
+       cred_create_session_key(clnt_chal,              /* Stored client challenge. */
+                               srv_chal,               /* Stored server challenge. */
+                               dc->mach_pw,              /* input machine password. */
+                               dc->sess_key);            /* output session key. */
 
-       /* first 4 bytes of the new seed is old client 4 bytes + clnt time + 1 */
-       new_cred = IVAL(sto_clnt_cred->challenge.data, 0);
-       new_cred += new_clnt_time.time;
+       dump_data_pw("creds_client_init: session key", dc->sess_key, 16);
 
-       DEBUG(5,("deal_with_creds: new_cred[0]=%x\n", new_cred));
+       /* Generate the next client and server creds. */
+       cred_hash2(dc->clnt_chal.data,  /* output */
+                       clnt_chal->data,                /* input */
+                       dc->sess_key);                  /* input */
 
-       /* doesn't matter that server time is 0 */
-       rtn_srv_cred->timestamp.time = 0;
+       cred_hash2(dc->srv_chal.data,           /* output */
+                       srv_chal->data,                 /* input */
+                       dc->sess_key);                  /* input */
 
-       DEBUG(5,("deal_with_creds: new_clnt_time=%x\n", new_clnt_time.time));
+       /* Seed is the client cred. */
+       memcpy(dc->seed_chal.data, dc->clnt_chal.data, 8);
 
-       /* create return credentials for inclusion in the reply */
-       cred_create(sess_key, &sto_clnt_cred->challenge, new_clnt_time,
-                   &rtn_srv_cred->challenge);
-       
-       DEBUG(5,("deal_with_creds: clnt_cred=%s\n", credstr(sto_clnt_cred->challenge.data)));
+       DEBUG(10,("creds_client_init: clnt : %s\n", credstr(dc->clnt_chal.data) ));
+       DEBUG(10,("creds_client_init: server : %s\n", credstr(dc->srv_chal.data) ));
+       DEBUG(10,("creds_client_init: seed : %s\n", credstr(dc->seed_chal.data) ));
 
-       /* store new seed in client credentials */
-       SIVAL(sto_clnt_cred->challenge.data, 0, new_cred);
+       memcpy(init_chal_out->data, dc->clnt_chal.data, 8);
+}
+
+/****************************************************************************
+ Check a credential returned by the server.
+****************************************************************************/
 
+BOOL creds_client_check(const struct dcinfo *dc, const DOM_CHAL *rcv_srv_chal_in)
+{
+       if (memcmp(dc->srv_chal.data, rcv_srv_chal_in->data, 8)) {
+               DEBUG(5,("creds_client_check: challenge : %s\n", credstr(rcv_srv_chal_in->data)));
+               DEBUG(5,("calculated: %s\n", credstr(dc->srv_chal.data)));
+               DEBUG(0,("creds_client_check: credentials check failed.\n"));
+               return False;
+       }
+       DEBUG(10,("creds_client_check: credentials check OK.\n"));
        return True;
 }
+
+/****************************************************************************
+  Step the client credentials to the next element in the chain, updating the
+  current client and server credentials and the seed
+  produce the next authenticator in the sequence ready to send to
+  the server
+****************************************************************************/
+
+void creds_client_step(struct dcinfo *dc, DOM_CRED *next_cred_out)
+{
+        dc->sequence += 2;
+       creds_step(dc);
+       creds_reseed(dc);
+
+       next_cred_out->challenge = dc->clnt_chal;
+       next_cred_out->timestamp.time = dc->sequence;
+}
index 8462fbee877d7cd7fe8f431b9f8fb976a44c6604..3c0b13ad6ff565d8fd9654d00f5f6c3698ae2a66 100644 (file)
@@ -62,7 +62,7 @@ static const struct {
        {ERRDOS,        193,    NT_STATUS_BAD_INITIAL_PC},
        {ERRDOS,        87,     NT_STATUS_INVALID_CID},
        {ERRHRD,        ERRgeneral,     NT_STATUS_TIMER_NOT_CANCELED},
-       {ERRDOS,        87,     NT_STATUS_INVALID_PARAMETER},
+       {ERRDOS,        ERRinvalidparam,        NT_STATUS_INVALID_PARAMETER},
        {ERRDOS,        ERRbadfile,     NT_STATUS_NO_SUCH_DEVICE},
        {ERRDOS,        ERRbadfile,     NT_STATUS_NO_SUCH_FILE},
        {ERRDOS,        ERRbadfunc,     NT_STATUS_INVALID_DEVICE_REQUEST},
@@ -338,7 +338,7 @@ static const struct {
        {ERRDOS,        203,    NT_STATUS(0xc0000100)},
        {ERRDOS,        145,    NT_STATUS_DIRECTORY_NOT_EMPTY},
        {ERRHRD,        ERRgeneral,     NT_STATUS_FILE_CORRUPT_ERROR},
-       {ERRDOS,        267,    NT_STATUS_NOT_A_DIRECTORY},
+       {ERRDOS,        ERRbaddirectory,        NT_STATUS_NOT_A_DIRECTORY},
        {ERRHRD,        ERRgeneral,     NT_STATUS_BAD_LOGON_SESSION_STATE},
        {ERRHRD,        ERRgeneral,     NT_STATUS_LOGON_SESSION_COLLISION},
        {ERRDOS,        206,    NT_STATUS_NAME_TOO_LONG},
index f9461f936834cce8d49f4b493e80f70f60ba9e7e..5699e153bbd2c59ba092e4cfaa687a169062b5f5 100644 (file)
@@ -420,7 +420,7 @@ int smbc_open_print_job(const char *fname)
 {
        SMBCFILE * file = statcont->open_print_job(statcont, fname);
        if (!file) return -1;
-       return (int) file;
+       return file->cli_fd;
 }
 
 int smbc_list_print_jobs(const char *purl, smbc_list_print_job_fn fn)
index fe8f878aa57c0cd0eb26293be3658aa2f9026bfb..1e729abb2218f4fd41b2e26cd981eeb60c2a17be 100644 (file)
@@ -80,6 +80,23 @@ static int DLIST_CONTAINS(SMBCFILE * list, SMBCFILE *p) {
        return False;
 }
 
+/*
+ * Find an lsa pipe handle associated with a cli struct.
+ */
+
+static struct rpc_pipe_client *find_lsa_pipe_hnd(struct cli_state *ipc_cli)
+{
+       struct rpc_pipe_client *pipe_hnd;
+
+       for (pipe_hnd = ipc_cli->pipe_list; pipe_hnd; pipe_hnd = pipe_hnd->next) {
+               if (pipe_hnd->pipe_idx == PI_LSARPC) {
+                       return pipe_hnd;
+               }
+       }
+
+       return NULL;
+}
+
 static int smbc_close_ctx(SMBCCTX *context, SMBCFILE *file);
 static off_t smbc_lseek_ctx(SMBCCTX *context, SMBCFILE *file, off_t offset, int whence);
 
@@ -800,6 +817,7 @@ SMBCSRV *smbc_attr_server(SMBCCTX *context,
 {
         struct in_addr ip;
        struct cli_state *ipc_cli;
+       struct rpc_pipe_client *pipe_hnd;
         NTSTATUS nt_status;
        SMBCSRV *ipc_srv=NULL;
 
@@ -835,29 +853,27 @@ SMBCSRV *smbc_attr_server(SMBCCTX *context,
                         return NULL;
                 }
 
-                if(pol) {
+               pipe_hnd = cli_rpc_pipe_open_noauth(ipc_cli, PI_LSARPC, &nt_status);
+                if (!pipe_hnd) {
+                        DEBUG(1, ("cli_nt_session_open fail!\n"));
+                        errno = ENOTSUP;
+                        cli_shutdown(ipc_cli);
+                        return NULL;
+                }
 
-                       if (!cli_nt_session_open(ipc_cli, PI_LSARPC)) {
-                         DEBUG(1, ("cli_nt_session_open fail!\n"));
-                           errno = ENOTSUP;
-                         cli_shutdown(ipc_cli);
-                         return NULL;
-                      }
-   
-                        /* Some systems don't support SEC_RIGHTS_MAXIMUM_ALLOWED,
-                         but NT sends 0x2000000 so we might as well do it too. */
-
-                      nt_status = cli_lsa_open_policy(ipc_cli,
-                            ipc_cli->mem_ctx,
-                            True, 
-                            GENERIC_EXECUTE_ACCESS,
-                            pol);
-
-                        if (!NT_STATUS_IS_OK(nt_status)) {
-                         errno = smbc_errno(context, ipc_cli);
-                         cli_shutdown(ipc_cli);
-                         return NULL;
-                      }
+                /* Some systems don't support SEC_RIGHTS_MAXIMUM_ALLOWED,
+                   but NT sends 0x2000000 so we might as well do it too. */
+        
+                nt_status = rpccli_lsa_open_policy(pipe_hnd,
+                                                ipc_cli->mem_ctx,
+                                                True, 
+                                                GENERIC_EXECUTE_ACCESS,
+                                                pol);
+        
+                if (!NT_STATUS_IS_OK(nt_status)) {
+                        errno = smbc_errno(context, ipc_cli);
+                        cli_shutdown(ipc_cli);
+                        return NULL;
                 }
 
                 ipc_srv = SMB_MALLOC_P(SMBCSRV);
@@ -1782,7 +1798,7 @@ static off_t smbc_lseek_ctx(SMBCCTX *context, SMBCFILE *file, off_t offset, int
                if (!cli_qfileinfo(targetcli, file->cli_fd, NULL, &size, NULL, NULL,
                                   NULL, NULL, NULL)) 
                {
-                   SMB_BIG_UINT b_size = size;
+                   SMB_OFF_T b_size = size;
                        if (!cli_getattrE(targetcli, file->cli_fd, NULL, &b_size, NULL, NULL,
                                      NULL)) 
                    {
@@ -3041,7 +3057,7 @@ static off_t smbc_telldir_ctx(SMBCCTX *context, SMBCFILE *dir)
        /*
         * We return the pointer here as the offset
         */
-       ret_val = (int)dir->dir_next;
+       ret_val = (off_t)(long)dir->dir_next;
        return ret_val;
 
 }
@@ -3347,14 +3363,20 @@ static void convert_sid_to_string(struct cli_state *ipc_cli,
        char **domains = NULL;
        char **names = NULL;
        uint32 *types = NULL;
-
+       struct rpc_pipe_client *pipe_hnd = find_lsa_pipe_hnd(ipc_cli);
        sid_to_string(str, sid);
 
-        if (numeric) return;     /* no lookup desired */
-        
+       if (numeric) {
+               return;     /* no lookup desired */
+       }
+       
+       if (!pipe_hnd) {
+               return;
+       }
        /* Ask LSA to convert the sid to a name */
 
-       if (!NT_STATUS_IS_OK(cli_lsa_lookup_sids(ipc_cli, ipc_cli->mem_ctx,  
+       if (!NT_STATUS_IS_OK(rpccli_lsa_lookup_sids(pipe_hnd, ipc_cli->mem_ctx,  
                                                 pol, 1, sid, &domains, 
                                                 &names, &types)) ||
            !domains || !domains[0] || !names || !names[0]) {
@@ -3378,6 +3400,11 @@ static BOOL convert_string_to_sid(struct cli_state *ipc_cli,
        uint32 *types = NULL;
        DOM_SID *sids = NULL;
        BOOL result = True;
+       struct rpc_pipe_client *pipe_hnd = find_lsa_pipe_hnd(ipc_cli);
+
+       if (!pipe_hnd) {
+               return False;
+       }
 
         if (numeric) {
                 if (strncmp(str, "S-", 2) == 0) {
@@ -3388,7 +3415,7 @@ static BOOL convert_string_to_sid(struct cli_state *ipc_cli,
                 goto done;
         }
 
-       if (!NT_STATUS_IS_OK(cli_lsa_lookup_names(ipc_cli, ipc_cli->mem_ctx, 
+       if (!NT_STATUS_IS_OK(rpccli_lsa_lookup_names(pipe_hnd, ipc_cli->mem_ctx, 
                                                  pol, 1, &str, &sids, 
                                                  &types))) {
                result = False;
@@ -5161,7 +5188,7 @@ static int smbc_print_file_ctx(SMBCCTX *c_file, const char *fname, SMBCCTX *c_pr
 
         /* Try to open the file for reading ... */
 
-        if ((int)(fid1 = c_file->open(c_file, fname, O_RDONLY, 0666)) < 0) {
+        if ((long)(fid1 = c_file->open(c_file, fname, O_RDONLY, 0666)) < 0) {
                 
                 DEBUG(3, ("Error, fname=%s, errno=%i\n", fname, errno));
                 return -1;  /* smbc_open sets errno */
@@ -5170,7 +5197,7 @@ static int smbc_print_file_ctx(SMBCCTX *c_file, const char *fname, SMBCCTX *c_pr
 
         /* Now, try to open the printer file for writing */
 
-        if ((int)(fid2 = c_print->open_print_job(c_print, printq)) < 0) {
+        if ((long)(fid2 = c_print->open_print_job(c_print, printq)) < 0) {
 
                 saverr = errno;  /* Save errno */
                 c_file->close_fn(c_file, fid1);
index b02c2384a8de62817a70390dc34c592481324512..6b551e8774c4bd7df761cfea90810f9b1517548f 100644 (file)
@@ -5,6 +5,7 @@
 
    Copyright (C) Andrew Tridgell      2001
    Copyright (C) Andrew Bartlett 2001-2003
+   Copyright (C) Andrew Bartlett 2005 (Updated from gensec).
 
    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
@@ -217,6 +218,12 @@ NTSTATUS ntlmssp_update(NTLMSSP_STATE *ntlmssp_state,
        uint32 ntlmssp_command;
        int i;
 
+       if (ntlmssp_state->expected_state == NTLMSSP_DONE) {
+               /* Called update after negotiations finished. */
+               DEBUG(1, ("Called NTLMSSP after state machine was 'done'\n"));
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
        *out = data_blob(NULL, 0);
 
        if (!in.length && ntlmssp_state->stored_response.length) {
@@ -348,6 +355,13 @@ static void ntlmssp_handle_neg_flags(struct ntlmssp_state *ntlmssp_state,
 
        if (!(neg_flags & NTLMSSP_NEGOTIATE_128)) {
                ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_128;
+               if (neg_flags & NTLMSSP_NEGOTIATE_56) {
+                       ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_56;
+               }
+       }
+
+       if (!(neg_flags & NTLMSSP_NEGOTIATE_56)) {
+               ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_56;
        }
 
        if (!(neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH)) {
@@ -360,6 +374,34 @@ static void ntlmssp_handle_neg_flags(struct ntlmssp_state *ntlmssp_state,
        
 }
 
+/**
+ Weaken NTLMSSP keys to cope with down-level clients and servers.
+
+ We probably should have some parameters to control this, but as
+ it only occours for LM_KEY connections, and this is controlled
+ by the client lanman auth/lanman auth parameters, it isn't too bad.
+*/
+
+void ntlmssp_weaken_keys(NTLMSSP_STATE *ntlmssp_state)
+{
+       /* Key weakening not performed on the master key for NTLM2
+          and does not occour for NTLM1.  Therefore we only need
+          to do this for the LM_KEY.
+       */
+
+       if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_LM_KEY) {
+               if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_128) {
+                       ;
+               } else if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_56) {
+                       ntlmssp_state->session_key.data[7] = 0xa0;
+               } else { /* forty bits */
+                       ntlmssp_state->session_key.data[5] = 0xe5;
+                       ntlmssp_state->session_key.data[6] = 0x38;
+                       ntlmssp_state->session_key.data[7] = 0xb0;
+               }
+               ntlmssp_state->session_key.length = 8;
+       }
+}
 
 /**
  * Next state function for the Negotiate packet
@@ -398,6 +440,9 @@ static NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state,
                        return NT_STATUS_INVALID_PARAMETER;
                }
                
+               DEBUG(10, ("ntlmssp_server_negotiate: client = %s, domain = %s\n",
+                               cliname ? cliname : "", domname ? domname : ""));
+
                SAFE_FREE(cliname);
                SAFE_FREE(domname);
                
@@ -495,7 +540,7 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state,
        DATA_BLOB lm_session_key = data_blob(NULL, 0);
        DATA_BLOB session_key = data_blob(NULL, 0);
        uint32 ntlmssp_command, auth_flags;
-       NTSTATUS nt_status;
+       NTSTATUS nt_status = NT_STATUS_OK;
 
        /* used by NTLM2 */
        BOOL doing_ntlm2 = False;
@@ -639,6 +684,9 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state,
                                data_blob_free(&encrypted_session_key);
                                return nt_status;
                        }
+
+                       /* LM Key is incompatible. */
+                       ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY;
                }
        }
 
@@ -710,11 +758,11 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state,
                if (!encrypted_session_key.data || encrypted_session_key.length != 16) {
                        data_blob_free(&encrypted_session_key);
                        DEBUG(1, ("Client-supplied KEY_EXCH session key was of invalid length (%u)!\n", 
-                                 encrypted_session_key.length));
+                                 (unsigned int)encrypted_session_key.length));
                        return NT_STATUS_INVALID_PARAMETER;
                } else if (!session_key.data || session_key.length != 16) {
                        DEBUG(5, ("server session key is invalid (len == %u), cannot do KEY_EXCH!\n", 
-                                 session_key.length));
+                                 (unsigned int)session_key.length));
                        ntlmssp_state->session_key = session_key;
                } else {
                        dump_data_pw("KEY_EXCH session key (enc):\n", encrypted_session_key.data, encrypted_session_key.length);
@@ -731,6 +779,9 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state,
                ntlmssp_state->session_key = session_key;
        }
 
+       /* The client might need us to use a partial-strength session key */
+       ntlmssp_weaken_keys(ntlmssp_state);
+
        if (!NT_STATUS_IS_OK(nt_status)) {
                ntlmssp_state->session_key = data_blob(NULL, 0);
        } else if (ntlmssp_state->session_key.length) {
@@ -739,8 +790,8 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state,
 
        data_blob_free(&encrypted_session_key);
        
-       /* allow arbitarily many authentications */
-       ntlmssp_state->expected_state = NTLMSSP_AUTH;
+       /* Only one authentication allowed per server state. */
+       ntlmssp_state->expected_state = NTLMSSP_DONE;
 
        return nt_status;
 }
@@ -784,7 +835,8 @@ NTSTATUS ntlmssp_server_start(NTLMSSP_STATE **ntlmssp_state)
                NTLMSSP_NEGOTIATE_NTLM |
                NTLMSSP_NEGOTIATE_NTLM2 |
                NTLMSSP_NEGOTIATE_KEY_EXCH |
-               NTLMSSP_NEGOTIATE_SIGN;
+               NTLMSSP_NEGOTIATE_SIGN |
+               NTLMSSP_NEGOTIATE_SEAL;
 
        return NT_STATUS_OK;
 }
@@ -851,7 +903,7 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state,
        DATA_BLOB nt_response = data_blob(NULL, 0);
        DATA_BLOB session_key = data_blob(NULL, 0);
        DATA_BLOB encrypted_session_key = data_blob(NULL, 0);
-       NTSTATUS nt_status;
+       NTSTATUS nt_status = NT_STATUS_OK;
 
        if (!msrpc_parse(&reply, "CdBd",
                         "NTLMSSP",
@@ -977,8 +1029,6 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state,
                hmac_md5(user_session_key, session_nonce, sizeof(session_nonce), session_key.data);
                dump_data_pw("NTLM2 session key:\n", session_key.data, session_key.length);
        } else {
-               
-               
                uchar lm_hash[16];
                uchar nt_hash[16];
                E_deshash(ntlmssp_state->password, lm_hash);
@@ -998,8 +1048,8 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state,
                session_key = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 16);
                if ((ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_LM_KEY) 
                    && lp_client_lanman_auth()) {
-                       SMBsesskeygen_lmv1(lm_hash, lm_response.data, 
-                                          session_key.data);
+                       SMBsesskeygen_lm_sess_key(lm_hash, lm_response.data,
+                                       session_key.data);
                        dump_data_pw("LM session key\n", session_key.data, session_key.length);
                } else {
                        SMBsesskeygen_ntv1(nt_hash, NULL, session_key.data);
@@ -1045,19 +1095,22 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state,
 
        data_blob_free(&ntlmssp_state->chal);
 
+       ntlmssp_state->session_key = session_key;
+
+       /* The client might be using 56 or 40 bit weakened keys */
+       ntlmssp_weaken_keys(ntlmssp_state);
+
        ntlmssp_state->chal = challenge_blob;
        ntlmssp_state->lm_resp = lm_response;
        ntlmssp_state->nt_resp = nt_response;
-       ntlmssp_state->session_key = session_key;
 
-       ntlmssp_state->expected_state = NTLMSSP_UNKNOWN;
+       ntlmssp_state->expected_state = NTLMSSP_DONE;
 
        if (!NT_STATUS_IS_OK(nt_status = ntlmssp_sign_init(ntlmssp_state))) {
                DEBUG(1, ("Could not setup NTLMSSP signing/sealing system (error was: %s)\n", nt_errstr(nt_status)));
-               return nt_status;
        }
 
-       return NT_STATUS_MORE_PROCESSING_REQUIRED;
+       return nt_status;
 }
 
 NTSTATUS ntlmssp_client_start(NTLMSSP_STATE **ntlmssp_state)
@@ -1103,4 +1156,3 @@ NTSTATUS ntlmssp_client_start(NTLMSSP_STATE **ntlmssp_state)
 
        return NT_STATUS_OK;
 }
-
index 4b3043aec8076ddf8a63d5cf8e4ecc228d87e9d1..e71504867e956cf32a8c3b4841f767b10b8ffbf6 100644 (file)
@@ -216,7 +216,7 @@ BOOL msrpc_parse(const DATA_BLOB *blob,
                                        /* if odd length and unicode */
                                        return False;
                                }
-                               if (blob->data + ptr < (uint8 *)ptr || blob->data + ptr < blob->data)
+                               if (blob->data + ptr < (uint8 *)(unsigned long)ptr || blob->data + ptr < blob->data)
                                        return False;
 
                                if (0 < len1) {
@@ -244,7 +244,7 @@ BOOL msrpc_parse(const DATA_BLOB *blob,
                                        return False;
                                }
 
-                               if (blob->data + ptr < (uint8 *)ptr || blob->data + ptr < blob->data)
+                               if (blob->data + ptr < (uint8 *)(unsigned long)ptr || blob->data + ptr < blob->data)
                                        return False;   
 
                                if (0 < len1) {
@@ -272,7 +272,7 @@ BOOL msrpc_parse(const DATA_BLOB *blob,
                                        return False;
                                }
 
-                               if (blob->data + ptr < (uint8 *)ptr || blob->data + ptr < blob->data)
+                               if (blob->data + ptr < (uint8 *)(unsigned long)ptr || blob->data + ptr < blob->data)
                                        return False;   
                        
                                *b = data_blob(blob->data + ptr, len1);
index b8105970762f4ce2617f3189879c48fa638204aa..51023ca35652562365a73d1daceb19bb5d1b6024 100644 (file)
@@ -2,8 +2,7 @@
  *  Unix SMB/CIFS implementation.
  *  Version 3.0
  *  NTLMSSP Signing routines
- *  Copyright (C) Luke Kenneth Casson Leighton 1996-2001
- *  Copyright (C) Andrew Bartlett 2003
+ *  Copyright (C) Andrew Bartlett 2003-2005
  *  
  *  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
 #define SRV_SIGN "session key to server-to-client signing key magic constant"
 #define SRV_SEAL "session key to server-to-client sealing key magic constant"
 
-static void NTLMSSPcalc_ap( unsigned char *hash, unsigned char *data, int len)
-{
-    unsigned char index_i = hash[256];
-    unsigned char index_j = hash[257];
-    int ind;
-
-    for (ind = 0; ind < len; ind++)
-    {
-        unsigned char tc;
-        unsigned char t;
-
-        index_i++;
-        index_j += hash[index_i];
-
-        tc = hash[index_i];
-        hash[index_i] = hash[index_j];
-        hash[index_j] = tc;
-
-        t = hash[index_i] + hash[index_j];
-        data[ind] = data[ind] ^ hash[t];
-    }
-
-    hash[256] = index_i;
-    hash[257] = index_j;
-}
-
-static void calc_hash(unsigned char hash[258], unsigned char *k2, int k2l)
-{
-       unsigned char j = 0;
-       int ind;
-
-       for (ind = 0; ind < 256; ind++)
-       {
-               hash[ind] = (unsigned char)ind;
-       }
-
-       for (ind = 0; ind < 256; ind++)
-       {
-               unsigned char tc;
-
-               j += (hash[ind] + k2[ind%k2l]);
-
-               tc = hash[ind];
-               hash[ind] = hash[j];
-               hash[j] = tc;
-       }
-
-       hash[256] = 0;
-       hash[257] = 0;
-}
+/**
+ * Some notes on then NTLM2 code:
+ *
+ * NTLM2 is a AEAD system.  This means that the data encrypted is not
+ * all the data that is signed.  In DCE-RPC case, the headers of the
+ * DCE-RPC packets are also signed.  This prevents some of the
+ * fun-and-games one might have by changing them.
+ *
+ */
 
-static void calc_ntlmv2_hash(unsigned char hash[258], unsigned char digest[16],
-                            DATA_BLOB session_key, 
-                            const char *constant)
+static void calc_ntlmv2_key(unsigned char subkey[16],
+                               DATA_BLOB session_key,
+                               const char *constant)
 {
        struct MD5Context ctx3;
-
-       /* NOTE:  This code is currently complate fantasy - it's
-          got more in common with reality than the previous code
-          (the LM session key is not the right thing to use) but
-          it still needs work */
-
        MD5Init(&ctx3);
        MD5Update(&ctx3, session_key.data, session_key.length);
-       MD5Update(&ctx3, (const unsigned char *)constant, strlen(constant)+1);
-       MD5Final(digest, &ctx3);
-
-       calc_hash(hash, digest, 16);
+       MD5Update(&ctx3, constant, strlen(constant)+1);
+       MD5Final(subkey, &ctx3);
 }
 
 enum ntlmssp_direction {
@@ -103,64 +53,107 @@ enum ntlmssp_direction {
 };
 
 static NTSTATUS ntlmssp_make_packet_signature(NTLMSSP_STATE *ntlmssp_state,
-                                             const uchar *data, size_t length, 
-                                             enum ntlmssp_direction direction,
-                                             DATA_BLOB *sig) 
+                                               const uchar *data, size_t length, 
+                                               const uchar *whole_pdu, size_t pdu_length,
+                                               enum ntlmssp_direction direction,
+                                               DATA_BLOB *sig,
+                                               BOOL encrypt_sig)
 {
        if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {
                HMACMD5Context ctx;
                uchar seq_num[4];
                uchar digest[16];
-               SIVAL(seq_num, 0, ntlmssp_state->ntlmssp_seq_num);
-
-               hmac_md5_init_limK_to_64((const unsigned char *)(ntlmssp_state->send_sign_const), 16, &ctx);
-               hmac_md5_update(seq_num, 4, &ctx);
-               hmac_md5_update(data, length, &ctx);
-               hmac_md5_final(digest, &ctx);
 
-               if (!msrpc_gen(sig, "dBd", NTLMSSP_SIGN_VERSION, digest, 8 /* only copy first 8 bytes */
-                              , ntlmssp_state->ntlmssp_seq_num)) {
+               *sig = data_blob(NULL, NTLMSSP_SIG_SIZE);
+               if (!sig->data) {
                        return NT_STATUS_NO_MEMORY;
                }
 
-               if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) {
+               switch (direction) {
+                       case NTLMSSP_SEND:
+                               DEBUG(100,("ntlmssp_make_packet_signature: SEND seq = %u, len = %u, pdu_len = %u\n",
+                                       ntlmssp_state->ntlm2_send_seq_num,
+                                       (unsigned int)length,
+                                       (unsigned int)pdu_length));
+
+                               SIVAL(seq_num, 0, ntlmssp_state->ntlm2_send_seq_num);
+                               ntlmssp_state->ntlm2_send_seq_num++;
+                               hmac_md5_init_limK_to_64(ntlmssp_state->send_sign_key, 16, &ctx);
+                               break;
+                       case NTLMSSP_RECEIVE:
+
+                               DEBUG(100,("ntlmssp_make_packet_signature: RECV seq = %u, len = %u, pdu_len = %u\n",
+                                       ntlmssp_state->ntlm2_recv_seq_num,
+                                       (unsigned int)length,
+                                       (unsigned int)pdu_length));
+
+                               SIVAL(seq_num, 0, ntlmssp_state->ntlm2_recv_seq_num);
+                               ntlmssp_state->ntlm2_recv_seq_num++;
+                               hmac_md5_init_limK_to_64(ntlmssp_state->recv_sign_key, 16, &ctx);
+                               break;
+                }
+
+               dump_data_pw("pdu data ", whole_pdu, pdu_length);
+
+               hmac_md5_update(seq_num, 4, &ctx);
+               hmac_md5_update(whole_pdu, pdu_length, &ctx);
+               hmac_md5_final(digest, &ctx);
+
+               if (encrypt_sig && (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH)) {
                        switch (direction) {
                        case NTLMSSP_SEND:
-                               NTLMSSPcalc_ap(ntlmssp_state->send_sign_hash,  sig->data+4, sig->length-4);
+                               smb_arc4_crypt(ntlmssp_state->send_seal_arc4_state,  digest, 8);
                                break;
                        case NTLMSSP_RECEIVE:
-                               NTLMSSPcalc_ap(ntlmssp_state->recv_sign_hash,  sig->data+4, sig->length-4);
+                               smb_arc4_crypt(ntlmssp_state->recv_seal_arc4_state,  digest, 8);
                                break;
                        }
                }
+
+               SIVAL(sig->data, 0, NTLMSSP_SIGN_VERSION);
+               memcpy(sig->data + 4, digest, 8);
+               memcpy(sig->data + 12, seq_num, 4);
+
+               dump_data_pw("ntlmssp v2 sig ", sig->data, sig->length);
+
        } else {
                uint32 crc;
                crc = crc32_calc_buffer((const char *)data, length);
-               if (!msrpc_gen(sig, "dddd", NTLMSSP_SIGN_VERSION, 0, crc, ntlmssp_state->ntlmssp_seq_num)) {
+               if (!msrpc_gen(sig, "dddd", NTLMSSP_SIGN_VERSION, 0, crc, ntlmssp_state->ntlmv1_seq_num)) {
                        return NT_STATUS_NO_MEMORY;
                }
                
-               dump_data_pw("ntlmssp hash:\n", ntlmssp_state->ntlmssp_hash,
-                            sizeof(ntlmssp_state->ntlmssp_hash));
-               NTLMSSPcalc_ap(ntlmssp_state->ntlmssp_hash, sig->data+4, sig->length-4);
+               ntlmssp_state->ntlmv1_seq_num++;
+
+               dump_data_pw("ntlmssp hash:\n", ntlmssp_state->ntlmv1_arc4_state,
+                            sizeof(ntlmssp_state->ntlmv1_arc4_state));
+               smb_arc4_crypt(ntlmssp_state->ntlmv1_arc4_state, sig->data+4, sig->length-4);
        }
        return NT_STATUS_OK;
 }
 
 NTSTATUS ntlmssp_sign_packet(NTLMSSP_STATE *ntlmssp_state,
                                    const uchar *data, size_t length, 
+                                   const uchar *whole_pdu, size_t pdu_length, 
                                    DATA_BLOB *sig) 
 {
        NTSTATUS nt_status;
+
+       if (!ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SIGN) {
+               DEBUG(3, ("NTLMSSP Signing not negotiated - cannot sign packet!\n"));
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
        if (!ntlmssp_state->session_key.length) {
                DEBUG(3, ("NO session key, cannot check sign packet\n"));
                return NT_STATUS_NO_USER_SESSION_KEY;
        }
 
-       nt_status = ntlmssp_make_packet_signature(ntlmssp_state, data, length, NTLMSSP_SEND, sig);
+       nt_status = ntlmssp_make_packet_signature(ntlmssp_state,
+                                               data, length,
+                                               whole_pdu, pdu_length,
+                                               NTLMSSP_SEND, sig, True);
 
-       /* increment counter on send */
-       ntlmssp_state->ntlmssp_seq_num++;
        return nt_status;
 }
 
@@ -171,8 +164,9 @@ NTSTATUS ntlmssp_sign_packet(NTLMSSP_STATE *ntlmssp_state,
  */
 
 NTSTATUS ntlmssp_check_packet(NTLMSSP_STATE *ntlmssp_state,
-                             const uchar *data, size_t length, 
-                             const DATA_BLOB *sig) 
+                               const uchar *data, size_t length, 
+                               const uchar *whole_pdu, size_t pdu_length, 
+                               const DATA_BLOB *sig) 
 {
        DATA_BLOB local_sig;
        NTSTATUS nt_status;
@@ -187,32 +181,51 @@ NTSTATUS ntlmssp_check_packet(NTLMSSP_STATE *ntlmssp_state,
                          (unsigned long)sig->length));
        }
 
-       nt_status = ntlmssp_make_packet_signature(ntlmssp_state, data, 
-                                                 length, NTLMSSP_RECEIVE, &local_sig);
+       nt_status = ntlmssp_make_packet_signature(ntlmssp_state,
+                                               data, length,
+                                               whole_pdu, pdu_length,
+                                               NTLMSSP_RECEIVE, &local_sig, True);
        
        if (!NT_STATUS_IS_OK(nt_status)) {
                DEBUG(0, ("NTLMSSP packet check failed with %s\n", nt_errstr(nt_status)));
+               data_blob_free(&local_sig);
                return nt_status;
        }
        
-       if (memcmp(sig->data+sig->length - 8, local_sig.data+local_sig.length - 8, 8) != 0) {
-               DEBUG(5, ("BAD SIG: wanted signature of\n"));
-               dump_data(5, (const char *)local_sig.data, local_sig.length);
-               
-               DEBUG(5, ("BAD SIG: got signature of\n"));
-               dump_data(5, (const char *)(sig->data), sig->length);
+       if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {
+               if (local_sig.length != sig->length ||
+                               memcmp(local_sig.data, sig->data, sig->length) != 0) {
+                       DEBUG(5, ("BAD SIG NTLM2: wanted signature of\n"));
+                       dump_data(5, local_sig.data, local_sig.length);
 
-               DEBUG(0, ("NTLMSSP packet check failed due to invalid signature!\n"));
-               return NT_STATUS_ACCESS_DENIED;
-       }
+                       DEBUG(5, ("BAD SIG: got signature of\n"));
+                       dump_data(5, sig->data, sig->length);
+
+                       DEBUG(0, ("NTLMSSP NTLM2 packet check failed due to invalid signature!\n"));
+                       data_blob_free(&local_sig);
+                       return NT_STATUS_ACCESS_DENIED;
+               }
+       } else {
+               if (local_sig.length != sig->length ||
+                               memcmp(local_sig.data + 8, sig->data + 8, sig->length - 8) != 0) {
+                       DEBUG(5, ("BAD SIG NTLM1: wanted signature of\n"));
+                       dump_data(5, local_sig.data, local_sig.length);
+
+                       DEBUG(5, ("BAD SIG: got signature of\n"));
+                       dump_data(5, sig->data, sig->length);
 
-       /* increment counter on recieive */
-       ntlmssp_state->ntlmssp_seq_num++;
+                       DEBUG(0, ("NTLMSSP NTLM1 packet check failed due to invalid signature!\n"));
+                       data_blob_free(&local_sig);
+                       return NT_STATUS_ACCESS_DENIED;
+               }
+       }
+       dump_data_pw("checked ntlmssp signature\n", sig->data, sig->length);
+       DEBUG(10,("ntlmssp_check_packet: NTLMSSP signature OK !\n"));
 
+       data_blob_free(&local_sig);
        return NT_STATUS_OK;
 }
 
-
 /**
  * Seal data with the NTLMSSP algorithm
  *
@@ -220,8 +233,16 @@ NTSTATUS ntlmssp_check_packet(NTLMSSP_STATE *ntlmssp_state,
 
 NTSTATUS ntlmssp_seal_packet(NTLMSSP_STATE *ntlmssp_state,
                             uchar *data, size_t length,
+                            uchar *whole_pdu, size_t pdu_length,
                             DATA_BLOB *sig)
 {      
+       NTSTATUS nt_status;
+
+       if (!ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL) {
+               DEBUG(3, ("NTLMSSP Sealing not negotiated - cannot seal packet!\n"));
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
        if (!ntlmssp_state->session_key.length) {
                DEBUG(3, ("NO session key, cannot seal packet\n"));
                return NT_STATUS_NO_USER_SESSION_KEY;
@@ -230,53 +251,44 @@ NTSTATUS ntlmssp_seal_packet(NTLMSSP_STATE *ntlmssp_state,
        DEBUG(10,("ntlmssp_seal_data: seal\n"));
        dump_data_pw("ntlmssp clear data\n", data, length);
        if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {
-               HMACMD5Context ctx;
-               char seq_num[4];
-               uchar digest[16];
-               SIVAL(seq_num, 0, ntlmssp_state->ntlmssp_seq_num);
-
-               hmac_md5_init_limK_to_64((const unsigned char *)(ntlmssp_state->send_sign_const), 16, &ctx);
-               hmac_md5_update((const unsigned char *)seq_num, 4, &ctx);
-               hmac_md5_update(data, length, &ctx);
-               hmac_md5_final(digest, &ctx);
-
-               if (!msrpc_gen(sig, "dBd", NTLMSSP_SIGN_VERSION, digest, 8 /* only copy first 8 bytes */
-                              , ntlmssp_state->ntlmssp_seq_num)) {
-                       return NT_STATUS_NO_MEMORY;
+               /* The order of these two operations matters - we must first seal the packet,
+                  then seal the sequence number - this is becouse the send_seal_hash is not
+                  constant, but is is rather updated with each iteration */
+               nt_status = ntlmssp_make_packet_signature(ntlmssp_state,
+                                                       data, length,
+                                                       whole_pdu, pdu_length,
+                                                       NTLMSSP_SEND, sig, False);
+               smb_arc4_crypt(ntlmssp_state->send_seal_arc4_state, data, length);
+               if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) {
+                       smb_arc4_crypt(ntlmssp_state->send_seal_arc4_state, sig->data+4, 8);
                }
-
-               dump_data_pw("ntlmssp client sealing hash:\n", 
-                            ntlmssp_state->send_seal_hash,
-                            sizeof(ntlmssp_state->send_seal_hash));
-               NTLMSSPcalc_ap(ntlmssp_state->send_seal_hash, data, length);
-               dump_data_pw("ntlmssp client signing hash:\n", 
-                            ntlmssp_state->send_sign_hash,
-                            sizeof(ntlmssp_state->send_sign_hash));
-               NTLMSSPcalc_ap(ntlmssp_state->send_sign_hash,  sig->data+4, sig->length-4);
        } else {
                uint32 crc;
                crc = crc32_calc_buffer((const char *)data, length);
-               if (!msrpc_gen(sig, "dddd", NTLMSSP_SIGN_VERSION, 0, crc, ntlmssp_state->ntlmssp_seq_num)) {
+               if (!msrpc_gen(sig, "dddd", NTLMSSP_SIGN_VERSION, 0, crc, ntlmssp_state->ntlmv1_seq_num)) {
                        return NT_STATUS_NO_MEMORY;
                }
 
                /* The order of these two operations matters - we must first seal the packet,
-                  then seal the sequence number - this is becouse the ntlmssp_hash is not
+                  then seal the sequence number - this is becouse the ntlmv1_arc4_state is not
                   constant, but is is rather updated with each iteration */
                
-               dump_data_pw("ntlmssp hash:\n", ntlmssp_state->ntlmssp_hash,
-                            sizeof(ntlmssp_state->ntlmssp_hash));
-               NTLMSSPcalc_ap(ntlmssp_state->ntlmssp_hash, data, length);
+               dump_data_pw("ntlmv1 arc4 state:\n", ntlmssp_state->ntlmv1_arc4_state,
+                            sizeof(ntlmssp_state->ntlmv1_arc4_state));
+               smb_arc4_crypt(ntlmssp_state->ntlmv1_arc4_state, data, length);
+
+               dump_data_pw("ntlmv1 arc4 state:\n", ntlmssp_state->ntlmv1_arc4_state,
+                            sizeof(ntlmssp_state->ntlmv1_arc4_state));
+
+               smb_arc4_crypt(ntlmssp_state->ntlmv1_arc4_state, sig->data+4, sig->length-4);
 
-               dump_data_pw("ntlmssp hash:\n", ntlmssp_state->ntlmssp_hash,
-                            sizeof(ntlmssp_state->ntlmssp_hash));
-               NTLMSSPcalc_ap(ntlmssp_state->ntlmssp_hash, sig->data+4, sig->length-4);
+               ntlmssp_state->ntlmv1_seq_num++;
+
+               nt_status = NT_STATUS_OK;
        }
+       dump_data_pw("ntlmssp signature\n", sig->data, sig->length);
        dump_data_pw("ntlmssp sealed data\n", data, length);
 
-       /* increment counter on send */
-       ntlmssp_state->ntlmssp_seq_num++;
-
        return NT_STATUS_OK;
 }
 
@@ -286,26 +298,27 @@ NTSTATUS ntlmssp_seal_packet(NTLMSSP_STATE *ntlmssp_state,
  */
 
 NTSTATUS ntlmssp_unseal_packet(NTLMSSP_STATE *ntlmssp_state,
-                                     uchar *data, size_t length,
-                                     DATA_BLOB *sig)
+                               uchar *data, size_t length,
+                               uchar *whole_pdu, size_t pdu_length,
+                               DATA_BLOB *sig)
 {
        if (!ntlmssp_state->session_key.length) {
                DEBUG(3, ("NO session key, cannot unseal packet\n"));
                return NT_STATUS_NO_USER_SESSION_KEY;
        }
 
-       DEBUG(10,("ntlmssp__unseal_data: seal\n"));
+       DEBUG(10,("ntlmssp_unseal_data: seal\n"));
        dump_data_pw("ntlmssp sealed data\n", data, length);
+
        if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {
-               NTLMSSPcalc_ap(ntlmssp_state->recv_seal_hash, data, length);
+               /* First unseal the data. */
+               smb_arc4_crypt(ntlmssp_state->recv_seal_arc4_state, data, length);
+               dump_data_pw("ntlmv2 clear data\n", data, length);
        } else {
-               dump_data_pw("ntlmssp hash:\n", ntlmssp_state->ntlmssp_hash,
-                            sizeof(ntlmssp_state->ntlmssp_hash));
-               NTLMSSPcalc_ap(ntlmssp_state->ntlmssp_hash, data, length);
+               smb_arc4_crypt(ntlmssp_state->ntlmv1_arc4_state, data, length);
+               dump_data_pw("ntlmv1 clear data\n", data, length);
        }
-       dump_data_pw("ntlmssp clear data\n", data, length);
-
-       return ntlmssp_check_packet(ntlmssp_state, data, length, sig);
+       return ntlmssp_check_packet(ntlmssp_state, data, length, whole_pdu, pdu_length, sig);
 }
 
 /**
@@ -326,6 +339,7 @@ NTSTATUS ntlmssp_sign_init(NTLMSSP_STATE *ntlmssp_state)
 
        if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2)
        {
+               DATA_BLOB weak_session_key = ntlmssp_state->session_key;
                const char *send_sign_const;
                const char *send_seal_const;
                const char *recv_sign_const;
@@ -352,62 +366,96 @@ NTSTATUS ntlmssp_sign_init(NTLMSSP_STATE *ntlmssp_state)
                        break;
                }
 
-               calc_ntlmv2_hash(ntlmssp_state->send_sign_hash, 
-                                ntlmssp_state->send_sign_const, 
-                                ntlmssp_state->session_key, send_sign_const);
-               dump_data_pw("NTLMSSP send sign hash:\n", 
-                            ntlmssp_state->send_sign_hash, 
-                            sizeof(ntlmssp_state->send_sign_hash));
-
-               calc_ntlmv2_hash(ntlmssp_state->send_seal_hash, 
-                                ntlmssp_state->send_seal_const, 
-                                ntlmssp_state->session_key, send_seal_const);
-               dump_data_pw("NTLMSSP send sesl hash:\n", 
-                            ntlmssp_state->send_seal_hash, 
-                            sizeof(ntlmssp_state->send_seal_hash));
-
-               calc_ntlmv2_hash(ntlmssp_state->recv_sign_hash, 
-                                ntlmssp_state->recv_sign_const, 
-                                ntlmssp_state->session_key, recv_sign_const);
-               dump_data_pw("NTLMSSP receive sign hash:\n", 
-                            ntlmssp_state->recv_sign_hash, 
-                            sizeof(ntlmssp_state->recv_sign_hash));
-
-               calc_ntlmv2_hash(ntlmssp_state->recv_seal_hash, 
-                                ntlmssp_state->recv_seal_const, 
-                                ntlmssp_state->session_key, recv_seal_const);
-               dump_data_pw("NTLMSSP receive seal hash:\n", 
-                            ntlmssp_state->recv_sign_hash, 
-                            sizeof(ntlmssp_state->recv_sign_hash));
-
-       } 
-       else if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_LM_KEY) {
-               if (!ntlmssp_state->session_key.data || ntlmssp_state->session_key.length < 8) {
-                       /* can't sign or check signatures yet */ 
-                       DEBUG(5, ("NTLMSSP Sign/Seal - cannot use LM KEY yet\n"));      
-                       return NT_STATUS_UNSUCCESSFUL;
+               /**
+                 Weaken NTLMSSP keys to cope with down-level clients, servers and export restrictions.
+                 We probably should have some parameters to control this, once we get NTLM2 working.
+               */
+
+               if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_128) {
+                       ;
+               } else if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_56) {
+                       weak_session_key.length = 6;
+               } else { /* forty bits */
+                       weak_session_key.length = 5;
                }
+
+               dump_data_pw("NTLMSSP weakend master key:\n",
+                               weak_session_key.data,
+                               weak_session_key.length);
+
+               /* SEND */
+               calc_ntlmv2_key(ntlmssp_state->send_sign_key,
+                               ntlmssp_state->session_key, send_sign_const);
+               dump_data_pw("NTLMSSP send sign key:\n",
+                               ntlmssp_state->send_sign_key, 16);
+
+               calc_ntlmv2_key(ntlmssp_state->send_seal_key,
+                               weak_session_key, send_seal_const);
+               dump_data_pw("NTLMSSP send seal key:\n",
+                               ntlmssp_state->send_seal_key, 16);
+
+               smb_arc4_init(ntlmssp_state->send_seal_arc4_state,
+                               ntlmssp_state->send_seal_key, 16);
+
+               dump_data_pw("NTLMSSP send seal arc4 state:\n", 
+                            ntlmssp_state->send_seal_arc4_state, 
+                            sizeof(ntlmssp_state->send_seal_arc4_state));
+
+               /* RECV */
+               calc_ntlmv2_key(ntlmssp_state->recv_sign_key,
+                               ntlmssp_state->session_key, recv_sign_const);
+               dump_data_pw("NTLMSSP recv send sign key:\n",
+                               ntlmssp_state->recv_sign_key, 16);
+
+               calc_ntlmv2_key(ntlmssp_state->recv_seal_key,
+                               weak_session_key, recv_seal_const);
                
-               DEBUG(5, ("NTLMSSP Sign/Seal - using LM KEY\n"));
+               dump_data_pw("NTLMSSP recv seal key:\n",
+                               ntlmssp_state->recv_seal_key, 16);
+                               
+               smb_arc4_init(ntlmssp_state->recv_seal_arc4_state,
+                               ntlmssp_state->recv_seal_key, 16);
+
+               dump_data_pw("NTLMSSP recv seal arc4 state:\n", 
+                            ntlmssp_state->recv_seal_arc4_state, 
+                            sizeof(ntlmssp_state->recv_seal_arc4_state));
+
+               ntlmssp_state->ntlm2_send_seq_num = 0;
+               ntlmssp_state->ntlm2_recv_seq_num = 0;
+
 
-               calc_hash(ntlmssp_state->ntlmssp_hash, ntlmssp_state->session_key.data, 8);
-               dump_data_pw("NTLMSSP hash:\n", ntlmssp_state->ntlmssp_hash,
-                            sizeof(ntlmssp_state->ntlmssp_hash));
        } else {
-               if (!ntlmssp_state->session_key.data || ntlmssp_state->session_key.length < 16) {
-                       /* can't sign or check signatures yet */ 
-                       DEBUG(5, ("NTLMSSP Sign/Seal - cannot use NT KEY yet\n"));
-                       return NT_STATUS_UNSUCCESSFUL;
+#if 0
+               /* Hmmm. Shouldn't we also weaken keys for ntlmv1 ? JRA. */
+
+               DATA_BLOB weak_session_key = ntlmssp_state->session_key;
+               /**
+                 Weaken NTLMSSP keys to cope with down-level clients, servers and export restrictions.
+                 We probably should have some parameters to control this, once we get NTLM2 working.
+               */
+
+               if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_128) {
+                       ;
+               } else if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_56) {
+                       weak_session_key.length = 6;
+               } else { /* forty bits */
+                       weak_session_key.length = 5;
                }
-               
-               DEBUG(5, ("NTLMSSP Sign/Seal - using NT KEY\n"));
+               dump_data_pw("NTLMSSP weakend master key:\n",
+                               weak_session_key.data,
+                               weak_session_key.length);
+#endif
 
-               calc_hash(ntlmssp_state->ntlmssp_hash, ntlmssp_state->session_key.data, 16);
-               dump_data_pw("NTLMSSP hash:\n", ntlmssp_state->ntlmssp_hash,
-                            sizeof(ntlmssp_state->ntlmssp_hash));
-       }
+               DEBUG(5, ("NTLMSSP Sign/Seal - using NTLM1\n"));
+
+               smb_arc4_init(ntlmssp_state->ntlmv1_arc4_state,
+                             ntlmssp_state->session_key.data, ntlmssp_state->session_key.length);
 
-       ntlmssp_state->ntlmssp_seq_num = 0;
+                dump_data_pw("NTLMv1 arc4 state:\n", ntlmssp_state->ntlmv1_arc4_state,
+                               sizeof(ntlmssp_state->ntlmv1_arc4_state));
+
+               ntlmssp_state->ntlmv1_seq_num = 0;
+       }
 
        return NT_STATUS_OK;
 }
index 8bce9c86a1e336460e62b414d6d9876e10f834b6..b104a4678d9a4fa6530625cf673684b64cc7fb94 100644 (file)
 #include "includes.h"
 
 /*************************************************************
-change a password on a remote machine using IPC calls
+ Change a password on a remote machine using IPC calls.
 *************************************************************/
+
 BOOL remote_password_change(const char *remote_machine, const char *user_name, 
                            const char *old_passwd, const char *new_passwd,
                            char *err_str, size_t err_str_len)
 {
        struct nmb_name calling, called;
        struct cli_state cli;
+       struct rpc_pipe_client *pipe_hnd;
        struct in_addr ip;
-       struct ntuser_creds creds;
 
        NTSTATUS result;
 
@@ -85,11 +86,9 @@ BOOL remote_password_change(const char *remote_machine, const char *user_name,
                        return False;
                }
 
-               init_creds(&creds, "", "", NULL);
-               cli_init_creds(&cli, &creds);
+               cli_init_creds(&cli, "", "", NULL);
        } else {
-               init_creds(&creds, user_name, "", old_passwd);
-               cli_init_creds(&cli, &creds);
+               cli_init_creds(&cli, user_name, "", old_passwd);
        }
 
        if (!cli_send_tconX(&cli, "IPC$", "IPC", "", 1)) {
@@ -99,14 +98,19 @@ BOOL remote_password_change(const char *remote_machine, const char *user_name,
                return False;
        }
 
-       /* Try not to give the password away to easily */
+       /* Try not to give the password away too easily */
 
-       cli.pipe_auth_flags = AUTH_PIPE_NTLMSSP;
-       cli.pipe_auth_flags |= AUTH_PIPE_SIGN;
-       cli.pipe_auth_flags |= AUTH_PIPE_SEAL;
-       
-       if ( !cli_nt_session_open( &cli, PI_SAMR ) ) {
+       pipe_hnd = cli_rpc_pipe_open_ntlmssp(&cli,
+                                               PI_SAMR,
+                                               PIPE_AUTH_LEVEL_PRIVACY,
+                                               "", /* what domain... ? */
+                                               user_name,
+                                               old_passwd,
+                                               &result);
+
+       if (!pipe_hnd) {
                if (lp_client_lanman_auth()) {
+                       /* Use the old RAP method. */
                        if (!cli_oem_change_password(&cli, user_name, new_passwd, old_passwd)) {
                                slprintf(err_str, err_str_len-1, "machine %s rejected the password change: Error was : %s.\n",
                                         remote_machine, cli_errstr(&cli) );
@@ -114,14 +118,16 @@ BOOL remote_password_change(const char *remote_machine, const char *user_name,
                                return False;
                        }
                } else {
-                       slprintf(err_str, err_str_len-1, "machine %s does not support SAMR connections, but LANMAN password changed are disabled\n",
-                                remote_machine);
+                       slprintf(err_str, err_str_len-1,
+                               "SAMR connection to machine %s failed. Error was %s, "
+                               "but LANMAN password changed are disabled\n",
+                               nt_errstr(result), remote_machine);
                        cli_shutdown(&cli);
                        return False;
                }
        }
 
-       if (NT_STATUS_IS_OK(result = cli_samr_chgpasswd_user(&cli, cli.mem_ctx, user_name, 
+       if (NT_STATUS_IS_OK(result = rpccli_samr_chgpasswd_user(pipe_hnd, cli.mem_ctx, user_name, 
                                                             new_passwd, old_passwd))) {
                /* Great - it all worked! */
                cli_shutdown(&cli);
@@ -138,25 +144,25 @@ BOOL remote_password_change(const char *remote_machine, const char *user_name,
        }
 
        /* OK, that failed, so try again... */
-       cli_nt_session_close(&cli);
+       cli_rpc_pipe_close(pipe_hnd);
        
        /* Try anonymous NTLMSSP... */
-       init_creds(&creds, "", "", NULL);
-       cli_init_creds(&cli, &creds);
+       cli_init_creds(&cli, "", "", NULL);
        
-       cli.pipe_auth_flags = 0;
-
        result = NT_STATUS_UNSUCCESSFUL;
        
-       /* OK, this is ugly, but... */
-       if ( cli_nt_session_open( &cli, PI_SAMR ) 
-            && NT_STATUS_IS_OK(result
-                               = cli_samr_chgpasswd_user(&cli, cli.mem_ctx, user_name, 
-                                                         new_passwd, old_passwd))) {
+       /* OK, this is ugly, but... try an anonymous pipe. */
+       pipe_hnd = cli_rpc_pipe_open_noauth(&cli, PI_SAMR, &result);
+
+       if ( pipe_hnd &&
+               (NT_STATUS_IS_OK(result = rpccli_samr_chgpasswd_user(pipe_hnd,
+                                               cli.mem_ctx,
+                                               user_name, 
+                                               new_passwd,
+                                               old_passwd)))) {
                /* Great - it all worked! */
                cli_shutdown(&cli);
                return True;
-
        } else {
                if (!(NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED) 
                      || NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL))) {
@@ -173,6 +179,7 @@ BOOL remote_password_change(const char *remote_machine, const char *user_name,
                   just might not support SAMR password changes, so fall back */
                
                if (lp_client_lanman_auth()) {
+                       /* Use the old RAP method. */
                        if (cli_oem_change_password(&cli, user_name, new_passwd, old_passwd)) {
                                /* SAMR failed, but the old LanMan protocol worked! */
 
@@ -185,9 +192,10 @@ BOOL remote_password_change(const char *remote_machine, const char *user_name,
                        cli_shutdown(&cli);
                        return False;
                } else {
-                       slprintf(err_str, err_str_len-1, 
-                                "machine %s does not support SAMR connections, but LANMAN password changed are disabled\n",
-                                remote_machine);
+                       slprintf(err_str, err_str_len-1,
+                               "SAMR connection to machine %s failed. Error was %s, "
+                               "but LANMAN password changed are disabled\n",
+                               nt_errstr(result), remote_machine);
                        cli_shutdown(&cli);
                        return False;
                }
index e010f226a02032e79859d2b09ebb1b374b0f2420..a0f3383e2970c38fc1c7200675508331df7db6ad 100644 (file)
@@ -60,4 +60,3 @@ void pwd_get_cleartext(struct pwd_info *pwd, fstring clr)
                clr[0] = 0;
 
 }
-
index 87a386307c1c245639bab6d38c2e2d477723cac4..7659d1cd6e8e492cc434d931842ef47a62dedaa3 100644 (file)
@@ -55,6 +55,12 @@ struct smbdb_ctx *smb_share_mode_db_open(const char *db_path)
        return smb_db;
 }
 
+/* key and data records in the tdb locking database */
+struct locking_key {
+        SMB_DEV_T dev;
+        SMB_INO_T inode;
+};
+
 int smb_share_mode_db_close(struct smbdb_ctx *db_ctx)
 {
        int ret = tdb_close(db_ctx->smb_tdb);
@@ -102,10 +108,10 @@ struct locking_data {
                        int num_share_mode_entries;
                        BOOL delete_on_close;
                } s;
-               share_mode_entry dummy; /* Needed for alignment. */
+               struct share_mode_entry dummy; /* Needed for alignment. */
        } u;
        /* the following two entries are implicit
-          share_mode_entry modes[num_share_mode_entries];
+          struct share_mode_entry modes[num_share_mode_entries];
           char file_name[];
        */
 };
@@ -114,9 +120,9 @@ struct locking_data {
  * Check if an external smb_share_mode_entry and an internal share_mode entry match.
  */
 
-static int share_mode_entry_equal(const struct smb_share_mode_entry *e_entry, const share_mode_entry *entry)
+static int share_mode_entry_equal(const struct smb_share_mode_entry *e_entry, const struct share_mode_entry *entry)
 {
-       return (e_entry->pid == entry->pid &&
+       return (procid_equal(&e_entry->pid, &entry->pid) &&
                e_entry->file_id == (uint32_t)entry->share_file_id &&
                e_entry->open_time.tv_sec == entry->time.tv_sec &&
                e_entry->open_time.tv_usec == entry->time.tv_usec &&
@@ -130,9 +136,9 @@ static int share_mode_entry_equal(const struct smb_share_mode_entry *e_entry, co
  * Create an internal Samba share_mode entry from an external smb_share_mode_entry.
  */
 
-static void create_share_mode_entry(share_mode_entry *out, const struct smb_share_mode_entry *in)
+static void create_share_mode_entry(struct share_mode_entry *out, const struct smb_share_mode_entry *in)
 {
-       memset(out, '\0', sizeof(share_mode_entry));
+       memset(out, '\0', sizeof(struct share_mode_entry));
 
        out->pid = in->pid;
        out->share_file_id = (unsigned long)in->file_id;
@@ -159,7 +165,7 @@ int smb_get_share_mode_entries(struct smbdb_ctx *db_ctx,
        struct smb_share_mode_entry *list = NULL;
        int num_share_modes = 0;
        struct locking_data *ld = NULL; /* internal samba db state. */
-       share_mode_entry *shares = NULL;
+       struct share_mode_entry *shares = NULL;
        size_t i;
        int list_num;
 
@@ -187,19 +193,24 @@ int smb_get_share_mode_entries(struct smbdb_ctx *db_ctx,
 
        memset(list, '\0', num_share_modes * sizeof(struct smb_share_mode_entry));
 
-       shares = (share_mode_entry *)(db_data.dptr + sizeof(share_mode_entry));
+       shares = (struct share_mode_entry *)(db_data.dptr + sizeof(struct share_mode_entry));
 
        list_num = 0;
        for (i = 0; i < num_share_modes; i++) {
-               share_mode_entry *share = &shares[i];
+               struct share_mode_entry *share = &shares[i];
                struct smb_share_mode_entry *sme = &list[list_num];
-               pid_t pid = share->pid;
+               struct process_id pid = share->pid;
 
                /* Check this process really exists. */
-               if (kill(pid, 0) == -1 && (errno == ESRCH)) {
+               if (kill(procid_to_pid(&pid), 0) == -1 && (errno == ESRCH)) {
                        continue; /* No longer exists. */
                }
 
+               /* Ignore deferred open entries. */
+               if (share->op_type == DEFERRED_OPEN_ENTRY) {
+                       continue;
+               }
+
                /* Copy into the external list. */
                sme->dev = (uint64_t)share->dev;
                sme->ino = (uint64_t)share->inode;
@@ -238,27 +249,27 @@ int smb_create_share_mode_entry(struct smbdb_ctx *db_ctx,
        TDB_DATA locking_key =  get_locking_key(dev, ino);
        int orig_num_share_modes = 0;
        struct locking_data *ld = NULL; /* internal samba db state. */
-       share_mode_entry *shares = NULL;
+       struct share_mode_entry *shares = NULL;
        char *new_data_p = NULL;
        size_t new_data_size = 0;
 
        db_data = tdb_fetch(db_ctx->smb_tdb, locking_key);
        if (!db_data.dptr) {
                /* We must create the entry. */
-               db_data.dptr = malloc((2*sizeof(share_mode_entry)) + strlen(filename) + 1);
+               db_data.dptr = malloc((2*sizeof(struct share_mode_entry)) + strlen(filename) + 1);
                if (!db_data.dptr) {
                        return -1;
                }
                ld = (struct locking_data *)db_data.dptr;
                ld->u.s.num_share_mode_entries = 1;
                ld->u.s.delete_on_close = 0;
-               shares = (share_mode_entry *)(db_data.dptr + sizeof(share_mode_entry));
+               shares = (struct share_mode_entry *)(db_data.dptr + sizeof(struct share_mode_entry));
                create_share_mode_entry(shares, new_entry);
-               memcpy(db_data.dptr + 2*sizeof(share_mode_entry),
+               memcpy(db_data.dptr + 2*sizeof(struct share_mode_entry),
                        filename,
                        strlen(filename) + 1);
 
-               db_data.dsize = 2*sizeof(share_mode_entry) + strlen(filename) + 1;
+               db_data.dsize = 2*sizeof(struct share_mode_entry) + strlen(filename) + 1;
                if (tdb_store(db_ctx->smb_tdb, locking_key, db_data, TDB_INSERT) == -1) {
                        free(db_data.dptr);
                        return -1;
@@ -268,7 +279,7 @@ int smb_create_share_mode_entry(struct smbdb_ctx *db_ctx,
        }
 
        /* Entry exists, we must add a new entry. */
-       new_data_p = malloc(db_data.dsize + sizeof(share_mode_entry));
+       new_data_p = malloc(db_data.dsize + sizeof(struct share_mode_entry));
        if (!new_data_p) {
                free(db_data.dptr);
                return -1;
@@ -278,11 +289,11 @@ int smb_create_share_mode_entry(struct smbdb_ctx *db_ctx,
        orig_num_share_modes = ld->u.s.num_share_mode_entries;
 
        /* Copy the original data. */
-       memcpy(new_data_p, db_data.dptr, (orig_num_share_modes+1)*sizeof(share_mode_entry));
+       memcpy(new_data_p, db_data.dptr, (orig_num_share_modes+1)*sizeof(struct share_mode_entry));
 
        /* Add in the new share mode */
-       shares = (share_mode_entry *)(new_data_p +
-                       ((orig_num_share_modes+1)*sizeof(share_mode_entry)));
+       shares = (struct share_mode_entry *)(new_data_p +
+                       ((orig_num_share_modes+1)*sizeof(struct share_mode_entry)));
 
        create_share_mode_entry(shares, new_entry);
 
@@ -290,11 +301,11 @@ int smb_create_share_mode_entry(struct smbdb_ctx *db_ctx,
        ld->u.s.num_share_mode_entries++;
 
        /* Append the original filename */
-       memcpy(new_data_p + ((ld->u.s.num_share_mode_entries+1)*sizeof(share_mode_entry)),
-               db_data.dptr + ((orig_num_share_modes+1)*sizeof(share_mode_entry)),
-               db_data.dsize - ((orig_num_share_modes+1) * sizeof(share_mode_entry)));
+       memcpy(new_data_p + ((ld->u.s.num_share_mode_entries+1)*sizeof(struct share_mode_entry)),
+               db_data.dptr + ((orig_num_share_modes+1)*sizeof(struct share_mode_entry)),
+               db_data.dsize - ((orig_num_share_modes+1) * sizeof(struct share_mode_entry)));
 
-       new_data_size = db_data.dsize + sizeof(share_mode_entry);
+       new_data_size = db_data.dsize + sizeof(struct share_mode_entry);
 
        free(db_data.dptr);
 
@@ -318,7 +329,7 @@ int smb_delete_share_mode_entry(struct smbdb_ctx *db_ctx,
        TDB_DATA locking_key =  get_locking_key(dev, ino);
        int orig_num_share_modes = 0;
        struct locking_data *ld = NULL; /* internal samba db state. */
-       share_mode_entry *shares = NULL;
+       struct share_mode_entry *shares = NULL;
        char *new_data_p = NULL;
        size_t filename_size = 0;
        size_t i, num_share_modes;
@@ -331,7 +342,7 @@ int smb_delete_share_mode_entry(struct smbdb_ctx *db_ctx,
 
        ld = (struct locking_data *)db_data.dptr;
        orig_num_share_modes = ld->u.s.num_share_mode_entries;
-       shares = (share_mode_entry *)(db_data.dptr + sizeof(share_mode_entry));
+       shares = (struct share_mode_entry *)(db_data.dptr + sizeof(struct share_mode_entry));
 
        if (orig_num_share_modes == 1) {
                /* Only one entry - better be ours... */
@@ -346,22 +357,22 @@ int smb_delete_share_mode_entry(struct smbdb_ctx *db_ctx,
        }
 
        /* More than one - allocate a new record minus the one we'll delete. */
-       new_data_p = malloc(db_data.dsize - sizeof(share_mode_entry));
+       new_data_p = malloc(db_data.dsize - sizeof(struct share_mode_entry));
        if (!new_data_p) {
                free(db_data.dptr);
                return -1;
        }
 
        /* Copy the header. */
-       memcpy(new_data_p, db_data.dptr, sizeof(share_mode_entry));
+       memcpy(new_data_p, db_data.dptr, sizeof(struct share_mode_entry));
 
        num_share_modes = 0;
        for (i = 0; i < orig_num_share_modes; i++) {
-               share_mode_entry *share = &shares[i];
-               pid_t pid = share->pid;
+               struct share_mode_entry *share = &shares[i];
+               struct process_id pid = share->pid;
 
                /* Check this process really exists. */
-               if (kill(pid, 0) == -1 && (errno == ESRCH)) {
+               if (kill(procid_to_pid(&pid), 0) == -1 && (errno == ESRCH)) {
                        continue; /* No longer exists. */
                }
 
@@ -369,8 +380,8 @@ int smb_delete_share_mode_entry(struct smbdb_ctx *db_ctx,
                        continue; /* This is our delete taget. */
                }
 
-               memcpy(new_data_p + ((num_share_modes+1)*sizeof(share_mode_entry)),
-                       share, sizeof(share_mode_entry) );
+               memcpy(new_data_p + ((num_share_modes+1)*sizeof(struct share_mode_entry)),
+                       share, sizeof(struct share_mode_entry) );
 
                num_share_modes++;
        }
@@ -383,10 +394,10 @@ int smb_delete_share_mode_entry(struct smbdb_ctx *db_ctx,
        }
 
        /* Copy the terminating filename. */
-       fname_ptr = db_data.dptr + ((orig_num_share_modes+1) * sizeof(share_mode_entry));
+       fname_ptr = db_data.dptr + ((orig_num_share_modes+1) * sizeof(struct share_mode_entry));
        filename_size = db_data.dsize - (fname_ptr - db_data.dptr);
 
-       memcpy(new_data_p + ((num_share_modes+1)*sizeof(share_mode_entry)),
+       memcpy(new_data_p + ((num_share_modes+1)*sizeof(struct share_mode_entry)),
                fname_ptr,
                filename_size);
 
@@ -398,7 +409,7 @@ int smb_delete_share_mode_entry(struct smbdb_ctx *db_ctx,
        ld = (struct locking_data *)db_data.dptr;
        ld->u.s.num_share_mode_entries = num_share_modes;
 
-       db_data.dsize = ((num_share_modes+1)*sizeof(share_mode_entry)) + filename_size;
+       db_data.dsize = ((num_share_modes+1)*sizeof(struct share_mode_entry)) + filename_size;
 
        if (tdb_store(db_ctx->smb_tdb, locking_key, db_data, TDB_REPLACE) == -1) {
                free(db_data.dptr);
@@ -418,7 +429,7 @@ int smb_change_share_mode_entry(struct smbdb_ctx *db_ctx,
        TDB_DATA locking_key =  get_locking_key(dev, ino);
        int num_share_modes = 0;
        struct locking_data *ld = NULL; /* internal samba db state. */
-       share_mode_entry *shares = NULL;
+       struct share_mode_entry *shares = NULL;
        size_t i;
        int found_entry = 0;
 
@@ -429,14 +440,14 @@ int smb_change_share_mode_entry(struct smbdb_ctx *db_ctx,
 
        ld = (struct locking_data *)db_data.dptr;
        num_share_modes = ld->u.s.num_share_mode_entries;
-       shares = (share_mode_entry *)(db_data.dptr + sizeof(share_mode_entry));
+       shares = (struct share_mode_entry *)(db_data.dptr + sizeof(struct share_mode_entry));
 
        for (i = 0; i < num_share_modes; i++) {
-               share_mode_entry *share = &shares[i];
-               pid_t pid = share->pid;
+               struct share_mode_entry *share = &shares[i];
+               struct process_id pid = share->pid;
 
                /* Check this process really exists. */
-               if (kill(pid, 0) == -1 && (errno == ESRCH)) {
+               if (kill(procid_to_pid(&pid), 0) == -1 && (errno == ESRCH)) {
                        continue; /* No longer exists. */
                }
 
index b7f0cd05c3308de80e554f23aaef0b3bc3ea79d9..dc49396d9e158ca9bf802d0fd52202b11aaf9407 100644 (file)
@@ -357,78 +357,24 @@ void cred_hash3(unsigned char *out, unsigned char *in, const unsigned char *key,
         des_crypt56(out + 8, in + 8, key2, forw);
 }
 
-void SamOEMhash( unsigned char *data, const unsigned char *key, int val)
-{
-       unsigned char s_box[256];
-       unsigned char index_i = 0;
-       unsigned char index_j = 0;
-       unsigned char j = 0;
-       int ind;
-
-       for (ind = 0; ind < 256; ind++) {
-               s_box[ind] = (unsigned char)ind;
-       }
-
-       for( ind = 0; ind < 256; ind++) {
-               unsigned char tc;
+/*****************************************************************
+ arc4 crypt/decrypt with a 16 byte key.
+*****************************************************************/
 
-               j += (s_box[ind] + key[ind%16]);
-
-               tc = s_box[ind];
-               s_box[ind] = s_box[j];
-               s_box[j] = tc;
-       }
-       for( ind = 0; ind < val; ind++) {
-               unsigned char tc;
-               unsigned char t;
-
-               index_i++;
-               index_j += s_box[index_i];
-
-               tc = s_box[index_i];
-               s_box[index_i] = s_box[index_j];
-               s_box[index_j] = tc;
+void SamOEMhash( unsigned char *data, const unsigned char key[16], size_t len)
+{
+       unsigned char arc4_state[258];
 
-               t = s_box[index_i] + s_box[index_j];
-               data[ind] = data[ind] ^ s_box[t];
-       }
+       smb_arc4_init(arc4_state, key, 16);
+       smb_arc4_crypt(arc4_state, data, len);
 }
 
-void SamOEMhashBlob( unsigned char *data, int len, DATA_BLOB *key)
+void SamOEMhashBlob( unsigned char *data, size_t len, DATA_BLOB *key)
 {
-       unsigned char s_box[256];
-       unsigned char index_i = 0;
-       unsigned char index_j = 0;
-       unsigned char j = 0;
-       int ind;
-
-       for (ind = 0; ind < 256; ind++) {
-               s_box[ind] = (unsigned char)ind;
-       }
-
-       for( ind = 0; ind < 256; ind++) {
-               unsigned char tc;
-
-               j += (s_box[ind] + key->data[ind%key->length]);
-
-               tc = s_box[ind];
-               s_box[ind] = s_box[j];
-               s_box[j] = tc;
-       }
-       for( ind = 0; ind < len; ind++) {
-               unsigned char tc;
-               unsigned char t;
-
-               index_i++;
-               index_j += s_box[index_i];
+       unsigned char arc4_state[258];
 
-               tc = s_box[index_i];
-               s_box[index_i] = s_box[index_j];
-               s_box[index_j] = tc;
-
-               t = s_box[index_i] + s_box[index_j];
-               data[ind] = data[ind] ^ s_box[t];
-       }
+       smb_arc4_init(arc4_state, key->data, key->length);
+       smb_arc4_crypt(arc4_state, data, len);
 }
 
 /* Decode a sam password hash into a password.  The password hash is the
index 8361c35a8e2bfb3b7392ab8631c0b79a103e2f54..0c9eacfe4c0eb1e4878a0de6478b399c6ac2fc23 100644 (file)
@@ -308,32 +308,6 @@ void SMBsesskeygen_ntv1(const uchar kr[16],
 #endif
 }
 
-void SMBsesskeygen_lmv1(const uchar lm_hash[16],
-                       const uchar lm_resp[24], /* only uses 8 */ 
-                       uint8 sess_key[16])
-{
-       /* Calculate the LM session key (effective length 40 bits,
-          but changes with each session) */
-
-       uchar p24[24];
-       uchar partial_lm_hash[16];
-       
-       memcpy(partial_lm_hash, lm_hash, 8);
-       memset(partial_lm_hash + 8, 0xbd, 8);    
-
-       SMBOWFencrypt(lm_hash, lm_resp, p24);
-       
-       memcpy(sess_key, p24, 16);
-       sess_key[5] = 0xe5;
-       sess_key[6] = 0x38;
-       sess_key[7] = 0xb0;
-
-#ifdef DEBUG_PASSWORD
-       DEBUG(100, ("SMBsesskeygen_lmv1:\n"));
-       dump_data(100, sess_key, 16);
-#endif
-}
-
 void SMBsesskeygen_lm_sess_key(const uchar lm_hash[16],
                        const uchar lm_resp[24], /* only uses 8 */ 
                        uint8 sess_key[16])
@@ -485,7 +459,7 @@ BOOL SMBNTLMv2encrypt(const char *user, const char *domain, const char *password
  encode a password buffer with a unicode password.  The buffer
  is filled with random data to make it harder to attack.
 ************************************************************/
-BOOL encode_pw_buffer(char buffer[516], const char *password, int string_flags)
+BOOL encode_pw_buffer(uint8 buffer[516], const char *password, int string_flags)
 {
        uchar new_pw[512];
        size_t new_pw_len;
@@ -496,7 +470,7 @@ BOOL encode_pw_buffer(char buffer[516], const char *password, int string_flags)
        
        memcpy(&buffer[512 - new_pw_len], new_pw, new_pw_len);
 
-       generate_random_buffer((unsigned char *)buffer, 512 - new_pw_len);
+       generate_random_buffer(buffer, 512 - new_pw_len);
 
        /* 
         * The length of the new password is in the last 4 bytes of
index a21063e52ac3371974d212cc4245ee61e73a636a..82a06bde2bcfbb2a3ab665bf684eb56b6b85b93b 100644 (file)
@@ -75,6 +75,7 @@ err_code_struct dos_msgs[] = {
   {"ERRlogonfailure",ERRlogonfailure,"Logon failure"},
   {"ERRdiskfull",ERRdiskfull,"Disk full"},
   {"ERRgeneral",ERRgeneral, "General failure"},
+  {"ERRbaddirectory", ERRbaddirectory, "Bad directory name"},
   {"ERRunknownlevel",ERRunknownlevel, "Unknown info level"},
   {NULL,-1,NULL}};
 
index 2eaec61ed792e3e7bed655b472a8db8fa869e1f7..2cf3480fce3a2156f2466e616bd87637636f6c85 100644 (file)
@@ -42,11 +42,11 @@ static BOOL read_negTokenInit(ASN1_DATA *asn1, negTokenInit_t *token)
                        asn1_start_tag(asn1, ASN1_CONTEXT(0));
                        asn1_start_tag(asn1, ASN1_SEQUENCE(0));
 
-                       token->mechTypes = SMB_MALLOC_P(char *);
+                       token->mechTypes = SMB_MALLOC_P(const char *);
                        for (i = 0; !asn1->has_error &&
                                     0 < asn1_tag_remaining(asn1); i++) {
                                token->mechTypes = 
-                                       SMB_REALLOC_ARRAY(token->mechTypes, char *, i + 2);
+                                       SMB_REALLOC_ARRAY(token->mechTypes, const char *, i + 2);
                                asn1_read_OID(asn1, &token->mechTypes[i]);
                        }
                        token->mechTypes[i] = NULL;
index aab0d7d151745887958fee39912b9169cfadb848..50fa613e72cd50839b5e46b65fcb55c478664ab2 100644 (file)
  Caller must have the cli connected to the netlogon pipe
  already.
 **********************************************************/
-static NTSTATUS just_change_the_password(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
+
+static NTSTATUS just_change_the_password(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, 
                                         unsigned char orig_trust_passwd_hash[16],
                                         unsigned char new_trust_passwd_hash[16],
                                         uint32 sec_channel_type)
 {
        NTSTATUS result;
 
-       /* ensure that schannel uses the right domain */
-       fstrcpy(cli->domain, lp_workgroup());
-       if (! NT_STATUS_IS_OK(result = cli_nt_establish_netlogon(cli, sec_channel_type, orig_trust_passwd_hash))) {
-               DEBUG(3,("just_change_the_password: unable to setup creds (%s)!\n",
-                        nt_errstr(result)));
-               return result;
+       /* Check if the netlogon pipe is open using schannel. If so we
+          already have valid creds. If not we must set them up. */
+
+       if (cli->auth.auth_type != PIPE_AUTH_TYPE_SCHANNEL) {
+               uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS;
+
+               result = rpccli_netlogon_setup_creds(cli, 
+                                       cli->cli->desthost,
+                                       lp_workgroup(),
+                                       global_myname(),
+                                       orig_trust_passwd_hash,
+                                       sec_channel_type,
+                                       &neg_flags);
+
+               if (!NT_STATUS_IS_OK(result)) {
+                       DEBUG(3,("just_change_the_password: unable to setup creds (%s)!\n",
+                                nt_errstr(result)));
+                       return result;
+               }
        }
-       
-       result = cli_net_srv_pwset(cli, mem_ctx, global_myname(), new_trust_passwd_hash);
+
+       result = rpccli_net_srv_pwset(cli, mem_ctx, global_myname(), new_trust_passwd_hash);
 
        if (!NT_STATUS_IS_OK(result)) {
                DEBUG(0,("just_change_the_password: unable to change password (%s)!\n",
@@ -59,7 +73,7 @@ static NTSTATUS just_change_the_password(struct cli_state *cli, TALLOC_CTX *mem_
  Caller must have already setup the connection to the NETLOGON pipe
 **********************************************************/
 
-NTSTATUS trust_pw_change_and_store_it(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
+NTSTATUS trust_pw_change_and_store_it(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, 
                                      const char *domain,
                                      unsigned char orig_trust_passwd_hash[16],
                                      uint32 sec_channel_type)
@@ -99,7 +113,7 @@ NTSTATUS trust_pw_change_and_store_it(struct cli_state *cli, TALLOC_CTX *mem_ctx
  already setup the connection to the NETLOGON pipe
 **********************************************************/
 
-NTSTATUS trust_pw_find_change_and_store_it(struct cli_state *cli, 
+NTSTATUS trust_pw_find_change_and_store_it(struct rpc_pipe_client *cli, 
                                           TALLOC_CTX *mem_ctx, 
                                           const char *domain) 
 {
@@ -116,7 +130,6 @@ NTSTATUS trust_pw_find_change_and_store_it(struct cli_state *cli,
        return trust_pw_change_and_store_it(cli, mem_ctx, domain,
                                            old_trust_passwd_hash,
                                            sec_channel_type);
-       
 }
 
 /*********************************************************************
@@ -133,6 +146,7 @@ BOOL enumerate_domain_trusts( TALLOC_CTX *mem_ctx, const char *domain,
        struct in_addr  dc_ip;
        uint32          enum_ctx = 0;
        struct cli_state *cli = NULL;
+       struct rpc_pipe_client *lsa_pipe;
        BOOL            retry;
 
        *domain_names = NULL;
@@ -156,21 +170,21 @@ BOOL enumerate_domain_trusts( TALLOC_CTX *mem_ctx, const char *domain,
 
        /* open the LSARPC_PIPE */
 
-       if ( !cli_nt_session_open( cli, PI_LSARPC ) ) {
-               result = NT_STATUS_UNSUCCESSFUL;
+       lsa_pipe = cli_rpc_pipe_open_noauth( cli, PI_LSARPC, &result );
+       if ( !lsa_pipe) {
                goto done;
        }
 
        /* get a handle */
 
-       result = cli_lsa_open_policy(cli, mem_ctx, True,
+       result = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, True,
                POLICY_VIEW_LOCAL_INFORMATION, &pol);
        if ( !NT_STATUS_IS_OK(result) )
                goto done;
 
        /* Lookup list of trusted domains */
 
-       result = cli_lsa_enum_trust_dom(cli, mem_ctx, &pol, &enum_ctx,
+       result = rpccli_lsa_enum_trust_dom(lsa_pipe, mem_ctx, &pol, &enum_ctx,
                num_domains, domain_names, sids);
        if ( !NT_STATUS_IS_OK(result) )
                goto done;
@@ -184,4 +198,3 @@ done:
 
        return NT_STATUS_IS_OK(result);
 }
-
index da7fc1e67d455a457a64dffb2c0ab84206164b8a..25a1ed5e2f6cad1fcc18e763a86358135fdf1fff 100644 (file)
@@ -39,7 +39,7 @@
 struct lock_context {
        uint16 smbpid;
        uint16 tid;
-       pid_t pid;
+       struct process_id pid;
 };
 
 /* The data in brlock records is an unsorted linear array of these
@@ -89,9 +89,9 @@ static TDB_DATA locking_key(SMB_DEV_T dev, SMB_INO_T inode)
 static BOOL brl_same_context(struct lock_context *ctx1, 
                             struct lock_context *ctx2)
 {
-       return (ctx1->pid == ctx2->pid) &&
+       return (procid_equal(&ctx1->pid, &ctx2->pid) &&
                (ctx1->smbpid == ctx2->smbpid) &&
-               (ctx1->tid == ctx2->tid);
+               (ctx1->tid == ctx2->tid));
 }
 
 /****************************************************************************
@@ -252,7 +252,7 @@ static int delete_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *stat
                        DEBUG(0,("brlock : delete_fn. LOGIC ERROR ! Shutting down and a record for my pid (%u) exists !\n",
                                        (unsigned int)lock->context.pid ));
 
-               } else if (process_exists(lock->context.pid)) {
+               } else if (process_exists(&lock->context.pid)) {
 
                        DEBUG(10,("brlock : delete_fn. pid %u exists.\n", (unsigned int)lock->context.pid ));
                        continue;
@@ -347,7 +347,7 @@ static int lock_compare(struct lock_struct *lck1,
 ****************************************************************************/
 
 NTSTATUS brl_lock(SMB_DEV_T dev, SMB_INO_T ino, int fnum,
-                 uint16 smbpid, pid_t pid, uint16 tid,
+                 uint16 smbpid, struct process_id pid, uint16 tid,
                  br_off start, br_off size, 
                  enum brl_type lock_type, BOOL *my_lock_ctx)
 {
@@ -450,7 +450,7 @@ static BOOL brl_pending_overlap(struct lock_struct *lock, struct lock_struct *pe
 ****************************************************************************/
 
 BOOL brl_unlock(SMB_DEV_T dev, SMB_INO_T ino, int fnum,
-               uint16 smbpid, pid_t pid, uint16 tid,
+               uint16 smbpid, struct process_id pid, uint16 tid,
                br_off start, br_off size,
                BOOL remove_pending_locks_only,
                void (*pre_unlock_fn)(void *),
@@ -542,8 +542,8 @@ BOOL brl_unlock(SMB_DEV_T dev, SMB_INO_T ino, int fnum,
 
                                        /* We could send specific lock info here... */
                                        if (brl_pending_overlap(lock, pend_lock)) {
-                                               DEBUG(10,("brl_unlock: sending unlock message to pid %u\n",
-                                                                       (unsigned int)pend_lock->context.pid ));
+                                               DEBUG(10,("brl_unlock: sending unlock message to pid %s\n",
+                                                                       procid_str_static(&pend_lock->context.pid )));
 
                                                message_send_pid(pend_lock->context.pid,
                                                                MSG_SMB_UNLOCK,
@@ -584,7 +584,7 @@ BOOL brl_unlock(SMB_DEV_T dev, SMB_INO_T ino, int fnum,
 ****************************************************************************/
 
 BOOL brl_locktest(SMB_DEV_T dev, SMB_INO_T ino, int fnum,
-                 uint16 smbpid, pid_t pid, uint16 tid,
+                 uint16 smbpid, struct process_id pid, uint16 tid,
                  br_off start, br_off size, 
                  enum brl_type lock_type)
 {
@@ -632,7 +632,7 @@ BOOL brl_locktest(SMB_DEV_T dev, SMB_INO_T ino, int fnum,
  Remove any locks associated with a open file.
 ****************************************************************************/
 
-void brl_close(SMB_DEV_T dev, SMB_INO_T ino, pid_t pid, int tid, int fnum)
+void brl_close(SMB_DEV_T dev, SMB_INO_T ino, struct process_id pid, int tid, int fnum)
 {
        TDB_DATA kbuf, dbuf;
        int count, i, j, dcount=0;
@@ -655,7 +655,7 @@ void brl_close(SMB_DEV_T dev, SMB_INO_T ino, pid_t pid, int tid, int fnum)
                struct lock_struct *lock = &locks[i];
 
                if (lock->context.tid == tid &&
-                   lock->context.pid == pid &&
+                   procid_equal(&lock->context.pid, &pid) &&
                    lock->fnum == fnum) {
 
                        /* Send unlock messages to any pending waiters that overlap. */
@@ -667,7 +667,7 @@ void brl_close(SMB_DEV_T dev, SMB_INO_T ino, pid_t pid, int tid, int fnum)
                                        continue;
 
                                if (pend_lock->context.tid == tid &&
-                                   pend_lock->context.pid == pid &&
+                                   procid_equal(&pend_lock->context.pid, &pid) &&
                                    pend_lock->fnum == fnum)
                                        continue;
 
index 5bcf7f2eda8ec480a6868259ba68f9781a63e142..e3131e26a2a4da688a5aabeae9a8655fe7e767aa 100644 (file)
@@ -43,7 +43,6 @@ uint16 global_smbpid;
 
 /* the locking database handle */
 static TDB_CONTEXT *tdb;
-static TDB_CONTEXT *deferred_open_tdb;
 
 struct locking_data {
         union {
@@ -51,10 +50,10 @@ struct locking_data {
                        int num_share_mode_entries;
                        BOOL delete_on_close;
                } s;
-                share_mode_entry dummy; /* Needed for alignment. */
+                struct share_mode_entry dummy; /* Needed for alignment. */
         } u;
         /* the following two entries are implicit
-           share_mode_entry modes[num_share_mode_entries];
+           struct share_mode_entry modes[num_share_mode_entries];
            char file_name[];
         */
 };
@@ -90,17 +89,18 @@ BOOL is_locked(files_struct *fsp,connection_struct *conn,
                if  (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && (lock_type == READ_LOCK || lock_type == WRITE_LOCK)) {
                        DEBUG(10,("is_locked: optimisation - exclusive oplock on file %s\n", fsp->fsp_name ));
                        ret = 0;
-               } else if (LEVEL_II_OPLOCK_TYPE(fsp->oplock_type) && (lock_type == READ_LOCK)) {
+               } else if ((fsp->oplock_type == LEVEL_II_OPLOCK) &&
+                          (lock_type == READ_LOCK)) {
                        DEBUG(10,("is_locked: optimisation - level II oplock on file %s\n", fsp->fsp_name ));
                        ret = 0;
                } else {
                        ret = !brl_locktest(fsp->dev, fsp->inode, fsp->fnum,
-                                    global_smbpid, sys_getpid(), conn->cnum, 
+                                    global_smbpid, procid_self(), conn->cnum, 
                                     offset, count, lock_type);
                }
        } else {
                ret = !brl_locktest(fsp->dev, fsp->inode, fsp->fnum,
-                               global_smbpid, sys_getpid(), conn->cnum,
+                               global_smbpid, procid_self(), conn->cnum,
                                offset, count, lock_type);
        }
 
@@ -143,7 +143,7 @@ static NTSTATUS do_lock(files_struct *fsp,connection_struct *conn, uint16 lock_p
 
        if (OPEN_FSP(fsp) && fsp->can_lock && (fsp->conn == conn)) {
                status = brl_lock(fsp->dev, fsp->inode, fsp->fnum,
-                                 lock_pid, sys_getpid(), conn->cnum, 
+                                 lock_pid, procid_self(), conn->cnum, 
                                  offset, count, 
                                  lock_type, my_lock_ctx);
 
@@ -166,7 +166,7 @@ static NTSTATUS do_lock(files_struct *fsp,connection_struct *conn, uint16 lock_p
                                 * lock entry.
                                 */
                                (void)brl_unlock(fsp->dev, fsp->inode, fsp->fnum,
-                                                               lock_pid, sys_getpid(), conn->cnum, 
+                                                               lock_pid, procid_self(), conn->cnum, 
                                                                offset, count, False,
                                                                NULL, NULL);
                        }
@@ -264,7 +264,7 @@ NTSTATUS do_unlock(files_struct *fsp,connection_struct *conn, uint16 lock_pid,
        posix_data.count = count;
 
        ok = brl_unlock(fsp->dev, fsp->inode, fsp->fnum,
-                       lock_pid, sys_getpid(), conn->cnum, offset, count,
+                       lock_pid, procid_self(), conn->cnum, offset, count,
                        False, posix_unlock, (void *)&posix_data);
    
        if (!ok) {
@@ -280,7 +280,7 @@ NTSTATUS do_unlock(files_struct *fsp,connection_struct *conn, uint16 lock_pid,
 
 void locking_close_file(files_struct *fsp)
 {
-       pid_t pid = sys_getpid();
+       struct process_id pid = procid_self();
 
        if (!lp_locking(SNUM(fsp->conn)))
                return;
@@ -324,20 +324,6 @@ BOOL locking_init(int read_only)
                return False;
        }
 
-       if (!read_only && !deferred_open_tdb) {
-               deferred_open_tdb = tdb_open_log(lock_path("deferred_open.tdb"), 
-                      0, TDB_DEFAULT|TDB_CLEAR_IF_FIRST, 
-                      O_RDWR|O_CREAT,
-                      0644);
-
-               if (!deferred_open_tdb) {
-                       DEBUG(0,("ERROR: Failed to initialise deferred open database\n"));
-                       tdb_close(tdb);
-                       tdb = NULL;
-                       return False;
-               }
-       }
-
        if (!posix_locking_init(read_only))
                return False;
 
@@ -360,11 +346,6 @@ BOOL locking_end(void)
                        ret = False;
        }
 
-       if (deferred_open_tdb) {
-               if (tdb_close(deferred_open_tdb) != 0)
-                       ret = False;
-       }
-               
        return ret;
 }
 
@@ -372,6 +353,16 @@ BOOL locking_end(void)
  Form a static locking key for a dev/inode pair.
 ******************************************************************/
 
+/* key and data records in the tdb locking database */
+struct locking_key {
+       SMB_DEV_T dev;
+       SMB_INO_T ino;
+};
+
+/*******************************************************************
+ Form a static locking key for a dev/inode pair.
+******************************************************************/
+
 static TDB_DATA locking_key(SMB_DEV_T dev, SMB_INO_T inode)
 {
        static struct locking_key key;
@@ -379,70 +370,27 @@ static TDB_DATA locking_key(SMB_DEV_T dev, SMB_INO_T inode)
 
        memset(&key, '\0', sizeof(key));
        key.dev = dev;
-       key.inode = inode;
+       key.ino = inode;
        kbuf.dptr = (char *)&key;
        kbuf.dsize = sizeof(key);
        return kbuf;
 }
 
-static TDB_DATA locking_key_fsp(files_struct *fsp)
-{
-       return locking_key(fsp->dev, fsp->inode);
-}
-
-/*******************************************************************
- Lock a hash bucket entry.
-******************************************************************/
-
-BOOL lock_share_entry(connection_struct *conn,
-                     SMB_DEV_T dev, SMB_INO_T inode)
-{
-       return tdb_chainlock(tdb, locking_key(dev, inode)) == 0;
-}
-
-/*******************************************************************
- Unlock a hash bucket entry.
-******************************************************************/
-
-void unlock_share_entry(connection_struct *conn,
-                       SMB_DEV_T dev, SMB_INO_T inode)
-{
-       tdb_chainunlock(tdb, locking_key(dev, inode));
-}
-
-/*******************************************************************
- Lock a hash bucket entry. use a fsp for convenience
-******************************************************************/
-
-BOOL lock_share_entry_fsp(files_struct *fsp)
-{
-       return tdb_chainlock(tdb, locking_key(fsp->dev, fsp->inode)) == 0;
-}
-
-/*******************************************************************
- Unlock a hash bucket entry.
-******************************************************************/
-
-void unlock_share_entry_fsp(files_struct *fsp)
-{
-       tdb_chainunlock(tdb, locking_key(fsp->dev, fsp->inode));
-}
-
 /*******************************************************************
  Print out a share mode.
 ********************************************************************/
 
-char *share_mode_str(int num, share_mode_entry *e)
+char *share_mode_str(int num, struct share_mode_entry *e)
 {
        static pstring share_str;
 
        slprintf(share_str, sizeof(share_str)-1, "share_mode_entry[%d]: "
-                "pid = %lu, share_access = 0x%x, private_options = 0x%x, "
-                "access_mask = 0x%x, port = 0x%x, type= 0x%x, file_id = %lu, "
+                "pid = %s, share_access = 0x%x, private_options = 0x%x, "
+                "access_mask = 0x%x, mid = 0x%x, type= 0x%x, file_id = %lu, "
                 "dev = 0x%x, inode = %.0f",
-                num, (unsigned long)e->pid,
+                num, procid_str_static(&e->pid),
                 e->share_access, e->private_options,
-                e->access_mask, e->op_port, e->op_type, e->share_file_id,
+                e->access_mask, e->op_mid, e->op_type, e->share_file_id,
                 (unsigned int)e->dev, (double)e->inode );
 
        return share_str;
@@ -455,12 +403,14 @@ char *share_mode_str(int num, share_mode_entry *e)
 static void print_share_mode_table(struct locking_data *data)
 {
        int num_share_modes = data->u.s.num_share_mode_entries;
-       share_mode_entry *shares = (share_mode_entry *)(data + 1);
+       struct share_mode_entry *shares =
+               (struct share_mode_entry *)(data + 1);
        int i;
 
        for (i = 0; i < num_share_modes; i++) {
-               share_mode_entry *entry_p = &shares[i];
-               DEBUG(10,("print_share_mode_table: %s\n", share_mode_str(i, entry_p) ));
+               struct share_mode_entry *entry_p = &shares[i];
+               DEBUG(10,("print_share_mode_table: %s\n",
+                         share_mode_str(i, entry_p)));
        }
 }
 
@@ -468,825 +418,581 @@ static void print_share_mode_table(struct locking_data *data)
  Get all share mode entries for a dev/inode pair.
 ********************************************************************/
 
-int get_share_modes(SMB_DEV_T dev, SMB_INO_T inode, 
-                   share_mode_entry **pp_shares,
-                   BOOL *delete_on_close)
+static BOOL parse_share_modes(TDB_DATA dbuf, struct share_mode_lock *lck)
 {
-       TDB_DATA dbuf;
        struct locking_data *data;
-       int num_share_modes;
-       share_mode_entry *shares = NULL;
-       TDB_DATA key = locking_key(dev, inode);
-       *pp_shares = NULL;
-       *delete_on_close = False;
-
-       dbuf = tdb_fetch(tdb, key);
-       if (!dbuf.dptr)
-               return 0;
-
-       data = (struct locking_data *)dbuf.dptr;
+       int i;
 
-       *delete_on_close = data->u.s.delete_on_close;
-       DEBUG(10, ("get_share_modes: delete_on_close: %d\n",
-                  *delete_on_close));
-       num_share_modes = data->u.s.num_share_mode_entries;
-       if(num_share_modes) {
-               pstring fname;
-               int i;
-               int del_count = 0;
-
-               shares = (share_mode_entry *)memdup(dbuf.dptr + sizeof(*data),  
-                                               num_share_modes * sizeof(share_mode_entry));
-
-               if (!shares) {
-                       SAFE_FREE(dbuf.dptr);
-                       return 0;
-               }
+       if (dbuf.dsize < sizeof(struct locking_data)) {
+               DEBUG(0, ("parse_share_modes: buffer too short\n"));
+               return False;
+       }
 
-               /* Save off the associated filename. */
-               pstrcpy(fname, dbuf.dptr + sizeof(*data) + num_share_modes * sizeof(share_mode_entry));
+       data = (struct locking_data *)dbuf.dptr;
 
-               /*
-                * Ensure that each entry has a real process attached.
-                */
+       lck->delete_on_close = data->u.s.delete_on_close;
+       lck->num_share_modes = data->u.s.num_share_mode_entries;
 
-               for (i = 0; i < num_share_modes; ) {
-                       share_mode_entry *entry_p = &shares[i];
-                       if (process_exists(entry_p->pid)) {
-                               DEBUG(10,("get_share_modes: %s\n", share_mode_str(i, entry_p) ));
-                               i++;
-                       } else {
-                               DEBUG(10,("get_share_modes: deleted %s\n", share_mode_str(i, entry_p) ));
-                               if (num_share_modes - i - 1 > 0) {
-                                       memcpy( &shares[i], &shares[i+1],
-                                               sizeof(share_mode_entry) * (num_share_modes - i - 1));
-                               }
-                               num_share_modes--;
-                               del_count++;
-                       }
-               }
+       DEBUG(10, ("parse_share_modes: delete_on_close: %d, "
+                  "num_share_modes: %d\n", lck->delete_on_close,
+                  lck->num_share_modes));
 
-               /* Did we delete any ? If so, re-store in tdb. */
-               if (del_count) {
-                       data->u.s.num_share_mode_entries = num_share_modes;
-                       
-                       if (num_share_modes) {
-                               memcpy(dbuf.dptr + sizeof(*data), shares,
-                                               num_share_modes * sizeof(share_mode_entry));
-                               /* Append the filename. */
-                               pstrcpy(dbuf.dptr + sizeof(*data) + num_share_modes * sizeof(share_mode_entry), fname);
-                       }
-
-                       /* The record has shrunk a bit */
-                       dbuf.dsize -= del_count * sizeof(share_mode_entry);
-
-                       if (data->u.s.num_share_mode_entries == 0) {
-                               if (tdb_delete(tdb, key) == -1) {
-                                       SAFE_FREE(shares);
-                                       SAFE_FREE(dbuf.dptr);
-                                       return 0;
-                               }
-                       } else {
-                               if (tdb_store(tdb, key, dbuf, TDB_REPLACE) == -1) {
-                                       SAFE_FREE(shares);
-                                       SAFE_FREE(dbuf.dptr);
-                                       return 0;
-                               }
-                       }
-               }
+       if ((lck->num_share_modes < 0) || (lck->num_share_modes > 1000000)) {
+               DEBUG(0, ("invalid number of share modes: %d\n",
+                         lck->num_share_modes));
+               return False;
        }
 
-       SAFE_FREE(dbuf.dptr);
-       *pp_shares = shares;
-       return num_share_modes;
-}
+       lck->share_modes = NULL;
 
-BOOL get_delete_on_close_flag(SMB_DEV_T dev, SMB_INO_T inode)
-{
-       share_mode_entry *shares;
-       BOOL result;
-       get_share_modes(dev, inode, &shares, &result);
-       SAFE_FREE(shares);
-       return result;
-}
+       if (lck->num_share_modes != 0) {
 
-/*******************************************************************
- Fill a share mode entry.
-********************************************************************/
+               if (dbuf.dsize < (sizeof(struct locking_data) +
+                                 (lck->num_share_modes *
+                                  sizeof(struct share_mode_entry)))) {
+                       DEBUG(0, ("parse_share_modes: buffer too short\n"));
+                       return False;
+               }
+                                 
+               lck->share_modes = talloc_memdup(lck, dbuf.dptr+sizeof(*data),
+                                                lck->num_share_modes *
+                                                sizeof(struct share_mode_entry));
 
-static void fill_share_mode(char *p, files_struct *fsp, uint16 port, uint16 op_type)
-{
-       share_mode_entry *e = (share_mode_entry *)p;
-       void *x = &e->time; /* Needed to force alignment. p may not be aligned.... */
+               if (lck->share_modes == NULL) {
+                       DEBUG(0, ("talloc failed\n"));
+                       return False;
+               }
+       }
 
-       memset(e, '\0', sizeof(share_mode_entry));
-       e->pid = sys_getpid();
-       e->share_access = fsp->share_access;
-       e->private_options = fsp->fh->private_options;
-       e->access_mask = fsp->access_mask;
-       e->op_port = port;
-       e->op_type = op_type;
-       memcpy(x, &fsp->open_time, sizeof(struct timeval));
-       e->share_file_id = fsp->file_id;
-       e->dev = fsp->dev;
-       e->inode = fsp->inode;
-}
+       /* Save off the associated filename. */
+       lck->filename = talloc_strdup(lck, dbuf.dptr + sizeof(*data) +
+                                     lck->num_share_modes *
+                                     sizeof(struct share_mode_entry));
 
-/*******************************************************************
- Check if two share mode entries are identical, ignoring oplock 
- and port info and desired_access.
-********************************************************************/
+       /*
+        * Ensure that each entry has a real process attached.
+        */
 
-BOOL share_modes_identical( share_mode_entry *e1, share_mode_entry *e2)
-{
-#if 1 /* JRA PARANOIA TEST - REMOVE LATER */
-       if (e1->pid == e2->pid &&
-               e1->share_file_id == e2->share_file_id &&
-               e1->dev == e2->dev &&
-               e1->inode == e2->inode &&
-               (e1->share_access) != (e2->share_access)) {
-                       DEBUG(0,("PANIC: share_modes_identical: share_mode "
-                                "mismatch (e1 = 0x%x, e2 = 0x%x). Logic error.\n",
-                                (unsigned int)e1->share_access,
-                                (unsigned int)e2->share_access ));
-               smb_panic("PANIC: share_modes_identical logic error.\n");
+       for (i = 0; i < lck->num_share_modes; i++) {
+               struct share_mode_entry *entry_p = &lck->share_modes[i];
+               DEBUG(10,("parse_share_modes: %s\n",
+                         share_mode_str(i, entry_p) ));
+               if (!process_exists(entry_p->pid)) {
+                       DEBUG(10,("parse_share_modes: deleted %s\n",
+                                 share_mode_str(i, entry_p) ));
+                       entry_p->op_type = UNUSED_SHARE_MODE_ENTRY;
+                       lck->modified = True;
+               }
        }
-#endif
 
-       return (e1->pid == e2->pid &&
-               (e1->share_access) == (e2->share_access) &&
-               e1->dev == e2->dev &&
-               e1->inode == e2->inode &&
-               e1->share_file_id == e2->share_file_id );
+       return True;
 }
 
-/*******************************************************************
- Delete a specific share mode. Return the number
- of entries left, and a memdup'ed copy of the entry deleted (if required).
- Ignore if no entry deleted.
-********************************************************************/
-
-ssize_t del_share_entry(SMB_DEV_T dev, SMB_INO_T inode,
-                       share_mode_entry *entry, share_mode_entry **ppse,
-                       BOOL *delete_on_close)
+static TDB_DATA unparse_share_modes(struct share_mode_lock *lck)
 {
-       TDB_DATA dbuf;
+       TDB_DATA result;
+       int num_valid = 0;
+       int i;
        struct locking_data *data;
-       int i, del_count=0;
-       share_mode_entry *shares;
-       ssize_t count = 0;
-       TDB_DATA key = locking_key(dev, inode);
-
-       if (ppse)
-               *ppse = NULL;
-
-       /* read in the existing share modes */
-       dbuf = tdb_fetch(tdb, key);
-       if (!dbuf.dptr)
-               return -1;
-
-       data = (struct locking_data *)dbuf.dptr;
-       *delete_on_close = data->u.s.delete_on_close;
-       shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data));
-
-       /*
-        * Find any with this pid and delete it
-        * by overwriting with the rest of the data 
-        * from the record.
-        */
-
-       DEBUG(10,("del_share_entry: num_share_modes = %d\n", data->u.s.num_share_mode_entries ));
-
-       for (i=0;i<data->u.s.num_share_mode_entries;) {
-               if (share_modes_identical(&shares[i], entry)) {
-                       DEBUG(10,("del_share_entry: deleted %s\n",
-                               share_mode_str(i, &shares[i]) ));
-                       if (ppse)
-                               *ppse = memdup(&shares[i], sizeof(*shares));
-                       data->u.s.num_share_mode_entries--;
-                       if ((dbuf.dsize - (sizeof(*data) + (i+1)*sizeof(*shares))) > 0) {
-                               memmove(&shares[i], &shares[i+1], 
-                                       dbuf.dsize - (sizeof(*data) + (i+1)*sizeof(*shares)));
-                       }
-                       del_count++;
+       ssize_t offset;
 
-                       DEBUG(10,("del_share_entry: deleting entry %d\n", i ));
+       result.dptr = NULL;
+       result.dsize = 0;
 
-               } else {
-                       i++;
+       for (i=0; i<lck->num_share_modes; i++) {
+               if (!is_unused_share_mode_entry(&lck->share_modes[i])) {
+                       num_valid += 1;
                }
        }
 
-       if (del_count) {
-               /* the record may have shrunk a bit */
-               dbuf.dsize -= del_count * sizeof(*shares);
-
-               count = (ssize_t)data->u.s.num_share_mode_entries;
-
-               /* store it back in the database */
-               if (data->u.s.num_share_mode_entries == 0) {
-                       if (tdb_delete(tdb, key) == -1)
-                               count = -1;
-               } else {
-                       if (tdb_store(tdb, key, dbuf, TDB_REPLACE) == -1)
-                               count = -1;
-               }
+       if (num_valid == 0) {
+               return result;
        }
-       DEBUG(10,("del_share_entry: Remaining table.\n"));
-       print_share_mode_table((struct locking_data *)dbuf.dptr);
-       SAFE_FREE(dbuf.dptr);
-       return count;
-}
 
-/*******************************************************************
- Del the share mode of a file for this process. Return the number
- of entries left, and a memdup'ed copy of the entry deleted.
-********************************************************************/
-
-ssize_t del_share_mode(files_struct *fsp, share_mode_entry **ppse,
-                      BOOL *delete_on_close)
-{
-       share_mode_entry entry;
+       result.dsize = sizeof(*data) +
+               lck->num_share_modes * sizeof(struct share_mode_entry) +
+               strlen(lck->filename) + 1;
+       result.dptr = talloc_size(lck, result.dsize);
 
-       /*
-        * Fake up a share_mode_entry for comparisons.
-        */
+       if (result.dptr == NULL) {
+               smb_panic("talloc failed\n");
+       }
 
-       fill_share_mode((char *)&entry, fsp, 0, 0);
-       return del_share_entry(fsp->dev, fsp->inode, &entry, ppse,
-                              delete_on_close);
+       data = (struct locking_data *)result.dptr;
+       ZERO_STRUCTP(data);
+       data->u.s.num_share_mode_entries = lck->num_share_modes;
+       data->u.s.delete_on_close = lck->delete_on_close;
+       DEBUG(10, ("unparse_share_modes: del: %d, num: %d\n",
+                  data->u.s.delete_on_close,
+                  data->u.s.num_share_mode_entries));
+       memcpy(result.dptr + sizeof(*data), lck->share_modes,
+              sizeof(struct share_mode_entry)*lck->num_share_modes);
+       offset = sizeof(*data) +
+               sizeof(struct share_mode_entry)*lck->num_share_modes;
+       safe_strcpy(result.dptr + offset, lck->filename,
+                   result.dsize - offset - 1);
+       print_share_mode_table(data);
+       return result;
 }
 
-/*******************************************************************
- Set the share mode of a file. Return False on fail, True on success.
-********************************************************************/
-
-BOOL set_share_mode(files_struct *fsp, uint16 port, uint16 op_type)
+static int share_mode_lock_destructor(void *p)
 {
-       TDB_DATA dbuf;
-       struct locking_data *data;
-       char *p=NULL;
-       int size;
-       TDB_DATA key = locking_key_fsp(fsp);
-       BOOL ret = True;
-               
-       /* read in the existing share modes if any */
-       dbuf = tdb_fetch(tdb, key);
-       if (!dbuf.dptr) {
-               size_t offset;
-               /* we'll need to create a new record */
-               pstring fname;
-
-               pstrcpy(fname, fsp->conn->connectpath);
-               pstrcat(fname, "/");
-               pstrcat(fname, fsp->fsp_name);
-
-               size = sizeof(*data) + sizeof(share_mode_entry) + strlen(fname) + 1;
-               p = (char *)SMB_MALLOC(size);
-               if (!p)
-                       return False;
-               data = (struct locking_data *)p;
-               ZERO_STRUCT(data->u); /* Keep valgrind happy */
-               data->u.s.num_share_mode_entries = 1;
-       
-               DEBUG(10,("set_share_mode: creating entry for file %s. num_share_modes = 1\n",
-                       fsp->fsp_name ));
+       struct share_mode_lock *lck =
+               talloc_get_type_abort(p, struct share_mode_lock);
+       TDB_DATA key = locking_key(lck->dev, lck->ino);
+       TDB_DATA data;
 
-               offset = sizeof(*data) + sizeof(share_mode_entry);
-               safe_strcpy(p + offset, fname, size - offset - 1);
-               fill_share_mode(p + sizeof(*data), fsp, port, op_type);
-               dbuf.dptr = p;
-               dbuf.dsize = size;
-               if (tdb_store(tdb, key, dbuf, TDB_REPLACE) == -1)
-                       ret = False;
+       if (!lck->modified) {
+               goto done;
+       }
 
-               print_share_mode_table((struct locking_data *)p);
+       data = unparse_share_modes(lck);
 
-               SAFE_FREE(p);
-               return ret;
+       if (data.dptr == NULL) {
+               if (!lck->fresh) {
+                       /* There has been an entry before, delete it */
+                       if (tdb_delete(tdb, key) == -1) {
+                               smb_panic("Could not delete share entry\n");
+                       }
+               }
+               goto done;
        }
 
-       /* we're adding to an existing entry - this is a bit fiddly */
-       data = (struct locking_data *)dbuf.dptr;
+       if (tdb_store(tdb, key, data, TDB_REPLACE) == -1) {
+               smb_panic("Could not store share mode entry\n");
+       }
 
-       data->u.s.num_share_mode_entries++;
-       
-       DEBUG(10,("set_share_mode: adding entry for file %s. new num_share_modes = %d\n",
-               fsp->fsp_name, data->u.s.num_share_mode_entries ));
+ done:
+       tdb_chainunlock(tdb, key);
 
-       size = dbuf.dsize + sizeof(share_mode_entry);
-       p = SMB_MALLOC(size);
-       if (!p) {
-               SAFE_FREE(dbuf.dptr);
-               return False;
-       }
-       memcpy(p, dbuf.dptr, sizeof(*data));
-       fill_share_mode(p + sizeof(*data), fsp, port, op_type);
-       memcpy(p + sizeof(*data) + sizeof(share_mode_entry), dbuf.dptr + sizeof(*data),
-              dbuf.dsize - sizeof(*data));
-       SAFE_FREE(dbuf.dptr);
-       dbuf.dptr = p;
-       dbuf.dsize = size;
-       if (tdb_store(tdb, key, dbuf, TDB_REPLACE) == -1)
-               ret = False;
-       print_share_mode_table((struct locking_data *)p);
-       SAFE_FREE(p);
-       return ret;
+       return 0;
 }
 
-/*******************************************************************
- A generic in-place modification call for share mode entries.
-********************************************************************/
-
-static BOOL mod_share_mode( SMB_DEV_T dev, SMB_INO_T inode, share_mode_entry *entry,
-                          void (*mod_fn)(share_mode_entry *, SMB_DEV_T, SMB_INO_T, void *),
-                          void *param)
+struct share_mode_lock *get_share_mode_lock(TALLOC_CTX *mem_ctx,
+                                           SMB_DEV_T dev, SMB_INO_T ino,
+                                           const char *fname)
 {
-       TDB_DATA dbuf;
-       struct locking_data *data;
-       int i;
-       share_mode_entry *shares;
-       BOOL need_store=False;
-       BOOL ret = True;
-       TDB_DATA key = locking_key(dev, inode);
-
-       /* read in the existing share modes */
-       dbuf = tdb_fetch(tdb, key);
-       if (!dbuf.dptr)
-               return False;
+       struct share_mode_lock *lck;
+       TDB_DATA key = locking_key(dev, ino);
+       TDB_DATA data;
 
-       data = (struct locking_data *)dbuf.dptr;
-       shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data));
+       lck = TALLOC_P(mem_ctx, struct share_mode_lock);
+       if (lck == NULL) {
+               DEBUG(0, ("talloc failed\n"));
+               return NULL;
+       }
 
-       /* find any with our pid and call the supplied function */
-       for (i=0;i<data->u.s.num_share_mode_entries;i++) {
-               if (share_modes_identical(entry, &shares[i])) {
-                       mod_fn(&shares[i], dev, inode, param);
-                       need_store=True;
-               }
+       lck->dev = dev;
+       lck->ino = ino;
+       lck->delete_on_close = False;
+       lck->num_share_modes = 0;
+       lck->share_modes = NULL;
+       lck->modified = False;
+
+       if (tdb_chainlock(tdb, key) != 0) {
+               DEBUG(3, ("Could not lock share entry\n"));
+               talloc_free(lck);
+               return NULL;
        }
 
-       /* if the mod fn was called then store it back */
-       if (need_store) {
-               if (data->u.s.num_share_mode_entries == 0) {
-                       if (tdb_delete(tdb, key) == -1)
-                               ret = False;
-               } else {
-                       if (tdb_store(tdb, key, dbuf, TDB_REPLACE) == -1)
-                               ret = False;
+       data = tdb_fetch(tdb, key);
+       lck->fresh = (data.dptr == NULL);
+
+       if (lck->fresh) {
+               if (fname == NULL) {
+                       DEBUG(0, ("New file, but no filename supplied\n"));
+                       talloc_free(lck);
+                       return NULL;
+               }
+               lck->filename = talloc_strdup(lck, fname);
+               if (lck->filename == NULL) {
+                       DEBUG(0, ("talloc failed\n"));
+                       talloc_free(lck);
+                       return NULL;
+               }
+       } else {
+               if (!parse_share_modes(data, lck)) {
+                       DEBUG(0, ("Could not parse share modes\n"));
+                       talloc_free(lck);
+                       SAFE_FREE(data.dptr);
+                       return NULL;
                }
        }
 
-       SAFE_FREE(dbuf.dptr);
-       return ret;
-}
+       talloc_set_destructor(lck, share_mode_lock_destructor);
+       SAFE_FREE(data.dptr);
 
-/*******************************************************************
- Static function that actually does the work for the generic function
- below.
-********************************************************************/
+       return lck;
+}
 
-static void remove_share_oplock_fn(share_mode_entry *entry, SMB_DEV_T dev, SMB_INO_T inode, 
-                                   void *param)
+BOOL get_delete_on_close_flag(SMB_DEV_T dev, SMB_INO_T inode,
+                             const char *fname)
 {
-       DEBUG(10,("remove_share_oplock_fn: removing oplock info for entry dev=%x ino=%.0f\n",
-                 (unsigned int)dev, (double)inode ));
-       /* Delete the oplock info. */
-       entry->op_port = 0;
-       entry->op_type = NO_OPLOCK;
+       BOOL result;
+       struct share_mode_lock *lck = get_share_mode_lock(NULL, dev, inode,
+                                                         fname);
+       result = lck->delete_on_close;
+       talloc_free(lck);
+       return result;
 }
 
-/*******************************************************************
- Remove an oplock port and mode entry from a share mode.
-********************************************************************/
-
-BOOL remove_share_oplock(files_struct *fsp)
+BOOL is_valid_share_mode_entry(const struct share_mode_entry *e)
 {
-       share_mode_entry entry;
-       /*
-        * Fake up an entry for comparisons...
-        */
-       fill_share_mode((char *)&entry, fsp, 0, 0);
-       return mod_share_mode(fsp->dev, fsp->inode, &entry, remove_share_oplock_fn, NULL);
+       int num_props = 0;
+
+       num_props += ((e->op_type == NO_OPLOCK) ? 1 : 0);
+       num_props += (EXCLUSIVE_OPLOCK_TYPE(e->op_type) ? 1 : 0);
+       num_props += (LEVEL_II_OPLOCK_TYPE(e->op_type) ? 1 : 0);
+
+       SMB_ASSERT(num_props <= 1);
+       return (num_props != 0);
 }
 
-/*******************************************************************
- Static function that actually does the work for the generic function
- below.
-********************************************************************/
+BOOL is_deferred_open_entry(const struct share_mode_entry *e)
+{
+       return (e->op_type == DEFERRED_OPEN_ENTRY);
+}
 
-static void downgrade_share_oplock_fn(share_mode_entry *entry, SMB_DEV_T dev, SMB_INO_T inode, 
-                                   void *param)
+BOOL is_unused_share_mode_entry(const struct share_mode_entry *e)
 {
-       DEBUG(10,("downgrade_share_oplock_fn: downgrading oplock info for entry dev=%x ino=%.0f\n",
-                 (unsigned int)dev, (double)inode ));
-       entry->op_type = LEVEL_II_OPLOCK;
+       return (e->op_type == UNUSED_SHARE_MODE_ENTRY);
 }
 
 /*******************************************************************
Downgrade a oplock type from exclusive to level II.
Fill a share mode entry.
 ********************************************************************/
 
-BOOL downgrade_share_oplock(files_struct *fsp)
+static void fill_share_mode_entry(struct share_mode_entry *e,
+                                 files_struct *fsp,
+                                 uint16 mid, uint16 op_type)
 {
-       share_mode_entry entry;
-       /*
-        * Fake up an entry for comparisons...
-        */
-       fill_share_mode((char *)&entry, fsp, 0, 0);
-       return mod_share_mode(fsp->dev, fsp->inode, &entry, downgrade_share_oplock_fn, NULL);
+       ZERO_STRUCTP(e);
+       e->pid = procid_self();
+       e->share_access = fsp->share_access;
+       e->private_options = fsp->fh->private_options;
+       e->access_mask = fsp->access_mask;
+       e->op_mid = mid;
+       e->op_type = op_type;
+       e->time.tv_sec = fsp->open_time.tv_sec;
+       e->time.tv_usec = fsp->open_time.tv_usec;
+       e->share_file_id = fsp->file_id;
+       e->dev = fsp->dev;
+       e->inode = fsp->inode;
 }
 
-/*******************************************************************
- Get/Set the delete on close flag in a set of share modes.
- Return False on fail, True on success.
-********************************************************************/
-
-BOOL modify_delete_flag( SMB_DEV_T dev, SMB_INO_T inode, BOOL delete_on_close)
+static void fill_deferred_open_entry(struct share_mode_entry *e,
+                                    const struct timeval request_time,
+                                    SMB_DEV_T dev, SMB_INO_T ino, uint16 mid)
 {
-       TDB_DATA dbuf;
-       struct locking_data *data;
-       BOOL res;
-       TDB_DATA key = locking_key(dev, inode);
+       ZERO_STRUCTP(e);
+       e->pid = procid_self();
+       e->op_mid = mid;
+       e->op_type = DEFERRED_OPEN_ENTRY;
+       e->time.tv_sec = request_time.tv_sec;
+       e->time.tv_usec = request_time.tv_usec;
+       e->dev = dev;
+       e->inode = ino;
+}
 
-       /* read in the existing share modes */
-       dbuf = tdb_fetch(tdb, key);
-       if (!dbuf.dptr)
-               return False;
+static void add_share_mode_entry(struct share_mode_lock *lck,
+                                const struct share_mode_entry *entry)
+{
+       int i;
 
-       data = (struct locking_data *)dbuf.dptr;
+       for (i=0; i<lck->num_share_modes; i++) {
+               struct share_mode_entry *e = &lck->share_modes[i];
+               if (is_unused_share_mode_entry(e)) {
+                       *e = *entry;
+                       break;
+               }
+       }
 
-       /* Set/Unset the delete on close element. */
-       data->u.s.delete_on_close = delete_on_close;
+       if (i == lck->num_share_modes) {
+               /* No unused entry found */
+               ADD_TO_ARRAY(lck, struct share_mode_entry, *entry,
+                            &lck->share_modes, &lck->num_share_modes);
+       }
+       lck->modified = True;
+}
 
-       res = (tdb_store(tdb, key, dbuf, TDB_REPLACE)!=-1);
+void set_share_mode(struct share_mode_lock *lck, files_struct *fsp,
+                   uint16 mid, uint16 op_type)
+{
+       struct share_mode_entry entry;
+       fill_share_mode_entry(&entry, fsp, mid, op_type);
+       add_share_mode_entry(lck, &entry);
+}
 
-       SAFE_FREE(dbuf.dptr);
-       return res;
+void add_deferred_open(struct share_mode_lock *lck, uint16 mid,
+                      struct timeval request_time,
+                      SMB_DEV_T dev, SMB_INO_T ino)
+{
+       struct share_mode_entry entry;
+       fill_deferred_open_entry(&entry, request_time, dev, ino, mid);
+       add_share_mode_entry(lck, &entry);
 }
 
 /*******************************************************************
- Print out a deferred open entry.
+ Check if two share mode entries are identical, ignoring oplock 
+ and mid info and desired_access.
 ********************************************************************/
 
-char *deferred_open_str(int num, deferred_open_entry *e)
+static BOOL share_modes_identical(struct share_mode_entry *e1,
+                                 struct share_mode_entry *e2)
 {
-       static pstring de_str;
-
-       slprintf(de_str, sizeof(de_str)-1, "deferred_open_entry[%d]: \
-pid = %lu, mid = %u, dev = 0x%x, inode = %.0f, port = %u, time = [%u.%06u]",
-               num, (unsigned long)e->pid, (unsigned int)e->mid, (unsigned int)e->dev, (double)e->inode,
-               (unsigned int)e->port,
-               (unsigned int)e->time.tv_sec, (unsigned int)e->time.tv_usec );
+#if 1 /* JRA PARANOIA TEST - REMOVE LATER */
+       if (procid_equal(&e1->pid, &e2->pid) &&
+           e1->share_file_id == e2->share_file_id &&
+           e1->dev == e2->dev &&
+           e1->inode == e2->inode &&
+           (e1->share_access) != (e2->share_access)) {
+               DEBUG(0,("PANIC: share_modes_identical: share_mode "
+                        "mismatch (e1 = 0x%x, e2 = 0x%x). Logic error.\n",
+                        (unsigned int)e1->share_access,
+                        (unsigned int)e2->share_access ));
+               smb_panic("PANIC: share_modes_identical logic error.\n");
+       }
+#endif
 
-       return de_str;
+       return (procid_equal(&e1->pid, &e2->pid) &&
+               (e1->share_access) == (e2->share_access) &&
+               e1->dev == e2->dev &&
+               e1->inode == e2->inode &&
+               e1->share_file_id == e2->share_file_id );
 }
 
-/* Internal data structures for deferred opens... */
+static BOOL deferred_open_identical(struct share_mode_entry *e1,
+                                   struct share_mode_entry *e2)
+{
+       return (procid_equal(&e1->pid, &e2->pid) &&
+               (e1->op_mid == e2->op_mid) &&
+               (e1->dev == e2->dev) &&
+               (e1->inode == e2->inode));
+}
 
-struct de_locking_key {
-       char name[4];
-       SMB_DEV_T dev;
-       SMB_INO_T inode;
-};
+static struct share_mode_entry *find_share_mode_entry(struct share_mode_lock *lck,
+                                                     struct share_mode_entry *entry)
+{
+       int i;
 
-struct deferred_open_data {
-        union {
-                int num_deferred_open_entries;
-                deferred_open_entry dummy; /* Needed for alignment. */
-        } u;
-        /* the following two entries are implicit
-           deferred_open_entry de_entries[num_deferred_open_entries];
-           char file_name[];
-        */
-};
+       for (i=0; i<lck->num_share_modes; i++) {
+               struct share_mode_entry *e = &lck->share_modes[i];
+               if (is_valid_share_mode_entry(entry) &&
+                   is_valid_share_mode_entry(e) &&
+                   share_modes_identical(e, entry)) {
+                       return e;
+               }
+               if (is_deferred_open_entry(entry) &&
+                   is_deferred_open_entry(e) &&
+                   deferred_open_identical(e, entry)) {
+                       return e;
+               }
+       }
+       return NULL;
+}
 
 /*******************************************************************
- Print out a deferred open table.
+ Del the share mode of a file for this process. Return the number of
+ entries left.
 ********************************************************************/
 
-static void print_deferred_open_table(struct deferred_open_data *data)
+BOOL del_share_mode(struct share_mode_lock *lck, files_struct *fsp)
 {
-       int num_de_entries = data->u.num_deferred_open_entries;
-       deferred_open_entry *de_entries = (deferred_open_entry *)(data + 1);
-       int i;
+       struct share_mode_entry entry, *e;
+
+       fill_share_mode_entry(&entry, fsp, 0, 0);
 
-       for (i = 0; i < num_de_entries; i++) {
-               deferred_open_entry *entry_p = &de_entries[i];
-               DEBUG(10,("print_deferred_open_table: %s\n", deferred_open_str(i, entry_p) ));
+       e = find_share_mode_entry(lck, &entry);
+       if (e == NULL) {
+               return False;
        }
+
+       e->op_type = UNUSED_SHARE_MODE_ENTRY;
+       lck->modified = True;
+       return True;
 }
 
+void del_deferred_open_entry(struct share_mode_lock *lck, uint16 mid)
+{
+       struct share_mode_entry entry, *e;
 
-/*******************************************************************
- Form a static deferred open locking key for a dev/inode pair.
-******************************************************************/
+       fill_deferred_open_entry(&entry, timeval_zero(),
+                                lck->dev, lck->ino, mid);
 
-static TDB_DATA deferred_open_locking_key(SMB_DEV_T dev, SMB_INO_T inode)
-{
-       static struct de_locking_key key;
-       TDB_DATA kbuf;
+       e = find_share_mode_entry(lck, &entry);
+       if (e == NULL) {
+               return;
+       }
 
-       memset(&key, '\0', sizeof(key));
-       memcpy(&key.name[0], "DOE", 4);
-       key.dev = dev;
-       key.inode = inode;
-       kbuf.dptr = (char *)&key;
-       kbuf.dsize = sizeof(key);
-       return kbuf;
+       e->op_type = UNUSED_SHARE_MODE_ENTRY;
+       lck->modified = True;
 }
 
 /*******************************************************************
Get all deferred open entries for a dev/inode pair.
Remove an oplock mid and mode entry from a share mode.
 ********************************************************************/
 
-int get_deferred_opens(connection_struct *conn, 
-                   SMB_DEV_T dev, SMB_INO_T inode, 
-                   deferred_open_entry **pp_de_entries)
+BOOL remove_share_oplock(struct share_mode_lock *lck, files_struct *fsp)
 {
-       TDB_DATA dbuf;
-       struct deferred_open_data *data;
-       int num_de_entries;
-       deferred_open_entry *de_entries = NULL;
-       TDB_DATA key = deferred_open_locking_key(dev, inode);
+       struct share_mode_entry entry, *e;
 
-       *pp_de_entries = NULL;
+       fill_share_mode_entry(&entry, fsp, 0, 0);
 
-       dbuf = tdb_fetch(deferred_open_tdb, key);
-       if (!dbuf.dptr)
-               return 0;
-
-       data = (struct deferred_open_data *)dbuf.dptr;
-       num_de_entries = data->u.num_deferred_open_entries;
-       if(num_de_entries) {
-               pstring fname;
-               int i;
-               int del_count = 0;
-
-               de_entries = (deferred_open_entry *)memdup(dbuf.dptr + sizeof(*data),   
-                                               num_de_entries * sizeof(deferred_open_entry));
-
-               if (!de_entries) {
-                       SAFE_FREE(dbuf.dptr);
-                       return 0;
-               }
+       e = find_share_mode_entry(lck, &entry);
+       if (e == NULL) {
+               return False;
+       }
 
-               /* Save off the associated filename. */
-               pstrcpy(fname, dbuf.dptr + sizeof(*data) + num_de_entries * sizeof(deferred_open_entry));
+       e->op_mid = 0;
+       e->op_type = NO_OPLOCK;
+       lck->modified = True;
+       return True;
+}
 
-               /*
               * Ensure that each entry has a real process attached.
-                */
+/*******************************************************************
Downgrade a oplock type from exclusive to level II.
+********************************************************************/
 
-               for (i = 0; i < num_de_entries; ) {
-                       deferred_open_entry *entry_p = &de_entries[i];
-                       if (process_exists(entry_p->pid)) {
-                               DEBUG(10,("get_deferred_opens: %s\n", deferred_open_str(i, entry_p) ));
-                               i++;
-                       } else {
-                               DEBUG(10,("get_deferred_opens: deleted %s\n", deferred_open_str(i, entry_p) ));
-                               if (num_de_entries - i - 1 > 0) {
-                                       memcpy( &de_entries[i], &de_entries[i+1],
-                                               sizeof(deferred_open_entry) * (num_de_entries - i - 1));
-                               }
-                               num_de_entries--;
-                               del_count++;
-                       }
-               }
+BOOL downgrade_share_oplock(struct share_mode_lock *lck, files_struct *fsp)
+{
+       struct share_mode_entry entry, *e;
 
-               /* Did we delete any ? If so, re-store in tdb. */
-               if (del_count) {
-                       data->u.num_deferred_open_entries = num_de_entries;
-                       
-                       if (num_de_entries) {
-                               memcpy(dbuf.dptr + sizeof(*data), de_entries,
-                                               num_de_entries * sizeof(deferred_open_entry));
-                               /* Append the filename. */
-                               pstrcpy(dbuf.dptr + sizeof(*data) + num_de_entries * sizeof(deferred_open_entry), fname);
-                       }
+       fill_share_mode_entry(&entry, fsp, 0, 0);
 
-                       /* The record has shrunk a bit */
-                       dbuf.dsize -= del_count * sizeof(deferred_open_entry);
-
-                       if (data->u.num_deferred_open_entries == 0) {
-                               if (tdb_delete(deferred_open_tdb, key) == -1) {
-                                       SAFE_FREE(de_entries);
-                                       SAFE_FREE(dbuf.dptr);
-                                       return 0;
-                               }
-                       } else {
-                               if (tdb_store(deferred_open_tdb, key, dbuf, TDB_REPLACE) == -1) {
-                                       SAFE_FREE(de_entries);
-                                       SAFE_FREE(dbuf.dptr);
-                                       return 0;
-                               }
-                       }
-               }
+       e = find_share_mode_entry(lck, &entry);
+       if (e == NULL) {
+               return False;
        }
 
-       SAFE_FREE(dbuf.dptr);
-       *pp_de_entries = de_entries;
-       return num_de_entries;
+       e->op_type = LEVEL_II_OPLOCK;
+       lck->modified = True;
+       return True;
 }
 
+
 /*******************************************************************
- Check if two deferred open entries are identical.
+ We've just told all the smbd's that our level2 or fake level2 has been
+ written to.
 ********************************************************************/
-
-static BOOL deferred_open_entries_identical( deferred_open_entry *e1, deferred_open_entry *e2)
+BOOL remove_all_share_oplocks(struct share_mode_lock *lck, files_struct *fsp)
 {
-       return (e1->pid == e2->pid &&
-               e1->mid == e2->mid &&
-               e1->port == e2->port &&
-               e1->dev == e2->dev &&
-               e1->inode == e2->inode &&
-               e1->time.tv_sec == e2->time.tv_sec &&
-               e1->time.tv_usec == e2->time.tv_usec);
+       int i;
+       for (i=0; i<lck->num_share_modes; i++) {
+               struct share_mode_entry *e = &lck->share_modes[i];
+               if (!is_valid_share_mode_entry(e)) {
+                       continue;
+               }
+               if (e->op_type == NO_OPLOCK) {
+                       continue;
+               }
+               e->op_type = NO_OPLOCK;
+               lck->modified = True;
+       }
+       return True;
 }
 
-/*******************************************************************
- Delete a specific deferred open entry.
- Ignore if no entry deleted.
-********************************************************************/
+/****************************************************************************
+ Deal with the internal needs of setting the delete on close flag. Note that
+ as the tdb locking is recursive, it is safe to call this from within 
+ open_file_shared. JRA.
+****************************************************************************/
 
-BOOL delete_deferred_open_entry(deferred_open_entry *entry)
+NTSTATUS can_set_delete_on_close(files_struct *fsp, BOOL delete_on_close,
+                                uint32 dosmode)
 {
-       TDB_DATA dbuf;
-       struct deferred_open_data *data;
-       int i, del_count=0;
-       deferred_open_entry *de_entries;
-       BOOL ret = True;
-       TDB_DATA key = deferred_open_locking_key(entry->dev, entry->inode);
-
-       /* read in the existing share modes */
-       dbuf = tdb_fetch(deferred_open_tdb, key);
-       if (!dbuf.dptr)
-               return -1;
-
-       data = (struct deferred_open_data *)dbuf.dptr;
-       de_entries = (deferred_open_entry *)(dbuf.dptr + sizeof(*data));
+       if (!delete_on_close) {
+               return NT_STATUS_OK;
+       }
 
        /*
-        * Find any with this pid and delete it
-        * by overwriting with the rest of the data 
-        * from the record.
+        * Only allow delete on close for writable files.
         */
 
-       DEBUG(10,("delete_deferred_open_entry: num_deferred_open_entries = %d\n",
-               data->u.num_deferred_open_entries ));
-
-       for (i=0;i<data->u.num_deferred_open_entries;) {
-               if (deferred_open_entries_identical(&de_entries[i], entry)) {
-                       DEBUG(10,("delete_deferred_open_entry: deleted %s\n",
-                               deferred_open_str(i, &de_entries[i]) ));
-
-                       data->u.num_deferred_open_entries--;
-                       if ((dbuf.dsize - (sizeof(*data) + (i+1)*sizeof(*de_entries))) > 0) {
-                               memmove(&de_entries[i], &de_entries[i+1], 
-                                       dbuf.dsize - (sizeof(*data) + (i+1)*sizeof(*de_entries)));
-                       }
-                       del_count++;
-
-                       DEBUG(10,("delete_deferred_open_entry: deleting entry %d\n", i ));
-
-               } else {
-                       i++;
-               }
+       if ((dosmode & aRONLY) &&
+           !lp_delete_readonly(SNUM(fsp->conn))) {
+               DEBUG(10,("can_set_delete_on_close: file %s delete on close "
+                         "flag set but file attribute is readonly.\n",
+                         fsp->fsp_name ));
+               return NT_STATUS_CANNOT_DELETE;
        }
 
-       SMB_ASSERT(del_count == 0 || del_count == 1);
-
-       if (del_count) {
-               /* the record may have shrunk a bit */
-               dbuf.dsize -= del_count * sizeof(*de_entries);
+       /*
+        * Only allow delete on close for writable shares.
+        */
 
-               /* store it back in the database */
-               if (data->u.num_deferred_open_entries == 0) {
-                       if (tdb_delete(deferred_open_tdb, key) == -1)
-                               ret = False;
-               } else {
-                       if (tdb_store(deferred_open_tdb, key, dbuf, TDB_REPLACE) == -1)
-                               ret = False;
-               }
+       if (!CAN_WRITE(fsp->conn)) {
+               DEBUG(10,("can_set_delete_on_close: file %s delete on "
+                         "close flag set but write access denied on share.\n",
+                         fsp->fsp_name ));
+               return NT_STATUS_ACCESS_DENIED;
        }
-       DEBUG(10,("delete_deferred_open_entry: Remaining table.\n"));
-       print_deferred_open_table((struct deferred_open_data*)dbuf.dptr);
-       SAFE_FREE(dbuf.dptr);
-       return ret;
-}
 
-/*******************************************************************
- Fill a deferred open entry.
-********************************************************************/
+       /*
+        * Only allow delete on close for files/directories opened with delete
+        * intent.
+        */
 
-static void fill_deferred_open(char *p, uint16 mid, struct timeval *ptv, SMB_DEV_T dev, SMB_INO_T inode, uint16 port)
-{
-       deferred_open_entry *e = (deferred_open_entry *)p;
-       void *x = &e->time; /* Needed to force alignment. p may not be aligned.... */
+       if (!(fsp->access_mask & DELETE_ACCESS)) {
+               DEBUG(10,("can_set_delete_on_close: file %s delete on "
+                         "close flag set but delete access denied.\n",
+                         fsp->fsp_name ));
+               return NT_STATUS_ACCESS_DENIED;
+       }
 
-       memset(e, '\0', sizeof(deferred_open_entry));
-       e->mid = mid;
-       e->pid = sys_getpid();
-       memcpy(x, ptv, sizeof(struct timeval));
-       e->dev = dev;
-       e->inode = inode;
-       e->port = port;
+       return NT_STATUS_OK;
 }
 
-/*******************************************************************
- Add a deferred open record. Return False on fail, True on success.
-********************************************************************/
+/****************************************************************************
+ Sets the delete on close flag over all share modes on this file.
+ Modify the share mode entry for all files open
+ on this device and inode to tell other smbds we have
+ changed the delete on close flag. This will be noticed
+ in the close code, the last closer will delete the file
+ if flag is set.
+****************************************************************************/
 
-BOOL add_deferred_open(uint16 mid, struct timeval *ptv, SMB_DEV_T dev, SMB_INO_T inode, uint16 port, const char *fname)
+BOOL set_delete_on_close(files_struct *fsp, BOOL delete_on_close)
 {
-       TDB_DATA dbuf;
-       struct deferred_open_data *data;
-       char *p=NULL;
-       int size;
-       TDB_DATA key = deferred_open_locking_key(dev, inode);
-       BOOL ret = True;
-               
-       /* read in the existing deferred open records if any */
-       dbuf = tdb_fetch(deferred_open_tdb, key);
-       if (!dbuf.dptr) {
-               size_t offset;
-               /* we'll need to create a new record */
-
-               size = sizeof(*data) + sizeof(deferred_open_entry) + strlen(fname) + 1;
-               p = (char *)SMB_MALLOC(size);
-               if (!p)
-                       return False;
-               data = (struct deferred_open_data *)p;
-               ZERO_STRUCT(data->u.dummy); /* Keep valgrind happy */
-               data->u.num_deferred_open_entries = 1;
+       struct share_mode_lock *lck;
        
-               DEBUG(10,("add_deferred_open: creating entry for file %s. num_deferred_open_entries = 1\n",
-                       fname ));
-
-               offset = sizeof(*data) + sizeof(deferred_open_entry);
-               safe_strcpy(p + offset, fname, size - offset - 1);
-               fill_deferred_open(p + sizeof(*data), mid, ptv, dev, inode, port);
-               dbuf.dptr = p;
-               dbuf.dsize = size;
-               if (tdb_store(deferred_open_tdb, key, dbuf, TDB_REPLACE) == -1)
-                       ret = False;
-
-               print_deferred_open_table((struct deferred_open_data *)p);
-
-               SAFE_FREE(p);
-               return ret;
-       }
-
-       /* we're adding to an existing entry - this is a bit fiddly */
-       data = (struct deferred_open_data *)dbuf.dptr;
+       DEBUG(10,("set_delete_on_close: %s delete on close flag for "
+                 "fnum = %d, file %s\n",
+                 delete_on_close ? "Adding" : "Removing", fsp->fnum,
+                 fsp->fsp_name ));
 
-       data->u.num_deferred_open_entries++;
-       
-       DEBUG(10,("add_deferred_open: adding entry for file %s. new num_deferred_open_entries = %d\n",
-               fname, data->u.num_deferred_open_entries ));
+       if (fsp->is_directory || fsp->is_stat)
+               return True;
 
-       size = dbuf.dsize + sizeof(deferred_open_entry);
-       p = SMB_MALLOC(size);
-       if (!p) {
-               SAFE_FREE(dbuf.dptr);
+       lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL);
+       if (lck == NULL) {
                return False;
        }
-       memcpy(p, dbuf.dptr, sizeof(*data));
-       fill_deferred_open(p + sizeof(*data), mid, ptv, dev, inode, port);
-       memcpy(p + sizeof(*data) + sizeof(deferred_open_entry), dbuf.dptr + sizeof(*data),
-              dbuf.dsize - sizeof(*data));
-       SAFE_FREE(dbuf.dptr);
-       dbuf.dptr = p;
-       dbuf.dsize = size;
-       if (tdb_store(deferred_open_tdb, key, dbuf, TDB_REPLACE) == -1)
-               ret = False;
-       print_deferred_open_table((struct deferred_open_data *)p);
-       SAFE_FREE(p);
-       return ret;
-}
+       if (lck->delete_on_close != delete_on_close) {
+               lck->delete_on_close = delete_on_close;
+               lck->modified = True;
+       }
 
-/****************************************************************************
- Traverse the whole database with this function, calling traverse_callback
- on each share mode
-****************************************************************************/
+       talloc_free(lck);
+       return True;
+}
 
 static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, 
-                       voidstate)
+                       void *state)
 {
        struct locking_data *data;
-       share_mode_entry *shares;
+       struct share_mode_entry *shares;
        char *name;
        int i;
-
-       SHAREMODE_FN(traverse_callback) = (SHAREMODE_FN_CAST())state;
+       void (*traverse_callback)(struct share_mode_entry *, char *) = state;
 
        /* Ensure this is a locking_key record. */
        if (kbuf.dsize != sizeof(struct locking_key))
                return 0;
 
        data = (struct locking_data *)dbuf.dptr;
-       shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data));
-       name = dbuf.dptr + sizeof(*data) + data->u.s.num_share_mode_entries*sizeof(*shares);
+       shares = (struct share_mode_entry *)(dbuf.dptr + sizeof(*data));
+       name = dbuf.dptr + sizeof(*data) +
+               data->u.s.num_share_mode_entries*sizeof(*shares);
 
        for (i=0;i<data->u.s.num_share_mode_entries;i++) {
                traverse_callback(&shares[i], name);
@@ -1299,9 +1005,9 @@ static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf,
  share mode system.
 ********************************************************************/
 
-int share_mode_forall(SHAREMODE_FN(fn))
+int share_mode_forall(void (*fn)(const struct share_mode_entry *, char *))
 {
-       if (!tdb)
+       if (tdb == NULL)
                return 0;
-       return tdb_traverse(tdb, traverse_fn, (void*)fn);
+       return tdb_traverse(tdb, traverse_fn, fn);
 }
index 3c59fd9d61f18b35115df84d0cb64b468524fd05..ccee9d71eddd94068d504163cdc9c1cc6368bb9a 100644 (file)
@@ -23,7 +23,7 @@
 
 static struct {
        char from;
-       char *to;
+       const char *to;
        int len;
 } weird_table[] = {
        {'q', "^q^", 3},
index 653cb97fbb0678481f3b1cc8d70d0b20d7824145..4db54ea198cee9f05a95c8589bc6bda1a88bf919 100644 (file)
@@ -201,7 +201,7 @@ void run_dns_queue(void)
         /* Allow SIGTERM to kill us. */
         BlockSignals(False, SIGTERM);
 
-       if (!process_exists(child_pid)) {
+       if (!process_exists_by_pid(child_pid)) {
                close(fd_in);
                start_async_dns();
        }
index bc58dd3a2814c0f6475fc4a3b72a6bd257db7b04..fcaba03b3dbaad5ce42eb4c53e45018c27dab2a9 100644 (file)
@@ -76,7 +76,8 @@ static void terminate(void)
  Handle a SHUTDOWN message from smbcontrol.
  **************************************************************************** */
 
-static void nmbd_terminate(int msg_type, pid_t src, void *buf, size_t len)
+static void nmbd_terminate(int msg_type, struct process_id src,
+                          void *buf, size_t len)
 {
        terminate();
 }
@@ -307,7 +308,8 @@ static BOOL reload_nmbd_services(BOOL test)
  * detects that there are no subnets.
  **************************************************************************** */
 
-static void msg_reload_nmbd_services(int msg_type, pid_t src, void *buf, size_t len)
+static void msg_reload_nmbd_services(int msg_type, struct process_id src,
+                                    void *buf, size_t len)
 {
        write_browse_list( 0, True );
        dump_all_namelists();
@@ -323,31 +325,33 @@ static void msg_reload_nmbd_services(int msg_type, pid_t src, void *buf, size_t
        }
 }
 
-static void msg_nmbd_send_packet(int msg_type, pid_t src,
+static void msg_nmbd_send_packet(int msg_type, struct process_id src,
                                 void *buf, size_t len)
 {
        struct packet_struct *p = (struct packet_struct *)buf;
        struct subnet_record *subrec;
        struct in_addr *local_ip;
 
-       DEBUG(10, ("Received send_packet from %d\n", src));
+       DEBUG(10, ("Received send_packet from %d\n", procid_to_pid(&src)));
 
        if (len != sizeof(struct packet_struct)) {
-               DEBUG(2, ("Discarding invalid packet length from %d\n", src));
+               DEBUG(2, ("Discarding invalid packet length from %d\n",
+                         procid_to_pid(&src)));
                return;
        }
 
        if ((p->packet_type != NMB_PACKET) &&
            (p->packet_type != DGRAM_PACKET)) {
                DEBUG(2, ("Discarding invalid packet type from %d: %d\n",
-                         src, p->packet_type));
+                         procid_to_pid(&src), p->packet_type));
                return;
        }
 
        local_ip = iface_ip(p->ip);
 
        if (local_ip == NULL) {
-               DEBUG(2, ("Could not find ip for packet from %d\n", src));
+               DEBUG(2, ("Could not find ip for packet from %d\n",
+                         procid_to_pid(&src)));
                return;
        }
 
@@ -590,7 +594,8 @@ static void process(void)
 
                if(reload_after_sighup) {
                        DEBUG( 0, ( "Got SIGHUP dumping debug info.\n" ) );
-                       msg_reload_nmbd_services(MSG_SMB_CONF_UPDATED, (pid_t) 0, (void*) &no_subnets, 0);
+                       msg_reload_nmbd_services(MSG_SMB_CONF_UPDATED,
+                                                pid_to_procid(0), (void*) &no_subnets, 0);
                        if(no_subnets)
                                return;
                        reload_after_sighup = 0;
index 470cf4277b52b4b2c1c4b23fae067394fd3d273e..6e8e8429becba31f767a2e32e231714ed86d78c4 100644 (file)
@@ -374,7 +374,8 @@ yet registered on subnet %s\n", nmb_namestr(&nmbname), subrec->subnet_name ));
  Process a internal Samba message forcing an election.
 ***************************************************************************/
 
-void nmbd_message_election(int msg_type, pid_t src, void *buf, size_t len)
+void nmbd_message_election(int msg_type, struct process_id src,
+                          void *buf, size_t len)
 {
        struct subnet_record *subrec;
 
index 4baf2d3d6cecab6c108c4f48cf9de5c8c456d052..c25473c4fba17ade781b095ec42c5a92f0fb8db1 100644 (file)
@@ -1246,7 +1246,7 @@ packet sent to name %s from IP %s\n",
 packet sent to name %s from IP %s\n",
                        dgram->datasize,
                        len,
-                       PTR_DIFF(buf2, dgram->data),
+                       (int)PTR_DIFF(buf2, dgram->data),
                        nmb_namestr(&dgram->dest_name),
                        inet_ntoa(p->ip) ));
                return;
@@ -1257,7 +1257,7 @@ packet sent to name %s from IP %s\n",
 packet sent to name %s from IP %s\n",
                        dgram->datasize,
                        len,
-                       PTR_DIFF(buf2, dgram->data),
+                       (int)PTR_DIFF(buf2, dgram->data),
                        nmb_namestr(&dgram->dest_name),
                        inet_ntoa(p->ip) ));
                return;
index 33690133bf88de614e6aa94eb17da3f805d0d970..28ad92ed108022ac277e51cd7d7c175c349f868b 100644 (file)
@@ -294,7 +294,7 @@ void sync_check_completion(void)
 
        for (s=syncs;s;s=next) {
                next = s->next;
-               if (!process_exists(s->pid)) {
+               if (!process_exists_by_pid(s->pid)) {
                        /* it has completed - grab the info */
                        complete_sync(s);
                        DLIST_REMOVE(syncs, s);
index 86f5b9c4261de1cd57b2ee206efd1003c1310596..d76cb8f03226c30db9412c8feb95c915678fa418 100644 (file)
@@ -1874,7 +1874,8 @@ void wins_write_database(BOOL background)
  Process a internal Samba message receiving a wins record.
 ***************************************************************************/
 
-void nmbd_wins_new_entry(int msg_type, pid_t src, void *buf, size_t len)
+void nmbd_wins_new_entry(int msg_type, struct process_id src,
+                        void *buf, size_t len)
 {
        WINS_RECORD *record;
        struct name_record *namerec = NULL;
index 6d09666525f7f2f142fbd189078ac57c2ff1a8e1..5521614965af548ceb8f5f6adb40f6ec581ea62e 100644 (file)
@@ -543,6 +543,11 @@ NSS_STATUS winbindd_send_request(int req_type, struct winbindd_request *request)
        if (write_sock(request, sizeof(*request), request->flags & WBFLAG_RECURSE) == -1) {
                return NSS_STATUS_UNAVAIL;
        }
+
+       if ((request->extra_len != 0) &&
+           (write_sock(request->extra_data, request->extra_len, request->flags & WBFLAG_RECURSE) == -1)) {
+               return NSS_STATUS_UNAVAIL;
+       }
        
        return NSS_STATUS_SUCCESS;
 }
index 34b2d6c9299f2d0fc707228a1812ee8ffa3552d9..60f1d6b7221d21f1722938a9554bd313c1c7b75a 100644 (file)
@@ -192,7 +192,6 @@ static BOOL wbinfo_get_userdomgroups(const char *user_sid)
        return True;
 }
 
-
 /* Convert NetBIOS name to IP */
 
 static BOOL wbinfo_wins_byname(char *name)
index dffaad5ef00a173c200ec01702222d11fca7c720..565764fa4be23db39fe62996d561a61cfe93aaa7 100644 (file)
@@ -204,7 +204,7 @@ static void sigchld_handler(int signum)
 }
 
 /* React on 'smbcontrol winbindd reload-config' in the same way as on SIGHUP*/
-static void msg_reload_services(int msg_type, pid_t src, void *buf, size_t len)
+static void msg_reload_services(int msg_type, struct process_id src, void *buf, size_t len)
 {
         /* Flush various caches */
        flush_caches();
@@ -212,7 +212,7 @@ static void msg_reload_services(int msg_type, pid_t src, void *buf, size_t len)
 }
 
 /* React on 'smbcontrol winbindd shutdown' in the same way as on SIGTERM*/
-static void msg_shutdown(int msg_type, pid_t src, void *buf, size_t len)
+static void msg_shutdown(int msg_type, struct process_id src, void *buf, size_t len)
 {
        terminate();
 }
@@ -455,6 +455,7 @@ void setup_async_write(struct fd_event *event, void *data, size_t length,
 
 static void request_len_recv(void *private_data, BOOL success);
 static void request_recv(void *private_data, BOOL success);
+static void request_main_recv(void *private_data, BOOL success);
 static void request_finished(struct winbindd_cli_state *state);
 void request_finished_cont(void *private_data, BOOL success);
 static void response_main_sent(void *private_data, BOOL success);
@@ -475,6 +476,7 @@ static void response_extra_sent(void *private_data, BOOL success)
                return;
        }
 
+       SAFE_FREE(state->request.extra_data);
        SAFE_FREE(state->response.extra_data);
 
        setup_async_read(&state->fd_event, &state->request, sizeof(uint32),
@@ -538,7 +540,7 @@ void request_finished_cont(void *private_data, BOOL success)
                request_error(state);
 }
 
-static void request_recv(void *private_data, BOOL success)
+static void request_len_recv(void *private_data, BOOL success)
 {
        struct winbindd_cli_state *state =
                talloc_get_type_abort(private_data, struct winbindd_cli_state);
@@ -548,10 +550,19 @@ static void request_recv(void *private_data, BOOL success)
                return;
        }
 
-       process_request(state);
+       if (*(uint32 *)(&state->request) != sizeof(state->request)) {
+               DEBUG(0,("request_len_recv: Invalid request size received: %d\n",
+                        *(uint32 *)(&state->request)));
+               state->finished = True;
+               return;
+       }
+
+       setup_async_read(&state->fd_event, (uint32 *)(&state->request)+1,
+                        sizeof(state->request) - sizeof(uint32),
+                        request_main_recv, state);
 }
 
-static void request_len_recv(void *private_data, BOOL success)
+static void request_main_recv(void *private_data, BOOL success)
 {
        struct winbindd_cli_state *state =
                talloc_get_type_abort(private_data, struct winbindd_cli_state);
@@ -561,16 +572,48 @@ static void request_len_recv(void *private_data, BOOL success)
                return;
        }
 
-       if (*(uint32 *)(&state->request) != sizeof(state->request)) {
-               DEBUG(0,("request_len_recv: Invalid request size received: %d\n",
-                        *(uint32 *)(&state->request)));
+       if (state->request.extra_len == 0) {
+               state->request.extra_data = NULL;
+               request_recv(state, True);
+               return;
+       }
+
+       if ((!state->privileged) &&
+           (state->request.extra_len > WINBINDD_MAX_EXTRA_DATA)) {
+               DEBUG(3, ("Got request with %d bytes extra data on "
+                         "unprivileged socket\n", (int)state->request.extra_len));
+               state->request.extra_data = NULL;
                state->finished = True;
                return;
        }
 
-       setup_async_read(&state->fd_event, (uint32 *)(&state->request)+1,
-                        sizeof(state->request) - sizeof(uint32),
-                        request_recv, state);
+       state->request.extra_data =
+               SMB_MALLOC_ARRAY(char, state->request.extra_len + 1);
+
+       if (state->request.extra_data == NULL) {
+               DEBUG(0, ("malloc failed\n"));
+               state->finished = True;
+               return;
+       }
+
+       /* Ensure null termination */
+       state->request.extra_data[state->request.extra_len] = '\0';
+
+       setup_async_read(&state->fd_event, state->request.extra_data,
+                        state->request.extra_len, request_recv, state);
+}
+
+static void request_recv(void *private_data, BOOL success)
+{
+       struct winbindd_cli_state *state =
+               talloc_get_type_abort(private_data, struct winbindd_cli_state);
+
+       if (!success) {
+               state->finished = True;
+               return;
+       }
+
+       process_request(state);
 }
 
 /* Process a new connection by adding it to the client connection list */
@@ -842,7 +885,7 @@ static void process_loop(void)
 
                DEBUG(3, ("got SIGHUP\n"));
 
-               msg_reload_services(MSG_SMB_CONF_UPDATED, (pid_t) 0, NULL, 0);
+               msg_reload_services(MSG_SMB_CONF_UPDATED, pid_to_procid(0), NULL, 0);
                do_sighup = False;
        }
 
index 3a7728e4a2c82fb3fff2f037ddb99d13820aed71..0db109dacde06497926ff41d7009dc1e2958eeff 100644 (file)
@@ -47,6 +47,14 @@ struct fd_event {
        void *private_data;
 };
 
+struct sid_ctr {
+       DOM_SID *sid;
+       BOOL finished;
+       const char *domain;
+       const char *name;
+       enum SID_NAME_USE type;
+};
+
 struct winbindd_cli_state {
        struct winbindd_cli_state *prev, *next;   /* Linked list pointers */
        int sock;                                 /* Open socket from client */
@@ -122,12 +130,6 @@ struct winbindd_cm_conn {
        struct rpc_pipe_client *lsa_pipe;
        POLICY_HND lsa_policy;
 
-       /* Auth2 pipe is the pipe used to setup the netlogon schannel key
-        * using rpccli_net_auth2. It needs to be kept open. */
-
-       struct rpc_pipe_client *netlogon_auth2_pipe;
-       unsigned char sess_key[16];        /* Current session key. */
-       DOM_CRED clnt_cred;                /* Client NETLOGON credential. */
        struct rpc_pipe_client *netlogon_pipe;
 };
 
@@ -305,8 +307,6 @@ struct winbindd_idmap_methods {
 
 #include "nsswitch/winbindd_proto.h"
 
-#include "rpc_parse.h"
-
 #define WINBINDD_ESTABLISH_LOOP 30
 #define WINBINDD_RESCAN_FREQ 300
 
index eda6dea2c48262bddbc3fd02bf95fd1884612ad2..dfabccd419443772e6ac4c4451c9b300a53188a9 100644 (file)
@@ -830,13 +830,7 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
        *names       = NULL;
        *dom_sids    = NULL;
 
-       {
-               unsigned char *session_key;
-               DOM_CRED *creds;
-
-               result = cm_connect_netlogon(domain, mem_ctx, &cli,
-                                            &session_key, &creds);
-       }
+       result = cm_connect_netlogon(domain, &cli);
 
        if (!NT_STATUS_IS_OK(result)) {
                DEBUG(5, ("trusted_domains: Could not open a connection to %s "
@@ -845,11 +839,12 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
                return NT_STATUS_UNSUCCESSFUL;
        }
        
-       if ( NT_STATUS_IS_OK(result) )
+       if ( NT_STATUS_IS_OK(result) ) {
                result = rpccli_ds_enum_domain_trusts(cli, mem_ctx,
                                                      cli->cli->desthost, 
                                                      flags, &domains,
                                                      (unsigned int *)&count);
+       }
        
        if ( NT_STATUS_IS_OK(result) && count) {
        
index acae7e7f37144c188979fb0242d5dd3e7dff2037..d43671380d00dce4a6805ccc10cc71e1cce08b8b 100644 (file)
@@ -84,12 +84,12 @@ static void do_async(TALLOC_CTX *mem_ctx, struct winbindd_child *child,
                      &state->response, do_async_recv, state);
 }
 
-static void do_async_domain(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
-                           const struct winbindd_request *request,
-                           void (*cont)(TALLOC_CTX *mem_ctx, BOOL success,
-                                        struct winbindd_response *response,
-                                        void *c, void *private_data),
-                           void *c, void *private_data)
+void do_async_domain(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
+                    const struct winbindd_request *request,
+                    void (*cont)(TALLOC_CTX *mem_ctx, BOOL success,
+                                 struct winbindd_response *response,
+                                 void *c, void *private_data),
+                    void *c, void *private_data)
 {
        struct do_async_state *state;
 
@@ -706,16 +706,16 @@ enum winbindd_result winbindd_dual_lookupname(struct winbindd_domain *domain,
        return WINBINDD_OK;
 }
 
-static BOOL print_sidlist(TALLOC_CTX *mem_ctx, const DOM_SID *sids,
-                         int num_sids, char **result)
+BOOL print_sidlist(TALLOC_CTX *mem_ctx, const DOM_SID *sids,
+                  int num_sids, char **result, ssize_t *len)
 {
        int i;
        size_t buflen = 0;
-       ssize_t len = 0;
 
+       *len = 0;
        *result = NULL;
        for (i=0; i<num_sids; i++) {
-               sprintf_append(mem_ctx, result, &len, &buflen,
+               sprintf_append(mem_ctx, result, len, &buflen,
                               "%s\n", sid_string_static(&sids[i]));
        }
 
@@ -726,14 +726,14 @@ static BOOL print_sidlist(TALLOC_CTX *mem_ctx, const DOM_SID *sids,
        return True;
 }
 
-static BOOL parse_sidlist(TALLOC_CTX *mem_ctx, char *sidstr,
-                         DOM_SID **sids, int *num_sids)
+BOOL parse_sidlist(TALLOC_CTX *mem_ctx, char *sidstr,
+                  DOM_SID **sids, int *num_sids)
 {
        char *p, *q;
 
        p = sidstr;
        if (p == NULL)
-               return True;
+               return False;
 
        while (p[0] != '\0') {
                DOM_SID sid;
@@ -754,6 +754,49 @@ static BOOL parse_sidlist(TALLOC_CTX *mem_ctx, char *sidstr,
        return True;
 }
 
+BOOL print_ridlist(TALLOC_CTX *mem_ctx, uint32 *rids, int num_rids,
+                  char **result, ssize_t *len)
+{
+       int i;
+       size_t buflen = 0;
+
+       *len = 0;
+       *result = NULL;
+       for (i=0; i<num_rids; i++) {
+               sprintf_append(mem_ctx, result, len, &buflen,
+                              "%ld\n", rids[i]);
+       }
+
+       if ((num_rids != 0) && (*result == NULL)) {
+               return False;
+       }
+
+       return True;
+}
+
+BOOL parse_ridlist(TALLOC_CTX *mem_ctx, char *ridstr,
+                  uint32 **sids, int *num_rids)
+{
+       char *p;
+
+       p = ridstr;
+       if (p == NULL)
+               return False;
+
+       while (p[0] != '\0') {
+               uint32 rid;
+               char *q;
+               rid = strtoul(p, &q, 10);
+               if (*q != '\n') {
+                       DEBUG(0, ("Got invalid ridstr: %s\n", p));
+                       return False;
+               }
+               p = q+1;
+               ADD_TO_ARRAY(mem_ctx, uint32, rid, sids, num_rids);
+       }
+       return True;
+}
+
 static void getsidaliases_recv(TALLOC_CTX *mem_ctx, BOOL success,
                               struct winbindd_response *response,
                               void *c, void *private_data)
@@ -806,28 +849,22 @@ void winbindd_getsidaliases_async(struct winbindd_domain *domain,
 {
        struct winbindd_request request;
        char *sidstr = NULL;
-       char *keystr;
+       ssize_t len;
 
        if (num_sids == 0) {
                cont(private_data, True, NULL, 0);
                return;
        }
 
-       if (!print_sidlist(mem_ctx, sids, num_sids, &sidstr)) {
-               cont(private_data, False, NULL, 0);
-               return;
-       }
-
-       keystr = cache_store_request_data(mem_ctx, sidstr);
-       if (keystr == NULL) {
+       if (!print_sidlist(mem_ctx, sids, num_sids, &sidstr, &len)) {
                cont(private_data, False, NULL, 0);
                return;
        }
 
        ZERO_STRUCT(request);
        request.cmd = WINBINDD_DUAL_GETSIDALIASES;
-       fstrcpy(request.domain_name, domain->name);
-       fstrcpy(request.data.dual_sidaliases.cache_key, keystr);
+       request.extra_len = len;
+       request.extra_data = sidstr;
 
        do_async_domain(mem_ctx, domain, &request, getsidaliases_recv,
                        cont, private_data);
@@ -838,20 +875,15 @@ enum winbindd_result winbindd_dual_getsidaliases(struct winbindd_domain *domain,
 {
        DOM_SID *sids = NULL;
        int num_sids = 0;
-       char *key = state->request.data.dual_sidaliases.cache_key;
        char *sidstr;
+       size_t len;
        int i, num_aliases;
        uint32 *alias_rids;
        NTSTATUS result;
 
        DEBUG(3, ("[%5lu]: getsidaliases\n", (unsigned long)state->pid));
 
-       /* Ensure null termination */
-        state->request.domain_name[sizeof(state->request.domain_name)-1]='\0';
-        state->request.data.dual_sidaliases.cache_key
-               [sizeof(state->request.data.dual_sidaliases.cache_key)-1]='\0';
-
-       sidstr = cache_retrieve_request_data(state->mem_ctx, key);
+       sidstr = state->request.extra_data;
        if (sidstr == NULL)
                sidstr = talloc_strdup(state->mem_ctx, "\n"); /* No SID */
 
@@ -891,7 +923,7 @@ enum winbindd_result winbindd_dual_getsidaliases(struct winbindd_domain *domain,
        }
 
        if (!print_sidlist(NULL, sids, num_sids,
-                          (char **)&state->response.extra_data)) {
+                          (char **)&state->response.extra_data, &len)) {
                DEBUG(0, ("Could not print_sidlist\n"));
                return WINBINDD_ERROR;
        }
@@ -899,7 +931,7 @@ enum winbindd_result winbindd_dual_getsidaliases(struct winbindd_domain *domain,
        if (state->response.extra_data != NULL) {
                DEBUG(10, ("aliases_list: %s\n",
                           (char *)state->response.extra_data));
-               state->response.length += strlen(state->response.extra_data)+1;
+               state->response.length += len+1;
        }
        
        return WINBINDD_OK;
@@ -1405,3 +1437,4 @@ void query_user_async(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
        do_async_domain(mem_ctx, domain, &request, query_user_recv,
                        cont, private_data);
 }
+
index ce291a6c25330bc1ebf1e888e1cae50d24c592db..78b49d01eac160f3d1cd9c306c7dddf2b2ed9134 100644 (file)
@@ -469,6 +469,7 @@ static struct cache_entry *wcache_fetch(struct winbind_cache *cache,
        centry->sequence_number = centry_uint32(centry);
 
        if (centry_expired(domain, kstr, centry)) {
+
                DEBUG(10,("wcache_fetch: entry %s expired for domain %s\n",
                         kstr, domain->name ));
 
@@ -1048,7 +1049,6 @@ do_query:
        return status;
 }
 
-
 /* Lookup user information from a rid */
 static NTSTATUS query_user(struct winbindd_domain *domain, 
                           TALLOC_CTX *mem_ctx, 
@@ -1466,7 +1466,7 @@ void cache_store_response(pid_t pid, struct winbindd_response *response)
        /* There's extra data */
 
        DEBUG(10, ("Storing extra data: len=%d\n",
-                  response->length - sizeof(*response)));
+                  (int)(response->length - sizeof(*response))));
 
        fstr_sprintf(key_str, "DE/%d", pid);
        if (tdb_store(wcache->tdb, string_tdb_data(key_str),
@@ -1514,7 +1514,7 @@ BOOL cache_retrieve_response(pid_t pid, struct winbindd_response * response)
        /* There's extra data */
 
        DEBUG(10, ("Retrieving extra data length=%d\n",
-                  response->length - sizeof(*response)));
+                  (int)(response->length - sizeof(*response))));
 
        fstr_sprintf(key_str, "DE/%d", pid);
        data = tdb_fetch(wcache->tdb, string_tdb_data(key_str));
@@ -1525,63 +1525,57 @@ BOOL cache_retrieve_response(pid_t pid, struct winbindd_response * response)
        }
 
        if (data.dsize != (response->length - sizeof(*response))) {
-               DEBUG(0, ("Invalid extra data length: %d\n", data.dsize));
+               DEBUG(0, ("Invalid extra data length: %d\n", (int)data.dsize));
                SAFE_FREE(data.dptr);
                return False;
        }
 
+       dump_data(11, data.dptr, data.dsize);
+
        response->extra_data = data.dptr;
        return True;
 }
 
-char *cache_store_request_data(TALLOC_CTX *mem_ctx, char *request_string)
+BOOL lookup_cached_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
+                      const char **domain_name, const char **name,
+                      enum SID_NAME_USE *type)
 {
-       int i;
-
-       if (!init_wcache())
-               return NULL;
+       struct winbindd_domain *domain;
+       struct winbind_cache *cache;
+       struct cache_entry *centry = NULL;
+       NTSTATUS status;
 
-       for (i=0; i<2; i++) {
-               char *key = talloc_strdup(mem_ctx, generate_random_str(16));
-               if (key == NULL)
-                       return NULL;
-               DEBUG(10, ("Storing request key %s\n", key));
-               if (tdb_store_bystring(wcache->tdb, key,
-                                      string_tdb_data(request_string),
-                                      TDB_INSERT) == 0)
-                       return key;
+       domain = find_lookup_domain_from_sid(sid);
+       if (domain == NULL) {
+               return False;
        }
-       return NULL;
-}
 
-char *cache_retrieve_request_data(TALLOC_CTX *mem_ctx, char *key)
-{
-       TDB_DATA data;
-       char *result = NULL;
+       cache = get_cache(domain);
 
-       if (!init_wcache())
-               return NULL;
-
-       DEBUG(10, ("Retrieving key %s\n", key));
-
-       data = tdb_fetch_bystring(wcache->tdb, key);
-       if (data.dptr == NULL)
-               return NULL;
-
-       if (strnlen(data.dptr, data.dsize) != (data.dsize)) {
-               DEBUG(0, ("Received invalid request string\n"));
-               goto done;
+       if (cache->tdb == NULL) {
+               return False;
        }
-       result = TALLOC_ARRAY(mem_ctx, char, data.dsize+1);
-       if (result != NULL) {
-               memcpy(result, data.dptr, data.dsize);
-               result[data.dsize] = '\0';
+
+       centry = wcache_fetch(cache, domain, "SN/%s", sid_string_static(sid));
+       if (centry == NULL) {
+               return False;
        }
-       if (tdb_delete_bystring(wcache->tdb, key) != 0) {
-               DEBUG(0, ("Could not delete key %s\n", key));
-               result = NULL;
+
+       if (NT_STATUS_IS_OK(centry->status)) {
+               *type = (enum SID_NAME_USE)centry_uint32(centry);
+               *domain_name = centry_string(centry, mem_ctx);
+               *name = centry_string(centry, mem_ctx);
        }
-  done:
-       SAFE_FREE(data.dptr);
-       return result;
+
+       status = centry->status;
+       centry_free(centry);
+       return NT_STATUS_IS_OK(status);
+}
+
+void cache_sid2name(struct winbindd_domain *domain, const DOM_SID *sid,
+                   const char *domain_name, const char *name,
+                   enum SID_NAME_USE type)
+{
+       wcache_save_sid_to_name(domain, NT_STATUS_OK, sid, domain_name,
+                               name, type);
 }
index 14221483adc5f075deb140488ea5b1f677b9bb0c..c91f9555682241c5d411740baf6e9920e4536abb 100644 (file)
@@ -73,7 +73,7 @@
    SAMR pipe as well for now.   --jerry
 ******************************************************************/
 
-#define DISABLE_SCHANNEL_WIN2K3_SP1    1
+/* #define DISABLE_SCHANNEL_WIN2K3_SP1 1 */
 
 
 /* Choose between anonymous or authenticated connections.  We need to use
@@ -113,8 +113,8 @@ static BOOL get_dc_name_via_netlogon(const struct winbindd_domain *domain,
                                     fstring dcname, struct in_addr *dc_ip)
 {
        struct winbindd_domain *our_domain;
+       struct rpc_pipe_client *netlogon_pipe;
        NTSTATUS result;
-       struct rpc_pipe_client *cli;
        TALLOC_CTX *mem_ctx;
 
        fstring tmp;
@@ -123,30 +123,26 @@ static BOOL get_dc_name_via_netlogon(const struct winbindd_domain *domain,
        /* Hmmmm. We can only open one connection to the NETLOGON pipe at the
         * moment.... */
 
-       if (IS_DC)
+       if (IS_DC) {
                return False;
+       }
 
-       if (domain->primary)
+       if (domain->primary) {
                return False;
+       }
 
        our_domain = find_our_domain();
 
-       if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL)
+       if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL) {
                return False;
-
-       {
-               /* These var's can be ignored -- we're not requesting
-                  anything in the credential chain here */
-               unsigned char *session_key;
-               DOM_CRED *creds;
-               result = cm_connect_netlogon(our_domain, mem_ctx, &cli,
-                                            &session_key, &creds);
        }
 
-       if (!NT_STATUS_IS_OK(result))
+       result = cm_connect_netlogon(our_domain, &netlogon_pipe);
+       if (!NT_STATUS_IS_OK(result)) {
                return False;
+       }
 
-       result = rpccli_netlogon_getdcname(cli, mem_ctx, domain->dcname,
+       result = rpccli_netlogon_getdcname(netlogon_pipe, mem_ctx, domain->dcname,
                                           domain->name, tmp);
 
        talloc_destroy(mem_ctx);
@@ -156,13 +152,18 @@ static BOOL get_dc_name_via_netlogon(const struct winbindd_domain *domain,
 
        /* cli_netlogon_getdcname gives us a name with \\ */
        p = tmp;
-       if (*p == '\\') p+=1;
-       if (*p == '\\') p+=1;
+       if (*p == '\\') {
+               p+=1;
+       }
+       if (*p == '\\') {
+               p+=1;
+       }
 
        fstrcpy(dcname, p);
 
-       if (!resolve_name(dcname, dc_ip, 0x20))
+       if (!resolve_name(dcname, dc_ip, 0x20)) {
                return False;
+       }
 
        return True;
 }
@@ -178,7 +179,7 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
                                      struct cli_state **cli,
                                      BOOL *retry)
 {
-       char *machine_password, *machine_krb5_principal;
+       char *machine_password, *machine_krb5_principal, *machine_account;
        char *ipc_username, *ipc_domain, *ipc_password;
 
        BOOL got_mutex;
@@ -194,8 +195,14 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
        machine_password = secrets_fetch_machine_password(lp_workgroup(), NULL,
                                                          NULL);
        
+       if (asprintf(&machine_account, "%s$", global_myname()) == -1) {
+               SAFE_FREE(machine_password);
+               return NT_STATUS_NO_MEMORY;
+       }
+
        if (asprintf(&machine_krb5_principal, "%s$@%s", global_myname(),
                     lp_realm()) == -1) {
+               SAFE_FREE(machine_account);
                SAFE_FREE(machine_password);
                return NT_STATUS_NO_MEMORY;
        }
@@ -257,33 +264,61 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
                goto done;
        }
 
-       /* Krb5 session */
                        
-       if ((lp_security() == SEC_ADS) 
-           && ((*cli)->protocol >= PROTOCOL_NT1 &&
-               (*cli)->capabilities & CAP_EXTENDED_SECURITY)) {
-
+       if ((*cli)->protocol >= PROTOCOL_NT1 && (*cli)->capabilities & CAP_EXTENDED_SECURITY) {
                ADS_STATUS ads_status;
-               (*cli)->use_kerberos = True;
-               DEBUG(5, ("connecting to %s from %s with kerberos principal "
-                         "[%s]\n", controller, global_myname(),
-                         machine_krb5_principal));
+
+               if (lp_security() == SEC_ADS) {
+
+                       /* Try a krb5 session */
+
+                       (*cli)->use_kerberos = True;
+                       DEBUG(5, ("connecting to %s from %s with kerberos principal "
+                                 "[%s]\n", controller, global_myname(),
+                                 machine_krb5_principal));
+
+                       ads_status = cli_session_setup_spnego(*cli,
+                                                             machine_krb5_principal, 
+                                                             machine_password, 
+                                                             lp_workgroup());
+
+                       if (!ADS_ERR_OK(ads_status)) {
+                               DEBUG(4,("failed kerberos session setup with %s\n",
+                                        ads_errstr(ads_status)));
+                       }
+
+                       result = ads_ntstatus(ads_status);
+                       if (NT_STATUS_IS_OK(result)) {
+                               /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
+                               cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
+                               goto session_setup_done;
+                       }
+               }
+
+               /* Fall back to non-kerberos session setup using NTLMSSP SPNEGO with the machine account. */
+               (*cli)->use_kerberos = False;
+
+               DEBUG(5, ("connecting to %s from %s with username "
+                         "[%s]\\[%s]\n",  controller, global_myname(),
+                         machine_account, machine_password));
 
                ads_status = cli_session_setup_spnego(*cli,
-                                                     machine_krb5_principal
+                                                     machine_account
                                                      machine_password, 
                                                      lp_workgroup());
-
-               if (!ADS_ERR_OK(ads_status))
-                       DEBUG(4,("failed kerberos session setup with %s\n",
-                                ads_errstr(ads_status)));
+               if (!ADS_ERR_OK(ads_status)) {
+                       DEBUG(4, ("authenticated session setup failed with %s\n",
+                               ads_errstr(ads_status)));
+               }
 
                result = ads_ntstatus(ads_status);
+               if (NT_STATUS_IS_OK(result)) {
+                       /* Ensure creds are stored for NTLMSSP authenticated pipe access. */
+                       cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password);
+                       goto session_setup_done;
+               }
        }
 
-       if (NT_STATUS_IS_OK(result))
-               goto session_setup_done;
-
        /* Fall back to non-kerberos session setup */
 
        (*cli)->use_kerberos = False;
@@ -301,8 +336,12 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
                                      ipc_password, strlen(ipc_password)+1,
                                      ipc_password, strlen(ipc_password)+1,
                                      ipc_domain)) {
-                       DEBUG(5, ("authenticated session setup failed\n"));
+                       /* Successful logon with given username. */
+                       cli_init_creds(*cli, ipc_username, ipc_domain, ipc_password);
                        goto session_setup_done;
+               } else {
+                       DEBUG(4, ("authenticated session setup with user %s\\%s failed.\n",
+                               ipc_domain, ipc_username ));
                }
        }
 
@@ -310,6 +349,7 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
 
        if (cli_session_setup(*cli, "", NULL, 0, NULL, 0, "")) {
                DEBUG(5, ("Connected anonymously\n"));
+               cli_init_creds(*cli, "", "", "");
                goto session_setup_done;
        }
 
@@ -342,26 +382,28 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain,
        *retry = False;
 
        /* set the domain if empty; needed for schannel connections */
-       if ( !*(*cli)->domain )
+       if ( !*(*cli)->domain ) {
                fstrcpy( (*cli)->domain, domain->name );
-
-       (*cli)->pipe_auth_flags = 0;
+       }
 
        result = NT_STATUS_OK;
        add_failed_connection = False;
 
  done:
-       if (got_mutex)
+       if (got_mutex) {
                secrets_named_mutex_release(controller);
+       }
 
+       SAFE_FREE(machine_account);
        SAFE_FREE(machine_password);
        SAFE_FREE(machine_krb5_principal);
        SAFE_FREE(ipc_username);
        SAFE_FREE(ipc_domain);
        SAFE_FREE(ipc_password);
 
-       if (add_failed_connection)
+       if (add_failed_connection) {
                add_failed_connection_entry(domain->name, controller, result);
+       }
 
        return result;
 }
@@ -721,7 +763,7 @@ static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
        for (retries = 0; retries < 3; retries++) {
 
                int fd = -1;
-               BOOL retry;
+               BOOL retry = False;
 
                result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
 
@@ -758,27 +800,23 @@ static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
 void invalidate_cm_connection(struct winbindd_cm_conn *conn)
 {
        if (conn->samr_pipe != NULL) {
-               cli_rpc_close(conn->samr_pipe);
+               cli_rpc_pipe_close(conn->samr_pipe);
                conn->samr_pipe = NULL;
        }
 
        if (conn->lsa_pipe != NULL) {
-               cli_rpc_close(conn->lsa_pipe);
+               cli_rpc_pipe_close(conn->lsa_pipe);
                conn->lsa_pipe = NULL;
        }
 
-       if (conn->netlogon_auth2_pipe != NULL) {
-               cli_rpc_close(conn->netlogon_auth2_pipe);
-               conn->netlogon_auth2_pipe = NULL;
-       }
-
        if (conn->netlogon_pipe != NULL) {
-               cli_rpc_close(conn->netlogon_pipe);
+               cli_rpc_pipe_close(conn->netlogon_pipe);
                conn->netlogon_pipe = NULL;
        }
 
-       if (conn->cli)
+       if (conn->cli) {
                cli_shutdown(conn->cli);
+       }
 
        conn->cli = NULL;
 }
@@ -872,7 +910,7 @@ void set_dc_type_and_flags( struct winbindd_domain *domain )
                return;
        }
 
-       cli = cli_rpc_open_noauth(domain->conn.cli, PI_LSARPC_DS);
+       cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC_DS, &result);
 
        if (cli == NULL) {
                DEBUG(5, ("set_dc_type_and_flags: Could not bind to "
@@ -885,7 +923,7 @@ void set_dc_type_and_flags( struct winbindd_domain *domain )
        result = rpccli_ds_getprimarydominfo(cli, cli->cli->mem_ctx,
                                             DsRolePrimaryDomainInfoBasic,
                                             &ctr);
-       cli_rpc_close(cli);
+       cli_rpc_pipe_close(cli);
 
        if (!NT_STATUS_IS_OK(result)) {
                domain->initialized = True;
@@ -896,7 +934,7 @@ void set_dc_type_and_flags( struct winbindd_domain *domain )
            !(ctr.basic->flags & DSROLE_PRIMARY_DS_MIXED_MODE) )
                domain->native_mode = True;
 
-       cli = cli_rpc_open_noauth(domain->conn.cli, PI_LSARPC);
+       cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC, &result);
 
        if (cli == NULL) {
                domain->initialized = True;
@@ -907,6 +945,7 @@ void set_dc_type_and_flags( struct winbindd_domain *domain )
                              domain->name);
        if (!mem_ctx) {
                DEBUG(1, ("set_dc_type_and_flags: talloc_init() failed\n"));
+               cli_rpc_pipe_close(cli);
                return;
        }
 
@@ -956,7 +995,7 @@ void set_dc_type_and_flags( struct winbindd_domain *domain )
        }
 done:
 
-       cli_rpc_close(cli);
+       cli_rpc_pipe_close(cli);
        
        talloc_destroy(mem_ctx);
 
@@ -965,20 +1004,28 @@ done:
        return;
 }
 
-static BOOL cm_get_schannel_key(struct winbindd_domain *domain,
-                               TALLOC_CTX *mem_ctx,
-                               unsigned char **session_key)
+#ifndef DISABLE_SCHANNEL_WIN2K3_SP1
+static BOOL cm_get_schannel_dcinfo(struct winbindd_domain *domain, struct dcinfo **ppdc)
 {
-       struct rpc_pipe_client *cli;
-       DOM_CRED *credentials;
+       NTSTATUS result;
+       struct rpc_pipe_client *netlogon_pipe;
 
-       if (lp_client_schannel() == False)
+       if (lp_client_schannel() == False) {
                return False;
+       }
 
-       return NT_STATUS_IS_OK(cm_connect_netlogon(domain, mem_ctx,
-                                                  &cli, session_key,
-                                                  &credentials));
+       result = cm_connect_netlogon(domain, &netlogon_pipe);
+       if (!NT_STATUS_IS_OK(result)) {
+               return False;
+       }
+
+       /* Return a pointer to the struct dcinfo from the
+          netlogon pipe. */
+
+       *ppdc = domain->conn.netlogon_pipe->dc;
+       return True;
 }
+#endif
 
 NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
                        struct rpc_pipe_client **cli, POLICY_HND *sam_handle)
@@ -987,24 +1034,85 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
        NTSTATUS result;
 
        result = init_dc_connection(domain);
-       if (!NT_STATUS_IS_OK(result))
+       if (!NT_STATUS_IS_OK(result)) {
                return result;
+       }
 
        conn = &domain->conn;
 
        if (conn->samr_pipe == NULL) {
+               /*
+                * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO
+                * authenticated sign and sealed pipe using the machine
+                * account password by preference. If we can't - try schannel,
+                * if that fails, try anonymous.
+                */
+
+               fstring conn_pwd;
+               pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
+               if (conn->cli->user_name[0] && conn->cli->domain[0] &&
+                   conn_pwd[0]) {
+                       /* We have an authenticated connection. Use
+                          a NTLMSSP SPNEGO authenticated SAMR pipe with
+                          sign & seal. */
+                       conn->samr_pipe =
+                               cli_rpc_pipe_open_spnego_ntlmssp(conn->cli,
+                                                                PI_SAMR,
+                                                                PIPE_AUTH_LEVEL_PRIVACY,
+                                                                conn->cli->domain,
+                                                                conn->cli->user_name,
+                                                                conn_pwd,
+                                                                &result);
+                       if (conn->samr_pipe == NULL) {
+                               DEBUG(10,("cm_connect_sam: failed to connect "
+                                         "to SAMR pipe for domain %s using "
+                                         "NTLMSSP authenticated pipe: user "
+                                         "%s\\%s. Error was %s\n",
+                                         domain->name, conn->cli->domain,
+                                         conn->cli->user_name,
+                                         nt_errstr(result)));
+                       } else {
+                               DEBUG(10,("cm_connect_sam: connected to SAMR "
+                                         "pipe for domain %s using NTLMSSP "
+                                         "authenticated pipe: user %s\\%s\n",
+                                         domain->name, conn->cli->domain,
+                                         conn->cli->user_name ));
+                       }
+               }
+
 #ifndef DISABLE_SCHANNEL_WIN2K3_SP1
-               unsigned char *session_key;
-
-               if (cm_get_schannel_key(domain, mem_ctx, &session_key))
-                       conn->samr_pipe = cli_rpc_open_schannel(conn->cli,
-                                                               PI_SAMR,
-                                                               session_key,
-                                                               domain->name);
-               else
+               /* Fall back to schannel if it's a W2K pre-SP1 box. */
+               if (conn->samr_pipe == NULL) {
+                       struct dcinfo *p_dcinfo;
+
+                       if (cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
+                               conn->samr_pipe =
+                                       cli_rpc_pipe_open_schannel_with_key(conn->cli,
+                                                                           PI_SAMR,
+                                                                           PIPE_AUTH_LEVEL_PRIVACY,
+                                                                           domain->name,
+                                                                           p_dcinfo,
+                                                                           &result);
+                       }
+                       if (conn->samr_pipe == NULL) {
+                               DEBUG(10,("cm_connect_sam: failed to connect "
+                                         "to SAMR pipe for domain %s using "
+                                         "schannel authenticated. Error "
+                                         "was %s\n", domain->name,
+                                         nt_errstr(result) ));
+                       } else {
+                               DEBUG(10,("cm_connect_sam: connected to SAMR "
+                                         "pipe for domain %s using schannel.\n",
+                                         domain->name ));
+                       }
+               }
 #endif /* DISABLE_SCHANNEL_WIN2K3_SP1 */
-                       conn->samr_pipe = cli_rpc_open_noauth(conn->cli,
-                                                             PI_SAMR);
+
+               /* Finally fall back to anonymous. */
+               if (conn->samr_pipe == NULL) {
+                       conn->samr_pipe =
+                               cli_rpc_pipe_open_noauth(conn->cli, PI_SAMR, &result);
+               }
 
                if (conn->samr_pipe == NULL) {
                        result = NT_STATUS_PIPE_NOT_AVAILABLE;
@@ -1014,8 +1122,12 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
                result = rpccli_samr_connect(conn->samr_pipe, mem_ctx,
                                             SEC_RIGHTS_MAXIMUM_ALLOWED,
                                             &conn->sam_connect_handle);
-               if (!NT_STATUS_IS_OK(result))
+               if (!NT_STATUS_IS_OK(result)) {
+                       DEBUG(10,("cm_connect_sam: rpccli_samr_connect failed "
+                                 "for domain %s Error was %s\n",
+                                 domain->name, nt_errstr(result) ));
                        goto done;
+               }
 
                result = rpccli_samr_open_domain(conn->samr_pipe,
                                                 mem_ctx,
@@ -1026,9 +1138,10 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
        }
 
  done:
+
        if (!NT_STATUS_IS_OK(result)) {
                invalidate_cm_connection(conn);
-               return NT_STATUS_UNSUCCESSFUL;
+               return result;
        }
 
        *cli = conn->samr_pipe;
@@ -1049,18 +1162,72 @@ NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
        conn = &domain->conn;
 
        if (conn->lsa_pipe == NULL) {
+               fstring conn_pwd;
+               pwd_get_cleartext(&conn->cli->pwd, conn_pwd);
+               if (conn->cli->user_name[0] && conn->cli->domain[0] &&
+                   conn_pwd[0]) {
+                       /* We have an authenticated connection. Use
+                          a NTLMSSP SPNEGO authenticated LSA pipe with
+                          sign & seal. */
+                       conn->lsa_pipe = 
+                               cli_rpc_pipe_open_spnego_ntlmssp(conn->cli,
+                                                                PI_LSARPC,
+                                                                PIPE_AUTH_LEVEL_PRIVACY,
+                                                                conn->cli->domain,
+                                                                conn->cli->user_name,
+                                                                conn_pwd,
+                                                                &result);
+                       if (conn->lsa_pipe == NULL) {
+                               DEBUG(10,("cm_connect_lsa: failed to connect "
+                                         "to LSA pipe for domain %s using "
+                                         "NTLMSSP authenticated pipe: user "
+                                         "%s\\%s. Error was %s\n",
+                                         domain->name, conn->cli->domain,
+                                         conn->cli->user_name,
+                                         nt_errstr(result)));
+                       } else {
+                               DEBUG(10,("cm_connect_lsa: connected to LSA "
+                                         "pipe for domain %s using NTLMSSP "
+                                         "authenticated pipe: user %s\\%s\n",
+                                         domain->name, conn->cli->domain,
+                                         conn->cli->user_name ));
+                       }
+               }
+               
 #ifndef DISABLE_SCHANNEL_WIN2K3_SP1
-               unsigned char *session_key;
-
-               if (cm_get_schannel_key(domain, mem_ctx, &session_key))
-                       conn->lsa_pipe = cli_rpc_open_schannel(conn->cli,
-                                                              PI_LSARPC,
-                                                              session_key,
-                                                              domain->name);
-               else
+               /* Fall back to schannel if it's a W2K pre-SP1 box. */
+               if (conn->lsa_pipe == NULL) {
+                       struct dcinfo *p_dcinfo;
+
+                       if (cm_get_schannel_dcinfo(domain, &p_dcinfo)) {
+                               conn->lsa_pipe =
+                                       cli_rpc_pipe_open_schannel_with_key(conn->cli,
+                                                                           PI_LSARPC,
+                                                                           PIPE_AUTH_LEVEL_PRIVACY,
+                                                                           domain->name,
+                                                                           p_dcinfo,
+                                                                           &result);
+                       }
+                       if (conn->lsa_pipe == NULL) {
+                               DEBUG(10,("cm_connect_lsa: failed to connect "
+                                         "to LSA pipe for domain %s using "
+                                         "schannel authenticated. Error "
+                                         "was %s\n", domain->name,
+                                         nt_errstr(result) ));
+                       } else {
+                               DEBUG(10,("cm_connect_lsa: connected to LSA "
+                                         "pipe for domain %s using schannel.\n",
+                                         domain->name ));
+                       }
+               }
 #endif /* DISABLE_SCHANNEL_WIN2K3_SP1 */
-                       conn->lsa_pipe = cli_rpc_open_noauth(conn->cli,
-                                                            PI_LSARPC);
+
+               /* Finally fall back to anonymous. */
+               if (conn->lsa_pipe == NULL) {
+                       conn->lsa_pipe = cli_rpc_pipe_open_noauth(conn->cli,
+                                                               PI_LSARPC,
+                                                               &result);
+               }
 
                if (conn->lsa_pipe == NULL) {
                        result = NT_STATUS_PIPE_NOT_AVAILABLE;
@@ -1083,55 +1250,12 @@ NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx,
        return result;
 }
 
-/*******************************************************************
- wrapper around retrieving the trust account password
-*******************************************************************/
+/****************************************************************************
+ Open the netlogon pipe to this DC. Use schannel if specified in client conf.
+ session key stored in conn->netlogon_pipe->dc->sess_key.
+****************************************************************************/
 
-static BOOL get_trust_pw(const char *domain, uint8 ret_pwd[16],
-                        uint32 *channel)
-{
-       DOM_SID sid;
-       char *pwd;
-       time_t last_set_time;
-
-       /* if we are a DC and this is not our domain, then lookup an account
-          for the domain trust */
-
-       if ( IS_DC && !strequal(domain, lp_workgroup()) &&
-            lp_allow_trusted_domains() ) {
-
-               if (!secrets_fetch_trusted_domain_password(domain, &pwd, &sid,
-                                                          &last_set_time)) {
-                       DEBUG(0, ("get_trust_pw: could not fetch trust "
-                                 "account password for trusted domain %s\n",
-                                 domain));
-                       return False;
-               }
-
-               *channel = SEC_CHAN_DOMAIN;
-               E_md4hash(pwd, ret_pwd);
-               SAFE_FREE(pwd);
-
-               return True;
-       }
-
-       /* Just get the account for the requested domain. In the future this
-        * might also cover to be member of more than one domain. */
-
-       if (secrets_fetch_trust_account_password(domain, ret_pwd,
-                                                &last_set_time, channel))
-               return True;
-
-       DEBUG(5, ("get_trust_pw: could not fetch trust account "
-                 "password for domain %s\n", domain));
-       return False;
-}
-
-NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
-                            TALLOC_CTX *mem_ctx,
-                            struct rpc_pipe_client **cli,
-                            unsigned char **session_key,
-                            DOM_CRED **credentials)
+NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, struct rpc_pipe_client **cli)
 {
        struct winbindd_cm_conn *conn;
        NTSTATUS result;
@@ -1139,119 +1263,100 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain,
        uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS;
        uint8  mach_pwd[16];
        uint32  sec_chan_type;
-       DOM_CHAL clnt_chal, srv_chal, rcv_chal;
-       const char *server_name;
        const char *account_name;
-       UTIME zerotime;
+       struct rpc_pipe_client *netlogon_pipe;
 
        result = init_dc_connection(domain);
-       if (!NT_STATUS_IS_OK(result))
+       if (!NT_STATUS_IS_OK(result)) {
                return result;
+       }
 
        conn = &domain->conn;
 
        if (conn->netlogon_pipe != NULL) {
                *cli = conn->netlogon_pipe;
-               *session_key = (unsigned char *)&conn->sess_key;
-               *credentials = &conn->clnt_cred;
                return NT_STATUS_OK;
        }
 
-       if (!get_trust_pw(domain->name, mach_pwd, &sec_chan_type))
+       if (!get_trust_pw(domain->name, mach_pwd, &sec_chan_type)) {
                return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
+       }
 
-       conn->netlogon_auth2_pipe = cli_rpc_open_noauth(conn->cli,
-                                                       PI_NETLOGON);
-       if (conn->netlogon_auth2_pipe == NULL)
-               return NT_STATUS_UNSUCCESSFUL;
+       netlogon_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_NETLOGON, &result);
+       if (netlogon_pipe == NULL) {
+               return result;
+       }
 
-       if (lp_client_schannel() != False)
+       if (lp_client_schannel() != False) {
                neg_flags |= NETLOGON_NEG_SCHANNEL;
-
-       generate_random_buffer(clnt_chal.data, 8);
-
-       server_name = talloc_asprintf(mem_ctx, "\\\\%s", domain->dcname);
+       }
 
        /* if we are a DC and this is a trusted domain, then we need to use our
           domain name in the net_req_auth2() request */
 
-       if ( IS_DC 
+       if ( IS_DC
                && !strequal(domain->name, lp_workgroup())
                && lp_allow_trusted_domains() ) 
        {
-               account_name = talloc_asprintf( mem_ctx, "%s$", lp_workgroup() );
-       }
-       else {
-               account_name = talloc_asprintf(mem_ctx, "%s$", 
-                       domain->primary ?  global_myname() : domain->name);
+               account_name = lp_workgroup();
+       } else {
+               account_name = domain->primary ? global_myname() : domain->name;
        }
 
-       if ((server_name == NULL) || (account_name == NULL))
+       if (account_name == NULL) {
+               cli_rpc_pipe_close(netlogon_pipe);
                return NT_STATUS_NO_MEMORY;
+       }
 
-       result = rpccli_net_req_chal(conn->netlogon_auth2_pipe, server_name,
-                                    global_myname(), &clnt_chal, &srv_chal);
-       if (!NT_STATUS_IS_OK(result))
-               return result;
-
-       /**************** Long-term Session key **************/
-
-       /* calculate the session key */
-       cred_session_key(&clnt_chal, &srv_chal, mach_pwd, conn->sess_key);
-       memset((char *)conn->sess_key+8, '\0', 8);
-
-       /* calculate auth2 credentials */
-       zerotime.time = 0;
-       cred_create(conn->sess_key, &clnt_chal, zerotime,
-                   &conn->clnt_cred.challenge);
-
-       result = rpccli_net_auth2(conn->netlogon_auth2_pipe, server_name,
-                                 account_name, sec_chan_type, global_myname(),
-                                 &conn->clnt_cred.challenge, &neg_flags,
-                                 &rcv_chal);
+       result = rpccli_netlogon_setup_creds(netlogon_pipe,
+                                               domain->dcname, /* server name. */
+                                               domain->name,   /* domain name */
+                                               account_name,   /* machine account */
+                                               mach_pwd,       /* machine password */
+                                               sec_chan_type,  /* from get_trust_pw */
+                                               &neg_flags);
 
-       if (!NT_STATUS_IS_OK(result))
+       if (!NT_STATUS_IS_OK(result)) {
+               cli_rpc_pipe_close(netlogon_pipe);
                return result;
-
-       zerotime.time = 0;
-       if (!cred_assert(&rcv_chal, conn->sess_key, &srv_chal, zerotime)) {
-               DEBUG(0, ("Server replied with bad credential\n"));
-               return NT_STATUS_ACCESS_DENIED;
        }
 
        if ((lp_client_schannel() == True) &&
-           ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
+                       ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
                DEBUG(3, ("Server did not offer schannel\n"));
-               cli_rpc_close(conn->netlogon_auth2_pipe);
-               conn->netlogon_auth2_pipe = NULL;
+               cli_rpc_pipe_close(netlogon_pipe);
                return NT_STATUS_ACCESS_DENIED;
        }
 
        if ((lp_client_schannel() == False) ||
-           ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
-               /* keep the existing connection to NETLOGON open */
-               conn->netlogon_pipe = conn->netlogon_auth2_pipe;
-               conn->netlogon_auth2_pipe = NULL;
+                       ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
+               /* We're done - just keep the existing connection to NETLOGON open */
+               conn->netlogon_pipe = netlogon_pipe;
                *cli = conn->netlogon_pipe;
-               *session_key = (unsigned char *)&conn->sess_key;
-               *credentials = &conn->clnt_cred;
                return NT_STATUS_OK;
        }
 
-       conn->netlogon_pipe = cli_rpc_open_schannel(conn->cli, PI_NETLOGON,
-                                                   conn->sess_key,
-                                                   domain->name);
+       /* Using the credentials from the first pipe, open a signed and sealed
+          second netlogon pipe. The session key is stored in the schannel
+          part of the new pipe auth struct.
+       */
+
+       conn->netlogon_pipe = cli_rpc_pipe_open_schannel_with_key(conn->cli,
+                                               PI_NETLOGON,
+                                               PIPE_AUTH_LEVEL_PRIVACY,
+                                               domain->name,
+                                               netlogon_pipe->dc,
+                                               &result);
+
+       /* We can now close the initial netlogon pipe. */
+       cli_rpc_pipe_close(netlogon_pipe);
 
        if (conn->netlogon_pipe == NULL) {
-               DEBUG(3, ("Could not open schannel'ed NETLOGON pipe\n"));
-               cli_rpc_close(conn->netlogon_auth2_pipe);
-               conn->netlogon_auth2_pipe = NULL;
-               return NT_STATUS_ACCESS_DENIED;
+               DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error was %s\n",
+                       nt_errstr(result)));
+               return result;
        }
 
        *cli = conn->netlogon_pipe;
-       *session_key = (unsigned char *)&conn->sess_key;
-       *credentials = &conn->clnt_cred;
-               
        return NT_STATUS_OK;
 }
index ec0b7a36e2fb976fb192efa503c49cb763e024e2..60b7411417226b2b65fadc67f90da5e91b35deb9 100644 (file)
 
 /* Read some data from a client connection */
 
-static void dual_client_read(struct winbindd_cli_state *state)
+static void child_read_request(struct winbindd_cli_state *state)
 {
-       int n;
-    
+       ssize_t len;
+
        /* Read data */
 
-       n = sys_read(state->sock, state->read_buf_len + 
-                (char *)&state->request, 
-                sizeof(state->request) - state->read_buf_len);
-       
-       DEBUG(10,("client_read: read %d bytes. Need %ld more for a full "
-                 "request.\n", n, (unsigned long)(sizeof(state->request) - n -
-                                                  state->read_buf_len) ));
+       len = read_data(state->sock, (char *)&state->request,
+                       sizeof(state->request));
 
-       /* Read failed, kill client */
-       
-       if (n == -1 || n == 0) {
-               DEBUG(5,("read failed on sock %d, pid %lu: %s\n",
-                        state->sock, (unsigned long)state->pid, 
-                        (n == -1) ? strerror(errno) : "EOF"));
-               
+       if (len != sizeof(state->request)) {
+               DEBUG(0, ("Got invalid request length: %d\n", (int)len));
+               state->finished = True;
+               return;
+       }
+
+       if (state->request.extra_len == 0) {
+               state->request.extra_data = NULL;
+               return;
+       }
+
+       DEBUG(10, ("Need to read %d extra bytes\n", (int)state->request.extra_len));
+
+       state->request.extra_data =
+               SMB_MALLOC_ARRAY(char, state->request.extra_len + 1);
+
+       if (state->request.extra_data == NULL) {
+               DEBUG(0, ("malloc failed\n"));
+               state->finished = True;
+               return;
+       }
+
+       /* Ensure null termination */
+       state->request.extra_data[state->request.extra_len] = '\0';
+
+       len = read_data(state->sock, state->request.extra_data,
+                       state->request.extra_len);
+
+       if (len != state->request.extra_len) {
+               DEBUG(0, ("Could not read extra data\n"));
                state->finished = True;
                return;
        }
-       
-       /* Update client state */
-       
-       state->read_buf_len += n;
-       state->last_access = time(NULL);
 }
 
 /*
@@ -86,6 +99,7 @@ struct winbindd_async_request {
        void *private_data;
 };
 
+static void async_main_request_sent(void *private_data, BOOL success);
 static void async_request_sent(void *private_data, BOOL success);
 static void async_reply_recv(void *private_data, BOOL success);
 static void schedule_async_request(struct winbindd_child *child);
@@ -122,7 +136,7 @@ void async_request(TALLOC_CTX *mem_ctx, struct winbindd_child *child,
        return;
 }
 
-static void async_request_sent(void *private_data, BOOL success)
+static void async_main_request_sent(void *private_data, BOOL success)
 {
        struct winbindd_async_request *state =
                talloc_get_type_abort(private_data, struct winbindd_async_request);
@@ -136,6 +150,30 @@ static void async_request_sent(void *private_data, BOOL success)
                return;
        }
 
+       if (state->request->extra_len == 0) {
+               async_request_sent(private_data, True);
+               return;
+       }
+
+       setup_async_write(&state->child->event, state->request->extra_data,
+                         state->request->extra_len,
+                         async_request_sent, state);
+}
+
+static void async_request_sent(void *private_data_data, BOOL success)
+{
+       struct winbindd_async_request *state =
+               talloc_get_type_abort(private_data_data, struct winbindd_async_request);
+
+       if (!success) {
+               DEBUG(5, ("Could not send async request\n"));
+
+               state->response->length = sizeof(struct winbindd_response);
+               state->response->result = WINBINDD_ERROR;
+               state->continuation(state->private_data, False);
+               return;
+       }
+
        /* Request successfully sent to the child, setup the wait for reply */
 
        setup_async_read(&state->child->event,
@@ -196,7 +234,7 @@ static void schedule_async_request(struct winbindd_child *child)
 
        setup_async_write(&child->event, request->request,
                          sizeof(*request->request),
-                         async_request_sent, request);
+                         async_main_request_sent, request);
        return;
 }
 
@@ -205,31 +243,31 @@ struct domain_request_state {
        struct winbindd_domain *domain;
        struct winbindd_request *request;
        struct winbindd_response *response;
-       void (*continuation)(void *private_data, BOOL success);
-       void *private_data;
+       void (*continuation)(void *private_data_data, BOOL success);
+       void *private_data_data;
 };
 
-static void domain_init_recv(void *private_data, BOOL success);
+static void domain_init_recv(void *private_data_data, BOOL success);
 
 void async_domain_request(TALLOC_CTX *mem_ctx,
                          struct winbindd_domain *domain,
                          struct winbindd_request *request,
                          struct winbindd_response *response,
-                         void (*continuation)(void *private_data, BOOL success),
-                         void *private_data)
+                         void (*continuation)(void *private_data_data, BOOL success),
+                         void *private_data_data)
 {
        struct domain_request_state *state;
 
        if (domain->initialized) {
                async_request(mem_ctx, &domain->child, request, response,
-                             continuation, private_data);
+                             continuation, private_data_data);
                return;
        }
 
        state = TALLOC_P(mem_ctx, struct domain_request_state);
        if (state == NULL) {
                DEBUG(0, ("talloc failed\n"));
-               continuation(private_data, False);
+               continuation(private_data_data, False);
                return;
        }
 
@@ -238,15 +276,15 @@ void async_domain_request(TALLOC_CTX *mem_ctx,
        state->request = request;
        state->response = response;
        state->continuation = continuation;
-       state->private_data = private_data;
+       state->private_data_data = private_data_data;
 
        init_child_connection(domain, domain_init_recv, state);
 }
 
-static void recvfrom_child(void *private_data, BOOL success)
+static void recvfrom_child(void *private_data_data, BOOL success)
 {
        struct winbindd_cli_state *state =
-               talloc_get_type_abort(private_data, struct winbindd_cli_state);
+               talloc_get_type_abort(private_data_data, struct winbindd_cli_state);
        enum winbindd_result result = state->response.result;
 
        /* This is an optimization: The child has written directly to the
@@ -278,20 +316,20 @@ void sendto_domain(struct winbindd_cli_state *state,
                             recvfrom_child, state);
 }
 
-static void domain_init_recv(void *private_data, BOOL success)
+static void domain_init_recv(void *private_data_data, BOOL success)
 {
        struct domain_request_state *state =
-               talloc_get_type_abort(private_data, struct domain_request_state);
+               talloc_get_type_abort(private_data_data, struct domain_request_state);
 
        if (!success) {
                DEBUG(5, ("Domain init returned an error\n"));
-               state->continuation(state->private_data, False);
+               state->continuation(state->private_data_data, False);
                return;
        }
 
        async_request(state->mem_ctx, &state->domain->child,
                      state->request, state->response,
-                     state->continuation, state->private_data);
+                     state->continuation, state->private_data_data);
 }
 
 struct winbindd_child_dispatch_table {
@@ -466,39 +504,34 @@ static BOOL fork_domain_child(struct winbindd_child *child)
                main_loop_talloc_free();
 
                /* fetch a request from the main daemon */
-               dual_client_read(&state);
+               child_read_request(&state);
 
                if (state.finished) {
                        /* we lost contact with our parent */
                        exit(0);
                }
 
-               /* process full rquests */
-               if (state.read_buf_len == sizeof(state.request)) {
-                       DEBUG(4,("child daemon request %d\n",
-                                (int)state.request.cmd));
+               DEBUG(4,("child daemon request %d\n", (int)state.request.cmd));
 
-                       ZERO_STRUCT(state.response);
-                       state.request.null_term = '\0';
-                       child_process_request(child->domain, &state);
+               ZERO_STRUCT(state.response);
+               state.request.null_term = '\0';
+               child_process_request(child->domain, &state);
 
-                       cache_store_response(sys_getpid(), &state.response);
+               SAFE_FREE(state.request.extra_data);
 
-                       SAFE_FREE(state.response.extra_data);
+               cache_store_response(sys_getpid(), &state.response);
 
-                       /* We just send the result code back, the result
-                        * structure needs to be fetched via the
-                        * winbindd_cache. Hmm. That needs fixing... */
+               SAFE_FREE(state.response.extra_data);
 
-                       if (write_data(state.sock,
-                                      (void *)&state.response.result,
-                                      sizeof(state.response.result)) !=
-                           sizeof(state.response.result)) {
-                               DEBUG(0, ("Could not write result\n"));
-                               exit(1);
-                       }
+               /* We just send the result code back, the result
+                * structure needs to be fetched via the
+                * winbindd_cache. Hmm. That needs fixing... */
 
-                       state.read_buf_len = 0;
+               if (write_data(state.sock, (void *)&state.response.result,
+                              sizeof(state.response.result)) !=
+                   sizeof(state.response.result)) {
+                       DEBUG(0, ("Could not write result\n"));
+                       exit(1);
                }
        }
 }
index 6261dfb6165c6df1af0ddf3551bc449fba40a146..c52ee2d960c5d1c1f8e9b72630ce7cfc98a7edad 100644 (file)
@@ -1150,10 +1150,10 @@ enum winbindd_result winbindd_dual_getuserdomgroups(struct winbindd_domain *doma
        DOM_SID user_sid;
        NTSTATUS status;
 
-       int i, num_groups;
-       size_t bufsize;
-       ssize_t len;
+       char *sidstring;
+       size_t len;
        DOM_SID *groups;
+       int num_groups;
 
        /* Ensure null termination */
        state->request.data.sid[sizeof(state->request.data.sid)-1]='\0';
@@ -1176,22 +1176,15 @@ enum winbindd_result winbindd_dual_getuserdomgroups(struct winbindd_domain *doma
                return WINBINDD_OK;
        }
 
-       len=bufsize=0;
-       state->response.extra_data = NULL;
-
-       for (i=0; i<num_groups; i++) {
-               sprintf_append(NULL, (char **)&state->response.extra_data,
-                              &len, &bufsize,
-                              "%s\n", sid_string_static(&groups[i]));
-       }
-
-       if (state->response.extra_data == NULL) {
-               /* Hmmm. Allocation failed somewhere */
+       if (!print_sidlist(NULL, groups, num_groups, &sidstring, &len)) {
+               DEBUG(0, ("malloc failed\n"));
                return WINBINDD_ERROR;
        }
 
-       state->response.data.num_entries = num_groups;
+       state->response.extra_data = sidstring;
        state->response.length += len+1;
+       state->response.data.num_entries = num_groups;
 
        return WINBINDD_OK;
 }
+
index 6f72a0e2c63f69de88fe2311e2ba124177e464d2..83c4c0f6ee5e5b391d1b68bfcae2b5c1c1721959 100644 (file)
@@ -58,12 +58,8 @@ enum winbindd_result winbindd_dual_check_machine_acct(struct winbindd_domain *do
        invalidate_cm_connection(&contact_domain->conn);
 
        {
-               struct rpc_pipe_client *cli;
-               unsigned char *session_key;
-               DOM_CRED *creds;
-
-               result = cm_connect_netlogon(contact_domain, state->mem_ctx,
-                                            &cli, &session_key, &creds);
+               struct rpc_pipe_client *netlogon_pipe;
+               result = cm_connect_netlogon(contact_domain, &netlogon_pipe);
        }
 
         if (!NT_STATUS_IS_OK(result)) {
@@ -169,7 +165,7 @@ enum winbindd_result winbindd_dual_getdcname(struct winbindd_domain *domain,
 {
        fstring dcname_slash;
        char *p;
-       struct rpc_pipe_client *cli;
+       struct rpc_pipe_client *netlogon_pipe;
        NTSTATUS result;
 
        state->request.domain_name
@@ -178,21 +174,14 @@ enum winbindd_result winbindd_dual_getdcname(struct winbindd_domain *domain,
        DEBUG(3, ("[%5lu]: Get DC name for %s\n", (unsigned long)state->pid,
                  state->request.domain_name));
 
-       {
-               /* These var's can be ignored -- we're not requesting
-                  anything in the credential chain here */
-               unsigned char *session_key;
-               DOM_CRED *creds;
-               result = cm_connect_netlogon(domain, state->mem_ctx, &cli,
-                                            &session_key, &creds);
-       }
+       result = cm_connect_netlogon(domain, &netlogon_pipe);
 
        if (!NT_STATUS_IS_OK(result)) {
                DEBUG(1, ("Can't contact our the NETLOGON pipe\n"));
                return WINBINDD_ERROR;
        }
 
-       result = rpccli_netlogon_getdcname(cli, state->mem_ctx, domain->dcname,
+       result = rpccli_netlogon_getdcname(netlogon_pipe, state->mem_ctx, domain->dcname,
                                           state->request.domain_name,
                                           dcname_slash);
 
@@ -202,11 +191,14 @@ enum winbindd_result winbindd_dual_getdcname(struct winbindd_domain *domain,
        }
 
        p = dcname_slash;
-       if (*p == '\\') p+=1;
-       if (*p == '\\') p+=1;
+       if (*p == '\\') {
+               p+=1;
+       }
+       if (*p == '\\') {
+               p+=1;
+       }
 
        fstrcpy(state->response.data.dc_name, p);
-
        return WINBINDD_OK;
 }
 
index d012811d379b4f20e7f5409ade0c608ba31d1595..c1bb4b2600abbfe1aaa89712368ca016b1c0cd60 100644 (file)
@@ -175,6 +175,8 @@ typedef struct winbindd_gr {
 /* Flag to say this is a winbindd internal send - don't recurse. */
 #define WBFLAG_RECURSE                 0x0800
 
+#define WINBINDD_MAX_EXTRA_DATA (128*1024)
+
 /* Winbind request structure */
 
 struct winbindd_request {
@@ -183,7 +185,6 @@ struct winbindd_request {
        pid_t pid;               /* pid of calling process */
        uint32 flags;            /* flags relavant to a given request */
        fstring domain_name;    /* name of domain for which the request applies */
-       int msgid;
 
        union {
                fstring winsreq;     /* WINS request */
@@ -240,10 +241,9 @@ struct winbindd_request {
                        gid_t gid;
                        fstring sid;
                } dual_idmapset;
-               struct {
-                       fstring cache_key;
-               } dual_sidaliases;
        } data;
+       char *extra_data;
+       size_t extra_len;
        char null_term;
 };
 
index a0712144eeb5131682cfccbc7988f61745d2470a..c2324291a6389bca6f6098636239b8aed41a0a5a 100644 (file)
@@ -37,7 +37,7 @@ static NTSTATUS append_info3_as_ndr(TALLOC_CTX *mem_ctx,
        if (!prs_init(&ps, 256 /* Random, non-zero number */, mem_ctx, MARSHALL)) {
                return NT_STATUS_NO_MEMORY;
        }
-       if (!net_io_user_info3("", info3, &ps, 1, 3)) {
+       if (!net_io_user_info3("", info3, &ps, 1, 3, False)) {
                prs_mem_free(&ps);
                return NT_STATUS_UNSUCCESSFUL;
        }
@@ -227,15 +227,11 @@ enum winbindd_result winbindd_dual_pam_auth(struct winbindd_domain *domain,
 {
        NTSTATUS result;
        fstring name_domain, name_user;
-       const char *srv_name_slash;
         NET_USER_INFO_3 info3;
-       unsigned char *session_key;
-       struct rpc_pipe_client *pipe_cli;
+       struct rpc_pipe_client *netlogon_pipe;
        uchar chal[8];
        DATA_BLOB lm_resp;
        DATA_BLOB nt_resp;
-       DOM_CRED ret_creds;
-       DOM_CRED *credentials;
        int attempts = 0;
        unsigned char local_lm_response[24];
        unsigned char local_nt_response[24];
@@ -311,7 +307,6 @@ enum winbindd_result winbindd_dual_pam_auth(struct winbindd_domain *domain,
                                           local_nt_response, 
                                           sizeof(local_nt_response));
        }
-
        
        /* what domain should we contact? */
        
@@ -333,49 +328,30 @@ enum winbindd_result winbindd_dual_pam_auth(struct winbindd_domain *domain,
                contact_domain = find_our_domain();
        }
 
-       srv_name_slash = talloc_asprintf(state->mem_ctx, "\\\\%s",
-                                        contact_domain->dcname);
-       if (srv_name_slash == NULL) {
-               DEBUG(0, ("talloc_asprintf failed\n"));
-               return WINBINDD_ERROR;
-       }
-               
        /* check authentication loop */
 
        do {
-               DOM_CRED clnt_creds;
 
                ZERO_STRUCT(info3);
-               ZERO_STRUCT(ret_creds);
                retry = False;
 
-               result = cm_connect_netlogon(contact_domain, state->mem_ctx,
-                                            &pipe_cli, &session_key,
-                                            &credentials);
+               result = cm_connect_netlogon(contact_domain, &netlogon_pipe);
 
                if (!NT_STATUS_IS_OK(result)) {
                        DEBUG(3, ("could not open handle to NETLOGON pipe\n"));
                        goto done;
                }
 
-               credentials->timestamp.time = time(NULL);
-               memcpy(&clnt_creds, credentials, sizeof(clnt_creds));
-
-               /* Calculate the new credentials. */
-               cred_create(session_key, &credentials->challenge,
-                           clnt_creds.timestamp, &(clnt_creds.challenge));
-
-               result = rpccli_netlogon_sam_network_logon(pipe_cli,
-                                                          state->mem_ctx,
-                                                          srv_name_slash,
-                                                          &clnt_creds,
-                                                          &ret_creds,
-                                                          name_user,
-                                                          name_domain, 
-                                                          global_myname(),
-                                                          chal, lm_resp,
-                                                          nt_resp, &info3,
-                                                          session_key);
+               result = rpccli_netlogon_sam_network_logon(netlogon_pipe,
+                                                       state->mem_ctx,
+                                                       contact_domain->dcname, /* server name */
+                                                       name_user,              /* user name */
+                                                       name_domain,            /* target domain */
+                                                       global_myname(),        /* workstation */
+                                                       chal,
+                                                       lm_resp,
+                                                       nt_resp,
+                                                       &info3);
                attempts += 1;
 
                /* We have to try a second time as cm_connect_netlogon
@@ -404,21 +380,11 @@ enum winbindd_result winbindd_dual_pam_auth(struct winbindd_domain *domain,
                
        } while ( (attempts < 2) && retry );
 
-       /* Only check creds if we got a connection. */
-       if (contact_domain->conn.cli &&
-                       !(NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND) ||
-                               NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL))) {
-               if (!clnt_deal_with_creds(session_key, credentials, &ret_creds)) {
-                       DEBUG(3, ("DC %s sent wrong credentials\n",
-                               pipe_cli->cli->srv_name_slash));
-                       result = NT_STATUS_ACCESS_DENIED;
-               }
-       }
-
        if (NT_STATUS_IS_OK(result)) {
                /* Check if the user is in the right group */
 
-               if (!NT_STATUS_IS_OK(result = check_info3_in_group(state->mem_ctx, &info3, state->request.data.auth.require_membership_of_sid))) {
+               if (!NT_STATUS_IS_OK(result = check_info3_in_group(state->mem_ctx, &info3,
+                                       state->request.data.auth.require_membership_of_sid))) {
                        DEBUG(3, ("User %s is not in the required group (%s), so plaintext authentication is rejected\n",
                                  state->request.data.auth.user, 
                                  state->request.data.auth.require_membership_of_sid));
@@ -426,8 +392,10 @@ enum winbindd_result winbindd_dual_pam_auth(struct winbindd_domain *domain,
        }
 
 done:
+
        /* give us a more useful (more correct?) error code */
-       if ((NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND) || (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)))) {
+       if ((NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND) ||
+                               (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)))) {
                result = NT_STATUS_NO_LOGON_SERVERS;
        }
        
@@ -450,7 +418,9 @@ done:
                char *afsname = SMB_STRDUP(lp_afs_username_map());
                char *cell;
 
-               if (afsname == NULL) goto no_token;
+               if (afsname == NULL) {
+                       goto no_token;
+               }
 
                afsname = realloc_string_sub(afsname, "%D", name_domain);
                afsname = realloc_string_sub(afsname, "%u", name_user);
@@ -466,7 +436,9 @@ done:
                        afsname = realloc_string_sub(afsname, "%s", sidstr);
                }
 
-               if (afsname == NULL) goto no_token;
+               if (afsname == NULL) {
+                       goto no_token;
+               }
 
                strlower_m(afsname);
 
@@ -474,7 +446,9 @@ done:
 
                cell = strchr(afsname, '@');
 
-               if (cell == NULL) goto no_token;
+               if (cell == NULL) {
+                       goto no_token;
+               }
 
                *cell = '\0';
                cell += 1;
@@ -565,16 +539,12 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain,
                                                 struct winbindd_cli_state *state) 
 {
        NTSTATUS result;
-       const char *srv_name_slash;
         NET_USER_INFO_3 info3;
-       unsigned char *session_key;
-       struct rpc_pipe_client *pipe_cli;
-       DOM_CRED *credentials;
+       struct rpc_pipe_client *netlogon_pipe;
        const char *name_user = NULL;
        const char *name_domain = NULL;
        const char *workstation;
        struct winbindd_domain *contact_domain;
-       DOM_CRED ret_creds;
        int attempts = 0;
        BOOL retry;
 
@@ -618,9 +588,10 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain,
                goto done;
        }
 
-       lm_resp = data_blob_talloc(state->mem_ctx, state->request.data.auth_crap.lm_resp, state->request.data.auth_crap.lm_resp_len);
-       nt_resp = data_blob_talloc(state->mem_ctx, state->request.data.auth_crap.nt_resp, state->request.data.auth_crap.nt_resp_len);
-       
+       lm_resp = data_blob_talloc(state->mem_ctx, state->request.data.auth_crap.lm_resp,
+                                       state->request.data.auth_crap.lm_resp_len);
+       nt_resp = data_blob_talloc(state->mem_ctx, state->request.data.auth_crap.nt_resp,
+                                       state->request.data.auth_crap.nt_resp_len);
 
        /* what domain should we contact? */
        
@@ -631,33 +602,20 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain,
                        result = NT_STATUS_NO_SUCH_USER;
                        goto done;
                }
-               
        } else {
                if (is_myname(name_domain)) {
                        DEBUG(3, ("Authentication for domain %s (local domain to this server) not supported at this stage\n", name_domain));
                        result =  NT_STATUS_NO_SUCH_USER;
                        goto done;
                }
-
                contact_domain = find_our_domain();
        }
 
-       srv_name_slash = talloc_asprintf(state->mem_ctx, "\\\\%s",
-                                        contact_domain->dcname);
-       if (srv_name_slash == NULL) {
-               DEBUG(0, ("talloc_asprintf failed\n"));
-               return WINBINDD_ERROR;
-       }
-               
        do {
-               DOM_CRED clnt_creds;
                ZERO_STRUCT(info3);
-               ZERO_STRUCT(ret_creds);
                retry = False;
 
-               result = cm_connect_netlogon(contact_domain, state->mem_ctx,
-                                            &pipe_cli, &session_key,
-                                            &credentials);
+               result = cm_connect_netlogon(contact_domain, &netlogon_pipe);
 
                if (!NT_STATUS_IS_OK(result)) {
                        DEBUG(3, ("could not open handle to NETLOGON pipe (error: %s)\n",
@@ -665,25 +623,16 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain,
                        goto done;
                }
 
-               credentials->timestamp.time = time(NULL);
-               memcpy(&clnt_creds, credentials, sizeof(clnt_creds));
-
-               /* Calculate the new credentials. */
-               cred_create(session_key, &credentials->challenge,
-                           clnt_creds.timestamp, &(clnt_creds.challenge));
-
-               result = rpccli_netlogon_sam_network_logon(pipe_cli,
-                                                          state->mem_ctx,
-                                                          srv_name_slash,
-                                                          &clnt_creds,
-                                                          &ret_creds,
-                                                          name_user,
-                                                          name_domain, 
-                                                          global_myname(),
-                                                          state->request.data.auth_crap.chal,
-                                                          lm_resp,
-                                                          nt_resp, &info3,
-                                                          session_key);
+               result = rpccli_netlogon_sam_network_logon(netlogon_pipe,
+                                                       state->mem_ctx,
+                                                       contact_domain->dcname,
+                                                       name_user,
+                                                       name_domain, 
+                                                       global_myname(),
+                                                       state->request.data.auth_crap.chal,
+                                                       lm_resp,
+                                                       nt_resp,
+                                                       &info3);
 
                attempts += 1;
 
@@ -712,19 +661,9 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain,
 
        } while ( (attempts < 2) && retry );
 
-       /* Only check creds if we got a connection. */
-       if (contact_domain->conn.cli &&
-                       !(NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND) ||
-                                       (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)))) {
-               if (!clnt_deal_with_creds(session_key, credentials, &ret_creds)) {
-                       DEBUG(3, ("DC %s sent wrong credentials\n",
-                               pipe_cli->cli->srv_name_slash));
-                       result = NT_STATUS_ACCESS_DENIED;
-               }
-       }
-
        if (NT_STATUS_IS_OK(result)) {
-               if (!NT_STATUS_IS_OK(result = check_info3_in_group(state->mem_ctx, &info3, state->request.data.auth_crap.require_membership_of_sid))) {
+               if (!NT_STATUS_IS_OK(result = check_info3_in_group(state->mem_ctx, &info3,
+                                                       state->request.data.auth_crap.require_membership_of_sid))) {
                        DEBUG(3, ("User %s is not in the required group (%s), so plaintext authentication is rejected\n",
                                  state->request.data.auth_crap.user, 
                                  state->request.data.auth_crap.require_membership_of_sid));
@@ -736,14 +675,14 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain,
                } else if (state->request.flags & WBFLAG_PAM_UNIX_NAME) {
                        /* ntlm_auth should return the unix username, per 
                           'winbind use default domain' settings and the like */
-                       
+
                        fstring username_out;
                        const char *nt_username, *nt_domain;
                        if (!(nt_username = unistr2_tdup(state->mem_ctx, &(info3.uni_user_name)))) {
                                /* If the server didn't give us one, just use the one we sent them */
                                nt_username = name_user;
                        }
-                       
+
                        if (!(nt_domain = unistr2_tdup(state->mem_ctx, &(info3.uni_logon_dom)))) {
                                /* If the server didn't give us one, just use the one we sent them */
                                nt_domain = name_domain;
@@ -762,29 +701,34 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain,
                }
                
                if (state->request.flags & WBFLAG_PAM_USER_SESSION_KEY) {
-                       memcpy(state->response.data.auth.user_session_key, info3.user_sess_key, sizeof(state->response.data.auth.user_session_key) /* 16 */);
+                       memcpy(state->response.data.auth.user_session_key, info3.user_sess_key,
+                                       sizeof(state->response.data.auth.user_session_key) /* 16 */);
                }
                if (state->request.flags & WBFLAG_PAM_LMKEY) {
-                       memcpy(state->response.data.auth.first_8_lm_hash, info3.lm_sess_key, sizeof(state->response.data.auth.first_8_lm_hash) /* 8 */);
+                       memcpy(state->response.data.auth.first_8_lm_hash, info3.lm_sess_key,
+                                       sizeof(state->response.data.auth.first_8_lm_hash) /* 8 */);
                }
        }
 
 done:
+
        /* give us a more useful (more correct?) error code */
-       if ((NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND) || (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)))) {
+       if ((NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND) ||
+                               (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)))) {
                result = NT_STATUS_NO_LOGON_SERVERS;
        }
 
        if (state->request.flags & WBFLAG_PAM_NT_STATUS_SQUASH) {
                result = nt_status_squash(result);
        }
-       
+
        state->response.data.auth.nt_status = NT_STATUS_V(result);
        fstrcpy(state->response.data.auth.nt_status_string, nt_errstr(result));
-       
+
        /* we might have given a more useful error above */
-       if (!*state->response.data.auth.error_string) 
+       if (!*state->response.data.auth.error_string) {
                fstrcpy(state->response.data.auth.error_string, get_friendly_nt_error_msg(result));
+       }
        state->response.data.auth.pam_error = nt_status_to_pam(result);
 
        DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, 
index 74645564d48efff58295e395f60bd51ed8f9c83a..70275abf9224a91ddf1a7104acfd38a2b7719481 100644 (file)
@@ -84,6 +84,11 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags,
        pam_sm_setcred(). */
     ret_data = SMB_MALLOC_P(int);
 
+    /* we need to do this before we call AUTH_RETURN */
+    /* Getting into places that might use LDAP -- protect the app
+       from a SIGPIPE it's not expecting */
+    oldsig_handler = CatchSignal(SIGPIPE, SIGNAL_CAST SIG_IGN);
+
     /* get the username */
     retval = pam_get_user( pamh, &name, "Username: " );
     if ( retval != PAM_SUCCESS ) {
@@ -96,10 +101,6 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags,
         _log_err( LOG_DEBUG, "username [%s] obtained", name );
     }
 
-    /* Getting into places that might use LDAP -- protect the app
-       from a SIGPIPE it's not expecting */
-    oldsig_handler = CatchSignal(SIGPIPE, SIGNAL_CAST SIG_IGN);
-
     if (!initialize_password_db(True)) {
         _log_err( LOG_ALERT, "Cannot access samba password database" );
         retval = PAM_AUTHINFO_UNAVAIL;
index 7c5a17b86f7e4451a0626fb9a4cc53bb280a306f..0a4f0556ae147acb11de5f37d4f23471c21ec581 100644 (file)
@@ -122,6 +122,7 @@ typedef struct
        char *szConfigFile;
        char *szSMBPasswdFile;
        char *szPrivateDir;
+        char *szCountersDir;
        char **szPassdbBackend;
        char **szPreloadModules;
        char *szPasswordServer;
@@ -188,6 +189,7 @@ typedef struct
         char *szEventLogNumRecordsCommand;
         char *szEventLogOldestRecordCommand;
        char *szEventLogCloseCommand;
+        char *szEventLogControlCommand;
         char **szEventLogs;
        char *szGuestaccount;
        char *szManglingMethod;
@@ -833,6 +835,7 @@ static struct parm_struct parm_table[] = {
        {"password server", P_STRING, P_GLOBAL, &Globals.szPasswordServer, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD}, 
        {"smb passwd file", P_STRING, P_GLOBAL, &Globals.szSMBPasswdFile, NULL, NULL, FLAG_ADVANCED}, 
        {"private dir", P_STRING, P_GLOBAL, &Globals.szPrivateDir, NULL, NULL, FLAG_ADVANCED}, 
+       {"counters dir", P_STRING, P_GLOBAL, &Globals.szCountersDir, NULL, NULL, FLAG_ADVANCED},
        {"passdb backend", P_LIST, P_GLOBAL, &Globals.szPassdbBackend, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD}, 
        {"algorithmic rid base", P_INTEGER, P_GLOBAL, &Globals.AlgorithmicRidBase, NULL, NULL, FLAG_ADVANCED}, 
        {"root directory", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL, NULL, FLAG_ADVANCED}, 
@@ -966,7 +969,7 @@ static struct parm_struct parm_table[] = {
        {"client use spnego", P_BOOL, P_GLOBAL, &Globals.bClientUseSpnego, NULL, NULL, FLAG_ADVANCED}, 
 
        {"enable asu support", P_BOOL, P_GLOBAL, &Globals.bASUSupport, NULL, NULL, FLAG_ADVANCED}, 
-       {"enable svcctl", P_LIST, P_GLOBAL, &Globals.szServicesList, NULL, NULL, FLAG_ADVANCED},
+       {"svcctl list", P_LIST, P_GLOBAL, &Globals.szServicesList, NULL, NULL, FLAG_ADVANCED},
 
        {N_("Tuning Options"), P_SEP, P_SEPARATOR}, 
 
@@ -1156,6 +1159,8 @@ static struct parm_struct parm_table[] = {
        {"eventlog clear command", P_STRING, P_GLOBAL, &Globals.szEventLogClearCommand, handle_eventlog, NULL, FLAG_ADVANCED},
        {"eventlog num records command", P_STRING, P_GLOBAL, &Globals.szEventLogNumRecordsCommand, handle_eventlog, NULL, FLAG_ADVANCED},
        {"eventlog oldest record command", P_STRING, P_GLOBAL, &Globals.szEventLogOldestRecordCommand, handle_eventlog, NULL, FLAG_ADVANCED},
+       {"eventlog close command", P_STRING, P_GLOBAL, &Globals.szEventLogCloseCommand, handle_eventlog, NULL, FLAG_ADVANCED},
+       {"eventlog control command", P_STRING, P_GLOBAL, &Globals.szEventLogControlCommand, handle_eventlog, NULL, FLAG_ADVANCED},
        {"eventlog list",  P_LIST, P_GLOBAL, &Globals.szEventLogs, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, 
        
        {"config file", P_STRING, P_GLOBAL, &Globals.szConfigFile, NULL, NULL, FLAG_HIDE}, 
@@ -1428,6 +1433,7 @@ static void init_globals(void)
 
        Globals.bLoadPrinters = True;
        Globals.PrintcapCacheTime = 750;        /* 12.5 minutes */
+
        /* Was 65535 (0xFFFF). 0x4101 matches W2K and causes major speed improvements... */
        /* Discovered by 2 days of pain by Don McCall @ HP :-). */
        Globals.max_xmit = 0x4104;
@@ -1520,7 +1526,6 @@ static void init_globals(void)
 #else
        Globals.szPassdbBackend = str_list_make("smbpasswd", NULL);
 #endif /* WITH_LDAP_SAMCONFIG */
-
        string_set(&Globals.szLdapSuffix, "");
        string_set(&Globals.szLdapMachineSuffix, "");
        string_set(&Globals.szLdapUserSuffix, "");
@@ -1581,6 +1586,8 @@ static void init_globals(void)
        string_set(&Globals.szEventLogClearCommand, "");
        string_set(&Globals.szEventLogNumRecordsCommand, "");
        string_set(&Globals.szEventLogOldestRecordCommand, "");
+       string_set(&Globals.szEventLogCloseCommand, "");
+       string_set(&Globals.szEventLogControlCommand, "");
 
        Globals.winbind_cache_time = 300;       /* 5 minutes */
        Globals.bWinbindEnumUsers = True;
@@ -1609,7 +1616,7 @@ static void init_globals(void)
           operations as root */
 
        Globals.bEnablePrivileges = False;
-       
+
        Globals.bASUSupport       = True;
        
        Globals.szServicesList = str_list_make( "Spooler NETLOGON", NULL );
@@ -1703,6 +1710,7 @@ FN_GLOBAL_STRING(lp_logfile, &Globals.szLogFile)
 FN_GLOBAL_STRING(lp_configfile, &Globals.szConfigFile)
 FN_GLOBAL_STRING(lp_smb_passwd_file, &Globals.szSMBPasswdFile)
 FN_GLOBAL_STRING(lp_private_dir, &Globals.szPrivateDir)
+FN_GLOBAL_STRING(lp_counters_dir, &Globals.szCountersDir)
 FN_GLOBAL_STRING(lp_serverstring, &Globals.szServerString)
 FN_GLOBAL_INTEGER(lp_printcap_cache_time, &Globals.PrintcapCacheTime)
 FN_GLOBAL_STRING(lp_enumports_cmd, &Globals.szEnumPortsCommand)
@@ -1804,6 +1812,8 @@ FN_GLOBAL_STRING(lp_eventlog_clear_cmd, &Globals.szEventLogClearCommand)
 FN_GLOBAL_STRING(lp_eventlog_num_records_cmd, &Globals.szEventLogNumRecordsCommand)
 FN_GLOBAL_STRING(lp_eventlog_oldest_record_cmd, &Globals.szEventLogOldestRecordCommand)
 FN_GLOBAL_STRING(lp_eventlog_close_cmd, &Globals.szEventLogCloseCommand)
+FN_GLOBAL_STRING(lp_eventlog_control_cmd, &Globals.szEventLogControlCommand)
+
 FN_GLOBAL_LIST(lp_eventlog_list, &Globals.szEventLogs)
 
 FN_GLOBAL_BOOL(lp_disable_netbios, &Globals.bDisableNetbios)
@@ -1904,7 +1914,7 @@ FN_LOCAL_STRING(lp_username, szUsername)
 FN_LOCAL_LIST(lp_invalid_users, szInvalidUsers)
 FN_LOCAL_LIST(lp_valid_users, szValidUsers)
 FN_LOCAL_LIST(lp_admin_users, szAdminUsers)
-FN_GLOBAL_LIST(lp_enable_svcctl, &Globals.szServicesList)
+FN_GLOBAL_LIST(lp_svcctl_list, &Globals.szServicesList)
 FN_LOCAL_STRING(lp_cups_options, szCupsOptions)
 FN_GLOBAL_STRING(lp_cups_server, &Globals.szCupsServer)
 FN_GLOBAL_STRING(lp_iprint_server, &Globals.szIPrintServer)
@@ -3344,7 +3354,10 @@ BOOL lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue
                        break;
 
                case P_OCTAL:
-                       sscanf(pszParmValue, "%o", (int *)parm_ptr);
+                       i = sscanf(pszParmValue, "%o", (int *)parm_ptr);
+                       if ( i != 1 ) {
+                           DEBUG ( 0, ("Invalid octal number %s\n", pszParmName ));
+                       }
                        break;
 
                case P_LIST:
@@ -3698,13 +3711,13 @@ static void dump_a_service(service * pService, FILE * f)
                }
        }
 
-       if (pService->param_opt != NULL) {
-               data = pService->param_opt;
-               while(data) {
-                       fprintf(f, "\t%s = %s\n", data->key, data->value);
-                       data = data->next;
-               }
-       }
+               if (pService->param_opt != NULL) {
+                       data = pService->param_opt;
+                       while(data) {
+                               fprintf(f, "\t%s = %s\n", data->key, data->value);
+                               data = data->next;
+                       }
+               }
 }
 
 /***************************************************************************
@@ -4128,7 +4141,7 @@ BOOL lp_load(const char *pszFname, BOOL global_only, BOOL save_defaults,
                   are denied */
                lp_add_ipc("IPC$", (lp_restrict_anonymous() < 2));
                if ( lp_enable_asu_support() )
-               lp_add_ipc("ADMIN$", False);
+                       lp_add_ipc("ADMIN$", False);
        }
 
        set_server_role();
index 4cd9516dd199ebbad80f2757cf16748087e47f1d..6b58210919a0a9c77310cfe896f45dc762436f6f 100644 (file)
@@ -97,19 +97,27 @@ BOOL lookup_sid(const DOM_SID *sid, fstring dom_name, fstring name, enum SID_NAM
                }
        }
 
-       if (!winbind_lookup_sid(sid, dom_name, name, name_type)) {
-               fstring sid_str;
-               DOM_SID tmp_sid;
-               uint32 rid;
+       if (winbind_lookup_sid(sid, dom_name, name, name_type)) {
+               return True;
+       }
 
-               DEBUG(10,("lookup_sid: winbind lookup for SID %s failed - trying local.\n", sid_to_string(sid_str, sid) ));
+       DEBUG(10,("lookup_sid: winbind lookup for SID %s failed - trying "
+                 "special SIDs.\n", sid_string_static(sid)));
 
-               sid_copy(&tmp_sid, sid);
-               sid_split_rid(&tmp_sid, &rid);
-               return map_domain_sid_to_name(&tmp_sid, dom_name) &&
-                       lookup_known_rid(&tmp_sid, rid, name, name_type);
+       {
+               const char *dom, *obj_name;
+               
+               if (lookup_special_sid(sid, &dom, &obj_name, name_type)) {
+                       DEBUG(10, ("found %s\\%s\n", dom, obj_name));
+                       fstrcpy(dom_name, dom);
+                       fstrcpy(name, obj_name);
+                       return True;
+               }
        }
-       return True;
+
+       DEBUG(10, ("lookup_sid failed\n"));
+
+       return False;
 }
 
 /*****************************************************************
index 283eb7f1c16cfbeffdd26ddf09fbe840f7dbcd4d..a7ff3a04f7e8939f755afc1ada7f19cce1601c17 100644 (file)
@@ -1875,7 +1875,7 @@ BOOL init_sam_from_buffer_v2(SAM_ACCOUNT *sampass, uint8 *buf, uint32 buflen)
        }
 
        /* Change from V1 is addition of password history field. */
-       account_policy_get(AP_PASSWORD_HISTORY, &pwHistLen);
+       pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen);
        if (pwHistLen) {
                uint8 *pw_hist = SMB_MALLOC(pwHistLen * PW_HISTORY_ENTRY_LEN);
                if (!pw_hist) {
@@ -2083,7 +2083,7 @@ uint32 init_buffer_from_sam_v2 (uint8 **buf, const SAM_ACCOUNT *sampass, BOOL si
                nt_pw_len = 0;
        }
 
-       account_policy_get(AP_PASSWORD_HISTORY, &pwHistLen);
+       pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen);
        nt_pw_hist =  pdb_get_pw_history(sampass, &nt_pw_hist_len);
        if (pwHistLen && nt_pw_hist && nt_pw_hist_len) {
                nt_pw_hist_len *= PW_HISTORY_ENTRY_LEN;
@@ -2292,8 +2292,8 @@ BOOL pdb_update_bad_password_count(SAM_ACCOUNT *sampass, BOOL *updated)
                return True;
        }
 
-       if (!account_policy_get(AP_RESET_COUNT_TIME, &resettime)) {
-               DEBUG(0, ("pdb_update_bad_password_count: account_policy_get failed.\n"));
+       if (!pdb_get_account_policy(AP_RESET_COUNT_TIME, &resettime)) {
+               DEBUG(0, ("pdb_update_bad_password_count: pdb_get_account_policy failed.\n"));
                return False;
        }
 
@@ -2334,8 +2334,8 @@ BOOL pdb_update_autolock_flag(SAM_ACCOUNT *sampass, BOOL *updated)
                return True;
        }
 
-       if (!account_policy_get(AP_LOCK_ACCOUNT_DURATION, &duration)) {
-               DEBUG(0, ("pdb_update_autolock_flag: account_policy_get failed.\n"));
+       if (!pdb_get_account_policy(AP_LOCK_ACCOUNT_DURATION, &duration)) {
+               DEBUG(0, ("pdb_update_autolock_flag: pdb_get_account_policy failed.\n"));
                return False;
        }
 
@@ -2383,9 +2383,9 @@ BOOL pdb_increment_bad_password_count(SAM_ACCOUNT *sampass)
                return False;
 
        /* Retrieve the account lockout policy */
-       if (!account_policy_get(AP_BAD_ATTEMPT_LOCKOUT,
+       if (!pdb_get_account_policy(AP_BAD_ATTEMPT_LOCKOUT,
                                &account_policy_lockout)) {
-               DEBUG(0, ("pdb_increment_bad_password_count: account_policy_get failed.\n"));
+               DEBUG(0, ("pdb_increment_bad_password_count: pdb_get_account_policy failed.\n"));
                return False;
        }
 
index 12e8bcc9cf947844f4ad8fcd7cac78564beb9d58..783e9e23fa306ecb696c33c2ff5e2e483a0d144e 100644 (file)
@@ -1123,7 +1123,7 @@ BOOL pdb_set_pass_changed_now (SAM_ACCOUNT *sampass)
        if (!pdb_set_pass_last_set_time (sampass, time(NULL), PDB_CHANGED))
                return False;
 
-       if (!account_policy_get(AP_MAX_PASSWORD_AGE, &expire) 
+       if (!pdb_get_account_policy(AP_MAX_PASSWORD_AGE, &expire) 
            || (expire==(uint32)-1) || (expire == 0)) {
                if (!pdb_set_pass_must_change_time (sampass, get_time_t_max(), PDB_CHANGED))
                        return False;
@@ -1134,7 +1134,7 @@ BOOL pdb_set_pass_changed_now (SAM_ACCOUNT *sampass)
                        return False;
        }
        
-       if (!account_policy_get(AP_MIN_PASSWORD_AGE, &min_age) 
+       if (!pdb_get_account_policy(AP_MIN_PASSWORD_AGE, &min_age) 
            || (min_age==(uint32)-1)) {
                if (!pdb_set_pass_can_change_time (sampass, 0, PDB_CHANGED))
                        return False;
@@ -1189,13 +1189,13 @@ BOOL pdb_set_plaintext_passwd (SAM_ACCOUNT *sampass, const char *plaintext)
        if (pdb_get_acct_ctrl(sampass) & ACB_NORMAL) {
                uchar *pwhistory;
                uint32 pwHistLen;
-               account_policy_get(AP_PASSWORD_HISTORY, &pwHistLen);
+               pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen);
                if (pwHistLen != 0){
                        uint32 current_history_len;
                        /* We need to make sure we don't have a race condition here - the
                           account policy history length can change between when the pw_history
                           was first loaded into the SAM_ACCOUNT struct and now.... JRA. */
-                       pwhistory = CONST_DISCARD(uchar *, pdb_get_pw_history(sampass, &current_history_len));
+                       pwhistory = (uchar *)pdb_get_pw_history(sampass, &current_history_len);
 
                        if (current_history_len != pwHistLen) {
                                /* After closing and reopening SAM_ACCOUNT the history
index d4407492c215aa50cc892f9c678971dad9f3be5d..a9e41984c3d119eefaadac9276b32168f2b6eedd 100644 (file)
@@ -665,43 +665,46 @@ static NTSTATUS context_lookup_rids(struct pdb_context *context,
                                                 rids, names, attrs);
 }
 
-static BOOL context_search_users(struct pdb_context *context,
-                                struct pdb_search *search, uint16 acct_flags)
+static NTSTATUS context_get_account_policy(struct pdb_context *context,
+                                          int policy_index, uint32 *value)
 {
+       NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+
        if ((!context) || (!context->pdb_methods)) {
                DEBUG(0, ("invalid pdb_context specified!\n"));
-               return False;
+               return ret;
        }
 
-       return context->pdb_methods->search_users(context->pdb_methods,
-                                                 search, acct_flags);
+       return context->pdb_methods->get_account_policy(context->pdb_methods,
+                                                       policy_index, value);
 }
 
-static BOOL context_search_groups(struct pdb_context *context,
-                                 struct pdb_search *search)
+static NTSTATUS context_set_account_policy(struct pdb_context *context,
+                                          int policy_index, uint32 value)
 {
+       NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+
        if ((!context) || (!context->pdb_methods)) {
                DEBUG(0, ("invalid pdb_context specified!\n"));
-               return False;
+               return ret;
        }
 
-       return context->pdb_methods->search_groups(context->pdb_methods,
-                                                  search);
+       return context->pdb_methods->set_account_policy(context->pdb_methods,
+                                                       policy_index, value);
 }
 
-static BOOL context_search_aliases(struct pdb_context *context,
-                                  struct pdb_search *search,
-                                  const DOM_SID *sid)
+static NTSTATUS context_get_seq_num(struct pdb_context *context, time_t *seq_num)
 {
+       NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+
        if ((!context) || (!context->pdb_methods)) {
                DEBUG(0, ("invalid pdb_context specified!\n"));
-               return False;
+               return ret;
        }
 
-       return context->pdb_methods->search_aliases(context->pdb_methods,
-                                                   search, sid);
+       return context->pdb_methods->get_seq_num(context->pdb_methods, seq_num);
 }
-
+       
 /******************************************************************
   Free and cleanup a pdb context, any associated data and anything
   that the attached modules might have associated.
@@ -721,6 +724,43 @@ static void free_pdb_context(struct pdb_context **context)
        *context = NULL;
 }
 
+static BOOL context_search_users(struct pdb_context *context,
+                                struct pdb_search *search, uint16 acct_flags)
+{
+       if ((!context) || (!context->pdb_methods)) {
+               DEBUG(0, ("invalid pdb_context specified!\n"));
+               return False;
+       }
+
+       return context->pdb_methods->search_users(context->pdb_methods,
+                                                 search, acct_flags);
+}
+
+static BOOL context_search_groups(struct pdb_context *context,
+                                 struct pdb_search *search)
+{
+       if ((!context) || (!context->pdb_methods)) {
+               DEBUG(0, ("invalid pdb_context specified!\n"));
+               return False;
+       }
+
+       return context->pdb_methods->search_groups(context->pdb_methods,
+                                                  search);
+}
+
+static BOOL context_search_aliases(struct pdb_context *context,
+                                  struct pdb_search *search,
+                                  const DOM_SID *sid)
+{
+       if ((!context) || (!context->pdb_methods)) {
+               DEBUG(0, ("invalid pdb_context specified!\n"));
+               return False;
+       }
+
+       return context->pdb_methods->search_aliases(context->pdb_methods,
+                                                   search, sid);
+}
+
 /******************************************************************
   Make a pdb_methods from scratch
  *******************************************************************/
@@ -832,6 +872,11 @@ static NTSTATUS make_pdb_context(struct pdb_context **context)
        (*context)->pdb_enum_alias_memberships = context_enum_alias_memberships;
        (*context)->pdb_lookup_rids = context_lookup_rids;
 
+       (*context)->pdb_get_account_policy = context_get_account_policy;
+       (*context)->pdb_set_account_policy = context_set_account_policy;
+
+       (*context)->pdb_get_seq_num = context_get_seq_num;
+
        (*context)->pdb_search_users = context_search_users;
        (*context)->pdb_search_groups = context_search_groups;
        (*context)->pdb_search_aliases = context_search_aliases;
@@ -1318,6 +1363,41 @@ NTSTATUS pdb_lookup_rids(TALLOC_CTX *mem_ctx,
                                            num_rids, rids, names, attrs);
 }
 
+BOOL pdb_get_account_policy(int policy_index, uint32 *value)
+{
+       struct pdb_context *pdb_context = pdb_get_static_context(False);
+
+       if (!pdb_context) {
+               return False;
+       }
+
+       return NT_STATUS_IS_OK(pdb_context->
+                              pdb_get_account_policy(pdb_context, policy_index, value));
+}
+
+BOOL pdb_set_account_policy(int policy_index, uint32 value)
+{
+       struct pdb_context *pdb_context = pdb_get_static_context(False);
+
+       if (!pdb_context) {
+               return False;
+       }
+
+       return NT_STATUS_IS_OK(pdb_context->
+                              pdb_set_account_policy(pdb_context, policy_index, value));
+}
+
+BOOL pdb_get_seq_num(time_t *seq_num)
+{
+       struct pdb_context *pdb_context = pdb_get_static_context(False);
+
+       if (!pdb_context) {
+               return False;
+       }
+
+       return NT_STATUS_IS_OK(pdb_context->
+                              pdb_get_seq_num(pdb_context, seq_num));
+}
 /***************************************************************
   Initialize the static context (at smbd startup etc). 
 
@@ -1380,6 +1460,22 @@ static void pdb_default_endsampwent(struct pdb_methods *methods)
        return; /* NT_STATUS_NOT_IMPLEMENTED; */
 }
 
+static NTSTATUS pdb_default_get_account_policy(struct pdb_methods *methods, int policy_index, uint32 *value)
+{
+       return account_policy_get(policy_index, value) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
+}
+
+static NTSTATUS pdb_default_set_account_policy(struct pdb_methods *methods, int policy_index, uint32 value)
+{
+       return account_policy_set(policy_index, value) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
+}
+
+static NTSTATUS pdb_default_get_seq_num(struct pdb_methods *methods, time_t *seq_num)
+{
+       *seq_num = time(NULL);
+       return NT_STATUS_OK;
+}
+
 static void add_uid_to_array_unique(TALLOC_CTX *mem_ctx,
                                    uid_t uid, uid_t **uids, int *num)
 {
@@ -1908,6 +2004,10 @@ NTSTATUS make_pdb_methods(TALLOC_CTX *mem_ctx, PDB_METHODS **methods)
        (*methods)->enum_aliasmem = pdb_default_enum_aliasmem;
        (*methods)->enum_alias_memberships = pdb_default_alias_memberships;
        (*methods)->lookup_rids = pdb_default_lookup_rids;
+       (*methods)->get_account_policy = pdb_default_get_account_policy;
+       (*methods)->set_account_policy = pdb_default_set_account_policy;
+       (*methods)->get_seq_num = pdb_default_get_seq_num;
+
        (*methods)->search_users = pdb_default_search_users;
        (*methods)->search_groups = pdb_default_search_groups;
        (*methods)->search_aliases = pdb_default_search_aliases;
index 99f6670653b019f3a33f1eb3bd2aa75d420eb180..e44ccc3bf98ca3bcae474b75b376c53af08787ab 100644 (file)
@@ -178,6 +178,146 @@ static const char* get_objclass_filter( int schema_ver )
        return objclass_filter; 
 }
 
+/*****************************************************************
+ Scan a sequence number off OpenLDAP's syncrepl contextCSN
+******************************************************************/
+
+static NTSTATUS ldapsam_get_seq_num(struct pdb_methods *my_methods, time_t *seq_num)
+{
+       struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
+       NTSTATUS ntstatus = NT_STATUS_UNSUCCESSFUL;
+       LDAPMessage *msg = NULL;
+       LDAPMessage *entry = NULL;
+       TALLOC_CTX *mem_ctx;
+       char **values = NULL;
+       int rc, num_result, num_values, rid;
+       pstring suffix;
+       fstring tok;
+       const char *p;
+       const char **attrs;
+
+       /* Unfortunatly there is no proper way to detect syncrepl-support in
+        * smbldap_connect_system(). The syncrepl OIDs are submitted for publication
+        * but do not show up in the root-DSE yet. Neither we can query the
+        * subschema-context for the syncProviderSubentry or syncConsumerSubentry
+        * objectclass. Currently we require lp_ldap_suffix() to show up as
+        * namingContext.  -  Guenther
+        */
+
+       if (!lp_parm_bool(-1, "ldapsam", "syncrepl_seqnum", False)) {
+               return ntstatus;
+       }
+
+       if (!seq_num) {
+               DEBUG(3,("ldapsam_get_seq_num: no sequence_number\n"));
+               return ntstatus;
+       }
+
+       if (!smbldap_has_naming_context(ldap_state->smbldap_state, lp_ldap_suffix())) {
+               DEBUG(3,("ldapsam_get_seq_num: DIT not configured to hold %s "
+                        "as top-level namingContext\n", lp_ldap_suffix()));
+               return ntstatus;
+       }
+
+       mem_ctx = talloc_init("ldapsam_get_seq_num");
+
+       if (mem_ctx == NULL)
+               return NT_STATUS_NO_MEMORY;
+
+       attrs = TALLOC_ARRAY(mem_ctx, const char *, 2);
+
+       /* if we got a syncrepl-rid (up to three digits long) we speak with a consumer */
+       rid = lp_parm_int(-1, "ldapsam", "syncrepl_rid", -1);
+       if (rid > 0) {
+
+               /* consumer syncreplCookie: */
+               /* csn=20050126161620Z#0000001#00#00000 */
+               attrs[0] = talloc_strdup(mem_ctx, "syncreplCookie");
+               attrs[1] = NULL;
+               pstr_sprintf( suffix, "cn=syncrepl%d,%s", rid, lp_ldap_suffix());
+
+       } else {
+
+               /* provider contextCSN */
+               /* 20050126161620Z#000009#00#000000 */
+               attrs[0] = talloc_strdup(mem_ctx, "contextCSN");
+               attrs[1] = NULL;
+               pstr_sprintf( suffix, "cn=ldapsync,%s", lp_ldap_suffix());
+
+       }
+
+       rc = smbldap_search(ldap_state->smbldap_state, suffix,
+                           LDAP_SCOPE_BASE, "(objectclass=*)", attrs, 0, &msg);
+
+       if (rc != LDAP_SUCCESS) {
+
+               char *ld_error = NULL;
+               ldap_get_option(ldap_state->smbldap_state->ldap_struct,
+                               LDAP_OPT_ERROR_STRING, &ld_error);
+               DEBUG(0,("ldapsam_get_seq_num: Failed search for suffix: %s, error: %s (%s)\n", 
+                       suffix,ldap_err2string(rc), ld_error?ld_error:"unknown"));
+               SAFE_FREE(ld_error);
+               goto done;
+       }
+
+       num_result = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, msg);
+       if (num_result != 1) {
+               DEBUG(3,("ldapsam_get_seq_num: Expected one entry, got %d\n", num_result));
+               goto done;
+       }
+
+       entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, msg);
+       if (entry == NULL) {
+               DEBUG(3,("ldapsam_get_seq_num: Could not retrieve entry\n"));
+               goto done;
+       }
+
+       values = ldap_get_values(ldap_state->smbldap_state->ldap_struct, entry, attrs[0]);
+       if (values == NULL) {
+               DEBUG(3,("ldapsam_get_seq_num: no values\n"));
+               goto done;
+       }
+
+       num_values = ldap_count_values(values);
+       if (num_values == 0) {
+               DEBUG(3,("ldapsam_get_seq_num: not a single value\n"));
+               goto done;
+       }
+
+       p = values[0];
+       if (!next_token(&p, tok, "#", sizeof(tok))) {
+               DEBUG(0,("ldapsam_get_seq_num: failed to parse sequence number\n"));
+               goto done;
+       }
+
+       p = tok;
+       if (!strncmp(p, "csn=", strlen("csn=")))
+               p += strlen("csn=");
+
+       DEBUG(10,("ldapsam_get_seq_num: got %s: %s\n", attrs[0], p));
+
+       *seq_num = generalized_to_unix_time(p);
+
+       /* very basic sanity check */
+       if (*seq_num <= 0) {
+               DEBUG(3,("ldapsam_get_seq_num: invalid sequence number: %d\n", 
+                       (int)*seq_num));
+               goto done;
+       }
+
+       ntstatus = NT_STATUS_OK;
+
+ done:
+       if (values != NULL)
+               ldap_value_free(values);
+       if (msg != NULL)
+               ldap_msgfree(msg);
+       if (mem_ctx)
+               talloc_destroy(mem_ctx);
+
+       return ntstatus;
+}
+
 /*******************************************************************
  Run the search by name.
 ******************************************************************/
@@ -694,9 +834,9 @@ static BOOL init_sam_from_ldap(struct ldapsam_privates *ldap_state,
 
        if (ldap_state->is_nds_ldap) {
                char *user_dn;
-               int pwd_len;
+               size_t pwd_len;
                char clear_text_pw[512];
-
+   
                /* Make call to Novell eDirectory ldap extension to get clear text password.
                        NOTE: This will only work if we have an SSL connection to eDirectory. */
                user_dn = smbldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry);
@@ -717,7 +857,7 @@ static BOOL init_sam_from_ldap(struct ldapsam_privates *ldap_state,
                } else {
                        DEBUG(0, ("init_sam_from_ldap: failed to get user_dn for '%s'\n", username));
                }
-       }
+       }
 
        if (use_samba_attrs) {
                if (!smbldap_get_single_pstring (ldap_state->smbldap_state->ldap_struct, entry, 
@@ -741,9 +881,11 @@ static BOOL init_sam_from_ldap(struct ldapsam_privates *ldap_state,
                                return False;
                        ZERO_STRUCT(smbntpwd);
                }
-       }
+       }
+
+       pwHistLen = 0;
 
-       account_policy_get(AP_PASSWORD_HISTORY, &pwHistLen);
+       pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen);
        if (pwHistLen > 0){
                uint8 *pwhist = NULL;
                int i;
@@ -1087,7 +1229,7 @@ static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state,
 
                if (need_update(sampass, PDB_PWHISTORY)) {
                        uint32 pwHistLen = 0;
-                       account_policy_get(AP_PASSWORD_HISTORY, &pwHistLen);
+                       pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen);
                        if (pwHistLen == 0) {
                                /* Remove any password history from the LDAP store. */
                                memset(temp, '0', 64); /* NOTE !!!! '0' *NOT '\0' */
@@ -1153,7 +1295,7 @@ static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state,
                uint16 badcount = pdb_get_bad_password_count(sampass);
                time_t badtime = pdb_get_bad_password_time(sampass);
                uint32 pol;
-               account_policy_get(AP_BAD_ATTEMPT_LOCKOUT, &pol);
+               pdb_get_account_policy(AP_BAD_ATTEMPT_LOCKOUT, &pol);
 
                DEBUG(3, ("updating bad password fields, policy=%u, count=%u, time=%u\n",
                        (unsigned int)pol, (unsigned int)badcount, (unsigned int)badtime));
@@ -2158,10 +2300,10 @@ static NTSTATUS ldapsam_getgrgid(struct pdb_methods *methods, GROUP_MAP *map,
 {
        pstring filter;
 
-       pstr_sprintf(filter, "(&(objectClass=%s)(%s=%d))",
+       pstr_sprintf(filter, "(&(objectClass=%s)(%s=%lu))",
                LDAP_OBJ_GROUPMAP,
                get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GIDNUMBER),
-               gid);
+               (unsigned long)gid);
 
        return ldapsam_getgroup(methods, filter, map);
 }
@@ -2312,7 +2454,7 @@ static NTSTATUS ldapsam_enum_group_members(struct pdb_methods *methods,
 
        {
                const char *attrs[] = { "memberUid", NULL };
-               rc = smbldap_search(conn, lp_ldap_group_suffix(),
+               rc = smbldap_search(conn, lp_ldap_user_suffix(),
                                    LDAP_SCOPE_SUBTREE, filter, attrs, 0,
                                    &msg);
        }
@@ -2536,10 +2678,10 @@ static int ldapsam_search_one_group_by_gid(struct ldapsam_privates *ldap_state,
 {
        pstring filter;
 
-       pstr_sprintf(filter, "(&(|(objectClass=%s)(objectclass=%s))(%s=%d))", 
+       pstr_sprintf(filter, "(&(|(objectClass=%s)(objectclass=%s))(%s=%lu))", 
                LDAP_OBJ_POSIXGROUP, LDAP_OBJ_IDMAP_ENTRY,
                get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GIDNUMBER),
-               gid);
+               (unsigned long)gid);
 
        return ldapsam_search_one_group(ldap_state, filter, result);
 }
@@ -2589,7 +2731,7 @@ static NTSTATUS ldapsam_add_group_mapping_entry(struct pdb_methods *methods,
                ldap_msgfree(result);
 
                pstrcpy( suffix, lp_ldap_idmap_suffix() );
-               pstr_sprintf(filter, "(&(objectClass=%s)(%s=%d))",
+               pstr_sprintf(filter, "(&(objectClass=%s)(%s=%u))",
                             LDAP_OBJ_IDMAP_ENTRY, LDAP_ATTRIBUTE_GIDNUMBER,
                             map->gid);
                
@@ -3131,6 +3273,187 @@ static NTSTATUS ldapsam_alias_memberships(struct pdb_methods *methods,
        return NT_STATUS_OK;
 }
 
+static NTSTATUS ldapsam_set_account_policy(struct pdb_methods *methods, int policy_index, uint32 value)
+{
+       NTSTATUS ntstatus = NT_STATUS_UNSUCCESSFUL;
+       int rc;
+       LDAPMod **mods = NULL;
+       fstring value_string;
+       const char *policy_attr = NULL;
+
+       struct ldapsam_privates *ldap_state =
+               (struct ldapsam_privates *)methods->private_data;
+
+       const char *attrs[2];
+
+       DEBUG(10,("ldapsam_set_account_policy\n"));
+
+       if (!ldap_state->domain_dn) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       policy_attr = get_account_policy_attr(policy_index);
+       if (policy_attr == NULL) {
+               DEBUG(0,("ldapsam_set_account_policy: invalid policy\n"));
+               return ntstatus;
+       }
+
+       attrs[0] = policy_attr;
+       attrs[1] = NULL;
+
+       slprintf(value_string, sizeof(value_string) - 1, "%i", value);
+
+       smbldap_set_mod(&mods, LDAP_MOD_REPLACE, policy_attr, value_string);
+
+       rc = smbldap_modify(ldap_state->smbldap_state, ldap_state->domain_dn, mods);
+
+       ldap_mods_free(mods, True);
+
+       if (rc != LDAP_SUCCESS) {
+               char *ld_error = NULL;
+               ldap_get_option(ldap_state->smbldap_state->ldap_struct,
+                               LDAP_OPT_ERROR_STRING,&ld_error);
+               
+               DEBUG(0, ("ldapsam_set_account_policy: Could not set account policy "
+                         "for %s, error: %s (%s)\n", ldap_state->domain_dn, ldap_err2string(rc),
+                         ld_error?ld_error:"unknown"));
+               SAFE_FREE(ld_error);
+               return ntstatus;
+       }
+
+       if (!cache_account_policy_set(policy_index, value)) {
+               DEBUG(0,("ldapsam_set_account_policy: failed to update local tdb cache\n"));
+               return ntstatus;
+       }
+
+       return NT_STATUS_OK;
+}
+
+static NTSTATUS ldapsam_get_account_policy_from_ldap(struct pdb_methods *methods, int policy_index, uint32 *value)
+{
+       NTSTATUS ntstatus = NT_STATUS_UNSUCCESSFUL;
+       LDAPMessage *result = NULL;
+       LDAPMessage *entry = NULL;
+       int count;
+       int rc;
+       char **vals = NULL;
+       const char *policy_attr = NULL;
+
+       struct ldapsam_privates *ldap_state =
+               (struct ldapsam_privates *)methods->private_data;
+
+       const char *attrs[2];
+
+       DEBUG(10,("ldapsam_get_account_policy_from_ldap\n"));
+
+       if (!ldap_state->domain_dn) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       policy_attr = get_account_policy_attr(policy_index);
+       if (!policy_attr) {
+               DEBUG(0,("ldapsam_get_account_policy_from_ldap: invalid policy index: %d\n", policy_index));
+               return ntstatus;
+       }
+
+       attrs[0] = policy_attr;
+       attrs[1] = NULL;
+
+       rc = smbldap_search(ldap_state->smbldap_state, ldap_state->domain_dn,
+                           LDAP_SCOPE_BASE, "(objectclass=*)", attrs, 0, &result);
+
+       if (rc != LDAP_SUCCESS) {
+               char *ld_error = NULL;
+               ldap_get_option(ldap_state->smbldap_state->ldap_struct,
+                               LDAP_OPT_ERROR_STRING,&ld_error);
+               
+               DEBUG(0, ("ldapsam_get_account_policy_from_ldap: Could not set account policy "
+                         "for %s, error: %s (%s)\n", ldap_state->domain_dn, ldap_err2string(rc),
+                         ld_error?ld_error:"unknown"));
+               SAFE_FREE(ld_error);
+               return ntstatus;
+       }
+
+       count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
+       if (count < 1) {
+               goto out;
+       }
+
+       entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result);
+       if (entry == NULL) {
+               goto out;
+       }
+
+       vals = ldap_get_values(ldap_state->smbldap_state->ldap_struct, entry, policy_attr);
+       if (vals == NULL) {
+               goto out;
+       }
+
+       *value = (uint32)atol(vals[0]);
+       
+       ntstatus = NT_STATUS_OK;
+
+out:
+       if (vals)
+               ldap_value_free(vals);
+       ldap_msgfree(result);
+
+       return ntstatus;
+}
+
+/* wrapper around ldapsam_get_account_policy_from_ldap(), handles tdb as cache 
+
+   - if there is a valid cache entry, return that
+   - if there is an LDAP entry, update cache and return 
+   - otherwise set to default, update cache and return
+
+   Guenther
+*/
+static NTSTATUS ldapsam_get_account_policy(struct pdb_methods *methods, int policy_index, uint32 *value)
+{
+       NTSTATUS ntstatus = NT_STATUS_UNSUCCESSFUL;
+
+       if (cache_account_policy_get(policy_index, value)) {
+               DEBUG(11,("ldapsam_get_account_policy: got valid value from cache\n"));
+               return NT_STATUS_OK;
+       }
+
+       ntstatus = ldapsam_get_account_policy_from_ldap(methods, policy_index, value);
+       if (NT_STATUS_IS_OK(ntstatus)) {
+               goto update_cache;
+       }
+
+       DEBUG(10,("ldapsam_get_account_policy: failed to retrieve from ldap, returning default.\n"));
+
+#if 0
+       /* should we automagically migrate old tdb value here ? */
+       if (account_policy_get(policy_index, value))
+               goto update_ldap;
+
+       DEBUG(10,("ldapsam_get_account_policy: no tdb for %d, trying default\n", policy_index));
+#endif
+
+       if (!account_policy_get_default(policy_index, value)) {
+               return ntstatus;
+       }
+       
+/* update_ldap: */
+       ntstatus = ldapsam_set_account_policy(methods, policy_index, *value);
+       if (!NT_STATUS_IS_OK(ntstatus)) {
+               return ntstatus;
+       }
+               
+ update_cache:
+       if (!cache_account_policy_set(policy_index, *value)) {
+               DEBUG(0,("ldapsam_get_account_policy: failed to update local tdb as a cache\n"));
+               return NT_STATUS_UNSUCCESSFUL;
+       }
+
+       return NT_STATUS_OK;
+}
+
 static NTSTATUS ldapsam_lookup_rids(struct pdb_methods *methods,
                                    TALLOC_CTX *mem_ctx,
                                    const DOM_SID *domain_sid,
@@ -3890,6 +4213,11 @@ static NTSTATUS pdb_init_ldapsam_common(PDB_CONTEXT *pdb_context, PDB_METHODS **
        (*pdb_method)->enum_group_memberships = ldapsam_enum_group_memberships;
        (*pdb_method)->lookup_rids = ldapsam_lookup_rids;
 
+       (*pdb_method)->get_account_policy = ldapsam_get_account_policy;
+       (*pdb_method)->set_account_policy = ldapsam_set_account_policy;
+
+       (*pdb_method)->get_seq_num = ldapsam_get_seq_num;
+
        /* TODO: Setup private data and free */
 
        ldap_state = TALLOC_ZERO_P(pdb_context->mem_ctx, struct ldapsam_privates);
index 3e5f8d1b9309047b62c4ca1f08b76911f2ceb63a..599a198c5a4cf7d122671ecb4e265032581823f9 100644 (file)
@@ -550,7 +550,7 @@ static int nmasldap_get_password(
        LDAP     *ld,
        char     *objectDN,
        size_t   *pwdSize,      /* in bytes */
-       char     *pwd )
+       unsigned char     *pwd )
 {
        int err = 0;
 
index edb578b1e7447bbeee1f900391cf5faccce5e176..6eb4305409a3a4b025720468afe430d4a1f03546 100644 (file)
@@ -313,10 +313,11 @@ static struct smb_passwd *getsmbfilepwent(struct smbpasswd_privates *smbpasswd_s
        unsigned char *smbpwd = smbpasswd_state->smbpwd;
        unsigned char *smbntpwd = smbpasswd_state->smbntpwd;
        char linebuf[256];
-       unsigned char c;
+       int c;
        unsigned char *p;
        long uidval;
        size_t linebuf_len;
+       char *status;
 
        if(fp == NULL) {
                DEBUG(0,("getsmbfilepwent: Bad password file pointer.\n"));
@@ -329,11 +330,12 @@ static struct smb_passwd *getsmbfilepwent(struct smbpasswd_privates *smbpasswd_s
        /*
         * Scan the file, a line at a time and check if the name matches.
         */
-       while (!feof(fp)) {
+       status = linebuf;
+       while (status && !feof(fp)) {
                linebuf[0] = '\0';
 
-               fgets(linebuf, 256, fp);
-               if (ferror(fp)) {
+               status = fgets(linebuf, 256, fp);
+               if (status == NULL && ferror(fp)) {
                        return NULL;
                }
 
@@ -651,7 +653,7 @@ Error was %s\n", newpwd->smb_name, pfile, strerror(errno)));
 
 #ifdef DEBUG_PASSWORD
        DEBUG(100, ("add_smbfilepwd_entry(%d): new_entry_len %d made line |%s|", 
-                       fd, new_entry_length, new_entry));
+                       fd, (int)new_entry_length, new_entry));
 #endif
 
        if ((wr_len = write(fd, new_entry, new_entry_length)) != new_entry_length) {
@@ -689,9 +691,10 @@ static BOOL mod_smbfilepwd_entry(struct smbpasswd_privates *smbpasswd_state, con
        /* Static buffers we will return. */
        pstring user_name;
 
+       char *status;
        char linebuf[256];
        char readbuf[1024];
-       unsigned char c;
+       int c;
        fstring ascii_p16;
        fstring encode_bits;
        unsigned char *p = NULL;
@@ -738,13 +741,14 @@ static BOOL mod_smbfilepwd_entry(struct smbpasswd_privates *smbpasswd_state, con
        /*
         * Scan the file, a line at a time and check if the name matches.
         */
-       while (!feof(fp)) {
+       status = linebuf;
+       while (status && !feof(fp)) {
                pwd_seekpos = sys_ftell(fp);
 
                linebuf[0] = '\0';
 
-               fgets(linebuf, sizeof(linebuf), fp);
-               if (ferror(fp)) {
+               status = fgets(linebuf, sizeof(linebuf), fp);
+               if (status == NULL && ferror(fp)) {
                        pw_file_unlock(lockfd, &smbpasswd_state->pw_file_lock_depth);
                        fclose(fp);
                        return False;
index 6144037200ffabd607ba912c26478b3c9ca434bb..29437c35a872ba98dcf7f0518c836f8893a084d4 100644 (file)
@@ -30,6 +30,9 @@
 
 static TDB_CONTEXT *tdb;
 
+/* Urrrg. global.... */
+BOOL global_machine_password_needs_changing;
+
 /**
  * Use a TDB to store an incrementing random seed.
  *
@@ -294,12 +297,23 @@ BOOL secrets_fetch_trust_account_password(const char *domain, uint8 ret_pwd[16],
                return False;
        }
 
-       if (pass_last_set_time) *pass_last_set_time = pass->mod_time;
+       if (pass_last_set_time) {
+               *pass_last_set_time = pass->mod_time;
+       }
        memcpy(ret_pwd, pass->hash, 16);
        SAFE_FREE(pass);
 
-       if (channel) 
+       if (channel) {
                *channel = get_default_sec_channel();
+       }
+
+       /* Test if machine password has expired and needs to be changed */
+       if (lp_machine_password_timeout()) {
+               if (pass->mod_time > 0 && time(NULL) > (pass->mod_time +
+                               lp_machine_password_timeout())) {
+                       global_machine_password_needs_changing = True;
+               }
+       }
 
        return True;
 }
@@ -454,11 +468,11 @@ BOOL secrets_store_machine_password(const char *pass, const char *domain, uint32
        return ret;
 }
 
-
 /************************************************************************
  Routine to fetch the plaintext machine account password for a realm
-the password is assumed to be a null terminated ascii string
+ the password is assumed to be a null terminated ascii string.
 ************************************************************************/
+
 char *secrets_fetch_machine_password(const char *domain, 
                                     time_t *pass_last_set_time,
                                     uint32 *channel)
@@ -503,7 +517,46 @@ char *secrets_fetch_machine_password(const char *domain,
        return ret;
 }
 
+/*******************************************************************
+ Wrapper around retrieving the trust account password
+*******************************************************************/
+                                                                                                                     
+BOOL get_trust_pw(const char *domain, uint8 ret_pwd[16], uint32 *channel)
+{
+       DOM_SID sid;
+       char *pwd;
+       time_t last_set_time;
+                                                                                                                     
+       /* if we are a DC and this is not our domain, then lookup an account
+               for the domain trust */
+                                                                                                                     
+       if ( IS_DC && !strequal(domain, lp_workgroup()) && lp_allow_trusted_domains() ) {
+               if (!secrets_fetch_trusted_domain_password(domain, &pwd, &sid,
+                                                       &last_set_time)) {
+                       DEBUG(0, ("get_trust_pw: could not fetch trust "
+                               "account password for trusted domain %s\n",
+                               domain));
+                       return False;
+               }
+                                                                                                                     
+               *channel = SEC_CHAN_DOMAIN;
+               E_md4hash(pwd, ret_pwd);
+               SAFE_FREE(pwd);
+
+               return True;
+       }
+                                                                                                                     
+       /* Just get the account for the requested domain. In the future this
+        * might also cover to be member of more than one domain. */
+                                                                                                                     
+       if (secrets_fetch_trust_account_password(domain, ret_pwd,
+                                               &last_set_time, channel))
+               return True;
 
+       DEBUG(5, ("get_trust_pw: could not fetch trust account "
+               "password for domain %s\n", domain));
+       return False;
+}
 
 /************************************************************************
  Routine to delete the machine trust account password file for a domain.
@@ -523,7 +576,6 @@ BOOL trusted_domain_password_delete(const char *domain)
        return secrets_delete(trustdom_keystr(domain));
 }
 
-
 BOOL secrets_store_ldap_pw(const char* dn, char* pw)
 {
        char *key = NULL;
@@ -541,8 +593,9 @@ BOOL secrets_store_ldap_pw(const char* dn, char* pw)
 }
 
 /*******************************************************************
- find the ldap password
+ Find the ldap password.
 ******************************************************************/
+
 BOOL fetch_ldap_pw(char **dn, char** pw)
 {
        char *key = NULL;
@@ -605,7 +658,6 @@ BOOL fetch_ldap_pw(char **dn, char** pw)
        return True;
 }
 
-
 /**
  * Get trusted domains info from secrets.tdb.
  *
index a9e1921e0d01757a0964f29ffad3f1744a732d77..42e4b6df967956c53195c859ede1a886f767de19 100644 (file)
@@ -30,15 +30,12 @@ typedef struct _known_sid_users {
        const char *known_user_name;
 } known_sid_users;
 
-static struct sid_name_map_info
+struct sid_name_map_info
 {
        const DOM_SID *sid;
        const char *name;
        const known_sid_users *known_users;
-} sid_name_map[MAX_SID_NAMES];
-
-static BOOL sid_name_map_initialized = False;
-/* static known_sid_users no_users[] = {{0, 0, NULL}}; */
+};
 
 static const known_sid_users everyone_users[] = {
        { 0, SID_NAME_WKN_GRP, "Everyone" },
@@ -83,64 +80,12 @@ static const known_sid_users builtin_groups[] = {
        { BUILTIN_ALIAS_RID_PRE_2K_ACCESS, SID_NAME_ALIAS, "Pre-Windows 2000 Compatible Access" },
        {  0, (enum SID_NAME_USE)0, NULL}};
 
-/**************************************************************************
- Quick init function.
-*************************************************************************/
-
-static void init_sid_name_map (void)
-{
-       int i = 0;
-       
-       if (sid_name_map_initialized) return;
-
-       if ((lp_security() == SEC_USER) && lp_domain_logons()) {
-               sid_name_map[i].sid = get_global_sam_sid();
-               /* This is not lp_workgroup() for good reason:
-                  it must stay around longer than the lp_*() 
-                  strings do */
-               sid_name_map[i].name = SMB_STRDUP(lp_workgroup());
-               sid_name_map[i].known_users = NULL;
-               i++;
-               sid_name_map[i].sid = get_global_sam_sid();
-               sid_name_map[i].name = SMB_STRDUP(global_myname());
-               sid_name_map[i].known_users = NULL;
-               i++;
-       } else {
-               sid_name_map[i].sid = get_global_sam_sid();
-               sid_name_map[i].name = SMB_STRDUP(global_myname());
-               sid_name_map[i].known_users = NULL;
-               i++;
-       }
-
-       sid_name_map[i].sid = &global_sid_Builtin;
-       sid_name_map[i].name = "BUILTIN";
-       sid_name_map[i].known_users = &builtin_groups[0];
-       i++;
-       
-       sid_name_map[i].sid = &global_sid_World_Domain;
-       sid_name_map[i].name = "";
-       sid_name_map[i].known_users = &everyone_users[0];
-       i++;
-
-       sid_name_map[i].sid = &global_sid_Creator_Owner_Domain;
-       sid_name_map[i].name = "";
-       sid_name_map[i].known_users = &creator_owner_users[0];
-       i++;
-               
-       sid_name_map[i].sid = &global_sid_NT_Authority;
-       sid_name_map[i].name = "NT Authority";
-       sid_name_map[i].known_users = &nt_authority_users[0];
-       i++;
-               
-       /* End of array. */
-       sid_name_map[i].sid = NULL;
-       sid_name_map[i].name = NULL;
-       sid_name_map[i].known_users = NULL;
-       
-       sid_name_map_initialized = True;
-               
-       return;
-}
+static struct sid_name_map_info special_domains[] = {
+       { &global_sid_Builtin, "BUILTIN", builtin_groups },
+       { &global_sid_World_Domain, "", everyone_users },
+       { &global_sid_Creator_Owner_Domain, "", creator_owner_users },
+       { &global_sid_NT_Authority, "NT Authority", nt_authority_users },
+       { NULL, NULL, NULL }};
 
 /**************************************************************************
  Turns a domain SID into a name, returned in the nt_domain argument.
@@ -153,101 +98,74 @@ BOOL map_domain_sid_to_name(DOM_SID *sid, fstring nt_domain)
        
        sid_to_string(sid_str, sid);
 
-       if (!sid_name_map_initialized) 
-               init_sid_name_map();
-
        DEBUG(5,("map_domain_sid_to_name: %s\n", sid_str));
 
-       if (nt_domain == NULL)
-               return False;
+       if (sid_check_is_domain(sid)) {
+               fstrcpy(nt_domain, get_global_sam_name());
+               return True;
+       }
 
-       while (sid_name_map[i].sid != NULL) {
-               sid_to_string(sid_str, sid_name_map[i].sid);
-               DEBUG(5,("map_domain_sid_to_name: compare: %s\n", sid_str));
-               if (sid_equal(sid_name_map[i].sid, sid)) {              
-                       fstrcpy(nt_domain, sid_name_map[i].name);
-                       DEBUG(5,("map_domain_sid_to_name: found '%s'\n", nt_domain));
+       while (special_domains[i].sid != NULL) {
+               DEBUG(5,("map_domain_sid_to_name: compare: %s\n",
+                        sid_string_static(special_domains[i].sid)));
+               if (sid_equal(special_domains[i].sid, sid)) {           
+                       fstrcpy(nt_domain, special_domains[i].name);
+                       DEBUG(5,("map_domain_sid_to_name: found '%s'\n",
+                                nt_domain));
                        return True;
                }
                i++;
        }
 
-       DEBUG(5,("map_domain_sid_to_name: mapping for %s not found\n", sid_str));
-
-    return False;
-}
-
-/**************************************************************************
- Looks up a known username from one of the known domains.
-***************************************************************************/
-
-BOOL lookup_known_rid(DOM_SID *sid, uint32 rid, char *name, enum SID_NAME_USE *psid_name_use)
-{
-       int i = 0;
-       struct sid_name_map_info *psnm;
-
-       if (!sid_name_map_initialized) 
-               init_sid_name_map();
-
-       for(i = 0; sid_name_map[i].sid != NULL; i++) {
-               psnm = &sid_name_map[i];
-               if(sid_equal(psnm->sid, sid)) {
-                       int j;
-                       for(j = 0; psnm->known_users && psnm->known_users[j].known_user_name != NULL; j++) {
-                               if(rid == psnm->known_users[j].rid) {
-                                       DEBUG(5,("lookup_builtin_rid: rid = %u, domain = '%s', user = '%s'\n",
-                                               (unsigned int)rid, psnm->name, psnm->known_users[j].known_user_name ));
-                                       fstrcpy( name, psnm->known_users[j].known_user_name);
-                                       *psid_name_use = psnm->known_users[j].sid_name_use;
-                                       return True;
-                               }
-                       }
-               }
-       }
+       DEBUG(5,("map_domain_sid_to_name: mapping for %s not found\n",
+                sid_string_static(sid)));
 
        return False;
 }
 
 /**************************************************************************
- Turns a domain name into a SID.
- *** side-effect: if the domain name is NULL, it is set to our domain ***
+ Looks up a known username from one of the known domains.
 ***************************************************************************/
 
-BOOL map_domain_name_to_sid(DOM_SID *sid, char *nt_domain)
+BOOL lookup_special_sid(const DOM_SID *sid, const char **domain,
+                       const char **name, enum SID_NAME_USE *type)
 {
-       int i = 0;
+       int i;
+       DOM_SID dom_sid;
+       uint32 rid;
+       const known_sid_users *users = NULL;
 
-       if (nt_domain == NULL) {
-               DEBUG(5,("map_domain_name_to_sid: mapping NULL domain to our SID.\n"));
-               sid_copy(sid, get_global_sam_sid());
-               return True;
+       sid_copy(&dom_sid, sid);
+       if (!sid_split_rid(&dom_sid, &rid)) {
+               DEBUG(2, ("Could not split rid from SID\n"));
+               return False;
        }
 
-       if (nt_domain[0] == 0) {
-               fstrcpy(nt_domain, global_myname());
-               DEBUG(5,("map_domain_name_to_sid: overriding blank name to %s\n", nt_domain));
-               sid_copy(sid, get_global_sam_sid());
-               return True;
+       for (i=0; special_domains[i].sid != NULL; i++) {
+               if (sid_equal(&dom_sid, special_domains[i].sid)) {
+                       *domain = special_domains[i].name;
+                       users = special_domains[i].known_users;
+                       break;
+               }
        }
 
-       DEBUG(5,("map_domain_name_to_sid: %s\n", nt_domain));
-
-       if (!sid_name_map_initialized) 
-               init_sid_name_map();
+       if (users == NULL) {
+               DEBUG(10, ("SID %s is no special sid\n",
+                          sid_string_static(sid)));
+               return False;
+       }
 
-       while (sid_name_map[i].name != NULL) {
-               DEBUG(5,("map_domain_name_to_sid: compare: %s\n", sid_name_map[i].name));
-               if (strequal(sid_name_map[i].name, nt_domain)) {
-                       fstring sid_str;
-                       sid_copy(sid, sid_name_map[i].sid);
-                       sid_to_string(sid_str, sid_name_map[i].sid);
-                       DEBUG(5,("map_domain_name_to_sid: found %s\n", sid_str));
+       for (i=0; users[i].known_user_name != NULL; i++) {
+               if (rid == users[i].rid) {
+                       *name = users[i].known_user_name;
+                       *type = users[i].sid_name_use;
                        return True;
                }
-               i++;
        }
 
-       DEBUG(0,("map_domain_name_to_sid: mapping to %s not found.\n", nt_domain));
+       DEBUG(10, ("RID of special SID %s not found\n",
+                  sid_string_static(sid)));
+
        return False;
 }
 
@@ -283,20 +201,17 @@ BOOL map_name_to_wellknown_sid(DOM_SID *sid, enum SID_NAME_USE *use, const char
 {
        int i, j;
 
-       if (!sid_name_map_initialized)
-               init_sid_name_map();
-
        DEBUG(10,("map_name_to_wellknown_sid: looking up %s\n", name));
 
-       for (i=0; sid_name_map[i].sid != NULL; i++) {
-               const known_sid_users *users = sid_name_map[i].known_users;
+       for (i=0; special_domains[i].sid != NULL; i++) {
+               const known_sid_users *users = special_domains[i].known_users;
 
                if (users == NULL)
                        continue;
 
                for (j=0; users[j].known_user_name != NULL; j++) {
                        if ( strequal(users[j].known_user_name, name) ) {
-                               sid_copy(sid, sid_name_map[i].sid);
+                               sid_copy(sid, special_domains[i].sid);
                                sid_append_rid(sid, users[j].rid);
                                *use = users[j].sid_name_use;
                                return True;
index e289eba1b6949a00b802aceaea1e34948d2e8449..e71d9e6f259020e22601284d09fe854bb9498bfb 100644 (file)
@@ -176,13 +176,15 @@ static void print_notify_send_messages_to_printer(const char *printer, unsigned
                return;
 
        for (i = 0; i < num_pids; i++) {
-               unsigned int q_len = messages_pending_for_pid(pid_list[i]);
+               unsigned int q_len = messages_pending_for_pid(pid_to_procid(pid_list[i]));
                if (q_len > 1000) {
                        DEBUG(5, ("print_notify_send_messages_to_printer: discarding notify to printer %s as queue length = %u\n",
                                printer, q_len ));
                        continue;
                }
-               message_send_pid_with_timeout(pid_list[i], MSG_PRINTER_NOTIFY2, buf, offset, True, timeout);
+               message_send_pid_with_timeout(pid_to_procid(pid_list[i]),
+                                             MSG_PRINTER_NOTIFY2,
+                                             buf, offset, True, timeout);
        }
 }
 
@@ -328,7 +330,7 @@ static void send_notify_field_values(const char *sharename, uint32 type,
 
 static void send_notify_field_buffer(const char *sharename, uint32 type,
                                     uint32 field, uint32 id, uint32 len,
-                                    char *buffer)
+                                    const char *buffer)
 {
        struct spoolss_notify_msg *msg;
 
@@ -349,7 +351,7 @@ static void send_notify_field_buffer(const char *sharename, uint32 type,
        msg->field = field;
        msg->id = id;
        msg->len = len;
-       msg->notify.data = buffer;
+       msg->notify.data = CONST_DISCARD(char *,buffer);
 
        send_spoolss_notify2_msg(msg);
 }
@@ -484,7 +486,7 @@ void notify_printer_location(int snum, char *location)
                snum, strlen(location) + 1, location);
 }
 
-void notify_printer_byname( const char *printername, uint32 change, char *value )
+void notify_printer_byname( const char *printername, uint32 change, const char *value )
 {
        int snum = print_queue_snum(printername);
        int type = PRINTER_NOTIFY_TYPE;
index e6064564dc81589c68e4de7e47f573a9548aa7eb..8ae896fddf41013c9104bac2b401de609a457d03 100644 (file)
@@ -265,7 +265,7 @@ BOOL cups_cache_reload(void)
  * 'cups_job_delete()' - Delete a job.
  */
 
-static int cups_job_delete(int snum, struct printjob *pjob)
+static int cups_job_delete(const char *sharename, const char *lprm_command, struct printjob *pjob)
 {
        int             ret = 1;                /* Return value */
        http_t          *http = NULL;           /* HTTP connection to server */
@@ -275,7 +275,7 @@ static int cups_job_delete(int snum, struct printjob *pjob)
        char            uri[HTTP_MAX_URI]; /* printer-uri attribute */
 
 
-       DEBUG(5,("cups_job_delete(%d, %p (%d))\n", snum, pjob, pjob->sysjob));
+       DEBUG(5,("cups_job_delete(%s, %p (%d))\n", sharename, pjob, pjob->sysjob));
 
        /*
         * Make sure we don't ask for passwords...
@@ -712,7 +712,7 @@ static int cups_queue_get(const char *sharename,
 
        *q = NULL;
 
-       /* HACK ALERT!!!  The porblem with support the 'printer name' 
+       /* HACK ALERT!!!  The problem with support the 'printer name' 
           option is that we key the tdb off the sharename.  So we will 
           overload the lpq_command string to pass in the printername 
           (which is basically what we do for non-cups printers ... using 
index 256654179e68141a37d5a3ab4e899a8058268a10..b2484d5b433245552af6f3d57f4f640dc4dd1252 100644 (file)
@@ -27,7 +27,8 @@ run a given print command
 a null terminated list of value/substitute pairs is provided
 for local substitution strings
 ****************************************************************************/
-static int print_run_command(int snum, const char* printername, BOOL do_sub, char *command, int *outfd, ...)
+static int print_run_command(int snum, const char* printername, BOOL do_sub,
+                            const char *command, int *outfd, ...)
 {
 
        pstring syscmd;
@@ -68,14 +69,13 @@ static int print_run_command(int snum, const char* printername, BOOL do_sub, cha
 /****************************************************************************
 delete a print job
 ****************************************************************************/
-static int generic_job_delete(int snum, struct printjob *pjob)
+static int generic_job_delete( const char *sharename, const char *lprm_command, struct printjob *pjob)
 {
        fstring jobstr;
 
        /* need to delete the spooled entry */
        slprintf(jobstr, sizeof(jobstr)-1, "%d", pjob->sysjob);
-       return print_run_command(snum, PRINTERNAME(snum), True,
-                  lp_lprmcommand(snum), NULL,
+       return print_run_command( -1, sharename, False, lprm_command, NULL,
                   "%j", jobstr,
                   "%T", http_timestring(pjob->starttime),
                   NULL);
index 33bbcb256ab6010072d4348821f13f7fd56e0c5d..6193dbe2ca94cbc50f69428c6580789ec24bdece 100644 (file)
@@ -423,7 +423,7 @@ BOOL iprint_cache_reload(void)
  * 'iprint_job_delete()' - Delete a job.
  */
 
-static int iprint_job_delete(int snum, struct printjob *pjob)
+static int iprint_job_delete(const char *sharename, const char *lprm_command, struct printjob *pjob)
 {
        int             ret = 1;                /* Return value */
        http_t          *http = NULL;           /* HTTP connection to server */
@@ -434,7 +434,7 @@ static int iprint_job_delete(int snum, struct printjob *pjob)
        char            httpPath[HTTP_MAX_URI]; /* path portion of the printer-uri */
 
 
-       DEBUG(5,("iprint_job_delete(%d, %p (%d))\n", snum, pjob, pjob->sysjob));
+       DEBUG(5,("iprint_job_delete(%s, %p (%d))\n", sharename, pjob, pjob->sysjob));
 
        /*
        * Make sure we don't ask for passwords...
@@ -476,7 +476,7 @@ static int iprint_job_delete(int snum, struct printjob *pjob)
        ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
                     "attributes-natural-language", NULL, language->language);
 
-       slprintf(uri, sizeof(uri) - 1, "ipp://%s/ipp/%s", iprint_server(), PRINTERNAME(snum));
+       slprintf(uri, sizeof(uri) - 1, "ipp://%s/ipp/%s", iprint_server(), sharename);
 
        ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri);
 
@@ -489,7 +489,7 @@ static int iprint_job_delete(int snum, struct printjob *pjob)
        * Do the request and get back a response...
        */
 
-       slprintf(httpPath, sizeof(httpPath) - 1, "/ipp/%s", PRINTERNAME(snum));
+       slprintf(httpPath, sizeof(httpPath) - 1, "/ipp/%s", sharename);
 
        if ((response = cupsDoRequest(http, request, httpPath)) != NULL) {
                if (response->request.status.status_code >= IPP_OK_CONFLICT) {
index 61470f151002269327addb24823f9b0e74b3c328..6e74095f719b01f8a6d8c75d2dc9ee08f6e9c949 100644 (file)
@@ -691,6 +691,8 @@ struct traverse_struct {
        int qcount, snum, maxcount, total_jobs;
        const char *sharename;
        time_t lpq_time;
+       const char *lprm_command;
+       struct printif *print_if;
 };
 
 /****************************************************************************
@@ -737,7 +739,7 @@ static int traverse_fn_delete(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void
                /* if a job is not spooled and the process doesn't
                    exist then kill it. This cleans up after smbd
                    deaths */
-               if (!process_exists(pjob.pid)) {
+               if (!process_exists_by_pid(pjob.pid)) {
                        DEBUG(10,("traverse_fn_delete: pjob %u deleted due to !process_exists (%u)\n",
                                                (unsigned int)jobid, (unsigned int)pjob.pid ));
                        pjob_delete(ts->sharename, jobid);
@@ -750,9 +752,38 @@ static int traverse_fn_delete(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void
        
        if ( pjob.smbjob ) {
                for (i=0;i<ts->qcount;i++) {
-                       uint32 curr_jobid = print_parse_jobid(ts->queue[i].fs_file);
-                       if (jobid == curr_jobid)
+                       uint32 curr_jobid;
+
+                       if ( pjob.status == LPQ_DELETED )
+                               continue;
+
+                       curr_jobid = print_parse_jobid(ts->queue[i].fs_file);
+
+                       if (jobid == curr_jobid) {
+
+                               /* try to clean up any jobs that need to be deleted */
+
+                               if ( pjob.status == LPQ_DELETING ) {
+                                       int result;
+
+                                       result = (*(ts->print_if->job_delete))( 
+                                               ts->sharename, ts->lprm_command, &pjob );
+
+                                       if ( result != 0 ) {
+                                               /* if we can't delete, then reset the job status */
+                                               pjob.status = LPQ_QUEUED;
+                                               pjob_store(ts->sharename, jobid, &pjob);
+                                       }
+                                       else {
+                                               /* if we deleted the job, the remove the tdb record */
+                                               pjob_delete(ts->sharename, jobid);
+                                               pjob.status = LPQ_DELETED;
+                                       }
+                                               
+                               }
+
                                break;
+                       }
                }
        }
        
@@ -779,9 +810,10 @@ static int traverse_fn_delete(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void
                return 0;
        }
 
-       /* Save the pjob attributes we will store. */
-       /* FIXME!!! This is the only place where queue->job 
+       /* Save the pjob attributes we will store. 
+          FIXME!!! This is the only place where queue->job 
           represents the SMB jobid      --jerry */
+
        ts->queue[i].job = jobid;               
        ts->queue[i].size = pjob.size;
        ts->queue[i].page_count = pjob.page_count;
@@ -840,7 +872,7 @@ static pid_t get_updating_pid(const char *sharename)
        updating_pid = IVAL(data.dptr, 0);
        SAFE_FREE(data.dptr);
 
-       if (process_exists(updating_pid))
+       if (process_exists_by_pid(updating_pid))
                return updating_pid;
 
        return (pid_t)-1;
@@ -910,6 +942,7 @@ static int printjob_comp(print_queue_struct *j1, print_queue_struct *j2)
 
 /****************************************************************************
  Store the sorted queue representation for later portmon retrieval.
+ Skip deleted jobs
 ****************************************************************************/
 
 static void store_queue_struct(struct tdb_print_db *pdb, struct traverse_struct *pts)
@@ -923,13 +956,17 @@ static void store_queue_struct(struct tdb_print_db *pdb, struct traverse_struct
 
        if (max_reported_jobs && (max_reported_jobs < pts->qcount))
                pts->qcount = max_reported_jobs;
-       qcount = pts->qcount;
+       qcount = 0;
 
        /* Work out the size. */
        data.dsize = 0;
        data.dsize += tdb_pack(NULL, 0, "d", qcount);
 
        for (i = 0; i < pts->qcount; i++) {
+               if ( queue[i].status == LPQ_DELETED )
+                       continue;
+
+               qcount++;
                data.dsize += tdb_pack(NULL, 0, "ddddddff",
                                (uint32)queue[i].job,
                                (uint32)queue[i].size,
@@ -947,6 +984,9 @@ static void store_queue_struct(struct tdb_print_db *pdb, struct traverse_struct
         len = 0;
        len += tdb_pack(data.dptr + len, data.dsize - len, "d", qcount);
        for (i = 0; i < pts->qcount; i++) {
+               if ( queue[i].status == LPQ_DELETED )
+                       continue;
+
                len += tdb_pack(data.dptr + len, data.dsize - len, "ddddddff",
                                (uint32)queue[i].job,
                                (uint32)queue[i].size,
@@ -1024,6 +1064,7 @@ static BOOL print_cache_expired(const char *sharename, BOOL check_pending)
                || (time_now - last_qscan_time) >= lp_lpqcachetime() 
                || last_qscan_time > (time_now + MAX_CACHE_VALID_TIME)) 
        {
+               uint32 u;
                time_t msg_pending_time;
 
                DEBUG(4, ("print_cache_expired: cache expired for queue %s " 
@@ -1039,8 +1080,8 @@ static BOOL print_cache_expired(const char *sharename, BOOL check_pending)
                snprintf(key, sizeof(key), "MSG_PENDING/%s", sharename);
 
                if ( check_pending 
-                       && tdb_fetch_uint32( pdb->tdb, key, (uint32*)&msg_pending_time ) 
-                       && msg_pending_time > 0
+                       && tdb_fetch_uint32( pdb->tdb, key, &u ) 
+                       && (msg_pending_time=u) > 0
                        && msg_pending_time <= time_now 
                        && (time_now - msg_pending_time) < 60 ) 
                {
@@ -1063,7 +1104,7 @@ done:
 
 static void print_queue_update_internal( const char *sharename, 
                                          struct printif *current_printif,
-                                         char *lpq_command )
+                                         char *lpq_command, char *lprm_command )
 {
        int i, qcount;
        print_queue_struct *queue = NULL;
@@ -1141,8 +1182,14 @@ static void print_queue_update_internal( const char *sharename,
                }
 
                pjob->sysjob = queue[i].job;
-               pjob->status = queue[i].status;
+
+               /* don't reset the status on jobs to be deleted */
+
+               if ( pjob->status != LPQ_DELETING )
+                       pjob->status = queue[i].status;
+
                pjob_store(sharename, jobid, pjob);
+
                check_job_changed(sharename, jcdata, jobid);
        }
 
@@ -1156,6 +1203,8 @@ static void print_queue_update_internal( const char *sharename,
        tstruct.total_jobs = 0;
        tstruct.lpq_time = time(NULL);
        tstruct.sharename = sharename;
+       tstruct.lprm_command = lprm_command;
+       tstruct.print_if = current_printif;
 
        tdb_traverse(pdb->tdb, traverse_fn_delete, (void *)&tstruct);
 
@@ -1216,7 +1265,7 @@ static void print_queue_update_internal( const char *sharename,
 
 static void print_queue_update_with_lock( const char *sharename, 
                                           struct printif *current_printif,
-                                          char *lpq_command )
+                                          char *lpq_command, char *lprm_command )
 {
        fstring keystr;
        struct tdb_print_db *pdb;
@@ -1283,7 +1332,8 @@ static void print_queue_update_with_lock( const char *sharename,
 
        /* do the main work now */
        
-       print_queue_update_internal( sharename, current_printif, lpq_command );
+       print_queue_update_internal( sharename, current_printif, 
+               lpq_command, lprm_command );
        
        /* Delete our pid from the db. */
        set_updating_pid(sharename, False);
@@ -1293,17 +1343,19 @@ static void print_queue_update_with_lock( const char *sharename,
 /****************************************************************************
 this is the receive function of the background lpq updater
 ****************************************************************************/
-static void print_queue_receive(int msg_type, pid_t src, void *buf, size_t msglen)
+static void print_queue_receive(int msg_type, struct process_id src,
+                               void *buf, size_t msglen)
 {
        fstring sharename;
-       pstring lpqcommand;
+       pstring lpqcommand, lprmcommand;
        int printing_type;
        size_t len;
 
-       len = tdb_unpack( buf, msglen, "fdP",
+       len = tdb_unpack( buf, msglen, "fdPP",
                sharename,
                &printing_type,
-               lpqcommand );
+               lpqcommand,
+               lprmcommand );
 
        if ( len == -1 ) {
                DEBUG(0,("print_queue_receive: Got invalid print queue update message\n"));
@@ -1312,7 +1364,7 @@ static void print_queue_receive(int msg_type, pid_t src, void *buf, size_t msgle
 
        print_queue_update_with_lock(sharename, 
                get_printer_fns_from_type(printing_type),
-               lpqcommand );
+               lpqcommand, lprmcommand );
 
        return;
 }
@@ -1382,7 +1434,7 @@ static void print_queue_update(int snum, BOOL force)
 {
        fstring key;
        fstring sharename;
-       pstring lpqcommand;
+       pstring lpqcommand, lprmcommand;
        char *buffer = NULL;
        size_t len = 0;
        size_t newlen;
@@ -1398,6 +1450,10 @@ static void print_queue_update(int snum, BOOL force)
        string_sub2( lpqcommand, "%p", PRINTERNAME(snum), sizeof(lpqcommand), False, False );
        standard_sub_snum( snum, lpqcommand, sizeof(lpqcommand) );
        
+       pstrcpy( lprmcommand, lp_lprmcommand(snum));
+       string_sub2( lprmcommand, "%p", PRINTERNAME(snum), sizeof(lprmcommand), False, False );
+       standard_sub_snum( snum, lprmcommand, sizeof(lprmcommand) );
+       
        /* 
         * Make sure that the background queue process exists.  
         * Otherwise just do the update ourselves 
@@ -1406,7 +1462,7 @@ static void print_queue_update(int snum, BOOL force)
        if ( force || background_lpq_updater_pid == -1 ) {
                DEBUG(4,("print_queue_update: updating queue [%s] myself\n", sharename));
                current_printif = get_printer_fns( snum );
-               print_queue_update_with_lock( sharename, current_printif, lpqcommand );
+               print_queue_update_with_lock( sharename, current_printif, lpqcommand, lprmcommand );
 
                return;
        }
@@ -1415,23 +1471,26 @@ static void print_queue_update(int snum, BOOL force)
        
        /* get the length */
 
-       len = tdb_pack( buffer, len, "fdP",
+       len = tdb_pack( buffer, len, "fdPP",
                sharename,
                type,
-               lpqcommand );
+               lpqcommand, 
+               lprmcommand );
 
        buffer = SMB_XMALLOC_ARRAY( char, len );
 
        /* now pack the buffer */
-       newlen = tdb_pack( buffer, len, "fdP",
+       newlen = tdb_pack( buffer, len, "fdPP",
                sharename,
                type,
-               lpqcommand );
+               lpqcommand,
+               lprmcommand );
 
        SMB_ASSERT( newlen == len );
 
        DEBUG(10,("print_queue_update: Sending message -> printer = %s, "
-               "type = %d, lpq command = [%s]\n", sharename, type, lpqcommand ));
+               "type = %d, lpq command = [%s] lprm command = [%s]\n", 
+               sharename, type, lpqcommand, lprmcommand ));
 
        /* here we set a msg pending record for other smbd processes 
           to throttle the number of duplicate print_queue_update msgs
@@ -1457,7 +1516,7 @@ static void print_queue_update(int snum, BOOL force)
        /* finally send the message */
        
        become_root();
-       message_send_pid(background_lpq_updater_pid,
+       message_send_pid(pid_to_procid(background_lpq_updater_pid),
                 MSG_PRINTER_UPDATE, buffer, len, False);
        unbecome_root();
 
@@ -1806,8 +1865,6 @@ static BOOL print_job_delete1(int snum, uint32 jobid)
        int result = 0;
        struct printif *current_printif = get_printer_fns( snum );
 
-       pjob = print_job_find(sharename, jobid);
-
        if (!pjob)
                return False;
 
@@ -1819,7 +1876,9 @@ static BOOL print_job_delete1(int snum, uint32 jobid)
                return True;
 
        /* Hrm - we need to be able to cope with deleting a job before it
-          has reached the spooler. */
+          has reached the spooler.  Just mark it as LPQ_DELETING and 
+          let the print_queue_update() code rmeove the record */
+          
 
        if (pjob->sysjob == -1) {
                DEBUG(5, ("attempt to delete job %u not seen by lpr\n", (unsigned int)jobid));
@@ -1830,24 +1889,31 @@ static BOOL print_job_delete1(int snum, uint32 jobid)
        pjob->status = LPQ_DELETING;
        pjob_store(sharename, jobid, pjob);
 
-       if (pjob->spooled && pjob->sysjob != -1)
-               result = (*(current_printif->job_delete))(snum, pjob);
+       if (pjob->spooled && pjob->sysjob != -1) 
+       {
+               result = (*(current_printif->job_delete))(
+                       PRINTERNAME(snum),
+                       lp_lprmcommand(snum), 
+                       pjob);
 
-       /* Delete the tdb entry if the delete succeeded or the job hasn't
-          been spooled. */
+               /* Delete the tdb entry if the delete succeeded or the job hasn't
+                  been spooled. */
 
-       if (result == 0) {
-               struct tdb_print_db *pdb = get_print_db_byname(sharename);
-               int njobs = 1;
+               if (result == 0) {
+                       struct tdb_print_db *pdb = get_print_db_byname(sharename);
+                       int njobs = 1;
 
-               if (!pdb)
-                       return False;
-               pjob_delete(sharename, jobid);
-               /* Ensure we keep a rough count of the number of total jobs... */
-               tdb_change_int32_atomic(pdb->tdb, "INFO/total_jobs", &njobs, -1);
-               release_print_db(pdb);
+                       if (!pdb)
+                               return False;
+                       pjob_delete(sharename, jobid);
+                       /* Ensure we keep a rough count of the number of total jobs... */
+                       tdb_change_int32_atomic(pdb->tdb, "INFO/total_jobs", &njobs, -1);
+                       release_print_db(pdb);
+               }
        }
 
+       remove_from_jobs_changed( sharename, jobid );
+
        return (result == 0);
 }
 
@@ -1877,7 +1943,8 @@ static BOOL is_owner(struct current_user *user, int snum, uint32 jobid)
 BOOL print_job_delete(struct current_user *user, int snum, uint32 jobid, WERROR *errcode)
 {
        const char* sharename = lp_const_servicename( snum );
-       BOOL    owner, deleted;
+       struct printjob *pjob;
+       BOOL    owner;
        char    *fname;
 
        *errcode = WERR_OK;
@@ -1929,11 +1996,11 @@ pause, or resume print job. User name: %s. Printer name: %s.",
 
        print_queue_update(snum, True);
        
-       deleted = !print_job_exists(sharename, jobid);
-       if ( !deleted )
+       pjob = print_job_find(sharename, jobid);
+       if ( pjob && (pjob->status != LPQ_DELETING) )
                *errcode = WERR_ACCESS_DENIED;
 
-       return deleted;
+       return (pjob == NULL );
 }
 
 /****************************************************************************
index b9b4b3c6b04ab6249f440bc235d995dd1cba1bde..adea10dfa691b5277152a65f1e63ad1f5a5e3677 100644 (file)
@@ -188,7 +188,7 @@ TDB_DATA get_printer_notify_pid_list(TDB_CONTEXT *tdb, const char *printer_name,
 
                /* Entry is dead if process doesn't exist or refcount is zero. */
 
-               while ((i < data.dsize) && ((IVAL(data.dptr, i + 4) == 0) || !process_exists(pid))) {
+               while ((i < data.dsize) && ((IVAL(data.dptr, i + 4) == 0) || !process_exists_by_pid(pid))) {
 
                        /* Refcount == zero is a logic error and should never happen. */
                        if (IVAL(data.dptr, i + 4) == 0) {
index e6d34e68cda7fcf3201f0b94086aad92bfa46cf1..0cf8c8e15bffa40fc4a7fdd353eae84acecbf04f 100644 (file)
@@ -79,7 +79,8 @@ void profile_message(int msg_type, pid_t src, void *buf, size_t len)
 /****************************************************************************
 receive a request profile level message
 ****************************************************************************/
-void reqprofile_message(int msg_type, pid_t src, void *buf, size_t len)
+void reqprofile_message(int msg_type, struct process_id src,
+                       void *buf, size_t len)
 {
         int level;
 
@@ -88,7 +89,8 @@ void reqprofile_message(int msg_type, pid_t src, void *buf, size_t len)
 #else
        level = 0;
 #endif
-       DEBUG(1,("INFO: Received REQ_PROFILELEVEL message from PID %u\n",(unsigned int)src));
+       DEBUG(1,("INFO: Received REQ_PROFILELEVEL message from PID %u\n",
+                (unsigned int)procid_to_pid(&src)));
        message_send_pid(src, MSG_PROFILELEVEL, &level, sizeof(int), True);
 }
 
index afb5c613c802d2f224980b8e51c0ca8fa87faa54..ab8fc14d909cd04c7787551749980f04881df763 100644 (file)
@@ -92,18 +92,10 @@ static BOOL init_registry_data( void )
        fstring keyname, subkeyname;
        REGSUBKEY_CTR *subkeys;
        REGVAL_CTR *values;
-       uint32 *ctx;
        int i;
        const char *p, *p2;
        UNISTR2 data;
        
-       /* create a new top level talloc ctx */
-
-       if ( !(ctx = TALLOC_P( NULL, uint32 )) ) {
-               DEBUG(0,("init_registry_data: top level talloc() failure!\n"));
-               return False;
-       }
-       
        /* loop over all of the predefined paths and add each component */
        
        for ( i=0; builtin_registry_paths[i] != NULL; i++ ) {
@@ -140,7 +132,7 @@ static BOOL init_registry_data( void )
                           we are about to update the record.  We just want any 
                           subkeys already present */
                        
-                       if ( !(subkeys = TALLOC_ZERO_P( ctx, REGSUBKEY_CTR )) ) {
+                       if ( !(subkeys = TALLOC_ZERO_P( NULL, REGSUBKEY_CTR )) ) {
                                DEBUG(0,("talloc() failure!\n"));
                                return False;
                        }
@@ -158,7 +150,7 @@ static BOOL init_registry_data( void )
        /* loop over all of the predefined values and add each component */
        
        for ( i=0; builtin_registry_values[i].path != NULL; i++ ) {
-               if ( !(values = TALLOC_ZERO_P( ctx, REGVAL_CTR )) ) {
+               if ( !(values = TALLOC_ZERO_P( NULL, REGVAL_CTR )) ) {
                        DEBUG(0,("talloc() failure!\n"));
                        return False;
                }
index 7f8f664ec6e196aee4bf9f1aab30328eb7350319..b1a2a307554ab1567baff624d06a3e8241c2d81f 100644 (file)
@@ -37,7 +37,7 @@ static int netlogon_params( REGVAL_CTR *regvals )
 {
        uint32 dwValue;
        
-       if ( !account_policy_get(AP_REFUSE_MACHINE_PW_CHANGE, &dwValue) )
+       if ( !pdb_get_account_policy(AP_REFUSE_MACHINE_PW_CHANGE, &dwValue) )
                dwValue = 0;
                
        regval_ctr_addvalue( regvals, "RefusePasswordChange", REG_DWORD,
@@ -98,6 +98,99 @@ static int tcpip_params( REGVAL_CTR *regvals )
        return regval_ctr_numvals( regvals );
 }
 
+/***********************************************************************
+***********************************************************************/
+
+static int perflib_params( REGVAL_CTR *regvals )
+{
+       int base_index = -1;
+       int last_counter = -1;
+       int last_help = -1;
+       int version = 0x00010001;
+       
+       base_index = reg_perfcount_get_base_index();
+       regval_ctr_addvalue(regvals, "Base Index", REG_DWORD, (char *)&base_index, sizeof(base_index));
+       last_counter = reg_perfcount_get_last_counter(base_index);
+       regval_ctr_addvalue(regvals, "Last Counter", REG_DWORD, (char *)&last_counter, sizeof(last_counter));
+       last_help = reg_perfcount_get_last_help(last_counter);
+       regval_ctr_addvalue(regvals, "Last Help", REG_DWORD, (char *)&last_help, sizeof(last_help));
+       regval_ctr_addvalue(regvals, "Version", REG_DWORD, (char *)&version, sizeof(version));
+
+       return regval_ctr_numvals( regvals );
+}
+
+/***********************************************************************
+***********************************************************************/
+
+static int perflib_009_params( REGVAL_CTR *regvals )
+{
+       int base_index;
+       int buffer_size;
+       char *buffer = NULL;
+
+       base_index = reg_perfcount_get_base_index();
+       buffer_size = reg_perfcount_get_counter_names(base_index, &buffer);
+       regval_ctr_addvalue(regvals, "Counter", REG_MULTI_SZ, buffer, buffer_size);
+       if(buffer_size > 0)
+               SAFE_FREE(buffer);
+       buffer_size = reg_perfcount_get_counter_help(base_index, &buffer);
+       regval_ctr_addvalue(regvals, "Help", REG_MULTI_SZ, buffer, buffer_size);
+       if(buffer_size > 0)
+               SAFE_FREE(buffer);
+       
+       return regval_ctr_numvals( regvals );
+}
+
+/***********************************************************************
+***********************************************************************/
+
+static int hkpt_params( REGVAL_CTR *regvals )
+{
+       uint32 base_index;
+       uint32 buffer_size;
+       char *buffer = NULL;
+
+       /* This is ALMOST the same as perflib_009_params, but HKPT has
+          a "Counters" entry instead of a "Counter" key. <Grrrr> */
+          
+       base_index = reg_perfcount_get_base_index();
+       buffer_size = reg_perfcount_get_counter_names(base_index, &buffer);
+       regval_ctr_addvalue(regvals, "Counters", REG_MULTI_SZ, buffer, buffer_size);
+       
+       if(buffer_size > 0)
+               SAFE_FREE(buffer);
+               
+       buffer_size = reg_perfcount_get_counter_help(base_index, &buffer);
+       regval_ctr_addvalue(regvals, "Help", REG_MULTI_SZ, buffer, buffer_size);
+       if(buffer_size > 0)
+               SAFE_FREE(buffer);
+       
+       return regval_ctr_numvals( regvals );
+}
+
+/***********************************************************************
+***********************************************************************/
+
+static int current_version( REGVAL_CTR *values )
+{
+       const char *sysroot_string = "c:\\Windows";
+       fstring sysversion;
+       fstring value;
+       uint32 value_length;
+       
+       value_length = push_ucs2( value, value, sysroot_string, sizeof(value), 
+               STR_TERMINATE|STR_NOALIGN );
+       regval_ctr_addvalue( values, "SystemRoot", REG_SZ, value, value_length );
+       
+       fstr_sprintf( sysversion, "%d.%d", lp_major_announce_version(), lp_minor_announce_version() );
+       value_length = push_ucs2( value, value, sysversion, sizeof(value), 
+               STR_TERMINATE|STR_NOALIGN );
+       regval_ctr_addvalue( values, "CurrentVersion", REG_SZ, value, value_length );
+       
+               
+       return regval_ctr_numvals( values );
+}
+
 
 /***********************************************************************
  Structure holding the registry paths and pointers to the value 
@@ -108,6 +201,10 @@ static struct reg_dyn_values dynamic_values[] = {
        { "HKLM/SYSTEM/CURRENTCONTROLSET/SERVICES/NETLOGON/PARAMETERS", &netlogon_params  },
        { "HKLM/SYSTEM/CURRENTCONTROLSET/CONTROL/PRODUCTOPTIONS",       &prod_options     },
        { "HKLM/SYSTEM/CURRENTCONTROLSET/SERVICES/TCPIP/PARAMETERS",    &tcpip_params     },
+       { "HKLM/SOFTWARE/MICROSOFT/WINDOWS NT/CURRENTVERSION/PERFLIB",  &perflib_params   }, 
+       { "HKLM/SOFTWARE/MICROSOFT/WINDOWS NT/CURRENTVERSION/PERFLIB/009", &perflib_009_params }, 
+       { "HKLM/SOFTWARE/MICROSOFT/WINDOWS NT/CURRENTVERSION",          &current_version }, 
+       { "HKPT", &hkpt_params },
        { NULL, NULL }
 };
 
index b20eb046db8034428140b31044b2458e92187c4d..bed9e1d59aec33ac8b4be8a801d29f81e8571a8c 100644 (file)
@@ -1,7 +1,8 @@
 /* 
  *  Unix SMB/CIFS implementation.
  *  Virtual Windows Registry Layer
- *  Copyright (C) Marcin Krzysztof Porwit    2005.
+ *  Copyright (C) Marcin Krzysztof Porwit    2005,
+ *  Copyright (C) Gerald (Jerry) Carter      2005.
  *  
  *  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
  
 #include "includes.h"
 
+
 /**********************************************************************
- handle enumeration of values AT KEY_EVENTLOG
- *********************************************************************/
-static int eventlog_topkey_values( char *key, REGVAL_CTR *val )
+ Enumerate registry subkey names given a registry path.  
+*********************************************************************/
+
+static int elog_fetch_keys( const char *key, REGSUBKEY_CTR *subkeys )
 {
-    int                num_values = 0;
-    char               *keystr, *key2 = NULL;
-    char               *base, *new_path;
-    fstring            evtlogname; 
-    UNISTR2            data;
-    int             iDisplayNameId;
-    int             iMaxSize;
-    
-    /* 
-     *  TODO - callout to get these values...
-     */
+       const char    **elogs = lp_eventlog_list();
+       char          *path;
+       int           i;
     
-    if ( key ) 
-    {
-       key2 = SMB_STRDUP( key );
-       keystr = key2;
-       reg_split_path( keystr, &base, &new_path );
+       path = reg_remaining_path( key + strlen(KEY_EVENTLOG) );
        
-       iDisplayNameId = 0x00000100;
-       iMaxSize=        0x00080000;
-       
-       fstrcpy( evtlogname, base );
-       DEBUG(10,("eventlog_topkey_values: subkey root=> [%s] subkey path=>[%s]\n", base,new_path));
-       
-       if ( !new_path ) 
-       {
-           iDisplayNameId = 0x01;
-           regval_ctr_addvalue( val, "ErrorControl",    REG_DWORD, (char*)&iDisplayNameId,       sizeof(int) ); 
-           
-           init_unistr2( &data, "EventLog", UNI_STR_TERMINATE);
-           regval_ctr_addvalue( val, "DisplayName",             REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
-           
-           num_values = regval_ctr_numvals( val );     
-           
-           
-           num_values = 0;
-       }
-    }
+       DEBUG(10,("elog_fetch_keys: entire key => [%s], subkey => [%s]\n", 
+               key, path));
     
-    SAFE_FREE( key2 ); 
-    return num_values;
-}
+       if ( !path ) { 
+               
+               if ( !elogs || !*elogs ) 
+                       return 0;
 
-/**********************************************************************
- handle enumeration of values below KEY_EVENTLOG\<Eventlog>
- *********************************************************************/
-static int eventlog_subkey_values( char *key, REGVAL_CTR *val )
-{
-    int        num_values = 0;
-    char       *keystr, *key2 = NULL;
-    char       *base, *new_path;
-    fstring            evtlogname; 
-    UNISTR2            data;
-    int         iDisplayNameId;
-    int         iMaxSize;
-    int         iRetention;
-    
-    /* 
-     *  TODO - callout to get these values...
-     */
-    
-    if ( !key ) 
-       return num_values;
-    
-    key2 = SMB_STRDUP( key );
-    keystr = key2;
-    reg_split_path( keystr, &base, &new_path );
-    
-    iDisplayNameId = 0x00000100;
-    /* MaxSize is limited to 0xFFFF0000 (UINT_MAX - USHRT_MAX) as per MSDN documentation */
-    iMaxSize=        0xFFFF0000;
-    /* records in the samba log are not overwritten */
-    iRetention =     0xFFFFFFFF;
-    
-    fstrcpy( evtlogname, base );
-    DEBUG(10,("eventlog_subpath_values_printer: eventlogname [%s]\n", base));
-    DEBUG(10,("eventlog_subpath_values_printer: new_path [%s]\n", new_path));
-    if ( !new_path ) 
-    {
-#if 0
-       regval_ctr_addvalue( val, "DisplayNameId",    REG_DWORD, (char*)&iDisplayNameId,       sizeof(int) ); 
-       
-       init_unistr2( &data, "%SystemRoot%\\system32\\els.dll", UNI_STR_TERMINATE);
-       regval_ctr_addvalue( val, "DisplayNameFile",             REG_EXPAND_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
-#endif
-       regval_ctr_addvalue( val, "MaxSize",          REG_DWORD, (char*)&iMaxSize, sizeof(int));
-       regval_ctr_addvalue( val, "Retention",  REG_DWORD, (char *)&iRetention, sizeof(int));
-#if 0
-       init_unistr2( &data, lp_logfile(), UNI_STR_TERMINATE);
-       regval_ctr_addvalue( val, "File",             REG_EXPAND_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
-#endif
-       init_unistr2( &data, base, UNI_STR_TERMINATE);
-       regval_ctr_addvalue( val, "PrimaryModule",         REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
-       
-       init_unistr2( &data, base, UNI_STR_TERMINATE);
-       regval_ctr_addvalue( val, "Sources",          REG_MULTI_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
-       
-       num_values = regval_ctr_numvals( val ); 
-       
-    } 
-    else
-    {
-       iDisplayNameId = 0x07;
-       regval_ctr_addvalue( val, "CategoryCount",    REG_DWORD, (char*)&iDisplayNameId,       sizeof(int) ); 
-       
-       init_unistr2( &data, "%SystemRoot%\\system32\\eventlog.dll", UNI_STR_TERMINATE);
-       regval_ctr_addvalue( val, "CategoryMessageFile", REG_EXPAND_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
-       
-       num_values = regval_ctr_numvals( val ); 
+               DEBUG(10,("elog_fetch_keys: Adding eventlog subkeys from smb.conf\n")); 
+               
+               for ( i=0; elogs[i]; i++ ) 
+                       regsubkey_ctr_addkey( subkeys, elogs[i] );
+
+               return regsubkey_ctr_numkeys( subkeys );
+       } 
        
-       num_values = 0;
-    }
-    
-    SAFE_FREE( key2 ); 
-    return num_values;
-}
+       /* if we get <logname>/<logname> then we don't add anymore */
 
+       if ( strchr( path, '\\' ) ) {
+               DEBUG(10,("elog_fetch_keys: Not adding subkey to %s\n",path));  
+               return 0;
+       }
 
-/**********************************************************************
- It is safe to assume that every registry path passed into on of 
- the exported functions here begins with KEY_EVENTLOG else
- these functions would have never been called.  This is a small utility
- function to strip the beginning of the path and make a copy that the 
- caller can modify.  Note that the caller is responsible for releasing
- the memory allocated here.
- **********************************************************************/
+       /* add in a subkey with the same name as the eventlog... */
 
-static char* trim_eventlog_reg_path( const char *path )
-{
-       const char *p;
-       uint16 key_len = strlen(KEY_EVENTLOG);
-       
-       /* 
-        * sanity check...this really should never be True.
-        * It is only here to prevent us from accessing outside
-        * the path buffer in the extreme case.
-        */
-       
-       if ( strlen(path) < key_len ) {
-               DEBUG(0,("trim_reg_path: Registry path too short! [%s]\n", path));
-               DEBUG(0,("trim_reg_path: KEY_EVENTLOG => [%s]!\n", KEY_EVENTLOG));
-               return NULL;
-       }
-       
-       
-       p = path + strlen( KEY_EVENTLOG );
-       
-       if ( *p == '\\' )
-               p++;
-       
-       if ( *p )
-               return SMB_STRDUP(p);
-       else
-               return NULL;
-}
-/**********************************************************************
- Enumerate registry subkey names given a registry path.  
- Caller is responsible for freeing memory to **subkeys
- *********************************************************************/
-static int eventlog_subkey_info( const char *key, REGSUBKEY_CTR *subkey_ctr )
-{
-    char       *path;
-    BOOL               top_level = False;
-    int                num_subkeys = 0;
-    const char        **evtlog_list;
-    
-    path = trim_eventlog_reg_path( key );
-    DEBUG(10,("eventlog_subkey_info: entire key=>[%s] SUBkey=>[%s]\n", key,path));     
-    
-    /* check to see if we are dealing with the top level key */
-    num_subkeys = 0;
-    
-    if ( !path )
-       top_level = True;
-    
-    num_subkeys = 0;
-    if ( !(evtlog_list = lp_eventlog_list()) ) {
-       SAFE_FREE(path);
-       return num_subkeys;
-    }
+       DEBUG(10,("elog_fetch_keys: Looking to add eventlog subkey to %s\n",path));     
 
-    
-    if ( top_level )
-    { 
-        /* todo - get the eventlog subkey values from the smb.conf file
-          for ( num_subkeys=0; num_subkeys<MAX_TOP_LEVEL_KEYS; num_subkeys++ )
-          regsubkey_ctr_addkey( subkey_ctr, top_level_keys[num_subkeys] ); */
-       DEBUG(10,("eventlog_subkey_info: Adding eventlog subkeys from globals\n"));     
-       /* TODO - make this  from the globals.szEventLogs list */
-       
-       while (*evtlog_list) 
-       {
-           DEBUG(10,("eventlog_subkey_info: Adding subkey =>[%s]\n",*evtlog_list));    
-           regsubkey_ctr_addkey( subkey_ctr, *evtlog_list);
-           evtlog_list++;
-           num_subkeys++;
-       }
-    }
-    else 
-    {
-       while (*evtlog_list && (0==num_subkeys) ) 
-       {
-           if (0 == StrCaseCmp(path,*evtlog_list)) 
-           {
-               DEBUG(10,("eventlog_subkey_info: Adding subkey [%s] for key =>[%s]\n",path,*evtlog_list));      
-               regsubkey_ctr_addkey( subkey_ctr, *evtlog_list);
-               num_subkeys = 1;
-           }
-           evtlog_list++;
+       /* look for a match */
+
+       if ( !elogs )
+               return -1; 
+
+       for ( i=0; elogs[i]; i++ ) { 
+               /* just verify that the keyname is a valid log name */
+               if ( strequal( path, elogs[i] ) )
+                       return 0;
        }
        
-       if (0==num_subkeys) 
-           DEBUG(10,("eventlog_subkey_info: No match on SUBkey=>[%s]\n", path));
-    }
-    
-    SAFE_FREE( path );
-    return num_subkeys;
+       return -1;
 }
 
 /**********************************************************************
  Enumerate registry values given a registry path.  
  Caller is responsible for freeing memory 
- *********************************************************************/
+*********************************************************************/
 
-static int eventlog_value_info( const char *key, REGVAL_CTR *val )
+static int elog_fetch_values( const char *key, REGVAL_CTR *values )
 {
-       char            *path;
-       BOOL            top_level = False;
-       int             num_values = 0;
+       char    *path;
+       uint32  uiDisplayNameId, uiMaxSize, uiRetention;
+       char    *base, *new_path;
+       UNISTR2 data;
        
-       DEBUG(10,("eventlog_value_info: key=>[%s]\n", key));
+       DEBUG(10,("elog_fetch_values: key=>[%s]\n", key));
        
-       path = trim_eventlog_reg_path( key );
+       path = reg_remaining_path( key + strlen(KEY_EVENTLOG) );
        
        /* check to see if we are dealing with the top level key */
        
-       if ( !path )
-           top_level = True;
-       if ( top_level )
-           num_values = eventlog_topkey_values(path,val);
-       else 
-       {
-           DEBUG(10,("eventlog_value_info: SUBkey=>[%s]\n", path));
-           num_values = eventlog_subkey_values(path,val);
-       }
-       return num_values;
+       if ( !path ) 
+               return regdb_fetch_values( KEY_EVENTLOG, values );
+               
+       /* deal with a log name */
+    
+       reg_split_path( path, &base, &new_path );
+       
+       /* MaxSize is limited to 0xFFFF0000 (UINT_MAX - USHRT_MAX) as per MSDN documentation */
+       
+    
+       if ( !new_path ) {
+               
+               /* try to fetch from the registry */
+               
+               regdb_fetch_values( key, values );
+
+               /* just verify one of the important keys.  If this 
+                  fails, then assume the values have not been initialized */
+               
+               if ( regval_ctr_getvalue( values, "Retention" ) )
+                       return regval_ctr_numvals( values );    
+
+               /* hard code some initial values */
+                               
+               uiDisplayNameId = 0x00000100;
+               uiMaxSize       = 0x00080000;   
+               uiRetention     = 0x93A80;
+               
+               regval_ctr_addvalue( values, "MaxSize", REG_DWORD, (char*)&uiMaxSize, sizeof(uint32));
+               regval_ctr_addvalue( values, "Retention", REG_DWORD, (char *)&uiRetention, sizeof(uint32));
+               
+               init_unistr2( &data, base, UNI_STR_TERMINATE);
+               regval_ctr_addvalue( values, "PrimaryModule", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
+       
+               init_unistr2( &data, base, UNI_STR_TERMINATE);
+               regval_ctr_addvalue( values, "Sources", REG_MULTI_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
+               
+               /* store them for later updates.  Complain if this fails but continue on */
+               
+               if ( !regdb_store_values( key, values ) ) {
+                       DEBUG(0,("elog_fetch_values: Failed to store initial values for log [%s]\n",
+                               base ));
+               }
+       
+               return regval_ctr_numvals( values );    
+       } 
+
+#if 0
+       /* hmmm....what to do here?  A subkey underneath the log name ? */
+
+       uiDisplayNameId = 0x07;
+       regval_ctr_addvalue( values, "CategoryCount",    REG_DWORD, (char*)&uiDisplayNameId,       sizeof(uint32) ); 
+       
+       init_unistr2( &data, "%SystemRoot%\\system32\\eventlog.dll", UNI_STR_TERMINATE);
+       regval_ctr_addvalue( values, "CategoryMessageFile", REG_EXPAND_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
+#endif
+       
+       return regval_ctr_numvals( values );
 }
 
 /**********************************************************************
- Stub function which always returns failure since we don't want
- people storing eventlog information directly via registry calls
- (for now at least)
- *********************************************************************/
-static BOOL eventlog_store_subkey( const char *key, REGSUBKEY_CTR *subkeys )
+*********************************************************************/
+
+static BOOL elog_store_keys( const char *key, REGSUBKEY_CTR *subkeys )
 {
+       /* cannot create any subkeys here */
+       
        return False;
 }
 
 /**********************************************************************
- Stub function which always returns failure since we don't want
- people storing eventlog information directly via registry calls
- (for now at least)
- *********************************************************************/
-static BOOL eventlog_store_value( const char *key, REGVAL_CTR *val )
+ Allow storing of particular values related to eventlog operation. 
+*********************************************************************/
+
+static BOOL elog_store_value( const char *key, REGVAL_CTR *values )
 {
-       return False;
+       /* the client had to have a valid handle to get here 
+          so just hand off to the registry tdb */
+       
+       return regdb_store_values( key, values );
 }
 
-/* 
- * Table of function pointers for accessing eventlog data
- */
+/******************************************************************** 
+ Table of function pointers for accessing eventlog data
+ *******************************************************************/
 REGISTRY_OPS eventlog_ops = {
-       eventlog_subkey_info,
-       eventlog_value_info,
-       eventlog_store_subkey,
-       eventlog_store_value,
+       elog_fetch_keys,
+       elog_fetch_values,
+       elog_store_keys,
+       elog_store_value,
        NULL
 };
index d6e02884616817f732368d0aee5725f38d4a3043..f41c5885bc4d7bdc8710793790ae8ab4e3336c93 100644 (file)
@@ -38,15 +38,70 @@ REGISTRY_HOOK reg_hooks[] = {
   { KEY_PRINTING,              &printing_ops },
   { KEY_PRINTING_2K,           &printing_ops },
   { KEY_PRINTING_PORTS,        &printing_ops },
-#if 0
   { KEY_EVENTLOG,              &eventlog_ops }, 
-#endif
   { KEY_SHARES,                &shares_reg_ops },
 #endif
   { NULL, NULL }
 };
 
 
+static struct generic_mapping reg_generic_map = 
+       { REG_KEY_READ, REG_KEY_WRITE, REG_KEY_EXECUTE, REG_KEY_ALL };
+
+/********************************************************************
+********************************************************************/
+
+static NTSTATUS registry_access_check( SEC_DESC *sec_desc, NT_USER_TOKEN *token, 
+                                     uint32 access_desired, uint32 *access_granted )
+{
+       NTSTATUS result;
+
+       if ( geteuid() == sec_initial_uid() ) {
+               DEBUG(5,("registry_access_check: using root's token\n"));
+               token = get_root_nt_token();
+       }
+
+       se_map_generic( &access_desired, &reg_generic_map );
+       se_access_check( sec_desc, token, access_desired, access_granted, &result );
+
+       return result;
+}
+
+/********************************************************************
+********************************************************************/
+
+static SEC_DESC* construct_registry_sd( TALLOC_CTX *ctx )
+{
+       SEC_ACE ace[2]; 
+       SEC_ACCESS mask;
+       size_t i = 0;
+       SEC_DESC *sd;
+       SEC_ACL *acl;
+       size_t sd_size;
+
+       /* basic access for Everyone */
+       
+       init_sec_access(&mask, REG_KEY_READ );
+       init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
+       
+       /* Full Access 'BUILTIN\Administrators' */
+       
+       init_sec_access(&mask, REG_KEY_ALL );
+       init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
+       
+       
+       /* create the security descriptor */
+       
+       if ( !(acl = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) )
+               return NULL;
+
+       if ( !(sd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL, acl, &sd_size)) )
+               return NULL;
+
+       return sd;
+}
+
+
 /***********************************************************************
  Open the registry database and initialize the REGISTRY_HOOK cache
  ***********************************************************************/
@@ -55,11 +110,12 @@ BOOL init_registry( void )
 {
        int i;
        
+       
        if ( !init_registry_db() ) {
                DEBUG(0,("init_registry: failed to initialize the registry tdb!\n"));
                return False;
        }
-               
+
        /* build the cache tree of registry hooks */
        
        reghook_cache_init();
@@ -72,6 +128,14 @@ BOOL init_registry( void )
        if ( DEBUGLEVEL >= 20 )
                reghook_dump_cache(20);
 
+       /* inform the external eventlog machinery of the change */
+
+       eventlog_refresh_external_parameters( get_root_nt_token() );
+
+       /* add any services keys */
+
+       svcctl_init_keys();
+
        return True;
 }
 
@@ -277,4 +341,70 @@ BOOL regkey_access_check( REGISTRY_KEY *key, uint32 requested, uint32 *granted,
        return key->hook->ops->reg_access_check( key->name, requested, granted, token );
 }
 
+/***********************************************************************
+***********************************************************************/
+
+WERROR regkey_open_internal( REGISTRY_KEY **regkey, const char *path, 
+                             NT_USER_TOKEN *token, uint32 access_desired )
+{
+       WERROR          result = WERR_OK;
+       REGISTRY_KEY    *keyinfo;
+       REGSUBKEY_CTR   *subkeys = NULL;
+       uint32 access_granted;
+       
+       DEBUG(7,("regkey_open_internal: name = [%s]\n", path));
 
+       if ( !(*regkey = TALLOC_ZERO_P(NULL, REGISTRY_KEY)) )
+               return WERR_NOMEM;
+               
+       keyinfo = *regkey;
+               
+       /* initialization */
+       
+       keyinfo->type = REG_KEY_GENERIC;
+       keyinfo->name = talloc_strdup( keyinfo, path );
+       
+       
+       /* Tag this as a Performance Counter Key */
+
+       if( StrnCaseCmp(path, KEY_HKPD, strlen(KEY_HKPD)) == 0 )
+               keyinfo->type = REG_KEY_HKPD;
+       
+       /* Look up the table of registry I/O operations */
+
+       if ( !(keyinfo->hook = reghook_cache_find( keyinfo->name )) ) {
+               DEBUG(0,("open_registry_key: Failed to assigned a REGISTRY_HOOK to [%s]\n",
+                       keyinfo->name ));
+               result = WERR_BADFILE;
+               goto done;
+       }
+       
+       /* check if the path really exists; failed is indicated by -1 */
+       /* if the subkey count failed, bail out */
+
+       if ( !(subkeys = TALLOC_ZERO_P( keyinfo, REGSUBKEY_CTR )) ) {
+               result = WERR_NOMEM;
+               goto done;
+       }
+
+       if ( fetch_reg_keys( keyinfo, subkeys ) == -1 )  {
+               result = WERR_BADFILE;
+               goto done;
+       }
+       
+       TALLOC_FREE( subkeys );
+
+       if ( !regkey_access_check( keyinfo, access_desired, &access_granted, token ) ) {
+               result = WERR_ACCESS_DENIED;
+               goto done;
+       }
+       
+       keyinfo->access_granted = access_granted;
+
+done:
+       if ( !W_ERROR_IS_OK(result) ) {
+               TALLOC_FREE( *regkey );
+       }
+
+       return result;
+}
index 70410a674095b607a237cb5366bc5d09fabe98d7..05567d561c62589a48b7f8e240dc31beaf81fd1a 100644 (file)
@@ -236,7 +236,7 @@ uint32 regval_type( REGISTRY_VALUE *val )
 
 /***********************************************************************
  Retreive a pointer to a specific value.  Caller shoud dup the structure
- since this memory may go away with a regval_ctr_destroy()
+ since this memory will go away when the ctr is free()'d
  **********************************************************************/
 
 REGISTRY_VALUE* regval_ctr_specific_value( REGVAL_CTR *ctr, uint32 idx )
@@ -385,3 +385,29 @@ REGISTRY_VALUE* regval_ctr_getvalue( REGVAL_CTR *ctr, const char *name )
        return NULL;
 }
 
+/***********************************************************************
+ return the data_p as a uint32
+ **********************************************************************/
+
+uint32 regval_dword( REGISTRY_VALUE *val )
+{
+       uint32 data;
+       
+       data = IVAL( regval_data_p(val), 0 );
+       
+       return data;
+}
+
+/***********************************************************************
+ return the data_p as a character string
+ **********************************************************************/
+
+char* regval_sz( REGISTRY_VALUE *val )
+{
+       static pstring data;
+
+       rpcstr_pull( data, regval_data_p(val), sizeof(data), regval_size(val), 0 );
+       
+       return data;
+}
+
diff --git a/source3/registry/reg_perfcount.c b/source3/registry/reg_perfcount.c
new file mode 100644 (file)
index 0000000..609f86d
--- /dev/null
@@ -0,0 +1,1225 @@
+#include "includes.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_RPC_SRV
+
+#define PERFCOUNT_MAX_LEN 256
+
+uint32 reg_perfcount_get_base_index(void)
+{
+       pstring fname;
+       TDB_CONTEXT *names;
+       TDB_DATA kbuf, dbuf;
+       char key[] = "1";
+       uint32 retval = 0;
+       char buf[PERFCOUNT_MAX_LEN];
+       const char *counter_dir = lp_counters_dir();
+       
+
+       if ( !*counter_dir ) 
+               return 0;
+
+       pstr_sprintf( fname, "%s/names.tdb", counter_dir );
+
+       names = tdb_open_log(fname, 0, TDB_DEFAULT, O_RDONLY, 0444);
+
+       if ( !names ) {
+               DEBUG(1, ("reg_perfcount_get_base_index: unable to open [%s].\n", fname));
+               return 0;
+       }    
+       /* needs to read the value of key "1" from the counter_names.tdb file, as that is
+          where the total number of counters is stored. We're assuming no holes in the
+          enumeration.
+          The format for the counter_names.tdb file is:
+          key        value
+          1          num_counters
+          2          perf_counter1
+          3          perf_counter1_help
+          4          perf_counter2
+          5          perf_counter2_help
+          even_num   perf_counter<even_num>
+          even_num+1 perf_counter<even_num>_help
+          and so on.
+          So last_counter becomes num_counters*2, and last_help will be last_counter+1 */
+       kbuf.dptr = key;
+       kbuf.dsize = strlen(key);
+       dbuf = tdb_fetch(names, kbuf);
+       if(dbuf.dptr == NULL)
+       {
+               DEBUG(1, ("reg_perfcount_get_base_index: failed to find key \'1\' in [%s].\n", fname));
+               tdb_close(names);
+               return 0;
+       }
+       else
+       {
+               tdb_close(names);
+               memset(buf, 0, PERFCOUNT_MAX_LEN);
+               memcpy(buf, dbuf.dptr, dbuf.dsize);
+               retval = (uint32)atoi(buf);
+               SAFE_FREE(dbuf.dptr);
+               return retval;
+       }
+       return 0;
+}
+
+uint32 reg_perfcount_get_last_counter(uint32 base_index)
+{
+       uint32 retval;
+
+       if(base_index == 0)
+               retval = 0;
+       else
+               retval = base_index * 2;
+
+       return retval;
+}
+
+uint32 reg_perfcount_get_last_help(uint32 last_counter)
+{
+       uint32 retval;
+
+       if(last_counter == 0)
+               retval = 0;
+       else
+               retval = last_counter + 1;
+
+       return retval;
+}
+
+static uint32 _reg_perfcount_multi_sz_from_tdb(TDB_CONTEXT *tdb, 
+                                              int keyval,
+                                              char **retbuf,
+                                              uint32 buffer_size)
+{
+       TDB_DATA kbuf, dbuf;
+       char temp[256];
+       char *buf1 = *retbuf, *buf2 = NULL;
+       uint32 working_size = 0;
+       UNISTR2 name_index, name;
+
+       memset(temp, 0, sizeof(temp));
+       snprintf(temp, sizeof(temp), "%d", keyval);
+       kbuf.dptr = temp;
+       kbuf.dsize = strlen(temp);
+       dbuf = tdb_fetch(tdb, kbuf);
+       if(dbuf.dptr == NULL)
+       {
+               /* If a key isn't there, just bypass it -- this really shouldn't 
+                  happen unless someone's mucking around with the tdb */
+               DEBUG(3, ("_reg_perfcount_multi_sz_from_tdb: failed to find key [%s] in [%s].\n",
+                         temp, tdb->name));
+               return buffer_size;
+       }
+       /* First encode the name_index */
+       working_size = (kbuf.dsize + 1)*sizeof(uint16);
+       buf2 = SMB_REALLOC(buf1, buffer_size + working_size);
+       if(!buf2)
+       {
+               SAFE_FREE(buf1);
+               buffer_size = 0;
+               return buffer_size;
+       }
+       buf1 = buf2;
+       init_unistr2(&name_index, kbuf.dptr, UNI_STR_TERMINATE);
+       memcpy(buf1+buffer_size, (char *)name_index.buffer, working_size);
+       buffer_size += working_size;
+       /* Now encode the actual name */
+       working_size = (dbuf.dsize + 1)*sizeof(uint16);
+       buf2 = SMB_REALLOC(buf1, buffer_size + working_size);
+       if(!buf2)
+       {
+               SAFE_FREE(buf1);
+               buffer_size = 0;
+               return buffer_size;
+       }
+       buf1 = buf2;
+       memset(temp, 0, sizeof(temp));
+       memcpy(temp, dbuf.dptr, dbuf.dsize);
+       SAFE_FREE(dbuf.dptr);
+       init_unistr2(&name, temp, UNI_STR_TERMINATE);
+       memcpy(buf1+buffer_size, (char *)name.buffer, working_size);
+       buffer_size += working_size;
+
+       *retbuf = buf1;
+
+       return buffer_size;
+}
+
+uint32 reg_perfcount_get_counter_help(uint32 base_index, char **retbuf)
+{
+       char *buf1 = NULL, *buf2 = NULL;
+       uint32 buffer_size = 0;
+       TDB_CONTEXT *names;
+       pstring fname;
+       int i;
+
+       if(base_index == 0)
+               return 0;
+
+       pstrcpy(fname, lp_counters_dir());
+       pstrcat(fname, "/names.tdb");
+
+       names = tdb_open_log(fname, 0, TDB_DEFAULT, O_RDONLY, 0444);
+
+       if(names == NULL)
+       {
+               DEBUG(1, ("reg_perfcount_get_counter_help: unable to open [%s].\n", fname));
+               return 0;
+       }    
+
+       for(i = 1; i <= base_index; i++)
+       {
+               buffer_size = _reg_perfcount_multi_sz_from_tdb(names, (i*2)+1, retbuf, buffer_size);
+       }
+       tdb_close(names);
+
+       /* Now terminate the MULTI_SZ with a double unicode NULL */
+       buf1 = *retbuf;
+       buf2 = SMB_REALLOC(buf1, buffer_size + 2);
+       if(!buf2)
+       {
+               SAFE_FREE(buf1);
+               buffer_size = 0;
+       }
+       else
+       {
+               buf1 = buf2;
+               buf1[buffer_size++] = '\0';
+               buf1[buffer_size++] = '\0';
+       }
+
+       *retbuf = buf1;
+
+       return buffer_size;
+}
+
+uint32 reg_perfcount_get_counter_names(uint32 base_index, char **retbuf)
+{
+       char *buf1 = NULL, *buf2 = NULL;
+       uint32 buffer_size = 0;
+       TDB_CONTEXT *names;
+       pstring fname;
+       int i;
+
+       if(base_index == 0)
+               return 0;
+
+       pstrcpy(fname, lp_counters_dir());
+       pstrcat(fname, "/names.tdb");
+
+       names = tdb_open_log(fname, 0, TDB_DEFAULT, O_RDONLY, 0444);
+
+       if(names == NULL)
+       {
+               DEBUG(1, ("reg_perfcount_get_counter_names: unable to open [%s].\n", fname));
+               return 0;
+       }    
+
+       buffer_size = _reg_perfcount_multi_sz_from_tdb(names, 1, retbuf, buffer_size);
+
+       for(i = 1; i <= base_index; i++)
+       {
+               buffer_size = _reg_perfcount_multi_sz_from_tdb(names, i*2, retbuf, buffer_size);
+       }
+       tdb_close(names);
+
+       /* Now terminate the MULTI_SZ with a double unicode NULL */
+       buf1 = *retbuf;
+       buf2 = SMB_REALLOC(buf1, buffer_size + 2);
+       if(!buf2)
+       {
+               SAFE_FREE(buf1);
+               buffer_size = 0;
+       }
+       else
+       {
+               buf1 = buf2;
+               buf1[buffer_size++] = '\0';
+               buf1[buffer_size++] = '\0';
+       }
+
+       *retbuf=buf1;
+
+       return buffer_size;
+}
+
+static void _reg_perfcount_make_key(TDB_DATA *key,
+                                   char *buf,
+                                   int buflen,
+                                   int key_part1,
+                                   const char *key_part2)
+{
+       memset(buf, 0, buflen);
+       if(key_part2 != NULL)
+               snprintf(buf, buflen,"%d%s", key_part1, key_part2);
+       else 
+               snprintf(buf, buflen, "%d", key_part1);
+
+       key->dptr = buf;
+       key->dsize = strlen(buf);
+
+       return;
+}
+
+static BOOL _reg_perfcount_isparent(TDB_DATA data)
+{
+       if(data.dsize > 0)
+       {
+               if(data.dptr[0] == 'p')
+                       return True;
+               else
+                       return False;
+       }
+       return False;
+}
+
+static BOOL _reg_perfcount_ischild(TDB_DATA data)
+{
+       if(data.dsize > 0)
+       {
+               if(data.dptr[0] == 'c')
+                       return True;
+               else
+                       return False;
+       }
+       return False;
+}
+
+static uint32 _reg_perfcount_get_numinst(int objInd, TDB_CONTEXT *names)
+{
+       TDB_DATA key, data;
+       char buf[PERFCOUNT_MAX_LEN];
+
+       _reg_perfcount_make_key(&key, buf, PERFCOUNT_MAX_LEN, objInd, "inst");
+       data = tdb_fetch(names, key);
+
+       if(data.dptr == NULL)
+               return (uint32)PERF_NO_INSTANCES;
+    
+       memset(buf, 0, PERFCOUNT_MAX_LEN);
+       memcpy(buf, data.dptr, data.dsize);
+       return (uint32)atoi(buf);
+}
+
+static BOOL _reg_perfcount_add_object(PERF_DATA_BLOCK *block,
+                                     prs_struct *ps,
+                                     int num,
+                                     TDB_DATA data,
+                                     TDB_CONTEXT *names)
+{
+       int i;
+       BOOL success = False;
+       PERF_OBJECT_TYPE *obj;
+
+       block->objects = (PERF_OBJECT_TYPE *)TALLOC_REALLOC_ARRAY(ps->mem_ctx,
+                                                                 block->objects,
+                                                                 PERF_OBJECT_TYPE,
+                                                                 block->NumObjectTypes+1);
+       if(block->objects == NULL)
+               return False;
+       obj = &(block->objects[block->NumObjectTypes]);
+       memset((void *)&(block->objects[block->NumObjectTypes]), 0, sizeof(PERF_OBJECT_TYPE));
+       block->objects[block->NumObjectTypes].ObjectNameTitleIndex = num;
+       block->objects[block->NumObjectTypes].ObjectNameTitlePointer = 0;
+       block->objects[block->NumObjectTypes].ObjectHelpTitleIndex = num+1;
+       block->objects[block->NumObjectTypes].ObjectHelpTitlePointer = 0;
+       block->objects[block->NumObjectTypes].NumCounters = 0;
+       block->objects[block->NumObjectTypes].DefaultCounter = 0;
+       block->objects[block->NumObjectTypes].NumInstances = _reg_perfcount_get_numinst(num, names);
+       block->objects[block->NumObjectTypes].counters = NULL;
+       block->objects[block->NumObjectTypes].instances = NULL;
+       block->objects[block->NumObjectTypes].counter_data.ByteLength = sizeof(uint32);
+       block->objects[block->NumObjectTypes].counter_data.data = NULL;
+       block->objects[block->NumObjectTypes].DetailLevel = PERF_DETAIL_NOVICE;
+       block->NumObjectTypes+=1;
+
+       for(i = 0; i < (int)obj->NumInstances; i++)
+       {
+               success = _reg_perfcount_add_instance(obj, ps, i, names);
+       }
+
+       return True;
+}
+
+BOOL _reg_perfcount_get_counter_data(TDB_DATA key, TDB_DATA *data)
+{
+       TDB_CONTEXT *counters;
+       pstring fname;
+    
+       pstrcpy(fname, lp_counters_dir());
+       pstrcat(fname, "/data.tdb");
+
+       counters = tdb_open_log(fname, 0, TDB_DEFAULT, O_RDONLY, 0444);
+
+       if(counters == NULL)
+       {
+               DEBUG(1, ("reg_perfcount_get_counter_data: unable to open [%s].\n", fname));
+               return False;
+       }    
+
+       *data = tdb_fetch(counters, key);
+    
+       tdb_close(counters);
+
+       return True;
+}
+
+static uint32 _reg_perfcount_get_size_field(uint32 CounterType)
+{
+       uint32 retval;
+
+       retval = CounterType;
+
+       /* First mask out reserved lower 8 bits */
+       retval = retval & 0xFFFFFF00;
+       retval = retval << 22;
+       retval = retval >> 22;
+
+       return retval;
+}
+
+static uint32 _reg_perfcount_compute_scale(long long int data)
+{
+       int scale = 0;
+       if(data == 0)
+               return scale;
+       while(data > 100)
+       {
+               data /= 10;
+               scale--;
+       }
+       while(data < 10)
+       {
+               data *= 10;
+               scale++;
+       }
+
+       return (uint32)scale;
+}
+
+static BOOL _reg_perfcount_get_counter_info(PERF_DATA_BLOCK *block,
+                                           prs_struct *ps,
+                                           int CounterIndex,
+                                           PERF_OBJECT_TYPE *obj,
+                                           TDB_CONTEXT *names)
+{
+       TDB_DATA key, data;
+       char buf[PERFCOUNT_MAX_LEN];
+       size_t dsize, padding;
+       long int data32, dbuf[2];
+       long long int data64;
+       uint32 counter_size;
+
+       obj->counters[obj->NumCounters].DefaultScale = 0;
+       dbuf[0] = dbuf[1] = 0;
+       padding = 0;
+
+       _reg_perfcount_make_key(&key, buf, PERFCOUNT_MAX_LEN, CounterIndex, "type");
+       data = tdb_fetch(names, key);
+       if(data.dptr == NULL)
+       {
+               DEBUG(3, ("_reg_perfcount_get_counter_info: No type data for counter [%d].\n", CounterIndex));
+               return False;
+       }
+       memset(buf, 0, PERFCOUNT_MAX_LEN);
+       memcpy(buf, data.dptr, data.dsize);
+       obj->counters[obj->NumCounters].CounterType = atoi(buf);
+       DEBUG(10, ("_reg_perfcount_get_counter_info: Got type [%d] for counter [%d].\n",
+                  obj->counters[obj->NumCounters].CounterType, CounterIndex));
+       free(data.dptr);
+
+       /* Fetch the actual data */
+       _reg_perfcount_make_key(&key, buf, PERFCOUNT_MAX_LEN, CounterIndex, "");
+       _reg_perfcount_get_counter_data(key, &data);
+       if(data.dptr == NULL)
+       {
+               DEBUG(3, ("_reg_perfcount_get_counter_info: No counter data for counter [%d].\n", CounterIndex));
+               return False;
+       }
+    
+       counter_size = _reg_perfcount_get_size_field(obj->counters[obj->NumCounters].CounterType);
+
+       if(counter_size == PERF_SIZE_DWORD)
+       {
+               dsize = sizeof(data32);
+               memset(buf, 0, PERFCOUNT_MAX_LEN);
+               memcpy(buf, data.dptr, data.dsize);
+               data32 = strtol(buf, NULL, 0);
+               if((obj->counters[obj->NumCounters].CounterType & 0x00000F00) == PERF_TYPE_NUMBER)
+                       obj->counters[obj->NumCounters].DefaultScale = _reg_perfcount_compute_scale((long long int)data32);
+               else
+                       obj->counters[obj->NumCounters].DefaultScale = 0;
+               dbuf[0] = data32;
+               padding = (dsize - (obj->counter_data.ByteLength%dsize)) % dsize;
+       }
+       else if(counter_size == PERF_SIZE_LARGE)
+       {
+               dsize = sizeof(data64);
+               memset(buf, 0, PERFCOUNT_MAX_LEN);
+               memcpy(buf, data.dptr, data.dsize);
+               data64 = strtoll(buf, NULL, 0);
+               if((obj->counters[obj->NumCounters].CounterType & 0x00000F00) == PERF_TYPE_NUMBER)
+                       obj->counters[obj->NumCounters].DefaultScale = _reg_perfcount_compute_scale(data64);
+               else
+                       obj->counters[obj->NumCounters].DefaultScale = 0;
+               memcpy((void *)dbuf, (const void *)&data64, dsize);
+               padding = (dsize - (obj->counter_data.ByteLength%dsize)) % dsize;
+       }
+       else /* PERF_SIZE_VARIABLE_LEN */
+       {
+               dsize = data.dsize;
+               memset(buf, 0, PERFCOUNT_MAX_LEN);
+               memcpy(buf, data.dptr, data.dsize);
+       }
+       free(data.dptr);
+
+       obj->counter_data.ByteLength += dsize + padding;
+       obj->counter_data.data = TALLOC_REALLOC_ARRAY(ps->mem_ctx,
+                                                     obj->counter_data.data,
+                                                     uint8,
+                                                     obj->counter_data.ByteLength - sizeof(uint32));
+       if(obj->counter_data.data == NULL)
+               return False;
+       if(dbuf[0] != 0 || dbuf[1] != 0)
+       {
+               memcpy((void *)(obj->counter_data.data + 
+                               (obj->counter_data.ByteLength - (sizeof(uint32) + dsize))), 
+                      (const void *)dbuf, dsize);
+       }
+       else
+       {
+               /* Handling PERF_SIZE_VARIABLE_LEN */
+               memcpy((void *)(obj->counter_data.data +
+                               (obj->counter_data.ByteLength - (sizeof(uint32) + dsize))),
+                      (const void *)buf, dsize);
+       }
+       obj->counters[obj->NumCounters].CounterOffset = obj->counter_data.ByteLength - dsize;
+       if(obj->counters[obj->NumCounters].CounterOffset % dsize != 0)
+       {
+               DEBUG(3,("Improperly aligned counter [%d]\n", obj->NumCounters));
+       }
+       obj->counters[obj->NumCounters].CounterSize = dsize;
+
+       return True;
+}
+
+PERF_OBJECT_TYPE *_reg_perfcount_find_obj(PERF_DATA_BLOCK *block, int objind)
+{
+       int i;
+
+       PERF_OBJECT_TYPE *obj = NULL;
+
+       for(i = 0; i < block->NumObjectTypes; i++)
+       {
+               if(block->objects[i].ObjectNameTitleIndex == objind)
+               {
+                       obj = &(block->objects[i]);
+               }
+       }
+
+       return obj;
+}
+
+static BOOL _reg_perfcount_add_counter(PERF_DATA_BLOCK *block,
+                                      prs_struct *ps,
+                                      int num,
+                                      TDB_DATA data,
+                                      TDB_CONTEXT *names)
+{
+       char *begin, *end, *start, *stop;
+       int parent;
+       PERF_OBJECT_TYPE *obj;
+       BOOL success = False;
+       char buf[PERFCOUNT_MAX_LEN];
+    
+       obj = NULL;
+       memset(buf, 0, PERFCOUNT_MAX_LEN);
+       memcpy(buf, data.dptr, data.dsize);
+       begin = index(buf, '[');
+       end = index(buf, ']');
+       if(begin == NULL || end == NULL)
+               return False;
+       start = begin+1;
+
+       while(start < end)
+       {
+               stop = index(start, ',');
+               if(stop == NULL)
+                       stop = end;
+               *stop = '\0';
+               parent = atoi(start);
+
+               obj = _reg_perfcount_find_obj(block, parent);
+               if(obj == NULL)
+               {
+                       /* At this point we require that the parent object exist.
+                          This can probably be handled better at some later time */
+                       DEBUG(3, ("_reg_perfcount_add_counter: Could not find parent object [%d] for counter [%d].\n",
+                                 parent, num));
+                       return False;
+               }
+               obj->counters = (PERF_COUNTER_DEFINITION *)TALLOC_REALLOC_ARRAY(ps->mem_ctx,
+                                                                               obj->counters,
+                                                                               PERF_COUNTER_DEFINITION,
+                                                                               obj->NumCounters+1);
+               if(obj->counters == NULL)
+                       return False;
+               memset((void *)&(obj->counters[obj->NumCounters]), 0, sizeof(PERF_COUNTER_DEFINITION));
+               obj->counters[obj->NumCounters].CounterNameTitleIndex=num;
+               obj->counters[obj->NumCounters].CounterHelpTitleIndex=num+1;
+               obj->counters[obj->NumCounters].DetailLevel = PERF_DETAIL_NOVICE;
+               obj->counters[obj->NumCounters].ByteLength = sizeof(PERF_COUNTER_DEFINITION);
+               success = _reg_perfcount_get_counter_info(block, ps, num, obj, names);
+               obj->NumCounters += 1;
+               start = stop + 1;
+       }
+       
+       /* Handle case of Objects/Counters without any counter data, which would suggest
+          that the required instances are not there yet, so change NumInstances from
+          PERF_NO_INSTANCES to 0 */
+
+       return True;
+}
+
+BOOL _reg_perfcount_get_instance_info(PERF_INSTANCE_DEFINITION *inst,
+                                     prs_struct *ps,
+                                     int instId,
+                                     PERF_OBJECT_TYPE *obj,
+                                     TDB_CONTEXT *names)
+{
+       TDB_DATA key, data;
+       char buf[PERFCOUNT_MAX_LEN], temp[PERFCOUNT_MAX_LEN];
+       wpstring name;
+       int pad;
+
+       /* First grab the instance data from the data file */
+       memset(temp, 0, PERFCOUNT_MAX_LEN);
+       snprintf(temp, PERFCOUNT_MAX_LEN, "i%d", instId);
+       _reg_perfcount_make_key(&key, buf, PERFCOUNT_MAX_LEN, obj->ObjectNameTitleIndex, temp);
+       _reg_perfcount_get_counter_data(key, &data);
+       if(data.dptr == NULL)
+       {
+               DEBUG(3, ("_reg_perfcount_get_instance_info: No instance data for instance [%s].\n",
+                         buf));
+               return False;
+       }
+       inst->counter_data.ByteLength = data.dsize + sizeof(inst->counter_data.ByteLength);
+       inst->counter_data.data = TALLOC_REALLOC_ARRAY(ps->mem_ctx,
+                                                      inst->counter_data.data,
+                                                      uint8,
+                                                      data.dsize);
+       if(inst->counter_data.data == NULL)
+               return False;
+       memset(inst->counter_data.data, 0, data.dsize);
+       memcpy(inst->counter_data.data, data.dptr, data.dsize);
+       free(data.dptr);
+
+       /* Fetch instance name */
+       memset(temp, 0, PERFCOUNT_MAX_LEN);
+       snprintf(temp, PERFCOUNT_MAX_LEN, "i%dname", instId);
+       _reg_perfcount_make_key(&key, buf, PERFCOUNT_MAX_LEN, obj->ObjectNameTitleIndex, temp);
+       data = tdb_fetch(names, key);
+       if(data.dptr == NULL)
+       {
+               /* Not actually an error, but possibly unintended? -- just logging FYI */
+               DEBUG(3, ("_reg_perfcount_get_instance_info: No instance name for instance [%s].\n",
+                         buf));
+               inst->NameLength = 0;
+       }
+       else
+       {
+               memset(buf, 0, PERFCOUNT_MAX_LEN);
+               memcpy(buf, data.dptr, data.dsize);
+               rpcstr_push((void *)name, buf, sizeof(name), STR_TERMINATE);
+               inst->NameLength = (strlen_w(name) * 2) + 2;
+               inst->data = TALLOC_REALLOC_ARRAY(ps->mem_ctx,
+                                                 inst->data,
+                                                 uint8,
+                                                 inst->NameLength);
+               memcpy(inst->data, name, inst->NameLength);
+               free(data.dptr);
+       }
+
+       inst->ParentObjectTitleIndex = 0;
+       inst->ParentObjectTitlePointer = 0;
+       inst->UniqueID = PERF_NO_UNIQUE_ID;
+       inst->NameOffset = 6 * sizeof(uint32);
+    
+       inst->ByteLength = inst->NameOffset + inst->NameLength;
+       /* Need to be aligned on a 64-bit boundary here for counter_data */
+       if((pad = (inst->ByteLength % 8)))
+       {
+               pad = 8 - pad;
+               inst->data = TALLOC_REALLOC_ARRAY(ps->mem_ctx,
+                                                 inst->data,
+                                                 uint8,
+                                                 inst->NameLength + pad);
+               memset(inst->data + inst->NameLength, 0, pad);
+               inst->ByteLength += pad;
+       }
+
+       return True;
+}
+
+BOOL _reg_perfcount_add_instance(PERF_OBJECT_TYPE *obj,
+                                prs_struct *ps,
+                                int instInd,
+                                TDB_CONTEXT *names)
+{
+       BOOL success;
+       PERF_INSTANCE_DEFINITION *inst;
+
+       success = False;
+
+       if(obj->instances == NULL)
+       {
+               obj->instances = TALLOC_REALLOC_ARRAY(ps->mem_ctx, 
+                                                     obj->instances,
+                                                     PERF_INSTANCE_DEFINITION,
+                                                     obj->NumInstances);
+       }
+       if(obj->instances == NULL)
+               return False;
+    
+       memset(&(obj->instances[instInd]), 0, sizeof(PERF_INSTANCE_DEFINITION));
+       inst = &(obj->instances[instInd]);
+       success = _reg_perfcount_get_instance_info(inst, ps, instInd, obj, names);
+    
+       return True;
+}
+
+static int _reg_perfcount_assemble_global(PERF_DATA_BLOCK *block,
+                                         prs_struct *ps,
+                                         int base_index,
+                                         TDB_CONTEXT *names)
+{
+       BOOL success;
+       int i, j, retval = 0;
+       char keybuf[PERFCOUNT_MAX_LEN];
+       TDB_DATA key, data;
+
+       for(i = 1; i <= base_index; i++)
+       {
+               j = i*2;
+               _reg_perfcount_make_key(&key, keybuf, PERFCOUNT_MAX_LEN, j, "rel");
+               data = tdb_fetch(names, key);
+               if(data.dptr != NULL)
+               {
+                       if(_reg_perfcount_isparent(data))
+                               success = _reg_perfcount_add_object(block, ps, j, data, names);
+                       else if(_reg_perfcount_ischild(data))
+                               success = _reg_perfcount_add_counter(block, ps, j, data, names);
+                       else
+                       {
+                               DEBUG(3, ("Bogus relationship [%s] for counter [%d].\n", data.dptr, j));
+                               success = False;
+                       }
+                       if(success == False)
+                       {
+                               DEBUG(3, ("_reg_perfcount_assemble_global: Failed to add new relationship for counter [%d].\n", j));
+                               retval = -1;
+                       }
+                       free(data.dptr);
+               }
+               else
+                       DEBUG(3, ("NULL relationship for counter [%d] using key [%s].\n", j, keybuf));
+       }       
+       return retval;
+}
+
+static BOOL _reg_perfcount_get_64(unsigned long long *retval,
+                                 TDB_CONTEXT *tdb,
+                                 int key_part1,
+                                 const char *key_part2)
+{
+       TDB_DATA key, data;
+       char buf[PERFCOUNT_MAX_LEN];
+
+       _reg_perfcount_make_key(&key, buf, PERFCOUNT_MAX_LEN, key_part1, key_part2);
+
+       data = tdb_fetch(tdb, key);
+       if(data.dptr == NULL)
+       {
+               DEBUG(3,("_reg_perfcount_get_64: No data found for key [%s].\n", key.dptr));
+               return False;
+       }
+
+       memset(buf, 0, PERFCOUNT_MAX_LEN);
+       memcpy(buf, data.dptr, data.dsize);
+       free(data.dptr);
+
+       *retval = strtoll(buf, NULL, 0);
+
+       return True;
+}
+
+static BOOL _reg_perfcount_init_data_block_perf(PERF_DATA_BLOCK *block,
+                                               TDB_CONTEXT *names)
+{
+       unsigned long long PerfFreq, PerfTime, PerfTime100nSec;
+       TDB_CONTEXT *counters;
+       BOOL status;
+       pstring fname;
+    
+       status = False;
+    
+       pstrcpy(fname, lp_counters_dir());
+       pstrcat(fname, "/data.tdb");
+    
+       counters = tdb_open_log(fname, 0, TDB_DEFAULT, O_RDONLY, 0444);
+    
+       if(counters == NULL)
+       {
+               DEBUG(1, ("reg_perfcount_init_data_block_perf: unable to open [%s].\n", fname));
+               return False;
+       }    
+    
+       status = _reg_perfcount_get_64(&PerfFreq, names, 0, "PerfFreq");
+       if(status == False)
+       {
+               tdb_close(counters);
+               return status;
+       }
+       memcpy((void *)&(block->PerfFreq), (const void *)&PerfFreq, sizeof(PerfFreq));
+
+       status = _reg_perfcount_get_64(&PerfTime, counters, 0, "PerfTime");
+       if(status == False)
+       {
+               tdb_close(counters);
+               return status;
+       }
+       memcpy((void *)&(block->PerfTime), (const void *)&PerfTime, sizeof(PerfTime));
+
+       status = _reg_perfcount_get_64(&PerfTime100nSec, counters, 0, "PerfTime100nSec");
+       if(status == False)
+       {
+               tdb_close(counters);
+               return status;
+       }
+       memcpy((void *)&(block->PerfTime100nSec), (const void *)&PerfTime100nSec, sizeof(PerfTime100nSec));
+
+       tdb_close(counters);
+       return True;
+}
+
+static void _reg_perfcount_init_data_block(PERF_DATA_BLOCK *block, prs_struct *ps, TDB_CONTEXT *names)
+{
+       wpstring temp;
+       time_t tm;
+       memset(temp, 0, sizeof(temp));
+       rpcstr_push((void *)temp, "PERF", sizeof(temp), STR_TERMINATE);
+       memcpy(block->Signature, temp, strlen_w(temp) *2);
+
+       if(ps->bigendian_data == RPC_BIG_ENDIAN)
+               block->LittleEndian = 0;
+       else
+               block->LittleEndian = 1;
+       block->Version = 1;
+       block->Revision = 1;
+       block->TotalByteLength = 0;
+       block->NumObjectTypes = 0;
+       block->DefaultObject = -1;
+       block->objects = NULL;
+       tm = time(NULL);
+       make_systemtime(&(block->SystemTime), gmtime(&tm));
+       _reg_perfcount_init_data_block_perf(block, names);
+       memset(temp, 0, sizeof(temp));
+       rpcstr_push((void *)temp, global_myname(), sizeof(temp), STR_TERMINATE);
+       block->SystemNameLength = (strlen_w(temp) * 2) + 2;
+       block->data = TALLOC_ZERO_ARRAY(ps->mem_ctx, uint8, block->SystemNameLength + (8 - (block->SystemNameLength % 8)));
+       memcpy(block->data, temp, block->SystemNameLength);
+       block->SystemNameOffset = sizeof(PERF_DATA_BLOCK) - sizeof(block->objects) - sizeof(block->data); 
+       block->HeaderLength = block->SystemNameOffset + block->SystemNameLength;
+       /* Make sure to adjust for 64-bit alignment for when we finish writing the system name,
+          so that the PERF_OBJECT_TYPE struct comes out 64-bit aligned */
+       block->HeaderLength += 8 - (block->HeaderLength % 8);
+
+       return;
+}
+
+static uint32 _reg_perfcount_perf_data_block_fixup(PERF_DATA_BLOCK *block, prs_struct *ps)
+{
+       int obj, cnt, inst, pad, i;
+       PERF_OBJECT_TYPE *object;
+       PERF_INSTANCE_DEFINITION *instance;
+       PERF_COUNTER_DEFINITION *counter;
+       PERF_COUNTER_BLOCK *counter_data;
+       char *temp = NULL, *src_addr, *dst_addr;
+
+       block->TotalByteLength = 0;
+       object = block->objects;
+       for(obj = 0; obj < block->NumObjectTypes; obj++)
+       {
+               object[obj].TotalByteLength = 0;
+               object[obj].DefinitionLength = 0;
+               instance = object[obj].instances;
+               counter = object[obj].counters;
+               for(cnt = 0; cnt < object[obj].NumCounters; cnt++)
+               {
+                       object[obj].TotalByteLength += counter[cnt].ByteLength;
+                       object[obj].DefinitionLength += counter[cnt].ByteLength;
+               }
+               if(object[obj].NumInstances != PERF_NO_INSTANCES)
+               {
+                       for(inst = 0; inst < object[obj].NumInstances; inst++)
+                       {
+                               instance = &(object[obj].instances[inst]);
+                               object[obj].TotalByteLength += instance->ByteLength;
+                               counter_data = &(instance->counter_data);
+                               counter = &(object[obj].counters[object[obj].NumCounters - 1]);
+                               counter_data->ByteLength = counter->CounterOffset + counter->CounterSize + sizeof(counter_data->ByteLength);
+                               temp = TALLOC_REALLOC_ARRAY(ps->mem_ctx, 
+                                                           temp, 
+                                                           uint8, 
+                                                           counter_data->ByteLength- sizeof(counter_data->ByteLength));
+                               memset(temp, 0, counter_data->ByteLength - sizeof(counter_data->ByteLength));
+                               src_addr = counter_data->data;
+                               for(i = 0; i < object[obj].NumCounters; i++)
+                               {
+                                       counter = &(object[obj].counters[i]);
+                                       dst_addr = temp + counter->CounterOffset - sizeof(counter_data->ByteLength);
+                                       memcpy(dst_addr, src_addr, counter->CounterSize);
+                                       src_addr += counter->CounterSize;
+                               }
+                               /* Make sure to be 64-bit aligned */
+                               if((pad = (counter_data->ByteLength % 8)))
+                               {
+                                       pad = 8 - pad;
+                               }
+                               counter_data->data = TALLOC_REALLOC_ARRAY(ps->mem_ctx,
+                                                                        counter_data->data,
+                                                                        uint8,
+                                                                        counter_data->ByteLength - sizeof(counter_data->ByteLength) + pad);
+                               memset(counter_data->data, 0, counter_data->ByteLength - sizeof(counter_data->ByteLength) + pad);
+                               memcpy(counter_data->data, temp, counter_data->ByteLength - sizeof(counter_data->ByteLength));
+                               counter_data->ByteLength += pad;
+                               object[obj].TotalByteLength += counter_data->ByteLength;
+                       }
+               }
+               else
+               {
+                       /* Need to be 64-bit aligned at the end of the counter_data block, so pad counter_data to a 64-bit boundary,
+                          so that the next PERF_OBJECT_TYPE can start on a 64-bit alignment */
+                       if((pad = (object[obj].counter_data.ByteLength % 8)))
+                       {
+                               pad = 8 - pad;
+                               object[obj].counter_data.data = TALLOC_REALLOC_ARRAY(ps->mem_ctx, 
+                                                                                    object[obj].counter_data.data,
+                                                                                    uint8, 
+                                                                                    object[obj].counter_data.ByteLength + pad);
+                               memset((void *)(object[obj].counter_data.data + object[obj].counter_data.ByteLength), 0, pad);
+                               object[obj].counter_data.ByteLength += pad;
+                       }
+                       object[obj].TotalByteLength += object[obj].counter_data.ByteLength;
+               }
+               object[obj].HeaderLength = sizeof(*object) - (sizeof(counter) + sizeof(instance) + sizeof(PERF_COUNTER_BLOCK));
+               object[obj].TotalByteLength += object[obj].HeaderLength;
+               object[obj].DefinitionLength += object[obj].HeaderLength;
+               
+               block->TotalByteLength += object[obj].TotalByteLength;
+       }
+
+       return block->TotalByteLength;
+}
+    
+uint32 reg_perfcount_get_perf_data_block(uint32 base_index, 
+                                        prs_struct *ps, 
+                                        PERF_DATA_BLOCK *block,
+                                        char *object_ids)
+{
+       uint32 buffer_size = 0, last_counter;
+       pstring fname;
+       TDB_CONTEXT *names;
+       int retval;
+
+       pstrcpy(fname, lp_counters_dir());
+       pstrcat(fname, "/names.tdb");
+
+       names = tdb_open_log(fname, 0, TDB_DEFAULT, O_RDONLY, 0444);
+
+       if(names == NULL)
+       {
+               DEBUG(1, ("reg_perfcount_get_perf_data_block: unable to open [%s].\n", fname));
+               return 0;
+       }
+
+       _reg_perfcount_init_data_block(block, ps, names);
+
+       last_counter = reg_perfcount_get_last_counter(base_index);
+    
+       if(object_ids == NULL)
+       {
+               /* we're getting a request for "Global" here */
+               retval = _reg_perfcount_assemble_global(block, ps, base_index, names);
+       }
+       else
+       {
+               /* we're getting a request for a specific set of PERF_OBJECT_TYPES */
+               retval = _reg_perfcount_assemble_global(block, ps, base_index, names);
+       }
+       buffer_size = _reg_perfcount_perf_data_block_fixup(block, ps);
+
+       tdb_close(names);
+
+       return buffer_size + block->HeaderLength;
+}
+
+static BOOL _reg_perfcount_marshall_perf_data_block(prs_struct *ps, PERF_DATA_BLOCK block, int depth)
+{
+       int i;
+       prs_debug(ps, depth, "", "_reg_perfcount_marshall_perf_data_block");
+       depth++;
+
+       if(!prs_align(ps))
+               return False;
+       for(i = 0; i < 4; i++)
+       {
+               if(!prs_uint16("Signature", ps, depth, &block.Signature[i]))
+                       return False;
+       }
+       if(!prs_uint32("Little Endian", ps, depth, &block.LittleEndian))
+               return False;
+       if(!prs_uint32("Version", ps, depth, &block.Version))
+               return False;
+       if(!prs_uint32("Revision", ps, depth, &block.Revision))
+               return False;
+       if(!prs_uint32("TotalByteLength", ps, depth, &block.TotalByteLength))
+               return False;
+       if(!prs_uint32("HeaderLength", ps, depth, &block.HeaderLength))
+               return False;
+       if(!prs_uint32("NumObjectTypes", ps, depth, &block.NumObjectTypes))
+               return False;
+       if(!prs_uint32("DefaultObject", ps, depth, &block.DefaultObject))
+               return False;
+       if(!spoolss_io_system_time("SystemTime", ps, depth, &block.SystemTime))
+               return False;
+       if(!prs_uint32("Padding", ps, depth, &block.Padding))
+               return False;
+       if(!prs_align_uint64(ps))
+               return False;
+       if(!prs_uint64("PerfTime", ps, depth, &block.PerfTime))
+               return False;
+       if(!prs_uint64("PerfFreq", ps, depth, &block.PerfFreq))
+               return False;
+       if(!prs_uint64("PerfTime100nSec", ps, depth, &block.PerfTime100nSec))
+               return False;
+       if(!prs_uint32("SystemNameLength", ps, depth, &block.SystemNameLength))
+               return False;
+       if(!prs_uint32("SystemNameOffset", ps, depth, &block.SystemNameOffset))
+               return False;
+       /* hack to make sure we're 64-bit aligned at the end of this whole mess */
+       if(!prs_uint8s(False, "SystemName", ps, depth, block.data, 
+                      block.HeaderLength - block.SystemNameOffset)) 
+               return False;
+
+       return True;
+}
+
+static BOOL _reg_perfcount_marshall_perf_counters(prs_struct *ps,
+                                                 PERF_OBJECT_TYPE object,
+                                                 int depth)
+{
+       int cnt;
+       PERF_COUNTER_DEFINITION counter;
+
+       prs_debug(ps, depth, "", "_reg_perfcount_marshall_perf_counters");
+       depth++;
+    
+       for(cnt = 0; cnt < object.NumCounters; cnt++)
+       {
+               counter = object.counters[cnt];
+
+               if(!prs_align(ps))
+                       return False;
+               if(!prs_uint32("ByteLength", ps, depth, &counter.ByteLength))
+                       return False;
+               if(!prs_uint32("CounterNameTitleIndex", ps, depth, &counter.CounterNameTitleIndex))
+                       return False;
+               if(!prs_uint32("CounterNameTitlePointer", ps, depth, &counter.CounterNameTitlePointer))
+                       return False;
+               if(!prs_uint32("CounterHelpTitleIndex", ps, depth, &counter.CounterHelpTitleIndex))
+                       return False;
+               if(!prs_uint32("CounterHelpTitlePointer", ps, depth, &counter.CounterHelpTitlePointer))
+                       return False;
+               if(!prs_uint32("DefaultScale", ps, depth, &counter.DefaultScale))
+                       return False;
+               if(!prs_uint32("DetailLevel", ps, depth, &counter.DetailLevel))
+                       return False;
+               if(!prs_uint32("CounterType", ps, depth, &counter.CounterType))
+                       return False;
+               if(!prs_uint32("CounterSize", ps, depth, &counter.CounterSize))
+                       return False;
+               if(!prs_uint32("CounterOffset", ps, depth, &counter.CounterOffset))
+                       return False;
+       }
+
+       return True;
+}
+
+static BOOL _reg_perfcount_marshall_perf_counter_data(prs_struct *ps, 
+                                                     PERF_COUNTER_BLOCK counter_data, 
+                                                     int depth)
+{
+       prs_debug(ps, depth, "", "_reg_perfcount_marshall_perf_counter_data");
+       depth++;
+    
+       if(!prs_align_uint64(ps))
+               return False;
+    
+       if(!prs_uint32("ByteLength", ps, depth, &counter_data.ByteLength))
+               return False;
+       if(!prs_uint8s(False, "CounterData", ps, depth, counter_data.data, counter_data.ByteLength - sizeof(uint32)))
+               return False;
+       if(!prs_align_uint64(ps))
+               return False;
+
+       return True;
+}
+
+static BOOL _reg_perfcount_marshall_perf_instances(prs_struct *ps,
+                                                  PERF_OBJECT_TYPE object, 
+                                                  int depth)
+{
+       PERF_INSTANCE_DEFINITION instance;
+       int inst;
+
+       prs_debug(ps, depth, "", "_reg_perfcount_marshall_perf_instances");
+       depth++;
+
+       for(inst = 0; inst < object.NumInstances; inst++)
+       {
+               instance = object.instances[inst];
+
+               if(!prs_align(ps))
+                       return False;
+               if(!prs_uint32("ByteLength", ps, depth, &instance.ByteLength))
+                       return False;
+               if(!prs_uint32("ParentObjectTitleIndex", ps, depth, &instance.ParentObjectTitleIndex))
+                       return False;
+               if(!prs_uint32("ParentObjectTitlePointer", ps, depth, &instance.ParentObjectTitlePointer))
+                       return False;
+               if(!prs_uint32("UniqueID", ps, depth, &instance.UniqueID))
+                       return False;
+               if(!prs_uint32("NameOffset", ps, depth, &instance.NameOffset))
+                       return False;
+               if(!prs_uint32("NameLength", ps, depth, &instance.NameLength))
+                       return False;
+               if(!prs_uint8s(False, "InstanceName", ps, depth, instance.data,
+                              instance.ByteLength - instance.NameOffset))
+                       return False;
+               if(_reg_perfcount_marshall_perf_counter_data(ps, instance.counter_data, depth) == False)
+                       return False;
+       }
+       
+       return True;
+}
+
+static BOOL _reg_perfcount_marshall_perf_objects(prs_struct *ps, PERF_DATA_BLOCK block, int depth)
+{
+       int obj;
+
+       PERF_OBJECT_TYPE object;
+    
+       prs_debug(ps, depth, "", "_reg_perfcount_marshall_perf_objects");
+       depth++;
+
+       for(obj = 0; obj < block.NumObjectTypes; obj++)
+       {
+               object = block.objects[obj];
+
+               if(!prs_align(ps))
+                       return False;
+
+               if(!prs_uint32("TotalByteLength", ps, depth, &object.TotalByteLength))
+                       return False;
+               if(!prs_uint32("DefinitionLength", ps, depth, &object.DefinitionLength))
+                       return False;
+               if(!prs_uint32("HeaderLength", ps, depth, &object.HeaderLength))
+                       return False;
+               if(!prs_uint32("ObjectNameTitleIndex", ps, depth, &object.ObjectNameTitleIndex))
+                       return False;
+               if(!prs_uint32("ObjectNameTitlePointer", ps, depth, &object.ObjectNameTitlePointer))
+                       return False;
+               if(!prs_uint32("ObjectHelpTitleIndex", ps, depth, &object.ObjectHelpTitleIndex))
+                       return False;
+               if(!prs_uint32("ObjectHelpTitlePointer", ps, depth, &object.ObjectHelpTitlePointer))
+                       return False;
+               if(!prs_uint32("DetailLevel", ps, depth, &object.DetailLevel))
+                       return False;
+               if(!prs_uint32("NumCounters", ps, depth, &object.NumCounters))
+                       return False;
+               if(!prs_uint32("DefaultCounter", ps, depth, &object.DefaultCounter))
+                       return False;
+               if(!prs_uint32("NumInstances", ps, depth, &object.NumInstances))
+                       return False;
+               if(!prs_uint32("CodePage", ps, depth, &object.CodePage))
+                       return False;
+               if(!prs_align_uint64(ps))
+                       return False;
+               if(!prs_uint64("PerfTime", ps, depth, &object.PerfTime))
+                       return False;
+               if(!prs_uint64("PerfFreq", ps, depth, &object.PerfFreq))
+                       return False;
+
+               /* Now do the counters */
+               /* If no instances, encode counter_data */
+               /* If instances, encode instace plus counter data for each instance */
+               if(_reg_perfcount_marshall_perf_counters(ps, object, depth) == False)
+                       return False;
+               if(object.NumInstances == PERF_NO_INSTANCES)
+               {
+                       if(_reg_perfcount_marshall_perf_counter_data(ps, object.counter_data, depth) == False)
+                               return False;
+               }
+               else
+               {
+                       if(_reg_perfcount_marshall_perf_instances(ps, object, depth) == False)
+                               return False;
+               }
+       }
+
+       return True;
+}
+
+static BOOL _reg_perfcount_marshall_hkpd(prs_struct *ps, PERF_DATA_BLOCK block)
+{
+       int depth = 0;
+       if(_reg_perfcount_marshall_perf_data_block(ps, block, depth) == True)
+       {
+               if(_reg_perfcount_marshall_perf_objects(ps, block, depth) == True)
+                       return True;
+       }
+       return False;
+}
+WERROR reg_perfcount_get_hkpd(prs_struct *ps, uint32 max_buf_size, uint32 *outbuf_len, char *object_ids)
+{
+       /*
+        * For a detailed description of the layout of this structure,
+        * see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/perfmon/base/performance_data_format.asp
+        */
+       PERF_DATA_BLOCK block;
+       uint32 buffer_size, base_index; 
+    
+       buffer_size = 0;
+       base_index = reg_perfcount_get_base_index();
+       ZERO_STRUCT(block);
+
+       buffer_size = reg_perfcount_get_perf_data_block(base_index, ps, &block, object_ids);
+
+       if(buffer_size < max_buf_size)
+       {
+               *outbuf_len = buffer_size;
+               if(_reg_perfcount_marshall_hkpd(ps, block) == True)
+                       return WERR_OK;
+               else
+                       return WERR_NOMEM;
+       }
+       else
+       {
+               *outbuf_len = max_buf_size;
+               _reg_perfcount_marshall_perf_data_block(ps, block, 0);
+               return WERR_INSUFFICIENT_BUFFER;
+       }
+}    
index d0f7daa926dec814b135614bb756abd5426aecf9..b07c8e9644f56424f92901b78975f5df5e0760a6 100644 (file)
@@ -55,34 +55,6 @@ struct reg_dyn_tree {
  *********************************************************************
  *********************************************************************/
 
-/**********************************************************************
- move to next non-delimter character
-*********************************************************************/
-
-static char* remaining_path( const char *key )
-{
-       static pstring new_path;
-       char *p;
-       
-       if ( !key || !*key )
-               return NULL;
-
-       pstrcpy( new_path, key );
-       /* normalize_reg_path( new_path ); */
-       
-       if ( !(p = strchr( new_path, '\\' )) ) 
-       {
-               if ( !(p = strchr( new_path, '/' )) )
-                       p = new_path;
-               else 
-                       p++;
-       }
-       else
-               p++;
-               
-       return p;
-}
-
 /***********************************************************************
  simple function to prune a pathname down to the basename of a file 
  **********************************************************************/
@@ -107,7 +79,7 @@ static char* dos_basename ( char *path )
 
 static int key_forms_fetch_keys( const char *key, REGSUBKEY_CTR *subkeys )
 {
-       char *p = remaining_path( key + strlen(KEY_FORMS) );
+       char *p = reg_remaining_path( key + strlen(KEY_FORMS) );
        
        /* no keys below Forms */
        
@@ -204,9 +176,9 @@ static char* strip_printers_prefix( const char *key )
        /* normalizing the path does not change length, just key delimiters and case */
 
        if ( strncmp( path, KEY_WINNT_PRINTERS, strlen(KEY_WINNT_PRINTERS) ) == 0 )
-               subkeypath = remaining_path( key + strlen(KEY_WINNT_PRINTERS) );
+               subkeypath = reg_remaining_path( key + strlen(KEY_WINNT_PRINTERS) );
        else
-               subkeypath = remaining_path( key + strlen(KEY_CONTROL_PRINTERS) );
+               subkeypath = reg_remaining_path( key + strlen(KEY_CONTROL_PRINTERS) );
                
        return subkeypath;
 }
@@ -445,7 +417,7 @@ static void fill_in_printer_values( NT_PRINTER_INFO_LEVEL_2 *info2, REGVAL_CTR *
        /* use a prs_struct for converting the devmode and security 
           descriptor to REG_BINARY */
        
-       prs_init( &prs, MAX_PDU_FRAG_LEN, values, MARSHALL);
+       prs_init( &prs, RPC_MAX_PDU_FRAG_LEN, values, MARSHALL);
 
        /* stream the device mode */
                
@@ -754,7 +726,7 @@ static int key_driver_fetch_keys( const char *key, REGSUBKEY_CTR *subkeys )
 
        DEBUG(10,("key_driver_fetch_keys key=>[%s]\n", key ? key : "NULL" ));
        
-       keystr = remaining_path( key + strlen(KEY_ENVIRONMENTS) );      
+       keystr = reg_remaining_path( key + strlen(KEY_ENVIRONMENTS) );  
        
        /* list all possible architectures */
        
@@ -1044,7 +1016,7 @@ static int key_driver_fetch_values( const char *key, REGVAL_CTR *values )
 
        /* no values in the Environments key */
        
-       if ( !(keystr = remaining_path( key + strlen(KEY_ENVIRONMENTS) )) )
+       if ( !(keystr = reg_remaining_path( key + strlen(KEY_ENVIRONMENTS) )) )
                return 0;
        
        pstrcpy( subkey, keystr);
index 165292cf2feb1c7ff948f3929b98beee738a804b..9f19db2646a12a61f2926b5e861accb5c15b180a 100644 (file)
@@ -97,3 +97,31 @@ void normalize_reg_path( pstring keyname )
        strupper_m( keyname  );
 }
 
+/**********************************************************************
+ move to next non-delimter character
+*********************************************************************/
+
+char* reg_remaining_path( const char *key )
+{
+       static pstring new_path;
+       char *p;
+       
+       if ( !key || !*key )
+               return NULL;
+
+       pstrcpy( new_path, key );
+       /* normalize_reg_path( new_path ); */
+       
+       if ( !(p = strchr( new_path, '\\' )) ) 
+       {
+               if ( !(p = strchr( new_path, '/' )) )
+                       p = new_path;
+               else 
+                       p++;
+       }
+       else
+               p++;
+               
+       return p;
+}
+
index e7b8cdc8bb24e1aeb190ca1c9877d12dc72a066b..954f4ae7bd0b6916984c3e783a429ef1d1f07bb4 100644 (file)
@@ -561,7 +561,7 @@ static REGF_HBIN* lookup_hbin_block( REGF_FILE *file, uint32 offset )
        /* start with the open list */
 
        for ( hbin=file->block_list; hbin; hbin=hbin->next ) {
-               DEBUG(10,("lookup_hbin_block: address = 0x%x [0x%x]\n", hbin->file_off, (uint32)hbin ));
+               DEBUG(10,("lookup_hbin_block: address = 0x%x [0x%lx]\n", hbin->file_off, (unsigned long)hbin ));
                if ( hbin_contains_offset( hbin, offset ) )
                        return hbin;
        }
index 79335191183735e4d1549411d6e215ce8bcd2a88..78df220ac2a3ecdbf7ac1ac3a8303cb49ea462c2 100644 (file)
@@ -2,6 +2,7 @@
    Unix SMB/CIFS implementation.
    RPC pipe client
    Copyright (C) Tim Potter                        2000-2001,
+   Copyright (C) Jeremy Allison                                2005.
    
    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
@@ -22,7 +23,7 @@
 
 /* Query DFS support */
 
-NTSTATUS cli_dfs_exist(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+NTSTATUS rpccli_dfs_exist(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                        BOOL *dfs_exists)
 {
        prs_struct qbuf, rbuf;
@@ -33,25 +34,16 @@ NTSTATUS cli_dfs_exist(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        /* Marshall data and send request */
 
         init_dfs_q_dfs_exist(&q);
 
-       if (!dfs_io_q_dfs_exist("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, PI_NETDFS, DFS_EXIST, &qbuf, &rbuf)) {
-               goto done;
-       }
-
-       /* Unmarshall response */
-
-       if (!dfs_io_r_dfs_exist("", &r, &rbuf, 0)) {
-               goto done;
-       }
+       CLI_DO_RPC( cli, mem_ctx, PI_NETDFS, DFS_EXIST,
+               q, r,
+               qbuf, rbuf,
+               dfs_io_q_dfs_exist,
+               dfs_io_r_dfs_exist,
+               NT_STATUS_UNSUCCESSFUL);
 
        /* Return result */
 
@@ -59,14 +51,10 @@ NTSTATUS cli_dfs_exist(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 
        result = NT_STATUS_OK;
 
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
        return result;
 }
 
-NTSTATUS cli_dfs_add(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+NTSTATUS rpccli_dfs_add(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                      const char *entrypath, const char *servername, 
                     const char *sharename, const char *comment, uint32 flags)
 {
@@ -78,39 +66,26 @@ NTSTATUS cli_dfs_add(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        /* Marshall data and send request */
 
         init_dfs_q_dfs_add(&q, entrypath, servername, sharename, comment,
                           flags);
 
-       if (!dfs_io_q_dfs_add("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, PI_NETDFS, DFS_ADD, &qbuf, &rbuf)) {
-               goto done;
-       }
-
-       /* Unmarshall response */
-
-       if (!dfs_io_r_dfs_add("", &r, &rbuf, 0)) {
-               goto done;
-       }
+       CLI_DO_RPC( cli, mem_ctx, PI_NETDFS, DFS_ADD,
+               q, r,
+               qbuf, rbuf,
+               dfs_io_q_dfs_add,
+               dfs_io_r_dfs_add,
+               NT_STATUS_UNSUCCESSFUL);
 
        /* Return result */
 
         result = werror_to_ntstatus(r.status);
 
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
        return result;
 }
 
-NTSTATUS cli_dfs_remove(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+NTSTATUS rpccli_dfs_remove(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                         const char *entrypath, const char *servername, 
                        const char *sharename)
 {
@@ -122,38 +97,25 @@ NTSTATUS cli_dfs_remove(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        /* Marshall data and send request */
 
         init_dfs_q_dfs_remove(&q, entrypath, servername, sharename);
 
-       if (!dfs_io_q_dfs_remove("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, PI_NETDFS, DFS_REMOVE, &qbuf, &rbuf)) {
-               goto done;
-       }
-
-       /* Unmarshall response */
-
-       if (!dfs_io_r_dfs_remove("", &r, &rbuf, 0)) {
-               goto done;
-       }
+       CLI_DO_RPC( cli, mem_ctx, PI_NETDFS, DFS_REMOVE,
+               q, r,
+               qbuf, rbuf,
+               dfs_io_q_dfs_remove,
+               dfs_io_r_dfs_remove,
+               NT_STATUS_UNSUCCESSFUL);
 
        /* Return result */
 
        result = werror_to_ntstatus(r.status);
 
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
        return result;
 }
 
-NTSTATUS cli_dfs_get_info(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+NTSTATUS rpccli_dfs_get_info(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                           const char *entrypath, const char *servername, 
                          const char *sharename, uint32 info_level, 
                          DFS_INFO_CTR *ctr)
@@ -167,42 +129,29 @@ NTSTATUS cli_dfs_get_info(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        /* Marshall data and send request */
 
         init_dfs_q_dfs_get_info(&q, entrypath, servername, sharename,
                                info_level);
 
-       if (!dfs_io_q_dfs_get_info("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, PI_NETDFS, DFS_GET_INFO, &qbuf, &rbuf)) {
-               goto done;
-       }
-
-       /* Unmarshall response */
-
-       if (!dfs_io_r_dfs_get_info("", &r, &rbuf, 0)) {
-               goto done;
-       }
+       CLI_DO_RPC( cli, mem_ctx, PI_NETDFS, DFS_GET_INFO,
+               q, r,
+               qbuf, rbuf,
+               dfs_io_q_dfs_get_info,
+               dfs_io_r_dfs_get_info,
+               NT_STATUS_UNSUCCESSFUL);
 
        /* Return result */
 
        result = werror_to_ntstatus(r.status);
        *ctr = r.ctr;
        
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
        return result;
 }
 
 /* Enumerate dfs shares */
 
-NTSTATUS cli_dfs_enum(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+NTSTATUS rpccli_dfs_enum(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                       uint32 info_level, DFS_INFO_CTR *ctr)
 {
        prs_struct qbuf, rbuf;
@@ -213,35 +162,22 @@ NTSTATUS cli_dfs_enum(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        /* Marshall data and send request */
 
         init_dfs_q_dfs_enum(&q, info_level, ctr);
 
-       if (!dfs_io_q_dfs_enum("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, PI_NETDFS, DFS_ENUM, &qbuf, &rbuf)) {
-               goto done;
-       }
-
-       /* Unmarshall response */
-       
        r.ctr = ctr;
 
-       if (!dfs_io_r_dfs_enum("", &r, &rbuf, 0)) {
-               goto done;
-       }
+       CLI_DO_RPC( cli, mem_ctx, PI_NETDFS, DFS_ENUM,
+               q, r,
+               qbuf, rbuf,
+               dfs_io_q_dfs_enum,
+               dfs_io_r_dfs_enum,
+               NT_STATUS_UNSUCCESSFUL);
 
        /* Return result */
 
        result = werror_to_ntstatus(r.status);
 
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
        return result;
 }
index 41063a5d7fb60f3ce623bf6b7cf63fe13b1e2690..8d1945f76988509dd8ad0e2006b5c19ee0c9580b 100644 (file)
@@ -2,6 +2,7 @@
    Unix SMB/CIFS implementation.
    RPC pipe client
    Copyright (C) Gerald Carter                        2002,
+   Copyright (C) Jeremy Allison                                2005.
    
    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
@@ -38,30 +39,14 @@ NTSTATUS rpccli_ds_getprimarydominfo(struct rpc_pipe_client *cli,
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       if (!prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
-               return NT_STATUS_NO_MEMORY;
-       }
-       if (!prs_init(&rbuf, 0, mem_ctx, UNMARSHALL)) {
-               prs_mem_free(&qbuf);
-               return NT_STATUS_NO_MEMORY;
-       }
-       
        q.level = level;
        
-       if (!ds_io_q_getprimdominfo("", &qbuf, 0, &q) 
-           || !rpc_api_pipe_req_int(cli, DS_GETPRIMDOMINFO, &qbuf, &rbuf)) {
-               result = NT_STATUS_UNSUCCESSFUL;
-               goto done;
-       }
-
-       /* Unmarshall response */
-
-       if (!ds_io_r_getprimdominfo("", &rbuf, 0, &r)) {
-               result = NT_STATUS_UNSUCCESSFUL;
-               goto done;
-       }
+       CLI_DO_RPC( cli, mem_ctx, PI_LSARPC_DS, DS_GETPRIMDOMINFO,
+               q, r,
+               qbuf, rbuf,
+               ds_io_q_getprimdominfo,
+               ds_io_r_getprimdominfo,
+               NT_STATUS_UNSUCCESSFUL);
        
        /* Return basic info - if we are requesting at info != 1 then
           there could be trouble. */ 
@@ -76,20 +61,10 @@ NTSTATUS rpccli_ds_getprimarydominfo(struct rpc_pipe_client *cli,
        }
        
 done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
 
        return result;
 }
 
-NTSTATUS cli_ds_getprimarydominfo(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
-                                 uint16 level, DS_DOMINFO_CTR *ctr)
-{
-       return rpccli_ds_getprimarydominfo(&cli->pipes[PI_LSARPC_DS], mem_ctx,
-                                          level, ctr);
-}
-
-
 /********************************************************************
  Enumerate trusted domains in an AD forest
 ********************************************************************/
@@ -108,30 +83,14 @@ NTSTATUS rpccli_ds_enum_domain_trusts(struct rpc_pipe_client *cli,
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       if (!prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
-               return NT_STATUS_NO_MEMORY;;
-       }
-       if (!prs_init(&rbuf, 0, mem_ctx, UNMARSHALL)) {
-               prs_mem_free(&qbuf);
-               return NT_STATUS_NO_MEMORY;
-       }
-
        init_q_ds_enum_domain_trusts( &q, server, flags );
                
-       if (!ds_io_q_enum_domain_trusts("", &qbuf, 0, &q) 
-           || !rpc_api_pipe_req_int(cli, DS_ENUM_DOM_TRUSTS, &qbuf, &rbuf)) {
-               result = NT_STATUS_UNSUCCESSFUL;
-               goto done;
-       }
-
-       /* Unmarshall response */
-
-       if (!ds_io_r_enum_domain_trusts("", &rbuf, 0, &r)) {
-               result = NT_STATUS_UNSUCCESSFUL;
-               goto done;
-       }
+       CLI_DO_RPC( cli, mem_ctx, PI_LSARPC_DS, DS_ENUM_DOM_TRUSTS,
+               q, r,
+               qbuf, rbuf,
+               ds_io_q_enum_domain_trusts,
+               ds_io_r_enum_domain_trusts,
+               NT_STATUS_UNSUCCESSFUL);
        
        result = r.status;
        
@@ -168,19 +127,5 @@ NTSTATUS rpccli_ds_enum_domain_trusts(struct rpc_pipe_client *cli,
                }
        }
        
-done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
        return result;
 }
-
-NTSTATUS cli_ds_enum_domain_trusts(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
-                                  const char *server, uint32 flags, 
-                                  struct ds_domain_trust **trusts,
-                                  uint32 *num_domains)
-{
-       return rpccli_ds_enum_domain_trusts(&cli->pipes[PI_NETLOGON], mem_ctx,
-                                           server, flags, trusts,
-                                           num_domains);
-}
index cd7e21f918f2e0e7d3ae32455759c025234f4171..89de6cec9417ab393da474513ca2ef3919837bf6 100644 (file)
@@ -4,6 +4,7 @@
    RPC pipe client
 
    Copyright (C) Tim Potter 2003
+   Copyright (C) Jeremy Allison 2005.
    
    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
@@ -22,7 +23,7 @@
 
 #include "includes.h"
 
-NTSTATUS cli_echo_add_one(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+NTSTATUS rpccli_echo_add_one(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                          uint32 request, uint32 *response)
 {
        prs_struct qbuf, rbuf;
@@ -33,42 +34,26 @@ NTSTATUS cli_echo_add_one(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       if (!prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
-               return NT_STATUS_NO_MEMORY;
-       }
-       if (!prs_init(&rbuf, 0, mem_ctx, UNMARSHALL)) {
-               prs_mem_free(&qbuf);
-               return NT_STATUS_NO_MEMORY;
-       }
-
        /* Marshall data and send request */
 
         init_echo_q_add_one(&q, request);
 
-       if (!echo_io_q_add_one("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, PI_ECHO, ECHO_ADD_ONE, &qbuf, &rbuf))
-               goto done;
-
-       /* Unmarshall response */
-
-       if (!echo_io_r_add_one("", &r, &rbuf, 0))
-               goto done;
+       CLI_DO_RPC( cli, mem_ctx, PI_ECHO, ECHO_ADD_ONE,
+                       q, r,
+                       qbuf, rbuf,
+                       echo_io_q_add_one,
+                       echo_io_r_add_one,
+                       NT_STATUS_UNSUCCESSFUL);
 
        if (response)
                *response = r.response;
 
        result = True;
 
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
        return result ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
 }
 
-NTSTATUS cli_echo_data(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+NTSTATUS rpccli_echo_data(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                       uint32 size, char *in_data, char **out_data)
 {
        prs_struct qbuf, rbuf;
@@ -79,28 +64,16 @@ NTSTATUS cli_echo_data(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       if (!prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
-               return NT_STATUS_NO_MEMORY;
-       }
-       if (!prs_init(&rbuf, 0, mem_ctx, UNMARSHALL)) {
-               prs_mem_free(&qbuf);
-               return NT_STATUS_NO_MEMORY;
-       }
-
        /* Marshall data and send request */
 
         init_echo_q_echo_data(&q, size, in_data);
 
-       if (!echo_io_q_echo_data("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, PI_ECHO, ECHO_DATA, &qbuf, &rbuf))
-               goto done;
-
-       /* Unmarshall response */
-
-       if (!echo_io_r_echo_data("", &r, &rbuf, 0))
-               goto done;
+       CLI_DO_RPC( cli, mem_ctx, PI_ECHO, ECHO_DATA,
+                       q, r,
+                       qbuf, rbuf,
+                       echo_io_q_echo_data,
+                       echo_io_r_echo_data,
+                       NT_STATUS_UNSUCCESSFUL);
 
        result = True;
 
@@ -109,14 +82,10 @@ NTSTATUS cli_echo_data(struct cli_state *cli, TALLOC_CTX *mem_ctx,
                memcpy(*out_data, r.data, size);
        }
 
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
        return result ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
 }
 
-NTSTATUS cli_echo_sink_data(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+NTSTATUS rpccli_echo_sink_data(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                            uint32 size, char *in_data)
 {
        prs_struct qbuf, rbuf;
@@ -127,41 +96,23 @@ NTSTATUS cli_echo_sink_data(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       if (!prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
-               return NT_STATUS_NO_MEMORY;
-       }
-       if (!prs_init(&rbuf, 0, mem_ctx, UNMARSHALL)) {
-               prs_mem_free(&qbuf);
-               return NT_STATUS_NO_MEMORY;
-       }
-
        /* Marshall data and send request */
 
         init_echo_q_sink_data(&q, size, in_data);
 
-       if (!echo_io_q_sink_data("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, PI_ECHO, ECHO_SINK_DATA, &qbuf, &rbuf)) {
-               goto done;
-       }
-
-       /* Unmarshall response */
-
-       if (!echo_io_r_sink_data("", &r, &rbuf, 0)) {
-               goto done;
-       }
+       CLI_DO_RPC( cli, mem_ctx, PI_ECHO, ECHO_SINK_DATA,
+                       q, r,
+                       qbuf, rbuf,
+                       echo_io_q_sink_data,
+                       echo_io_r_sink_data,
+                       NT_STATUS_UNSUCCESSFUL);
 
        result = True;
 
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
        return result ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
 }
 
-NTSTATUS cli_echo_source_data(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+NTSTATUS rpccli_echo_source_data(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                              uint32 size, char **out_data)
 {
        prs_struct qbuf, rbuf;
@@ -172,36 +123,18 @@ NTSTATUS cli_echo_source_data(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       if (!prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
-               return NT_STATUS_NO_MEMORY;
-       }
-       if (!prs_init(&rbuf, 0, mem_ctx, UNMARSHALL)) {
-               prs_mem_free(&qbuf);
-               return NT_STATUS_NO_MEMORY;
-       }
-
        /* Marshall data and send request */
 
         init_echo_q_source_data(&q, size);
 
-       if (!echo_io_q_source_data("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, PI_ECHO, ECHO_SOURCE_DATA, &qbuf, &rbuf)) {
-               goto done;
-       }
-
-       /* Unmarshall response */
-
-       if (!echo_io_r_source_data("", &r, &rbuf, 0)) {
-               goto done;
-       }
+       CLI_DO_RPC( cli, mem_ctx, PI_ECHO, ECHO_SOURCE_DATA,
+                       q, r,
+                       qbuf, rbuf,
+                       echo_io_q_source_data,
+                       echo_io_r_source_data,
+                       NT_STATUS_UNSUCCESSFUL);
 
        result = True;
 
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
        return result ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
 }
index 26f82cdfbe3e1ec885625373ae8e08aa37144160..d7dcda72e3f70ab728f4734ccfdd2eefe1abca04 100644 (file)
@@ -3,10 +3,8 @@
    RPC pipe client
    Copyright (C) Tim Potter                        2000-2001,
    Copyright (C) Andrew Tridgell              1992-1997,2000,
-   Copyright (C) Luke Kenneth Casson Leighton 1996-1997,2000,
-   Copyright (C) Paul Ashton                       1997,2000,
-   Copyright (C) Elrond                                 2000,
    Copyright (C) Rafal Szczesniak                       2002
+   Copyright (C) Jeremy Allison                                2005.
    
    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
@@ -24,7 +22,6 @@
 */
 
 #include "includes.h"
-#include "rpc_client.h"
 
 /** @defgroup lsa LSA - Local Security Architecture
  *  @ingroup rpc_client
@@ -54,16 +51,9 @@ NTSTATUS rpccli_lsa_open_policy(struct rpc_pipe_client *cli,
        LSA_SEC_QOS qos;
        NTSTATUS result;
 
-       SMB_ASSERT(cli->pipe_idx == PI_LSARPC);
-
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        /* Initialise input parameters */
 
        if (sec_qos) {
@@ -75,18 +65,12 @@ NTSTATUS rpccli_lsa_open_policy(struct rpc_pipe_client *cli,
 
        /* Marshall data and send request */
 
-       if (!lsa_io_q_open_pol("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req_int(cli, LSA_OPENPOLICY, &qbuf, &rbuf)) {
-               result = NT_STATUS_UNSUCCESSFUL;
-               goto done;
-       }
-
-       /* Unmarshall response */
-
-       if (!lsa_io_r_open_pol("", &r, &rbuf, 0)) {
-               result = NT_STATUS_UNSUCCESSFUL;
-               goto done;
-       }
+       CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_OPENPOLICY,
+                       q, r,
+                       qbuf, rbuf,
+                       lsa_io_q_open_pol,
+                       lsa_io_r_open_pol,
+                       NT_STATUS_UNSUCCESSFUL );
 
        /* Return output parameters */
 
@@ -97,20 +81,9 @@ NTSTATUS rpccli_lsa_open_policy(struct rpc_pipe_client *cli,
 #endif
        }
 
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
        return result;
 }
 
-NTSTATUS cli_lsa_open_policy(struct cli_state *cli, TALLOC_CTX *mem_ctx,
-                             BOOL sec_qos, uint32 des_access, POLICY_HND *pol)
-{
-       return rpccli_lsa_open_policy(&cli->pipes[PI_LSARPC], mem_ctx,
-                                     sec_qos, des_access, pol);
-}
-
 /** Open a LSA policy handle
   *
   * @param cli Handle on an initialised SMB connection 
@@ -125,40 +98,24 @@ NTSTATUS rpccli_lsa_open_policy2(struct rpc_pipe_client *cli,
        LSA_R_OPEN_POL2 r;
        LSA_SEC_QOS qos;
        NTSTATUS result;
+       char *srv_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", cli->cli->desthost);
 
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
-       /* Initialise input parameters */
-
        if (sec_qos) {
                init_lsa_sec_qos(&qos, 2, 1, 0);
-               init_q_open_pol2(&q, cli->cli->srv_name_slash, 0, des_access, 
-                                 &qos);
+               init_q_open_pol2(&q, srv_name_slash, 0, des_access, &qos);
        } else {
-               init_q_open_pol2(&q, cli->cli->srv_name_slash, 0, des_access, 
-                                 NULL);
+               init_q_open_pol2(&q, srv_name_slash, 0, des_access, NULL);
        }
 
-       /* Marshall data and send request */
-
-       if (!lsa_io_q_open_pol2("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req_int(cli, LSA_OPENPOLICY2, &qbuf, &rbuf)) {
-               result = NT_STATUS_UNSUCCESSFUL;
-               goto done;
-       }
-
-       /* Unmarshall response */
-
-       if (!lsa_io_r_open_pol2("", &r, &rbuf, 0)) {
-               result = NT_STATUS_UNSUCCESSFUL;
-               goto done;
-       }
+       CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_OPENPOLICY2,
+                       q, r,
+                       qbuf, rbuf,
+                       lsa_io_q_open_pol2,
+                       lsa_io_r_open_pol2,
+                       NT_STATUS_UNSUCCESSFUL );
 
        /* Return output parameters */
 
@@ -169,21 +126,9 @@ NTSTATUS rpccli_lsa_open_policy2(struct rpc_pipe_client *cli,
 #endif
        }
 
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
        return result;
 }
 
-NTSTATUS cli_lsa_open_policy2(struct cli_state *cli, TALLOC_CTX *mem_ctx,
-                              BOOL sec_qos, uint32 des_access, POLICY_HND *pol)
-{
-       return rpccli_lsa_open_policy2(&cli->pipes[PI_LSARPC], mem_ctx,
-                                      sec_qos, des_access, pol);
-}
-
-
 /** Close a LSA policy handle */
 
 NTSTATUS rpccli_lsa_close(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, 
@@ -194,32 +139,17 @@ NTSTATUS rpccli_lsa_close(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
        LSA_R_CLOSE r;
        NTSTATUS result;
 
-       SMB_ASSERT(cli->pipe_idx == PI_LSARPC);
-
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
-       /* Marshall data and send request */
-
        init_lsa_q_close(&q, pol);
 
-       if (!lsa_io_q_close("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req_int(cli, LSA_CLOSE, &qbuf, &rbuf)) {
-               result = NT_STATUS_UNSUCCESSFUL;
-               goto done;
-       }
-
-       /* Unmarshall response */
-
-       if (!lsa_io_r_close("", &r, &rbuf, 0)) {
-               result = NT_STATUS_UNSUCCESSFUL;
-               goto done;
-       }
+       CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_CLOSE,
+                       q, r,
+                       qbuf, rbuf,
+                       lsa_io_q_close,
+                       lsa_io_r_close,
+                       NT_STATUS_UNSUCCESSFUL );
 
        /* Return output parameters */
 
@@ -230,19 +160,9 @@ NTSTATUS rpccli_lsa_close(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                *pol = r.pol;
        }
 
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
        return result;
 }
 
-NTSTATUS cli_lsa_close(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
-                       POLICY_HND *pol)
-{
-       return rpccli_lsa_close(&cli->pipes[PI_LSARPC], mem_ctx, pol);
-}
-
 /** Lookup a list of sids */
 
 NTSTATUS rpccli_lsa_lookup_sids(struct rpc_pipe_client *cli,
@@ -256,46 +176,32 @@ NTSTATUS rpccli_lsa_lookup_sids(struct rpc_pipe_client *cli,
        LSA_R_LOOKUP_SIDS r;
        DOM_R_REF ref;
        LSA_TRANS_NAME_ENUM t_names;
-       NTSTATUS result;
+       NTSTATUS result = NT_STATUS_OK;
        int i;
 
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
-       /* Marshall data and send request */
-
        init_q_lookup_sids(mem_ctx, &q, pol, num_sids, sids, 1);
 
-       if (!lsa_io_q_lookup_sids("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req_int(cli, LSA_LOOKUPSIDS, &qbuf, &rbuf)) {
-               result = NT_STATUS_UNSUCCESSFUL;
-               goto done;
-       }
-
-       /* Unmarshall response */
-
        ZERO_STRUCT(ref);
        ZERO_STRUCT(t_names);
 
        r.dom_ref = &ref;
        r.names = &t_names;
 
-       if (!lsa_io_r_lookup_sids("", &r, &rbuf, 0)) {
-               result = NT_STATUS_UNSUCCESSFUL;
-               goto done;
-       }
-
-       result = r.status;
+       CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_LOOKUPSIDS,
+                       q, r,
+                       qbuf, rbuf,
+                       lsa_io_q_lookup_sids,
+                       lsa_io_r_lookup_sids,
+                       NT_STATUS_UNSUCCESSFUL );
 
-       if (!NT_STATUS_IS_OK(result) &&
-           NT_STATUS_V(result) != NT_STATUS_V(STATUS_SOME_UNMAPPED)) {
+       if (!NT_STATUS_IS_OK(r.status) &&
+           NT_STATUS_V(r.status) != NT_STATUS_V(STATUS_SOME_UNMAPPED)) {
          
                /* An actual error occured */
+               result = r.status;
 
                goto done;
        }
@@ -356,22 +262,10 @@ NTSTATUS rpccli_lsa_lookup_sids(struct rpc_pipe_client *cli,
        }
 
  done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
 
        return result;
 }
 
-NTSTATUS cli_lsa_lookup_sids(struct cli_state *cli, TALLOC_CTX *mem_ctx,
-                             POLICY_HND *pol, int num_sids,
-                            const DOM_SID *sids, 
-                             char ***domains, char ***names, uint32 **types)
-{
-       return rpccli_lsa_lookup_sids(&cli->pipes[PI_LSARPC], mem_ctx,
-                                     pol, num_sids, sids,
-                                     domains, names, types);
-}
-
 /** Lookup a list of names */
 
 NTSTATUS rpccli_lsa_lookup_names(struct rpc_pipe_client *cli,
@@ -390,30 +284,17 @@ NTSTATUS rpccli_lsa_lookup_names(struct rpc_pipe_client *cli,
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
-       /* Marshall data and send request */
-
-       init_q_lookup_names(mem_ctx, &q, pol, num_names, names);
-
-       if (!lsa_io_q_lookup_names("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req_int(cli, LSA_LOOKUPNAMES, &qbuf, &rbuf)) {
-               result = NT_STATUS_UNSUCCESSFUL;
-               goto done;
-       }
-       
-       /* Unmarshall response */
-
        ZERO_STRUCT(ref);
        r.dom_ref = &ref;
 
-       if (!lsa_io_r_lookup_names("", &r, &rbuf, 0)) {
-               result = NT_STATUS_UNSUCCESSFUL;
-               goto done;
-       }
+       init_q_lookup_names(mem_ctx, &q, pol, num_names, names);
+
+       CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_LOOKUPNAMES,
+                       q, r,
+                       qbuf, rbuf,
+                       lsa_io_q_lookup_names,
+                       lsa_io_r_lookup_names,
+                       NT_STATUS_UNSUCCESSFUL);
 
        result = r.status;
 
@@ -468,21 +349,10 @@ NTSTATUS rpccli_lsa_lookup_names(struct rpc_pipe_client *cli,
        }
 
  done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
 
        return result;
 }
 
-NTSTATUS cli_lsa_lookup_names(struct cli_state *cli, TALLOC_CTX *mem_ctx,
-                              POLICY_HND *pol, int num_names, 
-                             const char **names, DOM_SID **sids, 
-                             uint32 **types)
-{
-       return rpccli_lsa_lookup_names(&cli->pipes[PI_LSARPC], mem_ctx,
-                                      pol, num_names, names, sids, types);
-}
-
 /** Query info policy
  *
  *  @param domain_sid - returned remote server's domain sid */
@@ -497,32 +367,17 @@ NTSTATUS rpccli_lsa_query_info_policy(struct rpc_pipe_client *cli,
        LSA_R_QUERY_INFO r;
        NTSTATUS result;
 
-       SMB_ASSERT(cli->pipe_idx == PI_LSARPC);
-
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
-       /* Marshall data and send request */
-
        init_q_query(&q, pol, info_class);
 
-       if (!lsa_io_q_query("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req_int(cli, LSA_QUERYINFOPOLICY, &qbuf, &rbuf)) {
-               result = NT_STATUS_UNSUCCESSFUL;
-               goto done;
-       }
-
-       /* Unmarshall response */
-
-       if (!lsa_io_r_query("", &r, &rbuf, 0)) {
-               result = NT_STATUS_UNSUCCESSFUL;
-               goto done;
-       }
+       CLI_DO_RPC(cli, mem_ctx, PI_LSARPC, LSA_QUERYINFOPOLICY,
+               q, r,
+               qbuf, rbuf,
+               lsa_io_q_query,
+               lsa_io_r_query,
+               NT_STATUS_UNSUCCESSFUL);
 
        if (!NT_STATUS_IS_OK(result = r.status)) {
                goto done;
@@ -570,21 +425,10 @@ NTSTATUS rpccli_lsa_query_info_policy(struct rpc_pipe_client *cli,
        }
        
  done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
 
        return result;
 }
 
-NTSTATUS cli_lsa_query_info_policy(struct cli_state *cli, TALLOC_CTX *mem_ctx,
-                                   POLICY_HND *pol, uint16 info_class, 
-                                   char **domain_name, DOM_SID **domain_sid)
-{
-       return rpccli_lsa_query_info_policy(&cli->pipes[PI_LSARPC], mem_ctx,
-                                           pol, info_class, domain_name,
-                                           domain_sid);
-}
-
 /** Query info policy2
  *
  *  @param domain_name - returned remote server's domain name
@@ -612,27 +456,14 @@ NTSTATUS rpccli_lsa_query_info_policy2(struct rpc_pipe_client *cli,
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
-       /* Marshall data and send request */
-
        init_q_query2(&q, pol, info_class);
 
-       if (!lsa_io_q_query_info2("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req_int(cli, LSA_QUERYINFO2, &qbuf, &rbuf)) {
-               result = NT_STATUS_UNSUCCESSFUL;
-               goto done;
-       }
-
-       /* Unmarshall response */
-
-       if (!lsa_io_r_query_info2("", &r, &rbuf, 0)) {
-               result = NT_STATUS_UNSUCCESSFUL;
-               goto done;
-       }
+       CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_QUERYINFO2,
+               q, r,
+               qbuf, rbuf,
+               lsa_io_q_query_info2,
+               lsa_io_r_query_info2,
+               NT_STATUS_UNSUCCESSFUL);
 
        if (!NT_STATUS_IS_OK(result = r.status)) {
                goto done;
@@ -674,25 +505,10 @@ NTSTATUS rpccli_lsa_query_info_policy2(struct rpc_pipe_client *cli,
        }
        
  done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
 
        return result;
 }
 
-NTSTATUS cli_lsa_query_info_policy2(struct cli_state *cli, TALLOC_CTX *mem_ctx,
-                                   POLICY_HND *pol, uint16 info_class, 
-                                   char **domain_name, char **dns_name,
-                                   char **forest_name,
-                                   struct uuid **domain_guid,
-                                   DOM_SID **domain_sid)
-{
-       return rpccli_lsa_query_info_policy2(&cli->pipes[PI_LSARPC], mem_ctx,
-                                            pol, info_class, domain_name,
-                                            dns_name, forest_name,
-                                            domain_guid, domain_sid);
-}
-
 /**
  * Enumerate list of trusted domains
  *
@@ -720,7 +536,6 @@ NTSTATUS rpccli_lsa_enum_trust_dom(struct rpc_pipe_client *cli,
        int i;
        fstring tmp;
 
-
        ZERO_STRUCT(in);
        ZERO_STRUCT(out);
 
@@ -728,7 +543,7 @@ NTSTATUS rpccli_lsa_enum_trust_dom(struct rpc_pipe_client *cli,
        
         init_q_enum_trust_dom(&in, pol, *enum_ctx, 0x10000);
 
-       CLI_DO_RPC_EX( cli, mem_ctx, PI_LSARPC, LSA_ENUMTRUSTDOM, 
+       CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_ENUMTRUSTDOM, 
                    in, out, 
                    qbuf, rbuf,
                    lsa_io_q_enum_trust_dom,
@@ -779,19 +594,9 @@ NTSTATUS rpccli_lsa_enum_trust_dom(struct rpc_pipe_client *cli,
        return out.status;
 }
 
-NTSTATUS cli_lsa_enum_trust_dom(struct cli_state *cli, TALLOC_CTX *mem_ctx,
-                                POLICY_HND *pol, uint32 *enum_ctx, 
-                                uint32 *num_domains,
-                                char ***domain_names, DOM_SID **domain_sids)
-{
-       return rpccli_lsa_enum_trust_dom(&cli->pipes[PI_LSARPC], mem_ctx,
-                                        pol, enum_ctx, num_domains,
-                                        domain_names, domain_sids);
-}
-
 /** Enumerate privileges*/
 
-NTSTATUS cli_lsa_enum_privilege(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+NTSTATUS rpccli_lsa_enum_privilege(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                 POLICY_HND *pol, uint32 *enum_context, uint32 pref_max_length,
                                uint32 *count, char ***privs_name, uint32 **privs_high, uint32 **privs_low)
 {
@@ -804,27 +609,14 @@ NTSTATUS cli_lsa_enum_privilege(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
-       /* Marshall data and send request */
-
        init_q_enum_privs(&q, pol, *enum_context, pref_max_length);
 
-       if (!lsa_io_q_enum_privs("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, PI_LSARPC, LSA_ENUM_PRIVS, &qbuf, &rbuf)) {
-               result = NT_STATUS_UNSUCCESSFUL;
-               goto done;
-       }
-
-       /* Unmarshall response */
-
-       if (!lsa_io_r_enum_privs("", &r, &rbuf, 0)) {
-               result = NT_STATUS_UNSUCCESSFUL;
-               goto done;
-       }
+       CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_ENUM_PRIVS,
+               q, r,
+               qbuf, rbuf,
+               lsa_io_q_enum_privs,
+               lsa_io_r_enum_privs,
+               NT_STATUS_UNSUCCESSFUL);
 
        if (!NT_STATUS_IS_OK(result = r.status)) {
                goto done;
@@ -865,15 +657,13 @@ NTSTATUS cli_lsa_enum_privilege(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        }
 
  done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
 
        return result;
 }
 
 /** Get privilege name */
 
-NTSTATUS cli_lsa_get_dispname(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+NTSTATUS rpccli_lsa_get_dispname(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                              POLICY_HND *pol, const char *name, 
                              uint16 lang_id, uint16 lang_id_sys,
                              fstring description, uint16 *lang_id_desc)
@@ -886,27 +676,14 @@ NTSTATUS cli_lsa_get_dispname(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
-       /* Marshall data and send request */
-
        init_lsa_priv_get_dispname(&q, pol, name, lang_id, lang_id_sys);
 
-       if (!lsa_io_q_priv_get_dispname("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, PI_LSARPC, LSA_PRIV_GET_DISPNAME, &qbuf, &rbuf)) {
-               result = NT_STATUS_UNSUCCESSFUL;
-               goto done;
-       }
-
-       /* Unmarshall response */
-
-       if (!lsa_io_r_priv_get_dispname("", &r, &rbuf, 0)) {
-               result = NT_STATUS_UNSUCCESSFUL;
-               goto done;
-       }
+       CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_PRIV_GET_DISPNAME,
+               q, r,
+               qbuf, rbuf,
+               lsa_io_q_priv_get_dispname,
+               lsa_io_r_priv_get_dispname,
+               NT_STATUS_UNSUCCESSFUL);
 
        if (!NT_STATUS_IS_OK(result = r.status)) {
                goto done;
@@ -918,15 +695,13 @@ NTSTATUS cli_lsa_get_dispname(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        *lang_id_desc = r.lang_id;
 
  done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
 
        return result;
 }
 
 /** Enumerate list of SIDs  */
 
-NTSTATUS cli_lsa_enum_sids(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+NTSTATUS rpccli_lsa_enum_sids(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                 POLICY_HND *pol, uint32 *enum_ctx, uint32 pref_max_length, 
                                 uint32 *num_sids, DOM_SID **sids)
 {
@@ -939,27 +714,14 @@ NTSTATUS cli_lsa_enum_sids(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
-       /* Marshall data and send request */
-
         init_lsa_q_enum_accounts(&q, pol, *enum_ctx, pref_max_length);
 
-       if (!lsa_io_q_enum_accounts("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, PI_LSARPC, LSA_ENUM_ACCOUNTS, &qbuf, &rbuf)) {
-               result = NT_STATUS_UNSUCCESSFUL;
-               goto done;
-       }
-
-       /* Unmarshall response */
-
-       if (!lsa_io_r_enum_accounts("", &r, &rbuf, 0)) {
-               result = NT_STATUS_UNSUCCESSFUL;
-               goto done;
-       }
+       CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_ENUM_ACCOUNTS,
+               q, r,
+               qbuf, rbuf,
+               lsa_io_q_enum_accounts,
+               lsa_io_r_enum_accounts,
+               NT_STATUS_UNSUCCESSFUL);
 
        result = r.status;
 
@@ -989,8 +751,6 @@ NTSTATUS cli_lsa_enum_sids(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        *enum_ctx = r.enum_context;
 
  done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
 
        return result;
 }
@@ -1004,7 +764,7 @@ NTSTATUS cli_lsa_enum_sids(struct cli_state *cli, TALLOC_CTX *mem_ctx,
  *
  * */
 
-NTSTATUS cli_lsa_create_account(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+NTSTATUS rpccli_lsa_create_account(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                              POLICY_HND *dom_pol, DOM_SID *sid, uint32 desired_access, 
                             POLICY_HND *user_pol)
 {
@@ -1016,29 +776,16 @@ NTSTATUS cli_lsa_create_account(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        /* Initialise input parameters */
 
        init_lsa_q_create_account(&q, dom_pol, sid, desired_access);
 
-       /* Marshall data and send request */
-
-       if (!lsa_io_q_create_account("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, PI_LSARPC, LSA_CREATEACCOUNT, &qbuf, &rbuf)) {
-               result = NT_STATUS_UNSUCCESSFUL;
-               goto done;
-       }
-
-       /* Unmarshall response */
-
-       if (!lsa_io_r_create_account("", &r, &rbuf, 0)) {
-               result = NT_STATUS_UNSUCCESSFUL;
-               goto done;
-       }
+       CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_CREATEACCOUNT,
+               q, r,
+               qbuf, rbuf,
+               lsa_io_q_create_account,
+               lsa_io_r_create_account,
+               NT_STATUS_UNSUCCESSFUL);
 
        /* Return output parameters */
 
@@ -1046,10 +793,6 @@ NTSTATUS cli_lsa_create_account(struct cli_state *cli, TALLOC_CTX *mem_ctx,
                *user_pol = r.pol;
        }
 
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
        return result;
 }
 
@@ -1057,7 +800,7 @@ NTSTATUS cli_lsa_create_account(struct cli_state *cli, TALLOC_CTX *mem_ctx,
  *
  * @param cli Handle on an initialised SMB connection */
 
-NTSTATUS cli_lsa_open_account(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+NTSTATUS rpccli_lsa_open_account(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                              POLICY_HND *dom_pol, DOM_SID *sid, uint32 des_access, 
                             POLICY_HND *user_pol)
 {
@@ -1069,29 +812,16 @@ NTSTATUS cli_lsa_open_account(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        /* Initialise input parameters */
 
        init_lsa_q_open_account(&q, dom_pol, sid, des_access);
 
-       /* Marshall data and send request */
-
-       if (!lsa_io_q_open_account("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, PI_LSARPC, LSA_OPENACCOUNT, &qbuf, &rbuf)) {
-               result = NT_STATUS_UNSUCCESSFUL;
-               goto done;
-       }
-
-       /* Unmarshall response */
-
-       if (!lsa_io_r_open_account("", &r, &rbuf, 0)) {
-               result = NT_STATUS_UNSUCCESSFUL;
-               goto done;
-       }
+       CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_OPENACCOUNT,
+               q, r,
+               qbuf, rbuf,
+               lsa_io_q_open_account,
+               lsa_io_r_open_account,
+               NT_STATUS_UNSUCCESSFUL);
 
        /* Return output parameters */
 
@@ -1099,10 +829,6 @@ NTSTATUS cli_lsa_open_account(struct cli_state *cli, TALLOC_CTX *mem_ctx,
                *user_pol = r.pol;
        }
 
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
        return result;
 }
 
@@ -1110,7 +836,7 @@ NTSTATUS cli_lsa_open_account(struct cli_state *cli, TALLOC_CTX *mem_ctx,
  *
  * @param cli Handle on an initialised SMB connection */
 
-NTSTATUS cli_lsa_enum_privsaccount(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+NTSTATUS rpccli_lsa_enum_privsaccount(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                              POLICY_HND *pol, uint32 *count, LUID_ATTR **set)
 {
        prs_struct qbuf, rbuf;
@@ -1122,29 +848,16 @@ NTSTATUS cli_lsa_enum_privsaccount(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        /* Initialise input parameters */
 
        init_lsa_q_enum_privsaccount(&q, pol);
 
-       /* Marshall data and send request */
-
-       if (!lsa_io_q_enum_privsaccount("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, PI_LSARPC, LSA_ENUMPRIVSACCOUNT, &qbuf, &rbuf)) {
-               result = NT_STATUS_UNSUCCESSFUL;
-               goto done;
-       }
-
-       /* Unmarshall response */
-
-       if (!lsa_io_r_enum_privsaccount("", &r, &rbuf, 0)) {
-               result = NT_STATUS_UNSUCCESSFUL;
-               goto done;
-       }
+       CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_ENUMPRIVSACCOUNT,
+               q, r,
+               qbuf, rbuf,
+               lsa_io_q_enum_privsaccount,
+               lsa_io_r_enum_privsaccount,
+               NT_STATUS_UNSUCCESSFUL);
 
        /* Return output parameters */
 
@@ -1169,15 +882,13 @@ NTSTATUS cli_lsa_enum_privsaccount(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 
        *count=r.count;
  done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
 
        return result;
 }
 
 /** Get a privilege value given its name */
 
-NTSTATUS cli_lsa_lookup_priv_value(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+NTSTATUS rpccli_lsa_lookup_priv_value(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                 POLICY_HND *pol, const char *name, LUID *luid)
 {
        prs_struct qbuf, rbuf;
@@ -1188,27 +899,16 @@ NTSTATUS cli_lsa_lookup_priv_value(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        /* Marshall data and send request */
 
        init_lsa_q_lookup_priv_value(&q, pol, name);
 
-       if (!lsa_io_q_lookup_priv_value("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, PI_LSARPC, LSA_LOOKUPPRIVVALUE, &qbuf, &rbuf)) {
-               result = NT_STATUS_UNSUCCESSFUL;
-               goto done;
-       }
-
-       /* Unmarshall response */
-
-       if (!lsa_io_r_lookup_priv_value("", &r, &rbuf, 0)) {
-               result = NT_STATUS_UNSUCCESSFUL;
-               goto done;
-       }
+       CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_LOOKUPPRIVVALUE,
+               q, r,
+               qbuf, rbuf,
+               lsa_io_q_lookup_priv_value,
+               lsa_io_r_lookup_priv_value,
+               NT_STATUS_UNSUCCESSFUL);
 
        if (!NT_STATUS_IS_OK(result = r.status)) {
                goto done;
@@ -1220,15 +920,13 @@ NTSTATUS cli_lsa_lookup_priv_value(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        (*luid).high=r.luid.high;
 
  done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
 
        return result;
 }
 
 /** Query LSA security object */
 
-NTSTATUS cli_lsa_query_secobj(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+NTSTATUS rpccli_lsa_query_secobj(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                              POLICY_HND *pol, uint32 sec_info, 
                              SEC_DESC_BUF **psdb)
 {
@@ -1240,27 +938,16 @@ NTSTATUS cli_lsa_query_secobj(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        /* Marshall data and send request */
 
        init_q_query_sec_obj(&q, pol, sec_info);
 
-       if (!lsa_io_q_query_sec_obj("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, PI_LSARPC, LSA_QUERYSECOBJ, &qbuf, &rbuf)) {
-               result = NT_STATUS_UNSUCCESSFUL;
-               goto done;
-       }
-
-       /* Unmarshall response */
-
-       if (!lsa_io_r_query_sec_obj("", &r, &rbuf, 0)) {
-               result = NT_STATUS_UNSUCCESSFUL;
-               goto done;
-       }
+       CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_QUERYSECOBJ,
+               q, r,
+               qbuf, rbuf,
+               lsa_io_q_query_sec_obj,
+               lsa_io_r_query_sec_obj,
+               NT_STATUS_UNSUCCESSFUL);
 
        if (!NT_STATUS_IS_OK(result = r.status)) {
                goto done;
@@ -1272,8 +959,6 @@ NTSTATUS cli_lsa_query_secobj(struct cli_state *cli, TALLOC_CTX *mem_ctx,
                *psdb = r.buf;
 
  done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
 
        return result;
 }
@@ -1283,7 +968,7 @@ NTSTATUS cli_lsa_query_secobj(struct cli_state *cli, TALLOC_CTX *mem_ctx,
    takes a SID directly, avoiding the open_account call.
 */
 
-NTSTATUS cli_lsa_enum_account_rights(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+NTSTATUS rpccli_lsa_enum_account_rights(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                     POLICY_HND *pol, DOM_SID *sid,
                                     uint32 *count, char ***priv_names)
 {
@@ -1298,24 +983,15 @@ NTSTATUS cli_lsa_enum_account_rights(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        /* Marshall data and send request */
        init_q_enum_acct_rights(&q, pol, 2, sid);
 
-       if (!lsa_io_q_enum_acct_rights("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, PI_LSARPC, LSA_ENUMACCTRIGHTS, &qbuf, &rbuf)) {
-               result = NT_STATUS_UNSUCCESSFUL;
-               goto done;
-       }
-
-       if (!lsa_io_r_enum_acct_rights("", &r, &rbuf, 0)) {
-               result = NT_STATUS_UNSUCCESSFUL;
-               goto done;
-       }
+       CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_ENUMACCTRIGHTS,
+               q, r,
+               qbuf, rbuf,
+               lsa_io_q_enum_acct_rights,
+               lsa_io_r_enum_acct_rights,
+               NT_STATUS_UNSUCCESSFUL);
 
        if (!NT_STATUS_IS_OK(result = r.status)) {
                goto done;
@@ -1353,10 +1029,9 @@ done:
 
 /* add account rights to an account. */
 
-NTSTATUS cli_lsa_add_account_rights(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+NTSTATUS rpccli_lsa_add_account_rights(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                    POLICY_HND *pol, DOM_SID sid,
-                                   
-uint32 count, const char **privs_name)
+                                       uint32 count, const char **privs_name)
 {
        prs_struct qbuf, rbuf;
        LSA_Q_ADD_ACCT_RIGHTS q;
@@ -1364,26 +1039,17 @@ uint32 count, const char **privs_name)
        NTSTATUS result;
 
        ZERO_STRUCT(q);
-
-       /* Initialise parse structures */
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
+       ZERO_STRUCT(r);
 
        /* Marshall data and send request */
        init_q_add_acct_rights(&q, pol, &sid, count, privs_name);
 
-       if (!lsa_io_q_add_acct_rights("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, PI_LSARPC, LSA_ADDACCTRIGHTS, &qbuf, &rbuf)) {
-               result = NT_STATUS_UNSUCCESSFUL;
-               goto done;
-       }
-
-       /* Unmarshall response */
-
-       if (!lsa_io_r_add_acct_rights("", &r, &rbuf, 0)) {
-               result = NT_STATUS_UNSUCCESSFUL;
-               goto done;
-       }
+       CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_ADDACCTRIGHTS,
+               q, r,
+               qbuf, rbuf,
+               lsa_io_q_add_acct_rights,
+               lsa_io_r_add_acct_rights,
+               NT_STATUS_UNSUCCESSFUL);
 
        if (!NT_STATUS_IS_OK(result = r.status)) {
                goto done;
@@ -1396,7 +1062,7 @@ done:
 
 /* remove account rights for an account. */
 
-NTSTATUS cli_lsa_remove_account_rights(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+NTSTATUS rpccli_lsa_remove_account_rights(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                       POLICY_HND *pol, DOM_SID sid, BOOL removeall,
                                       uint32 count, const char **privs_name)
 {
@@ -1406,26 +1072,17 @@ NTSTATUS cli_lsa_remove_account_rights(struct cli_state *cli, TALLOC_CTX *mem_ct
        NTSTATUS result;
 
        ZERO_STRUCT(q);
-
-       /* Initialise parse structures */
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
+       ZERO_STRUCT(r);
 
        /* Marshall data and send request */
        init_q_remove_acct_rights(&q, pol, &sid, removeall?1:0, count, privs_name);
 
-       if (!lsa_io_q_remove_acct_rights("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, PI_LSARPC, LSA_REMOVEACCTRIGHTS, &qbuf, &rbuf)) {
-               result = NT_STATUS_UNSUCCESSFUL;
-               goto done;
-       }
-
-       /* Unmarshall response */
-
-       if (!lsa_io_r_remove_acct_rights("", &r, &rbuf, 0)) {
-               result = NT_STATUS_UNSUCCESSFUL;
-               goto done;
-       }
+       CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_REMOVEACCTRIGHTS,
+               q, r,
+               qbuf, rbuf,
+               lsa_io_q_remove_acct_rights,
+               lsa_io_r_remove_acct_rights,
+               NT_STATUS_UNSUCCESSFUL);
 
        if (!NT_STATUS_IS_OK(result = r.status)) {
                goto done;
@@ -1539,7 +1196,7 @@ Error was : %s.\n", remote_machine, cli_errstr(&cli) ));
 
 #endif
 
-NTSTATUS cli_lsa_open_trusted_domain(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+NTSTATUS rpccli_lsa_open_trusted_domain(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                     POLICY_HND *pol, DOM_SID *dom_sid, uint32 access_mask,
                                     POLICY_HND *trustdom_pol)
 {
@@ -1551,29 +1208,18 @@ NTSTATUS cli_lsa_open_trusted_domain(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        /* Initialise input parameters */
 
        init_lsa_q_open_trusted_domain(&q, pol, dom_sid, access_mask);
 
        /* Marshall data and send request */
 
-       if (!lsa_io_q_open_trusted_domain("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, PI_LSARPC, LSA_OPENTRUSTDOM, &qbuf, &rbuf)) {
-               result = NT_STATUS_UNSUCCESSFUL;
-               goto done;
-       }
-
-       /* Unmarshall response */
-
-       if (!lsa_io_r_open_trusted_domain("", &r, &rbuf, 0)) {
-               result = NT_STATUS_UNSUCCESSFUL;
-               goto done;
-       }
+       CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_OPENTRUSTDOM,
+               q, r,
+               qbuf, rbuf,
+               lsa_io_q_open_trusted_domain,
+               lsa_io_r_open_trusted_domain,
+               NT_STATUS_UNSUCCESSFUL);
 
        /* Return output parameters */
        
@@ -1581,14 +1227,10 @@ NTSTATUS cli_lsa_open_trusted_domain(struct cli_state *cli, TALLOC_CTX *mem_ctx,
                *trustdom_pol = r.handle;
        }
 
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
        return result;
 }
 
-NTSTATUS cli_lsa_query_trusted_domain_info(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+NTSTATUS rpccli_lsa_query_trusted_domain_info(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                           POLICY_HND *pol, 
                                           uint16 info_class, DOM_SID *dom_sid, 
                                           LSA_TRUSTED_DOMAIN_INFO **info)
@@ -1601,27 +1243,16 @@ NTSTATUS cli_lsa_query_trusted_domain_info(struct cli_state *cli, TALLOC_CTX *me
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        /* Marshall data and send request */
 
        init_q_query_trusted_domain_info(&q, pol, info_class); 
 
-       if (!lsa_io_q_query_trusted_domain_info("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, PI_LSARPC, LSA_QUERYTRUSTDOMINFO, &qbuf, &rbuf)) {
-               result = NT_STATUS_UNSUCCESSFUL;
-               goto done;
-       }
-
-       /* Unmarshall response */
-
-       if (!lsa_io_r_query_trusted_domain_info("", &r, &rbuf, 0)) {
-               result = NT_STATUS_UNSUCCESSFUL;
-               goto done;
-       }
+       CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_QUERYTRUSTDOMINFO,
+               q, r,
+               qbuf, rbuf,
+               lsa_io_q_query_trusted_domain_info,
+               lsa_io_r_query_trusted_domain_info,
+               NT_STATUS_UNSUCCESSFUL);
 
        if (!NT_STATUS_IS_OK(result = r.status)) {
                goto done;
@@ -1630,14 +1261,11 @@ NTSTATUS cli_lsa_query_trusted_domain_info(struct cli_state *cli, TALLOC_CTX *me
        *info = r.info;
                
 done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
        return result;
 }
 
 
-NTSTATUS cli_lsa_query_trusted_domain_info_by_sid(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+NTSTATUS rpccli_lsa_query_trusted_domain_info_by_sid(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                                  POLICY_HND *pol, 
                                                  uint16 info_class, DOM_SID *dom_sid, 
                                                  LSA_TRUSTED_DOMAIN_INFO **info)
@@ -1650,27 +1278,16 @@ NTSTATUS cli_lsa_query_trusted_domain_info_by_sid(struct cli_state *cli, TALLOC_
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        /* Marshall data and send request */
 
        init_q_query_trusted_domain_info_by_sid(&q, pol, info_class, dom_sid); 
 
-       if (!lsa_io_q_query_trusted_domain_info_by_sid("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, PI_LSARPC, LSA_QUERYTRUSTDOMINFOBYSID, &qbuf, &rbuf)) {
-               result = NT_STATUS_UNSUCCESSFUL;
-               goto done;
-       }
-
-       /* Unmarshall response */
-
-       if (!lsa_io_r_query_trusted_domain_info("", &r, &rbuf, 0)) {
-               result = NT_STATUS_UNSUCCESSFUL;
-               goto done;
-       }
+       CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_QUERYTRUSTDOMINFOBYSID,
+               q, r,
+               qbuf, rbuf,
+               lsa_io_q_query_trusted_domain_info_by_sid,
+               lsa_io_r_query_trusted_domain_info,
+               NT_STATUS_UNSUCCESSFUL);
 
        if (!NT_STATUS_IS_OK(result = r.status)) {
                goto done;
@@ -1679,13 +1296,11 @@ NTSTATUS cli_lsa_query_trusted_domain_info_by_sid(struct cli_state *cli, TALLOC_
        *info = r.info;
 
 done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
 
        return result;
 }
 
-NTSTATUS cli_lsa_query_trusted_domain_info_by_name(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+NTSTATUS rpccli_lsa_query_trusted_domain_info_by_name(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                                   POLICY_HND *pol, 
                                                   uint16 info_class, const char *domain_name, 
                                                   LSA_TRUSTED_DOMAIN_INFO **info)
@@ -1698,27 +1313,16 @@ NTSTATUS cli_lsa_query_trusted_domain_info_by_name(struct cli_state *cli, TALLOC
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        /* Marshall data and send request */
 
        init_q_query_trusted_domain_info_by_name(&q, pol, info_class, domain_name); 
 
-       if (!lsa_io_q_query_trusted_domain_info_by_name("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, PI_LSARPC, LSA_QUERYTRUSTDOMINFOBYNAME, &qbuf, &rbuf)) {
-               result = NT_STATUS_UNSUCCESSFUL;
-               goto done;
-       }
-
-       /* Unmarshall response */
-
-       if (!lsa_io_r_query_trusted_domain_info("", &r, &rbuf, 0)) {
-               result = NT_STATUS_UNSUCCESSFUL;
-               goto done;
-       }
+       CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_QUERYTRUSTDOMINFOBYNAME,
+               q, r,
+               qbuf, rbuf,
+               lsa_io_q_query_trusted_domain_info_by_name,
+               lsa_io_r_query_trusted_domain_info,
+               NT_STATUS_UNSUCCESSFUL);
 
        if (!NT_STATUS_IS_OK(result = r.status)) {
                goto done;
@@ -1727,11 +1331,6 @@ NTSTATUS cli_lsa_query_trusted_domain_info_by_name(struct cli_state *cli, TALLOC
        *info = r.info;
 
 done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
        
        return result;
 }
-
-/** @} **/
-
index fad60dbc20d9ce6c74e7830e415387b2b66cbb02..88b6c792ebfb7c393b76673ee0d2f70d7060da7b 100644 (file)
@@ -2,12 +2,9 @@
    Unix SMB/CIFS implementation.
    NT Domain Authentication SMB / MSRPC client
    Copyright (C) Andrew Tridgell 1992-2000
-   Copyright (C) Luke Kenneth Casson Leighton 1996-2000
-   Copyright (C) Tim Potter 2001
-   Copyright (C) Paul Ashton                       1997.
    Copyright (C) Jeremy Allison                    1998.
-   Copyright (C) Andrew Bartlett                   2001.
-   
+   Largely re-written by Jeremy Allison (C)       2005.
+
    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
 #include "includes.h"
 
 /* LSA Request Challenge. Sends our challenge to server, then gets
-   server response. These are used to generate the credentials. */
-
-NTSTATUS cli_net_req_chal(struct cli_state *cli, DOM_CHAL *clnt_chal, 
-                         DOM_CHAL *srv_chal)
-{
-        prs_struct qbuf, rbuf;
-        NET_Q_REQ_CHAL q;
-        NET_R_REQ_CHAL r;
-        NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
-
-        prs_init(&qbuf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL);
-        prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL);
-        
-        /* create and send a MSRPC command with api NET_REQCHAL */
-
-        DEBUG(4,("cli_net_req_chal: LSA Request Challenge from %s to %s: %s\n",
-                 global_myname(), cli->desthost, credstr(clnt_chal->data)));
-        
-        /* store the parameters */
-        init_q_req_chal(&q, cli->srv_name_slash, global_myname(), clnt_chal);
-        
-        /* Marshall data and send request */
-
-        if (!net_io_q_req_chal("", &q,  &qbuf, 0) ||
-            !rpc_api_pipe_req(cli, PI_NETLOGON, NET_REQCHAL, &qbuf, &rbuf)) {
-                goto done;
-        }
-
-        /* Unmarhall response */
-
-        if (!net_io_r_req_chal("", &r, &rbuf, 0)) {
-                goto done;
-        }
-
-        result = r.status;
-
-        /* Return result */
-
-        if (NT_STATUS_IS_OK(result)) {
-                memcpy(srv_chal, r.srv_chal.data, sizeof(srv_chal->data));
-        }
-        
- done:
-        prs_mem_free(&qbuf);
-        prs_mem_free(&rbuf);
-        
-        return result;
-}
+   server response. These are used to generate the credentials.
+ The sent and received challenges are stored in the netlog pipe
+ private data. Only call this via rpccli_netlogon_setup_creds(). JRA.
+*/
 
-NTSTATUS rpccli_net_req_chal(struct rpc_pipe_client *cli,
-                            const char *server_name,
-                            const char *computer_name,
-                            DOM_CHAL *clnt_chal, DOM_CHAL *srv_chal)
+static NTSTATUS rpccli_net_req_chal(struct rpc_pipe_client *cli,
+                               TALLOC_CTX *mem_ctx,
+                               const char *server_name,
+                               const char *clnt_name,
+                               const DOM_CHAL *clnt_chal_in,
+                               DOM_CHAL *srv_chal_out)
 {
-        prs_struct qbuf, rbuf;
-        NET_Q_REQ_CHAL q;
-        NET_R_REQ_CHAL r;
-        NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+       prs_struct qbuf, rbuf;
+       NET_Q_REQ_CHAL q;
+       NET_R_REQ_CHAL r;
+       NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
 
-        prs_init(&qbuf, MAX_PDU_FRAG_LEN, cli->cli->mem_ctx, MARSHALL);
-        prs_init(&rbuf, 0, cli->cli->mem_ctx, UNMARSHALL);
-        
-        /* create and send a MSRPC command with api NET_REQCHAL */
+       /* create and send a MSRPC command with api NET_REQCHAL */
 
-        DEBUG(4,("cli_net_req_chal: LSA Request Challenge from %s to %s\n",
-                 computer_name, server_name));
-        
-        /* store the parameters */
-        init_q_req_chal(&q, server_name, computer_name, clnt_chal);
+       DEBUG(4,("cli_net_req_chal: LSA Request Challenge from %s to %s\n",
+               clnt_name, server_name));
         
-        /* Marshall data and send request */
+       /* store the parameters */
+       init_q_req_chal(&q, server_name, clnt_name, clnt_chal_in);
 
-        if (!net_io_q_req_chal("", &q,  &qbuf, 0) ||
-            !rpc_api_pipe_req_int(cli, NET_REQCHAL, &qbuf, &rbuf)) {
-                goto done;
-        }
+       /* Marshall data and send request */
+       CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_REQCHAL,
+               q, r,
+               qbuf, rbuf,
+               net_io_q_req_chal,
+               net_io_r_req_chal,
+               NT_STATUS_UNSUCCESSFUL);
 
-        /* Unmarhall response */
+       result = r.status;
 
-        if (!net_io_r_req_chal("", &r, &rbuf, 0)) {
-                goto done;
-        }
+       /* Return result */
 
-        result = r.status;
-
-        /* Return result */
+       if (NT_STATUS_IS_OK(result)) {
+               /* Store the returned server challenge. */
+               *srv_chal_out = r.srv_chal;
+       }
 
-        if (NT_STATUS_IS_OK(result)) {
-                memcpy(srv_chal, r.srv_chal.data, sizeof(srv_chal->data));
-        }
-        
- done:
-        prs_mem_free(&qbuf);
-        prs_mem_free(&rbuf);
-        
-        return result;
+       return result;
 }
 
+#if 0
 /****************************************************************************
 LSA Authenticate 2
 
@@ -132,7 +77,7 @@ Ensure that the server credential returned matches the session key
 encrypt of the server challenge originally received. JRA.
 ****************************************************************************/
 
-NTSTATUS cli_net_auth2(struct cli_state *cli, 
+  NTSTATUS rpccli_net_auth2(struct rpc_pipe_client *cli, 
                       uint16 sec_chan, 
                       uint32 *neg_flags, DOM_CHAL *srv_chal)
 {
@@ -142,9 +87,6 @@ NTSTATUS cli_net_auth2(struct cli_state *cli,
         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
        fstring machine_acct;
 
-        prs_init(&qbuf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL);
-        prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL);
-
        if ( sec_chan == SEC_CHAN_DOMAIN )
                fstr_sprintf( machine_acct, "%s$", lp_workgroup() );
        else
@@ -164,16 +106,12 @@ NTSTATUS cli_net_auth2(struct cli_state *cli,
 
         /* turn parameters into data stream */
 
-        if (!net_io_q_auth_2("", &q,  &qbuf, 0) ||
-            !rpc_api_pipe_req(cli, PI_NETLOGON, NET_AUTH2, &qbuf, &rbuf)) {
-                goto done;
-        }
-        
-        /* Unmarshall response */
-        
-        if (!net_io_r_auth_2("", &r, &rbuf, 0)) {
-                goto done;
-        }
+       CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_AUTH2,
+               q, r,
+               qbuf, rbuf,
+               net_io_q_auth_2,
+               net_io_r_auth_2,
+               NT_STATUS_UNSUCCESSFUL);
 
         result = r.status;
 
@@ -186,259 +124,257 @@ NTSTATUS cli_net_auth2(struct cli_state *cli,
                  */
 
                 zerotime.time = 0;
-                if (cred_assert( &r.srv_chal, cli->sess_key, srv_chal, 
-                                 zerotime) == 0) {
+                if (cred_assert( &r.srv_chal, cli->sess_key, srv_chal, zerotime) == 0) {
 
                         /*
                          * Server replied with bad credential. Fail.
                          */
                         DEBUG(0,("cli_net_auth2: server %s replied with bad credential (bad machine \
-password ?).\n", cli->desthost ));
-                        result = NT_STATUS_ACCESS_DENIED;
-                        goto done;
+password ?).\n", cli->cli->desthost ));
+                       return NT_STATUS_ACCESS_DENIED;
                 }
                *neg_flags = r.srv_flgs.neg_flags;
         }
 
- done:
-        prs_mem_free(&qbuf);
-        prs_mem_free(&rbuf);
-        
         return result;
 }
+#endif
+
+/****************************************************************************
+ LSA Authenticate 2
 
-NTSTATUS rpccli_net_auth2(struct rpc_pipe_client *cli,
-                         const char *server_name,
-                         const char *account_name,
-                         uint16 sec_chan_type,
-                         const char *computer_name,
-                         const DOM_CHAL *credentials,
-                         uint32 *neg_flags,
-                         DOM_CHAL *srv_chal)
+ Send the client credential, receive back a server credential.
+ The caller *must* ensure that the server credential returned matches the session key 
+ encrypt of the server challenge originally received. JRA.
+****************************************************************************/
+
+static NTSTATUS rpccli_net_auth2(struct rpc_pipe_client *cli,
+                       TALLOC_CTX *mem_ctx,
+                       const char *server_name,
+                       const char *account_name,
+                       uint16 sec_chan_type,
+                       const char *computer_name,
+                       uint32 *neg_flags_inout,
+                       const DOM_CHAL *clnt_chal_in,
+                       DOM_CHAL *srv_chal_out)
 {
         prs_struct qbuf, rbuf;
         NET_Q_AUTH_2 q;
         NET_R_AUTH_2 r;
         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
 
-        prs_init(&qbuf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL);
-        prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL);
-
         /* create and send a MSRPC command with api NET_AUTH2 */
 
         DEBUG(4,("cli_net_auth2: srv:%s acct:%s sc:%x mc: %s neg: %x\n",
                  server_name, account_name, sec_chan_type, computer_name,
-                 *neg_flags));
+                 *neg_flags_inout));
 
         /* store the parameters */
 
         init_q_auth_2(&q, server_name, account_name, sec_chan_type,
-                     computer_name, credentials, *neg_flags);
+                     computer_name, clnt_chal_in, *neg_flags_inout);
 
         /* turn parameters into data stream */
 
-        if (!net_io_q_auth_2("", &q,  &qbuf, 0) ||
-            !rpc_api_pipe_req_int(cli, NET_AUTH2, &qbuf, &rbuf)) {
-                goto done;
-        }
-        
-        /* Unmarshall response */
-        
-        if (!net_io_r_auth_2("", &r, &rbuf, 0)) {
-                goto done;
-        }
+       CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_AUTH2,
+               q, r,
+               qbuf, rbuf,
+               net_io_q_auth_2,
+               net_io_r_auth_2,
+               NT_STATUS_UNSUCCESSFUL);
 
         result = r.status;
 
         if (NT_STATUS_IS_OK(result)) {
-               *srv_chal = r.srv_chal;
-               *neg_flags = r.srv_flgs.neg_flags;
+               *srv_chal_out = r.srv_chal;
+               *neg_flags_inout = r.srv_flgs.neg_flags;
         }
 
- done:
-        prs_mem_free(&qbuf);
-        prs_mem_free(&rbuf);
-        
         return result;
 }
 
+#if 0  /* not currebntly used */
 /****************************************************************************
-LSA Authenticate 3
+ LSA Authenticate 3
 
-Send the client credential, receive back a server credential.
-Ensure that the server credential returned matches the session key 
-encrypt of the server challenge originally received. JRA.
+ Send the client credential, receive back a server credential.
+ The caller *must* ensure that the server credential returned matches the session key 
+ encrypt of the server challenge originally received. JRA.
 ****************************************************************************/
 
-NTSTATUS cli_net_auth3(struct cli_state *cli, 
-                      uint16 sec_chan, 
-                      uint32 *neg_flags, DOM_CHAL *srv_chal)
+static NTSTATUS rpccli_net_auth3(struct rpc_pipe_client *cli, 
+                       TALLOC_CTX *mem_ctx,
+                       const char *server_name,
+                       const char *account_name,
+                       uint16 sec_chan_type,
+                       const char *computer_name,
+                       uint32 *neg_flags_inout,
+                       const DOM_CHAL *clnt_chal_in,
+                       DOM_CHAL *srv_chal_out)
 {
         prs_struct qbuf, rbuf;
         NET_Q_AUTH_3 q;
         NET_R_AUTH_3 r;
         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
 
-        prs_init(&qbuf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL);
-        prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL);
-
         /* create and send a MSRPC command with api NET_AUTH2 */
 
         DEBUG(4,("cli_net_auth3: srv:%s acct:%s sc:%x mc: %s chal %s neg: %x\n",
-                 cli->srv_name_slash, cli->mach_acct, sec_chan, global_myname(),
-                 credstr(cli->clnt_cred.challenge.data), *neg_flags));
+               server_name, account_name, sec_chan_type, computer_name,
+               credstr(clnt_chal_in->data), *neg_flags_inout));
 
         /* store the parameters */
-        init_q_auth_3(&q, cli->srv_name_slash, cli->mach_acct, 
-                      sec_chan, global_myname(), &cli->clnt_cred.challenge, 
-                      *neg_flags);
+        init_q_auth_3(&q, server_name, account_name, sec_chan_type,
+                       computer_name, clnt_chal_in, *neg_flags_inout);
 
         /* turn parameters into data stream */
 
-        if (!net_io_q_auth_3("", &q,  &qbuf, 0) ||
-            !rpc_api_pipe_req(cli, PI_NETLOGON, NET_AUTH3, &qbuf, &rbuf)) {
-                goto done;
-        }
-        
-        /* Unmarshall response */
-        
-        if (!net_io_r_auth_3("", &r, &rbuf, 0)) {
-                goto done;
-        }
-
-        result = r.status;
+       CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_AUTH3,
+               q, r,
+               qbuf, rbuf,
+               net_io_q_auth_3,
+               net_io_r_auth_3,
+               NT_STATUS_UNSUCCESSFUL);
 
         if (NT_STATUS_IS_OK(result)) {
-                UTIME zerotime;
-                
-                /*
-                 * Check the returned value using the initial
-                 * server received challenge.
-                 */
-
-                zerotime.time = 0;
-                if (cred_assert( &r.srv_chal, cli->sess_key, srv_chal, 
-                                 zerotime) == 0) {
-
-                        /*
-                         * Server replied with bad credential. Fail.
-                         */
-                        DEBUG(0,("cli_net_auth3: server %s replied with bad credential (bad machine \
-password ?).\n", cli->desthost ));
-                        result = NT_STATUS_ACCESS_DENIED;
-                        goto done;
-                }
-               *neg_flags = r.srv_flgs.neg_flags;
+               *srv_chal_out = r.srv_chal;
+               *neg_flags_inout = r.srv_flgs.neg_flags;
         }
 
- done:
-        prs_mem_free(&qbuf);
-        prs_mem_free(&rbuf);
-        
         return result;
 }
+#endif         /* not currebntly used */
 
-/* Initialize domain session credentials */
+/****************************************************************************
+ Wrapper function that uses the auth and auth2 calls to set up a NETLOGON
+ credentials chain. Stores the credentials in the struct dcinfo in the
+ netlogon pipe struct.
+****************************************************************************/
 
-NTSTATUS cli_nt_setup_creds(struct cli_state *cli, 
-                           uint16 sec_chan,
-                           const unsigned char mach_pwd[16], uint32 *neg_flags, int level)
+NTSTATUS rpccli_netlogon_setup_creds(struct rpc_pipe_client *cli,
+                               const char *server_name,
+                               const char *domain,
+                               const char *machine_account,
+                               const char machine_pwd[16],
+                               uint32 sec_chan_type,
+                               uint32 *neg_flags_inout)
 {
-        DOM_CHAL clnt_chal;
-        DOM_CHAL srv_chal;
-        UTIME zerotime;
-        NTSTATUS result;
+       NTSTATUS result;
+       DOM_CHAL clnt_chal_send;
+       DOM_CHAL srv_chal_recv;
+       struct dcinfo *dc;
 
-        /******************* Request Challenge ********************/
+       SMB_ASSERT(cli->pipe_idx == PI_NETLOGON);
 
-        generate_random_buffer(clnt_chal.data, 8);
-       
-        /* send a client challenge; receive a server challenge */
-        result = cli_net_req_chal(cli, &clnt_chal, &srv_chal);
+       dc = cli->dc;
+       if (!dc) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
 
-        if (!NT_STATUS_IS_OK(result)) {
-                DEBUG(0,("cli_nt_setup_creds: request challenge failed\n"));
-                return result;
-        }
-        
-        /**************** Long-term Session key **************/
+       /* Ensure we don't reuse any of this state. */
+       ZERO_STRUCTP(dc);
+
+       /* Store the machine account password we're going to use. */
+       memcpy(dc->mach_pw, machine_pwd, 16);
 
-        /* calculate the session key */
-        cred_session_key(&clnt_chal, &srv_chal, mach_pwd, 
-                         cli->sess_key);
-        memset((char *)cli->sess_key+8, '\0', 8);
+       fstrcpy(dc->remote_machine, "\\\\");
+       fstrcat(dc->remote_machine, server_name);
 
-        /******************* Authenticate 2/3 ********************/
+       fstrcpy(dc->domain, domain);
 
-        /* calculate auth-2/3 credentials */
-        zerotime.time = 0;
-        cred_create(cli->sess_key, &clnt_chal, zerotime, &cli->clnt_cred.challenge);
+       fstr_sprintf( dc->mach_acct, "%s$", machine_account);
+
+       /* Create the client challenge. */
+       generate_random_buffer(clnt_chal_send.data, 8);
+
+       /* Get the server challenge. */
+       result = rpccli_net_req_chal(cli,
+                               cli->mem_ctx,
+                               dc->remote_machine,
+                               machine_account,
+                               &clnt_chal_send,
+                               &srv_chal_recv);
+
+       if (!NT_STATUS_IS_OK(result)) {
+               return result;
+       }
+
+       /* Calculate the session key and client credentials */
+       creds_client_init(dc,
+                       &clnt_chal_send,
+                       &srv_chal_recv,
+                       machine_pwd,
+                       &clnt_chal_send);
 
         /*  
-         * Send client auth-2/3 challenge.
-         * Receive an auth-2/3 challenge response and check it.
+         * Send client auth-2 challenge and receive server repy.
          */
-        switch (level) {
-               case 2:
-                       result = cli_net_auth2(cli, sec_chan, neg_flags, &srv_chal);
-                       break;
-               case 3:
-                       result = cli_net_auth3(cli, sec_chan, neg_flags, &srv_chal);
-                       break;
-               default:
-                       DEBUG(1,("cli_nt_setup_creds: unsupported auth level: %d\n", level));
-                       break;
+
+       result = rpccli_net_auth2(cli,
+                       cli->mem_ctx,
+                       dc->remote_machine,
+                       dc->mach_acct,
+                       sec_chan_type,
+                       machine_account,
+                       neg_flags_inout,
+                       &clnt_chal_send, /* input. */
+                       &srv_chal_recv); /* output */
+
+       if (!NT_STATUS_IS_OK(result)) {
+               return result;
        }
 
-       if (!NT_STATUS_IS_OK(result))
-                DEBUG(3,("cli_nt_setup_creds: auth%d challenge failed %s\n", level, nt_errstr(result)));
+       /*
+        * Check the returned value using the initial
+        * server received challenge.
+        */
 
-        return result;
+       if (!creds_client_check(dc, &srv_chal_recv)) {
+               /*
+                * Server replied with bad credential. Fail.
+                */
+               DEBUG(0,("rpccli_netlogon_setup_creds: server %s "
+                       "replied with bad credential\n",
+                       cli->cli->desthost ));
+               return NT_STATUS_ACCESS_DENIED;
+       }
+
+       DEBUG(5,("rpccli_netlogon_setup_creds: server %s credential "
+               "chain established.\n",
+               cli->cli->desthost ));
+
+       return NT_STATUS_OK;
 }
 
 /* Logon Control 2 */
 
-NTSTATUS cli_netlogon_logon_ctrl2(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+NTSTATUS rpccli_netlogon_logon_ctrl2(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                   uint32 query_level)
 {
        prs_struct qbuf, rbuf;
        NET_Q_LOGON_CTRL2 q;
        NET_R_LOGON_CTRL2 r;
        NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+       fstring server;
 
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        /* Initialise input parameters */
 
-       init_net_q_logon_ctrl2(&q, cli->srv_name_slash, query_level);
+       slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
+       init_net_q_logon_ctrl2(&q, server, query_level);
 
        /* Marshall data and send request */
 
-       if (!net_io_q_logon_ctrl2("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, PI_NETLOGON, NET_LOGON_CTRL2, &qbuf, &rbuf)) {
-               result = NT_STATUS_UNSUCCESSFUL;
-               goto done;
-       }
-
-       /* Unmarshall response */
-
-       if (!net_io_r_logon_ctrl2("", &r, &rbuf, 0)) {
-               result = NT_STATUS_UNSUCCESSFUL;
-               goto done;
-       }
+       CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_LOGON_CTRL2,
+               q, r,
+               qbuf, rbuf,
+               net_io_q_logon_ctrl2,
+               net_io_r_logon_ctrl2,
+               NT_STATUS_UNSUCCESSFUL);
 
        result = r.status;
-
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
        return result;
 }
 
@@ -456,72 +392,29 @@ NTSTATUS rpccli_netlogon_getdcname(struct rpc_pipe_client *cli,
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        /* Initialise input parameters */
 
        init_net_q_getdcname(&q, mydcname, domainname);
 
        /* Marshall data and send request */
 
-       if (!net_io_q_getdcname("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req_int(cli, NET_GETDCNAME, &qbuf, &rbuf)) {
-               result = NT_STATUS_UNSUCCESSFUL;
-               goto done;
-       }
-
-       /* Unmarshall response */
-
-       if (!net_io_r_getdcname("", &r, &rbuf, 0)) {
-               result = NT_STATUS_UNSUCCESSFUL;
-               goto done;
-       }
-
-       result = r.status;
+       CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_GETDCNAME,
+               q, r,
+               qbuf, rbuf,
+               net_io_q_getdcname,
+               net_io_r_getdcname,
+               NT_STATUS_UNSUCCESSFUL);
 
-       if (NT_STATUS_IS_OK(result))
+       if (NT_STATUS_IS_OK(result)) {
                rpcstr_pull_unistr2_fstring(newdcname, &r.uni_dcname);
-
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
+       }
 
        return result;
 }
 
-NTSTATUS cli_netlogon_getdcname(struct cli_state *cli, TALLOC_CTX *mem_ctx,
-                               const char *domainname, fstring dcname)
-{
-       return rpccli_netlogon_getdcname(&cli->pipes[PI_NETLOGON], mem_ctx,
-                                        cli->srv_name_slash, domainname,
-                                        dcname);
-}
-
-/****************************************************************************
-Generate the next creds to use.
-****************************************************************************/
-
-static void gen_next_creds( struct cli_state *cli, DOM_CRED *new_clnt_cred)
-{
-       /*
-        * Create the new client credentials.
-        */
-       
-       cli->clnt_cred.timestamp.time = time(NULL);
-       
-       memcpy(new_clnt_cred, &cli->clnt_cred, sizeof(*new_clnt_cred));
-
-       /* Calculate the new credentials. */
-       cred_create(cli->sess_key, &(cli->clnt_cred.challenge),
-                   new_clnt_cred->timestamp, &(new_clnt_cred->challenge));
-}
-
 /* Sam synchronisation */
 
-NTSTATUS cli_netlogon_sam_sync(struct cli_state *cli, TALLOC_CTX *mem_ctx, DOM_CRED *ret_creds,
+NTSTATUS rpccli_netlogon_sam_sync(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                uint32 database_id, uint32 next_rid, uint32 *num_deltas,
                                SAM_DELTA_HDR **hdr_deltas, 
                                SAM_DELTA_CTR **deltas)
@@ -531,36 +424,31 @@ NTSTATUS cli_netlogon_sam_sync(struct cli_state *cli, TALLOC_CTX *mem_ctx, DOM_C
        NET_R_SAM_SYNC r;
        NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
         DOM_CRED clnt_creds;
+        DOM_CRED ret_creds;
 
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
+       ZERO_STRUCT(ret_creds);
 
        /* Initialise input parameters */
 
-        gen_next_creds(cli, &clnt_creds);
+       creds_client_step(cli->dc, &clnt_creds);
 
-       init_net_q_sam_sync(&q, cli->srv_name_slash, cli->clnt_name_slash + 2,
-                            &clnt_creds, ret_creds, database_id, next_rid);
+       prs_set_session_key(&qbuf, cli->dc->sess_key);
+       prs_set_session_key(&rbuf, cli->dc->sess_key);
 
-       /* Marshall data and send request */
-
-       if (!net_io_q_sam_sync("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, PI_NETLOGON, NET_SAM_SYNC, &qbuf, &rbuf)) {
-               result = NT_STATUS_UNSUCCESSFUL;
-               goto done;
-       }
+       init_net_q_sam_sync(&q, cli->dc->remote_machine, global_myname(),
+                            &clnt_creds, &ret_creds, database_id, next_rid);
 
-       /* Unmarshall response */
+       /* Marshall data and send request */
 
-       if (!net_io_r_sam_sync("", cli->sess_key, &r, &rbuf, 0)) {
-               result = NT_STATUS_UNSUCCESSFUL;
-               goto done;
-       }
+       CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_SAM_SYNC,
+               q, r,
+               qbuf, rbuf,
+               net_io_q_sam_sync,
+               net_io_r_sam_sync,
+               NT_STATUS_UNSUCCESSFUL);
 
         /* Return results */
 
@@ -569,18 +457,20 @@ NTSTATUS cli_netlogon_sam_sync(struct cli_state *cli, TALLOC_CTX *mem_ctx, DOM_C
         *hdr_deltas = r.hdr_deltas;
         *deltas = r.deltas;
 
-       memcpy(ret_creds, &r.srv_creds, sizeof(*ret_creds));
-
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
+       if (!NT_STATUS_IS_ERR(result)) {
+               /* Check returned credentials. */
+               if (!creds_client_check(cli->dc, &r.srv_creds.challenge)) {
+                       DEBUG(0,("cli_netlogon_sam_sync: credentials chain check failed\n"));
+                       return NT_STATUS_ACCESS_DENIED;
+               }
+       }
 
        return result;
 }
 
 /* Sam synchronisation */
 
-NTSTATUS cli_netlogon_sam_deltas(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+NTSTATUS rpccli_netlogon_sam_deltas(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                  uint32 database_id, UINT64_S seqnum,
                                  uint32 *num_deltas, 
                                  SAM_DELTA_HDR **hdr_deltas, 
@@ -595,33 +485,22 @@ NTSTATUS cli_netlogon_sam_deltas(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        /* Initialise input parameters */
 
-        gen_next_creds(cli, &clnt_creds);
+       creds_client_step(cli->dc, &clnt_creds);
 
-       init_net_q_sam_deltas(&q, cli->srv_name_slash, 
-                              cli->clnt_name_slash + 2, &clnt_creds, 
+       init_net_q_sam_deltas(&q, cli->dc->remote_machine,
+                              global_myname(), &clnt_creds, 
                               database_id, seqnum);
 
        /* Marshall data and send request */
 
-       if (!net_io_q_sam_deltas("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, PI_NETLOGON, NET_SAM_DELTAS, &qbuf, &rbuf)) {
-               result = NT_STATUS_UNSUCCESSFUL;
-               goto done;
-       }
-
-       /* Unmarshall response */
-
-       if (!net_io_r_sam_deltas("", cli->sess_key, &r, &rbuf, 0)) {
-               result = NT_STATUS_UNSUCCESSFUL;
-               goto done;
-       }
+       CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_SAM_DELTAS,
+               q, r,
+               qbuf, rbuf,
+               net_io_q_sam_deltas,
+               net_io_r_sam_deltas,
+               NT_STATUS_UNSUCCESSFUL);
 
         /* Return results */
 
@@ -630,47 +509,49 @@ NTSTATUS cli_netlogon_sam_deltas(struct cli_state *cli, TALLOC_CTX *mem_ctx,
         *hdr_deltas = r.hdr_deltas;
         *deltas = r.deltas;
 
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
+       if (!NT_STATUS_IS_ERR(result)) {
+               /* Check returned credentials. */
+               if (!creds_client_check(cli->dc, &r.srv_creds.challenge)) {
+                       DEBUG(0,("cli_netlogon_sam_sync: credentials chain check failed\n"));
+                       return NT_STATUS_ACCESS_DENIED;
+               }
+       }
 
        return result;
 }
 
 /* Logon domain user */
 
-NTSTATUS cli_netlogon_sam_logon(struct cli_state *cli, TALLOC_CTX *mem_ctx,
-                               DOM_CRED *ret_creds,
-                                const char *username, const char *password,
+NTSTATUS rpccli_netlogon_sam_logon(struct rpc_pipe_client *cli,
+                               TALLOC_CTX *mem_ctx,
+                               const char *domain,
+                                const char *username,
+                               const char *password,
                                 int logon_type)
 {
        prs_struct qbuf, rbuf;
        NET_Q_SAM_LOGON q;
        NET_R_SAM_LOGON r;
        NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
-        DOM_CRED clnt_creds, dummy_rtn_creds;
+       DOM_CRED clnt_creds;
+       DOM_CRED ret_creds;
         NET_ID_INFO_CTR ctr;
         NET_USER_INFO_3 user;
         int validation_level = 3;
+       fstring clnt_name_slash;
 
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
-       ZERO_STRUCT(dummy_rtn_creds);
-
-       /* Initialise parse structures */
+       ZERO_STRUCT(ret_creds);
 
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
+       fstr_sprintf( clnt_name_slash, "\\\\%s", global_myname() );
 
         /* Initialise input parameters */
 
-        gen_next_creds(cli, &clnt_creds);
+       creds_client_step(cli->dc, &clnt_creds);
 
         q.validation_level = validation_level;
 
-       if (ret_creds == NULL)
-               ret_creds = &dummy_rtn_creds;
-
         ctr.switch_value = logon_type;
 
         switch (logon_type) {
@@ -679,11 +560,11 @@ NTSTATUS cli_netlogon_sam_logon(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 
                 nt_lm_owf_gen(password, nt_owf_user_pwd, lm_owf_user_pwd);
 
-                init_id_info1(&ctr.auth.id1, lp_workgroup()
+                init_id_info1(&ctr.auth.id1, domain
                               0, /* param_ctrl */
                               0xdead, 0xbeef, /* LUID? */
-                              username, cli->clnt_name_slash,
-                              (const char *)cli->sess_key, lm_owf_user_pwd,
+                              username, clnt_name_slash,
+                              cli->dc->sess_key, lm_owf_user_pwd,
                               nt_owf_user_pwd);
 
                 break;
@@ -698,46 +579,45 @@ NTSTATUS cli_netlogon_sam_logon(struct cli_state *cli, TALLOC_CTX *mem_ctx,
                 SMBencrypt(password, chal, local_lm_response);
                 SMBNTencrypt(password, chal, local_nt_response);
 
-                init_id_info2(&ctr.auth.id2, lp_workgroup()
+                init_id_info2(&ctr.auth.id2, domain
                               0, /* param_ctrl */
                               0xdead, 0xbeef, /* LUID? */
-                              username, cli->clnt_name_slash, chal,
+                              username, clnt_name_slash, chal,
                               local_lm_response, 24, local_nt_response, 24);
                 break;
         }
         default:
                 DEBUG(0, ("switch value %d not supported\n", 
                           ctr.switch_value));
-                goto done;
+                return NT_STATUS_INVALID_INFO_CLASS;
         }
 
-        init_sam_info(&q.sam_id, cli->srv_name_slash, global_myname(),
-                      &clnt_creds, ret_creds, logon_type,
+        r.user = &user;
+
+        init_sam_info(&q.sam_id, cli->dc->remote_machine, global_myname(),
+                      &clnt_creds, &ret_creds, logon_type,
                       &ctr);
 
         /* Marshall data and send request */
 
-       if (!net_io_q_sam_logon("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, PI_NETLOGON, NET_SAMLOGON, &qbuf, &rbuf)) {
-               goto done;
-       }
-
-       /* Unmarshall response */
-
-        r.user = &user;
-
-       if (!net_io_r_sam_logon("", &r, &rbuf, 0)) {
-               goto done;
-       }
+       CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_SAMLOGON,
+               q, r,
+               qbuf, rbuf,
+               net_io_q_sam_logon,
+               net_io_r_sam_logon,
+               NT_STATUS_UNSUCCESSFUL);
 
         /* Return results */
 
        result = r.status;
-       memcpy(ret_creds, &r.srv_creds, sizeof(*ret_creds));
 
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
+       if (r.buffer_creds) {
+               /* Check returned credentials if present. */
+               if (!creds_client_check(cli->dc, &r.srv_creds.challenge)) {
+                       DEBUG(0,("rpccli_netlogon_sam_logon: credentials chain check failed\n"));
+                       return NT_STATUS_ACCESS_DENIED;
+               }
+       }
 
         return result;
 }
@@ -751,52 +631,55 @@ NTSTATUS cli_netlogon_sam_logon(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 
 NTSTATUS rpccli_netlogon_sam_network_logon(struct rpc_pipe_client *cli,
                                           TALLOC_CTX *mem_ctx,
-                                          const char *server_name_slash,
-                                          DOM_CRED *clnt_creds,
-                                          DOM_CRED *ret_creds,
+                                          const char *server,
                                           const char *username,
                                           const char *domain,
                                           const char *workstation, 
                                           const uint8 chal[8], 
                                           DATA_BLOB lm_response,
                                           DATA_BLOB nt_response,
-                                          NET_USER_INFO_3 *info3,
-                                          const uint8 *session_key)
+                                          NET_USER_INFO_3 *info3)
 {
        prs_struct qbuf, rbuf;
        NET_Q_SAM_LOGON q;
        NET_R_SAM_LOGON r;
        NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
-        DOM_CRED dummy_rtn_creds;
        NET_ID_INFO_CTR ctr;
        int validation_level = 3;
-       char *workstation_name_slash;
-       uint8 netlogon_sess_key[16];
+       const char *workstation_name_slash;
+       const char *server_name_slash;
        static uint8 zeros[16];
+       DOM_CRED clnt_creds;
+       DOM_CRED ret_creds;
        int i;
        
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
-       ZERO_STRUCT(dummy_rtn_creds);
+       ZERO_STRUCT(ret_creds);
 
-       workstation_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", workstation);
-       if (!workstation_name_slash) {
-               DEBUG(0, ("talloc_asprintf failed!\n"));
-               return NT_STATUS_NO_MEMORY;
+       creds_client_step(cli->dc, &clnt_creds);
+
+       if (server[0] != '\\' && server[1] != '\\') {
+               server_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", server);
+       } else {
+               server_name_slash = server;
        }
 
-       /* Initialise parse structures */
+       if (workstation[0] != '\\' && workstation[1] != '\\') {
+               workstation_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", workstation);
+       } else {
+               workstation_name_slash = workstation;
+       }
 
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
+       if (!workstation_name_slash || !server_name_slash) {
+               DEBUG(0, ("talloc_asprintf failed!\n"));
+               return NT_STATUS_NO_MEMORY;
+       }
 
        /* Initialise input parameters */
 
        q.validation_level = validation_level;
 
-       if (ret_creds == NULL)
-               ret_creds = &dummy_rtn_creds;
-
         ctr.switch_value = NET_LOGON_TYPE;
 
        init_id_info2(&ctr.auth.id2, domain,
@@ -806,35 +689,28 @@ NTSTATUS rpccli_netlogon_sam_network_logon(struct rpc_pipe_client *cli,
                      lm_response.data, lm_response.length, nt_response.data, nt_response.length);
  
         init_sam_info(&q.sam_id, server_name_slash, global_myname(),
-                      clnt_creds, ret_creds, NET_LOGON_TYPE,
+                      &clnt_creds, &ret_creds, NET_LOGON_TYPE,
                       &ctr);
 
-        /* Marshall data and send request */
-
-       if (!net_io_q_sam_logon("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req_int(cli, NET_SAMLOGON, &qbuf, &rbuf)) {
-               goto done;
-       }
-
-       /* Unmarshall response */
-
         r.user = info3;
 
-       if (!net_io_r_sam_logon("", &r, &rbuf, 0)) {
-               goto done;
-       }
+        /* Marshall data and send request */
+
+       CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_SAMLOGON,
+               q, r,
+               qbuf, rbuf,
+               net_io_q_sam_logon,
+               net_io_r_sam_logon,
+               NT_STATUS_UNSUCCESSFUL);
 
-       ZERO_STRUCT(netlogon_sess_key);
-       memcpy(netlogon_sess_key, session_key, 8);
-       
        if (memcmp(zeros, info3->user_sess_key, 16) != 0) {
-               SamOEMhash(info3->user_sess_key, netlogon_sess_key, 16);
+               SamOEMhash(info3->user_sess_key, cli->dc->sess_key, 16);
        } else {
                memset(info3->user_sess_key, '\0', 16);
        }
 
        if (memcmp(zeros, info3->lm_sess_key, 8) != 0) {
-               SamOEMhash(info3->lm_sess_key, netlogon_sess_key, 8);
+               SamOEMhash(info3->lm_sess_key, cli->dc->sess_key, 8);
        } else {
                memset(info3->lm_sess_key, '\0', 8);
        }
@@ -847,108 +723,62 @@ NTSTATUS rpccli_netlogon_sam_network_logon(struct rpc_pipe_client *cli,
         /* Return results */
 
        result = r.status;
-       memcpy(ret_creds, &r.srv_creds, sizeof(*ret_creds));
 
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
+       if (r.buffer_creds) {
+               /* Check returned credentials if present. */
+               if (!creds_client_check(cli->dc, &r.srv_creds.challenge)) {
+                       DEBUG(0,("rpccli_netlogon_sam_network_logon: credentials chain check failed\n"));
+                       return NT_STATUS_ACCESS_DENIED;
+               }
+       }
 
         return result;
 }
 
-NTSTATUS cli_netlogon_sam_network_logon(struct cli_state *cli,
-                                       TALLOC_CTX *mem_ctx,
-                                       DOM_CRED *ret_creds,
-                                       const char *username,
-                                       const char *domain,
-                                       const char *workstation, 
-                                       const uint8 chal[8], 
-                                       DATA_BLOB lm_response,
-                                       DATA_BLOB nt_response,
-                                       NET_USER_INFO_3 *info3)
-{
-       DOM_CRED clnt_creds;
-
-       gen_next_creds(cli, &clnt_creds);
-
-       return rpccli_netlogon_sam_network_logon(&cli->pipes[PI_NETLOGON],
-                                                mem_ctx, cli->srv_name_slash,
-                                                &clnt_creds,
-                                                ret_creds, username,
-                                                domain, workstation, chal, 
-                                                lm_response, nt_response,
-                                                info3, cli->sess_key);
-}
-
 /***************************************************************************
 LSA Server Password Set.
 ****************************************************************************/
 
-NTSTATUS cli_net_srv_pwset(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
+NTSTATUS rpccli_net_srv_pwset(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, 
                           const char *machine_name, uint8 hashed_mach_pwd[16])
 {
        prs_struct rbuf;
        prs_struct qbuf; 
-       DOM_CRED new_clnt_cred;
-       NET_Q_SRV_PWSET q_s;
+       DOM_CRED clnt_creds;
+       NET_Q_SRV_PWSET q;
+       NET_R_SRV_PWSET r;
        uint16 sec_chan_type = 2;
-       NTSTATUS nt_status;
+       NTSTATUS result;
 
-       gen_next_creds( cli, &new_clnt_cred);
-       
-       prs_init(&qbuf , 1024, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0,    mem_ctx, UNMARSHALL);
+       creds_client_step(cli->dc, &clnt_creds);
        
-       DEBUG(4,("cli_net_srv_pwset: srv:%s acct:%s sc: %d mc: %s clnt %s %x\n",
-                cli->srv_name_slash, cli->mach_acct, sec_chan_type, machine_name,
-                credstr(new_clnt_cred.challenge.data), new_clnt_cred.timestamp.time));
+       DEBUG(4,("cli_net_srv_pwset: srv:%s acct:%s sc: %d mc: %s\n",
+                cli->dc->remote_machine, cli->dc->mach_acct, sec_chan_type, machine_name));
        
         /* store the parameters */
-       init_q_srv_pwset(&q_s, cli->srv_name_slash, (const char *)cli->sess_key,
-                        cli->mach_acct, sec_chan_type, machine_name, 
-                        &new_clnt_cred, hashed_mach_pwd);
-       
-       /* turn parameters into data stream */
-       if(!net_io_q_srv_pwset("", &q_s,  &qbuf, 0)) {
-               DEBUG(0,("cli_net_srv_pwset: Error : failed to marshall NET_Q_SRV_PWSET struct.\n"));
-               nt_status = NT_STATUS_UNSUCCESSFUL;
-               goto done;
-       }
+       init_q_srv_pwset(&q, cli->dc->remote_machine, (const char *)cli->dc->sess_key,
+                        cli->dc->mach_acct, sec_chan_type, machine_name, 
+                        &clnt_creds, hashed_mach_pwd);
        
-       /* send the data on \PIPE\ */
-       if (rpc_api_pipe_req(cli, PI_NETLOGON, NET_SRVPWSET, &qbuf, &rbuf))
-       {
-               NET_R_SRV_PWSET r_s;
-               
-               if (!net_io_r_srv_pwset("", &r_s, &rbuf, 0)) {
-                       nt_status =  NT_STATUS_UNSUCCESSFUL;
-                       goto done;
-               }
-               
-               nt_status = r_s.status;
+       CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_SRVPWSET,
+               q, r,
+               qbuf, rbuf,
+               net_io_q_srv_pwset,
+               net_io_r_srv_pwset,
+               NT_STATUS_UNSUCCESSFUL);
 
-               if (!NT_STATUS_IS_OK(r_s.status))
-               {
-                       /* report error code */
-                       DEBUG(0,("cli_net_srv_pwset: %s\n", nt_errstr(nt_status)));
-               }
+       result = r.status;
 
-               /* Update the credentials. */
-               if (!clnt_deal_with_creds(cli->sess_key, &(cli->clnt_cred), &(r_s.srv_cred)))
-               {
-                       /*
-                        * Server replied with bad credential. Fail.
-                        */
-                       DEBUG(0,("cli_net_srv_pwset: server %s replied with bad credential (bad machine \
-password ?).\n", cli->desthost ));
-                       nt_status = NT_STATUS_UNSUCCESSFUL;
-               }
+       if (!NT_STATUS_IS_OK(result)) {
+               /* report error code */
+               DEBUG(0,("cli_net_srv_pwset: %s\n", nt_errstr(result)));
        }
 
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-       
-       return nt_status;
-}
+       /* Always check returned credentials. */
+       if (!creds_client_check(cli->dc, &r.srv_cred.challenge)) {
+               DEBUG(0,("rpccli_net_srv_pwset: credentials chain check failed\n"));
+               return NT_STATUS_ACCESS_DENIED;
+       }
 
+       return result;
+}
index 230750817a95f75abd15857474290d385132ff3e..df34b1c3d958433ecd72f91e93a4b3bea15dc5dc 100644 (file)
@@ -1,11 +1,7 @@
 /* 
  *  Unix SMB/CIFS implementation.
  *  RPC Pipe client / server routines
- *  Copyright (C) Andrew Tridgell              1992-1998,
- *  Copyright (C) Luke Kenneth Casson Leighton 1996-1998,
- *  Copyright (C) Paul Ashton                       1998.
- *  Copyright (C) Jeremy Allison                    1999.
- *  Copyright (C) Andrew Bartlett                   2003.
+ *  Largely rewritten by Jeremy Allison                    2005.
  *  
  *  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
 
 extern struct pipe_id_info pipe_names[];
 
-/* convert pipe auth flags into the RPC auth type and level */
+/********************************************************************
+ Map internal value to wire value.
+ ********************************************************************/
 
-void get_auth_type_level(int pipe_auth_flags, int *auth_type, int *auth_level) 
+static int map_pipe_auth_type_to_rpc_auth_type(enum pipe_auth_type auth_type)
 {
-       *auth_type = 0;
-       *auth_level = 0;
-       if (pipe_auth_flags & AUTH_PIPE_SEAL) {
-               *auth_level = RPC_PIPE_AUTH_SEAL_LEVEL;
-       } else if (pipe_auth_flags & AUTH_PIPE_SIGN) {
-               *auth_level = RPC_PIPE_AUTH_SIGN_LEVEL;
-       }
-       
-       if (pipe_auth_flags & AUTH_PIPE_NETSEC) {
-               *auth_type = NETSEC_AUTH_TYPE;
-       } else if (pipe_auth_flags & AUTH_PIPE_NTLMSSP) {
-               *auth_type = NTLMSSP_AUTH_TYPE;
+       switch (auth_type) {
+
+       case PIPE_AUTH_TYPE_NONE:
+               return RPC_ANONYMOUS_AUTH_TYPE;
+
+       case PIPE_AUTH_TYPE_NTLMSSP:
+               return RPC_NTLMSSP_AUTH_TYPE;
+
+       case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
+       case PIPE_AUTH_TYPE_SPNEGO_KRB5:
+               return RPC_SPNEGO_AUTH_TYPE;
+
+       case PIPE_AUTH_TYPE_SCHANNEL:
+               return RPC_SCHANNEL_AUTH_TYPE;
+
+       case PIPE_AUTH_TYPE_KRB5:
+               return RPC_KRB5_AUTH_TYPE;
+
+       default:
+               DEBUG(0,("map_pipe_auth_type_to_rpc_type: unknown pipe "
+                       "auth type %u\n",
+                       (unsigned int)auth_type ));
+               break;
        }
+       return -1;
 }
 
 /********************************************************************
@@ -60,55 +70,81 @@ static uint32 get_rpc_call_id(void)
 
 /*******************************************************************
  Use SMBreadX to get rest of one fragment's worth of rpc data.
+ Will expand the current_pdu struct to the correct size.
  ********************************************************************/
 
-static BOOL rpc_read(struct rpc_pipe_client *cli, prs_struct *rdata,
-                    uint32 data_to_read, uint32 *rdata_offset)
+static NTSTATUS rpc_read(struct rpc_pipe_client *cli,
+                       prs_struct *current_pdu,
+                       uint32 data_to_read,
+                       uint32 *current_pdu_offset)
 {
        size_t size = (size_t)cli->max_recv_frag;
-       int stream_offset = 0;
-       int num_read;
+       uint32 stream_offset = 0;
+       ssize_t num_read;
        char *pdata;
-       int extra_data_size = ((int)*rdata_offset) + ((int)data_to_read) - (int)prs_data_size(rdata);
+       ssize_t extra_data_size = ((ssize_t)*current_pdu_offset) + ((ssize_t)data_to_read) - (ssize_t)prs_data_size(current_pdu);
 
-       DEBUG(5,("rpc_read: data_to_read: %u rdata offset: %u extra_data_size: %d\n",
-               (int)data_to_read, (unsigned int)*rdata_offset, extra_data_size));
+       DEBUG(5,("rpc_read: data_to_read: %u current_pdu offset: %u extra_data_size: %d\n",
+               (unsigned int)data_to_read, (unsigned int)*current_pdu_offset, (int)extra_data_size ));
 
        /*
         * Grow the buffer if needed to accommodate the data to be read.
         */
 
        if (extra_data_size > 0) {
-               if(!prs_force_grow(rdata, (uint32)extra_data_size)) {
-                       DEBUG(0,("rpc_read: Failed to grow parse struct by %d bytes.\n", extra_data_size ));
-                       return False;
+               if(!prs_force_grow(current_pdu, (uint32)extra_data_size)) {
+                       DEBUG(0,("rpc_read: Failed to grow parse struct by %d bytes.\n", (int)extra_data_size ));
+                       return NT_STATUS_NO_MEMORY;
                }
-               DEBUG(5,("rpc_read: grew buffer by %d bytes to %u\n", extra_data_size, prs_data_size(rdata) ));
+               DEBUG(5,("rpc_read: grew buffer by %d bytes to %u\n", (int)extra_data_size, prs_data_size(current_pdu) ));
        }
 
-       pdata = prs_data_p(rdata) + *rdata_offset;
+       pdata = prs_data_p(current_pdu) + *current_pdu_offset;
 
-       do /* read data using SMBreadX */
-       {
-               uint32 ecode;
-               uint8 eclass;
-
-               if (size > (size_t)data_to_read)
+       do {
+               /* read data using SMBreadX */
+               if (size > (size_t)data_to_read) {
                        size = (size_t)data_to_read;
+               }
 
-               num_read = (int)cli_read(cli->cli, cli->fnum, pdata,
+               num_read = cli_read(cli->cli, cli->fnum, pdata,
                                         (off_t)stream_offset, size);
 
-               DEBUG(5,("rpc_read: num_read = %d, read offset: %d, to read: %d\n",
-                         num_read, stream_offset, data_to_read));
+               DEBUG(5,("rpc_read: num_read = %d, read offset: %u, to read: %u\n",
+                       (int)num_read, (unsigned int)stream_offset, (unsigned int)data_to_read));
 
+               /*
+                * A dos error of ERRDOS/ERRmoredata is not an error.
+                */
                if (cli_is_dos_error(cli->cli)) {
-                        cli_dos_error(cli->cli, &eclass, &ecode);
-                        if (eclass != ERRDOS && ecode != ERRmoredata) {
-                                DEBUG(0,("rpc_read: Error %d/%u in cli_read\n",
-                                         eclass, (unsigned int)ecode));
-                                return False;
-                        }
+                       uint32 ecode;
+                       uint8 eclass;
+                       cli_dos_error(cli->cli, &eclass, &ecode);
+                       if (eclass != ERRDOS && ecode != ERRmoredata) {
+                               DEBUG(0,("rpc_read: DOS Error %d/%u (%s) in cli_read on pipe %s\n",
+                                       eclass, (unsigned int)ecode,
+                                       cli_errstr(cli->cli),
+                                       cli->pipe_name ));
+                               return dos_to_ntstatus(eclass, ecode);
+                       }
+               }
+
+               /*
+                * Likewise for NT_STATUS_BUFFER_TOO_SMALL
+                */
+               if (cli_is_nt_error(cli->cli)) {
+                       if (!NT_STATUS_EQUAL(cli_nt_error(cli->cli), NT_STATUS_BUFFER_TOO_SMALL)) {
+                               DEBUG(0,("rpc_read: Error (%s) in cli_read on pipe %s\n",
+                                       nt_errstr(cli_nt_error(cli->cli)),
+                                       cli->pipe_name ));
+                               return cli_nt_error(cli->cli);
+                       }
+               }
+
+               if (num_read == -1) {
+                       DEBUG(0,("rpc_read: Error - cli_read on pipe %s returned -1\n",
+                               cli->pipe_name ));
+                       return cli_get_nt_error(cli->cli);
                }
 
                data_to_read -= num_read;
@@ -119,262 +155,565 @@ static BOOL rpc_read(struct rpc_pipe_client *cli, prs_struct *rdata,
        /* && err == (0x80000000 | STATUS_BUFFER_OVERFLOW)); */
 
        /*
-        * Update the current offset into rdata by the amount read.
+        * Update the current offset into current_pdu by the amount read.
         */
-       *rdata_offset += stream_offset;
-
-       return True;
+       *current_pdu_offset += stream_offset;
+       return NT_STATUS_OK;
 }
 
 /****************************************************************************
- Checks the header. This will set the endian bit in the rdata prs_struct. JRA.
+ Try and get a PDU's worth of data from current_pdu. If not, then read more
+ from the wire.
  ****************************************************************************/
 
-static BOOL rpc_check_hdr(prs_struct *rdata, RPC_HDR *rhdr, 
-                          BOOL *first, BOOL *last, uint32 *len)
+static NTSTATUS cli_pipe_get_current_pdu(struct rpc_pipe_client *cli, RPC_HDR *prhdr, prs_struct *current_pdu)
 {
-       DEBUG(5,("rpc_check_hdr: rdata->data_size = %u\n", (uint32)prs_data_size(rdata) ));
-
-       /* Next call sets endian bit. */
+       NTSTATUS ret = NT_STATUS_OK;
+       uint32 current_pdu_len = prs_data_size(current_pdu);
+
+       /* Ensure we have at least RPC_HEADER_LEN worth of data to parse. */
+       if (current_pdu_len < RPC_HEADER_LEN) {
+               /* rpc_read expands the current_pdu struct as neccessary. */
+               ret = rpc_read(cli, current_pdu, RPC_HEADER_LEN - current_pdu_len, &current_pdu_len);
+               if (!NT_STATUS_IS_OK(ret)) {
+                       return ret;
+               }
+       }
 
-       if(!smb_io_rpc_hdr("rpc_hdr   ", rhdr, rdata, 0)) {
-               DEBUG(0,("rpc_check_hdr: Failed to unmarshall RPC_HDR.\n"));
-               return False;
+       /* This next call sets the endian bit correctly in current_pdu. */
+       /* We will propagate this to rbuf later. */
+       if(!smb_io_rpc_hdr("rpc_hdr   ", prhdr, current_pdu, 0)) {
+               DEBUG(0,("cli_pipe_get_current_pdu: Failed to unmarshall RPC_HDR.\n"));
+               return NT_STATUS_BUFFER_TOO_SMALL;
        }
 
-       if (prs_offset(rdata) != RPC_HEADER_LEN) {
-               DEBUG(0,("rpc_check_hdr: offset was %x, should be %x.\n", prs_offset(rdata), RPC_HEADER_LEN));
-               return False;
+       /* Ensure we have frag_len bytes of data. */
+       if (current_pdu_len < prhdr->frag_len) {
+               /* rpc_read expands the current_pdu struct as neccessary. */
+               ret = rpc_read(cli, current_pdu, (uint32)prhdr->frag_len - current_pdu_len, &current_pdu_len);
+               if (!NT_STATUS_IS_OK(ret)) {
+                       return ret;
+               }
        }
 
-       (*first) = ((rhdr->flags & RPC_FLG_FIRST) != 0);
-       (*last) = ((rhdr->flags & RPC_FLG_LAST ) != 0);
-       (*len) = (uint32)rhdr->frag_len - prs_data_size(rdata);
+       if (current_pdu_len < prhdr->frag_len) {
+               return NT_STATUS_BUFFER_TOO_SMALL;
+       }
 
-       return (rhdr->pkt_type != RPC_FAULT);
+       return NT_STATUS_OK;
 }
 
 /****************************************************************************
- Verify data on an rpc pipe.
- The VERIFY & SEAL code is only executed on packets that look like this :
+ NTLMSSP specific sign/seal.
+ Virtually identical to rpc_server/srv_pipe.c:api_pipe_ntlmssp_auth_process.
+ In fact I should probably abstract these into identical pieces of code... JRA.
+ ****************************************************************************/
 
- Request/Response PDU's look like the following...
+static NTSTATUS cli_pipe_verify_ntlmssp(struct rpc_pipe_client *cli, RPC_HDR *prhdr,
+                               prs_struct *current_pdu,
+                               uint8 *p_ss_padding_len)
+{
+       RPC_HDR_AUTH auth_info;
+       uint32 save_offset = prs_offset(current_pdu);
+       uint32 auth_len = prhdr->auth_len;
+       NTLMSSP_STATE *ntlmssp_state = cli->auth.a_u.ntlmssp_state;
+       unsigned char *data = NULL;
+       size_t data_len;
+       unsigned char *full_packet_data = NULL;
+       size_t full_packet_data_len;
+       DATA_BLOB auth_blob;
+       NTSTATUS status;
+
+       if (cli->auth.auth_level == PIPE_AUTH_LEVEL_NONE || cli->auth.auth_level == PIPE_AUTH_LEVEL_CONNECT) {
+               return NT_STATUS_OK;
+       }
 
- |<------------------PDU len----------------------------------------------->|
- |<-HDR_LEN-->|<--REQ LEN------>|.............|<-AUTH_HDRLEN->|<-AUTH_LEN-->|
+       if (!ntlmssp_state) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
 
- +------------+-----------------+-------------+---------------+-------------+
- | RPC HEADER | REQ/RESP HEADER | DATA ...... | AUTH_HDR      | AUTH DATA   |
- +------------+-----------------+-------------+---------------+-------------+
+       /* Ensure there's enough data for an authenticated response. */
+       if ((auth_len > RPC_MAX_SIGN_SIZE) ||
+                       (RPC_HEADER_LEN + RPC_HDR_RESP_LEN + RPC_HDR_AUTH_LEN + auth_len > prhdr->frag_len)) {
+               DEBUG(0,("cli_pipe_verify_ntlmssp: auth_len %u is too large.\n",
+                       (unsigned int)auth_len ));
+               return NT_STATUS_BUFFER_TOO_SMALL;
+       }
 
- Never on bind requests/responses.
- ****************************************************************************/
+       /*
+        * We need the full packet data + length (minus auth stuff) as well as the packet data + length
+        * after the RPC header.
+        * We need to pass in the full packet (minus auth len) to the NTLMSSP sign and check seal
+        * functions as NTLMv2 checks the rpc headers also.
+        */
+
+       data = (unsigned char *)(prs_data_p(current_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN);
+       data_len = (size_t)(prhdr->frag_len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - RPC_HDR_AUTH_LEN - auth_len);
+
+       full_packet_data = prs_data_p(current_pdu);
+       full_packet_data_len = prhdr->frag_len - auth_len;
+
+       /* Pull the auth header and the following data into a blob. */
+       if(!prs_set_offset(current_pdu, RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len)) {
+               DEBUG(0,("cli_pipe_verify_ntlmssp: cannot move offset to %u.\n",
+                       (unsigned int)RPC_HEADER_LEN + (unsigned int)RPC_HDR_RESP_LEN + (unsigned int)data_len ));
+               return NT_STATUS_BUFFER_TOO_SMALL;
+       }
+
+       if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, current_pdu, 0)) {
+               DEBUG(0,("cli_pipe_verify_ntlmssp: failed to unmarshall RPC_HDR_AUTH.\n"));
+               return NT_STATUS_BUFFER_TOO_SMALL;
+       }
+
+       auth_blob.data = prs_data_p(current_pdu) + prs_offset(current_pdu);
+       auth_blob.length = auth_len;
+
+       switch (cli->auth.auth_level) {
+               case PIPE_AUTH_LEVEL_PRIVACY:
+                       /* Data is encrypted. */
+                       status = ntlmssp_unseal_packet(ntlmssp_state,
+                                                       data, data_len,
+                                                       full_packet_data,
+                                                       full_packet_data_len,
+                                                       &auth_blob);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               DEBUG(0,("cli_pipe_verify_ntlmssp: failed to unseal "
+                                       "packet from remote machine %s on pipe %s "
+                                       "fnum 0x%x. Error was %s.\n",
+                                       cli->cli->desthost,
+                                       cli->pipe_name,
+                                       (unsigned int)cli->fnum,
+                                       nt_errstr(status) ));
+                               return status;
+                       }
+                       break;
+               case PIPE_AUTH_LEVEL_INTEGRITY:
+                       /* Data is signed. */
+                       status = ntlmssp_check_packet(ntlmssp_state,
+                                                       data, data_len,
+                                                       full_packet_data,
+                                                       full_packet_data_len,
+                                                       &auth_blob);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               DEBUG(0,("cli_pipe_verify_ntlmssp: check signing failed on "
+                                       "packet from remote machine %s on pipe %s "
+                                       "fnum 0x%x. Error was %s.\n",
+                                       cli->cli->desthost,
+                                       cli->pipe_name,
+                                       (unsigned int)cli->fnum,
+                                       nt_errstr(status) ));
+                               return status;
+                       }
+                       break;
+               default:
+                       DEBUG(0,("cli_pipe_verify_ntlmssp: unknown internal auth level %d\n",
+                               cli->auth.auth_level ));
+                       return NT_STATUS_INVALID_INFO_CLASS;
+       }
 
-static BOOL rpc_auth_pipe(struct rpc_pipe_client *cli, prs_struct *rdata,
-                         uint32 fragment_start, int len, int auth_len, uint8 pkt_type,
-                         int *pauth_padding_len)
-{
-       
        /*
-        * The following is that length of the data we must sign or seal.
-        * This doesn't include the RPC headers or the auth_len or the RPC_HDR_AUTH_LEN
-        * preceeding the auth_data.
+        * Return the current pointer to the data offset.
         */
 
-       int data_len = len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - RPC_HDR_AUTH_LEN - auth_len;
+       if(!prs_set_offset(current_pdu, save_offset)) {
+               DEBUG(0,("api_pipe_auth_process: failed to set offset back to %u\n",
+                       (unsigned int)save_offset ));
+               return NT_STATUS_BUFFER_TOO_SMALL;
+       }
 
        /*
-        * The start of the data to sign/seal is just after the RPC headers.
+        * Remember the padding length. We must remove it from the real data
+        * stream once the sign/seal is done.
         */
-       char *reply_data = prs_data_p(rdata) + fragment_start + RPC_HEADER_LEN + RPC_HDR_REQ_LEN;
 
-       RPC_HDR_AUTH rhdr_auth; 
+       *p_ss_padding_len = auth_info.auth_pad_len;
+
+       return NT_STATUS_OK;
+}
+
+/****************************************************************************
+ schannel specific sign/seal.
+ ****************************************************************************/
 
-       char *dp = prs_data_p(rdata) + fragment_start + len -
-               RPC_HDR_AUTH_LEN - auth_len;
-       prs_struct auth_verf;
+static NTSTATUS cli_pipe_verify_schannel(struct rpc_pipe_client *cli, RPC_HDR *prhdr,
+                               prs_struct *current_pdu,
+                               uint8 *p_ss_padding_len)
+{
+       RPC_HDR_AUTH auth_info;
+       RPC_AUTH_SCHANNEL_CHK schannel_chk;
+       uint32 auth_len = prhdr->auth_len;
+       uint32 save_offset = prs_offset(current_pdu);
+       struct schannel_auth_struct *schannel_auth = cli->auth.a_u.schannel_auth;
+       uint32 data_len;
+
+       if (cli->auth.auth_level == PIPE_AUTH_LEVEL_NONE || cli->auth.auth_level == PIPE_AUTH_LEVEL_CONNECT) {
+               return NT_STATUS_OK;
+       }
 
-       *pauth_padding_len = 0;
+       if (auth_len != RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN) {
+               DEBUG(0,("cli_pipe_verify_schannel: auth_len %u.\n", (unsigned int)auth_len ));
+               return NT_STATUS_INVALID_PARAMETER;
+       }
 
-       if (auth_len == 0) {
-               if (cli->pipe_auth_flags == 0) {
-                       /* move along, nothing to see here */
-                       return True;
-               }
+       if (!schannel_auth) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
 
-               DEBUG(2, ("No authenticaton header recienved on reply, but this pipe is authenticated\n"));
-               return False;
+       /* Ensure there's enough data for an authenticated response. */
+       if ((auth_len > RPC_MAX_SIGN_SIZE) ||
+                       (RPC_HEADER_LEN + RPC_HDR_RESP_LEN + RPC_HDR_AUTH_LEN + auth_len > prhdr->frag_len)) {
+               DEBUG(0,("cli_pipe_verify_schannel: auth_len %u is too large.\n",
+                       (unsigned int)auth_len ));
+               return NT_STATUS_INVALID_PARAMETER;
        }
 
-       DEBUG(5,("rpc_auth_pipe: pkt_type: %d len: %d auth_len: %d NTLMSSP %s schannel %s sign %s seal %s \n",
-                pkt_type, len, auth_len, 
-                BOOLSTR(cli->pipe_auth_flags & AUTH_PIPE_NTLMSSP), 
-                BOOLSTR(cli->pipe_auth_flags & AUTH_PIPE_NETSEC), 
-                BOOLSTR(cli->pipe_auth_flags & AUTH_PIPE_SIGN), 
-                BOOLSTR(cli->pipe_auth_flags & AUTH_PIPE_SEAL)));
+       data_len = prhdr->frag_len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - RPC_HDR_AUTH_LEN - auth_len;
 
-       if (dp - prs_data_p(rdata) > prs_data_size(rdata)) {
-               DEBUG(0,("rpc_auth_pipe: schannel auth data > data size !\n"));
-               return False;
+       if(!prs_set_offset(current_pdu, RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len)) {
+               DEBUG(0,("cli_pipe_verify_schannel: cannot move offset to %u.\n",
+                       (unsigned int)RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len ));
+               return NT_STATUS_BUFFER_TOO_SMALL;
+       }
+                                                                                                                             
+       if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, current_pdu, 0)) {
+               DEBUG(0,("cli_pipe_verify_schannel: failed to unmarshall RPC_HDR_AUTH.\n"));
+               return NT_STATUS_BUFFER_TOO_SMALL;
        }
 
-       DEBUG(10,("rpc_auth_pipe: packet:\n"));
-       dump_data(100, dp, auth_len);
+       if (auth_info.auth_type != RPC_SCHANNEL_AUTH_TYPE) {
+               DEBUG(0,("cli_pipe_verify_schannel: Invalid auth info %d on schannel\n",
+                       auth_info.auth_type));
+               return NT_STATUS_BUFFER_TOO_SMALL;
+       }
 
-       prs_init(&auth_verf, 0, cli->cli->mem_ctx, UNMARSHALL);
-       
-       /* The endinness must be preserved. JRA. */
-       prs_set_endian_data( &auth_verf, rdata->bigendian_data);
-       
-       /* Point this new parse struct at the auth section of the main 
-          parse struct - rather than copying it.  Avoids needing to
-          free it on every error
-       */
-       prs_give_memory(&auth_verf, dp, RPC_HDR_AUTH_LEN + auth_len, False /* not dynamic */);
-       prs_set_offset(&auth_verf, 0);
+       if(!smb_io_rpc_auth_schannel_chk("", RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN,
+                               &schannel_chk, current_pdu, 0)) {
+               DEBUG(0,("cli_pipe_verify_schannel: failed to unmarshal RPC_AUTH_SCHANNEL_CHK.\n"));
+               return NT_STATUS_BUFFER_TOO_SMALL;
+       }
 
-       {
-               int auth_type;
-               int auth_level;
-               if (!smb_io_rpc_hdr_auth("auth_hdr", &rhdr_auth, &auth_verf, 0)) {
-                       DEBUG(0, ("rpc_auth_pipe: Could not parse auth header\n"));
-                       return False;
-               }
+       if (!schannel_decode(schannel_auth,
+                       cli->auth.auth_level,
+                       SENDER_IS_ACCEPTOR,
+                       &schannel_chk,
+                       prs_data_p(current_pdu)+RPC_HEADER_LEN+RPC_HDR_RESP_LEN,
+                       data_len)) {
+               DEBUG(3,("cli_pipe_verify_schannel: failed to decode PDU "
+                               "Connection to remote machine %s "
+                               "pipe %s fnum 0x%x.\n",
+                               cli->cli->desthost,
+                               cli->pipe_name,
+                               (unsigned int)cli->fnum ));
+               return NT_STATUS_INVALID_PARAMETER;
+       }
 
-               /* Let the caller know how much padding at the end of the data */
-               *pauth_padding_len = rhdr_auth.auth_pad_len;
-               
-               /* Check it's the type of reply we were expecting to decode */
+       /* The sequence number gets incremented on both send and receive. */
+       schannel_auth->seq_num++;
 
-               get_auth_type_level(cli->pipe_auth_flags, &auth_type, &auth_level);
-               if (rhdr_auth.auth_type != auth_type) {
-                       DEBUG(0, ("BAD auth type %d (should be %d)\n",
-                                 rhdr_auth.auth_type, auth_type));
-                       return False;
-               }
-               
-               if (rhdr_auth.auth_level != auth_level) {
-                       DEBUG(0, ("BAD auth level %d (should be %d)\n", 
-                                 rhdr_auth.auth_level, auth_level));
-                       return False;
-               }
+       /*
+        * Return the current pointer to the data offset.
+        */
+
+       if(!prs_set_offset(current_pdu, save_offset)) {
+               DEBUG(0,("api_pipe_auth_process: failed to set offset back to %u\n",
+                       (unsigned int)save_offset ));
+               return NT_STATUS_BUFFER_TOO_SMALL;
        }
 
-       if (pkt_type == RPC_BINDACK) {
-               if (cli->pipe_auth_flags & AUTH_PIPE_NTLMSSP) {
-                       /* copy the next auth_len bytes into a buffer for 
-                          later use */
+       /*
+        * Remember the padding length. We must remove it from the real data
+        * stream once the sign/seal is done.
+        */
+
+       *p_ss_padding_len = auth_info.auth_pad_len;
+
+       return NT_STATUS_OK;
+}
 
-                       DATA_BLOB ntlmssp_verf = data_blob(NULL, auth_len);
-                       BOOL store_ok;
+/****************************************************************************
+ Do the authentication checks on an incoming pdu. Check sign and unseal etc.
+ ****************************************************************************/
 
-                       /* save the reply away, for use a little later */
-                       prs_copy_data_out((char *)ntlmssp_verf.data, &auth_verf, auth_len);
+static NTSTATUS cli_pipe_validate_rpc_response(struct rpc_pipe_client *cli, RPC_HDR *prhdr,
+                               prs_struct *current_pdu,
+                               uint8 *p_ss_padding_len)
+{
+       NTSTATUS ret = NT_STATUS_OK;
 
-                       store_ok = (NT_STATUS_IS_OK(ntlmssp_store_response(cli->ntlmssp_pipe_state, 
-                                                                          ntlmssp_verf)));
+       /* Paranioa checks for auth_len. */
+       if (prhdr->auth_len) {
+               if (prhdr->auth_len > prhdr->frag_len) {
+                       return NT_STATUS_INVALID_PARAMETER;
+               }
 
-                       data_blob_free(&ntlmssp_verf);
-                       return store_ok;
-               } 
-               else if (cli->pipe_auth_flags & AUTH_PIPE_NETSEC) {
-                       /* nothing to do here - we don't seem to be able to 
-                          validate the bindack based on VL's comments */
-                       return True;
+               if (prhdr->auth_len + RPC_HDR_AUTH_LEN < prhdr->auth_len ||
+                               prhdr->auth_len + RPC_HDR_AUTH_LEN < RPC_HDR_AUTH_LEN) {
+                       /* Integer wrap attempt. */
+                       return NT_STATUS_INVALID_PARAMETER;
                }
        }
-       
-       if (cli->pipe_auth_flags & AUTH_PIPE_NTLMSSP) {
-               NTSTATUS nt_status;
-               DATA_BLOB sig;
-               if ((cli->pipe_auth_flags & AUTH_PIPE_SIGN) ||
-                   (cli->pipe_auth_flags & AUTH_PIPE_SEAL)) {
-                       if (auth_len != RPC_AUTH_NTLMSSP_CHK_LEN) {
-                               DEBUG(0,("rpc_auth_pipe: wrong ntlmssp auth len %d\n", auth_len));
-                               return False;
+
+       /*
+        * Now we have a complete RPC request PDU fragment, try and verify any auth data.
+        */
+
+       switch(cli->auth.auth_type) {
+               case PIPE_AUTH_TYPE_NONE:
+                       if (prhdr->auth_len) {
+                               DEBUG(3, ("cli_pipe_validate_rpc_response: Connection to remote machine %s "
+                                       "pipe %s fnum 0x%x - got non-zero auth len %u.\n",
+                                       cli->cli->desthost,
+                                       cli->pipe_name,
+                                       (unsigned int)cli->fnum,
+                                       (unsigned int)prhdr->auth_len ));
+                               return NT_STATUS_INVALID_PARAMETER;
                        }
-                       sig = data_blob(NULL, auth_len);
-                       prs_copy_data_out((char *)sig.data, &auth_verf, auth_len);
-               }
-       
-               /*
-                * Unseal any sealed data in the PDU, not including the
-                * 8 byte auth_header or the auth_data.
-                */
+                       break;
 
-               /*
-                * Now unseal and check the auth verifier in the auth_data at
-                * the end of the packet. 
-                */
+               case PIPE_AUTH_TYPE_NTLMSSP:
+               case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
+                       ret = cli_pipe_verify_ntlmssp(cli, prhdr, current_pdu, p_ss_padding_len);
+                       if (!NT_STATUS_IS_OK(ret)) {
+                               return ret;
+                       }
+                       break;
 
-               if (cli->pipe_auth_flags & AUTH_PIPE_SEAL) {
-                       if (data_len < 0) {
-                               DEBUG(1, ("Can't unseal - data_len < 0!!\n"));
-                               return False;
+               case PIPE_AUTH_TYPE_SCHANNEL:
+                       ret = cli_pipe_verify_schannel(cli, prhdr, current_pdu, p_ss_padding_len);
+                       if (!NT_STATUS_IS_OK(ret)) {
+                               return ret;
                        }
-                       nt_status = ntlmssp_unseal_packet(cli->ntlmssp_pipe_state, 
-                                                                (unsigned char *)reply_data, data_len,
-                                                                &sig);
-               } 
-               else if (cli->pipe_auth_flags & AUTH_PIPE_SIGN) {
-                       nt_status = ntlmssp_check_packet(cli->ntlmssp_pipe_state, 
-                                                               (const unsigned char *)reply_data, data_len,
-                                                               &sig);
-               }
+                       break;
+
+               case PIPE_AUTH_TYPE_KRB5:
+               case PIPE_AUTH_TYPE_SPNEGO_KRB5:
+               default:
+                       DEBUG(3, ("cli_pipe_validate_rpc_response: Connection to remote machine %s "
+                               "pipe %s fnum %x - unknown internal auth type %u.\n",
+                               cli->cli->desthost,
+                               cli->pipe_name,
+                               (unsigned int)cli->fnum,
+                               cli->auth.auth_type ));
+                       return NT_STATUS_INVALID_INFO_CLASS;
+       }
 
-               data_blob_free(&sig);
+       return NT_STATUS_OK;
+}
 
-               if (!NT_STATUS_IS_OK(nt_status)) {
-                       DEBUG(0, ("rpc_auth_pipe: could not validate "
-                                 "incoming NTLMSSP packet!\n"));
-                       return False;
-               }
+/****************************************************************************
+ Do basic authentication checks on an incoming pdu.
+ ****************************************************************************/
+
+static NTSTATUS cli_pipe_validate_current_pdu(struct rpc_pipe_client *cli, RPC_HDR *prhdr,
+                       prs_struct *current_pdu,
+                       uint8 expected_pkt_type,
+                       char **ppdata,
+                       uint32 *pdata_len,
+                       prs_struct *return_data)
+{
+
+       NTSTATUS ret = NT_STATUS_OK;
+       uint32 current_pdu_len = prs_data_size(current_pdu);
+
+       if (current_pdu_len != prhdr->frag_len) {
+               DEBUG(5,("cli_pipe_validate_current_pdu: incorrect pdu length %u, expected %u\n",
+                       (unsigned int)current_pdu_len, (unsigned int)prhdr->frag_len ));
+               return NT_STATUS_INVALID_PARAMETER;
        }
 
-       if (cli->pipe_auth_flags & AUTH_PIPE_NETSEC) {
-               RPC_AUTH_NETSEC_CHK chk;
+       /*
+        * Point the return values at the real data including the RPC
+        * header. Just in case the caller wants it.
+        */
+       *ppdata = prs_data_p(current_pdu);
+       *pdata_len = current_pdu_len;
 
-               if ( (auth_len != RPC_AUTH_NETSEC_SIGN_OR_SEAL_CHK_LEN) 
-                       && (auth_len != RPC_AUTH_NETSEC_SIGN_ONLY_CHK_LEN)  ) 
-               {
-                       DEBUG(0,("rpc_auth_pipe: wrong schannel auth len %d\n", auth_len));
-                       return False;
-               }
+       /* Ensure we have the correct type. */
+       switch (prhdr->pkt_type) {
+               case RPC_ALTCONTRESP:
+               case RPC_BINDACK:
+
+                       /* Alter context and bind ack share the same packet definitions. */
+                       break;
 
-               /* can't seal with no nonce */
-               if ( (cli->pipe_auth_flags & AUTH_PIPE_SEAL)
-                       && (auth_len != RPC_AUTH_NETSEC_SIGN_OR_SEAL_CHK_LEN)  )
+
+               case RPC_RESPONSE:
                {
-                       DEBUG(0,("rpc_auth_pipe: sealing not supported with schannel auth len %d\n", auth_len));
-                       return False;
+                       RPC_HDR_RESP rhdr_resp;
+                       uint8 ss_padding_len = 0;
+
+                       if(!smb_io_rpc_hdr_resp("rpc_hdr_resp", &rhdr_resp, current_pdu, 0)) {
+                               DEBUG(5,("cli_pipe_validate_current_pdu: failed to unmarshal RPC_HDR_RESP.\n"));
+                               return NT_STATUS_BUFFER_TOO_SMALL;
+                       }
+
+                       /* Here's where we deal with incoming sign/seal. */
+                       ret = cli_pipe_validate_rpc_response(cli, prhdr,
+                                       current_pdu, &ss_padding_len);
+                       if (!NT_STATUS_IS_OK(ret)) {
+                               return ret;
+                       }
+
+                       /* Point the return values at the NDR data. Remember to remove any ss padding. */
+                       *ppdata = prs_data_p(current_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN;
+
+                       if (current_pdu_len < RPC_HEADER_LEN + RPC_HDR_RESP_LEN + ss_padding_len) {
+                               return NT_STATUS_BUFFER_TOO_SMALL;
+                       }
+
+                       *pdata_len = current_pdu_len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - ss_padding_len;
+
+                       /* Remember to remove the auth footer. */
+                       if (prhdr->auth_len) {
+                               /* We've already done integer wrap tests on auth_len in
+                                       cli_pipe_validate_rpc_response(). */
+                               if (*pdata_len < RPC_HDR_AUTH_LEN + prhdr->auth_len) {
+                                       return NT_STATUS_BUFFER_TOO_SMALL;
+                               }
+                               *pdata_len -= (RPC_HDR_AUTH_LEN + prhdr->auth_len);
+                       }
+
+                       DEBUG(10,("cli_pipe_validate_current_pdu: got pdu len %u, data_len %u, ss_len %u\n",
+                               current_pdu_len, *pdata_len, ss_padding_len ));
+
+                       /*
+                        * If this is the first reply, and the allocation hint is reasonably, try and
+                        * set up the return_data parse_struct to the correct size.
+                        */
+
+                       if ((prs_data_size(return_data) == 0) && rhdr_resp.alloc_hint && (rhdr_resp.alloc_hint < 15*1024*1024)) {
+                               if (!prs_set_buffer_size(return_data, rhdr_resp.alloc_hint)) {
+                                       DEBUG(0,("cli_pipe_validate_current_pdu: reply alloc hint %u "
+                                               "too large to allocate\n",
+                                               (unsigned int)rhdr_resp.alloc_hint ));
+                                       return NT_STATUS_NO_MEMORY;
+                               }
+                       }
+
+                       break;
                }
-               
 
-               if (!smb_io_rpc_auth_netsec_chk("schannel_auth_sign", auth_len, &chk, &auth_verf, 0)) 
+               case RPC_BINDNACK:
+                       DEBUG(1, ("cli_pipe_validate_current_pdu: Bind NACK received from remote machine %s "
+                               "pipe %s fnum 0x%x!\n",
+                               cli->cli->desthost,
+                               cli->pipe_name,
+                               (unsigned int)cli->fnum));
+                       /* Use this for now... */
+                       return NT_STATUS_NETWORK_ACCESS_DENIED;
+
+               case RPC_FAULT:
                {
-                       DEBUG(0, ("rpc_auth_pipe: schannel unmarshalling "
-                                 "RPC_AUTH_NETSECK_CHK failed\n"));
-                       return False;
-               }
+                       RPC_HDR_RESP rhdr_resp;
+                       RPC_HDR_FAULT fault_resp;
+
+                       if(!smb_io_rpc_hdr_resp("rpc_hdr_resp", &rhdr_resp, current_pdu, 0)) {
+                               DEBUG(5,("cli_pipe_validate_current_pdu: failed to unmarshal RPC_HDR_RESP.\n"));
+                               return NT_STATUS_BUFFER_TOO_SMALL;
+                       }
+
+                       if(!smb_io_rpc_hdr_fault("fault", &fault_resp, current_pdu, 0)) {
+                               DEBUG(5,("cli_pipe_validate_current_pdu: failed to unmarshal RPC_HDR_FAULT.\n"));
+                               return NT_STATUS_BUFFER_TOO_SMALL;
+                       }
 
-               if (!netsec_decode(&cli->auth_info,
-                                  cli->pipe_auth_flags,
-                                  SENDER_IS_ACCEPTOR,
-                                  &chk, reply_data, data_len)) {
-                       DEBUG(0, ("rpc_auth_pipe: Could not decode schannel\n"));
-                       return False;
+                       DEBUG(1, ("cli_pipe_validate_current_pdu: RPC fault code %s received from remote machine %s "
+                               "pipe %s fnum 0x%x!\n",
+                               nt_errstr(fault_resp.status),
+                               cli->cli->desthost,
+                               cli->pipe_name,
+                               (unsigned int)cli->fnum));
+                       if (NT_STATUS_IS_OK(fault_resp.status)) {
+                               return NT_STATUS_UNSUCCESSFUL;
+                       } else {
+                               return fault_resp.status;
+                       }
+                       
                }
 
-               cli->auth_info.seq_num++;
+               default:
+                       DEBUG(0, ("cli_pipe_validate_current_pdu: unknown packet type %u received "
+                               "from remote machine %s pipe %s fnum 0x%x!\n",
+                               (unsigned int)prhdr->pkt_type,
+                               cli->cli->desthost,
+                               cli->pipe_name,
+                               (unsigned int)cli->fnum));
+                       return NT_STATUS_INVALID_INFO_CLASS;
+       }
 
+       if (prhdr->pkt_type != expected_pkt_type) {
+               DEBUG(3, ("cli_pipe_validate_current_pdu: Connection to remote machine %s "
+                       "pipe %s fnum %x got an unexpected RPC packet "
+                       "type - %u, not %u\n",
+                       cli->cli->desthost,
+                       cli->pipe_name,
+                       (unsigned int)cli->fnum,
+                       prhdr->pkt_type,
+                       expected_pkt_type));
+               return NT_STATUS_INVALID_INFO_CLASS;
        }
-       return True;
+
+       /* Do this just before return - we don't want to modify any rpc header
+          data before now as we may have needed to do cryptographic actions on
+          it before. */
+
+       if ((prhdr->pkt_type == RPC_BINDACK) && !(prhdr->flags & RPC_FLG_LAST)) {
+               DEBUG(5,("cli_pipe_validate_current_pdu: bug in server (AS/U?), "
+                       "setting fragment first/last ON.\n"));
+               prhdr->flags |= RPC_FLG_FIRST|RPC_FLG_LAST;
+       }
+
+       return NT_STATUS_OK;
 }
 
+/****************************************************************************
+ Ensure we eat the just processed pdu from the current_pdu prs_struct.
+ Normally the frag_len and buffer size will match, but on the first trans
+ reply there is a theoretical chance that buffer size > frag_len, so we must
+ deal with that.
+ ****************************************************************************/
+
+static NTSTATUS cli_pipe_reset_current_pdu(struct rpc_pipe_client *cli, RPC_HDR *prhdr, prs_struct *current_pdu)
+{
+       uint32 current_pdu_len = prs_data_size(current_pdu);
+
+       if (current_pdu_len < prhdr->frag_len) {
+               return NT_STATUS_BUFFER_TOO_SMALL;
+       }
+
+       /* Common case. */
+       if (current_pdu_len == (uint32)prhdr->frag_len) {
+               prs_mem_free(current_pdu);
+               prs_init(current_pdu, 0, prs_get_mem_context(current_pdu), UNMARSHALL);
+               /* Make current_pdu dynamic with no memory. */
+               prs_give_memory(current_pdu, 0, 0, True);
+               return NT_STATUS_OK;
+       }
+
+       /*
+        * Oh no ! More data in buffer than we processed in current pdu.
+        * Cheat. Move the data down and shrink the buffer.
+        */
+
+       memcpy(prs_data_p(current_pdu), prs_data_p(current_pdu) + prhdr->frag_len,
+                       current_pdu_len - prhdr->frag_len);
+
+       /* Remember to set the read offset back to zero. */
+       prs_set_offset(current_pdu, 0);
+
+       /* Shrink the buffer. */
+       if (!prs_set_buffer_size(current_pdu, current_pdu_len - prhdr->frag_len)) {
+               return NT_STATUS_BUFFER_TOO_SMALL;
+       }
+
+       return NT_STATUS_OK;
+}
 
 /****************************************************************************
- Send data on an rpc pipe via trans, which *must* be the last fragment.
- receive response data from an rpc pipe, which may be large...
+ Send data on an rpc pipe via trans. The prs_struct data must be the last
+ pdu fragment of an NDR data stream.
+
+ Receive response data from an rpc pipe, which may be large...
 
  Read the first fragment: unfortunately have to use SMBtrans for the first
  bit, then SMBreadX for subsequent bits.
@@ -391,41 +730,50 @@ static BOOL rpc_auth_pipe(struct rpc_pipe_client *cli, prs_struct *rdata,
  | RPC HEADER | REQ/RESP HEADER | DATA ...... | AUTH_HDR      | AUTH DATA   |
  +------------+-----------------+-------------+---------------+-------------+
 
- Where the presence of the AUTH_HDR and AUTH are dependent on the
+ Where the presence of the AUTH_HDR and AUTH DATA are dependent on the
  signing & sealing being negotiated.
 
  ****************************************************************************/
 
-static BOOL rpc_api_pipe(struct rpc_pipe_client *cli, prs_struct *data, prs_struct *rdata,
-                        uint8 expected_pkt_type)
+static NTSTATUS rpc_api_pipe(struct rpc_pipe_client *cli,
+                       prs_struct *data, /* Outgoing pdu fragment, already formatted for send. */
+                       prs_struct *rbuf, /* Incoming reply - return as an NDR stream. */
+                       uint8 expected_pkt_type)
 {
-       uint32 len;
+       NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
        char *rparam = NULL;
        uint32 rparam_len = 0;
        uint16 setup[2];
-       BOOL first = True;
-       BOOL last  = True;
-       RPC_HDR rhdr;
        char *pdata = data ? prs_data_p(data) : NULL;
        uint32 data_len = data ? prs_offset(data) : 0;
        char *prdata = NULL;
        uint32 rdata_len = 0;
-       uint32 current_offset = 0;
-       uint32 fragment_start = 0;
        uint32 max_data = cli->max_xmit_frag ? cli->max_xmit_frag : 1024;
-       int auth_padding_len = 0;
+       uint32 current_rbuf_offset = 0;
+       prs_struct current_pdu;
+       
+#ifdef DEVELOPER
+       /* Ensure we're not sending too much. */
+       SMB_ASSERT(data_len <= max_data);
+#endif
 
-       /* Create setup parameters - must be in native byte order. */
+       /* Set up the current pdu parse struct. */
+       prs_init(&current_pdu, 0, prs_get_mem_context(rbuf), UNMARSHALL);
 
+       /* Create setup parameters - must be in native byte order. */
        setup[0] = TRANSACT_DCERPCCMD; 
        setup[1] = cli->fnum; /* Pipe file handle. */
 
-       DEBUG(5,("rpc_api_pipe: fnum:%x\n", (int)cli->fnum));
+       DEBUG(5,("rpc_api_pipe: Remote machine %s pipe %s fnum 0x%x\n",
+               cli->cli->desthost,
+               cli->pipe_name,
+               (unsigned int)cli->fnum ));
 
-       /* Send the RPC request and receive a response.  For short RPC
-          calls (about 1024 bytes or so) the RPC request and response
-          appears in a SMBtrans request and response.  Larger RPC
-          responses are received further on. */
+       /*
+        * Send the last (or only) fragment of an RPC request. For small
+        * amounts of data (about 1024 bytes or so) the RPC request and response
+        * appears in a SMBtrans request and response.
+        */
 
        if (!cli_api_pipe(cli->cli, "\\PIPE\\",
                  setup, 2, 0,                     /* Setup, length, max */
@@ -434,9 +782,14 @@ static BOOL rpc_api_pipe(struct rpc_pipe_client *cli, prs_struct *data, prs_stru
                  &rparam, &rparam_len,            /* return params, len */
                  &prdata, &rdata_len))            /* return data, len */
        {
-               DEBUG(0, ("cli_pipe: return critical error. Error was %s\n",
-                         cli_errstr(cli->cli)));
-               return False;
+               DEBUG(0, ("rpc_api_pipe: Remote machine %s pipe %s fnum 0x%x"
+                       "returned critical error. Error was %s\n",
+                       cli->cli->desthost,
+                       cli->pipe_name,
+                       (unsigned int)cli->fnum,
+                       cli_errstr(cli->cli)));
+               ret = cli_get_nt_error(cli->cli);
+               goto err;
        }
 
        /* Throw away returned params - we know we won't use them. */
@@ -444,327 +797,343 @@ static BOOL rpc_api_pipe(struct rpc_pipe_client *cli, prs_struct *data, prs_stru
        SAFE_FREE(rparam);
 
        if (prdata == NULL) {
-               DEBUG(0,("rpc_api_pipe: pipe %x failed to return data.\n",
-                       (int)cli->fnum));
-               return False;
+               DEBUG(3,("rpc_api_pipe: Remote machine %s pipe %s "
+                       "fnum 0x%x failed to return data.\n",
+                       cli->cli->desthost,
+                       cli->pipe_name,
+                       (unsigned int)cli->fnum));
+               /* Yes - some calls can truely return no data... */
+               prs_mem_free(&current_pdu);
+               return NT_STATUS_OK;
        }
 
        /*
-        * Give this memory as dynamically allocated to the return parse
-        * struct.  
+        * Give this memory as dynamic to the current pdu.
         */
 
-       prs_give_memory(rdata, prdata, rdata_len, True);
-       current_offset = rdata_len;
-
-       /* This next call sets the endian bit correctly in rdata. */
+       prs_give_memory(&current_pdu, prdata, rdata_len, True);
 
-       if (!rpc_check_hdr(rdata, &rhdr, &first, &last, &len)) {
-               prs_mem_free(rdata);
-               return False;
-       }
+       /* Ensure we can mess with the return prs_struct. */
+       SMB_ASSERT(UNMARSHALLING(rbuf));
+       SMB_ASSERT(prs_data_size(rbuf) == 0);
 
-       if (rhdr.pkt_type == RPC_BINDACK) {
-               if (!last && !first) {
-                       DEBUG(5,("rpc_api_pipe: bug in server (AS/U?), setting fragment first/last ON.\n"));
-                       first = True;
-                       last = True;
-               }
-       }
+       /* Make rbuf dynamic with no memory. */
+       prs_give_memory(rbuf, 0, 0, True);
 
-       if (rhdr.pkt_type == RPC_BINDNACK) {
-               DEBUG(3, ("Bind NACK received on pipe %x!\n", (int)cli->fnum));
-               prs_mem_free(rdata);
-               return False;
-       }
+       while(1) {
+               RPC_HDR rhdr;
+               char *ret_data;
+               uint32 ret_data_len;
 
-       if (rhdr.pkt_type == RPC_RESPONSE) {
-               RPC_HDR_RESP rhdr_resp;
-               if(!smb_io_rpc_hdr_resp("rpc_hdr_resp", &rhdr_resp, rdata, 0)) {
-                       DEBUG(5,("rpc_api_pipe: failed to unmarshal RPC_HDR_RESP.\n"));
-                       prs_mem_free(rdata);
-                       return False;
+               /* Ensure we have enough data for a pdu. */
+               ret = cli_pipe_get_current_pdu(cli, &rhdr, &current_pdu);
+               if (!NT_STATUS_IS_OK(ret)) {
+                       goto err;
                }
-       }
 
-       if (rhdr.pkt_type != expected_pkt_type) {
-               DEBUG(3, ("Connection to pipe %x got an unexpected RPC packet "
-                         "type - %d, not %d\n", (int)cli->fnum,
-                         rhdr.pkt_type, expected_pkt_type));
-               prs_mem_free(rdata);
-               return False;
-       }
+               /* We pass in rbuf here so if the alloc hint is set correctly 
+                  we can set the output size and avoid reallocs. */
+
+               ret = cli_pipe_validate_current_pdu(cli, &rhdr, &current_pdu, expected_pkt_type,
+                               &ret_data, &ret_data_len, rbuf);
 
-       DEBUG(5,("rpc_api_pipe: len left: %u smbtrans read: %u\n",
-                 (unsigned int)len, (unsigned int)rdata_len ));
+               DEBUG(10,("rpc_api_pipe: got PDU len of %u at offset %u\n",
+                       prs_data_size(&current_pdu), current_rbuf_offset ));
 
-       /* check if data to be sent back was too large for one SMBtrans */
-       /* err status is only informational: the _real_ check is on the
-           length */
+               if (!NT_STATUS_IS_OK(ret)) {
+                       goto err;
+               }
 
-       if (len > 0) { 
-               /* || err == (0x80000000 | STATUS_BUFFER_OVERFLOW)) */
+               if ((rhdr.flags & RPC_FLG_FIRST)) {
+                       if (rhdr.pack_type[0] == 0) {
+                               /* Set the data type correctly for big-endian data on the first packet. */
+                               DEBUG(10,("rpc_api_pipe: On machine %s pipe %s fnum 0x%x "
+                                       "PDU data format is big-endian.\n",
+                                       cli->cli->desthost,
+                                       cli->pipe_name,
+                                       (unsigned int)cli->fnum));
+
+                               prs_set_endian_data(rbuf, RPC_BIG_ENDIAN);
+                       } else {
+                               /* Check endianness on subsequent packets. */
+                               if (current_pdu.bigendian_data != rbuf->bigendian_data) {
+                                       DEBUG(0,("rpc_api_pipe: Error : Endianness changed from %s to %s\n",
+                                               rbuf->bigendian_data ? "big" : "little",
+                                               current_pdu.bigendian_data ? "big" : "little" ));
+                                       ret = NT_STATUS_INVALID_PARAMETER;
+                                       goto err;
+                               }
+                       }
+               }
 
-               /* Read the remaining part of the first response fragment */
+               /* Now copy the data portion out of the pdu into rbuf. */
+               if (!prs_force_grow(rbuf, ret_data_len)) {
+                        ret = NT_STATUS_NO_MEMORY;
+                        goto err;
+                }
+               memcpy(prs_data_p(rbuf)+current_rbuf_offset, ret_data, (size_t)ret_data_len);
+               current_rbuf_offset += ret_data_len;
+
+               /* See if we've finished with all the data in current_pdu yet ? */
+               ret = cli_pipe_reset_current_pdu(cli, &rhdr, &current_pdu);
+               if (!NT_STATUS_IS_OK(ret)) {
+                       goto err;
+               }
 
-               if (!rpc_read(cli, rdata, len, &current_offset)) {
-                       prs_mem_free(rdata);
-                       return False;
+               if (rhdr.flags & RPC_FLG_LAST) {
+                       break; /* We're done. */
                }
        }
 
-       /*
-        * Now we have a complete PDU, check the auth struct if any was sent.
-        */
+       DEBUG(10,("rpc_api_pipe: Remote machine %s pipe %s fnum 0x%x returned %u bytes.\n",
+               cli->cli->desthost,
+               cli->pipe_name,
+               (unsigned int)cli->fnum,
+               (unsigned int)prs_data_size(rbuf) ));
 
-       if(!rpc_auth_pipe(cli, rdata, fragment_start, rhdr.frag_len,
-                         rhdr.auth_len, rhdr.pkt_type, &auth_padding_len)) {
-               prs_mem_free(rdata);
-               return False;
-       }
+       prs_mem_free(&current_pdu);
+       return NT_STATUS_OK;
 
-       if (rhdr.auth_len != 0) {
-               /*
-                * Drop the auth footers from the current offset.
-                * We need this if there are more fragments.
-                * The auth footers consist of the auth_data and the
-                * preceeding 8 byte auth_header.
-                */
-               current_offset -= (auth_padding_len + RPC_HDR_AUTH_LEN + rhdr.auth_len);
-       }
-       
-       /* 
-        * Only one rpc fragment, and it has been read.
-        */
+  err:
 
-       if (first && last) {
-               DEBUG(6,("rpc_api_pipe: fragment first and last both set\n"));
-               return True;
-       }
+       prs_mem_free(&current_pdu);
+       prs_mem_free(rbuf);
+       return ret;
+}
 
-       /*
-        * Read more fragments using SMBreadX until we get one with the
-        * last bit set.
-        */
+/*******************************************************************
+ Creates krb5 auth bind.
+ ********************************************************************/
 
-       while (!last) {
-               RPC_HDR_RESP rhdr_resp;
-               int num_read;
-               char hdr_data[RPC_HEADER_LEN+RPC_HDR_RESP_LEN];
-               prs_struct hps;
-               uint8 eclass;
-               uint32 ecode;
-               
-               /*
-                * First read the header of the next PDU.
-                */
+static NTSTATUS create_krb5_auth_bind_req( struct rpc_pipe_client *cli,
+                                               enum pipe_auth_level auth_level,
+                                               RPC_HDR_AUTH *pauth_out,
+                                               prs_struct *auth_data)
+{
+#ifdef HAVE_KRB5
+       int ret;
+       struct kerberos_auth_struct *a = cli->auth.a_u.kerberos_auth;
+       DATA_BLOB tkt = data_blob(NULL, 0);
+       DATA_BLOB tkt_wrapped = data_blob(NULL, 0);
 
-               prs_init(&hps, 0, cli->cli->mem_ctx, UNMARSHALL);
-               prs_give_memory(&hps, hdr_data, sizeof(hdr_data), False);
+       /* We may change the pad length before marshalling. */
+       init_rpc_hdr_auth(pauth_out, RPC_KRB5_AUTH_TYPE, (int)auth_level, 0, 1);
 
-               num_read = cli_read(cli->cli, cli->fnum, hdr_data, 0,
-                                   RPC_HEADER_LEN+RPC_HDR_RESP_LEN);
-               if (cli_is_dos_error(cli->cli)) {
-                        cli_dos_error(cli->cli, &eclass, &ecode);
-                        if (eclass != ERRDOS && ecode != ERRmoredata) {
-                                DEBUG(0,("rpc_api_pipe: cli_read error : %d/%d\n", eclass, ecode));
-                                return False;
-                        }
-               }
+       DEBUG(5, ("create_krb5_auth_bind_req: creating a service ticket for principal %s\n",
+               a->service_principal ));
 
-               DEBUG(5,("rpc_api_pipe: read header (size:%d)\n", num_read));
+       /* Create the ticket for the service principal and return it in a gss-api wrapped blob. */
 
-               if (num_read != RPC_HEADER_LEN+RPC_HDR_RESP_LEN) {
-                       DEBUG(0,("rpc_api_pipe: Error : requested %d bytes, got %d.\n",
-                               RPC_HEADER_LEN+RPC_HDR_RESP_LEN, num_read ));
-                       return False;
-               }
+       ret = cli_krb5_get_ticket(a->service_principal, 0, &tkt,
+                       &a->session_key, (uint32)AP_OPTS_MUTUAL_REQUIRED);
 
-               /* This call sets the endianness in hps. */
+       if (ret) {
+               DEBUG(1,("create_krb5_auth_bind_req: cli_krb5_get_ticket for principal %s "
+                       "failed with %s\n",
+                       a->service_principal,
+                       error_message(ret) ));
 
-               if (!rpc_check_hdr(&hps, &rhdr, &first, &last, &len))
-                       return False;
+               data_blob_free(&tkt);
+               prs_mem_free(auth_data);
+               return NT_STATUS_INVALID_PARAMETER;
+       }
 
-               /* Ensure the endianness in rdata is set correctly - must be same as hps. */
+       /* wrap that up in a nice GSS-API wrapping */
+       tkt_wrapped = spnego_gen_krb5_wrap(tkt, TOK_ID_KRB_AP_REQ);
 
-               if (hps.bigendian_data != rdata->bigendian_data) {
-                       DEBUG(0,("rpc_api_pipe: Error : Endianness changed from %s to %s\n",
-                               rdata->bigendian_data ? "big" : "little",
-                               hps.bigendian_data ? "big" : "little" ));
-                       return False;
-               }
+       data_blob_free(&tkt);
 
-               if(!smb_io_rpc_hdr_resp("rpc_hdr_resp", &rhdr_resp, &hps, 0)) {
-                       DEBUG(0,("rpc_api_pipe: Error in unmarshalling RPC_HDR_RESP.\n"));
-                       return False;
-               }
+       /* Auth len in the rpc header doesn't include auth_header. */
+       if (!prs_copy_data_in(auth_data, (char *)tkt_wrapped.data, tkt_wrapped.length)) {
+               data_blob_free(&tkt_wrapped);
+               prs_mem_free(auth_data);
+               return NT_STATUS_NO_MEMORY;
+       }
 
-               if (first) {
-                       DEBUG(0,("rpc_api_pipe: secondary PDU rpc header has 'first' set !\n"));
-                       return False;
-               }
+       DEBUG(5, ("create_krb5_auth_bind_req: Created krb5 GSS blob :\n"));
+       dump_data(5, (const char *)tkt_wrapped.data, tkt_wrapped.length);
 
-               /*
-                * Now read the rest of the PDU.
-                */
+       data_blob_free(&tkt_wrapped);
+       return NT_STATUS_OK;
+#else
+       return NT_STATUS_INVALID_PARAMETER;
+#endif
+}
 
-               if (!rpc_read(cli, rdata, len, &current_offset)) {
-                       prs_mem_free(rdata);
-                       return False;
-               }
+/*******************************************************************
+ Creates SPNEGO NTLMSSP auth bind.
+ ********************************************************************/
+
+static NTSTATUS create_spnego_ntlmssp_auth_rpc_bind_req( struct rpc_pipe_client *cli,
+                                               enum pipe_auth_level auth_level,
+                                               RPC_HDR_AUTH *pauth_out,
+                                               prs_struct *auth_data)
+{
+       NTSTATUS nt_status;
+       DATA_BLOB null_blob = data_blob(NULL, 0);
+       DATA_BLOB request = data_blob(NULL, 0);
+       DATA_BLOB spnego_msg = data_blob(NULL, 0);
 
-               fragment_start = current_offset - len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN;
+       /* We may change the pad length before marshalling. */
+       init_rpc_hdr_auth(pauth_out, RPC_SPNEGO_AUTH_TYPE, (int)auth_level, 0, 1);
 
-               /*
-                * Verify any authentication footer.
-                */
+       DEBUG(5, ("create_spnego_ntlmssp_auth_rpc_bind_req: Processing NTLMSSP Negotiate\n"));
+       nt_status = ntlmssp_update(cli->auth.a_u.ntlmssp_state,
+                                       null_blob,
+                                       &request);
 
-               
-               if(!rpc_auth_pipe(cli, rdata, fragment_start, rhdr.frag_len,
-                                 rhdr.auth_len, rhdr.pkt_type, &auth_padding_len)) {
-                       prs_mem_free(rdata);
-                       return False;
-               }
-               
-               if (rhdr.auth_len != 0 ) {
-                       
-                       /*
-                        * Drop the auth footers from the current offset.
-                        * The auth footers consist of the auth_data and the
-                        * preceeding 8 byte auth_header.
-                        * We need this if there are more fragments.
-                        */
-                       current_offset -= (auth_padding_len + RPC_HDR_AUTH_LEN + rhdr.auth_len);
-               }
+       if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
+               data_blob_free(&request);
+               prs_mem_free(auth_data);
+               return nt_status;
        }
 
-       return True;
-}
+       /* Wrap this in SPNEGO. */
+       spnego_msg = gen_negTokenInit(OID_NTLMSSP, request);
 
-/*******************************************************************
- creates a DCE/RPC bind request
+       data_blob_free(&request);
 
- - initialises the parse structure.
- - dynamically allocates the header data structure
- - caller is expected to free the header data structure once used.
+       /* Auth len in the rpc header doesn't include auth_header. */
+       if (!prs_copy_data_in(auth_data, (char *)spnego_msg.data, spnego_msg.length)) {
+               data_blob_free(&spnego_msg);
+               prs_mem_free(auth_data);
+               return NT_STATUS_NO_MEMORY;
+       }
 
- ********************************************************************/
+       DEBUG(5, ("create_spnego_ntlmssp_auth_rpc_bind_req: NTLMSSP Negotiate:\n"));
+       dump_data(5, (const char *)spnego_msg.data, spnego_msg.length);
 
-static NTSTATUS create_rpc_bind_req(struct rpc_pipe_client *cli,
-                                   prs_struct *rpc_out, 
-                                   uint32 rpc_call_id,
-                                   RPC_IFACE *abstract, RPC_IFACE *transfer,
-                                   const char *my_name, const char *domain)
+       data_blob_free(&spnego_msg);
+       return NT_STATUS_OK;
+}
+
+/*******************************************************************
+ Creates NTLMSSP auth bind.
+ ********************************************************************/
+
+static NTSTATUS create_ntlmssp_auth_rpc_bind_req( struct rpc_pipe_client *cli,
+                                               enum pipe_auth_level auth_level,
+                                               RPC_HDR_AUTH *pauth_out,
+                                               prs_struct *auth_data)
 {
-       RPC_HDR hdr;
-       RPC_HDR_RB hdr_rb;
-       RPC_HDR_AUTH hdr_auth;
-       RPC_CONTEXT rpc_ctx;
-       int auth_len = 0;
-       int auth_type, auth_level;
-       size_t saved_hdr_offset = 0;
+       NTSTATUS nt_status;
+       DATA_BLOB null_blob = data_blob(NULL, 0);
+       DATA_BLOB request = data_blob(NULL, 0);
 
-       prs_struct auth_info;
-       prs_init(&auth_info, RPC_HDR_AUTH_LEN, /* we will need at least this much */
-               prs_get_mem_context(rpc_out), MARSHALL);
-
-       if (cli->pipe_auth_flags) {
-               get_auth_type_level(cli->pipe_auth_flags, &auth_type, &auth_level);
-               
-               /*
-                * Create the auth structs we will marshall.
-                */
-               
-               init_rpc_hdr_auth(&hdr_auth, auth_type, auth_level, 0x00, 1);
-               
-               /*
-                * Now marshall the data into the temporary parse_struct.
-                */
-               
-               if(!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, &auth_info, 0)) {
-                       DEBUG(0,("create_rpc_bind_req: failed to marshall RPC_HDR_AUTH.\n"));
-                       prs_mem_free(&auth_info);
-                       return NT_STATUS_NO_MEMORY;
-               }
-               saved_hdr_offset = prs_offset(&auth_info);
-       }
-       
-       if (cli->pipe_auth_flags & AUTH_PIPE_NTLMSSP) {
+       /* We may change the pad length before marshalling. */
+       init_rpc_hdr_auth(pauth_out, RPC_NTLMSSP_AUTH_TYPE, (int)auth_level, 0, 1);
 
-               NTSTATUS nt_status;
-               DATA_BLOB null_blob = data_blob(NULL, 0);
-               DATA_BLOB request;
+       DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: Processing NTLMSSP Negotiate\n"));
+       nt_status = ntlmssp_update(cli->auth.a_u.ntlmssp_state,
+                                       null_blob,
+                                       &request);
 
-               DEBUG(5, ("Processing NTLMSSP Negotiate\n"));
-               nt_status = ntlmssp_update(cli->ntlmssp_pipe_state,
-                                          null_blob,
-                                          &request);
+       if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
+               data_blob_free(&request);
+               prs_mem_free(auth_data);
+               return nt_status;
+       }
 
-               if (!NT_STATUS_EQUAL(nt_status, 
-                                    NT_STATUS_MORE_PROCESSING_REQUIRED)) {
-                       prs_mem_free(&auth_info);
-                       return nt_status;
-               }
+       /* Auth len in the rpc header doesn't include auth_header. */
+       if (!prs_copy_data_in(auth_data, (char *)request.data, request.length)) {
+               data_blob_free(&request);
+               prs_mem_free(auth_data);
+               return NT_STATUS_NO_MEMORY;
+       }
 
-               /* Auth len in the rpc header doesn't include auth_header. */
-               auth_len = request.length;
-               prs_copy_data_in(&auth_info, (char *)request.data, request.length);
+       DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: NTLMSSP Negotiate:\n"));
+       dump_data(5, (const char *)request.data, request.length);
 
-               DEBUG(5, ("NTLMSSP Negotiate:\n"));
-               dump_data(5, (const char *)request.data, request.length);
+       data_blob_free(&request);
+       return NT_STATUS_OK;
+}
 
-               data_blob_free(&request);
+/*******************************************************************
+ Creates schannel auth bind.
+ ********************************************************************/
 
-       } else if (cli->pipe_auth_flags & AUTH_PIPE_NETSEC) {
-               RPC_AUTH_NETSEC_NEG netsec_neg;
+static NTSTATUS create_schannel_auth_rpc_bind_req( struct rpc_pipe_client *cli,
+                                               enum pipe_auth_level auth_level,
+                                               RPC_HDR_AUTH *pauth_out,
+                                               prs_struct *auth_data)
+{
+       RPC_AUTH_SCHANNEL_NEG schannel_neg;
 
-               /* Use lp_workgroup() if domain not specified */
+       /* We may change the pad length before marshalling. */
+       init_rpc_hdr_auth(pauth_out, RPC_SCHANNEL_AUTH_TYPE, (int)auth_level, 0, 1);
 
-               if (!domain || !domain[0]) {
-                       DEBUG(10,("create_rpc_bind_req: no domain; assuming my own\n"));
-                       domain = lp_workgroup();
-               }
+       /* Use lp_workgroup() if domain not specified */
 
-               init_rpc_auth_netsec_neg(&netsec_neg, domain, my_name);
+       if (!cli->domain || !cli->domain[0]) {
+               cli->domain = lp_workgroup();
+       }
 
-               /*
-                * Now marshall the data into the temporary parse_struct.
-                */
+       init_rpc_auth_schannel_neg(&schannel_neg, cli->domain, global_myname());
 
-               if(!smb_io_rpc_auth_netsec_neg("netsec_neg",
-                                              &netsec_neg, &auth_info, 0)) {
-                       DEBUG(0,("Failed to marshall RPC_AUTH_NETSEC_NEG.\n"));
-                       prs_mem_free(&auth_info);
-                       return NT_STATUS_NO_MEMORY;
-               }
+       /*
+        * Now marshall the data into the auth parse_struct.
+        */
 
-               /* Auth len in the rpc header doesn't include auth_header. */
-               auth_len = prs_offset(&auth_info) - saved_hdr_offset;
+       if(!smb_io_rpc_auth_schannel_neg("schannel_neg",
+                                      &schannel_neg, auth_data, 0)) {
+               DEBUG(0,("Failed to marshall RPC_AUTH_SCHANNEL_NEG.\n"));
+               prs_mem_free(auth_data);
+               return NT_STATUS_NO_MEMORY;
        }
 
+       return NT_STATUS_OK;
+}
+
+/*******************************************************************
+ Creates the internals of a DCE/RPC bind request or alter context PDU.
+ ********************************************************************/
+
+static NTSTATUS create_bind_or_alt_ctx_internal(uint8 pkt_type,
+                                               prs_struct *rpc_out, 
+                                               uint32 rpc_call_id,
+                                               RPC_IFACE *abstract,
+                                               RPC_IFACE *transfer,
+                                               RPC_HDR_AUTH *phdr_auth,
+                                               prs_struct *pauth_info)
+{
+       RPC_HDR hdr;
+       RPC_HDR_RB hdr_rb;
+       RPC_CONTEXT rpc_ctx;
+       uint16 auth_len = prs_offset(pauth_info);
+       uint8 ss_padding_len = 0;
+       uint16 frag_len = 0;
+
        /* create the RPC context. */
-       init_rpc_context(&rpc_ctx, 0 /* context id */,
-                       abstract, transfer);
+       init_rpc_context(&rpc_ctx, 0 /* context id */, abstract, transfer);
 
        /* create the bind request RPC_HDR_RB */
-       init_rpc_hdr_rb(&hdr_rb, MAX_PDU_FRAG_LEN, MAX_PDU_FRAG_LEN, 0x0, &rpc_ctx);
+       init_rpc_hdr_rb(&hdr_rb, RPC_MAX_PDU_FRAG_LEN, RPC_MAX_PDU_FRAG_LEN, 0x0, &rpc_ctx);
+
+       /* Start building the frag length. */
+       frag_len = RPC_HEADER_LEN + RPC_HDR_RB_LEN(&hdr_rb);
+
+       /* Do we need to pad ? */
+       if (auth_len) {
+               uint16 data_len = RPC_HEADER_LEN + RPC_HDR_RB_LEN(&hdr_rb);
+               if (data_len % 8) {
+                       ss_padding_len = 8 - (data_len % 8);
+                       phdr_auth->auth_pad_len = ss_padding_len;
+               }
+               frag_len += RPC_HDR_AUTH_LEN + auth_len + ss_padding_len;
+       }
 
        /* Create the request RPC_HDR */
-       init_rpc_hdr(&hdr, RPC_BIND, 0x3, rpc_call_id, 
-               RPC_HEADER_LEN + RPC_HDR_RB_LEN(&hdr_rb) + prs_offset(&auth_info),
-               auth_len);
+       init_rpc_hdr(&hdr, pkt_type, RPC_FLG_FIRST|RPC_FLG_LAST, rpc_call_id, frag_len, auth_len);
 
        /* Marshall the RPC header */
        if(!smb_io_rpc_hdr("hdr"   , &hdr, rpc_out, 0)) {
-               DEBUG(0,("create_rpc_bind_req: failed to marshall RPC_HDR.\n"));
-               prs_mem_free(&auth_info);
+               DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR.\n"));
                return NT_STATUS_NO_MEMORY;
        }
 
        /* Marshall the bind request data */
        if(!smb_io_rpc_hdr_rb("", &hdr_rb, rpc_out, 0)) {
-               DEBUG(0,("create_rpc_bind_req: failed to marshall RPC_HDR_RB.\n"));
-               prs_mem_free(&auth_info);
+               DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_RB.\n"));
                return NT_STATUS_NO_MEMORY;
        }
 
@@ -773,363 +1142,453 @@ static NTSTATUS create_rpc_bind_req(struct rpc_pipe_client *cli,
         */
 
        if(auth_len != 0) {
-               if(!prs_append_prs_data( rpc_out, &auth_info)) {
-                       DEBUG(0,("create_rpc_bind_req: failed to grow parse struct to add auth.\n"));
-                       prs_mem_free(&auth_info);
+               if (ss_padding_len) {
+                       unsigned char pad[8];
+                       memset(pad, '\0', 8);
+                       if (!prs_copy_data_in(rpc_out, pad, ss_padding_len)) {
+                               DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall padding.\n"));
+                               return NT_STATUS_NO_MEMORY;
+                       }
+               }
+
+               if(!smb_io_rpc_hdr_auth("hdr_auth", phdr_auth, rpc_out, 0)) {
+                       DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_AUTH.\n"));
+                       return NT_STATUS_NO_MEMORY;
+               }
+
+
+               if(!prs_append_prs_data( rpc_out, pauth_info)) {
+                       DEBUG(0,("create_bind_or_alt_ctx_internal: failed to grow parse struct to add auth.\n"));
                        return NT_STATUS_NO_MEMORY;
                }
        }
-       prs_mem_free(&auth_info);
+
        return NT_STATUS_OK;
 }
 
 /*******************************************************************
- Creates a DCE/RPC bind authentication response.
- This is the packet that is sent back to the server once we
- have received a BIND-ACK, to finish the third leg of
- the authentication handshake.
+ Creates a DCE/RPC bind request.
  ********************************************************************/
 
-static NTSTATUS create_rpc_bind_resp(struct rpc_pipe_client *cli,
-                                uint32 rpc_call_id,
-                                prs_struct *rpc_out)
+static NTSTATUS create_rpc_bind_req(struct rpc_pipe_client *cli,
+                               prs_struct *rpc_out, 
+                               uint32 rpc_call_id,
+                               RPC_IFACE *abstract, RPC_IFACE *transfer,
+                               enum pipe_auth_type auth_type,
+                               enum pipe_auth_level auth_level)
 {
-       NTSTATUS nt_status;
-       RPC_HDR hdr;
        RPC_HDR_AUTH hdr_auth;
-       RPC_HDR_AUTHA hdr_autha;
-       DATA_BLOB ntlmssp_null_response = data_blob(NULL, 0);
-       DATA_BLOB ntlmssp_reply;
-       int auth_type, auth_level;
-
-       /* The response is picked up from the internal cache,
-          where it was placed by the rpc_auth_pipe() code */
-       nt_status = ntlmssp_update(cli->ntlmssp_pipe_state,
-                                  ntlmssp_null_response,
-                                  &ntlmssp_reply);
-       
-       if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
-               return nt_status;
-       }
+       prs_struct auth_info;
+       NTSTATUS ret = NT_STATUS_OK;
 
-       /* Create the request RPC_HDR */
-       init_rpc_hdr(&hdr, RPC_BINDRESP, 0x0, rpc_call_id,
-                    RPC_HEADER_LEN + RPC_HDR_AUTHA_LEN + ntlmssp_reply.length,
-                    ntlmssp_reply.length );
-       
-       /* Marshall it. */
-       if(!smb_io_rpc_hdr("hdr", &hdr, rpc_out, 0)) {
-               DEBUG(0,("create_rpc_bind_resp: failed to marshall RPC_HDR.\n"));
-               data_blob_free(&ntlmssp_reply);
-               return NT_STATUS_NO_MEMORY;
-       }
+       ZERO_STRUCT(hdr_auth);
+       prs_init(&auth_info, RPC_HDR_AUTH_LEN, prs_get_mem_context(rpc_out), MARSHALL);
 
-       get_auth_type_level(cli->pipe_auth_flags, &auth_type, &auth_level);
-       
-       /* Create the request RPC_HDR_AUTHA */
-       init_rpc_hdr_auth(&hdr_auth, auth_type, auth_level, 0, 0x0014a0c0);
-       init_rpc_hdr_autha(&hdr_autha, MAX_PDU_FRAG_LEN, MAX_PDU_FRAG_LEN, &hdr_auth);
+       switch (auth_type) {
+               case PIPE_AUTH_TYPE_SCHANNEL:
+                       ret = create_schannel_auth_rpc_bind_req(cli, auth_level, &hdr_auth, &auth_info);
+                       if (!NT_STATUS_IS_OK(ret)) {
+                               prs_mem_free(&auth_info);
+                               return ret;
+                       }
+                       break;
 
-       if(!smb_io_rpc_hdr_autha("hdr_autha", &hdr_autha, rpc_out, 0)) {
-               DEBUG(0,("create_rpc_bind_resp: failed to marshall RPC_HDR_AUTHA.\n"));
-               data_blob_free(&ntlmssp_reply);
-               return NT_STATUS_NO_MEMORY;
-       }
+               case PIPE_AUTH_TYPE_NTLMSSP:
+                       ret = create_ntlmssp_auth_rpc_bind_req(cli, auth_level, &hdr_auth, &auth_info);
+                       if (!NT_STATUS_IS_OK(ret)) {
+                               prs_mem_free(&auth_info);
+                               return ret;
+                       }
+                       break;
 
-       /*
-        * Append the auth data to the outgoing buffer.
-        */
+               case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
+                       ret = create_spnego_ntlmssp_auth_rpc_bind_req(cli, auth_level, &hdr_auth, &auth_info);
+                       if (!NT_STATUS_IS_OK(ret)) {
+                               prs_mem_free(&auth_info);
+                               return ret;
+                       }
+                       break;
 
-       if(!prs_copy_data_in(rpc_out, (char *)ntlmssp_reply.data, ntlmssp_reply.length)) {
-               DEBUG(0,("create_rpc_bind_req: failed to grow parse struct to add auth.\n"));
-               data_blob_free(&ntlmssp_reply);
-               return NT_STATUS_NO_MEMORY;
+               case PIPE_AUTH_TYPE_KRB5:
+                       ret = create_krb5_auth_bind_req(cli, auth_level, &hdr_auth, &auth_info);
+                       if (!NT_STATUS_IS_OK(ret)) {
+                               prs_mem_free(&auth_info);
+                               return ret;
+                       }
+                       break;
+
+               case PIPE_AUTH_TYPE_NONE:
+                       break;
+
+               default:
+                       /* "Can't" happen. */
+                       return NT_STATUS_INVALID_INFO_CLASS;
        }
 
-       data_blob_free(&ntlmssp_reply);
-       return NT_STATUS_OK;
-}
+       ret = create_bind_or_alt_ctx_internal(RPC_BIND,
+                                               rpc_out, 
+                                               rpc_call_id,
+                                               abstract,
+                                               transfer,
+                                               &hdr_auth,
+                                               &auth_info);
 
+       prs_mem_free(&auth_info);
+       return ret;
+}
 
 /*******************************************************************
- Creates a DCE/RPC request.
+ Create and add the NTLMSSP sign/seal auth header and data.
  ********************************************************************/
 
-static uint32 create_rpc_request(prs_struct *rpc_out, uint8 op_num, int data_len, int auth_len, uint8 flags, uint32 oldid, uint32 data_left)
+static NTSTATUS add_ntlmssp_auth_footer(struct rpc_pipe_client *cli,
+                                       RPC_HDR *phdr,
+                                       uint32 ss_padding_len,
+                                       prs_struct *outgoing_pdu)
 {
-       uint32 alloc_hint;
-       RPC_HDR     hdr;
-       RPC_HDR_REQ hdr_req;
-       uint32 callid = oldid ? oldid : get_rpc_call_id();
+       RPC_HDR_AUTH auth_info;
+       NTSTATUS status;
+       DATA_BLOB auth_blob = data_blob(NULL, 0);
+       uint16 data_and_pad_len = prs_offset(outgoing_pdu) - RPC_HEADER_LEN - RPC_HDR_RESP_LEN;
 
-       DEBUG(5,("create_rpc_request: opnum: 0x%x data_len: 0x%x\n", op_num, data_len));
+       if (!cli->auth.a_u.ntlmssp_state) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
 
-       /* create the rpc header RPC_HDR */
-       init_rpc_hdr(&hdr, RPC_REQUEST, flags,
-                    callid, data_len, auth_len);
+       /* Init and marshall the auth header. */
+       init_rpc_hdr_auth(&auth_info,
+                       map_pipe_auth_type_to_rpc_auth_type(cli->auth.auth_type),
+                       cli->auth.auth_level,
+                       ss_padding_len,
+                       1 /* context id. */);
 
-       /*
-        * The alloc hint should be the amount of data, not including 
-        * RPC headers & footers.
-        */
+       if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, outgoing_pdu, 0)) {
+               DEBUG(0,("add_ntlmssp_auth_footer: failed to marshall RPC_HDR_AUTH.\n"));
+               data_blob_free(&auth_blob);
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       switch (cli->auth.auth_level) {
+               case PIPE_AUTH_LEVEL_PRIVACY:
+                       /* Data portion is encrypted. */
+                       status = ntlmssp_seal_packet(cli->auth.a_u.ntlmssp_state,
+                                       prs_data_p(outgoing_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN,
+                                       data_and_pad_len,
+                                       prs_data_p(outgoing_pdu),
+                                       (size_t)prs_offset(outgoing_pdu),
+                                       &auth_blob);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               data_blob_free(&auth_blob);
+                               return status;
+                       }
+                       break;
+
+               case PIPE_AUTH_LEVEL_INTEGRITY:
+                       /* Data is signed. */
+                       status = ntlmssp_sign_packet(cli->auth.a_u.ntlmssp_state,
+                                       prs_data_p(outgoing_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN,
+                                       data_and_pad_len,
+                                       prs_data_p(outgoing_pdu),
+                                       (size_t)prs_offset(outgoing_pdu),
+                                       &auth_blob);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               data_blob_free(&auth_blob);
+                               return status;
+                       }
+                       break;
+
+               default:
+                       /* Can't happen. */
+                       smb_panic("bad auth level");
+                       /* Notreached. */
+                       return NT_STATUS_INVALID_PARAMETER;
+       }
 
-       if (auth_len != 0)
-               alloc_hint = data_len - RPC_HEADER_LEN - RPC_HDR_AUTH_LEN - auth_len;
-       else
-               alloc_hint = data_len - RPC_HEADER_LEN;
+       /* Finally marshall the blob. */
+                                                                                                      
+       if (!prs_copy_data_in(outgoing_pdu, auth_blob.data, NTLMSSP_SIG_SIZE)) {
+               DEBUG(0,("add_ntlmssp_auth_footer: failed to add %u bytes auth blob.\n",
+                       (unsigned int)NTLMSSP_SIG_SIZE));
+               data_blob_free(&auth_blob);
+               return NT_STATUS_NO_MEMORY;
+       }
+                                                                                                                                
+       data_blob_free(&auth_blob);
+       return NT_STATUS_OK;
+}
 
-       DEBUG(10,("create_rpc_request: data_len: %x auth_len: %x alloc_hint: %x\n",
-                  data_len, auth_len, alloc_hint));
+/*******************************************************************
+ Create and add the schannel sign/seal auth header and data.
+ ********************************************************************/
 
-       /* Create the rpc request RPC_HDR_REQ */
-       init_rpc_hdr_req(&hdr_req, alloc_hint, op_num);
+static NTSTATUS add_schannel_auth_footer(struct rpc_pipe_client *cli,
+                                       RPC_HDR *phdr,
+                                       uint32 ss_padding_len,
+                                       prs_struct *outgoing_pdu)
+{
+       RPC_HDR_AUTH auth_info;
+       RPC_AUTH_SCHANNEL_CHK verf;
+       struct schannel_auth_struct *sas = cli->auth.a_u.schannel_auth;
+       char *data_p = prs_data_p(outgoing_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN;
+       size_t data_and_pad_len = prs_offset(outgoing_pdu) - RPC_HEADER_LEN - RPC_HDR_RESP_LEN;
+
+       if (!sas) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
 
-       /* stream-time... */
-       if(!smb_io_rpc_hdr("hdr    ", &hdr, rpc_out, 0))
-               return 0;
+       /* Init and marshall the auth header. */
+       init_rpc_hdr_auth(&auth_info,
+                       map_pipe_auth_type_to_rpc_auth_type(cli->auth.auth_type),
+                       cli->auth.auth_level,
+                       ss_padding_len,
+                       1 /* context id. */);
 
-       if(!smb_io_rpc_hdr_req("hdr_req", &hdr_req, rpc_out, 0))
-               return 0;
+       if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, outgoing_pdu, 0)) {
+               DEBUG(0,("add_schannel_auth_footer: failed to marshall RPC_HDR_AUTH.\n"));
+               return NT_STATUS_NO_MEMORY;
+       }
 
-       if (prs_offset(rpc_out) != RPC_HEADER_LEN + RPC_HDR_REQ_LEN)
-               return 0;
+       switch (cli->auth.auth_level) {
+               case PIPE_AUTH_LEVEL_PRIVACY:
+               case PIPE_AUTH_LEVEL_INTEGRITY:
+                       DEBUG(10,("add_schannel_auth_footer: SCHANNEL seq_num=%d\n",
+                               sas->seq_num));
+
+                       schannel_encode(sas,
+                                       cli->auth.auth_level,
+                                       SENDER_IS_INITIATOR,
+                                       &verf,
+                                       data_p,
+                                       data_and_pad_len);
+
+                       sas->seq_num++;
+                       break;
+
+               default:
+                       /* Can't happen. */
+                       smb_panic("bad auth level");
+                       /* Notreached. */
+                       return NT_STATUS_INVALID_PARAMETER;
+       }
 
-       return callid;
+       /* Finally marshall the blob. */
+       smb_io_rpc_auth_schannel_chk("",
+                       RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN,
+                       &verf,
+                       outgoing_pdu,
+                       0);
+                                                                                               
+       return NT_STATUS_OK;
 }
 
 /*******************************************************************
- Puts an auth header into an rpc request.
+ Calculate how much data we're going to send in this packet, also
+ work out any sign/seal padding length.
  ********************************************************************/
 
-static BOOL create_auth_hdr(prs_struct *outgoing_packet, 
-                           int auth_type, 
-                           int auth_level, int padding)
+static uint32 calculate_data_len_tosend(struct rpc_pipe_client *cli,
+                                       uint32 data_left,
+                                       uint16 *p_frag_len,
+                                       uint16 *p_auth_len,
+                                       uint32 *p_ss_padding)
 {
-       RPC_HDR_AUTH hdr_auth;
+       uint32 data_space, data_len;
+
+       switch (cli->auth.auth_level) {
+               case PIPE_AUTH_LEVEL_NONE:
+               case PIPE_AUTH_LEVEL_CONNECT:
+                       data_space = cli->max_xmit_frag - RPC_HEADER_LEN - RPC_HDR_REQ_LEN;
+                       data_len = MIN(data_space, data_left);
+                       *p_ss_padding = 0;
+                       *p_auth_len = 0;
+                       *p_frag_len = RPC_HEADER_LEN + RPC_HDR_REQ_LEN + data_len;
+                       return data_len;
+
+               case PIPE_AUTH_LEVEL_INTEGRITY:
+               case PIPE_AUTH_LEVEL_PRIVACY:
+                       /* Treat the same for all authenticated rpc requests. */
+                       switch(cli->auth.auth_type) {
+                               case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
+                               case PIPE_AUTH_TYPE_NTLMSSP:
+                                       *p_auth_len = NTLMSSP_SIG_SIZE;
+                                       break;
+                               case PIPE_AUTH_TYPE_SCHANNEL:
+                                       *p_auth_len = RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN;
+                                       break;
+                               default:
+                                       smb_panic("bad auth type");
+                                       break;
+                       }
 
-       init_rpc_hdr_auth(&hdr_auth, auth_type, auth_level,
-                         padding, 1);
-       if(!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, 
-                               outgoing_packet, 0)) {
-               DEBUG(0,("create_auth_hdr:Failed to marshal RPC_HDR_AUTH.\n"));
-               return False;
+                       data_space = cli->max_xmit_frag - RPC_HEADER_LEN - RPC_HDR_REQ_LEN -
+                                               RPC_HDR_AUTH_LEN - *p_auth_len;
+
+                       data_len = MIN(data_space, data_left);
+                       if (data_len % 8) {
+                               *p_ss_padding = 8 - (data_len % 8);
+                       }
+                       *p_frag_len = RPC_HEADER_LEN + RPC_HDR_REQ_LEN +                /* Normal headers. */
+                                       data_len + *p_ss_padding +              /* data plus padding. */
+                                       RPC_HDR_AUTH_LEN + *p_auth_len;         /* Auth header and auth data. */
+                       return data_len;
+
+               default:
+                       smb_panic("bad auth level");
+                       /* Notreached. */
+                       return 0;
        }
-       return True;
 }
 
-/**
* Send a request on an RPC pipe and get a response.
- *
- * @param data NDR contents of the request to be sent.
* @param rdata Unparsed NDR response data.
-**/
+/*******************************************************************
External interface.
+ Does an rpc request on a pipe. Incoming data is NDR encoded in in_data.
+ Reply is NDR encoded in out_data. Splits the data stream into RPC PDU's
and deals with signing/sealing details.
+ ********************************************************************/
 
-BOOL rpc_api_pipe_req_int(struct rpc_pipe_client *cli, uint8 op_num,
-                         prs_struct *data, prs_struct *rdata)
+NTSTATUS rpc_api_pipe_req(struct rpc_pipe_client *cli,
+                       uint8 op_num,
+                       prs_struct *in_data,
+                       prs_struct *out_data)
 {
-       uint32 auth_len, real_auth_len, auth_hdr_len, max_data, data_left, data_sent;
-       NTSTATUS nt_status;
-       BOOL ret = False;
-       uint32 callid = 0;
-       fstring dump_name;
-
-       auth_len = 0;
-       real_auth_len = 0;
-       auth_hdr_len = 0;
+       NTSTATUS ret;
+       uint32 data_left = prs_offset(in_data);
+       uint32 alloc_hint = prs_offset(in_data);
+       uint32 data_sent_thistime = 0;
+       uint32 current_data_offset = 0;
+       uint32 call_id = get_rpc_call_id();
+       char pad[8];
+       prs_struct outgoing_pdu;
+
+       memset(pad, '\0', 8);
+
+       if (cli->max_xmit_frag < RPC_HEADER_LEN + RPC_HDR_REQ_LEN + RPC_MAX_SIGN_SIZE) {
+               /* Server is screwed up ! */
+               return NT_STATUS_INVALID_PARAMETER;
+       }
 
-       if (cli->pipe_auth_flags & AUTH_PIPE_SIGN) {    
-               if (cli->pipe_auth_flags & AUTH_PIPE_NTLMSSP) { 
-                       auth_len = RPC_AUTH_NTLMSSP_CHK_LEN;
-               }
-               if (cli->pipe_auth_flags & AUTH_PIPE_NETSEC) {  
-                       auth_len = RPC_AUTH_NETSEC_SIGN_OR_SEAL_CHK_LEN;
-               }
-               auth_hdr_len = RPC_HDR_AUTH_LEN;
+       if (data_left == 0) {
+               /* Caller is screwed up ! */
+               return NT_STATUS_INVALID_PARAMETER;
        }
 
-       /*
-        * calc how much actual data we can send in a PDU fragment
-        */
-       max_data = cli->max_xmit_frag - RPC_HEADER_LEN - RPC_HDR_REQ_LEN -
-               auth_hdr_len - auth_len - 8;
-       
-       for (data_left = prs_offset(data), data_sent = 0; data_left > 0;) {
-               prs_struct outgoing_packet;
-               prs_struct sec_blob;
-               uint32 data_len, send_size;
+       prs_init(&outgoing_pdu, cli->max_xmit_frag, prs_get_mem_context(in_data), MARSHALL);
+
+       while (1) {
+               RPC_HDR hdr;
+               RPC_HDR_REQ hdr_req;
+               uint16 auth_len = 0;
+               uint16 frag_len = 0;
                uint8 flags = 0;
-               uint32 auth_padding = 0;
-               DATA_BLOB sign_blob;
+               uint32 ss_padding = 0;
 
-               /*
-                * how much will we send this time
-                */
-               send_size = MIN(data_left, max_data);
+               data_sent_thistime = calculate_data_len_tosend(cli, data_left,
+                                               &frag_len, &auth_len, &ss_padding);
 
-               if (!prs_init(&sec_blob, send_size, /* will need at least this much */
-                             cli->cli->mem_ctx, MARSHALL)) {
-                       DEBUG(0,("Could not malloc %u bytes",
-                                send_size+auth_padding));
-                       return False;
+               if (current_data_offset == 0) {
+                       flags = RPC_FLG_FIRST;
                }
 
-               if(!prs_append_some_prs_data(&sec_blob, data, 
-                                            data_sent, send_size)) {
-                       DEBUG(0,("Failed to append data to netsec blob\n"));
-                       prs_mem_free(&sec_blob);
-                       return False;
+               if (data_sent_thistime == data_left) {
+                       flags |= RPC_FLG_LAST;
                }
 
-               /*
-                * NT expects the data that is sealed to be 8-byte
-                * aligned. The padding must be encrypted as well and
-                * taken into account when generating the
-                * authentication verifier. The amount of padding must
-                * be stored in the auth header.
-                */
+               /* Create and marshall the header and request header. */
+               init_rpc_hdr(&hdr, RPC_REQUEST, flags, call_id, frag_len, auth_len);
 
-               if (cli->pipe_auth_flags) {
-                       size_t data_and_padding_size;
-                       int auth_type;
-                       int auth_level;
-                       prs_align_uint64(&sec_blob);
+               if(!smb_io_rpc_hdr("hdr    ", &hdr, &outgoing_pdu, 0)) {
+                       prs_mem_free(&outgoing_pdu);
+                       return NT_STATUS_NO_MEMORY;
+               }
 
-                       get_auth_type_level(cli->pipe_auth_flags, &auth_type, &auth_level);
+               /* Create the rpc request RPC_HDR_REQ */
+               init_rpc_hdr_req(&hdr_req, alloc_hint, op_num);
+
+               if(!smb_io_rpc_hdr_req("hdr_req", &hdr_req, &outgoing_pdu, 0)) {
+                       prs_mem_free(&outgoing_pdu);
+                       return NT_STATUS_NO_MEMORY;
+               }
 
-                       data_and_padding_size = prs_offset(&sec_blob);
-                       auth_padding = data_and_padding_size - send_size;
+               /* Copy in the data, plus any ss padding. */
+               if (!prs_append_some_prs_data(&outgoing_pdu, in_data, current_data_offset, data_sent_thistime)) {
+                       prs_mem_free(&outgoing_pdu);
+                       return NT_STATUS_NO_MEMORY;
+               }
 
-                       /* insert the auth header */
-                       
-                       if(!create_auth_hdr(&sec_blob, auth_type, auth_level, auth_padding)) {
-                               prs_mem_free(&sec_blob);
-                               return False;
+               /* Copy the sign/seal padding data. */
+               if (ss_padding) {
+                       if (!prs_copy_data_in(&outgoing_pdu, pad, ss_padding)) {
+                               prs_mem_free(&outgoing_pdu);
+                               return NT_STATUS_NO_MEMORY;
                        }
-                       
-                       /* create an NTLMSSP signature */
-                       if (cli->pipe_auth_flags & AUTH_PIPE_NTLMSSP) {
-                               /*
-                                * Seal the outgoing data if requested.
-                                */
-                               if (cli->pipe_auth_flags & AUTH_PIPE_SEAL) {
-                                       
-                                       nt_status = ntlmssp_seal_packet(cli->ntlmssp_pipe_state,
-                                                                              (unsigned char*)prs_data_p(&sec_blob),
-                                                                              data_and_padding_size,
-                                                                              &sign_blob);
-                                       if (!NT_STATUS_IS_OK(nt_status)) {
-                                               prs_mem_free(&sec_blob);
-                                               return False;
+               }
+
+               /* Generate any auth sign/seal and add the auth footer. */
+               if (auth_len) {
+                       switch (cli->auth.auth_type) {
+                               case PIPE_AUTH_TYPE_NONE:
+                                       break;
+                               case PIPE_AUTH_TYPE_NTLMSSP:
+                               case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
+                                       ret = add_ntlmssp_auth_footer(cli, &hdr, ss_padding, &outgoing_pdu);
+                                       if (!NT_STATUS_IS_OK(ret)) {
+                                               prs_mem_free(&outgoing_pdu);
+                                               return ret;
                                        }
-                               } 
-                               else if (cli->pipe_auth_flags & AUTH_PIPE_SIGN) {
-                                       
-                                       nt_status = ntlmssp_sign_packet(cli->ntlmssp_pipe_state,
-                                                                              (unsigned char*)prs_data_p(&sec_blob),
-                                                                              data_and_padding_size, &sign_blob);
-                                       if (!NT_STATUS_IS_OK(nt_status)) {
-                                               prs_mem_free(&sec_blob);
-                                               return False;
+                                       break;
+                               case PIPE_AUTH_TYPE_SCHANNEL:
+                                       ret = add_schannel_auth_footer(cli, &hdr, ss_padding, &outgoing_pdu);
+                                       if (!NT_STATUS_IS_OK(ret)) {
+                                               prs_mem_free(&outgoing_pdu);
+                                               return ret;
                                        }
-                               }
-                               
-
-                               /* write auth footer onto the packet */
-                               real_auth_len = sign_blob.length;
-                               
-                               prs_copy_data_in(&sec_blob, (char *)sign_blob.data, sign_blob.length);
-                               data_blob_free(&sign_blob);
-
-                       }
-                       else if (cli->pipe_auth_flags & AUTH_PIPE_NETSEC) {     
-                               size_t parse_offset_marker;
-                               RPC_AUTH_NETSEC_CHK verf;
-                               DEBUG(10,("SCHANNEL seq_num=%d\n", cli->auth_info.seq_num));
-                               
-                               netsec_encode(&cli->auth_info, 
-                                             cli->pipe_auth_flags,
-                                             SENDER_IS_INITIATOR,
-                                             &verf,
-                                             prs_data_p(&sec_blob),
-                                             data_and_padding_size);
-
-                               cli->auth_info.seq_num++;
-
-                               /* write auth footer onto the packet */
-                               
-                               parse_offset_marker = prs_offset(&sec_blob);
-                               if (!smb_io_rpc_auth_netsec_chk("", RPC_AUTH_NETSEC_SIGN_OR_SEAL_CHK_LEN, 
-                                       &verf, &sec_blob, 0)) 
-                               {
-                                       prs_mem_free(&sec_blob);
-                                       return False;
-                               }
-                               real_auth_len = prs_offset(&sec_blob) - parse_offset_marker;
+                                       break;
+                               default:
+                                       smb_panic("bad auth type");
+                                       break; /* notreached */
                        }
                }
 
-               data_len = RPC_HEADER_LEN + RPC_HDR_REQ_LEN + prs_offset(&sec_blob);
+               /* Actually send the packet. */
+               if (flags & RPC_FLG_LAST) {
+                       /* Last packet - send the data, get the reply and return. */
+                       ret = rpc_api_pipe(cli, &outgoing_pdu, out_data, RPC_RESPONSE);
+                       prs_mem_free(&outgoing_pdu);
 
-               /*
-                * Malloc parse struct to hold it (and enough for alignments).
-                */
-               if(!prs_init(&outgoing_packet, data_len + 8, 
-                            cli->cli->mem_ctx, MARSHALL)) {
-                       DEBUG(0,("rpc_api_pipe_req: Failed to malloc %u bytes.\n", (unsigned int)data_len ));
-                       return False;
-               }
-
-               if (data_left == prs_offset(data))
-                       flags |= RPC_FLG_FIRST;
+                       
+                       if (DEBUGLEVEL >= 50) {
+                               pstring dump_name;
+                               /* Also capture received data */
+                               slprintf(dump_name, sizeof(dump_name) - 1, "%s/reply_%s_%d",
+                                       dyn_LOGFILEBASE, cli->pipe_name, op_num);
+                               prs_dump(dump_name, op_num, out_data);
+                       }
 
-               if (data_left <= max_data)
-                       flags |= RPC_FLG_LAST;
-               /*
-                * Write out the RPC header and the request header.
-                */
-               if(!(callid = create_rpc_request(&outgoing_packet, op_num, 
-                                                data_len, real_auth_len, flags, 
-                                                callid, data_left))) {
-                       DEBUG(0,("rpc_api_pipe_req: Failed to create RPC request.\n"));
-                       prs_mem_free(&outgoing_packet);
-                       prs_mem_free(&sec_blob);
-                       return False;
+                       return ret;
+               } else {
+                       /* More packets to come - write and continue. */
+                       ssize_t num_written = cli_write(cli->cli, cli->fnum, 8, /* 8 means message mode. */
+                                                       prs_data_p(&outgoing_pdu),
+                                                       (off_t)0,
+                                                       (size_t)hdr.frag_len);
+
+                       if (num_written != hdr.frag_len) {
+                               prs_mem_free(&outgoing_pdu);
+                               return cli_get_nt_error(cli->cli);
+                       }
                }
 
-               prs_append_prs_data(&outgoing_packet, &sec_blob);
-               prs_mem_free(&sec_blob);
-
-               DEBUG(100,("data_len: %x data_calc_len: %x\n", data_len, 
-                          prs_offset(&outgoing_packet)));
-               
-               if (flags & RPC_FLG_LAST)
-                       ret = rpc_api_pipe(cli, &outgoing_packet, 
-                                          rdata, RPC_RESPONSE);
-               else {
-                       cli_write(cli->cli, cli->fnum, 0x0008,
-                                  prs_data_p(&outgoing_packet),
-                                  data_sent, data_len);
+               current_data_offset += data_sent_thistime;
+               data_left -= data_sent_thistime;
+
+               /* Reset the marshalling position back to zero. */
+               if (!prs_set_offset(&outgoing_pdu, 0)) {
+                       prs_mem_free(&outgoing_pdu);
+                       return NT_STATUS_NO_MEMORY;
                }
-               prs_mem_free(&outgoing_packet);
-               data_sent += send_size;
-               data_left -= send_size;
        }
-       /* Also capture received data */
-       slprintf(dump_name, sizeof(dump_name) - 1, "reply_%s",
-                cli_pipe_get_name(cli->cli));
-       prs_dump(dump_name, op_num, rdata);
-
-       return ret;
-}
-
-BOOL rpc_api_pipe_req(struct cli_state *cli, int pipe_idx, uint8 op_num,
-                      prs_struct *data, prs_struct *rdata)
-{
-       return rpc_api_pipe_req_int(&cli->pipes[pipe_idx], op_num,
-                                   data, rdata);
 }
-
-
+#if 0
 /****************************************************************************
  Set the handle state.
 ****************************************************************************/
@@ -1174,56 +1633,10 @@ static BOOL rpc_pipe_set_hnd_state(struct rpc_pipe_client *cli,
 
        return state_set;
 }
+#endif
 
 /****************************************************************************
- check the rpc bind acknowledge response
-****************************************************************************/
-
-int get_pipe_index( const char *pipe_name )
-{
-       int pipe_idx = 0;
-
-       while (pipe_names[pipe_idx].client_pipe != NULL) {
-               if (strequal(pipe_name, pipe_names[pipe_idx].client_pipe )) 
-                       return pipe_idx;
-               pipe_idx++;
-       };
-
-       return -1;
-}
-
-
-/****************************************************************************
- check the rpc bind acknowledge response
-****************************************************************************/
-
-const char* get_pipe_name_from_index( const int pipe_index )
-{
-
-       if ( (pipe_index < 0) || (pipe_index >= PI_MAX_PIPES) )
-               return NULL;
-
-       return pipe_names[pipe_index].client_pipe;              
-}
-
-/****************************************************************************
- Check to see if this pipe index points to one of 
- the pipes only supported by Win2k
- ****************************************************************************/
-
-BOOL is_win2k_pipe( const int pipe_idx )
-{
-       switch ( pipe_idx )
-       {
-               case PI_LSARPC_DS:
-                       return True;
-       }
-       
-       return False;
-}
-
-/****************************************************************************
- check the rpc bind acknowledge response
+ Check the rpc bind acknowledge response.
 ****************************************************************************/
 
 static BOOL valid_pipe_name(const int pipe_idx, RPC_IFACE *abstract, RPC_IFACE *transfer)
@@ -1235,10 +1648,10 @@ static BOOL valid_pipe_name(const int pipe_idx, RPC_IFACE *abstract, RPC_IFACE *
        }
 
        DEBUG(5,("Bind Abstract Syntax: "));    
-       dump_data(5, (char*)&(pipe_names[pipe_idx].abstr_syntax)
+       dump_data(5, (char*)&pipe_names[pipe_idx].abstr_syntax
                  sizeof(pipe_names[pipe_idx].abstr_syntax));
        DEBUG(5,("Bind Transfer Syntax: "));
-       dump_data(5, (char*)&(pipe_names[pipe_idx].trans_syntax),
+       dump_data(5, (char*)&pipe_names[pipe_idx].trans_syntax,
                  sizeof(pipe_names[pipe_idx].trans_syntax));
 
        /* copy the required syntaxes out so we can do the right bind */
@@ -1250,7 +1663,7 @@ static BOOL valid_pipe_name(const int pipe_idx, RPC_IFACE *abstract, RPC_IFACE *
 }
 
 /****************************************************************************
- check the rpc bind acknowledge response
+ Check the rpc bind acknowledge response.
 ****************************************************************************/
 
 static BOOL check_bind_response(RPC_HDR_BA *hdr_ba, const int pipe_idx, RPC_IFACE *transfer)
@@ -1259,7 +1672,6 @@ static BOOL check_bind_response(RPC_HDR_BA *hdr_ba, const int pipe_idx, RPC_IFAC
                DEBUG(4,("Ignoring length check -- ASU bug (server didn't fill in the pipe name correctly)"));
        }
 
-               
 # if 0 /* JERRY -- apparently ASU forgets to fill in the server pipe name sometimes */
        if ( !strequal(hdr_ba->addr.str, pipe_names[pipe_idx].client_pipe) &&
             !strequal(hdr_ba->addr.str, pipe_names[pipe_idx].server_pipe) )
@@ -1284,396 +1696,500 @@ static BOOL check_bind_response(RPC_HDR_BA *hdr_ba, const int pipe_idx, RPC_IFAC
                return False;
        }
 
-       /* lkclXXXX only accept one result: check the result(s) */
        if (hdr_ba->res.num_results != 0x1 || hdr_ba->res.result != 0) {
                DEBUG(2,("bind_rpc_pipe: bind denied results: %d reason: %x\n",
                          hdr_ba->res.num_results, hdr_ba->res.reason));
        }
 
-       DEBUG(5,("bind_rpc_pipe: accepted!\n"));
+       DEBUG(5,("check_bind_response: accepted!\n"));
        return True;
 }
 
-/****************************************************************************
- Create and send the third packet in an RPC auth.
-****************************************************************************/
+/*******************************************************************
+ Creates a DCE/RPC bind authentication response.
+ This is the packet that is sent back to the server once we
+ have received a BIND-ACK, to finish the third leg of
+ the authentication handshake.
+ ********************************************************************/
 
-static BOOL rpc_send_auth_reply(struct rpc_pipe_client *cli,
-                               prs_struct *rdata, uint32 rpc_call_id)
+static NTSTATUS create_rpc_bind_auth3(struct rpc_pipe_client *cli,
+                               uint32 rpc_call_id,
+                               enum pipe_auth_type auth_type,
+                               enum pipe_auth_level auth_level,
+                               DATA_BLOB *pauth_blob,
+                               prs_struct *rpc_out)
 {
-       prs_struct rpc_out;
-       ssize_t ret;
+       RPC_HDR hdr;
+       RPC_HDR_AUTH hdr_auth;
+       uint32 pad = 0;
+
+       /* Create the request RPC_HDR */
+       init_rpc_hdr(&hdr, RPC_AUTH3, RPC_FLG_FIRST|RPC_FLG_LAST, rpc_call_id,
+                    RPC_HEADER_LEN + 4 /* pad */ + RPC_HDR_AUTH_LEN + pauth_blob->length,
+                    pauth_blob->length );
+       
+       /* Marshall it. */
+       if(!smb_io_rpc_hdr("hdr", &hdr, rpc_out, 0)) {
+               DEBUG(0,("create_rpc_bind_auth3: failed to marshall RPC_HDR.\n"));
+               return NT_STATUS_NO_MEMORY;
+       }
 
-       prs_init(&rpc_out, RPC_HEADER_LEN + RPC_HDR_AUTHA_LEN, /* need at least this much */ 
-                cli->cli->mem_ctx, MARSHALL);
+       /*
+               I'm puzzled about this - seems to violate the DCE RPC auth rules,
+               about padding - shouldn't this pad to length 8 ? JRA.
+       */
 
-       if (!NT_STATUS_IS_OK(create_rpc_bind_resp(cli, rpc_call_id,
-                                                 &rpc_out))) {
-               return False;
+       /* 4 bytes padding. */
+       if (!prs_uint32("pad", rpc_out, 0, &pad)) {
+               DEBUG(0,("create_rpc_bind_auth3: failed to marshall 4 byte pad.\n"));
+               return NT_STATUS_NO_MEMORY;
        }
 
-       if ((ret = cli_write(cli->cli, cli->fnum, 0x8, prs_data_p(&rpc_out), 
-                       0, (size_t)prs_offset(&rpc_out))) != (ssize_t)prs_offset(&rpc_out)) {
-               DEBUG(0,("rpc_send_auth_reply: cli_write failed. Return was %d\n", (int)ret));
-               prs_mem_free(&rpc_out);
-               return False;
+       /* Create the request RPC_HDR_AUTHA */
+       init_rpc_hdr_auth(&hdr_auth,
+                       map_pipe_auth_type_to_rpc_auth_type(auth_type),
+                       auth_level, 0, 1);
+
+       if(!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, rpc_out, 0)) {
+               DEBUG(0,("create_rpc_bind_auth3: failed to marshall RPC_HDR_AUTHA.\n"));
+               return NT_STATUS_NO_MEMORY;
        }
 
-       prs_mem_free(&rpc_out);
-       return True;
+       /*
+        * Append the auth data to the outgoing buffer.
+        */
+
+       if(!prs_copy_data_in(rpc_out, (char *)pauth_blob->data, pauth_blob->length)) {
+               DEBUG(0,("create_rpc_bind_auth3: failed to marshall auth blob.\n"));
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       return NT_STATUS_OK;
 }
 
 /****************************************************************************
Do an rpc bind.
Create and send the third packet in an RPC auth.
 ****************************************************************************/
 
-static BOOL rpc_pipe_bind(struct rpc_pipe_client *cli)
+static NTSTATUS rpc_finish_auth3_bind(struct rpc_pipe_client *cli,
+                               RPC_HDR *phdr,
+                               prs_struct *rbuf,
+                               uint32 rpc_call_id,
+                               enum pipe_auth_type auth_type,
+                               enum pipe_auth_level auth_level)
 {
-       RPC_IFACE abstract;
-       RPC_IFACE transfer;
+       DATA_BLOB server_response = data_blob(NULL,0);
+       DATA_BLOB client_reply = data_blob(NULL,0);
+       RPC_HDR_AUTH hdr_auth;
+       NTSTATUS nt_status;
        prs_struct rpc_out;
-       prs_struct rdata;
-       uint32 rpc_call_id;
-       char buffer[MAX_PDU_FRAG_LEN];
+       ssize_t ret;
 
-       if ( (cli->pipe_idx < 0) || (cli->pipe_idx >= PI_MAX_PIPES) )
-               return False;
+       if (!phdr->auth_len || (phdr->frag_len < phdr->auth_len + RPC_HDR_AUTH_LEN)) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
 
-       DEBUG(5,("Bind RPC Pipe[%x]: %s\n", cli->fnum,
-                pipe_names[cli->pipe_idx].client_pipe));
+       /* Process the returned NTLMSSP blob first. */
+       if (!prs_set_offset(rbuf, phdr->frag_len - phdr->auth_len - RPC_HDR_AUTH_LEN)) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
 
-       if (!valid_pipe_name(cli->pipe_idx, &abstract, &transfer))
-               return False;
+       if(!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, rbuf, 0)) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
 
-       prs_init(&rpc_out, 0, cli->cli->mem_ctx, MARSHALL);
+       /* TODO - check auth_type/auth_level match. */
 
-       /*
-        * Use the MAX_PDU_FRAG_LEN buffer to store the bind request.
-        */
+       server_response = data_blob(NULL, phdr->auth_len);
+       prs_copy_data_out((char *)server_response.data, rbuf, phdr->auth_len);
+       
+       nt_status = ntlmssp_update(cli->auth.a_u.ntlmssp_state,
+                                  server_response,
+                                  &client_reply);
+       
+       if (!NT_STATUS_IS_OK(nt_status)) {
+               DEBUG(0,("rpc_finish_auth3_bind: NTLMSSP update using server blob failed.\n"));
+               return nt_status;
+       }
 
-       prs_give_memory( &rpc_out, buffer, sizeof(buffer), False);
+       prs_init(&rpc_out, 0, prs_get_mem_context(rbuf), MARSHALL);
 
-       rpc_call_id = get_rpc_call_id();
+       nt_status = create_rpc_bind_auth3(cli, rpc_call_id,
+                               auth_type, auth_level,
+                               &client_reply, &rpc_out);
 
-       if (cli->pipe_auth_flags & AUTH_PIPE_NTLMSSP) {
-               NTSTATUS nt_status;
-               fstring password;
+       if (!NT_STATUS_IS_OK(nt_status)) {
+               prs_mem_free(&rpc_out);
+               data_blob_free(&client_reply);
+               data_blob_free(&server_response);
+               return nt_status;
+       }
 
-               DEBUG(5, ("NTLMSSP authenticated pipe selected\n"));
+       /* 8 here is named pipe message mode. */
+       ret = cli_write(cli->cli, cli->fnum, 0x8, prs_data_p(&rpc_out), 0,
+                               (size_t)prs_offset(&rpc_out));
 
-               nt_status = ntlmssp_client_start(&cli->ntlmssp_pipe_state);
-               
-               if (!NT_STATUS_IS_OK(nt_status))
-                       return False;
+       if (ret != (ssize_t)prs_offset(&rpc_out)) {
+               DEBUG(0,("rpc_send_auth_auth3: cli_write failed. Return was %d\n", (int)ret));
+               prs_mem_free(&rpc_out);
+               data_blob_free(&client_reply);
+               data_blob_free(&server_response);
+               return cli_get_nt_error(cli->cli);
+       }
 
-               /* Currently the NTLMSSP code does not implement NTLM2 correctly for signing or sealing */
+       DEBUG(5,("rpc_send_auth_auth3: Remote machine %s pipe %s "
+               "fnum 0x%x sent auth3 response ok.\n",
+               cli->cli->desthost,
+               cli->pipe_name,
+               (unsigned int)cli->fnum));
 
-               cli->ntlmssp_pipe_state->neg_flags &= ~NTLMSSP_NEGOTIATE_NTLM2;
+       prs_mem_free(&rpc_out);
+       data_blob_free(&client_reply);
+       data_blob_free(&server_response);
+       return NT_STATUS_OK;
+}
 
-               nt_status = ntlmssp_set_username(cli->ntlmssp_pipe_state, 
-                                                cli->user_name);
-               if (!NT_STATUS_IS_OK(nt_status))
-                       return False;
+/*******************************************************************
+ Creates a DCE/RPC bind alter context authentication request which
+ may contain a spnego auth blobl
+ ********************************************************************/
 
-               nt_status = ntlmssp_set_domain(cli->ntlmssp_pipe_state, 
-                                              cli->domain);    
-               if (!NT_STATUS_IS_OK(nt_status))
-                       return False;
+static NTSTATUS create_rpc_alter_context(uint32 rpc_call_id,
+                                       RPC_IFACE *abstract,
+                                       RPC_IFACE *transfer,
+                                       enum pipe_auth_level auth_level,
+                                       const DATA_BLOB *pauth_blob, /* spnego auth blob already created. */
+                                       prs_struct *rpc_out)
+{
+       RPC_HDR_AUTH hdr_auth;
+       prs_struct auth_info;
+       NTSTATUS ret = NT_STATUS_OK;
 
-               if (cli->pwd.null_pwd) {
-                       nt_status = ntlmssp_set_password(cli->ntlmssp_pipe_state, 
-                                                        NULL);
-                       if (!NT_STATUS_IS_OK(nt_status))
-                               return False;
-               } else {
-                       pwd_get_cleartext(&cli->pwd, password);
-                       nt_status = ntlmssp_set_password(cli->ntlmssp_pipe_state, 
-                                                        password);
-                       if (!NT_STATUS_IS_OK(nt_status))
-                               return False;
-               }
+       ZERO_STRUCT(hdr_auth);
+       prs_init(&auth_info, RPC_HDR_AUTH_LEN, prs_get_mem_context(rpc_out), MARSHALL);
 
-               if (cli->pipe_auth_flags & AUTH_PIPE_SIGN) {
-                       cli->ntlmssp_pipe_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
-               }
+       /* We may change the pad length before marshalling. */
+       init_rpc_hdr_auth(&hdr_auth, RPC_SPNEGO_AUTH_TYPE, (int)auth_level, 0, 1);
 
-               if (cli->pipe_auth_flags & AUTH_PIPE_SEAL) {
-                       cli->ntlmssp_pipe_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL;
+       if (pauth_blob->length) {
+               if (!prs_copy_data_in(&auth_info, (const char *)pauth_blob->data, pauth_blob->length)) {
+                       prs_mem_free(&auth_info);
+                       return NT_STATUS_NO_MEMORY;
                }
-       } else if (cli->pipe_auth_flags & AUTH_PIPE_NETSEC) {
-               cli->auth_info.seq_num = 0;
        }
 
-       /* Marshall the outgoing data. */
-       create_rpc_bind_req(cli, &rpc_out, rpc_call_id,
-                           &abstract, &transfer,
-                           global_myname(), cli->domain);
-
-       /* Initialize the incoming data struct. */
-       prs_init(&rdata, 0, cli->cli->mem_ctx, UNMARSHALL);
-
-       /* send data on \PIPE\.  receive a response */
-       if (rpc_api_pipe(cli, &rpc_out, &rdata, RPC_BINDACK)) {
-               RPC_HDR_BA   hdr_ba;
-
-               DEBUG(5, ("rpc_pipe_bind: rpc_api_pipe returned OK.\n"));
-
-               if(!smb_io_rpc_hdr_ba("", &hdr_ba, &rdata, 0)) {
-                       DEBUG(0,("rpc_pipe_bind: Failed to unmarshall RPC_HDR_BA.\n"));
-                       prs_mem_free(&rdata);
-                       return False;
-               }
+       ret = create_bind_or_alt_ctx_internal(RPC_ALTCONT,
+                                               rpc_out, 
+                                               rpc_call_id,
+                                               abstract,
+                                               transfer,
+                                               &hdr_auth,
+                                               &auth_info);
+       prs_mem_free(&auth_info);
+       return ret;
+}
 
-               if(!check_bind_response(&hdr_ba, cli->pipe_idx, &transfer)) {
-                       DEBUG(2,("rpc_pipe_bind: check_bind_response failed.\n"));
-                       prs_mem_free(&rdata);
-                       return False;
-               }
+/*******************************************************************
+ Third leg of the SPNEGO bind mechanism - sends alter context PDU
+ and gets a response.
+ ********************************************************************/
 
-               cli->max_xmit_frag = hdr_ba.bba.max_tsize;
-               cli->max_recv_frag = hdr_ba.bba.max_rsize;
+static NTSTATUS rpc_finish_spnego_ntlmssp_bind(struct rpc_pipe_client *cli,
+                                RPC_HDR *phdr,
+                                prs_struct *rbuf,
+                                uint32 rpc_call_id,
+                               RPC_IFACE *abstract,
+                               RPC_IFACE *transfer,
+                                enum pipe_auth_type auth_type,
+                                enum pipe_auth_level auth_level)
+{
+       DATA_BLOB server_spnego_response = data_blob(NULL,0);
+       DATA_BLOB server_ntlm_response = data_blob(NULL,0);
+       DATA_BLOB client_reply = data_blob(NULL,0);
+       DATA_BLOB tmp_blob = data_blob(NULL, 0);
+       RPC_HDR_AUTH hdr_auth;
+       NTSTATUS nt_status;
+       prs_struct rpc_out;
 
-               /*
-                * If we're doing NTLMSSP auth we need to send a reply to
-                * the bind-ack to complete the 3-way challenge response
-                * handshake.
-                */
+       if (!phdr->auth_len || (phdr->frag_len < phdr->auth_len + RPC_HDR_AUTH_LEN)) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
 
-               if ((cli->pipe_auth_flags & AUTH_PIPE_NTLMSSP) 
-                   && !rpc_send_auth_reply(cli, &rdata, rpc_call_id)) {
-                       DEBUG(0,("rpc_pipe_bind: rpc_send_auth_reply failed.\n"));
-                       prs_mem_free(&rdata);
-                       return False;
-               }
-               prs_mem_free(&rdata);
-               return True;
+       /* Process the returned NTLMSSP blob first. */
+       if (!prs_set_offset(rbuf, phdr->frag_len - phdr->auth_len - RPC_HDR_AUTH_LEN)) {
+               return NT_STATUS_INVALID_PARAMETER;
        }
 
-       return False;
-}
+       if(!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, rbuf, 0)) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
 
-/****************************************************************************
- Open a session.
- ****************************************************************************/
+       server_spnego_response = data_blob(NULL, phdr->auth_len);
+       prs_copy_data_out((char *)server_spnego_response.data, rbuf, phdr->auth_len);
+       
+       /* The server might give us back two challenges - tmp_blob is for the second. */
+       if (!spnego_parse_challenge(server_spnego_response, &server_ntlm_response, &tmp_blob)) {
+               data_blob_free(&server_spnego_response);
+               data_blob_free(&server_ntlm_response);
+               data_blob_free(&tmp_blob);
+               return NT_STATUS_INVALID_PARAMETER;
+       }
 
-BOOL cli_nt_session_open(struct cli_state *cli, const int pipe_idx)
-{
-       int fnum;
-       struct rpc_pipe_client *cli_pipe;
+       /* We're finished with the server spnego response and the tmp_blob. */
+       data_blob_free(&server_spnego_response);
+       data_blob_free(&tmp_blob);
 
-       SMB_ASSERT(cli->pipes[pipe_idx].fnum == 0);
+       nt_status = ntlmssp_update(cli->auth.a_u.ntlmssp_state,
+                                  server_ntlm_response,
+                                  &client_reply);
        
-       /* The pipe index must fall within our array */
+       /* Finished with the server_ntlm response */
+       data_blob_free(&server_ntlm_response);
 
-       SMB_ASSERT((pipe_idx >= 0) && (pipe_idx < PI_MAX_PIPES));
+       if (!NT_STATUS_IS_OK(nt_status)) {
+               DEBUG(0,("rpc_finish_spnego_ntlmssp_bind: NTLMSSP update using server blob failed.\n"));
+               data_blob_free(&client_reply);
+               return nt_status;
+       }
 
-       if (cli->capabilities & CAP_NT_SMBS) {
-               if ((fnum = cli_nt_create(cli, &pipe_names[pipe_idx].client_pipe[5], DESIRED_ACCESS_PIPE)) == -1) {
-                       DEBUG(0,("cli_nt_session_open: cli_nt_create failed on pipe %s to machine %s.  Error was %s\n",
-                                &pipe_names[pipe_idx].client_pipe[5], cli->desthost, cli_errstr(cli)));
-                       return False;
-               }
+       /* SPNEGO wrap the client reply. */
+       tmp_blob = spnego_gen_auth(client_reply);
+       data_blob_free(&client_reply);
+       client_reply = tmp_blob;
+       tmp_blob = data_blob(NULL,0); /* Ensure it's safe to free this just in case. */
 
-               cli->pipes[pipe_idx].fnum = (uint16)fnum;
-       } else {
-               if ((fnum = cli_open(cli, pipe_names[pipe_idx].client_pipe, O_CREAT|O_RDWR, DENY_NONE)) == -1) {
-                       DEBUG(1,("cli_nt_session_open: cli_open failed on pipe %s to machine %s.  Error was %s\n",
-                                pipe_names[pipe_idx].client_pipe, cli->desthost, cli_errstr(cli)));
-                       return False;
-               }
+       /* Now prepare the alter context pdu. */
+       prs_init(&rpc_out, 0, prs_get_mem_context(rbuf), MARSHALL);
 
-               cli->pipes[pipe_idx].fnum = (uint16)fnum;
+       nt_status = create_rpc_alter_context(rpc_call_id,
+                                               abstract,
+                                               transfer,
+                                               auth_level,
+                                               &client_reply,
+                                               &rpc_out);
 
-               /**************** Set Named Pipe State ***************/
-               if (!rpc_pipe_set_hnd_state(&cli->pipes[pipe_idx], pipe_names[pipe_idx].client_pipe, 0x4300)) {
-                       DEBUG(0,("cli_nt_session_open: pipe hnd state failed.  Error was %s\n",
-                                 cli_errstr(cli)));
-                       cli_close(cli, cli->pipes[pipe_idx].fnum);
-                       cli->pipes[pipe_idx].fnum = 0;
-                       return False;
-               }
+       data_blob_free(&client_reply);
+
+       if (!NT_STATUS_IS_OK(nt_status)) {
+               prs_mem_free(&rpc_out);
+               return nt_status;
        }
 
-       cli_pipe = &cli->pipes[pipe_idx];
-       cli_pipe->pipe_idx = pipe_idx;
-       cli_pipe->cli = cli;
-       cli_pipe->pipe_auth_flags = cli->pipe_auth_flags;
-       memcpy(&cli_pipe->auth_info.sess_key,
-              cli->sess_key, sizeof(cli->sess_key));
+       /* Initialize the returning data struct. */
+       prs_mem_free(rbuf);
+       prs_init(rbuf, 0, cli->cli->mem_ctx, UNMARSHALL);
 
-       /******************* bind request on pipe *****************/
+       nt_status = rpc_api_pipe(cli, &rpc_out, rbuf, RPC_ALTCONTRESP);
+       if (!NT_STATUS_IS_OK(nt_status)) {
+               prs_mem_free(&rpc_out);
+               return nt_status;
+       }
 
-       if (!rpc_pipe_bind(&cli->pipes[pipe_idx])) {
-               DEBUG(2,("cli_nt_session_open: rpc bind to %s failed\n",
-                        get_pipe_name_from_index(pipe_idx)));
-               cli_close(cli, cli->pipes[pipe_idx].fnum);
-               cli->pipes[pipe_idx].fnum = 0;
-               return False;
+       prs_mem_free(&rpc_out);
+
+       /* Get the auth blob from the reply. */
+       if(!smb_io_rpc_hdr("rpc_hdr   ", phdr, rbuf, 0)) {
+               DEBUG(0,("rpc_finish_spnego_ntlmssp_bind: Failed to unmarshall RPC_HDR.\n"));
+               return NT_STATUS_BUFFER_TOO_SMALL;
        }
 
-       cli->pipe_idx = pipe_idx;
+       if (!prs_set_offset(rbuf, phdr->frag_len - phdr->auth_len - RPC_HDR_AUTH_LEN)) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
 
-       /* 
-        * Setup the remote server name prefixed by \ and the machine account name.
-        */
+       if(!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, rbuf, 0)) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
 
-       fstrcpy(cli->srv_name_slash, "\\\\");
-       fstrcat(cli->srv_name_slash, cli->desthost);
-       strupper_m(cli->srv_name_slash);
+       server_spnego_response = data_blob(NULL, phdr->auth_len);
+       prs_copy_data_out((char *)server_spnego_response.data, rbuf, phdr->auth_len);
 
-       fstrcpy(cli->clnt_name_slash, "\\\\");
-       fstrcat(cli->clnt_name_slash, global_myname());
-       strupper_m(cli->clnt_name_slash);
+       /* Check we got a valid auth response. */
+       if (!spnego_parse_auth_response(server_spnego_response, NT_STATUS_OK, &tmp_blob)) {
+               data_blob_free(&server_spnego_response);
+               data_blob_free(&tmp_blob);
+               return NT_STATUS_INVALID_PARAMETER;
+       }
 
-       fstrcpy(cli->mach_acct, global_myname());
-       fstrcat(cli->mach_acct, "$");
-       strupper_m(cli->mach_acct);
+       data_blob_free(&server_spnego_response);
+       data_blob_free(&tmp_blob);
 
-       /* Remember which pipe we're talking to */
-       fstrcpy(cli->pipe_name, pipe_names[pipe_idx].client_pipe);
+       DEBUG(5,("rpc_finish_spnego_ntlmssp_bind: alter context request to "
+               "remote machine %s pipe %s fnum 0x%x.\n",
+               cli->cli->desthost,
+               cli->pipe_name,
+               (unsigned int)cli->fnum));
 
-       return True;
+       return NT_STATUS_OK;
 }
 
-
 /****************************************************************************
- Open a session to the NETLOGON pipe using schannel.
-
- (Assumes that the netlogon pipe is already open)
- ****************************************************************************/
+ Do an rpc bind.
+****************************************************************************/
 
-NTSTATUS cli_nt_establish_netlogon(struct cli_state *cli, int sec_chan,
-                                  const uchar trust_password[16])
+static NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli,
+                       enum pipe_auth_type auth_type,
+                       enum pipe_auth_level auth_level)
 {
-       NTSTATUS result;        
-       uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS;
-
-       cli_nt_netlogon_netsec_session_close(cli);
-
-       if (lp_client_schannel() != False)
-               neg_flags |= NETLOGON_NEG_SCHANNEL;
+       RPC_HDR hdr;
+       RPC_HDR_BA hdr_ba;
+       RPC_IFACE abstract;
+       RPC_IFACE transfer;
+       prs_struct rpc_out;
+       prs_struct rbuf;
+       uint32 rpc_call_id;
+       NTSTATUS status;
 
-       result = cli_nt_setup_creds(cli, sec_chan, trust_password,
-                                   &neg_flags, 2);
+       DEBUG(5,("Bind RPC Pipe[%x]: %s auth_type %u, auth_level %u\n",
+               (unsigned int)cli->fnum,
+               cli->pipe_name,
+               (unsigned int)auth_type,
+               (unsigned int)auth_level ));
 
-       if (!NT_STATUS_IS_OK(result)) {
-               cli_nt_session_close(cli);
-               return result;
+       if (!valid_pipe_name(cli->pipe_idx, &abstract, &transfer)) {
+               return NT_STATUS_INVALID_PARAMETER;
        }
 
-       if ((lp_client_schannel() == True) &&
-           ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
+       prs_init(&rpc_out, 0, cli->cli->mem_ctx, MARSHALL);
 
-               DEBUG(3, ("Server did not offer schannel\n"));
-               cli_nt_session_close(cli);
-               return NT_STATUS_UNSUCCESSFUL;
-       }
+       rpc_call_id = get_rpc_call_id();
 
-       if ((lp_client_schannel() == False) ||
-           ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) {
-               return NT_STATUS_OK;
-               
-               /* keep the existing connection to NETLOGON open */
+       /* Marshall the outgoing data. */
+       status = create_rpc_bind_req(cli, &rpc_out, rpc_call_id,
+                               &abstract, &transfer,
+                               auth_type,
+                               auth_level);
 
+       if (!NT_STATUS_IS_OK(status)) {
+               prs_mem_free(&rpc_out);
+               return status;
        }
 
-       cli->netlogon_pipe = cli->pipes[PI_NETLOGON];
-       ZERO_STRUCT(cli->pipes[PI_NETLOGON]);
+       /* Initialize the incoming data struct. */
+       prs_init(&rbuf, 0, cli->cli->mem_ctx, UNMARSHALL);
 
-       /* Server offered schannel, so try it. */
+       /* send data on \PIPE\.  receive a response */
+       status = rpc_api_pipe(cli, &rpc_out, &rbuf, RPC_BINDACK);
+       if (!NT_STATUS_IS_OK(status)) {
+               prs_mem_free(&rpc_out);
+               return status;
+       }
 
-       memcpy(cli->pipes[PI_NETLOGON].auth_info.sess_key, cli->sess_key,
-              sizeof(cli->pipes[PI_NETLOGON].auth_info.sess_key));
+       prs_mem_free(&rpc_out);
 
-       cli->pipe_auth_flags = AUTH_PIPE_NETSEC;
-       cli->pipe_auth_flags |= AUTH_PIPE_SIGN;
-       cli->pipe_auth_flags |= AUTH_PIPE_SEAL;
+       DEBUG(3,("rpc_pipe_bind: Remote machine %s pipe %s "
+               "fnum 0x%x bind request returned ok.\n",
+               cli->cli->desthost,
+               cli->pipe_name,
+               (unsigned int)cli->fnum));
+
+       /* Unmarshall the RPC header */
+       if(!smb_io_rpc_hdr("hdr"   , &hdr, &rbuf, 0)) {
+               DEBUG(0,("rpc_pipe_bind: failed to unmarshall RPC_HDR.\n"));
+               prs_mem_free(&rbuf);
+               return NT_STATUS_BUFFER_TOO_SMALL;
+       }
 
-       return cli_nt_session_open(cli, PI_NETLOGON) ?
-               NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
-}
+       if(!smb_io_rpc_hdr_ba("", &hdr_ba, &rbuf, 0)) {
+               DEBUG(0,("rpc_pipe_bind: Failed to unmarshall RPC_HDR_BA.\n"));
+               prs_mem_free(&rbuf);
+               return NT_STATUS_BUFFER_TOO_SMALL;
+       }
 
+       if(!check_bind_response(&hdr_ba, cli->pipe_idx, &transfer)) {
+               DEBUG(2,("rpc_pipe_bind: check_bind_response failed.\n"));
+               prs_mem_free(&rbuf);
+               return NT_STATUS_BUFFER_TOO_SMALL;
+       }
 
-NTSTATUS cli_nt_setup_netsec(struct cli_state *cli, int sec_chan, int auth_flags,
-                            const uchar trust_password[16])
-{
-       NTSTATUS result;        
-       uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS;
-       cli->pipe_auth_flags = 0;
+       cli->max_xmit_frag = hdr_ba.bba.max_tsize;
+       cli->max_recv_frag = hdr_ba.bba.max_rsize;
 
-       if (lp_client_schannel() == False) {
-               return NT_STATUS_OK;
-       }
+       /* For authenticated binds we may need to do 3 or 4 leg binds. */
+       switch(auth_type) {
 
-       if (!cli_nt_session_open(cli, PI_NETLOGON)) {
-               DEBUG(0, ("Could not initialise %s\n",
-                         get_pipe_name_from_index(PI_NETLOGON)));
-               return NT_STATUS_UNSUCCESSFUL;
-       }
+               case PIPE_AUTH_TYPE_NONE:
+               case PIPE_AUTH_TYPE_SCHANNEL:
+                       /* Bind complete. */
+                       break;
 
-       neg_flags |= NETLOGON_NEG_SCHANNEL;
+               case PIPE_AUTH_TYPE_NTLMSSP:
+                       /* Need to send AUTH3 packet - no reply. */
+                       status = rpc_finish_auth3_bind(cli, &hdr, &rbuf, rpc_call_id,
+                                               auth_type, auth_level);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               prs_mem_free(&rbuf);
+                               return status;
+                       }
+                       break;
+
+               case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
+                       /* Need to send alter context request and reply. */
+                       status = rpc_finish_spnego_ntlmssp_bind(cli, &hdr, &rbuf, rpc_call_id,
+                                               &abstract, &transfer,
+                                               auth_type, auth_level);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               prs_mem_free(&rbuf);
+                               return status;
+                       }
+                       break;
 
-       result = cli_nt_setup_creds(cli, sec_chan, trust_password,
-                                   &neg_flags, 2);
+               case PIPE_AUTH_TYPE_KRB5:
+                       /* */
 
-       if (!(neg_flags & NETLOGON_NEG_SCHANNEL) 
-           && lp_client_schannel() == True) {
-               DEBUG(1, ("Could not negotiate SCHANNEL with the DC!\n"));
-               result = NT_STATUS_UNSUCCESSFUL;
+               default:
+                       DEBUG(0,("cli_finish_bind_auth: unknown auth type %u\n",
+                               (unsigned int)auth_type ));
+                       prs_mem_free(&rbuf);
+                       return NT_STATUS_INVALID_INFO_CLASS;
        }
 
-       if (!NT_STATUS_IS_OK(result)) {
-               ZERO_STRUCT(cli->pipes[cli->pipe_idx].auth_info.sess_key);
-               ZERO_STRUCT(cli->sess_key);
-               cli->pipe_auth_flags = 0;
-               cli_nt_session_close(cli);
-               return result;
-       }
+       /* Pipe is bound - set up auth_type and auth_level data. */
 
-       memcpy(cli->pipes[PI_NETLOGON].auth_info.sess_key, cli->sess_key,
-              sizeof(cli->pipes[PI_NETLOGON].auth_info.sess_key));
-
-       cli_close(cli, cli->pipes[PI_NETLOGON].fnum);
-       cli->pipes[PI_NETLOGON].fnum = 0;
-       cli->pipe_idx = -1;
-       
-       /* doing schannel, not per-user auth */
-       cli->pipe_auth_flags = auth_flags;
+       cli->auth.auth_type = auth_type;
+       cli->auth.auth_level = auth_level;
 
+       prs_mem_free(&rbuf);
        return NT_STATUS_OK;
 }
 
-const char *cli_pipe_get_name(struct cli_state *cli)
-{
-       return cli->pipe_name;
-}
+/****************************************************************************
+ Open a named pipe over SMB to a remote server.
+ ****************************************************************************/
 
-static struct rpc_pipe_client *cli_rpc_open(struct cli_state *cli,
-                                           int pipe_idx)
+static struct rpc_pipe_client *cli_rpc_pipe_open(struct cli_state *cli, int pipe_idx, NTSTATUS *perr)
 {
        TALLOC_CTX *mem_ctx;
        struct rpc_pipe_client *result;
        int fnum;
 
-       /* The pipe index must fall within our array */
+       *perr = NT_STATUS_NO_MEMORY;
+
+       /* The pipe name index must fall within our array */
        SMB_ASSERT((pipe_idx >= 0) && (pipe_idx < PI_MAX_PIPES));
 
        mem_ctx = talloc_init("struct rpc_pipe_client");
-       if (mem_ctx == NULL) return NULL;
+       if (mem_ctx == NULL) {
+               return NULL;
+       }
 
-       result = TALLOC_P(mem_ctx, struct rpc_pipe_client);
-       if (result == NULL) return NULL;
+       result = TALLOC_ZERO_P(mem_ctx, struct rpc_pipe_client);
+       if (result == NULL) {
+               return NULL;
+       }
 
        result->mem_ctx = mem_ctx;
 
-       fnum = cli_nt_create(cli, &pipe_names[pipe_idx].client_pipe[5],
-                            DESIRED_ACCESS_PIPE);
+       result->pipe_name = cli_get_pipe_name(pipe_idx);
+
+       fnum = cli_nt_create(cli, result->pipe_name, DESIRED_ACCESS_PIPE);
 
        if (fnum == -1) {
-               DEBUG(0,("cli_rpc_open failed on pipe %s "
+               DEBUG(0,("cli_rpc_pipe_open: cli_nt_create failed on pipe %s "
                         "to machine %s.  Error was %s\n",
-                        &pipe_names[pipe_idx].client_pipe[5], cli->desthost,
+                        result->pipe_name, cli->desthost,
                         cli_errstr(cli)));
+               *perr = cli_get_nt_error(cli);
                talloc_destroy(result->mem_ctx);
                return NULL;
        }
@@ -1681,91 +2197,440 @@ static struct rpc_pipe_client *cli_rpc_open(struct cli_state *cli,
        result->fnum = fnum;
        result->cli = cli;
        result->pipe_idx = pipe_idx;
+       result->auth.auth_type = PIPE_AUTH_TYPE_NONE;
+       result->auth.auth_level = PIPE_AUTH_LEVEL_NONE;
+
+       if (pipe_idx == PI_NETLOGON) {
+               /* Set up a netlogon credential chain for a netlogon pipe. */
+               result->dc = TALLOC_ZERO_P(mem_ctx, struct dcinfo);
+               if (result->dc == NULL) {
+                       talloc_destroy(result->mem_ctx);
+                       return NULL;
+               }
+       }
+
+       DLIST_ADD(cli->pipe_list, result);
+       *perr = NT_STATUS_OK;
 
        return result;
 }
 
-struct rpc_pipe_client *cli_rpc_open_noauth(struct cli_state *cli,
-                                           int pipe_idx)
+/****************************************************************************
+ Open a named pipe to an SMB server and bind anonymously.
+ ****************************************************************************/
+
+struct rpc_pipe_client *cli_rpc_pipe_open_noauth(struct cli_state *cli, int pipe_idx, NTSTATUS *perr)
 {
        struct rpc_pipe_client *result;
 
-       result = cli_rpc_open(cli, pipe_idx);
-       if (result == NULL) return NULL;
-
-       result->max_xmit_frag = 0;
-       result->pipe_auth_flags = 0;
+       result = cli_rpc_pipe_open(cli, pipe_idx, perr);
+       if (result == NULL) {
+               return NULL;
+       }
 
-       if (!rpc_pipe_bind(result)) {
-               DEBUG(0, ("rpc_pipe_bind failed\n"));
-               talloc_destroy(result->mem_ctx);
+       *perr = rpc_pipe_bind(result, PIPE_AUTH_TYPE_NONE, PIPE_AUTH_LEVEL_NONE);
+       if (!NT_STATUS_IS_OK(*perr)) {
+               DEBUG(0, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe %s failed with error %s\n",
+                       cli_get_pipe_name(pipe_idx), nt_errstr(*perr) ));
+               cli_rpc_pipe_close(result);
                return NULL;
        }
 
+       DEBUG(10,("cli_rpc_pipe_open_noauth: opened pipe %s to machine %s and bound anonymously.\n",
+                       result->pipe_name, cli->desthost ));
+
        return result;
 }
 
-struct rpc_pipe_client *cli_rpc_open_ntlmssp(struct cli_state *cli,
-                                            int pipe_idx,
-                                            const char *domain,
-                                            const char *username,
-                                            const char *password)
+/****************************************************************************
+ Free function for NTLMSSP auth.
+ ****************************************************************************/
+
+static void cli_ntlmssp_auth_free(struct cli_pipe_auth_data *auth)
+{
+       if (auth->a_u.ntlmssp_state) {
+               ntlmssp_end(&auth->a_u.ntlmssp_state);
+               auth->a_u.ntlmssp_state = NULL;
+       }
+}
+
+/****************************************************************************
+ Open a named pipe to an SMB server and bind using NTLMSSP or SPNEGO NTLMSSP
+ ****************************************************************************/
+
+static struct rpc_pipe_client *cli_rpc_pipe_open_ntlmssp_internal(struct cli_state *cli,
+                                               int pipe_idx,
+                                               enum pipe_auth_type auth_type,
+                                               enum pipe_auth_level auth_level,
+                                               const char *domain,
+                                               const char *username,
+                                               const char *password,
+                                               NTSTATUS *perr)
 {
        struct rpc_pipe_client *result;
+       NTLMSSP_STATE *ntlmssp_state = NULL;
 
-       result = cli_rpc_open(cli, pipe_idx);
-       if (result == NULL) return NULL;
+       result = cli_rpc_pipe_open(cli, pipe_idx, perr);
+       if (result == NULL) {
+               return NULL;
+       }
        
-       result->max_xmit_frag = 0;
-       result->pipe_auth_flags =
-               AUTH_PIPE_NTLMSSP|AUTH_PIPE_SIGN|AUTH_PIPE_SEAL;
+       result->auth.cli_auth_data_free_func = cli_ntlmssp_auth_free;
+
        result->domain = domain;
        result->user_name = username;
        pwd_set_cleartext(&result->pwd, password);
 
-       if (!rpc_pipe_bind(result)) {
-               DEBUG(0, ("cli_rpc_pipe_bind failed\n"));
-               talloc_destroy(result->mem_ctx);
-               return NULL;
+       *perr = ntlmssp_client_start(&ntlmssp_state);
+       if (!NT_STATUS_IS_OK(*perr)) {
+               goto err;
+       }
+
+       result->auth.a_u.ntlmssp_state = ntlmssp_state;
+
+       *perr = ntlmssp_set_username(ntlmssp_state, cli->user_name);
+       if (!NT_STATUS_IS_OK(*perr)) {
+               goto err;
+       }
+
+       *perr = ntlmssp_set_domain(ntlmssp_state, cli->domain); 
+       if (!NT_STATUS_IS_OK(*perr)) {
+               goto err;
        }
 
+       if (cli->pwd.null_pwd) {
+               *perr = ntlmssp_set_password(ntlmssp_state, NULL);
+               if (!NT_STATUS_IS_OK(*perr)) {
+                       goto err;
+               }
+       } else {
+               *perr = ntlmssp_set_password(ntlmssp_state, password);
+               if (!NT_STATUS_IS_OK(*perr)) {
+                       goto err;
+               }
+       }
+
+       /* Turn off sign+seal to allow selected auth level to turn it back on. */
+       ntlmssp_state->neg_flags &= ~(NTLMSSP_NEGOTIATE_SIGN|NTLMSSP_NEGOTIATE_SEAL);
+
+       if (auth_level == PIPE_AUTH_LEVEL_INTEGRITY) {
+               ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN;
+       } else if (auth_level == PIPE_AUTH_LEVEL_PRIVACY) {
+               ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL | NTLMSSP_NEGOTIATE_SIGN;
+       }
+       
+       *perr = rpc_pipe_bind(result, auth_type, auth_level);
+       if (!NT_STATUS_IS_OK(*perr)) {
+               DEBUG(0, ("cli_rpc_pipe_open_ntlmssp_internal: cli_rpc_pipe_bind failed with error %s\n",
+                       nt_errstr(*perr) ));
+               goto err;
+       }
+
+       DEBUG(10,("cli_rpc_pipe_open_ntlmssp_internal: opened pipe %s to machine %s and"
+               "bound NTLMSSP as user %s\\%s.\n",
+               result->pipe_name, cli->desthost,
+               domain, username ));
+
        return result;
+
+  err:
+
+       cli_rpc_pipe_close(result);
+       return NULL;
 }
 
-struct rpc_pipe_client *cli_rpc_open_schannel(struct cli_state *cli,
-                                             int pipe_idx,
-                                             const uchar session_key[16],
-                                             const char *domain)
+/****************************************************************************
+ External interface.
+ Open a named pipe to an SMB server and bind using NTLMSSP (bind type 10)
+ ****************************************************************************/
+
+struct rpc_pipe_client *cli_rpc_pipe_open_ntlmssp(struct cli_state *cli,
+                                               int pipe_idx,
+                                               enum pipe_auth_level auth_level,
+                                               const char *domain,
+                                               const char *username,
+                                               const char *password,
+                                               NTSTATUS *perr)
+{
+       return cli_rpc_pipe_open_ntlmssp_internal(cli,
+                                               pipe_idx,
+                                               PIPE_AUTH_TYPE_NTLMSSP,
+                                               auth_level,
+                                               domain,
+                                               username,
+                                               password,
+                                               perr);
+}
+
+/****************************************************************************
+ External interface.
+ Open a named pipe to an SMB server and bind using spnego NTLMSSP (bind type 9)
+ ****************************************************************************/
+
+struct rpc_pipe_client *cli_rpc_pipe_open_spnego_ntlmssp(struct cli_state *cli,
+                                               int pipe_idx,
+                                               enum pipe_auth_level auth_level,
+                                               const char *domain,
+                                               const char *username,
+                                               const char *password,
+                                               NTSTATUS *perr)
+{
+       return cli_rpc_pipe_open_ntlmssp_internal(cli,
+                                               pipe_idx,
+                                               PIPE_AUTH_TYPE_SPNEGO_NTLMSSP,
+                                               auth_level,
+                                               domain,
+                                               username,
+                                               password,
+                                               perr);
+}
+
+/****************************************************************************
+ Open a netlogon pipe and get the schannel session key.
+ ****************************************************************************/
+
+static struct rpc_pipe_client *get_schannel_session_key(struct cli_state *cli,
+                                                       const char *domain,
+                                                       NTSTATUS *perr)
+{
+       uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS|NETLOGON_NEG_SCHANNEL;
+       struct rpc_pipe_client *netlogon_pipe = NULL;
+       uint32 sec_chan_type = 0;
+       char machine_pwd[16];
+       fstring machine_account;
+
+       netlogon_pipe = cli_rpc_pipe_open_noauth(cli, PI_NETLOGON, perr);
+       if (!netlogon_pipe) {
+               return NULL;
+       }
+
+       /* Get the machine account credentials from secrets.tdb. */
+       if (!get_trust_pw(domain, machine_pwd, &sec_chan_type)) {
+               DEBUG(0, ("get_schannel_session_key: could not fetch "
+                       "trust account password for domain '%s'\n",
+                       domain));
+               cli_rpc_pipe_close(netlogon_pipe);
+               *perr = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
+               return NULL;
+       }
+
+       if ( IS_DC ) {
+               fstrcpy( machine_account, lp_workgroup() );
+        } else {
+                /* Hmmm. Is this correct for trusted domains when we're a member server ? JRA. */
+                if (strequal(domain, lp_workgroup())) {
+                        fstrcpy(machine_account, global_myname());
+                } else {
+                        fstrcpy(machine_account, domain);
+                }
+        }
+
+       *perr = rpccli_netlogon_setup_creds(netlogon_pipe,
+                                       cli->desthost,
+                                       domain,
+                                       machine_account,
+                                       machine_pwd,
+                                       sec_chan_type,
+                                       &neg_flags);
+
+       if (!NT_STATUS_IS_OK(*perr)) {
+               DEBUG(3,("get_schannel_session_key: rpccli_netlogon_setup_creds "
+                       "failed with result %s\n",
+                       nt_errstr(*perr) ));
+               cli_rpc_pipe_close(netlogon_pipe);
+               return NULL;
+       }
+
+       if ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0) {
+               DEBUG(3, ("get_schannel_session_key: Server %s did not offer schannel\n",
+                       cli->desthost));
+               cli_rpc_pipe_close(netlogon_pipe);
+               *perr = NT_STATUS_INVALID_NETWORK_RESPONSE;
+               return NULL;
+       }
+
+       return netlogon_pipe;
+}
+
+/****************************************************************************
+ External interface.
+ Open a named pipe to an SMB server and bind using schannel (bind type 68)
+ using session_key. sign and seal.
+ ****************************************************************************/
+
+struct rpc_pipe_client *cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli,
+                                       int pipe_idx,
+                                       enum pipe_auth_level auth_level,
+                                       const char *domain,
+                                       const struct dcinfo *pdc,
+                                       NTSTATUS *perr)
 {
        struct rpc_pipe_client *result;
 
-       result = cli_rpc_open(cli, pipe_idx);
-       if (result == NULL) return NULL;
-       
-       result->max_xmit_frag = 0;
-       result->pipe_auth_flags =
-               AUTH_PIPE_NETSEC | AUTH_PIPE_SIGN | AUTH_PIPE_SEAL;
+       result = cli_rpc_pipe_open(cli, pipe_idx, perr);
+       if (result == NULL) {
+               return NULL;
+       }
+
+       result->auth.a_u.schannel_auth = TALLOC_ZERO_P(result->mem_ctx, struct schannel_auth_struct);
+       if (!result->auth.a_u.schannel_auth) {
+               cli_rpc_pipe_close(result);
+               *perr = NT_STATUS_NO_MEMORY;
+               return NULL;
+       }
+
        result->domain = domain;
-       memcpy(result->auth_info.sess_key, session_key, 16);
+       memcpy(result->auth.a_u.schannel_auth->sess_key, pdc->sess_key, 16);
 
-       if (!rpc_pipe_bind(result)) {
-               DEBUG(0, ("cli_rpc_pipe_bind failed\n"));
-               talloc_destroy(result->mem_ctx);
+       *perr = rpc_pipe_bind(result, PIPE_AUTH_TYPE_SCHANNEL, auth_level);
+       if (!NT_STATUS_IS_OK(*perr)) {
+               DEBUG(0, ("cli_rpc_pipe_open_schannel_with_key: cli_rpc_pipe_bind failed with error %s\n",
+                       nt_errstr(*perr) ));
+               cli_rpc_pipe_close(result);
                return NULL;
        }
 
+       /* The credentials on a new netlogon pipe are the ones we are passed in - copy them over. */
+       if (result->dc) {
+               *result->dc = *pdc;
+       }
+
+       DEBUG(10,("cli_rpc_pipe_open_schannel_with_key: opened pipe %s to machine %s "
+               "for domain %s "
+               "and bound using schannel.\n",
+               result->pipe_name, cli->desthost, domain ));
+
        return result;
 }
 
-void cli_rpc_close(struct rpc_pipe_client *cli_pipe)
+/****************************************************************************
+ Open a named pipe to an SMB server and bind using schannel (bind type 68).
+ Fetch the session key ourselves using a temporary netlogon pipe.
+ ****************************************************************************/
+
+struct rpc_pipe_client *cli_rpc_pipe_open_schannel(struct cli_state *cli,
+                                                int pipe_idx,
+                                               enum pipe_auth_level auth_level,
+                                                const char *domain,
+                                               NTSTATUS *perr)
 {
-       if (!cli_close(cli_pipe->cli, cli_pipe->fnum))
-               DEBUG(0,("cli_rpc_open failed on pipe %s "
-                        "to machine %s.  Error was %s\n",
-                        &pipe_names[cli_pipe->pipe_idx].client_pipe[5],
-                        cli_pipe->cli->desthost,
-                        cli_errstr(cli_pipe->cli)));
+       struct rpc_pipe_client *netlogon_pipe = NULL;
+       struct rpc_pipe_client *result = NULL;
+
+       netlogon_pipe = get_schannel_session_key(cli, domain, perr);
+       if (!netlogon_pipe) {
+               DEBUG(0,("cli_rpc_pipe_open_schannel: failed to get schannel session "
+                       "key from server %s for domain %s.\n",
+                       cli->desthost, domain ));
+               return NULL;
+       }
+
+       result = cli_rpc_pipe_open_schannel_with_key(cli, pipe_idx,
+                               auth_level,
+                               domain, netlogon_pipe->dc, perr);
+
+       /* Now we've bound using the session key we can close the netlog pipe. */
+       cli_rpc_pipe_close(netlogon_pipe);
+
+       return result;
+}
+
+/****************************************************************************
+ Free function for the kerberos spcific data.
+ ****************************************************************************/
+
+static void kerberos_auth_struct_free(struct cli_pipe_auth_data *a)
+{
+       data_blob_free(&a->a_u.kerberos_auth->session_key);
+}
 
-       talloc_destroy(cli_pipe->mem_ctx);      
+/****************************************************************************
+ Open a named pipe to an SMB server and bind using krb5 (bind type 16).
+ ****************************************************************************/
+
+struct rpc_pipe_client *cli_rpc_pipe_open_krb5(struct cli_state *cli,
+                                               int pipe_idx,
+                                               enum pipe_auth_level auth_level,
+                                               const char *service_princ,
+                                               const char *username,
+                                               const char *password,
+                                               NTSTATUS *perr)
+{
+#ifdef HAVE_KRB5
+       struct rpc_pipe_client *result;
+
+       result = cli_rpc_pipe_open(cli, pipe_idx, perr);
+       if (result == NULL) {
+               return NULL;
+       }
+
+       /* Default service principal is "host/server@realm" */
+       if (!service_princ) {
+               service_princ = talloc_asprintf(result->mem_ctx, "host/%s@%s",
+                       cli->desthost, lp_realm() );
+               if (!service_princ) {
+                       cli_rpc_pipe_close(result);
+                       return NULL;
+               }
+       }
+
+       /* Only get a new TGT if username/password are given. */
+       if (username && password) {
+               int ret = kerberos_kinit_password(username, password, 0, NULL, NULL);
+               if (ret) {
+                       cli_rpc_pipe_close(result);
+                       return NULL;
+               }
+       }
+
+       result->auth.a_u.kerberos_auth = TALLOC_ZERO_P(cli->mem_ctx, struct kerberos_auth_struct);
+       if (!result->auth.a_u.kerberos_auth) {
+               cli_rpc_pipe_close(result);
+               *perr = NT_STATUS_NO_MEMORY;
+               return NULL;
+       }
+
+       result->auth.a_u.kerberos_auth->service_principal = service_princ;
+       result->auth.cli_auth_data_free_func = kerberos_auth_struct_free;
+
+       *perr = rpc_pipe_bind(result, PIPE_AUTH_TYPE_KRB5, auth_level);
+       if (!NT_STATUS_IS_OK(*perr)) {
+               DEBUG(0, ("cli_rpc_pipe_open_krb5: cli_rpc_pipe_bind failed with error %s\n",
+                       nt_errstr(*perr) ));
+               cli_rpc_pipe_close(result);
+               return NULL;
+       }
+
+       return result;
+#else
+       DEBUG(0,("cli_rpc_pipe_open_krb5: kerberos not found at compile time.\n"));
+       return NULL;
+#endif
 }
 
+#if 0 /* Moved to libsmb/clientgen.c */
+/****************************************************************************
+ External interface.
+ Close an open named pipe over SMB. Free any authentication data.
+ ****************************************************************************/
+
+void cli_rpc_pipe_close(struct rpc_pipe_client *cli)
+{
+       if (!cli_close(cli->cli, cli->fnum)) {
+               DEBUG(0,("cli_rpc_pipe_close: cli_close failed on pipe %s "
+                        "to machine %s.  Error was %s\n",
+                        cli->pipe_name),
+                        cli->cli->desthost,
+                        cli_errstr(cli->cli)));
+       }
+
+       if (cli->auth.cli_auth_data_free_func) {
+               (*cli->auth.cli_auth_data_free_func)(&cli->auth);
+       }
+       DEBUG(10,("cli_rpc_pipe_close: closed pipe %s to machine %s\n",
+               cli->pipe_name, cli->cli->desthost ));
+
+       DLIST_REMOVE(cli->cli->pipe_list, cli);
+       talloc_destroy(cli->mem_ctx);   
+}
+#endif
index 97ae8b29e7d9e9faf8e5ceb4984b3d282b8e3cb9..87ab5dc9dad143402ad871a2281ab8fa67f72b94 100644 (file)
@@ -3,9 +3,7 @@
    RPC Pipe client
  
    Copyright (C) Andrew Tridgell              1992-2000,
-   Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
-   Copyright (C) Paul Ashton                  1997-2000.
-   Copyright (C) Jeremy Allison                    1999.
+   Copyright (C) Jeremy Allison                    1999 - 2005
    Copyright (C) Simo Sorce                        2001
    Copyright (C) Jeremy Cooper                     2004
    Copyright (C) Gerald (Jerry) Carter             2005
@@ -34,7 +32,7 @@
  internal connect to a registry hive root (open a registry policy)
 *******************************************************************/
 
-static WERROR cli_reg_open_hive_int(struct cli_state *cli,
+static WERROR rpccli_reg_open_hive_int(struct rpc_pipe_client *cli,
                                       TALLOC_CTX *mem_ctx, uint16 op_code,
                                       const char *op_name,
                                       uint32 access_mask, POLICY_HND *hnd)
@@ -48,7 +46,7 @@ static WERROR cli_reg_open_hive_int(struct cli_state *cli,
 
        init_reg_q_open_hive(&in, access_mask);
 
-       CLI_DO_RPC( cli, mem_ctx, PI_WINREG, op_code, 
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_WINREG, op_code, 
                    in, out, 
                    qbuf, rbuf,
                    reg_io_q_open_hive,
@@ -67,7 +65,7 @@ static WERROR cli_reg_open_hive_int(struct cli_state *cli,
  connect to a registry hive root (open a registry policy)
 *******************************************************************/
 
-WERROR cli_reg_connect(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+WERROR rpccli_reg_connect(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                          uint32 reg_type, uint32 access_mask,
                          POLICY_HND *reg_hnd)
 {      uint16 op_code;
@@ -97,7 +95,7 @@ WERROR cli_reg_connect(struct cli_state *cli, TALLOC_CTX *mem_ctx,
                return WERR_INVALID_PARAM;
        }
 
-       return cli_reg_open_hive_int(cli, mem_ctx, op_code, op_name,
+       return rpccli_reg_open_hive_int(cli, mem_ctx, op_code, op_name,
                                      access_mask, reg_hnd);
 }
 
@@ -105,7 +103,7 @@ WERROR cli_reg_connect(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 /*******************************************************************
 *******************************************************************/
 
-WERROR cli_reg_shutdown(struct cli_state * cli, TALLOC_CTX *mem_ctx,
+WERROR rpccli_reg_shutdown(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                           const char *msg, uint32 timeout, BOOL do_reboot,
                          BOOL force)
 {
@@ -123,7 +121,7 @@ WERROR cli_reg_shutdown(struct cli_state * cli, TALLOC_CTX *mem_ctx,
 
        init_reg_q_shutdown(&in, msg, timeout, do_reboot, force);
 
-       CLI_DO_RPC( cli, mem_ctx, PI_WINREG, REG_SHUTDOWN, 
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_WINREG, REG_SHUTDOWN, 
                    in, out, 
                    qbuf, rbuf,
                    reg_io_q_shutdown,
@@ -136,7 +134,7 @@ WERROR cli_reg_shutdown(struct cli_state * cli, TALLOC_CTX *mem_ctx,
 /*******************************************************************
 *******************************************************************/
 
-WERROR cli_reg_abort_shutdown(struct cli_state * cli, TALLOC_CTX *mem_ctx)
+WERROR rpccli_reg_abort_shutdown(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx)
 {
        REG_Q_ABORT_SHUTDOWN in;
        REG_R_ABORT_SHUTDOWN out;
@@ -145,7 +143,7 @@ WERROR cli_reg_abort_shutdown(struct cli_state * cli, TALLOC_CTX *mem_ctx)
        ZERO_STRUCT (in);
        ZERO_STRUCT (out);
 
-       CLI_DO_RPC( cli, mem_ctx, PI_WINREG, REG_ABORT_SHUTDOWN, 
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_WINREG, REG_ABORT_SHUTDOWN, 
                    in, out, 
                    qbuf, rbuf,
                    reg_io_q_abort_shutdown,
@@ -161,7 +159,8 @@ do a REG Unknown 0xB command.  sent after a create key or create value.
 this might be some sort of "sync" or "refresh" command, sent after
 modification of the registry...
 ****************************************************************************/
-WERROR cli_reg_flush_key(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+
+WERROR rpccli_reg_flush_key(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                            POLICY_HND *hnd)
 {
        REG_Q_FLUSH_KEY in;
@@ -173,7 +172,7 @@ WERROR cli_reg_flush_key(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        
        init_reg_q_flush_key(&in, hnd);
 
-       CLI_DO_RPC( cli, mem_ctx, PI_WINREG, REG_FLUSH_KEY, 
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_WINREG, REG_FLUSH_KEY, 
                    in, out, 
                    qbuf, rbuf,
                    reg_io_q_flush_key,
@@ -186,7 +185,8 @@ WERROR cli_reg_flush_key(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 /****************************************************************************
 do a REG Query Key
 ****************************************************************************/
-WERROR cli_reg_query_key(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+
+WERROR rpccli_reg_query_key(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                            POLICY_HND *hnd,
                            char *key_class, uint32 *class_len,
                            uint32 *num_subkeys, uint32 *max_subkeylen,
@@ -204,7 +204,7 @@ WERROR cli_reg_query_key(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 
        init_reg_q_query_key( &in, hnd, key_class );
 
-       CLI_DO_RPC( cli, mem_ctx, PI_WINREG, REG_QUERY_KEY, 
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_WINREG, REG_QUERY_KEY, 
                    in, out, 
                    qbuf, rbuf,
                    reg_io_q_query_key,
@@ -227,7 +227,7 @@ WERROR cli_reg_query_key(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 
                ZERO_STRUCT (out);
 
-               CLI_DO_RPC( cli, mem_ctx, PI_WINREG, REG_QUERY_KEY, 
+               CLI_DO_RPC_WERR( cli, mem_ctx, PI_WINREG, REG_QUERY_KEY, 
                            in, out, 
                            qbuf, rbuf,
                            reg_io_q_query_key,
@@ -255,7 +255,7 @@ WERROR cli_reg_query_key(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 /****************************************************************************
 ****************************************************************************/
 
-WERROR cli_reg_getversion(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+WERROR rpccli_reg_getversion(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                             POLICY_HND *hnd, uint32 *version)
 {
        REG_Q_GETVERSION in;
@@ -267,7 +267,7 @@ WERROR cli_reg_getversion(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        
        init_reg_q_getversion(&in, hnd);
 
-       CLI_DO_RPC( cli, mem_ctx, PI_WINREG, REG_GETVERSION, 
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_WINREG, REG_GETVERSION, 
                    in, out, 
                    qbuf, rbuf,
                    reg_io_q_getversion,
@@ -286,7 +286,8 @@ WERROR cli_reg_getversion(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 /****************************************************************************
 do a REG Query Info
 ****************************************************************************/
-WERROR cli_reg_query_value(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+
+WERROR rpccli_reg_query_value(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                            POLICY_HND *hnd, const char *val_name,
                            uint32 *type, REGVAL_BUFFER *buffer)
 {
@@ -299,7 +300,7 @@ WERROR cli_reg_query_value(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        
        init_reg_q_query_value(&in, hnd, val_name, buffer);
 
-       CLI_DO_RPC( cli, mem_ctx, PI_WINREG, REG_QUERY_VALUE, 
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_WINREG, REG_QUERY_VALUE, 
                    in, out, 
                    qbuf, rbuf,
                    reg_io_q_query_value,
@@ -319,7 +320,8 @@ WERROR cli_reg_query_value(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 /****************************************************************************
 do a REG Set Key Security 
 ****************************************************************************/
-WERROR cli_reg_set_key_sec(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+
+WERROR rpccli_reg_set_key_sec(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                              POLICY_HND *hnd, uint32 sec_info,
                              size_t secdesc_size, SEC_DESC *sec_desc)
 {
@@ -338,7 +340,7 @@ WERROR cli_reg_set_key_sec(struct cli_state *cli, TALLOC_CTX *mem_ctx,
                
        init_reg_q_set_key_sec(&in, hnd, sec_info, sec_desc_buf);
 
-       CLI_DO_RPC( cli, mem_ctx, PI_WINREG, REG_SET_KEY_SEC, 
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_WINREG, REG_SET_KEY_SEC, 
                    in, out, 
                    qbuf, rbuf,
                    reg_io_q_set_key_sec,
@@ -353,7 +355,8 @@ WERROR cli_reg_set_key_sec(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 /****************************************************************************
 do a REG Query Key Security 
 ****************************************************************************/
-WERROR cli_reg_get_key_sec(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+
+WERROR rpccli_reg_get_key_sec(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                              POLICY_HND *hnd, uint32 sec_info,
                              uint32 *sec_buf_size, SEC_DESC_BUF *sec_buf)
 {
@@ -366,7 +369,7 @@ WERROR cli_reg_get_key_sec(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        
        init_reg_q_get_key_sec(&in, hnd, sec_info, *sec_buf_size, sec_buf);
 
-       CLI_DO_RPC( cli, mem_ctx, PI_WINREG, REG_GET_KEY_SEC, 
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_WINREG, REG_GET_KEY_SEC, 
                    in, out, 
                    qbuf, rbuf,
                    reg_io_q_get_key_sec,
@@ -388,7 +391,8 @@ WERROR cli_reg_get_key_sec(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 /****************************************************************************
 do a REG Delete Value
 ****************************************************************************/
-WERROR cli_reg_delete_val(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+
+WERROR rpccli_reg_delete_val(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                             POLICY_HND *hnd, char *val_name)
 {
        REG_Q_DELETE_VALUE in;
@@ -400,7 +404,7 @@ WERROR cli_reg_delete_val(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        
        init_reg_q_delete_val(&in, hnd, val_name);
 
-       CLI_DO_RPC( cli, mem_ctx, PI_WINREG, REG_DELETE_VALUE, 
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_WINREG, REG_DELETE_VALUE, 
                    in, out, 
                    qbuf, rbuf,
                    reg_io_q_delete_value,
@@ -413,7 +417,8 @@ WERROR cli_reg_delete_val(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 /****************************************************************************
 do a REG Delete Key
 ****************************************************************************/
-WERROR cli_reg_delete_key(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+
+WERROR rpccli_reg_delete_key(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                             POLICY_HND *hnd, char *key_name)
 {
        REG_Q_DELETE_KEY in;
@@ -425,7 +430,7 @@ WERROR cli_reg_delete_key(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        
        init_reg_q_delete_key(&in, hnd, key_name);
 
-       CLI_DO_RPC( cli, mem_ctx, PI_WINREG, REG_DELETE_KEY, 
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_WINREG, REG_DELETE_KEY, 
                    in, out, 
                    qbuf, rbuf,
                    reg_io_q_delete_key,
@@ -438,7 +443,8 @@ WERROR cli_reg_delete_key(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 /****************************************************************************
 do a REG Create Key
 ****************************************************************************/
-WERROR cli_reg_create_key_ex(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+
+WERROR rpccli_reg_create_key_ex(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                             POLICY_HND *hnd, char *key_name, char *key_class,
                             uint32 access_desired, POLICY_HND *key)
 {
@@ -453,8 +459,7 @@ WERROR cli_reg_create_key_ex(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        ZERO_STRUCT (out);
        
        if ( !(sec = make_sec_desc(mem_ctx, 1, SEC_DESC_SELF_RELATIVE,
-               NULL, NULL, NULL, NULL, &sec_len)) )
-       {
+               NULL, NULL, NULL, NULL, &sec_len)) ) {
                return WERR_GENERAL_FAILURE;
        }
                                 
@@ -463,7 +468,7 @@ WERROR cli_reg_create_key_ex(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 
        init_reg_q_create_key_ex(&in, hnd, key_name, key_class, access_desired, sec_buf);
 
-       CLI_DO_RPC( cli, mem_ctx, PI_WINREG, REG_CREATE_KEY_EX, 
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_WINREG, REG_CREATE_KEY_EX, 
                    in, out, 
                    qbuf, rbuf,
                    reg_io_q_create_key_ex,
@@ -482,7 +487,8 @@ WERROR cli_reg_create_key_ex(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 /****************************************************************************
 do a REG Enum Key
 ****************************************************************************/
-WERROR cli_reg_enum_key(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+
+WERROR rpccli_reg_enum_key(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                           POLICY_HND *hnd, int key_index, fstring key_name,
                           fstring class_name, time_t *mod_time)
 {
@@ -495,7 +501,7 @@ WERROR cli_reg_enum_key(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        
        init_reg_q_enum_key(&in, hnd, key_index);
 
-       CLI_DO_RPC( cli, mem_ctx, PI_WINREG, REG_ENUM_KEY, 
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_WINREG, REG_ENUM_KEY, 
                    in, out, 
                    qbuf, rbuf,
                    reg_io_q_enum_key,
@@ -523,7 +529,8 @@ WERROR cli_reg_enum_key(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 /****************************************************************************
 do a REG Create Value
 ****************************************************************************/
-WERROR cli_reg_set_val(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+
+WERROR rpccli_reg_set_val(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                             POLICY_HND *hnd, char *val_name, uint32 type,
                             RPC_DATA_BLOB *data)
 {
@@ -536,7 +543,7 @@ WERROR cli_reg_set_val(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        
        init_reg_q_set_val(&in, hnd, val_name, type, data);
 
-       CLI_DO_RPC( cli, mem_ctx, PI_WINREG, REG_SET_VALUE, 
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_WINREG, REG_SET_VALUE, 
                    in, out, 
                    qbuf, rbuf,
                    reg_io_q_set_value,
@@ -549,7 +556,8 @@ WERROR cli_reg_set_val(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 /****************************************************************************
 do a REG Enum Value
 ****************************************************************************/
-WERROR cli_reg_enum_val(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+
+WERROR rpccli_reg_enum_val(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                           POLICY_HND *hnd, int idx,
                           fstring val_name, uint32 *type, REGVAL_BUFFER *value)
 {
@@ -562,7 +570,7 @@ WERROR cli_reg_enum_val(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        
        init_reg_q_enum_val(&in, hnd, idx, 0x0100, 0x1000);
 
-       CLI_DO_RPC( cli, mem_ctx, PI_WINREG, REG_ENUM_VALUE, 
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_WINREG, REG_ENUM_VALUE, 
                    in, out, 
                    qbuf, rbuf,
                    reg_io_q_enum_val,
@@ -577,7 +585,7 @@ WERROR cli_reg_enum_val(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 
                ZERO_STRUCT (out);
 
-               CLI_DO_RPC( cli, mem_ctx, PI_WINREG, REG_ENUM_VALUE, 
+               CLI_DO_RPC_WERR( cli, mem_ctx, PI_WINREG, REG_ENUM_VALUE, 
                            in, out, 
                            qbuf, rbuf,
                            reg_io_q_enum_val,
@@ -598,7 +606,7 @@ WERROR cli_reg_enum_val(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 /****************************************************************************
 ****************************************************************************/
 
-WERROR cli_reg_open_entry(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+WERROR rpccli_reg_open_entry(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                             POLICY_HND *hnd, char *key_name,
                             uint32 access_desired, POLICY_HND *key_hnd)
 {
@@ -611,7 +619,7 @@ WERROR cli_reg_open_entry(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        
        init_reg_q_open_entry(&in, hnd, key_name, access_desired);
 
-       CLI_DO_RPC( cli, mem_ctx, PI_WINREG, REG_OPEN_ENTRY, 
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_WINREG, REG_OPEN_ENTRY, 
                    in, out, 
                    qbuf, rbuf,
                    reg_io_q_open_entry,
@@ -629,7 +637,7 @@ WERROR cli_reg_open_entry(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 /****************************************************************************
 ****************************************************************************/
 
-WERROR cli_reg_close(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+WERROR rpccli_reg_close(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                        POLICY_HND *hnd)
 {
        REG_Q_CLOSE in;
@@ -641,7 +649,7 @@ WERROR cli_reg_close(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        
        init_reg_q_close(&in, hnd);
 
-       CLI_DO_RPC( cli, mem_ctx, PI_WINREG, REG_CLOSE, 
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_WINREG, REG_CLOSE, 
                    in, out, 
                    qbuf, rbuf,
                    reg_io_q_close,
@@ -654,7 +662,8 @@ WERROR cli_reg_close(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 /****************************************************************************
 do a REG Query Info
 ****************************************************************************/
-WERROR cli_reg_save_key( struct cli_state *cli, TALLOC_CTX *mem_ctx,
+
+WERROR rpccli_reg_save_key(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                          POLICY_HND *hnd, const char *filename )
 {
        REG_Q_SAVE_KEY in;
@@ -666,7 +675,7 @@ WERROR cli_reg_save_key( struct cli_state *cli, TALLOC_CTX *mem_ctx,
        
        init_q_reg_save_key( &in, hnd, filename );
 
-       CLI_DO_RPC( cli, mem_ctx, PI_WINREG, REG_SAVE_KEY, 
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_WINREG, REG_SAVE_KEY, 
                    in, out, 
                    qbuf, rbuf,
                    reg_io_q_save_key,
@@ -720,5 +729,3 @@ BOOL reg_split_hive(const char *full_keyname, uint32 *reg_type, pstring key_name
 
        return True;
 }
-
-
index 01ec0bd51eb932ac5dd867dfb839e0c0abb6a6f5..d68c72e20c8b935d3d6440e87226d5c5f839014e 100644 (file)
@@ -3,10 +3,8 @@
    RPC pipe client
    Copyright (C) Tim Potter                        2000-2001,
    Copyright (C) Andrew Tridgell              1992-1997,2000,
-   Copyright (C) Luke Kenneth Casson Leighton 1996-1997,2000,
-   Copyright (C) Paul Ashton                       1997,2000,
-   Copyright (C) Elrond                                 2000,
    Copyright (C) Rafal Szczesniak                       2002.
+   Copyright (C) Jeremy Allison                         2005.
    
    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
@@ -40,24 +38,16 @@ NTSTATUS rpccli_samr_connect(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        /* Marshall data and send request */
 
        init_samr_q_connect(&q, cli->cli->desthost, access_mask);
 
-       if (!samr_io_q_connect("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req_int(cli, SAMR_CONNECT, &qbuf, &rbuf))
-               goto done;
-
-       /* Unmarshall response */
-
-       if (!samr_io_r_connect("", &r, &rbuf, 0))
-               goto done;
-
+       CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_CONNECT,
+               q, r,
+               qbuf, rbuf,
+               samr_io_q_connect,
+               samr_io_r_connect,
+               NT_STATUS_UNSUCCESSFUL); 
        /* Return output parameters */
 
        if (NT_STATUS_IS_OK(result = r.status)) {
@@ -67,22 +57,12 @@ NTSTATUS rpccli_samr_connect(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
 #endif
        }
 
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
        return result;
 }
 
-NTSTATUS cli_samr_connect(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
-                          uint32 access_mask, POLICY_HND *connect_pol)
-{
-       return rpccli_samr_connect(&cli->pipes[PI_SAMR], mem_ctx,
-                                  access_mask, connect_pol);
-}
 /* Connect to SAMR database */
 
-NTSTATUS cli_samr_connect4(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
+NTSTATUS rpccli_samr_connect4(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, 
                           uint32 access_mask, POLICY_HND *connect_pol)
 {
        prs_struct qbuf, rbuf;
@@ -90,28 +70,19 @@ NTSTATUS cli_samr_connect4(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        SAMR_R_CONNECT4 r;
        NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
 
-       DEBUG(10,("cli_samr_connect4 to %s\n", cli->desthost));
-
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        /* Marshall data and send request */
 
-       init_samr_q_connect4(&q, cli->desthost, access_mask);
-
-       if (!samr_io_q_connect4("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, PI_SAMR, SAMR_CONNECT4, &qbuf, &rbuf))
-               goto done;
-
-       /* Unmarshall response */
+       init_samr_q_connect4(&q, cli->cli->desthost, access_mask);
 
-       if (!samr_io_r_connect4("", &r, &rbuf, 0))
-               goto done;
+       CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_CONNECT4,
+               q, r,
+               qbuf, rbuf,
+               samr_io_q_connect4,
+               samr_io_r_connect4,
+               NT_STATUS_UNSUCCESSFUL); 
 
        /* Return output parameters */
 
@@ -122,10 +93,6 @@ NTSTATUS cli_samr_connect4(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 #endif
        }
 
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
        return result;
 }
 
@@ -144,23 +111,16 @@ NTSTATUS rpccli_samr_close(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        /* Marshall data and send request */
 
        init_samr_q_close_hnd(&q, connect_pol);
 
-       if (!samr_io_q_close_hnd("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req_int(cli, SAMR_CLOSE_HND, &qbuf, &rbuf))
-               goto done;
-
-       /* Unmarshall response */
-
-       if (!samr_io_r_close_hnd("", &r, &rbuf, 0))
-               goto done;
+       CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_CLOSE_HND,
+               q, r,
+               qbuf, rbuf,
+               samr_io_q_close_hnd,
+               samr_io_r_close_hnd,
+               NT_STATUS_UNSUCCESSFUL); 
 
        /* Return output parameters */
 
@@ -171,19 +131,9 @@ NTSTATUS rpccli_samr_close(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                *connect_pol = r.pol;
        }
 
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
        return result;
 }
 
-NTSTATUS cli_samr_close(struct cli_state *cli, TALLOC_CTX *mem_ctx,
-                        POLICY_HND *connect_pol)
-{
-       return rpccli_samr_close(&cli->pipes[PI_SAMR], mem_ctx, connect_pol);
-}
-
 /* Open handle on a domain */
 
 NTSTATUS rpccli_samr_open_domain(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
@@ -201,23 +151,16 @@ NTSTATUS rpccli_samr_open_domain(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ct
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        /* Marshall data and send request */
 
        init_samr_q_open_domain(&q, connect_pol, access_mask, domain_sid);
 
-       if (!samr_io_q_open_domain("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req_int(cli, SAMR_OPEN_DOMAIN, &qbuf, &rbuf))
-               goto done;
-
-       /* Unmarshall response */
-
-       if (!samr_io_r_open_domain("", &r, &rbuf, 0))
-               goto done;
+       CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_OPEN_DOMAIN,
+               q, r,
+               qbuf, rbuf,
+               samr_io_q_open_domain,
+               samr_io_r_open_domain,
+               NT_STATUS_UNSUCCESSFUL); 
 
        /* Return output parameters */
 
@@ -228,26 +171,9 @@ NTSTATUS rpccli_samr_open_domain(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ct
 #endif
        }
 
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
        return result;
 }
 
-/* Open handle on a user */
-
-NTSTATUS cli_samr_open_domain(struct cli_state *cli, TALLOC_CTX *mem_ctx,
-                              POLICY_HND *connect_pol, uint32 access_mask, 
-                              const DOM_SID *domain_sid,
-                             POLICY_HND *domain_pol)
-{
-       return rpccli_samr_open_domain(&cli->pipes[PI_SAMR], mem_ctx,
-                                      connect_pol, access_mask, domain_sid,
-                                      domain_pol);
-}
-
-
 NTSTATUS rpccli_samr_open_user(struct rpc_pipe_client *cli,
                               TALLOC_CTX *mem_ctx,
                               POLICY_HND *domain_pol, uint32 access_mask, 
@@ -263,23 +189,16 @@ NTSTATUS rpccli_samr_open_user(struct rpc_pipe_client *cli,
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        /* Marshall data and send request */
 
        init_samr_q_open_user(&q, domain_pol, access_mask, user_rid);
 
-       if (!samr_io_q_open_user("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req_int(cli, SAMR_OPEN_USER, &qbuf, &rbuf))
-               goto done;
-
-       /* Unmarshall response */
-
-       if (!samr_io_r_open_user("", &r, &rbuf, 0))
-               goto done;
+       CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_OPEN_USER,
+               q, r,
+               qbuf, rbuf,
+               samr_io_q_open_user,
+               samr_io_r_open_user,
+               NT_STATUS_UNSUCCESSFUL); 
 
        /* Return output parameters */
 
@@ -290,22 +209,9 @@ NTSTATUS rpccli_samr_open_user(struct rpc_pipe_client *cli,
 #endif
        }
 
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
        return result;
 }
 
-NTSTATUS cli_samr_open_user(struct cli_state *cli, TALLOC_CTX *mem_ctx,
-                            POLICY_HND *domain_pol, uint32 access_mask, 
-                            uint32 user_rid, POLICY_HND *user_pol)
-{
-       return rpccli_samr_open_user(&cli->pipes[PI_SAMR], mem_ctx, domain_pol,
-                                    access_mask, user_rid, user_pol);
-}
-
-
 /* Open handle on a group */
 
 NTSTATUS rpccli_samr_open_group(struct rpc_pipe_client *cli,
@@ -323,23 +229,16 @@ NTSTATUS rpccli_samr_open_group(struct rpc_pipe_client *cli,
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        /* Marshall data and send request */
 
        init_samr_q_open_group(&q, domain_pol, access_mask, group_rid);
 
-       if (!samr_io_q_open_group("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req_int(cli, SAMR_OPEN_GROUP, &qbuf, &rbuf))
-               goto done;
-
-       /* Unmarshall response */
-
-       if (!samr_io_r_open_group("", &r, &rbuf, 0))
-               goto done;
+       CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_OPEN_GROUP,
+               q, r,
+               qbuf, rbuf,
+               samr_io_q_open_group,
+               samr_io_r_open_group,
+               NT_STATUS_UNSUCCESSFUL); 
 
        /* Return output parameters */
 
@@ -350,25 +249,12 @@ NTSTATUS rpccli_samr_open_group(struct rpc_pipe_client *cli,
 #endif
        }
 
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
        return result;
 }
 
-NTSTATUS cli_samr_open_group(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
-                             POLICY_HND *domain_pol, uint32 access_mask, 
-                             uint32 group_rid, POLICY_HND *group_pol)
-{
-       return rpccli_samr_open_group(&cli->pipes[PI_SAMR], mem_ctx,
-                                     domain_pol, access_mask, group_rid,
-                                     group_pol);
-}
-
 /* Create domain group */
 
-NTSTATUS cli_samr_create_dom_group(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+NTSTATUS rpccli_samr_create_dom_group(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                   POLICY_HND *domain_pol,
                                   const char *group_name,
                                   uint32 access_mask, POLICY_HND *group_pol)
@@ -383,23 +269,16 @@ NTSTATUS cli_samr_create_dom_group(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        /* Marshall data and send request */
 
        init_samr_q_create_dom_group(&q, domain_pol, group_name, access_mask);
 
-       if (!samr_io_q_create_dom_group("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, PI_SAMR, SAMR_CREATE_DOM_GROUP, &qbuf, &rbuf))
-               goto done;
-
-       /* Unmarshall response */
-
-       if (!samr_io_r_create_dom_group("", &r, &rbuf, 0))
-               goto done;
+       CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_CREATE_DOM_GROUP,
+               q, r,
+               qbuf, rbuf,
+               samr_io_q_create_dom_group,
+               samr_io_r_create_dom_group,
+               NT_STATUS_UNSUCCESSFUL); 
 
        /* Return output parameters */
 
@@ -408,16 +287,12 @@ NTSTATUS cli_samr_create_dom_group(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        if (NT_STATUS_IS_OK(result))
                *group_pol = r.pol;
 
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
        return result;
 }
 
 /* Add a domain group member */
 
-NTSTATUS cli_samr_add_groupmem(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+NTSTATUS rpccli_samr_add_groupmem(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                               POLICY_HND *group_pol, uint32 rid)
 {
        prs_struct qbuf, rbuf;
@@ -430,38 +305,27 @@ NTSTATUS cli_samr_add_groupmem(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        /* Marshall data and send request */
 
        init_samr_q_add_groupmem(&q, group_pol, rid);
 
-       if (!samr_io_q_add_groupmem("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, PI_SAMR, SAMR_ADD_GROUPMEM, &qbuf, &rbuf))
-               goto done;
-
-       /* Unmarshall response */
-
-       if (!samr_io_r_add_groupmem("", &r, &rbuf, 0))
-               goto done;
+       CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_ADD_GROUPMEM,
+               q, r,
+               qbuf, rbuf,
+               samr_io_q_add_groupmem,
+               samr_io_r_add_groupmem,
+               NT_STATUS_UNSUCCESSFUL); 
 
        /* Return output parameters */
 
        result = r.status;
 
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
        return result;
 }
 
 /* Delete a domain group member */
 
-NTSTATUS cli_samr_del_groupmem(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+NTSTATUS rpccli_samr_del_groupmem(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                               POLICY_HND *group_pol, uint32 rid)
 {
        prs_struct qbuf, rbuf;
@@ -474,32 +338,21 @@ NTSTATUS cli_samr_del_groupmem(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        /* Marshall data and send request */
 
        init_samr_q_del_groupmem(&q, group_pol, rid);
 
-       if (!samr_io_q_del_groupmem("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, PI_SAMR, SAMR_DEL_GROUPMEM, &qbuf, &rbuf))
-               goto done;
-
-       /* Unmarshall response */
-
-       if (!samr_io_r_del_groupmem("", &r, &rbuf, 0))
-               goto done;
+       CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_DEL_GROUPMEM,
+               q, r,
+               qbuf, rbuf,
+               samr_io_q_del_groupmem,
+               samr_io_r_del_groupmem,
+               NT_STATUS_UNSUCCESSFUL); 
 
        /* Return output parameters */
 
        result = r.status;
 
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
        return result;
 }
 
@@ -520,47 +373,28 @@ NTSTATUS rpccli_samr_query_userinfo(struct rpc_pipe_client *cli,
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        /* Marshall data and send request */
 
        init_samr_q_query_userinfo(&q, user_pol, switch_value);
 
-       if (!samr_io_q_query_userinfo("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req_int(cli, SAMR_QUERY_USERINFO, &qbuf, &rbuf))
-               goto done;
-
-       /* Unmarshall response */
-
-       if (!samr_io_r_query_userinfo("", &r, &rbuf, 0))
-               goto done;
+       CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_QUERY_USERINFO,
+               q, r,
+               qbuf, rbuf,
+               samr_io_q_query_userinfo,
+               samr_io_r_query_userinfo,
+               NT_STATUS_UNSUCCESSFUL); 
 
        /* Return output parameters */
 
        result = r.status;
        *ctr = r.ctr;
 
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
        return result;
 }
 
-NTSTATUS cli_samr_query_userinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx,
-                                 POLICY_HND *user_pol, uint16 switch_value, 
-                                 SAM_USERINFO_CTR **ctr)
-{
-       return rpccli_samr_query_userinfo(&cli->pipes[PI_SAMR], mem_ctx,
-                                         user_pol, switch_value, ctr);
-}
-
 /* Set group info */
 
-NTSTATUS cli_samr_set_groupinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+NTSTATUS rpccli_samr_set_groupinfo(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                POLICY_HND *group_pol, GROUP_INFO_CTR *ctr)
 {
        prs_struct qbuf, rbuf;
@@ -573,38 +407,27 @@ NTSTATUS cli_samr_set_groupinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        /* Marshall data and send request */
 
        init_samr_q_set_groupinfo(&q, group_pol, ctr);
 
-       if (!samr_io_q_set_groupinfo("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, PI_SAMR, SAMR_SET_GROUPINFO, &qbuf, &rbuf))
-               goto done;
-
-       /* Unmarshall response */
-
-       if (!samr_io_r_set_groupinfo("", &r, &rbuf, 0))
-               goto done;
+       CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_SET_GROUPINFO,
+               q, r,
+               qbuf, rbuf,
+               samr_io_q_set_groupinfo,
+               samr_io_r_set_groupinfo,
+               NT_STATUS_UNSUCCESSFUL); 
 
        /* Return output parameters */
 
        result = r.status;
 
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
        return result;
 }
 
 /* Query group info */
 
-NTSTATUS cli_samr_query_groupinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+NTSTATUS rpccli_samr_query_groupinfo(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                   POLICY_HND *group_pol, uint32 info_level, 
                                   GROUP_INFO_CTR **ctr)
 {
@@ -618,23 +441,16 @@ NTSTATUS cli_samr_query_groupinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        /* Marshall data and send request */
 
        init_samr_q_query_groupinfo(&q, group_pol, info_level);
 
-       if (!samr_io_q_query_groupinfo("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, PI_SAMR, SAMR_QUERY_GROUPINFO, &qbuf, &rbuf))
-               goto done;
-
-       /* Unmarshall response */
-
-       if (!samr_io_r_query_groupinfo("", &r, &rbuf, 0))
-               goto done;
+       CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_QUERY_GROUPINFO,
+               q, r,
+               qbuf, rbuf,
+               samr_io_q_query_groupinfo,
+               samr_io_r_query_groupinfo,
+               NT_STATUS_UNSUCCESSFUL); 
 
        *ctr = r.ctr;
 
@@ -642,10 +458,6 @@ NTSTATUS cli_samr_query_groupinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 
        result = r.status;
 
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
        return result;
 }
 
@@ -667,23 +479,16 @@ NTSTATUS rpccli_samr_query_usergroups(struct rpc_pipe_client *cli,
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        /* Marshall data and send request */
 
        init_samr_q_query_usergroups(&q, user_pol);
 
-       if (!samr_io_q_query_usergroups("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req_int(cli, SAMR_QUERY_USERGROUPS, &qbuf, &rbuf))
-               goto done;
-
-       /* Unmarshall response */
-
-       if (!samr_io_r_query_usergroups("", &r, &rbuf, 0))
-               goto done;
+       CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_QUERY_USERGROUPS,
+               q, r,
+               qbuf, rbuf,
+               samr_io_q_query_usergroups,
+               samr_io_r_query_usergroups,
+               NT_STATUS_UNSUCCESSFUL); 
 
        /* Return output parameters */
 
@@ -692,24 +497,12 @@ NTSTATUS rpccli_samr_query_usergroups(struct rpc_pipe_client *cli,
                *gid = r.gid;
        }
 
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
        return result;
 }
 
-NTSTATUS cli_samr_query_usergroups(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
-                                   POLICY_HND *user_pol, uint32 *num_groups, 
-                                   DOM_GID **gid)
-{
-       return rpccli_samr_query_usergroups(&cli->pipes[PI_SAMR], mem_ctx,
-                                           user_pol, num_groups, gid);
-}
-
 /* Set alias info */
 
-NTSTATUS cli_samr_set_aliasinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+NTSTATUS rpccli_samr_set_aliasinfo(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                POLICY_HND *alias_pol, ALIAS_INFO_CTR *ctr)
 {
        prs_struct qbuf, rbuf;
@@ -722,32 +515,21 @@ NTSTATUS cli_samr_set_aliasinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        /* Marshall data and send request */
 
        init_samr_q_set_aliasinfo(&q, alias_pol, ctr);
 
-       if (!samr_io_q_set_aliasinfo("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, PI_SAMR, SAMR_SET_ALIASINFO, &qbuf, &rbuf))
-               goto done;
-
-       /* Unmarshall response */
-
-       if (!samr_io_r_set_aliasinfo("", &r, &rbuf, 0))
-               goto done;
+       CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_SET_ALIASINFO,
+               q, r,
+               qbuf, rbuf,
+               samr_io_q_set_aliasinfo,
+               samr_io_r_set_aliasinfo,
+               NT_STATUS_UNSUCCESSFUL); 
 
        /* Return output parameters */
 
        result = r.status;
 
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
        return result;
 }
 
@@ -771,11 +553,6 @@ NTSTATUS rpccli_samr_query_useraliases(struct rpc_pipe_client *cli,
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        sid_ptrs = TALLOC_ARRAY(mem_ctx, uint32, num_sids);
        if (sid_ptrs == NULL)
                return NT_STATUS_NO_MEMORY;
@@ -787,14 +564,12 @@ NTSTATUS rpccli_samr_query_useraliases(struct rpc_pipe_client *cli,
 
        init_samr_q_query_useraliases(&q, dom_pol, num_sids, sid_ptrs, sid);
 
-       if (!samr_io_q_query_useraliases("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req_int(cli, SAMR_QUERY_USERALIASES, &qbuf, &rbuf))
-               goto done;
-
-       /* Unmarshall response */
-
-       if (!samr_io_r_query_useraliases("", &r, &rbuf, 0))
-               goto done;
+       CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_QUERY_USERALIASES,
+               q, r,
+               qbuf, rbuf,
+               samr_io_q_query_useraliases,
+               samr_io_r_query_useraliases,
+               NT_STATUS_UNSUCCESSFUL); 
 
        /* Return output parameters */
 
@@ -803,25 +578,9 @@ NTSTATUS rpccli_samr_query_useraliases(struct rpc_pipe_client *cli,
                *als_rids = r.rid;
        }
 
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
        return result;
 }
 
-NTSTATUS cli_samr_query_useraliases(struct cli_state *cli,
-                                   TALLOC_CTX *mem_ctx, 
-                                   POLICY_HND *dom_pol, uint32 num_sids,
-                                   DOM_SID2 *sid,
-                                   uint32 *num_aliases, uint32 **als_rids)
-{
-       return rpccli_samr_query_useraliases(&cli->pipes[PI_SAMR], mem_ctx,
-                                            dom_pol, num_sids, sid,
-                                            num_aliases, als_rids);
-}
-
-
 /* Query user groups */
 
 NTSTATUS rpccli_samr_query_groupmem(struct rpc_pipe_client *cli,
@@ -839,23 +598,16 @@ NTSTATUS rpccli_samr_query_groupmem(struct rpc_pipe_client *cli,
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        /* Marshall data and send request */
 
        init_samr_q_query_groupmem(&q, group_pol);
 
-       if (!samr_io_q_query_groupmem("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req_int(cli, SAMR_QUERY_GROUPMEM, &qbuf, &rbuf))
-               goto done;
-
-       /* Unmarshall response */
-
-       if (!samr_io_r_query_groupmem("", &r, &rbuf, 0))
-               goto done;
+       CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_QUERY_GROUPMEM,
+               q, r,
+               qbuf, rbuf,
+               samr_io_q_query_groupmem,
+               samr_io_r_query_groupmem,
+               NT_STATUS_UNSUCCESSFUL); 
 
        /* Return output parameters */
 
@@ -865,22 +617,9 @@ NTSTATUS rpccli_samr_query_groupmem(struct rpc_pipe_client *cli,
                *attr = r.attr;
        }
 
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
        return result;
 }
 
-NTSTATUS cli_samr_query_groupmem(struct cli_state *cli, TALLOC_CTX *mem_ctx,
-                                 POLICY_HND *group_pol, uint32 *num_mem, 
-                                 uint32 **rid, uint32 **attr)
-{
-       return rpccli_samr_query_groupmem(&cli->pipes[PI_SAMR], mem_ctx,
-                                         group_pol, num_mem, rid, attr);
-}
-
-
 /**
  * Enumerate domain users
  *
@@ -898,7 +637,8 @@ NTSTATUS cli_samr_query_groupmem(struct cli_state *cli, TALLOC_CTX *mem_ctx,
  * 
  * @return NTSTATUS returned in rpc response
  **/
-NTSTATUS cli_samr_enum_dom_users(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+
+NTSTATUS rpccli_samr_enum_dom_users(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                  POLICY_HND *pol, uint32 *start_idx, uint16 acb_mask,
                                  uint32 size, char ***dom_users, uint32 **rids,
                                  uint32 *num_dom_users)
@@ -918,25 +658,17 @@ NTSTATUS cli_samr_enum_dom_users(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        /* always init this */
        *num_dom_users = 0;
        
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-       
        /* Fill query structure with parameters */
 
        init_samr_q_enum_dom_users(&q, pol, *start_idx, acb_mask, 0, size);
        
-       if (!samr_io_q_enum_dom_users("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, PI_SAMR, SAMR_ENUM_DOM_USERS, &qbuf, &rbuf)) {
-               goto done;
-       }
+       CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_ENUM_DOM_USERS,
+               q, r,
+               qbuf, rbuf,
+               samr_io_q_enum_dom_users,
+               samr_io_r_enum_dom_users,
+               NT_STATUS_UNSUCCESSFUL); 
 
-       /* unpack received stream */
-
-       if(!samr_io_r_enum_dom_users("", &r, &rbuf, 0))
-               goto done;
-       
        result = r.status;
 
        if (!NT_STATUS_IS_OK(result) &&
@@ -971,9 +703,6 @@ NTSTATUS cli_samr_enum_dom_users(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        }
        
 done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-       
        return result;
 }
 
@@ -996,23 +725,16 @@ NTSTATUS rpccli_samr_enum_dom_groups(struct rpc_pipe_client *cli,
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        /* Marshall data and send request */
 
        init_samr_q_enum_dom_groups(&q, pol, *start_idx, size);
 
-       if (!samr_io_q_enum_dom_groups("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req_int(cli, SAMR_ENUM_DOM_GROUPS, &qbuf, &rbuf))
-               goto done;
-
-       /* Unmarshall response */
-
-       if (!samr_io_r_enum_dom_groups("", &r, &rbuf, 0))
-               goto done;
+       CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_ENUM_DOM_GROUPS,
+               q, r,
+               qbuf, rbuf,
+               samr_io_q_enum_dom_groups,
+               samr_io_r_enum_dom_groups,
+               NT_STATUS_UNSUCCESSFUL); 
 
        /* Return output parameters */
 
@@ -1051,22 +773,9 @@ NTSTATUS rpccli_samr_enum_dom_groups(struct rpc_pipe_client *cli,
        }
 
  done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
        return result;
 }
 
-NTSTATUS cli_samr_enum_dom_groups(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
-                                  POLICY_HND *pol, uint32 *start_idx, 
-                                  uint32 size, struct acct_info **dom_groups,
-                                  uint32 *num_dom_groups)
-{
-       return rpccli_samr_enum_dom_groups(&cli->pipes[PI_SAMR], mem_ctx,
-                                          pol, start_idx, size, dom_groups,
-                                          num_dom_groups);
-}
-
 /* Enumerate domain groups */
 
 NTSTATUS rpccli_samr_enum_als_groups(struct rpc_pipe_client *cli,
@@ -1086,25 +795,16 @@ NTSTATUS rpccli_samr_enum_als_groups(struct rpc_pipe_client *cli,
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        /* Marshall data and send request */
 
        init_samr_q_enum_dom_aliases(&q, pol, *start_idx, size);
 
-       if (!samr_io_q_enum_dom_aliases("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req_int(cli, SAMR_ENUM_DOM_ALIASES, &qbuf, &rbuf)) {
-               goto done;
-       }
-
-       /* Unmarshall response */
-
-       if (!samr_io_r_enum_dom_aliases("", &r, &rbuf, 0)) {
-               goto done;
-       }
+       CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_ENUM_DOM_ALIASES,
+               q, r,
+               qbuf, rbuf,
+               samr_io_q_enum_dom_aliases,
+               samr_io_r_enum_dom_aliases,
+               NT_STATUS_UNSUCCESSFUL); 
 
        /* Return output parameters */
 
@@ -1144,27 +844,15 @@ NTSTATUS rpccli_samr_enum_als_groups(struct rpc_pipe_client *cli,
        }
 
  done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
        return result;
 }
 
-NTSTATUS cli_samr_enum_als_groups(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
-                                  POLICY_HND *pol, uint32 *start_idx, 
-                                  uint32 size, struct acct_info **dom_aliases,
-                                  uint32 *num_dom_aliases)
-{
-       return rpccli_samr_enum_als_groups(&cli->pipes[PI_SAMR], mem_ctx,
-                                          pol, start_idx, size, dom_aliases,
-                                          num_dom_aliases);
-}
-
 /* Query alias members */
 
-NTSTATUS cli_samr_query_aliasmem(struct cli_state *cli, TALLOC_CTX *mem_ctx,
-                                 POLICY_HND *alias_pol, uint32 *num_mem, 
-                                 DOM_SID **sids)
+NTSTATUS rpccli_samr_query_aliasmem(struct rpc_pipe_client *cli,
+                                   TALLOC_CTX *mem_ctx,
+                                   POLICY_HND *alias_pol, uint32 *num_mem, 
+                                   DOM_SID **sids)
 {
        prs_struct qbuf, rbuf;
        SAMR_Q_QUERY_ALIASMEM q;
@@ -1177,25 +865,16 @@ NTSTATUS cli_samr_query_aliasmem(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        /* Marshall data and send request */
 
        init_samr_q_query_aliasmem(&q, alias_pol);
 
-       if (!samr_io_q_query_aliasmem("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, PI_SAMR, SAMR_QUERY_ALIASMEM, &qbuf, &rbuf)) {
-               goto done;
-       }
-
-       /* Unmarshall response */
-
-       if (!samr_io_r_query_aliasmem("", &r, &rbuf, 0)) {
-               goto done;
-       }
+       CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_QUERY_ALIASMEM,
+               q, r,
+               qbuf, rbuf,
+               samr_io_q_query_aliasmem,
+               samr_io_r_query_aliasmem,
+               NT_STATUS_UNSUCCESSFUL); 
 
        /* Return output parameters */
 
@@ -1221,17 +900,15 @@ NTSTATUS cli_samr_query_aliasmem(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        }
 
  done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
        return result;
 }
 
 /* Open handle on an alias */
 
-NTSTATUS cli_samr_open_alias(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
-                             POLICY_HND *domain_pol, uint32 access_mask, 
-                             uint32 alias_rid, POLICY_HND *alias_pol)
+NTSTATUS rpccli_samr_open_alias(struct rpc_pipe_client *cli,
+                               TALLOC_CTX *mem_ctx, 
+                               POLICY_HND *domain_pol, uint32 access_mask, 
+                               uint32 alias_rid, POLICY_HND *alias_pol)
 {
        prs_struct qbuf, rbuf;
        SAMR_Q_OPEN_ALIAS q;
@@ -1243,27 +920,16 @@ NTSTATUS cli_samr_open_alias(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        /* Marshall data and send request */
 
        init_samr_q_open_alias(&q, domain_pol, access_mask, alias_rid);
 
-       if (!samr_io_q_open_alias("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, PI_SAMR, SAMR_OPEN_ALIAS, &qbuf, &rbuf)) {
-               result = NT_STATUS_UNSUCCESSFUL;
-               goto done;
-       }
-
-       /* Unmarshall response */
-
-       if (!samr_io_r_open_alias("", &r, &rbuf, 0)) {
-               result = NT_STATUS_UNSUCCESSFUL;
-               goto done;
-       }
+       CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_OPEN_ALIAS,
+               q, r,
+               qbuf, rbuf,
+               samr_io_q_open_alias,
+               samr_io_r_open_alias,
+               NT_STATUS_UNSUCCESSFUL); 
 
        /* Return output parameters */
 
@@ -1274,16 +940,12 @@ NTSTATUS cli_samr_open_alias(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 #endif
        }
 
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
        return result;
 }
 
 /* Create an alias */
 
-NTSTATUS cli_samr_create_dom_alias(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
+NTSTATUS rpccli_samr_create_dom_alias(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, 
                                   POLICY_HND *domain_pol, const char *name,
                                   POLICY_HND *alias_pol)
 {
@@ -1297,27 +959,16 @@ NTSTATUS cli_samr_create_dom_alias(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        /* Marshall data and send request */
 
        init_samr_q_create_dom_alias(&q, domain_pol, name);
 
-       if (!samr_io_q_create_dom_alias("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, PI_SAMR, SAMR_CREATE_DOM_ALIAS, &qbuf, &rbuf)) {
-               result = NT_STATUS_UNSUCCESSFUL;
-               goto done;
-       }
-
-       /* Unmarshall response */
-
-       if (!samr_io_r_create_dom_alias("", &r, &rbuf, 0)) {
-               result = NT_STATUS_UNSUCCESSFUL;
-               goto done;
-       }
+       CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_CREATE_DOM_ALIAS,
+               q, r,
+               qbuf, rbuf,
+               samr_io_q_create_dom_alias,
+               samr_io_r_create_dom_alias,
+               NT_STATUS_UNSUCCESSFUL); 
 
        /* Return output parameters */
 
@@ -1325,16 +976,12 @@ NTSTATUS cli_samr_create_dom_alias(struct cli_state *cli, TALLOC_CTX *mem_ctx,
                *alias_pol = r.alias_pol;
        }
 
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
        return result;
 }
 
 /* Add an alias member */
 
-NTSTATUS cli_samr_add_aliasmem(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
+NTSTATUS rpccli_samr_add_aliasmem(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, 
                               POLICY_HND *alias_pol, DOM_SID *member)
 {
        prs_struct qbuf, rbuf;
@@ -1347,40 +994,25 @@ NTSTATUS cli_samr_add_aliasmem(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        /* Marshall data and send request */
 
        init_samr_q_add_aliasmem(&q, alias_pol, member);
 
-       if (!samr_io_q_add_aliasmem("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, PI_SAMR, SAMR_ADD_ALIASMEM, &qbuf, &rbuf)) {
-               result = NT_STATUS_UNSUCCESSFUL;
-               goto done;
-       }
-
-       /* Unmarshall response */
-
-       if (!samr_io_r_add_aliasmem("", &r, &rbuf, 0)) {
-               result = NT_STATUS_UNSUCCESSFUL;
-               goto done;
-       }
+       CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_ADD_ALIASMEM,
+               q, r,
+               qbuf, rbuf,
+               samr_io_q_add_aliasmem,
+               samr_io_r_add_aliasmem,
+               NT_STATUS_UNSUCCESSFUL); 
 
        result = r.status;
 
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
        return result;
 }
 
 /* Delete an alias member */
 
-NTSTATUS cli_samr_del_aliasmem(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
+NTSTATUS rpccli_samr_del_aliasmem(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, 
                               POLICY_HND *alias_pol, DOM_SID *member)
 {
        prs_struct qbuf, rbuf;
@@ -1393,40 +1025,25 @@ NTSTATUS cli_samr_del_aliasmem(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        /* Marshall data and send request */
 
        init_samr_q_del_aliasmem(&q, alias_pol, member);
 
-       if (!samr_io_q_del_aliasmem("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, PI_SAMR, SAMR_DEL_ALIASMEM, &qbuf, &rbuf)) {
-               result = NT_STATUS_UNSUCCESSFUL;
-               goto done;
-       }
-
-       /* Unmarshall response */
-
-       if (!samr_io_r_del_aliasmem("", &r, &rbuf, 0)) {
-               result = NT_STATUS_UNSUCCESSFUL;
-               goto done;
-       }
+       CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_DEL_ALIASMEM,
+               q, r,
+               qbuf, rbuf,
+               samr_io_q_del_aliasmem,
+               samr_io_r_del_aliasmem,
+               NT_STATUS_UNSUCCESSFUL); 
 
        result = r.status;
 
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
        return result;
 }
 
 /* Query alias info */
 
-NTSTATUS cli_samr_query_alias_info(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+NTSTATUS rpccli_samr_query_alias_info(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                   POLICY_HND *alias_pol, uint16 switch_value,
                                   ALIAS_INFO_CTR *ctr)
 {
@@ -1440,25 +1057,16 @@ NTSTATUS cli_samr_query_alias_info(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        /* Marshall data and send request */
 
        init_samr_q_query_aliasinfo(&q, alias_pol, switch_value);
 
-       if (!samr_io_q_query_aliasinfo("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, PI_SAMR, SAMR_QUERY_ALIASINFO, &qbuf, &rbuf)) {
-               goto done;
-       }
-
-       /* Unmarshall response */
-
-       if (!samr_io_r_query_aliasinfo("", &r, &rbuf, 0)) {
-               goto done;
-       }
+       CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_QUERY_ALIASINFO,
+               q, r,
+               qbuf, rbuf,
+               samr_io_q_query_aliasinfo,
+               samr_io_r_query_aliasinfo,
+               NT_STATUS_UNSUCCESSFUL); 
 
        /* Return output parameters */
 
@@ -1468,9 +1076,7 @@ NTSTATUS cli_samr_query_alias_info(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 
        *ctr = *r.ctr;
 
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
+  done:
 
        return result;
 }
@@ -1493,27 +1099,18 @@ NTSTATUS rpccli_samr_query_dom_info(struct rpc_pipe_client *cli,
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        /* Marshall data and send request */
 
        init_samr_q_query_dom_info(&q, domain_pol, switch_value);
 
-       if (!samr_io_q_query_dom_info("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req_int(cli, SAMR_QUERY_DOMAIN_INFO, &qbuf, &rbuf)) {
-               goto done;
-       }
-
-       /* Unmarshall response */
-
        r.ctr = ctr;
 
-       if (!samr_io_r_query_dom_info("", &r, &rbuf, 0)) {
-               goto done;
-       }
+       CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_QUERY_DOMAIN_INFO,
+               q, r,
+               qbuf, rbuf,
+               samr_io_q_query_dom_info,
+               samr_io_r_query_dom_info,
+               NT_STATUS_UNSUCCESSFUL); 
 
        /* Return output parameters */
 
@@ -1522,20 +1119,10 @@ NTSTATUS rpccli_samr_query_dom_info(struct rpc_pipe_client *cli,
        }
 
  done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
 
        return result;
 }
 
-NTSTATUS cli_samr_query_dom_info(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
-                                 POLICY_HND *domain_pol, uint16 switch_value,
-                                 SAM_UNK_CTR *ctr)
-{
-       return rpccli_samr_query_dom_info(&cli->pipes[PI_SAMR], mem_ctx,
-                                         domain_pol, switch_value, ctr);
-}
-
 /* User change password */
 
 NTSTATUS rpccli_samr_chgpasswd_user(struct rpc_pipe_client *cli,
@@ -1559,7 +1146,9 @@ NTSTATUS rpccli_samr_chgpasswd_user(struct rpc_pipe_client *cli,
        uchar new_nt_hash[16];
        uchar new_lanman_hash[16];
 
-       DEBUG(10,("cli_samr_query_dom_info\n"));
+       char *srv_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", cli->cli->desthost);
+
+       DEBUG(10,("rpccli_samr_chgpasswd_user\n"));
 
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
@@ -1590,29 +1179,20 @@ NTSTATUS rpccli_samr_chgpasswd_user(struct rpc_pipe_client *cli,
        SamOEMhash( new_nt_password, old_nt_hash, 516);
        E_old_pw_hash( new_nt_hash, old_nt_hash, old_nt_hash_enc);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        /* Marshall data and send request */
 
-       init_samr_q_chgpasswd_user(&q, cli->cli->srv_name_slash, username, 
+       init_samr_q_chgpasswd_user(&q, srv_name_slash, username, 
                                   new_nt_password, 
                                   old_nt_hash_enc, 
                                   new_lm_password,
                                   old_lanman_hash_enc);
 
-       if (!samr_io_q_chgpasswd_user("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req_int(cli, SAMR_CHGPASSWD_USER, &qbuf, &rbuf)) {
-               goto done;
-       }
-
-       /* Unmarshall response */
-
-       if (!samr_io_r_chgpasswd_user("", &r, &rbuf, 0)) {
-               goto done;
-       }
+       CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_CHGPASSWD_USER,
+               q, r,
+               qbuf, rbuf,
+               samr_io_q_chgpasswd_user,
+               samr_io_r_chgpasswd_user,
+               NT_STATUS_UNSUCCESSFUL); 
 
        /* Return output parameters */
 
@@ -1621,21 +1201,10 @@ NTSTATUS rpccli_samr_chgpasswd_user(struct rpc_pipe_client *cli,
        }
 
  done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
 
        return result;
 }
 
-NTSTATUS cli_samr_chgpasswd_user(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
-                                const char *username, 
-                                const char *newpassword, 
-                                const char *oldpassword )
-{
-       return rpccli_samr_chgpasswd_user(&cli->pipes[PI_SAMR], mem_ctx,
-                                         username, newpassword, oldpassword);
-}
-
 /* This function returns the bizzare set of (max_entries, max_size) required
    for the QueryDisplayInfo RPC to actually work against a domain controller
    with large (10k and higher) numbers of users.  These values were 
@@ -1689,28 +1258,19 @@ NTSTATUS rpccli_samr_query_dispinfo(struct rpc_pipe_client *cli,
 
        *num_entries = 0;
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        /* Marshall data and send request */
 
        init_samr_q_query_dispinfo(&q, domain_pol, switch_value,
                                   *start_idx, max_entries, max_size);
 
-       if (!samr_io_q_query_dispinfo("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req_int(cli, SAMR_QUERY_DISPINFO, &qbuf, &rbuf)) {
-               goto done;
-       }
-
-       /* Unmarshall response */
-
        r.ctr = ctr;
 
-       if (!samr_io_r_query_dispinfo("", &r, &rbuf, 0)) {
-               goto done;
-       }
+       CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_QUERY_DISPINFO,
+               q, r,
+               qbuf, rbuf,
+               samr_io_q_query_dispinfo,
+               samr_io_r_query_dispinfo,
+               NT_STATUS_UNSUCCESSFUL); 
 
        /* Return output parameters */
 
@@ -1725,23 +1285,9 @@ NTSTATUS rpccli_samr_query_dispinfo(struct rpc_pipe_client *cli,
        *start_idx += r.num_entries;  /* No next_idx in this structure! */
 
  done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
        return result;
 }
 
-NTSTATUS cli_samr_query_dispinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
-                                 POLICY_HND *domain_pol, uint32 *start_idx,
-                                 uint16 switch_value, uint32 *num_entries,
-                                 uint32 max_entries, uint32 max_size,
-                                SAM_DISPINFO_CTR *ctr)
-{
-       return rpccli_samr_query_dispinfo(&cli->pipes[PI_SAMR], mem_ctx,
-                                         domain_pol, start_idx, switch_value,
-                                         num_entries, max_entries, max_size, ctr);
-}
-
 /* Lookup rids.  Note that NT4 seems to crash if more than ~1000 rids are
    looked up in one packet. */
 
@@ -1768,25 +1314,16 @@ NTSTATUS rpccli_samr_lookup_rids(struct rpc_pipe_client *cli,
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        /* Marshall data and send request */
 
        init_samr_q_lookup_rids(mem_ctx, &q, domain_pol, 1000, num_rids, rids);
 
-       if (!samr_io_q_lookup_rids("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req_int(cli, SAMR_LOOKUP_RIDS, &qbuf, &rbuf)) {
-               goto done;
-       }
-
-       /* Unmarshall response */
-
-       if (!samr_io_r_lookup_rids("", &r, &rbuf, 0)) {
-               goto done;
-       }
+       CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_LOOKUP_RIDS,
+               q, r,
+               qbuf, rbuf,
+               samr_io_q_lookup_rids,
+               samr_io_r_lookup_rids,
+               NT_STATUS_UNSUCCESSFUL); 
 
        /* Return output parameters */
 
@@ -1815,26 +1352,13 @@ NTSTATUS rpccli_samr_lookup_rids(struct rpc_pipe_client *cli,
        }
 
  done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
 
        return result;
 }
 
-NTSTATUS cli_samr_lookup_rids(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
-                              POLICY_HND *domain_pol,
-                              uint32 num_rids, uint32 *rids, 
-                              uint32 *num_names, char ***names,
-                              uint32 **name_types)
-{
-       return rpccli_samr_lookup_rids(&cli->pipes[PI_SAMR], mem_ctx, 
-                                      domain_pol, num_rids, rids, 
-                                      num_names, names, name_types);
-}
-
 /* Lookup names */
 
-NTSTATUS cli_samr_lookup_names(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
+NTSTATUS rpccli_samr_lookup_names(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, 
                                POLICY_HND *domain_pol, uint32 flags,
                                uint32 num_names, const char **names,
                                uint32 *num_rids, uint32 **rids,
@@ -1851,26 +1375,17 @@ NTSTATUS cli_samr_lookup_names(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        /* Marshall data and send request */
 
        init_samr_q_lookup_names(mem_ctx, &q, domain_pol, flags,
                                 num_names, names);
 
-       if (!samr_io_q_lookup_names("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, PI_SAMR, SAMR_LOOKUP_NAMES, &qbuf, &rbuf)) {
-               goto done;
-       }
-
-       /* Unmarshall response */
-
-       if (!samr_io_r_lookup_names("", &r, &rbuf, 0)) {
-               goto done;
-       }
+       CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_LOOKUP_NAMES,
+               q, r,
+               qbuf, rbuf,
+               samr_io_q_lookup_names,
+               samr_io_r_lookup_names,
+               NT_STATUS_UNSUCCESSFUL); 
 
        /* Return output parameters */
 
@@ -1893,15 +1408,13 @@ NTSTATUS cli_samr_lookup_names(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        }
 
  done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
 
        return result;
 }
 
 /* Create a domain user */
 
-NTSTATUS cli_samr_create_dom_user(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
+NTSTATUS rpccli_samr_create_dom_user(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, 
                                   POLICY_HND *domain_pol, const char *acct_name,
                                   uint32 acb_info, uint32 unknown, 
                                   POLICY_HND *user_pol, uint32 *rid)
@@ -1916,25 +1429,16 @@ NTSTATUS cli_samr_create_dom_user(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        /* Marshall data and send request */
 
        init_samr_q_create_user(&q, domain_pol, acct_name, acb_info, unknown);
 
-       if (!samr_io_q_create_user("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, PI_SAMR, SAMR_CREATE_USER, &qbuf, &rbuf)) {
-               goto done;
-       }
-
-       /* Unmarshall response */
-
-       if (!samr_io_r_create_user("", &r, &rbuf, 0)) {
-               goto done;
-       }
+       CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_CREATE_USER,
+               q, r,
+               qbuf, rbuf,
+               samr_io_q_create_user,
+               samr_io_r_create_user,
+               NT_STATUS_UNSUCCESSFUL); 
 
        /* Return output parameters */
 
@@ -1949,15 +1453,13 @@ NTSTATUS cli_samr_create_dom_user(struct cli_state *cli, TALLOC_CTX *mem_ctx,
                *rid = r.user_rid;
 
  done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
 
        return result;
 }
 
 /* Set userinfo */
 
-NTSTATUS cli_samr_set_userinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
+NTSTATUS rpccli_samr_set_userinfo(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, 
                                POLICY_HND *user_pol, uint16 switch_value,
                                DATA_BLOB *sess_key, SAM_USERINFO_CTR *ctr)
 {
@@ -1978,7 +1480,7 @@ NTSTATUS cli_samr_set_userinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 
        /* Initialise parse structures */
 
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
+       prs_init(&qbuf, RPC_MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
        prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
 
        /* Marshall data and send request */
@@ -1988,16 +1490,12 @@ NTSTATUS cli_samr_set_userinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        init_samr_q_set_userinfo(&q, user_pol, sess_key, switch_value, 
                                 ctr->info.id);
 
-       if (!samr_io_q_set_userinfo("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, PI_SAMR, SAMR_SET_USERINFO, &qbuf, &rbuf)) {
-               goto done;
-       }
-
-       /* Unmarshall response */
-
-       if (!samr_io_r_set_userinfo("", &r, &rbuf, 0)) {
-               goto done;
-       }
+       CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_SET_USERINFO,
+               q, r,
+               qbuf, rbuf,
+               samr_io_q_set_userinfo,
+               samr_io_r_set_userinfo,
+               NT_STATUS_UNSUCCESSFUL); 
 
        /* Return output parameters */
 
@@ -2006,15 +1504,13 @@ NTSTATUS cli_samr_set_userinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        }
 
  done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
 
        return result;
 }
 
 /* Set userinfo2 */
 
-NTSTATUS cli_samr_set_userinfo2(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
+NTSTATUS rpccli_samr_set_userinfo2(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, 
                                 POLICY_HND *user_pol, uint16 switch_value,
                                 DATA_BLOB *sess_key, SAM_USERINFO_CTR *ctr)
 {
@@ -2033,25 +1529,16 @@ NTSTATUS cli_samr_set_userinfo2(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        /* Marshall data and send request */
 
        init_samr_q_set_userinfo2(&q, user_pol, sess_key, switch_value, ctr);
 
-       if (!samr_io_q_set_userinfo2("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, PI_SAMR, SAMR_SET_USERINFO2, &qbuf, &rbuf)) {
-               goto done;
-       }
-
-       /* Unmarshall response */
-
-       if (!samr_io_r_set_userinfo2("", &r, &rbuf, 0)) {
-               goto done;
-       }
+       CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_SET_USERINFO2,
+               q, r,
+               qbuf, rbuf,
+               samr_io_q_set_userinfo2,
+               samr_io_r_set_userinfo2,
+               NT_STATUS_UNSUCCESSFUL); 
 
        /* Return output parameters */
 
@@ -2060,15 +1547,13 @@ NTSTATUS cli_samr_set_userinfo2(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        }
 
  done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
 
        return result;
 }
 
 /* Delete domain group */
 
-NTSTATUS cli_samr_delete_dom_group(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
+NTSTATUS rpccli_samr_delete_dom_group(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, 
                                   POLICY_HND *group_pol)
 {
        prs_struct qbuf, rbuf;
@@ -2081,40 +1566,27 @@ NTSTATUS cli_samr_delete_dom_group(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        /* Marshall data and send request */
 
        init_samr_q_delete_dom_group(&q, group_pol);
 
-       if (!samr_io_q_delete_dom_group("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, PI_SAMR, SAMR_DELETE_DOM_GROUP, &qbuf, &rbuf)) {
-               goto done;
-       }
-
-       /* Unmarshall response */
-
-       if (!samr_io_r_delete_dom_group("", &r, &rbuf, 0)) {
-               goto done;
-       }
+       CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_DELETE_DOM_GROUP,
+               q, r,
+               qbuf, rbuf,
+               samr_io_q_delete_dom_group,
+               samr_io_r_delete_dom_group,
+               NT_STATUS_UNSUCCESSFUL); 
 
        /* Return output parameters */
 
        result = r.status;
 
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
        return result;
 }
 
 /* Delete domain alias */
 
-NTSTATUS cli_samr_delete_dom_alias(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
+NTSTATUS rpccli_samr_delete_dom_alias(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, 
                                   POLICY_HND *alias_pol)
 {
        prs_struct qbuf, rbuf;
@@ -2127,40 +1599,27 @@ NTSTATUS cli_samr_delete_dom_alias(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        /* Marshall data and send request */
 
        init_samr_q_delete_dom_alias(&q, alias_pol);
 
-       if (!samr_io_q_delete_dom_alias("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, PI_SAMR, SAMR_DELETE_DOM_ALIAS, &qbuf, &rbuf)) {
-               goto done;
-       }
-
-       /* Unmarshall response */
-
-       if (!samr_io_r_delete_dom_alias("", &r, &rbuf, 0)) {
-               goto done;
-       }
+       CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_DELETE_DOM_ALIAS,
+               q, r,
+               qbuf, rbuf,
+               samr_io_q_delete_dom_alias,
+               samr_io_r_delete_dom_alias,
+               NT_STATUS_UNSUCCESSFUL); 
 
        /* Return output parameters */
 
        result = r.status;
 
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
        return result;
 }
 
 /* Delete domain user */
 
-NTSTATUS cli_samr_delete_dom_user(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
+NTSTATUS rpccli_samr_delete_dom_user(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, 
                                   POLICY_HND *user_pol)
 {
        prs_struct qbuf, rbuf;
@@ -2173,40 +1632,27 @@ NTSTATUS cli_samr_delete_dom_user(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        /* Marshall data and send request */
 
        init_samr_q_delete_dom_user(&q, user_pol);
 
-       if (!samr_io_q_delete_dom_user("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, PI_SAMR, SAMR_DELETE_DOM_USER, &qbuf, &rbuf)) {
-               goto done;
-       }
-
-       /* Unmarshall response */
-
-       if (!samr_io_r_delete_dom_user("", &r, &rbuf, 0)) {
-               goto done;
-       }
+       CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_DELETE_DOM_USER,
+               q, r,
+               qbuf, rbuf,
+               samr_io_q_delete_dom_user,
+               samr_io_r_delete_dom_user,
+               NT_STATUS_UNSUCCESSFUL); 
 
        /* Return output parameters */
 
        result = r.status;
 
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
        return result;
 }
 
 /* Remove foreign SID */
 
-NTSTATUS cli_samr_remove_sid_foreign_domain(struct cli_state *cli, 
+NTSTATUS rpccli_samr_remove_sid_foreign_domain(struct rpc_pipe_client *cli, 
                                            TALLOC_CTX *mem_ctx, 
                                            POLICY_HND *user_pol,
                                            DOM_SID *sid)
@@ -2221,40 +1667,27 @@ NTSTATUS cli_samr_remove_sid_foreign_domain(struct cli_state *cli,
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        /* Marshall data and send request */
 
        init_samr_q_remove_sid_foreign_domain(&q, user_pol, sid);
 
-       if (!samr_io_q_remove_sid_foreign_domain("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, PI_SAMR, SAMR_REMOVE_SID_FOREIGN_DOMAIN, &qbuf, &rbuf)) {
-               goto done;
-       }
-
-       /* Unmarshall response */
-
-       if (!samr_io_r_remove_sid_foreign_domain("", &r, &rbuf, 0)) {
-               goto done;
-       }
+       CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_REMOVE_SID_FOREIGN_DOMAIN,
+               q, r,
+               qbuf, rbuf,
+               samr_io_q_remove_sid_foreign_domain,
+               samr_io_r_remove_sid_foreign_domain,
+               NT_STATUS_UNSUCCESSFUL); 
 
        /* Return output parameters */
 
        result = r.status;
 
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
        return result;
 }
 
 /* Query user security object */
 
-NTSTATUS cli_samr_query_sec_obj(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+NTSTATUS rpccli_samr_query_sec_obj(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                  POLICY_HND *user_pol, uint16 switch_value, 
                                  TALLOC_CTX *ctx, SEC_DESC_BUF **sec_desc_buf)
 {
@@ -2268,41 +1701,28 @@ NTSTATUS cli_samr_query_sec_obj(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        /* Marshall data and send request */
 
        init_samr_q_query_sec_obj(&q, user_pol, switch_value);
 
-       if (!samr_io_q_query_sec_obj("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, PI_SAMR, SAMR_QUERY_SEC_OBJECT, &qbuf, &rbuf)) {
-               goto done;
-       }
-
-       /* Unmarshall response */
-
-       if (!samr_io_r_query_sec_obj("", &r, &rbuf, 0)) {
-               goto done;
-       }
+       CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_QUERY_SEC_OBJECT,
+               q, r,
+               qbuf, rbuf,
+               samr_io_q_query_sec_obj,
+               samr_io_r_query_sec_obj,
+               NT_STATUS_UNSUCCESSFUL); 
 
        /* Return output parameters */
 
        result = r.status;
        *sec_desc_buf=dup_sec_desc_buf(ctx, r.buf);
 
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
        return result;
 }
 
 /* Get domain password info */
 
-NTSTATUS cli_samr_get_dom_pwinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+NTSTATUS rpccli_samr_get_dom_pwinfo(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                 uint16 *unk_0, uint16 *unk_1)
 {
        prs_struct qbuf, rbuf;
@@ -2315,23 +1735,16 @@ NTSTATUS cli_samr_get_dom_pwinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        /* Marshall data and send request */
 
-       init_samr_q_get_dom_pwinfo(&q, cli->desthost);
-
-       if (!samr_io_q_get_dom_pwinfo("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, PI_SAMR, SAMR_GET_DOM_PWINFO, &qbuf, &rbuf))
-               goto done;
-
-       /* Unmarshall response */
+       init_samr_q_get_dom_pwinfo(&q, cli->cli->desthost);
 
-       if (!samr_io_r_get_dom_pwinfo("", &r, &rbuf, 0))
-               goto done;
+       CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_GET_DOM_PWINFO,
+               q, r,
+               qbuf, rbuf,
+               samr_io_q_get_dom_pwinfo,
+               samr_io_r_get_dom_pwinfo,
+               NT_STATUS_UNSUCCESSFUL); 
 
        /* Return output parameters */
 
@@ -2344,16 +1757,12 @@ NTSTATUS cli_samr_get_dom_pwinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx,
                        *unk_1 = r.unk_1;
        }
 
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
        return result;
 }
 
 /* Lookup Domain Name */
 
-NTSTATUS cli_samr_lookup_domain(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+NTSTATUS rpccli_samr_lookup_domain(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                POLICY_HND *user_pol, char *domain_name, 
                                DOM_SID *sid)
 {
@@ -2367,23 +1776,16 @@ NTSTATUS cli_samr_lookup_domain(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        /* Marshall data and send request */
 
        init_samr_q_lookup_domain(&q, user_pol, domain_name);
 
-       if (!samr_io_q_lookup_domain("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, PI_SAMR, SAMR_LOOKUP_DOMAIN, &qbuf, &rbuf))
-               goto done;
-
-       /* Unmarshall response */
-
-       if (!samr_io_r_lookup_domain("", &r, &rbuf, 0))
-               goto done;
+       CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_LOOKUP_DOMAIN,
+               q, r,
+               qbuf, rbuf,
+               samr_io_q_lookup_domain,
+               samr_io_r_lookup_domain,
+               NT_STATUS_UNSUCCESSFUL); 
 
        /* Return output parameters */
 
@@ -2392,9 +1794,5 @@ NTSTATUS cli_samr_lookup_domain(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        if (NT_STATUS_IS_OK(result))
                sid_copy(sid, &r.dom_sid.sid);
 
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
        return result;
 }
index c342f255a9fec0e829f6445adbdc29e73c8e16a4..c06586e98abc15acc9a9061b67c4a1fba056c4de 100644 (file)
@@ -3,10 +3,7 @@
    RPC Pipe client
  
    Copyright (C) Andrew Tridgell              1992-1998,
-   Copyright (C) Luke Kenneth Casson Leighton 1996-1998,
-   Copyright (C) Paul Ashton                  1997-1998.
-   Copyright (C) Jeremy Allison                    1999,
-   Copyright (C) Simo Sorce                        2001,
+   Largely rewritten by Jeremy Allison (C)        2005.
    Copyright (C) Jim McDonough (jmcd@us.ibm.com)   2003.
    
    This program is free software; you can redistribute it and/or modify
 
 /* Shutdown a server */
 
-NTSTATUS cli_shutdown_init(struct cli_state * cli, TALLOC_CTX *mem_ctx,
+NTSTATUS rpccli_shutdown_init(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                           const char *msg, uint32 timeout, BOOL do_reboot,
                           BOOL force)
 {
        prs_struct qbuf;
        prs_struct rbuf; 
-       SHUTDOWN_Q_INIT q_s;
-       SHUTDOWN_R_INIT r_s;
+       SHUTDOWN_Q_INIT q;
+       SHUTDOWN_R_INIT r;
        WERROR result = WERR_GENERAL_FAILURE;
 
        if (msg == NULL) 
                return NT_STATUS_INVALID_PARAMETER;
 
-       ZERO_STRUCT (q_s);
-       ZERO_STRUCT (r_s);
-
-       prs_init(&qbuf , MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
+       ZERO_STRUCT (q);
+       ZERO_STRUCT (r);
 
        /* Marshall data and send request */
 
-       init_shutdown_q_init(&q_s, msg, timeout, do_reboot, force);
-
-       if (!shutdown_io_q_init("", &q_s, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, PI_SHUTDOWN, SHUTDOWN_INIT, &qbuf, &rbuf))
-               goto done;
-       
-       /* Unmarshall response */
-       
-       if(shutdown_io_r_init("", &r_s, &rbuf, 0))
-               result = r_s.status;
+       init_shutdown_q_init(&q, msg, timeout, do_reboot, force);
 
-done:
-       prs_mem_free(&rbuf);
-       prs_mem_free(&qbuf);
+       CLI_DO_RPC(cli, mem_ctx, PI_SHUTDOWN, SHUTDOWN_INIT,
+               q, r,
+               qbuf, rbuf,
+               shutdown_io_q_init,
+               shutdown_io_r_init,
+               NT_STATUS_UNSUCCESSFUL);
 
+       result = r.status;
        return werror_to_ntstatus(result);
 }
 
 /* Shutdown a server */
 
-NTSTATUS cli_shutdown_init_ex(struct cli_state * cli, TALLOC_CTX *mem_ctx,
+NTSTATUS rpccli_shutdown_init_ex(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                           const char *msg, uint32 timeout, BOOL do_reboot,
                           BOOL force, uint32 reason)
 {
        prs_struct qbuf;
        prs_struct rbuf; 
-       SHUTDOWN_Q_INIT_EX q_s;
-       SHUTDOWN_R_INIT_EX r_s;
+       SHUTDOWN_Q_INIT_EX q;
+       SHUTDOWN_R_INIT_EX r;
        WERROR result = WERR_GENERAL_FAILURE;
 
        if (msg == NULL) 
                return NT_STATUS_INVALID_PARAMETER;
 
-       ZERO_STRUCT (q_s);
-       ZERO_STRUCT (r_s);
-
-       prs_init(&qbuf , MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
+       ZERO_STRUCT (q);
+       ZERO_STRUCT (r);
 
        /* Marshall data and send request */
 
-       init_shutdown_q_init_ex(&q_s, msg, timeout, do_reboot, force, reason);
+       init_shutdown_q_init_ex(&q, msg, timeout, do_reboot, force, reason);
 
-       if (!shutdown_io_q_init_ex("", &q_s, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, PI_SHUTDOWN, SHUTDOWN_INIT_EX, &qbuf, &rbuf))
-               goto done;
-       
-       /* Unmarshall response */
-       
-       if(shutdown_io_r_init_ex("", &r_s, &rbuf, 0))
-               result = r_s.status;
-
-done:
-       prs_mem_free(&rbuf);
-       prs_mem_free(&qbuf);
+       CLI_DO_RPC(cli, mem_ctx, PI_SHUTDOWN, SHUTDOWN_INIT_EX,
+               q, r,
+               qbuf, rbuf,
+               shutdown_io_q_init_ex,
+               shutdown_io_r_init_ex,
+               NT_STATUS_UNSUCCESSFUL);
 
+       result = r.status;
        return werror_to_ntstatus(result);
 }
 
 
 /* Abort a server shutdown */
 
-NTSTATUS cli_shutdown_abort(struct cli_state * cli, TALLOC_CTX *mem_ctx)
+NTSTATUS rpccli_shutdown_abort(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx)
 {
        prs_struct rbuf;
        prs_struct qbuf; 
-       SHUTDOWN_Q_ABORT q_s;
-       SHUTDOWN_R_ABORT r_s;
+       SHUTDOWN_Q_ABORT q;
+       SHUTDOWN_R_ABORT r;
        WERROR result = WERR_GENERAL_FAILURE;
 
-       ZERO_STRUCT (q_s);
-       ZERO_STRUCT (r_s);
+       ZERO_STRUCT (q);
+       ZERO_STRUCT (r);
 
-       prs_init(&qbuf , MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-       
        /* Marshall data and send request */
 
-       init_shutdown_q_abort(&q_s);
-
-       if (!shutdown_io_q_abort("", &q_s, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, PI_SHUTDOWN, SHUTDOWN_ABORT, &qbuf, &rbuf))
-               goto done;
-       
-               /* Unmarshall response */
-       
-       if (shutdown_io_r_abort("", &r_s, &rbuf, 0))
-               result = r_s.status;
+       init_shutdown_q_abort(&q);
 
-done:
-       prs_mem_free(&rbuf);
-       prs_mem_free(&qbuf );
+       CLI_DO_RPC(cli, mem_ctx, PI_SHUTDOWN, SHUTDOWN_ABORT,
+               q, r,
+               qbuf, rbuf,
+               shutdown_io_q_abort,
+               shutdown_io_r_abort,
+               NT_STATUS_UNSUCCESSFUL);
 
+       result = r.status;
        return werror_to_ntstatus(result);
 }
index 271382b71fea51689e0d6240d723570c4d7e9d26..4322bacfc8752739dafa243321b2a740ae8375d4 100644 (file)
@@ -5,8 +5,8 @@
    Copyright (C) Gerald Carter                2001-2005,
    Copyright (C) Tim Potter                   2000-2002,
    Copyright (C) Andrew Tridgell              1994-2000,
-   Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
    Copyright (C) Jean-Francois Micouleau      1999-2000.
+   Copyright (C) Jeremy Allison                         2005.
 
    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
@@ -301,7 +301,7 @@ static void decode_forms_1(TALLOC_CTX *mem_ctx, RPC_BUFFER *buffer,
 /**********************************************************************
 **********************************************************************/
 
-WERROR cli_spoolss_open_printer_ex(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+WERROR rpccli_spoolss_open_printer_ex(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                const char *printername, const char *datatype, uint32 access_required,
                                const char *station, const char *username, POLICY_HND *pol)
 {
@@ -315,7 +315,7 @@ WERROR cli_spoolss_open_printer_ex(struct cli_state *cli, TALLOC_CTX *mem_ctx,
         make_spoolss_q_open_printer_ex( &in, printername, datatype,
                access_required, station, username );
 
-       CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_OPENPRINTEREX,
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_OPENPRINTEREX,
                    in, out, 
                    qbuf, rbuf,
                    spoolss_io_q_open_printer_ex,
@@ -330,7 +330,7 @@ WERROR cli_spoolss_open_printer_ex(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 /**********************************************************************
 **********************************************************************/
 
-WERROR cli_spoolss_close_printer(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+WERROR rpccli_spoolss_close_printer(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                 POLICY_HND *pol)
 {
        prs_struct qbuf, rbuf;
@@ -342,7 +342,7 @@ WERROR cli_spoolss_close_printer(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 
         make_spoolss_q_closeprinter( &in, pol );
 
-       CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_CLOSEPRINTER,
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_CLOSEPRINTER,
                    in, out, 
                    qbuf, rbuf,
                    spoolss_io_q_closeprinter,
@@ -355,7 +355,7 @@ WERROR cli_spoolss_close_printer(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 /**********************************************************************
 **********************************************************************/
 
-WERROR cli_spoolss_enum_printers(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+WERROR rpccli_spoolss_enum_printers(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                 char *name, uint32 flags, uint32 level,
                                 uint32 *num_printers, PRINTER_INFO_CTR *ctr)
 {
@@ -372,7 +372,7 @@ WERROR cli_spoolss_enum_printers(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        rpcbuf_init(&buffer, offered, mem_ctx);
        make_spoolss_q_enumprinters( &in, flags, name, level, &buffer, offered );
 
-       CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ENUMPRINTERS,
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ENUMPRINTERS,
                    in, out, 
                    qbuf, rbuf,
                    spoolss_io_q_enumprinters,
@@ -388,7 +388,7 @@ WERROR cli_spoolss_enum_printers(struct cli_state *cli, TALLOC_CTX *mem_ctx,
                rpcbuf_init(&buffer, offered, mem_ctx);
                make_spoolss_q_enumprinters( &in, flags, name, level, &buffer, offered );
 
-               CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ENUMPRINTERS,
+               CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ENUMPRINTERS,
                            in, out, 
                            qbuf, rbuf,
                            spoolss_io_q_enumprinters,
@@ -422,7 +422,7 @@ WERROR cli_spoolss_enum_printers(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 /**********************************************************************
 **********************************************************************/
 
-WERROR cli_spoolss_enum_ports(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+WERROR rpccli_spoolss_enum_ports(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                              uint32 level, uint32 *num_ports, PORT_INFO_CTR *ctr)
 {
        prs_struct qbuf, rbuf;
@@ -435,14 +435,14 @@ WERROR cli_spoolss_enum_ports(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        ZERO_STRUCT(in);
        ZERO_STRUCT(out);
 
-        slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->desthost);
+        slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
         strupper_m(server);
 
        offered = 0;
        rpcbuf_init(&buffer, offered, mem_ctx);
        make_spoolss_q_enumports( &in, server, level, &buffer, offered );
        
-       CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ENUMPORTS,
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ENUMPORTS,
                    in, out, 
                    qbuf, rbuf,
                    spoolss_io_q_enumports,
@@ -458,7 +458,7 @@ WERROR cli_spoolss_enum_ports(struct cli_state *cli, TALLOC_CTX *mem_ctx,
                rpcbuf_init(&buffer, offered, mem_ctx);
                make_spoolss_q_enumports( &in, server, level, &buffer, offered );
 
-               CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ENUMPORTS,
+               CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ENUMPORTS,
                            in, out, 
                            qbuf, rbuf,
                            spoolss_io_q_enumports,
@@ -486,7 +486,7 @@ WERROR cli_spoolss_enum_ports(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 /**********************************************************************
 **********************************************************************/
 
-WERROR cli_spoolss_getprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+WERROR rpccli_spoolss_getprinter(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                              POLICY_HND *pol, uint32 level, 
                              PRINTER_INFO_CTR *ctr)
 {
@@ -505,7 +505,7 @@ WERROR cli_spoolss_getprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        rpcbuf_init(&buffer, offered, mem_ctx);
        make_spoolss_q_getprinter( mem_ctx, &in, pol, level, &buffer, offered );
        
-       CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_GETPRINTER,
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_GETPRINTER,
                    in, out, 
                    qbuf, rbuf,
                    spoolss_io_q_getprinter,
@@ -521,7 +521,7 @@ WERROR cli_spoolss_getprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx,
                rpcbuf_init(&buffer, offered, mem_ctx);
                make_spoolss_q_getprinter( mem_ctx, &in, pol, level, &buffer, offered );
 
-               CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_GETPRINTER,
+               CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_GETPRINTER,
                            in, out, 
                            qbuf, rbuf,
                            spoolss_io_q_getprinter,
@@ -556,7 +556,7 @@ WERROR cli_spoolss_getprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 /**********************************************************************
 **********************************************************************/
 
-WERROR cli_spoolss_setprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+WERROR rpccli_spoolss_setprinter(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                              POLICY_HND *pol, uint32 level, 
                              PRINTER_INFO_CTR *ctr, uint32 command)
 {
@@ -569,7 +569,7 @@ WERROR cli_spoolss_setprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 
        make_spoolss_q_setprinter( mem_ctx, &in, pol, level, ctr, command );
 
-       CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_SETPRINTER,
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_SETPRINTER,
                    in, out, 
                    qbuf, rbuf,
                    spoolss_io_q_setprinter,
@@ -582,7 +582,7 @@ WERROR cli_spoolss_setprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 /**********************************************************************
 **********************************************************************/
 
-WERROR cli_spoolss_getprinterdriver(struct cli_state *cli, 
+WERROR rpccli_spoolss_getprinterdriver(struct rpc_pipe_client *cli, 
                                    TALLOC_CTX *mem_ctx, 
                                    POLICY_HND *pol, uint32 level, 
                                    const char *env, int version, PRINTER_DRIVER_CTR *ctr)
@@ -597,7 +597,7 @@ WERROR cli_spoolss_getprinterdriver(struct cli_state *cli,
        ZERO_STRUCT(in);
        ZERO_STRUCT(out);
 
-       fstrcpy(server, cli->desthost);
+       fstrcpy(server, cli->cli->desthost);
        strupper_m(server);
 
        offered = 0;
@@ -605,7 +605,7 @@ WERROR cli_spoolss_getprinterdriver(struct cli_state *cli,
        make_spoolss_q_getprinterdriver2( &in, pol, env, level, 
                version, 2, &buffer, offered);
 
-       CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_GETPRINTERDRIVER2,
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_GETPRINTERDRIVER2,
                    in, out, 
                    qbuf, rbuf,
                    spoolss_io_q_getprinterdriver2,
@@ -622,7 +622,7 @@ WERROR cli_spoolss_getprinterdriver(struct cli_state *cli,
                make_spoolss_q_getprinterdriver2( &in, pol, env, level, 
                        version, 2, &buffer, offered);
 
-               CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_GETPRINTERDRIVER2,
+               CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_GETPRINTERDRIVER2,
                            in, out, 
                            qbuf, rbuf,
                            spoolss_io_q_getprinterdriver2,
@@ -651,7 +651,7 @@ WERROR cli_spoolss_getprinterdriver(struct cli_state *cli,
 /**********************************************************************
 **********************************************************************/
 
-WERROR cli_spoolss_enumprinterdrivers (struct cli_state *cli, 
+WERROR rpccli_spoolss_enumprinterdrivers (struct rpc_pipe_client *cli, 
                                       TALLOC_CTX *mem_ctx,
                                       uint32 level, const char *env,
                                       uint32 *num_drivers,
@@ -667,7 +667,7 @@ WERROR cli_spoolss_enumprinterdrivers (struct cli_state *cli,
        ZERO_STRUCT(in);
        ZERO_STRUCT(out);
 
-        slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->desthost);
+        slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
         strupper_m(server);
 
        offered = 0;
@@ -675,7 +675,7 @@ WERROR cli_spoolss_enumprinterdrivers (struct cli_state *cli,
        make_spoolss_q_enumprinterdrivers( &in, server, env, level, 
                &buffer, offered);
        
-       CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ENUMPRINTERDRIVERS,
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ENUMPRINTERDRIVERS,
                    in, out, 
                    qbuf, rbuf,
                    spoolss_io_q_enumprinterdrivers,
@@ -692,7 +692,7 @@ WERROR cli_spoolss_enumprinterdrivers (struct cli_state *cli,
                make_spoolss_q_enumprinterdrivers( &in, server, env, level, 
                        &buffer, offered);
        
-               CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ENUMPRINTERDRIVERS,
+               CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ENUMPRINTERDRIVERS,
                            in, out, 
                            qbuf, rbuf,
                            spoolss_io_q_enumprinterdrivers,
@@ -727,7 +727,7 @@ WERROR cli_spoolss_enumprinterdrivers (struct cli_state *cli,
 /**********************************************************************
 **********************************************************************/
 
-WERROR cli_spoolss_getprinterdriverdir (struct cli_state *cli, 
+WERROR rpccli_spoolss_getprinterdriverdir (struct rpc_pipe_client *cli, 
                                        TALLOC_CTX *mem_ctx,
                                        uint32 level, char *env,
                                        DRIVER_DIRECTORY_CTR *ctr)
@@ -742,7 +742,7 @@ WERROR cli_spoolss_getprinterdriverdir (struct cli_state *cli,
        ZERO_STRUCT(in);
        ZERO_STRUCT(out);
 
-        slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->desthost);
+        slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
         strupper_m(server);
 
        offered = 0;
@@ -750,7 +750,7 @@ WERROR cli_spoolss_getprinterdriverdir (struct cli_state *cli,
        make_spoolss_q_getprinterdriverdir( &in, server, env, level, 
                &buffer, offered );
 
-       CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_GETPRINTERDRIVERDIRECTORY,
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_GETPRINTERDRIVERDIRECTORY,
                    in, out, 
                    qbuf, rbuf,
                    spoolss_io_q_getprinterdriverdir,
@@ -767,7 +767,7 @@ WERROR cli_spoolss_getprinterdriverdir (struct cli_state *cli,
                make_spoolss_q_getprinterdriverdir( &in, server, env, level, 
                        &buffer, offered );
 
-               CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_GETPRINTERDRIVERDIRECTORY,
+               CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_GETPRINTERDRIVERDIRECTORY,
                            in, out, 
                            qbuf, rbuf,
                            spoolss_io_q_getprinterdriverdir,
@@ -786,7 +786,7 @@ WERROR cli_spoolss_getprinterdriverdir (struct cli_state *cli,
 /**********************************************************************
 **********************************************************************/
 
-WERROR cli_spoolss_addprinterdriver (struct cli_state *cli, 
+WERROR rpccli_spoolss_addprinterdriver (struct rpc_pipe_client *cli, 
                                     TALLOC_CTX *mem_ctx, uint32 level,
                                     PRINTER_DRIVER_CTR *ctr)
 {
@@ -798,12 +798,12 @@ WERROR cli_spoolss_addprinterdriver (struct cli_state *cli,
        ZERO_STRUCT(in);
        ZERO_STRUCT(out);
        
-        slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->desthost);
+        slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
         strupper_m(server);
 
        make_spoolss_q_addprinterdriver( mem_ctx, &in, server, level, ctr );
 
-       CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ADDPRINTERDRIVER,
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ADDPRINTERDRIVER,
                    in, out, 
                    qbuf, rbuf,
                    spoolss_io_q_addprinterdriver,
@@ -816,7 +816,7 @@ WERROR cli_spoolss_addprinterdriver (struct cli_state *cli,
 /**********************************************************************
 **********************************************************************/
 
-WERROR cli_spoolss_addprinterex (struct cli_state *cli, TALLOC_CTX *mem_ctx,
+WERROR rpccli_spoolss_addprinterex (struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                 uint32 level, PRINTER_INFO_CTR*ctr)
 {
        prs_struct qbuf, rbuf;
@@ -827,8 +827,8 @@ WERROR cli_spoolss_addprinterex (struct cli_state *cli, TALLOC_CTX *mem_ctx,
        ZERO_STRUCT(in);
        ZERO_STRUCT(out);
        
-        slprintf(client, sizeof(fstring)-1, "\\\\%s", cli->desthost);
-        slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->desthost);
+        slprintf(client, sizeof(fstring)-1, "\\\\%s", global_myname());
+        slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
        
         strupper_m(client);
         strupper_m(server);
@@ -838,7 +838,7 @@ WERROR cli_spoolss_addprinterex (struct cli_state *cli, TALLOC_CTX *mem_ctx,
        make_spoolss_q_addprinterex( mem_ctx, &in, server, client, 
                user, level, ctr);
 
-       CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ADDPRINTEREX,
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ADDPRINTEREX,
                    in, out, 
                    qbuf, rbuf,
                    spoolss_io_q_addprinterex,
@@ -851,7 +851,7 @@ WERROR cli_spoolss_addprinterex (struct cli_state *cli, TALLOC_CTX *mem_ctx,
 /**********************************************************************
 **********************************************************************/
 
-WERROR cli_spoolss_deleteprinterdriverex(struct cli_state *cli, 
+WERROR rpccli_spoolss_deleteprinterdriverex(struct rpc_pipe_client *cli, 
                                          TALLOC_CTX *mem_ctx, const char *arch,
                                          const char *driver, int version)
 {
@@ -863,12 +863,12 @@ WERROR cli_spoolss_deleteprinterdriverex(struct cli_state *cli,
        ZERO_STRUCT(in);
        ZERO_STRUCT(out);
 
-       slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->desthost);
+       slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
        strupper_m(server);
 
        make_spoolss_q_deleteprinterdriverex( mem_ctx, &in, server, arch, driver, version );
 
-       CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_DELETEPRINTERDRIVEREX,
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_DELETEPRINTERDRIVEREX,
                    in, out, 
                    qbuf, rbuf,
                    spoolss_io_q_deleteprinterdriverex,
@@ -881,7 +881,7 @@ WERROR cli_spoolss_deleteprinterdriverex(struct cli_state *cli,
 /**********************************************************************
 **********************************************************************/
 
-WERROR cli_spoolss_deleteprinterdriver (struct cli_state *cli, 
+WERROR rpccli_spoolss_deleteprinterdriver (struct rpc_pipe_client *cli, 
                                        TALLOC_CTX *mem_ctx, const char *arch,
                                        const char *driver)
 {
@@ -893,12 +893,12 @@ WERROR cli_spoolss_deleteprinterdriver (struct cli_state *cli,
        ZERO_STRUCT(in);
        ZERO_STRUCT(out);
 
-        slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->desthost);
+        slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
         strupper_m(server);
 
        make_spoolss_q_deleteprinterdriver( mem_ctx, &in, server, arch, driver );
 
-       CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_DELETEPRINTERDRIVER,
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_DELETEPRINTERDRIVER,
                    in, out, 
                    qbuf, rbuf,
                    spoolss_io_q_deleteprinterdriver,
@@ -911,7 +911,7 @@ WERROR cli_spoolss_deleteprinterdriver (struct cli_state *cli,
 /**********************************************************************
 **********************************************************************/
 
-WERROR cli_spoolss_getprintprocessordirectory(struct cli_state *cli,
+WERROR rpccli_spoolss_getprintprocessordirectory(struct rpc_pipe_client *cli,
                                              TALLOC_CTX *mem_ctx,
                                              char *name, char *environment,
                                              fstring procdir)
@@ -931,7 +931,7 @@ WERROR cli_spoolss_getprintprocessordirectory(struct cli_state *cli,
        make_spoolss_q_getprintprocessordirectory( &in, name, 
                environment, level, &buffer, offered );
 
-       CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_GETPRINTPROCESSORDIRECTORY,
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_GETPRINTPROCESSORDIRECTORY,
                    in, out, 
                    qbuf, rbuf,
                    spoolss_io_q_getprintprocessordirectory,
@@ -948,7 +948,7 @@ WERROR cli_spoolss_getprintprocessordirectory(struct cli_state *cli,
                make_spoolss_q_getprintprocessordirectory( &in, name, 
                        environment, level, &buffer, offered );
 
-               CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_GETPRINTPROCESSORDIRECTORY,
+               CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_GETPRINTPROCESSORDIRECTORY,
                            in, out, 
                            qbuf, rbuf,
                            spoolss_io_q_getprintprocessordirectory,
@@ -967,7 +967,7 @@ WERROR cli_spoolss_getprintprocessordirectory(struct cli_state *cli,
 /**********************************************************************
 **********************************************************************/
 
-WERROR cli_spoolss_addform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+WERROR rpccli_spoolss_addform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                           POLICY_HND *handle, uint32 level, FORM *form)
 {
        prs_struct qbuf, rbuf;
@@ -979,7 +979,7 @@ WERROR cli_spoolss_addform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 
         make_spoolss_q_addform( &in, handle, level, form );
        
-       CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ADDFORM,
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ADDFORM,
                    in, out, 
                    qbuf, rbuf,
                    spoolss_io_q_addform,
@@ -992,7 +992,7 @@ WERROR cli_spoolss_addform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 /**********************************************************************
 **********************************************************************/
 
-WERROR cli_spoolss_setform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+WERROR rpccli_spoolss_setform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                           POLICY_HND *handle, uint32 level, 
                           const char *form_name, FORM *form)
 {
@@ -1005,7 +1005,7 @@ WERROR cli_spoolss_setform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 
         make_spoolss_q_setform( &in, handle, level, form_name, form );
        
-       CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_SETFORM,
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_SETFORM,
                    in, out, 
                    qbuf, rbuf,
                    spoolss_io_q_setform,
@@ -1018,7 +1018,7 @@ WERROR cli_spoolss_setform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 /**********************************************************************
 **********************************************************************/
 
-WERROR cli_spoolss_getform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+WERROR rpccli_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                           POLICY_HND *handle, const char *formname, 
                           uint32 level, FORM_1 *form)
 {
@@ -1035,7 +1035,7 @@ WERROR cli_spoolss_getform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        rpcbuf_init(&buffer, offered, mem_ctx);
        make_spoolss_q_getform( &in, handle, formname, level, &buffer, offered );
        
-       CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_GETFORM,
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_GETFORM,
                    in, out, 
                    qbuf, rbuf,
                    spoolss_io_q_getform,
@@ -1051,7 +1051,7 @@ WERROR cli_spoolss_getform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
                rpcbuf_init(&buffer, offered, mem_ctx);
                make_spoolss_q_getform( &in, handle, formname, level, &buffer, offered );
        
-               CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_GETFORM,
+               CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_GETFORM,
                            in, out, 
                            qbuf, rbuf,
                            spoolss_io_q_getform,
@@ -1070,7 +1070,7 @@ WERROR cli_spoolss_getform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 /**********************************************************************
 **********************************************************************/
 
-WERROR cli_spoolss_deleteform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+WERROR rpccli_spoolss_deleteform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                              POLICY_HND *handle, const char *form_name)
 {
        prs_struct qbuf, rbuf;
@@ -1082,7 +1082,7 @@ WERROR cli_spoolss_deleteform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 
         make_spoolss_q_deleteform( &in, handle, form_name );
        
-       CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_DELETEFORM,
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_DELETEFORM,
                    in, out, 
                    qbuf, rbuf,
                    spoolss_io_q_deleteform,
@@ -1095,7 +1095,7 @@ WERROR cli_spoolss_deleteform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 /**********************************************************************
 **********************************************************************/
 
-WERROR cli_spoolss_enumforms(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+WERROR rpccli_spoolss_enumforms(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                             POLICY_HND *handle, int level, uint32 *num_forms,
                             FORM_1 **forms)
 {
@@ -1112,7 +1112,7 @@ WERROR cli_spoolss_enumforms(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        rpcbuf_init(&buffer, offered, mem_ctx);
        make_spoolss_q_enumforms( &in, handle, level, &buffer, offered );
 
-       CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ENUMFORMS,
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ENUMFORMS,
                    in, out, 
                    qbuf, rbuf,
                    spoolss_io_q_enumforms,
@@ -1128,7 +1128,7 @@ WERROR cli_spoolss_enumforms(struct cli_state *cli, TALLOC_CTX *mem_ctx,
                rpcbuf_init(&buffer, offered, mem_ctx);
                make_spoolss_q_enumforms( &in, handle, level, &buffer, offered );
 
-               CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ENUMFORMS,
+               CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ENUMFORMS,
                            in, out, 
                            qbuf, rbuf,
                            spoolss_io_q_enumforms,
@@ -1149,7 +1149,7 @@ WERROR cli_spoolss_enumforms(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 /**********************************************************************
 **********************************************************************/
 
-WERROR cli_spoolss_enumjobs(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+WERROR rpccli_spoolss_enumjobs(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                            POLICY_HND *hnd, uint32 level, uint32 firstjob, 
                            uint32 num_jobs, uint32 *returned, JOB_INFO_CTR *ctr)
 {
@@ -1167,7 +1167,7 @@ WERROR cli_spoolss_enumjobs(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        make_spoolss_q_enumjobs( &in, hnd, firstjob, num_jobs, level, 
                &buffer, offered );
 
-       CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ENUMJOBS,
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ENUMJOBS,
                    in, out, 
                    qbuf, rbuf,
                    spoolss_io_q_enumjobs,
@@ -1184,7 +1184,7 @@ WERROR cli_spoolss_enumjobs(struct cli_state *cli, TALLOC_CTX *mem_ctx,
                make_spoolss_q_enumjobs( &in, hnd, firstjob, num_jobs, level, 
                        &buffer, offered );
 
-               CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ENUMJOBS,
+               CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ENUMJOBS,
                            in, out, 
                            qbuf, rbuf,
                            spoolss_io_q_enumjobs,
@@ -1215,7 +1215,7 @@ WERROR cli_spoolss_enumjobs(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 /**********************************************************************
 **********************************************************************/
 
-WERROR cli_spoolss_setjob(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+WERROR rpccli_spoolss_setjob(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                          POLICY_HND *hnd, uint32 jobid, uint32 level, 
                          uint32 command)
 {
@@ -1228,7 +1228,7 @@ WERROR cli_spoolss_setjob(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 
         make_spoolss_q_setjob( &in, hnd, jobid, level, command );
 
-       CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_SETJOB,
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_SETJOB,
                    in, out, 
                    qbuf, rbuf,
                    spoolss_io_q_setjob,
@@ -1241,7 +1241,7 @@ WERROR cli_spoolss_setjob(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 /**********************************************************************
 **********************************************************************/
 
-WERROR cli_spoolss_getjob(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+WERROR rpccli_spoolss_getjob(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                          POLICY_HND *hnd, uint32 jobid, uint32 level,
                          JOB_INFO_CTR *ctr)
 {
@@ -1258,7 +1258,7 @@ WERROR cli_spoolss_getjob(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        rpcbuf_init(&buffer, offered, mem_ctx);
        make_spoolss_q_getjob( &in, hnd, jobid, level, &buffer, offered );
 
-       CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_GETJOB,
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_GETJOB,
                    in, out, 
                    qbuf, rbuf,
                    spoolss_io_q_getjob,
@@ -1274,7 +1274,7 @@ WERROR cli_spoolss_getjob(struct cli_state *cli, TALLOC_CTX *mem_ctx,
                rpcbuf_init(&buffer, offered, mem_ctx);
                make_spoolss_q_getjob( &in, hnd, jobid, level, &buffer, offered );
 
-               CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_GETJOB,
+               CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_GETJOB,
                            in, out, 
                            qbuf, rbuf,
                            spoolss_io_q_getjob,
@@ -1300,7 +1300,7 @@ WERROR cli_spoolss_getjob(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 /**********************************************************************
 **********************************************************************/
 
-WERROR cli_spoolss_startpageprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+WERROR rpccli_spoolss_startpageprinter(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                    POLICY_HND *hnd)
 {
        prs_struct qbuf, rbuf;
@@ -1312,7 +1312,7 @@ WERROR cli_spoolss_startpageprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 
         make_spoolss_q_startpageprinter( &in, hnd );
 
-       CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_STARTPAGEPRINTER,
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_STARTPAGEPRINTER,
                    in, out, 
                    qbuf, rbuf,
                    spoolss_io_q_startpageprinter,
@@ -1325,7 +1325,7 @@ WERROR cli_spoolss_startpageprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 /**********************************************************************
 **********************************************************************/
 
-WERROR cli_spoolss_endpageprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+WERROR rpccli_spoolss_endpageprinter(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                  POLICY_HND *hnd)
 {
        prs_struct qbuf, rbuf;
@@ -1337,7 +1337,7 @@ WERROR cli_spoolss_endpageprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 
         make_spoolss_q_endpageprinter( &in, hnd );
 
-       CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ENDPAGEPRINTER,
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ENDPAGEPRINTER,
                    in, out, 
                    qbuf, rbuf,
                    spoolss_io_q_endpageprinter,
@@ -1350,7 +1350,7 @@ WERROR cli_spoolss_endpageprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 /**********************************************************************
 **********************************************************************/
 
-WERROR cli_spoolss_startdocprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+WERROR rpccli_spoolss_startdocprinter(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                   POLICY_HND *hnd, char *docname, 
                                   char *outputfile, char *datatype, 
                                   uint32 *jobid)
@@ -1366,7 +1366,7 @@ WERROR cli_spoolss_startdocprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx,
         make_spoolss_q_startdocprinter( &in, hnd, level, docname, 
                outputfile, datatype );
 
-       CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_STARTDOCPRINTER,
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_STARTDOCPRINTER,
                    in, out, 
                    qbuf, rbuf,
                    spoolss_io_q_startdocprinter,
@@ -1381,7 +1381,7 @@ WERROR cli_spoolss_startdocprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 /**********************************************************************
 **********************************************************************/
 
-WERROR cli_spoolss_enddocprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+WERROR rpccli_spoolss_enddocprinter(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                  POLICY_HND *hnd)
 {
        prs_struct qbuf, rbuf;
@@ -1393,7 +1393,7 @@ WERROR cli_spoolss_enddocprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 
         make_spoolss_q_enddocprinter( &in, hnd );
 
-       CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ENDDOCPRINTER,
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ENDDOCPRINTER,
                    in, out, 
                    qbuf, rbuf,
                    spoolss_io_q_enddocprinter,
@@ -1406,7 +1406,7 @@ WERROR cli_spoolss_enddocprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 /**********************************************************************
 **********************************************************************/
 
-WERROR cli_spoolss_getprinterdata(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+WERROR rpccli_spoolss_getprinterdata(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                  POLICY_HND *hnd, const char *valuename, 
                                  REGISTRY_VALUE *value)
 {
@@ -1421,7 +1421,7 @@ WERROR cli_spoolss_getprinterdata(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        offered = 0;
        make_spoolss_q_getprinterdata( &in, hnd, valuename, offered );
 
-       CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_GETPRINTERDATA,
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_GETPRINTERDATA,
                    in, out, 
                    qbuf, rbuf,
                    spoolss_io_q_getprinterdata,
@@ -1436,7 +1436,7 @@ WERROR cli_spoolss_getprinterdata(struct cli_state *cli, TALLOC_CTX *mem_ctx,
                
                make_spoolss_q_getprinterdata( &in, hnd, valuename, offered );
 
-               CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_GETPRINTERDATA,
+               CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_GETPRINTERDATA,
                            in, out, 
                            qbuf, rbuf,
                            spoolss_io_q_getprinterdata,
@@ -1459,7 +1459,7 @@ WERROR cli_spoolss_getprinterdata(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 /**********************************************************************
 **********************************************************************/
 
-WERROR cli_spoolss_getprinterdataex(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+WERROR rpccli_spoolss_getprinterdataex(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                    POLICY_HND *hnd, const char *keyname, 
                                    const char *valuename, 
                                    REGISTRY_VALUE *value)
@@ -1474,7 +1474,7 @@ WERROR cli_spoolss_getprinterdataex(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 
        make_spoolss_q_getprinterdataex( &in, hnd, keyname, valuename, offered );
 
-       CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_GETPRINTERDATAEX,
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_GETPRINTERDATAEX,
                    in, out, 
                    qbuf, rbuf,
                    spoolss_io_q_getprinterdataex,
@@ -1489,7 +1489,7 @@ WERROR cli_spoolss_getprinterdataex(struct cli_state *cli, TALLOC_CTX *mem_ctx,
                
                make_spoolss_q_getprinterdataex( &in, hnd, keyname, valuename, offered );
 
-               CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_GETPRINTERDATAEX,
+               CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_GETPRINTERDATAEX,
                            in, out, 
                            qbuf, rbuf,
                            spoolss_io_q_getprinterdataex,
@@ -1512,7 +1512,7 @@ WERROR cli_spoolss_getprinterdataex(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 /**********************************************************************
 **********************************************************************/
 
-WERROR cli_spoolss_setprinterdata(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+WERROR rpccli_spoolss_setprinterdata(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                  POLICY_HND *hnd, REGISTRY_VALUE *value)
 {
        prs_struct qbuf, rbuf;
@@ -1525,7 +1525,7 @@ WERROR cli_spoolss_setprinterdata(struct cli_state *cli, TALLOC_CTX *mem_ctx,
         make_spoolss_q_setprinterdata( &in, hnd, value->valuename, 
                value->type, (char *)value->data_p, value->size);
 
-       CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_SETPRINTERDATA,
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_SETPRINTERDATA,
                    in, out, 
                    qbuf, rbuf,
                    spoolss_io_q_setprinterdata,
@@ -1538,7 +1538,7 @@ WERROR cli_spoolss_setprinterdata(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 /**********************************************************************
 **********************************************************************/
 
-WERROR cli_spoolss_setprinterdataex(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+WERROR rpccli_spoolss_setprinterdataex(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                    POLICY_HND *hnd, char *keyname, 
                                    REGISTRY_VALUE *value)
 {
@@ -1552,7 +1552,7 @@ WERROR cli_spoolss_setprinterdataex(struct cli_state *cli, TALLOC_CTX *mem_ctx,
         make_spoolss_q_setprinterdataex( &in, hnd, keyname, value->valuename, 
                value->type, (char *)value->data_p, value->size);
 
-       CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_SETPRINTERDATAEX,
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_SETPRINTERDATAEX,
                    in, out, 
                    qbuf, rbuf,
                    spoolss_io_q_setprinterdataex,
@@ -1565,7 +1565,7 @@ WERROR cli_spoolss_setprinterdataex(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 /**********************************************************************
 **********************************************************************/
 
-WERROR cli_spoolss_enumprinterdata(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+WERROR rpccli_spoolss_enumprinterdata(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                   POLICY_HND *hnd, uint32 ndx,
                                   uint32 value_offered, uint32 data_offered,
                                   uint32 *value_needed, uint32 *data_needed,
@@ -1580,7 +1580,7 @@ WERROR cli_spoolss_enumprinterdata(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 
         make_spoolss_q_enumprinterdata( &in, hnd, ndx, value_offered, data_offered );
 
-       CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ENUMPRINTERDATA,
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ENUMPRINTERDATA,
                    in, out, 
                    qbuf, rbuf,
                    spoolss_io_q_enumprinterdata,
@@ -1609,7 +1609,7 @@ WERROR cli_spoolss_enumprinterdata(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 /**********************************************************************
 **********************************************************************/
 
-WERROR cli_spoolss_enumprinterdataex(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+WERROR rpccli_spoolss_enumprinterdataex(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                     POLICY_HND *hnd, const char *keyname, 
                                     REGVAL_CTR *ctr)
 {
@@ -1625,7 +1625,7 @@ WERROR cli_spoolss_enumprinterdataex(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        offered = 0;
        make_spoolss_q_enumprinterdataex( &in, hnd, keyname, offered );
 
-       CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ENUMPRINTERDATAEX,
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ENUMPRINTERDATAEX,
                    in, out, 
                    qbuf, rbuf,
                    spoolss_io_q_enumprinterdataex,
@@ -1640,7 +1640,7 @@ WERROR cli_spoolss_enumprinterdataex(struct cli_state *cli, TALLOC_CTX *mem_ctx,
                
                make_spoolss_q_enumprinterdataex( &in, hnd, keyname, offered );
 
-               CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ENUMPRINTERDATAEX,
+               CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ENUMPRINTERDATAEX,
                            in, out, 
                            qbuf, rbuf,
                            spoolss_io_q_enumprinterdataex,
@@ -1666,7 +1666,7 @@ WERROR cli_spoolss_enumprinterdataex(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 /**********************************************************************
 **********************************************************************/
 
-WERROR cli_spoolss_writeprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+WERROR rpccli_spoolss_writeprinter(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                POLICY_HND *hnd, uint32 data_size, char *data,
                                uint32 *num_written)
 {
@@ -1679,7 +1679,7 @@ WERROR cli_spoolss_writeprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 
         make_spoolss_q_writeprinter( &in, hnd, data_size, data );
 
-       CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_WRITEPRINTER,
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_WRITEPRINTER,
                    in, out, 
                    qbuf, rbuf,
                    spoolss_io_q_writeprinter,
@@ -1695,7 +1695,7 @@ WERROR cli_spoolss_writeprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 /**********************************************************************
 **********************************************************************/
 
-WERROR cli_spoolss_deleteprinterdata(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+WERROR rpccli_spoolss_deleteprinterdata(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                     POLICY_HND *hnd, char *valuename)
 {
        prs_struct qbuf, rbuf;
@@ -1707,7 +1707,7 @@ WERROR cli_spoolss_deleteprinterdata(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 
         make_spoolss_q_deleteprinterdata( &in, hnd, valuename );
 
-       CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_DELETEPRINTERDATA,
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_DELETEPRINTERDATA,
                    in, out, 
                    qbuf, rbuf,
                    spoolss_io_q_deleteprinterdata,
@@ -1720,7 +1720,7 @@ WERROR cli_spoolss_deleteprinterdata(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 /**********************************************************************
 **********************************************************************/
 
-WERROR cli_spoolss_deleteprinterdataex(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+WERROR rpccli_spoolss_deleteprinterdataex(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                       POLICY_HND *hnd, char *keyname, 
                                       char *valuename)
 {
@@ -1733,7 +1733,7 @@ WERROR cli_spoolss_deleteprinterdataex(struct cli_state *cli, TALLOC_CTX *mem_ct
 
         make_spoolss_q_deleteprinterdataex( &in, hnd, keyname, valuename );
 
-       CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_DELETEPRINTERDATAEX, 
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_DELETEPRINTERDATAEX, 
                    in, out, 
                    qbuf, rbuf,
                    spoolss_io_q_deleteprinterdataex,
@@ -1746,7 +1746,7 @@ WERROR cli_spoolss_deleteprinterdataex(struct cli_state *cli, TALLOC_CTX *mem_ct
 /**********************************************************************
 **********************************************************************/
 
-WERROR cli_spoolss_enumprinterkey(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+WERROR rpccli_spoolss_enumprinterkey(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                  POLICY_HND *hnd, const char *keyname,
                                  uint16 **keylist, uint32 *len)
 {
@@ -1760,7 +1760,7 @@ WERROR cli_spoolss_enumprinterkey(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 
        make_spoolss_q_enumprinterkey( &in, hnd, keyname, offered );
 
-       CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ENUMPRINTERKEY, 
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ENUMPRINTERKEY, 
                    in, out, 
                    qbuf, rbuf,
                    spoolss_io_q_enumprinterkey,
@@ -1775,7 +1775,7 @@ WERROR cli_spoolss_enumprinterkey(struct cli_state *cli, TALLOC_CTX *mem_ctx,
                
                make_spoolss_q_enumprinterkey( &in, hnd, keyname, offered );
 
-               CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ENUMPRINTERKEY, 
+               CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ENUMPRINTERKEY, 
                            in, out, 
                            qbuf, rbuf,
                            spoolss_io_q_enumprinterkey,
@@ -1799,7 +1799,7 @@ WERROR cli_spoolss_enumprinterkey(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 /**********************************************************************
 **********************************************************************/
 
-WERROR cli_spoolss_deleteprinterkey(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+WERROR rpccli_spoolss_deleteprinterkey(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                    POLICY_HND *hnd, char *keyname)
 {
        prs_struct qbuf, rbuf;
@@ -1811,7 +1811,7 @@ WERROR cli_spoolss_deleteprinterkey(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 
         make_spoolss_q_deleteprinterkey( &in, hnd, keyname );
 
-       CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_DELETEPRINTERKEY, 
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_DELETEPRINTERKEY, 
                    in, out, 
                    qbuf, rbuf,
                    spoolss_io_q_deleteprinterkey,
index d6bcc8ba9c0cecc6de8acbf0493fb2c543f1e0d2..f8098943dbf58b223fa13e7e70beebce2381dde6 100644 (file)
@@ -5,8 +5,8 @@
    Copyright (C) Gerald Carter                2001-2002,
    Copyright (C) Tim Potter                   2000-2002,
    Copyright (C) Andrew Tridgell              1994-2000,
-   Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
    Copyright (C) Jean-Francois Micouleau      1999-2000.
+   Copyright (C) Jeremy Allison                    2005.
 
    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
@@ -36,7 +36,7 @@
    value) and this rpc establishes a back-channel over which printer
    notifications are performed. */
 
-WERROR cli_spoolss_reply_open_printer(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
+WERROR rpccli_spoolss_reply_open_printer(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, 
                                      const char *printer, uint32 printerlocal, uint32 type, 
                                      POLICY_HND *handle)
 {
@@ -47,37 +47,28 @@ WERROR cli_spoolss_reply_open_printer(struct cli_state *cli, TALLOC_CTX *mem_ctx
        
        /* Initialise input parameters */
 
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        make_spoolss_q_replyopenprinter(&q, printer, printerlocal, type);
 
        /* Marshall data and send request */
 
-       if (!spoolss_io_q_replyopenprinter("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req (cli, PI_SPOOLSS, SPOOLSS_REPLYOPENPRINTER, &qbuf, &rbuf)) 
-               goto done;
-       
-       /* Unmarshall response */
-       
-       if (!spoolss_io_r_replyopenprinter("", &r, &rbuf, 0))
-               goto done;
-               
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_REPLYOPENPRINTER,
+               q, r,
+               qbuf, rbuf,
+               spoolss_io_q_replyopenprinter,
+               spoolss_io_r_replyopenprinter,
+               WERR_GENERAL_FAILURE );
+
        /* Return result */
 
        memcpy(handle, &r.handle, sizeof(r.handle));
        result = r.status;
 
-done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
        return result;
 }
 
 /* Close a back-channel notification connection */
 
-WERROR cli_spoolss_reply_close_printer(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
+WERROR rpccli_spoolss_reply_close_printer(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, 
                                       POLICY_HND *handle)
 {
        prs_struct qbuf, rbuf;
@@ -87,30 +78,20 @@ WERROR cli_spoolss_reply_close_printer(struct cli_state *cli, TALLOC_CTX *mem_ct
 
        /* Initialise input parameters */
 
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        make_spoolss_q_reply_closeprinter(&q, handle);
 
        /* Marshall data and send request */
 
-       if (!spoolss_io_q_replycloseprinter("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req (cli, PI_SPOOLSS, SPOOLSS_REPLYCLOSEPRINTER, &qbuf, &rbuf)) 
-               goto done;
-       
-       /* Unmarshall response */
-       
-       if (!spoolss_io_r_replycloseprinter("", &r, &rbuf, 0))
-               goto done;
-               
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_REPLYCLOSEPRINTER,
+               q, r,
+               qbuf, rbuf,
+               spoolss_io_q_replycloseprinter,
+               spoolss_io_r_replycloseprinter,
+               WERR_GENERAL_FAILURE );
+
        /* Return result */
 
        result = r.status;
-       
-done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
        return result;
 }
 
@@ -121,7 +102,7 @@ done:
  Also see cli_spolss_reply_rrpcn()
  *********************************************************************/
  
-WERROR cli_spoolss_routerreplyprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+WERROR rpccli_spoolss_routerreplyprinter(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                      POLICY_HND *pol, uint32 condition, uint32 change_id)
 {
        prs_struct qbuf, rbuf;
@@ -131,30 +112,20 @@ WERROR cli_spoolss_routerreplyprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx
 
        /* Initialise input parameters */
 
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        make_spoolss_q_routerreplyprinter(&q, pol, condition, change_id);
 
        /* Marshall data and send request */
 
-       if (!spoolss_io_q_routerreplyprinter("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req (cli, PI_SPOOLSS, SPOOLSS_ROUTERREPLYPRINTER, &qbuf, &rbuf)) 
-               goto done;
-       
-       /* Unmarshall response */
-       
-       if (!spoolss_io_r_routerreplyprinter("", &r, &rbuf, 0))
-               goto done;
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ROUTERREPLYPRINTER,
+               q, r,
+               qbuf, rbuf,
+               spoolss_io_q_routerreplyprinter,
+               spoolss_io_r_routerreplyprinter,
+               WERR_GENERAL_FAILURE );
 
        /* Return output parameters */
 
        result = r.status;
-
-done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
        return result;  
 }
 
@@ -165,7 +136,7 @@ done:
  Also see cli_spoolss_routereplyprinter()
  *********************************************************************/
 
-WERROR cli_spoolss_rrpcn(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
+WERROR rpccli_spoolss_rrpcn(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, 
                         POLICY_HND *pol, uint32 notify_data_len,
                         SPOOL_NOTIFY_INFO_DATA *notify_data,
                         uint32 change_low, uint32 change_high)
@@ -179,11 +150,6 @@ WERROR cli_spoolss_rrpcn(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        ZERO_STRUCT(notify_info);
 
        /* Initialise input parameters */
@@ -201,14 +167,12 @@ WERROR cli_spoolss_rrpcn(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 
        /* Marshall data and send request */
 
-       if(!spoolss_io_q_reply_rrpcn("", &q,  &qbuf, 0) ||
-          !rpc_api_pipe_req(cli, PI_SPOOLSS, SPOOLSS_RRPCN, &qbuf, &rbuf)) 
-               goto done;
-
-       /* Unmarshall response */
-       
-       if(!spoolss_io_r_reply_rrpcn("", &r, &rbuf, 0))
-               goto done;
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_RRPCN,
+               q, r,
+               qbuf, rbuf,
+               spoolss_io_q_reply_rrpcn,
+               spoolss_io_r_reply_rrpcn,
+               WERR_GENERAL_FAILURE );
 
        if (r.unknown0 == 0x00080000)
                DEBUG(8,("cli_spoolss_reply_rrpcn: I think the spooler resonded that the notification was ignored.\n"));
@@ -216,18 +180,13 @@ WERROR cli_spoolss_rrpcn(struct cli_state *cli, TALLOC_CTX *mem_ctx,
                DEBUG(8,("cli_spoolss_reply_rrpcn: unknown0 is non-zero [0x%x]\n", r.unknown0));
        
        result = r.status;
-
-done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
        return result;
 }
 
 /*********************************************************************
  *********************************************************************/
  
-WERROR cli_spoolss_rffpcnex(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+WERROR rpccli_spoolss_rffpcnex(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                            POLICY_HND *pol, uint32 flags, uint32 options,
                            const char *localmachine, uint32 printerlocal,
                            SPOOL_NOTIFY_OPTION *option)
@@ -240,11 +199,6 @@ WERROR cli_spoolss_rffpcnex(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        /* Initialise input parameters */
 
        make_spoolss_q_rffpcnex(
@@ -253,20 +207,13 @@ WERROR cli_spoolss_rffpcnex(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 
        /* Marshall data and send request */
 
-       if(!spoolss_io_q_rffpcnex("", &q,  &qbuf, 0) ||
-          !rpc_api_pipe_req(cli, PI_SPOOLSS, SPOOLSS_RFFPCNEX, &qbuf, &rbuf)) 
-               goto done;
-
-       /* Unmarshall response */
-       
-       if(!spoolss_io_r_rffpcnex("", &r, &rbuf, 0))
-               goto done;
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_RFFPCNEX,
+               q, r,
+               qbuf, rbuf,
+               spoolss_io_q_rffpcnex,
+               spoolss_io_r_rffpcnex,
+               WERR_GENERAL_FAILURE );
 
        result = r.status;
-
-done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
        return result;
 }
index b2449a79038e9f1e7a1716ea9f88d4b1ca73bc66..2c71d6b18eaca96ab12b179dc10733862866d5c9 100644 (file)
@@ -2,10 +2,10 @@
    Unix SMB/CIFS implementation.
    NT Domain Authentication SMB / MSRPC client
    Copyright (C) Andrew Tridgell 1994-2000
-   Copyright (C) Luke Kenneth Casson Leighton 1996-2000
    Copyright (C) Tim Potter 2001
    Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2002
-   
+   Copyright (C) Jeremy Allison  2005.
+
    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
@@ -23,7 +23,7 @@
 
 #include "includes.h"
 
-WERROR cli_srvsvc_net_srv_get_info(struct cli_state *cli, 
+WERROR rpccli_srvsvc_net_srv_get_info(struct rpc_pipe_client *cli, 
                                   TALLOC_CTX *mem_ctx,
                                   uint32 switch_value, SRV_INFO_CTR *ctr)
 {
@@ -31,42 +31,33 @@ WERROR cli_srvsvc_net_srv_get_info(struct cli_state *cli,
        SRV_Q_NET_SRV_GET_INFO q;
        SRV_R_NET_SRV_GET_INFO r;
        WERROR result = W_ERROR(ERRgeneral);
+       fstring server;
 
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        /* Initialise input parameters */
 
-       init_srv_q_net_srv_get_info(&q, cli->srv_name_slash, switch_value);
-
-       /* Marshall data and send request */
-
-       if (!srv_io_q_net_srv_get_info("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, PI_SRVSVC, SRV_NET_SRV_GET_INFO, &qbuf, &rbuf))
-               goto done;
-
-       /* Unmarshall response */
+       slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
+       strupper_m(server);
 
+       init_srv_q_net_srv_get_info(&q, server, switch_value);
        r.ctr = ctr;
 
-       if (!srv_io_r_net_srv_get_info("", &r, &rbuf, 0))
-               goto done;
-
-       result = r.status;
+       /* Marshall data and send request */
 
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
+       CLI_DO_RPC_WERR(cli, mem_ctx, PI_SRVSVC, SRV_NET_SRV_GET_INFO,
+               q, r,
+               qbuf, rbuf,
+               srv_io_q_net_srv_get_info,
+               srv_io_r_net_srv_get_info,
+               WERR_GENERAL_FAILURE);
 
+       result = r.status;
        return result;
 }
 
-WERROR cli_srvsvc_net_share_enum(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+WERROR rpccli_srvsvc_net_share_enum(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                 uint32 info_level, SRV_SHARE_INFO_CTR *ctr,
                                 int preferred_len, ENUM_HND *hnd)
 {
@@ -74,31 +65,27 @@ WERROR cli_srvsvc_net_share_enum(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        SRV_Q_NET_SHARE_ENUM q;
        SRV_R_NET_SHARE_ENUM r;
        WERROR result = W_ERROR(ERRgeneral);
+       fstring server;
        int i;
 
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        /* Initialise input parameters */
 
-       init_srv_q_net_share_enum(
-               &q, cli->srv_name_slash, info_level, preferred_len, hnd);
+       slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
+       strupper_m(server);
 
-       /* Marshall data and send request */
+       init_srv_q_net_share_enum(&q, server, info_level, preferred_len, hnd);
 
-       if (!srv_io_q_net_share_enum("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, PI_SRVSVC, SRV_NET_SHARE_ENUM_ALL, &qbuf, &rbuf))
-               goto done;
+       /* Marshall data and send request */
 
-       /* Unmarshall response */
-
-       if (!srv_io_r_net_share_enum("", &r, &rbuf, 0))
-               goto done;
+       CLI_DO_RPC_WERR(cli, mem_ctx, PI_SRVSVC, SRV_NET_SHARE_ENUM_ALL,
+               q, r,
+               qbuf, rbuf,
+               srv_io_q_net_share_enum,
+               srv_io_r_net_share_enum,
+               WERR_GENERAL_FAILURE);
 
        result = r.status;
 
@@ -215,14 +202,13 @@ WERROR cli_srvsvc_net_share_enum(struct cli_state *cli, TALLOC_CTX *mem_ctx,
                }
                break;
        }
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
+
+  done:
 
        return result;
 }
 
-WERROR cli_srvsvc_net_share_get_info(struct cli_state *cli,
+WERROR rpccli_srvsvc_net_share_get_info(struct rpc_pipe_client *cli,
                                     TALLOC_CTX *mem_ctx,
                                     const char *sharename,
                                     uint32 info_level,
@@ -232,30 +218,26 @@ WERROR cli_srvsvc_net_share_get_info(struct cli_state *cli,
        SRV_Q_NET_SHARE_GET_INFO q;
        SRV_R_NET_SHARE_GET_INFO r;
        WERROR result = W_ERROR(ERRgeneral);
+       fstring server;
 
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        /* Initialise input parameters */
 
-       init_srv_q_net_share_get_info(&q, cli->srv_name_slash, sharename,
-                                     info_level);
+       slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
+       strupper_m(server);
 
-       /* Marshall data and send request */
+       init_srv_q_net_share_get_info(&q, server, sharename, info_level);
 
-       if (!srv_io_q_net_share_get_info("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, PI_SRVSVC, SRV_NET_SHARE_GET_INFO, &qbuf, &rbuf))
-               goto done;
+       /* Marshall data and send request */
 
-       /* Unmarshall response */
-
-       if (!srv_io_r_net_share_get_info("", &r, &rbuf, 0))
-               goto done;
+       CLI_DO_RPC_WERR(cli, mem_ctx, PI_SRVSVC, SRV_NET_SHARE_GET_INFO,
+               q, r,
+               qbuf, rbuf,
+               srv_io_q_net_share_get_info,
+               srv_io_r_net_share_get_info,
+               WERR_GENERAL_FAILURE);
 
        result = r.status;
 
@@ -363,14 +345,12 @@ WERROR cli_srvsvc_net_share_get_info(struct cli_state *cli,
                break;
        }
 
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
+  done:
 
        return result;
 }
 
-WERROR cli_srvsvc_net_share_set_info(struct cli_state *cli,
+WERROR rpccli_srvsvc_net_share_set_info(struct rpc_pipe_client *cli,
                                     TALLOC_CTX *mem_ctx,
                                     const char *sharename,
                                     uint32 info_level,
@@ -380,84 +360,64 @@ WERROR cli_srvsvc_net_share_set_info(struct cli_state *cli,
        SRV_Q_NET_SHARE_SET_INFO q;
        SRV_R_NET_SHARE_SET_INFO r;
        WERROR result = W_ERROR(ERRgeneral);
+       fstring server;
 
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        /* Initialise input parameters */
 
-       init_srv_q_net_share_set_info(&q, cli->srv_name_slash, sharename,
-                                     info_level, info);
-
-       /* Marshall data and send request */
+       slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
+       strupper_m(server);
 
-       if (!srv_io_q_net_share_set_info("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, PI_SRVSVC, SRV_NET_SHARE_SET_INFO, &qbuf, &rbuf))
-               goto done;
+       init_srv_q_net_share_set_info(&q, server, sharename, info_level, info);
 
-       /* Unmarshall response */
+       /* Marshall data and send request */
 
-       if (!srv_io_r_net_share_set_info("", &r, &rbuf, 0))
-               goto done;
+       CLI_DO_RPC_WERR(cli, mem_ctx, PI_SRVSVC, SRV_NET_SHARE_SET_INFO,
+               q, r,
+               qbuf, rbuf,
+               srv_io_q_net_share_set_info,
+               srv_io_r_net_share_set_info,
+               WERR_GENERAL_FAILURE);
 
        result = r.status;
-
-       if (!W_ERROR_IS_OK(result))
-               goto done;
-
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
        return result;
 }
 
-WERROR cli_srvsvc_net_share_del(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+WERROR rpccli_srvsvc_net_share_del(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                const char *sharename)
 {
        prs_struct qbuf, rbuf;
        SRV_Q_NET_SHARE_DEL q;
        SRV_R_NET_SHARE_DEL r;
        WERROR result = W_ERROR(ERRgeneral);
+       fstring server;
 
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        /* Initialise input parameters */
 
-       init_srv_q_net_share_del(&q, cli->srv_name_slash, sharename);
+       slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
+       strupper_m(server);
 
-       /* Marshall data and send request */
+       init_srv_q_net_share_del(&q, server, sharename);
 
-       if (!srv_io_q_net_share_del("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, PI_SRVSVC, SRV_NET_SHARE_DEL, &qbuf, &rbuf))
-               goto done;
-
-       /* Unmarshall response */
+       /* Marshall data and send request */
 
-       if (!srv_io_r_net_share_del("", &r, &rbuf, 0))
-               goto done;
+       CLI_DO_RPC_WERR(cli, mem_ctx, PI_SRVSVC, SRV_NET_SHARE_DEL,
+               q, r,
+               qbuf, rbuf,
+               srv_io_q_net_share_del,
+               srv_io_r_net_share_del,
+               WERR_GENERAL_FAILURE);
 
        result = r.status;
-
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
        return result;
 }
 
-WERROR cli_srvsvc_net_share_add(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+WERROR rpccli_srvsvc_net_share_add(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                const char *netname, uint32 type, 
                                const char *remark, uint32 perms, 
                                uint32 max_uses, uint32 num_uses, 
@@ -468,85 +428,65 @@ WERROR cli_srvsvc_net_share_add(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        SRV_Q_NET_SHARE_ADD q;
        SRV_R_NET_SHARE_ADD r;
        WERROR result = W_ERROR(ERRgeneral);
+       fstring server;
 
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
+       slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
+       strupper_m(server);
 
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
-       init_srv_q_net_share_add(&q,cli->srv_name_slash, netname, type, remark,
+       init_srv_q_net_share_add(&q,server, netname, type, remark,
                                 perms, max_uses, num_uses, path, passwd, 
                                 level, sd);
 
        /* Marshall data and send request */
 
-       if (!srv_io_q_net_share_add("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, PI_SRVSVC, SRV_NET_SHARE_ADD, &qbuf, &rbuf))
-               goto done;
-
-       /* Unmarshall response */
-
-       if (!srv_io_r_net_share_add("", &r, &rbuf, 0))
-               goto done;
+       CLI_DO_RPC_WERR(cli, mem_ctx, PI_SRVSVC, SRV_NET_SHARE_ADD,
+               q, r,
+               qbuf, rbuf,
+               srv_io_q_net_share_add,
+               srv_io_r_net_share_add,
+               WERR_GENERAL_FAILURE);
 
        result = r.status;
-
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
        return result;  
 }
 
-WERROR cli_srvsvc_net_remote_tod(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+WERROR rpccli_srvsvc_net_remote_tod(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                 char *server, TIME_OF_DAY_INFO *tod)
 {
        prs_struct qbuf, rbuf;
        SRV_Q_NET_REMOTE_TOD q;
        SRV_R_NET_REMOTE_TOD r;
        WERROR result = W_ERROR(ERRgeneral);
+       fstring server_slash;
 
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        /* Initialise input parameters */
 
-       init_srv_q_net_remote_tod(&q, cli->srv_name_slash);
-
-       /* Marshall data and send request */
-
-       if (!srv_io_q_net_remote_tod("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, PI_SRVSVC, SRV_NET_REMOTE_TOD, &qbuf, &rbuf))
-               goto done;
-
-       /* Unmarshall response */
+       slprintf(server_slash, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
+       strupper_m(server_slash);
 
+       init_srv_q_net_remote_tod(&q, server_slash);
        r.tod = tod;
 
-       if (!srv_io_r_net_remote_tod("", &r, &rbuf, 0))
-               goto done;
-
-       result = r.status;
-
-       if (!W_ERROR_IS_OK(result))
-               goto done;
+       /* Marshall data and send request */
 
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
+       CLI_DO_RPC_WERR(cli, mem_ctx, PI_SRVSVC, SRV_NET_REMOTE_TOD,
+               q, r,
+               qbuf, rbuf,
+               srv_io_q_net_remote_tod,
+               srv_io_r_net_remote_tod,
+               WERR_GENERAL_FAILURE);
 
+       result = r.status;
        return result;  
 }
 
-WERROR cli_srvsvc_net_file_enum(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+WERROR rpccli_srvsvc_net_file_enum(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                uint32 file_level, const char *user_name,
                                SRV_FILE_INFO_CTR *ctr, int preferred_len,
                                ENUM_HND *hnd)
@@ -555,31 +495,28 @@ WERROR cli_srvsvc_net_file_enum(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        SRV_Q_NET_FILE_ENUM q;
        SRV_R_NET_FILE_ENUM r;
        WERROR result = W_ERROR(ERRgeneral);
+       fstring server;
        int i;
 
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        /* Initialise input parameters */
 
-       init_srv_q_net_file_enum(&q, cli->srv_name_slash, NULL, user_name, 
+       slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
+       strupper_m(server);
+
+       init_srv_q_net_file_enum(&q, server, NULL, user_name, 
                                 file_level, ctr, preferred_len, hnd);
 
        /* Marshall data and send request */
 
-       if (!srv_io_q_net_file_enum("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, PI_SRVSVC, SRV_NET_FILE_ENUM, &qbuf, &rbuf))
-               goto done;
-
-       /* Unmarshall response */
-
-       if (!srv_io_r_net_file_enum("", &r, &rbuf, 0))
-               goto done;
+       CLI_DO_RPC_WERR(cli, mem_ctx, PI_SRVSVC, SRV_NET_FILE_ENUM,
+               q, r,
+               qbuf, rbuf,
+               srv_io_q_net_file_enum,
+               srv_io_r_net_file_enum,
+               WERR_GENERAL_FAILURE);
 
        result = r.status;
 
@@ -625,47 +562,38 @@ WERROR cli_srvsvc_net_file_enum(struct cli_state *cli, TALLOC_CTX *mem_ctx,
                break;
        }
 
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
-
+  done:
        return result;
 }
 
-WERROR cli_srvsvc_net_file_close(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+WERROR rpccli_srvsvc_net_file_close(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                 uint32 file_id)
 {
        prs_struct qbuf, rbuf;
        SRV_Q_NET_FILE_CLOSE q;
        SRV_R_NET_FILE_CLOSE r;
        WERROR result = W_ERROR(ERRgeneral);
+       fstring server;
 
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-       /* Initialise parse structures */
-
-       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        /* Initialise input parameters */
 
-       init_srv_q_net_file_close(&q, cli->srv_name_slash, file_id);
+       slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
+       strupper_m(server);
 
-       /* Marshall data and send request */
-
-       if (!srv_io_q_net_file_close("", &q, &qbuf, 0) ||
-           !rpc_api_pipe_req(cli, PI_SRVSVC, SRV_NET_FILE_CLOSE, &qbuf, &rbuf))
-               goto done;
+       init_srv_q_net_file_close(&q, server, file_id);
 
-       /* Unmarshall response */
+       /* Marshall data and send request */
 
-       if (!srv_io_r_net_file_close("", &r, &rbuf, 0))
-               goto done;
+       CLI_DO_RPC_WERR(cli, mem_ctx, PI_SRVSVC, SRV_NET_FILE_CLOSE,
+               q, r,
+               qbuf, rbuf,
+               srv_io_q_net_file_close,
+               srv_io_r_net_file_close,
+               WERR_GENERAL_FAILURE);
 
        result = r.status;
- done:
-       prs_mem_free(&qbuf);
-       prs_mem_free(&rbuf);
        return result;
 }
index 9f80bb79a399cfc59bf87af54db6f76b31dad6e8..2df27c2da5b51d2e822ea8739b8fd5e91c2b96e6 100644 (file)
@@ -61,7 +61,7 @@ const char* svc_status_string( uint32 state )
 /********************************************************************
 ********************************************************************/
 
-WERROR cli_svcctl_open_scm( struct cli_state *cli, TALLOC_CTX *mem_ctx, 
+WERROR rpccli_svcctl_open_scm(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, 
                               POLICY_HND *hSCM, uint32 access_desired )
 {
        SVCCTL_Q_OPEN_SCMANAGER in;
@@ -80,12 +80,12 @@ WERROR cli_svcctl_open_scm( struct cli_state *cli, TALLOC_CTX *mem_ctx,
 
        if ( !(in.servername = TALLOC_P( mem_ctx, UNISTR2 )) )
                return WERR_NOMEM;
-       fstr_sprintf( server, "\\\\%s", cli->desthost );
+       fstr_sprintf( server, "\\\\%s", cli->cli->desthost );
        init_unistr2( in.servername, server, UNI_STR_TERMINATE );
 
        in.access = access_desired;
        
-       CLI_DO_RPC( cli, mem_ctx, PI_SVCCTL, SVCCTL_OPEN_SCMANAGER_W, 
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_SVCCTL, SVCCTL_OPEN_SCMANAGER_W, 
                    in, out, 
                    qbuf, rbuf,
                    svcctl_io_q_open_scmanager,
@@ -103,7 +103,7 @@ WERROR cli_svcctl_open_scm( struct cli_state *cli, TALLOC_CTX *mem_ctx,
 /********************************************************************
 ********************************************************************/
 
-WERROR cli_svcctl_open_service( struct cli_state *cli, TALLOC_CTX *mem_ctx, 
+WERROR rpccli_svcctl_open_service( struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, 
                                 POLICY_HND *hSCM, POLICY_HND *hService, 
                                const char *servicename, uint32 access_desired )
 {
@@ -118,7 +118,7 @@ WERROR cli_svcctl_open_service( struct cli_state *cli, TALLOC_CTX *mem_ctx,
        init_unistr2( &in.servicename, servicename, UNI_STR_TERMINATE );
        in.access = access_desired;
        
-       CLI_DO_RPC( cli, mem_ctx, PI_SVCCTL, SVCCTL_OPEN_SERVICE_W, 
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_SVCCTL, SVCCTL_OPEN_SERVICE_W, 
                    in, out, 
                    qbuf, rbuf,
                    svcctl_io_q_open_service,
@@ -136,7 +136,7 @@ WERROR cli_svcctl_open_service( struct cli_state *cli, TALLOC_CTX *mem_ctx,
 /********************************************************************
 ********************************************************************/
 
-WERROR cli_svcctl_close_service( struct cli_state *cli, TALLOC_CTX *mem_ctx, POLICY_HND *hService )
+WERROR rpccli_svcctl_close_service(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *hService )
 {
        SVCCTL_Q_CLOSE_SERVICE in;
        SVCCTL_R_CLOSE_SERVICE out;
@@ -147,7 +147,7 @@ WERROR cli_svcctl_close_service( struct cli_state *cli, TALLOC_CTX *mem_ctx, POL
        
        memcpy( &in.handle, hService, sizeof(POLICY_HND) );
        
-       CLI_DO_RPC( cli, mem_ctx, PI_SVCCTL, SVCCTL_CLOSE_SERVICE, 
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_SVCCTL, SVCCTL_CLOSE_SERVICE, 
                    in, out, 
                    qbuf, rbuf,
                    svcctl_io_q_close_service,
@@ -160,7 +160,7 @@ WERROR cli_svcctl_close_service( struct cli_state *cli, TALLOC_CTX *mem_ctx, POL
 /*******************************************************************
 *******************************************************************/
 
-WERROR cli_svcctl_enumerate_services( struct cli_state *cli, TALLOC_CTX *mem_ctx,
+WERROR rpccli_svcctl_enumerate_services( struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                       POLICY_HND *hSCM, uint32 type, uint32 state, 
                                      uint32 *returned, ENUM_SERVICES_STATUS **service_array  )
 {
@@ -185,7 +185,7 @@ WERROR cli_svcctl_enumerate_services( struct cli_state *cli, TALLOC_CTX *mem_ctx
        /* first time is to get the buffer size */
        in.buffer_size = 0;
 
-       CLI_DO_RPC( cli, mem_ctx, PI_SVCCTL, SVCCTL_ENUM_SERVICES_STATUS_W, 
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_SVCCTL, SVCCTL_ENUM_SERVICES_STATUS_W, 
                    in, out, 
                    qbuf, rbuf,
                    svcctl_io_q_enum_services_status,
@@ -197,7 +197,7 @@ WERROR cli_svcctl_enumerate_services( struct cli_state *cli, TALLOC_CTX *mem_ctx
        if ( W_ERROR_EQUAL( out.status, WERR_MORE_DATA ) ) {
                in.buffer_size = out.needed;
 
-               CLI_DO_RPC( cli, mem_ctx, PI_SVCCTL, SVCCTL_ENUM_SERVICES_STATUS_W, 
+               CLI_DO_RPC_WERR( cli, mem_ctx, PI_SVCCTL, SVCCTL_ENUM_SERVICES_STATUS_W, 
                            in, out, 
                            qbuf, rbuf,
                            svcctl_io_q_enum_services_status,
@@ -225,7 +225,7 @@ WERROR cli_svcctl_enumerate_services( struct cli_state *cli, TALLOC_CTX *mem_ctx
 /*******************************************************************
 *******************************************************************/
 
-WERROR cli_svcctl_query_status( struct cli_state *cli, TALLOC_CTX *mem_ctx,
+WERROR rpccli_svcctl_query_status( struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                 POLICY_HND *hService, SERVICE_STATUS *status )
 {
        SVCCTL_Q_QUERY_STATUS in;
@@ -237,7 +237,7 @@ WERROR cli_svcctl_query_status( struct cli_state *cli, TALLOC_CTX *mem_ctx,
        
        memcpy( &in.handle, hService, sizeof(POLICY_HND) );
        
-       CLI_DO_RPC( cli, mem_ctx, PI_SVCCTL, SVCCTL_QUERY_STATUS, 
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_SVCCTL, SVCCTL_QUERY_STATUS, 
                    in, out, 
                    qbuf, rbuf,
                    svcctl_io_q_query_status,
@@ -255,7 +255,7 @@ WERROR cli_svcctl_query_status( struct cli_state *cli, TALLOC_CTX *mem_ctx,
 /*******************************************************************
 *******************************************************************/
 
-WERROR cli_svcctl_query_config(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+WERROR rpccli_svcctl_query_config(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                 POLICY_HND *hService, SERVICE_CONFIG *config )
 {
        SVCCTL_Q_QUERY_SERVICE_CONFIG in;
@@ -269,7 +269,7 @@ WERROR cli_svcctl_query_config(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        in.buffer_size = 0;
        
        
-       CLI_DO_RPC( cli, mem_ctx, PI_SVCCTL, SVCCTL_QUERY_SERVICE_CONFIG_W, 
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_SVCCTL, SVCCTL_QUERY_SERVICE_CONFIG_W, 
                    in, out, 
                    qbuf, rbuf,
                    svcctl_io_q_query_service_config,
@@ -279,7 +279,7 @@ WERROR cli_svcctl_query_config(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        if ( W_ERROR_EQUAL( out.status, WERR_INSUFFICIENT_BUFFER ) ) {
                in.buffer_size = out.needed;
 
-               CLI_DO_RPC( cli, mem_ctx, PI_SVCCTL, SVCCTL_QUERY_SERVICE_CONFIG_W,
+               CLI_DO_RPC_WERR( cli, mem_ctx, PI_SVCCTL, SVCCTL_QUERY_SERVICE_CONFIG_W,
                            in, out, 
                            qbuf, rbuf,
                            svcctl_io_q_query_service_config,
@@ -298,11 +298,30 @@ WERROR cli_svcctl_query_config(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        config->startname      = TALLOC_ZERO_P( mem_ctx, UNISTR2 );
        config->displayname    = TALLOC_ZERO_P( mem_ctx, UNISTR2 );
        
-       copy_unistr2( config->executablepath, out.config.executablepath );
-       copy_unistr2( config->loadordergroup, out.config.loadordergroup );
-       copy_unistr2( config->dependencies, out.config.dependencies );
-       copy_unistr2( config->startname, out.config.startname );
-       copy_unistr2( config->displayname, out.config.displayname );
+       if ( out.config.executablepath ) {
+               config->executablepath = TALLOC_ZERO_P( mem_ctx, UNISTR2 );
+               copy_unistr2( config->executablepath, out.config.executablepath );
+       }
+
+       if ( out.config.loadordergroup ) {
+               config->loadordergroup = TALLOC_ZERO_P( mem_ctx, UNISTR2 );
+               copy_unistr2( config->loadordergroup, out.config.loadordergroup );
+       }
+
+       if ( out.config.dependencies ) {
+               config->dependencies = TALLOC_ZERO_P( mem_ctx, UNISTR2 );
+               copy_unistr2( config->dependencies, out.config.dependencies );
+       }
+
+       if ( out.config.startname ) {
+               config->startname = TALLOC_ZERO_P( mem_ctx, UNISTR2 );
+               copy_unistr2( config->startname, out.config.startname );
+       }
+
+       if ( out.config.displayname ) {
+               config->displayname = TALLOC_ZERO_P( mem_ctx, UNISTR2 );
+               copy_unistr2( config->displayname, out.config.displayname );
+       }
        
        return out.status;
 }
@@ -310,7 +329,7 @@ WERROR cli_svcctl_query_config(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 /*******************************************************************
 *******************************************************************/
 
-WERROR cli_svcctl_start_service( struct cli_state *cli, TALLOC_CTX *mem_ctx,
+WERROR rpccli_svcctl_start_service( struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                  POLICY_HND *hService,
                                  const char **parm_array, uint32 parmcount )
 {
@@ -326,7 +345,7 @@ WERROR cli_svcctl_start_service( struct cli_state *cli, TALLOC_CTX *mem_ctx,
        in.parmcount  = 0;
        in.parameters = NULL;
        
-       CLI_DO_RPC( cli, mem_ctx, PI_SVCCTL, SVCCTL_START_SERVICE_W,
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_SVCCTL, SVCCTL_START_SERVICE_W,
                    in, out, 
                    qbuf, rbuf,
                    svcctl_io_q_start_service,
@@ -339,7 +358,7 @@ WERROR cli_svcctl_start_service( struct cli_state *cli, TALLOC_CTX *mem_ctx,
 /*******************************************************************
 *******************************************************************/
 
-WERROR cli_svcctl_control_service( struct cli_state *cli, TALLOC_CTX *mem_ctx,
+WERROR rpccli_svcctl_control_service( struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                    POLICY_HND *hService, uint32 control,
                                   SERVICE_STATUS *status )
 {
@@ -353,7 +372,7 @@ WERROR cli_svcctl_control_service( struct cli_state *cli, TALLOC_CTX *mem_ctx,
        memcpy( &in.handle, hService, sizeof(POLICY_HND) );
        in.control = control;
        
-       CLI_DO_RPC( cli, mem_ctx, PI_SVCCTL, SVCCTL_CONTROL_SERVICE, 
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_SVCCTL, SVCCTL_CONTROL_SERVICE, 
                    in, out, 
                    qbuf, rbuf,
                    svcctl_io_q_control_service,
@@ -372,7 +391,7 @@ WERROR cli_svcctl_control_service( struct cli_state *cli, TALLOC_CTX *mem_ctx,
 /*******************************************************************
 *******************************************************************/
 
-WERROR cli_svcctl_get_dispname( struct cli_state *cli, TALLOC_CTX *mem_ctx, 
+WERROR rpccli_svcctl_get_dispname( struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, 
                                 POLICY_HND *hService, fstring displayname )
 {
        SVCCTL_Q_GET_DISPLAY_NAME in;
@@ -385,7 +404,7 @@ WERROR cli_svcctl_get_dispname( struct cli_state *cli, TALLOC_CTX *mem_ctx,
        memcpy( &in.handle, hService, sizeof(POLICY_HND) );
        in.display_name_len = 0;
        
-       CLI_DO_RPC( cli, mem_ctx, PI_SVCCTL, SVCCTL_GET_DISPLAY_NAME, 
+       CLI_DO_RPC_WERR( cli, mem_ctx, PI_SVCCTL, SVCCTL_GET_DISPLAY_NAME, 
                    in, out, 
                    qbuf, rbuf,
                    svcctl_io_q_get_display_name,
@@ -397,7 +416,7 @@ WERROR cli_svcctl_get_dispname( struct cli_state *cli, TALLOC_CTX *mem_ctx,
        if ( W_ERROR_EQUAL( out.status, WERR_INSUFFICIENT_BUFFER ) ) {
                in.display_name_len = out.display_name_len;
 
-               CLI_DO_RPC( cli, mem_ctx, PI_SVCCTL, SVCCTL_GET_DISPLAY_NAME, 
+               CLI_DO_RPC_WERR( cli, mem_ctx, PI_SVCCTL, SVCCTL_GET_DISPLAY_NAME, 
                            in, out, 
                            qbuf, rbuf,
                            svcctl_io_q_get_display_name,
@@ -412,4 +431,3 @@ WERROR cli_svcctl_get_dispname( struct cli_state *cli, TALLOC_CTX *mem_ctx,
        
        return out.status;
 }
-
index aea474439887d78190271fe8cc73771509568b82..d8e97beb6493e9cbb00332d83eaa98293cce5f33 100644 (file)
@@ -2,10 +2,10 @@
    Unix SMB/CIFS implementation.
    NT Domain Authentication SMB / MSRPC client
    Copyright (C) Andrew Tridgell 1994-2000
-   Copyright (C) Luke Kenneth Casson Leighton 1996-2000
    Copyright (C) Tim Potter 2001
-   Copytight (C) Rafal Szczesniak 2002
-   
+   Copyright (C) Rafal Szczesniak 2002
+   Copyright (C) Jeremy Allison 2005.
+
    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
  * @return NTSTATUS of rpc call
  */
  
-NTSTATUS cli_wks_query_info(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+NTSTATUS rpccli_wks_query_info(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                            WKS_INFO_100 *wks100)
 {
-       prs_struct buf;
+       prs_struct qbuf;
        prs_struct rbuf;
-       WKS_Q_QUERY_INFO q_o;
-       WKS_R_QUERY_INFO r_o;
+       WKS_Q_QUERY_INFO q;
+       WKS_R_QUERY_INFO r;
 
        if (cli == NULL || wks100 == NULL)
                return NT_STATUS_UNSUCCESSFUL;
 
-       /* init rpc parse structures */
-       prs_init(&buf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
-       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
-
        DEBUG(4, ("WksQueryInfo\n"));
        
        /* init query structure with rpc call arguments */
-       init_wks_q_query_info(&q_o, cli->desthost, 100);
-       
-       /* marshall data */
-       if (!wks_io_q_query_info("", &q_o, &buf, 0)) {
-               prs_mem_free(&buf);
-               prs_mem_free(&rbuf);
-               return NT_STATUS_UNSUCCESSFUL;
-       }
-       
-       /* actual rpc call over \PIPE\wkssvc */
-       if (!rpc_api_pipe_req(cli, PI_WKSSVC, WKS_QUERY_INFO, &buf, &rbuf)) {
-               prs_mem_free(&buf);
-               prs_mem_free(&rbuf);
-               return NT_STATUS_UNSUCCESSFUL;
-       }
-       
-       prs_mem_free(&buf);
+       init_wks_q_query_info(&q, cli->cli->desthost, 100);
+       r.wks100 = wks100;
 
-       r_o.wks100 = wks100;
-
-       /* get call results from response buffer */
-       if (!wks_io_r_query_info("", &r_o, &rbuf, 0)) {
-               prs_mem_free(&rbuf);
-               return NT_STATUS_UNSUCCESSFUL;
-       }
-       
+       CLI_DO_RPC(cli, mem_ctx, PI_WKSSVC, WKS_QUERY_INFO,
+               q, r,
+               qbuf, rbuf,
+               wks_io_q_query_info,
+               wks_io_r_query_info,
+               NT_STATUS_UNSUCCESSFUL);
+               
        /* check returnet status code */
-       if (NT_STATUS_IS_ERR(r_o.status)) {
+       if (NT_STATUS_IS_ERR(r.status)) {
                /* report the error */
-               DEBUG(0,("WKS_R_QUERY_INFO: %s\n", nt_errstr(r_o.status)));
-               prs_mem_free(&rbuf);
-               return r_o.status;
+               DEBUG(0,("WKS_R_QUERY_INFO: %s\n", nt_errstr(r.status)));
+               return r.status;
        }
        
-       /* do clean up */
-       prs_mem_free(&rbuf);
-       
        return NT_STATUS_OK;
 }
-
index ff2a7cc2f6e456e5c6cc038f89a4b2cbb805bb59..36d8eda8474685bc4d3b8f75ff86842f47c9a0f0 100644 (file)
@@ -106,7 +106,7 @@ BOOL prs_rpcbuffer_p(const char *desc, prs_struct *ps, int depth, RPC_BUFFER **b
 
        /* caputure the pointer value to stream */
 
-       data_p = (uint32) *buffer;
+       data_p = *buffer ? 0xf000baaa : 0;
 
        if ( !prs_uint32("ptr", ps, depth, &data_p ))
                return False;
index 3f7b2a4cd59f279f0d976addfa369f500a4d6659..f102e950042be73287d1299458561c45bf33d873 100644 (file)
@@ -22,8 +22,6 @@
  */
 
 #include "includes.h"
-#include "nterr.h"
-#include "rpc_parse.h"   
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_RPC_PARSE
index 9155419ae438848b59ab9fb0e9ef844719f2a3fe..c6131452226bb433a58fb7c90f753ec72d6b11a0 100644 (file)
 /************************************************************************
 ************************************************************************/
 
-static BOOL ds_io_dominfobasic( const char *desc, prs_struct *ps, int depth, DSROLE_PRIMARY_DOMAIN_INFO_BASIC **basic)
+static BOOL ds_io_dominfobasic(const char *desc, DSROLE_PRIMARY_DOMAIN_INFO_BASIC **basic, prs_struct *ps, int depth)
 {
        DSROLE_PRIMARY_DOMAIN_INFO_BASIC *p = *basic;
        
-       if ( UNMARSHALLING(ps) )
+       if ( UNMARSHALLING(ps) ) {
                p = *basic = PRS_ALLOC_MEM(ps, DSROLE_PRIMARY_DOMAIN_INFO_BASIC, 1);
+       }
                
        if ( !p )
                return False;
@@ -75,7 +76,7 @@ static BOOL ds_io_dominfobasic( const char *desc, prs_struct *ps, int depth, DSR
 /************************************************************************
 ************************************************************************/
 
-BOOL ds_io_q_getprimdominfo( const char *desc, prs_struct *ps, int depth, DS_Q_GETPRIMDOMINFO *q_u)
+BOOL ds_io_q_getprimdominfo( const char *desc, DS_Q_GETPRIMDOMINFO *q_u, prs_struct *ps, int depth)
 {
        prs_debug(ps, depth, desc, "ds_io_q_getprimdominfo");
        depth++;
@@ -92,7 +93,7 @@ BOOL ds_io_q_getprimdominfo( const char *desc, prs_struct *ps, int depth, DS_Q_G
 /************************************************************************
 ************************************************************************/
 
-BOOL ds_io_r_getprimdominfo( const char *desc, prs_struct *ps, int depth, DS_R_GETPRIMDOMINFO *r_u)
+BOOL ds_io_r_getprimdominfo( const char *desc, DS_R_GETPRIMDOMINFO *r_u, prs_struct *ps, int depth)
 {
        prs_debug(ps, depth, desc, "ds_io_r_getprimdominfo");
        depth++;
@@ -114,7 +115,7 @@ BOOL ds_io_r_getprimdominfo( const char *desc, prs_struct *ps, int depth, DS_R_G
                switch ( r_u->level )
                {
                        case DsRolePrimaryDomainInfoBasic:
-                               if ( !ds_io_dominfobasic( "dominfobasic", ps, depth, &r_u->info.basic ) )
+                               if ( !ds_io_dominfobasic( "dominfobasic", &r_u->info.basic, ps, depth) )
                                        return False;
                                break;
                        default:
@@ -135,8 +136,7 @@ BOOL ds_io_r_getprimdominfo( const char *desc, prs_struct *ps, int depth, DS_R_G
  initialize a DS_ENUM_DOM_TRUSTS structure
 ************************************************************************/
 
-BOOL init_q_ds_enum_domain_trusts( DS_Q_ENUM_DOM_TRUSTS *q, const char *server, 
-                                 uint32 flags )
+BOOL init_q_ds_enum_domain_trusts( DS_Q_ENUM_DOM_TRUSTS *q, const char *server, uint32 flags )
 {
        q->flags = flags;
        
@@ -153,7 +153,7 @@ BOOL init_q_ds_enum_domain_trusts( DS_Q_ENUM_DOM_TRUSTS *q, const char *server,
 /************************************************************************
 ************************************************************************/
 
-static BOOL ds_io_domain_trusts( const char *desc, prs_struct *ps, int depth, DS_DOMAIN_TRUSTS *trust)
+static BOOL ds_io_domain_trusts( const char *desc, DS_DOMAIN_TRUSTS *trust, prs_struct *ps, int depth)
 {
        prs_debug(ps, depth, desc, "ds_io_dom_trusts_ctr");
        depth++;
@@ -188,7 +188,7 @@ static BOOL ds_io_domain_trusts( const char *desc, prs_struct *ps, int depth, DS
 /************************************************************************
 ************************************************************************/
 
-static BOOL ds_io_dom_trusts_ctr( const char *desc, prs_struct *ps, int depth, DS_DOMAIN_TRUSTS_CTR *ctr)
+static BOOL ds_io_dom_trusts_ctr( const char *desc, DS_DOMAIN_TRUSTS_CTR *ctr, prs_struct *ps, int depth)
 {
        int i;
 
@@ -217,7 +217,7 @@ static BOOL ds_io_dom_trusts_ctr( const char *desc, prs_struct *ps, int depth, D
           we need another loop to read the UNISTR2's and SID's */
           
        for ( i=0; i<ctr->max_count;i++ ) {
-               if ( !ds_io_domain_trusts("domain_trusts", ps, depth, &ctr->trusts[i] ) )
+               if ( !ds_io_domain_trusts("domain_trusts", &ctr->trusts[i], ps, depth) )
                        return False;
        }
 
@@ -248,7 +248,7 @@ static BOOL ds_io_dom_trusts_ctr( const char *desc, prs_struct *ps, int depth, D
  initialize a DS_ENUM_DOM_TRUSTS request
 ************************************************************************/
 
-BOOL ds_io_q_enum_domain_trusts( const char *desc, prs_struct *ps, int depth, DS_Q_ENUM_DOM_TRUSTS *q_u)
+BOOL ds_io_q_enum_domain_trusts( const char *desc, DS_Q_ENUM_DOM_TRUSTS *q_u, prs_struct *ps, int depth)
 {
        prs_debug(ps, depth, desc, "ds_io_q_enum_domain_trusts");
        depth++;
@@ -274,7 +274,7 @@ BOOL ds_io_q_enum_domain_trusts( const char *desc, prs_struct *ps, int depth, DS
 /************************************************************************
 ************************************************************************/
 
-BOOL ds_io_r_enum_domain_trusts( const char *desc, prs_struct *ps, int depth, DS_R_ENUM_DOM_TRUSTS *r_u)
+BOOL ds_io_r_enum_domain_trusts( const char *desc, DS_R_ENUM_DOM_TRUSTS *r_u, prs_struct *ps, int depth)
 {
        prs_debug(ps, depth, desc, "ds_io_r_enum_domain_trusts");
        depth++;
@@ -286,7 +286,7 @@ BOOL ds_io_r_enum_domain_trusts( const char *desc, prs_struct *ps, int depth, DS
                return False;
                
        if ( r_u->num_domains ) {
-               if ( !ds_io_dom_trusts_ctr("domains", ps, depth, &r_u->domains ) )
+               if ( !ds_io_dom_trusts_ctr("domains", &r_u->domains, ps, depth) )
                        return False;
        }
                
@@ -298,5 +298,3 @@ BOOL ds_io_r_enum_domain_trusts( const char *desc, prs_struct *ps, int depth, DS
                
        return True;
 }
-
-
index b4aa8de24ab9a78c2168e1473efb179f57bf23e9..48dda7b17152b8504eea79e10c5237d674696d27 100644 (file)
@@ -21,8 +21,6 @@
  */
 
 #include "includes.h"
-#include "nterr.h"
-#include "rpc_parse.h"   
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_RPC_PARSE
index 734f52fffb37f8ac0552417ce2f04f718b2f5c3b..1b57272ca4c85c8f75bed6d00bf163865d5310d3 100644 (file)
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_RPC_PARSE
 
-/*
- * called from eventlog_q_open_eventlog (srv_eventlog.c)
- */
+/********************************************************************
+********************************************************************/
+
+BOOL prs_ev_open_unknown0( const char *desc, prs_struct *ps, int depth, EVENTLOG_OPEN_UNKNOWN0 *u )
+{
+       if ( !u )
+               return False;
+       
+       if ( !prs_uint16("", ps, depth, &u->unknown1) )
+               return False;
+       if ( !prs_uint16("", ps, depth, &u->unknown2) )
+               return False;
+
+       return True;
+}
+
+/********************************************************************
+********************************************************************/
 
 BOOL eventlog_io_q_open_eventlog(const char *desc, EVENTLOG_Q_OPEN_EVENTLOG *q_u,
                                 prs_struct *ps, int depth)
@@ -33,62 +48,28 @@ BOOL eventlog_io_q_open_eventlog(const char *desc, EVENTLOG_Q_OPEN_EVENTLOG *q_u
        if(q_u == NULL)
                return False;
     
-    /** Data format seems to be:
-       UNKNOWN structure
-         uint32            unknown
-         uint16            unknown
-         uint16            unknown
-       Eventlog name
-         uint16            eventlog name length
-         uint16            eventlog name size
-         Character Array
-          uint32          unknown
-          uint32          max count
-           uint32          offset
-           uint32          actual count
-          UNISTR2         log file name
-       Server Name
-         uint16            server name length
-         uint16            server name size
-        Character Array
-          UNISTR2         server name
-    */
-
        prs_debug(ps, depth, desc, "eventlog_io_q_open_eventlog");
        depth++;
 
        if(!prs_align(ps))
                return False;
 
-       /* Munch unknown bits */
-
-       if(!prs_uint32("", ps, depth, &q_u->unknown1))
-               return False;
-       if(!prs_uint16("", ps, depth, &q_u->unknown2))
-               return False;
-       if(!prs_uint16("", ps, depth, &q_u->unknown3))
-               return False;
-       if(!prs_align(ps))
+       if ( !prs_pointer("", ps, depth, (void**)&q_u->unknown0, sizeof(EVENTLOG_OPEN_UNKNOWN0), (PRS_POINTER_CAST)prs_ev_open_unknown0))
                return False;
 
-       /* Get name of log source */
-
-       if(!prs_uint16("sourcename_length", ps, depth, &q_u->sourcename_length))
-               return False;
-       if(!prs_uint16("sourcename_size", ps, depth, &q_u->sourcename_size))
+       if ( !prs_unistr4("logname", ps, depth, &q_u->logname) )
                return False;
-       if(!prs_uint32("sourcename_ptr", ps, depth, &q_u->sourcename_ptr))
+       if ( !prs_align(ps) )
                return False;
-       if(!smb_io_unistr2("", &q_u->sourcename, q_u->sourcename_ptr, ps, depth))
+
+       if ( !prs_unistr4("servername", ps, depth, &q_u->servername) )
                return False;
-       if(!prs_align(ps))
+       if ( !prs_align(ps) )
                return False;
 
-       /* Get server name */
-
-       if(!prs_uint32("servername_ptr", ps, depth, &q_u->servername_ptr))
+       if ( !prs_uint32("unknown1", ps, depth, &q_u->unknown1) )
                return False;
-       if(!smb_io_unistr2("", &q_u->servername, q_u->servername_ptr, ps, depth))
+       if ( !prs_uint32("unknown2", ps, depth, &q_u->unknown2) )
                return False;
 
        return True;
@@ -424,17 +405,8 @@ BOOL eventlog_io_q_clear_eventlog(const char *desc, EVENTLOG_Q_CLEAR_EVENTLOG *q
                return False;
        if(!(smb_io_pol_hnd("log handle", &(q_u->handle), ps, depth)))
                return False;
-       if(!prs_align(ps))
-               return False;
-       if(!(prs_uint32("unknown1", ps, depth, &q_u->unknown1)))
-               return False;
-       if(!(prs_uint16("backup_file_length", ps, depth, &q_u->backup_file_length)))
-               return False;
-       if(!(prs_uint16("backup_file_size", ps, depth, &q_u->backup_file_size)))
-               return False;
-       if(!prs_uint32("backup_file_ptr", ps, depth, &q_u->backup_file_ptr))
-               return False;
-       if(!smb_io_unistr2("backup file", &q_u->backup_file, q_u->backup_file_ptr, ps, depth))
+
+       if ( !prs_unistr4("backupfile", ps, depth, &q_u->backupfile) )
                return False;
 
        return True;
index 921e366f11a9dcf3f7bc8cc6bf8528a0ce8b2bd0..8bbb97f226db7119a1c0bcf81f2b3c3d40127a32 100644 (file)
@@ -296,7 +296,7 @@ BOOL smb_io_dom_sid2_p(const char *desc, prs_struct *ps, int depth, DOM_SID2 **s
 
        /* caputure the pointer value to stream */
 
-       data_p = (uint32) *sid2;
+       data_p = *sid2 ? 0xf000baaa : 0;
 
        if ( !prs_uint32("dom_sid2_p", ps, depth, &data_p ))
                return False;
@@ -1003,7 +1003,7 @@ BOOL prs_io_unistr2_p(const char *desc, prs_struct *ps, int depth, UNISTR2 **uni
 
        /* caputure the pointer value to stream */
 
-       data_p = (uint32) *uni2;
+       data_p = *uni2 ? 0xf000baaa : 0;
 
        if ( !prs_uint32("ptr", ps, depth, &data_p ))
                return False;
@@ -1038,7 +1038,7 @@ BOOL prs_io_unistr2(const char *desc, prs_struct *ps, int depth, UNISTR2 *uni2 )
        /* just pass off to smb_io_unstr2() passing the uni2 address as 
           the pointer (like you would expect) */
 
-       return smb_io_unistr2( desc, uni2, (uint32)uni2, ps, depth );
+       return smb_io_unistr2( desc, uni2, uni2 ? 1 : 0, ps, depth );
 }
 
 /*******************************************************************
@@ -1139,7 +1139,7 @@ BOOL prs_unistr4_str(const char *desc, prs_struct *ps, int depth, UNISTR4 *uni4)
 }
 
 /*******************************************************************
- Reads or writes a UNISTR2_ARRAY structure.
+ Reads or writes a UNISTR4_ARRAY structure.
 ********************************************************************/
 
 BOOL prs_unistr4_array(const char *desc, prs_struct *ps, int depth, UNISTR4_ARRAY *array )
index 3a050148c9f7ed2ad200ef67c5e19423e3d82542..35533e360a1ed5fe3defd36cec672b59f246a289 100644 (file)
@@ -671,7 +671,7 @@ BOOL net_io_q_trust_dom(const char *desc, NET_Q_TRUST_DOM_LIST *q_l, prs_struct
 
 void init_q_req_chal(NET_Q_REQ_CHAL *q_c,
                     const char *logon_srv, const char *logon_clnt,
-                    DOM_CHAL *clnt_chal)
+                    const DOM_CHAL *clnt_chal)
 {
        DEBUG(5,("init_q_req_chal: %d\n", __LINE__));
 
@@ -860,7 +860,7 @@ BOOL net_io_r_auth_2(const char *desc, NET_R_AUTH_2 *r_a, prs_struct *ps, int de
 
 void init_q_auth_3(NET_Q_AUTH_3 *q_a,
                const char *logon_srv, const char *acct_name, uint16 sec_chan, const char *comp_name,
-               DOM_CHAL *clnt_chal, uint32 clnt_flgs)
+               const DOM_CHAL *clnt_chal, uint32 clnt_flgs)
 {
        DEBUG(5,("init_q_auth_3: %d\n", __LINE__));
 
@@ -1496,7 +1496,7 @@ void init_net_user_info3(TALLOC_CTX *ctx, NET_USER_INFO_3 *usr,
 ********************************************************************/
 
 BOOL net_io_user_info3(const char *desc, NET_USER_INFO_3 *usr, prs_struct *ps, 
-                      int depth, uint16 validation_level)
+                      int depth, uint16 validation_level, BOOL kerb_validation_level)
 {
        unsigned int i;
 
@@ -1595,6 +1595,18 @@ BOOL net_io_user_info3(const char *desc, NET_USER_INFO_3 *usr, prs_struct *ps,
                }
        }
                
+       /* get kerb validation info (not really part of user_info_3) - Guenther */
+
+       if (kerb_validation_level) {
+
+               if(!prs_uint32("ptr_res_group_dom_sid", ps, depth, &usr->ptr_res_group_dom_sid))
+                       return False;
+               if(!prs_uint32("res_group_count", ps, depth, &usr->res_group_count))
+                       return False;
+               if(!prs_uint32("ptr_res_groups", ps, depth, &usr->ptr_res_groups))
+                       return False;
+       }
+
        if(!smb_io_unistr2("uni_user_name", &usr->uni_user_name, usr->hdr_user_name.buffer, ps, depth)) /* username unicode string */
                return False;
        if(!smb_io_unistr2("uni_full_name", &usr->uni_full_name, usr->hdr_full_name.buffer, ps, depth)) /* user's full name unicode string */
@@ -1636,6 +1648,11 @@ BOOL net_io_user_info3(const char *desc, NET_USER_INFO_3 *usr, prs_struct *ps,
 
                uint32 num_other_sids = usr->num_other_sids;
 
+               if (!(usr->user_flgs & LOGON_EXTRA_SIDS)) {
+                       DEBUG(10,("net_io_user_info3: user_flgs attribute does not have LOGON_EXTRA_SIDS\n"));
+                       /* return False; */
+               }
+
                if (!prs_uint32("num_other_sids", ps, depth,
                                &num_other_sids))
                        return False;
@@ -1724,8 +1741,10 @@ BOOL net_io_r_sam_logon(const char *desc, NET_R_SAM_LOGON *r_l, prs_struct *ps,
 
        if(!prs_uint32("buffer_creds", ps, depth, &r_l->buffer_creds)) /* undocumented buffer pointer */
                return False;
-       if(!smb_io_cred("", &r_l->srv_creds, ps, depth)) /* server credentials.  server time stamp appears to be ignored. */
-               return False;
+       if (&r_l->buffer_creds) {
+               if(!smb_io_cred("", &r_l->srv_creds, ps, depth)) /* server credentials.  server time stamp appears to be ignored. */
+                       return False;
+       }
 
        if(!prs_uint16("switch_value", ps, depth, &r_l->switch_value))
                return False;
@@ -1733,11 +1752,11 @@ BOOL net_io_r_sam_logon(const char *desc, NET_R_SAM_LOGON *r_l, prs_struct *ps,
                return False;
 
 #if 1 /* W2k always needs this - even for bad passwd. JRA */
-       if(!net_io_user_info3("", r_l->user, ps, depth, r_l->switch_value))
+       if(!net_io_user_info3("", r_l->user, ps, depth, r_l->switch_value, False))
                return False;
 #else
        if (r_l->switch_value != 0) {
-               if(!net_io_user_info3("", r_l->user, ps, depth, r_l->switch_value))
+               if(!net_io_user_info3("", r_l->user, ps, depth, r_l->switch_value, False))
                        return False;
        }
 #endif
@@ -2139,9 +2158,8 @@ BOOL make_sam_account_info(SAM_ACCOUNT_INFO * info,
 /*******************************************************************
 reads or writes a structure.
 ********************************************************************/
-static BOOL net_io_sam_account_info(const char *desc, uint8 sess_key[16],
-                                   SAM_ACCOUNT_INFO * info, prs_struct *ps,
-                                   int depth)
+static BOOL net_io_sam_account_info(const char *desc, SAM_ACCOUNT_INFO *info,
+                               prs_struct *ps, int depth)
 {
        BUFHDR2 hdr_priv_data;
        uint32 i;
@@ -2295,7 +2313,7 @@ static BOOL net_io_sam_account_info(const char *desc, uint8 sess_key[16],
                        if (ps->io)
                        {
                                /* reading */
-                                if (!prs_hash1(ps, ps->data_offset, sess_key, len))
+                                if (!prs_hash1(ps, ps->data_offset, len))
                                         return False;
                        }
                        if (!net_io_sam_passwd_info("pass", &info->pass, 
@@ -2305,7 +2323,7 @@ static BOOL net_io_sam_account_info(const char *desc, uint8 sess_key[16],
                        if (!ps->io)
                        {
                                /* writing */
-                                if (!prs_hash1(ps, old_offset, sess_key, len))
+                                if (!prs_hash1(ps, old_offset, len))
                                         return False;
                        }
                }
@@ -2834,7 +2852,7 @@ static BOOL net_io_sam_privs_info(const char *desc, SAM_DELTA_PRIVS *info,
 /*******************************************************************
 reads or writes a structure.
 ********************************************************************/
-static BOOL net_io_sam_delta_ctr(const char *desc, uint8 sess_key[16],
+static BOOL net_io_sam_delta_ctr(const char *desc,
                                 SAM_DELTA_CTR * delta, uint16 type,
                                 prs_struct *ps, int depth)
 {
@@ -2859,7 +2877,7 @@ static BOOL net_io_sam_delta_ctr(const char *desc, uint8 sess_key[16],
                        break;
 
                case SAM_DELTA_ACCOUNT_INFO:
-                       if (!net_io_sam_account_info("", sess_key, &delta->account_info, ps, depth))
+                       if (!net_io_sam_account_info("", &delta->account_info, ps, depth))
                                 return False;
                        break;
 
@@ -2912,7 +2930,7 @@ static BOOL net_io_sam_delta_ctr(const char *desc, uint8 sess_key[16],
 /*******************************************************************
 reads or writes a structure.
 ********************************************************************/
-BOOL net_io_r_sam_sync(const char *desc, uint8 sess_key[16],
+BOOL net_io_r_sam_sync(const char *desc,
                       NET_R_SAM_SYNC * r_s, prs_struct *ps, int depth)
 {
        uint32 i;
@@ -2976,7 +2994,7 @@ BOOL net_io_r_sam_sync(const char *desc, uint8 sess_key[16],
                        for (i = 0; i < r_s->num_deltas2; i++)
                        {
                                if (!net_io_sam_delta_ctr(
-                                        "", sess_key, &r_s->deltas[i],
+                                        "", &r_s->deltas[i],
                                         r_s->hdr_deltas[i].type3,
                                         ps, depth)) {
                                         DEBUG(0, ("hmm, failed on i=%d\n", i));
@@ -3048,7 +3066,7 @@ BOOL net_io_q_sam_deltas(const char *desc, NET_Q_SAM_DELTAS *q_s, prs_struct *ps
 /*******************************************************************
 reads or writes a structure.
 ********************************************************************/
-BOOL net_io_r_sam_deltas(const char *desc, uint8 sess_key[16],
+BOOL net_io_r_sam_deltas(const char *desc,
                          NET_R_SAM_DELTAS *r_s, prs_struct *ps, int depth)
 {
         unsigned int i;
@@ -3104,7 +3122,7 @@ BOOL net_io_r_sam_deltas(const char *desc, uint8 sess_key[16],
                        for (i = 0; i < r_s->num_deltas; i++)
                        {
                                if (!net_io_sam_delta_ctr(
-                                        "", sess_key,
+                                        "",
                                         &r_s->deltas[i],
                                         r_s->hdr_deltas[i].type2,
                                         ps, depth))
diff --git a/source3/rpc_parse/parse_ntsvcs.c b/source3/rpc_parse/parse_ntsvcs.c
new file mode 100644 (file)
index 0000000..f2e4456
--- /dev/null
@@ -0,0 +1,415 @@
+/* 
+ *  Unix SMB/CIFS implementation.
+ *  RPC Pipe client / server routines
+ *  Copyright (C) Gerald (Jerry) Carter             2005.
+ *  
+ *  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"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_RPC_PARSE
+
+/*******************************************************************
+********************************************************************/
+
+BOOL ntsvcs_io_q_get_version(const char *desc, NTSVCS_Q_GET_VERSION *q_u, prs_struct *ps, int depth)
+{
+       if (q_u == NULL)
+               return False;
+
+       prs_debug(ps, depth, desc, "ntsvcs_io_q_get_version");
+       depth++;
+
+       /* there is nothing to parse in this PDU */
+
+       return True;
+
+}
+
+/*******************************************************************
+********************************************************************/
+
+BOOL ntsvcs_io_r_get_version(const char *desc, NTSVCS_R_GET_VERSION *r_u, prs_struct *ps, int depth)
+{
+       if ( !r_u )
+               return False;
+
+       prs_debug(ps, depth, desc, "ntsvcs_io_r_get_version");
+       depth++;
+
+       if(!prs_align(ps))
+               return False;
+               
+       if(!prs_uint32("version", ps, depth, &r_u->version))
+               return False;
+               
+       if(!prs_werror("status", ps, depth, &r_u->status))
+               return False;
+
+       return True;
+}
+
+/*******************************************************************
+********************************************************************/
+
+BOOL ntsvcs_io_q_get_device_list_size(const char *desc, NTSVCS_Q_GET_DEVICE_LIST_SIZE *q_u, prs_struct *ps, int depth)
+{
+       if (q_u == NULL)
+               return False;
+
+       prs_debug(ps, depth, desc, "ntsvcs_io_q_get_device_list_size");
+       depth++;
+       
+       if(!prs_align(ps))
+               return False;
+
+       if ( !prs_pointer("devicename", ps, depth, (void**)&q_u->devicename, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2) )
+               return False;
+       if( !prs_align(ps) )
+               return False;
+               
+       if ( !prs_uint32("flags", ps, depth, &q_u->flags) )
+               return False;
+       
+       return True;
+
+}
+
+/*******************************************************************
+********************************************************************/
+
+BOOL ntsvcs_io_r_get_device_list_size(const char *desc, NTSVCS_R_GET_DEVICE_LIST_SIZE *r_u, prs_struct *ps, int depth)
+{
+       if ( !r_u )
+               return False;
+
+       prs_debug(ps, depth, desc, "ntsvcs_io_r_get_device_list_size");
+       depth++;
+
+       if(!prs_align(ps))
+               return False;
+               
+       if(!prs_uint32("size", ps, depth, &r_u->size))
+               return False;
+               
+       if(!prs_werror("status", ps, depth, &r_u->status))
+               return False;
+
+       return True;
+}
+
+
+/*******************************************************************
+********************************************************************/
+
+BOOL ntsvcs_io_q_get_device_list(const char *desc, NTSVCS_Q_GET_DEVICE_LIST *q_u, prs_struct *ps, int depth)
+{
+       if (q_u == NULL)
+               return False;
+
+       prs_debug(ps, depth, desc, "ntsvcs_io_q_get_device_list");
+       depth++;
+       
+       if(!prs_align(ps))
+               return False;
+
+       if ( !prs_pointer("devicename", ps, depth, (void**)&q_u->devicename, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2) )
+               return False;
+       if( !prs_align(ps) )
+               return False;
+               
+       if ( !prs_uint32("buffer_size", ps, depth, &q_u->buffer_size) )
+               return False;
+       if ( !prs_uint32("flags", ps, depth, &q_u->flags) )
+               return False;
+       
+       return True;
+
+}
+
+/*******************************************************************
+********************************************************************/
+
+BOOL ntsvcs_io_r_get_device_list(const char *desc, NTSVCS_R_GET_DEVICE_LIST *r_u, prs_struct *ps, int depth)
+{
+       if ( !r_u )
+               return False;
+
+       prs_debug(ps, depth, desc, "ntsvcs_io_r_get_device_list_size");
+       depth++;
+
+       if(!prs_align(ps))
+               return False;
+               
+       if ( !prs_io_unistr2("devicepath", ps, depth, &r_u->devicepath) )
+               return False;
+       if(!prs_align(ps))
+               return False;
+               
+       if(!prs_uint32("needed", ps, depth, &r_u->needed))
+               return False;
+               
+       if(!prs_werror("status", ps, depth, &r_u->status))
+               return False;
+
+       return True;
+}
+
+/*******************************************************************
+********************************************************************/
+
+BOOL ntsvcs_io_q_validate_device_instance(const char *desc, NTSVCS_Q_VALIDATE_DEVICE_INSTANCE *q_u, prs_struct *ps, int depth)
+{
+       if (q_u == NULL)
+               return False;
+
+       prs_debug(ps, depth, desc, "ntsvcs_io_q_validate_device_instance");
+       depth++;
+       
+       if(!prs_align(ps))
+               return False;
+
+       if ( !prs_io_unistr2("devicepath", ps, depth, &q_u->devicepath) )
+               return False;
+       if( !prs_align(ps) )
+               return False;
+               
+       if ( !prs_uint32("flags", ps, depth, &q_u->flags) )
+               return False;
+       
+       return True;
+
+}
+
+/*******************************************************************
+********************************************************************/
+
+BOOL ntsvcs_io_r_validate_device_instance(const char *desc, NTSVCS_R_VALIDATE_DEVICE_INSTANCE *r_u, prs_struct *ps, int depth)
+{
+       if ( !r_u )
+               return False;
+
+       prs_debug(ps, depth, desc, "ntsvcs_io_r_validate_device_instance");
+       depth++;
+
+       if(!prs_werror("status", ps, depth, &r_u->status))
+               return False;
+
+       return True;
+}
+
+/*******************************************************************
+********************************************************************/
+
+BOOL ntsvcs_io_q_get_device_reg_property(const char *desc, NTSVCS_Q_GET_DEVICE_REG_PROPERTY *q_u, prs_struct *ps, int depth)
+{
+       if (q_u == NULL)
+               return False;
+
+       prs_debug(ps, depth, desc, "ntsvcs_io_q_get_device_reg_property");
+       depth++;
+       
+       if(!prs_align(ps))
+               return False;
+
+       if ( !prs_io_unistr2("devicepath", ps, depth, &q_u->devicepath) )
+               return False;
+       if( !prs_align(ps) )
+               return False;
+
+       if ( !prs_uint32("property", ps, depth, &q_u->property) )
+               return False;
+       if ( !prs_uint32("unknown2", ps, depth, &q_u->unknown2) )
+               return False;
+       if ( !prs_uint32("buffer_size1", ps, depth, &q_u->buffer_size1) )
+               return False;
+       if ( !prs_uint32("buffer_size2", ps, depth, &q_u->buffer_size2) )
+               return False;
+       if ( !prs_uint32("unknown5", ps, depth, &q_u->unknown5) )
+               return False;
+       
+       return True;
+
+}
+
+/*******************************************************************
+********************************************************************/
+
+BOOL ntsvcs_io_r_get_device_reg_property(const char *desc, NTSVCS_R_GET_DEVICE_REG_PROPERTY *r_u, prs_struct *ps, int depth)
+{
+       if ( !r_u )
+               return False;
+
+       prs_debug(ps, depth, desc, "ntsvcs_io_r_get_device_reg_property");
+       depth++;
+
+       if ( !prs_align(ps) )
+               return False;
+
+       if ( !prs_uint32("unknown1", ps, depth, &r_u->unknown1) )
+               return False;
+
+       if ( !smb_io_regval_buffer("value", ps, depth, &r_u->value) )
+               return False;
+       if ( !prs_align(ps) )
+               return False;
+
+       if ( !prs_uint32("size", ps, depth, &r_u->size) )
+               return False;
+
+       if ( !prs_uint32("needed", ps, depth, &r_u->needed) )
+               return False;
+
+       if(!prs_werror("status", ps, depth, &r_u->status))
+               return False;
+
+       return True;
+}
+
+/*******************************************************************
+********************************************************************/
+
+BOOL ntsvcs_io_q_get_hw_profile_info(const char *desc, NTSVCS_Q_GET_HW_PROFILE_INFO *q_u, prs_struct *ps, int depth)
+{
+       if (q_u == NULL)
+               return False;
+
+       prs_debug(ps, depth, desc, "ntsvcs_io_q_get_hw_profile_info");
+       depth++;
+       
+       if(!prs_align(ps))
+               return False;
+
+       if ( !prs_uint32("index", ps, depth, &q_u->index) )
+               return False;
+
+       q_u->buffer_size = 0x000000a8;
+
+       if ( UNMARSHALLING(ps) )
+               q_u->buffer = TALLOC_ARRAY(get_talloc_ctx(), uint8, q_u->buffer_size );
+
+       if ( !prs_uint8s(True, "buffer", ps, depth, q_u->buffer, q_u->buffer_size) )
+               return False;
+
+       if ( !prs_uint32("buffer_size", ps, depth, &q_u->buffer_size) )
+               return False;
+
+       if ( !prs_uint32("unknown1", ps, depth, &q_u->unknown1) )
+               return False;
+       
+       return True;
+
+}
+
+/*******************************************************************
+********************************************************************/
+
+BOOL ntsvcs_io_r_get_hw_profile_info(const char *desc, NTSVCS_R_GET_HW_PROFILE_INFO *r_u, prs_struct *ps, int depth)
+{
+       if ( !r_u )
+               return False;
+
+       prs_debug(ps, depth, desc, "ntsvcs_io_r_get_device_reg_property");
+       depth++;
+
+       if ( !prs_align(ps) )
+               return False;
+
+       if ( UNMARSHALLING(ps) )
+               r_u->buffer = TALLOC_ARRAY(get_talloc_ctx(), uint8, r_u->buffer_size );
+
+       if ( !prs_uint8s(True, "buffer", ps, depth, r_u->buffer, r_u->buffer_size) )
+               return False;
+
+       if(!prs_werror("status", ps, depth, &r_u->status))
+               return False;
+
+       return True;
+}
+
+/*******************************************************************
+********************************************************************/
+
+BOOL ntsvcs_io_q_hw_profile_flags(const char *desc, NTSVCS_Q_HW_PROFILE_FLAGS *q_u, prs_struct *ps, int depth)
+{
+       if (q_u == NULL)
+               return False;
+
+       prs_debug(ps, depth, desc, "ntsvcs_io_q_hw_profile_flags");
+       depth++;
+       
+       if(!prs_align(ps))
+               return False;
+
+       if ( !prs_uint32("unknown1", ps, depth, &q_u->unknown1) )
+               return False;
+               
+
+       if ( !prs_io_unistr2("devicepath", ps, depth, &q_u->devicepath) )
+               return False;
+       if( !prs_align(ps) )
+               return False;
+
+       if ( !prs_uint32("unknown2", ps, depth, &q_u->unknown2) )
+               return False;
+       if ( !prs_uint32("unknown3", ps, depth, &q_u->unknown3) )
+               return False;
+       if ( !prs_uint32("unknown4", ps, depth, &q_u->unknown4) )
+               return False;
+       if ( !prs_uint32("unknown5", ps, depth, &q_u->unknown5) )
+               return False;
+       if ( !prs_uint32("unknown6", ps, depth, &q_u->unknown6) )
+               return False;
+       if ( !prs_uint32("unknown7", ps, depth, &q_u->unknown7) )
+               return False;
+
+       if ( !prs_uint32("unknown1", ps, depth, &q_u->unknown1) )
+               return False;
+       
+       return True;
+
+}
+
+/*******************************************************************
+********************************************************************/
+
+BOOL ntsvcs_io_r_hw_profile_flags(const char *desc, NTSVCS_R_HW_PROFILE_FLAGS *r_u, prs_struct *ps, int depth)
+{
+       if ( !r_u )
+               return False;
+
+       prs_debug(ps, depth, desc, "ntsvcs_io_r_hw_profile_flags");
+       depth++;
+
+       if ( !prs_align(ps) )
+               return False;
+
+       if ( !prs_uint32("unknown1", ps, depth, &r_u->unknown1) )
+               return False;
+       if ( !prs_uint32("unknown2", ps, depth, &r_u->unknown2) )
+               return False;
+       if ( !prs_uint32("unknown3", ps, depth, &r_u->unknown3) )
+               return False;
+       if(!prs_werror("status", ps, depth, &r_u->status))
+               return False;
+
+       return True;
+}
+
+
+
+
index 709a5d39af6c3f78178c45baebd0a5727adfe662..d174bad444d7714e181088ecd3e29aae812880bf 100644 (file)
@@ -34,7 +34,6 @@ void prs_dump(char *name, int v, prs_struct *ps)
        prs_dump_region(name, v, ps, ps->data_offset, ps->buffer_size);
 }
 
-
 /**
  * Dump from the start of the prs to the current location.
  **/
@@ -43,7 +42,6 @@ void prs_dump_before(char *name, int v, prs_struct *ps)
        prs_dump_region(name, v, ps, 0, ps->data_offset);
 }
 
-
 /**
  * Dump everything from the start of the prs up to the current location.
  **/
@@ -52,6 +50,7 @@ void prs_dump_region(char *name, int v, prs_struct *ps,
 {
        int fd, i;
        pstring fname;
+       ssize_t sz;
        if (DEBUGLEVEL < 50) return;
        for (i=1;i<100;i++) {
                if (v != -1) {
@@ -63,26 +62,28 @@ void prs_dump_region(char *name, int v, prs_struct *ps,
                if (fd != -1 || errno != EEXIST) break;
        }
        if (fd != -1) {
-               write(fd, ps->data_p + from_off, to_off - from_off);
-               close(fd);
-               DEBUG(0,("created %s\n", fname));
+               sz = write(fd, ps->data_p + from_off, to_off - from_off);
+               i = close(fd);
+               if ( (sz != to_off-from_off) || (i != 0) ) {
+                       DEBUG(0,("Error writing/closing %s: %ld!=%ld %d\n", fname, (unsigned long)sz, (unsigned long)to_off-from_off, i ));
+               } else {
+                       DEBUG(0,("created %s\n", fname));
+               }
        }
 }
 
-
-
 /*******************************************************************
- debug output for parsing info.
+ Debug output for parsing info
 
- XXXX side-effect of this function is to increase the debug depth XXXX
+ XXXX side-effect of this function is to increase the debug depth XXXX.
+
+********************************************************************/
 
- ********************************************************************/
 void prs_debug(prs_struct *ps, int depth, const char *desc, const char *fn_name)
 {
        DEBUG(5+depth, ("%s%06x %s %s\n", tab_depth(depth), ps->data_offset, fn_name, desc));
 }
 
-
 /**
  * Initialise an expandable parse structure.
  *
@@ -91,6 +92,7 @@ void prs_debug(prs_struct *ps, int depth, const char *desc, const char *fn_name)
  *
  * @return False if allocation fails, otherwise True.
  **/
+
 BOOL prs_init(prs_struct *ps, uint32 size, TALLOC_CTX *ctx, BOOL io)
 {
        ZERO_STRUCTP(ps);
@@ -111,6 +113,9 @@ BOOL prs_init(prs_struct *ps, uint32 size, TALLOC_CTX *ctx, BOOL io)
                }
                memset(ps->data_p, '\0', (size_t)size);
                ps->is_dynamic = True; /* We own this memory. */
+       } else if (MARSHALLING(ps)) {
+               /* If size is zero and we're marshalling we should allocate memory on demand. */
+               ps->is_dynamic = True;
        }
 
        return True;
@@ -254,7 +259,7 @@ BOOL prs_grow(prs_struct *ps, uint32 extra_space)
                 * is greater.
                 */
 
-               new_size = MAX(MAX_PDU_FRAG_LEN,extra_space);
+               new_size = MAX(RPC_MAX_PDU_FRAG_LEN,extra_space);
 
                if((new_data = SMB_MALLOC(new_size)) == NULL) {
                        DEBUG(0,("prs_grow: Malloc failure for size %u.\n", (unsigned int)new_size));
@@ -398,7 +403,7 @@ BOOL prs_append_some_prs_data(prs_struct *dst, prs_struct *src, int32 start, uin
  Append the data from a buffer into a parse_struct.
  ********************************************************************/
 
-BOOL prs_copy_data_in(prs_struct *dst, char *src, uint32 len)
+BOOL prs_copy_data_in(prs_struct *dst, const char *src, uint32 len)
 {
        if (len == 0)
                return True;
@@ -564,6 +569,15 @@ void prs_force_dynamic(prs_struct *ps)
        ps->is_dynamic=True;
 }
 
+/*******************************************************************
+ Associate a session key with a parse struct.
+ ********************************************************************/
+
+void prs_set_session_key(prs_struct *ps, const char sess_key[16])
+{
+       ps->sess_key = sess_key;
+}
+
 /*******************************************************************
  Stream a uint8.
  ********************************************************************/
@@ -596,9 +610,9 @@ BOOL prs_pointer( const char *name, prs_struct *ps, int depth,
 {
        uint32 data_p;
 
-       /* caputure the pointer value to stream */
+       /* output f000baaa to stream if the pointer is non-zero. */
 
-       data_p = (uint32) *data;
+       data_p = *data ? 0xf000baaa : 0;
 
        if ( !prs_uint32("ptr", ps, depth, &data_p ))
                return False;
@@ -1387,7 +1401,7 @@ int tdb_prs_fetch(TDB_CONTEXT *tdb, char *keystr, prs_struct *ps, TALLOC_CTX *me
  hash a stream.
  ********************************************************************/
 
-BOOL prs_hash1(prs_struct *ps, uint32 offset, uint8 sess_key[16], int len)
+BOOL prs_hash1(prs_struct *ps, uint32 offset, int len)
 {
        char *q;
 
@@ -1396,10 +1410,10 @@ BOOL prs_hash1(prs_struct *ps, uint32 offset, uint8 sess_key[16], int len)
 
 #ifdef DEBUG_PASSWORD
        DEBUG(100, ("prs_hash1\n"));
-       dump_data(100, sess_key, 16);
+       dump_data(100, ps->sess_key, 16);
        dump_data(100, q, len);
 #endif
-       SamOEMhash((uchar *) q, sess_key, len);
+       SamOEMhash((uchar *) q, ps->sess_key, len);
 
 #ifdef DEBUG_PASSWORD
        dump_data(100, q, len);
@@ -1413,9 +1427,9 @@ BOOL prs_hash1(prs_struct *ps, uint32 offset, uint8 sess_key[16], int len)
  MD5 it with the session key.
  ********************************************************************/
 
-static void netsec_digest(struct netsec_auth_struct *a,
-                         int auth_flags,
-                         RPC_AUTH_NETSEC_CHK * verf,
+static void schannel_digest(struct schannel_auth_struct *a,
+                         enum pipe_auth_level auth_level,
+                         RPC_AUTH_SCHANNEL_CHK * verf,
                          char *data, size_t data_len,
                          uchar digest_final[16]) 
 {
@@ -1429,7 +1443,7 @@ static void netsec_digest(struct netsec_auth_struct *a,
           out of order */
        MD5Update(&ctx3, zeros, sizeof(zeros));
        MD5Update(&ctx3, verf->sig, sizeof(verf->sig));
-       if (auth_flags & AUTH_PIPE_SEAL) {
+       if (auth_level == PIPE_AUTH_LEVEL_PRIVACY) {
                MD5Update(&ctx3, verf->confounder, sizeof(verf->confounder));
        }
        MD5Update(&ctx3, (const unsigned char *)data, data_len);
@@ -1445,8 +1459,8 @@ static void netsec_digest(struct netsec_auth_struct *a,
  Calculate the key with which to encode the data payload 
  ********************************************************************/
 
-static void netsec_get_sealing_key(struct netsec_auth_struct *a,
-                                  RPC_AUTH_NETSEC_CHK *verf,
+static void schannel_get_sealing_key(struct schannel_auth_struct *a,
+                                  RPC_AUTH_SCHANNEL_CHK *verf,
                                   uchar sealing_key[16]) 
 {
        static uchar zeros[4];
@@ -1473,8 +1487,8 @@ static void netsec_get_sealing_key(struct netsec_auth_struct *a,
  Encode or Decode the sequence number (which is symmetric)
  ********************************************************************/
 
-static void netsec_deal_with_seq_num(struct netsec_auth_struct *a,
-                                    RPC_AUTH_NETSEC_CHK *verf)
+static void schannel_deal_with_seq_num(struct schannel_auth_struct *a,
+                                    RPC_AUTH_SCHANNEL_CHK *verf)
 {
        static uchar zeros[4];
        uchar sequence_key[16];
@@ -1493,10 +1507,10 @@ static void netsec_deal_with_seq_num(struct netsec_auth_struct *a,
 }
 
 /*******************************************************************
-creates an RPC_AUTH_NETSEC_CHK structure.
+creates an RPC_AUTH_SCHANNEL_CHK structure.
 ********************************************************************/
 
-static BOOL init_rpc_auth_netsec_chk(RPC_AUTH_NETSEC_CHK * chk,
+static BOOL init_rpc_auth_schannel_chk(RPC_AUTH_SCHANNEL_CHK * chk,
                              const uchar sig[8],
                              const uchar packet_digest[8],
                              const uchar seq_num[8], const uchar confounder[8])
@@ -1513,15 +1527,15 @@ static BOOL init_rpc_auth_netsec_chk(RPC_AUTH_NETSEC_CHK * chk,
 }
 
 /*******************************************************************
- Encode a blob of data using the netsec (schannel) alogrithm, also produceing
+ Encode a blob of data using the schannel alogrithm, also produceing
  a checksum over the original data.  We currently only support
  signing and sealing togeather - the signing-only code is close, but not
  quite compatible with what MS does.
  ********************************************************************/
 
-void netsec_encode(struct netsec_auth_struct *a, int auth_flags, 
-                  enum netsec_direction direction,
-                  RPC_AUTH_NETSEC_CHK * verf,
+void schannel_encode(struct schannel_auth_struct *a, enum pipe_auth_level auth_level,
+                  enum schannel_direction direction,
+                  RPC_AUTH_SCHANNEL_CHK * verf,
                   char *data, size_t data_len)
 {
        uchar digest_final[16];
@@ -1529,16 +1543,16 @@ void netsec_encode(struct netsec_auth_struct *a, int auth_flags,
        uchar seq_num[8];
        static const uchar nullbytes[8];
 
-       static const uchar netsec_seal_sig[8] = NETSEC_SEAL_SIGNATURE;
-       static const uchar netsec_sign_sig[8] = NETSEC_SIGN_SIGNATURE;
-       const uchar *netsec_sig = NULL;
+       static const uchar schannel_seal_sig[8] = SCHANNEL_SEAL_SIGNATURE;
+       static const uchar schannel_sign_sig[8] = SCHANNEL_SIGN_SIGNATURE;
+       const uchar *schannel_sig = NULL;
 
-       DEBUG(10,("SCHANNEL: netsec_encode seq_num=%d data_len=%lu\n", a->seq_num, (unsigned long)data_len));
+       DEBUG(10,("SCHANNEL: schannel_encode seq_num=%d data_len=%lu\n", a->seq_num, (unsigned long)data_len));
        
-       if (auth_flags & AUTH_PIPE_SEAL) {
-               netsec_sig = netsec_seal_sig;
-       } else if (auth_flags & AUTH_PIPE_SIGN) {
-               netsec_sig = netsec_sign_sig;
+       if (auth_level == PIPE_AUTH_LEVEL_PRIVACY) {
+               schannel_sig = schannel_seal_sig;
+       } else {
+               schannel_sig = schannel_sign_sig;
        }
 
        /* fill the 'confounder' with random data */
@@ -1559,18 +1573,18 @@ void netsec_encode(struct netsec_auth_struct *a, int auth_flags,
 
        dump_data_pw("verf->seq_num:\n", seq_num, sizeof(verf->seq_num));
 
-       init_rpc_auth_netsec_chk(verf, netsec_sig, nullbytes,
+       init_rpc_auth_schannel_chk(verf, schannel_sig, nullbytes,
                                 seq_num, confounder);
                                
        /* produce a digest of the packet to prove it's legit (before we seal it) */
-       netsec_digest(a, auth_flags, verf, data, data_len, digest_final);
+       schannel_digest(a, auth_level, verf, data, data_len, digest_final);
        memcpy(verf->packet_digest, digest_final, sizeof(verf->packet_digest));
 
-       if (auth_flags & AUTH_PIPE_SEAL) {
+       if (auth_level == PIPE_AUTH_LEVEL_PRIVACY) {
                uchar sealing_key[16];
 
                /* get the key to encode the data with */
-               netsec_get_sealing_key(a, verf, sealing_key);
+               schannel_get_sealing_key(a, verf, sealing_key);
 
                /* encode the verification data */
                dump_data_pw("verf->confounder:\n", verf->confounder, sizeof(verf->confounder));
@@ -1587,35 +1601,35 @@ void netsec_encode(struct netsec_auth_struct *a, int auth_flags,
        /* encode the sequence number (key based on packet digest) */
        /* needs to be done after the sealing, as the original version 
           is used in the sealing stuff... */
-       netsec_deal_with_seq_num(a, verf);
+       schannel_deal_with_seq_num(a, verf);
 
        return;
 }
 
 /*******************************************************************
- Decode a blob of data using the netsec (schannel) alogrithm, also verifiying
+ Decode a blob of data using the schannel alogrithm, also verifiying
  a checksum over the original data.  We currently can verify signed messages,
  as well as decode sealed messages
  ********************************************************************/
 
-BOOL netsec_decode(struct netsec_auth_struct *a, int auth_flags,
-                  enum netsec_direction direction, 
-                  RPC_AUTH_NETSEC_CHK * verf, char *data, size_t data_len)
+BOOL schannel_decode(struct schannel_auth_struct *a, enum pipe_auth_level auth_level,
+                  enum schannel_direction direction, 
+                  RPC_AUTH_SCHANNEL_CHK * verf, char *data, size_t data_len)
 {
        uchar digest_final[16];
 
-       static const uchar netsec_seal_sig[8] = NETSEC_SEAL_SIGNATURE;
-       static const uchar netsec_sign_sig[8] = NETSEC_SIGN_SIGNATURE;
-       const uchar *netsec_sig = NULL;
+       static const uchar schannel_seal_sig[8] = SCHANNEL_SEAL_SIGNATURE;
+       static const uchar schannel_sign_sig[8] = SCHANNEL_SIGN_SIGNATURE;
+       const uchar *schannel_sig = NULL;
 
        uchar seq_num[8];
 
-       DEBUG(10,("SCHANNEL: netsec_encode seq_num=%d data_len=%lu\n", a->seq_num, (unsigned long)data_len));
+       DEBUG(10,("SCHANNEL: schannel_decode seq_num=%d data_len=%lu\n", a->seq_num, (unsigned long)data_len));
        
-       if (auth_flags & AUTH_PIPE_SEAL) {
-               netsec_sig = netsec_seal_sig;
-       } else if (auth_flags & AUTH_PIPE_SIGN) {
-               netsec_sig = netsec_sign_sig;
+       if (auth_level == PIPE_AUTH_LEVEL_PRIVACY) {
+               schannel_sig = schannel_seal_sig;
+       } else {
+               schannel_sig = schannel_sign_sig;
        }
 
        /* Create the expected sequence number for comparison */
@@ -1630,7 +1644,7 @@ BOOL netsec_decode(struct netsec_auth_struct *a, int auth_flags,
                break;
        }
 
-       DEBUG(10,("SCHANNEL: netsec_decode seq_num=%d data_len=%lu\n", a->seq_num, (unsigned long)data_len));
+       DEBUG(10,("SCHANNEL: schannel_decode seq_num=%d data_len=%lu\n", a->seq_num, (unsigned long)data_len));
        dump_data_pw("a->sess_key:\n", a->sess_key, sizeof(a->sess_key));
 
        dump_data_pw("seq_num:\n", seq_num, sizeof(seq_num));
@@ -1638,7 +1652,7 @@ BOOL netsec_decode(struct netsec_auth_struct *a, int auth_flags,
        /* extract the sequence number (key based on supplied packet digest) */
        /* needs to be done before the sealing, as the original version 
           is used in the sealing stuff... */
-       netsec_deal_with_seq_num(a, verf);
+       schannel_deal_with_seq_num(a, verf);
 
        if (memcmp(verf->seq_num, seq_num, sizeof(seq_num))) {
                /* don't even bother with the below if the sequence number is out */
@@ -1646,7 +1660,7 @@ BOOL netsec_decode(struct netsec_auth_struct *a, int auth_flags,
                   digest, as supplied by the client.  We check that it's a valid 
                   checksum after the decode, below
                */
-               DEBUG(2, ("netsec_decode: FAILED: packet sequence number:\n"));
+               DEBUG(2, ("schannel_decode: FAILED: packet sequence number:\n"));
                dump_data(2, (const char*)verf->seq_num, sizeof(verf->seq_num));
                DEBUG(2, ("should be:\n"));
                dump_data(2, (const char*)seq_num, sizeof(seq_num));
@@ -1654,20 +1668,20 @@ BOOL netsec_decode(struct netsec_auth_struct *a, int auth_flags,
                return False;
        }
 
-       if (memcmp(verf->sig, netsec_sig, sizeof(verf->sig))) {
+       if (memcmp(verf->sig, schannel_sig, sizeof(verf->sig))) {
                /* Validate that the other end sent the expected header */
-               DEBUG(2, ("netsec_decode: FAILED: packet header:\n"));
+               DEBUG(2, ("schannel_decode: FAILED: packet header:\n"));
                dump_data(2, (const char*)verf->sig, sizeof(verf->sig));
                DEBUG(2, ("should be:\n"));
-               dump_data(2, (const char*)netsec_sig, sizeof(netsec_sig));
+               dump_data(2, (const char*)schannel_sig, sizeof(schannel_sig));
                return False;
        }
 
-       if (auth_flags & AUTH_PIPE_SEAL) {
+       if (auth_level == PIPE_AUTH_LEVEL_PRIVACY) {
                uchar sealing_key[16];
                
                /* get the key to extract the data with */
-               netsec_get_sealing_key(a, verf, sealing_key);
+               schannel_get_sealing_key(a, verf, sealing_key);
 
                /* extract the verification data */
                dump_data_pw("verf->confounder:\n", verf->confounder, 
@@ -1684,7 +1698,7 @@ BOOL netsec_decode(struct netsec_auth_struct *a, int auth_flags,
        }
 
        /* digest includes 'data' after unsealing */
-       netsec_digest(a, auth_flags, verf, data, data_len, digest_final);
+       schannel_digest(a, auth_level, verf, data, data_len, digest_final);
 
        dump_data_pw("Calculated digest:\n", digest_final, 
                     sizeof(digest_final));
index be452033fe2c3a8792bc9982024477e6c1c41e8c..295fead103566195d23948c4c840c97d6b3bf191 100644 (file)
@@ -33,7 +33,7 @@
  Fill in a REGVAL_BUFFER for the data given a REGISTRY_VALUE
  *******************************************************************/
 
-static uint32 reg_init_regval_buffer( REGVAL_BUFFER *buf2, REGISTRY_VALUE *val )
+uint32 reg_init_regval_buffer( REGVAL_BUFFER *buf2, REGISTRY_VALUE *val )
 {
        uint32          real_size = 0;
        
index ce081b92e834464c2261d96eef1bdc1b2afc6b17..ea4ec2c8639d33526a67cfa83e0ef0cdbae89343 100644 (file)
@@ -191,6 +191,26 @@ interface/version dce/rpc pipe identification
        }, 0x00                             \
 }
 
+#define SYNT_UNIXINFO_V0                    \
+{                                           \
+       {                                   \
+               0x9c54e310, 0xa955, 0x4885, \
+               { 0xbd, 0x31 },             \
+                { 0x78, 0x78,               \
+                  0x71, 0x47, 0xdf, 0xa6 }  \
+       }, 0x00                             \
+}
+
+#define SYNT_NTSVCS_V1                      \
+{                                           \
+       {                                   \
+               0x8d9f4e40, 0xa03d, 0x11ce, \
+               { 0x8f, 0x69},              \
+                { 0x08, 0x00,               \
+                  0x3e, 0x30, 0x05, 0x1b }  \
+       }, 0x01                             \
+}
+
 /*
  * IMPORTANT!!  If you update this structure, make sure to
  * update the index #defines in smb.h.
@@ -212,9 +232,19 @@ const struct pipe_id_info pipe_names [] =
        { PIPE_SHUTDOWN, SYNT_SHUTDOWN_V1      , PIPE_SHUTDOWN , TRANS_SYNT_V2 },
        { PIPE_SVCCTL  , SYNT_SVCCTL_V2        , PIPE_NTSVCS   , TRANS_SYNT_V2 },
        { PIPE_EVENTLOG, SYNT_EVENTLOG_V0      , PIPE_EVENTLOG , TRANS_SYNT_V2 },
+       { PIPE_NTSVCS  , SYNT_NTSVCS_V1        , PIPE_NTSVCS   , TRANS_SYNT_V2 },
        { NULL         , SYNT_NONE_V0          , NULL          , SYNT_NONE_V0  }
 };
 
+/****************************************************************************
+ Return the pipe name from the index.
+ ****************************************************************************/
+
+const char *cli_get_pipe_name(int pipe_idx)
+{
+       return &pipe_names[pipe_idx].client_pipe[5];
+}
+
 /*******************************************************************
  Inits an RPC_HDR structure.
 ********************************************************************/
@@ -658,8 +688,8 @@ void init_rpc_hdr_auth(RPC_HDR_AUTH *rai,
                                uint8 auth_pad_len,
                                uint32 auth_context_id)
 {
-       rai->auth_type     = auth_type; /* nt lm ssp 0x0a */
-       rai->auth_level    = auth_level; /* 0x06 */
+       rai->auth_type     = auth_type;
+       rai->auth_level    = auth_level;
        rai->auth_pad_len  = auth_pad_len;
        rai->auth_reserved = 0;
        rai->auth_context_id = auth_context_id;
@@ -680,9 +710,9 @@ BOOL smb_io_rpc_hdr_auth(const char *desc, RPC_HDR_AUTH *rai, prs_struct *ps, in
        if(!prs_align(ps))
                return False;
 
-       if(!prs_uint8 ("auth_type    ", ps, depth, &rai->auth_type)) /* 0x0a nt lm ssp */
+       if(!prs_uint8 ("auth_type    ", ps, depth, &rai->auth_type))
                return False;
-       if(!prs_uint8 ("auth_level   ", ps, depth, &rai->auth_level)) /* 0x06 */
+       if(!prs_uint8 ("auth_level   ", ps, depth, &rai->auth_level))
                return False;
        if(!prs_uint8 ("auth_pad_len ", ps, depth, &rai->auth_pad_len))
                return False;
@@ -694,43 +724,6 @@ BOOL smb_io_rpc_hdr_auth(const char *desc, RPC_HDR_AUTH *rai, prs_struct *ps, in
        return True;
 }
 
-
-/*******************************************************************
- Init an RPC_HDR_AUTHA structure.
-********************************************************************/
-
-void init_rpc_hdr_autha(RPC_HDR_AUTHA *rai,
-                               uint16 max_tsize, uint16 max_rsize,
-                               RPC_HDR_AUTH *auth)
-{
-       rai->max_tsize = max_tsize; /* maximum transmission fragment size (0x1630) */
-       rai->max_rsize = max_rsize; /* max receive fragment size (0x1630) */   
-       rai->auth = *auth;
-}
-
-/*******************************************************************
- Reads or writes an RPC_HDR_AUTHA structure.
-********************************************************************/
-
-BOOL smb_io_rpc_hdr_autha(const char *desc, RPC_HDR_AUTHA *rai, prs_struct *ps, int depth)
-{
-       if (rai == NULL)
-               return False;
-
-       prs_debug(ps, depth, desc, "smb_io_rpc_hdr_autha");
-       depth++;
-
-       if(!prs_uint16("max_tsize    ", ps, depth, &rai->max_tsize))
-               return False;
-       if(!prs_uint16("max_rsize    ", ps, depth, &rai->max_rsize))
-               return False;
-
-       if(!smb_io_rpc_hdr_auth("auth", &rai->auth, ps, depth))
-               return False;
-
-       return True;
-}
-
 /*******************************************************************
  Checks an RPC_AUTH_VERIFIER structure.
 ********************************************************************/
@@ -775,17 +768,15 @@ BOOL smb_io_rpc_auth_verifier(const char *desc, RPC_AUTH_VERIFIER *rav, prs_stru
 }
 
 /*******************************************************************
- This parses an RPC_AUTH_VERIFIER for NETLOGON schannel. I think
- assuming "NTLMSSP" in sm_io_rpc_auth_verifier is somewhat wrong.
- I have to look at that later...
+ This parses an RPC_AUTH_VERIFIER for schannel. I think
 ********************************************************************/
 
-BOOL smb_io_rpc_netsec_verifier(const char *desc, RPC_AUTH_VERIFIER *rav, prs_struct *ps, int depth)
+BOOL smb_io_rpc_schannel_verifier(const char *desc, RPC_AUTH_VERIFIER *rav, prs_struct *ps, int depth)
 {
        if (rav == NULL)
                return False;
 
-       prs_debug(ps, depth, desc, "smb_io_rpc_auth_verifier");
+       prs_debug(ps, depth, desc, "smb_io_rpc_schannel_verifier");
        depth++;
 
        if(!prs_string("signature", ps, depth, rav->signature, sizeof(rav->signature)))
@@ -797,424 +788,10 @@ BOOL smb_io_rpc_netsec_verifier(const char *desc, RPC_AUTH_VERIFIER *rav, prs_st
 }
 
 /*******************************************************************
- Inits an RPC_AUTH_NTLMSSP_NEG structure.
-********************************************************************/
-
-void init_rpc_auth_ntlmssp_neg(RPC_AUTH_NTLMSSP_NEG *neg,
-                               uint32 neg_flgs,
-                               const char *myname, const char *domain)
-{
-       int len_myname = strlen(myname);
-       int len_domain = strlen(domain);
-
-       neg->neg_flgs = neg_flgs ; /* 0x00b2b3 */
-
-       init_str_hdr(&neg->hdr_domain, len_domain, len_domain, 0x20 + len_myname); 
-       init_str_hdr(&neg->hdr_myname, len_myname, len_myname, 0x20); 
-
-       fstrcpy(neg->myname, myname);
-       fstrcpy(neg->domain, domain);
-}
-
-/*******************************************************************
- Reads or writes an RPC_AUTH_NTLMSSP_NEG structure.
-
- *** lkclXXXX HACK ALERT! ***
-********************************************************************/
-
-BOOL smb_io_rpc_auth_ntlmssp_neg(const char *desc, RPC_AUTH_NTLMSSP_NEG *neg, prs_struct *ps, int depth)
-{
-       uint32 start_offset = prs_offset(ps);
-       if (neg == NULL)
-               return False;
-
-       prs_debug(ps, depth, desc, "smb_io_rpc_auth_ntlmssp_neg");
-       depth++;
-
-       if(!prs_uint32("neg_flgs ", ps, depth, &neg->neg_flgs))
-               return False;
-
-       if (ps->io) {
-               uint32 old_offset;
-               uint32 old_neg_flags = neg->neg_flgs;
-
-               /* reading */
-
-               ZERO_STRUCTP(neg);
-
-               neg->neg_flgs = old_neg_flags;
-
-               if(!smb_io_strhdr("hdr_domain", &neg->hdr_domain, ps, depth))
-                       return False;
-               if(!smb_io_strhdr("hdr_myname", &neg->hdr_myname, ps, depth))
-                       return False;
-
-               old_offset = prs_offset(ps);
-
-               if(!prs_set_offset(ps, neg->hdr_myname.buffer + start_offset - 12))
-                       return False;
-
-               if(!prs_uint8s(True, "myname", ps, depth, (uint8*)neg->myname, 
-                               MIN(neg->hdr_myname.str_str_len, sizeof(neg->myname))))
-                       return False;
-
-               old_offset += neg->hdr_myname.str_str_len;
-
-               if(!prs_set_offset(ps, neg->hdr_domain.buffer + start_offset - 12))
-                       return False;
-
-               if(!prs_uint8s(True, "domain", ps, depth, (uint8*)neg->domain, 
-                       MIN(neg->hdr_domain.str_str_len, sizeof(neg->domain  ))))
-                       return False;
-
-               old_offset += neg->hdr_domain  .str_str_len;
-
-               if(!prs_set_offset(ps, old_offset))
-                       return False;
-       } else {
-               /* writing */
-               if(!smb_io_strhdr("hdr_domain", &neg->hdr_domain, ps, depth))
-                       return False;
-               if(!smb_io_strhdr("hdr_myname", &neg->hdr_myname, ps, depth))
-                       return False;
-
-               if(!prs_uint8s(True, "myname", ps, depth, (uint8*)neg->myname, 
-                                       MIN(neg->hdr_myname.str_str_len, sizeof(neg->myname))))
-                       return False;
-               if(!prs_uint8s(True, "domain", ps, depth, (uint8*)neg->domain, 
-                                       MIN(neg->hdr_domain.str_str_len, sizeof(neg->domain  ))))
-                       return False;
-       }
-
-       return True;
-}
-
-/*******************************************************************
-creates an RPC_AUTH_NTLMSSP_CHAL structure.
-********************************************************************/
-
-void init_rpc_auth_ntlmssp_chal(RPC_AUTH_NTLMSSP_CHAL *chl,
-                               uint32 neg_flags,
-                               uint8 challenge[8])
-{
-       chl->unknown_1 = 0x0; 
-       chl->unknown_2 = 0x00000028;
-       chl->neg_flags = neg_flags; /* 0x0082b1 */
-
-       memcpy(chl->challenge, challenge, sizeof(chl->challenge)); 
-       memset((char *)chl->reserved , '\0', sizeof(chl->reserved)); 
-}
-
-/*******************************************************************
- Reads or writes an RPC_AUTH_NTLMSSP_CHAL structure.
-********************************************************************/
-
-BOOL smb_io_rpc_auth_ntlmssp_chal(const char *desc, RPC_AUTH_NTLMSSP_CHAL *chl, prs_struct *ps, int depth)
-{
-       if (chl == NULL)
-               return False;
-
-       prs_debug(ps, depth, desc, "smb_io_rpc_auth_ntlmssp_chal");
-       depth++;
-
-       if(!prs_uint32("unknown_1", ps, depth, &chl->unknown_1)) /* 0x0000 0000 */
-               return False;
-       if(!prs_uint32("unknown_2", ps, depth, &chl->unknown_2)) /* 0x0000 b2b3 */
-               return False;
-       if(!prs_uint32("neg_flags", ps, depth, &chl->neg_flags)) /* 0x0000 82b1 */
-               return False;
-
-       if(!prs_uint8s (False, "challenge", ps, depth, chl->challenge, sizeof(chl->challenge)))
-               return False;
-       if(!prs_uint8s (False, "reserved ", ps, depth, chl->reserved , sizeof(chl->reserved )))
-               return False;
-
-       return True;
-}
-
-/*******************************************************************
- Inits an RPC_AUTH_NTLMSSP_RESP structure.
-
- *** lkclXXXX FUDGE!  HAVE TO MANUALLY SPECIFY OFFSET HERE (0x1c bytes) ***
- *** lkclXXXX the actual offset is at the start of the auth verifier    ***
-********************************************************************/
-
-void init_rpc_auth_ntlmssp_resp(RPC_AUTH_NTLMSSP_RESP *rsp,
-                               uchar lm_resp[24], uchar nt_resp[24],
-                               const char *domain, const char *user, const char *wks,
-                               uint32 neg_flags)
-{
-       uint32 offset;
-       int dom_len = strlen(domain);
-       int wks_len = strlen(wks);
-       int usr_len = strlen(user);
-       int lm_len  = (lm_resp != NULL) ? 24 : 0;
-       int nt_len  = (nt_resp != NULL) ? 24 : 0;
-
-       DEBUG(5,("make_rpc_auth_ntlmssp_resp\n"));
-
-#ifdef DEBUG_PASSWORD
-       DEBUG(100,("lm_resp\n"));
-       dump_data(100, (char *)lm_resp, 24);
-       DEBUG(100,("nt_resp\n"));
-       dump_data(100, (char *)nt_resp, 24);
-#endif
-
-       DEBUG(6,("dom: %s user: %s wks: %s neg_flgs: 0x%x\n",
-                 domain, user, wks, neg_flags));
-
-       offset = 0x40;
-
-       if (neg_flags & NTLMSSP_NEGOTIATE_UNICODE) {
-               dom_len *= 2;
-               wks_len *= 2;
-               usr_len *= 2;
-       }
-
-       init_str_hdr(&rsp->hdr_domain, dom_len, dom_len, offset);
-       offset += dom_len;
-
-       init_str_hdr(&rsp->hdr_usr, usr_len, usr_len, offset);
-       offset += usr_len;
-
-       init_str_hdr(&rsp->hdr_wks, wks_len, wks_len, offset);
-       offset += wks_len;
-
-       init_str_hdr(&rsp->hdr_lm_resp, lm_len, lm_len, offset);
-       offset += lm_len;
-
-       init_str_hdr(&rsp->hdr_nt_resp, nt_len, nt_len, offset);
-       offset += nt_len;
-
-       init_str_hdr(&rsp->hdr_sess_key, 0, 0, offset);
-
-       rsp->neg_flags = neg_flags;
-
-       memcpy(rsp->lm_resp, lm_resp, 24);
-       memcpy(rsp->nt_resp, nt_resp, 24);
-
-       if (neg_flags & NTLMSSP_NEGOTIATE_UNICODE) {
-               rpcstr_push(rsp->domain, domain, sizeof(rsp->domain), 0);
-               rpcstr_push(rsp->user, user, sizeof(rsp->user), 0);
-               rpcstr_push(rsp->wks, wks, sizeof(rsp->wks), 0);
-       } else {
-               fstrcpy(rsp->domain, domain);
-               fstrcpy(rsp->user, user);
-               fstrcpy(rsp->wks, wks);
-       }
-       
-       rsp->sess_key[0] = 0;
-}
-
-/*******************************************************************
- Reads or writes an RPC_AUTH_NTLMSSP_RESP structure.
-
- *** lkclXXXX FUDGE!  HAVE TO MANUALLY SPECIFY OFFSET HERE (0x1c bytes) ***
- *** lkclXXXX the actual offset is at the start of the auth verifier    ***
-********************************************************************/
-
-BOOL smb_io_rpc_auth_ntlmssp_resp(const char *desc, RPC_AUTH_NTLMSSP_RESP *rsp, prs_struct *ps, int depth)
-{
-       if (rsp == NULL)
-               return False;
-
-       prs_debug(ps, depth, desc, "smb_io_rpc_auth_ntlmssp_resp");
-       depth++;
-
-       if (ps->io) {
-               uint32 old_offset;
-
-               /* reading */
-
-               ZERO_STRUCTP(rsp);
-
-               if(!smb_io_strhdr("hdr_lm_resp ", &rsp->hdr_lm_resp, ps, depth))
-                       return False;
-               if(!smb_io_strhdr("hdr_nt_resp ", &rsp->hdr_nt_resp, ps, depth))
-                       return False;
-               if(!smb_io_strhdr("hdr_domain  ", &rsp->hdr_domain, ps, depth))
-                       return False;
-               if(!smb_io_strhdr("hdr_user    ", &rsp->hdr_usr, ps, depth))
-                       return False;
-               if(!smb_io_strhdr("hdr_wks     ", &rsp->hdr_wks, ps, depth)) 
-                       return False;
-               if(!smb_io_strhdr("hdr_sess_key", &rsp->hdr_sess_key, ps, depth))
-                       return False;
-
-               if(!prs_uint32("neg_flags", ps, depth, &rsp->neg_flags)) /* 0x0000 82b1 */
-                       return False;
-
-               old_offset = prs_offset(ps);
-
-               if(!prs_set_offset(ps, rsp->hdr_domain.buffer + 0xc))
-                       return False;
-
-               if(!prs_uint8s(True , "domain  ", ps, depth, (uint8*)rsp->domain,
-                               MIN(rsp->hdr_domain.str_str_len, sizeof(rsp->domain))))
-                       return False;
-
-               old_offset += rsp->hdr_domain.str_str_len;
-
-               if(!prs_set_offset(ps, rsp->hdr_usr.buffer + 0xc))
-                       return False;
-
-               if(!prs_uint8s(True , "user    ", ps, depth, (uint8*)rsp->user,
-                               MIN(rsp->hdr_usr.str_str_len, sizeof(rsp->user))))
-                       return False;
-
-               old_offset += rsp->hdr_usr.str_str_len;
-
-               if(!prs_set_offset(ps, rsp->hdr_wks.buffer + 0xc))
-                       return False;
-
-               if(!prs_uint8s(True, "wks     ", ps, depth, (uint8*)rsp->wks,
-                               MIN(rsp->hdr_wks.str_str_len, sizeof(rsp->wks))))
-                       return False;
-
-               old_offset += rsp->hdr_wks.str_str_len;
-
-               if(!prs_set_offset(ps, rsp->hdr_lm_resp.buffer + 0xc))
-                       return False;
-
-               if(!prs_uint8s(False, "lm_resp ", ps, depth, (uint8*)rsp->lm_resp,
-                               MIN(rsp->hdr_lm_resp.str_str_len, sizeof(rsp->lm_resp ))))
-                       return False;
-
-               old_offset += rsp->hdr_lm_resp.str_str_len;
-
-               if(!prs_set_offset(ps, rsp->hdr_nt_resp.buffer + 0xc))
-                       return False;
-
-               if(!prs_uint8s(False, "nt_resp ", ps, depth, (uint8*)rsp->nt_resp,
-                               MIN(rsp->hdr_nt_resp.str_str_len, sizeof(rsp->nt_resp ))))
-                       return False;
-
-               old_offset += rsp->hdr_nt_resp.str_str_len;
-
-               if (rsp->hdr_sess_key.str_str_len != 0) {
-
-                       if(!prs_set_offset(ps, rsp->hdr_sess_key.buffer + 0x10))
-                               return False;
-
-                       old_offset += rsp->hdr_sess_key.str_str_len;
-
-                       if(!prs_uint8s(False, "sess_key", ps, depth, (uint8*)rsp->sess_key,
-                                       MIN(rsp->hdr_sess_key.str_str_len, sizeof(rsp->sess_key))))
-                               return False;
-               }
-
-               if(!prs_set_offset(ps, old_offset))
-                       return False;
-       } else {
-               /* writing */
-               if(!smb_io_strhdr("hdr_lm_resp ", &rsp->hdr_lm_resp, ps, depth))
-                       return False;
-               if(!smb_io_strhdr("hdr_nt_resp ", &rsp->hdr_nt_resp, ps, depth))
-                       return False;
-               if(!smb_io_strhdr("hdr_domain  ", &rsp->hdr_domain, ps, depth))
-                       return False;
-               if(!smb_io_strhdr("hdr_user    ", &rsp->hdr_usr, ps, depth))
-                       return False;
-               if(!smb_io_strhdr("hdr_wks     ", &rsp->hdr_wks, ps, depth))
-                       return False;
-               if(!smb_io_strhdr("hdr_sess_key", &rsp->hdr_sess_key, ps, depth))
-                       return False;
-
-               if(!prs_uint32("neg_flags", ps, depth, &rsp->neg_flags)) /* 0x0000 82b1 */
-                       return False;
-
-               if(!prs_uint8s(True , "domain  ", ps, depth, (uint8*)rsp->domain,
-                               MIN(rsp->hdr_domain.str_str_len, sizeof(rsp->domain))))
-                       return False;
-
-               if(!prs_uint8s(True , "user    ", ps, depth, (uint8*)rsp->user,
-                               MIN(rsp->hdr_usr.str_str_len, sizeof(rsp->user))))
-                       return False;
-
-               if(!prs_uint8s(True , "wks     ", ps, depth, (uint8*)rsp->wks,
-                               MIN(rsp->hdr_wks.str_str_len, sizeof(rsp->wks))))
-                       return False;
-               if(!prs_uint8s(False, "lm_resp ", ps, depth, (uint8*)rsp->lm_resp,
-                               MIN(rsp->hdr_lm_resp .str_str_len, sizeof(rsp->lm_resp))))
-                       return False;
-               if(!prs_uint8s(False, "nt_resp ", ps, depth, (uint8*)rsp->nt_resp,
-                               MIN(rsp->hdr_nt_resp .str_str_len, sizeof(rsp->nt_resp ))))
-                       return False;
-               if(!prs_uint8s(False, "sess_key", ps, depth, (uint8*)rsp->sess_key,
-                               MIN(rsp->hdr_sess_key.str_str_len, sizeof(rsp->sess_key))))
-                       return False;
-       }
-
-       return True;
-}
-
-/*******************************************************************
- Checks an RPC_AUTH_NTLMSSP_CHK structure.
-********************************************************************/
-
-BOOL rpc_auth_ntlmssp_chk(RPC_AUTH_NTLMSSP_CHK *chk, uint32 crc32, uint32 seq_num)
-{
-       if (chk == NULL)
-               return False;
-
-       if (chk->crc32 != crc32 ||
-           chk->ver   != NTLMSSP_SIGN_VERSION ||
-           chk->seq_num != seq_num)
-       {
-               DEBUG(5,("verify failed - crc %x ver %x seq %d\n",
-                        chk->crc32, chk->ver, chk->seq_num));
-                       
-               DEBUG(5,("verify expect - crc %x ver %x seq %d\n",
-                       crc32, NTLMSSP_SIGN_VERSION, seq_num));
-               return False;
-       }
-       return True;
-}
-
-/*******************************************************************
- Inits an RPC_AUTH_NTLMSSP_CHK structure.
-********************************************************************/
-
-void init_rpc_auth_ntlmssp_chk(RPC_AUTH_NTLMSSP_CHK *chk,
-                               uint32 ver, uint32 crc32, uint32 seq_num)
-{
-       chk->ver      = ver;
-       chk->reserved = 0x0;
-       chk->crc32    = crc32;
-       chk->seq_num  = seq_num;
-}
-
-/*******************************************************************
- Reads or writes an RPC_AUTH_NTLMSSP_CHK structure.
+creates an RPC_AUTH_SCHANNEL_NEG structure.
 ********************************************************************/
 
-BOOL smb_io_rpc_auth_ntlmssp_chk(const char *desc, RPC_AUTH_NTLMSSP_CHK *chk, prs_struct *ps, int depth)
-{
-       if (chk == NULL)
-               return False;
-
-       prs_debug(ps, depth, desc, "smb_io_rpc_auth_ntlmssp_chk");
-       depth++;
-
-       if(!prs_align(ps))
-               return False;
-
-       if(!prs_uint32("ver     ", ps, depth, &chk->ver))
-               return False;
-       if(!prs_uint32("reserved", ps, depth, &chk->reserved))
-               return False;
-       if(!prs_uint32("crc32   ", ps, depth, &chk->crc32))
-               return False;
-       if(!prs_uint32("seq_num ", ps, depth, &chk->seq_num))
-               return False;
-
-       return True;
-}
-
-/*******************************************************************
-creates an RPC_AUTH_NETSEC_NEG structure.
-********************************************************************/
-void init_rpc_auth_netsec_neg(RPC_AUTH_NETSEC_NEG *neg,
+void init_rpc_auth_schannel_neg(RPC_AUTH_SCHANNEL_NEG *neg,
                              const char *domain, const char *myname)
 {
        neg->type1 = 0;
@@ -1224,16 +801,16 @@ void init_rpc_auth_netsec_neg(RPC_AUTH_NETSEC_NEG *neg,
 }
 
 /*******************************************************************
- Reads or writes an RPC_AUTH_NETSEC_NEG structure.
+ Reads or writes an RPC_AUTH_SCHANNEL_NEG structure.
 ********************************************************************/
 
-BOOL smb_io_rpc_auth_netsec_neg(const char *desc, RPC_AUTH_NETSEC_NEG *neg,
+BOOL smb_io_rpc_auth_schannel_neg(const char *desc, RPC_AUTH_SCHANNEL_NEG *neg,
                                prs_struct *ps, int depth)
 {
        if (neg == NULL)
                return False;
 
-       prs_debug(ps, depth, desc, "smb_io_rpc_auth_netsec_neg");
+       prs_debug(ps, depth, desc, "smb_io_rpc_auth_schannel_neg");
        depth++;
 
        if(!prs_align(ps))
@@ -1252,16 +829,17 @@ BOOL smb_io_rpc_auth_netsec_neg(const char *desc, RPC_AUTH_NETSEC_NEG *neg,
 }
 
 /*******************************************************************
-reads or writes an RPC_AUTH_NETSEC_CHK structure.
+reads or writes an RPC_AUTH_SCHANNEL_CHK structure.
 ********************************************************************/
-BOOL smb_io_rpc_auth_netsec_chk(const char *desc, int auth_len, 
-                                RPC_AUTH_NETSEC_CHK * chk,
+
+BOOL smb_io_rpc_auth_schannel_chk(const char *desc, int auth_len, 
+                                RPC_AUTH_SCHANNEL_CHK * chk,
                                prs_struct *ps, int depth)
 {
        if (chk == NULL)
                return False;
 
-       prs_debug(ps, depth, desc, "smb_io_rpc_auth_netsec_chk");
+       prs_debug(ps, depth, desc, "smb_io_rpc_auth_schannel_chk");
        depth++;
 
        if ( !prs_uint8s(False, "sig  ", ps, depth, chk->sig, sizeof(chk->sig)) )
@@ -1273,7 +851,7 @@ BOOL smb_io_rpc_auth_netsec_chk(const char *desc, int auth_len,
        if ( !prs_uint8s(False, "packet_digest", ps, depth, chk->packet_digest, sizeof(chk->packet_digest)) )
                return False;
        
-       if ( auth_len == RPC_AUTH_NETSEC_SIGN_OR_SEAL_CHK_LEN ) {
+       if ( auth_len == RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN ) {
                if ( !prs_uint8s(False, "confounder", ps, depth, chk->confounder, sizeof(chk->confounder)) )
                        return False;
        }
index 6b0193c6e46e58a402c000b58b8541c1185e09e6..1aaebf71e39cefb8cc2d9dedbd653db00cfc1e18 100644 (file)
@@ -25,8 +25,6 @@
  */
 
 #include "includes.h"
-#include "rpc_parse.h"
-#include "nterr.h"
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_RPC_PARSE
@@ -7038,9 +7036,9 @@ inits a SAMR_R_GET_DOM_PWINFO structure.
 
 void init_samr_q_chgpasswd_user(SAMR_Q_CHGPASSWD_USER * q_u,
                                const char *dest_host, const char *user_name,
-                               const char nt_newpass[516],
+                               const uchar nt_newpass[516],
                                const uchar nt_oldhash[16],
-                               const char lm_newpass[516],
+                               const uchar lm_newpass[516],
                                const uchar lm_oldhash[16])
 {
        DEBUG(5, ("init_samr_q_chgpasswd_user\n"));
index b86ca23df158a4290234abad05bf1ef01f1205c5..e1a7ad84273a33709c0f189eb3f6aaf90fbf22d5 100644 (file)
@@ -100,40 +100,48 @@ static BOOL svcctl_io_service_config( const char *desc, SERVICE_CONFIG *config,
 
        return True;
 }
+
 /*******************************************************************
 ********************************************************************/
 
-BOOL svcctl_io_service_description( const char *desc, UNISTR2 *svcdesc, prs_struct *ps, int depth )
+BOOL svcctl_io_enum_services_status( const char *desc, ENUM_SERVICES_STATUS *enum_status, RPC_BUFFER *buffer, int depth )
 {
-
-       prs_debug(ps, depth, desc, "svcctl_io_service_description");
+       prs_struct *ps=&buffer->prs;
+       
+       prs_debug(ps, depth, desc, "svcctl_io_enum_services_status");
        depth++;
-
-       if (!prs_io_unistr2("", ps, depth, svcdesc))
+       
+       if ( !smb_io_relstr("servicename", buffer, depth, &enum_status->servicename) )
+               return False;
+       if ( !smb_io_relstr("displayname", buffer, depth, &enum_status->displayname) )
                return False;
 
+       if ( !svcctl_io_service_status("svc_status", &enum_status->status, ps, depth) )
+               return False;
+       
        return True;
 }
 
-
 /*******************************************************************
 ********************************************************************/
 
-BOOL svcctl_io_enum_services_status( const char *desc, ENUM_SERVICES_STATUS *enum_status, RPC_BUFFER *buffer, int depth )
+BOOL svcctl_io_service_status_process( const char *desc, SERVICE_STATUS_PROCESS *status, RPC_BUFFER *buffer, int depth )
 {
        prs_struct *ps=&buffer->prs;
-       
-       prs_debug(ps, depth, desc, "svcctl_io_enum_services_status");
+
+       prs_debug(ps, depth, desc, "svcctl_io_service_status_process");
        depth++;
-       
-       if ( !smb_io_relstr("servicename", buffer, depth, &enum_status->servicename) )
+
+       if ( !svcctl_io_service_status("status", &status->status, ps, depth) )
                return False;
-       if ( !smb_io_relstr("displayname", buffer, depth, &enum_status->displayname) )
+       if(!prs_align(ps))
                return False;
 
-       if ( !svcctl_io_service_status("svc_status", &enum_status->status, ps, depth) )
+       if(!prs_uint32("process_id", ps, depth, &status->process_id))
                return False;
-       
+       if(!prs_uint32("service_flags", ps, depth, &status->service_flags))
+               return False;
+
        return True;
 }
 
@@ -151,6 +159,45 @@ uint32 svcctl_sizeof_enum_services_status( ENUM_SERVICES_STATUS *status )
        return size;
 }
 
+/********************************************************************
+********************************************************************/
+
+static uint32 sizeof_unistr2( UNISTR2 *string )
+{
+       uint32 size = 0;
+
+       if ( !string ) 
+               return 0;       
+
+       size  = sizeof(uint32) * 3;             /* length fields */
+       size += 2 * string->uni_max_len;        /* string data */
+       size += size % 4;                       /* alignment */
+
+       return size;
+}
+
+/********************************************************************
+********************************************************************/
+
+uint32 svcctl_sizeof_service_config( SERVICE_CONFIG *config )
+{
+       uint32 size = 0;
+
+       size = sizeof(uint32) * 4;      /* static uint32 fields */
+
+       /* now add the UNISTR2 + pointer sizes */
+
+       size += sizeof(uint32) * sizeof_unistr2(config->executablepath);
+       size += sizeof(uint32) * sizeof_unistr2(config->loadordergroup);
+       size += sizeof(uint32) * sizeof_unistr2(config->dependencies);
+       size += sizeof(uint32) * sizeof_unistr2(config->startname);
+       size += sizeof(uint32) * sizeof_unistr2(config->displayname);
+       
+       return size;
+}
+
+
+
 /*******************************************************************
 ********************************************************************/
 
@@ -694,7 +741,7 @@ BOOL svcctl_io_q_query_service_config2(const char *desc, SVCCTL_Q_QUERY_SERVICE_
        if(!smb_io_pol_hnd("service_pol", &q_u->handle, ps, depth))
                return False;
 
-       if(!prs_uint32("info_level", ps, depth, &q_u->info_level))
+       if(!prs_uint32("level", ps, depth, &q_u->level))
                return False;
 
        if(!prs_uint32("buffer_size", ps, depth, &q_u->buffer_size))
@@ -705,36 +752,145 @@ BOOL svcctl_io_q_query_service_config2(const char *desc, SVCCTL_Q_QUERY_SERVICE_
 
 
 /*******************************************************************
- Creates a service description response buffer.
- The format seems to be DWORD:length of buffer
-                        DWORD:offset (fixed as four)
-                        UNISTR: unicode description in the rest of the buffer
 ********************************************************************/
 
-void init_service_description_buffer(RPC_DATA_BLOB *str,  const char *service_desc, int blob_length)
+void init_service_description_buffer(SERVICE_DESCRIPTION *desc, const char *service_desc )
 {
-       uint32 offset;
-       uint8 *bp;
+       desc->unknown = 0x04;   /* always 0x0000 0004 (no idea what this is) */
+       init_unistr( &desc->description, service_desc );
+}
 
-       ZERO_STRUCTP(str);
+/*******************************************************************
+********************************************************************/
 
-       offset = 4;
+BOOL svcctl_io_service_description( const char *desc, SERVICE_DESCRIPTION *description, RPC_BUFFER *buffer, int depth )
+{
+        prs_struct *ps = &buffer->prs;
 
-       /* set up string lengths. */
+        prs_debug(ps, depth, desc, "svcctl_io_service_description");
+        depth++;
 
-       str->buf_len = create_rpc_blob(str, blob_length);
-       DEBUG(10, ("init_service_description buffer: Allocated a blob of [%d] \n",str->buf_len));
+       if ( !prs_uint32("unknown", ps, depth, &description->unknown) )
+               return False;
+       if ( !prs_unistr("description", ps, depth, &description->description) )
+               return False;
 
-       if ( str && str->buffer && str->buf_len) {
-               memset(str->buffer,0,str->buf_len);
-               memcpy(str->buffer, &offset, sizeof(uint32));
-               bp = &str->buffer[4];
-               if (service_desc) {
-                       rpcstr_push(bp, service_desc,str->buf_len-4,0);
+       return True;
+} 
+
+/*******************************************************************
+********************************************************************/
+
+uint32 svcctl_sizeof_service_description( SERVICE_DESCRIPTION *desc )
+{
+       if ( !desc )
+               return 0;
+
+       /* make sure to include the terminating NULL */
+       return ( sizeof(uint32) + (2*(str_len_uni(&desc->description)+1)) );
+}
+
+/*******************************************************************
+********************************************************************/
+
+static BOOL svcctl_io_action( const char *desc, SC_ACTION *action, prs_struct *ps, int depth )
+{
+
+       prs_debug(ps, depth, desc, "svcctl_io_action");
+       depth++;
+
+       if ( !prs_uint32("type", ps, depth, &action->type) )
+               return False;
+       if ( !prs_uint32("delay", ps, depth, &action->delay) )
+               return False;
+
+       return True;
+}
+
+/*******************************************************************
+********************************************************************/
+
+BOOL svcctl_io_service_fa( const char *desc, SERVICE_FAILURE_ACTIONS *fa, RPC_BUFFER *buffer, int depth )
+{
+        prs_struct *ps = &buffer->prs;
+       int i;
+
+        prs_debug(ps, depth, desc, "svcctl_io_service_description");
+        depth++;
+
+       if ( !prs_uint32("reset_period", ps, depth, &fa->reset_period) )
+               return False;
+
+       if ( !prs_pointer( desc, ps, depth, (void**)&fa->rebootmsg, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2 ) )
+               return False;
+       if ( !prs_pointer( desc, ps, depth, (void**)&fa->command, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2 ) )
+               return False;
+
+       if ( !prs_uint32("num_actions", ps, depth, &fa->num_actions) )
+               return False;
+
+       if ( UNMARSHALLING(ps) && fa->num_actions ) {
+               if ( !(fa->actions = TALLOC_ARRAY( get_talloc_ctx(), SC_ACTION, fa->num_actions )) ) {
+                       DEBUG(0,("svcctl_io_service_fa: talloc() failure!\n"));
+                       return False;
                }
        }
+
+       for ( i=0; i<fa->num_actions; i++ ) {
+               if ( !svcctl_io_action( "actions", &fa->actions[i], ps, depth ) )
+                       return False;
+       }
+
+       return True;
+} 
+
+/*******************************************************************
+********************************************************************/
+
+uint32 svcctl_sizeof_service_fa( SERVICE_FAILURE_ACTIONS *fa)
+{
+       uint32 size = 0;
+
+       if ( !fa )
+               return 0;
+
+       size  = sizeof(uint32) * 2;
+       size += sizeof_unistr2( fa->rebootmsg );
+       size += sizeof_unistr2( fa->command );
+       size += sizeof(SC_ACTION) * fa->num_actions;
+
+       return size;
 }
 
+/*******************************************************************
+********************************************************************/
+
+BOOL svcctl_io_r_query_service_config2(const char *desc, SVCCTL_R_QUERY_SERVICE_CONFIG2 *r_u, prs_struct *ps, int depth)
+{
+       if ( !r_u )
+               return False;
+
+       prs_debug(ps, depth, desc, "svcctl_io_r_query_service_config2");
+       depth++;
+
+       if ( !prs_align(ps) )
+               return False;
+
+       if (!prs_rpcbuffer("", ps, depth, &r_u->buffer))
+               return False;
+       if(!prs_align(ps))
+               return False;
+
+       if (!prs_uint32("needed", ps, depth, &r_u->needed))
+               return False;
+
+       if(!prs_werror("status", ps, depth, &r_u->status))
+               return False;
+
+       return True;
+}
+
+
 /*******************************************************************
 ********************************************************************/
 
@@ -752,7 +908,7 @@ BOOL svcctl_io_q_query_service_status_ex(const char *desc, SVCCTL_Q_QUERY_SERVIC
        if(!smb_io_pol_hnd("service_pol", &q_u->handle, ps, depth))
                return False;
 
-       if(!prs_uint32("info_level", ps, depth, &q_u->info_level))
+       if(!prs_uint32("level", ps, depth, &q_u->level))
                return False;
 
        if(!prs_uint32("buffer_size", ps, depth, &q_u->buffer_size))
@@ -771,7 +927,7 @@ BOOL svcctl_io_r_query_service_status_ex(const char *desc, SVCCTL_R_QUERY_SERVIC
                return False;
 
        prs_debug(ps, depth, desc, "svcctl_io_r_query_service_status_ex");
-               depth++;
+       depth++;
 
        if (!prs_rpcbuffer("", ps, depth, &r_u->buffer))
                return False;
@@ -791,37 +947,80 @@ BOOL svcctl_io_r_query_service_status_ex(const char *desc, SVCCTL_R_QUERY_SERVIC
 /*******************************************************************
 ********************************************************************/
 
-BOOL svcctl_io_r_query_service_config2(const char *desc, SVCCTL_R_QUERY_SERVICE_CONFIG2 *r_u, prs_struct *ps, int depth)
+BOOL svcctl_io_q_lock_service_db(const char *desc, SVCCTL_Q_LOCK_SERVICE_DB *q_u, prs_struct *ps, int depth)
+{
+       if (q_u == NULL)
+               return False;
+
+       prs_debug(ps, depth, desc, "svcctl_io_q_lock_service_db");
+       depth++;
+
+       if(!prs_align(ps))
+               return False;
+
+       if(!smb_io_pol_hnd("scm_handle", &q_u->handle, ps, depth))
+               return False;
+
+       return True;
+
+}
+
+/*******************************************************************
+********************************************************************/
+
+BOOL svcctl_io_r_lock_service_db(const char *desc, SVCCTL_R_LOCK_SERVICE_DB *r_u, prs_struct *ps, int depth)
 {
        if ( !r_u )
                return False;
 
-       prs_debug(ps, depth, desc, "svcctl_io_r_query_service_config2");
+       prs_debug(ps, depth, desc, "svcctl_io_r_lock_service_db");
        depth++;
 
        if(!prs_align(ps))
                return False;
 
-       if(!prs_uint32("returned", ps, depth, &r_u->returned))
+       if(!smb_io_pol_hnd("lock_handle", &r_u->h_lock, ps, depth))
                return False;
 
-       if (r_u->returned > 4) {
-               if (!prs_uint32("offset", ps, depth, &r_u->offset))
-                       return False;
+       if(!prs_werror("status", ps, depth, &r_u->status))
+               return False;
 
-               if ( !prs_pointer( desc, ps, depth, (void**)&r_u->description, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2 ) )
-                       return False;
+       return True;
+}
 
-               if(!prs_align(ps))
-                       return False;
-       } else {
-               /* offset does double duty here */
-               r_u->offset = 0;
-               if (!prs_uint32("offset", ps, depth, &r_u->offset))
-                       return False;
-       }
+/*******************************************************************
+********************************************************************/
 
-       if (!prs_uint32("needed", ps, depth, &r_u->needed))
+BOOL svcctl_io_q_unlock_service_db(const char *desc, SVCCTL_Q_UNLOCK_SERVICE_DB *q_u, prs_struct *ps, int depth)
+{
+       if (q_u == NULL)
+               return False;
+
+       prs_debug(ps, depth, desc, "svcctl_io_q_unlock_service_db");
+       depth++;
+
+       if(!prs_align(ps))
+               return False;
+
+       if(!smb_io_pol_hnd("h_lock", &q_u->h_lock, ps, depth))
+               return False;
+
+       return True;
+
+}
+
+/*******************************************************************
+********************************************************************/
+
+BOOL svcctl_io_r_unlock_service_db(const char *desc, SVCCTL_R_UNLOCK_SERVICE_DB *r_u, prs_struct *ps, int depth)
+{
+       if ( !r_u )
+               return False;
+
+       prs_debug(ps, depth, desc, "svcctl_io_r_unlock_service_db");
+       depth++;
+
+       if(!prs_align(ps))
                return False;
 
        if(!prs_werror("status", ps, depth, &r_u->status))
@@ -831,3 +1030,5 @@ BOOL svcctl_io_r_query_service_config2(const char *desc, SVCCTL_R_QUERY_SERVICE_
 }
 
 
+
+
index 65b10e8fe40dcc93b89222614139ef4f1ca2aa67..ae15d43f4bab2d108d751b98eafd40c7b8c68a99 100644 (file)
@@ -27,7 +27,6 @@ static BOOL api_eventlog_open_eventlog(pipes_struct *p)
 {
        EVENTLOG_Q_OPEN_EVENTLOG q_u;
        EVENTLOG_R_OPEN_EVENTLOG r_u;
-
        prs_struct *data = &p->in_data.data;
        prs_struct *rdata = &p->out_data.rdata;
 
@@ -53,7 +52,6 @@ static BOOL api_eventlog_close_eventlog(pipes_struct *p)
 {
        EVENTLOG_Q_CLOSE_EVENTLOG q_u;
        EVENTLOG_R_CLOSE_EVENTLOG r_u;
-
        prs_struct *data = &p->in_data.data;
        prs_struct *rdata = &p->out_data.rdata;
 
@@ -79,7 +77,6 @@ static BOOL api_eventlog_get_num_records(pipes_struct *p)
 {
        EVENTLOG_Q_GET_NUM_RECORDS q_u;
        EVENTLOG_R_GET_NUM_RECORDS r_u;
-
        prs_struct *data = &p->in_data.data;
        prs_struct *rdata = &p->out_data.rdata;
 
@@ -105,7 +102,6 @@ static BOOL api_eventlog_get_oldest_entry(pipes_struct *p)
 {
        EVENTLOG_Q_GET_OLDEST_ENTRY q_u;
        EVENTLOG_R_GET_OLDEST_ENTRY r_u;
-
        prs_struct *data = &p->in_data.data;
        prs_struct *rdata = &p->out_data.rdata;
 
@@ -131,7 +127,6 @@ static BOOL api_eventlog_read_eventlog(pipes_struct *p)
 {
        EVENTLOG_Q_READ_EVENTLOG q_u;
        EVENTLOG_R_READ_EVENTLOG r_u;
-
        prs_struct *data = &p->in_data.data;
        prs_struct *rdata = &p->out_data.rdata;
 
@@ -157,7 +152,6 @@ static BOOL api_eventlog_clear_eventlog(pipes_struct *p)
 {
        EVENTLOG_Q_CLEAR_EVENTLOG q_u;
        EVENTLOG_R_CLEAR_EVENTLOG r_u;
-
        prs_struct *data = &p->in_data.data;
        prs_struct *rdata = &p->out_data.rdata;
 
index a9b0c9bed80fca291d7bf5e1077d532748d31bdb..414c99d28e2bcc0ec292845d6cbf3f245819d3af 100644 (file)
@@ -1,7 +1,8 @@
 /* 
  *  Unix SMB/CIFS implementation.
  *  RPC Pipe client / server routines
- *  Copyright (C) Marcin Krzysztof Porwit    2005.
+ *  Copyright (C) Marcin Krzysztof Porwit    2005,
+ *  Copyright (C) Gerald (Jerry) Carter      2005.
  *  
  *  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
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_RPC_SRV
 
-typedef struct eventlog_info
+typedef struct {
+       char *logname;
+       char *servername;
+       uint32 num_records;
+       uint32 oldest_entry;
+       uint32 flags;
+} EventlogInfo;
+
+  
+/********************************************************************
+ Inform the external eventlog machinery of default values (on startup 
+ probably)
+********************************************************************/
+
+void eventlog_refresh_external_parameters( NT_USER_TOKEN *token )
 {
-    /* for use by the \PIPE\eventlog policy */
-    fstring source_log_file_name;
-    fstring source_server_name;
-    fstring handle_string;
-    uint32 num_records;
-    uint32 oldest_entry;
-    uint32 active_entry;
-    uint32 flags;
-} Eventlog_info;
+       const char **elogs = lp_eventlog_list();
+       int i;
+
+       if ( !elogs )
+               return ;
+
+       if ( !*lp_eventlog_control_cmd() )
+               return;
+
+       for ( i=0; elogs[i]; i++ ) {
+       
+               DEBUG(10,("eventlog_refresh_external_parameters: Refreshing =>[%s]\n", 
+                       elogs[i]));     
+               
+               if ( !control_eventlog_hook( token, elogs[i] ) ) {
+                       DEBUG(0,("eventlog_refresh_external_parameters: failed to refresh [%s]\n",
+                               elogs[i]));
+               }
+       }  
+    
+       return;
+}
+
+/********************************************************************
+********************************************************************/
 
 static void free_eventlog_info(void *ptr)
 {
-    struct eventlog_info *info = (struct eventlog_info *)ptr;
-    memset(info->source_log_file_name, '0', sizeof(*(info->source_log_file_name)));
-    memset(info->source_server_name, '0', sizeof(*(info->source_server_name)));
-    memset(info->handle_string, '0', sizeof(*(info->handle_string)));
-    memset(info, 0, sizeof(*(info)));
-    SAFE_FREE(info);
+       TALLOC_FREE( ptr );
 }
 
-static Eventlog_info *find_eventlog_info_by_hnd(pipes_struct *p,
-                                               POLICY_HND *handle)
+/********************************************************************
+********************************************************************/
+
+static EventlogInfo *find_eventlog_info_by_hnd(pipes_struct *p, POLICY_HND *handle)
 {
-    Eventlog_info *info = NULL;
+       EventlogInfo *info;
     
-    if(!(find_policy_by_hnd(p,handle,(void **)&info)))
-    {
-       DEBUG(2,("find_eventlog_info_by_hnd: eventlog not found.\n"));
-    }
+       if ( !find_policy_by_hnd(p,handle,(void **)&info) ) {
+               DEBUG(2,("find_eventlog_info_by_hnd: eventlog not found.\n"));
+               return NULL;
+       }
 
-    return info;
+       return info;
 }
 
-void policy_handle_to_string(POLICY_HND *handle, fstring *dest)
+/********************************************************************
+ Callout to control the specified event log - passing out only 
+ the MaxSize and Retention values, along with eventlog name
+ uses smbrun...
+      INPUT: <control_cmd> <log name> <retention> <maxsize>
+      OUTPUT: nothing
+********************************************************************/
+
+BOOL control_eventlog_hook(NT_USER_TOKEN *token, const char *elogname )
 {
-    memset(dest, 0, sizeof(*dest));
-    snprintf((char *)dest, sizeof(*dest), "%08X-%08X-%04X-%04X-%02X%02X%02X%02X%02X",
-            handle->data1,
-            handle->data2,
-            handle->data3,
-            handle->data4,
-            handle->data5[0],
-            handle->data5[1],
-            handle->data5[2],
-            handle->data5[3],
-            handle->data5[4]);
+       char *cmd = lp_eventlog_control_cmd();
+       pstring command;
+       int ret;
+       int fd = -1;
+       uint32 uiMaxSize, uiRetention;
+       pstring path;
+       REGISTRY_KEY *keyinfo;
+       REGISTRY_VALUE *val;
+       REGVAL_CTR *values;
+       WERROR wresult;
+
+       if ( !cmd || !*cmd ) {
+               DEBUG(0, ("control_eventlog_hook: No \"eventlog control command\" defined in smb.conf!\n"));
+               return False;
+       }
+
+       /* set resonable defaults.  512Kb on size and 1 week on time */
+       
+       uiMaxSize = 0x80000;
+       uiRetention = 604800;
+       
+       /* the general idea is to internally open the registry 
+          key and retreive the values.  That way we can continue 
+          to use the same fetch/store api that we use in 
+          srv_reg_nt.c */
+
+       pstr_sprintf( path, "%s/%s", KEY_EVENTLOG, elogname );
+       wresult = regkey_open_internal( &keyinfo, path, token, REG_KEY_READ );
+       
+       if ( !W_ERROR_IS_OK( wresult ) ) {
+               DEBUG(4,("control_eventlog_hook: Failed to open key [%s] (%s)\n",
+                       path, dos_errstr(wresult) ));
+               return False;
+       }
+       
+       if ( !(values = TALLOC_ZERO_P( keyinfo, REGVAL_CTR )) ) {
+               TALLOC_FREE( keyinfo );
+               DEBUG(0,("control_eventlog_hook: talloc() failed!\n"));
+               
+               return False;
+       }
+       fetch_reg_values( keyinfo, values );
+       
+       if ( (val = regval_ctr_getvalue( values, "Retention" )) != NULL )
+               uiRetention = IVAL( regval_data_p(val), 0 );
+
+       if ( (val = regval_ctr_getvalue( values, "MaxSize" )) != NULL )
+               uiMaxSize = IVAL( regval_data_p(val), 0 );
+               
+       TALLOC_FREE( keyinfo );
+       
+       /* now run the command */
+
+       pstr_sprintf(command, "%s \"%s\" %u %u", cmd, elogname, uiRetention, uiMaxSize );
+
+       DEBUG(10, ("control_eventlog_hook: Running [%s]\n", command));
+       ret = smbrun(command, &fd);
+       DEBUGADD(10, ("returned [%d]\n", ret));
+
+       if ( ret != 0 ) {
+               DEBUG(10,("control_eventlog_hook: Command returned  [%d]\n", ret));
+               if (fd != -1 )
+                       close(fd);
+               return False;
+       }
+
+       close(fd);
+       return True;
 }
 
+
+/********************************************************************
+********************************************************************/
+
 /**
  * Callout to open the specified event log
  * 
@@ -81,109 +178,53 @@ void policy_handle_to_string(POLICY_HND *handle, fstring *dest)
  *     OUTPUT: the string "SUCCESS" if the command succeeded
  *             no such string if there was a failure.
  */
-static BOOL _eventlog_open_eventlog_hook(Eventlog_info *info)
+static BOOL open_eventlog_hook( EventlogInfo *info )
 {
-    char *cmd = lp_eventlog_open_cmd();
-    char **qlines;
-    pstring command;
-    int numlines = 0;
-    int ret;
-    int fd = -1;
-
-    if(cmd == NULL || strlen(cmd) == 0)
-    {
-       DEBUG(0, ("Must define an \"eventlog open command\" entry in the config.\n"));
-       return False;
-    }
-
-    memset(command, 0, sizeof(command));
-    slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\"",
-            cmd,
-            info->source_log_file_name,
-            info->handle_string);
-
-    DEBUG(10, ("Running [%s]\n", command));
-    ret = smbrun(command, &fd);
-    DEBUGADD(10, ("returned [%d]\n", ret));
-
-    if(ret != 0)
-    {
-       if(fd != -1)
-           close(fd);
-       return False;
-    }
+       char *cmd = lp_eventlog_open_cmd();
+       char **qlines;
+       pstring command;
+       int numlines = 0;
+       int ret;
+       int fd = -1;
+
+       if ( !cmd || !*cmd ) {
+               DEBUG(0, ("Must define an \"eventlog open command\" entry in the config.\n"));
+               return False;
+       }
+
+       pstr_sprintf(command, "%s \"%s\"", cmd, info->logname );
 
-    qlines = fd_lines_load(fd, &numlines);
-    DEBUGADD(10, ("Lines returned = [%d]\n", numlines));
-    close(fd);
+       DEBUG(10, ("Running [%s]\n", command));
+       ret = smbrun(command, &fd);
+       DEBUGADD(10, ("returned [%d]\n", ret));
 
-    if(numlines)
-    {
-       DEBUGADD(10, ("Line[0] = [%s]\n", qlines[0]));
-       if(0 == strncmp(qlines[0], "SUCCESS", strlen("SUCCESS")))
-       {
-           DEBUGADD(10, ("Able to open [%s].\n", info->source_log_file_name));
-           file_lines_free(qlines);
-           return True;
+       if(ret != 0) {
+               if(fd != -1) {
+                       close(fd);
+               }
+               return False;
        }
-    }
 
-    file_lines_free(qlines);
-    return False;
-}
+       qlines = fd_lines_load(fd, &numlines);
+       DEBUGADD(10, ("Lines returned = [%d]\n", numlines));
+       close(fd);
 
-WERROR _eventlog_open_eventlog(pipes_struct *p,
-                              EVENTLOG_Q_OPEN_EVENTLOG *q_u,
-                              EVENTLOG_R_OPEN_EVENTLOG *r_u)
-{
-    Eventlog_info *info = NULL;
-    
-    if(!q_u || !r_u)
-       return WERR_NOMEM;
-    
-    if((info = SMB_MALLOC_P(Eventlog_info)) == NULL)
-       return WERR_NOMEM;
-    
-    ZERO_STRUCTP(info);
-
-    if(q_u->servername_ptr != 0)
-    {
-       unistr2_to_ascii(info->source_server_name, &(q_u->servername), sizeof(info->source_server_name));
-    }
-    else
-    {
-       /* if servername == NULL, use the local computer */
-       fstrcpy(info->source_server_name, global_myname());
-    }
-    DEBUG(10, ("_eventlog_open_eventlog: Using [%s] as the server name.\n", info->source_server_name));
-
-    if(q_u->sourcename_ptr != 0)
-    {
-       unistr2_to_ascii(info->source_log_file_name, &(q_u->sourcename), sizeof(info->source_log_file_name));
-    }
-    else
-    {
-        /* if sourcename == NULL, default to "Application" log */
-       fstrcpy(info->source_log_file_name, "Application");
-    }
-    DEBUG(10, ("_eventlog_open_eventlog: Using [%s] as the source log file.\n", info->source_log_file_name));
-
-    if(!create_policy_hnd(p, &(r_u->handle), free_eventlog_info, (void *)info))
-    {
-       free_eventlog_info(info);
-       return WERR_NOMEM;
-    }
-
-    policy_handle_to_string(&r_u->handle, &info->handle_string);
-
-    if(!(_eventlog_open_eventlog_hook(info)))
-    {
-       close_policy_hnd(p, &r_u->handle);
-       return WERR_BADFILE;
-    }
-
-    return WERR_OK;
+       if(numlines) {
+               DEBUGADD(10, ("Line[0] = [%s]\n", qlines[0]));
+               if(0 == strncmp(qlines[0], "SUCCESS", strlen("SUCCESS"))) {
+                       DEBUGADD(10, ("Able to open [%s].\n", info->logname));
+                       file_lines_free(qlines);
+                       return True;
+               }
+       }
+
+       file_lines_free(qlines);
+
+       return False;
 }
+
+/********************************************************************
+********************************************************************/
 /**
  * Callout to get the number of records in the specified event log
  * 
@@ -192,74 +233,52 @@ WERROR _eventlog_open_eventlog(pipes_struct *p,
  *     OUTPUT: A single line with a single integer containing the number of
  *             entries in the log. If there are no entries in the log, return 0.
  */
-static BOOL _eventlog_get_num_records_hook(Eventlog_info *info)
-{
-    char *cmd = lp_eventlog_num_records_cmd();
-    char **qlines;
-    pstring command;
-    int numlines = 0;
-    int ret;
-    int fd = -1;
-
-    if(cmd == NULL || strlen(cmd) == 0)
-    {
-       DEBUG(0, ("Must define an \"eventlog num records command\" entry in the config.\n"));
-       return False;
-    }
-
-    memset(command, 0, sizeof(command));
-    slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\"", 
-            cmd,
-            info->source_log_file_name,
-            info->handle_string);
-
-    DEBUG(10, ("Running [%s]\n", command));
-    ret = smbrun(command, &fd);
-    DEBUGADD(10, ("returned [%d]\n", ret));
-
-    if(ret != 0)
-    {
-       if(fd != -1)
-           close(fd);
-       return False;
-    }
 
-    qlines = fd_lines_load(fd, &numlines);
-    DEBUGADD(10, ("Lines returned = [%d]\n", numlines));
-    close(fd);
+static BOOL get_num_records_hook(EventlogInfo *info)
+{
+       char *cmd = lp_eventlog_num_records_cmd();
+       char **qlines;
+       pstring command;
+       int numlines = 0;
+       int ret;
+       int fd = -1;
+
+       if ( !cmd || !*cmd ) {
+               DEBUG(0, ("Must define an \"eventlog num records command\" entry in the config.\n"));
+               return False;
+       }
 
-    if(numlines)
-    {
-       DEBUGADD(10, ("Line[0] = [%s]\n", qlines[0]));
-       sscanf(qlines[0], "%d", &(info->num_records));
-       file_lines_free(qlines);
-       return True;
-    }
+       pstr_sprintf( command, "%s \"%s\"", cmd, info->logname );
 
-    file_lines_free(qlines);
-    return False;
-}
+       DEBUG(10, ("Running [%s]\n", command));
+       ret = smbrun(command, &fd);
+       DEBUGADD(10, ("returned [%d]\n", ret));
 
-WERROR _eventlog_get_num_records(pipes_struct *p,
-                                EVENTLOG_Q_GET_NUM_RECORDS *q_u,
-                                EVENTLOG_R_GET_NUM_RECORDS *r_u)
-{
-    Eventlog_info *info = NULL;
-    POLICY_HND *handle = NULL;
+       if(ret != 0) {
+               if(fd != -1) {
+                       close(fd);
+               }
+               return False;
+       }
 
-    if(!q_u || !r_u)
-       return WERR_NOMEM;
+       qlines = fd_lines_load(fd, &numlines);
+       DEBUGADD(10, ("Lines returned = [%d]\n", numlines));
+       close(fd);
 
-    handle = &(q_u->handle);
-    info = find_eventlog_info_by_hnd(p, handle);
+       if(numlines) {
+               DEBUGADD(10, ("Line[0] = [%s]\n", qlines[0]));
+               sscanf(qlines[0], "%d", &(info->num_records));
+               file_lines_free(qlines);
+               return True;
+       }
 
-    if(!(_eventlog_get_num_records_hook(info)))
-       return WERR_BADFILE;
+       file_lines_free(qlines);
+       return False;
+}
 
-    r_u->num_records = info->num_records;
+/********************************************************************
+********************************************************************/
 
-    return WERR_OK;
-}
 /**
  * Callout to find the oldest record in the log
  * 
@@ -269,75 +288,51 @@ WERROR _eventlog_get_num_records(pipes_struct *p,
  *             oldest entry. Must be 1 or greater.
  *             If there are no entries in the log, returns a 0
  */
-static BOOL _eventlog_get_oldest_entry_hook(Eventlog_info *info)
-{
-    char *cmd = lp_eventlog_oldest_record_cmd();
-    char **qlines;
-    pstring command;
-    int numlines = 0;
-    int ret;
-    int fd = -1;
-
-    if(cmd == NULL || strlen(cmd) == 0)
-    {
-       DEBUG(0, ("Must define an \"eventlog oldest record command\" entry in the config.\n"));
-       return False;
-    }
-
-    memset(command, 0, sizeof(command));
-    slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\"", 
-            cmd,
-            info->source_log_file_name,
-            info->handle_string);
-
-    DEBUG(10, ("Running [%s]\n", command));
-    ret = smbrun(command, &fd);
-    DEBUGADD(10, ("returned [%d]\n", ret));
-
-    if(ret != 0)
-    {
-       if(fd != -1)
-           close(fd);
-       return False;
-    }
 
-    qlines = fd_lines_load(fd, &numlines);
-    DEBUGADD(10, ("Lines returned = [%d]\n", numlines));
-    close(fd);
-
-    if(numlines)
-    {
-       DEBUGADD(10, ("Line[0] = [%s]\n", qlines[0]));
-       sscanf(qlines[0], "%d", &(info->oldest_entry));
-       file_lines_free(qlines);
-       return True;
-    }
-
-    file_lines_free(qlines);
-    return False;
-}
-
-WERROR _eventlog_get_oldest_entry(pipes_struct *p,
-                                 EVENTLOG_Q_GET_OLDEST_ENTRY *q_u,
-                                 EVENTLOG_R_GET_OLDEST_ENTRY *r_u)
+static BOOL get_oldest_entry_hook(EventlogInfo *info)
 {
-    Eventlog_info *info = NULL;
-    POLICY_HND *handle = NULL;
+       char *cmd = lp_eventlog_oldest_record_cmd();
+       char **qlines;
+       pstring command;
+       int numlines = 0;
+       int ret;
+       int fd = -1;
+
+       if ( !cmd || !*cmd ) {
+               DEBUG(0, ("Must define an \"eventlog oldest record command\" entry in the config.\n"));
+               return False;
+       }
+
+       pstr_sprintf( command, "%s \"%s\"", cmd, info->logname );
 
-    if(!q_u || !r_u)
-       return WERR_NOMEM;
+       DEBUG(10, ("Running [%s]\n", command));
+       ret = smbrun(command, &fd);
+       DEBUGADD(10, ("returned [%d]\n", ret));
 
-    handle = &(q_u->handle);
-    info = find_eventlog_info_by_hnd(p, handle);
+       if(ret != 0) {
+               if(fd != -1) {
+                       close(fd);
+               }
+               return False;
+       }
 
-    if(!(_eventlog_get_oldest_entry_hook(info)))
-       return WERR_BADFILE;
+       qlines = fd_lines_load(fd, &numlines);
+       DEBUGADD(10, ("Lines returned = [%d]\n", numlines));
+       close(fd);
 
-    r_u->oldest_entry = info->oldest_entry;
+       if(numlines) {
+               DEBUGADD(10, ("Line[0] = [%s]\n", qlines[0]));
+               sscanf(qlines[0], "%d", &(info->oldest_entry));
+               file_lines_free(qlines);
+               return True;
+       }
 
-    return WERR_OK;
+       file_lines_free(qlines);
+       return False;
 }
 
+/********************************************************************
+********************************************************************/
 /**
  * Callout to close the specified event log
  * 
@@ -346,270 +341,206 @@ WERROR _eventlog_get_oldest_entry(pipes_struct *p,
  *     OUTPUT: the string "SUCCESS" if the command succeeded
  *             no such string if there was a failure.
  */
-static BOOL _eventlog_close_eventlog_hook(Eventlog_info *info)
+
+static BOOL close_eventlog_hook(EventlogInfo *info)
 {
-    char *cmd = lp_eventlog_close_cmd();
-    char **qlines;
-    pstring command;
-    int numlines = 0;
-    int ret;
-    int fd = -1;
-
-    if(cmd == NULL || strlen(cmd) == 0)
-    {
-       DEBUG(0, ("Must define an \"eventlog close command\" entry in the config.\n"));
-       return False;
-    }
-
-    memset(command, 0, sizeof(command));
-    slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\"", 
-            cmd, 
-            info->source_log_file_name, 
-            info->handle_string);
-
-    DEBUG(10, ("Running [%s]\n", command));
-    ret = smbrun(command, &fd);
-    DEBUGADD(10, ("returned [%d]\n", ret));
-
-    if(ret != 0)
-    {
-       if(fd != -1)
-           close(fd);
-       return False;
-    }
+       char *cmd = lp_eventlog_close_cmd();
+       char **qlines;
+       pstring command;
+       int numlines = 0;
+       int ret;
+       int fd = -1;
+
+       if ( !cmd || !*cmd ) {
+               DEBUG(0, ("Must define an \"eventlog close command\" entry in the config.\n"));
+               return False;
+       }
 
-    qlines = fd_lines_load(fd, &numlines);
-    DEBUGADD(10, ("Lines returned = [%d]\n", numlines));
-    close(fd);
+       pstr_sprintf( command, "%s \"%s\"", cmd, info->logname );
 
-    if(numlines)
-    {
-       DEBUGADD(10, ("Line[0] = [%s]\n", qlines[0]));
-       if(0 == strncmp(qlines[0], "SUCCESS", strlen("SUCCESS")))
-       {
-           DEBUGADD(10, ("Able to close [%s].\n", info->source_log_file_name));
-           file_lines_free(qlines);
-           return True;
-       }
-    }
+       DEBUG(10, ("Running [%s]\n", command));
+       ret = smbrun(command, &fd);
+       DEBUGADD(10, ("returned [%d]\n", ret));
 
-    file_lines_free(qlines);
-    return False;
-}
+       if(ret != 0) {
+               if(fd != -1) {
+                       close(fd);
+               }
+               return False;
+       }
 
-WERROR _eventlog_close_eventlog(pipes_struct *p,
-                               EVENTLOG_Q_CLOSE_EVENTLOG *q_u,
-                               EVENTLOG_R_CLOSE_EVENTLOG *r_u)
-{
-    Eventlog_info *info = NULL;
-    POLICY_HND *handle;
+       qlines = fd_lines_load(fd, &numlines);
+       DEBUGADD(10, ("Lines returned = [%d]\n", numlines));
+       close(fd);
 
-    if(!q_u || !r_u)
-       return WERR_NOMEM;
+       if(numlines) {
+               DEBUGADD(10, ("Line[0] = [%s]\n", qlines[0]));
+               if(0 == strncmp(qlines[0], "SUCCESS", 7)) {
+                       DEBUGADD(10, ("Able to close [%s].\n", info->logname));
+                       file_lines_free(qlines);
+                       return True;
+               }
+       }
 
-    handle = &(q_u->handle);
-    
-    info = find_eventlog_info_by_hnd(p, handle);
-    if(!(_eventlog_close_eventlog_hook(info)))
-       return WERR_BADFILE;
-
-    if(!(close_policy_hnd(p, handle)))
-    {
-       /* WERR_NOMEM is probably not the correct error, but until I figure out a better
-          one it will have to do */
-       return WERR_NOMEM;
-    }
-
-    return WERR_OK;
+       file_lines_free(qlines);
+       return False;
 }
 
-static BOOL _eventlog_read_parse_line(char *line, Eventlog_entry *entry, BOOL *eor)
+/********************************************************************
+********************************************************************/
+
+static BOOL parse_logentry(char *line, Eventlog_entry *entry, BOOL *eor)
 {
-    char *start = NULL, *stop = NULL;
-    pstring temp;
-    int temp_len = 0, i;
+       char *start = NULL, *stop = NULL;
+       pstring temp;
+       int temp_len = 0, i;
  
-    start = line;
+       start = line;
 
-    /* empty line signyfiying record delimeter, or we're at the end of the buffer */
-    if(start == NULL || strlen(start) == 0)
-    {
-       DEBUG(6, ("_eventlog_read_parse_line: found end-of-record indicator.\n"));
-       *eor = True;
-       return True;
-    }
-    if(!(stop = strchr(line, ':')))
-       return False;
+       /* empty line signyfiying record delimeter, or we're at the end of the buffer */
+       if(start == NULL || strlen(start) == 0) {
+               DEBUG(6, ("parse_logentry: found end-of-record indicator.\n"));
+               *eor = True;
+               return True;
+       }
+       if(!(stop = strchr(line, ':'))) {
+               return False;
+       }
     
-    DEBUG(6, ("_eventlog_read_parse_line: trying to parse [%s].\n", line));
-
-    if(0 == strncmp(start, "LEN", stop - start))
-    {
-       /* This will get recomputed later anyway -- probably not necessary */
-       entry->record.length = atoi(stop + 1);
-    }
-    else if(0 == strncmp(start, "RS1", stop - start))
-    {
-       /* For now all these reserved entries seem to have the same value,
-          which can be hardcoded to int(1699505740) for now */
-       entry->record.reserved1 = atoi(stop + 1);
-    }
-    else if(0 == strncmp(start, "RCN", stop - start))
-    {
-       entry->record.record_number = atoi(stop + 1);
-    }
-    else if(0 == strncmp(start, "TMG", stop - start))
-    {
-       entry->record.time_generated = atoi(stop + 1);
-    }
-    else if(0 == strncmp(start, "TMW", stop - start))
-    {
-       entry->record.time_written = atoi(stop + 1);
-    }
-    else if(0 == strncmp(start, "EID", stop - start))
-    {
-       entry->record.event_id = atoi(stop + 1);
-    }
-    else if(0 == strncmp(start, "ETP", stop - start))
-    {
-       if(strstr(start, "ERROR"))
-       {
-           entry->record.event_type = EVENTLOG_ERROR_TYPE;
-       }
-       else if(strstr(start, "WARNING"))
-       {
-           entry->record.event_type = EVENTLOG_WARNING_TYPE;
-       }
-       else if(strstr(start, "INFO"))
-       {
-           entry->record.event_type = EVENTLOG_INFORMATION_TYPE;
-       }
-       else if(strstr(start, "AUDIT_SUCCESS"))
-       {
-           entry->record.event_type = EVENTLOG_AUDIT_SUCCESS;
-       }
-       else if(strstr(start, "AUDIT_FAILURE"))
-       {
-           entry->record.event_type = EVENTLOG_AUDIT_FAILURE;
-       }
-       else if(strstr(start, "SUCCESS"))
-       {
-           entry->record.event_type = EVENTLOG_SUCCESS;
-       }
-       else
-       {
-           /* some other eventlog type -- currently not defined in MSDN docs, so error out */
-           return False;
-       }
-    }
+       DEBUG(6, ("parse_logentry: trying to parse [%s].\n", line));
+
+       if(0 == strncmp(start, "LEN", stop - start)) {
+               /* This will get recomputed later anyway -- probably not necessary */
+               entry->record.length = atoi(stop + 1);
+       } else if(0 == strncmp(start, "RS1", stop - start)) {
+               /* For now all these reserved entries seem to have the same value,
+                  which can be hardcoded to int(1699505740) for now */
+               entry->record.reserved1 = atoi(stop + 1);
+       } else if(0 == strncmp(start, "RCN", stop - start)) {
+               entry->record.record_number = atoi(stop + 1);
+       } else if(0 == strncmp(start, "TMG", stop - start)) {
+               entry->record.time_generated = atoi(stop + 1);
+       } else if(0 == strncmp(start, "TMW", stop - start)) {
+               entry->record.time_written = atoi(stop + 1);
+       } else if(0 == strncmp(start, "EID", stop - start)) {
+               entry->record.event_id = atoi(stop + 1);
+       } else if(0 == strncmp(start, "ETP", stop - start)) {
+               if(strstr(start, "ERROR")) {
+                       entry->record.event_type = EVENTLOG_ERROR_TYPE;
+               } else if(strstr(start, "WARNING")) {
+                       entry->record.event_type = EVENTLOG_WARNING_TYPE;
+               } else if(strstr(start, "INFO")) {
+                       entry->record.event_type = EVENTLOG_INFORMATION_TYPE;
+               } else if(strstr(start, "AUDIT_SUCCESS")) {
+                       entry->record.event_type = EVENTLOG_AUDIT_SUCCESS;
+               } else if(strstr(start, "AUDIT_FAILURE")) {
+                       entry->record.event_type = EVENTLOG_AUDIT_FAILURE;
+               } else if(strstr(start, "SUCCESS")) {
+                       entry->record.event_type = EVENTLOG_SUCCESS;
+               } else {
+                       /* some other eventlog type -- currently not defined in MSDN docs, so error out */
+                       return False;
+               }
+       }
 /*
-    else if(0 == strncmp(start, "NST", stop - start))
-    {
-       entry->record.num_strings = atoi(stop + 1);
-    }
+  else if(0 == strncmp(start, "NST", stop - start))
+  {
+  entry->record.num_strings = atoi(stop + 1);
+  }
 */
-    else if(0 == strncmp(start, "ECT", stop - start))
-    {
-       entry->record.event_category = atoi(stop + 1);
-    }
-    else if(0 == strncmp(start, "RS2", stop - start))
-    {
-       entry->record.reserved2 = atoi(stop + 1);
-    }
-    else if(0 == strncmp(start, "CRN", stop - start))
-    {
-       entry->record.closing_record_number = atoi(stop + 1);
-    }
-    else if(0 == strncmp(start, "USL", stop - start))
-    {
-       entry->record.user_sid_length = atoi(stop + 1);
-    }
-    else if(0 == strncmp(start, "SRC", stop - start))
-    {
-       memset(temp, 0, sizeof(temp));
-       stop++;
-       while(isspace(stop[0]))
-           stop++;
-       temp_len = strlen(stop);
-       strncpy(temp, stop, temp_len);
-       rpcstr_push((void *)(entry->data_record.source_name), temp, 
-                   sizeof(entry->data_record.source_name), STR_TERMINATE);
-       entry->data_record.source_name_len = (strlen_w(entry->data_record.source_name)* 2) + 2;
-    }
-    else if(0 == strncmp(start, "SRN", stop - start))
-    {
-       memset(temp, 0, sizeof(temp));
-       stop++;
-       while(isspace(stop[0]))
-           stop++;
-       temp_len = strlen(stop);
-       strncpy(temp, stop, temp_len);
-       rpcstr_push((void *)(entry->data_record.computer_name), temp,
-                   sizeof(entry->data_record.computer_name), STR_TERMINATE);
-       entry->data_record.computer_name_len = (strlen_w(entry->data_record.computer_name)* 2) + 2;
-    }
-    else if(0 == strncmp(start, "SID", stop - start))
-    {
-       memset(temp, 0, sizeof(temp));
-       stop++;
-       while(isspace(stop[0]))
-           stop++;
-       temp_len = strlen(stop);
-       strncpy(temp, stop, temp_len);
-       rpcstr_push((void *)(entry->data_record.sid), temp,
-                   sizeof(entry->data_record.sid), STR_TERMINATE);
-       entry->record.user_sid_length = (strlen_w(entry->data_record.sid) * 2) + 2;
-    }
-    else if(0 == strncmp(start, "STR", stop - start))
-    {
-       /* skip past initial ":" */
-       stop++;
-       /* now skip any other leading whitespace */
-       while(isspace(stop[0]))
-           stop++;
-       temp_len = strlen(stop);
-       memset(temp, 0, sizeof(temp));
-       strncpy(temp, stop, temp_len);
-       rpcstr_push((void *)(entry->data_record.strings + entry->data_record.strings_len),
-                   temp,
-                   sizeof(entry->data_record.strings) - entry->data_record.strings_len, 
-                   STR_TERMINATE);
-       entry->data_record.strings_len += temp_len + 1;
-       fprintf(stderr, "Dumping strings:\n");
-       for(i = 0; i < entry->data_record.strings_len; i++)
-       {
-           fputc((char)entry->data_record.strings[i], stderr);
-       }
-       fprintf(stderr, "\nDone\n");
-       entry->record.num_strings++;
-    }
-    else if(0 == strncmp(start, "DAT", stop - start))
-    {
-       /* Now that we're done processing the STR data, adjust the length to account for
-          unicode, then proceed with the DAT data. */
-       entry->data_record.strings_len *= 2;
-       /* skip past initial ":" */
-       stop++;
-       /* now skip any other leading whitespace */
-       while(isspace(stop[0]))
-           stop++;
-       memset(temp, 0, sizeof(temp));
-       temp_len = strlen(stop);
-       strncpy(temp, stop, temp_len);
-       rpcstr_push((void *)(entry->data_record.user_data), temp,
-                   sizeof(entry->data_record.user_data), STR_TERMINATE);
-       entry->data_record.user_data_len = (strlen_w((const smb_ucs2_t *)entry->data_record.user_data) * 2) + 2;
-    }
-    else
-    {
-       /* some other eventlog entry -- not implemented, so dropping on the floor */
-       DEBUG(10, ("Unknown entry [%s]. Ignoring.\n", line));
-       /* For now return true so that we can keep on parsing this mess. Eventually
-          we will return False here. */
+       else if(0 == strncmp(start, "ECT", stop - start)) {
+               entry->record.event_category = atoi(stop + 1);
+       } else if(0 == strncmp(start, "RS2", stop - start)) {
+               entry->record.reserved2 = atoi(stop + 1);
+       } else if(0 == strncmp(start, "CRN", stop - start)) {
+               entry->record.closing_record_number = atoi(stop + 1);
+       } else if(0 == strncmp(start, "USL", stop - start)) {
+               entry->record.user_sid_length = atoi(stop + 1);
+       } else if(0 == strncmp(start, "SRC", stop - start)) {
+               memset(temp, 0, sizeof(temp));
+               stop++;
+               while(isspace(stop[0])) {
+                       stop++;
+               }
+               temp_len = strlen(stop);
+               strncpy(temp, stop, temp_len);
+               rpcstr_push((void *)(entry->data_record.source_name), temp, 
+                           sizeof(entry->data_record.source_name), STR_TERMINATE);
+               entry->data_record.source_name_len = (strlen_w(entry->data_record.source_name)* 2) + 2;
+       } else if(0 == strncmp(start, "SRN", stop - start)) {
+               memset(temp, 0, sizeof(temp));
+               stop++;
+               while(isspace(stop[0])) {
+                       stop++; 
+               }
+               temp_len = strlen(stop);
+               strncpy(temp, stop, temp_len);
+               rpcstr_push((void *)(entry->data_record.computer_name), temp,
+                           sizeof(entry->data_record.computer_name), STR_TERMINATE);
+               entry->data_record.computer_name_len = (strlen_w(entry->data_record.computer_name)* 2) + 2;
+       } else if(0 == strncmp(start, "SID", stop - start)) {
+               memset(temp, 0, sizeof(temp));
+               stop++;
+               while(isspace(stop[0])) {
+                       stop++;
+               }
+               temp_len = strlen(stop);
+               strncpy(temp, stop, temp_len);
+               rpcstr_push((void *)(entry->data_record.sid), temp,
+                           sizeof(entry->data_record.sid), STR_TERMINATE);
+               entry->record.user_sid_length = (strlen_w(entry->data_record.sid) * 2) + 2;
+       } else if(0 == strncmp(start, "STR", stop - start)) {
+               /* skip past initial ":" */
+               stop++;
+               /* now skip any other leading whitespace */
+               while(isspace(stop[0])) {
+                       stop++;
+               }
+               temp_len = strlen(stop);
+               memset(temp, 0, sizeof(temp));
+               strncpy(temp, stop, temp_len);
+               rpcstr_push((void *)(entry->data_record.strings + entry->data_record.strings_len),
+                           temp,
+                           sizeof(entry->data_record.strings) - entry->data_record.strings_len, 
+                           STR_TERMINATE);
+               entry->data_record.strings_len += temp_len + 1;
+               fprintf(stderr, "Dumping strings:\n");
+               for(i = 0; i < entry->data_record.strings_len; i++) {
+                       fputc((char)entry->data_record.strings[i], stderr);
+               }
+               fprintf(stderr, "\nDone\n");
+               entry->record.num_strings++;
+       } else if(0 == strncmp(start, "DAT", stop - start)) {
+               /* Now that we're done processing the STR data, adjust the length to account for
+                  unicode, then proceed with the DAT data. */
+               entry->data_record.strings_len *= 2;
+               /* skip past initial ":" */
+               stop++;
+               /* now skip any other leading whitespace */
+               while(isspace(stop[0])) {
+                       stop++;
+               }
+               entry->data_record.user_data_len = strlen(stop);
+               memset(entry->data_record.user_data, 0, sizeof(entry->data_record.user_data));
+               if(entry->data_record.user_data_len > 0) {
+                       /* copy no more than the first 1024 bytes */
+                       if(entry->data_record.user_data_len > sizeof(entry->data_record.user_data))
+                               entry->data_record.user_data_len = sizeof(entry->data_record.user_data);
+                       memcpy(entry->data_record.user_data, stop, entry->data_record.user_data_len);
+               }
+       } else {
+               /* some other eventlog entry -- not implemented, so dropping on the floor */
+               DEBUG(10, ("Unknown entry [%s]. Ignoring.\n", line));
+               /* For now return true so that we can keep on parsing this mess. Eventually
+                  we will return False here. */
+               return True;
+       }
        return True;
-    }
-    return True;
 }
+
+/********************************************************************
+********************************************************************/
+
 /**
  * Callout to read entries from the specified event log
  *
@@ -640,254 +571,162 @@ static BOOL _eventlog_read_parse_line(char *line, Eventlog_entry *entry, BOOL *e
  *               DAT:[(uint8)] - The user-defined data portion of the event log. Can not be multiple lines.
  *               <empty line>  - end-of-record indicator 
  */
-static BOOL _eventlog_read_eventlog_hook(Eventlog_info *info,
-                                        Eventlog_entry *entry, 
-                                        const char *direction, 
-                                        int starting_record, 
-                                        int buffer_size, 
-                                        BOOL *eof,
-                                        char ***buffer,
-                                        int *numlines)
+
+static BOOL read_eventlog_hook(EventlogInfo *info, Eventlog_entry *entry, 
+                                        const char *direction, int starting_record, 
+                                        int buffer_size, BOOL *eof,
+                                        char ***buffer, int *numlines)
 {
-    char *cmd = lp_eventlog_read_cmd();
-    pstring command;
-    int ret;
-    int fd = -1;
+       char *cmd = lp_eventlog_read_cmd();
+       pstring command;
+       int ret;
+       int fd = -1;
 
-    if(info == NULL)
-       return False;
+       if ( !info )
+               return False;
 
-    if(cmd == NULL || strlen(cmd) == 0)
-    {
-       DEBUG(0, ("Must define an \"eventlog read command\" entry in the config.\n"));
-       return False;
-    }
-
-    slprintf(command, sizeof(command)-1, "%s \"%s\" %s %d %d \"%s\"",
-            cmd,
-            info->source_log_file_name,
-            direction,
-            starting_record,
-            buffer_size,
-            info->handle_string);
-
-    *numlines = 0;
-
-    DEBUG(10, ("Running [%s]\n", command));
-    ret = smbrun(command, &fd);
-    DEBUGADD(10, ("returned [%d]\n", ret));
-
-    if(ret != 0)
-    {
-       if(fd != -1)
-           close(fd);
-       return False;
-    }
+       if ( !cmd || !*cmd ) {
+               DEBUG(0, ("Must define an \"eventlog read command\" entry in the config.\n"));
+               return False;
+       }
 
-    *buffer = fd_lines_load(fd, numlines);
-    DEBUGADD(10, ("Lines returned = [%d]\n", *numlines));
-    close(fd);
+       pstr_sprintf( command, "%s \"%s\" %s %d %d",
+                cmd, info->logname, direction, starting_record, buffer_size );
+
+       *numlines = 0;
+
+       DEBUG(10, ("Running [%s]\n", command));
+       ret = smbrun(command, &fd);
+       DEBUGADD(10, ("returned [%d]\n", ret));
+
+       if(ret != 0) {
+               if(fd != -1) {
+                       close(fd);
+               }
+               return False;
+       }
+
+       *buffer = fd_lines_load(fd, numlines);
+       DEBUGADD(10, ("Lines returned = [%d]\n", *numlines));
+       close(fd);
     
-    if(*numlines)
-    {
-       /*
-       for(i = 0; i < numlines; i++)
-       {
-           DEBUGADD(10, ("Line[%d] = %s\n", i, qlines[i]));
-           _eventlog_read_parse_line(qlines[i], entry);
+       if(*numlines) {
+               /*
+                 for(i = 0; i < numlines; i++)
+                 {
+                 DEBUGADD(10, ("Line[%d] = %s\n", i, qlines[i]));
+                 parse_logentry(qlines[i], entry);
+                 }
+                 file_lines_free(qlines);
+               */
+               *eof = False;
+               return True;
        }
-       file_lines_free(qlines);
-       */
-       *eof = False;
-       return True;
-    }
-    *eof = True;
+       *eof = True;
 
 /*    file_lines_free(qlines);*/
-    return False;
+       return False;
 }
-       
-static Eventlog_entry *_eventlog_read_package_entry(prs_struct *ps,
+
+/********************************************************************
+********************************************************************/
+
+static Eventlog_entry *read_package_entry(prs_struct *ps,
                                                    EVENTLOG_Q_READ_EVENTLOG *q_u,
                                                    EVENTLOG_R_READ_EVENTLOG *r_u,
                                                    Eventlog_entry *entry)
 {
-    uint8 *offset;
-    Eventlog_entry *ee_new = NULL;
-
-    ee_new = PRS_ALLOC_MEM(ps, Eventlog_entry, 1);
-    if(ee_new == NULL)
-       return NULL;
-
-    entry->data_record.sid_padding = ((4 - ((entry->data_record.source_name_len 
-                                     + entry->data_record.computer_name_len) % 4)) %4);
-    entry->data_record.data_padding = (4 - ((entry->data_record.strings_len 
-                                          + entry->data_record.user_data_len) % 4)) % 4;
-    entry->record.length = sizeof(Eventlog_record);
-    entry->record.length += entry->data_record.source_name_len;
-    entry->record.length += entry->data_record.computer_name_len;
-    if(entry->record.user_sid_length == 0)
-    {
-       /* Should not pad to a DWORD boundary for writing out the sid if there is
-          no SID, so just propagate the padding to pad the data */
-       entry->data_record.data_padding += entry->data_record.sid_padding;
-       entry->data_record.sid_padding = 0;
-    }
-    DEBUG(10, ("sid_padding is [%d].\n", entry->data_record.sid_padding));
-    DEBUG(10, ("data_padding is [%d].\n", entry->data_record.data_padding));
-
-    entry->record.length += entry->data_record.sid_padding;
-    entry->record.length += entry->record.user_sid_length;
-    entry->record.length += entry->data_record.strings_len;
-    entry->record.length += entry->data_record.user_data_len;
-    entry->record.length += entry->data_record.data_padding;
-    /* need another copy of length at the end of the data */
-    entry->record.length += sizeof(entry->record.length);
-    DEBUG(10, ("entry->record.length is [%d].\n", entry->record.length));
-    entry->data = PRS_ALLOC_MEM(ps, uint8, entry->record.length - sizeof(Eventlog_record) - sizeof(entry->record.length));
-    if(entry->data == NULL)
-       return NULL;
-    offset = entry->data;
-    memcpy(offset, &(entry->data_record.source_name), entry->data_record.source_name_len);
-    offset += entry->data_record.source_name_len;
-    memcpy(offset, &(entry->data_record.computer_name), entry->data_record.computer_name_len);
-    offset += entry->data_record.computer_name_len;
-    /* SID needs to be DWORD-aligned */
-    offset += entry->data_record.sid_padding;
-    entry->record.user_sid_offset = sizeof(Eventlog_record) + (offset - entry->data);
-    memcpy(offset, &(entry->data_record.sid), entry->record.user_sid_length);
-    offset += entry->record.user_sid_length;
-    /* Now do the strings */
-    entry->record.string_offset = sizeof(Eventlog_record) + (offset - entry->data);
-    memcpy(offset, &(entry->data_record.strings), entry->data_record.strings_len);
-    offset += entry->data_record.strings_len;
-    /* Now do the data */
-    entry->record.data_length = entry->data_record.user_data_len;
-    entry->record.data_offset = sizeof(Eventlog_record) + (offset - entry->data);
-    memcpy(offset, &(entry->data_record.user_data), entry->data_record.user_data_len);
-    offset += entry->data_record.user_data_len;
-
-    memcpy(&(ee_new->record), &entry->record, sizeof(Eventlog_record));
-    memcpy(&(ee_new->data_record), &entry->data_record, sizeof(Eventlog_data_record));
-    ee_new->data = entry->data;
-
-    return ee_new;
-}
+       uint8 *offset;
+       Eventlog_entry *ee_new = NULL;
 
-static BOOL _eventlog_add_record_to_resp(EVENTLOG_R_READ_EVENTLOG *r_u, Eventlog_entry *ee_new)
-{
-    Eventlog_entry *insert_point;
-
-    insert_point=r_u->entry;
-
-    if (NULL == insert_point) 
-    {
-       r_u->entry = ee_new;
-       ee_new->next = NULL;
-    } 
-    else
-    {
-       while ((NULL != insert_point->next)) 
-       {
-           insert_point=insert_point->next;
-       }
-       ee_new->next = NULL;
-       insert_point->next = ee_new;
-    }
-    r_u->num_records++; 
-    r_u->num_bytes_in_resp += ee_new->record.length;
-
-    return True;
+       ee_new = PRS_ALLOC_MEM(ps, Eventlog_entry, 1);
+       if(ee_new == NULL) {
+               return NULL;
+       }
+
+       entry->data_record.sid_padding = ((4 - ((entry->data_record.source_name_len 
+                                                + entry->data_record.computer_name_len) % 4)) %4);
+       entry->data_record.data_padding = (4 - ((entry->data_record.strings_len 
+                                                + entry->data_record.user_data_len) % 4)) % 4;
+       entry->record.length = sizeof(Eventlog_record);
+       entry->record.length += entry->data_record.source_name_len;
+       entry->record.length += entry->data_record.computer_name_len;
+       if(entry->record.user_sid_length == 0) {
+               /* Should not pad to a DWORD boundary for writing out the sid if there is
+                  no SID, so just propagate the padding to pad the data */
+               entry->data_record.data_padding += entry->data_record.sid_padding;
+               entry->data_record.sid_padding = 0;
+       }
+       DEBUG(10, ("sid_padding is [%d].\n", entry->data_record.sid_padding));
+       DEBUG(10, ("data_padding is [%d].\n", entry->data_record.data_padding));
+
+       entry->record.length += entry->data_record.sid_padding;
+       entry->record.length += entry->record.user_sid_length;
+       entry->record.length += entry->data_record.strings_len;
+       entry->record.length += entry->data_record.user_data_len;
+       entry->record.length += entry->data_record.data_padding;
+       /* need another copy of length at the end of the data */
+       entry->record.length += sizeof(entry->record.length);
+       DEBUG(10, ("entry->record.length is [%d].\n", entry->record.length));
+       entry->data = PRS_ALLOC_MEM(ps, uint8, entry->record.length - sizeof(Eventlog_record) - sizeof(entry->record.length));
+       if(entry->data == NULL) {
+               return NULL;
+       }
+       offset = entry->data;
+       memcpy(offset, &(entry->data_record.source_name), entry->data_record.source_name_len);
+       offset += entry->data_record.source_name_len;
+       memcpy(offset, &(entry->data_record.computer_name), entry->data_record.computer_name_len);
+       offset += entry->data_record.computer_name_len;
+       /* SID needs to be DWORD-aligned */
+       offset += entry->data_record.sid_padding;
+       entry->record.user_sid_offset = sizeof(Eventlog_record) + (offset - entry->data);
+       memcpy(offset, &(entry->data_record.sid), entry->record.user_sid_length);
+       offset += entry->record.user_sid_length;
+       /* Now do the strings */
+       entry->record.string_offset = sizeof(Eventlog_record) + (offset - entry->data);
+       memcpy(offset, &(entry->data_record.strings), entry->data_record.strings_len);
+       offset += entry->data_record.strings_len;
+       /* Now do the data */
+       entry->record.data_length = entry->data_record.user_data_len;
+       entry->record.data_offset = sizeof(Eventlog_record) + (offset - entry->data);
+       memcpy(offset, &(entry->data_record.user_data), entry->data_record.user_data_len);
+       offset += entry->data_record.user_data_len;
+
+       memcpy(&(ee_new->record), &entry->record, sizeof(Eventlog_record));
+       memcpy(&(ee_new->data_record), &entry->data_record, sizeof(Eventlog_data_record));
+       ee_new->data = entry->data;
+
+       return ee_new;
 }
-    
-WERROR _eventlog_read_eventlog(pipes_struct *p,
-                              EVENTLOG_Q_READ_EVENTLOG *q_u,
-                              EVENTLOG_R_READ_EVENTLOG *r_u)
+
+/********************************************************************
+********************************************************************/
+
+static BOOL add_record_to_resp(EVENTLOG_R_READ_EVENTLOG *r_u, Eventlog_entry *ee_new)
 {
-    Eventlog_info *info = NULL;
-    POLICY_HND *handle;
-    Eventlog_entry entry, *ee_new;
-    BOOL eof = False, eor = False;
-    const char *direction = "";
-    uint32 num_records_read = 0;
-    prs_struct *ps;
-    int numlines, i;
-    char **buffer;
-
-    if(!q_u || !r_u)
-       return WERR_NOMEM;
-
-    handle = &(q_u->handle);
-    info = find_eventlog_info_by_hnd(p, handle);
-    info->flags = q_u->flags;
-    ps = &p->out_data.rdata;
-    /* if this is the first time we're reading on this handle */
-    if(info->active_entry == 0)
-    {
-       /* Rather than checking the EVENTLOG_SEQUENTIAL_READ/EVENTLOG_SEEK_READ flags,
-          we'll just go to the offset specified in the request, or the oldest entry
-          if no offset is specified */
-       if(q_u->offset > 0)
-           info->active_entry = q_u->offset;
-       else
-           info->active_entry = info->oldest_entry;
-       
-    }
-    
-    if(q_u->flags & EVENTLOG_FORWARDS_READ)
-       direction = "forward";
-    else if(q_u->flags & EVENTLOG_BACKWARDS_READ)
-       direction = "backward";
-
-    if(!(_eventlog_read_eventlog_hook(info, &entry, direction, info->active_entry, q_u->max_read_size, &eof, &buffer, &numlines)))
-    {
-       if(eof == False)
-           return WERR_NOMEM;
-    }
-    if(numlines > 0)
-    {
-       ZERO_STRUCT(entry);
-       for(i = 0; i < numlines; i++)
-       {
-           num_records_read = r_u->num_records;
-           DEBUGADD(10, ("Line[%d] = [%s]\n", i, buffer[i]));
-           _eventlog_read_parse_line(buffer[i], &entry, &eor);
-           if(eor == True)
-           {
-               /* package ee_new entry */
-               if((ee_new = _eventlog_read_package_entry(ps, q_u, r_u, &entry)) == NULL)
-               {
-                   free(buffer);
-                   return WERR_NOMEM;
-               }
-               /* Now see if there is enough room to add */
-               if(r_u->num_bytes_in_resp + ee_new->record.length > q_u->max_read_size)
-               {
-                   r_u->bytes_in_next_record = ee_new->record.length;
-                   /* response would be too big to fit in client-size buffer */
-                   break;
+       Eventlog_entry *insert_point;
+
+       insert_point=r_u->entry;
+
+       if (NULL == insert_point) {
+               r_u->entry = ee_new;
+               ee_new->next = NULL;
+       } else {
+               while ((NULL != insert_point->next)) {
+                       insert_point=insert_point->next;
                }
-               _eventlog_add_record_to_resp(r_u, ee_new);
-               ZERO_STRUCT(entry);
-               eor=False;
-               num_records_read = r_u->num_records - num_records_read;
-               DEBUG(10, ("_eventlog_read_eventlog: read [%d] records for a total of [%d] records using [%d] bytes out of a max of [%d].\n",
-                          num_records_read,
-                          r_u->num_records,
-                          r_u->num_bytes_in_resp,
-                          q_u->max_read_size));
-               /* update the active record */
-               if(info->flags & EVENTLOG_FORWARDS_READ)
-                   info->active_entry += num_records_read;
-               else if(info->flags & EVENTLOG_BACKWARDS_READ)
-                   info->active_entry -= num_records_read;
-           }
-       }
-       free(buffer);
-    }
-
-    return WERR_OK;
+               ee_new->next = NULL;
+               insert_point->next = ee_new;
+       }
+       r_u->num_records++; 
+       r_u->num_bytes_in_resp += ee_new->record.length;
+
+       return True;
 }
+
+/********************************************************************
+********************************************************************/
+
 /**
  * Callout to clear (and optionally backup) a specified event log
  *
@@ -902,96 +741,224 @@ WERROR _eventlog_read_eventlog(pipes_struct *p,
  *             The given log is copied to that location on the server. See comments for
  *               eventlog_io_q_clear_eventlog for info about odd file name behavior
  */
-static BOOL _eventlog_clear_eventlog_hook(Eventlog_info *info,
-                                         pstring backup_file_name)
+
+static BOOL clear_eventlog_hook(EventlogInfo *info, pstring backup_file_name)
 {
-    char *cmd = lp_eventlog_clear_cmd();
-    char **qlines;
-    pstring command;
-    int numlines = 0;
-    int ret;
-    int fd = -1;
-
-    if(cmd == NULL || strlen(cmd) == 0)
-    {
-       DEBUG(0, ("Must define an \"eventlog clear command\" entry in the config.\n"));
-       return False;
-    }
-
-    memset(command, 0, sizeof(command));
-    if(strlen(backup_file_name) > 0)
-       slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\"",
-                cmd,
-                info->source_log_file_name,
-                backup_file_name,
-                info->handle_string);
-    else
-       slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\"", 
-                cmd, 
-                info->source_log_file_name, 
-                info->handle_string);
-
-    DEBUG(10, ("Running [%s]\n", command));
-    ret = smbrun(command, &fd);
-    DEBUGADD(10, ("returned [%d]\n", ret));
-
-    if(ret != 0)
-    {
-       if(fd != -1)
-           close(fd);
-       return False;
-    }
+       char *cmd = lp_eventlog_clear_cmd();
+       char **qlines;
+       pstring command;
+       int numlines = 0;
+       int ret;
+       int fd = -1;
+
+       if ( !cmd || !*cmd ) {
+               DEBUG(0, ("Must define an \"eventlog clear command\" entry in the config.\n"));
+               return False;
+       }
+
+       if ( strlen(backup_file_name) ) 
+               pstr_sprintf( command, "%s \"%s\" \"%s\"", cmd, info->logname, backup_file_name );
+       else 
+               pstr_sprintf( command, "%s \"%s\"", cmd, info->logname );
+
+       DEBUG(10, ("Running [%s]\n", command));
+       ret = smbrun(command, &fd);
+       DEBUGADD(10, ("returned [%d]\n", ret));
 
-    qlines = fd_lines_load(fd, &numlines);
-    DEBUGADD(10, ("Lines returned = [%d]\n", numlines));
-    close(fd);
+       if(ret != 0) {
+               if(fd != -1) {
+                       close(fd);
+               }
+               return False;
+       }
 
-    if(numlines)
-    {
-       DEBUGADD(10, ("Line[0] = [%s]\n", qlines[0]));
-       if(0 == strncmp(qlines[0], "SUCCESS", strlen("SUCCESS")))
-       {
-           DEBUGADD(10, ("Able to clear [%s].\n", info->source_log_file_name));
-           file_lines_free(qlines);
-           return True;
+       qlines = fd_lines_load(fd, &numlines);
+       DEBUGADD(10, ("Lines returned = [%d]\n", numlines));
+       close(fd);
+
+       if(numlines) {
+               DEBUGADD(10, ("Line[0] = [%s]\n", qlines[0]));
+               if(0 == strncmp(qlines[0], "SUCCESS", strlen("SUCCESS"))) {
+                       DEBUGADD(10, ("Able to clear [%s].\n", info->logname));
+                       file_lines_free(qlines);
+                       return True;
+               }
        }
-    }
 
-    file_lines_free(qlines);
-    return False;
+       file_lines_free(qlines);
+       return False;
+}
+
+/*******************************************************************
+*******************************************************************/
+
+WERROR _eventlog_open_eventlog(pipes_struct *p, EVENTLOG_Q_OPEN_EVENTLOG *q_u, EVENTLOG_R_OPEN_EVENTLOG *r_u)
+{
+       EventlogInfo *info = NULL;
+       fstring str;
+    
+       if ( !(info = TALLOC_ZERO_P(NULL, EventlogInfo)) ) 
+               return WERR_NOMEM;
+
+       fstrcpy( str, global_myname() );
+       if ( q_u->servername.string ) {
+               rpcstr_pull( str, q_u->servername.string->buffer, 
+                       sizeof(str), q_u->servername.string->uni_str_len*2, 0 );
+       } 
+       info->servername = talloc_strdup( info, str );
+
+       fstrcpy( str, "Application" );
+       if ( q_u->logname.string ) {
+               rpcstr_pull( str, q_u->logname.string->buffer, 
+                       sizeof(str), q_u->logname.string->uni_str_len*2, 0 );
+       } 
+       info->logname = talloc_strdup( info, str );
+
+       DEBUG(10, ("_eventlog_open_eventlog: Using [%s] as the server name.\n", info->servername));
+       DEBUG(10, ("_eventlog_open_eventlog: Using [%s] as the source log file.\n", info->logname));
+
+       if ( !create_policy_hnd(p, &r_u->handle, free_eventlog_info, (void *)info) ) {
+               free_eventlog_info(info);
+               return WERR_NOMEM;
+       }
+       
+       if ( !(open_eventlog_hook(info)) ) {
+               close_policy_hnd(p, &r_u->handle);
+               return WERR_BADFILE;
+       }
+       
+       return WERR_OK;
 }
 
-WERROR _eventlog_clear_eventlog(pipes_struct *p,
-                               EVENTLOG_Q_CLEAR_EVENTLOG *q_u,
-                               EVENTLOG_R_CLEAR_EVENTLOG *r_u)
+/********************************************************************
+********************************************************************/
+
+WERROR _eventlog_clear_eventlog(pipes_struct *p, EVENTLOG_Q_CLEAR_EVENTLOG *q_u, EVENTLOG_R_CLEAR_EVENTLOG *r_u)
 {
-    Eventlog_info *info = NULL;
-    pstring backup_file_name;
-    POLICY_HND *handle = NULL;
+       EventlogInfo *info = find_eventlog_info_by_hnd(p, &q_u->handle);
+       pstring backup_file_name;
 
-    if(!q_u || !r_u)
-       return WERR_NOMEM;
+       pstrcpy( backup_file_name, "" );
 
-    handle = &(q_u->handle);
-    info = find_eventlog_info_by_hnd(p, handle);
-    memset(backup_file_name, 0, sizeof(backup_file_name));
+       if ( q_u->backupfile.string ) 
+               unistr2_to_ascii(backup_file_name, q_u->backupfile.string, sizeof(backup_file_name));
 
-    if(q_u->backup_file_ptr != 0)
-    {
-       unistr2_to_ascii(backup_file_name, &(q_u->backup_file), sizeof(backup_file_name));
        DEBUG(10, ("_eventlog_clear_eventlog: Using [%s] as the backup file name for log [%s].",
-                  backup_file_name,
-                  info->source_log_file_name));
-    }
-    else
-    {
-       /* if backup_file == NULL, do not back up the log before clearing it */
-       DEBUG(10, ("_eventlog_clear_eventlog: clearing [%s] log without making a backup.",
-                  info->source_log_file_name));
-    }
-
-    if(!(_eventlog_clear_eventlog_hook(info, backup_file_name)))
-       return WERR_BADFILE;
-
-    return WERR_OK;
+                  backup_file_name, info->logname));
+
+       if ( !(clear_eventlog_hook(info, backup_file_name)) )
+               return WERR_BADFILE;
+
+       return WERR_OK;
+}
+
+/********************************************************************
+********************************************************************/
+
+WERROR _eventlog_close_eventlog(pipes_struct *p, EVENTLOG_Q_CLOSE_EVENTLOG *q_u, EVENTLOG_R_CLOSE_EVENTLOG *r_u)
+{
+       EventlogInfo *info = find_eventlog_info_by_hnd(p,&q_u->handle);
+
+       if ( !(close_eventlog_hook(info)) )
+               return WERR_BADFILE;
+
+       if ( !(close_policy_hnd(p, &q_u->handle)) ) {
+               return WERR_BADFID;
+       }
+
+       return WERR_OK;
 }
+
+/********************************************************************
+********************************************************************/
+   
+WERROR _eventlog_read_eventlog(pipes_struct *p, EVENTLOG_Q_READ_EVENTLOG *q_u, EVENTLOG_R_READ_EVENTLOG *r_u)
+{
+       EventlogInfo *info = find_eventlog_info_by_hnd(p, &q_u->handle);
+       Eventlog_entry entry, *ee_new;
+       BOOL eof = False, eor = False;
+       const char *direction = "";
+       uint32 num_records_read = 0;
+       prs_struct *ps;
+       int numlines, i;
+       char **buffer;
+
+       info->flags = q_u->flags;
+       ps = &p->out_data.rdata;
+
+       if ( info->flags & EVENTLOG_FORWARDS_READ ) 
+               direction = "forward";
+       else if ( info->flags & EVENTLOG_BACKWARDS_READ )
+               direction = "backward";
+
+       if ( !(read_eventlog_hook(info, &entry, direction, q_u->offset, q_u->max_read_size, &eof, &buffer, &numlines)) ) {
+               if(eof == False) {
+                       return WERR_NOMEM;
+               }
+       }
+
+       if(numlines > 0) {
+               ZERO_STRUCT(entry);
+               for(i = 0; i < numlines; i++) {
+                       num_records_read = r_u->num_records;
+                       DEBUGADD(10, ("Line[%d] = [%s]\n", i, buffer[i]));
+                       parse_logentry(buffer[i], &entry, &eor);
+                       if(eor == True) {
+                               /* package ee_new entry */
+                               if((ee_new = read_package_entry(ps, q_u, r_u, &entry)) == NULL) {
+                                       SAFE_FREE(buffer);
+                                       return WERR_NOMEM;
+                               }
+                               /* Now see if there is enough room to add */
+                               if(r_u->num_bytes_in_resp + ee_new->record.length > q_u->max_read_size) {
+                                       r_u->bytes_in_next_record = ee_new->record.length;
+                                       /* response would be too big to fit in client-size buffer */
+                                       break;
+                               }
+                               add_record_to_resp(r_u, ee_new);
+                               ZERO_STRUCT(entry);
+                               eor=False;
+                               num_records_read = r_u->num_records - num_records_read;
+                               DEBUG(10, ("_eventlog_read_eventlog: read [%d] records for a total of [%d] records using [%d] bytes out of a max of [%d].\n",
+                                          num_records_read,
+                                          r_u->num_records,
+                                          r_u->num_bytes_in_resp,
+                                          q_u->max_read_size));
+                       }
+               }
+               SAFE_FREE(buffer);
+       }
+
+       return WERR_OK;
+}
+
+/********************************************************************
+********************************************************************/
+
+WERROR _eventlog_get_oldest_entry(pipes_struct *p, EVENTLOG_Q_GET_OLDEST_ENTRY *q_u, EVENTLOG_R_GET_OLDEST_ENTRY *r_u)
+{
+       EventlogInfo *info = find_eventlog_info_by_hnd(p, &q_u->handle);
+
+       if ( !(get_oldest_entry_hook(info)) ) 
+               return WERR_BADFILE;
+
+       r_u->oldest_entry = info->oldest_entry;
+
+       return WERR_OK;
+}
+
+/********************************************************************
+********************************************************************/
+
+WERROR _eventlog_get_num_records(pipes_struct *p, EVENTLOG_Q_GET_NUM_RECORDS *q_u, EVENTLOG_R_GET_NUM_RECORDS *r_u)
+{
+       EventlogInfo *info = find_eventlog_info_by_hnd(p, &q_u->handle);
+
+       if ( !(get_num_records_hook(info)) )
+               return WERR_BADFILE;
+
+       r_u->num_records = info->num_records;
+
+       return WERR_OK;
+}
+
index 68072b528aaac439872014e4fd31796e59e34b40..7da87d5b93d028e6429d6cba07519f187055449f 100644 (file)
@@ -253,16 +253,18 @@ BOOL pipe_access_check(pipes_struct *p)
                user_struct *user = get_valid_user_struct(p->vuid);
 
                /* schannel, so we must be ok */
-               if (p->netsec_auth_validated)
+               if (p->pipe_bound && (p->auth.auth_type == PIPE_AUTH_TYPE_SCHANNEL)) {
                        return True;
+               }
 
                if (!user) {
                        DEBUG(3, ("invalid vuid %d\n", p->vuid));
                        return False;
                }
 
-               if (user->guest)
+               if (user->guest) {
                        return False;
+               }
        }
 
        return True;
index 021f1dc8e0f286e250c15c6e84ca0a3496c43389..15d420538ef11d8f957f44b5c2864d96e03da523 100644 (file)
@@ -805,17 +805,12 @@ NTSTATUS _lsa_enum_privs(pipes_struct *p, LSA_Q_ENUM_PRIVS *q_u, LSA_R_ENUM_PRIV
        struct lsa_info *handle;
        uint32 i;
        uint32 enum_context = q_u->enum_context;
-       int num_privs = 0;
+       int num_privs = count_all_privileges();
        LSA_PRIV_ENTRY *entries = NULL;
        LUID_ATTR luid;
 
        /* remember that the enum_context starts at 0 and not 1 */
 
-       if ( lp_enable_privileges() )
-               num_privs = count_all_privileges();
-       else
-               DEBUG(2,("_lsa_enum_privs: client trying to enumerate privileges by not enabled in smb.conf!\n"));
-
        if ( enum_context >= num_privs )
                return NT_STATUS_NO_MORE_ENTRIES;
                
index 15827a8b55e4eec0e2eda6a8b2b83a93e4f9b6a8..5aefe3ca3c977d717d1615afed370b29925178ce 100644 (file)
@@ -74,6 +74,7 @@ NTSTATUS _net_logon_ctrl(pipes_struct *p, NET_Q_LOGON_CTRL *q_u,
 /****************************************************************************
 Send a message to smbd to do a sam synchronisation
 **************************************************************************/
+
 static void send_sync_message(void)
 {
         TDB_CONTEXT *tdb;
@@ -268,26 +269,33 @@ static BOOL get_md4pw(char *md4pw, char *mach_acct)
 
 NTSTATUS _net_req_chal(pipes_struct *p, NET_Q_REQ_CHAL *q_u, NET_R_REQ_CHAL *r_u)
 {
-       NTSTATUS status = NT_STATUS_OK;
-
-       rpcstr_pull(p->dc.remote_machine,q_u->uni_logon_clnt.buffer,sizeof(fstring),q_u->uni_logon_clnt.uni_str_len*2,0);
-
-       /* create a server challenge for the client */
-       /* Set these to random values. */
-       generate_random_buffer(p->dc.srv_chal.data, 8);
-       
-       memcpy(p->dc.srv_cred.challenge.data, p->dc.srv_chal.data, 8);
+       if (!p->dc) {
+               p->dc = TALLOC_ZERO_P(p->pipe_state_mem_ctx, struct dcinfo);
+               if (!p->dc) {
+                       return NT_STATUS_NO_MEMORY;
+               }
+       } else {
+               DEBUG(10,("_net_req_chal: new challenge requested. Clearing old state.\n"));
+               ZERO_STRUCTP(p->dc);
+       }
 
-       memcpy(p->dc.clnt_chal.data          , q_u->clnt_chal.data, sizeof(q_u->clnt_chal.data));
-       memcpy(p->dc.clnt_cred.challenge.data, q_u->clnt_chal.data, sizeof(q_u->clnt_chal.data));
+       rpcstr_pull(p->dc->remote_machine,
+                       q_u->uni_logon_clnt.buffer,
+                       sizeof(fstring),q_u->uni_logon_clnt.uni_str_len*2,0);
 
-       memset((char *)p->dc.sess_key, '\0', sizeof(p->dc.sess_key));
+       /* Save the client challenge to the server. */
+       memcpy(p->dc->clnt_chal.data, q_u->clnt_chal.data, sizeof(q_u->clnt_chal.data));
 
-       p->dc.challenge_sent = True;
+       /* Create a server challenge for the client */
+       /* Set this to a random value. */
+       generate_random_buffer(p->dc->srv_chal.data, 8);
+       
        /* set up the LSA REQUEST CHALLENGE response */
-       init_net_r_req_chal(r_u, &p->dc.srv_chal, status);
+       init_net_r_req_chal(r_u, &p->dc->srv_chal, NT_STATUS_OK);
        
-       return status;
+       p->dc->challenge_sent = True;
+
+       return NT_STATUS_OK;
 }
 
 /*************************************************************************
@@ -301,50 +309,54 @@ static void init_net_r_auth(NET_R_AUTH *r_a, DOM_CHAL *resp_cred, NTSTATUS statu
 }
 
 /*************************************************************************
- _net_auth
+ _net_auth. Create the initial credentials.
  *************************************************************************/
 
 NTSTATUS _net_auth(pipes_struct *p, NET_Q_AUTH *q_u, NET_R_AUTH *r_u)
 {
-       NTSTATUS status = NT_STATUS_OK;
-       DOM_CHAL srv_cred;
-       UTIME srv_time;
        fstring mach_acct;
+       fstring remote_machine;
+       DOM_CHAL srv_chal_out;
 
-       srv_time.time = 0;
-
-       rpcstr_pull(mach_acct, q_u->clnt_id.uni_acct_name.buffer,sizeof(fstring),q_u->clnt_id.uni_acct_name.uni_str_len*2,0);
+       if (!p->dc || !p->dc->challenge_sent) {
+               return NT_STATUS_ACCESS_DENIED;
+       }
 
-       if (p->dc.challenge_sent && get_md4pw((char *)p->dc.md4pw, mach_acct)) {
+       rpcstr_pull(mach_acct, q_u->clnt_id.uni_acct_name.buffer,sizeof(fstring),
+                               q_u->clnt_id.uni_acct_name.uni_str_len*2,0);
+       rpcstr_pull(remote_machine, q_u->clnt_id.uni_comp_name.buffer,sizeof(fstring),
+                               q_u->clnt_id.uni_comp_name.uni_str_len*2,0);
 
-               /* from client / server challenges and md4 password, generate sess key */
-               cred_session_key(&p->dc.clnt_chal, &p->dc.srv_chal,
-                                p->dc.md4pw, p->dc.sess_key);
-               
-               /* check that the client credentials are valid */
-               if (cred_assert(&q_u->clnt_chal, p->dc.sess_key, &p->dc.clnt_cred.challenge, srv_time)) {
-                       
-                       /* create server challenge for inclusion in the reply */
-                       cred_create(p->dc.sess_key, &p->dc.srv_cred.challenge, srv_time, &srv_cred);
-               
-                       /* copy the received client credentials for use next time */
-                       memcpy(p->dc.clnt_cred.challenge.data, q_u->clnt_chal.data, sizeof(q_u->clnt_chal.data));
-                       memcpy(p->dc.srv_cred .challenge.data, q_u->clnt_chal.data, sizeof(q_u->clnt_chal.data));
-                       
-                       /* Save the machine account name. */
-                       fstrcpy(p->dc.mach_acct, mach_acct);
-               
-                       p->dc.authenticated = True;
+       if (!get_md4pw((char *)p->dc->mach_pw, mach_acct)) {
+               DEBUG(0,("_net_auth: creds_server_check failed. Failed to "
+                       "get pasword for machine account %s "
+                       "from client %s\n",
+                       mach_acct, remote_machine ));
+               return NT_STATUS_ACCESS_DENIED;
+       }
 
-               } else {
-                       status = NT_STATUS_ACCESS_DENIED;
-               }
-       } else {
-               status = NT_STATUS_ACCESS_DENIED;
+       /* From the client / server challenges and md4 password, generate sess key */
+       creds_server_init(p->dc,
+                       &p->dc->clnt_chal,      /* Stored client chal. */
+                       &p->dc->srv_chal,       /* Stored server chal. */
+                       p->dc->mach_pw,
+                       &srv_chal_out); 
+
+       /* Check client credentials are valid. */
+       if (!creds_server_check(p->dc, &q_u->clnt_chal)) {
+               DEBUG(0,("_net_auth: creds_server_check failed. Rejecting auth "
+                       "request from client %s machine account %s\n",
+                       remote_machine, mach_acct ));
+               return NT_STATUS_ACCESS_DENIED;
        }
-       
+
+       fstrcpy(p->dc->mach_acct, mach_acct);
+       fstrcpy(p->dc->remote_machine, remote_machine);
+       p->dc->authenticated = True;
+
        /* set up the LSA AUTH response */
-       init_net_r_auth(r_u, &srv_cred, status);
+       /* Return the server credentials. */
+       init_net_r_auth(r_u, &srv_chal_out, NT_STATUS_OK);
 
        return r_u->status;
 }
@@ -367,51 +379,54 @@ static void init_net_r_auth_2(NET_R_AUTH_2 *r_a,
 
 NTSTATUS _net_auth_2(pipes_struct *p, NET_Q_AUTH_2 *q_u, NET_R_AUTH_2 *r_u)
 {
-       NTSTATUS status = NT_STATUS_OK;
-       DOM_CHAL srv_cred;
-       UTIME srv_time;
        NEG_FLAGS srv_flgs;
        fstring mach_acct;
+       fstring remote_machine;
+       DOM_CHAL srv_chal_out;
 
-       srv_time.time = 0;
+       rpcstr_pull(mach_acct, q_u->clnt_id.uni_acct_name.buffer,sizeof(fstring),
+                               q_u->clnt_id.uni_acct_name.uni_str_len*2,0);
+       rpcstr_pull(remote_machine, q_u->clnt_id.uni_comp_name.buffer,sizeof(fstring),
+                               q_u->clnt_id.uni_comp_name.uni_str_len*2,0);
+
+       if (!p->dc || !p->dc->challenge_sent) {
+               DEBUG(0,("_net_auth2: no challenge sent to client %s\n",
+                       remote_machine ));
+               return NT_STATUS_ACCESS_DENIED;
+       }
 
        if ( (lp_server_schannel() == True) &&
             ((q_u->clnt_flgs.neg_flags & NETLOGON_NEG_SCHANNEL) == 0) ) {
 
                /* schannel must be used, but client did not offer it. */
-               status = NT_STATUS_ACCESS_DENIED;
+               DEBUG(0,("_net_auth2: schannel required but client failed "
+                       "to offer it. Client was %s\n",
+                       mach_acct ));
+               return NT_STATUS_ACCESS_DENIED;
        }
 
-       rpcstr_pull(mach_acct, q_u->clnt_id.uni_acct_name.buffer,sizeof(fstring),q_u->clnt_id.uni_acct_name.uni_str_len*2,0);
-
-       if (p->dc.challenge_sent && get_md4pw((char *)p->dc.md4pw, mach_acct)) {
-               
-               /* from client / server challenges and md4 password, generate sess key */
-               cred_session_key(&p->dc.clnt_chal, &p->dc.srv_chal,
-                                p->dc.md4pw, p->dc.sess_key);
-               
-               /* check that the client credentials are valid */
-               if (cred_assert(&q_u->clnt_chal, p->dc.sess_key, &p->dc.clnt_cred.challenge, srv_time)) {
-                       
-                       /* create server challenge for inclusion in the reply */
-                       cred_create(p->dc.sess_key, &p->dc.srv_cred.challenge, srv_time, &srv_cred);
-                       
-                       /* copy the received client credentials for use next time */
-                       memcpy(p->dc.clnt_cred.challenge.data, q_u->clnt_chal.data, sizeof(q_u->clnt_chal.data));
-                       memcpy(p->dc.srv_cred .challenge.data, q_u->clnt_chal.data, sizeof(q_u->clnt_chal.data));
-                       
-                       /* Save the machine account name. */
-                       fstrcpy(p->dc.mach_acct, mach_acct);
-                       
-                       p->dc.authenticated = True;
+       if (!get_md4pw((char *)p->dc->mach_pw, mach_acct)) {
+               DEBUG(0,("_net_auth2: failed to get machine password for "
+                       "account %s\n",
+                       mach_acct ));
+               return NT_STATUS_ACCESS_DENIED;
+       }
 
-               } else {
-                       status = NT_STATUS_ACCESS_DENIED;
-               }
-       } else {
-               status = NT_STATUS_ACCESS_DENIED;
+       /* From the client / server challenges and md4 password, generate sess key */
+       creds_server_init(p->dc,
+                       &p->dc->clnt_chal,      /* Stored client chal. */
+                       &p->dc->srv_chal,       /* Stored server chal. */
+                       p->dc->mach_pw,
+                       &srv_chal_out); 
+
+       /* Check client credentials are valid. */
+       if (!creds_server_check(p->dc, &q_u->clnt_chal)) {
+               DEBUG(0,("_net_auth2: creds_server_check failed. Rejecting auth "
+                       "request from client %s machine account %s\n",
+                       remote_machine, mach_acct ));
+               return NT_STATUS_ACCESS_DENIED;
        }
-       
+
        srv_flgs.neg_flags = 0x000001ff;
 
        if (lp_server_schannel() != False) {
@@ -419,12 +434,11 @@ NTSTATUS _net_auth_2(pipes_struct *p, NET_Q_AUTH_2 *q_u, NET_R_AUTH_2 *r_u)
        }
 
        /* set up the LSA AUTH 2 response */
-       init_net_r_auth_2(r_u, &srv_cred, &srv_flgs, status);
+       init_net_r_auth_2(r_u, &srv_chal_out, &srv_flgs, NT_STATUS_OK);
 
-       if (NT_STATUS_IS_OK(status)) {
-               server_auth2_negotiated = True;
-               last_dcinfo = p->dc;
-       }
+       server_auth2_negotiated = True;
+       p->dc->authenticated = True;
+       last_dcinfo = *p->dc;
 
        return r_u->status;
 }
@@ -436,32 +450,39 @@ NTSTATUS _net_auth_2(pipes_struct *p, NET_Q_AUTH_2 *q_u, NET_R_AUTH_2 *r_u)
 NTSTATUS _net_srv_pwset(pipes_struct *p, NET_Q_SRV_PWSET *q_u, NET_R_SRV_PWSET *r_u)
 {
        NTSTATUS status = NT_STATUS_ACCESS_DENIED;
-       DOM_CRED srv_cred;
-       pstring workstation;
+       fstring workstation;
        SAM_ACCOUNT *sampass=NULL;
        BOOL ret = False;
        unsigned char pwd[16];
        int i;
        uint32 acct_ctrl;
+       DOM_CRED cred_out;
        const uchar *old_pw;
 
-       /* checks and updates credentials.  creates reply credentials */
-       if (!(p->dc.authenticated && deal_with_creds(p->dc.sess_key, &p->dc.clnt_cred, &q_u->clnt_id.cred, &srv_cred)))
+       if (!p->dc || !p->dc->authenticated) {
                return NT_STATUS_INVALID_HANDLE;
+       }
 
-       memcpy(&p->dc.srv_cred, &p->dc.clnt_cred, sizeof(p->dc.clnt_cred));
+       /* Step the creds chain forward. */
+       if (!creds_server_step(p->dc, &q_u->clnt_id.cred, &cred_out)) {
+               DEBUG(0,("_net_srv_pwset: creds_server_step failed. Rejecting auth "
+                       "request from client %s machine account %s\n",
+                       p->dc->remote_machine, p->dc->mach_acct ));
+               return NT_STATUS_ACCESS_DENIED;
+       }
 
        DEBUG(5,("_net_srv_pwset: %d\n", __LINE__));
 
        rpcstr_pull(workstation,q_u->clnt_id.login.uni_comp_name.buffer,
                    sizeof(workstation),q_u->clnt_id.login.uni_comp_name.uni_str_len*2,0);
 
-       DEBUG(3,("Server Password Set by Wksta:[%s] on account [%s]\n", workstation, p->dc.mach_acct));
+       DEBUG(3,("_net_srv_pwset: Server Password Set by Wksta:[%s] on account [%s]\n",
+                       workstation, p->dc->mach_acct));
        
        pdb_init_sam(&sampass);
 
        become_root();
-       ret=pdb_getsampwnam(sampass, p->dc.mach_acct);
+       ret=pdb_getsampwnam(sampass, p->dc->mach_acct);
        unbecome_root();
 
        /* Ensure the account exists and is a machine account. */
@@ -481,7 +502,8 @@ NTSTATUS _net_srv_pwset(pipes_struct *p, NET_Q_SRV_PWSET *q_u, NET_R_SRV_PWSET *
                return NT_STATUS_ACCOUNT_DISABLED;
        }
 
-       cred_hash3( pwd, q_u->pwd, p->dc.sess_key, 0);
+       /* Woah - what does this to to the credential chain ? JRA */
+       cred_hash3( pwd, q_u->pwd, p->dc->sess_key, 0);
 
        DEBUG(100,("Server password set : new given value was :\n"));
        for(i = 0; i < sizeof(pwd); i++)
@@ -498,17 +520,17 @@ NTSTATUS _net_srv_pwset(pipes_struct *p, NET_Q_SRV_PWSET *q_u, NET_R_SRV_PWSET *
        } else {
 
                /* LM password should be NULL for machines */
-               if (!pdb_set_lanman_passwd (sampass, NULL, PDB_CHANGED)) {
+               if (!pdb_set_lanman_passwd(sampass, NULL, PDB_CHANGED)) {
                        pdb_free_sam(&sampass);
                        return NT_STATUS_NO_MEMORY;
                }
                
-               if (!pdb_set_nt_passwd     (sampass, pwd, PDB_CHANGED)) {
+               if (!pdb_set_nt_passwd(sampass, pwd, PDB_CHANGED)) {
                        pdb_free_sam(&sampass);
                        return NT_STATUS_NO_MEMORY;
                }
                
-               if (!pdb_set_pass_changed_now     (sampass)) {
+               if (!pdb_set_pass_changed_now(sampass)) {
                        pdb_free_sam(&sampass);
                        /* Not quite sure what this one qualifies as, but this will do */
                        return NT_STATUS_UNSUCCESSFUL; 
@@ -518,42 +540,41 @@ NTSTATUS _net_srv_pwset(pipes_struct *p, NET_Q_SRV_PWSET *q_u, NET_R_SRV_PWSET *
                ret = pdb_update_sam_account (sampass);
                unbecome_root();
        }
-       if (ret)
+       if (ret) {
                status = NT_STATUS_OK;
+       }
 
        /* set up the LSA Server Password Set response */
-       init_net_r_srv_pwset(r_u, &srv_cred, status);
+       init_net_r_srv_pwset(r_u, &cred_out, status);
 
        pdb_free_sam(&sampass);
        return r_u->status;
 }
 
-
 /*************************************************************************
  _net_sam_logoff:
  *************************************************************************/
 
 NTSTATUS _net_sam_logoff(pipes_struct *p, NET_Q_SAM_LOGOFF *q_u, NET_R_SAM_LOGOFF *r_u)
 {
-       DOM_CRED srv_cred;
-
        if (!get_valid_user_struct(p->vuid))
                return NT_STATUS_NO_SUCH_USER;
 
-       /* checks and updates credentials.  creates reply credentials */
-       if (!(p->dc.authenticated && deal_with_creds(p->dc.sess_key, &p->dc.clnt_cred, 
-                                                    &q_u->sam_id.client.cred, &srv_cred)))
+       if (!p->dc || !p->dc->authenticated) {
                return NT_STATUS_INVALID_HANDLE;
+       }
 
-       /* what happens if we get a logoff for an unknown user? */
-       memcpy(&p->dc.srv_cred, &p->dc.clnt_cred, sizeof(p->dc.clnt_cred));
-
-       /* XXXX maybe we want to say 'no', reject the client's credentials */
        r_u->buffer_creds = 1; /* yes, we have valid server credentials */
-       memcpy(&r_u->srv_creds, &srv_cred, sizeof(r_u->srv_creds));
 
-       r_u->status = NT_STATUS_OK;
+       /* checks and updates credentials.  creates reply credentials */
+       if (!creds_server_step(p->dc, &q_u->sam_id.client.cred, &r_u->srv_creds)) {
+               DEBUG(0,("_net_sam_logoff: creds_server_step failed. Rejecting auth "
+                       "request from client %s machine account %s\n",
+                       p->dc->remote_machine, p->dc->mach_acct ));
+               return NT_STATUS_ACCESS_DENIED;
+       }
 
+       r_u->status = NT_STATUS_OK;
        return r_u->status;
 }
 
@@ -567,7 +588,6 @@ NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON *
        NTSTATUS status = NT_STATUS_OK;
        NET_USER_INFO_3 *usr_info = NULL;
        NET_ID_INFO_CTR *ctr = q_u->sam_id.ctr;
-       DOM_CRED srv_cred;
        UNISTR2 *uni_samlogon_user = NULL;
        UNISTR2 *uni_samlogon_domain = NULL;
        UNISTR2 *uni_samlogon_workstation = NULL;
@@ -588,26 +608,31 @@ NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON *
        r_u->switch_value = 0; /* indicates no info */
        r_u->auth_resp = 1; /* authoritative response */
        r_u->switch_value = 3; /* indicates type of validation user info */
+       r_u->buffer_creds = 1; /* Ensure we always return server creds. */
  
        if (!get_valid_user_struct(p->vuid))
                return NT_STATUS_NO_SUCH_USER;
 
+       if (!p->dc || !p->dc->authenticated) {
+               return NT_STATUS_INVALID_HANDLE;
+       }
 
-       if ( (lp_server_schannel() == True) && (!p->netsec_auth_validated) ) {
+       if ( (lp_server_schannel() == True) && (p->auth.auth_type != PIPE_AUTH_TYPE_SCHANNEL) ) {
                /* 'server schannel = yes' should enforce use of
                   schannel, the client did offer it in auth2, but
                   obviously did not use it. */
+               DEBUG(0,("_net_sam_logoff: client %s not using schannel for netlogon\n",
+                       p->dc->remote_machine ));
                return NT_STATUS_ACCESS_DENIED;
        }
 
        /* checks and updates credentials.  creates reply credentials */
-       if (!(p->dc.authenticated && deal_with_creds(p->dc.sess_key, &p->dc.clnt_cred, &q_u->sam_id.client.cred, &srv_cred)))
-               return NT_STATUS_INVALID_HANDLE;
-
-       memcpy(&p->dc.srv_cred, &p->dc.clnt_cred, sizeof(p->dc.clnt_cred));
-
-       r_u->buffer_creds = 1; /* yes, we have valid server credentials */
-       memcpy(&r_u->srv_creds, &srv_cred, sizeof(r_u->srv_creds));
+       if (!creds_server_step(p->dc, &q_u->sam_id.client.cred,  &r_u->srv_creds)) {
+               DEBUG(0,("_net_sam_logoff: creds_server_step failed. Rejecting auth "
+                       "request from client %s machine account %s\n",
+                       p->dc->remote_machine, p->dc->mach_acct ));
+               return NT_STATUS_ACCESS_DENIED;
+       }
 
        /* find the username */
     
@@ -692,7 +717,7 @@ NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON *
                                                         nt_workstation, chal,
                                                         ctr->auth.id1.lm_owf.data, 
                                                         ctr->auth.id1.nt_owf.data, 
-                                                        p->dc.sess_key)) {
+                                                        p->dc->sess_key)) {
                        status = NT_STATUS_NO_MEMORY;
                }
                break;
@@ -791,7 +816,7 @@ NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON *
                }
 
                ZERO_STRUCT(netlogon_sess_key);
-               memcpy(netlogon_sess_key, p->dc.sess_key, 8);
+               memcpy(netlogon_sess_key, p->dc->sess_key, 8);
                if (server_info->user_session_key.length) {
                        memcpy(user_session_key, server_info->user_session_key.data, 
                               MIN(sizeof(user_session_key), server_info->user_session_key.length));
diff --git a/source3/rpc_server/srv_ntsvcs.c b/source3/rpc_server/srv_ntsvcs.c
new file mode 100644 (file)
index 0000000..48910db
--- /dev/null
@@ -0,0 +1,220 @@
+/* 
+ *  Unix SMB/CIFS implementation.
+ *  RPC Pipe client / server routines
+ *  Copyright (C) Gerald Carter                   2005.
+ *  
+ *  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"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_RPC_SRV
+
+/*******************************************************************
+ ********************************************************************/
+
+static BOOL api_ntsvcs_get_version(pipes_struct *p)
+{
+       NTSVCS_Q_GET_VERSION q_u;
+       NTSVCS_R_GET_VERSION r_u;
+       prs_struct *data = &p->in_data.data;
+       prs_struct *rdata = &p->out_data.rdata;
+
+       ZERO_STRUCT(q_u);
+       ZERO_STRUCT(r_u);
+
+       if(!ntsvcs_io_q_get_version("", &q_u, data, 0))
+               return False;
+
+       r_u.status = _ntsvcs_get_version(p, &q_u, &r_u);
+
+       if(!ntsvcs_io_r_get_version("", &r_u, rdata, 0))
+               return False;
+
+       return True;
+}
+
+/*******************************************************************
+ ********************************************************************/
+
+static BOOL api_ntsvcs_get_device_list_size(pipes_struct *p)
+{
+       NTSVCS_Q_GET_DEVICE_LIST_SIZE q_u;
+       NTSVCS_R_GET_DEVICE_LIST_SIZE r_u;
+       prs_struct *data = &p->in_data.data;
+       prs_struct *rdata = &p->out_data.rdata;
+
+       ZERO_STRUCT(q_u);
+       ZERO_STRUCT(r_u);
+
+       if(!ntsvcs_io_q_get_device_list_size("", &q_u, data, 0))
+               return False;
+
+       r_u.status = _ntsvcs_get_device_list_size(p, &q_u, &r_u);
+
+       if(!ntsvcs_io_r_get_device_list_size("", &r_u, rdata, 0))
+               return False;
+
+       return True;
+}
+
+/*******************************************************************
+ ********************************************************************/
+
+static BOOL api_ntsvcs_get_device_list(pipes_struct *p)
+{
+       NTSVCS_Q_GET_DEVICE_LIST q_u;
+       NTSVCS_R_GET_DEVICE_LIST r_u;
+       prs_struct *data = &p->in_data.data;
+       prs_struct *rdata = &p->out_data.rdata;
+
+       ZERO_STRUCT(q_u);
+       ZERO_STRUCT(r_u);
+
+       if(!ntsvcs_io_q_get_device_list("", &q_u, data, 0))
+               return False;
+
+       r_u.status = _ntsvcs_get_device_list(p, &q_u, &r_u);
+
+       if(!ntsvcs_io_r_get_device_list("", &r_u, rdata, 0))
+               return False;
+
+       return True;
+}
+
+/*******************************************************************
+ ********************************************************************/
+
+static BOOL api_ntsvcs_validate_device_instance(pipes_struct *p)
+{
+       NTSVCS_Q_VALIDATE_DEVICE_INSTANCE q_u;
+       NTSVCS_R_VALIDATE_DEVICE_INSTANCE r_u;
+       prs_struct *data = &p->in_data.data;
+       prs_struct *rdata = &p->out_data.rdata;
+
+       ZERO_STRUCT(q_u);
+       ZERO_STRUCT(r_u);
+
+       if(!ntsvcs_io_q_validate_device_instance("", &q_u, data, 0))
+               return False;
+
+       r_u.status = _ntsvcs_validate_device_instance(p, &q_u, &r_u);
+
+       if(!ntsvcs_io_r_validate_device_instance("", &r_u, rdata, 0))
+               return False;
+
+       return True;
+}
+
+/*******************************************************************
+ ********************************************************************/
+
+static BOOL api_ntsvcs_get_device_reg_property(pipes_struct *p)
+{
+       NTSVCS_Q_GET_DEVICE_REG_PROPERTY q_u;
+       NTSVCS_R_GET_DEVICE_REG_PROPERTY r_u;
+       prs_struct *data = &p->in_data.data;
+       prs_struct *rdata = &p->out_data.rdata;
+
+       ZERO_STRUCT(q_u);
+       ZERO_STRUCT(r_u);
+
+       if(!ntsvcs_io_q_get_device_reg_property("", &q_u, data, 0))
+               return False;
+
+       r_u.status = _ntsvcs_get_device_reg_property(p, &q_u, &r_u);
+
+       if(!ntsvcs_io_r_get_device_reg_property("", &r_u, rdata, 0))
+               return False;
+
+       return True;
+}
+
+/*******************************************************************
+ ********************************************************************/
+
+static BOOL api_ntsvcs_get_hw_profile_info(pipes_struct *p)
+{
+       NTSVCS_Q_GET_HW_PROFILE_INFO q_u;
+       NTSVCS_R_GET_HW_PROFILE_INFO r_u;
+       prs_struct *data = &p->in_data.data;
+       prs_struct *rdata = &p->out_data.rdata;
+
+       ZERO_STRUCT(q_u);
+       ZERO_STRUCT(r_u);
+
+       if(!ntsvcs_io_q_get_hw_profile_info("", &q_u, data, 0))
+               return False;
+
+       r_u.status = _ntsvcs_get_hw_profile_info(p, &q_u, &r_u);
+
+       if(!ntsvcs_io_r_get_hw_profile_info("", &r_u, rdata, 0))
+               return False;
+
+       return True;
+}
+
+/*******************************************************************
+ ********************************************************************/
+
+static BOOL api_ntsvcs_hw_profile_flags(pipes_struct *p)
+{
+       NTSVCS_Q_HW_PROFILE_FLAGS q_u;
+       NTSVCS_R_HW_PROFILE_FLAGS r_u;
+       prs_struct *data = &p->in_data.data;
+       prs_struct *rdata = &p->out_data.rdata;
+
+       ZERO_STRUCT(q_u);
+       ZERO_STRUCT(r_u);
+
+       if(!ntsvcs_io_q_hw_profile_flags("", &q_u, data, 0))
+               return False;
+
+       r_u.status = _ntsvcs_hw_profile_flags(p, &q_u, &r_u);
+
+       if(!ntsvcs_io_r_hw_profile_flags("", &r_u, rdata, 0))
+               return False;
+
+       return True;
+}
+
+/*******************************************************************
+ \PIPE\svcctl commands
+ ********************************************************************/
+
+static struct api_struct api_ntsvcs_cmds[] =
+{
+      { "NTSVCS_GET_VERSION"              , NTSVCS_GET_VERSION              , api_ntsvcs_get_version },
+      { "NTSVCS_GET_DEVICE_LIST_SIZE"     , NTSVCS_GET_DEVICE_LIST_SIZE     , api_ntsvcs_get_device_list_size },
+      { "NTSVCS_GET_DEVICE_LIST"          , NTSVCS_GET_DEVICE_LIST          , api_ntsvcs_get_device_list },
+      { "NTSVCS_VALIDATE_DEVICE_INSTANCE" , NTSVCS_VALIDATE_DEVICE_INSTANCE , api_ntsvcs_validate_device_instance },
+      { "NTSVCS_GET_DEVICE_REG_PROPERTY"  , NTSVCS_GET_DEVICE_REG_PROPERTY  , api_ntsvcs_get_device_reg_property },
+      { "NTSVCS_GET_HW_PROFILE_INFO"      , NTSVCS_GET_HW_PROFILE_INFO      , api_ntsvcs_get_hw_profile_info },
+      { "NTSVCS_HW_PROFILE_FLAGS"         , NTSVCS_HW_PROFILE_FLAGS         , api_ntsvcs_hw_profile_flags }
+};
+
+
+void ntsvcs_get_pipe_fns( struct api_struct **fns, int *n_fns )
+{
+       *fns = api_ntsvcs_cmds;
+       *n_fns = sizeof(api_ntsvcs_cmds) / sizeof(struct api_struct);
+}
+
+NTSTATUS rpc_ntsvcs_init(void)
+{
+  return rpc_pipe_register_commands(SMB_RPC_INTERFACE_VERSION, "ntsvcs", "ntsvcs", api_ntsvcs_cmds,
+                                   sizeof(api_ntsvcs_cmds) / sizeof(struct api_struct));
+}
diff --git a/source3/rpc_server/srv_ntsvcs_nt.c b/source3/rpc_server/srv_ntsvcs_nt.c
new file mode 100644 (file)
index 0000000..0bb9154
--- /dev/null
@@ -0,0 +1,174 @@
+/* 
+ *  Unix SMB/CIFS implementation.
+ *  RPC Pipe client / server routines
+ *
+ *  Copyright (C) Gerald (Jerry) Carter             2005.
+ *  
+ *  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"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_RPC_SRV
+
+/********************************************************************
+********************************************************************/
+
+static char* get_device_path( const char *device )
+{
+       static pstring path;
+
+       pstr_sprintf( path, "ROOT\\Legacy_%s\\0000", device );
+
+       return path;
+}
+
+/********************************************************************
+********************************************************************/
+
+WERROR _ntsvcs_get_version( pipes_struct *p, NTSVCS_Q_GET_VERSION *q_u, NTSVCS_R_GET_VERSION *r_u )
+{
+       r_u->version = 0x00000400;      /* no idea what this means */
+               
+       return WERR_OK;
+}
+
+/********************************************************************
+********************************************************************/
+
+WERROR _ntsvcs_get_device_list_size( pipes_struct *p, NTSVCS_Q_GET_DEVICE_LIST_SIZE *q_u, NTSVCS_R_GET_DEVICE_LIST_SIZE *r_u )
+{
+       fstring device;
+       const char *devicepath;
+
+       if ( !q_u->devicename )
+               return WERR_ACCESS_DENIED;
+
+       rpcstr_pull(device, q_u->devicename->buffer, sizeof(device), q_u->devicename->uni_str_len*2, 0);
+       devicepath = get_device_path( device );
+
+       r_u->size = strlen(devicepath) + 2;
+
+       return WERR_OK;
+}
+
+
+/********************************************************************
+********************************************************************/
+
+WERROR _ntsvcs_get_device_list( pipes_struct *p, NTSVCS_Q_GET_DEVICE_LIST *q_u, NTSVCS_R_GET_DEVICE_LIST *r_u )
+{
+       fstring device;
+       const char *devicepath;
+
+       if ( !q_u->devicename )
+               return WERR_ACCESS_DENIED;
+
+       rpcstr_pull(device, q_u->devicename->buffer, sizeof(device), q_u->devicename->uni_str_len*2, 0);
+       devicepath = get_device_path( device );
+
+       /* From the packet traces I've see, I think this really should be an array
+          of UNISTR2's.  But I've never seen more than one string in spite of the 
+          fact that the string in double NULL terminated.  -- jerry */
+
+       init_unistr2( &r_u->devicepath, devicepath, UNI_STR_TERMINATE );
+       r_u->needed = r_u->devicepath.uni_str_len;
+
+       return WERR_OK;
+}
+
+/********************************************************************
+********************************************************************/
+
+WERROR _ntsvcs_get_device_reg_property( pipes_struct *p, NTSVCS_Q_GET_DEVICE_REG_PROPERTY *q_u, NTSVCS_R_GET_DEVICE_REG_PROPERTY *r_u )
+{
+       fstring devicepath;
+       char *ptr;
+       REGVAL_CTR *values;
+       REGISTRY_VALUE *val;
+
+       rpcstr_pull(devicepath, q_u->devicepath.buffer, sizeof(devicepath), q_u->devicepath.uni_str_len*2, 0);
+
+       switch( q_u->property ) {
+       case DEV_REGPROP_DESC:
+               /* just parse the service name from the device path and then 
+                  lookup the display name */
+               if ( !(ptr = strrchr_m( devicepath, '\\' )) )
+                       return WERR_GENERAL_FAILURE;    
+               *ptr = '\0';
+               
+               if ( !(ptr = strrchr_m( devicepath, '_' )) )
+                       return WERR_GENERAL_FAILURE;    
+               ptr++;
+               
+               if ( !(values = svcctl_fetch_regvalues( ptr, p->pipe_user.nt_user_token )) )
+                       return WERR_GENERAL_FAILURE;    
+               
+               if ( !(val = regval_ctr_getvalue( values, "DisplayName" )) ) {
+                       TALLOC_FREE( values );
+                       return WERR_GENERAL_FAILURE;
+               }
+               
+               r_u->unknown1 = 0x1;    /* always 1...tested using a remove device manager connection */
+               r_u->size = reg_init_regval_buffer( &r_u->value, val );
+               r_u->needed = r_u->size;
+
+               TALLOC_FREE(values);
+
+               break;
+               
+       default:
+               r_u->unknown1 = 0x00437c98;
+               return WERR_CM_NO_SUCH_VALUE;
+       }
+
+       return WERR_OK;
+}
+
+/********************************************************************
+********************************************************************/
+
+WERROR _ntsvcs_validate_device_instance( pipes_struct *p, NTSVCS_Q_VALIDATE_DEVICE_INSTANCE *q_u, NTSVCS_R_VALIDATE_DEVICE_INSTANCE *r_u )
+{
+       /* whatever dude */
+       return WERR_OK;
+}
+
+/********************************************************************
+********************************************************************/
+
+WERROR _ntsvcs_get_hw_profile_info( pipes_struct *p, NTSVCS_Q_GET_HW_PROFILE_INFO *q_u, NTSVCS_R_GET_HW_PROFILE_INFO *r_u )
+{
+       /* steal the incoming buffer */
+
+       r_u->buffer_size = q_u->buffer_size;
+       r_u->buffer = q_u->buffer;
+
+       /* Take the 5th Ammentment */
+
+       return WERR_CM_NO_MORE_HW_PROFILES;
+}
+
+/********************************************************************
+********************************************************************/
+
+WERROR _ntsvcs_hw_profile_flags( pipes_struct *p, NTSVCS_Q_HW_PROFILE_FLAGS *q_u, NTSVCS_R_HW_PROFILE_FLAGS *r_u )
+{      
+       /* just nod your head */
+       
+       return WERR_OK;
+}
+
index 63e8d2f5cdaed21fe409372ae03a5de0cd6fbce7..ba6d9704e808375ef8c62fb685390bcabd548cf0 100644 (file)
@@ -1,11 +1,7 @@
 /* 
  *  Unix SMB/CIFS implementation.
  *  RPC Pipe client / server routines
- *  Copyright (C) Andrew Tridgell              1992-1998
- *  Copyright (C) Luke Kenneth Casson Leighton 1996-1998,
- *  Copyright (C) Paul Ashton                  1997-1998,
- *  Copyright (C) Jeremy Allison                    1999,
- *  Copyright (C) Jim McDonough <jmcd@us.ibm.com>   2003.
+ *  Almost completely rewritten by (C) Jeremy Allison 2005.
  *  
  *  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
  *  and DCE/RPC, while minimising the amount of mallocs, unnecessary
  *  data copies, and network traffic.
  *
- *  in this version, which takes a "let's learn what's going on and
- *  get something running" approach, there is additional network
- *  traffic generated, but the code should be easier to understand...
- *
- *  ... if you read the docs.  or stare at packets for weeks on end.
- *
  */
 
 #include "includes.h"
@@ -51,52 +41,38 @@ extern struct current_user current_user;
  We need to transfer the session key from one rpc bind to the
  next. This is the way the netlogon schannel works.
 **************************************************************/
+
 struct dcinfo last_dcinfo;
 BOOL server_auth2_negotiated = False;
 
-static void NTLMSSPcalc_p( pipes_struct *p, unsigned char *data, int len)
+static void free_pipe_ntlmssp_auth_data(struct pipe_auth_data *auth)
 {
-       unsigned char *hash = p->ntlmssp_hash;
-       unsigned char index_i = hash[256];
-       unsigned char index_j = hash[257];
-       int ind;
-
-       for( ind = 0; ind < len; ind++) {
-               unsigned char tc;
-               unsigned char t;
+       AUTH_NTLMSSP_STATE *a = auth->a_u.auth_ntlmssp_state;
 
-               index_i++;
-               index_j += hash[index_i];
-
-               tc = hash[index_i];
-               hash[index_i] = hash[index_j];
-               hash[index_j] = tc;
-
-               t = hash[index_i] + hash[index_j];
-               data[ind] = data[ind] ^ hash[t];
+       if (a) {
+               auth_ntlmssp_end(&a);
        }
-
-       hash[256] = index_i;
-       hash[257] = index_j;
+       auth->a_u.auth_ntlmssp_state = NULL;
 }
 
 /*******************************************************************
  Generate the next PDU to be returned from the data in p->rdata. 
- We cheat here as this function doesn't handle the special auth
- footers of the authenticated bind response reply.
+ Handle NTLMSSP.
  ********************************************************************/
 
-BOOL create_next_pdu(pipes_struct *p)
+static BOOL create_next_pdu_ntlmssp(pipes_struct *p)
 {
        RPC_HDR_RESP hdr_resp;
-       BOOL auth_verify = ((p->ntlmssp_chal_flags & NTLMSSP_NEGOTIATE_SIGN) != 0);
-       BOOL auth_seal   = ((p->ntlmssp_chal_flags & NTLMSSP_NEGOTIATE_SEAL) != 0);
        uint32 ss_padding_len = 0;
-       uint32 data_len;
        uint32 data_space_available;
        uint32 data_len_left;
+       uint32 data_len;
        prs_struct outgoing_pdu;
-       uint32 data_pos;
+       NTSTATUS status;
+       DATA_BLOB auth_blob;
+       RPC_HDR_AUTH auth_info;
+       uint8 auth_type, auth_level;
+       AUTH_NTLMSSP_STATE *a = p->auth.a_u.auth_ntlmssp_state;
 
        /*
         * If we're in the fault state, keep returning fault PDU's until
@@ -124,18 +100,6 @@ BOOL create_next_pdu(pipes_struct *p)
         * Work out how much we can fit in a single PDU.
         */
 
-       data_space_available = sizeof(p->out_data.current_pdu) - RPC_HEADER_LEN - RPC_HDR_RESP_LEN;
-       if(p->ntlmssp_auth_validated) {
-               data_space_available -= (RPC_HDR_AUTH_LEN + RPC_AUTH_NTLMSSP_CHK_LEN);
-       } else if(p->netsec_auth_validated) {
-               data_space_available -= (RPC_HDR_AUTH_LEN + RPC_AUTH_NETSEC_SIGN_OR_SEAL_CHK_LEN);
-       }
-
-       /*
-        * The amount we send is the minimum of the available
-        * space and the amount left to send.
-        */
-
        data_len_left = prs_offset(&p->out_data.rdata) - p->out_data.data_sent_length;
 
        /*
@@ -143,10 +107,18 @@ BOOL create_next_pdu(pipes_struct *p)
         */
 
        if(!data_len_left) {
-               DEBUG(0,("create_next_pdu: no data left to send !\n"));
+               DEBUG(0,("create_next_pdu_ntlmssp: no data left to send !\n"));
                return False;
        }
 
+       data_space_available = sizeof(p->out_data.current_pdu) - RPC_HEADER_LEN - RPC_HDR_RESP_LEN -
+                                       RPC_HDR_AUTH_LEN - NTLMSSP_SIG_SIZE;
+
+       /*
+        * The amount we send is the minimum of the available
+        * space and the amount left to send.
+        */
+
        data_len = MIN(data_len_left, data_space_available);
 
        /*
@@ -162,9 +134,9 @@ BOOL create_next_pdu(pipes_struct *p)
 
        if(p->out_data.data_sent_length + data_len >= prs_offset(&p->out_data.rdata)) {
                p->hdr.flags |= RPC_FLG_LAST;
-               if ((auth_seal || auth_verify || p->netsec_auth_validated) && (data_len_left % 8)) {
+               if (data_len_left % 8) {
                        ss_padding_len = 8 - (data_len_left % 8);
-                       DEBUG(10,("create_next_pdu: adding sign/seal padding of %u\n",
+                       DEBUG(10,("create_next_pdu_ntlmssp: adding sign/seal padding of %u\n",
                                ss_padding_len ));
                }
        }
@@ -173,20 +145,11 @@ BOOL create_next_pdu(pipes_struct *p)
         * Set up the header lengths.
         */
 
-       if (p->ntlmssp_auth_validated) {
-               p->hdr.frag_len = RPC_HEADER_LEN + RPC_HDR_RESP_LEN +
+       p->hdr.frag_len = RPC_HEADER_LEN + RPC_HDR_RESP_LEN +
                        data_len + ss_padding_len +
-                       RPC_HDR_AUTH_LEN + RPC_AUTH_NTLMSSP_CHK_LEN;
-               p->hdr.auth_len = RPC_AUTH_NTLMSSP_CHK_LEN;
-       } else if (p->netsec_auth_validated) {
-               p->hdr.frag_len = RPC_HEADER_LEN + RPC_HDR_RESP_LEN +
-                       data_len + ss_padding_len +
-                       RPC_HDR_AUTH_LEN + RPC_AUTH_NETSEC_SIGN_OR_SEAL_CHK_LEN;
-               p->hdr.auth_len = RPC_AUTH_NETSEC_SIGN_OR_SEAL_CHK_LEN;
-       } else {
-               p->hdr.frag_len = RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len;
-               p->hdr.auth_len = 0;
-       }
+                       RPC_HDR_AUTH_LEN + NTLMSSP_SIG_SIZE;
+       p->hdr.auth_len = NTLMSSP_SIG_SIZE;
+
 
        /*
         * Init the parse struct to point at the outgoing
@@ -198,127 +161,105 @@ BOOL create_next_pdu(pipes_struct *p)
 
        /* Store the header in the data stream. */
        if(!smb_io_rpc_hdr("hdr", &p->hdr, &outgoing_pdu, 0)) {
-               DEBUG(0,("create_next_pdu: failed to marshall RPC_HDR.\n"));
+               DEBUG(0,("create_next_pdu_ntlmssp: failed to marshall RPC_HDR.\n"));
                prs_mem_free(&outgoing_pdu);
                return False;
        }
 
        if(!smb_io_rpc_hdr_resp("resp", &hdr_resp, &outgoing_pdu, 0)) {
-               DEBUG(0,("create_next_pdu: failed to marshall RPC_HDR_RESP.\n"));
+               DEBUG(0,("create_next_pdu_ntlmssp: failed to marshall RPC_HDR_RESP.\n"));
                prs_mem_free(&outgoing_pdu);
                return False;
        }
 
-       /* Store the current offset. */
-       data_pos = prs_offset(&outgoing_pdu);
-
        /* Copy the data into the PDU. */
 
        if(!prs_append_some_prs_data(&outgoing_pdu, &p->out_data.rdata, p->out_data.data_sent_length, data_len)) {
-               DEBUG(0,("create_next_pdu: failed to copy %u bytes of data.\n", (unsigned int)data_len));
+               DEBUG(0,("create_next_pdu_ntlmssp: failed to copy %u bytes of data.\n", (unsigned int)data_len));
                prs_mem_free(&outgoing_pdu);
                return False;
        }
 
        /* Copy the sign/seal padding data. */
        if (ss_padding_len) {
-               char pad[8];
+               unsigned char pad[8];
+
                memset(pad, '\0', 8);
                if (!prs_copy_data_in(&outgoing_pdu, pad, ss_padding_len)) {
-                       DEBUG(0,("create_next_pdu: failed to add %u bytes of pad data.\n", (unsigned int)ss_padding_len));
+                       DEBUG(0,("create_next_pdu_ntlmssp: failed to add %u bytes of pad data.\n",
+                                       (unsigned int)ss_padding_len));
                        prs_mem_free(&outgoing_pdu);
                        return False;
                }
        }
 
-       if (p->ntlmssp_auth_validated) {
-               /*
-                * NTLMSSP processing. Mutually exclusive with Schannel.
-                */
-               uint32 crc32 = 0;
-               char *data;
-
-               DEBUG(5,("create_next_pdu: sign: %s seal: %s data %d auth %d\n",
-                        BOOLSTR(auth_verify), BOOLSTR(auth_seal), data_len + ss_padding_len, p->hdr.auth_len));
-
-               /*
-                * Set data to point to where we copied the data into.
-                */
 
-               data = prs_data_p(&outgoing_pdu) + data_pos;
+       /* Now write out the auth header and null blob. */
+       if (p->auth.auth_type == PIPE_AUTH_TYPE_NTLMSSP) {
+               auth_type = RPC_NTLMSSP_AUTH_TYPE;
+       } else {
+               auth_type = RPC_SPNEGO_AUTH_TYPE;
+       }
+       if (p->auth.auth_level == PIPE_AUTH_LEVEL_PRIVACY) {
+               auth_level = RPC_AUTH_LEVEL_PRIVACY;
+       } else {
+               auth_level = RPC_AUTH_LEVEL_INTEGRITY;
+       }
 
-               if (auth_seal) {
-                       crc32 = crc32_calc_buffer(data, data_len + ss_padding_len);
-                       NTLMSSPcalc_p(p, (uchar*)data, data_len + ss_padding_len);
-               }
+       init_rpc_hdr_auth(&auth_info, auth_type, auth_level, ss_padding_len, 1 /* context id. */);
+       if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, &outgoing_pdu, 0)) {
+               DEBUG(0,("create_next_pdu_ntlmssp: failed to marshall RPC_HDR_AUTH.\n"));
+               prs_mem_free(&outgoing_pdu);
+               return False;
+       }
 
-               if (auth_seal || auth_verify) {
-                       RPC_HDR_AUTH auth_info;
+       /* Generate the sign blob. */
 
-                       init_rpc_hdr_auth(&auth_info, NTLMSSP_AUTH_TYPE,
-                                       auth_seal ? RPC_PIPE_AUTH_SEAL_LEVEL : RPC_PIPE_AUTH_SIGN_LEVEL,
-                                       (auth_verify ? ss_padding_len : 0), (auth_verify ? 1 : 0));
-                       if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, &outgoing_pdu, 0)) {
-                               DEBUG(0,("create_next_pdu: failed to marshall RPC_HDR_AUTH.\n"));
+       switch (p->auth.auth_level) {
+               case PIPE_AUTH_LEVEL_PRIVACY:
+                       /* Data portion is encrypted. */
+                       status = ntlmssp_seal_packet(a->ntlmssp_state,
+                                                       prs_data_p(&outgoing_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN,
+                                                       data_len + ss_padding_len,
+                                                       prs_data_p(&outgoing_pdu),
+                                                       (size_t)prs_offset(&outgoing_pdu),
+                                                       &auth_blob);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               data_blob_free(&auth_blob);
                                prs_mem_free(&outgoing_pdu);
                                return False;
                        }
-               }
-
-               if (auth_verify) {
-                       RPC_AUTH_NTLMSSP_CHK ntlmssp_chk;
-                       char *auth_data = prs_data_p(&outgoing_pdu);
-
-                       p->ntlmssp_seq_num++;
-                       init_rpc_auth_ntlmssp_chk(&ntlmssp_chk, NTLMSSP_SIGN_VERSION,
-                                       crc32, p->ntlmssp_seq_num++);
-                       auth_data = prs_data_p(&outgoing_pdu) + prs_offset(&outgoing_pdu) + 4;
-                       if(!smb_io_rpc_auth_ntlmssp_chk("auth_sign", &ntlmssp_chk, &outgoing_pdu, 0)) {
-                               DEBUG(0,("create_next_pdu: failed to marshall RPC_AUTH_NTLMSSP_CHK.\n"));
+                       break;
+               case PIPE_AUTH_LEVEL_INTEGRITY:
+                       /* Data is signed. */
+                       status = ntlmssp_sign_packet(a->ntlmssp_state,
+                                                       prs_data_p(&outgoing_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN,
+                                                       data_len + ss_padding_len,
+                                                       prs_data_p(&outgoing_pdu),
+                                                       (size_t)prs_offset(&outgoing_pdu),
+                                                       &auth_blob);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               data_blob_free(&auth_blob);
                                prs_mem_free(&outgoing_pdu);
                                return False;
                        }
-                       NTLMSSPcalc_p(p, (uchar*)auth_data, RPC_AUTH_NTLMSSP_CHK_LEN - 4);
-               }
-       } else if (p->netsec_auth_validated) {
-               /*
-                * Schannel processing. Mutually exclusive with NTLMSSP.
-                */
-               int auth_type, auth_level;
-               char *data;
-               RPC_HDR_AUTH auth_info;
-
-               RPC_AUTH_NETSEC_CHK verf;
-               prs_struct rverf;
-               prs_struct rauth;
-
-               data = prs_data_p(&outgoing_pdu) + data_pos;
-               /* Check it's the type of reply we were expecting to decode */
-
-               get_auth_type_level(p->netsec_auth.auth_flags, &auth_type, &auth_level);
-               init_rpc_hdr_auth(&auth_info, auth_type, auth_level, 
-                                 ss_padding_len, 1);
-
-               if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, &outgoing_pdu, 0)) {
-                       DEBUG(0,("create_next_pdu: failed to marshall RPC_HDR_AUTH.\n"));
+                       break;
+               default:
                        prs_mem_free(&outgoing_pdu);
                        return False;
-               }
-
-               prs_init(&rverf, 0, p->mem_ctx, MARSHALL);
-               prs_init(&rauth, 0, p->mem_ctx, MARSHALL);
-
-               netsec_encode(&p->netsec_auth, 
-                             p->netsec_auth.auth_flags,
-                             SENDER_IS_ACCEPTOR,
-                             &verf, data, data_len + ss_padding_len);
-
-               smb_io_rpc_auth_netsec_chk("", RPC_AUTH_NETSEC_SIGN_OR_SEAL_CHK_LEN, 
-                       &verf, &outgoing_pdu, 0);
+       }
 
-               p->netsec_auth.seq_num++;
+       /* Append the auth blob. */
+       if (!prs_copy_data_in(&outgoing_pdu, auth_blob.data, NTLMSSP_SIG_SIZE)) {
+               DEBUG(0,("create_next_pdu_ntlmssp: failed to add %u bytes auth blob.\n",
+                               (unsigned int)NTLMSSP_SIG_SIZE));
+               data_blob_free(&auth_blob);
+               prs_mem_free(&outgoing_pdu);
+               return False;
        }
 
+       data_blob_free(&auth_blob);
+
        /*
         * Setup the counts for this PDU.
         */
@@ -332,292 +273,501 @@ BOOL create_next_pdu(pipes_struct *p)
 }
 
 /*******************************************************************
- Process an NTLMSSP authentication response.
- If this function succeeds, the user has been authenticated
- and their domain, name and calling workstation stored in
- the pipe struct.
- The initial challenge is stored in p->challenge.
- *******************************************************************/
+ Generate the next PDU to be returned from the data in p->rdata. 
+ Return an schannel authenticated fragment.
+ ********************************************************************/
 
-static BOOL api_pipe_ntlmssp_verify(pipes_struct *p, RPC_AUTH_NTLMSSP_RESP *ntlmssp_resp)
+static BOOL create_next_pdu_schannel(pipes_struct *p)
 {
-       uchar lm_owf[24];
-       uchar nt_owf[128];
-       int nt_pw_len;
-       int lm_pw_len;
-       fstring user_name;
-       fstring domain;
-       fstring wks;
+       RPC_HDR_RESP hdr_resp;
+       uint32 ss_padding_len = 0;
+       uint32 data_len;
+       uint32 data_space_available;
+       uint32 data_len_left;
+       prs_struct outgoing_pdu;
+       uint32 data_pos;
 
-       NTSTATUS nt_status;
+       /*
+        * If we're in the fault state, keep returning fault PDU's until
+        * the pipe gets closed. JRA.
+        */
 
-       struct auth_context *auth_context = NULL;
-       auth_usersupplied_info *user_info = NULL;
-       auth_serversupplied_info *server_info = NULL;
+       if(p->fault_state) {
+               setup_fault_pdu(p, NT_STATUS(0x1c010002));
+               return True;
+       }
 
-       DEBUG(5,("api_pipe_ntlmssp_verify: checking user details\n"));
+       memset((char *)&hdr_resp, '\0', sizeof(hdr_resp));
 
-       memset(p->user_name, '\0', sizeof(p->user_name));
-       memset(p->pipe_user_name, '\0', sizeof(p->pipe_user_name));
-       memset(p->domain, '\0', sizeof(p->domain));
-       memset(p->wks, '\0', sizeof(p->wks));
+       /* Change the incoming request header to a response. */
+       p->hdr.pkt_type = RPC_RESPONSE;
 
-       /* Set up for non-authenticated user. */
-       delete_nt_token(&p->pipe_user.nt_user_token);
-       p->pipe_user.ngroups = 0;
-       SAFE_FREE( p->pipe_user.groups);
+       /* Set up rpc header flags. */
+       if (p->out_data.data_sent_length == 0) {
+               p->hdr.flags = RPC_FLG_FIRST;
+       } else {
+               p->hdr.flags = 0;
+       }
 
-       /* 
-        * Setup an empty password for a guest user.
+       /*
+        * Work out how much we can fit in a single PDU.
         */
 
+       data_len_left = prs_offset(&p->out_data.rdata) - p->out_data.data_sent_length;
+
        /*
-        * We always negotiate UNICODE.
+        * Ensure there really is data left to send.
         */
 
-       if (p->ntlmssp_chal_flags & NTLMSSP_NEGOTIATE_UNICODE) {
-               rpcstr_pull(user_name, ntlmssp_resp->user, sizeof(fstring), ntlmssp_resp->hdr_usr.str_str_len*2, 0 );
-               rpcstr_pull(domain, ntlmssp_resp->domain, sizeof(fstring), ntlmssp_resp->hdr_domain.str_str_len*2, 0);
-               rpcstr_pull(wks, ntlmssp_resp->wks, sizeof(fstring), ntlmssp_resp->hdr_wks.str_str_len*2, 0);
-       } else {
-               pull_ascii_fstring(user_name, ntlmssp_resp->user);
-               pull_ascii_fstring(domain, ntlmssp_resp->domain);
-               pull_ascii_fstring(wks, ntlmssp_resp->wks);
+       if(!data_len_left) {
+               DEBUG(0,("create_next_pdu_schannel: no data left to send !\n"));
+               return False;
        }
 
-       DEBUG(5,("user: %s domain: %s wks: %s\n", user_name, domain, wks));
+       data_space_available = sizeof(p->out_data.current_pdu) - RPC_HEADER_LEN - RPC_HDR_RESP_LEN -
+                                       RPC_HDR_AUTH_LEN - RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN;
 
-       nt_pw_len = MIN(sizeof(nt_owf), ntlmssp_resp->hdr_nt_resp.str_str_len);
-       lm_pw_len = MIN(sizeof(lm_owf), ntlmssp_resp->hdr_lm_resp.str_str_len);
-
-       memcpy(lm_owf, ntlmssp_resp->lm_resp, sizeof(lm_owf));
-       memcpy(nt_owf, ntlmssp_resp->nt_resp, nt_pw_len);
+       /*
+        * The amount we send is the minimum of the available
+        * space and the amount left to send.
+        */
 
-#ifdef DEBUG_PASSWORD
-       DEBUG(100,("lm, nt owfs, chal\n"));
-       dump_data(100, (char *)lm_owf, sizeof(lm_owf));
-       dump_data(100, (char *)nt_owf, nt_pw_len);
-       dump_data(100, (char *)p->challenge, 8);
-#endif
+       data_len = MIN(data_len_left, data_space_available);
 
        /*
-        * Allow guest access. Patch from Shirish Kalele <kalele@veritas.com>.
+        * Set up the alloc hint. This should be the data left to
+        * send.
         */
 
-       if (*user_name) {
-
-               /* 
-                * Do the length checking only if user is not NULL.
-                */
+       hdr_resp.alloc_hint = data_len_left;
 
-               if (ntlmssp_resp->hdr_lm_resp.str_str_len == 0)
-                       return False;
-               if (ntlmssp_resp->hdr_nt_resp.str_str_len == 0)
-                       return False;
-               if (ntlmssp_resp->hdr_usr.str_str_len == 0)
-                       return False;
-               if (ntlmssp_resp->hdr_domain.str_str_len == 0)
-                       return False;
-               if (ntlmssp_resp->hdr_wks.str_str_len == 0)
-                       return False;
+       /*
+        * Work out if this PDU will be the last.
+        */
 
+       if(p->out_data.data_sent_length + data_len >= prs_offset(&p->out_data.rdata)) {
+               p->hdr.flags |= RPC_FLG_LAST;
+               if (data_len_left % 8) {
+                       ss_padding_len = 8 - (data_len_left % 8);
+                       DEBUG(10,("create_next_pdu_schannel: adding sign/seal padding of %u\n",
+                               ss_padding_len ));
+               }
        }
-       
-       make_auth_context_fixed(&auth_context, (uchar*)p->challenge);
 
-       if (!make_user_info_netlogon_network(&user_info, 
-                                            user_name, domain, wks,
-                                            lm_owf, lm_pw_len, 
-                                            nt_owf, nt_pw_len)) {
-               DEBUG(0,("make_user_info_netlogon_network failed!  Failing authenticaion.\n"));
-               return False;
-       }
-       
-       nt_status = auth_context->check_ntlm_password(auth_context, user_info, &server_info); 
-       
-       (auth_context->free)(&auth_context);
-       free_user_info(&user_info);
-       
-       p->ntlmssp_auth_validated = NT_STATUS_IS_OK(nt_status);
-       
-       if (!p->ntlmssp_auth_validated) {
-               DEBUG(1,("api_pipe_ntlmssp_verify: User [%s]\\[%s] from machine %s \
-failed authentication on named pipe %s.\n", domain, user_name, wks, p->name ));
-               free_server_info(&server_info);
-               return False;
-       }
+       p->hdr.frag_len = RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len + ss_padding_len +
+                               RPC_HDR_AUTH_LEN + RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN;
+       p->hdr.auth_len = RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN;
 
        /*
-        * Set up the sign/seal data.
+        * Init the parse struct to point at the outgoing
+        * data.
         */
 
-       if (server_info->lm_session_key.length != 16) {
-               DEBUG(1,("api_pipe_ntlmssp_verify: User [%s]\\[%s] from machine %s \
-succeeded authentication on named pipe %s, but session key was of incorrect length [%u].\n", 
-                        domain, user_name, wks, p->name, server_info->lm_session_key.length));
-               free_server_info(&server_info);
-               return False;
-       } else {
-               uchar p24[24];
-               NTLMSSPOWFencrypt(server_info->lm_session_key.data, lm_owf, p24);
-               {
-                       unsigned char j = 0;
-                       int ind;
-
-                       unsigned char k2[8];
+       prs_init( &outgoing_pdu, 0, p->mem_ctx, MARSHALL);
+       prs_give_memory( &outgoing_pdu, (char *)p->out_data.current_pdu, sizeof(p->out_data.current_pdu), False);
 
-                       memcpy(k2, p24, 5);
-                       k2[5] = 0xe5;
-                       k2[6] = 0x38;
-                       k2[7] = 0xb0;
+       /* Store the header in the data stream. */
+       if(!smb_io_rpc_hdr("hdr", &p->hdr, &outgoing_pdu, 0)) {
+               DEBUG(0,("create_next_pdu_schannel: failed to marshall RPC_HDR.\n"));
+               prs_mem_free(&outgoing_pdu);
+               return False;
+       }
 
-                       for (ind = 0; ind < 256; ind++)
-                               p->ntlmssp_hash[ind] = (unsigned char)ind;
+       if(!smb_io_rpc_hdr_resp("resp", &hdr_resp, &outgoing_pdu, 0)) {
+               DEBUG(0,("create_next_pdu_schannel: failed to marshall RPC_HDR_RESP.\n"));
+               prs_mem_free(&outgoing_pdu);
+               return False;
+       }
 
-                       for( ind = 0; ind < 256; ind++) {
-                               unsigned char tc;
+       /* Store the current offset. */
+       data_pos = prs_offset(&outgoing_pdu);
 
-                               j += (p->ntlmssp_hash[ind] + k2[ind%8]);
+       /* Copy the data into the PDU. */
 
-                               tc = p->ntlmssp_hash[ind];
-                               p->ntlmssp_hash[ind] = p->ntlmssp_hash[j];
-                               p->ntlmssp_hash[j] = tc;
-                       }
+       if(!prs_append_some_prs_data(&outgoing_pdu, &p->out_data.rdata, p->out_data.data_sent_length, data_len)) {
+               DEBUG(0,("create_next_pdu_schannel: failed to copy %u bytes of data.\n", (unsigned int)data_len));
+               prs_mem_free(&outgoing_pdu);
+               return False;
+       }
 
-                       p->ntlmssp_hash[256] = 0;
-                       p->ntlmssp_hash[257] = 0;
+       /* Copy the sign/seal padding data. */
+       if (ss_padding_len) {
+               char pad[8];
+               memset(pad, '\0', 8);
+               if (!prs_copy_data_in(&outgoing_pdu, pad, ss_padding_len)) {
+                       DEBUG(0,("create_next_pdu_schannel: failed to add %u bytes of pad data.\n", (unsigned int)ss_padding_len));
+                       prs_mem_free(&outgoing_pdu);
+                       return False;
                }
+       }
 
-               dump_data_pw("NTLMSSP hash (v1)\n", p->ntlmssp_hash, 
-                            sizeof(p->ntlmssp_hash));
-
-/*             NTLMSSPhash(p->ntlmssp_hash, p24); */
-               p->ntlmssp_seq_num = 0;
+       {
+               /*
+                * Schannel processing.
+                */
+               char *data;
+               RPC_HDR_AUTH auth_info;
+               RPC_AUTH_SCHANNEL_CHK verf;
 
-       }
+               data = prs_data_p(&outgoing_pdu) + data_pos;
+               /* Check it's the type of reply we were expecting to decode */
 
-       fstrcpy(p->user_name, user_name);
-       fstrcpy(p->pipe_user_name, server_info->unix_name);
-       fstrcpy(p->domain, domain);
-       fstrcpy(p->wks, wks);
+               init_rpc_hdr_auth(&auth_info,
+                               RPC_SCHANNEL_AUTH_TYPE,
+                               p->auth.auth_level == PIPE_AUTH_LEVEL_PRIVACY ?
+                                       RPC_AUTH_LEVEL_PRIVACY : RPC_AUTH_LEVEL_INTEGRITY,
+                               ss_padding_len, 1);
 
-       /*
-        * Store the UNIX credential data (uid/gid pair) in the pipe structure.
-        */
+               if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, &outgoing_pdu, 0)) {
+                       DEBUG(0,("create_next_pdu_schannel: failed to marshall RPC_HDR_AUTH.\n"));
+                       prs_mem_free(&outgoing_pdu);
+                       return False;
+               }
 
-       if (p->session_key.data) {
-               data_blob_free(&p->session_key);
-       }
-       p->session_key = data_blob(server_info->lm_session_key.data, server_info->lm_session_key.length);
+               schannel_encode(p->auth.a_u.schannel_auth, 
+                             p->auth.auth_level,
+                             SENDER_IS_ACCEPTOR,
+                             &verf, data, data_len + ss_padding_len);
 
-       p->pipe_user.uid = server_info->uid;
-       p->pipe_user.gid = server_info->gid;
-       
-       p->pipe_user.ngroups = server_info->n_groups;
-       if (p->pipe_user.ngroups) {
-               if (!(p->pipe_user.groups = memdup(server_info->groups, sizeof(gid_t) * p->pipe_user.ngroups))) {
-                       DEBUG(0,("failed to memdup group list to p->pipe_user.groups\n"));
-                       free_server_info(&server_info);
+               if (!smb_io_rpc_auth_schannel_chk("", RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN, 
+                               &verf, &outgoing_pdu, 0)) {
+                       prs_mem_free(&outgoing_pdu);
                        return False;
                }
-       }
 
-       if (server_info->ptok)
-               p->pipe_user.nt_user_token = dup_nt_token(server_info->ptok);
-       else {
-               DEBUG(1,("Error: Authmodule failed to provide nt_user_token\n"));
-               p->pipe_user.nt_user_token = NULL;
-               free_server_info(&server_info);
-               return False;
+               p->auth.a_u.schannel_auth->seq_num++;
        }
 
-       p->ntlmssp_auth_validated = True;
+       /*
+        * Setup the counts for this PDU.
+        */
+
+       p->out_data.data_sent_length += data_len;
+       p->out_data.current_pdu_len = p->hdr.frag_len;
+       p->out_data.current_pdu_sent = 0;
 
-       free_server_info(&server_info);
+       prs_mem_free(&outgoing_pdu);
        return True;
 }
 
 /*******************************************************************
- The switch table for the pipe names and the functions to handle them.
- *******************************************************************/
+ Generate the next PDU to be returned from the data in p->rdata. 
+ No authentication done.
+********************************************************************/
 
-struct rpc_table
+static BOOL create_next_pdu_noauth(pipes_struct *p)
 {
-  struct
-  {
-    const char *clnt;
-    const char *srv;
-  } pipe;
-  struct api_struct *cmds;
-  int n_cmds;
-};
+       RPC_HDR_RESP hdr_resp;
+       uint32 data_len;
+       uint32 data_space_available;
+       uint32 data_len_left;
+       prs_struct outgoing_pdu;
 
-static struct rpc_table *rpc_lookup;
-static int rpc_lookup_size;
+       /*
+        * If we're in the fault state, keep returning fault PDU's until
+        * the pipe gets closed. JRA.
+        */
 
-/*******************************************************************
- This is the client reply to our challenge for an authenticated 
- bind request. The challenge we sent is in p->challenge.
-*******************************************************************/
+       if(p->fault_state) {
+               setup_fault_pdu(p, NT_STATUS(0x1c010002));
+               return True;
+       }
 
-BOOL api_pipe_bind_auth_resp(pipes_struct *p, prs_struct *rpc_in_p)
-{
-       RPC_HDR_AUTHA autha_info;
-       RPC_AUTH_VERIFIER auth_verifier;
-       RPC_AUTH_NTLMSSP_RESP ntlmssp_resp;
+       memset((char *)&hdr_resp, '\0', sizeof(hdr_resp));
 
-       DEBUG(5,("api_pipe_bind_auth_resp: decode request. %d\n", __LINE__));
+       /* Change the incoming request header to a response. */
+       p->hdr.pkt_type = RPC_RESPONSE;
 
-       if (p->hdr.auth_len == 0) {
-               DEBUG(0,("api_pipe_bind_auth_resp: No auth field sent !\n"));
-               return False;
+       /* Set up rpc header flags. */
+       if (p->out_data.data_sent_length == 0) {
+               p->hdr.flags = RPC_FLG_FIRST;
+       } else {
+               p->hdr.flags = 0;
        }
 
        /*
-        * Decode the authentication verifier response.
+        * Work out how much we can fit in a single PDU.
+        */
+
+       data_len_left = prs_offset(&p->out_data.rdata) - p->out_data.data_sent_length;
+
+       /*
+        * Ensure there really is data left to send.
+        */
+
+       if(!data_len_left) {
+               DEBUG(0,("create_next_pdu_noath: no data left to send !\n"));
+               return False;
+       }
+
+       data_space_available = sizeof(p->out_data.current_pdu) - RPC_HEADER_LEN - RPC_HDR_RESP_LEN;
+
+       /*
+        * The amount we send is the minimum of the available
+        * space and the amount left to send.
+        */
+
+       data_len = MIN(data_len_left, data_space_available);
+
+       /*
+        * Set up the alloc hint. This should be the data left to
+        * send.
+        */
+
+       hdr_resp.alloc_hint = data_len_left;
+
+       /*
+        * Work out if this PDU will be the last.
         */
 
-       if(!smb_io_rpc_hdr_autha("", &autha_info, rpc_in_p, 0)) {
-               DEBUG(0,("api_pipe_bind_auth_resp: unmarshall of RPC_HDR_AUTHA failed.\n"));
+       if(p->out_data.data_sent_length + data_len >= prs_offset(&p->out_data.rdata)) {
+               p->hdr.flags |= RPC_FLG_LAST;
+       }
+
+       /*
+        * Set up the header lengths.
+        */
+
+       p->hdr.frag_len = RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len;
+       p->hdr.auth_len = 0;
+
+       /*
+        * Init the parse struct to point at the outgoing
+        * data.
+        */
+
+       prs_init( &outgoing_pdu, 0, p->mem_ctx, MARSHALL);
+       prs_give_memory( &outgoing_pdu, (char *)p->out_data.current_pdu, sizeof(p->out_data.current_pdu), False);
+
+       /* Store the header in the data stream. */
+       if(!smb_io_rpc_hdr("hdr", &p->hdr, &outgoing_pdu, 0)) {
+               DEBUG(0,("create_next_pdu_noath: failed to marshall RPC_HDR.\n"));
+               prs_mem_free(&outgoing_pdu);
                return False;
        }
 
-       if (autha_info.auth.auth_type != NTLMSSP_AUTH_TYPE || autha_info.auth.auth_level != RPC_PIPE_AUTH_SEAL_LEVEL) {
-               DEBUG(0,("api_pipe_bind_auth_resp: incorrect auth type (%d) or level (%d).\n",
-                       (int)autha_info.auth.auth_type, (int)autha_info.auth.auth_level ));
+       if(!smb_io_rpc_hdr_resp("resp", &hdr_resp, &outgoing_pdu, 0)) {
+               DEBUG(0,("create_next_pdu_noath: failed to marshall RPC_HDR_RESP.\n"));
+               prs_mem_free(&outgoing_pdu);
                return False;
        }
 
-       if(!smb_io_rpc_auth_verifier("", &auth_verifier, rpc_in_p, 0)) {
-               DEBUG(0,("api_pipe_bind_auth_resp: unmarshall of RPC_AUTH_VERIFIER failed.\n"));
+       /* Copy the data into the PDU. */
+
+       if(!prs_append_some_prs_data(&outgoing_pdu, &p->out_data.rdata, p->out_data.data_sent_length, data_len)) {
+               DEBUG(0,("create_next_pdu_noauth: failed to copy %u bytes of data.\n", (unsigned int)data_len));
+               prs_mem_free(&outgoing_pdu);
                return False;
        }
 
        /*
-        * Ensure this is a NTLMSSP_AUTH packet type.
+        * Setup the counts for this PDU.
         */
 
-       if (!rpc_auth_verifier_chk(&auth_verifier, "NTLMSSP", NTLMSSP_AUTH)) {
-               DEBUG(0,("api_pipe_bind_auth_resp: rpc_auth_verifier_chk failed.\n"));
+       p->out_data.data_sent_length += data_len;
+       p->out_data.current_pdu_len = p->hdr.frag_len;
+       p->out_data.current_pdu_sent = 0;
+
+       prs_mem_free(&outgoing_pdu);
+       return True;
+}
+
+/*******************************************************************
+ Generate the next PDU to be returned from the data in p->rdata. 
+********************************************************************/
+
+BOOL create_next_pdu(pipes_struct *p)
+{
+       switch(p->auth.auth_level) {
+               case PIPE_AUTH_LEVEL_NONE:
+               case PIPE_AUTH_LEVEL_CONNECT:
+                       /* This is incorrect for auth level connect. Fixme. JRA */
+                       return create_next_pdu_noauth(p);
+               
+               default:
+                       switch(p->auth.auth_type) {
+                               case PIPE_AUTH_TYPE_NTLMSSP:
+                               case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
+                                       return create_next_pdu_ntlmssp(p);
+                               case PIPE_AUTH_TYPE_SCHANNEL:
+                                       return create_next_pdu_schannel(p);
+                               default:
+                                       break;
+                       }
+       }
+
+       DEBUG(0,("create_next_pdu: invalid internal auth level %u / type %u",
+                       (unsigned int)p->auth.auth_level,
+                       (unsigned int)p->auth.auth_type));
+       return False;
+}
+
+/*******************************************************************
+ Process an NTLMSSP authentication response.
+ If this function succeeds, the user has been authenticated
+ and their domain, name and calling workstation stored in
+ the pipe struct.
+*******************************************************************/
+
+static BOOL pipe_ntlmssp_verify_final(pipes_struct *p, DATA_BLOB *p_resp_blob)
+{
+       DATA_BLOB reply;
+       NTSTATUS status;
+       AUTH_NTLMSSP_STATE *a = p->auth.a_u.auth_ntlmssp_state;
+
+       DEBUG(5,("pipe_ntlmssp_verify_final: checking user details\n"));
+
+       ZERO_STRUCT(reply);
+
+       memset(p->user_name, '\0', sizeof(p->user_name));
+       memset(p->pipe_user_name, '\0', sizeof(p->pipe_user_name));
+       memset(p->domain, '\0', sizeof(p->domain));
+       memset(p->wks, '\0', sizeof(p->wks));
+
+       /* Set up for non-authenticated user. */
+       delete_nt_token(&p->pipe_user.nt_user_token);
+       p->pipe_user.ngroups = 0;
+       SAFE_FREE( p->pipe_user.groups);
+
+       status = auth_ntlmssp_update(a, *p_resp_blob, &reply);
+
+       /* Don't generate a reply. */
+       data_blob_free(&reply);
+
+       if (!NT_STATUS_IS_OK(status)) {
                return False;
        }
 
-       if(!smb_io_rpc_auth_ntlmssp_resp("", &ntlmssp_resp, rpc_in_p, 0)) {
-               DEBUG(0,("api_pipe_bind_auth_resp: Failed to unmarshall RPC_AUTH_NTLMSSP_RESP.\n"));
+       fstrcpy(p->user_name, a->ntlmssp_state->user);
+       fstrcpy(p->pipe_user_name, a->server_info->unix_name);
+       fstrcpy(p->domain, a->ntlmssp_state->domain);
+       fstrcpy(p->wks, a->ntlmssp_state->workstation);
+
+       DEBUG(5,("pipe_ntlmssp_verify_final: OK: user: %s domain: %s workstation: %s\n",
+               p->user_name, p->domain, p->wks));
+
+       /*
+        * Store the UNIX credential data (uid/gid pair) in the pipe structure.
+        */
+
+       p->pipe_user.uid = a->server_info->uid;
+       p->pipe_user.gid = a->server_info->gid;
+       
+       /*
+        * Copy the session key from the ntlmssp state.
+        */
+
+       data_blob_free(&p->session_key);
+       p->session_key = data_blob(a->ntlmssp_state->session_key.data, a->ntlmssp_state->session_key.length);
+       if (!p->session_key.data) {
                return False;
        }
 
+       p->pipe_user.ngroups = a->server_info->n_groups;
+       if (p->pipe_user.ngroups) {
+               if (!(p->pipe_user.groups = memdup(a->server_info->groups, sizeof(gid_t) * p->pipe_user.ngroups))) {
+                       DEBUG(0,("failed to memdup group list to p->pipe_user.groups\n"));
+                       return False;
+               }
+       }
+
+       if (a->server_info->ptok) {
+               p->pipe_user.nt_user_token = dup_nt_token(a->server_info->ptok);
+       } else {
+               DEBUG(1,("Error: Authmodule failed to provide nt_user_token\n"));
+               p->pipe_user.nt_user_token = NULL;
+               return False;
+       }
+
+       return True;
+}
+
+/*******************************************************************
+ The switch table for the pipe names and the functions to handle them.
+*******************************************************************/
+
+struct rpc_table {
+       struct {
+               const char *clnt;
+               const char *srv;
+       } pipe;
+       struct api_struct *cmds;
+       int n_cmds;
+};
+
+static struct rpc_table *rpc_lookup;
+static int rpc_lookup_size;
+
+/*******************************************************************
+ This is the "stage3" NTLMSSP response after a bind request and reply.
+*******************************************************************/
+
+BOOL api_pipe_bind_auth3(pipes_struct *p, prs_struct *rpc_in_p)
+{
+       RPC_HDR_AUTH auth_info;
+       uint32 pad;
+       DATA_BLOB blob;
+
+       ZERO_STRUCT(blob);
+
+       DEBUG(5,("api_pipe_bind_auth3: decode request. %d\n", __LINE__));
+
+       if (p->hdr.auth_len == 0) {
+               DEBUG(0,("api_pipe_bind_auth3: No auth field sent !\n"));
+               goto err;
+       }
+
+       /* 4 bytes padding. */
+       if (!prs_uint32("pad", rpc_in_p, 0, &pad)) {
+               DEBUG(0,("api_pipe_bind_auth3: unmarshall of 4 byte pad failed.\n"));
+               goto err;
+       }
+
+       /*
+        * Decode the authentication verifier response.
+        */
+
+       if(!smb_io_rpc_hdr_auth("", &auth_info, rpc_in_p, 0)) {
+               DEBUG(0,("api_pipe_bind_auth3: unmarshall of RPC_HDR_AUTH failed.\n"));
+               goto err;
+       }
+
+       if (auth_info.auth_type != RPC_NTLMSSP_AUTH_TYPE) {
+               DEBUG(0,("api_pipe_bind_auth3: incorrect auth type (%u).\n",
+                       (unsigned int)auth_info.auth_type ));
+               return False;
+       }
+
+       blob = data_blob(NULL,p->hdr.auth_len);
+
+       if (!prs_copy_data_out(blob.data, rpc_in_p, p->hdr.auth_len)) {
+               DEBUG(0,("api_pipe_bind_auth3: Failed to pull %u bytes - the response blob.\n",
+                       (unsigned int)p->hdr.auth_len ));
+               goto err;
+       }
+
        /*
         * The following call actually checks the challenge/response data.
         * for correctness against the given DOMAIN\user name.
         */
        
-       if (!api_pipe_ntlmssp_verify(p, &ntlmssp_resp))
-               return False;
+       if (!pipe_ntlmssp_verify_final(p, &blob)) {
+               goto err;
+       }
+
+       data_blob_free(&blob);
+
+       p->pipe_bound = True;
 
-       p->pipe_bound = True
-;
        return True;
+
+ err:
+
+       data_blob_free(&blob);
+       free_pipe_ntlmssp_auth_data(&p->auth);
+       p->auth.a_u.auth_ntlmssp_state = NULL;
+
+       return False;
 }
 
 /*******************************************************************
@@ -642,13 +792,12 @@ static BOOL setup_bind_nak(pipes_struct *p)
        prs_init( &outgoing_rpc, 0, p->mem_ctx, MARSHALL);
        prs_give_memory( &outgoing_rpc, (char *)p->out_data.current_pdu, sizeof(p->out_data.current_pdu), False);
 
-
        /*
         * Initialize a bind_nak header.
         */
 
        init_rpc_hdr(&nak_hdr, RPC_BINDNACK, RPC_FLG_FIRST | RPC_FLG_LAST,
-            p->hdr.call_id, RPC_HEADER_LEN + sizeof(uint16), 0);
+               p->hdr.call_id, RPC_HEADER_LEN + sizeof(uint16), 0);
 
        /*
         * Marshall the header into the outgoing PDU.
@@ -673,6 +822,11 @@ static BOOL setup_bind_nak(pipes_struct *p)
        p->out_data.current_pdu_len = prs_offset(&outgoing_rpc);
        p->out_data.current_pdu_sent = 0;
 
+       if (p->auth.auth_data_free_func) {
+               (*p->auth.auth_data_free_func)(&p->auth);
+       }
+       p->auth.auth_level = PIPE_AUTH_LEVEL_NONE;
+       p->auth.auth_type = PIPE_AUTH_TYPE_NONE;
        p->pipe_bound = False;
 
        return True;
@@ -766,15 +920,13 @@ BOOL check_bind_req(struct pipes_struct *p, RPC_IFACE* abstract,
 
        /* we have to check all now since win2k introduced a new UUID on the lsaprpc pipe */
                
-       for ( i=0; pipe_names[i].client_pipe; i++ ) 
-       {
+       for ( i=0; pipe_names[i].client_pipe; i++ ) {
                DEBUG(10,("checking %s\n", pipe_names[i].client_pipe));
                if ( strequal(pipe_names[i].client_pipe, pname)
                        && (abstract->version == pipe_names[i].abstr_syntax.version) 
                        && (memcmp(&abstract->uuid, &pipe_names[i].abstr_syntax.uuid, sizeof(struct uuid)) == 0)
                        && (transfer->version == pipe_names[i].trans_syntax.version)
-                       && (memcmp(&transfer->uuid, &pipe_names[i].trans_syntax.uuid, sizeof(struct uuid)) == 0) )
-               {
+                       && (memcmp(&transfer->uuid, &pipe_names[i].trans_syntax.uuid, sizeof(struct uuid)) == 0) ) {
                        struct api_struct       *fns = NULL;
                        int                     n_fns = 0;
                        PIPE_RPC_FNS            *context_fns;
@@ -800,8 +952,9 @@ BOOL check_bind_req(struct pipes_struct *p, RPC_IFACE* abstract,
                }
        }
 
-       if(pipe_names[i].client_pipe == NULL)
+       if(pipe_names[i].client_pipe == NULL) {
                return False;
+       }
 
        return True;
 }
@@ -809,6 +962,7 @@ BOOL check_bind_req(struct pipes_struct *p, RPC_IFACE* abstract,
 /*******************************************************************
  Register commands to an RPC pipe
 *******************************************************************/
+
 NTSTATUS rpc_pipe_register_commands(int version, const char *clnt, const char *srv, const struct api_struct *cmds, int size)
 {
         struct rpc_table *rpc_entry;
@@ -856,6 +1010,365 @@ NTSTATUS rpc_pipe_register_commands(int version, const char *clnt, const char *s
         return NT_STATUS_OK;
 }
 
+/*******************************************************************
+ Handle a SPNEGO krb5 bind auth.
+*******************************************************************/
+
+static BOOL pipe_spnego_auth_bind_kerberos(pipes_struct *p, prs_struct *rpc_in_p, RPC_HDR_AUTH *pauth_info,
+               DATA_BLOB *psecblob, prs_struct *pout_auth)
+{
+       return False;
+}
+
+/*******************************************************************
+ Handle the first part of a SPNEGO bind auth.
+*******************************************************************/
+
+static BOOL pipe_spnego_auth_bind_negotiate(pipes_struct *p, prs_struct *rpc_in_p,
+                                       RPC_HDR_AUTH *pauth_info, prs_struct *pout_auth)
+{
+       DATA_BLOB blob;
+       DATA_BLOB secblob;
+       DATA_BLOB response;
+       DATA_BLOB chal;
+       char *OIDs[ASN1_MAX_OIDS];
+        int i;
+       NTSTATUS status;
+        BOOL got_kerberos_mechanism = False;
+       AUTH_NTLMSSP_STATE *a = NULL;
+       RPC_HDR_AUTH auth_info;
+
+       ZERO_STRUCT(secblob);
+       ZERO_STRUCT(chal);
+       ZERO_STRUCT(response);
+
+       /* Grab the SPNEGO blob. */
+       blob = data_blob(NULL,p->hdr.auth_len);
+
+       if (!prs_copy_data_out(blob.data, rpc_in_p, p->hdr.auth_len)) {
+               DEBUG(0,("pipe_spnego_auth_bind_negotiate: Failed to pull %u bytes - the SPNEGO auth header.\n",
+                       (unsigned int)p->hdr.auth_len ));
+               goto err;
+       }
+
+       if (blob.data[0] != ASN1_APPLICATION(0)) {
+               goto err;
+       }
+
+       /* parse out the OIDs and the first sec blob */
+       if (!parse_negTokenTarg(blob, OIDs, &secblob)) {
+               DEBUG(0,("pipe_spnego_auth_bind_negotiate: Failed to parse the security blob.\n"));
+               goto err;
+        }
+
+       if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 || strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
+               got_kerberos_mechanism = True;
+       }
+
+       for (i=0;OIDs[i];i++) {
+               DEBUG(3,("pipe_spnego_auth_bind_negotiate: Got OID %s\n", OIDs[i]));
+               SAFE_FREE(OIDs[i]);
+       }
+       DEBUG(3,("pipe_spnego_auth_bind_negotiate: Got secblob of size %lu\n", (unsigned long)secblob.length));
+
+       if ( got_kerberos_mechanism && ((lp_security()==SEC_ADS) || lp_use_kerberos_keytab()) ) {
+               BOOL ret = pipe_spnego_auth_bind_kerberos(p, rpc_in_p, pauth_info, &secblob, pout_auth);
+               data_blob_free(&secblob);
+               data_blob_free(&blob);
+               return ret;
+       }
+
+       if (p->auth.auth_type == PIPE_AUTH_TYPE_SPNEGO_NTLMSSP && p->auth.a_u.auth_ntlmssp_state) {
+               /* Free any previous auth type. */
+               free_pipe_ntlmssp_auth_data(&p->auth);
+       }
+
+       /* Initialize the NTLM engine. */
+       status = auth_ntlmssp_start(&a);
+       if (!NT_STATUS_IS_OK(status)) {
+               goto err;
+       }
+
+       /*
+        * Pass the first security blob of data to it.
+        * This can return an error or NT_STATUS_MORE_PROCESSING_REQUIRED
+        * which means we need another packet to complete the bind.
+        */
+
+        status = auth_ntlmssp_update(a, secblob, &chal);
+
+       if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
+               DEBUG(3,("pipe_spnego_auth_bind_negotiate: auth_ntlmssp_update failed.\n"));
+               goto err;
+       }
+
+       /* Generate the response blob we need for step 2 of the bind. */
+       response = spnego_gen_auth_response(&chal, status, OID_NTLMSSP);
+
+       /* Copy the blob into the pout_auth parse struct */
+       init_rpc_hdr_auth(&auth_info, RPC_SPNEGO_AUTH_TYPE, pauth_info->auth_level, RPC_HDR_AUTH_LEN, 1);
+       if(!smb_io_rpc_hdr_auth("", &auth_info, pout_auth, 0)) {
+               DEBUG(0,("pipe_spnego_auth_bind_negotiate: marshalling of RPC_HDR_AUTH failed.\n"));
+               goto err;
+       }
+
+       if (!prs_copy_data_in(pout_auth, response.data, response.length)) {
+               DEBUG(0,("pipe_spnego_auth_bind_negotiate: marshalling of data blob failed.\n"));
+               goto err;
+       }
+
+       p->auth.a_u.auth_ntlmssp_state = a;
+       p->auth.auth_data_free_func = &free_pipe_ntlmssp_auth_data;
+       p->auth.auth_type = PIPE_AUTH_TYPE_SPNEGO_NTLMSSP;
+
+       data_blob_free(&blob);
+       data_blob_free(&secblob);
+       data_blob_free(&chal);
+       data_blob_free(&response);
+
+       /* We can't set pipe_bound True yet - we need an RPC_ALTER_CONTEXT response packet... */
+       return True;
+
+ err:
+
+       data_blob_free(&blob);
+       data_blob_free(&secblob);
+       data_blob_free(&chal);
+       data_blob_free(&response);
+
+       p->auth.a_u.auth_ntlmssp_state = NULL;
+
+       return False;
+}
+
+/*******************************************************************
+ Handle the second part of a SPNEGO bind auth.
+*******************************************************************/
+
+static BOOL pipe_spnego_auth_bind_continue(pipes_struct *p, prs_struct *rpc_in_p,
+                                       RPC_HDR_AUTH *pauth_info, prs_struct *pout_auth)
+{
+       DATA_BLOB spnego_blob, auth_blob, auth_reply;
+       AUTH_NTLMSSP_STATE *a = p->auth.a_u.auth_ntlmssp_state;
+
+       ZERO_STRUCT(spnego_blob);
+       ZERO_STRUCT(auth_blob);
+       ZERO_STRUCT(auth_reply);
+
+       if (p->auth.auth_type != PIPE_AUTH_TYPE_SPNEGO_NTLMSSP || !a) {
+               DEBUG(0,("pipe_spnego_auth_bind_continue: not in NTLMSSP auth state.\n"));
+               goto err;
+       }
+
+       /* Grab the SPNEGO blob. */
+       spnego_blob = data_blob(NULL,p->hdr.auth_len);
+
+       if (!prs_copy_data_out(spnego_blob.data, rpc_in_p, p->hdr.auth_len)) {
+               DEBUG(0,("pipe_spnego_auth_bind_continue: Failed to pull %u bytes - the SPNEGO auth header.\n",
+                       (unsigned int)p->hdr.auth_len ));
+               goto err;
+       }
+
+       if (spnego_blob.data[0] != ASN1_CONTEXT(1)) {
+               DEBUG(0,("pipe_spnego_auth_bind_continue: invalid SPNEGO blob type.\n"));
+               goto err;
+       }
+
+       if (!spnego_parse_auth(spnego_blob, &auth_blob)) {
+               DEBUG(0,("pipe_spnego_auth_bind_continue: invalid SPNEGO blob.\n"));
+               goto err;
+       }
+
+       /*
+        * The following call actually checks the challenge/response data.
+        * for correctness against the given DOMAIN\user name.
+        */
+       
+       if (!pipe_ntlmssp_verify_final(p, &auth_blob)) {
+               goto err;
+       }
+
+       data_blob_free(&spnego_blob);
+       data_blob_free(&auth_blob);
+       data_blob_free(&auth_reply);
+
+       p->pipe_bound = True;
+
+       return True;
+
+ err:
+
+       data_blob_free(&spnego_blob);
+       data_blob_free(&auth_blob);
+       data_blob_free(&auth_reply);
+
+       free_pipe_ntlmssp_auth_data(&p->auth);
+       p->auth.a_u.auth_ntlmssp_state = NULL;
+
+       return False;
+}
+
+/*******************************************************************
+ Handle an schannel bind auth.
+*******************************************************************/
+
+static BOOL pipe_schannel_auth_bind(pipes_struct *p, prs_struct *rpc_in_p,
+                                       RPC_HDR_AUTH *pauth_info, prs_struct *pout_auth)
+{
+       RPC_HDR_AUTH auth_info;
+       RPC_AUTH_SCHANNEL_NEG neg;
+       RPC_AUTH_VERIFIER auth_verifier;
+       uint32 flags;
+
+       if (!server_auth2_negotiated) {
+               DEBUG(0, ("pipe_schannel_auth_bind: Attempt to bind using schannel without successful serverauth2\n"));
+               return False;
+       }
+
+       if (!smb_io_rpc_auth_schannel_neg("", &neg, rpc_in_p, 0)) {
+               DEBUG(0,("pipe_schannel_auth_bind: Could not unmarshal SCHANNEL auth neg\n"));
+               return False;
+       }
+
+       p->auth.a_u.schannel_auth = TALLOC_P(p->pipe_state_mem_ctx, struct schannel_auth_struct);
+       if (!p->auth.a_u.schannel_auth) {
+               return False;
+       }
+
+       memset(p->auth.a_u.schannel_auth->sess_key, 0, sizeof(p->auth.a_u.schannel_auth->sess_key));
+       memcpy(p->auth.a_u.schannel_auth->sess_key, last_dcinfo.sess_key, sizeof(last_dcinfo.sess_key));
+
+       p->auth.a_u.schannel_auth->seq_num = 0;
+
+       /*
+        * JRA. Should we also copy the schannel session key into the pipe session key p->session_key
+        * here ? We do that for NTLMSPP, but the session key is already set up from the vuser
+        * struct of the person who opened the pipe. I need to test this further. JRA.
+        */
+
+       /* The client opens a second RPC NETLOGON pipe without
+               doing a auth2. The credentials for the schannel are
+               re-used from the auth2 the client did before. */
+       p->dc = TALLOC_ZERO_P(p->pipe_state_mem_ctx, struct dcinfo);
+       if (!p->dc) {
+               return False;
+       }
+       *p->dc = last_dcinfo;
+
+       init_rpc_hdr_auth(&auth_info, RPC_SCHANNEL_AUTH_TYPE, pauth_info->auth_level, RPC_HDR_AUTH_LEN, 1);
+       if(!smb_io_rpc_hdr_auth("", &auth_info, pout_auth, 0)) {
+               DEBUG(0,("pipe_schannel_auth_bind: marshalling of RPC_HDR_AUTH failed.\n"));
+               return False;
+       }
+
+       /*** SCHANNEL verifier ***/
+
+       init_rpc_auth_verifier(&auth_verifier, "\001", 0x0);
+       if(!smb_io_rpc_schannel_verifier("", &auth_verifier, pout_auth, 0)) {
+               DEBUG(0,("pipe_schannel_auth_bind: marshalling of RPC_AUTH_VERIFIER failed.\n"));
+               return False;
+       }
+
+       prs_align(pout_auth);
+
+       flags = 5;
+       if(!prs_uint32("flags ", pout_auth, 0, &flags)) {
+               return False;
+       }
+
+       DEBUG(10,("pipe_schannel_auth_bind: schannel auth: domain [%s] myname [%s]\n",
+               neg.domain, neg.myname));
+
+       /* We're finished with this bind - no more packets. */
+       p->auth.auth_data_free_func = NULL;
+       p->auth.auth_type = PIPE_AUTH_TYPE_SCHANNEL;
+
+       p->pipe_bound = True;
+
+       return True;
+}
+
+/*******************************************************************
+ Handle an NTLMSSP bind auth.
+*******************************************************************/
+
+static BOOL pipe_ntlmssp_auth_bind(pipes_struct *p, prs_struct *rpc_in_p,
+                                       RPC_HDR_AUTH *pauth_info, prs_struct *pout_auth)
+{
+       RPC_HDR_AUTH auth_info;
+        DATA_BLOB blob;
+       DATA_BLOB response;
+        NTSTATUS status;
+       AUTH_NTLMSSP_STATE *a = NULL;
+
+       ZERO_STRUCT(blob);
+       ZERO_STRUCT(response);
+
+       /* Grab the NTLMSSP blob. */
+       blob = data_blob(NULL,p->hdr.auth_len);
+
+       if (!prs_copy_data_out(blob.data, rpc_in_p, p->hdr.auth_len)) {
+               DEBUG(0,("pipe_ntlmssp_auth_bind: Failed to pull %u bytes - the NTLM auth header.\n",
+                       (unsigned int)p->hdr.auth_len ));
+               goto err;
+       }
+
+       if (strncmp(blob.data, "NTLMSSP", 7) != 0) {
+               DEBUG(0,("pipe_ntlmssp_auth_bind: Failed to read NTLMSSP in blob\n"));
+                goto err;
+        }
+
+       /* We have an NTLMSSP blob. */
+       status = auth_ntlmssp_start(&a);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0,("pipe_ntlmssp_auth_bind: auth_ntlmssp_start failed: %s\n",
+                       nt_errstr(status) ));
+               goto err;
+       }
+
+       status = auth_ntlmssp_update(a, blob, &response);
+       if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
+               DEBUG(0,("pipe_ntlmssp_auth_bind: auth_ntlmssp_update failed: %s\n",
+                       nt_errstr(status) ));
+               goto err;
+       }
+
+       data_blob_free(&blob);
+
+       /* Copy the blob into the pout_auth parse struct */
+       init_rpc_hdr_auth(&auth_info, RPC_NTLMSSP_AUTH_TYPE, pauth_info->auth_level, RPC_HDR_AUTH_LEN, 1);
+       if(!smb_io_rpc_hdr_auth("", &auth_info, pout_auth, 0)) {
+               DEBUG(0,("pipe_ntlmssp_auth_bind: marshalling of RPC_HDR_AUTH failed.\n"));
+               goto err;
+       }
+
+       if (!prs_copy_data_in(pout_auth, response.data, response.length)) {
+               DEBUG(0,("pipe_ntlmssp_auth_bind: marshalling of data blob failed.\n"));
+               goto err;
+       }
+
+       p->auth.a_u.auth_ntlmssp_state = a;
+       p->auth.auth_data_free_func = &free_pipe_ntlmssp_auth_data;
+       p->auth.auth_type = PIPE_AUTH_TYPE_NTLMSSP;
+
+       data_blob_free(&blob);
+       data_blob_free(&response);
+
+       DEBUG(10,("pipe_ntlmssp_auth_bind: NTLMSSP auth started\n"));
+
+       /* We can't set pipe_bound True yet - we need an RPC_AUTH3 response packet... */
+       return True;
+
+  err:
+
+       data_blob_free(&blob);
+       data_blob_free(&response);
+
+       free_pipe_ntlmssp_auth_data(&p->auth);
+       p->auth.a_u.auth_ntlmssp_state = NULL;
+       return False;
+}
+
 /*******************************************************************
  Respond to a pipe bind request.
 *******************************************************************/
@@ -872,162 +1385,280 @@ BOOL api_pipe_bind_req(pipes_struct *p, prs_struct *rpc_in_p)
        prs_struct outgoing_rpc;
        int i = 0;
        int auth_len = 0;
-       enum RPC_PKT_TYPE reply_pkt_type;
+       unsigned int auth_type = RPC_ANONYMOUS_AUTH_TYPE;
+
+       /* No rebinds on a bound pipe - use alter context. */
+       if (p->pipe_bound) {
+               DEBUG(2,("api_pipe_bind_req: rejecting bind request on bound pipe %s.\n", p->pipe_srv_name));
+               return setup_bind_nak(p);
+       }
 
-       p->ntlmssp_auth_requested = False;
-       p->netsec_auth_validated = False;
+       prs_init( &outgoing_rpc, 0, p->mem_ctx, MARSHALL);
+
+       /* 
+        * Marshall directly into the outgoing PDU space. We
+        * must do this as we need to set to the bind response
+        * header and are never sending more than one PDU here.
+        */
+
+       prs_give_memory( &outgoing_rpc, (char *)p->out_data.current_pdu, sizeof(p->out_data.current_pdu), False);
+
+       /*
+        * Setup the memory to marshall the ba header, and the
+        * auth footers.
+        */
+
+       if(!prs_init(&out_hdr_ba, 1024, p->mem_ctx, MARSHALL)) {
+               DEBUG(0,("api_pipe_bind_req: malloc out_hdr_ba failed.\n"));
+               prs_mem_free(&outgoing_rpc);
+               return False;
+       }
+
+       if(!prs_init(&out_auth, 1024, p->mem_ctx, MARSHALL)) {
+               DEBUG(0,("api_pipe_bind_req: malloc out_auth failed.\n"));
+               prs_mem_free(&outgoing_rpc);
+               prs_mem_free(&out_hdr_ba);
+               return False;
+       }
 
        DEBUG(5,("api_pipe_bind_req: decode request. %d\n", __LINE__));
 
        /*
-        * Try and find the correct pipe name to ensure
-        * that this is a pipe name we support.
+        * Try and find the correct pipe name to ensure
+        * that this is a pipe name we support.
+        */
+
+
+       for (i = 0; i < rpc_lookup_size; i++) {
+               if (strequal(rpc_lookup[i].pipe.clnt, p->name)) {
+                       DEBUG(3, ("api_pipe_bind_req: \\PIPE\\%s -> \\PIPE\\%s\n",
+                               rpc_lookup[i].pipe.clnt, rpc_lookup[i].pipe.srv));
+                       fstrcpy(p->pipe_srv_name, rpc_lookup[i].pipe.srv);
+                       break;
+               }
+       }
+
+       if (i == rpc_lookup_size) {
+               if (NT_STATUS_IS_ERR(smb_probe_module("rpc", p->name))) {
+                       DEBUG(3,("api_pipe_bind_req: Unknown pipe name %s in bind request.\n",
+                                p->name ));
+                       prs_mem_free(&outgoing_rpc);
+                       prs_mem_free(&out_hdr_ba);
+                       prs_mem_free(&out_auth);
+
+                       return setup_bind_nak(p);
+                }
+
+                for (i = 0; i < rpc_lookup_size; i++) {
+                       if (strequal(rpc_lookup[i].pipe.clnt, p->name)) {
+                               DEBUG(3, ("api_pipe_bind_req: \\PIPE\\%s -> \\PIPE\\%s\n",
+                                         rpc_lookup[i].pipe.clnt, rpc_lookup[i].pipe.srv));
+                               fstrcpy(p->pipe_srv_name, rpc_lookup[i].pipe.srv);
+                               break;
+                       }
+                }
+
+               if (i == rpc_lookup_size) {
+                       DEBUG(0, ("module %s doesn't provide functions for pipe %s!\n", p->name, p->name));
+                       goto err_exit;
+               }
+       }
+
+       /* decode the bind request */
+       if(!smb_io_rpc_hdr_rb("", &hdr_rb, rpc_in_p, 0))  {
+               DEBUG(0,("api_pipe_bind_req: unable to unmarshall RPC_HDR_RB struct.\n"));
+               goto err_exit;
+       }
+
+       /* name has to be \PIPE\xxxxx */
+       fstrcpy(ack_pipe_name, "\\PIPE\\");
+       fstrcat(ack_pipe_name, p->pipe_srv_name);
+
+       DEBUG(5,("api_pipe_bind_req: make response. %d\n", __LINE__));
+
+       /*
+        * Check if this is an authenticated bind request.
+        */
+
+       if (p->hdr.auth_len) {
+               /* 
+                * Decode the authentication verifier.
+                */
+
+               if(!smb_io_rpc_hdr_auth("", &auth_info, rpc_in_p, 0)) {
+                       DEBUG(0,("api_pipe_bind_req: unable to unmarshall RPC_HDR_AUTH struct.\n"));
+                       goto err_exit;
+               }
+
+               auth_type = auth_info.auth_type;
+
+               /* Work out if we have to sign or seal etc. */
+               switch (auth_info.auth_level) {
+                       case RPC_AUTH_LEVEL_INTEGRITY:
+                               p->auth.auth_level = PIPE_AUTH_LEVEL_INTEGRITY;
+                               break;
+                       case RPC_AUTH_LEVEL_PRIVACY:
+                               p->auth.auth_level = PIPE_AUTH_LEVEL_PRIVACY;
+                               break;
+                       default:
+                               DEBUG(0,("api_pipe_bind_req: unexpected auth level (%u).\n",
+                                       (unsigned int)auth_info.auth_level ));
+                               goto err_exit;
+               }
+       } else {
+               ZERO_STRUCT(auth_info);
+       }
+
+       assoc_gid = hdr_rb.bba.assoc_gid ? hdr_rb.bba.assoc_gid : 0x53f0;
+
+       switch(auth_type) {
+               case RPC_NTLMSSP_AUTH_TYPE:
+                       if (!pipe_ntlmssp_auth_bind(p, rpc_in_p, &auth_info, &out_auth)) {
+                               goto err_exit;
+                       }
+                       assoc_gid = 0x7a77;
+                       break;
+
+               case RPC_SCHANNEL_AUTH_TYPE:
+                       if (!pipe_schannel_auth_bind(p, rpc_in_p, &auth_info, &out_auth)) {
+                               goto err_exit;
+                       }
+                       break;
+
+               case RPC_SPNEGO_AUTH_TYPE:
+                       if (!pipe_spnego_auth_bind_negotiate(p, rpc_in_p, &auth_info, &out_auth)) {
+                               goto err_exit;
+                       }
+                       break;
+
+               case RPC_ANONYMOUS_AUTH_TYPE:
+                       /* Unauthenticated bind request. */
+                       /* We're finished - no more packets. */
+                       p->auth.auth_type = PIPE_AUTH_TYPE_NONE;
+                       /* We must set the pipe auth_level here also. */
+                       p->auth.auth_level = PIPE_AUTH_LEVEL_NONE;
+                       p->pipe_bound = True;
+                       break;
+
+               default:
+                       DEBUG(0,("api_pipe_bind_req: unknown auth type %x requested.\n", auth_type ));
+                       goto err_exit;
+       }
+
+       /*
+        * Create the bind response struct.
+        */
+
+       /* If the requested abstract synt uuid doesn't match our client pipe,
+               reject the bind_ack & set the transfer interface synt to all 0's,
+               ver 0 (observed when NT5 attempts to bind to abstract interfaces
+               unknown to NT4)
+               Needed when adding entries to a DACL from NT5 - SK */
+
+       if(check_bind_req(p, &hdr_rb.rpc_context[0].abstract, &hdr_rb.rpc_context[0].transfer[0],
+                               hdr_rb.rpc_context[0].context_id )) {
+               init_rpc_hdr_ba(&hdr_ba,
+                       RPC_MAX_PDU_FRAG_LEN,
+                       RPC_MAX_PDU_FRAG_LEN,
+                       assoc_gid,
+                       ack_pipe_name,
+                       0x1, 0x0, 0x0,
+                       &hdr_rb.rpc_context[0].transfer[0]);
+       } else {
+               RPC_IFACE null_interface;
+               ZERO_STRUCT(null_interface);
+               /* Rejection reason: abstract syntax not supported */
+               init_rpc_hdr_ba(&hdr_ba, RPC_MAX_PDU_FRAG_LEN,
+                                       RPC_MAX_PDU_FRAG_LEN, assoc_gid,
+                                       ack_pipe_name, 0x1, 0x2, 0x1,
+                                       &null_interface);
+               p->pipe_bound = False;
+       }
+
+       /*
+        * and marshall it.
         */
 
-
-       for (i = 0; i < rpc_lookup_size; i++) {
-               if (strequal(rpc_lookup[i].pipe.clnt, p->name)) {
-                  DEBUG(3, ("api_pipe_bind_req: \\PIPE\\%s -> \\PIPE\\%s\n",
-                            rpc_lookup[i].pipe.clnt, rpc_lookup[i].pipe.srv));
-                  fstrcpy(p->pipe_srv_name, rpc_lookup[i].pipe.srv);
-                  break;
-                }
+       if(!smb_io_rpc_hdr_ba("", &hdr_ba, &out_hdr_ba, 0)) {
+               DEBUG(0,("api_pipe_bind_req: marshalling of RPC_HDR_BA failed.\n"));
+               goto err_exit;
        }
 
-       if (i == rpc_lookup_size) {
-               if (NT_STATUS_IS_ERR(smb_probe_module("rpc", p->name))) {
-                       DEBUG(3,("api_pipe_bind_req: Unknown pipe name %s in bind request.\n",
-                               p->name ));
-                       return setup_bind_nak(p);
-                }
-
-                for (i = 0; i < rpc_lookup_size; i++) {
-                       if (strequal(rpc_lookup[i].pipe.clnt, p->name)) {
-                               DEBUG(3, ("api_pipe_bind_req: \\PIPE\\%s -> \\PIPE\\%s\n",
-                                         rpc_lookup[i].pipe.clnt, rpc_lookup[i].pipe.srv));
-                               fstrcpy(p->pipe_srv_name, rpc_lookup[i].pipe.srv);
-                               break;
-                       }
-                }
+       /*
+        * Create the header, now we know the length.
+        */
 
-               if (i == rpc_lookup_size) {
-                       DEBUG(0, ("module %s doesn't provide functions for pipe %s!\n", p->name, p->name));
-                       return False;
-               }
+       if (prs_offset(&out_auth)) {
+               auth_len = prs_offset(&out_auth) - RPC_HDR_AUTH_LEN;
        }
 
-       /* decode the bind request */
-       if(!smb_io_rpc_hdr_rb("", &hdr_rb, rpc_in_p, 0))  {
-               DEBUG(0,("api_pipe_bind_req: unable to unmarshall RPC_HDR_RB struct.\n"));
-               return setup_bind_nak(p);
-       }
+       init_rpc_hdr(&p->hdr, RPC_BINDACK, RPC_FLG_FIRST | RPC_FLG_LAST,
+                       p->hdr.call_id,
+                       RPC_HEADER_LEN + prs_offset(&out_hdr_ba) + prs_offset(&out_auth),
+                       auth_len);
 
        /*
-        * Check if this is an authenticated request.
+        * Marshall the header into the outgoing PDU.
         */
 
-       if (p->hdr.auth_len != 0) {
-               RPC_AUTH_VERIFIER auth_verifier;
-               RPC_AUTH_NTLMSSP_NEG ntlmssp_neg;
-
-               /* 
-                * Decode the authentication verifier.
-                */
-
-               if(!smb_io_rpc_hdr_auth("", &auth_info, rpc_in_p, 0)) {
-                       DEBUG(0,("api_pipe_bind_req: unable to unmarshall RPC_HDR_AUTH struct.\n"));
-                       return setup_bind_nak(p);
-               }
-
-               switch(auth_info.auth_type) {
-                       case NTLMSSP_AUTH_TYPE:
-
-                               if(!smb_io_rpc_auth_verifier("", &auth_verifier, rpc_in_p, 0)) {
-                                       DEBUG(0,("api_pipe_bind_req: unable to "
-                                                "unmarshall RPC_HDR_AUTH struct.\n"));
-                                       return setup_bind_nak(p);
-                               }
-
-                               if(!strequal(auth_verifier.signature, "NTLMSSP")) {
-                                       DEBUG(0,("api_pipe_bind_req: "
-                                                "auth_verifier.signature != NTLMSSP\n"));
-                                       return setup_bind_nak(p);
-                               }
-
-                               if(auth_verifier.msg_type != NTLMSSP_NEGOTIATE) {
-                                       DEBUG(0,("api_pipe_bind_req: "
-                                                "auth_verifier.msg_type (%d) != NTLMSSP_NEGOTIATE\n",
-                                                auth_verifier.msg_type));
-                                       return setup_bind_nak(p);
-                               }
+       if(!smb_io_rpc_hdr("", &p->hdr, &outgoing_rpc, 0)) {
+               DEBUG(0,("api_pipe_bind_req: marshalling of RPC_HDR failed.\n"));
+               goto err_exit;
+       }
 
-                               if(!smb_io_rpc_auth_ntlmssp_neg("", &ntlmssp_neg, rpc_in_p, 0)) {
-                                       DEBUG(0,("api_pipe_bind_req: "
-                                                "Failed to unmarshall RPC_AUTH_NTLMSSP_NEG.\n"));
-                                       return setup_bind_nak(p);
-                               }
+       /*
+        * Now add the RPC_HDR_BA and any auth needed.
+        */
 
-                               p->ntlmssp_chal_flags = SMBD_NTLMSSP_NEG_FLAGS;
-                               p->ntlmssp_auth_requested = True;
-                               break;
+       if(!prs_append_prs_data( &outgoing_rpc, &out_hdr_ba)) {
+               DEBUG(0,("api_pipe_bind_req: append of RPC_HDR_BA failed.\n"));
+               goto err_exit;
+       }
 
-                       case NETSEC_AUTH_TYPE:
-                       {
-                               RPC_AUTH_NETSEC_NEG neg;
-                               struct netsec_auth_struct *a = &(p->netsec_auth);
+       if (auth_len && !prs_append_prs_data( &outgoing_rpc, &out_auth)) {
+               DEBUG(0,("api_pipe_bind_req: append of auth info failed.\n"));
+               goto err_exit;
+       }
 
-                               if (!server_auth2_negotiated) {
-                                       DEBUG(0, ("Attempt to bind using schannel "
-                                                 "without successful serverauth2\n"));
-                                       return setup_bind_nak(p);
-                               }
+       /*
+        * Setup the lengths for the initial reply.
+        */
 
-                               if (!smb_io_rpc_auth_netsec_neg("", &neg, rpc_in_p, 0)) {
-                                       DEBUG(0,("api_pipe_bind_req: "
-                                                "Could not unmarshal SCHANNEL auth neg\n"));
-                                       return setup_bind_nak(p);
-                               }
+       p->out_data.data_sent_length = 0;
+       p->out_data.current_pdu_len = prs_offset(&outgoing_rpc);
+       p->out_data.current_pdu_sent = 0;
 
-                               p->netsec_auth_validated = True;
+       prs_mem_free(&out_hdr_ba);
+       prs_mem_free(&out_auth);
 
-                               memset(a->sess_key, 0, sizeof(a->sess_key));
-                               memcpy(a->sess_key, last_dcinfo.sess_key, sizeof(last_dcinfo.sess_key));
+       return True;
 
-                               a->seq_num = 0;
+  err_exit:
 
-                               DEBUG(10,("schannel auth: domain [%s] myname [%s]\n",
-                                         neg.domain, neg.myname));
-                               break;
-                       }
+       prs_mem_free(&outgoing_rpc);
+       prs_mem_free(&out_hdr_ba);
+       prs_mem_free(&out_auth);
+       return setup_bind_nak(p);
+}
 
-                       case SPNEGO_AUTH_TYPE:
-                       default:
-                               DEBUG(0,("api_pipe_bind_req: unknown auth type %x requested.\n",
-                                        auth_info.auth_type ));
-                               return setup_bind_nak(p);
-               }
-       }
+/****************************************************************************
+ Deal with an alter context call. Can be third part of 3 leg auth request for
+ SPNEGO calls.
+****************************************************************************/
 
-       switch(p->hdr.pkt_type) {
-               case RPC_BIND:
-                       /* name has to be \PIPE\xxxxx */
-                       fstrcpy(ack_pipe_name, "\\PIPE\\");
-                       fstrcat(ack_pipe_name, p->pipe_srv_name);
-                       reply_pkt_type = RPC_BINDACK;
-                       break;
-               case RPC_ALTCONT:
-                       /* secondary address CAN be NULL
-                        * as the specs say it's ignored.
-                        * It MUST NULL to have the spoolss working.
-                        */
-                       fstrcpy(ack_pipe_name,"");
-                       reply_pkt_type = RPC_ALTCONTRESP;
-                       break;
-               default:
-                       return False;
-       }
+BOOL api_pipe_alter_context(pipes_struct *p, prs_struct *rpc_in_p)
+{
+       RPC_HDR_BA hdr_ba;
+       RPC_HDR_RB hdr_rb;
+       RPC_HDR_AUTH auth_info;
+       uint16 assoc_gid;
+       fstring ack_pipe_name;
+       prs_struct out_hdr_ba;
+       prs_struct out_auth;
+       prs_struct outgoing_rpc;
+       int auth_len = 0;
 
-       DEBUG(5,("api_pipe_bind_req: make response. %d\n", __LINE__));
+       prs_init( &outgoing_rpc, 0, p->mem_ctx, MARSHALL);
 
        /* 
         * Marshall directly into the outgoing PDU space. We
@@ -1035,7 +1666,6 @@ BOOL api_pipe_bind_req(pipes_struct *p, prs_struct *rpc_in_p)
         * header and are never sending more than one PDU here.
         */
 
-       prs_init( &outgoing_rpc, 0, p->mem_ctx, MARSHALL);
        prs_give_memory( &outgoing_rpc, (char *)p->out_data.current_pdu, sizeof(p->out_data.current_pdu), False);
 
        /*
@@ -1044,22 +1674,68 @@ BOOL api_pipe_bind_req(pipes_struct *p, prs_struct *rpc_in_p)
         */
 
        if(!prs_init(&out_hdr_ba, 1024, p->mem_ctx, MARSHALL)) {
-               DEBUG(0,("api_pipe_bind_req: malloc out_hdr_ba failed.\n"));
+               DEBUG(0,("api_pipe_alter_context: malloc out_hdr_ba failed.\n"));
                prs_mem_free(&outgoing_rpc);
                return False;
        }
 
        if(!prs_init(&out_auth, 1024, p->mem_ctx, MARSHALL)) {
-               DEBUG(0,("pi_pipe_bind_req: malloc out_auth failed.\n"));
+               DEBUG(0,("api_pipe_alter_context: malloc out_auth failed.\n"));
                prs_mem_free(&outgoing_rpc);
                prs_mem_free(&out_hdr_ba);
                return False;
        }
 
-       if (p->ntlmssp_auth_requested)
-               assoc_gid = 0x7a77;
-       else
-               assoc_gid = hdr_rb.bba.assoc_gid ? hdr_rb.bba.assoc_gid : 0x53f0;
+       DEBUG(5,("api_pipe_alter_context: decode request. %d\n", __LINE__));
+
+       /* decode the alter context request */
+       if(!smb_io_rpc_hdr_rb("", &hdr_rb, rpc_in_p, 0))  {
+               DEBUG(0,("api_pipe_alter_context: unable to unmarshall RPC_HDR_RB struct.\n"));
+               goto err_exit;
+       }
+
+       /* secondary address CAN be NULL
+        * as the specs say it's ignored.
+        * It MUST be NULL to have the spoolss working.
+        */
+       fstrcpy(ack_pipe_name,"");
+
+       DEBUG(5,("api_pipe_alter_context: make response. %d\n", __LINE__));
+
+       /*
+        * Check if this is an authenticated alter context request.
+        */
+
+       if (p->hdr.auth_len != 0) {
+               /* 
+                * Decode the authentication verifier.
+                */
+
+               if(!smb_io_rpc_hdr_auth("", &auth_info, rpc_in_p, 0)) {
+                       DEBUG(0,("api_pipe_alter_context: unable to unmarshall RPC_HDR_AUTH struct.\n"));
+                       goto err_exit;
+               }
+
+               /*
+                * Currently only the SPNEGO auth type uses the alter ctx
+                * response in place of the NTLMSSP auth3 type.
+                */
+
+               if (auth_info.auth_type == RPC_SPNEGO_AUTH_TYPE) {
+                       /* We can only finish if the pipe is unbound. */
+                       if (!p->pipe_bound) {
+                               if (!pipe_spnego_auth_bind_continue(p, rpc_in_p, &auth_info, &out_auth)) {
+                                       goto err_exit;
+                               }
+                       } else {
+                               goto err_exit;
+                       }
+               }
+       } else {
+               ZERO_STRUCT(auth_info);
+       }
+
+       assoc_gid = hdr_rb.bba.assoc_gid ? hdr_rb.bba.assoc_gid : 0x53f0;
 
        /*
         * Create the bind response struct.
@@ -1074,8 +1750,8 @@ BOOL api_pipe_bind_req(pipes_struct *p, prs_struct *rpc_in_p)
        if(check_bind_req(p, &hdr_rb.rpc_context[0].abstract, &hdr_rb.rpc_context[0].transfer[0],
                                hdr_rb.rpc_context[0].context_id )) {
                init_rpc_hdr_ba(&hdr_ba,
-                       MAX_PDU_FRAG_LEN,
-                       MAX_PDU_FRAG_LEN,
+                       RPC_MAX_PDU_FRAG_LEN,
+                       RPC_MAX_PDU_FRAG_LEN,
                        assoc_gid,
                        ack_pipe_name,
                        0x1, 0x0, 0x0,
@@ -1084,10 +1760,11 @@ BOOL api_pipe_bind_req(pipes_struct *p, prs_struct *rpc_in_p)
                RPC_IFACE null_interface;
                ZERO_STRUCT(null_interface);
                /* Rejection reason: abstract syntax not supported */
-               init_rpc_hdr_ba(&hdr_ba, MAX_PDU_FRAG_LEN,
-                                       MAX_PDU_FRAG_LEN, assoc_gid,
+               init_rpc_hdr_ba(&hdr_ba, RPC_MAX_PDU_FRAG_LEN,
+                                       RPC_MAX_PDU_FRAG_LEN, assoc_gid,
                                        ack_pipe_name, 0x1, 0x2, 0x1,
                                        &null_interface);
+               p->pipe_bound = False;
        }
 
        /*
@@ -1095,85 +1772,19 @@ BOOL api_pipe_bind_req(pipes_struct *p, prs_struct *rpc_in_p)
         */
 
        if(!smb_io_rpc_hdr_ba("", &hdr_ba, &out_hdr_ba, 0)) {
-               DEBUG(0,("api_pipe_bind_req: marshalling of RPC_HDR_BA failed.\n"));
+               DEBUG(0,("api_pipe_alter_context: marshalling of RPC_HDR_BA failed.\n"));
                goto err_exit;
        }
 
        /*
-        * Now the authentication.
+        * Create the header, now we know the length.
         */
 
-       if (p->ntlmssp_auth_requested) {
-               RPC_AUTH_VERIFIER auth_verifier;
-               RPC_AUTH_NTLMSSP_CHAL ntlmssp_chal;
-
-               generate_random_buffer(p->challenge, 8);
-
-               /*** Authentication info ***/
-
-               init_rpc_hdr_auth(&auth_info, NTLMSSP_AUTH_TYPE, RPC_PIPE_AUTH_SEAL_LEVEL, RPC_HDR_AUTH_LEN, 1);
-               if(!smb_io_rpc_hdr_auth("", &auth_info, &out_auth, 0)) {
-                       DEBUG(0,("api_pipe_bind_req: marshalling of RPC_HDR_AUTH failed.\n"));
-                       goto err_exit;
-               }
-
-               /*** NTLMSSP verifier ***/
-
-               init_rpc_auth_verifier(&auth_verifier, "NTLMSSP", NTLMSSP_CHALLENGE);
-               if(!smb_io_rpc_auth_verifier("", &auth_verifier, &out_auth, 0)) {
-                       DEBUG(0,("api_pipe_bind_req: marshalling of RPC_AUTH_VERIFIER failed.\n"));
-                       goto err_exit;
-               }
-
-               /* NTLMSSP challenge ***/
-
-               init_rpc_auth_ntlmssp_chal(&ntlmssp_chal, p->ntlmssp_chal_flags, p->challenge);
-               if(!smb_io_rpc_auth_ntlmssp_chal("", &ntlmssp_chal, &out_auth, 0)) {
-                       DEBUG(0,("api_pipe_bind_req: marshalling of RPC_AUTH_NTLMSSP_CHAL failed.\n"));
-                       goto err_exit;
-               }
-
-               /* Auth len in the rpc header doesn't include auth_header. */
-               auth_len = prs_offset(&out_auth) - RPC_HDR_AUTH_LEN;
-       }
-
-       if (p->netsec_auth_validated) {
-               RPC_AUTH_VERIFIER auth_verifier;
-               uint32 flags;
-
-               /* The client opens a second RPC NETLOGON pipe without
-                   doing a auth2. The credentials for the schannel are
-                   re-used from the auth2 the client did before. */
-               p->dc = last_dcinfo;
-
-               init_rpc_hdr_auth(&auth_info, NETSEC_AUTH_TYPE, auth_info.auth_level, RPC_HDR_AUTH_LEN, 1);
-               if(!smb_io_rpc_hdr_auth("", &auth_info, &out_auth, 0)) {
-                       DEBUG(0,("api_pipe_bind_req: marshalling of RPC_HDR_AUTH failed.\n"));
-                       goto err_exit;
-               }
-
-               /*** NETSEC verifier ***/
-
-               init_rpc_auth_verifier(&auth_verifier, "\001", 0x0);
-               if(!smb_io_rpc_netsec_verifier("", &auth_verifier, &out_auth, 0)) {
-                       DEBUG(0,("api_pipe_bind_req: marshalling of RPC_AUTH_VERIFIER failed.\n"));
-                       goto err_exit;
-               }
-
-               prs_align(&out_auth);
-
-               flags = 5;
-               if(!prs_uint32("flags ", &out_auth, 0, &flags))
-                       goto err_exit;
-
+       if (prs_offset(&out_auth)) {
                auth_len = prs_offset(&out_auth) - RPC_HDR_AUTH_LEN;
        }
 
-       /*
-        * Create the header, now we know the length.
-        */
-
-       init_rpc_hdr(&p->hdr, reply_pkt_type, RPC_FLG_FIRST | RPC_FLG_LAST,
+       init_rpc_hdr(&p->hdr, RPC_ALTCONTRESP, RPC_FLG_FIRST | RPC_FLG_LAST,
                        p->hdr.call_id,
                        RPC_HEADER_LEN + prs_offset(&out_hdr_ba) + prs_offset(&out_auth),
                        auth_len);
@@ -1183,7 +1794,7 @@ BOOL api_pipe_bind_req(pipes_struct *p, prs_struct *rpc_in_p)
         */
 
        if(!smb_io_rpc_hdr("", &p->hdr, &outgoing_rpc, 0)) {
-               DEBUG(0,("pi_pipe_bind_req: marshalling of RPC_HDR failed.\n"));
+               DEBUG(0,("api_pipe_alter_context: marshalling of RPC_HDR failed.\n"));
                goto err_exit;
        }
 
@@ -1192,19 +1803,15 @@ BOOL api_pipe_bind_req(pipes_struct *p, prs_struct *rpc_in_p)
         */
 
        if(!prs_append_prs_data( &outgoing_rpc, &out_hdr_ba)) {
-               DEBUG(0,("api_pipe_bind_req: append of RPC_HDR_BA failed.\n"));
+               DEBUG(0,("api_pipe_alter_context: append of RPC_HDR_BA failed.\n"));
                goto err_exit;
        }
 
-       if((p->ntlmssp_auth_requested|p->netsec_auth_validated) &&
-          !prs_append_prs_data( &outgoing_rpc, &out_auth)) {
-               DEBUG(0,("api_pipe_bind_req: append of auth info failed.\n"));
+       if (auth_len && !prs_append_prs_data( &outgoing_rpc, &out_auth)) {
+               DEBUG(0,("api_pipe_alter_context: append of auth info failed.\n"));
                goto err_exit;
        }
 
-       if(!p->ntlmssp_auth_requested)
-               p->pipe_bound = True;
-
        /*
         * Setup the lengths for the initial reply.
         */
@@ -1223,138 +1830,141 @@ BOOL api_pipe_bind_req(pipes_struct *p, prs_struct *rpc_in_p)
        prs_mem_free(&outgoing_rpc);
        prs_mem_free(&out_hdr_ba);
        prs_mem_free(&out_auth);
-       return False;
+       return setup_bind_nak(p);
 }
 
 /****************************************************************************
- Deal with sign & seal processing on an RPC request.
+ Deal with NTLMSSP sign & seal processing on an RPC request.
 ****************************************************************************/
 
-BOOL api_pipe_auth_process(pipes_struct *p, prs_struct *rpc_in)
+BOOL api_pipe_ntlmssp_auth_process(pipes_struct *p, prs_struct *rpc_in,
+                                       uint32 *p_ss_padding_len, NTSTATUS *pstatus)
 {
-       /*
-        * We always negotiate the following two bits....
-        */
-       BOOL auth_verify = ((p->ntlmssp_chal_flags & NTLMSSP_NEGOTIATE_SIGN) != 0);
-       BOOL auth_seal   = ((p->ntlmssp_chal_flags & NTLMSSP_NEGOTIATE_SEAL) != 0);
-       int data_len;
-       int auth_len;
-       uint32 old_offset;
-       uint32 crc32 = 0;
+       RPC_HDR_AUTH auth_info;
+       uint32 auth_len = p->hdr.auth_len;
+       uint32 save_offset = prs_offset(rpc_in);
+       AUTH_NTLMSSP_STATE *a = p->auth.a_u.auth_ntlmssp_state;
+       unsigned char *data = NULL;
+       size_t data_len;
+       unsigned char *full_packet_data = NULL;
+       size_t full_packet_data_len;
+       DATA_BLOB auth_blob;
+       
+       *pstatus = NT_STATUS_OK;
 
-       auth_len = p->hdr.auth_len;
+       if (p->auth.auth_level == PIPE_AUTH_LEVEL_NONE || p->auth.auth_level == PIPE_AUTH_LEVEL_CONNECT) {
+               return True;
+       }
+
+       if (!a) {
+               *pstatus = NT_STATUS_INVALID_PARAMETER;
+               return False;
+       }
 
-       if ((auth_len != RPC_AUTH_NTLMSSP_CHK_LEN) && auth_verify) {
-               DEBUG(0,("api_pipe_auth_process: Incorrect auth_len %d.\n", auth_len ));
+       /* Ensure there's enough data for an authenticated request. */
+       if ((auth_len > RPC_MAX_SIGN_SIZE) ||
+                       (RPC_HEADER_LEN + RPC_HDR_REQ_LEN + RPC_HDR_AUTH_LEN + auth_len > p->hdr.frag_len)) {
+               DEBUG(0,("api_pipe_ntlmssp_auth_process: auth_len %u is too large.\n",
+                       (unsigned int)auth_len ));
+               *pstatus = NT_STATUS_INVALID_PARAMETER;
                return False;
        }
 
        /*
-        * The following is that length of the data we must verify or unseal.
-        * This doesn't include the RPC headers or the auth_len or the RPC_HDR_AUTH_LEN
-        * preceeding the auth_data.
+        * We need the full packet data + length (minus auth stuff) as well as the packet data + length
+        * after the RPC header. 
+        * We need to pass in the full packet (minus auth len) to the NTLMSSP sign and check seal
+        * functions as NTLMv2 checks the rpc headers also.
         */
 
-       data_len = p->hdr.frag_len - RPC_HEADER_LEN - RPC_HDR_REQ_LEN - 
-                       (auth_verify ? RPC_HDR_AUTH_LEN : 0) - auth_len;
-       
-       DEBUG(5,("api_pipe_auth_process: sign: %s seal: %s data %d auth %d\n",
-                BOOLSTR(auth_verify), BOOLSTR(auth_seal), data_len, auth_len));
+       data = (unsigned char *)(prs_data_p(rpc_in) + RPC_HDR_REQ_LEN);
+       data_len = (size_t)(p->hdr.frag_len - RPC_HEADER_LEN - RPC_HDR_REQ_LEN - RPC_HDR_AUTH_LEN - auth_len);
 
-       if (auth_seal) {
-               /*
-                * The data in rpc_in doesn't contain the RPC_HEADER as this
-                * has already been consumed.
-                */
-               char *data = prs_data_p(rpc_in) + RPC_HDR_REQ_LEN;
-               dump_data_pw("NTLMSSP hash (v1)\n", p->ntlmssp_hash, 
-                            sizeof(p->ntlmssp_hash));
+       full_packet_data = p->in_data.current_in_pdu;
+       full_packet_data_len = p->hdr.frag_len - auth_len;
 
-               dump_data_pw("Incoming RPC PDU (NTLMSSP sealed)\n", 
-                            (const unsigned char *)data, data_len);
-               NTLMSSPcalc_p(p, (uchar*)data, data_len);
-               dump_data_pw("Incoming RPC PDU (NTLMSSP unsealed)\n", 
-                            (const unsigned char *)data, data_len);
-               crc32 = crc32_calc_buffer(data, data_len);
+       /* Pull the auth header and the following data into a blob. */
+       if(!prs_set_offset(rpc_in, RPC_HDR_REQ_LEN + data_len)) {
+               DEBUG(0,("api_pipe_ntlmssp_auth_process: cannot move offset to %u.\n",
+                       (unsigned int)RPC_HDR_REQ_LEN + (unsigned int)data_len ));
+               *pstatus = NT_STATUS_INVALID_PARAMETER;
+               return False;
        }
 
-       old_offset = prs_offset(rpc_in);
-
-       if (auth_seal || auth_verify) {
-               RPC_HDR_AUTH auth_info;
-
-               if(!prs_set_offset(rpc_in, old_offset + data_len)) {
-                       DEBUG(0,("api_pipe_auth_process: cannot move offset to %u.\n",
-                               (unsigned int)old_offset + data_len ));
-                       return False;
-               }
-
-               if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, rpc_in, 0)) {
-                       DEBUG(0,("api_pipe_auth_process: failed to unmarshall RPC_HDR_AUTH.\n"));
-                       return False;
-               }
+       if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, rpc_in, 0)) {
+               DEBUG(0,("api_pipe_ntlmssp_auth_process: failed to unmarshall RPC_HDR_AUTH.\n"));
+               *pstatus = NT_STATUS_INVALID_PARAMETER;
+               return False;
        }
 
-       if (auth_verify) {
-               RPC_AUTH_NTLMSSP_CHK ntlmssp_chk;
-               char *req_data = prs_data_p(rpc_in) + prs_offset(rpc_in) + 4;
-
-               DEBUG(5,("api_pipe_auth_process: auth %d\n", prs_offset(rpc_in) + 4));
-
-               /*
-                * Ensure we have RPC_AUTH_NTLMSSP_CHK_LEN - 4 more bytes in the
-                * incoming buffer.
-                */
-               if(prs_mem_get(rpc_in, RPC_AUTH_NTLMSSP_CHK_LEN - 4) == NULL) {
-                       DEBUG(0,("api_pipe_auth_process: missing %d bytes in buffer.\n",
-                               RPC_AUTH_NTLMSSP_CHK_LEN - 4 ));
-                       return False;
-               }
-
-               NTLMSSPcalc_p(p, (uchar*)req_data, RPC_AUTH_NTLMSSP_CHK_LEN - 4);
-               if(!smb_io_rpc_auth_ntlmssp_chk("auth_sign", &ntlmssp_chk, rpc_in, 0)) {
-                       DEBUG(0,("api_pipe_auth_process: failed to unmarshall RPC_AUTH_NTLMSSP_CHK.\n"));
-                       return False;
-               }
-
-               if (!rpc_auth_ntlmssp_chk(&ntlmssp_chk, crc32, p->ntlmssp_seq_num)) {
-                       DEBUG(0,("api_pipe_auth_process: NTLMSSP check failed.\n"));
+       auth_blob.data = prs_data_p(rpc_in) + prs_offset(rpc_in);
+       auth_blob.length = auth_len;
+       
+       switch (p->auth.auth_level) {
+               case PIPE_AUTH_LEVEL_PRIVACY:
+                       /* Data is encrypted. */
+                       *pstatus = ntlmssp_unseal_packet(a->ntlmssp_state,
+                                                       data, data_len,
+                                                       full_packet_data,
+                                                       full_packet_data_len,
+                                                       &auth_blob);
+                       if (!NT_STATUS_IS_OK(*pstatus)) {
+                               return False;
+                       }
+                       break;
+               case PIPE_AUTH_LEVEL_INTEGRITY:
+                       /* Data is signed. */
+                       *pstatus = ntlmssp_check_packet(a->ntlmssp_state,
+                                                       data, data_len,
+                                                       full_packet_data,
+                                                       full_packet_data_len,
+                                                       &auth_blob);
+                       if (!NT_STATUS_IS_OK(*pstatus)) {
+                               return False;
+                       }
+                       break;
+               default:
+                       *pstatus = NT_STATUS_INVALID_PARAMETER;
                        return False;
-               }
        }
 
        /*
         * Return the current pointer to the data offset.
         */
 
-       if(!prs_set_offset(rpc_in, old_offset)) {
+       if(!prs_set_offset(rpc_in, save_offset)) {
                DEBUG(0,("api_pipe_auth_process: failed to set offset back to %u\n",
-                       (unsigned int)old_offset ));
+                       (unsigned int)save_offset ));
+               *pstatus = NT_STATUS_INVALID_PARAMETER;
                return False;
        }
 
+       /*
+        * Remember the padding length. We must remove it from the real data
+        * stream once the sign/seal is done.
+        */
+
+       *p_ss_padding_len = auth_info.auth_pad_len;
+
        return True;
 }
 
 /****************************************************************************
  Deal with schannel processing on an RPC request.
 ****************************************************************************/
-BOOL api_pipe_netsec_process(pipes_struct *p, prs_struct *rpc_in)
+
+BOOL api_pipe_schannel_process(pipes_struct *p, prs_struct *rpc_in, uint32 *p_ss_padding_len)
 {
-       /*
-        * We always negotiate the following two bits....
-        */
-       int data_len;
-       int auth_len;
-       uint32 old_offset;
+       uint32 data_len;
+       uint32 auth_len;
+       uint32 save_offset = prs_offset(rpc_in);
        RPC_HDR_AUTH auth_info;
-       RPC_AUTH_NETSEC_CHK netsec_chk;
-
+       RPC_AUTH_SCHANNEL_CHK schannel_chk;
 
        auth_len = p->hdr.auth_len;
 
-       if (auth_len != RPC_AUTH_NETSEC_SIGN_OR_SEAL_CHK_LEN) {
-               DEBUG(0,("Incorrect auth_len %d.\n", auth_len ));
+       if (auth_len != RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN) {
+               DEBUG(0,("Incorrect auth_len %u.\n", (unsigned int)auth_len ));
                return False;
        }
 
@@ -1364,16 +1974,21 @@ BOOL api_pipe_netsec_process(pipes_struct *p, prs_struct *rpc_in)
         * preceeding the auth_data.
         */
 
+       if (p->hdr.frag_len < RPC_HEADER_LEN + RPC_HDR_REQ_LEN + RPC_HDR_AUTH_LEN + auth_len) {
+               DEBUG(0,("Incorrect frag %u, auth %u.\n",
+                       (unsigned int)p->hdr.frag_len,
+                       (unsigned int)auth_len ));
+               return False;
+       }
+
        data_len = p->hdr.frag_len - RPC_HEADER_LEN - RPC_HDR_REQ_LEN - 
                RPC_HDR_AUTH_LEN - auth_len;
        
        DEBUG(5,("data %d auth %d\n", data_len, auth_len));
 
-       old_offset = prs_offset(rpc_in);
-
-       if(!prs_set_offset(rpc_in, old_offset + data_len)) {
+       if(!prs_set_offset(rpc_in, RPC_HDR_REQ_LEN + data_len)) {
                DEBUG(0,("cannot move offset to %u.\n",
-                        (unsigned int)old_offset + data_len ));
+                        (unsigned int)RPC_HDR_REQ_LEN + data_len ));
                return False;
        }
 
@@ -1382,34 +1997,22 @@ BOOL api_pipe_netsec_process(pipes_struct *p, prs_struct *rpc_in)
                return False;
        }
 
-       if (auth_info.auth_type != NETSEC_AUTH_TYPE) {
+       if (auth_info.auth_type != RPC_SCHANNEL_AUTH_TYPE) {
                DEBUG(0,("Invalid auth info %d on schannel\n",
                         auth_info.auth_type));
                return False;
        }
 
-       if (auth_info.auth_level == RPC_PIPE_AUTH_SEAL_LEVEL) {
-               p->netsec_auth.auth_flags = AUTH_PIPE_NETSEC|AUTH_PIPE_SIGN|AUTH_PIPE_SEAL;
-       } else if (auth_info.auth_level == RPC_PIPE_AUTH_SIGN_LEVEL) {
-               p->netsec_auth.auth_flags = AUTH_PIPE_NETSEC|AUTH_PIPE_SIGN;
-       } else {
-               DEBUG(0,("Invalid auth level %d on schannel\n",
-                        auth_info.auth_level));
-               return False;
-       }
-
-       if(!smb_io_rpc_auth_netsec_chk("", RPC_AUTH_NETSEC_SIGN_OR_SEAL_CHK_LEN, 
-               &netsec_chk, rpc_in, 0)) 
-       {
-               DEBUG(0,("failed to unmarshal RPC_AUTH_NETSEC_CHK.\n"));
+       if(!smb_io_rpc_auth_schannel_chk("", RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN, &schannel_chk, rpc_in, 0)) {
+               DEBUG(0,("failed to unmarshal RPC_AUTH_SCHANNEL_CHK.\n"));
                return False;
        }
 
-       if (!netsec_decode(&p->netsec_auth,
-                          p->netsec_auth.auth_flags,
+       if (!schannel_decode(p->auth.a_u.schannel_auth,
+                          p->auth.auth_level,
                           SENDER_IS_INITIATOR,
-                          &netsec_chk,
-                          prs_data_p(rpc_in)+old_offset, data_len)) {
+                          &schannel_chk,
+                          prs_data_p(rpc_in)+RPC_HDR_REQ_LEN, data_len)) {
                DEBUG(3,("failed to decode PDU\n"));
                return False;
        }
@@ -1418,14 +2021,21 @@ BOOL api_pipe_netsec_process(pipes_struct *p, prs_struct *rpc_in)
         * Return the current pointer to the data offset.
         */
 
-       if(!prs_set_offset(rpc_in, old_offset)) {
+       if(!prs_set_offset(rpc_in, save_offset)) {
                DEBUG(0,("failed to set offset back to %u\n",
-                        (unsigned int)old_offset ));
+                        (unsigned int)save_offset ));
                return False;
        }
 
        /* The sequence number gets incremented on both send and receive. */
-       p->netsec_auth.seq_num++;
+       p->auth.a_u.schannel_auth->seq_num++;
+
+       /*
+        * Remember the padding length. We must remove it from the real data
+        * stream once the sign/seal is done.
+        */
+
+       *p_ss_padding_len = auth_info.auth_pad_len;
 
        return True;
 }
@@ -1436,7 +2046,9 @@ BOOL api_pipe_netsec_process(pipes_struct *p, prs_struct *rpc_in)
 
 struct current_user *get_current_user(struct current_user *user, pipes_struct *p)
 {
-       if (p->ntlmssp_auth_validated) {
+       if (p->pipe_bound &&
+                       (p->auth.auth_type == PIPE_AUTH_TYPE_NTLMSSP ||
+                       (p->auth.auth_type == PIPE_AUTH_TYPE_SPNEGO_NTLMSSP))) {
                memcpy(user, &p->pipe_user, sizeof(struct current_user));
        } else {
                memcpy(user, &current_user, sizeof(struct current_user));
@@ -1470,7 +2082,7 @@ static PIPE_RPC_FNS* find_pipe_fns_by_context( PIPE_RPC_FNS *list, uint32 contex
 }
 
 /****************************************************************************
- memory cleanup
+ Memory cleanup.
 ****************************************************************************/
 
 void free_pipe_rpc_context( PIPE_RPC_FNS *list )
@@ -1496,14 +2108,17 @@ void free_pipe_rpc_context( PIPE_RPC_FNS *list )
 BOOL api_pipe_request(pipes_struct *p)
 {
        BOOL ret = False;
+       BOOL changed_user = False;
        PIPE_RPC_FNS *pipe_fns;
        
-       if (p->ntlmssp_auth_validated) {
-
+       if (p->pipe_bound &&
+                       ((p->auth.auth_type == PIPE_AUTH_TYPE_NTLMSSP) ||
+                        (p->auth.auth_type == PIPE_AUTH_TYPE_SPNEGO_NTLMSSP))) {
                if(!become_authenticated_pipe_user(p)) {
                        prs_mem_free(&p->out_data.rdata);
                        return False;
                }
+               changed_user = True;
        }
 
        DEBUG(5, ("Requested \\PIPE\\%s\n", p->name));
@@ -1522,8 +2137,9 @@ BOOL api_pipe_request(pipes_struct *p)
                        p->hdr_req.context_id, p->name));
        }
 
-       if(p->ntlmssp_auth_validated)
+       if (changed_user) {
                unbecome_authenticated_pipe_user();
+       }
 
        return ret;
 }
@@ -1649,6 +2265,9 @@ void get_pipe_fns( int idx, struct api_struct **fns, int *n_fns )
                case PI_EVENTLOG:
                        eventlog_get_pipe_fns( &cmds, &n_cmds );
                        break;
+               case PI_NTSVCS:
+                       ntsvcs_get_pipe_fns( &cmds, &n_cmds );
+                       break;
 #ifdef DEVELOPER
                case PI_ECHO:
                        echo_get_pipe_fns( &cmds, &n_cmds );
@@ -1663,5 +2282,3 @@ void get_pipe_fns( int idx, struct api_struct **fns, int *n_fns )
 
        return;
 }
-
-
index 83b78f8d2f6de89665466a30a33324aa59c9eee4..205223190b442191c854874d0ccf1c814b7d781b 100644 (file)
@@ -2,8 +2,8 @@
  *  Unix SMB/CIFS implementation.
  *  RPC Pipe client / server routines
  *  Copyright (C) Andrew Tridgell              1992-1998,
- *  Copyright (C) Luke Kenneth Casson Leighton 1996-1998,
- *  Copyright (C) Jeremy Allison                                   1999.
+ *  Largely re-written : 2005
+ *  Copyright (C) Jeremy Allison               1998 - 2005
  *  
  *  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
@@ -106,10 +106,11 @@ static int pipe_handle_offset;
 
 void set_pipe_handle_offset(int max_open_files)
 {
-  if(max_open_files < 0x7000)
-    pipe_handle_offset = 0x7000;
-  else
-    pipe_handle_offset = max_open_files + 10; /* For safety. :-) */
+       if(max_open_files < 0x7000) {
+               pipe_handle_offset = 0x7000;
+       } else {
+               pipe_handle_offset = max_open_files + 10; /* For safety. :-) */
+       }
 }
 
 /****************************************************************************
@@ -128,8 +129,9 @@ void reset_chain_p(void)
 void init_rpc_pipe_hnd(void)
 {
        bmap = bitmap_allocate(MAX_OPEN_PIPES);
-       if (!bmap)
+       if (!bmap) {
                exit_server("out of memory in init_rpc_pipe_hnd");
+       }
 }
 
 /****************************************************************************
@@ -154,7 +156,7 @@ static BOOL pipe_init_outgoing_data(pipes_struct *p)
         * Initialize the outgoing RPC data buffer.
         * we will use this as the raw data area for replying to rpc requests.
         */     
-       if(!prs_init(&o_data->rdata, MAX_PDU_FRAG_LEN, p->mem_ctx, MARSHALL)) {
+       if(!prs_init(&o_data->rdata, RPC_MAX_PDU_FRAG_LEN, p->mem_ctx, MARSHALL)) {
                DEBUG(0,("pipe_init_outgoing_data: malloc fail.\n"));
                return False;
        }
@@ -177,8 +179,9 @@ smb_np_struct *open_rpc_pipe_p(char *pipe_name,
        DEBUG(4,("Open pipe requested %s (pipes_open=%d)\n",
                 pipe_name, pipes_open));
 
-       if (strstr(pipe_name, "spoolss"))
+       if (strstr(pipe_name, "spoolss")) {
                is_spoolss_pipe = True;
+       }
  
        if (is_spoolss_pipe && current_spoolss_pipes_open >= MAX_OPEN_SPOOLSS_PIPES) {
                DEBUG(10,("open_rpc_pipe_p: spooler bug workaround. Denying open on pipe %s\n",
@@ -189,8 +192,10 @@ smb_np_struct *open_rpc_pipe_p(char *pipe_name,
        /* not repeating pipe numbers makes it easier to track things in 
           log files and prevents client bugs where pipe numbers are reused
           over connection restarts */
-       if (next_pipe == 0)
+
+       if (next_pipe == 0) {
                next_pipe = (sys_getpid() ^ time(NULL)) % MAX_OPEN_PIPES;
+       }
 
        i = bitmap_find(bmap, next_pipe);
 
@@ -201,8 +206,9 @@ smb_np_struct *open_rpc_pipe_p(char *pipe_name,
 
        next_pipe = (i+1) % MAX_OPEN_PIPES;
 
-       for (p = Pipes; p; p = p->next)
+       for (p = Pipes; p; p = p->next) {
                DEBUG(5,("open_rpc_pipe_p: name %s pnum=%x\n", p->name, p->pnum));  
+       }
 
        p = SMB_MALLOC_P(smb_np_struct);
        if (!p) {
@@ -259,8 +265,9 @@ smb_np_struct *open_rpc_pipe_p(char *pipe_name,
        chain_p = p;
        
        /* Iterate over p_it as a temp variable, to display all open pipes */ 
-       for (p_it = Pipes; p_it; p_it = p_it->next)
+       for (p_it = Pipes; p_it; p_it = p_it->next) {
                DEBUG(5,("open pipes: name %s pnum=%x\n", p_it->name, p_it->pnum));  
+       }
 
        return chain_p;
 }
@@ -297,9 +304,17 @@ static void *make_internal_rpc_pipe_p(char *pipe_name,
                return NULL;
        }
 
+       if ((p->pipe_state_mem_ctx = talloc_init("pipe_state %s %p", pipe_name, p)) == NULL) {
+               DEBUG(0,("open_rpc_pipe_p: talloc_init failed.\n"));
+               talloc_destroy(p->mem_ctx);
+               SAFE_FREE(p);
+               return NULL;
+       }
+
        if (!init_pipe_handle_list(p, pipe_name)) {
                DEBUG(0,("open_rpc_pipe_p: init_pipe_handles failed.\n"));
                talloc_destroy(p->mem_ctx);
+               talloc_destroy(p->pipe_state_mem_ctx);
                SAFE_FREE(p);
                return NULL;
        }
@@ -311,8 +326,10 @@ static void *make_internal_rpc_pipe_p(char *pipe_name,
         * change the type to UNMARSALLING before processing the stream.
         */
 
-       if(!prs_init(&p->in_data.data, MAX_PDU_FRAG_LEN, p->mem_ctx, MARSHALL)) {
+       if(!prs_init(&p->in_data.data, RPC_MAX_PDU_FRAG_LEN, p->mem_ctx, MARSHALL)) {
                DEBUG(0,("open_rpc_pipe_p: malloc fail for in_data struct.\n"));
+               talloc_destroy(p->mem_ctx);
+               talloc_destroy(p->pipe_state_mem_ctx);
                return NULL;
        }
 
@@ -325,12 +342,6 @@ static void *make_internal_rpc_pipe_p(char *pipe_name,
 
        p->vuid  = vuid;
 
-       p->ntlmssp_chal_flags = 0;
-       p->ntlmssp_auth_validated = False;
-       p->ntlmssp_auth_requested = False;
-
-       p->pipe_bound = False;
-       p->fault_state = False;
        p->endian = RPC_LITTLE_ENDIAN;
 
        ZERO_STRUCT(p->pipe_user);
@@ -344,21 +355,6 @@ static void *make_internal_rpc_pipe_p(char *pipe_name,
                p->pipe_user.nt_user_token = dup_nt_token(vuser->nt_user_token);
        }
 
-       /*
-        * Initialize the incoming RPC struct.
-        */
-
-       p->in_data.pdu_needed_len = 0;
-       p->in_data.pdu_received_len = 0;
-
-       /*
-        * Initialize the outgoing RPC struct.
-        */
-
-       p->out_data.current_pdu_len = 0;
-       p->out_data.current_pdu_sent = 0;
-       p->out_data.data_sent_length = 0;
-
        /*
         * Initialize the outgoing RPC data buffer with no memory.
         */     
@@ -504,7 +500,7 @@ static ssize_t unmarshall_rpc_header(pipes_struct *p)
         * Ensure that the pdu length is sane.
         */
 
-       if((p->hdr.frag_len < RPC_HEADER_LEN) || (p->hdr.frag_len > MAX_PDU_FRAG_LEN)) {
+       if((p->hdr.frag_len < RPC_HEADER_LEN) || (p->hdr.frag_len > RPC_MAX_PDU_FRAG_LEN)) {
                DEBUG(0,("unmarshall_rpc_header: assert on frag length failed.\n"));
                set_incoming_fault(p);
                prs_mem_free(&rpc_in);
@@ -514,18 +510,8 @@ static ssize_t unmarshall_rpc_header(pipes_struct *p)
        DEBUG(10,("unmarshall_rpc_header: type = %u, flags = %u\n", (unsigned int)p->hdr.pkt_type,
                        (unsigned int)p->hdr.flags ));
 
-       /*
-        * Adjust for the header we just ate.
-        */
-       p->in_data.pdu_received_len = 0;
        p->in_data.pdu_needed_len = (uint32)p->hdr.frag_len - RPC_HEADER_LEN;
 
-       /*
-        * Null the data we just ate.
-        */
-
-       memset((char *)&p->in_data.current_in_pdu[0], '\0', RPC_HEADER_LEN);
-
        prs_mem_free(&rpc_in);
 
        return 0; /* No extra data processed. */
@@ -540,12 +526,13 @@ static void free_pipe_context(pipes_struct *p)
 {
        if (p->mem_ctx) {
                DEBUG(3,("free_pipe_context: destroying talloc pool of size "
-                        "%llu\n", talloc_total_size(p->mem_ctx) ));
+                        "%lu\n", (unsigned long)talloc_total_size(p->mem_ctx) ));
                talloc_free_children(p->mem_ctx);
        } else {
                p->mem_ctx = talloc_init("pipe %s %p", p->name, p);
-               if (p->mem_ctx == NULL)
+               if (p->mem_ctx == NULL) {
                        p->fault_state = True;
+               }
        }
 }
 
@@ -556,9 +543,9 @@ static void free_pipe_context(pipes_struct *p)
 
 static BOOL process_request_pdu(pipes_struct *p, prs_struct *rpc_in_p)
 {
-       BOOL auth_verify = ((p->ntlmssp_chal_flags & NTLMSSP_NEGOTIATE_SIGN) != 0);
+       uint32 ss_padding_len = 0;
        size_t data_len = p->hdr.frag_len - RPC_HEADER_LEN - RPC_HDR_REQ_LEN -
-                               (auth_verify ? RPC_HDR_AUTH_LEN : 0) - p->hdr.auth_len;
+                               (p->hdr.auth_len ? RPC_HDR_AUTH_LEN : 0) - p->hdr.auth_len;
 
        if(!p->pipe_bound) {
                DEBUG(0,("process_request_pdu: rpc request with no bind.\n"));
@@ -581,29 +568,40 @@ static BOOL process_request_pdu(pipes_struct *p, prs_struct *rpc_in_p)
                return False;
        }
 
-       if(p->ntlmssp_auth_validated && !api_pipe_auth_process(p, rpc_in_p)) {
-               DEBUG(0,("process_request_pdu: failed to do auth processing.\n"));
-               set_incoming_fault(p);
-               return False;
-       }
+       switch(p->auth.auth_type) {
+               case PIPE_AUTH_TYPE_NONE:
+                       break;
 
-       if (p->ntlmssp_auth_requested && !p->ntlmssp_auth_validated) {
+               case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
+               case PIPE_AUTH_TYPE_NTLMSSP:
+               {
+                       NTSTATUS status;
+                       if(!api_pipe_ntlmssp_auth_process(p, rpc_in_p, &ss_padding_len, &status)) {
+                               DEBUG(0,("process_request_pdu: failed to do auth processing.\n"));
+                               DEBUG(0,("process_request_pdu: error was %s.\n", nt_errstr(status) ));
+                               set_incoming_fault(p);
+                               return False;
+                       }
+                       break;
+               }
 
-               /*
-                * Authentication _was_ requested and it already failed.
-                */
+               case PIPE_AUTH_TYPE_SCHANNEL:
+                       if (!api_pipe_schannel_process(p, rpc_in_p, &ss_padding_len)) {
+                               DEBUG(3,("process_request_pdu: failed to do schannel processing.\n"));
+                               set_incoming_fault(p);
+                               return False;
+                       }
+                       break;
 
-               DEBUG(0,("process_request_pdu: RPC request received on pipe %s "
-                        "where authentication failed. Denying the request.\n",
-                        p->name));
-               set_incoming_fault(p);
-               return False;
+               default:
+                       DEBUG(0,("process_request_pdu: unknown auth type %u set.\n", (unsigned int)p->auth.auth_type ));
+                       set_incoming_fault(p);
+                       return False;
        }
 
-       if (p->netsec_auth_validated && !api_pipe_netsec_process(p, rpc_in_p)) {
-               DEBUG(3,("process_request_pdu: failed to do schannel processing.\n"));
-               set_incoming_fault(p);
-               return False;
+       /* Now we've done the sign/seal we can remove any padding data. */
+       if (data_len > ss_padding_len) {
+               data_len -= ss_padding_len;
        }
 
        /*
@@ -643,8 +641,7 @@ static BOOL process_request_pdu(pipes_struct *p, prs_struct *rpc_in_p)
                 * size as the current offset.
                 */
 
-               if(!prs_set_buffer_size(&p->in_data.data, prs_offset(&p->in_data.data)))
-               {
+               if(!prs_set_buffer_size(&p->in_data.data, prs_offset(&p->in_data.data))) {
                        DEBUG(0,("process_request_pdu: Call to prs_set_buffer_size failed!\n"));
                        set_incoming_fault(p);
                        return False;
@@ -664,8 +661,9 @@ static BOOL process_request_pdu(pipes_struct *p, prs_struct *rpc_in_p)
 
                free_pipe_context(p);
 
-               if(pipe_init_outgoing_data(p))
+               if(pipe_init_outgoing_data(p)) {
                        ret = api_pipe_request(p);
+               }
 
                free_pipe_context(p);
 
@@ -690,11 +688,11 @@ static BOOL process_request_pdu(pipes_struct *p, prs_struct *rpc_in_p)
  already been parsed and stored in p->hdr.
 ****************************************************************************/
 
-static ssize_t process_complete_pdu(pipes_struct *p)
+static void process_complete_pdu(pipes_struct *p)
 {
        prs_struct rpc_in;
-       size_t data_len = p->in_data.pdu_received_len;
-       char *data_p = (char *)&p->in_data.current_in_pdu[0];
+       size_t data_len = p->in_data.pdu_received_len - RPC_HEADER_LEN;
+       char *data_p = (char *)&p->in_data.current_in_pdu[RPC_HEADER_LEN];
        BOOL reply = False;
 
        if(p->fault_state) {
@@ -702,7 +700,7 @@ static ssize_t process_complete_pdu(pipes_struct *p)
                        p->name ));
                set_incoming_fault(p);
                setup_fault_pdu(p, NT_STATUS(0x1c010002));
-               return (ssize_t)data_len;
+               return;
        }
 
        prs_init( &rpc_in, 0, p->mem_ctx, UNMARSHALL);
@@ -722,19 +720,28 @@ static ssize_t process_complete_pdu(pipes_struct *p)
 
        switch (p->hdr.pkt_type) {
                case RPC_BIND:
-               case RPC_ALTCONT:
                        /*
                         * We assume that a pipe bind is only in one pdu.
                         */
-                       if(pipe_init_outgoing_data(p))
+                       if(pipe_init_outgoing_data(p)) {
                                reply = api_pipe_bind_req(p, &rpc_in);
+                       }
+                       break;
+               case RPC_ALTCONT:
+                       /*
+                        * We assume that a pipe bind is only in one pdu.
+                        */
+                       if(pipe_init_outgoing_data(p)) {
+                               reply = api_pipe_alter_context(p, &rpc_in);
+                       }
                        break;
-               case RPC_BINDRESP:
+               case RPC_AUTH3:
                        /*
-                        * We assume that a pipe bind_resp is only in one pdu.
+                        * The third packet in an NTLMSSP auth exchange.
                         */
-                       if(pipe_init_outgoing_data(p))
-                               reply = api_pipe_bind_auth_resp(p, &rpc_in);
+                       if(pipe_init_outgoing_data(p)) {
+                               reply = api_pipe_bind_auth3(p, &rpc_in);
+                       }
                        break;
                case RPC_REQUEST:
                        reply = process_request_pdu(p, &rpc_in);
@@ -761,7 +768,6 @@ static ssize_t process_complete_pdu(pipes_struct *p)
        }
 
        prs_mem_free(&rpc_in);
-       return (ssize_t)data_len;
 }
 
 /****************************************************************************
@@ -770,8 +776,7 @@ static ssize_t process_complete_pdu(pipes_struct *p)
 
 static ssize_t process_incoming_data(pipes_struct *p, char *data, size_t n)
 {
-       size_t data_to_copy = MIN(n, MAX_PDU_FRAG_LEN - p->in_data.pdu_received_len);
-       size_t old_pdu_received_len = p->in_data.pdu_received_len;
+       size_t data_to_copy = MIN(n, RPC_MAX_PDU_FRAG_LEN - p->in_data.pdu_received_len);
 
        DEBUG(10,("process_incoming_data: Start: pdu_received_len = %u, pdu_needed_len = %u, incoming data = %u\n",
                (unsigned int)p->in_data.pdu_received_len, (unsigned int)p->in_data.pdu_needed_len,
@@ -812,8 +817,9 @@ incoming data size = %u\n", (unsigned int)p->in_data.pdu_received_len, (unsigned
         * data we need, then loop again.
         */
 
-       if(p->in_data.pdu_needed_len == 0)
+       if(p->in_data.pdu_needed_len == 0) {
                return unmarshall_rpc_header(p);
+       }
 
        /*
         * Ok - at this point we have a valid RPC_HEADER in p->hdr.
@@ -824,24 +830,27 @@ incoming data size = %u\n", (unsigned int)p->in_data.pdu_received_len, (unsigned
 
        /*
         * Copy as much of the data as we need into the current_in_pdu buffer.
+        * pdu_needed_len becomes zero when we have a complete pdu.
         */
 
        memcpy( (char *)&p->in_data.current_in_pdu[p->in_data.pdu_received_len], data, data_to_copy);
        p->in_data.pdu_received_len += data_to_copy;
+       p->in_data.pdu_needed_len -= data_to_copy;
 
        /*
         * Do we have a complete PDU ?
-        * (return the nym of bytes handled in the call)
+        * (return the number of bytes handled in the call)
         */
 
-       if(p->in_data.pdu_received_len == p->in_data.pdu_needed_len)
-               return process_complete_pdu(p) - old_pdu_received_len;
+       if(p->in_data.pdu_needed_len == 0) {
+               process_complete_pdu(p);
+               return data_to_copy;
+       }
 
        DEBUG(10,("process_incoming_data: not a complete PDU yet. pdu_received_len = %u, pdu_needed_len = %u\n",
                (unsigned int)p->in_data.pdu_received_len, (unsigned int)p->in_data.pdu_needed_len ));
 
        return (ssize_t)data_to_copy;
-
 }
 
 /****************************************************************************
@@ -878,8 +887,9 @@ static ssize_t write_to_internal_pipe(void *np_conn, char *data, size_t n)
 
                DEBUG(10,("write_to_pipe: data_used = %d\n", (int)data_used ));
 
-               if(data_used < 0)
+               if(data_used < 0) {
                        return -1;
+               }
 
                data_left -= data_used;
                data += data_used;
@@ -948,9 +958,9 @@ static ssize_t read_from_internal_pipe(void *np_conn, char *data, size_t n,
         * authentications failing.  Just ignore it so things work.
         */
 
-       if(n > MAX_PDU_FRAG_LEN) {
+       if(n > RPC_MAX_PDU_FRAG_LEN) {
                 DEBUG(5,("read_from_pipe: too large read (%u) requested on \
-pipe %s. We can only service %d sized reads.\n", (unsigned int)n, p->name, MAX_PDU_FRAG_LEN ));
+pipe %s. We can only service %d sized reads.\n", (unsigned int)n, p->name, RPC_MAX_PDU_FRAG_LEN ));
        }
 
        /*
@@ -1019,8 +1029,9 @@ returning %d bytes.\n", p->name, (unsigned int)p->out_data.current_pdu_len,
 
 BOOL wait_rpc_pipe_hnd_state(smb_np_struct *p, uint16 priority)
 {
-       if (p == NULL)
+       if (p == NULL) {
                return False;
+       }
 
        if (p->open) {
                DEBUG(3,("wait_rpc_pipe_hnd_state: Setting pipe wait state priority=%x on pipe (name=%s)\n",
@@ -1043,8 +1054,9 @@ BOOL wait_rpc_pipe_hnd_state(smb_np_struct *p, uint16 priority)
 
 BOOL set_rpc_pipe_hnd_state(smb_np_struct *p, uint16 device_state)
 {
-       if (p == NULL)
+       if (p == NULL) {
                return False;
+       }
 
        if (p->open) {
                DEBUG(3,("set_rpc_pipe_hnd_state: Setting pipe device state=%x on pipe (name=%s)\n",
@@ -1121,9 +1133,18 @@ static BOOL close_internal_rpc_pipe_hnd(void *np_conn)
        prs_mem_free(&p->out_data.rdata);
        prs_mem_free(&p->in_data.data);
 
-       if (p->mem_ctx)
+       if (p->auth.auth_data_free_func) {
+               (*p->auth.auth_data_free_func)(&p->auth);
+       }
+
+       if (p->mem_ctx) {
                talloc_destroy(p->mem_ctx);
-               
+       }
+
+       if (p->pipe_state_mem_ctx) {
+               talloc_destroy(p->pipe_state_mem_ctx);
+       }
+
        free_pipe_rpc_context( p->contexts );
 
        /* Free the handles database. */
@@ -1152,8 +1173,9 @@ smb_np_struct *get_rpc_pipe_p(char *buf, int where)
 {
        int pnum = SVAL(buf,where);
 
-       if (chain_p)
+       if (chain_p) {
                return chain_p;
+       }
 
        return get_rpc_pipe(pnum);
 }
@@ -1168,9 +1190,10 @@ smb_np_struct *get_rpc_pipe(int pnum)
 
        DEBUG(4,("search for pipe pnum=%x\n", pnum));
 
-       for (p=Pipes;p;p=p->next)
+       for (p=Pipes;p;p=p->next) {
                DEBUG(5,("pipe name %s pnum=%x (pipes_open=%d)\n", 
                          p->name, p->pnum, pipes_open));  
+       }
 
        for (p=Pipes;p;p=p->next) {
                if (p->pnum == pnum) {
index 871b1a9f121c01ce9e5aaee68efb4860429f8ed8..17725240387f3d7c394c91ed9b272f06da078368 100644 (file)
@@ -383,7 +383,7 @@ static BOOL api_reg_restore_key(pipes_struct *p)
 
        if(!reg_io_q_restore_key("", &q_u, data, 0))
                return False;
-               
+
        r_u.status = _reg_restore_key(p, &q_u, &r_u);
 
        if(!reg_io_r_restore_key("", &r_u, rdata, 0))
@@ -393,7 +393,7 @@ static BOOL api_reg_restore_key(pipes_struct *p)
 }
 
 /*******************************************************************
- ******************************************************************/
+ ********************************************************************/
 
 static BOOL api_reg_save_key(pipes_struct *p)
 {
@@ -416,6 +416,57 @@ static BOOL api_reg_save_key(pipes_struct *p)
        return True;
 }
 
+/*******************************************************************
+ api_reg_open_hkpd
+ ********************************************************************/
+
+static BOOL api_reg_open_hkpd(pipes_struct *p)
+{
+       REG_Q_OPEN_HIVE q_u;
+       REG_R_OPEN_HIVE r_u;
+       prs_struct *data = &p->in_data.data;
+       prs_struct *rdata = &p->out_data.rdata;
+
+       ZERO_STRUCT(q_u);
+       ZERO_STRUCT(r_u);
+
+       /* grab the reg open */
+       if(!reg_io_q_open_hive("", &q_u, data, 0))
+               return False;
+
+       r_u.status = _reg_open_hkpd(p, &q_u, &r_u);
+
+       if(!reg_io_r_open_hive("", &r_u, rdata, 0))
+               return False;
+
+       return True;
+}
+
+/*******************************************************************
+ api_reg_open_hkpd
+ ********************************************************************/
+static BOOL api_reg_open_hkpt(pipes_struct *p)
+{
+       REG_Q_OPEN_HIVE q_u;
+       REG_R_OPEN_HIVE r_u;
+       prs_struct *data = &p->in_data.data;
+       prs_struct *rdata = &p->out_data.rdata;
+
+       ZERO_STRUCT(q_u);
+       ZERO_STRUCT(r_u);
+
+       /* grab the reg open */
+       if(!reg_io_q_open_hive("", &q_u, data, 0))
+               return False;
+
+       r_u.status = _reg_open_hkpt(p, &q_u, &r_u);
+
+       if(!reg_io_r_open_hive("", &r_u, rdata, 0))
+               return False;
+
+       return True;
+}
+
 /*******************************************************************
  ******************************************************************/
 
@@ -573,6 +624,8 @@ static struct api_struct api_reg_cmds[] =
       { "REG_OPEN_ENTRY"         , REG_OPEN_ENTRY         , api_reg_open_entry       },
       { "REG_OPEN_HKCR"          , REG_OPEN_HKCR          , api_reg_open_hkcr        },
       { "REG_OPEN_HKLM"          , REG_OPEN_HKLM          , api_reg_open_hklm        },
+      { "REG_OPEN_HKPD"          , REG_OPEN_HKPD          , api_reg_open_hkpd        },
+      { "REG_OPEN_HKPT"          , REG_OPEN_HKPT          , api_reg_open_hkpt        },
       { "REG_OPEN_HKU"           , REG_OPEN_HKU           , api_reg_open_hku         },
       { "REG_ENUM_KEY"           , REG_ENUM_KEY           , api_reg_enum_key         },
       { "REG_ENUM_VALUE"         , REG_ENUM_VALUE         , api_reg_enum_value       },
index a405948864b8eae8b1794d1fbd4798ef0e069332..4db5ed0ed6227df9fb0d64bb3f6b005f9acade0f 100644 (file)
 #define OUR_HANDLE(hnd) (((hnd)==NULL)?"NULL":(IVAL((hnd)->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER")), \
 ((unsigned int)IVAL((hnd)->data5,4)),((unsigned int)sys_getpid())
 
+static struct generic_mapping reg_generic_map = 
+       { REG_KEY_READ, REG_KEY_WRITE, REG_KEY_EXECUTE, REG_KEY_ALL };
 
-static struct generic_mapping reg_generic_map = { REG_KEY_READ, REG_KEY_WRITE, REG_KEY_EXECUTE, REG_KEY_ALL };
-
-/********************************************************************
-********************************************************************/
-
-NTSTATUS registry_access_check( SEC_DESC *sec_desc, NT_USER_TOKEN *token, 
-                                     uint32 access_desired, uint32 *access_granted )
-{
-       NTSTATUS result;
-               
-       if ( geteuid() == sec_initial_uid() ) {
-               DEBUG(5,("registry_access_check: access check bypassed for 'root'\n"));
-               *access_granted = REG_KEY_ALL;
-               return NT_STATUS_OK;
-       }
-
-       se_map_generic( &access_desired, &reg_generic_map );
-       se_access_check( sec_desc, token, access_desired, access_granted, &result );
-
-       return result;
-}
-
-/********************************************************************
-********************************************************************/
-
-SEC_DESC* construct_registry_sd( TALLOC_CTX *ctx )
-{
-       SEC_ACE ace[2]; 
-       SEC_ACCESS mask;
-       size_t i = 0;
-       SEC_DESC *sd;
-       SEC_ACL *acl;
-       uint32 sd_size;
-
-       /* basic access for Everyone */
-       
-       init_sec_access(&mask, REG_KEY_READ );
-       init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
-       
-       /* Full Access 'BUILTIN\Administrators' */
-       
-       init_sec_access(&mask, REG_KEY_ALL );
-       init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
-       
-       
-       /* create the security descriptor */
-       
-       if ( !(acl = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) )
-               return NULL;
-
-       if ( !(sd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL, acl, &sd_size)) )
-               return NULL;
-
-       return sd;
-}
 
 /******************************************************************
  free() function for REGISTRY_KEY
@@ -96,9 +43,7 @@ SEC_DESC* construct_registry_sd( TALLOC_CTX *ctx )
  
 static void free_regkey_info(void *ptr)
 {
-       REGISTRY_KEY *info = (REGISTRY_KEY*)ptr;
-       
-       SAFE_FREE(info);
+       TALLOC_FREE( ptr );
 }
 
 /******************************************************************
@@ -126,89 +71,38 @@ static REGISTRY_KEY *find_regkey_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
  HK[LM|U]\<key>\<key>\...
  *******************************************************************/
  
-static WERROR open_registry_key(pipes_struct *p, POLICY_HND *hnd, REGISTRY_KEY *parent,
-                               const char *subkeyname, uint32 access_granted  )
+static WERROR open_registry_key( pipes_struct *p, POLICY_HND *hnd, 
+                                 REGISTRY_KEY **keyinfo, REGISTRY_KEY *parent,
+                                const char *subkeyname, uint32 access_desired  )
 {
-       REGISTRY_KEY    *regkey = NULL;
+       pstring         keypath;
+       int             path_len;
        WERROR          result = WERR_OK;
-       REGSUBKEY_CTR   *subkeys = NULL;
-       pstring         subkeyname2;
-       int             subkey_len;
-       
-       DEBUG(7,("open_registry_key: name = [%s][%s]\n", 
-               parent ? parent->name : "NULL", subkeyname));
-
-       /* strip any trailing '\'s */
-       pstrcpy( subkeyname2, subkeyname );
-       subkey_len = strlen ( subkeyname2 );
-       if ( subkey_len && subkeyname2[subkey_len-1] == '\\' )
-               subkeyname2[subkey_len-1] = '\0';
 
-       if ((regkey=SMB_MALLOC_P(REGISTRY_KEY)) == NULL)
-               return WERR_NOMEM;
-               
-       ZERO_STRUCTP( regkey );
-       
-       /* 
-        * very crazy, but regedit.exe on Win2k will attempt to call 
-        * REG_OPEN_ENTRY with a keyname of "".  We should return a new 
-        * (second) handle here on the key->name.  regedt32.exe does 
-        * not do this stupidity.   --jerry
-        */
-       
-       if ( !subkey_len ) {
-               pstrcpy( regkey->name, parent->name );  
-       }
-       else {
-               pstrcpy( regkey->name, "" );
-               if ( parent ) {
-                       pstrcat( regkey->name, parent->name );
-                       pstrcat( regkey->name, "\\" );
-               }
-               pstrcat( regkey->name, subkeyname2 );
-       }
+       /* create a full registry path and strip any trailing '\' 
+          characters */
+          
+       pstr_sprintf( keypath, "%s%s%s", 
+               parent ? parent->name : "",
+               parent ? "\\" : "", 
+               subkeyname );
        
-       /* Look up the table of registry I/O operations */
-
-       if ( !(regkey->hook = reghook_cache_find( regkey->name )) ) {
-               DEBUG(0,("open_registry_key: Failed to assigned a REGISTRY_HOOK to [%s]\n",
-                       regkey->name ));
-               result = WERR_BADFILE;
-               goto done;
-       }
+       path_len = strlen( keypath );
+       if ( path_len && keypath[path_len-1] == '\\' )
+               keypath[path_len-1] = '\0';
        
-       /* check if the path really exists; failed is indicated by -1 */
-       /* if the subkey count failed, bail out */
-
-       if ( !(subkeys = TALLOC_ZERO_P( p->mem_ctx, REGSUBKEY_CTR )) ) {
-               result = WERR_NOMEM;
-               goto done;
-       }
-
-       if ( fetch_reg_keys( regkey, subkeys ) == -1 )  {
-               result = WERR_BADFILE;
-               goto done;
-       }
+       /* now do the internal open */
                
-       if ( !create_policy_hnd( p, hnd, free_regkey_info, regkey ) ) {
+       result = regkey_open_internal( keyinfo, keypath, p->pipe_user.nt_user_token, access_desired );
+       if ( !W_ERROR_IS_OK(result) )
+               return result;
+       
+       if ( !create_policy_hnd( p, hnd, free_regkey_info, *keyinfo ) ) {
                result = WERR_BADFILE; 
-               goto done;
+               TALLOC_FREE( *keyinfo );
        }
        
-       /* save the access mask */
-
-       regkey->access_granted = access_granted;
-       
-done:
-       /* clean up */
-
-       TALLOC_FREE( subkeys );
-       
-       if ( ! NT_STATUS_IS_OK(result) )
-               SAFE_FREE( regkey );
        
-       DEBUG(7,("open_registry_key: exit\n"));
-
        return result;
 }
 
@@ -332,43 +226,39 @@ WERROR _reg_close(pipes_struct *p, REG_Q_CLOSE *q_u, REG_R_CLOSE *r_u)
 
 WERROR _reg_open_hklm(pipes_struct *p, REG_Q_OPEN_HIVE *q_u, REG_R_OPEN_HIVE *r_u)
 {
-       SEC_DESC *sec_desc;
-       uint32 access_granted = 0;
-       NTSTATUS status;
+       REGISTRY_KEY *keyinfo;
        
-       /* perform access checks */
-       /* top level keys are done here without passing through the REGISTRY_HOOK api */
+       return open_registry_key( p, &r_u->pol, &keyinfo, NULL, KEY_HKLM, q_u->access );
+}
+
+/*******************************************************************
+ ********************************************************************/
+
+WERROR _reg_open_hkpd(pipes_struct *p, REG_Q_OPEN_HIVE *q_u, REG_R_OPEN_HIVE *r_u)
+{
+       REGISTRY_KEY *keyinfo;
        
-       if ( !(sec_desc = construct_registry_sd( p->mem_ctx )) )
-               return WERR_NOMEM;
-               
-       status = registry_access_check( sec_desc, p->pipe_user.nt_user_token, q_u->access, &access_granted );
-       if ( !NT_STATUS_IS_OK(status) )
-               return ntstatus_to_werror( status );
-               
-       return open_registry_key( p, &r_u->pol, NULL, KEY_HKLM, access_granted );
+       return open_registry_key( p, &r_u->pol, &keyinfo, NULL, KEY_HKPD, q_u->access );
 }
 
 /*******************************************************************
  ********************************************************************/
 
-WERROR _reg_open_hkcr(pipes_struct *p, REG_Q_OPEN_HIVE *q_u, REG_R_OPEN_HIVE *r_u)
+WERROR _reg_open_hkpt(pipes_struct *p, REG_Q_OPEN_HIVE *q_u, REG_R_OPEN_HIVE *r_u)
 {
-       SEC_DESC *sec_desc;
-       uint32 access_granted = 0;
-       NTSTATUS status;
+       REGISTRY_KEY *keyinfo;
        
-       /* perform access checks */
-       /* top level keys are done here without passing through the REGISTRY_HOOK api */
+       return open_registry_key( p, &r_u->pol, &keyinfo, NULL, KEY_HKPT, q_u->access );
+}
+
+/*******************************************************************
+ ********************************************************************/
+
+WERROR _reg_open_hkcr(pipes_struct *p, REG_Q_OPEN_HIVE *q_u, REG_R_OPEN_HIVE *r_u)
+{
+       REGISTRY_KEY *keyinfo;
        
-       if ( !(sec_desc = construct_registry_sd( p->mem_ctx )) )
-               return WERR_NOMEM;
-               
-       status = registry_access_check( sec_desc, p->pipe_user.nt_user_token, q_u->access, &access_granted );
-       if ( !NT_STATUS_IS_OK(status) )
-               return ntstatus_to_werror( status );
-               
-       return open_registry_key( p, &r_u->pol, NULL, KEY_HKCR, access_granted );
+       return open_registry_key( p, &r_u->pol, &keyinfo, NULL, KEY_HKCR, q_u->access );
 }
 
 /*******************************************************************
@@ -376,21 +266,9 @@ WERROR _reg_open_hkcr(pipes_struct *p, REG_Q_OPEN_HIVE *q_u, REG_R_OPEN_HIVE *r_
 
 WERROR _reg_open_hku(pipes_struct *p, REG_Q_OPEN_HIVE *q_u, REG_R_OPEN_HIVE *r_u)
 {
-       SEC_DESC *sec_desc;
-       uint32 access_granted = 0;
-       NTSTATUS status;
-       
-       /* perform access checks */
-       /* top level keys are done here without passing through the REGISTRY_HOOK api */
+       REGISTRY_KEY *keyinfo;
        
-       if ( !(sec_desc = construct_registry_sd( p->mem_ctx )) )
-               return WERR_NOMEM;
-               
-       status = registry_access_check( sec_desc, p->pipe_user.nt_user_token, q_u->access, &access_granted );
-       if ( !NT_STATUS_IS_OK(status) )
-               return ntstatus_to_werror( status );
-               
-       return open_registry_key( p, &r_u->pol, NULL, KEY_HKU, access_granted );
+       return open_registry_key( p, &r_u->pol, &keyinfo, NULL, KEY_HKU, q_u->access );
 }
 
 /*******************************************************************
@@ -401,9 +279,8 @@ WERROR _reg_open_entry(pipes_struct *p, REG_Q_OPEN_ENTRY *q_u, REG_R_OPEN_ENTRY
 {
        fstring name;
        REGISTRY_KEY *parent = find_regkey_index_by_hnd(p, &q_u->pol);
-       REGISTRY_KEY *newkey;
-       uint32 access_granted;
-       WERROR result;
+       REGISTRY_KEY *newkey = NULL;
+       uint32 check_rights;
 
        if ( !parent )
                return WERR_BADFID;
@@ -412,29 +289,22 @@ WERROR _reg_open_entry(pipes_struct *p, REG_Q_OPEN_ENTRY *q_u, REG_R_OPEN_ENTRY
        
        /* check granted access first; what is the correct mask here? */
 
-       if ( !(parent->access_granted & (SEC_RIGHTS_ENUM_SUBKEYS|SEC_RIGHTS_CREATE_SUBKEY|SEC_RIGHTS_QUERY_VALUE|SEC_RIGHTS_SET_VALUE)) )
+       check_rights = ( SEC_RIGHTS_ENUM_SUBKEYS|
+                         SEC_RIGHTS_CREATE_SUBKEY|
+                        SEC_RIGHTS_QUERY_VALUE|
+                        SEC_RIGHTS_SET_VALUE);
+                        
+       if ( !(parent->access_granted & check_rights) )
                return WERR_ACCESS_DENIED;
        
-       /* open the key first to get the appropriate REGISTRY_HOOK 
-          and then check the premissions */
-
-       if ( !W_ERROR_IS_OK(result = open_registry_key( p, &r_u->handle, parent, name, 0 )) )
-               return result;
-
-       newkey = find_regkey_index_by_hnd(p, &r_u->handle);
-
-       /* finally allow the backend to check the access for the requested key */
-
-       if ( !regkey_access_check( newkey, q_u->access, &access_granted, p->pipe_user.nt_user_token ) ) {
-               close_registry_key( p, &r_u->handle );
-               return WERR_ACCESS_DENIED;
-       }
-
-       /* if successful, save the granted access mask */
-
-       newkey->access_granted = access_granted;
-       
-       return WERR_OK;
+       /* 
+        * very crazy, but regedit.exe on Win2k will attempt to call 
+        * REG_OPEN_ENTRY with a keyname of "".  We should return a new 
+        * (second) handle here on the key->name.  regedt32.exe does 
+        * not do this stupidity.   --jerry
+        */
+        
+       return open_registry_key( p, &r_u->handle, &newkey, parent, name, q_u->access );
 }
 
 /*******************************************************************
@@ -454,16 +324,93 @@ WERROR _reg_query_value(pipes_struct *p, REG_Q_QUERY_VALUE *q_u, REG_R_QUERY_VAL
                return WERR_BADFID;
                
        DEBUG(7,("_reg_info: policy key name = [%s]\n", regkey->name));
+       DEBUG(7,("_reg_info: policy key type = [%08x]\n", regkey->type));
        
        rpcstr_pull(name, q_u->name.string->buffer, sizeof(name), q_u->name.string->uni_str_len*2, 0);
 
-       DEBUG(5,("reg_info: looking up value: [%s]\n", name));
+       DEBUG(5,("_reg_info: looking up value: [%s]\n", name));
 
        if ( !(regvals = TALLOC_P( p->mem_ctx, REGVAL_CTR )) ) 
                return WERR_NOMEM;
        
-       for ( i=0; fetch_reg_values_specific(regkey, &val, i); i++ ) 
+       /* Handle QueryValue calls on HKEY_PERFORMANCE_DATA */
+       if(regkey->type == REG_KEY_HKPD) 
+       {
+               if(strequal(name, "Global"))
+               {
+                       uint32 outbuf_len;
+                       prs_struct prs_hkpd;
+                       prs_init(&prs_hkpd, q_u->bufsize, p->mem_ctx, MARSHALL);
+                       status = reg_perfcount_get_hkpd(&prs_hkpd, q_u->bufsize, &outbuf_len, NULL);
+                       regval_ctr_addvalue(regvals, "HKPD", REG_BINARY,
+                                           prs_hkpd.data_p, outbuf_len);
+                       val = dup_registry_value(regval_ctr_specific_value(regvals, 0));
+                       prs_mem_free(&prs_hkpd);
+               }
+               else if(strequal(name, "Counter 009"))
+               {
+                       uint32 base_index;
+                       uint32 buffer_size;
+                       char *buffer;
+                       
+                       buffer = NULL;
+                       base_index = reg_perfcount_get_base_index();
+                       buffer_size = reg_perfcount_get_counter_names(base_index, &buffer);
+                       regval_ctr_addvalue(regvals, "Counter 009", 
+                                           REG_MULTI_SZ, buffer, buffer_size);
+                       
+                       val = dup_registry_value(regval_ctr_specific_value(regvals, 0));
+                       
+                       if(buffer_size > 0)
+                       {
+                               SAFE_FREE(buffer);
+                               status = WERR_OK;
+                       }
+               }
+               else if(strequal(name, "Explain 009"))
+               {               
+                       uint32 base_index;
+                       uint32 buffer_size;
+                       char *buffer;
+                       
+                       buffer = NULL;
+                       base_index = reg_perfcount_get_base_index();
+                       buffer_size = reg_perfcount_get_counter_help(base_index, &buffer);
+                       regval_ctr_addvalue(regvals, "Explain 009", 
+                                           REG_MULTI_SZ, buffer, buffer_size);
+                       
+                       val = dup_registry_value(regval_ctr_specific_value(regvals, 0));
+                       
+                       if(buffer_size > 0)
+                       {
+                               SAFE_FREE(buffer);
+                               status = WERR_OK;
+                       }
+               }
+               else if(isdigit(name[0]))
+               {
+                       /* we probably have a request for a specific object here */
+                       uint32 outbuf_len;
+                       prs_struct prs_hkpd;
+                       prs_init(&prs_hkpd, q_u->bufsize, p->mem_ctx, MARSHALL);
+                       status = reg_perfcount_get_hkpd(&prs_hkpd, q_u->bufsize, &outbuf_len, name);
+                       regval_ctr_addvalue(regvals, "HKPD", REG_BINARY,
+                                           prs_hkpd.data_p, outbuf_len);
+                       
+                       val = dup_registry_value(regval_ctr_specific_value(regvals, 0));
+                       prs_mem_free(&prs_hkpd);
+               }
+               else
+               {
+                       DEBUG(3,("Unsupported key name [%s] for HKPD.\n", name));
+                       return WERR_BADFILE;
+               }
+       }
+       /* HKPT calls can be handled out of reg_dynamic.c with the hkpt_params handler */
+       else
        {
+           for ( i=0; fetch_reg_values_specific(regkey, &val, i); i++ ) 
+           {
                DEBUG(10,("_reg_info: Testing value [%s]\n", val->valuename));
                if ( strequal( val->valuename, name ) ) {
                        DEBUG(10,("_reg_info: Found match for value [%s]\n", name));
@@ -472,6 +419,7 @@ WERROR _reg_query_value(pipes_struct *p, REG_Q_QUERY_VALUE *q_u, REG_R_QUERY_VAL
                }
                
                free_registry_value( val );
+           }
        }
 
        init_reg_r_query_value(q_u->ptr_buf, r_u, val, status);
@@ -482,7 +430,6 @@ WERROR _reg_query_value(pipes_struct *p, REG_Q_QUERY_VALUE *q_u, REG_R_QUERY_VAL
        return status;
 }
 
-
 /*****************************************************************************
  Implementation of REG_QUERY_KEY
  ****************************************************************************/
@@ -998,7 +945,7 @@ static WERROR make_default_reg_sd( TALLOC_CTX *ctx, SEC_DESC **psd )
        SEC_ACE ace[2];         /* at most 2 entries */
        SEC_ACCESS mask;
        SEC_ACL *psa = NULL;
-       uint32 sd_size;
+       size_t sd_size;
 
        /* set the owner to BUILTIN\Administrator */
 
@@ -1092,7 +1039,7 @@ WERROR _reg_save_key(pipes_struct *p, REG_Q_SAVE_KEY  *q_u, REG_R_SAVE_KEY *r_u)
 WERROR _reg_create_key_ex(pipes_struct *p, REG_Q_CREATE_KEY_EX *q_u, REG_R_CREATE_KEY_EX *r_u)
 {
        REGISTRY_KEY *parent = find_regkey_index_by_hnd(p, &q_u->handle);
-       REGISTRY_KEY *newparent;
+       REGISTRY_KEY *newparentinfo, *keyinfo;
        POLICY_HND newparent_handle;
        REGSUBKEY_CTR *subkeys;
        BOOL write_result;
@@ -1109,7 +1056,6 @@ WERROR _reg_create_key_ex(pipes_struct *p, REG_Q_CREATE_KEY_EX *q_u, REG_R_CREAT
        if ( strrchr( name, '\\' ) ) {
                pstring newkeyname;
                char *ptr;
-               uint32 access_granted;
                
                /* (1) check for enumerate rights on the parent handle.  CLients can try 
                       create things like 'SOFTWARE\Samba' on the HKLM handle. 
@@ -1122,19 +1068,11 @@ WERROR _reg_create_key_ex(pipes_struct *p, REG_Q_CREATE_KEY_EX *q_u, REG_R_CREAT
                ptr = strrchr( newkeyname, '\\' );
                *ptr = '\0';
 
-               result = open_registry_key( p, &newparent_handle, parent, newkeyname, 0 );
+               result = open_registry_key( p, &newparent_handle, &newparentinfo, 
+                       parent, newkeyname, (REG_KEY_READ|REG_KEY_WRITE) );
+                       
                if ( !W_ERROR_IS_OK(result) )
                        return result;
-               
-               newparent = find_regkey_index_by_hnd(p, &newparent_handle);
-               SMB_ASSERT( newparent != NULL );
-                       
-               if ( !regkey_access_check( newparent, REG_KEY_READ|REG_KEY_WRITE, &access_granted, p->pipe_user.nt_user_token ) ) {
-                       result = WERR_ACCESS_DENIED;
-                       goto done;
-               }
-
-               newparent->access_granted = access_granted;
 
                /* copy the new key name (just the lower most keyname) */
 
@@ -1142,13 +1080,13 @@ WERROR _reg_create_key_ex(pipes_struct *p, REG_Q_CREATE_KEY_EX *q_u, REG_R_CREAT
        }
        else {
                /* use the existing open key information */
-               newparent = parent;
+               newparentinfo = parent;
                memcpy( &newparent_handle, &q_u->handle, sizeof(POLICY_HND) );
        }
        
        /* (3) check for create subkey rights on the correct parent */
        
-       if ( !(newparent->access_granted & SEC_RIGHTS_CREATE_SUBKEY) ) {
+       if ( !(newparentinfo->access_granted & SEC_RIGHTS_CREATE_SUBKEY) ) {
                result = WERR_ACCESS_DENIED;
                goto done;
        }       
@@ -1160,12 +1098,12 @@ WERROR _reg_create_key_ex(pipes_struct *p, REG_Q_CREATE_KEY_EX *q_u, REG_R_CREAT
 
        /* (4) lookup the current keys and add the new one */
        
-       fetch_reg_keys( newparent, subkeys );
+       fetch_reg_keys( newparentinfo, subkeys );
        regsubkey_ctr_addkey( subkeys, name );
        
        /* now write to the registry backend */
        
-       write_result = store_reg_keys( newparent, subkeys );
+       write_result = store_reg_keys( newparentinfo, subkeys );
        
        TALLOC_FREE( subkeys );
 
@@ -1173,16 +1111,15 @@ WERROR _reg_create_key_ex(pipes_struct *p, REG_Q_CREATE_KEY_EX *q_u, REG_R_CREAT
                return WERR_REG_IO_FAILURE;
                
        /* (5) open the new key and return the handle.  Note that it is probably 
-          not correct to grant full access on this open handle.  We should pass
-          the new open through the regkey_access_check() like we do for 
-          _reg_open_entry() but this is ok for now. */
+          not correct to grant full access on this open handle. */
        
-       result = open_registry_key( p, &r_u->handle, newparent, name, REG_KEY_ALL );
+       result = open_registry_key( p, &r_u->handle, &keyinfo, newparentinfo, name, REG_KEY_READ );
+       keyinfo->access_granted = REG_KEY_ALL;
 
 done:
        /* close any intermediate key handles */
        
-       if ( newparent != parent )
+       if ( newparentinfo != parent )
                close_registry_key( p, &newparent_handle );
                
        return result;
@@ -1243,7 +1180,7 @@ WERROR _reg_set_value(pipes_struct *p, REG_Q_SET_VALUE  *q_u, REG_R_SET_VALUE *r
 WERROR _reg_delete_key(pipes_struct *p, REG_Q_DELETE_KEY  *q_u, REG_R_DELETE_KEY *r_u)
 {
        REGISTRY_KEY *parent = find_regkey_index_by_hnd(p, &q_u->handle);
-       REGISTRY_KEY *newparent;
+       REGISTRY_KEY *newparentinfo;
        POLICY_HND newparent_handle;
        REGSUBKEY_CTR *subkeys;
        BOOL write_result;
@@ -1252,6 +1189,15 @@ WERROR _reg_delete_key(pipes_struct *p, REG_Q_DELETE_KEY  *q_u, REG_R_DELETE_KEY
 
        if ( !parent )
                return WERR_BADFID;
+
+       /* MSDN says parent the handle must have been opened with DELETE access */
+
+       /* (1) check for delete rights on the parent */
+       
+       if ( !(parent->access_granted & STD_RIGHT_DELETE_ACCESS) ) {
+               result = WERR_ACCESS_DENIED;
+               goto done;
+       }
                
        rpcstr_pull( name, q_u->name.string->buffer, sizeof(name), q_u->name.string->uni_str_len*2, 0 );
                
@@ -1260,50 +1206,24 @@ WERROR _reg_delete_key(pipes_struct *p, REG_Q_DELETE_KEY  *q_u, REG_R_DELETE_KEY
        if ( strrchr( name, '\\' ) ) {
                pstring newkeyname;
                char *ptr;
-               uint32 access_granted;
                
-               /* (1) check for enumerate rights on the parent handle.  CLients can try 
-                      create things like 'SOFTWARE\Samba' on the HKLM handle. 
-                  (2) open the path to the child parent key if necessary */
+               /* (2) open the path to the child parent key if necessary */
+               /* split the registry path and save the subkeyname */
        
-               if ( !(parent->access_granted & SEC_RIGHTS_ENUM_SUBKEYS) )
-                       return WERR_ACCESS_DENIED;
-               
                pstrcpy( newkeyname, name );
                ptr = strrchr( newkeyname, '\\' );
                *ptr = '\0';
+               pstrcpy( name, ptr+1 );
 
-               result = open_registry_key( p, &newparent_handle, parent, newkeyname, 0 );
+               result = open_registry_key( p, &newparent_handle, &newparentinfo, parent, newkeyname, (REG_KEY_READ|REG_KEY_WRITE) );
                if ( !W_ERROR_IS_OK(result) )
                        return result;
-               
-               newparent = find_regkey_index_by_hnd(p, &newparent_handle);
-               SMB_ASSERT( newparent != NULL );
-                       
-               if ( !regkey_access_check( newparent, REG_KEY_READ|REG_KEY_WRITE, &access_granted, p->pipe_user.nt_user_token ) ) {
-                       result = WERR_ACCESS_DENIED;
-                       goto done;
-               }
-
-               newparent->access_granted = access_granted;
-
-               /* copy the new key name (just the lower most keyname) */
-
-               pstrcpy( name, ptr+1 );
        }
        else {
                /* use the existing open key information */
-               newparent = parent;
-               memcpy( &newparent_handle, &q_u->handle, sizeof(POLICY_HND) );
+               newparentinfo = parent;
        }
        
-       /* (3) check for create subkey rights on the correct parent */
-       
-       if ( !(newparent->access_granted & STD_RIGHT_DELETE_ACCESS) ) {
-               result = WERR_ACCESS_DENIED;
-               goto done;
-       }
-
        if ( !(subkeys = TALLOC_ZERO_P( p->mem_ctx, REGSUBKEY_CTR )) ) {
                result = WERR_NOMEM;
                goto done;
@@ -1311,13 +1231,13 @@ WERROR _reg_delete_key(pipes_struct *p, REG_Q_DELETE_KEY  *q_u, REG_R_DELETE_KEY
        
        /* lookup the current keys and delete the new one */
        
-       fetch_reg_keys( newparent, subkeys );
+       fetch_reg_keys( newparentinfo, subkeys );
        
        regsubkey_ctr_delkey( subkeys, name );
        
        /* now write to the registry backend */
        
-       write_result = store_reg_keys( newparent, subkeys );
+       write_result = store_reg_keys( newparentinfo, subkeys );
        
        TALLOC_FREE( subkeys );
 
@@ -1326,7 +1246,7 @@ WERROR _reg_delete_key(pipes_struct *p, REG_Q_DELETE_KEY  *q_u, REG_R_DELETE_KEY
 done:
        /* close any intermediate key handles */
        
-       if ( newparent != parent )
+       if ( newparentinfo != parent )
                close_registry_key( p, &newparent_handle );
 
        return result;
@@ -1414,5 +1334,3 @@ WERROR _reg_set_key_sec(pipes_struct *p, REG_Q_SET_KEY_SEC  *q_u, REG_R_SET_KEY_
                
        return WERR_ACCESS_DENIED;
 }
-
-
index 656241a73f9aadd8022647501e5e9479993529b0..b69f03a3a283cf0ac569d4029eb4dfa4a9e66709 100644 (file)
@@ -6,7 +6,7 @@
  *  Copyright (C) Paul Ashton                       1997,
  *  Copyright (C) Marc Jacobsen                            1999,
  *  Copyright (C) Jeremy Allison                    2001-2002,
- *  Copyright (C) Jean François Micouleau          1998-2001,
+ *  Copyright (C) Jean François Micouleau           1998-2001,
  *  Copyright (C) Jim McDonough <jmcd@us.ibm.com>   2002,
  *  Copyright (C) Gerald (Jerry) Carter             2003-2004,
  *  Copyright (C) Simo Sorce                        2003.
@@ -88,17 +88,17 @@ static NTSTATUS make_samr_object_sd( TALLOC_CTX *ctx, SEC_DESC **psd, size_t *sd
        SEC_ACL *psa = NULL;
 
        /* basic access for Everyone */
-       
+
        init_sec_access(&mask, map->generic_execute | map->generic_read );
        init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
-       
+
        /* add Full Access 'BUILTIN\Administrators' and 'BUILTIN\Account Operators */
-       
+
        init_sec_access(&mask, map->generic_all);
        
        init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
        init_sec_ace(&ace[i++], &global_sid_Builtin_Account_Operators, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
-       
+
        /* Add Full Access for Domain Admins if we are a DC */
        
        if ( IS_DC ) {
@@ -108,14 +108,14 @@ static NTSTATUS make_samr_object_sd( TALLOC_CTX *ctx, SEC_DESC **psd, size_t *sd
        }
 
        /* if we have a sid, give it some special access */
-       
+
        if ( sid ) {
                init_sec_access( &mask, sid_access );
                init_sec_ace(&ace[i++], sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
-       }
-       
+}
+
        /* create the security descriptor */
-       
+
        if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) == NULL)
                return NT_STATUS_NO_MEMORY;
 
@@ -347,7 +347,7 @@ NTSTATUS _samr_open_domain(pipes_struct *p, SAMR_Q_OPEN_DOMAIN *q_u, SAMR_R_OPEN
        uint32    acc_granted;
        uint32    des_access = q_u->flags;
        NTSTATUS  status;
-       size_t sd_size;
+       size_t    sd_size;
        SE_PRIV se_rights;
 
        r_u->status = NT_STATUS_OK;
@@ -421,7 +421,6 @@ NTSTATUS _samr_get_usrdom_pwinfo(pipes_struct *p, SAMR_Q_GET_USRDOM_PWINFO *q_u,
        return r_u->status;
 }
 
-
 /*******************************************************************
  _samr_set_sec_obj
  ********************************************************************/
@@ -1456,11 +1455,13 @@ static NTSTATUS get_user_info_18(pipes_struct *p, TALLOC_CTX *mem_ctx, SAM_USER_
        BOOL ret;
        NTSTATUS nt_status;
 
-       if (!p->ntlmssp_auth_validated)
+       if (p->auth.auth_type != PIPE_AUTH_TYPE_NTLMSSP || p->auth.auth_type != PIPE_AUTH_TYPE_SPNEGO_NTLMSSP) {
                return NT_STATUS_ACCESS_DENIED;
+       }
 
-       if (!(p->ntlmssp_chal_flags & NTLMSSP_NEGOTIATE_SIGN) || !(p->ntlmssp_chal_flags & NTLMSSP_NEGOTIATE_SEAL))
+       if (p->auth.auth_level != PIPE_AUTH_LEVEL_PRIVACY) {
                return NT_STATUS_ACCESS_DENIED;
+       }
 
        /*
         * Do *NOT* do become_root()/unbecome_root() here ! JRA.
@@ -1794,11 +1795,12 @@ NTSTATUS _samr_query_dom_info(pipes_struct *p, SAMR_Q_QUERY_DOMAIN_INFO *q_u, SA
        time_t u_lock_duration, u_reset_time;
        NTTIME nt_lock_duration, nt_reset_time;
        uint32 lockout;
-       
        time_t u_logout;
        NTTIME nt_logout;
 
        uint32 account_policy_temp;
+
+       time_t seq_num;
        uint32 server_role;
 
        uint32 num_users=0, num_groups=0, num_aliases=0;
@@ -1819,19 +1821,19 @@ NTSTATUS _samr_query_dom_info(pipes_struct *p, SAMR_Q_QUERY_DOMAIN_INFO *q_u, SA
        switch (q_u->switch_value) {
                case 0x01:
                        
-                       account_policy_get(AP_MIN_PASSWORD_LEN, &account_policy_temp);
+                       pdb_get_account_policy(AP_MIN_PASSWORD_LEN, &account_policy_temp);
                        min_pass_len = account_policy_temp;
 
-                       account_policy_get(AP_PASSWORD_HISTORY, &account_policy_temp);
+                       pdb_get_account_policy(AP_PASSWORD_HISTORY, &account_policy_temp);
                        pass_hist = account_policy_temp;
 
-                       account_policy_get(AP_USER_MUST_LOGON_TO_CHG_PASS, &account_policy_temp);
+                       pdb_get_account_policy(AP_USER_MUST_LOGON_TO_CHG_PASS, &account_policy_temp);
                        flag = account_policy_temp;
 
-                       account_policy_get(AP_MAX_PASSWORD_AGE, &account_policy_temp);
+                       pdb_get_account_policy(AP_MAX_PASSWORD_AGE, &account_policy_temp);
                        u_expire = account_policy_temp;
 
-                       account_policy_get(AP_MIN_PASSWORD_AGE, &account_policy_temp);
+                       pdb_get_account_policy(AP_MIN_PASSWORD_AGE, &account_policy_temp);
                        u_min_age = account_policy_temp;
                        
                        unix_to_nt_time_abs(&nt_expire, u_expire);
@@ -1847,21 +1849,23 @@ NTSTATUS _samr_query_dom_info(pipes_struct *p, SAMR_Q_QUERY_DOMAIN_INFO *q_u, SA
                        num_groups=count_sam_groups(&info->disp_info);
                        unbecome_root();
 
-                       account_policy_get(AP_TIME_TO_LOGOUT, &account_policy_temp);
+                       pdb_get_account_policy(AP_TIME_TO_LOGOUT, &account_policy_temp);
                        u_logout = account_policy_temp;
 
                        unix_to_nt_time_abs(&nt_logout, u_logout);
 
+                       if (!pdb_get_seq_num(&seq_num))
+                               seq_num = time(NULL);
+
                        server_role = ROLE_DOMAIN_PDC;
                        if (lp_server_role() == ROLE_DOMAIN_BDC)
                                server_role = ROLE_DOMAIN_BDC;
 
-                       /* The time call below is to get a sequence number for the sam. FIXME !!! JRA. */
-                       init_unk_info2(&ctr->info.inf2, lp_serverstring(), lp_workgroup(), global_myname(), time(NULL), 
+                       init_unk_info2(&ctr->info.inf2, lp_serverstring(), lp_workgroup(), global_myname(), seq_num, 
                                       num_users, num_groups, num_aliases, nt_logout, server_role);
                        break;
                case 0x03:
-                       account_policy_get(AP_TIME_TO_LOGOUT, (unsigned int *)&u_logout);
+                       pdb_get_account_policy(AP_TIME_TO_LOGOUT, (unsigned int *)&u_logout);
                        unix_to_nt_time_abs(&nt_logout, u_logout);
                        
                        init_unk_info3(&ctr->info.inf3, nt_logout);
@@ -1880,18 +1884,21 @@ NTSTATUS _samr_query_dom_info(pipes_struct *p, SAMR_Q_QUERY_DOMAIN_INFO *q_u, SA
                        init_unk_info7(&ctr->info.inf7, server_role);
                        break;
                case 0x08:
-                       init_unk_info8(&ctr->info.inf8, (uint32) time(NULL));
+                       if (!pdb_get_seq_num(&seq_num))
+                               seq_num = time(NULL);
+
+                       init_unk_info8(&ctr->info.inf8, (uint32) seq_num);
                        break;
                case 0x0c:
-                       account_policy_get(AP_LOCK_ACCOUNT_DURATION, &account_policy_temp);
+                       pdb_get_account_policy(AP_LOCK_ACCOUNT_DURATION, &account_policy_temp);
                        u_lock_duration = account_policy_temp;
                        if (u_lock_duration != -1)
                                u_lock_duration *= 60;
 
-                       account_policy_get(AP_RESET_COUNT_TIME, &account_policy_temp);
+                       pdb_get_account_policy(AP_RESET_COUNT_TIME, &account_policy_temp);
                        u_reset_time = account_policy_temp * 60;
 
-                       account_policy_get(AP_BAD_ATTEMPT_LOCKOUT, &account_policy_temp);
+                       pdb_get_account_policy(AP_BAD_ATTEMPT_LOCKOUT, &account_policy_temp);
                        lockout = account_policy_temp;
 
                        unix_to_nt_time_abs(&nt_lock_duration, u_lock_duration);
@@ -1955,7 +1962,7 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_CREA
 
        rpcstr_pull(account, user_account.buffer, sizeof(account), user_account.uni_str_len*2, 0);
        strlower_m(account);
-               
+
        pdb_init_sam(&sam_pass);
 
        become_root();
@@ -1968,7 +1975,7 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_CREA
        }
 
        pdb_free_sam(&sam_pass);
-       
+
        /*********************************************************************
         * HEADS UP!  If we have to create a new user account, we have to get 
         * a new RID from somewhere.  This used to be done by the passdb 
@@ -1979,7 +1986,7 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_CREA
         * of what ever passdb backend people may use.
         *                                             --jerry (2003-07-10)
         *********************************************************************/
-       
+
        pw = Get_Pwnam(account);
 
        /* determine which user right we need to check based on the acb_info */
@@ -2005,27 +2012,27 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_CREA
                        /* only Domain Admins can add a BDC or domain trust */
                        se_priv_copy( &se_rights, &se_priv_none );
                        can_add_account = nt_token_check_domain_rid( p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS );
-               }
        }
-       
+       }
+               
        DEBUG(5, ("_samr_create_user: %s can add this account : %s\n",
                p->pipe_user_name, can_add_account ? "True":"False" ));
                
        /********** BEGIN Admin BLOCK **********/
-       
+
        if ( can_add_account )
                become_root();
-                               
+
        if ( !pw ) {
                if (*add_script) {
-                       int add_ret;
-                       
-                       all_string_sub(add_script, "%u", account, sizeof(add_script));
-                       add_ret = smbrun(add_script,NULL);
-                       DEBUG(add_ret ? 0 : 3,("_samr_create_user: Running the command `%s' gave %d\n", add_script, add_ret));
-               }
+                       int add_ret;
+
+                       all_string_sub(add_script, "%u", account, sizeof(add_script));
+                       add_ret = smbrun(add_script,NULL);
+                       DEBUG(add_ret ? 0 : 3,("_samr_create_user: Running the command `%s' gave %d\n", add_script, add_ret));
+               }
        }
-       
+
        /* implicit call to getpwnam() next.  we have a valid SID coming out of this call */
 
        flush_pwnam_cache();
@@ -2147,7 +2154,7 @@ NTSTATUS _samr_connect(pipes_struct *p, SAMR_Q_CONNECT *q_u, SAMR_R_CONNECT *r_u
        uint32    acc_granted;
        uint32    des_access = q_u->access_mask;
        NTSTATUS  nt_status;
-       size_t sd_size;
+       size_t    sd_size;
 
 
        DEBUG(5,("_samr_connect: %d\n", __LINE__));
@@ -2198,7 +2205,7 @@ NTSTATUS _samr_connect4(pipes_struct *p, SAMR_Q_CONNECT4 *q_u, SAMR_R_CONNECT4 *
        uint32    acc_granted;
        uint32    des_access = q_u->access_mask;
        NTSTATUS  nt_status;
-       size_t sd_size;
+       size_t    sd_size;
 
 
        DEBUG(5,("_samr_connect4: %d\n", __LINE__));
@@ -2734,7 +2741,7 @@ NTSTATUS _samr_set_userinfo(pipes_struct *p, SAMR_Q_SET_USERINFO *q_u, SAMR_R_SE
        if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, acc_required, "_samr_set_userinfo"))) {
                return r_u->status;
        }
-               
+
        DEBUG(5, ("_samr_set_userinfo: sid:%s, level:%d\n", sid_string_static(&sid), switch_value));
 
        if (ctr == NULL) {
@@ -2765,7 +2772,7 @@ NTSTATUS _samr_set_userinfo(pipes_struct *p, SAMR_Q_SET_USERINFO *q_u, SAMR_R_SE
                if ( lp_enable_privileges() )
                        has_enough_rights = nt_token_check_domain_rid( p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS );
        }
-               
+       
        DEBUG(5, ("_samr_set_userinfo: %s does%s possess sufficient rights\n",
                p->pipe_user_name, has_enough_rights ? "" : " not"));
 
@@ -2905,7 +2912,7 @@ NTSTATUS _samr_set_userinfo2(pipes_struct *p, SAMR_Q_SET_USERINFO2 *q_u, SAMR_R_
                if ( lp_enable_privileges() )
                        has_enough_rights = nt_token_check_domain_rid( p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS );
        }
-               
+       
        DEBUG(5, ("_samr_set_userinfo: %s does%s possess sufficient rights\n",
                p->pipe_user_name, has_enough_rights ? "" : " not"));
 
@@ -3597,7 +3604,7 @@ NTSTATUS _samr_delete_dom_group(pipes_struct *p, SAMR_Q_DELETE_DOM_GROUP *q_u, S
        gid=map.gid;
 
        /* check if group really exists */
-       if ( (grp=getgrgid(gid)) == NULL)
+       if ( (grp=getgrgid(gid)) == NULL) 
                return NT_STATUS_NO_SUCH_GROUP;
 
        se_priv_copy( &se_rights, &se_add_users );
@@ -4195,6 +4202,8 @@ NTSTATUS _samr_unknown_2e(pipes_struct *p, SAMR_Q_UNKNOWN_2E *q_u, SAMR_R_UNKNOW
        uint32 num_users=0, num_groups=0, num_aliases=0;
 
        uint32 account_policy_temp;
+
+       time_t seq_num;
        uint32 server_role;
 
        if ((ctr = TALLOC_ZERO_P(p->mem_ctx, SAM_UNK_CTR)) == NULL)
@@ -4212,19 +4221,19 @@ NTSTATUS _samr_unknown_2e(pipes_struct *p, SAMR_Q_UNKNOWN_2E *q_u, SAMR_R_UNKNOW
 
        switch (q_u->switch_value) {
                case 0x01:
-                       account_policy_get(AP_MIN_PASSWORD_LEN, &account_policy_temp);
+                       pdb_get_account_policy(AP_MIN_PASSWORD_LEN, &account_policy_temp);
                        min_pass_len = account_policy_temp;
 
-                       account_policy_get(AP_PASSWORD_HISTORY, &account_policy_temp);
+                       pdb_get_account_policy(AP_PASSWORD_HISTORY, &account_policy_temp);
                        pass_hist = account_policy_temp;
 
-                       account_policy_get(AP_USER_MUST_LOGON_TO_CHG_PASS, &account_policy_temp);
+                       pdb_get_account_policy(AP_USER_MUST_LOGON_TO_CHG_PASS, &account_policy_temp);
                        flag = account_policy_temp;
 
-                       account_policy_get(AP_MAX_PASSWORD_AGE, &account_policy_temp);
+                       pdb_get_account_policy(AP_MAX_PASSWORD_AGE, &account_policy_temp);
                        u_expire = account_policy_temp;
 
-                       account_policy_get(AP_MIN_PASSWORD_AGE, &account_policy_temp);
+                       pdb_get_account_policy(AP_MIN_PASSWORD_AGE, &account_policy_temp);
                        u_min_age = account_policy_temp;
 
                        unix_to_nt_time_abs(&nt_expire, u_expire);
@@ -4242,21 +4251,23 @@ NTSTATUS _samr_unknown_2e(pipes_struct *p, SAMR_Q_UNKNOWN_2E *q_u, SAMR_R_UNKNOW
 
                        free_samr_db(info);
 
-                       account_policy_get(AP_TIME_TO_LOGOUT, &account_policy_temp);
+                       pdb_get_account_policy(AP_TIME_TO_LOGOUT, &account_policy_temp);
                        u_logout = account_policy_temp;
 
                        unix_to_nt_time_abs(&nt_logout, u_logout);
 
+                       if (!pdb_get_seq_num(&seq_num))
+                               seq_num = time(NULL);
+
                        server_role = ROLE_DOMAIN_PDC;
                        if (lp_server_role() == ROLE_DOMAIN_BDC)
                                server_role = ROLE_DOMAIN_BDC;
 
-                       /* The time call below is to get a sequence number for the sam. FIXME !!! JRA. */
-                       init_unk_info2(&ctr->info.inf2, lp_serverstring(), lp_workgroup(), global_myname(), time(NULL), 
+                       init_unk_info2(&ctr->info.inf2, lp_serverstring(), lp_workgroup(), global_myname(), seq_num, 
                                       num_users, num_groups, num_aliases, nt_logout, server_role);
                        break;
                case 0x03:
-                       account_policy_get(AP_TIME_TO_LOGOUT, &account_policy_temp);
+                       pdb_get_account_policy(AP_TIME_TO_LOGOUT, &account_policy_temp);
                        u_logout = account_policy_temp;
 
                        unix_to_nt_time_abs(&nt_logout, u_logout);
@@ -4273,21 +4284,25 @@ NTSTATUS _samr_unknown_2e(pipes_struct *p, SAMR_Q_UNKNOWN_2E *q_u, SAMR_R_UNKNOW
                        server_role = ROLE_DOMAIN_PDC;
                        if (lp_server_role() == ROLE_DOMAIN_BDC)
                                server_role = ROLE_DOMAIN_BDC;
+
                        init_unk_info7(&ctr->info.inf7, server_role);
                        break;
                case 0x08:
-                       init_unk_info8(&ctr->info.inf8, (uint32) time(NULL));
+                       if (!pdb_get_seq_num(&seq_num))
+                               seq_num = time(NULL);
+
+                       init_unk_info8(&ctr->info.inf8, (uint32) seq_num);
                        break;
                case 0x0c:
-                       account_policy_get(AP_LOCK_ACCOUNT_DURATION, &account_policy_temp);
+                       pdb_get_account_policy(AP_LOCK_ACCOUNT_DURATION, &account_policy_temp);
                        u_lock_duration = account_policy_temp;
                        if (u_lock_duration != -1)
                                u_lock_duration *= 60;
 
-                       account_policy_get(AP_RESET_COUNT_TIME, &account_policy_temp);
+                       pdb_get_account_policy(AP_RESET_COUNT_TIME, &account_policy_temp);
                        u_reset_time = account_policy_temp * 60;
 
-                       account_policy_get(AP_BAD_ATTEMPT_LOCKOUT, &account_policy_temp);
+                       pdb_get_account_policy(AP_BAD_ATTEMPT_LOCKOUT, &account_policy_temp);
                        lockout = account_policy_temp;
        
                        unix_to_nt_time_abs(&nt_lock_duration, u_lock_duration);
@@ -4331,17 +4346,17 @@ NTSTATUS _samr_set_dom_info(pipes_struct *p, SAMR_Q_SET_DOMAIN_INFO *q_u, SAMR_R
                        u_expire=nt_time_to_unix_abs(&q_u->ctr->info.inf1.expire);
                        u_min_age=nt_time_to_unix_abs(&q_u->ctr->info.inf1.min_passwordage);
                        
-                       account_policy_set(AP_MIN_PASSWORD_LEN, (uint32)q_u->ctr->info.inf1.min_length_password);
-                       account_policy_set(AP_PASSWORD_HISTORY, (uint32)q_u->ctr->info.inf1.password_history);
-                       account_policy_set(AP_USER_MUST_LOGON_TO_CHG_PASS, (uint32)q_u->ctr->info.inf1.flag);
-                       account_policy_set(AP_MAX_PASSWORD_AGE, (int)u_expire);
-                       account_policy_set(AP_MIN_PASSWORD_AGE, (int)u_min_age);
+                       pdb_set_account_policy(AP_MIN_PASSWORD_LEN, (uint32)q_u->ctr->info.inf1.min_length_password);
+                       pdb_set_account_policy(AP_PASSWORD_HISTORY, (uint32)q_u->ctr->info.inf1.password_history);
+                       pdb_set_account_policy(AP_USER_MUST_LOGON_TO_CHG_PASS, (uint32)q_u->ctr->info.inf1.flag);
+                       pdb_set_account_policy(AP_MAX_PASSWORD_AGE, (int)u_expire);
+                       pdb_set_account_policy(AP_MIN_PASSWORD_AGE, (int)u_min_age);
                        break;
                case 0x02:
                        break;
                case 0x03:
                        u_logout=nt_time_to_unix_abs(&q_u->ctr->info.inf3.logout);
-                       account_policy_set(AP_TIME_TO_LOGOUT, (int)u_logout);
+                       pdb_set_account_policy(AP_TIME_TO_LOGOUT, (int)u_logout);
                        break;
                case 0x05:
                        break;
@@ -4356,9 +4371,9 @@ NTSTATUS _samr_set_dom_info(pipes_struct *p, SAMR_Q_SET_DOMAIN_INFO *q_u, SAMR_R
 
                        u_reset_time=nt_time_to_unix_abs(&q_u->ctr->info.inf12.reset_count)/60;
                        
-                       account_policy_set(AP_LOCK_ACCOUNT_DURATION, (int)u_lock_duration);
-                       account_policy_set(AP_RESET_COUNT_TIME, (int)u_reset_time);
-                       account_policy_set(AP_BAD_ATTEMPT_LOCKOUT, (uint32)q_u->ctr->info.inf12.bad_attempt_lockout);
+                       pdb_set_account_policy(AP_LOCK_ACCOUNT_DURATION, (int)u_lock_duration);
+                       pdb_set_account_policy(AP_RESET_COUNT_TIME, (int)u_reset_time);
+                       pdb_set_account_policy(AP_BAD_ATTEMPT_LOCKOUT, (uint32)q_u->ctr->info.inf12.bad_attempt_lockout);
                        break;
                default:
                        return NT_STATUS_INVALID_INFO_CLASS;
index 24869d5d2bd07a07665055fa66e3871ce059f379..1d9a8ecd1dbe63f35208ccbbd740bf95870baab7 100644 (file)
@@ -291,7 +291,7 @@ void copy_id21_to_sam_passwd(SAM_ACCOUNT *to, SAM_USER_INFO_21 *from)
                uint32 expire;
                time_t new_time;
                if (pdb_get_pass_must_change_time(to) == 0) {
-                       if (!account_policy_get(AP_MAX_PASSWORD_AGE, &expire)
+                       if (!pdb_get_account_policy(AP_MAX_PASSWORD_AGE, &expire)
                            || expire == (uint32)-1) {
                                new_time = get_time_t_max();
                        } else {
@@ -531,7 +531,7 @@ void copy_id23_to_sam_passwd(SAM_ACCOUNT *to, SAM_USER_INFO_23 *from)
                uint32 expire;
                time_t new_time;
                if (pdb_get_pass_must_change_time(to) == 0) {
-                       if (!account_policy_get(AP_MAX_PASSWORD_AGE, &expire)
+                       if (!pdb_get_account_policy(AP_MAX_PASSWORD_AGE, &expire)
                            || expire == (uint32)-1) {
                                new_time = get_time_t_max();
                        } else {
index cda3f26137ce23907cc766d6eb588e0f9675bd99..5233d6c252df040734f2a77bea58473b1bee2d53 100644 (file)
@@ -75,7 +75,7 @@ typedef struct _counter_printer_0 {
 
 static counter_printer_0 *counter_list;
 
-static struct cli_state notify_cli; /* print notify back-channel */
+static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
 static uint32 smb_connections=0;
 
 
@@ -166,7 +166,7 @@ static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle)
                return;
        }
 
-       result = cli_spoolss_reply_close_printer(&notify_cli, notify_cli.mem_ctx, handle);
+       result = rpccli_spoolss_reply_close_printer(notify_cli_pipe, notify_cli_pipe->cli->mem_ctx, handle);
        
        if (!W_ERROR_IS_OK(result))
                DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
@@ -174,9 +174,8 @@ static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle)
 
        /* if it's the last connection, deconnect the IPC$ share */
        if (smb_connections==1) {
-               cli_nt_session_close(&notify_cli);
-               cli_ulogoff(&notify_cli);
-               cli_shutdown(&notify_cli);
+               cli_shutdown(notify_cli_pipe->cli);
+               notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
                message_deregister(MSG_PRINTER_NOTIFY2);
 
                /* Tell the connections db we're no longer interested in
@@ -688,7 +687,7 @@ static void notify_system_time(struct spoolss_notify_msg *msg,
                return;
        }
 
-       if (!prs_init(&ps, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
+       if (!prs_init(&ps, RPC_MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
                DEBUG(5, ("notify_system_time: prs_init() failed\n"));
                return;
        }
@@ -1021,7 +1020,7 @@ static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
                }
 
                if ( sending_msg_count ) {
-                       cli_spoolss_rrpcn( &notify_cli, mem_ctx, &p->notify.client_hnd, 
+                       rpccli_spoolss_rrpcn( notify_cli_pipe, mem_ctx, &p->notify.client_hnd, 
                                        data_len, data, p->notify.change, 0 );
                }
        }
@@ -1075,7 +1074,8 @@ static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, voi
  Receive a notify2 message list
  ********************************************************************/
 
-static void receive_notify2_message_list(int msg_type, pid_t src, void *msg, size_t len)
+static void receive_notify2_message_list(int msg_type, struct process_id src,
+                                        void *msg, size_t len)
 {
        size_t                  msg_count, i;
        char                    *buf = (char *)msg;
@@ -1176,7 +1176,8 @@ static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
        DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
                drivername));
                
-       message_send_pid(sys_getpid(), MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
+       message_send_pid(pid_to_procid(sys_getpid()),
+                        MSG_PRINTER_DRVUPGRADE, drivername, len+1, False);
 
        return True;
 }
@@ -1186,7 +1187,7 @@ static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
  over all printers, upgrading ones as necessary 
  **********************************************************************/
  
-void do_drv_upgrade_printer(int msg_type, pid_t src, void *buf, size_t len)
+void do_drv_upgrade_printer(int msg_type, struct process_id src, void *buf, size_t len)
 {
        fstring drivername;
        int snum;
@@ -1272,7 +1273,8 @@ static BOOL srv_spoolss_reset_printerdata(char* drivername)
        DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
                drivername));
                
-       message_send_pid(sys_getpid(), MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
+       message_send_pid(pid_to_procid(sys_getpid()),
+                        MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False);
 
        return True;
 }
@@ -1282,7 +1284,8 @@ static BOOL srv_spoolss_reset_printerdata(char* drivername)
  over all printers, resetting printer data as neessary 
  **********************************************************************/
  
-void reset_all_printerdata(int msg_type, pid_t src, void *buf, size_t len)
+void reset_all_printerdata(int msg_type, struct process_id src,
+                          void *buf, size_t len)
 {
        fstring drivername;
        int snum;
@@ -2001,7 +2004,10 @@ WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER
                
                        /* this should not have failed---if it did, report to client */
                        if ( !W_ERROR_IS_OK(status_win2k) )
+                       {
+                               status = status_win2k;
                                goto done;
+                       }
                }
        }
        
@@ -2479,9 +2485,10 @@ done:
  Connect to the client machine.
 **********************************************************/
 
-static BOOL spoolss_connect_to_client(struct cli_state *the_cli, 
+static BOOL spoolss_connect_to_client(struct cli_state *the_cli, struct rpc_pipe_client **pp_pipe,
                        struct in_addr *client_ip, const char *remote_machine)
 {
+       NTSTATUS ret;
        ZERO_STRUCTP(the_cli);
        
        if(cli_initialise(the_cli) == NULL) {
@@ -2563,10 +2570,10 @@ static BOOL spoolss_connect_to_client(struct cli_state *the_cli,
         * Now start the NT Domain stuff :-).
         */
 
-       if(cli_nt_session_open(the_cli, PI_SPOOLSS) == False) {
-               DEBUG(0,("spoolss_connect_to_client: unable to open the domain client session to machine %s. Error was : %s.\n", remote_machine, cli_errstr(the_cli)));
-               cli_nt_session_close(the_cli);
-               cli_ulogoff(the_cli);
+       *pp_pipe = cli_rpc_pipe_open_noauth(the_cli, PI_SPOOLSS, &ret);
+       if(!*pp_pipe) {
+               DEBUG(0,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
+                       remote_machine, nt_errstr(ret)));
                cli_shutdown(the_cli);
                return False;
        } 
@@ -2589,13 +2596,14 @@ static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
         * and connect to the IPC$ share anonymously
         */
        if (smb_connections==0) {
+               struct cli_state notify_cli; /* print notify back-channel */
                fstring unix_printer;
 
                fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
 
                ZERO_STRUCT(notify_cli);
 
-               if(!spoolss_connect_to_client(&notify_cli, client_ip, unix_printer))
+               if(!spoolss_connect_to_client(&notify_cli, &notify_cli_pipe, client_ip, unix_printer))
                        return False;
                        
                message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
@@ -2614,7 +2622,7 @@ static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer,
 
        smb_connections++;
 
-       result = cli_spoolss_reply_open_printer(&notify_cli, notify_cli.mem_ctx, printer, localprinter, 
+       result = rpccli_spoolss_reply_open_printer(notify_cli_pipe, notify_cli_pipe->cli->mem_ctx, printer, localprinter, 
                        type, handle);
                        
        if (!W_ERROR_IS_OK(result))
@@ -6117,17 +6125,12 @@ static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
                        || !strequal(printer->info_2->portname, old_printer->info_2->portname)
                        || !strequal(printer->info_2->location, old_printer->info_2->location)) )
        {
+               /* add_printer_hook() will call reload_services() */
+
                if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) {
                        result = WERR_ACCESS_DENIED;
                        goto done;
                }
-
-               /* 
-                * make sure we actually reload the services after 
-                * this as smb.conf could have a new section in it 
-                * .... shouldn't .... but could
-                */
-               reload_services(False); 
        }
        
        /*
index e9dd015421ca974c1e44fff566be8f65c4b6d75e..9643b2a72498711c33ae7a868057c372e78eea70 100644 (file)
@@ -113,7 +113,8 @@ static void init_srv_share_info_2(pipes_struct *p, SRV_SHARE_INFO_2 *sh2, int sn
  What to do when smb.conf is updated.
  ********************************************************************/
 
-static void smb_conf_updated(int msg_type, pid_t src, void *buf, size_t len)
+static void smb_conf_updated(int msg_type, struct process_id src,
+                            void *buf, size_t len)
 {
        DEBUG(10,("smb_conf_updated: Got message saying smb.conf was updated. Reloading.\n"));
        reload_services(False);
@@ -1394,7 +1395,7 @@ WERROR _srv_net_sess_del(pipes_struct *p, SRV_Q_NET_SESS_DEL *q_u, SRV_R_NET_SES
                                become_root();
                        }
 
-                       if (message_send_pid(session_list[snum].pid, MSG_SHUTDOWN, NULL, 0, False))
+                       if (message_send_pid(pid_to_procid(session_list[snum].pid), MSG_SHUTDOWN, NULL, 0, False))
                                r_u->status = WERR_OK;
 
                        if (not_root) 
index 6ba26414d363a0cae3cab341e65a2cb9d828f6ad..31d8bbe9b3d91c497a529918134dadb5b5f512e5 100644 (file)
@@ -309,24 +309,76 @@ static BOOL api_svcctl_query_service_config2(pipes_struct *p)
        return True;
 }
 
+/*******************************************************************
+ ********************************************************************/
+
+static BOOL api_svcctl_lock_service_db(pipes_struct *p)
+{
+       SVCCTL_Q_LOCK_SERVICE_DB q_u;
+       SVCCTL_R_LOCK_SERVICE_DB r_u;
+       prs_struct *data = &p->in_data.data;
+       prs_struct *rdata = &p->out_data.rdata;
+
+       ZERO_STRUCT(q_u);
+       ZERO_STRUCT(r_u);
+
+       if(!svcctl_io_q_lock_service_db("", &q_u, data, 0))
+               return False;
+
+       r_u.status = _svcctl_lock_service_db(p, &q_u, &r_u);
+
+       if(!svcctl_io_r_lock_service_db("", &r_u, rdata, 0))
+               return False;
+
+       return True;
+}
+
+
+/*******************************************************************
+ ********************************************************************/
+
+static BOOL api_svcctl_unlock_service_db(pipes_struct *p)
+{
+       SVCCTL_Q_UNLOCK_SERVICE_DB q_u;
+       SVCCTL_R_UNLOCK_SERVICE_DB r_u;
+       prs_struct *data = &p->in_data.data;
+       prs_struct *rdata = &p->out_data.rdata;
+
+       ZERO_STRUCT(q_u);
+       ZERO_STRUCT(r_u);
+
+       if(!svcctl_io_q_unlock_service_db("", &q_u, data, 0))
+               return False;
+
+       r_u.status = _svcctl_unlock_service_db(p, &q_u, &r_u);
+
+       if(!svcctl_io_r_unlock_service_db("", &r_u, rdata, 0))
+               return False;
+
+       return True;
+}
+
+
 /*******************************************************************
  \PIPE\svcctl commands
  ********************************************************************/
 
 static struct api_struct api_svcctl_cmds[] =
 {
-      { "SVCCTL_CLOSE_SERVICE"         , SVCCTL_CLOSE_SERVICE         , api_svcctl_close_service },
-      { "SVCCTL_OPEN_SCMANAGER_W"      , SVCCTL_OPEN_SCMANAGER_W      , api_svcctl_open_scmanager },
-      { "SVCCTL_OPEN_SERVICE_W"        , SVCCTL_OPEN_SERVICE_W        , api_svcctl_open_service },
-      { "SVCCTL_GET_DISPLAY_NAME"      , SVCCTL_GET_DISPLAY_NAME      , api_svcctl_get_display_name },
-      { "SVCCTL_QUERY_STATUS"          , SVCCTL_QUERY_STATUS          , api_svcctl_query_status },
-      { "SVCCTL_QUERY_SERVICE_CONFIG_W", SVCCTL_QUERY_SERVICE_CONFIG_W, api_svcctl_query_service_config },
-      { "SVCCTL_QUERY_SERVICE_CONFIG2_W", SVCCTL_QUERY_SERVICE_CONFIG2_W, api_svcctl_query_service_config2 },
-      { "SVCCTL_ENUM_SERVICES_STATUS_W", SVCCTL_ENUM_SERVICES_STATUS_W, api_svcctl_enum_services_status },
-      { "SVCCTL_ENUM_DEPENDENT_SERVICES_W", SVCCTL_ENUM_DEPENDENT_SERVICES_W, api_svcctl_enum_dependent_services },
-      { "SVCCTL_START_SERVICE_W"       , SVCCTL_START_SERVICE_W       , api_svcctl_start_service },
-      { "SVCCTL_CONTROL_SERVICE"       , SVCCTL_CONTROL_SERVICE       , api_svcctl_control_service },
-      { "SVCCTL_QUERY_SERVICE_STATUSEX_W", SVCCTL_QUERY_SERVICE_STATUSEX_W, api_svcctl_query_service_status_ex }
+      { "SVCCTL_CLOSE_SERVICE"              , SVCCTL_CLOSE_SERVICE              , api_svcctl_close_service },
+      { "SVCCTL_OPEN_SCMANAGER_W"           , SVCCTL_OPEN_SCMANAGER_W           , api_svcctl_open_scmanager },
+      { "SVCCTL_OPEN_SERVICE_W"             , SVCCTL_OPEN_SERVICE_W             , api_svcctl_open_service },
+      { "SVCCTL_GET_DISPLAY_NAME"           , SVCCTL_GET_DISPLAY_NAME           , api_svcctl_get_display_name },
+      { "SVCCTL_QUERY_STATUS"               , SVCCTL_QUERY_STATUS               , api_svcctl_query_status },
+      { "SVCCTL_QUERY_SERVICE_CONFIG_W"     , SVCCTL_QUERY_SERVICE_CONFIG_W     , api_svcctl_query_service_config },
+      { "SVCCTL_QUERY_SERVICE_CONFIG2_W"    , SVCCTL_QUERY_SERVICE_CONFIG2_W    , api_svcctl_query_service_config2 },
+      { "SVCCTL_ENUM_SERVICES_STATUS_W"     , SVCCTL_ENUM_SERVICES_STATUS_W     , api_svcctl_enum_services_status },
+      { "SVCCTL_ENUM_DEPENDENT_SERVICES_W"  , SVCCTL_ENUM_DEPENDENT_SERVICES_W  , api_svcctl_enum_dependent_services },
+      { "SVCCTL_START_SERVICE_W"            , SVCCTL_START_SERVICE_W            , api_svcctl_start_service },
+      { "SVCCTL_CONTROL_SERVICE"            , SVCCTL_CONTROL_SERVICE            , api_svcctl_control_service },
+      { "SVCCTL_QUERY_SERVICE_STATUSEX_W"   , SVCCTL_QUERY_SERVICE_STATUSEX_W   , api_svcctl_query_service_status_ex },
+      { "SVCCTL_LOCK_SERVICE_DB"            , SVCCTL_LOCK_SERVICE_DB            , api_svcctl_lock_service_db },
+      { "SVCCTL_UNLOCK_SERVICE_DB"          , SVCCTL_UNLOCK_SERVICE_DB          , api_svcctl_unlock_service_db }
 };
 
 
index 538b97a2b17f2e2c131eb9ec82a8da674e775648..e8df2acb22fec61ea99995e048343afcd4c875c5 100644 (file)
@@ -1,8 +1,11 @@
 /* 
  *  Unix SMB/CIFS implementation.
  *  RPC Pipe client / server routines
- *  Copyright (C) Gerald (Jerry) Carter             2005,
+ *
  *  Copyright (C) Marcin Krzysztof Porwit           2005.
+ * 
+ *  Largely Rewritten (Again) by:
+ *  Copyright (C) Gerald (Jerry) Carter             2005.
  *  
  *  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
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-/* TODO - Do the OpenService service name matching case-independently, or at least make it an option. */
-
-
 #include "includes.h"
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_RPC_SRV
 
-#define SERVICEDB_VERSION_V1 1 /* Will there be more? */
-#define INTERNAL_SERVICES_LIST "NETLOGON Spooler"
-
-/*                                                                                                                     */
-/* scripts will execute from the following libdir, if they are in the enable svcctl=<list of scripts>                  */
-/* these should likely be symbolic links. Note that information about them will be extracted from the files themselves */
-/* using the LSB standard keynames for various information                                                             */
-
-#define SVCCTL_SCRIPT_DIR  "/svcctl/"
-
-
-struct service_control_op_table {
+struct service_control_op {
        const char *name;
        SERVICE_CONTROL_OPS *ops;
 };
 
 extern SERVICE_CONTROL_OPS spoolss_svc_ops;
+extern SERVICE_CONTROL_OPS rcinit_svc_ops;
+extern SERVICE_CONTROL_OPS netlogon_svc_ops;
+extern SERVICE_CONTROL_OPS winreg_svc_ops;
 
-struct service_control_op_table svcctl_ops[] = { 
-       { "Spooler",    &spoolss_svc_ops },
-       { "NETLOGON",   NULL },
-       { NULL,         NULL }
-};
+struct service_control_op *svcctl_ops;
+
+static struct generic_mapping scm_generic_map =
+       { SC_MANAGER_READ_ACCESS, SC_MANAGER_WRITE_ACCESS, SC_MANAGER_EXECUTE_ACCESS, SC_MANAGER_ALL_ACCESS };
+static struct generic_mapping svc_generic_map =
+       { SERVICE_READ_ACCESS, SERVICE_WRITE_ACCESS, SERVICE_EXECUTE_ACCESS, SERVICE_ALL_ACCESS };
 
 
 /********************************************************************
 ********************************************************************/
 
+BOOL init_service_op_table( void )
+{
+       const char **service_list = lp_svcctl_list();
+       int num_services = 3 + str_list_count( service_list );
+       int i;
+       
+       if ( !(svcctl_ops = TALLOC_ARRAY( NULL, struct service_control_op, num_services+1)) ) {
+               DEBUG(0,("init_service_op_table: talloc() failed!\n"));
+               return False;
+       }
+
+       /* services listed in smb.conf get the rc.init interface */
+       
+       for ( i=0; service_list[i]; i++ ) {
+               svcctl_ops[i].name = talloc_strdup( svcctl_ops, service_list[i] );
+               svcctl_ops[i].ops  = &rcinit_svc_ops;
+       }
+       
+       /* add builtin services */
+       
+       svcctl_ops[i].name = talloc_strdup( svcctl_ops, "Spooler" );
+       svcctl_ops[i].ops  = &spoolss_svc_ops;
+       i++;
+       
+       svcctl_ops[i].name = talloc_strdup( svcctl_ops, "NETLOGON" );
+       svcctl_ops[i].ops  = &netlogon_svc_ops;
+       i++;
+       
+       svcctl_ops[i].name = talloc_strdup( svcctl_ops, "RemoteRegistry" );
+       svcctl_ops[i].ops  = &winreg_svc_ops;
+       i++;
+       
+       /* NULL terminate the array */
+       
+       svcctl_ops[i].name = NULL;
+       svcctl_ops[i].ops  = NULL;
+       
+       return True;
+}
+
+/********************************************************************
+********************************************************************/
+
+static struct service_control_op* find_service_by_name( const char *name )
+{
+       int i;
+
+       for ( i=0; svcctl_ops[i].name; i++ ) {
+               if ( strequal( name, svcctl_ops[i].name ) )
+                       return &svcctl_ops[i];
+       }
+
+       return NULL;
+}
+/********************************************************************
+********************************************************************/
+
 static NTSTATUS svcctl_access_check( SEC_DESC *sec_desc, NT_USER_TOKEN *token, 
                                      uint32 access_desired, uint32 *access_granted )
 {
        NTSTATUS result;
 
        if ( geteuid() == sec_initial_uid() ) {
-               DEBUG(5,("svcctl_access_check: access check bypassed for 'root'\n"));
-               *access_granted = access_desired;
-               return NT_STATUS_OK;
+               DEBUG(5,("svcctl_access_check: using root's token\n"));
+               token = get_root_nt_token();
        }
        
        se_access_check( sec_desc, token, access_desired, access_granted, &result );
@@ -81,7 +130,7 @@ static SEC_DESC* construct_scm_sd( TALLOC_CTX *ctx )
        size_t i = 0;
        SEC_DESC *sd;
        SEC_ACL *acl;
-       uint32 sd_size;
+       size_t sd_size;
 
        /* basic access for Everyone */
        
@@ -105,51 +154,13 @@ static SEC_DESC* construct_scm_sd( TALLOC_CTX *ctx )
        return sd;
 }
 
-/********************************************************************
-********************************************************************/
-
-static SEC_DESC* construct_service_sd( TALLOC_CTX *ctx )
-{
-       SEC_ACE ace[4]; 
-       SEC_ACCESS mask;
-       size_t i = 0;
-       SEC_DESC *sd;
-       SEC_ACL *acl;
-       uint32 sd_size;
-
-       /* basic access for Everyone */
-       
-       init_sec_access(&mask, SERVICE_READ_ACCESS );
-       init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
-               
-       init_sec_access(&mask,SERVICE_EXECUTE_ACCESS );
-       init_sec_ace(&ace[i++], &global_sid_Builtin_Power_Users, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
-       
-       init_sec_access(&mask,SERVICE_ALL_ACCESS );
-       init_sec_ace(&ace[i++], &global_sid_Builtin_Server_Operators, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
-       init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
-       
-       /* create the security descriptor */
-       
-       if ( !(acl = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) )
-               return NULL;
-
-       if ( !(sd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL, acl, &sd_size)) )
-               return NULL;
-
-       return sd;
-}
-
 /******************************************************************
  free() function for REGISTRY_KEY
  *****************************************************************/
  
 static void free_service_handle_info(void *ptr)
 {
-       SERVICE_INFO *info = (SERVICE_INFO*)ptr;
-       
-       SAFE_FREE(info->name);
-       SAFE_FREE(info);
+       TALLOC_FREE( ptr );
 }
 
 /******************************************************************
@@ -171,44 +182,50 @@ static SERVICE_INFO *find_service_info_by_hnd(pipes_struct *p, POLICY_HND *hnd)
 /******************************************************************
  *****************************************************************/
  
-static WERROR create_open_service_handle( pipes_struct *p, POLICY_HND *handle, 
+static WERROR create_open_service_handle( pipes_struct *p, POLICY_HND *handle, uint32 type,
                                           const char *service, uint32 access_granted )
 {
        SERVICE_INFO *info = NULL;
        WERROR result = WERR_OK;
+       struct service_control_op *s_op;
        
-       if ( !(info = SMB_MALLOC_P( SERVICE_INFO )) )
+       if ( !(info = TALLOC_ZERO_P( NULL, SERVICE_INFO )) )
                return WERR_NOMEM;
 
-       ZERO_STRUCTP( info );
-               
        /* the Service Manager has a NULL name */
        
-       if ( !service ) {
+       info->type = SVC_HANDLE_IS_SCM;
+       
+       switch ( type ) {
+       case SVC_HANDLE_IS_SCM:
                info->type = SVC_HANDLE_IS_SCM;
-       } else {
-               int i;
+               break;
 
+       case SVC_HANDLE_IS_DBLOCK:
+               info->type = SVC_HANDLE_IS_DBLOCK;
+               break;
+               
+       case SVC_HANDLE_IS_SERVICE:
                info->type = SVC_HANDLE_IS_SERVICE;
                
                /* lookup the SERVICE_CONTROL_OPS */
 
-               for ( i=0; svcctl_ops[i].name; i++ ) {
-                       if ( strequal( svcctl_ops[i].name, service ) )  {
-                               info->ops = svcctl_ops[i].ops;
-                               break;
-                       }
-               }
-
-               if ( !svcctl_ops[i].name ) {
+               if ( !(s_op = find_service_by_name( service )) ) {
                        result = WERR_NO_SUCH_SERVICE;
                        goto done;
                }
+               
+               info->ops = s_op->ops;
 
-               if ( !(info->name  = SMB_STRDUP( service )) ) {
+               if ( !(info->name  = talloc_strdup( info, s_op->name )) ) {
                        result = WERR_NOMEM;
                        goto done;
                }
+               break;
+
+       default:
+               result = WERR_NO_SUCH_SERVICE;
+               goto done;
        }
 
        info->access_granted = access_granted;  
@@ -241,11 +258,12 @@ WERROR _svcctl_open_scmanager(pipes_struct *p, SVCCTL_Q_OPEN_SCMANAGER *q_u, SVC
        if ( !(sec_desc = construct_scm_sd( p->mem_ctx )) )
                return WERR_NOMEM;
                
+       se_map_generic( &q_u->access, &scm_generic_map );
        status = svcctl_access_check( sec_desc, p->pipe_user.nt_user_token, q_u->access, &access_granted );
        if ( !NT_STATUS_IS_OK(status) )
                return ntstatus_to_werror( status );
                
-       return create_open_service_handle( p, &r_u->handle, NULL, access_granted );
+       return create_open_service_handle( p, &r_u->handle, SVC_HANDLE_IS_SCM, NULL, access_granted );
 }
 
 /********************************************************************
@@ -268,21 +286,18 @@ WERROR _svcctl_open_service(pipes_struct *p, SVCCTL_Q_OPEN_SERVICE *q_u, SVCCTL_
        if ( !find_service_info_by_hnd( p, &q_u->handle ) )
                return WERR_BADFID;
                        
-       /* perform access checks */
+       /* perform access checks.  Use the root token in order to ensure that we 
+          retreive the security descriptor */
        
-       if ( !(sec_desc = construct_service_sd( p->mem_ctx )) )
+       if ( !(sec_desc = svcctl_get_secdesc( p->mem_ctx, service, get_root_nt_token() )) )
                return WERR_NOMEM;
                
+       se_map_generic( &q_u->access, &svc_generic_map );
        status = svcctl_access_check( sec_desc, p->pipe_user.nt_user_token, q_u->access, &access_granted );
        if ( !NT_STATUS_IS_OK(status) )
                return ntstatus_to_werror( status );
-               
-#if 0  /* FIXME!!! */
-       if ( ! get_service_info(service_tdb, service, info) ) {
-               return WERR_NO_SUCH_SERVICE;
-#endif
        
-       return create_open_service_handle( p, &r_u->handle, service, access_granted );
+       return create_open_service_handle( p, &r_u->handle, SVC_HANDLE_IS_SERVICE, service, access_granted );
 }
 
 /********************************************************************
@@ -299,7 +314,7 @@ WERROR _svcctl_close_service(pipes_struct *p, SVCCTL_Q_CLOSE_SERVICE *q_u, SVCCT
 WERROR _svcctl_get_display_name(pipes_struct *p, SVCCTL_Q_GET_DISPLAY_NAME *q_u, SVCCTL_R_GET_DISPLAY_NAME *r_u)
 {
        fstring service;
-       fstring displayname;
+       const char *display_name;
        SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle );
        
        /* can only use an SCM handle here */
@@ -308,12 +323,9 @@ WERROR _svcctl_get_display_name(pipes_struct *p, SVCCTL_Q_GET_DISPLAY_NAME *q_u,
                return WERR_BADFID;
                
        rpcstr_pull(service, q_u->servicename.buffer, sizeof(service), q_u->servicename.uni_str_len*2, 0);
-
-       /* need a tdb lookup here or something */
        
-       fstrcpy( displayname, "FIX ME!" );
-
-       init_svcctl_r_get_display_name( r_u, displayname );
+       display_name = svcctl_lookup_dispname( service, p->pipe_user.nt_user_token );
+       init_svcctl_r_get_display_name( r_u, display_name );
 
        return WERR_OK;
 }
@@ -335,87 +347,40 @@ WERROR _svcctl_query_status(pipes_struct *p, SVCCTL_Q_QUERY_STATUS *q_u, SVCCTL_
                
        /* try the service specific status call */
 
-       if ( info->ops ) 
-               return info->ops->service_status( &r_u->svc_status );
-
-       /* default action for now */
-
-       r_u->svc_status.type = 0x0020;
-       r_u->svc_status.state = 0x0004;
-       r_u->svc_status.controls_accepted = 0x0005;
-
-       return WERR_OK;
+       return info->ops->service_status( info->name, &r_u->svc_status );
 }
 
+/********************************************************************
+********************************************************************/
 
-/*********************************************************************
- TODO - for internal services, do similar to external services, except 
- we have to call the right status routine...
-**********************************************************************/
-
-static WERROR enum_internal_services(TALLOC_CTX *ctx,ENUM_SERVICES_STATUS **svc_ptr, int existing_services, uint32 *added) 
+static int enumerate_status( TALLOC_CTX *ctx, ENUM_SERVICES_STATUS **status, NT_USER_TOKEN *token )
 {
-       int num_services = 2;
-       int i = 0;
-       ENUM_SERVICES_STATUS *services=NULL;
-
-       if (!svc_ptr || !(*svc_ptr)) 
-               return WERR_NOMEM;
-
-       services = *svc_ptr;
-
-       if ( (existing_services > 0) && svc_ptr && *svc_ptr ) {
-               ENUM_SERVICES_STATUS *tmp_services = NULL;              
-               uint32 total_svc = existing_services + num_services;
-               
-               if ( !(tmp_services = TALLOC_REALLOC_ARRAY( ctx, services, ENUM_SERVICES_STATUS, total_svc )) )
-                       return WERR_NOMEM;
-                       
-               services = tmp_services;
-               i += existing_services;
-       } 
-       else {
-               if ( !(services = TALLOC_ARRAY( ctx, ENUM_SERVICES_STATUS, num_services )) )
-                       return WERR_NOMEM;
+       int num_services = 0;
+       int i;
+       ENUM_SERVICES_STATUS *st;
+       const char *display_name;
+       
+       /* just count */
+       while ( svcctl_ops[num_services].name )
+               num_services++;
+
+       if ( !(st = TALLOC_ARRAY( ctx, ENUM_SERVICES_STATUS, num_services )) ) {
+               DEBUG(0,("enumerate_status: talloc() failed!\n"));
+               return -1;
        }
-
-       DEBUG(8,("enum_internal_services: Creating %d services, starting index %d\n", 
-               num_services, existing_services));
-                               
-       init_unistr( &services[i].servicename, "Spooler" );
-       init_unistr( &services[i].displayname, "Print Spooler" );
-       
-       services[i].status.type               = 0x110;
-       services[i].status.controls_accepted  = 0x0;
-       services[i].status.win32_exit_code    = 0x0;
-       services[i].status.service_exit_code  = 0x0;
-       services[i].status.check_point        = 0x0;
-       services[i].status.wait_hint          = 0x0;
-       if ( !lp_disable_spoolss() ) 
-               services[i].status.state              = SVCCTL_RUNNING;
-       else
-               services[i].status.state              = SVCCTL_STOPPED;
-
-       i++;            
        
-       init_unistr( &services[i].servicename, "NETLOGON" );
-       init_unistr( &services[i].displayname, "Net Logon" );
+       for ( i=0; i<num_services; i++ ) {
+               init_unistr( &st[i].servicename, svcctl_ops[i].name );
+               
+               display_name = svcctl_lookup_dispname( svcctl_ops[i].name, token );
+               init_unistr( &st[i].displayname, display_name );
+               
+               svcctl_ops[i].ops->service_status( svcctl_ops[i].name, &st[i].status );
+       }
        
-       services[i].status.type               = 0x20;   
-       services[i].status.controls_accepted  = 0x0;
-       services[i].status.win32_exit_code    = 0x0;
-       services[i].status.service_exit_code  = 0x0;
-       services[i].status.check_point        = 0x0;
-       services[i].status.wait_hint          = 0x0;
-       if ( lp_servicenumber("NETLOGON") != -1 ) 
-               services[i].status.state              = SVCCTL_RUNNING;
-       else
-               services[i].status.state              = SVCCTL_STOPPED;
-
-       *added   = num_services;
-       *svc_ptr = services;
+       *status = st;
 
-       return WERR_OK;
+       return num_services;
 }
 
 /********************************************************************
@@ -424,11 +389,12 @@ static WERROR enum_internal_services(TALLOC_CTX *ctx,ENUM_SERVICES_STATUS **svc_
 WERROR _svcctl_enum_services_status(pipes_struct *p, SVCCTL_Q_ENUM_SERVICES_STATUS *q_u, SVCCTL_R_ENUM_SERVICES_STATUS *r_u)
 {
        ENUM_SERVICES_STATUS *services = NULL;
-       uint32 num_int_services, num_ext_services, total_services;
+       uint32 num_services;
        int i = 0;
        size_t buffer_size = 0;
        WERROR result = WERR_OK;
        SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle );
+       NT_USER_TOKEN *token = p->pipe_user.nt_user_token;
        
        /* perform access checks */
 
@@ -438,50 +404,29 @@ WERROR _svcctl_enum_services_status(pipes_struct *p, SVCCTL_Q_ENUM_SERVICES_STAT
        if ( !(info->access_granted & SC_RIGHT_MGR_ENUMERATE_SERVICE) )
                return WERR_ACCESS_DENIED;
 
-       num_int_services = 0;
-       num_ext_services = 0;
-
-       /* num_services = str_list_count( lp_enable_svcctl() ); */
-
-       /* here's where we'll read the db of external services */
-       /* _svcctl_read_LSB_data(NULL,NULL); */
-       /* init_svcctl_db(); */
-       
-       if ( !(services = TALLOC_ARRAY(p->mem_ctx, ENUM_SERVICES_STATUS, num_int_services+num_ext_services )) )
+       if ( (num_services = enumerate_status( p->mem_ctx, &services, token )) == -1 )
                return WERR_NOMEM;
 
-       if ( W_ERROR_IS_OK(enum_internal_services(p->mem_ctx, &services, 0, &num_int_services)) )
-               DEBUG(8,("_svcctl_enum_services_status: Got %d internal services\n", num_int_services));
-
-#if 0  
-       if ( W_ERROR_IS_OK(enum_external_services(p->mem_ctx, &services, num_int_services, &num_ext_services)) )
-               DEBUG(8,("_svcctl_enum_services_status: Got %d external services\n", num_ext_services));
-#endif
-
-       total_services = num_int_services + num_ext_services; 
-
-        DEBUG(8,("_svcctl_enum_services_status: total of %d services\n", total_services ));
-
-        for ( i=0; i<total_services; i++ ) {
+        for ( i=0; i<num_services; i++ ) {
                buffer_size += svcctl_sizeof_enum_services_status(&services[i]);
        }
 
        buffer_size += buffer_size % 4;
 
        if (buffer_size > q_u->buffer_size ) {
-               total_services = 0;
+               num_services = 0;
                result = WERR_MORE_DATA;
        }
 
        rpcbuf_init(&r_u->buffer, q_u->buffer_size, p->mem_ctx);
 
        if ( W_ERROR_IS_OK(result) ) {
-               for ( i=0; i<num_int_services+num_ext_services; i++ )
+               for ( i=0; i<num_services; i++ )
                        svcctl_io_enum_services_status( "", &services[i], &r_u->buffer, 0 );
        }
 
        r_u->needed      = (buffer_size > q_u->buffer_size) ? buffer_size : q_u->buffer_size;
-       r_u->returned    = total_services;
+       r_u->returned    = num_services;
 
        if ( !(r_u->resume = TALLOC_P( p->mem_ctx, uint32 )) )
                return WERR_NOMEM;
@@ -506,7 +451,7 @@ WERROR _svcctl_start_service(pipes_struct *p, SVCCTL_Q_START_SERVICE *q_u, SVCCT
        if ( !(info->access_granted & SC_RIGHT_SVC_START) )
                return WERR_ACCESS_DENIED;
                
-       return info->ops->start_service();
+       return info->ops->start_service( info->name );
 }
 
 /********************************************************************
@@ -517,18 +462,27 @@ WERROR _svcctl_control_service(pipes_struct *p, SVCCTL_Q_CONTROL_SERVICE *q_u, S
        SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle );
        
        /* perform access checks */
-       /* we only support stop so don't get complicated */
-
+       
        if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) )
                return WERR_BADFID;     
        
-       if ( q_u->control != SVCCTL_CONTROL_STOP )
-               return WERR_ACCESS_DENIED;
-               
-       if ( !(info->access_granted & SC_RIGHT_SVC_STOP) )
-               return WERR_ACCESS_DENIED;
+       switch ( q_u->control ) {
+       case SVCCTL_CONTROL_STOP:
+               if ( !(info->access_granted & SC_RIGHT_SVC_STOP) )
+                       return WERR_ACCESS_DENIED;
+                       
+               return info->ops->stop_service( info->name, &r_u->svc_status );
                
-       return info->ops->stop_service( &r_u->svc_status );
+       case SVCCTL_CONTROL_INTERROGATE:
+               if ( !(info->access_granted & SC_RIGHT_SVC_QUERY_STATUS) )
+                       return WERR_ACCESS_DENIED;
+                       
+               return info->ops->service_status( info->name, &r_u->svc_status );
+       }
+       
+       /* default control action */
+       
+       return WERR_ACCESS_DENIED;
 }
 
 /********************************************************************
@@ -564,11 +518,8 @@ WERROR _svcctl_enum_dependent_services( pipes_struct *p, SVCCTL_Q_ENUM_DEPENDENT
 
 WERROR _svcctl_query_service_status_ex( pipes_struct *p, SVCCTL_Q_QUERY_SERVICE_STATUSEX *q_u, SVCCTL_R_QUERY_SERVICE_STATUSEX *r_u )
 {
-        SERVICE_STATUS_PROCESS ssp;
-       POLICY_HND *handle;
-       SERVICE_INFO *service_info;
-       pstring     command;
        SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle );
+       uint32 buffer_size;
        
        /* perform access checks */
 
@@ -579,68 +530,80 @@ WERROR _svcctl_query_service_status_ex( pipes_struct *p, SVCCTL_Q_QUERY_SERVICE_
                return WERR_ACCESS_DENIED;
 
        /* we have to set the outgoing buffer size to the same as the 
-          incoming buffer size (even in the case of failure */
-
-       r_u->needed      = q_u->buffer_size;
-
-        /* need to find the service name by the handle that is open */
-       handle = &(q_u->handle);
+          incoming buffer size (even in the case of failure) */
 
+       rpcbuf_init( &r_u->buffer, q_u->buffer_size, p->mem_ctx );
+       r_u->needed = q_u->buffer_size;
+       
+       switch ( q_u->level ) {
+               case SVC_STATUS_PROCESS_INFO:
+               {
+                       SERVICE_STATUS_PROCESS svc_stat_proc;
 
-       /* get rid of the easy errors */
+                       /* Get the status of the service.. */
+                       info->ops->service_status( info->name, &svc_stat_proc.status );
+                       svc_stat_proc.process_id     = sys_getpid();
+                       svc_stat_proc.service_flags  = 0x0;
 
-       if (q_u->info_level != SVC_STATUS_PROCESS_INFO) {
-               DEBUG(10, ("_svcctl_query_service_status_ex :  Invalid information level specified\n"));
-               return WERR_UNKNOWN_LEVEL; 
+                       svcctl_io_service_status_process( "", &svc_stat_proc, &r_u->buffer, 0 );
+                       buffer_size = sizeof(SERVICE_STATUS_PROCESS);
+                       break;
+               }
+                       
+               default:
+                       return WERR_UNKNOWN_LEVEL; 
        }
 
-       service_info = find_service_info_by_hnd(p, handle);
-
-       if (!service_info) {
-               DEBUG(10, ("_svcctl_query_service_status_ex : Can't find the service for the handle\n"));
-               return WERR_BADFID; 
-       }
        
-       if (r_u->needed < (sizeof(SERVICE_STATUS_PROCESS)+sizeof(uint32)+sizeof(uint32))) {
-               DEBUG(10, ("_svcctl_query_service_status_ex : buffer size of [%d] is too small.\n",r_u->needed));
-               return WERR_INSUFFICIENT_BUFFER;
-       }
-
-       ZERO_STRUCT(ssp); 
-           
-#if 0
-        if (!strwicmp(service_info->servicetype,"EXTERNAL")) 
-               ssp.type = SVCCTL_WIN32_OWN_PROC;
-       else 
-               ssp.type = SVCCTL_WIN32_SHARED_PROC;
-#endif
+        buffer_size += buffer_size % 4;
+       r_u->needed = (buffer_size > q_u->buffer_size) ? buffer_size : q_u->buffer_size;
 
-       /* Get the status of the service.. */
+        if (buffer_size > q_u->buffer_size ) 
+                return WERR_MORE_DATA;
+       
+       return WERR_OK;
+}
 
-        memset(command, 0, sizeof(command));
+/********************************************************************
+********************************************************************/
 
-#if 0
-       slprintf(command, sizeof(command)-1, "%s%s%s %s", dyn_LIBDIR, SVCCTL_SCRIPT_DIR, service_info->filename, "status");
+static WERROR fill_svc_config( TALLOC_CTX *ctx, const char *name, SERVICE_CONFIG *config, NT_USER_TOKEN *token )
+{
+       REGVAL_CTR *values;
+       REGISTRY_VALUE *val;
 
-        DEBUG(10, ("_svcctl_query_service_status_ex: status command is [%s]\n", command));
+       /* retrieve the registry values for this service */
+       
+       if ( !(values = svcctl_fetch_regvalues( name, token )) )
+               return WERR_REG_CORRUPT;
+       
+       /* now fill in the individual values */
+               
+       config->displayname = TALLOC_ZERO_P( ctx, UNISTR2 );
+       if ( (val = regval_ctr_getvalue( values, "DisplayName" )) != NULL )
+               init_unistr2( config->displayname, regval_sz( val ), UNI_STR_TERMINATE );
+       else
+               init_unistr2( config->displayname, name, UNI_STR_TERMINATE );
 
-       /* TODO  - wrap in privilege check */
+       if ( (val = regval_ctr_getvalue( values, "ObjectName" )) != NULL ) {
+               config->startname = TALLOC_ZERO_P( ctx, UNISTR2 );              
+               init_unistr2( config->startname, regval_sz( val ), UNI_STR_TERMINATE );
+       }
+               
+       if ( (val = regval_ctr_getvalue( values, "ImagePath" )) != NULL ) {
+               config->executablepath = TALLOC_ZERO_P( ctx, UNISTR2 );         
+               init_unistr2( config->executablepath, regval_sz( val ), UNI_STR_TERMINATE );
+       }
 
-       ret = smbrun(command, &fd);
-       DEBUGADD(10, ("returned [%d]\n", ret));
-        close(fd);
-       if(ret != 0)
-               DEBUG(10, ("_svcctl_query_service_status_ex: Command returned  [%d]\n", ret));
+       /* a few hard coded values */
+       /* loadordergroup and dependencies are empty */
+       
+       config->tag_id           = 0x00000000;                  /* unassigned loadorder group */
+       config->service_type     = SVCCTL_WIN32_OWN_PROC;
+       config->start_type       = SVCCTL_DEMAND_START;
+       config->error_control    = SVCCTL_SVC_ERROR_NORMAL;
 
-       /* SET all service_stats bits here... */
-       if (ret == 0) {
-               ssp.state              = SVCCTL_RUNNING;
-               ssp.controls_accepted  = SVCCTL_CONTROL_SHUTDOWN | SVCCTL_CONTROL_STOP;
-       } else {
-               ssp.state              = SVCCTL_STOPPED;
-               ssp.controls_accepted  = 0;
-       }
-#endif
+       TALLOC_FREE( values );
 
        return WERR_OK;
 }
@@ -650,10 +613,9 @@ WERROR _svcctl_query_service_status_ex( pipes_struct *p, SVCCTL_Q_QUERY_SERVICE_
 
 WERROR _svcctl_query_service_config( pipes_struct *p, SVCCTL_Q_QUERY_SERVICE_CONFIG *q_u, SVCCTL_R_QUERY_SERVICE_CONFIG *r_u )
 {
-       POLICY_HND *handle;
-       SERVICE_INFO *service_info;
-        uint32      needed_size;
        SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle );
+       uint32 buffer_size;
+       WERROR wresult;
        
        /* perform access checks */
 
@@ -667,89 +629,19 @@ WERROR _svcctl_query_service_config( pipes_struct *p, SVCCTL_Q_QUERY_SERVICE_CON
           incoming buffer size (even in the case of failure */
 
        r_u->needed      = q_u->buffer_size;
+       
+       wresult = fill_svc_config( p->mem_ctx, info->name, &r_u->config, p->pipe_user.nt_user_token );
+       if ( !W_ERROR_IS_OK(wresult) )
+               return wresult;
+       
+       buffer_size = svcctl_sizeof_service_config( &r_u->config );
+       r_u->needed = (buffer_size > q_u->buffer_size) ? buffer_size : q_u->buffer_size;
 
-        /* need to find the service name by the handle that is open */
-       handle = &(q_u->handle);
-
-       service_info = find_service_info_by_hnd(p, handle);
-
-#if 0
-       if (q_u->buffer_size < sizeof(Service_info)) {
-               /* have to report need more... */
-               /* TODO worst case -- should actualy calc what we need here. */
-               r_u->needed = sizeof(Service_info)+sizeof(pstring)*5; 
-               DEBUG(10, ("_svcctl_query_service_config: NOT ENOUGH BUFFER ALLOCATED FOR RETURN DATA -- provided %d wanted %d\n",
-               q_u->buffer_size,r_u->needed));
-
-               return WERR_INSUFFICIENT_BUFFER;
-       }
-#endif
-       if (!service_info) {
-               DEBUG(10, ("_svcctl_query_service_config : Can't find the service for the handle\n"));
-               return WERR_BADFID; 
-       }
-
-#if 0
-       if ( !(service_config = (SERVICE_CONFIG *)TALLOC_ZERO_P(p->mem_ctx, SERVICE_CONFIG)) )
-               return WERR_NOMEM;
-#endif
-
-       r_u->config.service_type       = SVCCTL_WIN32_OWN_PROC;
-       r_u->config.start_type         = SVCCTL_DEMAND_START;
-       r_u->config.error_control      = SVCCTL_SVC_ERROR_IGNORE;
-       r_u->config.tag_id = 0x00000000;
-
-       /* Init the strings */
-
-       r_u->config.executablepath = TALLOC_ZERO_P(p->mem_ctx,  UNISTR2);
-       r_u->config.loadordergroup = TALLOC_ZERO_P(p->mem_ctx,  UNISTR2);
-       r_u->config.dependencies = TALLOC_ZERO_P(p->mem_ctx,  UNISTR2);
-       r_u->config.startname = TALLOC_ZERO_P(p->mem_ctx,  UNISTR2);
-       r_u->config.displayname = TALLOC_ZERO_P(p->mem_ctx,  UNISTR2);
-
-#if 0
-       pstrcpy(fullpathinfo,dyn_LIBDIR);
-       pstrcat(fullpathinfo,SVCCTL_SCRIPT_DIR);
-       pstrcat(fullpathinfo,service_info->filename);
-       /* Get and calculate the size of the fields. Note that we're still building the fields in the "too-small buffer case"
-          even though we throw it away. */
-       
-       DEBUG(10, ("_svcctl_query_service_config: fullpath info [%s]\n",fullpathinfo));
-       init_unistr2(r_u->config.executablepath,fullpathinfo,UNI_STR_TERMINATE);
-       init_unistr2(r_u->config.loadordergroup,"",UNI_STR_TERMINATE);
-       init_unistr2(r_u->config.dependencies,service_info->dependencies,UNI_STR_TERMINATE);
-
-       /* TODO - if someone really cares, perhaps "LocalSystem" should be changed to something else here... */
-
-       init_unistr2(r_u->config.startname,"LocalSystem",UNI_STR_TERMINATE);
-       init_unistr2(r_u->config.displayname,service_info->servicename,UNI_STR_TERMINATE);
-#endif
-
-       needed_size = 0x04 + sizeof(SERVICE_CONFIG)+ 2*(
-                     r_u->config.executablepath->uni_str_len +
-                     r_u->config.loadordergroup->uni_str_len + 
-                     r_u->config.dependencies->uni_str_len + 
-                      r_u->config.startname->uni_str_len + 
-                      r_u->config.displayname->uni_str_len);
-       
-               DEBUG(10, ("_svcctl_query_service_config: ****** need to have a buffer of [%d], [%d] for struct \n",needed_size,
-                  sizeof(SERVICE_CONFIG)));
-       DEBUG(10, ("\tsize of executable path : %d\n",r_u->config.executablepath->uni_str_len));
-       DEBUG(10, ("\tsize of loadordergroup  : %d\n", r_u->config.loadordergroup->uni_str_len)); 
-       DEBUG(10, ("\tsize of dependencies    : %d\n", r_u->config.dependencies->uni_str_len)); 
-       DEBUG(10, ("\tsize of startname       : %d\n", r_u->config.startname->uni_str_len));
-       DEBUG(10, ("\tsize of displayname     : %d\n", r_u->config.displayname->uni_str_len));
-
-       if (q_u->buffer_size < needed_size) {
-               /* have to report need more...*/
-               r_u->needed = needed_size;
-                       DEBUG(10, ("_svcctl_query_service_config: ****** zeroing strings for return\n"));
-               memset(&r_u->config,0,sizeof(SERVICE_CONFIG));
-               DEBUG(10, ("_svcctl_query_service_config: Not enouh buffer provided for return -- provided %d wanted %d\n",
-                       q_u->buffer_size,needed_size));
-               return WERR_INSUFFICIENT_BUFFER;
+        if (buffer_size > q_u->buffer_size ) {
+               ZERO_STRUCTP( &r_u->config );
+                return WERR_INSUFFICIENT_BUFFER;
        }
-
+               
        return WERR_OK;
 }
 
@@ -758,9 +650,8 @@ WERROR _svcctl_query_service_config( pipes_struct *p, SVCCTL_Q_QUERY_SERVICE_CON
 
 WERROR _svcctl_query_service_config2( pipes_struct *p, SVCCTL_Q_QUERY_SERVICE_CONFIG2 *q_u, SVCCTL_R_QUERY_SERVICE_CONFIG2 *r_u )
 {
-       POLICY_HND *handle;
-       SERVICE_INFO *service_info;
        SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle );
+       uint32 buffer_size;
        
        /* perform access checks */
 
@@ -773,55 +664,84 @@ WERROR _svcctl_query_service_config2( pipes_struct *p, SVCCTL_Q_QUERY_SERVICE_CO
        /* we have to set the outgoing buffer size to the same as the 
           incoming buffer size (even in the case of failure */
 
-       r_u->needed      = q_u->buffer_size;
-       r_u->description = NULL;               
-       r_u->returned = q_u->buffer_size;
-       r_u->offset = 4;                       
+       rpcbuf_init( &r_u->buffer, q_u->buffer_size, p->mem_ctx );
+       r_u->needed = q_u->buffer_size;
 
-       handle = &(q_u->handle);
+       switch ( q_u->level ) {
+       case SERVICE_CONFIG_DESCRIPTION:
+               {
+                       SERVICE_DESCRIPTION desc_buf;
+                       const char *description;
+                       
+                       description = svcctl_lookup_description( info->name, p->pipe_user.nt_user_token );
+                       
+                       ZERO_STRUCTP( &desc_buf );
 
-       service_info = find_service_info_by_hnd(p, handle);
+                       init_service_description_buffer( &desc_buf, description );
+                       svcctl_io_service_description( "", &desc_buf, &r_u->buffer, 0 );
+                       buffer_size = svcctl_sizeof_service_description( &desc_buf );
 
-       if (!service_info) {
-               DEBUG(10, ("_svcctl_query_service_config2 : Can't find the service for the handle\n"));
-               return WERR_BADFID; 
-       }
-       
-       /* 
-          TODO - perhaps move the RPC_DATA_BLOB into the R_QUERY_SERVICE_CONFIG structure, and to the processing in here, vs
-           in the *r_query_config2 marshalling routine...
-       */
-
-#if 0
-       if (SERVICE_CONFIG_DESCRIPTION == q_u->info_level) {
-               if (service_info && service_info->shortdescription) {
-                       /* length of the string, plus the terminator... */
-                       string_buffer_size = strlen(service_info->shortdescription)+1; 
-                       DEBUG(10, ("_svcctl_query_service_config: copying the description [%s] length [%d]\n",
-                       service_info->shortdescription,string_buffer_size));
-           
-                       if (q_u->buffer_size >= ((string_buffer_size)*2+4)) {
-                               r_u->description = TALLOC_ZERO_P(p->mem_ctx,  UNISTR2);
-                               if (!r_u->description) return WERR_NOMEM;
-                                       init_unistr2(r_u->description,service_info->shortdescription,UNI_STR_TERMINATE);
-                       }
+                       break;
                }
-               else { 
-                       string_buffer_size = 0;
-               }
-               DEBUG(10, ("_svcctl_query_service_config2: buffer needed is [%x], return buffer size is [%x]\n",
-                       string_buffer_size,q_u->buffer_size));
-               if (((string_buffer_size)*2+4) > q_u->buffer_size) {
-                       r_u->needed = (string_buffer_size+1)*2+4;
-                       DEBUG(10, ("_svcctl_query_service_config2: INSUFFICIENT BUFFER\n"));
-                       return WERR_INSUFFICIENT_BUFFER;
+               break;
+       case SERVICE_CONFIG_FAILURE_ACTIONS:
+               {
+                       SERVICE_FAILURE_ACTIONS actions;
+
+                       /* nothing to say...just service the request */
+
+                       ZERO_STRUCTP( &actions );
+                       svcctl_io_service_fa( "", &actions, &r_u->buffer, 0 );
+                       buffer_size = svcctl_sizeof_service_fa( &actions );
+
+                       break;
                }
-               DEBUG(10, ("_svcctl_query_service_config2: returning ok, needed is [%x], buffer size is [%x]\n",
-               r_u->needed,q_u->buffer_size));
+               break;
+
+       default:
+               return WERR_UNKNOWN_LEVEL;
+       }
+       
+       buffer_size += buffer_size % 4;
+       r_u->needed = (buffer_size > q_u->buffer_size) ? buffer_size : q_u->buffer_size;
 
-               return WERR_OK;    
-       } 
-#endif
+        if (buffer_size > q_u->buffer_size )
+                return WERR_INSUFFICIENT_BUFFER;
 
-       return WERR_ACCESS_DENIED;
+       return WERR_OK;
+}
+
+/********************************************************************
+********************************************************************/
+
+WERROR _svcctl_lock_service_db( pipes_struct *p, SVCCTL_Q_LOCK_SERVICE_DB *q_u, SVCCTL_R_LOCK_SERVICE_DB *r_u )
+{
+       SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle );
+       
+       /* perform access checks */
+
+       if ( !info || (info->type != SVC_HANDLE_IS_SCM) )
+               return WERR_BADFID;     
+       
+       if ( !(info->access_granted & SC_RIGHT_MGR_LOCK) )
+               return WERR_ACCESS_DENIED;
+
+       /* Just open a handle.  Doesn't actually lock anything */
+       
+       return create_open_service_handle( p, &r_u->h_lock, SVC_HANDLE_IS_DBLOCK, NULL, 0 );
+;
+}
+
+/********************************************************************
+********************************************************************/
+
+WERROR _svcctl_unlock_service_db( pipes_struct *p, SVCCTL_Q_UNLOCK_SERVICE_DB *q_u, SVCCTL_R_UNLOCK_SERVICE_DB *r_u )
+{
+       SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->h_lock );
+
+
+       if ( !info || (info->type != SVC_HANDLE_IS_DBLOCK) )
+               return WERR_BADFID;     
+               
+       return close_policy_hnd( p, &q_u->h_lock) ? WERR_OK : WERR_BADFID;
 }
index 44e97f9881e7bba20d4b6ed5cd2aca5422b6b52f..956dbfa402702fd0b1f2074d0ef7eca0943cb86f 100644 (file)
@@ -24,7 +24,7 @@
 
 /* Check DFS is supported by the remote server */
 
-static NTSTATUS cmd_dfs_exist(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+static NTSTATUS cmd_dfs_exist(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                               int argc, const char **argv)
 {
        BOOL dfs_exists;
@@ -35,7 +35,7 @@ static NTSTATUS cmd_dfs_exist(struct cli_state *cli, TALLOC_CTX *mem_ctx,
                return NT_STATUS_OK;
        }
 
-       result = cli_dfs_exist(cli, mem_ctx, &dfs_exists);
+       result = rpccli_dfs_exist(cli, mem_ctx, &dfs_exists);
 
        if (NT_STATUS_IS_OK(result))
                printf("dfs is %spresent\n", dfs_exists ? "" : "not ");
@@ -43,7 +43,7 @@ static NTSTATUS cmd_dfs_exist(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        return result;
 }
 
-static NTSTATUS cmd_dfs_add(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+static NTSTATUS cmd_dfs_add(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                             int argc, const char **argv)
 {
        NTSTATUS result;
@@ -61,13 +61,13 @@ static NTSTATUS cmd_dfs_add(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        sharename = argv[3];
        comment = argv[4];
 
-       result = cli_dfs_add(cli, mem_ctx, entrypath, servername, 
+       result = rpccli_dfs_add(cli, mem_ctx, entrypath, servername, 
                             sharename, comment, flags);
 
        return result;
 }
 
-static NTSTATUS cmd_dfs_remove(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+static NTSTATUS cmd_dfs_remove(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                int argc, const char **argv)
 {
        NTSTATUS result;
@@ -82,7 +82,7 @@ static NTSTATUS cmd_dfs_remove(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        servername = argv[2];
        sharename = argv[3];
 
-       result = cli_dfs_remove(cli, mem_ctx, entrypath, servername, 
+       result = rpccli_dfs_remove(cli, mem_ctx, entrypath, servername, 
                                sharename);
 
        return result;
@@ -168,7 +168,7 @@ static void display_dfs_info_ctr(DFS_INFO_CTR *ctr)
 
 /* Enumerate dfs shares */
 
-static NTSTATUS cmd_dfs_enum(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+static NTSTATUS cmd_dfs_enum(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                              int argc, const char **argv)
 {
        DFS_INFO_CTR ctr;
@@ -183,7 +183,7 @@ static NTSTATUS cmd_dfs_enum(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        if (argc == 2)
                info_level = atoi(argv[1]);
 
-       result = cli_dfs_enum(cli, mem_ctx, info_level, &ctr);
+       result = rpccli_dfs_enum(cli, mem_ctx, info_level, &ctr);
 
        if (NT_STATUS_IS_OK(result))
                display_dfs_info_ctr(&ctr);
@@ -191,7 +191,7 @@ static NTSTATUS cmd_dfs_enum(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        return result;
 }
 
-static NTSTATUS cmd_dfs_getinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+static NTSTATUS cmd_dfs_getinfo(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                 int argc, const char **argv)
 {
        NTSTATUS result;
@@ -212,7 +212,7 @@ static NTSTATUS cmd_dfs_getinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        if (argc == 5)
                info_level = atoi(argv[4]);
 
-       result = cli_dfs_get_info(cli, mem_ctx, entrypath, servername, 
+       result = rpccli_dfs_get_info(cli, mem_ctx, entrypath, servername, 
                                  sharename, info_level, &ctr);
 
        if (NT_STATUS_IS_OK(result))
@@ -227,11 +227,11 @@ struct cmd_set dfs_commands[] = {
 
        { "DFS" },
 
-       { "dfsexist",  RPC_RTYPE_NTSTATUS, cmd_dfs_exist,   NULL, PI_NETDFS, "Query DFS support",    "" },
-       { "dfsadd",    RPC_RTYPE_NTSTATUS, cmd_dfs_add,     NULL, PI_NETDFS, "Add a DFS share",      "" },
-       { "dfsremove", RPC_RTYPE_NTSTATUS, cmd_dfs_remove,  NULL, PI_NETDFS, "Remove a DFS share",   "" },
-       { "dfsgetinfo",RPC_RTYPE_NTSTATUS, cmd_dfs_getinfo, NULL, PI_NETDFS, "Query DFS share info", "" },
-       { "dfsenum",   RPC_RTYPE_NTSTATUS, cmd_dfs_enum,    NULL, PI_NETDFS, "Enumerate dfs shares", "" },
+       { "dfsexist",  RPC_RTYPE_NTSTATUS, cmd_dfs_exist,   NULL, PI_NETDFS, NULL, "Query DFS support",    "" },
+       { "dfsadd",    RPC_RTYPE_NTSTATUS, cmd_dfs_add,     NULL, PI_NETDFS, NULL, "Add a DFS share",      "" },
+       { "dfsremove", RPC_RTYPE_NTSTATUS, cmd_dfs_remove,  NULL, PI_NETDFS, NULL, "Remove a DFS share",   "" },
+       { "dfsgetinfo",RPC_RTYPE_NTSTATUS, cmd_dfs_getinfo, NULL, PI_NETDFS, NULL, "Query DFS share info", "" },
+       { "dfsenum",   RPC_RTYPE_NTSTATUS, cmd_dfs_enum,    NULL, PI_NETDFS, NULL, "Enumerate dfs shares", "" },
 
        { NULL }
 };
index 0a1fd7e012ba19515e846ed9a3946134cc540906..951d18a710e3c3497c4b653b05dcd31a2db2ec56 100644 (file)
 
 /* Look up domain related information on a remote host */
 
-static NTSTATUS cmd_ds_dsrole_getprimarydominfo(struct cli_state *cli, 
+static NTSTATUS cmd_ds_dsrole_getprimarydominfo(struct rpc_pipe_client *cli, 
                                     TALLOC_CTX *mem_ctx, int argc, 
                                     const char **argv) 
 {
        NTSTATUS result;
        DS_DOMINFO_CTR  ctr;
        
-       result = cli_ds_getprimarydominfo( cli, mem_ctx, DsRolePrimaryDomainInfoBasic, &ctr );
+       result = rpccli_ds_getprimarydominfo( cli, mem_ctx, DsRolePrimaryDomainInfoBasic, &ctr );
        if ( NT_STATUS_IS_OK(result) )
        {
                printf ("Machine Role = [%d]\n", ctr.basic->machine_role);
@@ -47,7 +47,7 @@ static NTSTATUS cmd_ds_dsrole_getprimarydominfo(struct cli_state *cli,
        return result;
 }
 
-static NTSTATUS cmd_ds_enum_domain_trusts(struct cli_state *cli, 
+static NTSTATUS cmd_ds_enum_domain_trusts(struct rpc_pipe_client *cli,
                                     TALLOC_CTX *mem_ctx, int argc, 
                                     const char **argv) 
 {
@@ -57,7 +57,7 @@ static NTSTATUS cmd_ds_enum_domain_trusts(struct cli_state *cli,
        unsigned int                    num_domains = 0;
        int i;
        
-       result = cli_ds_enum_domain_trusts( cli, mem_ctx, cli->desthost, flags, 
+       result = rpccli_ds_enum_domain_trusts( cli, mem_ctx, cli->cli->desthost, flags, 
                &trusts, &num_domains );
        
        printf( "%d domains returned\n", num_domains );
@@ -74,8 +74,8 @@ struct cmd_set ds_commands[] = {
 
        { "LSARPC-DS" },
 
-       { "dsroledominfo",   RPC_RTYPE_NTSTATUS, cmd_ds_dsrole_getprimarydominfo, NULL, PI_LSARPC_DS, "Get Primary Domain Information", "" },
-       { "dsenumdomtrusts", RPC_RTYPE_NTSTATUS, cmd_ds_enum_domain_trusts,       NULL, PI_NETLOGON,  "Enumerate all trusted domains in an AD forest", "" },
+       { "dsroledominfo",   RPC_RTYPE_NTSTATUS, cmd_ds_dsrole_getprimarydominfo, NULL, PI_LSARPC_DS, NULL, "Get Primary Domain Information", "" },
+       { "dsenumdomtrusts", RPC_RTYPE_NTSTATUS, cmd_ds_enum_domain_trusts,       NULL, PI_NETLOGON,  NULL, "Enumerate all trusted domains in an AD forest", "" },
 
-       { NULL }
+{ NULL }
 };
index fce8e4c7b8f9a3257c84b6fbde86fea1508f4cc0..6d608ebaf10ab8c4059de38039111f15947d9eaf 100644 (file)
@@ -22,7 +22,7 @@
 #include "includes.h"
 #include "rpcclient.h"
 
-static NTSTATUS cmd_echo_add_one(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+static NTSTATUS cmd_echo_add_one(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                 int argc, const char **argv)
 {
        uint32 request = 1, response;
@@ -36,7 +36,7 @@ static NTSTATUS cmd_echo_add_one(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        if (argc == 2)
                request = atoi(argv[1]);
 
-       result = cli_echo_add_one(cli, mem_ctx, request, &response);
+       result = rpccli_echo_add_one(cli, mem_ctx, request, &response);
 
        if (!NT_STATUS_IS_OK(result))
                goto done;
@@ -47,7 +47,7 @@ done:
        return result;
 }
 
-static NTSTATUS cmd_echo_data(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+static NTSTATUS cmd_echo_data(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                              int argc, const char **argv)
 {
        uint32 size, i;
@@ -65,7 +65,7 @@ static NTSTATUS cmd_echo_data(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        for (i = 0; i < size; i++)
                in_data[i] = i & 0xff;
 
-       result = cli_echo_data(cli, mem_ctx, size, in_data, &out_data);
+       result = rpccli_echo_data(cli, mem_ctx, size, in_data, &out_data);
 
        if (!NT_STATUS_IS_OK(result))
                goto done;
@@ -84,7 +84,7 @@ done:
        return result;
 }
 
-static NTSTATUS cmd_echo_source_data(struct cli_state *cli, 
+static NTSTATUS cmd_echo_source_data(struct rpc_pipe_client *cli, 
                                     TALLOC_CTX *mem_ctx, int argc, 
                                     const char **argv)
 {
@@ -99,7 +99,7 @@ static NTSTATUS cmd_echo_source_data(struct cli_state *cli,
 
        size = atoi(argv[1]);
 
-       result = cli_echo_source_data(cli, mem_ctx, size, &out_data);
+       result = rpccli_echo_source_data(cli, mem_ctx, size, &out_data);
 
        if (!NT_STATUS_IS_OK(result))
                goto done;
@@ -116,7 +116,7 @@ done:
        return result;
 }
 
-static NTSTATUS cmd_echo_sink_data(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+static NTSTATUS cmd_echo_sink_data(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                   int argc, const char **argv)
 {
        uint32 size, i;
@@ -134,7 +134,7 @@ static NTSTATUS cmd_echo_sink_data(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        for (i = 0; i < size; i++)
                in_data[i] = i & 0xff;
 
-       result = cli_echo_sink_data(cli, mem_ctx, size, in_data);
+       result = rpccli_echo_sink_data(cli, mem_ctx, size, in_data);
 
        if (!NT_STATUS_IS_OK(result))
                goto done;
@@ -151,9 +151,9 @@ struct cmd_set echo_commands[] = {
 
        { "ECHO" },
 
-       { "echoaddone", RPC_RTYPE_NTSTATUS, cmd_echo_add_one,     NULL, PI_ECHO, "Add one to a number", "" },
-       { "echodata",   RPC_RTYPE_NTSTATUS, cmd_echo_data,        NULL, PI_ECHO, "Echo data",           "" },
-       { "sinkdata",   RPC_RTYPE_NTSTATUS, cmd_echo_sink_data,   NULL, PI_ECHO, "Sink data",           "" },
-       { "sourcedata", RPC_RTYPE_NTSTATUS, cmd_echo_source_data, NULL, PI_ECHO, "Source data",         "" },
+       { "echoaddone", RPC_RTYPE_NTSTATUS, cmd_echo_add_one,     NULL, PI_ECHO, NULL, "Add one to a number", "" },
+       { "echodata",   RPC_RTYPE_NTSTATUS, cmd_echo_data,        NULL, PI_ECHO, NULL, "Echo data",           "" },
+       { "sinkdata",   RPC_RTYPE_NTSTATUS, cmd_echo_sink_data,   NULL, PI_ECHO, NULL, "Sink data",           "" },
+       { "sourcedata", RPC_RTYPE_NTSTATUS, cmd_echo_source_data, NULL, PI_ECHO, NULL, "Source data",         "" },
        { NULL }
 };
index b01f63924774b878e582a744440db8d54c7585c0..00ed515245bcbf22a6096534f20ebaddcb653335 100644 (file)
@@ -26,7 +26,7 @@
 
 /* useful function to allow entering a name instead of a SID and
  * looking it up automatically */
-static NTSTATUS name_to_sid(struct cli_state *cli, 
+static NTSTATUS name_to_sid(struct rpc_pipe_client *cli, 
                            TALLOC_CTX *mem_ctx,
                            DOM_SID *sid, const char *name)
 {
@@ -41,17 +41,17 @@ static NTSTATUS name_to_sid(struct cli_state *cli,
                return NT_STATUS_OK;
        }
 
-       result = cli_lsa_open_policy(cli, mem_ctx, True, 
+       result = rpccli_lsa_open_policy(cli, mem_ctx, True, 
                                     SEC_RIGHTS_MAXIMUM_ALLOWED,
                                     &pol);
        if (!NT_STATUS_IS_OK(result))
                goto done;
 
-       result = cli_lsa_lookup_names(cli, mem_ctx, &pol, 1, &name, &sids, &sid_types);
+       result = rpccli_lsa_lookup_names(cli, mem_ctx, &pol, 1, &name, &sids, &sid_types);
        if (!NT_STATUS_IS_OK(result))
                goto done;
 
-       cli_lsa_close(cli, mem_ctx, &pol);
+       rpccli_lsa_close(cli, mem_ctx, &pol);
 
        *sid = sids[0];
 
@@ -62,7 +62,7 @@ done:
 
 /* Look up domain related information on a remote host */
 
-static NTSTATUS cmd_lsa_query_info_policy(struct cli_state *cli, 
+static NTSTATUS cmd_lsa_query_info_policy(struct rpc_pipe_client *cli, 
                                           TALLOC_CTX *mem_ctx, int argc, 
                                           const char **argv) 
 {
@@ -88,25 +88,25 @@ static NTSTATUS cmd_lsa_query_info_policy(struct cli_state *cli,
        /* Lookup info policy */
        switch (info_class) {
        case 12:
-               result = cli_lsa_open_policy2(cli, mem_ctx, True, 
+               result = rpccli_lsa_open_policy2(cli, mem_ctx, True, 
                                             SEC_RIGHTS_MAXIMUM_ALLOWED,
                                             &pol);
 
                if (!NT_STATUS_IS_OK(result))
                        goto done;
-               result = cli_lsa_query_info_policy2(cli, mem_ctx, &pol,
+               result = rpccli_lsa_query_info_policy2(cli, mem_ctx, &pol,
                                                    info_class, &domain_name,
                                                    &dns_name, &forest_name,
                                                    &dom_guid, &dom_sid);
                break;
        default:
-               result = cli_lsa_open_policy(cli, mem_ctx, True, 
+               result = rpccli_lsa_open_policy(cli, mem_ctx, True, 
                                     SEC_RIGHTS_MAXIMUM_ALLOWED,
                                     &pol);
 
                if (!NT_STATUS_IS_OK(result))
                        goto done;
-               result = cli_lsa_query_info_policy(cli, mem_ctx, &pol, 
+               result = rpccli_lsa_query_info_policy(cli, mem_ctx, &pol, 
                                                   info_class, &domain_name, 
                                                   &dom_sid);
        }
@@ -130,13 +130,16 @@ static NTSTATUS cmd_lsa_query_info_policy(struct cli_state *cli,
                printf("domain GUID is ");
                smb_uuid_string_static(*dom_guid);
        }
+
+       rpccli_lsa_close(cli, mem_ctx, &pol);
+
  done:
        return result;
 }
 
 /* Resolve a list of names to a list of sids */
 
-static NTSTATUS cmd_lsa_lookup_names(struct cli_state *cli, 
+static NTSTATUS cmd_lsa_lookup_names(struct rpc_pipe_client *cli, 
                                      TALLOC_CTX *mem_ctx, int argc, 
                                      const char **argv)
 {
@@ -151,14 +154,14 @@ static NTSTATUS cmd_lsa_lookup_names(struct cli_state *cli,
                return NT_STATUS_OK;
        }
 
-       result = cli_lsa_open_policy(cli, mem_ctx, True, 
+       result = rpccli_lsa_open_policy(cli, mem_ctx, True, 
                                     SEC_RIGHTS_MAXIMUM_ALLOWED,
                                     &pol);
 
        if (!NT_STATUS_IS_OK(result))
                goto done;
 
-       result = cli_lsa_lookup_names(cli, mem_ctx, &pol, argc - 1, 
+       result = rpccli_lsa_lookup_names(cli, mem_ctx, &pol, argc - 1, 
                                      (const char**)(argv + 1), &sids, &types);
 
        if (!NT_STATUS_IS_OK(result) && NT_STATUS_V(result) != 
@@ -176,7 +179,7 @@ static NTSTATUS cmd_lsa_lookup_names(struct cli_state *cli,
                       sid_type_lookup(types[i]), types[i]);
        }
 
-       cli_lsa_close(cli, mem_ctx, &pol);
+       rpccli_lsa_close(cli, mem_ctx, &pol);
 
  done:
        return result;
@@ -184,7 +187,7 @@ static NTSTATUS cmd_lsa_lookup_names(struct cli_state *cli,
 
 /* Resolve a list of SIDs to a list of names */
 
-static NTSTATUS cmd_lsa_lookup_sids(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+static NTSTATUS cmd_lsa_lookup_sids(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                     int argc, const char **argv)
 {
        POLICY_HND pol;
@@ -200,7 +203,7 @@ static NTSTATUS cmd_lsa_lookup_sids(struct cli_state *cli, TALLOC_CTX *mem_ctx,
                return NT_STATUS_OK;
        }
 
-       result = cli_lsa_open_policy(cli, mem_ctx, True, 
+       result = rpccli_lsa_open_policy(cli, mem_ctx, True, 
                                     SEC_RIGHTS_MAXIMUM_ALLOWED,
                                     &pol);
 
@@ -224,7 +227,7 @@ static NTSTATUS cmd_lsa_lookup_sids(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 
        /* Lookup the SIDs */
 
-       result = cli_lsa_lookup_sids(cli, mem_ctx, &pol, argc - 1, sids, 
+       result = rpccli_lsa_lookup_sids(cli, mem_ctx, &pol, argc - 1, sids, 
                                     &domains, &names, &types);
 
        if (!NT_STATUS_IS_OK(result) && NT_STATUS_V(result) != 
@@ -244,7 +247,7 @@ static NTSTATUS cmd_lsa_lookup_sids(struct cli_state *cli, TALLOC_CTX *mem_ctx,
                       names[i] ? names[i] : "*unknown*", types[i]);
        }
 
-       cli_lsa_close(cli, mem_ctx, &pol);
+       rpccli_lsa_close(cli, mem_ctx, &pol);
 
  done:
        return result;
@@ -252,7 +255,7 @@ static NTSTATUS cmd_lsa_lookup_sids(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 
 /* Enumerate list of trusted domains */
 
-static NTSTATUS cmd_lsa_enum_trust_dom(struct cli_state *cli, 
+static NTSTATUS cmd_lsa_enum_trust_dom(struct rpc_pipe_client *cli, 
                                        TALLOC_CTX *mem_ctx, int argc, 
                                        const char **argv)
 {
@@ -275,7 +278,7 @@ static NTSTATUS cmd_lsa_enum_trust_dom(struct cli_state *cli,
                enum_ctx = atoi(argv[2]);
        }       
 
-       result = cli_lsa_open_policy(cli, mem_ctx, True, 
+       result = rpccli_lsa_open_policy(cli, mem_ctx, True, 
                                     POLICY_VIEW_LOCAL_INFORMATION,
                                     &pol);
 
@@ -288,7 +291,7 @@ static NTSTATUS cmd_lsa_enum_trust_dom(struct cli_state *cli,
 
                /* Lookup list of trusted domains */
 
-               result = cli_lsa_enum_trust_dom(cli, mem_ctx, &pol, &enum_ctx,
+               result = rpccli_lsa_enum_trust_dom(cli, mem_ctx, &pol, &enum_ctx,
                                                &num_domains,
                                                &domain_names, &domain_sids);
                if (!NT_STATUS_IS_OK(result) &&
@@ -307,13 +310,14 @@ static NTSTATUS cmd_lsa_enum_trust_dom(struct cli_state *cli,
                }
        }
 
+       rpccli_lsa_close(cli, mem_ctx, &pol);
  done:
        return result;
 }
 
 /* Enumerates privileges */
 
-static NTSTATUS cmd_lsa_enum_privilege(struct cli_state *cli, 
+static NTSTATUS cmd_lsa_enum_privilege(struct rpc_pipe_client *cli, 
                                       TALLOC_CTX *mem_ctx, int argc, 
                                       const char **argv) 
 {
@@ -339,14 +343,14 @@ static NTSTATUS cmd_lsa_enum_privilege(struct cli_state *cli,
        if (argc==3)
                pref_max_length=atoi(argv[2]);
 
-       result = cli_lsa_open_policy(cli, mem_ctx, True, 
+       result = rpccli_lsa_open_policy(cli, mem_ctx, True, 
                                     SEC_RIGHTS_MAXIMUM_ALLOWED,
                                     &pol);
 
        if (!NT_STATUS_IS_OK(result))
                goto done;
 
-       result = cli_lsa_enum_privilege(cli, mem_ctx, &pol, &enum_context, pref_max_length,
+       result = rpccli_lsa_enum_privilege(cli, mem_ctx, &pol, &enum_context, pref_max_length,
                                        &count, &privs_name, &privs_high, &privs_low);
 
        if (!NT_STATUS_IS_OK(result))
@@ -360,13 +364,14 @@ static NTSTATUS cmd_lsa_enum_privilege(struct cli_state *cli,
                       privs_high[i], privs_low[i], privs_high[i], privs_low[i]);
        }
 
+       rpccli_lsa_close(cli, mem_ctx, &pol);
  done:
        return result;
 }
 
 /* Get privilege name */
 
-static NTSTATUS cmd_lsa_get_dispname(struct cli_state *cli, 
+static NTSTATUS cmd_lsa_get_dispname(struct rpc_pipe_client *cli, 
                                      TALLOC_CTX *mem_ctx, int argc, 
                                      const char **argv) 
 {
@@ -383,14 +388,14 @@ static NTSTATUS cmd_lsa_get_dispname(struct cli_state *cli,
                return NT_STATUS_OK;
        }
 
-       result = cli_lsa_open_policy(cli, mem_ctx, True, 
+       result = rpccli_lsa_open_policy(cli, mem_ctx, True, 
                                     SEC_RIGHTS_MAXIMUM_ALLOWED,
                                     &pol);
 
        if (!NT_STATUS_IS_OK(result))
                goto done;
 
-       result = cli_lsa_get_dispname(cli, mem_ctx, &pol, argv[1], lang_id, lang_id_sys, description, &lang_id_desc);
+       result = rpccli_lsa_get_dispname(cli, mem_ctx, &pol, argv[1], lang_id, lang_id_sys, description, &lang_id_desc);
 
        if (!NT_STATUS_IS_OK(result))
                goto done;
@@ -398,13 +403,14 @@ static NTSTATUS cmd_lsa_get_dispname(struct cli_state *cli,
        /* Print results */
        printf("%s -> %s (language: 0x%x)\n", argv[1], description, lang_id_desc);
 
+       rpccli_lsa_close(cli, mem_ctx, &pol);
  done:
        return result;
 }
 
 /* Enumerate the LSA SIDS */
 
-static NTSTATUS cmd_lsa_enum_sids(struct cli_state *cli, 
+static NTSTATUS cmd_lsa_enum_sids(struct rpc_pipe_client *cli, 
                                  TALLOC_CTX *mem_ctx, int argc, 
                                  const char **argv) 
 {
@@ -428,14 +434,14 @@ static NTSTATUS cmd_lsa_enum_sids(struct cli_state *cli,
        if (argc==3)
                pref_max_length=atoi(argv[2]);
 
-       result = cli_lsa_open_policy(cli, mem_ctx, True, 
+       result = rpccli_lsa_open_policy(cli, mem_ctx, True, 
                                     SEC_RIGHTS_MAXIMUM_ALLOWED,
                                     &pol);
 
        if (!NT_STATUS_IS_OK(result))
                goto done;
 
-       result = cli_lsa_enum_sids(cli, mem_ctx, &pol, &enum_context, pref_max_length,
+       result = rpccli_lsa_enum_sids(cli, mem_ctx, &pol, &enum_context, pref_max_length,
                                        &count, &sids);
 
        if (!NT_STATUS_IS_OK(result))
@@ -451,13 +457,14 @@ static NTSTATUS cmd_lsa_enum_sids(struct cli_state *cli,
                printf("%s\n", sid_str);
        }
 
+       rpccli_lsa_close(cli, mem_ctx, &pol);
  done:
        return result;
 }
 
 /* Create a new account */
 
-static NTSTATUS cmd_lsa_create_account(struct cli_state *cli, 
+static NTSTATUS cmd_lsa_create_account(struct rpc_pipe_client *cli, 
                                            TALLOC_CTX *mem_ctx, int argc, 
                                            const char **argv) 
 {
@@ -477,14 +484,14 @@ static NTSTATUS cmd_lsa_create_account(struct cli_state *cli,
        if (!NT_STATUS_IS_OK(result))
                goto done;      
 
-       result = cli_lsa_open_policy2(cli, mem_ctx, True, 
+       result = rpccli_lsa_open_policy2(cli, mem_ctx, True, 
                                     SEC_RIGHTS_MAXIMUM_ALLOWED,
                                     &dom_pol);
 
        if (!NT_STATUS_IS_OK(result))
                goto done;
 
-       result = cli_lsa_create_account(cli, mem_ctx, &dom_pol, &sid, des_access, &user_pol);
+       result = rpccli_lsa_create_account(cli, mem_ctx, &dom_pol, &sid, des_access, &user_pol);
 
        if (!NT_STATUS_IS_OK(result))
                goto done;
@@ -492,6 +499,7 @@ static NTSTATUS cmd_lsa_create_account(struct cli_state *cli,
        printf("Account for SID %s successfully created\n\n", argv[1]);
        result = NT_STATUS_OK;
 
+       rpccli_lsa_close(cli, mem_ctx, &dom_pol);
  done:
        return result;
 }
@@ -499,7 +507,7 @@ static NTSTATUS cmd_lsa_create_account(struct cli_state *cli,
 
 /* Enumerate the privileges of an SID */
 
-static NTSTATUS cmd_lsa_enum_privsaccounts(struct cli_state *cli, 
+static NTSTATUS cmd_lsa_enum_privsaccounts(struct rpc_pipe_client *cli, 
                                            TALLOC_CTX *mem_ctx, int argc, 
                                            const char **argv) 
 {
@@ -522,19 +530,19 @@ static NTSTATUS cmd_lsa_enum_privsaccounts(struct cli_state *cli,
        if (!NT_STATUS_IS_OK(result))
                goto done;      
 
-       result = cli_lsa_open_policy2(cli, mem_ctx, True, 
+       result = rpccli_lsa_open_policy2(cli, mem_ctx, True, 
                                     SEC_RIGHTS_MAXIMUM_ALLOWED,
                                     &dom_pol);
 
        if (!NT_STATUS_IS_OK(result))
                goto done;
 
-       result = cli_lsa_open_account(cli, mem_ctx, &dom_pol, &sid, access_desired, &user_pol);
+       result = rpccli_lsa_open_account(cli, mem_ctx, &dom_pol, &sid, access_desired, &user_pol);
 
        if (!NT_STATUS_IS_OK(result))
                goto done;
 
-       result = cli_lsa_enum_privsaccount(cli, mem_ctx, &user_pol, &count, &set);
+       result = rpccli_lsa_enum_privsaccount(cli, mem_ctx, &user_pol, &count, &set);
 
        if (!NT_STATUS_IS_OK(result))
                goto done;
@@ -547,6 +555,7 @@ static NTSTATUS cmd_lsa_enum_privsaccounts(struct cli_state *cli,
                printf("%u\t%u\t%u\n", set[i].luid.high, set[i].luid.low, set[i].attr);
        }
 
+       rpccli_lsa_close(cli, mem_ctx, &dom_pol);
  done:
        return result;
 }
@@ -554,7 +563,7 @@ static NTSTATUS cmd_lsa_enum_privsaccounts(struct cli_state *cli,
 
 /* Enumerate the privileges of an SID via LsaEnumerateAccountRights */
 
-static NTSTATUS cmd_lsa_enum_acct_rights(struct cli_state *cli, 
+static NTSTATUS cmd_lsa_enum_acct_rights(struct rpc_pipe_client *cli, 
                                         TALLOC_CTX *mem_ctx, int argc, 
                                         const char **argv) 
 {
@@ -576,14 +585,14 @@ static NTSTATUS cmd_lsa_enum_acct_rights(struct cli_state *cli,
        if (!NT_STATUS_IS_OK(result))
                goto done;      
 
-       result = cli_lsa_open_policy2(cli, mem_ctx, True, 
+       result = rpccli_lsa_open_policy2(cli, mem_ctx, True, 
                                     SEC_RIGHTS_MAXIMUM_ALLOWED,
                                     &dom_pol);
 
        if (!NT_STATUS_IS_OK(result))
                goto done;
 
-       result = cli_lsa_enum_account_rights(cli, mem_ctx, &dom_pol, &sid, &count, &rights);
+       result = rpccli_lsa_enum_account_rights(cli, mem_ctx, &dom_pol, &sid, &count, &rights);
 
        if (!NT_STATUS_IS_OK(result))
                goto done;
@@ -594,6 +603,7 @@ static NTSTATUS cmd_lsa_enum_acct_rights(struct cli_state *cli,
                printf("\t%s\n", rights[i]);
        }
 
+       rpccli_lsa_close(cli, mem_ctx, &dom_pol);
  done:
        return result;
 }
@@ -601,7 +611,7 @@ static NTSTATUS cmd_lsa_enum_acct_rights(struct cli_state *cli,
 
 /* add some privileges to a SID via LsaAddAccountRights */
 
-static NTSTATUS cmd_lsa_add_acct_rights(struct cli_state *cli, 
+static NTSTATUS cmd_lsa_add_acct_rights(struct rpc_pipe_client *cli, 
                                        TALLOC_CTX *mem_ctx, int argc, 
                                        const char **argv) 
 {
@@ -619,19 +629,20 @@ static NTSTATUS cmd_lsa_add_acct_rights(struct cli_state *cli,
        if (!NT_STATUS_IS_OK(result))
                goto done;      
 
-       result = cli_lsa_open_policy2(cli, mem_ctx, True, 
+       result = rpccli_lsa_open_policy2(cli, mem_ctx, True, 
                                     SEC_RIGHTS_MAXIMUM_ALLOWED,
                                     &dom_pol);
 
        if (!NT_STATUS_IS_OK(result))
                goto done;
 
-       result = cli_lsa_add_account_rights(cli, mem_ctx, &dom_pol, sid, 
+       result = rpccli_lsa_add_account_rights(cli, mem_ctx, &dom_pol, sid, 
                                            argc-2, argv+2);
 
        if (!NT_STATUS_IS_OK(result))
                goto done;
 
+       rpccli_lsa_close(cli, mem_ctx, &dom_pol);
  done:
        return result;
 }
@@ -639,7 +650,7 @@ static NTSTATUS cmd_lsa_add_acct_rights(struct cli_state *cli,
 
 /* remove some privileges to a SID via LsaRemoveAccountRights */
 
-static NTSTATUS cmd_lsa_remove_acct_rights(struct cli_state *cli, 
+static NTSTATUS cmd_lsa_remove_acct_rights(struct rpc_pipe_client *cli, 
                                        TALLOC_CTX *mem_ctx, int argc, 
                                        const char **argv) 
 {
@@ -657,19 +668,21 @@ static NTSTATUS cmd_lsa_remove_acct_rights(struct cli_state *cli,
        if (!NT_STATUS_IS_OK(result))
                goto done;      
 
-       result = cli_lsa_open_policy2(cli, mem_ctx, True, 
+       result = rpccli_lsa_open_policy2(cli, mem_ctx, True, 
                                     SEC_RIGHTS_MAXIMUM_ALLOWED,
                                     &dom_pol);
 
        if (!NT_STATUS_IS_OK(result))
                goto done;
 
-       result = cli_lsa_remove_account_rights(cli, mem_ctx, &dom_pol, sid, 
+       result = rpccli_lsa_remove_account_rights(cli, mem_ctx, &dom_pol, sid, 
                                               False, argc-2, argv+2);
 
        if (!NT_STATUS_IS_OK(result))
                goto done;
 
+       rpccli_lsa_close(cli, mem_ctx, &dom_pol);
+
  done:
        return result;
 }
@@ -677,7 +690,7 @@ static NTSTATUS cmd_lsa_remove_acct_rights(struct cli_state *cli,
 
 /* Get a privilege value given its name */
 
-static NTSTATUS cmd_lsa_lookup_priv_value(struct cli_state *cli, 
+static NTSTATUS cmd_lsa_lookup_priv_value(struct rpc_pipe_client *cli, 
                                        TALLOC_CTX *mem_ctx, int argc, 
                                        const char **argv) 
 {
@@ -690,14 +703,14 @@ static NTSTATUS cmd_lsa_lookup_priv_value(struct cli_state *cli,
                return NT_STATUS_OK;
        }
 
-       result = cli_lsa_open_policy2(cli, mem_ctx, True, 
+       result = rpccli_lsa_open_policy2(cli, mem_ctx, True, 
                                     SEC_RIGHTS_MAXIMUM_ALLOWED,
                                     &pol);
 
        if (!NT_STATUS_IS_OK(result))
                goto done;
 
-       result = cli_lsa_lookup_priv_value(cli, mem_ctx, &pol, argv[1], &luid);
+       result = rpccli_lsa_lookup_priv_value(cli, mem_ctx, &pol, argv[1], &luid);
 
        if (!NT_STATUS_IS_OK(result))
                goto done;
@@ -706,13 +719,14 @@ static NTSTATUS cmd_lsa_lookup_priv_value(struct cli_state *cli,
 
        printf("%u:%u (0x%x:0x%x)\n", luid.high, luid.low, luid.high, luid.low);
 
+       rpccli_lsa_close(cli, mem_ctx, &pol);
  done:
        return result;
 }
 
 /* Query LSA security object */
 
-static NTSTATUS cmd_lsa_query_secobj(struct cli_state *cli, 
+static NTSTATUS cmd_lsa_query_secobj(struct rpc_pipe_client *cli, 
                                     TALLOC_CTX *mem_ctx, int argc, 
                                     const char **argv) 
 {
@@ -726,14 +740,14 @@ static NTSTATUS cmd_lsa_query_secobj(struct cli_state *cli,
                return NT_STATUS_OK;
        }
 
-       result = cli_lsa_open_policy2(cli, mem_ctx, True, 
+       result = rpccli_lsa_open_policy2(cli, mem_ctx, True, 
                                      SEC_RIGHTS_MAXIMUM_ALLOWED,
                                      &pol);
 
        if (!NT_STATUS_IS_OK(result))
                goto done;
 
-       result = cli_lsa_query_secobj(cli, mem_ctx, &pol, sec_info, &sdb);
+       result = rpccli_lsa_query_secobj(cli, mem_ctx, &pol, sec_info, &sdb);
 
        if (!NT_STATUS_IS_OK(result))
                goto done;
@@ -742,6 +756,7 @@ static NTSTATUS cmd_lsa_query_secobj(struct cli_state *cli,
 
        display_sec_desc(sdb->sec);
 
+       rpccli_lsa_close(cli, mem_ctx, &pol);
  done:
        return result;
 }
@@ -800,7 +815,7 @@ static void display_trust_dom_info(LSA_TRUSTED_DOMAIN_INFO *info, uint32 info_cl
        }
 }
 
-static NTSTATUS cmd_lsa_query_trustdominfobysid(struct cli_state *cli,
+static NTSTATUS cmd_lsa_query_trustdominfobysid(struct rpc_pipe_client *cli,
                                                TALLOC_CTX *mem_ctx, int argc, 
                                                const char **argv) 
 {
@@ -823,12 +838,12 @@ static NTSTATUS cmd_lsa_query_trustdominfobysid(struct cli_state *cli,
        if (argc == 3)
                info_class = atoi(argv[2]);
 
-       result = cli_lsa_open_policy2(cli, mem_ctx, True, access_mask, &pol);
+       result = rpccli_lsa_open_policy2(cli, mem_ctx, True, access_mask, &pol);
 
        if (!NT_STATUS_IS_OK(result))
                goto done;
 
-       result = cli_lsa_query_trusted_domain_info_by_sid(cli, mem_ctx, &pol,
+       result = rpccli_lsa_query_trusted_domain_info_by_sid(cli, mem_ctx, &pol,
                                                          info_class, &dom_sid, &info);
 
        if (!NT_STATUS_IS_OK(result))
@@ -838,12 +853,12 @@ static NTSTATUS cmd_lsa_query_trustdominfobysid(struct cli_state *cli,
 
  done:
        if (&pol)
-               cli_lsa_close(cli, mem_ctx, &pol);
+               rpccli_lsa_close(cli, mem_ctx, &pol);
 
        return result;
 }
 
-static NTSTATUS cmd_lsa_query_trustdominfobyname(struct cli_state *cli,
+static NTSTATUS cmd_lsa_query_trustdominfobyname(struct rpc_pipe_client *cli,
                                                 TALLOC_CTX *mem_ctx, int argc,
                                                 const char **argv) 
 {
@@ -861,12 +876,12 @@ static NTSTATUS cmd_lsa_query_trustdominfobyname(struct cli_state *cli,
        if (argc == 3)
                info_class = atoi(argv[2]);
 
-       result = cli_lsa_open_policy2(cli, mem_ctx, True, access_mask, &pol);
+       result = rpccli_lsa_open_policy2(cli, mem_ctx, True, access_mask, &pol);
 
        if (!NT_STATUS_IS_OK(result))
                goto done;
 
-       result = cli_lsa_query_trusted_domain_info_by_name(cli, mem_ctx, &pol, 
+       result = rpccli_lsa_query_trusted_domain_info_by_name(cli, mem_ctx, &pol, 
                                                           info_class, argv[1], &info);
 
        if (!NT_STATUS_IS_OK(result))
@@ -876,12 +891,12 @@ static NTSTATUS cmd_lsa_query_trustdominfobyname(struct cli_state *cli,
 
  done:
        if (&pol)
-               cli_lsa_close(cli, mem_ctx, &pol);
+               rpccli_lsa_close(cli, mem_ctx, &pol);
 
        return result;
 }
 
-static NTSTATUS cmd_lsa_query_trustdominfo(struct cli_state *cli,
+static NTSTATUS cmd_lsa_query_trustdominfo(struct rpc_pipe_client *cli,
                                           TALLOC_CTX *mem_ctx, int argc,
                                           const char **argv) 
 {
@@ -904,18 +919,18 @@ static NTSTATUS cmd_lsa_query_trustdominfo(struct cli_state *cli,
        if (argc == 3)
                info_class = atoi(argv[2]);
 
-       result = cli_lsa_open_policy2(cli, mem_ctx, True, access_mask, &pol);
+       result = rpccli_lsa_open_policy2(cli, mem_ctx, True, access_mask, &pol);
 
        if (!NT_STATUS_IS_OK(result))
                goto done;
        
-       result = cli_lsa_open_trusted_domain(cli, mem_ctx, &pol,
+       result = rpccli_lsa_open_trusted_domain(cli, mem_ctx, &pol,
                                             &dom_sid, access_mask, &trustdom_pol);
 
        if (!NT_STATUS_IS_OK(result))
                goto done;
 
-       result = cli_lsa_query_trusted_domain_info(cli, mem_ctx, &trustdom_pol, 
+       result = rpccli_lsa_query_trusted_domain_info(cli, mem_ctx, &trustdom_pol, 
                                                   info_class, &dom_sid, &info);
 
        if (!NT_STATUS_IS_OK(result))
@@ -925,7 +940,7 @@ static NTSTATUS cmd_lsa_query_trustdominfo(struct cli_state *cli,
 
  done:
        if (&pol)
-               cli_lsa_close(cli, mem_ctx, &pol);
+               rpccli_lsa_close(cli, mem_ctx, &pol);
 
        return result;
 }
@@ -938,27 +953,27 @@ struct cmd_set lsarpc_commands[] = {
 
        { "LSARPC" },
 
-       { "lsaquery",            RPC_RTYPE_NTSTATUS, cmd_lsa_query_info_policy,  NULL, PI_LSARPC, "Query info policy",                    "" },
-       { "lookupsids",          RPC_RTYPE_NTSTATUS, cmd_lsa_lookup_sids,        NULL, PI_LSARPC, "Convert SIDs to names",                "" },
-       { "lookupnames",         RPC_RTYPE_NTSTATUS, cmd_lsa_lookup_names,       NULL, PI_LSARPC, "Convert names to SIDs",                "" },
-       { "enumtrust",           RPC_RTYPE_NTSTATUS, cmd_lsa_enum_trust_dom,     NULL, PI_LSARPC, "Enumerate trusted domains",            "Usage: [preferred max number] [enum context (0)]" },
-       { "enumprivs",           RPC_RTYPE_NTSTATUS, cmd_lsa_enum_privilege,     NULL, PI_LSARPC, "Enumerate privileges",                 "" },
-       { "getdispname",         RPC_RTYPE_NTSTATUS, cmd_lsa_get_dispname,       NULL, PI_LSARPC, "Get the privilege name",               "" },
-       { "lsaenumsid",          RPC_RTYPE_NTSTATUS, cmd_lsa_enum_sids,          NULL, PI_LSARPC, "Enumerate the LSA SIDS",               "" },
-       { "lsacreateaccount",    RPC_RTYPE_NTSTATUS, cmd_lsa_create_account,     NULL, PI_LSARPC, "Create a new lsa account",   "" },
-       { "lsaenumprivsaccount", RPC_RTYPE_NTSTATUS, cmd_lsa_enum_privsaccounts, NULL, PI_LSARPC, "Enumerate the privileges of an SID",   "" },
-       { "lsaenumacctrights",   RPC_RTYPE_NTSTATUS, cmd_lsa_enum_acct_rights,   NULL, PI_LSARPC, "Enumerate the rights of an SID",   "" },
+       { "lsaquery",            RPC_RTYPE_NTSTATUS, cmd_lsa_query_info_policy,  NULL, PI_LSARPC, NULL, "Query info policy",                    "" },
+       { "lookupsids",          RPC_RTYPE_NTSTATUS, cmd_lsa_lookup_sids,        NULL, PI_LSARPC, NULL, "Convert SIDs to names",                "" },
+       { "lookupnames",         RPC_RTYPE_NTSTATUS, cmd_lsa_lookup_names,       NULL, PI_LSARPC, NULL, "Convert names to SIDs",                "" },
+       { "enumtrust",           RPC_RTYPE_NTSTATUS, cmd_lsa_enum_trust_dom,     NULL, PI_LSARPC, NULL, "Enumerate trusted domains",            "Usage: [preferred max number] [enum context (0)]" },
+       { "enumprivs",           RPC_RTYPE_NTSTATUS, cmd_lsa_enum_privilege,     NULL, PI_LSARPC, NULL, "Enumerate privileges",                 "" },
+       { "getdispname",         RPC_RTYPE_NTSTATUS, cmd_lsa_get_dispname,       NULL, PI_LSARPC, NULL, "Get the privilege name",               "" },
+       { "lsaenumsid",          RPC_RTYPE_NTSTATUS, cmd_lsa_enum_sids,          NULL, PI_LSARPC, NULL, "Enumerate the LSA SIDS",               "" },
+       { "lsacreateaccount",    RPC_RTYPE_NTSTATUS, cmd_lsa_create_account,     NULL, PI_LSARPC, NULL, "Create a new lsa account",   "" },
+       { "lsaenumprivsaccount", RPC_RTYPE_NTSTATUS, cmd_lsa_enum_privsaccounts, NULL, PI_LSARPC, NULL, "Enumerate the privileges of an SID",   "" },
+       { "lsaenumacctrights",   RPC_RTYPE_NTSTATUS, cmd_lsa_enum_acct_rights,   NULL, PI_LSARPC, NULL, "Enumerate the rights of an SID",   "" },
 #if 0
        { "lsaaddpriv",          RPC_RTYPE_NTSTATUS, cmd_lsa_add_priv,           NULL, PI_LSARPC, "Assign a privilege to a SID", "" },
        { "lsadelpriv",          RPC_RTYPE_NTSTATUS, cmd_lsa_del_priv,           NULL, PI_LSARPC, "Revoke a privilege from a SID", "" },
 #endif
-       { "lsaaddacctrights",    RPC_RTYPE_NTSTATUS, cmd_lsa_add_acct_rights,    NULL, PI_LSARPC, "Add rights to an account",   "" },
-       { "lsaremoveacctrights", RPC_RTYPE_NTSTATUS, cmd_lsa_remove_acct_rights, NULL, PI_LSARPC, "Remove rights from an account",   "" },
-       { "lsalookupprivvalue",  RPC_RTYPE_NTSTATUS, cmd_lsa_lookup_priv_value,  NULL, PI_LSARPC, "Get a privilege value given its name", "" },
-       { "lsaquerysecobj",      RPC_RTYPE_NTSTATUS, cmd_lsa_query_secobj,       NULL, PI_LSARPC, "Query LSA security object", "" },
-       { "lsaquerytrustdominfo",RPC_RTYPE_NTSTATUS, cmd_lsa_query_trustdominfo, NULL, PI_LSARPC, "Query LSA trusted domains info (given a SID)", "" },
-       { "lsaquerytrustdominfobyname",RPC_RTYPE_NTSTATUS, cmd_lsa_query_trustdominfobyname, NULL, PI_LSARPC, "Query LSA trusted domains info (given a name), only works for Windows > 2k", "" },
-       { "lsaquerytrustdominfobysid",RPC_RTYPE_NTSTATUS, cmd_lsa_query_trustdominfobysid, NULL, PI_LSARPC, "Query LSA trusted domains info (given a SID)", "" },
+       { "lsaaddacctrights",    RPC_RTYPE_NTSTATUS, cmd_lsa_add_acct_rights,    NULL, PI_LSARPC, NULL, "Add rights to an account",   "" },
+       { "lsaremoveacctrights", RPC_RTYPE_NTSTATUS, cmd_lsa_remove_acct_rights, NULL, PI_LSARPC, NULL, "Remove rights from an account",   "" },
+       { "lsalookupprivvalue",  RPC_RTYPE_NTSTATUS, cmd_lsa_lookup_priv_value,  NULL, PI_LSARPC, NULL, "Get a privilege value given its name", "" },
+       { "lsaquerysecobj",      RPC_RTYPE_NTSTATUS, cmd_lsa_query_secobj,       NULL, PI_LSARPC, NULL, "Query LSA security object", "" },
+       { "lsaquerytrustdominfo",RPC_RTYPE_NTSTATUS, cmd_lsa_query_trustdominfo, NULL, PI_LSARPC, NULL, "Query LSA trusted domains info (given a SID)", "" },
+       { "lsaquerytrustdominfobyname",RPC_RTYPE_NTSTATUS, cmd_lsa_query_trustdominfobyname, NULL, PI_LSARPC, NULL, "Query LSA trusted domains info (given a name), only works for Windows > 2k", "" },
+       { "lsaquerytrustdominfobysid",RPC_RTYPE_NTSTATUS, cmd_lsa_query_trustdominfobysid, NULL, PI_LSARPC, NULL, "Query LSA trusted domains info (given a SID)", "" },
 
        { NULL }
 };
index b55306ddc8805f8c9c5c7d3616756e3c57c6122b..153daa5cf2d51e3c8fa3fdb006a7c710dc5a982b 100644 (file)
@@ -22,7 +22,7 @@
 #include "includes.h"
 #include "rpcclient.h"
 
-static NTSTATUS cmd_netlogon_logon_ctrl2(struct cli_state *cli, 
+static NTSTATUS cmd_netlogon_logon_ctrl2(struct rpc_pipe_client *cli, 
                                          TALLOC_CTX *mem_ctx, int argc, 
                                          const char **argv)
 {
@@ -34,7 +34,7 @@ static NTSTATUS cmd_netlogon_logon_ctrl2(struct cli_state *cli,
                return NT_STATUS_OK;
        }
 
-       result = cli_netlogon_logon_ctrl2(cli, mem_ctx, query_level);
+       result = rpccli_netlogon_logon_ctrl2(cli, mem_ctx, query_level);
 
        if (!NT_STATUS_IS_OK(result))
                goto done;
@@ -45,7 +45,7 @@ static NTSTATUS cmd_netlogon_logon_ctrl2(struct cli_state *cli,
        return result;
 }
 
-static NTSTATUS cmd_netlogon_getdcname(struct cli_state *cli, 
+static NTSTATUS cmd_netlogon_getdcname(struct rpc_pipe_client *cli, 
                                       TALLOC_CTX *mem_ctx, int argc, 
                                       const char **argv)
 {
@@ -57,7 +57,7 @@ static NTSTATUS cmd_netlogon_getdcname(struct cli_state *cli,
                return NT_STATUS_OK;
        }
 
-       result = cli_netlogon_getdcname(cli, mem_ctx, argv[1], dcname);
+       result = rpccli_netlogon_getdcname(cli, mem_ctx, cli->cli->desthost, argv[1], dcname);
 
        if (!NT_STATUS_IS_OK(result))
                goto done;
@@ -70,7 +70,7 @@ static NTSTATUS cmd_netlogon_getdcname(struct cli_state *cli,
        return result;
 }
 
-static NTSTATUS cmd_netlogon_logon_ctrl(struct cli_state *cli, 
+static NTSTATUS cmd_netlogon_logon_ctrl(struct rpc_pipe_client *cli, 
                                         TALLOC_CTX *mem_ctx, int argc, 
                                         const char **argv)
 {
@@ -166,7 +166,7 @@ static void display_sam_sync(uint32 num_deltas, SAM_DELTA_HDR *hdr_deltas,
 
 /* Perform sam synchronisation */
 
-static NTSTATUS cmd_netlogon_sam_sync(struct cli_state *cli, 
+static NTSTATUS cmd_netlogon_sam_sync(struct rpc_pipe_client *cli, 
                                       TALLOC_CTX *mem_ctx, int argc,
                                       const char **argv)
 {
@@ -174,7 +174,6 @@ static NTSTATUS cmd_netlogon_sam_sync(struct cli_state *cli,
         uint32 database_id = 0, num_deltas;
         SAM_DELTA_HDR *hdr_deltas;
         SAM_DELTA_CTR *deltas;
-       DOM_CRED ret_creds;
 
         if (argc > 2) {
                 fprintf(stderr, "Usage: %s [database_id]\n", argv[0]);
@@ -184,12 +183,9 @@ static NTSTATUS cmd_netlogon_sam_sync(struct cli_state *cli,
         if (argc == 2)
                 database_id = atoi(argv[1]);
 
-       /* on first call the returnAuthenticator is empty */
-       memset(&ret_creds, 0, sizeof(ret_creds));
         /* Synchronise sam database */
 
-       result = cli_netlogon_sam_sync(cli, mem_ctx, &ret_creds, database_id,
+       result = rpccli_netlogon_sam_sync(cli, mem_ctx, database_id,
                                       0, &num_deltas, &hdr_deltas, &deltas);
 
        if (!NT_STATUS_IS_OK(result))
@@ -205,7 +201,7 @@ static NTSTATUS cmd_netlogon_sam_sync(struct cli_state *cli,
 
 /* Perform sam delta synchronisation */
 
-static NTSTATUS cmd_netlogon_sam_deltas(struct cli_state *cli, 
+static NTSTATUS cmd_netlogon_sam_deltas(struct rpc_pipe_client *cli, 
                                         TALLOC_CTX *mem_ctx, int argc,
                                         const char **argv)
 {
@@ -226,7 +222,7 @@ static NTSTATUS cmd_netlogon_sam_deltas(struct cli_state *cli,
         seqnum.low = tmp & 0xffff;
         seqnum.high = 0;
 
-       result = cli_netlogon_sam_deltas(cli, mem_ctx, database_id,
+       result = rpccli_netlogon_sam_deltas(cli, mem_ctx, database_id,
                                         seqnum, &num_deltas, 
                                         &hdr_deltas, &deltas);
 
@@ -243,7 +239,7 @@ static NTSTATUS cmd_netlogon_sam_deltas(struct cli_state *cli,
 
 /* Log on a domain user */
 
-static NTSTATUS cmd_netlogon_sam_logon(struct cli_state *cli, 
+static NTSTATUS cmd_netlogon_sam_logon(struct rpc_pipe_client *cli, 
                                        TALLOC_CTX *mem_ctx, int argc,
                                        const char **argv)
 {
@@ -252,7 +248,6 @@ static NTSTATUS cmd_netlogon_sam_logon(struct cli_state *cli,
         const char *username, *password;
        uint32 neg_flags = 0x000001ff;
        int auth_level = 2;
-       DOM_CRED ret_creds;
 
         /* Check arguments */
 
@@ -277,12 +272,8 @@ static NTSTATUS cmd_netlogon_sam_logon(struct cli_state *cli,
 
         /* Perform the sam logon */
 
-       ZERO_STRUCT(ret_creds);
+        result = rpccli_netlogon_sam_logon(cli, mem_ctx, lp_workgroup(), username, password, logon_type);
 
-        result = cli_netlogon_sam_logon(cli, mem_ctx, &ret_creds, username, password, logon_type);
-
-       clnt_deal_with_creds(cli->sess_key, &(cli->clnt_cred), &ret_creds);
-       
        if (!NT_STATUS_IS_OK(result))
                goto done;
 
@@ -292,12 +283,11 @@ static NTSTATUS cmd_netlogon_sam_logon(struct cli_state *cli,
 
 /* Change the trust account password */
 
-static NTSTATUS cmd_netlogon_change_trust_pw(struct cli_state *cli, 
+static NTSTATUS cmd_netlogon_change_trust_pw(struct rpc_pipe_client *cli, 
                                             TALLOC_CTX *mem_ctx, int argc,
                                             const char **argv)
 {
         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
-       DOM_CRED ret_creds;
 
         /* Check arguments */
 
@@ -308,13 +298,9 @@ static NTSTATUS cmd_netlogon_change_trust_pw(struct cli_state *cli,
 
         /* Perform the sam logon */
 
-       ZERO_STRUCT(ret_creds);
-
        result = trust_pw_find_change_and_store_it(cli, mem_ctx,
                                                   lp_workgroup());
 
-       clnt_deal_with_creds(cli->sess_key, &(cli->clnt_cred), &ret_creds);
-
        if (!NT_STATUS_IS_OK(result))
                goto done;
 
@@ -329,13 +315,13 @@ struct cmd_set netlogon_commands[] = {
 
        { "NETLOGON" },
 
-       { "logonctrl2", RPC_RTYPE_NTSTATUS, cmd_netlogon_logon_ctrl2, NULL, PI_NETLOGON, "Logon Control 2",     "" },
-       { "getdcname", RPC_RTYPE_NTSTATUS, cmd_netlogon_getdcname, NULL, PI_NETLOGON, "Get trusted DC name",     "" },
-       { "logonctrl",  RPC_RTYPE_NTSTATUS, cmd_netlogon_logon_ctrl,  NULL, PI_NETLOGON, "Logon Control",       "" },
-       { "samsync",    RPC_RTYPE_NTSTATUS, cmd_netlogon_sam_sync,    NULL, PI_NETLOGON, "Sam Synchronisation", "" },
-       { "samdeltas",  RPC_RTYPE_NTSTATUS, cmd_netlogon_sam_deltas,  NULL, PI_NETLOGON, "Query Sam Deltas",    "" },
-       { "samlogon",   RPC_RTYPE_NTSTATUS, cmd_netlogon_sam_logon,   NULL, PI_NETLOGON, "Sam Logon",           "" },
-       { "change_trust_pw",   RPC_RTYPE_NTSTATUS, cmd_netlogon_change_trust_pw,   NULL, PI_NETLOGON, "Change Trust Account Password",           "" },
+       { "logonctrl2", RPC_RTYPE_NTSTATUS, cmd_netlogon_logon_ctrl2, NULL, PI_NETLOGON, NULL, "Logon Control 2",     "" },
+       { "getdcname", RPC_RTYPE_NTSTATUS, cmd_netlogon_getdcname, NULL, PI_NETLOGON, NULL, "Get trusted DC name",     "" },
+       { "logonctrl",  RPC_RTYPE_NTSTATUS, cmd_netlogon_logon_ctrl,  NULL, PI_NETLOGON, NULL, "Logon Control",       "" },
+       { "samsync",    RPC_RTYPE_NTSTATUS, cmd_netlogon_sam_sync,    NULL, PI_NETLOGON, NULL, "Sam Synchronisation", "" },
+       { "samdeltas",  RPC_RTYPE_NTSTATUS, cmd_netlogon_sam_deltas,  NULL, PI_NETLOGON, NULL, "Query Sam Deltas",    "" },
+       { "samlogon",   RPC_RTYPE_NTSTATUS, cmd_netlogon_sam_logon,   NULL, PI_NETLOGON, NULL, "Sam Logon",           "" },
+       { "change_trust_pw",   RPC_RTYPE_NTSTATUS, cmd_netlogon_change_trust_pw,   NULL, PI_NETLOGON, NULL, "Change Trust Account Password",           "" },
 
        { NULL }
 };
index acb392710507b5c26293e8f03a132a9a8d3b2b41..a05c2c8a0b06d79b099faf9fc8eea5d6d9e6fa07 100644 (file)
@@ -300,14 +300,14 @@ static void display_sam_info_5(SAM_ENTRY5 *e5, SAM_STR5 *s5)
 /****************************************************************************
  Try samr_connect4 first, then samr_conenct if it fails
  ****************************************************************************/
-static NTSTATUS try_samr_connects(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
+static NTSTATUS try_samr_connects(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, 
                                  uint32 access_mask, POLICY_HND *connect_pol)
 {
        NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
        
-       result = cli_samr_connect4(cli, mem_ctx, access_mask, connect_pol);
+       result = rpccli_samr_connect4(cli, mem_ctx, access_mask, connect_pol);
        if (!NT_STATUS_IS_OK(result)) {
-               result = cli_samr_connect(cli, mem_ctx, access_mask,
+               result = rpccli_samr_connect(cli, mem_ctx, access_mask,
                                          connect_pol);
        }
        return result;
@@ -316,7 +316,7 @@ static NTSTATUS try_samr_connects(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 /**********************************************************************
  * Query user information 
  */
-static NTSTATUS cmd_samr_query_user(struct cli_state *cli, 
+static NTSTATUS cmd_samr_query_user(struct rpc_pipe_client *cli, 
                                     TALLOC_CTX *mem_ctx,
                                     int argc, const char **argv) 
 {
@@ -342,7 +342,7 @@ static NTSTATUS cmd_samr_query_user(struct cli_state *cli,
                sscanf(argv[3], "%x", &access_mask);
        
 
-       slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->desthost);
+       slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
        strupper_m(server);
        
        result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
@@ -351,14 +351,14 @@ static NTSTATUS cmd_samr_query_user(struct cli_state *cli,
        if (!NT_STATUS_IS_OK(result))
                goto done;
 
-       result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
+       result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
                                      MAXIMUM_ALLOWED_ACCESS,
                                      &domain_sid, &domain_pol);
 
        if (!NT_STATUS_IS_OK(result))
                goto done;
 
-       result = cli_samr_open_user(cli, mem_ctx, &domain_pol,
+       result = rpccli_samr_open_user(cli, mem_ctx, &domain_pol,
                                    access_mask,
                                    user_rid, &user_pol);
 
@@ -367,7 +367,7 @@ static NTSTATUS cmd_samr_query_user(struct cli_state *cli,
 
        ZERO_STRUCT(user_ctr);
 
-       result = cli_samr_query_userinfo(cli, mem_ctx, &user_pol, 
+       result = rpccli_samr_query_userinfo(cli, mem_ctx, &user_pol, 
                                         info_level, &user_ctr);
 
        if (!NT_STATUS_IS_OK(result))
@@ -385,6 +385,10 @@ static NTSTATUS cmd_samr_query_user(struct cli_state *cli,
                break;
        }
 
+       rpccli_samr_close(cli, mem_ctx, &user_pol);
+       rpccli_samr_close(cli, mem_ctx, &domain_pol);
+       rpccli_samr_close(cli, mem_ctx, &connect_pol);
+
 done:
        return result;
 }
@@ -435,7 +439,7 @@ static void display_group_info_ctr(GROUP_INFO_CTR *ctr)
 /***********************************************************************
  * Query group information 
  */
-static NTSTATUS cmd_samr_query_group(struct cli_state *cli, 
+static NTSTATUS cmd_samr_query_group(struct rpc_pipe_client *cli, 
                                      TALLOC_CTX *mem_ctx,
                                      int argc, const char **argv) 
 {
@@ -460,7 +464,7 @@ static NTSTATUS cmd_samr_query_group(struct cli_state *cli,
        if (argc > 3)
                sscanf(argv[3], "%x", &access_mask);
 
-       slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->desthost);
+       slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
        strupper_m(server);
 
        result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
@@ -469,21 +473,21 @@ static NTSTATUS cmd_samr_query_group(struct cli_state *cli,
        if (!NT_STATUS_IS_OK(result))
                goto done;
 
-       result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
+       result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
                                      MAXIMUM_ALLOWED_ACCESS,
                                      &domain_sid, &domain_pol);
 
        if (!NT_STATUS_IS_OK(result))
                goto done;
 
-       result = cli_samr_open_group(cli, mem_ctx, &domain_pol,
+       result = rpccli_samr_open_group(cli, mem_ctx, &domain_pol,
                                     access_mask,
                                     group_rid, &group_pol);
 
        if (!NT_STATUS_IS_OK(result))
                goto done;
 
-       result = cli_samr_query_groupinfo(cli, mem_ctx, &group_pol, 
+       result = rpccli_samr_query_groupinfo(cli, mem_ctx, &group_pol, 
                                          info_level, &group_ctr);
        if (!NT_STATUS_IS_OK(result)) {
                goto done;
@@ -491,13 +495,16 @@ static NTSTATUS cmd_samr_query_group(struct cli_state *cli,
 
        display_group_info_ctr(group_ctr);
 
+       rpccli_samr_close(cli, mem_ctx, &group_pol);
+       rpccli_samr_close(cli, mem_ctx, &domain_pol);
+       rpccli_samr_close(cli, mem_ctx, &connect_pol);
 done:
        return result;
 }
 
 /* Query groups a user is a member of */
 
-static NTSTATUS cmd_samr_query_usergroups(struct cli_state *cli, 
+static NTSTATUS cmd_samr_query_usergroups(struct rpc_pipe_client *cli, 
                                           TALLOC_CTX *mem_ctx,
                                           int argc, const char **argv) 
 {
@@ -522,7 +529,7 @@ static NTSTATUS cmd_samr_query_usergroups(struct cli_state *cli,
        if (argc > 2)
                sscanf(argv[2], "%x", &access_mask);
 
-       slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->desthost);
+       slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
        strupper_m(server);
                
        result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
@@ -531,21 +538,21 @@ static NTSTATUS cmd_samr_query_usergroups(struct cli_state *cli,
        if (!NT_STATUS_IS_OK(result))
                goto done;
 
-       result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
+       result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
                                      MAXIMUM_ALLOWED_ACCESS,
                                      &domain_sid, &domain_pol);
 
        if (!NT_STATUS_IS_OK(result))
                goto done;
 
-       result = cli_samr_open_user(cli, mem_ctx, &domain_pol,
+       result = rpccli_samr_open_user(cli, mem_ctx, &domain_pol,
                                    access_mask,
                                    user_rid, &user_pol);
 
        if (!NT_STATUS_IS_OK(result))
                goto done;
 
-       result = cli_samr_query_usergroups(cli, mem_ctx, &user_pol,
+       result = rpccli_samr_query_usergroups(cli, mem_ctx, &user_pol,
                                           &num_groups, &user_gids);
 
        if (!NT_STATUS_IS_OK(result))
@@ -556,13 +563,16 @@ static NTSTATUS cmd_samr_query_usergroups(struct cli_state *cli,
                       user_gids[i].g_rid, user_gids[i].attr);
        }
 
+       rpccli_samr_close(cli, mem_ctx, &user_pol);
+       rpccli_samr_close(cli, mem_ctx, &domain_pol);
+       rpccli_samr_close(cli, mem_ctx, &connect_pol);
  done:
        return result;
 }
 
 /* Query aliases a user is a member of */
 
-static NTSTATUS cmd_samr_query_useraliases(struct cli_state *cli, 
+static NTSTATUS cmd_samr_query_useraliases(struct rpc_pipe_client *cli, 
                                           TALLOC_CTX *mem_ctx,
                                           int argc, const char **argv) 
 {
@@ -602,7 +612,7 @@ static NTSTATUS cmd_samr_query_useraliases(struct cli_state *cli,
                sid2[i].num_auths = sid2[i].sid.num_auths;
        }
 
-       slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->desthost);
+       slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
        strupper_m(server);
                
        result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
@@ -612,11 +622,11 @@ static NTSTATUS cmd_samr_query_useraliases(struct cli_state *cli,
                goto done;
 
        if (StrCaseCmp(argv[1], "domain")==0)
-               result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
+               result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
                                              access_mask,
                                              &domain_sid, &domain_pol);
        else if (StrCaseCmp(argv[1], "builtin")==0)
-               result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
+               result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
                                              access_mask,
                                              &global_sid_Builtin,
                                              &domain_pol);
@@ -628,7 +638,7 @@ static NTSTATUS cmd_samr_query_useraliases(struct cli_state *cli,
        if (!NT_STATUS_IS_OK(result))
                goto done;
 
-       result = cli_samr_query_useraliases(cli, mem_ctx, &domain_pol,
+       result = rpccli_samr_query_useraliases(cli, mem_ctx, &domain_pol,
                                            num_sids, sid2,
                                            &num_aliases, &alias_rids);
 
@@ -639,13 +649,15 @@ static NTSTATUS cmd_samr_query_useraliases(struct cli_state *cli,
                printf("\tgroup rid:[0x%x]\n", alias_rids[i]);
        }
 
+       rpccli_samr_close(cli, mem_ctx, &domain_pol);
+       rpccli_samr_close(cli, mem_ctx, &connect_pol);
  done:
        return result;
 }
 
 /* Query members of a group */
 
-static NTSTATUS cmd_samr_query_groupmem(struct cli_state *cli, 
+static NTSTATUS cmd_samr_query_groupmem(struct rpc_pipe_client *cli, 
                                         TALLOC_CTX *mem_ctx,
                                         int argc, const char **argv) 
 {
@@ -666,7 +678,7 @@ static NTSTATUS cmd_samr_query_groupmem(struct cli_state *cli,
        if (argc > 2)
                sscanf(argv[2], "%x", &access_mask);
 
-       slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->desthost);
+       slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
        strupper_m(server);
 
        result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
@@ -675,21 +687,21 @@ static NTSTATUS cmd_samr_query_groupmem(struct cli_state *cli,
        if (!NT_STATUS_IS_OK(result))
                goto done;
 
-       result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
+       result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
                                      MAXIMUM_ALLOWED_ACCESS,
                                      &domain_sid, &domain_pol);
 
        if (!NT_STATUS_IS_OK(result))
                goto done;
 
-       result = cli_samr_open_group(cli, mem_ctx, &domain_pol,
+       result = rpccli_samr_open_group(cli, mem_ctx, &domain_pol,
                                     access_mask,
                                     group_rid, &group_pol);
 
        if (!NT_STATUS_IS_OK(result))
                goto done;
 
-       result = cli_samr_query_groupmem(cli, mem_ctx, &group_pol,
+       result = rpccli_samr_query_groupmem(cli, mem_ctx, &group_pol,
                                         &num_members, &group_rids,
                                         &group_attrs);
 
@@ -701,13 +713,16 @@ static NTSTATUS cmd_samr_query_groupmem(struct cli_state *cli,
                       group_attrs[i]);
        }
 
+       rpccli_samr_close(cli, mem_ctx, &group_pol);
+       rpccli_samr_close(cli, mem_ctx, &domain_pol);
+       rpccli_samr_close(cli, mem_ctx, &connect_pol);
  done:
        return result;
 }
 
 /* Enumerate domain users */
 
-static NTSTATUS cmd_samr_enum_dom_users(struct cli_state *cli, 
+static NTSTATUS cmd_samr_enum_dom_users(struct rpc_pipe_client *cli, 
                                        TALLOC_CTX *mem_ctx,
                                        int argc, const char **argv) 
 {
@@ -743,7 +758,7 @@ static NTSTATUS cmd_samr_enum_dom_users(struct cli_state *cli,
 
        /* Get domain policy handle */
 
-       result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
+       result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
                                      access_mask,
                                      &domain_sid, &domain_pol);
 
@@ -758,7 +773,7 @@ static NTSTATUS cmd_samr_enum_dom_users(struct cli_state *cli,
        size = 0xffff;
 
        do {
-               result = cli_samr_enum_dom_users(
+               result = rpccli_samr_enum_dom_users(
                        cli, mem_ctx, &domain_pol, &start_idx, acb_mask,
                        size, &dom_users, &dom_rids, &num_dom_users);
 
@@ -774,17 +789,17 @@ static NTSTATUS cmd_samr_enum_dom_users(struct cli_state *cli,
 
  done:
        if (got_domain_pol)
-               cli_samr_close(cli, mem_ctx, &domain_pol);
+               rpccli_samr_close(cli, mem_ctx, &domain_pol);
 
        if (got_connect_pol)
-               cli_samr_close(cli, mem_ctx, &connect_pol);
+               rpccli_samr_close(cli, mem_ctx, &connect_pol);
 
        return result;
 }
 
 /* Enumerate domain groups */
 
-static NTSTATUS cmd_samr_enum_dom_groups(struct cli_state *cli, 
+static NTSTATUS cmd_samr_enum_dom_groups(struct rpc_pipe_client *cli, 
                                          TALLOC_CTX *mem_ctx,
                                          int argc, const char **argv) 
 {
@@ -815,7 +830,7 @@ static NTSTATUS cmd_samr_enum_dom_groups(struct cli_state *cli,
 
        /* Get domain policy handle */
 
-       result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
+       result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
                                      access_mask,
                                      &domain_sid, &domain_pol);
 
@@ -830,7 +845,7 @@ static NTSTATUS cmd_samr_enum_dom_groups(struct cli_state *cli,
        size = 0xffff;
 
        do {
-               result = cli_samr_enum_dom_groups(
+               result = rpccli_samr_enum_dom_groups(
                        cli, mem_ctx, &domain_pol, &start_idx, size,
                        &dom_groups, &num_dom_groups);
 
@@ -847,17 +862,17 @@ static NTSTATUS cmd_samr_enum_dom_groups(struct cli_state *cli,
 
  done:
        if (got_domain_pol)
-               cli_samr_close(cli, mem_ctx, &domain_pol);
+               rpccli_samr_close(cli, mem_ctx, &domain_pol);
 
        if (got_connect_pol)
-               cli_samr_close(cli, mem_ctx, &connect_pol);
+               rpccli_samr_close(cli, mem_ctx, &connect_pol);
 
        return result;
 }
 
 /* Enumerate alias groups */
 
-static NTSTATUS cmd_samr_enum_als_groups(struct cli_state *cli, 
+static NTSTATUS cmd_samr_enum_als_groups(struct rpc_pipe_client *cli, 
                                          TALLOC_CTX *mem_ctx,
                                          int argc, const char **argv) 
 {
@@ -889,11 +904,11 @@ static NTSTATUS cmd_samr_enum_als_groups(struct cli_state *cli,
        /* Get domain policy handle */
 
        if (StrCaseCmp(argv[1], "domain")==0)
-               result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
+               result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
                                              access_mask,
                                              &domain_sid, &domain_pol);
        else if (StrCaseCmp(argv[1], "builtin")==0)
-               result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
+               result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
                                              access_mask,
                                              &global_sid_Builtin, &domain_pol);
        else
@@ -910,7 +925,7 @@ static NTSTATUS cmd_samr_enum_als_groups(struct cli_state *cli,
        size = 0xffff;          /* Number of groups to retrieve */
 
        do {
-               result = cli_samr_enum_als_groups(
+               result = rpccli_samr_enum_als_groups(
                        cli, mem_ctx, &domain_pol, &start_idx, size,
                        &als_groups, &num_als_groups);
 
@@ -926,17 +941,17 @@ static NTSTATUS cmd_samr_enum_als_groups(struct cli_state *cli,
 
  done:
        if (got_domain_pol)
-               cli_samr_close(cli, mem_ctx, &domain_pol);
+               rpccli_samr_close(cli, mem_ctx, &domain_pol);
        
        if (got_connect_pol)
-               cli_samr_close(cli, mem_ctx, &connect_pol);
+               rpccli_samr_close(cli, mem_ctx, &connect_pol);
        
        return result;
 }
 
 /* Query alias membership */
 
-static NTSTATUS cmd_samr_query_aliasmem(struct cli_state *cli, 
+static NTSTATUS cmd_samr_query_aliasmem(struct rpc_pipe_client *cli, 
                                         TALLOC_CTX *mem_ctx,
                                         int argc, const char **argv) 
 {
@@ -967,11 +982,11 @@ static NTSTATUS cmd_samr_query_aliasmem(struct cli_state *cli,
        /* Open handle on domain */
        
        if (StrCaseCmp(argv[1], "domain")==0)
-               result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
+               result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
                                              MAXIMUM_ALLOWED_ACCESS,
                                              &domain_sid, &domain_pol);
        else if (StrCaseCmp(argv[1], "builtin")==0)
-               result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
+               result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
                                              MAXIMUM_ALLOWED_ACCESS,
                                              &global_sid_Builtin, &domain_pol);
        else
@@ -982,13 +997,13 @@ static NTSTATUS cmd_samr_query_aliasmem(struct cli_state *cli,
 
        /* Open handle on alias */
 
-       result = cli_samr_open_alias(cli, mem_ctx, &domain_pol,
+       result = rpccli_samr_open_alias(cli, mem_ctx, &domain_pol,
                                     access_mask,
                                     alias_rid, &alias_pol);
        if (!NT_STATUS_IS_OK(result))
                goto done;
 
-       result = cli_samr_query_aliasmem(cli, mem_ctx, &alias_pol,
+       result = rpccli_samr_query_aliasmem(cli, mem_ctx, &alias_pol,
                                         &num_members, &alias_sids);
 
        if (!NT_STATUS_IS_OK(result))
@@ -1001,13 +1016,16 @@ static NTSTATUS cmd_samr_query_aliasmem(struct cli_state *cli,
                printf("\tsid:[%s]\n", sid_str);
        }
 
+       rpccli_samr_close(cli, mem_ctx, &alias_pol);
+       rpccli_samr_close(cli, mem_ctx, &domain_pol);
+       rpccli_samr_close(cli, mem_ctx, &connect_pol);
  done:
        return result;
 }
 
 /* Query display info */
 
-static NTSTATUS cmd_samr_query_dispinfo(struct cli_state *cli, 
+static NTSTATUS cmd_samr_query_dispinfo(struct rpc_pipe_client *cli, 
                                         TALLOC_CTX *mem_ctx,
                                         int argc, const char **argv) 
 {
@@ -1059,7 +1077,7 @@ static NTSTATUS cmd_samr_query_dispinfo(struct cli_state *cli,
 
        /* Get domain policy handle */
 
-       result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
+       result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
                                      access_mask, 
                                      &domain_sid, &domain_pol);
 
@@ -1101,7 +1119,7 @@ static NTSTATUS cmd_samr_query_dispinfo(struct cli_state *cli,
                        get_query_dispinfo_params(
                                loop_count, &max_entries, &max_size);
                
-               result = cli_samr_query_dispinfo(cli, mem_ctx, &domain_pol,
+               result = rpccli_samr_query_dispinfo(cli, mem_ctx, &domain_pol,
                                                 &start_idx, info_level,
                                                 &num_entries, max_entries, 
                                                 max_size, &ctr);
@@ -1135,13 +1153,15 @@ static NTSTATUS cmd_samr_query_dispinfo(struct cli_state *cli,
                }
        } while ( NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
 
+       rpccli_samr_close(cli, mem_ctx, &domain_pol);
+       rpccli_samr_close(cli, mem_ctx, &connect_pol);
  done:
        return result;
 }
 
 /* Query domain info */
 
-static NTSTATUS cmd_samr_query_dominfo(struct cli_state *cli, 
+static NTSTATUS cmd_samr_query_dominfo(struct rpc_pipe_client *cli, 
                                        TALLOC_CTX *mem_ctx,
                                        int argc, const char **argv) 
 {
@@ -1172,7 +1192,7 @@ static NTSTATUS cmd_samr_query_dominfo(struct cli_state *cli,
 
        /* Get domain policy handle */
 
-       result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
+       result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
                                      access_mask,
                                      &domain_sid, &domain_pol);
 
@@ -1181,7 +1201,7 @@ static NTSTATUS cmd_samr_query_dominfo(struct cli_state *cli,
 
        /* Query domain info */
 
-       result = cli_samr_query_dom_info(cli, mem_ctx, &domain_pol,
+       result = rpccli_samr_query_dom_info(cli, mem_ctx, &domain_pol,
                                         switch_level, &ctr);
 
        if (!NT_STATUS_IS_OK(result))
@@ -1213,14 +1233,14 @@ static NTSTATUS cmd_samr_query_dominfo(struct cli_state *cli,
 
  done:
  
-       cli_samr_close(cli, mem_ctx, &domain_pol);
-       cli_samr_close(cli, mem_ctx, &connect_pol);
+       rpccli_samr_close(cli, mem_ctx, &domain_pol);
+       rpccli_samr_close(cli, mem_ctx, &connect_pol);
        return result;
 }
 
 /* Create domain user */
 
-static NTSTATUS cmd_samr_create_dom_user(struct cli_state *cli, 
+static NTSTATUS cmd_samr_create_dom_user(struct rpc_pipe_client *cli, 
                                          TALLOC_CTX *mem_ctx,
                                          int argc, const char **argv) 
 {
@@ -1251,7 +1271,7 @@ static NTSTATUS cmd_samr_create_dom_user(struct cli_state *cli,
 
        /* Get domain policy handle */
 
-       result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
+       result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
                                      access_mask,
                                      &domain_sid, &domain_pol);
 
@@ -1263,20 +1283,20 @@ static NTSTATUS cmd_samr_create_dom_user(struct cli_state *cli,
        acb_info = ACB_NORMAL;
        unknown = 0xe005000b; /* No idea what this is - a permission mask? */
 
-       result = cli_samr_create_dom_user(cli, mem_ctx, &domain_pol,
+       result = rpccli_samr_create_dom_user(cli, mem_ctx, &domain_pol,
                                          acct_name, acb_info, unknown,
                                          &user_pol, &user_rid);
 
        if (!NT_STATUS_IS_OK(result))
                goto done;
 
-       result = cli_samr_close(cli, mem_ctx, &user_pol);
+       result = rpccli_samr_close(cli, mem_ctx, &user_pol);
        if (!NT_STATUS_IS_OK(result)) goto done;
 
-       result = cli_samr_close(cli, mem_ctx, &domain_pol);
+       result = rpccli_samr_close(cli, mem_ctx, &domain_pol);
        if (!NT_STATUS_IS_OK(result)) goto done;
 
-       result = cli_samr_close(cli, mem_ctx, &connect_pol);
+       result = rpccli_samr_close(cli, mem_ctx, &connect_pol);
        if (!NT_STATUS_IS_OK(result)) goto done;
 
  done:
@@ -1285,7 +1305,7 @@ static NTSTATUS cmd_samr_create_dom_user(struct cli_state *cli,
 
 /* Create domain group */
 
-static NTSTATUS cmd_samr_create_dom_group(struct cli_state *cli, 
+static NTSTATUS cmd_samr_create_dom_group(struct rpc_pipe_client *cli, 
                                           TALLOC_CTX *mem_ctx,
                                           int argc, const char **argv) 
 {
@@ -1314,7 +1334,7 @@ static NTSTATUS cmd_samr_create_dom_group(struct cli_state *cli,
 
        /* Get domain policy handle */
 
-       result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
+       result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
                                      access_mask,
                                      &domain_sid, &domain_pol);
 
@@ -1323,20 +1343,20 @@ static NTSTATUS cmd_samr_create_dom_group(struct cli_state *cli,
 
        /* Create domain user */
 
-       result = cli_samr_create_dom_group(cli, mem_ctx, &domain_pol,
+       result = rpccli_samr_create_dom_group(cli, mem_ctx, &domain_pol,
                                           grp_name, MAXIMUM_ALLOWED_ACCESS,
                                           &group_pol);
 
        if (!NT_STATUS_IS_OK(result))
                goto done;
 
-       result = cli_samr_close(cli, mem_ctx, &group_pol);
+       result = rpccli_samr_close(cli, mem_ctx, &group_pol);
        if (!NT_STATUS_IS_OK(result)) goto done;
 
-       result = cli_samr_close(cli, mem_ctx, &domain_pol);
+       result = rpccli_samr_close(cli, mem_ctx, &domain_pol);
        if (!NT_STATUS_IS_OK(result)) goto done;
 
-       result = cli_samr_close(cli, mem_ctx, &connect_pol);
+       result = rpccli_samr_close(cli, mem_ctx, &connect_pol);
        if (!NT_STATUS_IS_OK(result)) goto done;
 
  done:
@@ -1345,7 +1365,7 @@ static NTSTATUS cmd_samr_create_dom_group(struct cli_state *cli,
 
 /* Lookup sam names */
 
-static NTSTATUS cmd_samr_lookup_names(struct cli_state *cli, 
+static NTSTATUS cmd_samr_lookup_names(struct rpc_pipe_client *cli, 
                                       TALLOC_CTX *mem_ctx,
                                       int argc, const char **argv) 
 {
@@ -1372,11 +1392,11 @@ static NTSTATUS cmd_samr_lookup_names(struct cli_state *cli,
                goto done;
 
        if (StrCaseCmp(argv[1], "domain")==0)
-               result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
+               result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
                                              MAXIMUM_ALLOWED_ACCESS,
                                              &domain_sid, &domain_pol);
        else if (StrCaseCmp(argv[1], "builtin")==0)
-               result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
+               result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
                                              MAXIMUM_ALLOWED_ACCESS,
                                              &global_sid_Builtin, &domain_pol);
        else
@@ -1393,7 +1413,7 @@ static NTSTATUS cmd_samr_lookup_names(struct cli_state *cli,
        for (i = 0; i < argc - 2; i++)
                names[i] = argv[i + 2];
 
-       result = cli_samr_lookup_names(cli, mem_ctx, &domain_pol,
+       result = rpccli_samr_lookup_names(cli, mem_ctx, &domain_pol,
                                       flags, num_names, names,
                                       &num_rids, &rids, &name_types);
 
@@ -1406,13 +1426,15 @@ static NTSTATUS cmd_samr_lookup_names(struct cli_state *cli,
                printf("name %s: 0x%x (%d)\n", names[i], rids[i], 
                       name_types[i]);
 
+       rpccli_samr_close(cli, mem_ctx, &domain_pol);
+       rpccli_samr_close(cli, mem_ctx, &connect_pol);
  done:
        return result;
 }
 
 /* Lookup sam rids */
 
-static NTSTATUS cmd_samr_lookup_rids(struct cli_state *cli, 
+static NTSTATUS cmd_samr_lookup_rids(struct rpc_pipe_client *cli, 
                                      TALLOC_CTX *mem_ctx,
                                      int argc, const char **argv) 
 {
@@ -1435,7 +1457,7 @@ static NTSTATUS cmd_samr_lookup_rids(struct cli_state *cli,
        if (!NT_STATUS_IS_OK(result))
                goto done;
 
-       result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
+       result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
                                      MAXIMUM_ALLOWED_ACCESS,
                                      &domain_sid, &domain_pol);
 
@@ -1450,7 +1472,7 @@ static NTSTATUS cmd_samr_lookup_rids(struct cli_state *cli,
        for (i = 0; i < argc - 1; i++)
                 sscanf(argv[i + 1], "%i", &rids[i]);
 
-       result = cli_samr_lookup_rids(cli, mem_ctx, &domain_pol, num_rids, rids,
+       result = rpccli_samr_lookup_rids(cli, mem_ctx, &domain_pol, num_rids, rids,
                                      &num_names, &names, &name_types);
 
        if (!NT_STATUS_IS_OK(result) &&
@@ -1462,13 +1484,15 @@ static NTSTATUS cmd_samr_lookup_rids(struct cli_state *cli,
        for (i = 0; i < num_names; i++)
                printf("rid 0x%x: %s (%d)\n", rids[i], names[i], name_types[i]);
 
+       rpccli_samr_close(cli, mem_ctx, &domain_pol);
+       rpccli_samr_close(cli, mem_ctx, &connect_pol);
  done:
        return result;
 }
 
 /* Delete domain user */
 
-static NTSTATUS cmd_samr_delete_dom_user(struct cli_state *cli, 
+static NTSTATUS cmd_samr_delete_dom_user(struct rpc_pipe_client *cli, 
                                          TALLOC_CTX *mem_ctx,
                                          int argc, const char **argv) 
 {
@@ -1492,7 +1516,7 @@ static NTSTATUS cmd_samr_delete_dom_user(struct cli_state *cli,
        if (!NT_STATUS_IS_OK(result))
                goto done;
 
-       result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
+       result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
                                      MAXIMUM_ALLOWED_ACCESS,
                                      &domain_sid, &domain_pol);
 
@@ -1505,7 +1529,7 @@ static NTSTATUS cmd_samr_delete_dom_user(struct cli_state *cli,
                uint32 *user_rids, num_rids, *name_types;
                uint32 flags = 0x000003e8; /* Unknown */
 
-               result = cli_samr_lookup_names(cli, mem_ctx, &domain_pol,
+               result = rpccli_samr_lookup_names(cli, mem_ctx, &domain_pol,
                                               flags, 1, (const char **)&argv[1],
                                               &num_rids, &user_rids,
                                               &name_types);
@@ -1513,7 +1537,7 @@ static NTSTATUS cmd_samr_delete_dom_user(struct cli_state *cli,
                if (!NT_STATUS_IS_OK(result))
                        goto done;
 
-               result = cli_samr_open_user(cli, mem_ctx, &domain_pol,
+               result = rpccli_samr_open_user(cli, mem_ctx, &domain_pol,
                                            access_mask,
                                            user_rids[0], &user_pol);
 
@@ -1523,13 +1547,17 @@ static NTSTATUS cmd_samr_delete_dom_user(struct cli_state *cli,
 
        /* Delete user */
 
-       result = cli_samr_delete_dom_user(cli, mem_ctx, &user_pol);
+       result = rpccli_samr_delete_dom_user(cli, mem_ctx, &user_pol);
 
        if (!NT_STATUS_IS_OK(result))
                goto done;
 
        /* Display results */
 
+       rpccli_samr_close(cli, mem_ctx, &user_pol);
+       rpccli_samr_close(cli, mem_ctx, &domain_pol);
+       rpccli_samr_close(cli, mem_ctx, &connect_pol);
+
  done:
        return result;
 }
@@ -1537,7 +1565,7 @@ static NTSTATUS cmd_samr_delete_dom_user(struct cli_state *cli,
 /**********************************************************************
  * Query user security object 
  */
-static NTSTATUS cmd_samr_query_sec_obj(struct cli_state *cli, 
+static NTSTATUS cmd_samr_query_sec_obj(struct rpc_pipe_client *cli, 
                                     TALLOC_CTX *mem_ctx,
                                     int argc, const char **argv) 
 {
@@ -1565,7 +1593,7 @@ static NTSTATUS cmd_samr_query_sec_obj(struct cli_state *cli,
                        sscanf(argv[1], "%i", &user_rid);
        }
        
-       slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->desthost);
+       slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost);
        strupper_m(server);
        result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
                                   &connect_pol);
@@ -1574,7 +1602,7 @@ static NTSTATUS cmd_samr_query_sec_obj(struct cli_state *cli,
                goto done;
 
        if (domain || user_rid)
-               result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
+               result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
                                              MAXIMUM_ALLOWED_ACCESS,
                                              &domain_sid, &domain_pol);
 
@@ -1582,7 +1610,7 @@ static NTSTATUS cmd_samr_query_sec_obj(struct cli_state *cli,
                goto done;
 
        if (user_rid)
-               result = cli_samr_open_user(cli, mem_ctx, &domain_pol,
+               result = rpccli_samr_open_user(cli, mem_ctx, &domain_pol,
                                            MAXIMUM_ALLOWED_ACCESS,
                                            user_rid, &user_pol);
 
@@ -1601,7 +1629,7 @@ static NTSTATUS cmd_samr_query_sec_obj(struct cli_state *cli,
 
        /* Query SAM security object */
 
-       result = cli_samr_query_sec_obj(cli, mem_ctx, pol, info_level, ctx, 
+       result = rpccli_samr_query_sec_obj(cli, mem_ctx, pol, info_level, ctx, 
                                        &sec_desc_buf);
 
        if (!NT_STATUS_IS_OK(result))
@@ -1609,12 +1637,15 @@ static NTSTATUS cmd_samr_query_sec_obj(struct cli_state *cli,
 
        display_sec_desc(sec_desc_buf->sec);
        
+       rpccli_samr_close(cli, mem_ctx, &user_pol);
+       rpccli_samr_close(cli, mem_ctx, &domain_pol);
+       rpccli_samr_close(cli, mem_ctx, &connect_pol);
 done:
        talloc_destroy(ctx);
        return result;
 }
 
-static NTSTATUS cmd_samr_get_dom_pwinfo(struct cli_state *cli, 
+static NTSTATUS cmd_samr_get_dom_pwinfo(struct rpc_pipe_client *cli, 
                                        TALLOC_CTX *mem_ctx,
                                        int argc, const char **argv) 
 {
@@ -1626,7 +1657,7 @@ static NTSTATUS cmd_samr_get_dom_pwinfo(struct cli_state *cli,
                return NT_STATUS_OK;
        }
 
-       result = cli_samr_get_dom_pwinfo(cli, mem_ctx, &unk_0, &unk_1) ;
+       result = rpccli_samr_get_dom_pwinfo(cli, mem_ctx, &unk_0, &unk_1) ;
        
        if (NT_STATUS_IS_OK(result)) {
                printf("unk_0 = 0x%08x\n", unk_0);
@@ -1638,7 +1669,7 @@ static NTSTATUS cmd_samr_get_dom_pwinfo(struct cli_state *cli,
 
 /* Look up domain name */
 
-static NTSTATUS cmd_samr_lookup_domain(struct cli_state *cli, 
+static NTSTATUS cmd_samr_lookup_domain(struct rpc_pipe_client *cli, 
                                       TALLOC_CTX *mem_ctx,
                                       int argc, const char **argv) 
 {
@@ -1660,13 +1691,13 @@ static NTSTATUS cmd_samr_lookup_domain(struct cli_state *cli,
        if (!NT_STATUS_IS_OK(result))
                goto done;
 
-       result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
+       result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
                                      access_mask, &domain_sid, &domain_pol);
 
        if (!NT_STATUS_IS_OK(result))
                goto done;
        
-       result = cli_samr_lookup_domain(
+       result = rpccli_samr_lookup_domain(
                cli, mem_ctx, &connect_pol, domain_name, &sid);
 
        sid_to_string(sid_string,&sid);
@@ -1675,6 +1706,8 @@ static NTSTATUS cmd_samr_lookup_domain(struct cli_state *cli,
                printf("SAMR_LOOKUP_DOMAIN: Domain Name: %s Domain SID: %s\n",
                       domain_name,sid_string);
 
+       rpccli_samr_close(cli, mem_ctx, &domain_pol);
+       rpccli_samr_close(cli, mem_ctx, &connect_pol);
 done:
        return result;
 }
@@ -1686,26 +1719,26 @@ struct cmd_set samr_commands[] = {
 
        { "SAMR" },
 
-       { "queryuser",  RPC_RTYPE_NTSTATUS, cmd_samr_query_user,                NULL, PI_SAMR,  "Query user info",         "" },
-       { "querygroup",         RPC_RTYPE_NTSTATUS, cmd_samr_query_group,               NULL, PI_SAMR,  "Query group info",        "" },
-       { "queryusergroups",    RPC_RTYPE_NTSTATUS, cmd_samr_query_usergroups,  NULL, PI_SAMR,  "Query user groups",       "" },
-       { "queryuseraliases",   RPC_RTYPE_NTSTATUS, cmd_samr_query_useraliases,         NULL, PI_SAMR,  "Query user aliases",      "" },
-       { "querygroupmem",      RPC_RTYPE_NTSTATUS, cmd_samr_query_groupmem,    NULL, PI_SAMR,  "Query group membership",  "" },
-       { "queryaliasmem",      RPC_RTYPE_NTSTATUS, cmd_samr_query_aliasmem,    NULL, PI_SAMR,  "Query alias membership",  "" },
-       { "querydispinfo",      RPC_RTYPE_NTSTATUS, cmd_samr_query_dispinfo,    NULL, PI_SAMR,  "Query display info",      "" },
-       { "querydominfo",       RPC_RTYPE_NTSTATUS, cmd_samr_query_dominfo,     NULL, PI_SAMR,  "Query domain info",       "" },
-       { "enumdomusers",      RPC_RTYPE_NTSTATUS, cmd_samr_enum_dom_users,       NULL, PI_SAMR,        "Enumerate domain users", "" },
-       { "enumdomgroups",      RPC_RTYPE_NTSTATUS, cmd_samr_enum_dom_groups,       NULL, PI_SAMR,      "Enumerate domain groups", "" },
-       { "enumalsgroups",      RPC_RTYPE_NTSTATUS, cmd_samr_enum_als_groups,       NULL, PI_SAMR,      "Enumerate alias groups",  "" },
-
-       { "createdomuser",      RPC_RTYPE_NTSTATUS, cmd_samr_create_dom_user,       NULL, PI_SAMR,      "Create domain user",      "" },
-       { "createdomgroup",     RPC_RTYPE_NTSTATUS, cmd_samr_create_dom_group,      NULL, PI_SAMR,      "Create domain group",     "" },
-       { "samlookupnames",     RPC_RTYPE_NTSTATUS, cmd_samr_lookup_names,          NULL, PI_SAMR,      "Look up names",           "" },
-       { "samlookuprids",      RPC_RTYPE_NTSTATUS, cmd_samr_lookup_rids,           NULL, PI_SAMR,      "Look up names",           "" },
-       { "deletedomuser",      RPC_RTYPE_NTSTATUS, cmd_samr_delete_dom_user,       NULL, PI_SAMR,      "Delete domain user",      "" },
-       { "samquerysecobj",     RPC_RTYPE_NTSTATUS, cmd_samr_query_sec_obj,         NULL, PI_SAMR, "Query SAMR security object",   "" },
-       { "getdompwinfo",       RPC_RTYPE_NTSTATUS, cmd_samr_get_dom_pwinfo,        NULL, PI_SAMR, "Retrieve domain password info", "" },
-
-       { "lookupdomain",       RPC_RTYPE_NTSTATUS, cmd_samr_lookup_domain,         NULL, PI_SAMR, "Lookup Domain Name", "" },
+       { "queryuser",  RPC_RTYPE_NTSTATUS, cmd_samr_query_user,                NULL, PI_SAMR, NULL,    "Query user info",         "" },
+       { "querygroup",         RPC_RTYPE_NTSTATUS, cmd_samr_query_group,               NULL, PI_SAMR, NULL,    "Query group info",        "" },
+       { "queryusergroups",    RPC_RTYPE_NTSTATUS, cmd_samr_query_usergroups,  NULL, PI_SAMR, NULL,    "Query user groups",       "" },
+       { "queryuseraliases",   RPC_RTYPE_NTSTATUS, cmd_samr_query_useraliases,         NULL, PI_SAMR, NULL,    "Query user aliases",      "" },
+       { "querygroupmem",      RPC_RTYPE_NTSTATUS, cmd_samr_query_groupmem,    NULL, PI_SAMR, NULL,    "Query group membership",  "" },
+       { "queryaliasmem",      RPC_RTYPE_NTSTATUS, cmd_samr_query_aliasmem,    NULL, PI_SAMR, NULL,    "Query alias membership",  "" },
+       { "querydispinfo",      RPC_RTYPE_NTSTATUS, cmd_samr_query_dispinfo,    NULL, PI_SAMR, NULL,    "Query display info",      "" },
+       { "querydominfo",       RPC_RTYPE_NTSTATUS, cmd_samr_query_dominfo,     NULL, PI_SAMR, NULL,    "Query domain info",       "" },
+       { "enumdomusers",      RPC_RTYPE_NTSTATUS, cmd_samr_enum_dom_users,       NULL, PI_SAMR, NULL,  "Enumerate domain users", "" },
+       { "enumdomgroups",      RPC_RTYPE_NTSTATUS, cmd_samr_enum_dom_groups,       NULL, PI_SAMR, NULL,        "Enumerate domain groups", "" },
+       { "enumalsgroups",      RPC_RTYPE_NTSTATUS, cmd_samr_enum_als_groups,       NULL, PI_SAMR, NULL,        "Enumerate alias groups",  "" },
+
+       { "createdomuser",      RPC_RTYPE_NTSTATUS, cmd_samr_create_dom_user,       NULL, PI_SAMR, NULL,        "Create domain user",      "" },
+       { "createdomgroup",     RPC_RTYPE_NTSTATUS, cmd_samr_create_dom_group,      NULL, PI_SAMR, NULL,        "Create domain group",     "" },
+       { "samlookupnames",     RPC_RTYPE_NTSTATUS, cmd_samr_lookup_names,          NULL, PI_SAMR, NULL,        "Look up names",           "" },
+       { "samlookuprids",      RPC_RTYPE_NTSTATUS, cmd_samr_lookup_rids,           NULL, PI_SAMR, NULL,        "Look up names",           "" },
+       { "deletedomuser",      RPC_RTYPE_NTSTATUS, cmd_samr_delete_dom_user,       NULL, PI_SAMR, NULL,        "Delete domain user",      "" },
+       { "samquerysecobj",     RPC_RTYPE_NTSTATUS, cmd_samr_query_sec_obj,         NULL, PI_SAMR, NULL, "Query SAMR security object",   "" },
+       { "getdompwinfo",       RPC_RTYPE_NTSTATUS, cmd_samr_get_dom_pwinfo,        NULL, PI_SAMR, NULL, "Retrieve domain password info", "" },
+
+       { "lookupdomain",       RPC_RTYPE_NTSTATUS, cmd_samr_lookup_domain,         NULL, PI_SAMR, NULL, "Lookup Domain Name", "" },
        { NULL }
 };
index 1b3d3b7e0c41af782d1816399df9acc1c02db892..0ae16e8f1ae2d9b42110af5d78dc2013dbee8e5d 100644 (file)
@@ -93,7 +93,7 @@ static const char *cmd_spoolss_get_short_archi(const char *long_archi)
 /****************************************************************************
 ****************************************************************************/
 
-static WERROR cmd_spoolss_open_printer_ex(struct cli_state *cli, 
+static WERROR cmd_spoolss_open_printer_ex(struct rpc_pipe_client *cli, 
                                             TALLOC_CTX *mem_ctx,
                                             int argc, const char **argv)
 {
@@ -110,20 +110,20 @@ static WERROR cmd_spoolss_open_printer_ex(struct cli_state *cli,
        if (!cli)
             return WERR_GENERAL_FAILURE;
 
-       slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
+       slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
        strupper_m(servername);
        fstrcpy(user, cli->user_name);
        fstrcpy(printername, argv[1]);
 
        /* Open the printer handle */
 
-       werror = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, 
+       werror = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, 
                                             "", PRINTER_ALL_ACCESS, 
                                             servername, user, &hnd);
 
        if (W_ERROR_IS_OK(werror)) {
                printf("Printer %s opened successfully\n", printername);
-               werror = cli_spoolss_close_printer(cli, mem_ctx, &hnd);
+               werror = rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
 
                if (!W_ERROR_IS_OK(werror)) {
                        printf("Error closing printer handle! (%s)\n", 
@@ -298,7 +298,7 @@ static void display_print_info_7(PRINTER_INFO_7 *i7)
 /****************************************************************************
 ****************************************************************************/
 
-static WERROR cmd_spoolss_enum_printers(struct cli_state *cli, 
+static WERROR cmd_spoolss_enum_printers(struct rpc_pipe_client *cli, 
                                           TALLOC_CTX *mem_ctx,
                                           int argc, const char **argv)
 {
@@ -320,13 +320,13 @@ static WERROR cmd_spoolss_enum_printers(struct cli_state *cli,
        if (argc == 3)
                fstrcpy(name, argv[2]);
        else {
-               slprintf(name, sizeof(name)-1, "\\\\%s", cli->desthost);
+               slprintf(name, sizeof(name)-1, "\\\\%s", cli->cli->desthost);
                strupper_m(name);
        }
 
        ZERO_STRUCT(ctr);
 
-       result = cli_spoolss_enum_printers(cli, mem_ctx, name, PRINTER_ENUM_LOCAL, 
+       result = rpccli_spoolss_enum_printers(cli, mem_ctx, name, PRINTER_ENUM_LOCAL, 
                info_level, &num_printers, &ctr);
 
        if (W_ERROR_IS_OK(result)) {
@@ -419,7 +419,7 @@ static void display_port_info_2(PORT_INFO_2 *i2)
 /****************************************************************************
 ****************************************************************************/
 
-static WERROR cmd_spoolss_enum_ports(struct cli_state *cli, 
+static WERROR cmd_spoolss_enum_ports(struct rpc_pipe_client *cli, 
                                       TALLOC_CTX *mem_ctx, int argc, 
                                       const char **argv)
 {
@@ -440,7 +440,7 @@ static WERROR cmd_spoolss_enum_ports(struct cli_state *cli,
 
        ZERO_STRUCT(ctr);
 
-       result = cli_spoolss_enum_ports(cli, mem_ctx, info_level, &returned, &ctr);
+       result = rpccli_spoolss_enum_ports(cli, mem_ctx, info_level, &returned, &ctr);
 
        if (W_ERROR_IS_OK(result)) {
                int i;
@@ -466,7 +466,7 @@ static WERROR cmd_spoolss_enum_ports(struct cli_state *cli,
 /****************************************************************************
 ****************************************************************************/
 
-static WERROR cmd_spoolss_setprinter(struct cli_state *cli,
+static WERROR cmd_spoolss_setprinter(struct rpc_pipe_client *cli,
                                        TALLOC_CTX *mem_ctx,
                                        int argc, const char **argv)
 {
@@ -491,13 +491,13 @@ static WERROR cmd_spoolss_setprinter(struct cli_state *cli,
                fstrcpy(comment, argv[2]);
        }
 
-       slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
+       slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
        strupper_m(servername);
        slprintf(printername, sizeof(servername)-1, "%s\\%s", servername, argv[1]);
        fstrcpy(user, cli->user_name);
 
        /* get a printer handle */
-       result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, "", 
+       result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "", 
                                PRINTER_ALL_ACCESS, servername,
                                user, &pol);
                                
@@ -507,7 +507,7 @@ static WERROR cmd_spoolss_setprinter(struct cli_state *cli,
        opened_hnd = True;
 
        /* Get printer info */
-        result = cli_spoolss_getprinter(cli, mem_ctx, &pol, info_level, &ctr);
+        result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, info_level, &ctr);
 
         if (!W_ERROR_IS_OK(result))
                 goto done;
@@ -518,13 +518,13 @@ static WERROR cmd_spoolss_setprinter(struct cli_state *cli,
        ctr.printers_2->devmode = NULL;
        ctr.printers_2->secdesc = NULL;
 
-       result = cli_spoolss_setprinter(cli, mem_ctx, &pol, info_level, &ctr, 0);
+       result = rpccli_spoolss_setprinter(cli, mem_ctx, &pol, info_level, &ctr, 0);
        if (W_ERROR_IS_OK(result))
                printf("Success in setting comment.\n");
 
  done:
        if (opened_hnd)
-               cli_spoolss_close_printer(cli, mem_ctx, &pol);
+               rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
 
        return result;
 }
@@ -532,7 +532,7 @@ static WERROR cmd_spoolss_setprinter(struct cli_state *cli,
 /****************************************************************************
 ****************************************************************************/
 
-static WERROR cmd_spoolss_setprintername(struct cli_state *cli,
+static WERROR cmd_spoolss_setprintername(struct rpc_pipe_client *cli,
                                        TALLOC_CTX *mem_ctx,
                                        int argc, const char **argv)
 {
@@ -557,13 +557,13 @@ static WERROR cmd_spoolss_setprintername(struct cli_state *cli,
                fstrcpy(new_printername, argv[2]);
        }
 
-       slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
+       slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
        strupper_m(servername);
        slprintf(printername, sizeof(printername)-1, "%s\\%s", servername, argv[1]);
        fstrcpy(user, cli->user_name);
 
        /* get a printer handle */
-       result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, "", 
+       result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "", 
                                PRINTER_ALL_ACCESS, servername,
                                user, &pol);
                                
@@ -573,7 +573,7 @@ static WERROR cmd_spoolss_setprintername(struct cli_state *cli,
        opened_hnd = True;
 
        /* Get printer info */
-        result = cli_spoolss_getprinter(cli, mem_ctx, &pol, info_level, &ctr);
+        result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, info_level, &ctr);
 
         if (!W_ERROR_IS_OK(result))
                 goto done;
@@ -583,13 +583,13 @@ static WERROR cmd_spoolss_setprintername(struct cli_state *cli,
        ctr.printers_2->devmode = NULL;
        ctr.printers_2->secdesc = NULL;
 
-       result = cli_spoolss_setprinter(cli, mem_ctx, &pol, info_level, &ctr, 0);
+       result = rpccli_spoolss_setprinter(cli, mem_ctx, &pol, info_level, &ctr, 0);
        if (W_ERROR_IS_OK(result))
                printf("Success in setting printername.\n");
 
  done:
        if (opened_hnd)
-               cli_spoolss_close_printer(cli, mem_ctx, &pol);
+               rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
 
        return result;
 }
@@ -597,7 +597,7 @@ static WERROR cmd_spoolss_setprintername(struct cli_state *cli,
 /****************************************************************************
 ****************************************************************************/
 
-static WERROR cmd_spoolss_getprinter(struct cli_state *cli,
+static WERROR cmd_spoolss_getprinter(struct rpc_pipe_client *cli,
                                        TALLOC_CTX *mem_ctx,
                                        int argc, const char **argv)
 {
@@ -620,14 +620,14 @@ static WERROR cmd_spoolss_getprinter(struct cli_state *cli,
                info_level = atoi(argv[2]);
        }
 
-       slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
+       slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
        strupper_m(servername);
        slprintf(printername, sizeof(printername)-1, "%s\\%s", servername, argv[1]);
        fstrcpy(user, cli->user_name);
        
        /* get a printer handle */
 
-       result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, 
+       result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, 
                                             "", MAXIMUM_ALLOWED_ACCESS, 
                                             servername, user, &pol);
 
@@ -638,7 +638,7 @@ static WERROR cmd_spoolss_getprinter(struct cli_state *cli,
 
        /* Get printer info */
 
-       result = cli_spoolss_getprinter(cli, mem_ctx, &pol, info_level, &ctr);
+       result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, info_level, &ctr);
 
        if (!W_ERROR_IS_OK(result))
                goto done;
@@ -668,7 +668,7 @@ static WERROR cmd_spoolss_getprinter(struct cli_state *cli,
 
  done: 
        if (opened_hnd) 
-               cli_spoolss_close_printer(cli, mem_ctx, &pol);
+               rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
 
        return result;
 }
@@ -729,7 +729,7 @@ static void display_reg_value(REGISTRY_VALUE value)
 /****************************************************************************
 ****************************************************************************/
 
-static WERROR cmd_spoolss_getprinterdata(struct cli_state *cli,
+static WERROR cmd_spoolss_getprinterdata(struct rpc_pipe_client *cli,
                                           TALLOC_CTX *mem_ctx,
                                           int argc, const char **argv)
 {
@@ -751,7 +751,7 @@ static WERROR cmd_spoolss_getprinterdata(struct cli_state *cli,
 
        /* Open a printer handle */
 
-       slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
+       slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
        strupper_m(servername);
        if (strncmp(argv[1], ".", sizeof(".")) == 0)
                fstrcpy(printername, servername);
@@ -762,7 +762,7 @@ static WERROR cmd_spoolss_getprinterdata(struct cli_state *cli,
        
        /* get a printer handle */
 
-       result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, 
+       result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, 
                                             "", MAXIMUM_ALLOWED_ACCESS, 
                                             servername, user, &pol);
 
@@ -773,7 +773,7 @@ static WERROR cmd_spoolss_getprinterdata(struct cli_state *cli,
 
        /* Get printer info */
 
-       result = cli_spoolss_getprinterdata(cli, mem_ctx, &pol, valuename, &value);
+       result = rpccli_spoolss_getprinterdata(cli, mem_ctx, &pol, valuename, &value);
 
        if (!W_ERROR_IS_OK(result))
                goto done;
@@ -786,7 +786,7 @@ static WERROR cmd_spoolss_getprinterdata(struct cli_state *cli,
 
  done: 
        if (opened_hnd) 
-               cli_spoolss_close_printer(cli, mem_ctx, &pol);
+               rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
 
        return result;
 }
@@ -794,7 +794,7 @@ static WERROR cmd_spoolss_getprinterdata(struct cli_state *cli,
 /****************************************************************************
 ****************************************************************************/
 
-static WERROR cmd_spoolss_getprinterdataex(struct cli_state *cli,
+static WERROR cmd_spoolss_getprinterdataex(struct rpc_pipe_client *cli,
                                             TALLOC_CTX *mem_ctx,
                                             int argc, const char **argv)
 {
@@ -818,7 +818,7 @@ static WERROR cmd_spoolss_getprinterdataex(struct cli_state *cli,
 
        /* Open a printer handle */
 
-       slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
+       slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
        strupper_m(servername);
        if (strncmp(argv[1], ".", sizeof(".")) == 0)
                fstrcpy(printername, servername);
@@ -829,7 +829,7 @@ static WERROR cmd_spoolss_getprinterdataex(struct cli_state *cli,
        
        /* get a printer handle */
 
-       result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, 
+       result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, 
                                             "", MAXIMUM_ALLOWED_ACCESS, 
                                             servername, user, &pol);
 
@@ -840,7 +840,7 @@ static WERROR cmd_spoolss_getprinterdataex(struct cli_state *cli,
 
        /* Get printer info */
 
-       result = cli_spoolss_getprinterdataex(cli, mem_ctx, &pol, keyname, 
+       result = rpccli_spoolss_getprinterdataex(cli, mem_ctx, &pol, keyname, 
                valuename, &value);
 
        if (!W_ERROR_IS_OK(result))
@@ -854,7 +854,7 @@ static WERROR cmd_spoolss_getprinterdataex(struct cli_state *cli,
 
  done: 
        if (opened_hnd) 
-               cli_spoolss_close_printer(cli, mem_ctx, &pol);
+               rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
 
        return result;
 }
@@ -972,7 +972,7 @@ static void display_print_driver_3(DRIVER_INFO_3 *i1)
 /****************************************************************************
 ****************************************************************************/
 
-static WERROR cmd_spoolss_getdriver(struct cli_state *cli, 
+static WERROR cmd_spoolss_getdriver(struct rpc_pipe_client *cli, 
                                       TALLOC_CTX *mem_ctx,
                                       int argc, const char **argv)
 {
@@ -994,7 +994,7 @@ static WERROR cmd_spoolss_getdriver(struct cli_state *cli,
        }
 
        /* get the arguments need to open the printer handle */
-       slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
+       slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
        strupper_m(servername);
        fstrcpy(user, cli->user_name);
        slprintf(printername, sizeof(servername)-1, "%s\\%s", servername, argv[1]);
@@ -1003,7 +1003,7 @@ static WERROR cmd_spoolss_getdriver(struct cli_state *cli,
 
        /* Open a printer handle */
 
-       werror = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, "", 
+       werror = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "", 
                                             PRINTER_ACCESS_USE,
                                             servername, user, &pol);
 
@@ -1018,7 +1018,7 @@ static WERROR cmd_spoolss_getdriver(struct cli_state *cli,
 
        for (i=0; archi_table[i].long_archi!=NULL; i++) {
 
-               werror = cli_spoolss_getprinterdriver( cli, mem_ctx, &pol, info_level, 
+               werror = rpccli_spoolss_getprinterdriver( cli, mem_ctx, &pol, info_level, 
                        archi_table[i].long_archi, archi_table[i].version,
                        &ctr);
 
@@ -1050,7 +1050,7 @@ static WERROR cmd_spoolss_getdriver(struct cli_state *cli,
        /* Cleanup */
 
        if (opened_hnd)
-               cli_spoolss_close_printer (cli, mem_ctx, &pol);
+               rpccli_spoolss_close_printer (cli, mem_ctx, &pol);
        
        if ( success )
                werror = WERR_OK;
@@ -1061,7 +1061,7 @@ static WERROR cmd_spoolss_getdriver(struct cli_state *cli,
 /****************************************************************************
 ****************************************************************************/
 
-static WERROR cmd_spoolss_enum_drivers(struct cli_state *cli, 
+static WERROR cmd_spoolss_enum_drivers(struct rpc_pipe_client *cli, 
                                          TALLOC_CTX *mem_ctx,
                                          int argc, const char **argv)
 {
@@ -1089,7 +1089,7 @@ static WERROR cmd_spoolss_enum_drivers(struct cli_state *cli,
                if ( i>0 && strequal(archi_table[i].long_archi, archi_table[i-1].long_archi) )
                        continue;
 
-               werror = cli_spoolss_enumprinterdrivers(
+               werror = rpccli_spoolss_enumprinterdrivers(
                        cli, mem_ctx, info_level, 
                        archi_table[i].long_archi, &returned, &ctr);
 
@@ -1154,7 +1154,7 @@ static void display_printdriverdir_1(DRIVER_DIRECTORY_1 *i1)
 /****************************************************************************
 ****************************************************************************/
 
-static WERROR cmd_spoolss_getdriverdir(struct cli_state *cli, 
+static WERROR cmd_spoolss_getdriverdir(struct rpc_pipe_client *cli, 
                                          TALLOC_CTX *mem_ctx,
                                          int argc, const char **argv)
 {
@@ -1176,7 +1176,7 @@ static WERROR cmd_spoolss_getdriverdir(struct cli_state *cli,
 
        /* Get the directory.  Only use Info level 1 */
 
-       result = cli_spoolss_getprinterdriverdir(cli, mem_ctx, 1, env, &ctr);
+       result = rpccli_spoolss_getprinterdriverdir(cli, mem_ctx, 1, env, &ctr);
 
        if (W_ERROR_IS_OK(result))
                display_printdriverdir_1(ctr.info1);
@@ -1293,7 +1293,7 @@ static BOOL init_drv_info_3_members ( TALLOC_CTX *mem_ctx, DRIVER_INFO_3 *info,
 /****************************************************************************
 ****************************************************************************/
 
-static WERROR cmd_spoolss_addprinterdriver(struct cli_state *cli, 
+static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli, 
                                              TALLOC_CTX *mem_ctx,
                                              int argc, const char **argv)
 {
@@ -1344,7 +1344,7 @@ static WERROR cmd_spoolss_addprinterdriver(struct cli_state *cli,
 
 
        ctr.info3 = &info3;
-       result = cli_spoolss_addprinterdriver (cli, mem_ctx, level, &ctr);
+       result = rpccli_spoolss_addprinterdriver (cli, mem_ctx, level, &ctr);
 
        if (W_ERROR_IS_OK(result)) {
                rpcstr_pull(driver_name, info3.name.buffer, 
@@ -1360,7 +1360,7 @@ static WERROR cmd_spoolss_addprinterdriver(struct cli_state *cli,
 /****************************************************************************
 ****************************************************************************/
 
-static WERROR cmd_spoolss_addprinterex(struct cli_state *cli, 
+static WERROR cmd_spoolss_addprinterex(struct rpc_pipe_client *cli, 
                                          TALLOC_CTX *mem_ctx,
                                          int argc, const char **argv)
 {
@@ -1377,7 +1377,7 @@ static WERROR cmd_spoolss_addprinterex(struct cli_state *cli,
                return WERR_OK;
         }
        
-        slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
+        slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
         strupper_m(servername);
 
        /* Fill in the DRIVER_INFO_2 struct */
@@ -1407,7 +1407,7 @@ static WERROR cmd_spoolss_addprinterex(struct cli_state *cli,
        */
 
        ctr.printers_2 = &info2;
-       result = cli_spoolss_addprinterex (cli, mem_ctx, level, &ctr);
+       result = rpccli_spoolss_addprinterex (cli, mem_ctx, level, &ctr);
 
        if (W_ERROR_IS_OK(result))
                printf ("Printer %s successfully installed.\n", argv[1]);
@@ -1418,7 +1418,7 @@ static WERROR cmd_spoolss_addprinterex(struct cli_state *cli,
 /****************************************************************************
 ****************************************************************************/
 
-static WERROR cmd_spoolss_setdriver(struct cli_state *cli, 
+static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *cli, 
                                       TALLOC_CTX *mem_ctx,
                                       int argc, const char **argv)
 {
@@ -1439,14 +1439,14 @@ static WERROR cmd_spoolss_setdriver(struct cli_state *cli,
                return WERR_OK;
         }
 
-       slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
+       slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
        strupper_m(servername);
        slprintf(printername, sizeof(printername)-1, "%s\\%s", servername, argv[1]);
        fstrcpy(user, cli->user_name);
 
        /* Get a printer handle */
 
-       result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, "", 
+       result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "", 
                                             PRINTER_ALL_ACCESS,
                                             servername, user, &pol);
 
@@ -1460,7 +1460,7 @@ static WERROR cmd_spoolss_setdriver(struct cli_state *cli,
        ZERO_STRUCT (info2);
        ctr.printers_2 = &info2;
 
-       result = cli_spoolss_getprinter(cli, mem_ctx, &pol, level, &ctr);
+       result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, level, &ctr);
 
        if (!W_ERROR_IS_OK(result)) {
                printf ("Unable to retrieve printer information!\n");
@@ -1471,7 +1471,7 @@ static WERROR cmd_spoolss_setdriver(struct cli_state *cli,
 
        init_unistr(&ctr.printers_2->drivername, argv[2]);
 
-       result = cli_spoolss_setprinter(cli, mem_ctx, &pol, level, &ctr, 0);
+       result = rpccli_spoolss_setprinter(cli, mem_ctx, &pol, level, &ctr, 0);
 
        if (!W_ERROR_IS_OK(result)) {
                printf("SetPrinter call failed!\n");
@@ -1484,7 +1484,7 @@ done:
        /* Cleanup */
 
        if (opened_hnd)
-               cli_spoolss_close_printer(cli, mem_ctx, &pol);
+               rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
 
        return result;
 }
@@ -1493,7 +1493,7 @@ done:
 /****************************************************************************
 ****************************************************************************/
 
-static WERROR cmd_spoolss_deletedriverex(struct cli_state *cli, 
+static WERROR cmd_spoolss_deletedriverex(struct rpc_pipe_client *cli, 
                                          TALLOC_CTX *mem_ctx,
                                          int argc, const char **argv)
 {
@@ -1526,7 +1526,7 @@ static WERROR cmd_spoolss_deletedriverex(struct cli_state *cli,
                        continue;
 
                /* make the call to remove the driver */
-               result = cli_spoolss_deleteprinterdriverex(
+               result = rpccli_spoolss_deleteprinterdriverex(
                        cli, mem_ctx, archi_table[i].long_archi, argv[1], archi_table[i].version); 
 
                if ( !W_ERROR_IS_OK(result) ) 
@@ -1551,7 +1551,7 @@ static WERROR cmd_spoolss_deletedriverex(struct cli_state *cli,
 /****************************************************************************
 ****************************************************************************/
 
-static WERROR cmd_spoolss_deletedriver(struct cli_state *cli, 
+static WERROR cmd_spoolss_deletedriver(struct rpc_pipe_client *cli, 
                                          TALLOC_CTX *mem_ctx,
                                          int argc, const char **argv)
 {
@@ -1566,14 +1566,14 @@ static WERROR cmd_spoolss_deletedriver(struct cli_state *cli,
                return WERR_OK;
         }
 
-       slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
+       slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
        strupper_m(servername);
 
        /* delete the driver for all architectures */
        for (i=0; archi_table[i].long_archi; i++)
        {
                /* make the call to remove the driver */
-               result = cli_spoolss_deleteprinterdriver(
+               result = rpccli_spoolss_deleteprinterdriver(
                        cli, mem_ctx, archi_table[i].long_archi, argv[1]);
 
                if ( !W_ERROR_IS_OK(result) ) {
@@ -1596,7 +1596,7 @@ static WERROR cmd_spoolss_deletedriver(struct cli_state *cli,
 /****************************************************************************
 ****************************************************************************/
 
-static WERROR cmd_spoolss_getprintprocdir(struct cli_state *cli, 
+static WERROR cmd_spoolss_getprintprocdir(struct rpc_pipe_client *cli, 
                                            TALLOC_CTX *mem_ctx,
                                            int argc, const char **argv)
 {
@@ -1610,7 +1610,7 @@ static WERROR cmd_spoolss_getprintprocdir(struct cli_state *cli,
                return WERR_OK;
         }
 
-       if (asprintf(&servername, "\\\\%s", cli->desthost) < 0)
+       if (asprintf(&servername, "\\\\%s", cli->cli->desthost) < 0)
                return WERR_NOMEM;
        strupper_m(servername);
 
@@ -1620,7 +1620,7 @@ static WERROR cmd_spoolss_getprintprocdir(struct cli_state *cli,
                return WERR_NOMEM;
        }
 
-       result = cli_spoolss_getprintprocessordirectory(
+       result = rpccli_spoolss_getprintprocessordirectory(
                cli, mem_ctx, servername, environment, procdir);
 
        if (W_ERROR_IS_OK(result))
@@ -1635,7 +1635,7 @@ static WERROR cmd_spoolss_getprintprocdir(struct cli_state *cli,
 /****************************************************************************
 ****************************************************************************/
 
-static WERROR cmd_spoolss_addform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+static WERROR cmd_spoolss_addform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                    int argc, const char **argv)
 {
        POLICY_HND handle;
@@ -1653,11 +1653,11 @@ static WERROR cmd_spoolss_addform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        
        /* Get a printer handle */
 
-       asprintf(&servername, "\\\\%s", cli->desthost);
+       asprintf(&servername, "\\\\%s", cli->cli->desthost);
        strupper_m(servername);
        asprintf(&printername, "%s\\%s", servername, argv[1]);
 
-       werror = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, "", 
+       werror = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "", 
                                             PRINTER_ALL_ACCESS, 
                                             servername, cli->user_name, &handle);
 
@@ -1680,11 +1680,11 @@ static WERROR cmd_spoolss_addform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        /* Add the form */
 
 
-       werror = cli_spoolss_addform(cli, mem_ctx, &handle, 1, &form);
+       werror = rpccli_spoolss_addform(cli, mem_ctx, &handle, 1, &form);
 
  done:
        if (got_handle)
-               cli_spoolss_close_printer(cli, mem_ctx, &handle);
+               rpccli_spoolss_close_printer(cli, mem_ctx, &handle);
 
        SAFE_FREE(servername);
        SAFE_FREE(printername);
@@ -1695,7 +1695,7 @@ static WERROR cmd_spoolss_addform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 /****************************************************************************
 ****************************************************************************/
 
-static WERROR cmd_spoolss_setform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+static WERROR cmd_spoolss_setform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                    int argc, const char **argv)
 {
        POLICY_HND handle;
@@ -1713,11 +1713,11 @@ static WERROR cmd_spoolss_setform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        
        /* Get a printer handle */
 
-       asprintf(&servername, "\\\\%s", cli->desthost);
+       asprintf(&servername, "\\\\%s", cli->cli->desthost);
        strupper_m(servername);
        asprintf(&printername, "%s\\%s", servername, argv[1]);
 
-       werror = cli_spoolss_open_printer_ex(
+       werror = rpccli_spoolss_open_printer_ex(
                cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS, 
                servername, cli->user_name, &handle);
 
@@ -1739,11 +1739,11 @@ static WERROR cmd_spoolss_setform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 
        /* Set the form */
 
-       werror = cli_spoolss_setform(cli, mem_ctx, &handle, 1, argv[2], &form);
+       werror = rpccli_spoolss_setform(cli, mem_ctx, &handle, 1, argv[2], &form);
 
  done:
        if (got_handle)
-               cli_spoolss_close_printer(cli, mem_ctx, &handle);
+               rpccli_spoolss_close_printer(cli, mem_ctx, &handle);
 
        SAFE_FREE(servername);
        SAFE_FREE(printername);
@@ -1792,7 +1792,7 @@ static void display_form(FORM_1 *form)
 /****************************************************************************
 ****************************************************************************/
 
-static WERROR cmd_spoolss_getform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+static WERROR cmd_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                    int argc, const char **argv)
 {
        POLICY_HND handle;
@@ -1810,11 +1810,11 @@ static WERROR cmd_spoolss_getform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        
        /* Get a printer handle */
 
-       asprintf(&servername, "\\\\%s", cli->desthost);
+       asprintf(&servername, "\\\\%s", cli->cli->desthost);
        strupper_m(servername);
        asprintf(&printername, "%s\\%s", servername, argv[1]);
 
-       werror = cli_spoolss_open_printer_ex(
+       werror = rpccli_spoolss_open_printer_ex(
                cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS, 
                servername, cli->user_name, &handle);
 
@@ -1825,7 +1825,7 @@ static WERROR cmd_spoolss_getform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 
        /* Get the form */
 
-       werror = cli_spoolss_getform(cli, mem_ctx, &handle, argv[2], 1, &form);
+       werror = rpccli_spoolss_getform(cli, mem_ctx, &handle, argv[2], 1, &form);
 
        if (!W_ERROR_IS_OK(werror))
                goto done;
@@ -1834,7 +1834,7 @@ static WERROR cmd_spoolss_getform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 
  done:
        if (got_handle)
-               cli_spoolss_close_printer(cli, mem_ctx, &handle);
+               rpccli_spoolss_close_printer(cli, mem_ctx, &handle);
 
        SAFE_FREE(servername);
        SAFE_FREE(printername);
@@ -1845,7 +1845,7 @@ static WERROR cmd_spoolss_getform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 /****************************************************************************
 ****************************************************************************/
 
-static WERROR cmd_spoolss_deleteform(struct cli_state *cli, 
+static WERROR cmd_spoolss_deleteform(struct rpc_pipe_client *cli, 
                                       TALLOC_CTX *mem_ctx, int argc, 
                                       const char **argv)
 {
@@ -1863,11 +1863,11 @@ static WERROR cmd_spoolss_deleteform(struct cli_state *cli,
        
        /* Get a printer handle */
 
-       asprintf(&servername, "\\\\%s", cli->desthost);
+       asprintf(&servername, "\\\\%s", cli->cli->desthost);
        strupper_m(servername);
        asprintf(&printername, "%s\\%s", servername, argv[1]);
 
-       werror = cli_spoolss_open_printer_ex(
+       werror = rpccli_spoolss_open_printer_ex(
                cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS, 
                servername, cli->user_name, &handle);
 
@@ -1878,11 +1878,11 @@ static WERROR cmd_spoolss_deleteform(struct cli_state *cli,
 
        /* Delete the form */
 
-       werror = cli_spoolss_deleteform(cli, mem_ctx, &handle, argv[2]);
+       werror = rpccli_spoolss_deleteform(cli, mem_ctx, &handle, argv[2]);
 
  done:
        if (got_handle)
-               cli_spoolss_close_printer(cli, mem_ctx, &handle);
+               rpccli_spoolss_close_printer(cli, mem_ctx, &handle);
 
        SAFE_FREE(servername);
        SAFE_FREE(printername);
@@ -1893,7 +1893,7 @@ static WERROR cmd_spoolss_deleteform(struct cli_state *cli,
 /****************************************************************************
 ****************************************************************************/
 
-static WERROR cmd_spoolss_enum_forms(struct cli_state *cli, 
+static WERROR cmd_spoolss_enum_forms(struct rpc_pipe_client *cli, 
                                       TALLOC_CTX *mem_ctx, int argc, 
                                       const char **argv)
 {
@@ -1913,11 +1913,11 @@ static WERROR cmd_spoolss_enum_forms(struct cli_state *cli,
        
        /* Get a printer handle */
 
-       asprintf(&servername, "\\\\%s", cli->desthost);
+       asprintf(&servername, "\\\\%s", cli->cli->desthost);
        strupper_m(servername);
        asprintf(&printername, "%s\\%s", servername, argv[1]);
 
-       werror = cli_spoolss_open_printer_ex(
+       werror = rpccli_spoolss_open_printer_ex(
                cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS, 
                servername, cli->user_name, &handle);
 
@@ -1929,7 +1929,7 @@ static WERROR cmd_spoolss_enum_forms(struct cli_state *cli,
        /* Enumerate forms */
 
        offered = needed = 0;
-       werror = cli_spoolss_enumforms(cli, mem_ctx, &handle, level, &num_forms, &forms);
+       werror = rpccli_spoolss_enumforms(cli, mem_ctx, &handle, level, &num_forms, &forms);
 
        if (!W_ERROR_IS_OK(werror))
                goto done;
@@ -1944,7 +1944,7 @@ static WERROR cmd_spoolss_enum_forms(struct cli_state *cli,
 
  done:
        if (got_handle)
-               cli_spoolss_close_printer(cli, mem_ctx, &handle);
+               rpccli_spoolss_close_printer(cli, mem_ctx, &handle);
 
        SAFE_FREE(servername);
        SAFE_FREE(printername);
@@ -1955,7 +1955,7 @@ static WERROR cmd_spoolss_enum_forms(struct cli_state *cli,
 /****************************************************************************
 ****************************************************************************/
 
-static WERROR cmd_spoolss_setprinterdata(struct cli_state *cli,
+static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
                                            TALLOC_CTX *mem_ctx,
                                            int argc, const char **argv)
 {
@@ -1975,7 +1975,7 @@ static WERROR cmd_spoolss_setprinterdata(struct cli_state *cli,
                return WERR_INVALID_PARAM;
        }
 
-       slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
+       slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
        strupper_m(servername);
        slprintf(printername, sizeof(servername)-1, "%s\\%s", servername, argv[1]);
        fstrcpy(user, cli->user_name);
@@ -2004,7 +2004,7 @@ static WERROR cmd_spoolss_setprinterdata(struct cli_state *cli,
        }
 
        /* get a printer handle */
-       result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
+       result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
                                             MAXIMUM_ALLOWED_ACCESS, servername, 
                                             user, &pol);
        if (!W_ERROR_IS_OK(result))
@@ -2014,7 +2014,7 @@ static WERROR cmd_spoolss_setprinterdata(struct cli_state *cli,
 
        ctr.printers_0 = &info;
 
-        result = cli_spoolss_getprinter(cli, mem_ctx, &pol, 0, &ctr);
+        result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, 0, &ctr);
 
         if (!W_ERROR_IS_OK(result))
                 goto done;
@@ -2082,7 +2082,7 @@ static WERROR cmd_spoolss_setprinterdata(struct cli_state *cli,
                goto done;
        }
 
-       result = cli_spoolss_setprinterdata(cli, mem_ctx, &pol, &value);
+       result = rpccli_spoolss_setprinterdata(cli, mem_ctx, &pol, &value);
                
        if (!W_ERROR_IS_OK(result)) {
                printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
@@ -2090,7 +2090,7 @@ static WERROR cmd_spoolss_setprinterdata(struct cli_state *cli,
        }
        printf("\tSetPrinterData succeeded [%s: %s]\n", argv[3], argv[4]);
        
-        result = cli_spoolss_getprinter(cli, mem_ctx, &pol, 0, &ctr);
+        result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, 0, &ctr);
 
         if (!W_ERROR_IS_OK(result))
                 goto done;
@@ -2101,7 +2101,7 @@ static WERROR cmd_spoolss_setprinterdata(struct cli_state *cli,
 done:
        /* cleanup */
        if (opened_hnd)
-               cli_spoolss_close_printer(cli, mem_ctx, &pol);
+               rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
 
        return result;
 }
@@ -2151,7 +2151,7 @@ static void display_job_info_2(JOB_INFO_2 *job)
 /****************************************************************************
 ****************************************************************************/
 
-static WERROR cmd_spoolss_enum_jobs(struct cli_state *cli, 
+static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli, 
                                      TALLOC_CTX *mem_ctx, int argc, 
                                      const char **argv)
 {
@@ -2173,14 +2173,14 @@ static WERROR cmd_spoolss_enum_jobs(struct cli_state *cli,
 
        /* Open printer handle */
 
-       slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
+       slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
        strupper_m(servername);
        fstrcpy(user, cli->user_name);
-       slprintf(printername, sizeof(servername)-1, "\\\\%s\\", cli->desthost);
+       slprintf(printername, sizeof(servername)-1, "\\\\%s\\", cli->cli->desthost);
        strupper_m(printername);
        pstrcat(printername, argv[1]);
 
-       result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, 
+       result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, 
                                             "", MAXIMUM_ALLOWED_ACCESS, 
                                             servername, user, &hnd);
 
@@ -2192,7 +2192,7 @@ static WERROR cmd_spoolss_enum_jobs(struct cli_state *cli,
        /* Enumerate ports */
 
        offered = needed = 0;
-       result = cli_spoolss_enumjobs(cli, mem_ctx, &hnd, level, 0, 1000,
+       result = rpccli_spoolss_enumjobs(cli, mem_ctx, &hnd, level, 0, 1000,
                &num_jobs, &ctr);
 
        if (!W_ERROR_IS_OK(result))
@@ -2214,7 +2214,7 @@ static WERROR cmd_spoolss_enum_jobs(struct cli_state *cli,
        
 done:
        if (got_hnd)
-               cli_spoolss_close_printer(cli, mem_ctx, &hnd);
+               rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
 
        return result;
 }
@@ -2222,7 +2222,7 @@ done:
 /****************************************************************************
 ****************************************************************************/
 
-static WERROR cmd_spoolss_enum_data( struct cli_state *cli, 
+static WERROR cmd_spoolss_enum_data( struct rpc_pipe_client *cli, 
                                       TALLOC_CTX *mem_ctx, int argc, 
                                       const char **argv)
 {
@@ -2240,14 +2240,14 @@ static WERROR cmd_spoolss_enum_data( struct cli_state *cli,
        
        /* Open printer handle */
 
-       slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
+       slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
        strupper_m(servername);
        fstrcpy(user, cli->user_name);
-       slprintf(printername, sizeof(printername)-1, "\\\\%s\\", cli->desthost);
+       slprintf(printername, sizeof(printername)-1, "\\\\%s\\", cli->cli->desthost);
        strupper_m(printername);
        pstrcat(printername, argv[1]);
 
-       result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, 
+       result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, 
                                             "", MAXIMUM_ALLOWED_ACCESS, 
                                             servername, user, &hnd);
 
@@ -2258,12 +2258,12 @@ static WERROR cmd_spoolss_enum_data( struct cli_state *cli,
 
        /* Enumerate data */
 
-       result = cli_spoolss_enumprinterdata(cli, mem_ctx, &hnd, i, 0, 0,
+       result = rpccli_spoolss_enumprinterdata(cli, mem_ctx, &hnd, i, 0, 0,
                                             &val_needed, &data_needed,
                                             NULL);
        while (W_ERROR_IS_OK(result)) {
                REGISTRY_VALUE value;
-               result = cli_spoolss_enumprinterdata(
+               result = rpccli_spoolss_enumprinterdata(
                        cli, mem_ctx, &hnd, i++, val_needed,
                        data_needed, 0, 0, &value);
                if (W_ERROR_IS_OK(result))
@@ -2274,7 +2274,7 @@ static WERROR cmd_spoolss_enum_data( struct cli_state *cli,
 
 done:
        if (got_hnd)
-               cli_spoolss_close_printer(cli, mem_ctx, &hnd);
+               rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
 
        return result;
 }
@@ -2282,7 +2282,7 @@ done:
 /****************************************************************************
 ****************************************************************************/
 
-static WERROR cmd_spoolss_enum_data_ex( struct cli_state *cli, 
+static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli, 
                                          TALLOC_CTX *mem_ctx, int argc, 
                                          const char **argv)
 {
@@ -2304,14 +2304,14 @@ static WERROR cmd_spoolss_enum_data_ex( struct cli_state *cli,
 
        /* Open printer handle */
 
-       slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
+       slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
        strupper_m(servername);
        fstrcpy(user, cli->user_name);
-       slprintf(printername, sizeof(printername)-1, "\\\\%s\\", cli->desthost);
+       slprintf(printername, sizeof(printername)-1, "\\\\%s\\", cli->cli->desthost);
        strupper_m(printername);
        pstrcat(printername, argv[1]);
 
-       result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, 
+       result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, 
                                             "", MAXIMUM_ALLOWED_ACCESS, 
                                             servername, user, &hnd);
 
@@ -2325,7 +2325,7 @@ static WERROR cmd_spoolss_enum_data_ex( struct cli_state *cli,
        if ( !(ctr = TALLOC_ZERO_P( mem_ctx, REGVAL_CTR )) ) 
                return WERR_NOMEM;
 
-       result = cli_spoolss_enumprinterdataex(cli, mem_ctx, &hnd, keyname, ctr);
+       result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx, &hnd, keyname, ctr);
 
        if (!W_ERROR_IS_OK(result))
                goto done;
@@ -2338,7 +2338,7 @@ static WERROR cmd_spoolss_enum_data_ex( struct cli_state *cli,
 
 done:
        if (got_hnd)
-               cli_spoolss_close_printer(cli, mem_ctx, &hnd);
+               rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
 
        return result;
 }
@@ -2346,7 +2346,7 @@ done:
 /****************************************************************************
 ****************************************************************************/
 
-static WERROR cmd_spoolss_enum_printerkey( struct cli_state *cli, 
+static WERROR cmd_spoolss_enum_printerkey( struct rpc_pipe_client *cli, 
                                             TALLOC_CTX *mem_ctx, int argc, 
                                             const char **argv)
 {
@@ -2370,14 +2370,14 @@ static WERROR cmd_spoolss_enum_printerkey( struct cli_state *cli,
 
        /* Open printer handle */
 
-       slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
+       slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
        strupper_m(servername);
        fstrcpy(user, cli->user_name);
-       slprintf(printername, sizeof(printername)-1, "\\\\%s\\", cli->desthost);
+       slprintf(printername, sizeof(printername)-1, "\\\\%s\\", cli->cli->desthost);
        strupper_m(printername);
        pstrcat(printername, argv[1]);
 
-       result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, 
+       result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, 
                                             "", MAXIMUM_ALLOWED_ACCESS, 
                                             servername, user, &hnd);
 
@@ -2388,7 +2388,7 @@ static WERROR cmd_spoolss_enum_printerkey( struct cli_state *cli,
 
        /* Enumerate subkeys */
 
-       result = cli_spoolss_enumprinterkey(cli, mem_ctx, &hnd, keyname, &keylist, NULL);
+       result = rpccli_spoolss_enumprinterkey(cli, mem_ctx, &hnd, keyname, &keylist, NULL);
 
        if (!W_ERROR_IS_OK(result))
                goto done;
@@ -2406,7 +2406,7 @@ static WERROR cmd_spoolss_enum_printerkey( struct cli_state *cli,
 
 done:
        if (got_hnd)
-               cli_spoolss_close_printer(cli, mem_ctx, &hnd);
+               rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
 
        return result;
 }
@@ -2414,7 +2414,7 @@ done:
 /****************************************************************************
 ****************************************************************************/
 
-static WERROR cmd_spoolss_rffpcnex(struct cli_state *cli, 
+static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli, 
                                     TALLOC_CTX *mem_ctx, int argc, 
                                     const char **argv)
 {
@@ -2432,14 +2432,14 @@ static WERROR cmd_spoolss_rffpcnex(struct cli_state *cli,
 
        /* Open printer */
 
-       slprintf(servername, sizeof(servername) - 1, "\\\\%s", cli->desthost);
+       slprintf(servername, sizeof(servername) - 1, "\\\\%s", cli->cli->desthost);
        strupper_m(servername);
 
-       slprintf(printername, sizeof(printername) - 1, "\\\\%s\\%s", cli->desthost,
+       slprintf(printername, sizeof(printername) - 1, "\\\\%s\\%s", cli->cli->desthost,
                 argv[1]);
        strupper_m(printername);
 
-       result = cli_spoolss_open_printer_ex(
+       result = rpccli_spoolss_open_printer_ex(
                cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS, 
                servername, cli->user_name, &hnd);
 
@@ -2477,7 +2477,7 @@ static WERROR cmd_spoolss_rffpcnex(struct cli_state *cli,
        slprintf(servername, sizeof(servername) - 1, "\\\\%s", myhostname());
        strupper_m(servername);
 
-       result = cli_spoolss_rffpcnex(
+       result = rpccli_spoolss_rffpcnex(
                cli, mem_ctx, &hnd, 0, 0, servername, 123, &option);
 
        if (!W_ERROR_IS_OK(result)) {
@@ -2487,44 +2487,236 @@ static WERROR cmd_spoolss_rffpcnex(struct cli_state *cli,
 
 done:          
        if (got_hnd)
-               cli_spoolss_close_printer(cli, mem_ctx, &hnd);
+               rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
 
        return result;
 }
 
+/****************************************************************************
+****************************************************************************/
+
+static BOOL compare_printer( struct rpc_pipe_client *cli1, POLICY_HND *hnd1,
+                             struct rpc_pipe_client *cli2, POLICY_HND *hnd2 )
+{
+       PRINTER_INFO_CTR ctr1, ctr2;
+       WERROR werror;
+       TALLOC_CTX *mem_ctx = talloc_init("compare_printer");
+
+       printf("Retrieving printer propertiesfor %s...", cli1->cli->desthost);
+       werror = rpccli_spoolss_getprinter( cli1, mem_ctx, hnd1, 2, &ctr1);
+       if ( !W_ERROR_IS_OK(werror) ) {
+               printf("failed (%s)\n", dos_errstr(werror));
+               talloc_destroy(mem_ctx);
+               return False;
+       }
+       printf("ok\n");
+
+       printf("Retrieving printer properties for %s...", cli2->cli->desthost);
+       werror = rpccli_spoolss_getprinter( cli2, mem_ctx, hnd2, 2, &ctr2);
+       if ( !W_ERROR_IS_OK(werror) ) {
+               printf("failed (%s)\n", dos_errstr(werror));
+               talloc_destroy(mem_ctx);
+               return False;
+       }
+       printf("ok\n");
+
+       talloc_destroy(mem_ctx);
+
+       return True;
+}
+
+/****************************************************************************
+****************************************************************************/
+
+static BOOL compare_printer_secdesc( struct rpc_pipe_client *cli1, POLICY_HND *hnd1,
+                                     struct rpc_pipe_client *cli2, POLICY_HND *hnd2 )
+{
+       PRINTER_INFO_CTR ctr1, ctr2;
+       WERROR werror;
+       TALLOC_CTX *mem_ctx = talloc_init("compare_printer_secdesc");
+       SEC_DESC *sd1, *sd2;
+       BOOL result = True;
+
+
+       printf("Retreiving printer security for %s...", cli1->cli->desthost);
+       werror = rpccli_spoolss_getprinter( cli1, mem_ctx, hnd1, 3, &ctr1);
+       if ( !W_ERROR_IS_OK(werror) ) {
+               printf("failed (%s)\n", dos_errstr(werror));
+               result = False;
+               goto done;
+       }
+       printf("ok\n");
+
+       printf("Retrieving printer security for %s...", cli2->cli->desthost);
+       werror = rpccli_spoolss_getprinter( cli2, mem_ctx, hnd2, 3, &ctr2);
+       if ( !W_ERROR_IS_OK(werror) ) {
+               printf("failed (%s)\n", dos_errstr(werror));
+               result = False;
+               goto done;
+       }
+       printf("ok\n");
+       
+
+       printf("++ ");
+
+       if ( (ctr1.printers_3 != ctr2.printers_3) && (!ctr1.printers_3 || !ctr2.printers_3) ) {
+               printf("NULL PRINTER_INFO_3!\n");
+               result = False;
+               goto done;
+       }
+       
+       sd1 = ctr1.printers_3->secdesc;
+       sd2 = ctr2.printers_3->secdesc;
+       
+       if ( (sd1 != sd2) && ( !sd1 || !sd2 ) ) {
+               printf("NULL secdesc!\n");
+               result = False;
+               goto done;
+       }
+       
+       if ( (ctr1.printers_3->flags != ctr1.printers_3->flags ) || !sec_desc_equal( sd1, sd2 ) ) {
+               printf("Security Descriptors *not* equal!\n");
+               result = False;
+               goto done;
+       }
+       
+       printf("Security descriptors match\n");
+       
+done:
+       talloc_destroy(mem_ctx);
+       return result;
+}
+
+
+/****************************************************************************
+****************************************************************************/
+
+static WERROR cmd_spoolss_printercmp(struct rpc_pipe_client *cli, 
+                                    TALLOC_CTX *mem_ctx, int argc, 
+                                    const char **argv)
+{
+       fstring printername, servername1, servername2;
+       pstring printername_path;
+       struct cli_state *cli_server1 = cli->cli;
+       struct cli_state *cli_server2 = NULL;
+       struct rpc_pipe_client *cli2 = NULL;
+       POLICY_HND hPrinter1, hPrinter2;
+       NTSTATUS nt_status;
+       WERROR werror;
+       
+       if ( argc != 3 )  {
+               printf("Usage: %s <printer> <server>\n", argv[0]);
+               return WERR_OK;
+       }
+       
+       fstrcpy( printername, argv[1] );
+       
+       fstr_sprintf( servername1, cli->cli->desthost );
+       fstrcpy( servername2, argv[2] );
+       strupper_m( servername1 );
+       strupper_m( servername2 );
+       
+       
+       /* first get the connection to the remote server */
+       
+       nt_status = cli_full_connection(&cli_server2, global_myname(), servername2, 
+                                       NULL, 0,
+                                       "IPC$", "IPC",  
+                                       cmdline_auth_info.username, 
+                                       lp_workgroup(),
+                                       cmdline_auth_info.password, 
+                                       cmdline_auth_info.use_kerberos ? CLI_FULL_CONNECTION_USE_KERBEROS : 0,
+                                       cmdline_auth_info.signing_state, NULL);
+                                       
+       if ( !NT_STATUS_IS_OK(nt_status) )
+               return WERR_GENERAL_FAILURE;
+
+       cli2 = cli_rpc_pipe_open_noauth(cli_server2, PI_SPOOLSS, &nt_status);
+       if (!cli2) {
+               printf("failed to open spoolss pipe on server %s (%s)\n",
+                       servername2, nt_errstr(nt_status));
+               return WERR_GENERAL_FAILURE;
+       }
+                                       
+       /* now open up both printers */
+
+       pstr_sprintf( printername_path, "\\\\%s\\%s", servername1, printername );
+       printf("Opening %s...", printername_path);
+       werror = rpccli_spoolss_open_printer_ex( cli, mem_ctx, printername_path, 
+               "", PRINTER_ALL_ACCESS, servername1, cli_server1->user_name, &hPrinter1);
+       if ( !W_ERROR_IS_OK(werror) ) {
+               printf("failed (%s)\n", dos_errstr(werror));
+               goto done;
+       }
+       printf("ok\n");
+       
+       pstr_sprintf( printername_path, "\\\\%s\\%s", servername2, printername );
+       printf("Opening %s...", printername_path);
+       werror = rpccli_spoolss_open_printer_ex( cli2, mem_ctx, printername_path,  
+               "", PRINTER_ALL_ACCESS, servername2, cli_server2->user_name, &hPrinter2 );
+       if ( !W_ERROR_IS_OK(werror) ) {
+                printf("failed (%s)\n", dos_errstr(werror));
+               goto done;
+       }
+       printf("ok\n");
+       
+       
+       compare_printer( cli, &hPrinter1, cli2, &hPrinter2 );
+       compare_printer_secdesc( cli, &hPrinter1, cli2, &hPrinter2 );
+#if 0
+       compare_printerdata( cli_server1, &hPrinter1, cli_server2, &hPrinter2 );
+#endif
+
+
+done:
+       /* cleanup */
+
+       printf("Closing printers...");  
+       rpccli_spoolss_close_printer( cli, mem_ctx, &hPrinter1 );
+       rpccli_spoolss_close_printer( cli2, mem_ctx, &hPrinter2 );
+       printf("ok\n");
+       
+       /* close the second remote connection */
+       
+       cli_shutdown( cli_server2 );
+       
+       return WERR_OK;
+}
+
 /* List of commands exported by this module */
 struct cmd_set spoolss_commands[] = {
 
        { "SPOOLSS"  },
 
-       { "adddriver",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterdriver,   PI_SPOOLSS, "Add a print driver",                  "" },
-       { "addprinter",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterex,       PI_SPOOLSS, "Add a printer",                       "" },
-       { "deldriver",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriver,       PI_SPOOLSS, "Delete a printer driver",             "" },
-       { "deldriverex",        RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriverex,     PI_SPOOLSS, "Delete a printer driver with files",  "" },
-       { "enumdata",           RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data,          PI_SPOOLSS, "Enumerate printer data",              "" },
-       { "enumdataex",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data_ex,       PI_SPOOLSS, "Enumerate printer data for a key",    "" },
-       { "enumkey",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printerkey,    PI_SPOOLSS, "Enumerate printer keys",              "" },
-       { "enumjobs",           RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_jobs,          PI_SPOOLSS, "Enumerate print jobs",                "" },
-       { "enumports",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_ports,         PI_SPOOLSS, "Enumerate printer ports",             "" },
-       { "enumdrivers",        RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_drivers,       PI_SPOOLSS, "Enumerate installed printer drivers", "" },
-       { "enumprinters",       RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printers,      PI_SPOOLSS, "Enumerate printers",                  "" },
-       { "getdata",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdata,     PI_SPOOLSS, "Get print driver data",               "" },
-       { "getdataex",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdataex,   PI_SPOOLSS, "Get printer driver data with keyname", ""},
-       { "getdriver",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriver,          PI_SPOOLSS, "Get print driver information",        "" },
-       { "getdriverdir",       RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriverdir,       PI_SPOOLSS, "Get print driver upload directory",   "" },
-       { "getprinter",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinter,         PI_SPOOLSS, "Get printer info",                    "" },
-       { "openprinter",        RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer_ex,    PI_SPOOLSS, "Open printer handle",                 "" },
-       { "setdriver",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_setdriver,          PI_SPOOLSS, "Set printer driver",                  "" },
-       { "getprintprocdir",    RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprintprocdir,    PI_SPOOLSS, "Get print processor directory",       "" },
-       { "addform",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_addform,            PI_SPOOLSS, "Add form",                            "" },
-       { "setform",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_setform,            PI_SPOOLSS, "Set form",                            "" },
-       { "getform",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_getform,            PI_SPOOLSS, "Get form",                            "" },
-       { "deleteform",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_deleteform,         PI_SPOOLSS, "Delete form",                         "" },
-       { "enumforms",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_forms,         PI_SPOOLSS, "Enumerate forms",                     "" },
-       { "setprinter",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinter,         PI_SPOOLSS, "Set printer comment",                 "" },
-       { "setprintername",     RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprintername,     PI_SPOOLSS, "Set printername",                 "" },
-       { "setprinterdata",     RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinterdata,     PI_SPOOLSS, "Set REG_SZ printer data",             "" },
-       { "rffpcnex",           RPC_RTYPE_WERROR, NULL, cmd_spoolss_rffpcnex,           PI_SPOOLSS, "Rffpcnex test", "" },
+       { "adddriver",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterdriver,   PI_SPOOLSS, NULL, "Add a print driver",                  "" },
+       { "addprinter",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterex,       PI_SPOOLSS, NULL, "Add a printer",                       "" },
+       { "deldriver",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriver,       PI_SPOOLSS, NULL, "Delete a printer driver",             "" },
+       { "deldriverex",        RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriverex,     PI_SPOOLSS, NULL, "Delete a printer driver with files",  "" },
+       { "enumdata",           RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data,          PI_SPOOLSS, NULL, "Enumerate printer data",              "" },
+       { "enumdataex",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data_ex,       PI_SPOOLSS, NULL, "Enumerate printer data for a key",    "" },
+       { "enumkey",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printerkey,    PI_SPOOLSS, NULL, "Enumerate printer keys",              "" },
+       { "enumjobs",           RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_jobs,          PI_SPOOLSS, NULL, "Enumerate print jobs",                "" },
+       { "enumports",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_ports,         PI_SPOOLSS, NULL, "Enumerate printer ports",             "" },
+       { "enumdrivers",        RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_drivers,       PI_SPOOLSS, NULL, "Enumerate installed printer drivers", "" },
+       { "enumprinters",       RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printers,      PI_SPOOLSS, NULL, "Enumerate printers",                  "" },
+       { "getdata",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdata,     PI_SPOOLSS, NULL, "Get print driver data",               "" },
+       { "getdataex",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdataex,   PI_SPOOLSS, NULL, "Get printer driver data with keyname", ""},
+       { "getdriver",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriver,          PI_SPOOLSS, NULL, "Get print driver information",        "" },
+       { "getdriverdir",       RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriverdir,       PI_SPOOLSS, NULL, "Get print driver upload directory",   "" },
+       { "getprinter",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinter,         PI_SPOOLSS, NULL, "Get printer info",                    "" },
+       { "openprinter",        RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer_ex,    PI_SPOOLSS, NULL, "Open printer handle",                 "" },
+       { "setdriver",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_setdriver,          PI_SPOOLSS, NULL, "Set printer driver",                  "" },
+       { "getprintprocdir",    RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprintprocdir,    PI_SPOOLSS, NULL, "Get print processor directory",       "" },
+       { "addform",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_addform,            PI_SPOOLSS, NULL, "Add form",                            "" },
+       { "setform",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_setform,            PI_SPOOLSS, NULL, "Set form",                            "" },
+       { "getform",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_getform,            PI_SPOOLSS, NULL, "Get form",                            "" },
+       { "deleteform",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_deleteform,         PI_SPOOLSS, NULL, "Delete form",                         "" },
+       { "enumforms",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_forms,         PI_SPOOLSS, NULL, "Enumerate forms",                     "" },
+       { "setprinter",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinter,         PI_SPOOLSS, NULL, "Set printer comment",                 "" },
+       { "setprintername",     RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprintername,     PI_SPOOLSS, NULL, "Set printername",                 "" },
+       { "setprinterdata",     RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinterdata,     PI_SPOOLSS, NULL, "Set REG_SZ printer data",             "" },
+       { "rffpcnex",           RPC_RTYPE_WERROR, NULL, cmd_spoolss_rffpcnex,           PI_SPOOLSS, NULL, "Rffpcnex test", "" },
+       { "printercmp",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_printercmp,         PI_SPOOLSS, NULL, "Printer comparison test", "" },
 
        { NULL }
 };
index 1d173ffdff13cab97aa73753be0935f2d43b1e6d..da81a82c8d55ce7363759d3c78f7b13113a42ca2 100644 (file)
@@ -179,7 +179,7 @@ static void display_srv_info_102(SRV_INFO_102 *sv102)
 }
 
 /* Server query info */
-static WERROR cmd_srvsvc_srv_query_info(struct cli_state *cli, 
+static WERROR cmd_srvsvc_srv_query_info(struct rpc_pipe_client *cli, 
                                           TALLOC_CTX *mem_ctx,
                                           int argc, const char **argv)
 {
@@ -195,7 +195,7 @@ static WERROR cmd_srvsvc_srv_query_info(struct cli_state *cli,
        if (argc == 2)
                info_level = atoi(argv[1]);
 
-       result = cli_srvsvc_net_srv_get_info(cli, mem_ctx, info_level,
+       result = rpccli_srvsvc_net_srv_get_info(cli, mem_ctx, info_level,
                                             &ctr);
 
        if (!W_ERROR_IS_OK(result)) {
@@ -270,7 +270,7 @@ static void display_share_info_502(SRV_SHARE_INFO_502 *info502)
 
 }
 
-static WERROR cmd_srvsvc_net_share_enum(struct cli_state *cli, 
+static WERROR cmd_srvsvc_net_share_enum(struct rpc_pipe_client *cli, 
                                           TALLOC_CTX *mem_ctx,
                                           int argc, const char **argv)
 {
@@ -290,7 +290,7 @@ static WERROR cmd_srvsvc_net_share_enum(struct cli_state *cli,
 
        init_enum_hnd(&hnd, 0);
 
-       result = cli_srvsvc_net_share_enum(
+       result = rpccli_srvsvc_net_share_enum(
                cli, mem_ctx, info_level, &ctr, preferred_len, &hnd);
 
        if (!W_ERROR_IS_OK(result) || !ctr.num_entries)
@@ -320,7 +320,7 @@ static WERROR cmd_srvsvc_net_share_enum(struct cli_state *cli,
        return result;
 }
 
-static WERROR cmd_srvsvc_net_share_get_info(struct cli_state *cli, 
+static WERROR cmd_srvsvc_net_share_get_info(struct rpc_pipe_client *cli, 
                                            TALLOC_CTX *mem_ctx,
                                            int argc, const char **argv)
 {
@@ -336,7 +336,7 @@ static WERROR cmd_srvsvc_net_share_get_info(struct cli_state *cli,
        if (argc == 3)
                info_level = atoi(argv[2]);
 
-       result = cli_srvsvc_net_share_get_info(cli, mem_ctx, argv[1], info_level, &info);
+       result = rpccli_srvsvc_net_share_get_info(cli, mem_ctx, argv[1], info_level, &info);
 
        if (!W_ERROR_IS_OK(result))
                goto done;
@@ -362,7 +362,7 @@ static WERROR cmd_srvsvc_net_share_get_info(struct cli_state *cli,
        return result;
 }
 
-static WERROR cmd_srvsvc_net_share_set_info(struct cli_state *cli, 
+static WERROR cmd_srvsvc_net_share_set_info(struct rpc_pipe_client *cli, 
                                            TALLOC_CTX *mem_ctx,
                                            int argc, const char **argv)
 {
@@ -376,7 +376,7 @@ static WERROR cmd_srvsvc_net_share_set_info(struct cli_state *cli,
        }
 
        /* retrieve share info */
-       result = cli_srvsvc_net_share_get_info(cli, mem_ctx, argv[1], info_level, &info_get);
+       result = rpccli_srvsvc_net_share_get_info(cli, mem_ctx, argv[1], info_level, &info_get);
        if (!W_ERROR_IS_OK(result))
                goto done;
 
@@ -385,13 +385,13 @@ static WERROR cmd_srvsvc_net_share_set_info(struct cli_state *cli,
        init_unistr2(&(info_get.share.info502.info_502_str.uni_remark), argv[2], UNI_STR_TERMINATE);
        
        /* set share info */
-       result = cli_srvsvc_net_share_set_info(cli, mem_ctx, argv[1], info_level, &info_get);
+       result = rpccli_srvsvc_net_share_set_info(cli, mem_ctx, argv[1], info_level, &info_get);
 
        if (!W_ERROR_IS_OK(result))
                goto done;
 
        /* re-retrieve share info and display */
-       result = cli_srvsvc_net_share_get_info(cli, mem_ctx, argv[1], info_level, &info_get);
+       result = rpccli_srvsvc_net_share_get_info(cli, mem_ctx, argv[1], info_level, &info_get);
        if (!W_ERROR_IS_OK(result))
                goto done;
 
@@ -401,11 +401,12 @@ static WERROR cmd_srvsvc_net_share_set_info(struct cli_state *cli,
        return result;
 }
 
-static WERROR cmd_srvsvc_net_remote_tod(struct cli_state *cli, 
+static WERROR cmd_srvsvc_net_remote_tod(struct rpc_pipe_client *cli, 
                                           TALLOC_CTX *mem_ctx,
                                           int argc, const char **argv)
 {
        TIME_OF_DAY_INFO tod;
+       fstring srv_name_slash;
        WERROR result;
 
        if (argc > 1) {
@@ -413,8 +414,9 @@ static WERROR cmd_srvsvc_net_remote_tod(struct cli_state *cli,
                return WERR_OK;
        }
 
-       result = cli_srvsvc_net_remote_tod(
-               cli, mem_ctx, cli->srv_name_slash, &tod);
+       fstr_sprintf(srv_name_slash, "\\\\%s", cli->cli->desthost);
+       result = rpccli_srvsvc_net_remote_tod(
+               cli, mem_ctx, srv_name_slash, &tod);
 
        if (!W_ERROR_IS_OK(result))
                goto done;
@@ -423,7 +425,7 @@ static WERROR cmd_srvsvc_net_remote_tod(struct cli_state *cli,
        return result;
 }
 
-static WERROR cmd_srvsvc_net_file_enum(struct cli_state *cli, 
+static WERROR cmd_srvsvc_net_file_enum(struct rpc_pipe_client *cli, 
                                         TALLOC_CTX *mem_ctx,
                                         int argc, const char **argv)
 {
@@ -445,7 +447,7 @@ static WERROR cmd_srvsvc_net_file_enum(struct cli_state *cli,
 
        ZERO_STRUCT(ctr);
 
-       result = cli_srvsvc_net_file_enum(
+       result = rpccli_srvsvc_net_file_enum(
                cli, mem_ctx, info_level, NULL, &ctr, preferred_len, &hnd);
 
        if (!W_ERROR_IS_OK(result))
@@ -461,12 +463,12 @@ struct cmd_set srvsvc_commands[] = {
 
        { "SRVSVC" },
 
-       { "srvinfo",     RPC_RTYPE_WERROR, NULL, cmd_srvsvc_srv_query_info, PI_SRVSVC, "Server query info", "" },
-       { "netshareenum",RPC_RTYPE_WERROR, NULL, cmd_srvsvc_net_share_enum, PI_SRVSVC, "Enumerate shares", "" },
-       { "netsharegetinfo",RPC_RTYPE_WERROR, NULL, cmd_srvsvc_net_share_get_info, PI_SRVSVC, "Get Share Info", "" },
-       { "netsharesetinfo",RPC_RTYPE_WERROR, NULL, cmd_srvsvc_net_share_set_info, PI_SRVSVC, "Set Share Info", "" },
-       { "netfileenum", RPC_RTYPE_WERROR, NULL, cmd_srvsvc_net_file_enum,  PI_SRVSVC, "Enumerate open files", "" },
-       { "netremotetod",RPC_RTYPE_WERROR, NULL, cmd_srvsvc_net_remote_tod, PI_SRVSVC, "Fetch remote time of day", "" },
+       { "srvinfo",     RPC_RTYPE_WERROR, NULL, cmd_srvsvc_srv_query_info, PI_SRVSVC, NULL, "Server query info", "" },
+       { "netshareenum",RPC_RTYPE_WERROR, NULL, cmd_srvsvc_net_share_enum, PI_SRVSVC, NULL, "Enumerate shares", "" },
+       { "netsharegetinfo",RPC_RTYPE_WERROR, NULL, cmd_srvsvc_net_share_get_info, PI_SRVSVC, NULL, "Get Share Info", "" },
+       { "netsharesetinfo",RPC_RTYPE_WERROR, NULL, cmd_srvsvc_net_share_set_info, PI_SRVSVC, NULL, "Set Share Info", "" },
+       { "netfileenum", RPC_RTYPE_WERROR, NULL, cmd_srvsvc_net_file_enum,  PI_SRVSVC, NULL, "Enumerate open files", "" },
+       { "netremotetod",RPC_RTYPE_WERROR, NULL, cmd_srvsvc_net_remote_tod, PI_SRVSVC, NULL, "Fetch remote time of day", "" },
 
        { NULL }
 };
diff --git a/source3/rpcclient/cmd_test.c b/source3/rpcclient/cmd_test.c
new file mode 100644 (file)
index 0000000..94545dc
--- /dev/null
@@ -0,0 +1,68 @@
+/* 
+   Unix SMB/CIFS implementation.
+   RPC pipe client
+
+   Copyright (C) Volker Lendecke 2005
+
+   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 "rpcclient.h"
+
+static NTSTATUS cmd_testme(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
+                          int argc, const char **argv)
+{
+       struct rpc_pipe_client *lsa_pipe = NULL, *samr_pipe = NULL;
+       NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
+       POLICY_HND pol;
+
+       d_printf("testme\n");
+
+       lsa_pipe = cli_rpc_pipe_open_noauth(cli->cli, PI_LSARPC, &status);
+       if (lsa_pipe == NULL) goto done;
+
+       samr_pipe = cli_rpc_pipe_open_noauth(cli->cli, PI_SAMR, &status);
+       if (samr_pipe == NULL) goto done;
+
+       status = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, False,
+                                       SEC_RIGHTS_QUERY_VALUE, &pol);
+
+       if (!NT_STATUS_IS_OK(status))
+               goto done;
+
+       status = rpccli_lsa_close(lsa_pipe, mem_ctx, &pol);
+
+       if (!NT_STATUS_IS_OK(status))
+               goto done;
+
+ done:
+       if (lsa_pipe != NULL) cli_rpc_pipe_close(lsa_pipe);
+       if (samr_pipe != NULL) cli_rpc_pipe_close(samr_pipe);
+
+       return status;
+}
+
+/* List of commands exported by this module */
+
+struct cmd_set test_commands[] = {
+
+       { "TESTING" },
+
+       { "testme", RPC_RTYPE_NTSTATUS, cmd_testme, NULL,
+         -1, NULL, "Sample test", "testme" },
+
+       { NULL }
+};
index 137ff3bdae93d09545bd23a43f1fff004c1e84a0..a65cd1f799f9d9678c7b133ea17fdb1d58f5e2aa 100644 (file)
@@ -19,6 +19,8 @@
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
+THIS IS NO LONGER USED - NEEDS REMOVAL.
+
 #include "includes.h"
 
 #define DEBUG_TESTING
index 34e81cafe68d4e44d945cd9bdf8af3cd2184d4dd..630add0e9bd12e925531f028cd3d568d37bc3309 100644 (file)
@@ -25,6 +25,8 @@
 
 DOM_SID domain_sid;
 
+static enum pipe_auth_type pipe_default_auth_type = PIPE_AUTH_TYPE_NONE;
+static enum pipe_auth_level pipe_default_auth_level = PIPE_AUTH_LEVEL_NONE;
 
 /* List to hold groups of commands.
  *
@@ -128,29 +130,28 @@ static void fetch_machine_sid(struct cli_state *cli)
        static BOOL got_domain_sid;
        TALLOC_CTX *mem_ctx;
        DOM_SID *dom_sid = NULL;
+       struct rpc_pipe_client *lsapipe = NULL;
 
        if (got_domain_sid) return;
 
-       if (!(mem_ctx=talloc_init("fetch_machine_sid")))
-       {
+       if (!(mem_ctx=talloc_init("fetch_machine_sid"))) {
                DEBUG(0,("fetch_machine_sid: talloc_init returned NULL!\n"));
                goto error;
        }
 
-
-       if (!cli_nt_session_open (cli, PI_LSARPC)) {
-               fprintf(stderr, "could not initialise lsa pipe\n");
+       if ((lsapipe = cli_rpc_pipe_open_noauth(cli, PI_LSARPC, &result)) == NULL) {
+               fprintf(stderr, "could not initialise lsa pipe. Error was %s\n", nt_errstr(result) );
                goto error;
        }
        
-       result = cli_lsa_open_policy(cli, mem_ctx, True, 
+       result = rpccli_lsa_open_policy(lsapipe, mem_ctx, True, 
                                     SEC_RIGHTS_MAXIMUM_ALLOWED,
                                     &pol);
        if (!NT_STATUS_IS_OK(result)) {
                goto error;
        }
 
-       result = cli_lsa_query_info_policy(cli, mem_ctx, &pol, info_class, 
+       result = rpccli_lsa_query_info_policy(lsapipe, mem_ctx, &pol, info_class, 
                                           &domain_name, &dom_sid);
        if (!NT_STATUS_IS_OK(result)) {
                goto error;
@@ -159,13 +160,18 @@ static void fetch_machine_sid(struct cli_state *cli)
        got_domain_sid = True;
        sid_copy( &domain_sid, dom_sid );
 
-       cli_lsa_close(cli, mem_ctx, &pol);
-       cli_nt_session_close(cli);
+       rpccli_lsa_close(lsapipe, mem_ctx, &pol);
+       cli_rpc_pipe_close(lsapipe);
        talloc_destroy(mem_ctx);
 
        return;
 
  error:
+
+       if (lsapipe) {
+               cli_rpc_pipe_close(lsapipe);
+       }
+
        fprintf(stderr, "could not obtain sid for domain %s\n", cli->domain);
 
        if (!NT_STATUS_IS_OK(result)) {
@@ -177,7 +183,7 @@ static void fetch_machine_sid(struct cli_state *cli)
 
 /* List the available commands on a given pipe */
 
-static NTSTATUS cmd_listcommands(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+static NTSTATUS cmd_listcommands(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                 int argc, const char **argv)
 {
        struct cmd_list *tmp;
@@ -222,7 +228,7 @@ static NTSTATUS cmd_listcommands(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 
 /* Display help on commands */
 
-static NTSTATUS cmd_help(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+static NTSTATUS cmd_help(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                          int argc, const char **argv)
 {
        struct cmd_list *tmp;
@@ -282,7 +288,7 @@ static NTSTATUS cmd_help(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 
 /* Change the debug level */
 
-static NTSTATUS cmd_debuglevel(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+static NTSTATUS cmd_debuglevel(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                int argc, const char **argv)
 {
        if (argc > 2) {
@@ -299,114 +305,118 @@ static NTSTATUS cmd_debuglevel(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        return NT_STATUS_OK;
 }
 
-static NTSTATUS cmd_quit(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+static NTSTATUS cmd_quit(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                          int argc, const char **argv)
 {
        exit(0);
        return NT_STATUS_OK; /* NOTREACHED */
 }
 
-static NTSTATUS cmd_sign(struct cli_state *cli, TALLOC_CTX *mem_ctx,
-                         int argc, const char **argv)
+static NTSTATUS cmd_set_ss_level(void)
 {
-       if (cli->pipe_auth_flags == (AUTH_PIPE_NTLMSSP|AUTH_PIPE_SIGN)) {
-               return NT_STATUS_OK;
-       } else {
-               /* still have session, just need to use it again */
-               cli->pipe_auth_flags = AUTH_PIPE_NTLMSSP;
-               cli->pipe_auth_flags |= AUTH_PIPE_SIGN;
-               if (cli->pipes[cli->pipe_idx].fnum != 0)
-                       cli_nt_session_close(cli);
-       }
+       struct cmd_list *tmp;
 
-       return NT_STATUS_OK; 
-}
+       /* Close any existing connections not at this level. */
 
-static NTSTATUS cmd_seal(struct cli_state *cli, TALLOC_CTX *mem_ctx,
-                         int argc, const char **argv)
-{
-       if (cli->pipe_auth_flags == (AUTH_PIPE_NTLMSSP|AUTH_PIPE_SIGN|AUTH_PIPE_SEAL)) {
-               return NT_STATUS_OK;
-       } else {
-               /* still have session, just need to use it again */
-               cli->pipe_auth_flags = AUTH_PIPE_NTLMSSP;
-               cli->pipe_auth_flags |= AUTH_PIPE_SIGN;
-               cli->pipe_auth_flags |= AUTH_PIPE_SEAL;
-               if (cli->pipes[cli->pipe_idx].fnum != 0)
-                       cli_nt_session_close(cli);
-       }
-       return NT_STATUS_OK; 
+       for (tmp = cmd_list; tmp; tmp = tmp->next) {
+               struct cmd_set *tmp_set;
+
+               for (tmp_set = tmp->cmd_set; tmp_set->name; tmp_set++) {
+                       if (tmp_set->rpc_pipe == NULL) {
+                               continue;
+                       }
+
+                       if (tmp_set->rpc_pipe->auth.auth_type != pipe_default_auth_type ||
+                                       tmp_set->rpc_pipe->auth.auth_level != pipe_default_auth_level) {
+                               cli_rpc_pipe_close(tmp_set->rpc_pipe);
+                               tmp_set->rpc_pipe = NULL;
+                       }
+               }
+       }
+       return NT_STATUS_OK;
 }
 
-static NTSTATUS cmd_none(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+static NTSTATUS cmd_sign(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                          int argc, const char **argv)
 {
-       if (cli->pipe_auth_flags == 0) {
+       pipe_default_auth_level = PIPE_AUTH_LEVEL_INTEGRITY;
+       pipe_default_auth_type = PIPE_AUTH_TYPE_NTLMSSP;
+
+       if (argc > 2) {
+               printf("Usage: %s [NTLMSSP|NTLMSSP_SPNEGO|SCHANNEL]\n", argv[0]);
                return NT_STATUS_OK;
-       } else {
-               /* still have session, just need to use it again */
-               cli->pipe_auth_flags = 0;
-               if (cli->pipes[cli->pipe_idx].fnum != 0)
-                       cli_nt_session_close(cli);
        }
-       cli->pipe_auth_flags = 0;
 
-       return NT_STATUS_OK; 
-}
-
-static NTSTATUS setup_schannel(struct cli_state *cli, int pipe_auth_flags,
-                              int argc, const char **argv)
-{
-       NTSTATUS ret;
-       static uchar zeros[16];
-       uchar trust_password[16];
-       uint32 sec_channel_type;
        if (argc == 2) {
-               strhex_to_str(cli->sess_key, strlen(argv[1]), argv[1]);
-               cli->pipe_auth_flags = pipe_auth_flags;
-               return NT_STATUS_OK;
+               if (strequal(argv[1], "NTLMSSP")) {
+                       pipe_default_auth_type = PIPE_AUTH_TYPE_NTLMSSP;
+               } else if (strequal(argv[1], "NTLMSSP_SPNEGO")) {
+                       pipe_default_auth_type = PIPE_AUTH_TYPE_SPNEGO_NTLMSSP;
+               } else if (strequal(argv[1], "SCHANNEL")) {
+                       pipe_default_auth_type = PIPE_AUTH_TYPE_SCHANNEL;
+               } else {
+                       printf("unknown type %s\n", argv[1]);
+                       return NT_STATUS_INVALID_LEVEL;
+               }
        }
 
-       /* Cleanup */
+       printf("debuglevel is %d\n", DEBUGLEVEL);
+       return cmd_set_ss_level();
+}
 
-       if ((memcmp(cli->sess_key, zeros, sizeof(cli->sess_key)) != 0) &&
-           (cli->pipe_auth_flags == pipe_auth_flags)) {
-                       /* already in this mode nothing to do */
-                       return NT_STATUS_OK;
-       }
-       
-       if (!secrets_fetch_trust_account_password(lp_workgroup(),
-                                                 trust_password,
-                                                 NULL, &sec_channel_type)) {
-               return NT_STATUS_UNSUCCESSFUL;
+static NTSTATUS cmd_seal(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
+                         int argc, const char **argv)
+{
+       pipe_default_auth_level = PIPE_AUTH_LEVEL_PRIVACY;
+       pipe_default_auth_type = PIPE_AUTH_TYPE_NTLMSSP;
+
+       if (argc > 2) {
+               printf("Usage: %s [NTLMSSP|NTLMSSP_SPNEGO|SCHANNEL]\n", argv[0]);
+               return NT_STATUS_OK;
        }
 
-       ret = cli_nt_setup_netsec(cli, sec_channel_type, pipe_auth_flags, trust_password);
-       if (NT_STATUS_IS_OK(ret)) {
-               char *hex_session_key;
-               hex_session_key = hex_encode(NULL, cli->pipes[cli->pipe_idx].auth_info.sess_key,
-                                            sizeof(cli->pipes[cli->pipe_idx].auth_info.sess_key));
-               printf("Got Session key: %s\n", hex_session_key);
-               talloc_free(hex_session_key);
+       if (argc == 2) {
+               if (strequal(argv[1], "NTLMSSP")) {
+                       pipe_default_auth_type = PIPE_AUTH_TYPE_NTLMSSP;
+               } else if (strequal(argv[1], "NTLMSSP_SPNEGO")) {
+                       pipe_default_auth_type = PIPE_AUTH_TYPE_SPNEGO_NTLMSSP;
+               } else if (strequal(argv[1], "SCHANNEL")) {
+                       pipe_default_auth_type = PIPE_AUTH_TYPE_SCHANNEL;
+               } else {
+                       printf("unknown type %s\n", argv[1]);
+                       return NT_STATUS_INVALID_LEVEL;
+               }
        }
-       return ret;
+       return cmd_set_ss_level();
 }
 
+static NTSTATUS cmd_none(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
+                         int argc, const char **argv)
+{
+       pipe_default_auth_level = PIPE_AUTH_LEVEL_NONE;
+       pipe_default_auth_type = PIPE_AUTH_TYPE_NONE;
+
+       return cmd_set_ss_level();
+}
 
-static NTSTATUS cmd_schannel(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+static NTSTATUS cmd_schannel(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                             int argc, const char **argv)
 {
        d_printf("Setting schannel - sign and seal\n");
-       return setup_schannel(cli, AUTH_PIPE_NETSEC | AUTH_PIPE_SIGN | AUTH_PIPE_SEAL, 
-                             argc, argv);
+       pipe_default_auth_level = PIPE_AUTH_LEVEL_PRIVACY;
+       pipe_default_auth_type = PIPE_AUTH_TYPE_SCHANNEL;
+
+       return cmd_set_ss_level();
 }
 
-static NTSTATUS cmd_schannel_sign(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+static NTSTATUS cmd_schannel_sign(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                             int argc, const char **argv)
 {
        d_printf("Setting schannel - sign only\n");
-       return setup_schannel(cli, AUTH_PIPE_NETSEC | AUTH_PIPE_SIGN, 
-                             argc, argv);
+       pipe_default_auth_level = PIPE_AUTH_LEVEL_INTEGRITY;
+       pipe_default_auth_type = PIPE_AUTH_TYPE_SCHANNEL;
+
+       return cmd_set_ss_level();
 }
 
 
@@ -416,23 +426,23 @@ static struct cmd_set rpcclient_commands[] = {
 
        { "GENERAL OPTIONS" },
 
-       { "help", RPC_RTYPE_NTSTATUS, cmd_help, NULL,     -1,   "Get help on commands", "[command]" },
-       { "?",  RPC_RTYPE_NTSTATUS, cmd_help, NULL,       -1,   "Get help on commands", "[command]" },
-       { "debuglevel", RPC_RTYPE_NTSTATUS, cmd_debuglevel, NULL,   -1, "Set debug level", "level" },
-       { "list",       RPC_RTYPE_NTSTATUS, cmd_listcommands, NULL, -1, "List available commands on <pipe>", "pipe" },
-       { "exit", RPC_RTYPE_NTSTATUS, cmd_quit, NULL,   -1,     "Exit program", "" },
-       { "quit", RPC_RTYPE_NTSTATUS, cmd_quit, NULL,     -1,   "Exit program", "" },
-       { "sign", RPC_RTYPE_NTSTATUS, cmd_sign, NULL,     -1,   "Force RPC pipe connections to be signed", "" },
-       { "seal", RPC_RTYPE_NTSTATUS, cmd_seal, NULL,     -1,   "Force RPC pipe connections to be sealed", "" },
-       { "schannel", RPC_RTYPE_NTSTATUS, cmd_schannel, NULL,     -1,   "Force RPC pipe connections to be sealed with 'schannel' (NETSEC).  Assumes valid machine account to this domain controller.", "" },
-       { "schannelsign", RPC_RTYPE_NTSTATUS, cmd_schannel_sign, NULL,    -1,   "Force RPC pipe connections to be signed (not sealed) with 'schannel' (NETSEC).  Assumes valid machine account to this domain controller.", "" },
-       { "none", RPC_RTYPE_NTSTATUS, cmd_none, NULL,     -1,   "Force RPC pipe connections to have no special properties", "" },
+       { "help", RPC_RTYPE_NTSTATUS, cmd_help, NULL,     -1, NULL,     "Get help on commands", "[command]" },
+       { "?",  RPC_RTYPE_NTSTATUS, cmd_help, NULL,       -1, NULL,     "Get help on commands", "[command]" },
+       { "debuglevel", RPC_RTYPE_NTSTATUS, cmd_debuglevel, NULL,   -1, NULL, "Set debug level", "level" },
+       { "list",       RPC_RTYPE_NTSTATUS, cmd_listcommands, NULL, -1, NULL, "List available commands on <pipe>", "pipe" },
+       { "exit", RPC_RTYPE_NTSTATUS, cmd_quit, NULL,   -1,     NULL,   "Exit program", "" },
+       { "quit", RPC_RTYPE_NTSTATUS, cmd_quit, NULL,     -1,   NULL, "Exit program", "" },
+       { "sign", RPC_RTYPE_NTSTATUS, cmd_sign, NULL,     -1,   NULL, "Force RPC pipe connections to be signed", "" },
+       { "seal", RPC_RTYPE_NTSTATUS, cmd_seal, NULL,     -1,   NULL, "Force RPC pipe connections to be sealed", "" },
+       { "schannel", RPC_RTYPE_NTSTATUS, cmd_schannel, NULL,     -1, NULL,     "Force RPC pipe connections to be sealed with 'schannel'.  Assumes valid machine account to this domain controller.", "" },
+       { "schannelsign", RPC_RTYPE_NTSTATUS, cmd_schannel_sign, NULL,    -1, NULL, "Force RPC pipe connections to be signed (not sealed) with 'schannel'.  Assumes valid machine account to this domain controller.", "" },
+       { "none", RPC_RTYPE_NTSTATUS, cmd_none, NULL,     -1, NULL, "Force RPC pipe connections to have no special properties", "" },
 
        { NULL }
 };
 
 static struct cmd_set separator_command[] = {
-       { "---------------", MAX_RPC_RETURN_TYPE, NULL, NULL,   -1,     "----------------------" },
+       { "---------------", MAX_RPC_RETURN_TYPE, NULL, NULL,   -1, NULL, "----------------------" },
        { NULL }
 };
 
@@ -449,6 +459,7 @@ extern struct cmd_set reg_commands[];
 extern struct cmd_set ds_commands[];
 extern struct cmd_set echo_commands[];
 extern struct cmd_set shutdown_commands[];
+extern struct cmd_set test_commands[];
 
 static struct cmd_set *rpcclient_command_list[] = {
        rpcclient_commands,
@@ -462,6 +473,7 @@ static struct cmd_set *rpcclient_command_list[] = {
        reg_commands,
        echo_commands,
        shutdown_commands,
+       test_commands,
        NULL
 };
 
@@ -492,7 +504,6 @@ static NTSTATUS do_cmd(struct cli_state *cli,
 {
        NTSTATUS ntresult;
        WERROR wresult;
-       uchar trust_password[16];
        
        TALLOC_CTX *mem_ctx;
 
@@ -505,57 +516,93 @@ static NTSTATUS do_cmd(struct cli_state *cli,
 
        /* Open pipe */
 
-       if (cmd_entry->pipe_idx != -1
-           && cmd_entry->pipe_idx != cli->pipe_idx) {
-               if (cli->pipes[cli->pipe_idx].fnum != 0)
-                       cli_nt_session_close(cli);
-               
-               if (!cli_nt_session_open(cli, cmd_entry->pipe_idx)) {
-                       DEBUG(0, ("Could not initialise %s\n",
-                                 get_pipe_name_from_index(cmd_entry->pipe_idx)));
-                       return NT_STATUS_UNSUCCESSFUL;
+       if (cmd_entry->pipe_idx != -1 && cmd_entry->rpc_pipe == NULL) {
+               switch (pipe_default_auth_type) {
+                       case PIPE_AUTH_TYPE_NONE:
+                               cmd_entry->rpc_pipe = cli_rpc_pipe_open_noauth(cli,
+                                                               cmd_entry->pipe_idx,
+                                                               &ntresult);
+                               break;
+                       case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP:
+                               cmd_entry->rpc_pipe = cli_rpc_pipe_open_spnego_ntlmssp(cli,
+                                                               cmd_entry->pipe_idx,
+                                                               pipe_default_auth_level,
+                                                               lp_workgroup(),
+                                                               cmdline_auth_info.username,
+                                                               cmdline_auth_info.password,
+                                                               &ntresult);
+                               break;
+                       case PIPE_AUTH_TYPE_NTLMSSP:
+                               cmd_entry->rpc_pipe = cli_rpc_pipe_open_ntlmssp(cli,
+                                                               cmd_entry->pipe_idx,
+                                                               pipe_default_auth_level,
+                                                               lp_workgroup(),
+                                                               cmdline_auth_info.username,
+                                                               cmdline_auth_info.password,
+                                                               &ntresult);
+                               break;
+                       case PIPE_AUTH_TYPE_SCHANNEL:
+                               cmd_entry->rpc_pipe = cli_rpc_pipe_open_schannel(cli,
+                                                               cmd_entry->pipe_idx,
+                                                               pipe_default_auth_level,
+                                                               lp_workgroup(),
+                                                               &ntresult);
+                               break;
+                       default:
+                               DEBUG(0, ("Could not initialise %s. Invalid auth type %u\n",
+                                       cli_get_pipe_name(cmd_entry->pipe_idx),
+                                       pipe_default_auth_type ));
+                               return NT_STATUS_UNSUCCESSFUL;
+               }
+               if (!cmd_entry->rpc_pipe) {
+                       DEBUG(0, ("Could not initialise %s. Error was %s\n",
+                               cli_get_pipe_name(cmd_entry->pipe_idx),
+                               nt_errstr(ntresult) ));
+                       return ntresult;
                }
-       }
-
-       /* some of the DsXXX commands use the netlogon pipe */
 
-       if (lp_client_schannel() && (cmd_entry->pipe_idx == PI_NETLOGON) && !(cli->pipe_auth_flags & AUTH_PIPE_NETSEC)) {
-               uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS;
-               uint32 sec_channel_type;
+               if (cmd_entry->pipe_idx == PI_NETLOGON) {
+                       uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS;
+                       uint32 sec_channel_type;
+                       uchar trust_password[16];
        
-               if (!secrets_fetch_trust_account_password(lp_workgroup(),
-                                                         trust_password,
-                                                         NULL, &sec_channel_type)) {
-                       return NT_STATUS_UNSUCCESSFUL;
-               }
+                       if (!secrets_fetch_trust_account_password(lp_workgroup(),
+                                                       trust_password,
+                                                       NULL, &sec_channel_type)) {
+                               return NT_STATUS_UNSUCCESSFUL;
+                       }
                
-               ntresult = cli_nt_setup_creds(cli, sec_channel_type, 
-                                             trust_password,
-                                             &neg_flags, 2);
-               if (!NT_STATUS_IS_OK(ntresult)) {
-                       ZERO_STRUCT(cli->pipes[cli->pipe_idx].auth_info.sess_key);
-                       printf("nt_setup_creds failed with %s\n", nt_errstr(ntresult));
-                       return ntresult;
+                       ntresult = rpccli_netlogon_setup_creds(cmd_entry->rpc_pipe,
+                                               cli->desthost,
+                                               lp_workgroup(),
+                                               global_myname(),
+                                               trust_password,
+                                               sec_channel_type,
+                                               &neg_flags);
+
+                       if (!NT_STATUS_IS_OK(ntresult)) {
+                               DEBUG(0, ("Could not initialise credentials for %s.\n",
+                                       cli_get_pipe_name(cmd_entry->pipe_idx)));
+                               return ntresult;
+                       }
                }
-               
        }
 
-     /* Run command */
+       /* Run command */
 
-     if ( cmd_entry->returntype == RPC_RTYPE_NTSTATUS ) {
-          ntresult = cmd_entry->ntfn(cli, mem_ctx, argc, (const char **) argv);
-          if (!NT_STATUS_IS_OK(ntresult)) {
-              printf("result was %s\n", nt_errstr(ntresult));
-          }
-     } else {
-          wresult = cmd_entry->wfn( cli, mem_ctx, argc, (const char **) argv);
-          /* print out the DOS error */
-          if (!W_ERROR_IS_OK(wresult)) {
-                  printf( "result was %s\n", dos_errstr(wresult));
-          }
-          ntresult = W_ERROR_IS_OK(wresult)?NT_STATUS_OK:NT_STATUS_UNSUCCESSFUL;
-     }
-            
+       if ( cmd_entry->returntype == RPC_RTYPE_NTSTATUS ) {
+               ntresult = cmd_entry->ntfn(cmd_entry->rpc_pipe, mem_ctx, argc, (const char **) argv);
+               if (!NT_STATUS_IS_OK(ntresult)) {
+                       printf("result was %s\n", nt_errstr(ntresult));
+               }
+       } else {
+               wresult = cmd_entry->wfn(cmd_entry->rpc_pipe, mem_ctx, argc, (const char **) argv);
+               /* print out the DOS error */
+               if (!W_ERROR_IS_OK(wresult)) {
+                       printf( "result was %s\n", dos_errstr(wresult));
+               }
+               ntresult = W_ERROR_IS_OK(wresult)?NT_STATUS_OK:NT_STATUS_UNSUCCESSFUL;
+       }
 
        /* Cleanup */
 
@@ -736,7 +783,9 @@ out_free:
                return 1;
        }
 
+#if 0  /* COMMENT OUT FOR TESTING */
        memset(cmdline_auth_info.password,'X',sizeof(cmdline_auth_info.password));
+#endif
 
        /* Load command lists */
 
index e1e61dc43d555223002d70b1038524fd48c1f61c..3c86c0be62eecd8a8bd249a653ef28db552c5d1b 100644 (file)
@@ -30,11 +30,12 @@ typedef enum {
 
 struct cmd_set {
        const char *name;
-        RPC_RETURN_TYPE returntype;
-       NTSTATUS (*ntfn)(struct cli_state *cli, TALLOC_CTX *mem_ctx, int argc, 
-                       const char **argv);
-        WERROR (*wfn)(struct cli_state *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv);
-        int pipe_idx;
+       RPC_RETURN_TYPE returntype;
+       NTSTATUS (*ntfn)(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, 
+                       const char **argv);
+       WERROR (*wfn)(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv);
+       int pipe_idx;
+       struct rpc_pipe_client *rpc_pipe;
        const char *description;
        const char *usage;
 };
index 0ba97946965ce65d01554d22cfba56f7449f08bc..4a1ae141b106ae8ac87851382d4729065de2a10b 100644 (file)
@@ -142,6 +142,7 @@ static NTSTATUS rid_idmap_get_domains(uint32 *num_domains, fstring **domain_name
 {
        NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
        struct cli_state *cli;
+       struct rpc_pipe_client *pipe_hnd;
        TALLOC_CTX *mem_ctx;
        POLICY_HND pol;
        uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
@@ -233,18 +234,22 @@ static NTSTATUS rid_idmap_get_domains(uint32 *num_domains, fstring **domain_name
        }       
 
        /* query the lsa-pipe */
-       if (!cli_nt_session_open (cli, PI_LSARPC)) {
+       pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_LSARPC, &status);
+       if (!NT_STATUS_IS_OK(status)) {
                DEBUG(1, ("rid_idmap_get_domains: could not setup connection to dc\n"));
                goto out;
        }
 
        /* query policies */
-       status = cli_lsa_open_policy(cli, mem_ctx, False, des_access, &pol);
+       status = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, False, des_access,
+                                       &pol);
        if (!NT_STATUS_IS_OK(status)) {
                goto out;
        }
 
-       status = cli_lsa_query_info_policy(cli, mem_ctx, &pol, info_class, &domain_name, &domain_sid);
+       status = rpccli_lsa_query_info_policy(pipe_hnd, mem_ctx, &pol,
+                                             info_class, &domain_name,
+                                             &domain_sid);
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(1, ("rid_idmap_get_domains: cannot retrieve domain-info\n"));
                goto out;
@@ -255,10 +260,10 @@ static NTSTATUS rid_idmap_get_domains(uint32 *num_domains, fstring **domain_name
 
        /* scan trusted domains */
        DEBUG(10, ("rid_idmap_get_domains: enumerating trusted domains\n"));
-       status = cli_lsa_enum_trust_dom(cli, mem_ctx, &pol, &enum_ctx,
-                       &trusted_num_domains,
-                       &trusted_domain_names, 
-                       &trusted_domain_sids);
+       status = rpccli_lsa_enum_trust_dom(pipe_hnd, mem_ctx, &pol, &enum_ctx,
+                                          &trusted_num_domains,
+                                          &trusted_domain_names, 
+                                          &trusted_domain_sids);
 
        if (!NT_STATUS_IS_OK(status) &&
            !NT_STATUS_EQUAL(status, NT_STATUS_NO_MORE_ENTRIES) &&
@@ -315,8 +320,8 @@ static NTSTATUS rid_idmap_get_domains(uint32 *num_domains, fstring **domain_name
        status = NT_STATUS_OK;
 
 out:
-       cli_lsa_close(cli, mem_ctx, &pol);
-       cli_nt_session_close(cli);
+       rpccli_lsa_close(pipe_hnd, mem_ctx, &pol);
+       cli_rpc_pipe_close(pipe_hnd);
        talloc_destroy(mem_ctx);
        cli_shutdown(cli);
 
diff --git a/source3/sam/idmap_smbldap.c b/source3/sam/idmap_smbldap.c
new file mode 100644 (file)
index 0000000..b1aae2b
--- /dev/null
@@ -0,0 +1,453 @@
+/*
+   Unix SMB/CIFS implementation.
+
+   idmap LDAP backend
+
+   Copyright (C) Tim Potter            2000
+   Copyright (C) Jim McDonough <jmcd@us.ibm.com>       2003
+   Copyright (C) Simo Sorce            2003
+   Copyright (C) Gerald Carter                 2003
+
+   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"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_IDMAP
+
+struct ldap_connection *ldap_conn = NULL;
+
+/* number tries while allocating new id */
+#define LDAP_MAX_ALLOC_ID 128
+
+
+/***********************************************************************
+ This function cannot be called to modify a mapping, only set a new one
+***********************************************************************/
+
+static NTSTATUS ldap_set_mapping(const DOM_SID *sid, unid_t id, int id_type)
+{
+       NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+       pstring id_str;
+       const char *type;
+       fstring sid_string;
+       struct ldap_message *msg;
+       struct ldap_message *mod_res = NULL;
+       char *mod;
+
+       type = (id_type & ID_USERID) ? "uidNumber" : "gidNumber";
+
+       sid_to_string( sid_string, sid );
+
+       pstr_sprintf(id_str, "%lu",
+                    ((id_type & ID_USERID) ?
+                     (unsigned long)id.uid : (unsigned long)id.gid));
+
+       asprintf(&mod,
+                "dn: sambaSID=%s,%s\n"
+                "changetype: add\n"
+                "objectClass: sambaIdmapEntry\n"
+                "objectClass: sambaSidEntry\n"
+                "sambaSID: %s\n"
+                "%s: %lu\n",
+                sid_string, lp_ldap_idmap_suffix(), sid_string, type,
+                ((id_type & ID_USERID) ?
+                 (unsigned long)id.uid : (unsigned long)id.gid));
+
+       msg = ldap_ldif2msg(mod);
+
+       SAFE_FREE(mod);
+
+       if (msg == NULL)
+               return NT_STATUS_NO_MEMORY;
+
+       mod_res = ldap_transaction(ldap_conn, msg);
+
+       if ((mod_res == NULL) || (mod_res->r.ModifyResponse.resultcode != 0))
+               goto out;
+
+       ret = NT_STATUS_OK;
+ out:
+       destroy_ldap_message(msg);
+       destroy_ldap_message(mod_res);
+       return ret;
+}
+
+/*****************************************************************************
+ Allocate a new RID
+*****************************************************************************/
+
+static NTSTATUS ldap_allocate_rid(uint32 *rid, int rid_type)
+{
+       return NT_STATUS_UNSUCCESSFUL;
+}
+
+/*****************************************************************************
+ Allocate a new uid or gid
+*****************************************************************************/
+
+static NTSTATUS ldap_allocate_id(unid_t *id, int id_type)
+{
+       NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+       uid_t   luid, huid;
+       gid_t   lgid, hgid;
+       const char *attrs[] = { "uidNumber", "gidNumber" };
+       struct ldap_message *idpool_s = NULL;
+       struct ldap_message *idpool = NULL;
+       struct ldap_message *mod_msg = NULL;
+       struct ldap_message *mod_res = NULL;
+       int value;
+       const char *id_attrib;
+       char *mod;
+
+       id_attrib = (id_type & ID_USERID) ? "uidNumber" : "gidNumber";
+
+       idpool_s = new_ldap_search_message(lp_ldap_suffix(),
+                                          LDAP_SEARCH_SCOPE_SUB,
+                                          "(objectclass=sambaUnixIdPool)",
+                                          2, attrs);
+
+       if (idpool_s == NULL)
+               return NT_STATUS_NO_MEMORY;
+
+       idpool = ldap_searchone(ldap_conn, idpool_s, NULL);
+
+       if (idpool == NULL)
+               goto out;
+
+       if (!ldap_find_single_int(idpool, id_attrib, &value))
+               goto out;
+
+       /* this must succeed or else we wouldn't have initialized */
+               
+       lp_idmap_uid( &luid, &huid);
+       lp_idmap_gid( &lgid, &hgid);
+       
+       /* make sure we still have room to grow */
+       
+       if (id_type & ID_USERID) {
+               id->uid = value;
+               if (id->uid > huid ) {
+                       DEBUG(0,("ldap_allocate_id: Cannot allocate uid "
+                                "above %lu!\n",  (unsigned long)huid));
+                       goto out;
+               }
+       }
+       else { 
+               id->gid = value;
+               if (id->gid > hgid ) {
+                       DEBUG(0,("ldap_allocate_id: Cannot allocate gid "
+                                "above %lu!\n", (unsigned long)hgid));
+                       goto out;
+               }
+       }
+       
+       asprintf(&mod,
+                "dn: %s\n"
+                "changetype: modify\n"
+                "delete: %s\n"
+                "%s: %d\n"
+                "-\n"
+                "add: %s\n"
+                "%s: %d\n",
+                idpool->r.SearchResultEntry.dn, id_attrib, id_attrib, value,
+                id_attrib, id_attrib, value+1);
+
+       mod_msg = ldap_ldif2msg(mod);
+
+       SAFE_FREE(mod);
+
+       if (mod_msg == NULL)
+               goto out;
+
+       mod_res = ldap_transaction(ldap_conn, mod_msg);
+
+       if ((mod_res == NULL) || (mod_res->r.ModifyResponse.resultcode != 0))
+               goto out;
+
+       ret = NT_STATUS_OK;
+out:
+       destroy_ldap_message(idpool_s);
+       destroy_ldap_message(idpool);
+       destroy_ldap_message(mod_msg);
+       destroy_ldap_message(mod_res);
+
+       return ret;
+}
+
+/*****************************************************************************
+ get a sid from an id
+*****************************************************************************/
+
+static NTSTATUS ldap_get_sid_from_id(DOM_SID *sid, unid_t id, int id_type)
+{
+       pstring filter;
+       const char *type;
+       NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+       const char *attr_list[] = { "sambaSID" };
+       struct ldap_message *msg;
+       struct ldap_message *entry = NULL;
+       char *sid_str;
+
+       type = (id_type & ID_USERID) ? "uidNumber" : "gidNumber";
+
+       pstr_sprintf(filter, "(&(objectClass=%s)(%s=%lu))", "sambaIdmapEntry",
+                    type,
+                    ((id_type & ID_USERID) ?
+                     (unsigned long)id.uid : (unsigned long)id.gid));
+
+       msg = new_ldap_search_message(lp_ldap_idmap_suffix(),
+                                     LDAP_SEARCH_SCOPE_SUB,
+                                     filter, 1, attr_list);
+
+       if (msg == NULL)
+               return NT_STATUS_NO_MEMORY;
+
+       entry = ldap_searchone(ldap_conn, msg, NULL);
+
+       if (entry == NULL)
+               goto out;
+
+       if (!ldap_find_single_string(entry, "sambaSID", entry->mem_ctx,
+                                    &sid_str))
+               goto out;
+
+       if (!string_to_sid(sid, sid_str))
+               goto out;
+
+       ret = NT_STATUS_OK;
+out:
+       destroy_ldap_message(msg);
+       destroy_ldap_message(entry);
+
+       return ret;
+}
+
+/***********************************************************************
+ Get an id from a sid 
+***********************************************************************/
+
+static NTSTATUS ldap_get_id_from_sid(unid_t *id, int *id_type,
+                                    const DOM_SID *sid)
+{
+       pstring filter;
+       const char *type;
+       NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
+       struct ldap_message *msg;
+       struct ldap_message *entry = NULL;
+       int i;
+
+       DEBUG(8,("ldap_get_id_from_sid: %s (%s)\n", sid_string_static(sid),
+               (*id_type & ID_GROUPID ? "group" : "user") ));
+
+       type = ((*id_type) & ID_USERID) ? "uidNumber" : "gidNumber";
+
+       pstr_sprintf(filter, "(&(objectClass=%s)(%s=%s))", 
+                    "sambaIdmapEntry", "sambaSID", sid_string_static(sid));
+
+       msg = new_ldap_search_message(lp_ldap_idmap_suffix(),
+                                     LDAP_SEARCH_SCOPE_SUB,
+                                     filter, 1, &type);
+
+       if (msg == NULL)
+               return NT_STATUS_NO_MEMORY;
+
+       entry = ldap_searchone(ldap_conn, msg, NULL);
+
+       if (entry != NULL) {
+               int value;
+
+               if (!ldap_find_single_int(entry, type, &value))
+                       goto out;
+
+               if ((*id_type) & ID_USERID)
+                       id->uid = value;
+               else
+                       id->gid = value;
+
+               ret = NT_STATUS_OK;
+               goto out;
+       }
+
+       if ((*id_type) & ID_QUERY_ONLY)
+               goto out;
+
+       /* Allocate a new RID */
+
+       for (i = 0; i < LDAP_MAX_ALLOC_ID; i++) {
+               ret = ldap_allocate_id(id, *id_type);
+               if ( NT_STATUS_IS_OK(ret) )
+                       break;
+       }
+               
+       if ( !NT_STATUS_IS_OK(ret) ) {
+               DEBUG(0,("Could not allocate id\n"));
+               goto out;
+       }
+
+       DEBUG(10,("ldap_get_id_from_sid: Allocated new %cid [%ul]\n",
+                 (*id_type & ID_GROUPID ? 'g' : 'u'), (uint32)id->uid ));
+
+       ret = ldap_set_mapping(sid, *id, *id_type);
+
+out:
+       destroy_ldap_message(msg);
+       destroy_ldap_message(entry);
+
+       return ret;
+}
+
+/**********************************************************************
+ Verify the sambaUnixIdPool entry in the directory.  
+**********************************************************************/
+static NTSTATUS verify_idpool(void)
+{
+       const char *attr_list[3] = { "uidnumber", "gidnumber", "objectclass" };
+       BOOL result;
+       char *mod;
+       struct ldap_message *msg, *entry, *res;
+
+       uid_t   luid, huid;
+       gid_t   lgid, hgid;
+
+       msg = new_ldap_search_message(lp_ldap_suffix(),
+                                     LDAP_SEARCH_SCOPE_SUB,
+                                     "(objectClass=sambaUnixIdPool)",
+                                     3, attr_list);
+
+       if (msg == NULL)
+               return NT_STATUS_NO_MEMORY;
+
+       entry = ldap_searchone(ldap_conn, msg, NULL);
+
+       result = (entry != NULL);
+
+       destroy_ldap_message(msg);
+       destroy_ldap_message(entry);
+
+       if (result)
+               return NT_STATUS_OK;
+
+       if ( !lp_idmap_uid(&luid, &huid) || !lp_idmap_gid( &lgid, &hgid ) ) {
+               DEBUG(3,("ldap_idmap_init: idmap uid/gid parameters not "
+                        "specified\n"));
+               return NT_STATUS_UNSUCCESSFUL;
+       }
+
+       asprintf(&mod,
+                "dn: %s\n"
+                "changetype: modify\n"
+                "add: objectClass\n"
+                "objectClass: sambaUnixIdPool\n"
+                "-\n"
+                "add: uidNumber\n"
+                "uidNumber: %lu\n"
+                "-\n"
+                "add: gidNumber\n"
+                "gidNumber: %lu\n",
+                lp_ldap_idmap_suffix(),
+                (unsigned long)luid, (unsigned long)lgid);
+                
+       msg = ldap_ldif2msg(mod);
+
+       SAFE_FREE(mod);
+
+       if (msg == NULL)
+               return NT_STATUS_NO_MEMORY;
+
+       res = ldap_transaction(ldap_conn, msg);
+
+       if ((res == NULL) || (res->r.ModifyResponse.resultcode != 0)) {
+               destroy_ldap_message(msg);
+               destroy_ldap_message(res);
+               DEBUG(5, ("Could not add sambaUnixIdPool\n"));
+               return NT_STATUS_UNSUCCESSFUL;
+       }
+
+       destroy_ldap_message(msg);
+       destroy_ldap_message(res);
+       return NT_STATUS_OK;
+}
+
+/*****************************************************************************
+ Initialise idmap database. 
+*****************************************************************************/
+
+static NTSTATUS ldap_idmap_init( char *params )
+{
+       NTSTATUS nt_status;
+       char *dn, *pw;
+
+       ldap_conn = new_ldap_connection();
+
+       if (!fetch_ldap_pw(&dn, &pw))
+               return NT_STATUS_UNSUCCESSFUL;
+
+       ldap_conn->auth_dn = talloc_strdup(ldap_conn->mem_ctx, dn);
+       ldap_conn->simple_pw = talloc_strdup(ldap_conn->mem_ctx, pw);
+
+       SAFE_FREE(dn);
+       SAFE_FREE(pw);
+
+       if (!ldap_setup_connection(ldap_conn, params, NULL, NULL))
+               return NT_STATUS_UNSUCCESSFUL;
+
+       /* see if the idmap suffix and sub entries exists */
+       
+       nt_status = verify_idpool();    
+       if ( !NT_STATUS_IS_OK(nt_status) )
+               return nt_status;
+               
+       return NT_STATUS_OK;
+}
+
+/*****************************************************************************
+ End the LDAP session
+*****************************************************************************/
+
+static NTSTATUS ldap_idmap_close(void)
+{
+
+       DEBUG(5,("The connection to the LDAP server was closed\n"));
+       /* maybe free the results here --metze */
+       
+       return NT_STATUS_OK;
+}
+
+
+/* This function doesn't make as much sense in an LDAP world since the calling
+   node doesn't really control the ID ranges */
+static void ldap_idmap_status(void)
+{
+       DEBUG(0, ("LDAP IDMAP Status not available\n"));
+}
+
+static struct idmap_methods ldap_methods = {
+       ldap_idmap_init,
+       ldap_allocate_rid,
+       ldap_allocate_id,
+       ldap_get_sid_from_id,
+       ldap_get_id_from_sid,
+       ldap_set_mapping,
+       ldap_idmap_close,
+       ldap_idmap_status
+
+};
+
+NTSTATUS idmap_smbldap_init(void)
+{
+       return smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION, "smbldap", &ldap_methods);
+}
index 9cd91008392aaf9c0becbedb6183872fec99e871..5564ac02318e276d4d52ae0450c4f18537673028 100755 (executable)
@@ -13,7 +13,7 @@ if [ $# -ge 4 ] ; then
   GROFF=$4                    # sh cmd line, including options 
 fi
 
-if test ! -d ../docs/manpages; then
+if test ! -d docs/manpages; then
        echo "No manpages present.  SVN development version maybe?"
        exit 0
 fi
index 2b99b9c57f1a4092dc09aa7df5da0ea0f2408d39..cba3a294f871a51cd586f8ecb7e78749126c26e1 100755 (executable)
@@ -3,7 +3,7 @@
 
 SWATDIR=`echo $1 | sed 's/\/\//\//g'`
 SRCDIR=$2/
-BOOKDIR=$SWATDIR/help/using_samba
+BOOKDIR=$SWATDIR/using_samba
 
 echo Installing SWAT in $SWATDIR
 echo Installing the Samba Web Administration Tool
@@ -14,7 +14,7 @@ echo Installing langs are `cd $SRCDIR../swat/lang/; /bin/echo ??`
 for ln in $LANGS; do 
  SWATLANGDIR=$SWATDIR/$ln
  for d in $SWATLANGDIR $SWATLANGDIR/help $SWATLANGDIR/images \
-       $SWATLANGDIR/include; do
+       $SWATLANGDIR/include $SWATLANGDIR/js; do
     if [ ! -d $d ]; then
        mkdir -p $d
        if [ ! -d $d ]; then
@@ -28,7 +28,7 @@ done
 # Install images
 for ln in $LANGS; do
 
-  for f in $SRCDIR../swat/$ln/images/*.gif; do
+  for f in $SRCDIR../swat/$ln/images/*.png; do
       if [ ! -f $f ] ; then
        continue
       fi
@@ -59,7 +59,7 @@ for ln in $LANGS; do
 
   # Install "server-side" includes
 
-  for f in $SRCDIR../swat/$ln/include/*.html; do
+  for f in $SRCDIR../swat/$ln/include/*; do
       if [ ! -f $f ] ; then
        continue
       fi
@@ -69,13 +69,25 @@ for ln in $LANGS; do
       chmod 0644 $FNAME
   done
 
+  # Install javascripts
+
+  for f in $SRCDIR../swat/$ln/js/*.js; do
+      if [ ! -f $f ] ; then
+       continue
+      fi
+      FNAME=$SWATDIR/$ln/js/`basename $f`
+      echo $FNAME
+      cp $f $FNAME || echo Cannot install $FNAME. Does $USER have privileges?
+      chmod 0644 $FNAME
+  done
+
 done
 
 # Install html documentation (if html documentation tree is here)
 
 if [ -d $SRCDIR../docs/htmldocs/ ]; then
 
-    for dir in htmldocs/manpages  htmldocs/Samba3-ByExample  htmldocs/Samba3-Developers-Guide  htmldocs/Samba3-HOWTO  
+    for dir in htmldocs/ htmldocs/Samba-HOWTO-Collection htmldocs/Samba-Guide htmldocs/Samba-Developers-Guide
     do 
     
       if [ ! -d $SRCDIR../docs/$dir ]; then
index 3940c34700a2bf0b2762b6eab6fbcf130aa7cfb8..73a1c2b3f0a0f487aef2e20c163c7ce504109940 100644 (file)
@@ -128,7 +128,7 @@ END {
     gotstart = 1;
   }
 
-  if( $0 ~ /^SAM_ACCT_INFO_NODE|^SMB_ACL_T|^ADS_MODLIST|^PyObject|^SORTED_TREE|^REGISTRY_HOOK|^REGISTRY_VALUE|^DEVICEMODE|^PAC_DATA|^NET_USER_INFO_3|^smb_event_id_t/ ) {
+  if( $0 ~ /^SAM_ACCT_INFO_NODE|^SMB_ACL_T|^ADS_MODLIST|^PyObject|^SORTED_TREE|^REGISTRY_HOOK|^REGISTRY_VALUE|^REGVAL_CTR|^DEVICEMODE|^PAC_DATA|^NET_USER_INFO_3|^smb_event_id_t/ ) {
     gotstart = 1;
   }
 
index 0981d9e29e149770853ac3060b22576a6cb29ff5..40e185e153f76bbaab89ccc5caa812d0df97c16d 100644 (file)
@@ -2,16 +2,13 @@
 ## library file for test functions
 ##
 
-
-SMBCONTROL="smbcontrol -t 3"
-
 ##
 ## start/stop smbd daemon
 ##
 check_smbd_running()
 {
        ## the smbcontrol ping will return a 0 on success
-       $SMBCONTROL $CONFIGURATION smbd ping 2>&1 > /dev/null
+       smbcontrol $CONFIGURATION smbd ping 2>&1 > /dev/null
 }
 
 start_smbd()
@@ -22,7 +19,7 @@ start_smbd()
 
        sleep 1
 
-       $SMBCONTROL $CONFIGURATION `cat $PIDDIR/smbd.pid` ping 2>&1 > /dev/null || return $?
+       smbcontrol $CONFIGURATION `cat $PIDDIR/smbd.pid` ping 2>&1 > /dev/null || return $?
 }
 
 stop_smbd()
@@ -33,7 +30,7 @@ stop_smbd()
        ## belt and braces; first kill and then send a shutdown message
 
        kill -TERM $smbd_pid
-       $SMBCONTROL $CONFIGURATION smbd shutdown
+       smbcontrol $CONFIGURATION smbd shutdown
 
        ## check to see if smbd is already running
        check_smbd_running
@@ -43,23 +40,14 @@ stop_smbd()
        fi
 }
 
-check_ret_value()
-{
-       ret=$@
-
-       if test $ret != 0; then
-               stop_smbd
-               exit $ret
-       fi
-}
 
 ##
-## start/stop nmbd daemon
+## start/stop smbd daemon
 ##
 check_nmbd_running()
 {
        ## the smbcontrol ping will return a 0 on success
-       $SMBCONTROL $CONFIGURATION nmbd ping 2>&1 > /dev/null
+       smbcontrol $CONFIGURATION nmbd ping 2>&1 > /dev/null
 }
 
 start_nmbd()
index 7db2abe226e8d20218d73ee7195c796b86fd595e..6d54d0e4895a70e2b23b282c98660a57e180c4fb 100644 (file)
@@ -22,27 +22,9 @@ chmod 1777 $PREFIX_ABS/tmp
 
 start_smbd || exit $?
 
-## share enumeration
-
 smbclient $CONFIGURATION -L localhost -N -p 139
-check_ret_value $? 
-
-testfile=`echo $CONFIGURATION | awk '{print $2}'`
-filename=`basename $testfile`
-dirname=`dirname $testfile`
-
-
-# file get/put
-
-smbclient //localhost/test $PASSWORD $CONFIGURATION -c "lcd $dirname; put $filename"
-check_ret_value $? 
-
-smbclient //localhost/test $PASSWORD $CONFIGURATION -c "get $filename; rm $filename"
-check_ret_value $? 
-
-diff $filename $testfile 2> /dev/null > /dev/null
-check_ret_value $?
+ret=$?
 
 stop_smbd
-exit 0
 
+exit $ret
index 29c5a9f6e6969ec3e1d236ef779fa552483e6e6d..b59cd5330e5acae3e40761e47a397f700486cfd0 100644 (file)
@@ -1,8 +1,10 @@
 /* 
  *  Unix SMB/CIFS implementation.
  *  Service Control API Implementation
- *  Copyright (C) Gerald Carter                   2005.
+ * 
  *  Copyright (C) Marcin Krzysztof Porwit         2005.
+ *  Largely Rewritten by:
+ *  Copyright (C) Gerald (Jerry) Carter           2005.
  *  
  *  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
 
 #include "includes.h"
 
-#if 0
-
-/* backend database routines for services.tdb */
-
-#define SERVICEDB_VERSION_V1 1 /* Will there be more? */
-#define INTERNAL_SERVICES_LIST "NETLOGON Spooler"
-
-/*                                                                                                                     */
-/* scripts will execute from the following libdir, if they are in the enable svcctl=<list of scripts>                  */
-/* these should likely be symbolic links. Note that information about them will be extracted from the files themselves */
-/* using the LSB standard keynames for various information                                                             */
-
-#define SCVCTL_DATABASE_VERSION_V1 1
-static TDB_CONTEXT *service_tdb; /* used for services tdb file */
-
-/* there are two types of services -- internal, and external.
-   Internal services are "built-in" to samba -- there may be 
-   functions that exist to provide the control and enumeration 
-   functions.  There certainly is information returned to be 
-   displayed in the typical management console.
-
-   External services are those that can be specified in the smb.conf 
-   file -- and they conform to the LSB specification as to having 
-   particular keywords in the scripts. Note that these "scripts" are 
-   located in the lib directory, and are likely links to LSB-compliant 
-   init.d scripts, such as those that might come with Suse. Note 
-   that the spec is located  http://www.linuxbase.org/spec/ */
-
-
-
-/* Expand this to include what can and can't be done 
-   with a particular internal service. Expand as necessary 
-   to add other infromation like what can be controlled, 
-   etc. */
+/********************************************************************
+********************************************************************/
 
-typedef struct Internal_service_struct
+static SEC_DESC* construct_service_sd( TALLOC_CTX *ctx )
 {
-       const char *filename;           /* internal name "index" */
-       const char *displayname;
-       const char *description;
-       const uint32 statustype;
-       void *status_fn; 
-       void *control_fn;
-} Internal_service_description;
-
+       SEC_ACE ace[4]; 
+       SEC_ACCESS mask;
+       size_t i = 0;
+       SEC_DESC *sd;
+       SEC_ACL *acl;
+       size_t sd_size;
+       
+       /* basic access for Everyone */
+       
+       init_sec_access(&mask, SERVICE_READ_ACCESS );
+       init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
+               
+       init_sec_access(&mask,SERVICE_EXECUTE_ACCESS );
+       init_sec_ace(&ace[i++], &global_sid_Builtin_Power_Users, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
+       
+       init_sec_access(&mask,SERVICE_ALL_ACCESS );
+       init_sec_ace(&ace[i++], &global_sid_Builtin_Server_Operators, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
+       init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
+       
+       /* create the security descriptor */
+       
+       if ( !(acl = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) )
+               return NULL;
 
-static const Internal_service_description ISD[] = {
-       { "NETLOGON",   "Net Logon",    "Provides logon and authentication service to the network",     0x110,  NULL, NULL},
-       { "Spooler",    "Spooler",      "Printing Services",                                            0x0020, NULL, NULL},
-       { NULL, NULL, NULL, 0, NULL, NULL}
-};
+       if ( !(sd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL, acl, &sd_size)) )
+               return NULL;
 
+       return sd;
+}
 
 /********************************************************************
- allocate an array of external services and return them. Null return 
- is okay, make sure &added is also zero! 
+ This is where we do the dirty work of filling in things like the
+ Display name, Description, etc...
 ********************************************************************/
 
-int num_external_services(void)
+static void fill_service_values( const char *name, REGVAL_CTR *values )
 {
-       int num_services;
-       char **svc_list;
-       pstring keystring, external_services_string;
-       TDB_DATA key_data;
-
-
-       if (!service_tdb) {
-               DEBUG(8,("enum_external_services: service database is not open!!!\n"));
-               num_services = 0;
-       } else {
-               pstrcpy(keystring,"EXTERNAL_SERVICES");
-               key_data = tdb_fetch_bystring(service_tdb, keystring);
-
-               if ((key_data.dptr != NULL) && (key_data.dsize != 0)) {
-                       strncpy(external_services_string,key_data.dptr,key_data.dsize);
-                       external_services_string[key_data.dsize] = 0;
-                       DEBUG(8,("enum_external_services: services list is %s, size is %d\n",external_services_string,key_data.dsize));
-               }
-       } 
-       svc_list = str_list_make(external_services_string,NULL);
-       num_services = str_list_count( (const char **)svc_list);
+       UNISTR2 data, dname, ipath, description;
+       uint32 dword;
+       pstring pstr;
+       
+       /* These values are hardcoded in all QueryServiceConfig() replies.
+          I'm just storing them here for cosmetic purposes */
+       
+       dword = SVCCTL_AUTO_START;
+       regval_ctr_addvalue( values, "Start", REG_DWORD, (char*)&dword, sizeof(uint32));
+       
+       dword = SVCCTL_WIN32_OWN_PROC;
+       regval_ctr_addvalue( values, "Type", REG_DWORD, (char*)&dword, sizeof(uint32));
 
-       return num_services;
+       dword = SVCCTL_SVC_ERROR_NORMAL;
+       regval_ctr_addvalue( values, "ErrorControl", REG_DWORD, (char*)&dword, sizeof(uint32));
+       
+       /* everything runs as LocalSystem */
+       
+       init_unistr2( &data, "LocalSystem", UNI_STR_TERMINATE );
+       regval_ctr_addvalue( values, "ObjectName", REG_SZ, (char*)data.buffer, data.uni_str_len*2);
+       
+       /* special considerations for internal services and the DisplayName value */
+       
+       if ( strequal(name, "Spooler") ) {
+               pstr_sprintf( pstr, "%s/%s/smbd",dyn_LIBDIR, SVCCTL_SCRIPT_DIR );
+               init_unistr2( &ipath, pstr, UNI_STR_TERMINATE );
+               init_unistr2( &description, "Internal service for spooling files to print devices", UNI_STR_TERMINATE );
+               init_unistr2( &dname, "Print Spooler", UNI_STR_TERMINATE );
+       } 
+       else if ( strequal(name, "NETLOGON") ) {
+               pstr_sprintf( pstr, "%s/%s/smbd",dyn_LIBDIR, SVCCTL_SCRIPT_DIR );
+               init_unistr2( &ipath, pstr, UNI_STR_TERMINATE );
+               init_unistr2( &description, "File service providing access to policy and profile data", UNI_STR_TERMINATE );
+               init_unistr2( &dname, "Net Logon", UNI_STR_TERMINATE );
+       } 
+       else if ( strequal(name, "RemoteRegistry") ) {
+               pstr_sprintf( pstr, "%s/%s/smbd",dyn_LIBDIR, SVCCTL_SCRIPT_DIR );
+               init_unistr2( &ipath, pstr, UNI_STR_TERMINATE );
+               init_unistr2( &description, "Internal service providing remote access to the Samba registry", UNI_STR_TERMINATE );
+               init_unistr2( &dname, "Remote Registry Service", UNI_STR_TERMINATE );
+       } 
+       else {
+               pstr_sprintf( pstr, "%s/%s/%s",dyn_LIBDIR, SVCCTL_SCRIPT_DIR, name );
+               init_unistr2( &ipath, pstr, UNI_STR_TERMINATE );
+               init_unistr2( &description, "External Unix Service", UNI_STR_TERMINATE );
+               init_unistr2( &dname, name, UNI_STR_TERMINATE );
+       }
+       regval_ctr_addvalue( values, "DisplayName", REG_SZ, (char*)dname.buffer, dname.uni_str_len*2);
+       regval_ctr_addvalue( values, "ImagePath", REG_SZ, (char*)ipath.buffer, ipath.uni_str_len*2);
+       regval_ctr_addvalue( values, "Description", REG_SZ, (char*)description.buffer, description.uni_str_len*2);
+       
+       return;
 }
 
-
-
 /********************************************************************
-  Gather information on the "external services". These are services 
-  listed in the smb.conf file, and found to exist through checks in 
-  this code. Note that added will be incremented on the basis of the 
-  number of services added.  svc_ptr should have enough memory allocated 
-  to accommodate all of the services that exist. 
-
-  Typically num_external_services is used to "size" the amount of
-  memory allocated, but does little/no work. 
-
-  enum_external_services() actually examines each of the specified 
-  external services, populates the memory structures, and returns.
-
-  ** note that 'added' may end up with less than the number of services 
-  found in _num_external_services, such as the case when a service is
-  called out, but the actual service doesn't exist or the file can't be 
-  read for the service information.
 ********************************************************************/
 
-WERROR enum_external_services(TALLOC_CTX *tcx,ENUM_SERVICES_STATUS **svc_ptr, int existing_services,int *added) 
+static void add_new_svc_name( REGISTRY_KEY *key_parent, REGSUBKEY_CTR *subkeys, 
+                              const char *name )
 {
-       /* *svc_ptr must have pre-allocated memory */
-       int num_services = 0;
-       int i = 0;
-       ENUM_SERVICES_STATUS *services=NULL;
-       char **svc_list,**svcname;
-       pstring command, keystring, external_services_string;
-       int ret;
-       int fd = -1;
-       Service_info *si;
-       TDB_DATA key_data;
-
-       *added = num_services;
-
-       if (!service_tdb) {
-               DEBUG(8,("enum_external_services: service database is not open!!!\n"));
-       } else {
-               pstrcpy(keystring,"EXTERNAL_SERVICES");
-               key_data = tdb_fetch_bystring(service_tdb, keystring);
-               if ((key_data.dptr != NULL) && (key_data.dsize != 0)) {
-                       strncpy(external_services_string,key_data.dptr,key_data.dsize);
-                       external_services_string[key_data.dsize] = 0;
-                       DEBUG(8,("enum_external_services: services list is %s, size is %d\n",external_services_string,key_data.dsize));
-               }
-       } 
-       svc_list = str_list_make(external_services_string,NULL);
-       num_services = str_list_count( (const char **)svc_list);
-
-       if (0 == num_services) {
-               DEBUG(8,("enum_external_services: there are no external services\n"));
-               *added = num_services;
-               return WERR_OK;
+       REGISTRY_KEY *key_service, *key_secdesc;
+       WERROR wresult;
+       pstring path;
+       REGVAL_CTR *values;
+       REGSUBKEY_CTR *svc_subkeys;
+       SEC_DESC *sd;
+       prs_struct ps;
+
+       /* add to the list and create the subkey path */
+
+       regsubkey_ctr_addkey( subkeys, name );
+       store_reg_keys( key_parent, subkeys );
+
+       /* open the new service key */
+
+       pstr_sprintf( path, "%s\\%s", KEY_SERVICES, name );
+       wresult = regkey_open_internal( &key_service, path, get_root_nt_token(), 
+               REG_KEY_ALL );
+       if ( !W_ERROR_IS_OK(wresult) ) {
+               DEBUG(0,("add_new_svc_name: key lookup failed! [%s] (%s)\n", 
+                       path, dos_errstr(wresult)));
+               return;
        }
-       DEBUG(8,("enum_external_services: there are [%d] external services\n",num_services));
-       si=TALLOC_ARRAY( tcx, Service_info, 1 );
-       if (si == NULL) { 
-               DEBUG(8,("enum_external_services: Failed to alloc si\n"));
-               return WERR_NOMEM;
+       
+       /* add the 'Security' key */
+
+       if ( !(svc_subkeys = TALLOC_ZERO_P( key_service, REGSUBKEY_CTR )) ) {
+               DEBUG(0,("add_new_svc_name: talloc() failed!\n"));
+               return;
        }
+       
+       fetch_reg_keys( key_service, svc_subkeys );
+       regsubkey_ctr_addkey( svc_subkeys, "Security" );
+       store_reg_keys( key_service, svc_subkeys );
 
-#if 0
-/* *svc_ptr has the pointer to the array if there is one already. NULL if not. */
-       if ((existing_services>0) && svc_ptr && *svc_ptr) { /* reallocate vs. allocate */
-               DEBUG(8,("enum_external_services: REALLOCing %x to %d services\n", *svc_ptr, existing_services+num_services));
+       /* now for the service values */
+       
+       if ( !(values = TALLOC_ZERO_P( key_service, REGVAL_CTR )) ) {
+               DEBUG(0,("add_new_svc_name: talloc() failed!\n"));
+               return;
+       }
 
-               services=TALLOC_REALLOC_ARRAY(tcx,*svc_ptr,ENUM_SERVICES_STATUS,existing_services+num_services);
-               DEBUG(8,("enum_external_services: REALLOCed to %x services\n", services));
+       fill_service_values( name, values );
+       store_reg_values( key_service, values );
 
-               if (!services) return WERR_NOMEM;
-                       *svc_ptr = services;
-       } else {
-               if ( !(services = TALLOC_ARRAY( tcx, ENUM_SERVICES_STATUS, num_services )) )
-                       return WERR_NOMEM;
-       }
-#endif
+       /* cleanup the service key*/
+
+       TALLOC_FREE( key_service );
+
+       /* now add the security descriptor */
 
-       if (!svc_ptr || !(*svc_ptr)) 
-               return WERR_NOMEM;
-       services = *svc_ptr;
-       if (existing_services > 0) {
-               i+=existing_services;
+       pstr_sprintf( path, "%s\\%s\\%s", KEY_SERVICES, name, "Security" );
+       wresult = regkey_open_internal( &key_secdesc, path, get_root_nt_token(), 
+               REG_KEY_ALL );
+       if ( !W_ERROR_IS_OK(wresult) ) {
+               DEBUG(0,("add_new_svc_name: key lookup failed! [%s] (%s)\n", 
+                       path, dos_errstr(wresult)));
+               return;
        }
 
-       svcname = svc_list;
-       DEBUG(8,("enum_external_services: enumerating %d external services starting at index %d\n", num_services,existing_services));
-
-       while (*svcname) {
-               DEBUG(10,("enum_external_services: Reading information on service %s, index %d\n",*svcname,i));
-               /* get_LSB_data(*svcname,si);  */
-               if (!get_service_info(service_tdb,*svcname, si)) {
-                       DEBUG(1,("enum_external_services: CAN'T FIND INFO FOR SERVICE %s in the services DB\n",*svcname));
-               }
-
-               if ((si->filename == NULL) || (*si->filename == 0)) {
-                       init_unistr(&services[i].servicename, *svcname );
-               } else {
-                       init_unistr( &services[i].servicename, si->filename );    
-                       /* init_unistr( &services[i].servicename, si->servicename ); */
-               }
-
-               if ((si->provides == NULL) || (*si->provides == 0)) {
-                       init_unistr(&services[i].displayname, *svcname );
-               } else {
-                       init_unistr( &services[i].displayname, si->provides );
-               }
-
-               /* TODO - we could keep the following info in the DB, too... */
-
-               DEBUG(8,("enum_external_services: Service name [%s] displayname [%s]\n",
-               si->filename, si->provides)); 
-               services[i].status.type               = SVCCTL_WIN32_OWN_PROC; 
-               services[i].status.win32_exit_code    = 0x0;
-               services[i].status.service_exit_code  = 0x0;
-               services[i].status.check_point        = 0x0;
-               services[i].status.wait_hint          = 0x0;
-
-               /* TODO - do callout here to get the status */
-
-               memset(command, 0, sizeof(command));
-               slprintf(command, sizeof(command)-1, "%s%s%s %s", dyn_LIBDIR, SVCCTL_SCRIPT_DIR, *svcname, "status");
-
-               DEBUG(10, ("enum_external_services: status command is [%s]\n", command));
-
-               /* TODO  - wrap in privilege check */
-
-               ret = smbrun(command, &fd);
-               DEBUGADD(10, ("returned [%d]\n", ret));
-               close(fd);
-               if(ret != 0)
-                       DEBUG(10, ("enum_external_services: Command returned  [%d]\n", ret));
-               services[i].status.state              = SVCCTL_STOPPED;
-               if (ret == 0) {
-                       services[i].status.state              = SVCCTL_RUNNING;
-                       services[i].status.controls_accepted  = SVCCTL_CONTROL_SHUTDOWN | SVCCTL_CONTROL_STOP;
-               } else {
-                       services[i].status.state              = SVCCTL_STOPPED;
-                       services[i].status.controls_accepted  = 0;
-               }
-               svcname++; 
-               i++;
-       } 
+       if ( !(values = TALLOC_ZERO_P( key_secdesc, REGVAL_CTR )) ) {
+               DEBUG(0,("add_new_svc_name: talloc() failed!\n"));
+               return;
+       }
 
-       DEBUG(10,("enum_external_services: Read services %d\n",num_services));
-       *added = num_services;
+       if ( !(sd = construct_service_sd(key_secdesc)) ) {
+               DEBUG(0,("add_new_svc_name: Failed to create default sec_desc!\n"));
+               TALLOC_FREE( key_secdesc );
+               return;
+       }
+       
+       /* stream the printer security descriptor */
+       
+       prs_init( &ps, RPC_MAX_PDU_FRAG_LEN, key_secdesc, MARSHALL);
+       
+       if ( sec_io_desc("sec_desc", &sd, &ps, 0 ) ) {
+               uint32 offset = prs_offset( &ps );
+               regval_ctr_addvalue( values, "Security", REG_BINARY, prs_data_p(&ps), offset );
+               store_reg_values( key_secdesc, values );
+       }
+       
+       /* finally cleanup the Security key */
+       
+       prs_mem_free( &ps );
+       TALLOC_FREE( key_secdesc );
 
-       return WERR_OK;
+       return;
 }
 
 /********************************************************************
 ********************************************************************/
 
-int num_internal_services(void)
+void svcctl_init_keys( void )
 {
-       int num_services;
-       char **svc_list;
-       pstring keystring, internal_services_string;
-       TDB_DATA key_data;
-
-       if (!service_tdb) {
-               DEBUG(8,("enum_internal_services: service database is not open!!!\n"));
-               num_services = 0;
-       } else {
-               pstrcpy(keystring,"INTERNAL_SERVICES");
-               key_data = tdb_fetch_bystring(service_tdb, keystring);
-
-               if ((key_data.dptr != NULL) && (key_data.dsize != 0)) {
-                       strncpy(internal_services_string,key_data.dptr,key_data.dsize);
-                       internal_services_string[key_data.dsize] = 0;
-                       DEBUG(8,("enum_internal_services: services list is %s, size is %d\n",internal_services_string,key_data.dsize));
-               }
-       } 
-       svc_list = str_list_make(internal_services_string,NULL);
-       num_services = str_list_count( (const char **)svc_list);
-
-       return num_services;
-}
-
-#if 0 
-/*********************************************************************
- given a service nice name, find the underlying service name
-*********************************************************************/
-
-static BOOL convert_service_displayname(TDB_CONTEXT *stdb,pstring service_nicename, pstring servicename,int szsvcname) 
-{
-       pstring keystring;
-       TDB_DATA key_data;
-
-       if ((stdb == NULL) || (service_nicename==NULL) || (servicename == NULL)) 
-               return False;
+       const char **service_list = lp_svcctl_list();
+       int i;
+       REGSUBKEY_CTR *subkeys;
+       REGISTRY_KEY *key = NULL;
+       WERROR wresult;
+       BOOL new_services = False;
+       
+       /* bad mojo here if the lookup failed.  Should not happen */
+       
+       wresult = regkey_open_internal( &key, KEY_SERVICES, get_root_nt_token(), 
+               REG_KEY_ALL );
 
-       pstr_sprintf(keystring,"SERVICE_NICENAME/%s", servicename);
+       if ( !W_ERROR_IS_OK(wresult) ) {
+               DEBUG(0,("init_services_keys: key lookup failed! (%s)\n", 
+                       dos_errstr(wresult)));
+               return;
+       }
+       
+       /* lookup the available subkeys */      
+       
+       if ( !(subkeys = TALLOC_ZERO_P( key, REGSUBKEY_CTR )) ) {
+               DEBUG(0,("init_services_keys: talloc() failed!\n"));
+               return;
+       }
+       
+       fetch_reg_keys( key, subkeys );
+       
+       /* the builting services exist */
+       
+       add_new_svc_name( key, subkeys, "Spooler" );
+       add_new_svc_name( key, subkeys, "NETLOGON" );
+       add_new_svc_name( key, subkeys, "RemoteRegistry" );
+               
+       for ( i=0; service_list[i]; i++ ) {
+       
+               /* only add new services */
+               if ( regsubkey_ctr_key_exists( subkeys, service_list[i] ) )
+                       continue;
 
-       DEBUG(5, ("convert_service_displayname: Looking for service name [%s], key [%s]\n", 
-               service_nicename, keystring));
+               /* Add the new service key and initialize the appropriate values */
 
-       key_data = tdb_fetch_bystring(stdb,keystring);
+               add_new_svc_name( key, subkeys, service_list[i] );
 
-       if (key_data.dsize == 0) {
-               DEBUG(5, ("convert_service_displayname: [%s] Not found, tried key [%s]\n",service_nicename,keystring));
-               return False; 
+               new_services = True;
        }
 
-       strncpy(servicename,key_data.dptr,szsvcname);
-       servicename[(key_data.dsize > szsvcname ? szsvcname : key_data.dsize)] = 0;
-       DEBUG(5, ("convert_service_displayname: Found service name [%s], name is  [%s]\n",
-               service_nicename,servicename));
+       TALLOC_FREE( key );
 
-       return True;
-}
-#endif
+       /* initialize the control hooks */
 
-/*******************************************************************************
- Get the INTERNAL services information for the given service name. 
-*******************************************************************************/
+       init_service_op_table();
 
-static BOOL get_internal_service_data(const Internal_service_description *isd, Service_info *si)
-{
-       ZERO_STRUCTP( si );
-#if 0
-       
-       pstrcpy( si->servicename, isd->displayname);
-       pstrcpy( si->servicetype, "INTERNAL");
-       pstrcpy( si->filename, isd->filename);
-       pstrcpy( si->provides, isd->displayname);
-       pstrcpy( si->description, isd->description);
-       pstrcpy( si->shortdescription, isd->description);
-#endif
-       
-       return True;
+       return;
 }
 
 /********************************************************************
+ This is where we do the dirty work of filling in things like the
+ Display name, Description, etc...Always return a default secdesc 
+ in case of any failure.
 ********************************************************************/
 
-BOOL get_service_info(TDB_CONTEXT *stdb,char *service_name, Service_info *si) 
-{
-
-       pstring keystring;
-       TDB_DATA  key_data;
-
-       if ((stdb == NULL) || (si == NULL) || (service_name==NULL) || (*service_name == 0)) 
-               return False;
-
-       /* TODO  - error handling -- what if the service isn't in the DB? */
-    
-       pstr_sprintf(keystring,"SERVICE/%s/TYPE", service_name);
-       key_data = tdb_fetch_bystring(stdb,keystring);
-       strncpy(si->servicetype,key_data.dptr,key_data.dsize);
-       si->servicetype[key_data.dsize] = 0;
-
-       /* crude check to see if the service exists... */
-       DEBUG(3,("Size of the TYPE field is %d\n",key_data.dsize));
-       if (key_data.dsize == 0) 
-               return False;
-
-       pstr_sprintf(keystring,"SERVICE/%s/FILENAME", service_name);
-       key_data = tdb_fetch_bystring(stdb,keystring);
-       strncpy(si->filename,key_data.dptr,key_data.dsize);
-       si->filename[key_data.dsize] = 0;
-
-       pstr_sprintf(keystring,"SERVICE/%s/PROVIDES", service_name);
-       key_data = tdb_fetch_bystring(stdb,keystring);
-       strncpy(si->provides,key_data.dptr,key_data.dsize);
-       si->provides[key_data.dsize] = 0;
-       strncpy(si->servicename,key_data.dptr,key_data.dsize);
-       si->servicename[key_data.dsize] = 0;
-
-           
-       pstr_sprintf(keystring,"SERVICE/%s/DEPENDENCIES", service_name);
-       key_data = tdb_fetch_bystring(stdb,keystring);
-       strncpy(si->dependencies,key_data.dptr,key_data.dsize);
-       si->dependencies[key_data.dsize] = 0;
-
-       pstr_sprintf(keystring,"SERVICE/%s/SHOULDSTART", service_name);
-       key_data = tdb_fetch_bystring(stdb,keystring);
-       strncpy(si->shouldstart,key_data.dptr,key_data.dsize);
-       si->shouldstart[key_data.dsize] = 0;
-
-       pstr_sprintf(keystring,"SERVICE/%s/SHOULD_STOP", service_name);
-       key_data = tdb_fetch_bystring(stdb,keystring);
-       strncpy(si->shouldstop,key_data.dptr,key_data.dsize);
-       si->shouldstop[key_data.dsize] = 0;
-
-       pstr_sprintf(keystring,"SERVICE/%s/REQUIREDSTART", service_name);
-       key_data = tdb_fetch_bystring(stdb,keystring);
-       strncpy(si->requiredstart,key_data.dptr,key_data.dsize);
-       si->requiredstart[key_data.dsize] = 0;
-
-       pstr_sprintf(keystring,"SERVICE/%s/REQUIREDSTOP", service_name);
-       key_data = tdb_fetch_bystring(stdb,keystring);
-       strncpy(si->requiredstop,key_data.dptr,key_data.dsize);
-       si->requiredstop[key_data.dsize] = 0;
-
-       pstr_sprintf(keystring,"SERVICE/%s/DESCRIPTION", service_name);
-       key_data = tdb_fetch_bystring(stdb,keystring);
-       strncpy(si->description,key_data.dptr,key_data.dsize);
-       si->description[key_data.dsize] = 0;
-
-       pstr_sprintf(keystring,"SERVICE/%s/SHORTDESC", service_name);
-       key_data = tdb_fetch_bystring(stdb,keystring);
-       strncpy(si->shortdescription,key_data.dptr,key_data.dsize);
-       si->shortdescription[key_data.dsize] = 0;
-
-       return True;
-}
-
-/*********************************************************************
-*********************************************************************/
-
-BOOL store_service_info(TDB_CONTEXT *stdb,char *service_name, Service_info *si) 
+SEC_DESC* svcctl_get_secdesc( TALLOC_CTX *ctx, const char *name, NT_USER_TOKEN *token )
 {
-       pstring keystring;
-
-       /* Note -- when we write to the tdb, we "index" on the filename 
-          field, not the nice name. when a service is "opened", it is 
-          opened by the nice (SERVICENAME) name, not the file name. 
-          So there needs to be a mapping from nice name back to the file name. */
-
-       if ((stdb == NULL) || (si == NULL) || (service_name==NULL) || (*service_name == 0)) 
-               return False;
-
-
-       /* Store the nicename */
-
-       pstr_sprintf(keystring,"SERVICE_NICENAME/%s", si->servicename);
-       tdb_store_bystring(stdb,keystring,string_tdb_data(service_name),TDB_REPLACE);
-
-       pstr_sprintf(keystring,"SERVICE/%s/TYPE", service_name);
-       tdb_store_bystring(stdb,keystring,string_tdb_data(si->servicetype),TDB_REPLACE);
-
-       pstr_sprintf(keystring,"SERVICE/%s/FILENAME", service_name);
-       tdb_store_bystring(stdb,keystring,string_tdb_data(si->filename),TDB_REPLACE);
-
-       pstr_sprintf(keystring,"SERVICE/%s/PROVIDES", service_name);
-       tdb_store_bystring(stdb,keystring,string_tdb_data(si->provides),TDB_REPLACE);
+       REGISTRY_KEY *key;
+       prs_struct ps;
+       REGVAL_CTR *values;
+       REGISTRY_VALUE *val;
+       SEC_DESC *sd = NULL;
+       SEC_DESC *ret_sd = NULL;
+       pstring path;
+       WERROR wresult;
+       
+       /* now add the security descriptor */
+
+       pstr_sprintf( path, "%s\\%s\\%s", KEY_SERVICES, name, "Security" );
+       wresult = regkey_open_internal( &key, path, token, REG_KEY_ALL );
+       if ( !W_ERROR_IS_OK(wresult) ) {
+               DEBUG(0,("svcctl_get_secdesc: key lookup failed! [%s] (%s)\n", 
+                       path, dos_errstr(wresult)));
+               return NULL;
+       }
 
-       pstr_sprintf(keystring,"SERVICE/%s/SERVICENAME", service_name);
-       tdb_store_bystring(stdb,keystring,string_tdb_data(si->servicename),TDB_REPLACE);
+       if ( !(values = TALLOC_ZERO_P( key, REGVAL_CTR )) ) {
+               DEBUG(0,("add_new_svc_name: talloc() failed!\n"));
+               TALLOC_FREE( key );
+               return NULL;
+       }
 
-       pstr_sprintf(keystring,"SERVICE/%s/DEPENDENCIES", service_name);
-       tdb_store_bystring(stdb,keystring,string_tdb_data(si->dependencies),TDB_REPLACE);
+       fetch_reg_values( key, values );
+       
+       if ( !(val = regval_ctr_getvalue( values, "Security" )) ) {
+               DEBUG(6,("svcctl_get_secdesc: constructing default secdesc for service [%s]\n", 
+                       name));
+               TALLOC_FREE( key );
+               return construct_service_sd( ctx );
+       }
+       
 
-       pstr_sprintf(keystring,"SERVICE/%s/SHOULDSTART", service_name);
-       tdb_store_bystring(stdb,keystring,string_tdb_data(si->shouldstart),TDB_REPLACE);
+       /* stream the printer security descriptor */
+       
+       prs_init( &ps, 0, key, UNMARSHALL);
+       prs_give_memory( &ps, regval_data_p(val), regval_size(val), False );
+       
+       if ( !sec_io_desc("sec_desc", &sd, &ps, 0 ) ) {
+               TALLOC_FREE( key );
+               return construct_service_sd( ctx );
+       }
+       
+       ret_sd = dup_sec_desc( ctx, sd );
+       
+       /* finally cleanup the Security key */
+       
+       prs_mem_free( &ps );
+       TALLOC_FREE( key );
 
-       pstr_sprintf(keystring,"SERVICE/%s/SHOULDSTOP", service_name);
-       tdb_store_bystring(stdb,keystring,string_tdb_data(si->shouldstop),TDB_REPLACE);
+       return ret_sd;
+}
 
-       pstr_sprintf(keystring,"SERVICE/%s/REQUIREDSTART", service_name);
-       tdb_store_bystring(stdb,keystring,string_tdb_data(si->requiredstart),TDB_REPLACE);
+/********************************************************************
+********************************************************************/
 
-       pstr_sprintf(keystring,"SERVICE/%s/REQUIREDSTOP", service_name);
-       tdb_store_bystring(stdb,keystring,string_tdb_data(si->requiredstop),TDB_REPLACE);
+char* svcctl_lookup_dispname( const char *name, NT_USER_TOKEN *token )
+{
+       static fstring display_name;
+       REGISTRY_KEY *key;
+       REGVAL_CTR *values;
+       REGISTRY_VALUE *val;
+       pstring path;
+       WERROR wresult;
+       
+       /* now add the security descriptor */
+
+       pstr_sprintf( path, "%s\\%s", KEY_SERVICES, name );
+       wresult = regkey_open_internal( &key, path, token, REG_KEY_ALL );
+       if ( !W_ERROR_IS_OK(wresult) ) {
+               DEBUG(0,("svcctl_lookup_dispname: key lookup failed! [%s] (%s)\n", 
+                       path, dos_errstr(wresult)));
+               return NULL;
+       }
 
-       pstr_sprintf(keystring,"SERVICE/%s/DESCRIPTION", service_name);
-       tdb_store_bystring(stdb,keystring,string_tdb_data(si->description),TDB_REPLACE);
+       if ( !(values = TALLOC_ZERO_P( key, REGVAL_CTR )) ) {
+               DEBUG(0,("svcctl_lookup_dispname: talloc() failed!\n"));
+               TALLOC_FREE( key );
+               return NULL;
+       }
 
-       pstr_sprintf(keystring,"SERVICE/%s/SHORTDESC", service_name);
-       if (si->shortdescription && *si->shortdescription) 
-               tdb_store_bystring(stdb,keystring,string_tdb_data(si->shortdescription),TDB_REPLACE);
+       fetch_reg_values( key, values );
+       
+       if ( !(val = regval_ctr_getvalue( values, "DisplayName" )) )
+               fstrcpy( display_name, name );
        else
-               tdb_store_bystring(stdb,keystring,string_tdb_data(si->description),TDB_REPLACE);
+               rpcstr_pull( display_name, regval_data_p(val), sizeof(display_name), regval_size(val), 0 );
 
-       return True;
+       TALLOC_FREE( key );
+       
+       return display_name;
 }
 
-/****************************************************************************
- Create/Open the service control manager tdb. This code a clone of init_group_mapping.
-****************************************************************************/
+/********************************************************************
+********************************************************************/
 
-BOOL init_svcctl_db(void)
+char* svcctl_lookup_description( const char *name, NT_USER_TOKEN *token )
 {
-       const char *vstring = "INFO/version";
-       uint32 vers_id;
-       char **svc_list;
-       char **svcname;
-       pstring keystring;
-       pstring external_service_list;
-       pstring internal_service_list;
-       Service_info si;
-       const Internal_service_description *isd_ptr;
-       /* svc_list = str_list_make( "etc/init.d/skeleton  etc/init.d/syslog", NULL ); */
-       svc_list=(char **)lp_enable_svcctl(); 
-
-       if (service_tdb)
-               return True;
-
-       pstrcpy(external_service_list,"");
-
-       service_tdb = tdb_open_log(lock_path("services.tdb"), 0, TDB_DEFAULT, O_RDWR, 0600);
-       if (!service_tdb) {
-               DEBUG(0,("Failed to open service db\n"));
-               service_tdb = tdb_open_log(lock_path("services.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
-               if (!service_tdb) return False;
-               DEBUG(0,("Created new services db\n"));
+       static fstring description;
+       REGISTRY_KEY *key;
+       REGVAL_CTR *values;
+       REGISTRY_VALUE *val;
+       pstring path;
+       WERROR wresult;
+       
+       /* now add the security descriptor */
+
+       pstr_sprintf( path, "%s\\%s", KEY_SERVICES, name );
+       wresult = regkey_open_internal( &key, path, token, REG_KEY_ALL );
+       if ( !W_ERROR_IS_OK(wresult) ) {
+               DEBUG(0,("svcctl_lookup_dispname: key lookup failed! [%s] (%s)\n", 
+                       path, dos_errstr(wresult)));
+               return NULL;
        }
 
-       if ((-1 == tdb_fetch_uint32(service_tdb, vstring,&vers_id)) || (vers_id != SERVICEDB_VERSION_V1)) {
-         /* wrong version of DB, or db was just created */
-         tdb_traverse(service_tdb, tdb_traverse_delete_fn, NULL);
-         tdb_store_uint32(service_tdb, vstring, SERVICEDB_VERSION_V1);
+       if ( !(values = TALLOC_ZERO_P( key, REGVAL_CTR )) ) {
+               DEBUG(0,("svcctl_lookup_dispname: talloc() failed!\n"));
+               TALLOC_FREE( key );
+               return NULL;
        }
-       tdb_unlock_bystring(service_tdb, vstring);
 
-       DEBUG(0,("Initializing services db\n"));
+       fetch_reg_values( key, values );
+       
+       if ( !(val = regval_ctr_getvalue( values, "Description" )) )
+               fstrcpy( description, "Unix Service");
+       else
+               rpcstr_pull( description, regval_data_p(val), sizeof(description), regval_size(val), 0 );
+
+       TALLOC_FREE( key );
        
-       svcname = svc_list;
+       return description;
+}
 
-       /* Get the EXTERNAL services as mentioned by line in smb.conf */
 
-       while (*svcname) {
-               DEBUG(10,("Reading information on service %s\n",*svcname));
-               if (get_LSB_data(*svcname,&si));{
-                       /* write the information to the TDB */
-                       store_service_info(service_tdb,*svcname,&si);
-                       /* definitely not efficient to do it this way. */
-                       pstrcat(external_service_list,"\"");
-                       pstrcat(external_service_list,*svcname);
-                       pstrcat(external_service_list,"\" ");
-               }
-               svcname++;
+/********************************************************************
+********************************************************************/
+
+REGVAL_CTR* svcctl_fetch_regvalues( const char *name, NT_USER_TOKEN *token )
+{
+       REGISTRY_KEY *key;
+       REGVAL_CTR *values;
+       pstring path;
+       WERROR wresult;
+       
+       /* now add the security descriptor */
+
+       pstr_sprintf( path, "%s\\%s", KEY_SERVICES, name );
+       wresult = regkey_open_internal( &key, path, token, REG_KEY_ALL );
+       if ( !W_ERROR_IS_OK(wresult) ) {
+               DEBUG(0,("svcctl_fetch_regvalues: key lookup failed! [%s] (%s)\n", 
+                       path, dos_errstr(wresult)));
+               return NULL;
        }
-       pstrcpy(keystring,"EXTERNAL_SERVICES");
-       DEBUG(8,("Storing external service list [%s]\n",external_service_list));
-        tdb_store_bystring(service_tdb,keystring,string_tdb_data(external_service_list),TDB_REPLACE);
-
-       /* Get the INTERNAL services */
-       
-       pstrcpy(internal_service_list,"");
-       isd_ptr = ISD; 
-
-       while (isd_ptr && (isd_ptr->filename)) {
-               DEBUG(10,("Reading information on service %s\n",isd_ptr->filename));
-               if (get_internal_service_data(isd_ptr,&si)){
-                       /* write the information to the TDB */
-                       store_service_info(service_tdb,(char *)isd_ptr->filename,&si);
-                       /* definitely not efficient to do it this way. */
-                       pstrcat(internal_service_list,"\"");
-                       pstrcat(internal_service_list,isd_ptr->filename);
-                       pstrcat(internal_service_list,"\" ");
-
-               }
-               isd_ptr++;
+
+       if ( !(values = TALLOC_ZERO_P( NULL, REGVAL_CTR )) ) {
+               DEBUG(0,("svcctl_fetch_regvalues: talloc() failed!\n"));
+               TALLOC_FREE( key );
+               return NULL;
        }
-       pstrcpy(keystring,"INTERNAL_SERVICES");
-       DEBUG(8,("Storing internal service list [%s]\n",internal_service_list));
-        tdb_store_bystring(service_tdb,keystring,string_tdb_data(internal_service_list),TDB_REPLACE);
+       
+       fetch_reg_values( key, values );
 
-       return True;
+       TALLOC_FREE( key );
+       
+       return values;
 }
-#endif
+
diff --git a/source3/services/svc_netlogon.c b/source3/services/svc_netlogon.c
new file mode 100644 (file)
index 0000000..2aa5a31
--- /dev/null
@@ -0,0 +1,66 @@
+/* 
+ *  Unix SMB/CIFS implementation.
+ *  Service Control API Implementation
+ *  Copyright (C) Gerald Carter                   2005.
+ *  
+ *  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"
+
+/* Implementation for internal netlogon service */
+
+/*********************************************************************
+*********************************************************************/
+
+static WERROR netlogon_stop( const char *service, SERVICE_STATUS *service_status )
+{
+       return WERR_ACCESS_DENIED;
+}
+
+/*********************************************************************
+*********************************************************************/
+
+static WERROR netlogon_start( const char *service )
+{
+       return WERR_ACCESS_DENIED;
+}
+
+/*********************************************************************
+*********************************************************************/
+
+static WERROR netlogon_status( const char *service, SERVICE_STATUS *service_status )
+{
+       ZERO_STRUCTP( service_status );
+
+       service_status->type              = 0x20;
+       if ( lp_servicenumber("NETLOGON") != -1 ) 
+               service_status->state              = SVCCTL_RUNNING;
+       else
+               service_status->state              = SVCCTL_STOPPED;
+       
+       return WERR_OK;
+}
+
+/*********************************************************************
+*********************************************************************/
+
+/* struct for svcctl control to manipulate netlogon service */
+
+SERVICE_CONTROL_OPS netlogon_svc_ops = {
+       netlogon_stop,
+       netlogon_start,
+       netlogon_status
+};
index c856ae2a9955bead87b836cd99123e5088590970..5801d076c496ebc22d6b6affedeee68d7b3b53ce 100644 (file)
@@ -171,24 +171,78 @@ BOOL get_LSB_data(char *fname,Service_info *si )
 /*********************************************************************
 *********************************************************************/
 
-static WERROR rcinit_stop( SERVICE_STATUS *service_status )
+static WERROR rcinit_stop( const char *service, SERVICE_STATUS *status )
 {
-       return WERR_OK;
+       pstring command;
+       int ret, fd;
+       
+       pstr_sprintf( command, "%s/%s/%s stop", dyn_LIBDIR, SVCCTL_SCRIPT_DIR, service );
+       
+       /* we've already performed the access check when the service was opened */
+       
+       become_root();
+       ret = smbrun( command , &fd );
+       unbecome_root();
+       
+       DEBUGADD(5, ("rcinit_start: [%s] returned [%d]\n", command, ret));
+       close(fd);
+       
+       ZERO_STRUCTP( status );
+       status->type = 0x0020;
+       status->state = (ret == 0 ) ? 0x0001 : 0x0004;
+       status->controls_accepted = 0x0005;
+
+       return ( ret == 0 ) ? WERR_OK : WERR_ACCESS_DENIED;
 }
 
 /*********************************************************************
 *********************************************************************/
 
-static WERROR rcinit_start( void )
+static WERROR rcinit_start( const char *service )
 {
-       return WERR_OK;
+       pstring command;
+       int ret, fd;
+       
+       pstr_sprintf( command, "%s/%s/%s start", dyn_LIBDIR, SVCCTL_SCRIPT_DIR, service );
+       
+       /* we've already performed the access check when the service was opened */
+       
+       become_root();
+       ret = smbrun( command , &fd );
+       unbecome_root();
+       
+       DEBUGADD(5, ("rcinit_start: [%s] returned [%d]\n", command, ret));
+       close(fd);      
+
+       return ( ret == 0 ) ? WERR_OK : WERR_ACCESS_DENIED;
 }
 
 /*********************************************************************
 *********************************************************************/
 
-static WERROR rcinit_status( SERVICE_STATUS *service_status )
+static WERROR rcinit_status( const char *service, SERVICE_STATUS *status )
 {
+       pstring command;
+       int ret, fd;
+       
+       pstr_sprintf( command, "%s/%s/%s status", dyn_LIBDIR, SVCCTL_SCRIPT_DIR, service );
+       
+       /* we've already performed the access check when the service was opened */
+       /* assume as return code of 0 means that the service is ok.  Anything else
+          is STOPPED */
+       
+       become_root();
+       ret = smbrun( command , &fd );
+       unbecome_root();
+       
+       DEBUGADD(5, ("rcinit_start: [%s] returned [%d]\n", command, ret));
+       close(fd);
+       
+       ZERO_STRUCTP( status );
+       status->type = 0x0020;
+       status->state = (ret == 0 ) ? 0x0004 : 0x0001;
+       status->controls_accepted = 0x0005;
+
        return WERR_OK;
 }
 
index 5f8fa73ced4ab16c67cb6cf33358b8dfac6337c8..13a1dbb1bdf697307d5fd79b8e7490d6de554161 100644 (file)
@@ -25,7 +25,7 @@
 /*********************************************************************
 *********************************************************************/
 
-static WERROR spoolss_stop( SERVICE_STATUS *service_status )
+static WERROR spoolss_stop( const char *service, SERVICE_STATUS *service_status )
 {
        ZERO_STRUCTP( service_status );
        
@@ -43,7 +43,7 @@ static WERROR spoolss_stop( SERVICE_STATUS *service_status )
 /*********************************************************************
 *********************************************************************/
 
-static WERROR spoolss_start( void )
+static WERROR spoolss_start( const char *service )
 {
        /* see if the smb.conf will support this anyways */
        
@@ -58,8 +58,10 @@ static WERROR spoolss_start( void )
 /*********************************************************************
 *********************************************************************/
 
-static WERROR spoolss_status( SERVICE_STATUS *service_status )
+static WERROR spoolss_status( const char *service, SERVICE_STATUS *service_status )
 {
+       ZERO_STRUCTP( service_status );
+
        service_status->type              = 0x110;
        service_status->state             = lp_get_spoolss_state();
        service_status->controls_accepted = SVCCTL_ACCEPT_STOP;
diff --git a/source3/services/svc_winreg.c b/source3/services/svc_winreg.c
new file mode 100644 (file)
index 0000000..1bccee2
--- /dev/null
@@ -0,0 +1,63 @@
+/* 
+ *  Unix SMB/CIFS implementation.
+ *  Service Control API Implementation
+ *  Copyright (C) Gerald Carter                   2005.
+ *  
+ *  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"
+
+/* Implementation for internal winreg service */
+
+/*********************************************************************
+*********************************************************************/
+
+static WERROR winreg_stop( const char *service, SERVICE_STATUS *service_status )
+{
+       return WERR_ACCESS_DENIED;
+}
+
+/*********************************************************************
+*********************************************************************/
+
+static WERROR winreg_start( const char *service )
+{
+       return WERR_ACCESS_DENIED;
+}
+
+/*********************************************************************
+*********************************************************************/
+
+static WERROR winreg_status( const char *service, SERVICE_STATUS *service_status )
+{
+       ZERO_STRUCTP( service_status );
+
+       service_status->type              = 0x20;
+       service_status->state              = SVCCTL_RUNNING;
+       
+       return WERR_OK;
+}
+
+/*********************************************************************
+*********************************************************************/
+
+/* struct for svcctl control to manipulate winreg service */
+
+SERVICE_CONTROL_OPS winreg_svc_ops = {
+       winreg_stop,
+       winreg_start,
+       winreg_status
+};
index 72d021d4e64b2f53f0289a488535c5cd6a740681..805e45f6ea33f2d870e3905d88dd615b297eb882 100644 (file)
@@ -80,7 +80,8 @@ static BOOL in_chained_smb(void)
        return (chain_size != 0);
 }
 
-static void received_unlock_msg(int msg_type, pid_t src, void *buf, size_t len);
+static void received_unlock_msg(int msg_type, struct process_id src,
+                               void *buf, size_t len);
 
 /****************************************************************************
  Function to push a blocking lock request onto the lock queue.
@@ -127,7 +128,7 @@ BOOL push_blocking_lock_request( char *inbuf, int length, int lock_timeout,
 
        /* Add a pending lock record for this. */
        status = brl_lock(blr->fsp->dev, blr->fsp->inode, blr->fsp->fnum,
-                       lock_pid, sys_getpid(), blr->fsp->conn->cnum,
+                       lock_pid, procid_self(), blr->fsp->conn->cnum,
                        offset, count, PENDING_LOCK, &my_lock_ctx);
 
        if (!NT_STATUS_IS_OK(status)) {
@@ -351,8 +352,8 @@ static BOOL process_lockread(blocking_lock_record *blr)
        SSVAL(p,0,nread); p += 2;
        set_message_end(outbuf, p+nread);
        
-       DEBUG(3, ( "process_lockread file = %s, fnum=%d num=%d nread=%d\n",
-                  fsp->fsp_name, fsp->fnum, (int)numtoread, (int)nread ) );
+       DEBUG(3, ( "process_lockread file = %s, fnum=%d num=%lu nread=%ld\n",
+                  fsp->fsp_name, fsp->fnum, (unsigned long)numtoread, (long)nread ) );
        
        send_blocking_reply(outbuf,outsize);
        return True;
@@ -526,7 +527,7 @@ void remove_pending_lock_requests_by_fid(files_struct *fsp)
 file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum ));
 
                        brl_unlock(blr->fsp->dev, blr->fsp->inode, blr->fsp->fnum,
-                               blr->lock_pid, sys_getpid(), blr->fsp->conn->cnum,
+                               blr->lock_pid, procid_self(), blr->fsp->conn->cnum,
                                blr->offset, blr->count, True, NULL, NULL);
 
                        free_blocking_lock_record(blr);
@@ -552,7 +553,7 @@ file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum ));
 
                        blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT);
                        brl_unlock(blr->fsp->dev, blr->fsp->inode, blr->fsp->fnum,
-                               blr->lock_pid, sys_getpid(), blr->fsp->conn->cnum,
+                               blr->lock_pid, procid_self(), blr->fsp->conn->cnum,
                                blr->offset, blr->count, True, NULL, NULL);
                        free_blocking_lock_record(blr);
                }
@@ -563,7 +564,8 @@ file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum ));
   Set a flag as an unlock request affects one of our pending locks.
 *****************************************************************************/
 
-static void received_unlock_msg(int msg_type, pid_t src, void *buf, size_t len)
+static void received_unlock_msg(int msg_type, struct process_id src,
+                               void *buf, size_t len)
 {
        DEBUG(10,("received_unlock_msg\n"));
        process_blocking_lock_queue(time(NULL));
@@ -641,7 +643,7 @@ void process_blocking_lock_queue(time_t t)
                                fsp->fnum, fsp->fsp_name ));
 
                        brl_unlock(fsp->dev, fsp->inode, fsp->fnum,
-                               blr->lock_pid, sys_getpid(), conn->cnum,
+                               blr->lock_pid, procid_self(), conn->cnum,
                                blr->offset, blr->count, True, NULL, NULL);
 
                        blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT);
@@ -658,7 +660,7 @@ void process_blocking_lock_queue(time_t t)
                        blocking_lock_reply_error(blr,NT_STATUS_ACCESS_DENIED);
 
                        brl_unlock(fsp->dev, fsp->inode, fsp->fnum,
-                                       blr->lock_pid, sys_getpid(), conn->cnum,
+                                       blr->lock_pid, procid_self(), conn->cnum,
                                        blr->offset, blr->count, True, NULL, NULL);
 
                        free_blocking_lock_record(blr);
@@ -673,7 +675,7 @@ void process_blocking_lock_queue(time_t t)
                        blocking_lock_reply_error(blr,NT_STATUS_ACCESS_DENIED);
 
                        brl_unlock(fsp->dev, fsp->inode, fsp->fnum,
-                                       blr->lock_pid, sys_getpid(), conn->cnum,
+                                       blr->lock_pid, procid_self(), conn->cnum,
                                        blr->offset, blr->count, True, NULL, NULL);
 
                        free_blocking_lock_record(blr);
@@ -690,7 +692,7 @@ void process_blocking_lock_queue(time_t t)
                if(blocking_lock_record_process(blr)) {
 
                        brl_unlock(fsp->dev, fsp->inode, fsp->fnum,
-                                       blr->lock_pid, sys_getpid(), conn->cnum,
+                                       blr->lock_pid, procid_self(), conn->cnum,
                                        blr->offset, blr->count, True, NULL, NULL);
 
                        free_blocking_lock_record(blr);
index 1178400e4db25fe481915727930d61e2ec312a01..738d12151db5252a33972a60878ff3d5d82d28d5 100644 (file)
@@ -33,7 +33,8 @@ NTSTATUS change_trust_account_password( const char *domain, const char *remote_m
        NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
        struct in_addr pdc_ip;
        fstring dc_name;
-       struct cli_state *cli;
+       struct cli_state *cli = NULL;
+       struct rpc_pipe_client *netlogon_pipe = NULL;
 
        DEBUG(5,("change_trust_account_password: Attempting to change trust account password in domain %s....\n",
                domain));
@@ -71,20 +72,18 @@ NTSTATUS change_trust_account_password( const char *domain, const char *remote_m
         * Now start the NT Domain stuff :-).
         */
 
-       if(cli_nt_session_open(cli, PI_NETLOGON) == False) {
+       /* Shouldn't we open this with schannel ? JRA. */
+
+       netlogon_pipe = cli_rpc_pipe_open_noauth(cli, PI_NETLOGON, &nt_status);
+       if (!netlogon_pipe) {
                DEBUG(0,("modify_trust_password: unable to open the domain client session to machine %s. Error was : %s.\n", 
-                       dc_name, cli_errstr(cli)));
-               cli_nt_session_close(cli);
-               cli_ulogoff(cli);
+                       dc_name, nt_errstr(nt_status)));
                cli_shutdown(cli);
-               nt_status = NT_STATUS_UNSUCCESSFUL;
                goto failed;
        }
 
-       nt_status = trust_pw_find_change_and_store_it(cli, cli->mem_ctx, domain);
+       nt_status = trust_pw_find_change_and_store_it(netlogon_pipe, cli->mem_ctx, domain);
   
-       cli_nt_session_close(cli);
-       cli_ulogoff(cli);
        cli_shutdown(cli);
        
 failed:
index 374c57a083ae582d76f393c140c212e655e1f619..c1168583ae7e2a9969fc45832167b8986c61a117 100644 (file)
@@ -946,7 +946,7 @@ static BOOL check_passwd_history(SAM_ACCOUNT *sampass, const char *plaintext)
        int i;
        uint32 pwHisLen, curr_pwHisLen;
 
-       account_policy_get(AP_PASSWORD_HISTORY, &pwHisLen);
+       pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHisLen);
        if (pwHisLen == 0) {
                return False;
        }
@@ -1017,7 +1017,7 @@ NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passw
                return NT_STATUS_ACCOUNT_RESTRICTION;
        }
 
-       if (account_policy_get(AP_MIN_PASSWORD_LEN, &min_len) && (str_charnum(new_passwd) < min_len)) {
+       if (pdb_get_account_policy(AP_MIN_PASSWORD_LEN, &min_len) && (str_charnum(new_passwd) < min_len)) {
                DEBUG(1, ("user %s cannot change password - password too short\n", 
                          username));
                DEBUGADD(1, (" account policy min password len = %d\n", min_len));
index afc645ca0627bd1bb7470d4d69d9e8f495b946e8..becca003b64df3241a1f37acf86eef2efafc217e 100644 (file)
@@ -110,31 +110,30 @@ static int close_filestruct(files_struct *fsp)
  If any deferred opens are waiting on this close, notify them.
 ****************************************************************************/
 
-static void notify_deferred_opens(files_struct *fsp)
+static void notify_deferred_opens(struct share_mode_lock *lck)
 {
-       deferred_open_entry *de_array = NULL;
-       int num_de_entries, i;
-       pid_t mypid = sys_getpid();
-
-       if (!lp_defer_sharing_violations()) {
-               return;
-       }
-
-       num_de_entries = get_deferred_opens(fsp->conn, fsp->dev, fsp->inode, &de_array);
-       for (i = 0; i < num_de_entries; i++) {
-               deferred_open_entry *entry = &de_array[i];
-               if (entry->pid == mypid) {
-                       /*
-                        * We need to notify ourself to retry the open.
-                        * Do this by finding the queued SMB record, moving it
-                        * to the head of the queue and changing the wait time to zero.
-                        */
-                       schedule_sharing_violation_open_smb_message(entry->mid);
-               } else {
-                       send_deferred_open_retry_message(entry);
-               }
-       }
-       SAFE_FREE(de_array);
+       int i;
+       for (i=0; i<lck->num_share_modes; i++) {
+               struct share_mode_entry *e = &lck->share_modes[i];
+               if (!is_deferred_open_entry(e)) {
+                       continue;
+               }
+               if (procid_is_me(&e->pid)) {
+                       /*
+                        * We need to notify ourself to retry the open.  Do
+                        * this by finding the queued SMB record, moving it to
+                        * the head of the queue and changing the wait time to
+                        * zero.
+                        */
+                       schedule_deferred_open_smb_message(e->op_mid);
+               } else {
+                       message_send_pid(e->pid, MSG_SMB_OPEN_RETRY,
+                                        e, sizeof(*e), True);
+               }
+       }
 }
 
 /****************************************************************************
@@ -148,13 +147,12 @@ static void notify_deferred_opens(files_struct *fsp)
 
 static int close_normal_file(files_struct *fsp, BOOL normal_close)
 {
-       share_mode_entry *share_entry = NULL;
-       size_t share_entry_count = 0;
        BOOL delete_file = False;
        connection_struct *conn = fsp->conn;
        int saved_errno = 0;
        int err = 0;
        int err1 = 0;
+       struct share_mode_lock *lck;
 
        remove_pending_lock_requests_by_fid(fsp);
 
@@ -194,23 +192,34 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close)
         * This prevents race conditions with the file being created. JRA.
         */
 
-       lock_share_entry_fsp(fsp);
-
-       share_entry_count = del_share_mode(fsp, &share_entry,
-                                          &delete_file);
+       lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, fsp->fsp_name);
 
-       DEBUG(10,("close_normal_file: share_entry_count = %lu for file %s\n",
-               (unsigned long)share_entry_count, fsp->fsp_name ));
+       if (lck == NULL) {
+               DEBUG(0, ("Could not get share mode lock\n"));
+               return EINVAL;
+       }
 
-       if (share_entry_count != 0) {
-               /* We're not the last ones -- don't delete */
-               delete_file = False;
+       if (!del_share_mode(lck, fsp)) {
+               DEBUG(0, ("Could not delete share entry\n"));
        }
 
-       SAFE_FREE(share_entry);
+       delete_file = lck->delete_on_close;
+
+       if (delete_file) {
+               int i;
+               /* See if others still have the file open. If this is the
+                * case, then don't delete */
+               for (i=0; i<lck->num_share_modes; i++) {
+                       if (is_valid_share_mode_entry(&lck->share_modes[i])) {
+                               delete_file = False;
+                               break;
+                       }
+               }
+       }
 
        /* Notify any deferred opens waiting on this close. */
-       notify_deferred_opens(fsp);
+       notify_deferred_opens(lck);
+       reply_to_oplock_break_requests(fsp);
 
        /*
         * NT can set delete_on_close of the last open
@@ -234,7 +243,7 @@ with error %s\n", fsp->fsp_name, strerror(errno) ));
                process_pending_change_notify_queue((time_t)0);
        }
 
-       unlock_share_entry_fsp(fsp);
+       talloc_free(lck);
 
        if(fsp->oplock_type)
                release_file_oplock(fsp);
@@ -296,7 +305,7 @@ static int close_directory(files_struct *fsp, BOOL normal_close)
         */
 
        if (normal_close &&
-           get_delete_on_close_flag(fsp->dev, fsp->inode)) {
+           get_delete_on_close_flag(fsp->dev, fsp->inode, fsp->fsp_name)) {
                BOOL ok = rmdir_internals(fsp->conn, fsp->fsp_name);
                DEBUG(5,("close_directory: %s. Delete on close was set - deleting directory %s.\n",
                        fsp->fsp_name, ok ? "succeeded" : "failed" ));
index b69868ecec10af5cd073d8e03fb34509569cef40..bb000bac30ec86ee39045e3b3410911f51c48f66 100644 (file)
@@ -287,7 +287,7 @@ the message contains just a share name and all instances of that
 share are unmounted
 the special sharename '*' forces unmount of all shares
 ****************************************************************************/
-void msg_force_tdis(int msg_type, pid_t pid, void *buf, size_t len)
+void msg_force_tdis(int msg_type, struct process_id pid, void *buf, size_t len)
 {
        connection_struct *conn, *next;
        fstring sharename;
index 32e2f058fc23fea73b8c42dde24969a709aa1447..07d3181144f7dfd53c70fdbacdf3cd35c22c21ab 100644 (file)
@@ -38,7 +38,7 @@ TDB_CONTEXT *conn_tdb_ctx(void)
 static void make_conn_key(connection_struct *conn, const char *name, TDB_DATA *pkbuf, struct connections_key *pkey)
 {
        ZERO_STRUCTP(pkey);
-       pkey->pid = sys_getpid();
+       pkey->pid = procid_self();
        pkey->cnum = conn?conn->cnum:-1;
        fstrcpy(pkey->name, name);
 #ifdef DEVELOPER
@@ -107,8 +107,8 @@ static int count_fn( TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *u
        /* If the pid was not found delete the entry from connections.tdb */
 
        if (cs->Clear && !process_exists(crec.pid) && (errno == ESRCH)) {
-               DEBUG(2,("pid %u doesn't exist - deleting connections %d [%s]\n",
-                       (unsigned int)crec.pid, crec.cnum, crec.name));
+               DEBUG(2,("pid %s doesn't exist - deleting connections %d [%s]\n",
+                       procid_str_static(&crec.pid), crec.cnum, crec.name));
                if (tdb_delete(the_tdb, kbuf) != 0)
                        DEBUG(0,("count_fn: tdb_delete failed with error %s\n", tdb_errorstr(tdb) ));
                return 0;
@@ -174,7 +174,7 @@ BOOL claim_connection(connection_struct *conn, const char *name,int max_connecti
        /* fill in the crec */
        ZERO_STRUCT(crec);
        crec.magic = 0x280267;
-       crec.pid = sys_getpid();
+       crec.pid = procid_self();
        crec.cnum = conn?conn->cnum:-1;
        if (conn) {
                crec.uid = conn->uid;
index 090a2f6d813c93621d6822db91d61c5cfc81ebc9..3cdcae5c7f5f8525d11b94b994a1601b90193965 100644 (file)
@@ -41,23 +41,22 @@ void set_saved_error_triple(int eclass, int ecode, NTSTATUS status)
        override_ERR_ntstatus = status;
 }
 
+void set_saved_ntstatus(NTSTATUS status)
+{
+       uint8 tmp_eclass;       /* Hmmm. override_ERR_class is not uint8... */
+       override_ERR_ntstatus = status;
+       ntstatus_to_dos(status, &tmp_eclass, &override_ERR_code);
+       override_ERR_class = tmp_eclass;
+       
+}
+
 /****************************************************************************
  Return the current settings of the error triple. Return True if any are set.
 ****************************************************************************/
 
-BOOL get_saved_error_triple(int *peclass, int *pecode, NTSTATUS *pstatus)
+NTSTATUS get_saved_ntstatus(void)
 {
-       if (peclass) {
-               *peclass = override_ERR_class;
-       }
-       if (pecode) {
-               *pecode = override_ERR_code;
-       }
-       if (pstatus) {
-               *pstatus = override_ERR_ntstatus;
-       }
-
-       return (override_ERR_class || !NT_STATUS_IS_OK(override_ERR_ntstatus));
+       return override_ERR_ntstatus;
 }
 
 /****************************************************************************
index 65986e96127bc90be36ecd6b0e8270b9ef37ab11..181e17b11fb445fcc1a9238cc21045c37c578e77 100644 (file)
@@ -65,7 +65,7 @@ files_struct *file_new(connection_struct *conn)
 {
        int i;
        static int first_file;
-       files_struct *fsp, *next;
+       files_struct *fsp;
 
        /* we want to give out file handles differently on each new
           connection because of a common bug in MS clients where they try to
@@ -76,32 +76,21 @@ files_struct *file_new(connection_struct *conn)
                first_file = (sys_getpid() ^ (int)time(NULL)) % real_max_open_files;
        }
 
+       /* TODO: Port the id-tree implementation from Samba4 */
+
        i = bitmap_find(file_bmap, first_file);
        if (i == -1) {
-               /* 
-                * Before we give up, go through the open files 
-                * and see if there are any files opened with a
-                * batch oplock. If so break the oplock and then
-                * re-use that entry (if it becomes closed).
-                * This may help as NT/95 clients tend to keep
-                * files batch oplocked for quite a long time
-                * after they have finished with them.
-                */
-               for (fsp=Files;fsp;fsp=next) {
-                       next=fsp->next;
-                       if (attempt_close_oplocked_file(fsp)) {
-                               return file_new(conn);
-                       }
-               }
-
                DEBUG(0,("ERROR! Out of file structures\n"));
-               set_saved_error_triple(ERRSRV, ERRnofids, NT_STATUS_TOO_MANY_OPENED_FILES);
+               /* TODO: We have to unconditionally return a DOS error here,
+                * W2k3 even returns ERRDOS/ERRnofids for ntcreate&x with
+                * NTSTATUS negotiated */
+               set_saved_ntstatus(NT_STATUS_TOO_MANY_OPENED_FILES);
                return NULL;
        }
 
        fsp = SMB_MALLOC_P(files_struct);
        if (!fsp) {
-               set_saved_error_triple(ERRDOS, ERRnomem, NT_STATUS_NO_MEMORY);
+               set_saved_ntstatus(NT_STATUS_NO_MEMORY);
                return NULL;
        }
 
@@ -110,7 +99,7 @@ files_struct *file_new(connection_struct *conn)
        fsp->fh = SMB_MALLOC_P(struct fd_handle);
        if (!fsp->fh) {
                SAFE_FREE(fsp);
-               set_saved_error_triple(ERRDOS, ERRnomem, NT_STATUS_NO_MEMORY);
+               set_saved_ntstatus(NT_STATUS_NO_MEMORY);
                return NULL;
        }
 
@@ -293,7 +282,9 @@ files_struct *file_find_dif(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_i
                                DLIST_PROMOTE(Files, fsp);
                        }
                        /* Paranoia check. */
-                       if (fsp->fh->fd == -1 && fsp->oplock_type != NO_OPLOCK) {
+                       if ((fsp->fh->fd == -1) &&
+                           (fsp->oplock_type != NO_OPLOCK) &&
+                           (fsp->oplock_type != FAKE_LEVEL_II_OPLOCK)) {
                                DEBUG(0,("file_find_dif: file %s dev = %x, inode = %.0f, file_id = %u \
 oplock_type = %u is a stat open with oplock type !\n", fsp->fsp_name, (unsigned int)fsp->dev,
                                                (double)fsp->inode, (unsigned int)fsp->file_id,
index 613dda9a16bd3d1374d5d39d1989b6033e1bbd09..335ba8e2ef9315e21e1f4240c7a47d14c85b2e27 100644 (file)
@@ -212,7 +212,7 @@ static BOOL is_mangled_component(const char *name, size_t len)
 {
        unsigned int i;
 
-       M_DEBUG(10,("is_mangled_component %s (len %u) ?\n", name, (unsigned int)len));
+       M_DEBUG(10,("is_mangled_component %s (len %lu) ?\n", name, (unsigned long)len));
 
        /* check the length */
        if (len > 12 || len < 8)
@@ -250,7 +250,7 @@ static BOOL is_mangled_component(const char *name, size_t len)
                }
        }
 
-       M_DEBUG(10,("is_mangled_component %s (len %u) -> yes\n", name, (unsigned int)len));
+       M_DEBUG(10,("is_mangled_component %s (len %lu) -> yes\n", name, (unsigned long)len));
 
        return True;
 }
index 5af7d3e451e01ac1beea324ed3d30bf80f6a7670..e975da3e1530e16bde6b588fd11de64f121eb160 100644 (file)
@@ -43,6 +43,7 @@ static void msg_deliver(void)
   int fd;
   char *msg;
   int len;
+  ssize_t sz;
 
   if (! (*lp_msg_command()))
     {
@@ -70,14 +71,20 @@ static void msg_deliver(void)
       if (msgbuf[i] == '\r' && i < (msgpos-1) && msgbuf[i+1] == '\n') {
        i++; continue;
       }
-      write(fd, &msgbuf[i++], 1);
+      sz = write(fd, &msgbuf[i++], 1);
+      if ( sz != 1 ) {
+       DEBUG(0,("Write error to fd %d: %ld(%d)\n",fd, (long)sz, errno ));
+      }
     }
   } else {
     for (i = 0; i < len;) {
       if (msg[i] == '\r' && i < (len-1) && msg[i+1] == '\n') {
        i++; continue;
       }
-      write(fd, &msg[i++],1);
+      sz = write(fd, &msg[i++],1);
+      if ( sz != 1 ) {
+       DEBUG(0,("Write error to fd %d: %ld(%d)\n",fd, (long)sz, errno ));
+      }
     }
     SAFE_FREE(msg);
   }
index f9b70de0ace3d3e17237cf73f0d64fa63b1bf078..3db55bad14d275da0adb908071a51daaa6069c80 100644 (file)
@@ -24,7 +24,6 @@
 extern int max_send;
 extern enum protocol_types Protocol;
 extern int smb_read_error;
-extern int global_oplock_break;
 extern struct current_user current_user;
 
 static const char *known_nt_pipes[] = {
@@ -43,6 +42,7 @@ static const char *known_nt_pipes[] = {
        "\\rpcecho",
         "\\svcctl",
        "\\eventlog",
+       "\\unixinfo",
        NULL
 };
 
@@ -861,7 +861,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n",
                } else {
                        SCVAL(p,0, EXCLUSIVE_OPLOCK_RETURN);
                }
-       } else if (LEVEL_II_OPLOCK_TYPE(fsp->oplock_type)) {
+       } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
                SCVAL(p,0, LEVEL_II_OPLOCK_RETURN);
        } else {
                SCVAL(p,0,NO_OPLOCK_RETURN);
@@ -1666,11 +1666,11 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new
                        &info);
 
        if (!fsp1) {
-               get_saved_error_triple(NULL, NULL, &status);
+               status = get_saved_ntstatus();
                if (NT_STATUS_IS_OK(status)) {
                        status = NT_STATUS_ACCESS_DENIED;
                }
-               set_saved_error_triple(0, 0, NT_STATUS_OK);
+               set_saved_ntstatus(NT_STATUS_OK);
                return status;
        }
 
@@ -1684,11 +1684,11 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new
                        &info);
 
        if (!fsp2) {
-               get_saved_error_triple(NULL, NULL, &status);
+               status = get_saved_ntstatus();
                if (NT_STATUS_IS_OK(status)) {
                        status = NT_STATUS_ACCESS_DENIED;
                }
-               set_saved_error_triple(0, 0, NT_STATUS_OK);
+               set_saved_ntstatus(NT_STATUS_OK);
                close_file(fsp1,False);
                return status;
        }
@@ -1989,7 +1989,7 @@ static int call_nt_transact_query_security_desc(connection_struct *conn, char *i
                return(UNIXERROR(ERRDOS,ERRnoaccess));
        }
 
-       DEBUG(3,("call_nt_transact_query_security_desc: sd_size = %d.\n",(int)sd_size));
+       DEBUG(3,("call_nt_transact_query_security_desc: sd_size = %lu.\n",(unsigned long)sd_size));
 
        SIVAL(params,0,(uint32)sd_size);
 
@@ -2743,21 +2743,6 @@ int reply_nttrans(connection_struct *conn,
        uint32 num_params_sofar, num_data_sofar;
        START_PROFILE(SMBnttrans);
 
-       if(global_oplock_break &&
-                       ((function_code == NT_TRANSACT_CREATE) ||
-                        (function_code == NT_TRANSACT_RENAME))) {
-               /*
-                * Queue this open message as we are the process of an oplock break.
-                */
-
-               DEBUG(2,("reply_nttrans: queueing message code 0x%x \
-due to being in oplock break state.\n", (unsigned int)function_code ));
-
-               push_oplock_pending_smb_message( inbuf, length);
-               END_PROFILE(SMBnttrans);
-               return -1;
-       }
-
        if (IS_IPC(conn) && (function_code != NT_TRANSACT_CREATE)) {
                END_PROFILE(SMBnttrans);
                return ERROR_DOS(ERRSRV,ERRaccess);
index ed847826d5205495075ee13694432ab473a0f9f4..56d31c69409c4971feb9ac23d2b345986efef110 100644 (file)
 
 extern struct current_user current_user;
 extern userdom_struct current_user_info;
-extern uint16 global_oplock_port;
 extern uint16 global_smbpid;
 extern BOOL global_client_failed_oplock_break;
 
-struct dev_inode_bundle {
+struct deferred_open_record {
+       BOOL delayed_for_oplocks;
        SMB_DEV_T dev;
        SMB_INO_T inode;
 };
@@ -208,7 +208,6 @@ static BOOL open_file(files_struct *fsp,
        BOOL file_existed = VALID_STAT(*psbuf);
 
        fsp->fh->fd = -1;
-       fsp->oplock_type = NO_OPLOCK;
        errno = EPERM;
 
        /* Check permissions */
@@ -283,8 +282,7 @@ static BOOL open_file(files_struct *fsp,
                /* Don't create files with Microsoft wildcard characters. */
                if ((local_flags & O_CREAT) && !file_existed &&
                    ms_has_wild(fname))  {
-                       set_saved_error_triple(ERRDOS, ERRinvalidname,
-                                              NT_STATUS_OBJECT_NAME_INVALID);
+                       set_saved_ntstatus(NT_STATUS_OBJECT_NAME_INVALID);
                        return False;
                }
 
@@ -354,7 +352,6 @@ static BOOL open_file(files_struct *fsp,
        }
        fsp->print_file = False;
        fsp->modified = False;
-       fsp->oplock_type = NO_OPLOCK;
        fsp->sent_oplock_break = NO_BREAK_SENT;
        fsp->is_directory = False;
        fsp->is_stat = False;
@@ -397,7 +394,7 @@ static BOOL is_executable(const char *fname)
  Returns True if conflict, False if not.
 ****************************************************************************/
 
-static BOOL share_conflict(share_mode_entry *entry,
+static BOOL share_conflict(struct share_mode_entry *entry,
                           uint32 access_mask,
                           uint32 share_access)
 {
@@ -445,7 +442,6 @@ static BOOL share_conflict(share_mode_entry *entry,
                DEBUG(10,("share_conflict: check %d conflict am = 0x%x, right = 0x%x, \
 sa = 0x%x, share = 0x%x\n", (num), (unsigned int)(am), (unsigned int)(right), (unsigned int)(sa), \
                        (unsigned int)(share) )); \
-               set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION); \
                return True; \
        }
 #else
@@ -454,7 +450,6 @@ sa = 0x%x, share = 0x%x\n", (num), (unsigned int)(am), (unsigned int)(right), (u
                DEBUG(10,("share_conflict: check %d conflict am = 0x%x, right = 0x%x, \
 sa = 0x%x, share = 0x%x\n", (num), (unsigned int)(am), (unsigned int)(right), (unsigned int)(sa), \
                        (unsigned int)(share) )); \
-               set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION); \
                return True; \
        }
 #endif
@@ -480,11 +475,23 @@ sa = 0x%x, share = 0x%x\n", (num), (unsigned int)(am), (unsigned int)(right), (u
 
 #if defined(DEVELOPER)
 static void validate_my_share_entries(int num,
-                                       share_mode_entry *share_entry)
+                                     struct share_mode_entry *share_entry)
 {
        files_struct *fsp;
 
-       if (share_entry->pid != sys_getpid()) {
+       if (!procid_is_me(&share_entry->pid)) {
+               return;
+       }
+
+       if (is_deferred_open_entry(share_entry) &&
+           !open_was_deferred(share_entry->op_mid)) {
+               pstring str;
+               DEBUG(0, ("Got a deferred entry without a request: "
+                         "PANIC: %s\n", share_mode_str(num, share_entry)));
+               smb_panic(str);
+       }
+
+       if (!is_valid_share_mode_entry(share_entry)) {
                return;
        }
 
@@ -497,7 +504,26 @@ static void validate_my_share_entries(int num,
                          "share entry with an open file\n");
        }
 
+       if (is_deferred_open_entry(share_entry) ||
+           is_unused_share_mode_entry(share_entry)) {
+               goto panic;
+       }
+
+       if ((share_entry->op_type == NO_OPLOCK) &&
+           (fsp->oplock_type == FAKE_LEVEL_II_OPLOCK)) {
+               /* Someone has already written to it, but I haven't yet
+                * noticed */
+               return;
+       }
+
        if (((uint16)fsp->oplock_type) != share_entry->op_type) {
+               goto panic;
+       }
+
+       return;
+
+ panic:
+       {
                pstring str;
                DEBUG(0,("validate_my_share_entries: PANIC : %s\n",
                         share_mode_str(num, share_entry) ));
@@ -510,375 +536,217 @@ static void validate_my_share_entries(int num,
 }
 #endif
 
-struct share_mode_entry_list {
-       struct share_mode_entry_list *next, *prev;
-       share_mode_entry entry;
-};
-
-static void free_broken_entry_list(struct share_mode_entry_list *broken_entry_list)
+static BOOL is_stat_open(uint32 access_mask)
 {
-       while (broken_entry_list) {
-               struct share_mode_entry_list *broken_entry = broken_entry_list;
-               DLIST_REMOVE(broken_entry_list, broken_entry);
-               SAFE_FREE(broken_entry);
-       }
-}
-
-static BOOL cause_oplock_break(int request, int existing, uint32 access_mask)
-{
-       if ((access_mask == DELETE_ACCESS) &&
-           (request == NO_OPLOCK)) {
-               /* This is a delete request */
-               return (BATCH_OPLOCK_TYPE(existing) != 0);
-       }
-
-       if (EXCLUSIVE_OPLOCK_TYPE(existing) && (request != NO_OPLOCK)) {
-               return True;
-       }
-
-       if ((existing != NO_OPLOCK) && (request == NO_OPLOCK)) {
-               return True;
-       }
-
-       return False;
+       return (access_mask &&
+               ((access_mask & ~(SYNCHRONIZE_ACCESS| FILE_READ_ATTRIBUTES|
+                                 FILE_WRITE_ATTRIBUTES))==0) &&
+               ((access_mask & (SYNCHRONIZE_ACCESS|FILE_READ_ATTRIBUTES|
+                                FILE_WRITE_ATTRIBUTES)) != 0));
 }
 
 /****************************************************************************
- Deal with open deny mode and oplock break processing.
+ Deal with share modes
  Invarient: Share mode must be locked on entry and exit.
  Returns -1 on error, or number of share modes on success (may be zero).
 ****************************************************************************/
 
-static int open_mode_check(connection_struct *conn,
-                          const char *fname,
-                          SMB_DEV_T dev,
-                          SMB_INO_T inode, 
-                          uint32 access_mask,
-                          uint32 share_access,
-                          uint32 create_options,
-                          int *p_oplock_request,
-                          BOOL *p_all_current_opens_are_level_II)
+static NTSTATUS open_mode_check(connection_struct *conn,
+                               const char *fname,
+                               struct share_mode_lock *lck,
+                               uint32 access_mask,
+                               uint32 share_access,
+                               uint32 create_options,
+                               BOOL *file_existed)
 {
        int i;
-       int num_share_modes;
-       int oplock_contention_count = 0;
-       share_mode_entry *old_shares = NULL;
-       BOOL broke_oplock;
-       BOOL delete_on_close;
 
-       num_share_modes = get_share_modes(dev, inode, &old_shares, &delete_on_close);
-       
-       if(num_share_modes == 0) {
-               SAFE_FREE(old_shares);
-               return 0;
+       if(lck->num_share_modes == 0) {
+               return NT_STATUS_OK;
        }
+
+       *file_existed = True;
        
-       if (access_mask &&
-           ((access_mask & ~(SYNCHRONIZE_ACCESS| FILE_READ_ATTRIBUTES|
-                             FILE_WRITE_ATTRIBUTES))==0) &&
-           ((access_mask & (SYNCHRONIZE_ACCESS|FILE_READ_ATTRIBUTES|
-                            FILE_WRITE_ATTRIBUTES)) != 0)) {
+       if (is_stat_open(access_mask)) {
                /* Stat open that doesn't trigger oplock breaks or share mode
                 * checks... ! JRA. */
-               SAFE_FREE(old_shares);
-               return num_share_modes;
+               return NT_STATUS_OK;
        }
 
        /* A delete on close prohibits everything */
 
-       if (delete_on_close) {
-               SAFE_FREE(old_shares);
-               errno = EACCES;
-               return -1;
+       if (lck->delete_on_close) {
+               return NT_STATUS_DELETE_PENDING;
        }
 
        /*
         * Check if the share modes will give us access.
         */
        
-       do {
-               struct share_mode_entry_list *broken_entry_list = NULL;
-               struct share_mode_entry_list *broken_entry = NULL;
-
-               broke_oplock = False;
-               *p_all_current_opens_are_level_II = True;
-               
-               for(i = 0; i < num_share_modes; i++) {
-                       share_mode_entry *share_entry = &old_shares[i];
-                       BOOL opb_ret;
-                       
 #if defined(DEVELOPER)
-                       validate_my_share_entries(i, share_entry);
+       for(i = 0; i < lck->num_share_modes; i++) {
+               validate_my_share_entries(i, &lck->share_modes[i]);
+       }
 #endif
 
-                       /* 
-                        * By observation of NetBench, oplocks are broken
-                        * *before* share modes are checked. This allows a
-                        * file to be closed by the client if the share mode
-                        * would deny access and the client has an oplock.
-                        * Check if someone has an oplock on this file. If so
-                        * we must break it before continuing.
-                        */
+       if (!lp_share_modes(SNUM(conn))) {
+               return NT_STATUS_OK;
+       }
 
-                       if (!cause_oplock_break(*p_oplock_request,
-                                               share_entry->op_type,
-                                               access_mask)) {
-                               if (!LEVEL_II_OPLOCK_TYPE(share_entry->op_type)) {
-                                       *p_all_current_opens_are_level_II = False;
-                               }
-                               continue;
-                       }
+       /* Now we check the share modes, after any oplock breaks. */
+       for(i = 0; i < lck->num_share_modes; i++) {
 
-                       /* This is an oplock break */
-
-                       DEBUG(5,("open_mode_check: oplock_request = %d, "
-                                "breaking oplock (%x) on file %s, "
-                                "dev = %x, inode = %.0f\n",
-                                *p_oplock_request, share_entry->op_type,
-                                fname, (unsigned int)dev, (double)inode));
-                               
-                       /* Ensure the reply for the open uses the correct
-                        * sequence number. */
-                       /* This isn't a real deferred packet as it's response
-                        * will also increment the sequence.
-                        */
-                       srv_defer_sign_response(get_current_mid());
-
-                       /* Oplock break - unlock to request it. */
-                       unlock_share_entry(conn, dev, inode);
-                               
-                       opb_ret = request_oplock_break(share_entry);
-                               
-                       /* Now relock. */
-                       lock_share_entry(conn, dev, inode);
-                               
-                       if (!opb_ret) {
-                               DEBUG(0,("open_mode_check: FAILED when breaking "
-                                        "oplock (%x) on file %s, dev = %x, "
-                                        "inode = %.0f\n",
-                                        old_shares[i].op_type, fname,
-                                        (unsigned int)dev, (double)inode));
-                               SAFE_FREE(old_shares);
-                               set_saved_error_triple(ERRDOS, ERRbadshare,
-                                                      NT_STATUS_SHARING_VIOLATION);
-                               return -1;
-                       }
-                               
-                       broken_entry = SMB_MALLOC_P(struct share_mode_entry_list);
-                       if (!broken_entry) {
-                               smb_panic("open_mode_check: malloc fail.\n");
-                       }
-                       broken_entry->entry = *share_entry;
-                       DLIST_ADD(broken_entry_list, broken_entry);
-                       broke_oplock = True;
-                               
-               } /* end for */
-               
-               if (broke_oplock) {
-                       /* Update the current open table. */
-                       SAFE_FREE(old_shares);
-                       num_share_modes = get_share_modes(dev, inode,
-                                                         &old_shares,
-                                                         &delete_on_close);
+               if (!is_valid_share_mode_entry(&lck->share_modes[i])) {
+                       continue;
                }
 
-               if (lp_share_modes(SNUM(conn))) {
-                       /* Now we check the share modes, after any oplock breaks. */
-                       for(i = 0; i < num_share_modes; i++) {
-                               share_mode_entry *share_entry = &old_shares[i];
-
-                               /* someone else has a share lock on it, check to see
-                                * if we can too */
-                               if (share_conflict(share_entry, access_mask,
-                                                  share_access)) {
-                                       SAFE_FREE(old_shares);
-                                       free_broken_entry_list(broken_entry_list);
-                                       errno = EACCES;
-                                       return -1;
-                               }
-                       }
+               /* someone else has a share lock on it, check to see if we can
+                * too */
+               if (share_conflict(&lck->share_modes[i],
+                                  access_mask, share_access)) {
+                       return NT_STATUS_SHARING_VIOLATION;
                }
-
-               for(broken_entry = broken_entry_list; broken_entry;
-                   broken_entry = broken_entry->next) {
-                       oplock_contention_count++;
-                       
-                       /* Paranoia check that this is no longer an exlusive entry. */
-                       for(i = 0; i < num_share_modes; i++) {
-                               share_mode_entry *share_entry = &old_shares[i];
-                               
-                               if (!(share_modes_identical(&broken_entry->entry,
-                                                           share_entry) && 
-                                     EXCLUSIVE_OPLOCK_TYPE(share_entry->op_type))) {
-                                       continue;
-                               }
-                                       
-                               /*
-                                * This should not happen. The target left this oplock
-                                * as exlusive.... The process *must* be dead.... 
-                                */
-                                       
-                               DEBUG(0,("open_mode_check: exlusive oplock left by "
-                                        "process %d after break ! For file %s, "
-                                        "dev = %x, inode = %.0f. Deleting it to "
-                                        "continue...\n",
-                                        (int)broken_entry->entry.pid, fname,
-                                        (unsigned int)dev, (double)inode));
-                                       
-                               if (process_exists(broken_entry->entry.pid)) {
-                                       DEBUG(0,("open_mode_check: Existent process "
-                                                "%lu left active oplock.\n",
-                                                (unsigned long)broken_entry->entry.pid ));
-                               }
-                                       
-                               if (del_share_entry(dev, inode, &broken_entry->entry,
-                                                   NULL, &delete_on_close) == -1) {
-                                       free_broken_entry_list(broken_entry_list);
-                                       errno = EACCES;
-                                       set_saved_error_triple(ERRDOS, ERRbadshare,
-                                                              NT_STATUS_SHARING_VIOLATION);
-                                       return -1;
-                               }
-                                       
-                               /*
-                                * We must reload the share modes after deleting the 
-                                * other process's entry.
-                                */
-                                       
-                               SAFE_FREE(old_shares);
-                               num_share_modes = get_share_modes(dev, inode,
-                                                                 &old_shares,
-                                                                 &delete_on_close);
-                               break;
-                       } /* end for paranoia... */
-               } /* end for broken_entry */
-               free_broken_entry_list(broken_entry_list);
-       } while(broke_oplock);
-       
-       /*
-        * Refuse to grant an oplock in case the contention limit is
-        * reached when going through the lock list multiple times.
-        */
-       
-       if(oplock_contention_count >= lp_oplock_contention_limit(SNUM(conn))) {
-               *p_oplock_request = 0;
-               DEBUG(4,("open_mode_check: oplock contention = %d. Not granting oplock.\n",
-                        oplock_contention_count ));
        }
        
-       SAFE_FREE(old_shares);
-       return num_share_modes;
+       return NT_STATUS_OK;
 }
 
-/****************************************************************************
- Delete the record for a handled deferred open entry.
-****************************************************************************/
+static BOOL is_delete_request(files_struct *fsp) {
+       return ((fsp->access_mask == DELETE_ACCESS) &&
+               (fsp->oplock_type == NO_OPLOCK));
+}
 
-static void delete_defered_open_entry_record(connection_struct *conn,
-                                               SMB_DEV_T dev,
-                                               SMB_INO_T inode)
+/*
+ * 1) No files open at all: Grant whatever the client wants.
+ *
+ * 2) Exclusive (or batch) oplock around: If the requested access is a delete
+ *    request, break if the oplock around is a batch oplock. If it's another
+ *    requested access type, break.
+ * 
+ * 3) Only level2 around: Grant level2 and do nothing else.
+ */
+
+static BOOL delay_for_oplocks(struct share_mode_lock *lck, files_struct *fsp)
 {
-       uint16 mid = get_current_mid();
-       pid_t mypid = sys_getpid();
-       deferred_open_entry *de_array = NULL;
-       int num_de_entries, i;
+       int i, num_level2;
+       struct share_mode_entry *exclusive = NULL;
+       BOOL delay_it = False;
+       BOOL have_level2 = False;
 
-       if (!lp_defer_sharing_violations()) {
-               return;
+       if (is_stat_open(fsp->access_mask)) {
+               fsp->oplock_type = NO_OPLOCK;
+               return False;
        }
 
-       num_de_entries = get_deferred_opens(conn, dev, inode, &de_array);
-       for (i = 0; i < num_de_entries; i++) {
-               deferred_open_entry *entry = &de_array[i];
-               if (entry->pid == mypid && entry->mid == mid && entry->dev == dev &&
-                               entry->inode == inode) {
+       num_level2 = 0;
 
-                       /* Remove the deferred open entry from the array. */
-                       delete_deferred_open_entry(entry);
-                       SAFE_FREE(de_array);
-                       return;
+       if (lck->num_share_modes == 0) {
+               /* No files open at all: Directly grant whatever the client
+                * wants. */
+
+               if (fsp->oplock_type == NO_OPLOCK) {
+                       /* Store a level2 oplock, but don't tell the client */
+                       fsp->oplock_type = FAKE_LEVEL_II_OPLOCK;
+               }
+               return False;
+       }
+
+       for (i=0; i<lck->num_share_modes; i++) {
+
+               if (!is_valid_share_mode_entry(&lck->share_modes[i])) {
+                       continue;
+               }
+
+               if (EXCLUSIVE_OPLOCK_TYPE(lck->share_modes[i].op_type)) {
+                       SMB_ASSERT(exclusive == NULL);                  
+                       exclusive = &lck->share_modes[i];
+               }
+
+               if (lck->share_modes[i].op_type == LEVEL_II_OPLOCK) {
+                       have_level2 = True;
                }
        }
-       SAFE_FREE(de_array);
+
+       if (exclusive != NULL) { /* Found an exclusive oplock */
+               SMB_ASSERT(!have_level2);
+               delay_it = is_delete_request(fsp) ?
+                       BATCH_OPLOCK_TYPE(exclusive->op_type) : True;
+       }
+
+       if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
+               /* We can at most grant level2 */
+               fsp->oplock_type = LEVEL_II_OPLOCK;
+       }
+
+       if ((fsp->oplock_type == NO_OPLOCK) && have_level2) {
+               /* Store a level2 oplock, but don't tell the client */
+               fsp->oplock_type = FAKE_LEVEL_II_OPLOCK;
+       }
+
+       if (delay_it) {
+               DEBUG(10, ("Sending break request to PID %s\n",
+                          procid_str_static(&exclusive->pid)));
+               exclusive->op_mid = get_current_mid();
+               if (!message_send_pid(exclusive->pid, MSG_SMB_BREAK_REQUEST,
+                                     exclusive, sizeof(*exclusive), True)) {
+                       DEBUG(3, ("Could not send oplock break message\n"));
+               }
+               file_free(fsp);
+       }
+
+       return delay_it;
+}
+
+static BOOL request_timed_out(struct timeval request_time,
+                             struct timeval timeout)
+{
+       struct timeval now, end_time;
+       GetTimeOfDay(&now);
+       end_time = timeval_sum(&request_time, &timeout);
+       return (timeval_compare(&end_time, &now) < 0);
 }
 
 /****************************************************************************
  Handle the 1 second delay in returning a SHARING_VIOLATION error.
 ****************************************************************************/
 
-static void defer_open_sharing_error(connection_struct *conn,
-                                    struct timeval *ptv,
-                                    const char *fname,
-                                    SMB_DEV_T dev,
-                                    SMB_INO_T inode)
+static void defer_open(struct share_mode_lock *lck,
+                      struct timeval request_time,
+                      struct timeval timeout,
+                      struct deferred_open_record *state)
 {
        uint16 mid = get_current_mid();
-       pid_t mypid = sys_getpid();
-       deferred_open_entry *de_array = NULL;
-       int num_de_entries, i;
-       struct dev_inode_bundle dib;
+       int i;
 
-       if (!lp_defer_sharing_violations()) {
-               return;
-       }
+       /* Paranoia check */
 
-       dib.dev = dev;
-       dib.inode = inode;
+       for (i=0; i<lck->num_share_modes; i++) {
+               struct share_mode_entry *e = &lck->share_modes[i];
 
-       num_de_entries = get_deferred_opens(conn, dev, inode, &de_array);
-       for (i = 0; i < num_de_entries; i++) {
-               deferred_open_entry *entry = &de_array[i];
-               if (entry->pid == mypid && entry->mid == mid) {
-                       /*
-                        * Check if a 1 second timeout has expired.
-                        */
-                       if (usec_time_diff(ptv, &entry->time) >
-                           SHARING_VIOLATION_USEC_WAIT) {
-                               DEBUG(10,("defer_open_sharing_error: Deleting "
-                                         "deferred open entry for mid %u, "
-                                         "file %s\n",
-                                         (unsigned int)mid, fname ));
-
-                               /* Expired, return a real error. */
-                               /* Remove the deferred open entry from the array. */
-
-                               delete_deferred_open_entry(entry);
-                               SAFE_FREE(de_array);
-                               return;
-                       }
-                       /*
-                        * If the timeout hasn't expired yet and we still have
-                        * a sharing violation, just leave the entry in the
-                        * deferred open array alone. We do need to reschedule
-                        * this open call though (with the original created
-                        * time).
-                        */
-                       DEBUG(10,("defer_open_sharing_error: time [%u.%06u] "
-                                 "updating deferred open entry for mid %u, file %s\n",
-                                 (unsigned int)entry->time.tv_sec,
-                                 (unsigned int)entry->time.tv_usec,
-                                 (unsigned int)mid, fname ));
-
-                       push_sharing_violation_open_smb_message(&entry->time,
-                                                               (char *)&dib,
-                                                               sizeof(dib));
-                       SAFE_FREE(de_array);
-                       return;
+               if (!is_deferred_open_entry(e)) {
+                       continue;
+               }
+
+               if (procid_is_me(&e->pid) && (e->op_mid == mid)) {
+                       DEBUG(0, ("Trying to defer an already deferred "
+                                 "request: mid=%d, exiting\n", mid));
+                       exit_server("exiting");
                }
        }
 
+       /* End paranoia check */
+
        DEBUG(10,("defer_open_sharing_error: time [%u.%06u] adding deferred "
-                 "open entry for mid %u, file %s\n",
-                 (unsigned int)ptv->tv_sec, (unsigned int)ptv->tv_usec,
-                 (unsigned int)mid, fname ));
+                 "open entry for mid %u\n",
+                 (unsigned int)request_time.tv_sec,
+                 (unsigned int)request_time.tv_usec,
+                 (unsigned int)mid));
 
-       if (!push_sharing_violation_open_smb_message(ptv, (char *)&dib, sizeof(dib))) {
-               SAFE_FREE(de_array);
-               return;
-       }
-       if (!add_deferred_open(mid, ptv, dev, inode, global_oplock_port, fname)) {
-               remove_sharing_violation_open_smb_message(mid);
+       if (!push_deferred_smb_message(mid, request_time, timeout,
+                                      (char *)state, sizeof(*state))) {
+               exit_server("push_deferred_smb_message failed\n");
        }
+       add_deferred_open(lck, mid, request_time, state->dev, state->inode);
 
        /*
         * Push the MID of this packet on the signing queue.
@@ -888,8 +756,6 @@ static void defer_open_sharing_error(connection_struct *conn,
         */
 
        srv_defer_sign_response(mid);
-
-       SAFE_FREE(de_array);
 }
 
 /****************************************************************************
@@ -1196,8 +1062,6 @@ files_struct *open_file_ntcreate(connection_struct *conn,
        BOOL internal_only_open = False;
        SMB_DEV_T dev = 0;
        SMB_INO_T inode = 0;
-       int num_share_modes = 0;
-       BOOL all_current_opens_are_level_II = False;
        BOOL fsp_open = False;
        files_struct *fsp = NULL;
        mode_t new_unx_mode = (mode_t)0;
@@ -1205,8 +1069,11 @@ files_struct *open_file_ntcreate(connection_struct *conn,
        int info;
        uint32 existing_dos_attributes = 0;
        struct pending_message_list *pml = NULL;
-       uint16 port = 0;
        uint16 mid = get_current_mid();
+       BOOL delayed_for_oplocks = False;
+       struct timeval request_time = timeval_zero();
+       struct share_mode_lock *lck = NULL;
+       NTSTATUS status;
 
        if (conn->printer) {
                /* 
@@ -1241,9 +1108,11 @@ files_struct *open_file_ntcreate(connection_struct *conn,
        }
 
        if ((pml = get_open_deferred_message(mid)) != NULL) {
-               struct dev_inode_bundle dib;
+               struct deferred_open_record *state =
+                       (struct deferred_open_record *)pml->private_data.data;
 
-               memcpy(&dib, pml->private_data.data, sizeof(dib));
+               request_time = pml->request_time;
+               delayed_for_oplocks = state->delayed_for_oplocks;
 
                /* There could be a race condition where the dev/inode pair
                   has changed since we deferred the message. If so, just
@@ -1255,24 +1124,18 @@ files_struct *open_file_ntcreate(connection_struct *conn,
                   notified of a close and we don't want to trigger another
                   spurious oplock break. */
 
-               if (!file_existed || dib.dev != psbuf->st_dev ||
-                   dib.inode != psbuf->st_ino || pml->msg_time.tv_sec ||
-                   pml->msg_time.tv_usec) {
-                       /* Ensure we don't reprocess this message. */
-                       remove_sharing_violation_open_smb_message(mid);
-
-                       /* Now remove the deferred open entry under lock. */
-                       lock_share_entry(conn, dib.dev, dib.inode);
-                       delete_defered_open_entry_record(conn, dib.dev,
-                                                        dib.inode);
-                       unlock_share_entry(conn, dib.dev, dib.inode);
-
-                       set_saved_error_triple(ERRDOS, ERRbadshare,
-                                              NT_STATUS_SHARING_VIOLATION);
-                       return NULL;
+               /* Now remove the deferred open entry under lock. */
+               lck = get_share_mode_lock(NULL, state->dev, state->inode,
+                                         fname);
+               if (lck == NULL) {
+                       DEBUG(0, ("could not get share mode lock\n"));
+               } else {
+                       del_deferred_open_entry(lck, mid);
+                       talloc_destroy(lck);
                }
+
                /* Ensure we don't reprocess this message. */
-               remove_sharing_violation_open_smb_message(mid);
+               remove_deferred_open_smb_message(mid);
        }
 
        if (!check_name(fname,conn)) {
@@ -1285,7 +1148,8 @@ files_struct *open_file_ntcreate(connection_struct *conn,
        }
 
        /* ignore any oplock requests if oplocks are disabled */
-       if (!lp_oplocks(SNUM(conn)) || global_client_failed_oplock_break) {
+       if (!lp_oplocks(SNUM(conn)) || global_client_failed_oplock_break ||
+           IS_VETO_OPLOCK_PATH(conn, fname)) {
                oplock_request = 0;
        }
 
@@ -1325,7 +1189,7 @@ files_struct *open_file_ntcreate(connection_struct *conn,
                                DEBUG(5,("open_file_ntcreate: FILE_OPEN "
                                         "requested for file %s and file "
                                         "doesn't exist.\n", fname ));
-                               set_saved_error_triple(ERRDOS, ERRbadfile, NT_STATUS_OBJECT_NAME_NOT_FOUND);
+                               set_saved_ntstatus(NT_STATUS_OBJECT_NAME_NOT_FOUND);
                                errno = ENOENT;
                                return NULL;
                        }
@@ -1338,7 +1202,7 @@ files_struct *open_file_ntcreate(connection_struct *conn,
                                DEBUG(5,("open_file_ntcreate: FILE_OVERWRITE "
                                         "requested for file %s and file "
                                         "doesn't exist.\n", fname ));
-                               set_saved_error_triple(ERRDOS, ERRbadfile, NT_STATUS_OBJECT_NAME_NOT_FOUND);
+                               set_saved_ntstatus(NT_STATUS_OBJECT_NAME_NOT_FOUND);
                                errno = ENOENT;
                                return NULL;
                        }
@@ -1369,8 +1233,7 @@ files_struct *open_file_ntcreate(connection_struct *conn,
                        break;
 
                default:
-                       set_saved_error_triple(ERRDOS, ERRinvalidparam,
-                                              NT_STATUS_INVALID_PARAMETER);
+                       set_saved_ntstatus(NT_STATUS_INVALID_PARAMETER);
                        return NULL;
        }
 
@@ -1447,8 +1310,7 @@ files_struct *open_file_ntcreate(connection_struct *conn,
                DEBUG(5,("open_file_ntcreate: write access requested for "
                         "file %s on read only %s\n",
                         fname, !CAN_WRITE(conn) ? "share" : "file" ));
-               set_saved_error_triple(ERRDOS, ERRnoaccess,
-                                      NT_STATUS_ACCESS_DENIED);
+               set_saved_ntstatus(NT_STATUS_ACCESS_DENIED);
                errno = EACCES;
                return NULL;
        }
@@ -1458,45 +1320,96 @@ files_struct *open_file_ntcreate(connection_struct *conn,
                return NULL;
        }
 
+       fsp->dev = psbuf->st_dev;
+       fsp->inode = psbuf->st_ino;
+       fsp->share_access = share_access;
+       fsp->fh->private_options = create_options;
+       fsp->access_mask = access_mask;
+       fsp->oplock_type = oplock_request;
+
+       if (timeval_is_zero(&request_time)) {
+               request_time = fsp->open_time;
+       }
+
        if (file_existed) {
 
                dev = psbuf->st_dev;
                inode = psbuf->st_ino;
 
-               lock_share_entry(conn, dev, inode);
-
-               num_share_modes = open_mode_check(conn, fname, dev, inode,
-                                                 access_mask, share_access,
-                                                 create_options,
-                                                 &oplock_request,
-                                                 &all_current_opens_are_level_II);
-               if(num_share_modes == -1) {
-
-                       if (!internal_only_open) {
-                               NTSTATUS status;
-                               get_saved_error_triple(NULL, NULL, &status);
-                               if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION)) {
-                                       /* Check if this can be done with the
-                                        * deny_dos and fcb calls. */
-                                       if (create_options &
-                                           (NTCREATEX_OPTIONS_PRIVATE_DENY_DOS|
-                                            NTCREATEX_OPTIONS_PRIVATE_DENY_FCB)) {
-                                               files_struct *fsp_dup;
-                                               fsp_dup = fcb_or_dos_open(conn, fname, dev,
-                                                                         inode, access_mask,
-                                                                         share_access,
-                                                                         create_options);
-
-                                               if (fsp_dup) {
-                                                       unlock_share_entry(conn, dev, inode);
-                                                       file_free(fsp);
-                                                       if (pinfo) {
-                                                               *pinfo = FILE_WAS_OPENED;
-                                                       }
-                                                       conn->num_files_open++;
-                                                       return fsp_dup;
-                                               }
+               lck = get_share_mode_lock(NULL, dev, inode, fname);
+
+               if (lck == NULL) {
+                       DEBUG(0, ("Could not get share mode lock\n"));
+                       set_saved_ntstatus(NT_STATUS_SHARING_VIOLATION);
+                       return NULL;
+               }
+
+               if (delay_for_oplocks(lck, fsp)) {
+                       struct deferred_open_record state;
+                       struct timeval timeout;
+
+                       if (delayed_for_oplocks) {
+                               DEBUG(0, ("Trying to delay for oplocks "
+                                         "twice\n"));
+                               exit_server("exiting");
+                       }
+
+                       timeout = timeval_set(OPLOCK_BREAK_TIMEOUT*2, 0);
+
+                       /* Normally the smbd we asked should respond within
+                        * OPLOCK_BREAK_TIMEOUT seconds regardless of whether
+                        * the client did, give twice the timeout as a safety
+                        * measure here in case the other smbd is stuck
+                        * somewhere else. */
+
+                       state.delayed_for_oplocks = True;
+                       state.dev = dev;
+                       state.inode = inode;
+
+                       if (!request_timed_out(request_time, timeout)) {
+                               defer_open(lck, request_time, timeout,
+                                          &state);
+                       }
+
+                       talloc_free(lck);
+                       return NULL;
+               }
+
+               status = open_mode_check(conn, fname, lck,
+                                        access_mask, share_access,
+                                        create_options, &file_existed);
+
+               if (NT_STATUS_EQUAL(status, NT_STATUS_DELETE_PENDING)) {
+                       /* DELETE_PENDING is not deferred for a second */
+                       set_saved_ntstatus(status);
+                       talloc_free(lck);
+                       file_free(fsp);
+                       return NULL;
+               }
+
+               if (!NT_STATUS_IS_OK(status)) {
+
+                       SMB_ASSERT(NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION));
+
+                       /* Check if this can be done with the deny_dos and fcb
+                        * calls. */
+                       if (create_options &
+                           (NTCREATEX_OPTIONS_PRIVATE_DENY_DOS|
+                            NTCREATEX_OPTIONS_PRIVATE_DENY_FCB)) {
+                               files_struct *fsp_dup;
+                               fsp_dup = fcb_or_dos_open(conn, fname, dev,
+                                                         inode, access_mask,
+                                                         share_access,
+                                                         create_options);
+
+                               if (fsp_dup) {
+                                       talloc_free(lck);
+                                       file_free(fsp);
+                                       if (pinfo) {
+                                               *pinfo = FILE_WAS_OPENED;
                                        }
+                                       conn->num_files_open++;
+                                       return fsp_dup;
                                }
                        }
 
@@ -1527,8 +1440,7 @@ files_struct *open_file_ntcreate(connection_struct *conn,
 
                        if (!fsp_open && errno) {
                                /* Default error. */
-                               set_saved_error_triple(ERRDOS, ERRnoaccess,
-                                                      NT_STATUS_ACCESS_DENIED);
+                               set_saved_ntstatus(NT_STATUS_ACCESS_DENIED);
                        }
 
                        /* 
@@ -1536,27 +1448,32 @@ files_struct *open_file_ntcreate(connection_struct *conn,
                         * cope with the braindead 1 second delay.
                         */
 
-                       if (!internal_only_open) {
-                               NTSTATUS status;
-                               get_saved_error_triple(NULL, NULL, &status);
-                               if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION)) {
-                                       /* The fsp->open_time here represents
-                                        * the current time of day. */
-                                       defer_open_sharing_error(conn,
-                                                                &fsp->open_time,
-                                                                fname, dev, inode);
+                       if (!internal_only_open &&
+                           lp_defer_sharing_violations()) {
+                               struct timeval timeout;
+                               struct deferred_open_record state;
+
+                               timeout = timeval_set(0, SHARING_VIOLATION_USEC_WAIT);
+
+                               state.delayed_for_oplocks = False;
+                               state.dev = dev;
+                               state.inode = inode;
+
+                               if (!request_timed_out(request_time,
+                                                      timeout)) {
+                                       defer_open(lck, request_time, timeout,
+                                                  &state);
                                }
                        }
 
-                       unlock_share_entry(conn, dev, inode);
+                       talloc_free(lck);
                        if (fsp_open) {
                                fd_close(conn, fsp);
                                /*
                                 * We have detected a sharing violation here
                                 * so return the correct error code
                                 */
-                               set_saved_error_triple(ERRDOS, ERRbadshare,
-                                                      NT_STATUS_SHARING_VIOLATION);
+                               set_saved_ntstatus(NT_STATUS_SHARING_VIOLATION);
                        }
                        file_free(fsp);
                        return NULL;
@@ -1567,23 +1484,28 @@ files_struct *open_file_ntcreate(connection_struct *conn,
                 */
        }
 
+       SMB_ASSERT(!file_existed || (lck != NULL));
+
        /*
         * Ensure we pay attention to default ACLs on directories if required.
         */
 
         if ((flags2 & O_CREAT) && lp_inherit_acls(SNUM(conn)) &&
-                       (def_acl = directory_has_default_acl(conn, parent_dirname(fname)))) {
+           (def_acl = directory_has_default_acl(conn,
+                                                parent_dirname(fname)))) {
                unx_mode = 0777;
        }
 
        DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n",
-                       (unsigned int)flags,(unsigned int)flags2,(unsigned int)unx_mode));
+                (unsigned int)flags, (unsigned int)flags2,
+                (unsigned int)unx_mode));
 
        /*
         * open_file strips any O_TRUNC flags itself.
         */
 
-       fsp_open = open_file(fsp,conn,fname,psbuf,flags|flags2,unx_mode,access_mask);
+       fsp_open = open_file(fsp,conn,fname,psbuf,flags|flags2,unx_mode,
+                            access_mask);
 
        if (!fsp_open && (flags2 & O_EXCL) && (errno == EEXIST)) {
                /*
@@ -1602,22 +1524,23 @@ files_struct *open_file_ntcreate(connection_struct *conn,
        }
 
        if (!fsp_open) {
-               if(file_existed) {
-                       unlock_share_entry(conn, dev, inode);
+               if (lck != NULL) {
+                       talloc_free(lck);
                }
                file_free(fsp);
                return NULL;
        }
 
-       /*
-        * Deal with the race condition where two smbd's detect the file
-        * doesn't exist and do the create at the same time. One of them will
-        * win and set a share mode, the other (ie. this one) should check if
-        * the requested share mode for this create is allowed.
-        */
-
        if (!file_existed) { 
 
+               /*
+                * Deal with the race condition where two smbd's detect the
+                * file doesn't exist and do the create at the same time. One
+                * of them will win and set a share mode, the other (ie. this
+                * one) should check if the requested share mode for this
+                * create is allowed.
+                */
+
                /*
                 * Now the file exists and fsp is successfully opened,
                 * fsp->dev and fsp->inode are valid and should replace the
@@ -1628,70 +1551,41 @@ files_struct *open_file_ntcreate(connection_struct *conn,
                dev = fsp->dev;
                inode = fsp->inode;
 
-               lock_share_entry_fsp(fsp);
-
-               num_share_modes = open_mode_check(conn, fname, dev, inode,
-                                                 access_mask, share_access,
-                                                 create_options,
-                                                 &oplock_request,
-                                                 &all_current_opens_are_level_II);
-
-               if(num_share_modes == -1) {
-                       NTSTATUS status;
-                       get_saved_error_triple(NULL, NULL, &status);
-                       if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION)) {
-                               /* Check if this can be done with the deny_dos
-                                * and fcb calls. */
-                               if (create_options &
-                                   (NTCREATEX_OPTIONS_PRIVATE_DENY_DOS|
-                                    NTCREATEX_OPTIONS_PRIVATE_DENY_FCB)) {
-                                       files_struct *fsp_dup;
-                                       fsp_dup = fcb_or_dos_open(conn, fname, dev, inode,
-                                                                 access_mask, share_access,
-                                                                 create_options);
-                                       if (fsp_dup) {
-                                               unlock_share_entry(conn, dev, inode);
-                                               fd_close(conn, fsp);
-                                               file_free(fsp);
-                                               if (pinfo) {
-                                                       *pinfo = FILE_WAS_OPENED;
-                                               }
-                                               conn->num_files_open++;
-                                               return fsp_dup;
-                                       }
-                               }
-
-                               /* 
-                                * If we're returning a share violation,
-                                * ensure we cope with the braindead 1 second
-                                * delay.
-                                */
-
-                               /* The fsp->open_time here represents the
-                                * current time of day. */
-                               defer_open_sharing_error(conn, &fsp->open_time,
-                                                        fname, dev, inode);
-                       }
+               lck = get_share_mode_lock(NULL, dev, inode, fname);
 
-                       unlock_share_entry_fsp(fsp);
-                       fd_close(conn,fsp);
+               if (lck == NULL) {
+                       DEBUG(0, ("Coult not get share mode lock\n"));
+                       fd_close(conn, fsp);
                        file_free(fsp);
-                       /*
-                        * We have detected a sharing violation here, so
-                        * return the correct code.
-                        */
-                       set_saved_error_triple(ERRDOS, ERRbadshare,
-                                              NT_STATUS_SHARING_VIOLATION);
+                       set_saved_ntstatus(NT_STATUS_SHARING_VIOLATION);
                        return NULL;
                }
 
-               /*
-                * If there are any share modes set then the file *did*
-                * exist. Ensure we return the correct value for action.
-                */
+               status = open_mode_check(conn, fname, lck,
+                                        access_mask, share_access,
+                                        create_options, &file_existed);
+
+               if (!NT_STATUS_IS_OK(status)) {
+                       struct deferred_open_record state;
 
-               if (num_share_modes > 0) {
-                       file_existed = True;
+                       fd_close(conn, fsp);
+                       file_free(fsp);
+
+                       state.delayed_for_oplocks = False;
+                       state.dev = dev;
+                       state.inode = inode;
+
+                       /* Do it all over again immediately. In the second
+                        * round we will find that the file existed and handle
+                        * the DELETE_PENDING and FCB cases correctly. No need
+                        * to duplicate the code here. Essentially this is a
+                        * "goto top of this function", but don't tell
+                        * anybody... */
+
+                       defer_open(lck, request_time, timeval_zero(),
+                                  &state);
+                       talloc_free(lck);
+                       return NULL;
                }
 
                /*
@@ -1699,6 +1593,8 @@ files_struct *open_file_ntcreate(connection_struct *conn,
                 */
        }
 
+       SMB_ASSERT(lck != NULL);
+
        /* note that we ignore failure for the following. It is
            basically a hack for NFS, and NFS will never set one of
            these only read them. Nobody but Samba can ever set a deny
@@ -1725,7 +1621,7 @@ files_struct *open_file_ntcreate(connection_struct *conn,
                 */
                if ((SMB_VFS_FTRUNCATE(fsp,fsp->fh->fd,0) == -1) ||
                    (SMB_VFS_FSTAT(fsp,fsp->fh->fd,psbuf)==-1)) {
-                       unlock_share_entry_fsp(fsp);
+                       talloc_free(lck);
                        fd_close(conn,fsp);
                        file_free(fsp);
                        return NULL;
@@ -1761,20 +1657,14 @@ files_struct *open_file_ntcreate(connection_struct *conn,
         * file structs.
         */
 
-       if(oplock_request && (num_share_modes == 0) && 
-          !IS_VETO_OPLOCK_PATH(conn,fname) &&
-          set_file_oplock(fsp, oplock_request) ) {
-               port = global_oplock_port;
-       } else if (oplock_request && all_current_opens_are_level_II) {
-               port = global_oplock_port;
-               oplock_request = LEVEL_II_OPLOCK;
-               set_file_oplock(fsp, oplock_request);
-       } else {
-               port = 0;
-               oplock_request = 0;
+       if ((fsp->oplock_type != NO_OPLOCK) &&
+           (fsp->oplock_type != FAKE_LEVEL_II_OPLOCK)) {
+               if (!set_file_oplock(fsp, fsp->oplock_type)) {
+                       /* Could not get the kernel oplock */
+                       fsp->oplock_type = NO_OPLOCK;
+               }
        }
-
-       set_share_mode(fsp, port, oplock_request);
+       set_share_mode(lck, fsp, 0, fsp->oplock_type);
 
        if (create_options & FILE_DELETE_ON_CLOSE) {
                uint32 dosattr= existing_dos_attributes;
@@ -1788,19 +1678,16 @@ files_struct *open_file_ntcreate(connection_struct *conn,
                result = can_set_delete_on_close(fsp, True, dosattr);
 
                if (!NT_STATUS_IS_OK(result)) {
-                       uint8 u_e_c;
-                       uint32 u_e_code;
-                       BOOL dummy_del_on_close;
                        /* Remember to delete the mode we just added. */
-                       del_share_mode(fsp, NULL, &dummy_del_on_close);
-                       unlock_share_entry_fsp(fsp);
+                       del_share_mode(lck, fsp);
+                       talloc_free(lck);
                        fd_close(conn,fsp);
                        file_free(fsp);
-                       ntstatus_to_dos(result, &u_e_c, &u_e_code);
-                       set_saved_error_triple(u_e_c, u_e_code, result);
+                       set_saved_ntstatus(result);
                        return NULL;
                }
-               set_delete_on_close(fsp, True);
+               lck->delete_on_close = True;
+               lck->modified = True;
        }
        
        if (info == FILE_WAS_OVERWRITTEN || info == FILE_WAS_CREATED ||
@@ -1860,8 +1747,8 @@ files_struct *open_file_ntcreate(connection_struct *conn,
 
        /* If this is a successful open, we must remove any deferred open
         * records. */
-       delete_defered_open_entry_record(conn, fsp->dev, fsp->inode);
-       unlock_share_entry_fsp(fsp);
+       del_deferred_open_entry(lck, mid);
+       talloc_free(lck);
 
        conn->num_files_open++;
 
@@ -1945,17 +1832,13 @@ files_struct *open_directory(connection_struct *conn,
 
        if (is_ntfs_stream_name(fname)) {
                DEBUG(0,("open_directory: %s is a stream name!\n", fname ));
-               /* NB. Is the DOS error ERRbadpath or ERRbaddirectory ? */
-               set_saved_error_triple(ERRDOS, ERRbadpath,
-                                      NT_STATUS_NOT_A_DIRECTORY);
+               set_saved_ntstatus(NT_STATUS_NOT_A_DIRECTORY);
                return NULL;
        }
 
        if (dir_existed && !S_ISDIR(psbuf->st_mode)) {
                DEBUG(0,("open_directory: %s is not a directory !\n", fname ));
-               /* NB. Is the DOS error ERRbadpath or ERRbaddirectory ? */
-               set_saved_error_triple(ERRDOS, ERRbadpath,
-                                      NT_STATUS_NOT_A_DIRECTORY);
+               set_saved_ntstatus(NT_STATUS_NOT_A_DIRECTORY);
                return NULL;
        }
 
@@ -1967,8 +1850,7 @@ files_struct *open_directory(connection_struct *conn,
                                DEBUG(5,("open_directory: FILE_OPEN requested "
                                         "for directory %s and it doesn't "
                                         "exist.\n", fname ));
-                               set_saved_error_triple(ERRDOS, ERRbadfile,
-                                                      NT_STATUS_OBJECT_NAME_NOT_FOUND);
+                               set_saved_ntstatus(NT_STATUS_OBJECT_NAME_NOT_FOUND);
                                return NULL;
                        }
                        info = FILE_WAS_OPENED;
@@ -2008,8 +1890,7 @@ files_struct *open_directory(connection_struct *conn,
                                 "0x%x for directory %s\n",
                                 (unsigned int)create_disposition, fname));
                        file_free(fsp);
-                       set_saved_error_triple(ERRDOS, ERRinvalidparam,
-                                              NT_STATUS_INVALID_PARAMETER);
+                       set_saved_ntstatus(NT_STATUS_INVALID_PARAMETER);
                        return NULL;
        }
 
index c0c9e989a9970abe5938e7c5bdc482adc7ec8077..385f998b1ce31ac46a8cc19c056c984175b0b3c8 100644 (file)
@@ -3,6 +3,7 @@
    oplock processing
    Copyright (C) Andrew Tridgell 1992-1998
    Copyright (C) Jeremy Allison 1998 - 2001
+   Copyright (C) Volker Lendecke 2005
    
    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
 
 #include "includes.h"
 
-/* Oplock ipc UDP socket. */
-static int oplock_sock = -1;
-uint16 global_oplock_port = 0;
-
 /* Current number of oplocks we have outstanding. */
 static int32 exclusive_oplocks_open = 0;
 static int32 level_II_oplocks_open = 0;
 BOOL global_client_failed_oplock_break = False;
-BOOL global_oplock_break = False;
 
 extern struct timeval smb_last_time;
 extern uint32 global_client_caps;
-extern struct current_user current_user;
 extern int smb_read_error;
 
 static struct kernel_oplocks *koplocks;
 
-static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_id, BOOL local);
-
 /****************************************************************************
  Get the number of current exclusive oplocks.
 ****************************************************************************/
@@ -58,9 +51,6 @@ BOOL oplock_message_waiting(fd_set *fds)
        if (koplocks && koplocks->msg_waiting(fds))
                return True;
 
-       if (FD_ISSET(oplock_sock, fds))
-               return True;
-
        return False;
 }
 
@@ -75,13 +65,9 @@ BOOL oplock_message_waiting(fd_set *fds)
 
 ****************************************************************************/
 
-BOOL receive_local_message( char *buffer, int buffer_len, int timeout)
+void process_kernel_oplocks(void)
 {
-       struct sockaddr_in from;
-       socklen_t fromlen = sizeof(from);
-       int32 msg_len = 0;
        fd_set fds;
-       int selrtn = -1;
 
        FD_ZERO(&fds);
        smb_read_error = 0;
@@ -92,110 +78,29 @@ BOOL receive_local_message( char *buffer, int buffer_len, int timeout)
         * already been eaten. JRA.
         */
 
-       if (koplocks && koplocks->msg_waiting(&fds)) {
-               return koplocks->receive_message(&fds, buffer, buffer_len);
+       if (!koplocks) {
+               return;
        }
 
-       while (timeout > 0 && selrtn == -1) {
-               struct timeval to;
-               int maxfd = oplock_sock;
-               time_t starttime = time(NULL);
-
-               FD_ZERO(&fds);
-               maxfd = setup_oplock_select_set(&fds);
+       while (koplocks->msg_waiting(&fds)) { 
+               files_struct *fsp;
+               struct kernel_oplock_message msg;
 
-               to.tv_sec = timeout / 1000;
-               to.tv_usec = (timeout % 1000) * 1000;
-
-               DEBUG(5,("receive_local_message: doing select with timeout of %d ms\n", timeout));
-
-               selrtn = sys_select(maxfd+1,&fds,NULL,NULL,&to);
-
-               if (selrtn == -1 && errno == EINTR) {
-
-                       /* could be a kernel oplock interrupt */
-                       if (koplocks && koplocks->msg_waiting(&fds)) {
-                               return koplocks->receive_message(&fds, buffer, buffer_len);
-                       }
+               fsp = koplocks->receive_message(&fds);
 
-                       /*
-                        * Linux 2.0.x seems to have a bug in that
-                        * it can return -1, EINTR with a timeout of zero.
-                        * Make sure we bail out here with a read timeout
-                        * if we got EINTR on a timeout of 1 or less.
-                        */
-
-                       if (timeout <= 1) {
-                               smb_read_error = READ_TIMEOUT;
-                               return False;
-                       }
-
-                       /* Not a kernel interrupt - could be a SIGUSR1 message. We must restart. */
-                       /* We need to decrement the timeout here. */
-                       timeout -= ((time(NULL) - starttime)*1000);
-                       if (timeout < 0)
-                               timeout = 1;
-
-                       DEBUG(5,("receive_local_message: EINTR : new timeout %d ms\n", timeout));
-                       continue;
+               if (fsp == NULL) {
+                       DEBUG(3, ("Kernel oplock message announced, but none "
+                                 "received\n"));
+                       return;
                }
 
-               /* 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 (koplocks && koplocks->msg_waiting(&fds)) {
-               return koplocks->receive_message(&fds, buffer, buffer_len);
+               msg.dev = fsp->dev;
+               msg.inode = fsp->inode;
+               msg.file_id = fsp->file_id;
+               message_send_pid(pid_to_procid(sys_getpid()),
+                                MSG_SMB_KERNEL_BREAK,
+                                &msg, sizeof(msg), True);
        }
-
-       if (!FD_ISSET(oplock_sock, &fds))
-               return False;
-
-       /*
-        * From here down we deal with the smbd <--> smbd
-        * oplock break protocol only.
-        */
-
-       /*
-        * Read a loopback udp message.
-        */
-       msg_len = sys_recvfrom(oplock_sock, &buffer[OPBRK_CMD_HEADER_LEN],
-                                               buffer_len - OPBRK_CMD_HEADER_LEN, 0, (struct sockaddr *)&from, &fromlen);
-
-       if(msg_len < 0) {
-               DEBUG(0,("receive_local_message. Error in recvfrom. (%s).\n",strerror(errno)));
-               return False;
-       }
-
-       /* Validate message length. */
-       if(msg_len > (buffer_len - OPBRK_CMD_HEADER_LEN)) {
-               DEBUG(0,("receive_local_message: invalid msg_len (%d) max can be %d\n", msg_len,
-                       buffer_len  - OPBRK_CMD_HEADER_LEN));
-               return False;
-       }
-
-       /* Validate message from address (must be localhost). */
-       if(from.sin_addr.s_addr != htonl(INADDR_LOOPBACK)) {
-               DEBUG(0,("receive_local_message: invalid 'from' address \
-(was %lx should be 127.0.0.1)\n", (long)from.sin_addr.s_addr));
-               return False;
-       }
-
-       /* Setup the message header */
-       SIVAL(buffer,OPBRK_CMD_LEN_OFFSET,msg_len);
-       SSVAL(buffer,OPBRK_CMD_PORT_OFFSET,ntohs(from.sin_port));
-
-       return True;
 }
 
 /****************************************************************************
@@ -229,13 +134,19 @@ tv_sec = %x, tv_usec = %x\n",
 
 void release_file_oplock(files_struct *fsp)
 {
-       if ((fsp->oplock_type != NO_OPLOCK) && koplocks)
+       if ((fsp->oplock_type != NO_OPLOCK) &&
+           (fsp->oplock_type != FAKE_LEVEL_II_OPLOCK) &&
+           koplocks) {
                koplocks->release_oplock(fsp);
+       }
 
        if (fsp->oplock_type == LEVEL_II_OPLOCK)
                level_II_oplocks_open--;
-       else if (fsp->oplock_type)
+       else if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
                exclusive_oplocks_open--;
+
+       SMB_ASSERT(exclusive_oplocks_open>=0);
+       SMB_ASSERT(level_II_oplocks_open>=0);
        
        fsp->oplock_type = NO_OPLOCK;
        fsp->sent_oplock_break = NO_BREAK_SENT;
@@ -263,45 +174,58 @@ static void downgrade_file_oplock(files_struct *fsp)
  to none even if a "break-to-level II" was sent.
 ****************************************************************************/
 
-BOOL remove_oplock(files_struct *fsp, BOOL break_to_none)
+BOOL remove_oplock(files_struct *fsp)
 {
        SMB_DEV_T dev = fsp->dev;
        SMB_INO_T inode = fsp->inode;
-       BOOL ret = True;
+       BOOL ret;
+       struct share_mode_lock *lck;
 
        /* Remove the oplock flag from the sharemode. */
-       if (lock_share_entry_fsp(fsp) == False) {
-               DEBUG(0,("remove_oplock: failed to lock share entry for file %s\n",
-                        fsp->fsp_name ));
+       lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL);
+       if (lck == NULL) {
+               DEBUG(0,("remove_oplock: failed to lock share entry for "
+                        "file %s\n", fsp->fsp_name ));
                return False;
        }
+       ret = remove_share_oplock(lck, fsp);
+       if (!ret) {
+               DEBUG(0,("remove_oplock: failed to remove share oplock for "
+                        "file %s fnum %d, dev = %x, inode = %.0f\n",
+                        fsp->fsp_name, fsp->fnum, (unsigned int)dev,
+                        (double)inode));
+       }
+       release_file_oplock(fsp);
+       talloc_free(lck);
+       return ret;
+}
 
-       if (fsp->sent_oplock_break == BREAK_TO_NONE_SENT || break_to_none) {
-               /*
-                * Deal with a reply when a break-to-none was sent.
-                */
-
-               if(remove_share_oplock(fsp)==False) {
-                       DEBUG(0,("remove_oplock: failed to remove share oplock for file %s fnum %d, \
-dev = %x, inode = %.0f\n", fsp->fsp_name, fsp->fnum, (unsigned int)dev, (double)inode));
-                       ret = False;
-               }
+/*
+ * Deal with a reply when a break-to-level II was sent.
+ */
+BOOL downgrade_oplock(files_struct *fsp)
+{
+       SMB_DEV_T dev = fsp->dev;
+       SMB_INO_T inode = fsp->inode;
+       BOOL ret;
+       struct share_mode_lock *lck;
 
-               release_file_oplock(fsp);
-       } else {
-               /*
-                * Deal with a reply when a break-to-level II was sent.
-                */
-               if(downgrade_share_oplock(fsp)==False) {
-                       DEBUG(0,("remove_oplock: failed to downgrade share oplock for file %s fnum %d, \
-dev = %x, inode = %.0f\n", fsp->fsp_name, fsp->fnum, (unsigned int)dev, (double)inode));
-                       ret = False;
-               }
-               
-               downgrade_file_oplock(fsp);
+       lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL);
+       if (lck == NULL) {
+               DEBUG(0,("downgrade_oplock: failed to lock share entry for "
+                        "file %s\n", fsp->fsp_name ));
+               return False;
        }
-
-       unlock_share_entry_fsp(fsp);
+       ret = downgrade_share_oplock(lck, fsp);
+       if (!ret) {
+               DEBUG(0,("downgrade_oplock: failed to downgrade share oplock "
+                        "for file %s fnum %d, dev = %x, inode = %.0f\n",
+                        fsp->fsp_name, fsp->fnum, (unsigned int)dev,
+                        (double)inode));
+       }
+               
+       downgrade_file_oplock(fsp);
+       talloc_free(lck);
        return ret;
 }
 
@@ -313,12 +237,7 @@ dev = %x, inode = %.0f\n", fsp->fsp_name, fsp->fnum, (unsigned int)dev, (double)
 
 int setup_oplock_select_set( fd_set *fds)
 {
-       int maxfd = oplock_sock;
-
-       if(oplock_sock == -1)
-               return 0;
-
-       FD_SET(oplock_sock,fds);
+       int maxfd = 0;
 
        if (koplocks && koplocks->notification_fd != -1) {
                FD_SET(koplocks->notification_fd, fds);
@@ -329,197 +248,31 @@ int setup_oplock_select_set( fd_set *fds)
 }
 
 /****************************************************************************
- Process an oplock break message - whether it came from the UDP socket
- or from the kernel.
+ Set up an oplock break message.
 ****************************************************************************/
 
-BOOL process_local_message(char *buffer, int buf_size)
+static char *new_break_smb_message(TALLOC_CTX *mem_ctx,
+                                  files_struct *fsp, uint8_t cmd)
 {
-       int32 msg_len;
-       uint16 from_port;
-       char *msg_start;
-       pid_t remotepid;
-       SMB_DEV_T dev;
-       SMB_INO_T inode;
-       unsigned long file_id;
-       uint16 break_cmd_type;
-       struct sockaddr_in toaddr;
-
-       msg_len = IVAL(buffer,OPBRK_CMD_LEN_OFFSET);
-       from_port = SVAL(buffer,OPBRK_CMD_PORT_OFFSET);
-
-       msg_start = &buffer[OPBRK_CMD_HEADER_LEN];
-
-       DEBUG(5,("process_local_message: Got a message of length %d from port (%d)\n", 
-               msg_len, from_port));
-
-       /* 
-        * Pull the info out of the requesting packet.
-        */
-
-       break_cmd_type = SVAL(msg_start,OPBRK_MESSAGE_CMD_OFFSET);
-
-       switch(break_cmd_type) {
-               case KERNEL_OPLOCK_BREAK_CMD:
-                       if (!koplocks) {
-                               DEBUG(0,("unexpected kernel oplock break!\n"));
-                               break;
-                       } 
-                       if (!koplocks->parse_message(msg_start, msg_len, &inode, &dev, &file_id)) {
-                               DEBUG(0,("kernel oplock break parse failure!\n"));
-                               return False;
-                       }
-                       break;
-
-               case OPLOCK_BREAK_CMD:
-               case LEVEL_II_OPLOCK_BREAK_CMD:
-               case ASYNC_LEVEL_II_OPLOCK_BREAK_CMD:
-
-                       /* Ensure that the msg length is correct. */
-                       if(msg_len != OPLOCK_BREAK_MSG_LEN) {
-                               DEBUG(0,("process_local_message: incorrect length for OPLOCK_BREAK_CMD (was %d, should be %d).\n",
-                                       (int)msg_len, (int)OPLOCK_BREAK_MSG_LEN));
-                               return False;
-                       }
-
-                       memcpy((char *)&remotepid, msg_start+OPLOCK_BREAK_PID_OFFSET,sizeof(remotepid));
-                       memcpy((char *)&inode, msg_start+OPLOCK_BREAK_INODE_OFFSET,sizeof(inode));
-                       memcpy((char *)&dev, msg_start+OPLOCK_BREAK_DEV_OFFSET,sizeof(dev));
-                       memcpy((char *)&file_id, msg_start+OPLOCK_BREAK_FILEID_OFFSET,sizeof(file_id));
-
-                       DEBUG(5,("process_local_message: (%s) oplock break request from \
-pid %d, port %d, dev = %x, inode = %.0f, file_id = %lu\n",
-                               (break_cmd_type == OPLOCK_BREAK_CMD) ? "exclusive" : "level II",
-                               (int)remotepid, from_port, (unsigned int)dev, (double)inode, file_id));
-                       break;
-
-               case RETRY_DEFERRED_OPEN_CMD:
-
-                       /* Request to retry and open that would return SHARING_VIOLATION. */
-                       if (msg_len != DEFERRED_OPEN_MSG_LEN) {
-                               DEBUG(0,("process_local_message: incorrect length for RETRY_DEFERRED_OPEN_CMD (was %d, should be %d).\n",
-                                       (int)msg_len, (int)DEFERRED_OPEN_MSG_LEN));
-                               return False;
-                       }
-                       {
-                               uint16 mid;
-
-                               memcpy((char *)&remotepid, msg_start+DEFERRED_OPEN_PID_OFFSET,sizeof(remotepid));
-                               memcpy((char *)&inode, msg_start+DEFERRED_OPEN_INODE_OFFSET,sizeof(inode));
-                               memcpy((char *)&dev, msg_start+DEFERRED_OPEN_DEV_OFFSET,sizeof(dev));
-                               memcpy((char *)&mid, msg_start+DEFERRED_OPEN_MID_OFFSET,sizeof(mid));
-
-                               DEBUG(5,("process_local_message: RETRY_DEFERRED_OPEN from \
-pid %d, port %d, dev = %x, inode = %.0f, mid = %u\n",
-                                       (int)remotepid, from_port, (unsigned int)dev, (double)inode, (unsigned int)mid));
-
-                               schedule_sharing_violation_open_smb_message(mid);
-                       }
-                       return True;
-
-               /* 
-                * Keep this as a debug case - eventually we can remove it.
-                */
-               case 0x8001:
-                       DEBUG(0,("process_local_message: Received unsolicited break \
-reply - dumping info.\n"));
-
-                       if(msg_len != OPLOCK_BREAK_MSG_LEN) {
-                               DEBUG(0,("process_local_message: ubr: incorrect length for reply \
-(was %d, should be %d).\n", (int)msg_len, (int)OPLOCK_BREAK_MSG_LEN));
-                               return False;
-                       }
-
-                       memcpy((char *)&inode, msg_start+OPLOCK_BREAK_INODE_OFFSET,sizeof(inode));
-                       memcpy((char *)&remotepid, msg_start+OPLOCK_BREAK_PID_OFFSET,sizeof(remotepid));
-                       memcpy((char *)&dev, msg_start+OPLOCK_BREAK_DEV_OFFSET,sizeof(dev));
-                       memcpy((char *)&file_id, msg_start+OPLOCK_BREAK_FILEID_OFFSET,sizeof(file_id));
+       char *result = TALLOC_ARRAY(mem_ctx, char, smb_size + 8*2 + 0);
 
-                       DEBUG(0,("process_local_message: unsolicited oplock break reply from \
-pid %d, port %d, dev = %x, inode = %.0f, file_id = %lu\n",
-                               (int)remotepid, from_port, (unsigned int)dev, (double)inode, file_id));
-
-                       return False;
-
-               default:
-                       DEBUG(0,("process_local_message: unknown UDP message command code (%x) - ignoring.\n",
-                               (unsigned int)SVAL(msg_start,0)));
-                       return False;
-       }
-
-       /*
-        * Now actually process the break request.
-        */
-
-       if ((exclusive_oplocks_open == 0) &&
-           (level_II_oplocks_open == 0)) {
-               /*
-                * If we have no record of any currently open oplocks,
-                * it's not an error, as a close command may have
-                * just been issued on the file that was oplocked.
-                * Just log a message and return success in this case.
-                */
-               DEBUG(3,("process_local_message: oplock break requested with "
-                        "no outstanding oplocks. Returning success.\n"));
-
-       } else {
-               if (!oplock_break(dev, inode, file_id, False)) {
-                       DEBUG(0,("process_local_message: oplock break failed.\n"));
-                       return False;
-               }
-       }
-
-       /* 
-        * Do the appropriate reply - none in the kernel or async level II
-        * case.
-        */
-
-       if (!((break_cmd_type == OPLOCK_BREAK_CMD) ||
-             (break_cmd_type == LEVEL_II_OPLOCK_BREAK_CMD))) {
-               return True;
-       }
-
-       /* Send the message back after OR'ing in the 'REPLY' bit. */
-       SSVAL(msg_start,OPBRK_MESSAGE_CMD_OFFSET,break_cmd_type | CMD_REPLY);
-
-       memset((char *)&toaddr,'\0',sizeof(toaddr));
-       toaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
-       toaddr.sin_port = htons(from_port);
-       toaddr.sin_family = AF_INET;
-
-       if(sys_sendto( oplock_sock, msg_start, OPLOCK_BREAK_MSG_LEN, 0,
-                      (struct sockaddr *)&toaddr, sizeof(toaddr)) < 0) {
-               DEBUG(0,("process_local_message: sendto process %d failed. "
-                        "Errno was %s\n", (int)remotepid, strerror(errno)));
-               return False;
+       if (result == NULL) {
+               DEBUG(0, ("talloc failed\n"));
+               return NULL;
        }
 
-       DEBUG(5,("process_local_message: oplock break reply sent to pid %d, "
-                "port %d, for file dev = %x, inode = %.0f, file_id = %lu\n",
-                (int)remotepid, from_port, (unsigned int)dev,
-                (double)inode, file_id));
-
-       return True;
-}
-
-/****************************************************************************
- Set up an oplock break message.
-****************************************************************************/
-
-static void prepare_break_message(char *outbuf, files_struct *fsp, BOOL level2)
-{
-       memset(outbuf,'\0',smb_size);
-       set_message(outbuf,8,0,True);
-
-       SCVAL(outbuf,smb_com,SMBlockingX);
-       SSVAL(outbuf,smb_tid,fsp->conn->cnum);
-       SSVAL(outbuf,smb_pid,0xFFFF);
-       SSVAL(outbuf,smb_uid,0);
-       SSVAL(outbuf,smb_mid,0xFFFF);
-       SCVAL(outbuf,smb_vwv0,0xFF);
-       SSVAL(outbuf,smb_vwv2,fsp->fnum);
-       SCVAL(outbuf,smb_vwv3,LOCKING_ANDX_OPLOCK_RELEASE);
-       SCVAL(outbuf,smb_vwv3+1,level2 ? OPLOCKLEVEL_II : OPLOCKLEVEL_NONE);
+       memset(result,'\0',smb_size);
+       set_message(result,8,0,True);
+       SCVAL(result,smb_com,SMBlockingX);
+       SSVAL(result,smb_tid,fsp->conn->cnum);
+       SSVAL(result,smb_pid,0xFFFF);
+       SSVAL(result,smb_uid,0);
+       SSVAL(result,smb_mid,0xFFFF);
+       SCVAL(result,smb_vwv0,0xFF);
+       SSVAL(result,smb_vwv2,fsp->fnum);
+       SCVAL(result,smb_vwv3,LOCKING_ANDX_OPLOCK_RELEASE);
+       SCVAL(result,smb_vwv3+1,cmd);
+       return result;
 }
 
 /****************************************************************************
@@ -602,639 +355,266 @@ static files_struct *initial_break_processing(SMB_DEV_T dev, SMB_INO_T inode, un
        return fsp;
 }
 
-/****************************************************************************
- Process a level II oplock break directly.
- We must call this function with the share mode entry locked.
-****************************************************************************/
-
-static BOOL oplock_break_level2(files_struct *fsp, BOOL local_request)
+static void oplock_timeout_handler(struct timed_event *te,
+                                  const struct timeval *now,
+                                  void *private_data)
 {
-       char outbuf[128];
-       SMB_DEV_T dev = fsp->dev;
-       SMB_INO_T inode = fsp->inode;
-
-       /*
-        * We can have a level II oplock even if the client is not
-        * level II oplock aware. In this case just remove the
-        * flags and don't send the break-to-none message to
-        * the client.
-        */
-
-       if (global_client_caps & CAP_LEVEL_II_OPLOCKS) {
-               BOOL sign_state;
-
-               /*
-                * If we are sending an oplock break due to an SMB sent
-                * by our own client we ensure that we wait at leat
-                * lp_oplock_break_wait_time() milliseconds before sending
-                * the packet. Sending the packet sooner can break Win9x
-                * and has reported to cause problems on NT. JRA.
-                */
-
-               if (local_request) {
-                       wait_before_sending_break();
-               }
-
-               /* Prepare the SMBlockingX message. */
-               prepare_break_message( outbuf, fsp, False);
-
-               /* Save the server smb signing state. */
-               sign_state = srv_oplock_set_signing(False);
-
-               show_msg(outbuf);
-               if (!send_smb(smbd_server_fd(), outbuf))
-                       exit_server("oplock_break_level2: send_smb failed.");
+       files_struct *fsp = private_data;
 
-               /* Restore the sign state to what it was. */
-               srv_oplock_set_signing(sign_state);
-       }
-
-       /*
-        * Now we must update the shared memory structure to tell
-        * everyone else we no longer have a level II oplock on 
-        * this open file. We must call this function with the share mode
-        * entry locked so we can change the entry directly.
-        */
-
-       if(remove_share_oplock(fsp)==False) {
-               DEBUG(0,("oplock_break_level2: unable to remove level II oplock for file %s\n", fsp->fsp_name ));
-       }
-
-       release_file_oplock(fsp);
-
-       if(level_II_oplocks_open < 0) {
-               DEBUG(0,("oplock_break_level2: level_II_oplocks_open < 0 (%d). PANIC ERROR\n",
-                       level_II_oplocks_open));
-               abort();
-       }
-
-       if( DEBUGLVL( 3 ) ) {
-               dbgtext( "oplock_break_level2: returning success for " );
-               dbgtext( "dev = %x, inode = %.0f, file_id = %lu\n", (unsigned int)dev, (double)inode, fsp->file_id );
-               dbgtext( "Current level II oplocks_open = %d\n", level_II_oplocks_open );
-       }
-
-       return True;
+       DEBUG(0, ("Oplock break failed -- replying anyway\n"));
+       global_client_failed_oplock_break = True;
+       remove_oplock(fsp);
+       reply_to_oplock_break_requests(fsp);
 }
 
-/****************************************************************************
- Process an oplock break directly.
- This is always called with the share mode lock *NOT* held.
-****************************************************************************/
-
-static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_id, BOOL local_request)
+static void process_oplock_break_message(int msg_type, struct process_id src,
+                                        void *buf, size_t len)
 {
-       char *inbuf = NULL;
-       char *saved_inbuf = NULL;
-       char *outbuf = NULL;
-       char *saved_outbuf = NULL;
-       files_struct *fsp = NULL;
-       time_t start_time;
-       BOOL shutdown_server = False;
-       BOOL oplock_timeout = False;
+       struct share_mode_entry *msg = buf;
+       files_struct *fsp;
+       char *break_msg;
+       BOOL break_to_level2 = False;
        BOOL sign_state;
-       connection_struct *saved_user_conn;
-       connection_struct *saved_fsp_conn;
-       int saved_vuid;
-       pstring saved_dir; 
-       int timeout = (OPLOCK_BREAK_TIMEOUT * 1000);
-       pstring file_name;
-       BOOL using_levelII;
-
-       if((fsp = initial_break_processing(dev, inode, file_id)) == NULL)
-               return True;
 
-       /*
-        * Deal with a level II oplock going break to none separately.
-        */
-
-       if (LEVEL_II_OPLOCK_TYPE(fsp->oplock_type)) {
-               BOOL ret;
-               /* We must always call oplock_break_level2() with
-                  the share mode entry locked. */
-               if (lock_share_entry_fsp(fsp) == False) {
-                       DEBUG(0,("oplock_break: unable to lock share entry for file %s\n", fsp->fsp_name ));
-                       return False;
-               }
-               ret = oplock_break_level2(fsp, local_request);
-               unlock_share_entry_fsp(fsp);
-               return ret;
+       if (buf == NULL) {
+               DEBUG(0, ("Got NULL buffer\n"));
+               return;
        }
 
-       /* Mark the oplock break as sent - we don't want to send twice! */
-       if (fsp->sent_oplock_break) {
-               if( DEBUGLVL( 0 ) ) {
-                       dbgtext( "oplock_break: ERROR: oplock_break already sent for " );
-                       dbgtext( "file %s ", fsp->fsp_name);
-                       dbgtext( "(dev = %x, inode = %.0f, file_id = %lu)\n", (unsigned int)dev, (double)inode, fsp->file_id );
-               }
-
-               /*
-                * We have to fail the open here as we cannot send another oplock break on
-                * this file whilst we are awaiting a response from the client - neither
-                * can we allow another open to succeed while we are waiting for the client.
-                */
-               return False;
+       if (len != sizeof(*msg)) {
+               DEBUG(0, ("Got invalid msg len %d\n", (int)len));
+               return;
        }
 
-       if(global_oplock_break) {
-               DEBUG(0,("ABORT : ABORT : recursion in oplock_break !!!!!\n"));
-               abort();
-       }
+       DEBUG(10, ("Got oplock break message from pid %d: %d/%d/%d\n",
+                  (int)procid_to_pid(&src), (int)msg->dev, (int)msg->inode,
+                  (int)msg->share_file_id));
 
-       /*
-        * Now comes the horrid part. We must send an oplock break to the client,
-        * and then process incoming messages until we get a close or oplock release.
-        * At this point we know we need a new inbuf/outbuf buffer pair.
-        * We cannot use these staticaly as we may recurse into here due to
-        * messages crossing on the wire.
-        */
+       fsp = initial_break_processing(msg->dev, msg->inode,
+                                      msg->share_file_id);
 
-       if((inbuf = NewInBuffer(&saved_inbuf))==NULL) {
-               DEBUG(0,("oplock_break: malloc fail for input buffer.\n"));
-               return False;
+       if (fsp == NULL) {
+               /* We hit race here. Break messages are sent, and before we
+                * get to process this message, we have closed the file. Reply
+                * with 'ok, oplock broken' */
+               DEBUG(3, ("Did not find fsp\n"));
+               message_send_pid(src, MSG_SMB_BREAK_RESPONSE,
+                                msg, sizeof(*msg), True);
+               return;
        }
 
-       if((outbuf = NewOutBuffer(&saved_outbuf))==NULL) {
-               DEBUG(0,("oplock_break: malloc fail for output buffer.\n"));
-               /* Free must be done before set.. */
-               free_InBuffer(inbuf);
-               set_InBuffer(saved_inbuf);
-               return False;
+       if (fsp->sent_oplock_break != NO_BREAK_SENT) {
+               /* Remember we have to inform the requesting PID when the
+                * client replies */
+               msg->pid = src;
+               ADD_TO_ARRAY(NULL, struct share_mode_entry, *msg,
+                            &fsp->pending_break_messages,
+                            &fsp->num_pending_break_messages);
+               return;
        }
 
-       /*
-        * If we are sending an oplock break due to an SMB sent
-        * by our own client we ensure that we wait at leat
-        * lp_oplock_break_wait_time() milliseconds before sending
-        * the packet. Sending the packet sooner can break Win9x
-        * and has reported to cause problems on NT. JRA.
-        */
-
-       if (local_request) {
-               wait_before_sending_break();
+       if (EXCLUSIVE_OPLOCK_TYPE(msg->op_type) &&
+           !EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
+               DEBUG(3, ("Already downgraded oplock on %.0f/%.0f: %s\n",
+                         (double)fsp->dev, (double)fsp->inode,
+                         fsp->fsp_name));
+               message_send_pid(src, MSG_SMB_BREAK_RESPONSE,
+                                msg, sizeof(*msg), True);
+               return;
        }
 
-       /* Prepare the SMBlockingX message. */
+       if ((msg_type == MSG_SMB_BREAK_REQUEST) &&
+           (global_client_caps & CAP_LEVEL_II_OPLOCKS) && 
+           !koplocks && /* NOTE: we force levelII off for kernel oplocks -
+                         * this will change when it is supported */
+           lp_level2_oplocks(SNUM(fsp->conn))) {
+               break_to_level2 = True;
+       }
 
-       if ((global_client_caps & CAP_LEVEL_II_OPLOCKS) && 
-                       !koplocks && /* NOTE: we force levelII off for kernel oplocks - this will change when it is supported */
-                       lp_level2_oplocks(SNUM(fsp->conn))) {
-               using_levelII = True;
-       } else {
-               using_levelII = False;
+       break_msg = new_break_smb_message(NULL, fsp, break_to_level2 ?
+                                         OPLOCKLEVEL_II : OPLOCKLEVEL_NONE);
+       if (break_msg == NULL) {
+               exit_server("Could not talloc break_msg\n");
        }
 
-       prepare_break_message( outbuf, fsp, using_levelII);
-       /* Remember if we just sent a break to level II on this file. */
-       fsp->sent_oplock_break = using_levelII? LEVEL_II_BREAK_SENT:BREAK_TO_NONE_SENT;
+       /* Need to wait before sending a break message to a file of our own */
+       if (procid_to_pid(&src) == sys_getpid()) {
+               wait_before_sending_break();
+       }
 
        /* Save the server smb signing state. */
        sign_state = srv_oplock_set_signing(False);
 
-       show_msg(outbuf);
-       if (!send_smb(smbd_server_fd(), outbuf)) {
-               srv_oplock_set_signing(sign_state);
+       show_msg(break_msg);
+       if (!send_smb(smbd_server_fd(), break_msg)) {
                exit_server("oplock_break: send_smb failed.");
        }
 
        /* Restore the sign state to what it was. */
        srv_oplock_set_signing(sign_state);
 
-       /* We need this in case a readraw crosses on the wire. */
-       global_oplock_break = True;
-       /* Process incoming messages. */
-
-       /*
-        * JRA - If we don't get a break from the client in OPLOCK_BREAK_TIMEOUT
-        * seconds we should just die....
-        */
-
-       start_time = time(NULL);
+       talloc_free(break_msg);
 
-       /*
-        * Save the information we need to re-become the
-        * user, then unbecome the user whilst we're doing this.
-        */
-       saved_user_conn = current_user.conn;
-       saved_vuid = current_user.vuid;
-       saved_fsp_conn = fsp->conn;
-       /*
-        * Initialize saved_dir to something sensible: vfs_GetWd may not work well
-        * for root: the directory may be NFS-mounted and exported with root_squash
-        * (so has no root access).
-        */
-       pstrcpy(saved_dir,saved_fsp_conn->connectpath);
-       vfs_GetWd(saved_fsp_conn,saved_dir);
-       /* Save the chain fnum. */
-       file_chain_save();
-
-       pstrcpy(file_name, fsp->fsp_name);
-
-       change_to_root_user();
-
-       /*
-        * From Charles Hoch <hoch@exemplary.com>. If the break processing
-        * code closes the file (as it often does), then the fsp pointer here
-        * points to free()'d memory. We *must* revalidate fsp each time
-        * around the loop. With async I/O, write calls may steal the global InBuffer,
-        * so ensure we're using the correct one each time around the loop.
-        */
-
-       while((fsp = initial_break_processing(dev, inode, file_id)) &&
-                       OPEN_FSP(fsp) && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
-
-               inbuf = get_InBuffer();
-               outbuf = get_OutBuffer();
-
-               if(receive_smb(smbd_server_fd(),inbuf, timeout) == False) {
-                       /*
-                        * Die if we got an error.
-                        */
-
-                       if (smb_read_error == READ_EOF) {
-                               DEBUG( 0, ( "oplock_break: end of file from client\n" ) );
-                               shutdown_server = True;
-                       } else if (smb_read_error == READ_ERROR) {
-                               DEBUG( 0, ("oplock_break: receive_smb error (%s)\n", strerror(errno)) );
-                               shutdown_server = True;
-                       } else if (smb_read_error == READ_BAD_SIG) {
-                               DEBUG( 0, ("oplock_break: bad signature from client\n" ));
-                               shutdown_server = True;
-                       } else if (smb_read_error == READ_TIMEOUT) {
-                               DEBUG( 0, ( "oplock_break: receive_smb timed out after %d seconds.\n", OPLOCK_BREAK_TIMEOUT ) );
-                               oplock_timeout = True;
-                       }
-
-                       DEBUGADD( 0, ( "oplock_break failed for file %s ", file_name ) );
-                       DEBUGADD( 0, ( "(dev = %x, inode = %.0f, file_id = %lu).\n",
-                               (unsigned int)dev, (double)inode, file_id));
+       if (msg_type == MSG_SMB_BREAK_REQUEST) {
+               fsp->sent_oplock_break = break_to_level2 ?
+                       LEVEL_II_BREAK_SENT:BREAK_TO_NONE_SENT;
+       } else {
+               /* Async level2 request, don't send a reply */
+               fsp->sent_oplock_break = ASYNC_LEVEL_II_BREAK_SENT;
+       }
+       msg->pid = src;
+       ADD_TO_ARRAY(NULL, struct share_mode_entry, *msg,
+                    &fsp->pending_break_messages,
+                    &fsp->num_pending_break_messages);
 
-                       break;
-               }
+       if (fsp->oplock_timeout != NULL) {
+               DEBUG(0, ("Logic problem -- have an oplock event hanging "
+                         "around\n"));
+       }
 
-               /*
-                * There are certain SMB requests that we shouldn't allow
-                * to recurse. opens, renames and deletes are the obvious
-                * ones. This is handled in the switch_message() function.
-                * If global_oplock_break is set they will push the packet onto
-                * the pending smb queue and return -1 (no reply).
-                * JRA.
-                */
+       fsp->oplock_timeout =
+               add_timed_event(NULL,
+                               timeval_current_ofs(OPLOCK_BREAK_TIMEOUT, 0),
+                               "oplock_timeout_handler",
+                               oplock_timeout_handler, fsp);
 
-               process_smb(inbuf, outbuf);
+       if (fsp->oplock_timeout == NULL) {
+               DEBUG(0, ("Could not add oplock timeout handler\n"));
+       }
+}
 
-               /*
-                * Die if we go over the time limit.
-                */
+static void process_kernel_oplock_break(int msg_type, struct process_id src,
+                                       void *buf, size_t len)
+{
+       struct kernel_oplock_message *msg = buf;
+       files_struct *fsp;
+       char *break_msg;
+       BOOL sign_state;
 
-               if((time(NULL) - start_time) > OPLOCK_BREAK_TIMEOUT) {
-                       if( DEBUGLVL( 0 ) ) {
-                               dbgtext( "oplock_break: no break received from client " );
-                               dbgtext( "within %d seconds.\n", OPLOCK_BREAK_TIMEOUT );
-                               dbgtext( "oplock_break failed for file %s ", fsp->fsp_name );
-                               dbgtext( "(dev = %x, inode = %.0f, file_id = %lu).\n",  
-                                       (unsigned int)dev, (double)inode, file_id );
-                       }
-                       oplock_timeout = True;
-                       break;
-               }
+       if (buf == NULL) {
+               DEBUG(0, ("Got NULL buffer\n"));
+               return;
        }
 
-       /*
-        * Go back to being the user who requested the oplock
-        * break.
-        */
-       if((saved_user_conn != NULL) && (saved_vuid != UID_FIELD_INVALID) && !change_to_user(saved_user_conn, saved_vuid)) {
-               DEBUG( 0, ( "oplock_break: unable to re-become user!" ) );
-               DEBUGADD( 0, ( "Shutting down server\n" ) );
-               close(oplock_sock);
-               exit_server("unable to re-become user");
+       if (len != sizeof(*msg)) {
+               DEBUG(0, ("Got invalid msg len %d\n", (int)len));
+               return;
        }
 
-       /* Including the directory. */
-       vfs_ChDir(saved_fsp_conn,saved_dir);
-
-       /* Restore the chain fnum. */
-       file_chain_restore();
+       DEBUG(10, ("Got kernel oplock break message from pid %d: %d/%d/%d\n",
+                  (int)procid_to_pid(&src), (int)msg->dev, (int)msg->inode,
+                  (int)msg->file_id));
 
-       /* Free the buffers we've been using to recurse. */
-       /* Free must be done before set.. */
-       free_InBuffer(inbuf);
-       free_OutBuffer(outbuf);
+       fsp = initial_break_processing(msg->dev, msg->inode, msg->file_id);
 
-       /* Restore the global In/Out buffers. */
-       set_InBuffer(saved_inbuf);
-       set_OutBuffer(saved_outbuf);
-
-       /* We need this in case a readraw crossed on the wire. */
-       if(global_oplock_break)
-               global_oplock_break = False;
-
-       /*
-        * If the client timed out then clear the oplock (or go to level II)
-        * and continue. This seems to be what NT does and is better than dropping
-        * the connection.
-        */
-
-       if(oplock_timeout && (fsp = initial_break_processing(dev, inode, file_id)) &&
-                       OPEN_FSP(fsp) && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
-               DEBUG(0,("oplock_break: client failure in oplock break in file %s\n", fsp->fsp_name));
-               remove_oplock(fsp,True);
-#if FASCIST_OPLOCK_BACKOFF
-               global_client_failed_oplock_break = True; /* Never grant this client an oplock again. */
-#endif
+       if (fsp == NULL) {
+               DEBUG(3, ("Got a kernel oplock break message for a file "
+                         "I don't know about\n"));
+               return;
        }
 
-       /*
-        * If the client had an error we must die.
-        */
-
-       if(shutdown_server) {
-               DEBUG( 0, ( "oplock_break: client failure in break - " ) );
-               DEBUGADD( 0, ( "shutting down this smbd.\n" ) );
-               close(oplock_sock);
-               exit_server("oplock break failure");
+       if (fsp->sent_oplock_break != NO_BREAK_SENT) {
+               /* This is ok, kernel oplocks come in completely async */
+               DEBUG(3, ("Got a kernel oplock request while waiting for a "
+                         "break reply\n"));
+               return;
        }
 
-       /* Santity check - remove this later. JRA */
-       if(exclusive_oplocks_open < 0) {
-               DEBUG(0,("oplock_break: exclusive_oplocks_open < 0 (%d). PANIC ERROR\n", exclusive_oplocks_open));
-               abort();
+       break_msg = new_break_smb_message(NULL, fsp, OPLOCKLEVEL_NONE);
+       if (break_msg == NULL) {
+               exit_server("Could not talloc break_msg\n");
        }
 
-       /* We know we have no saved errors here. */
-       set_saved_error_triple(0, 0, NT_STATUS_OK);
+       /* Save the server smb signing state. */
+       sign_state = srv_oplock_set_signing(False);
 
-       if( DEBUGLVL( 3 ) ) {
-               dbgtext( "oplock_break: returning success for " );
-               dbgtext( "dev = %x, inode = %.0f, file_id = %lu\n", (unsigned int)dev, (double)inode, file_id );
-               dbgtext( "Current exclusive_oplocks_open = %d\n", exclusive_oplocks_open );
+       show_msg(break_msg);
+       if (!send_smb(smbd_server_fd(), break_msg)) {
+               exit_server("oplock_break: send_smb failed.");
        }
 
-       return True;
-}
-
-/****************************************************************************
- Send an oplock break message to another smbd process. If the oplock is held 
- by the local smbd then call the oplock break function directly.
- This function is called with no share locks held.
-****************************************************************************/
+       /* Restore the sign state to what it was. */
+       srv_oplock_set_signing(sign_state);
 
-BOOL request_oplock_break(share_mode_entry *share_entry)
-{
-       char op_break_msg[OPLOCK_BREAK_MSG_LEN];
-       struct sockaddr_in addr_out;
-       pid_t pid = sys_getpid();
-       time_t start_time;
-       int time_left;
-       SMB_DEV_T dev = share_entry->dev;
-       SMB_INO_T inode = share_entry->inode;
-       unsigned long file_id = share_entry->share_file_id;
-       uint16 break_cmd_type;
-
-       if(pid == share_entry->pid) {
-               /* We are breaking our own oplock, make sure it's us. */
-               if(share_entry->op_port != global_oplock_port) {
-                       DEBUG(0,("request_oplock_break: corrupt share mode entry - pid = %d, port = %d \
-should be %d\n", (int)pid, share_entry->op_port, global_oplock_port));
-                       return False;
-               }
+       talloc_free(break_msg);
 
-               DEBUG(5,("request_oplock_break: breaking our own oplock\n"));
+       fsp->sent_oplock_break = BREAK_TO_NONE_SENT;
+}
 
-#if 1 /* JRA PARANOIA TEST.... */
-               {
-                       files_struct *fsp = file_find_dif(dev, inode, file_id);
-                       if (!fsp) {
-                               DEBUG(0,("request_oplock_break: PANIC : breaking our own oplock requested for \
-dev = %x, inode = %.0f, file_id = %lu and no fsp found !\n",
-            (unsigned int)dev, (double)inode, file_id ));
-                               smb_panic("request_oplock_break: no fsp found for our own oplock\n");
-                       }
-               }
-#endif /* END JRA PARANOIA TEST... */
+void reply_to_oplock_break_requests(files_struct *fsp)
+{
+       int i;
 
-               /* Call oplock break direct. */
-               return oplock_break(dev, inode, file_id, True);
+       for (i=0; i<fsp->num_pending_break_messages; i++) {
+               struct share_mode_entry *msg = &fsp->pending_break_messages[i];
+               message_send_pid(msg->pid, MSG_SMB_BREAK_RESPONSE,
+                                msg, sizeof(*msg), True);
        }
 
-       /* We need to send a OPLOCK_BREAK_CMD message to the port in the share mode entry. */
-
-       if (LEVEL_II_OPLOCK_TYPE(share_entry->op_type)) {
-               break_cmd_type = LEVEL_II_OPLOCK_BREAK_CMD;
-       } else {
-               break_cmd_type = OPLOCK_BREAK_CMD;
+       SAFE_FREE(fsp->pending_break_messages);
+       fsp->num_pending_break_messages = 0;
+       if (fsp->oplock_timeout != NULL) {
+               talloc_free(fsp->oplock_timeout);
+               fsp->oplock_timeout = NULL;
        }
+       return;
+}
 
-       SSVAL(op_break_msg,OPBRK_MESSAGE_CMD_OFFSET,break_cmd_type);
-       memcpy(op_break_msg+OPLOCK_BREAK_PID_OFFSET,(char *)&pid,sizeof(pid));
-       memcpy(op_break_msg+OPLOCK_BREAK_DEV_OFFSET,(char *)&dev,sizeof(dev));
-       memcpy(op_break_msg+OPLOCK_BREAK_INODE_OFFSET,(char *)&inode,sizeof(inode));
-       memcpy(op_break_msg+OPLOCK_BREAK_FILEID_OFFSET,(char *)&file_id,sizeof(file_id));
-
-       /* Set the address and port. */
-       memset((char *)&addr_out,'\0',sizeof(addr_out));
-       addr_out.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
-       addr_out.sin_port = htons( share_entry->op_port );
-       addr_out.sin_family = AF_INET;
-   
-       if( DEBUGLVL( 3 ) ) {
-               dbgtext( "request_oplock_break: sending a synchronous oplock break message to " );
-               dbgtext( "pid %d on port %d ", (int)share_entry->pid, share_entry->op_port );
-               dbgtext( "for dev = %x, inode = %.0f, file_id = %lu\n",
-            (unsigned int)dev, (double)inode, file_id );
-       }
+static void process_oplock_break_response(int msg_type, struct process_id src,
+                                         void *buf, size_t len)
+{
+       struct share_mode_entry *msg = buf;
 
-       if(sys_sendto(oplock_sock,op_break_msg,OPLOCK_BREAK_MSG_LEN,0,
-                       (struct sockaddr *)&addr_out,sizeof(addr_out)) < 0) {
-               if( DEBUGLVL( 0 ) ) {
-                       dbgtext( "request_oplock_break: failed when sending a oplock " );
-                       dbgtext( "break message to pid %d ", (int)share_entry->pid );
-                       dbgtext( "on port %d ", share_entry->op_port );
-                       dbgtext( "for dev = %x, inode = %.0f, file_id = %lu\n",
-                               (unsigned int)dev, (double)inode, file_id );
-                       dbgtext( "Error was %s\n", strerror(errno) );
-               }
-               return False;
+       if (buf == NULL) {
+               DEBUG(0, ("Got NULL buffer\n"));
+               return;
        }
 
-       /*
-        * Now we must await the oplock broken message coming back
-        * from the target smbd process. Timeout if it fails to
-        * return in (OPLOCK_BREAK_TIMEOUT + OPLOCK_BREAK_TIMEOUT_FUDGEFACTOR) seconds.
-        * While we get messages that aren't ours, loop.
-        */
-
-       start_time = time(NULL);
-       time_left = OPLOCK_BREAK_TIMEOUT+OPLOCK_BREAK_TIMEOUT_FUDGEFACTOR;
-
-       while(time_left >= 0) {
-               char op_break_reply[OPBRK_CMD_HEADER_LEN+OPLOCK_BREAK_MSG_LEN];
-               uint16 reply_from_port;
-               char *reply_msg_start;
-
-               if(receive_local_message(op_break_reply, sizeof(op_break_reply),
-                               time_left ? time_left * 1000 : 1) == False) {
-                       if(smb_read_error == READ_TIMEOUT) {
-                               if( DEBUGLVL( 0 ) ) {
-                                       dbgtext( "request_oplock_break: no response received to oplock " );
-                                       dbgtext( "break request to pid %d ", (int)share_entry->pid );
-                                       dbgtext( "on port %d ", share_entry->op_port );
-                                       dbgtext( "for dev = %x, inode = %.0f, file_id = %lu\n",
-                                                       (unsigned int)dev, (double)inode, file_id );
-                               }
-
-                               /*
-                                * This is a hack to make handling of failing clients more robust.
-                                * If a oplock break response message is not received in the timeout
-                                * period we may assume that the smbd servicing that client holding
-                                * the oplock has died and the client changes were lost anyway, so
-                                * we should continue to try and open the file.
-                                */
-                               break;
-                       } else {
-                               if( DEBUGLVL( 0 ) ) {
-                                       dbgtext( "request_oplock_break: error in response received " );
-                                       dbgtext( "to oplock break request to pid %d ", (int)share_entry->pid );
-                                       dbgtext( "on port %d ", share_entry->op_port );
-                                       dbgtext( "for dev = %x, inode = %.0f, file_id = %lu\n",
-                                               (unsigned int)dev, (double)inode, file_id );
-                                       dbgtext( "Error was (%s).\n", strerror(errno) );
-                               }
-                       }
-                       return False;
-               }
-
-               reply_from_port = SVAL(op_break_reply,OPBRK_CMD_PORT_OFFSET);
-               reply_msg_start = &op_break_reply[OPBRK_CMD_HEADER_LEN];
-
-               /*
-                * Test to see if this is the reply we are awaiting (ie. the one we sent with the CMD_REPLY flag OR'ed in).
-                */
-               if((SVAL(reply_msg_start,OPBRK_MESSAGE_CMD_OFFSET) & CMD_REPLY) &&
-                       ((SVAL(reply_msg_start,OPBRK_MESSAGE_CMD_OFFSET) & ~CMD_REPLY) == break_cmd_type) &&
-                       (reply_from_port == share_entry->op_port) && 
-                       (memcmp(&reply_msg_start[OPLOCK_BREAK_PID_OFFSET], &op_break_msg[OPLOCK_BREAK_PID_OFFSET],
-                               OPLOCK_BREAK_MSG_LEN - OPLOCK_BREAK_PID_OFFSET) == 0)) {
-
-                       /*
-                        * This is the reply we've been waiting for.
-                        */
-                       break;
-               } else {
-                       /*
-                        * This is another message - a break request.
-                        * Note that both kernel oplock break requests
-                        * and UDP inter-smbd oplock break requests will
-                        * be processed here.
-                        *
-                        * Process it to prevent potential deadlock.
-                        * Note that the code in switch_message() prevents
-                        * us from recursing into here as any SMB requests
-                        * we might process that would cause another oplock
-                        * break request to be made will be queued.
-                        * JRA.
-                        */
-
-                       process_local_message(op_break_reply, sizeof(op_break_reply));
-               }
-
-               time_left -= (time(NULL) - start_time);
+       if (len != sizeof(*msg)) {
+               DEBUG(0, ("Got invalid msg len %d\n", (int)len));
+               return;
        }
 
-       DEBUG(3,("request_oplock_break: broke oplock.\n"));
+       DEBUG(10, ("Got oplock break response from pid %d: %d/%d/%d mid %d\n",
+                  (int)procid_to_pid(&src), (int)msg->dev, (int)msg->inode,
+                  (int)msg->share_file_id, (int)msg->op_mid));
 
-       return True;
+       /* Here's the hack from open.c, store the mid in the 'port' field */
+       schedule_deferred_open_smb_message(msg->op_mid);
 }
 
-/****************************************************************************
-  Attempt to break an oplock on a file (if oplocked).
-  Returns True if the file was closed as a result of
-  the oplock break, False otherwise.
-  Used as a last ditch attempt to free a space in the 
-  file table when we have run out.
-****************************************************************************/
-
-BOOL attempt_close_oplocked_file(files_struct *fsp)
+static void process_open_retry_message(int msg_type, struct process_id src,
+                                      void *buf, size_t len)
 {
-       DEBUG(5,("attempt_close_oplocked_file: checking file %s.\n", fsp->fsp_name));
-
-       if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && !fsp->sent_oplock_break && (fsp->fh->fd != -1)) {
-               /* Try and break the oplock. */
-               if (oplock_break(fsp->dev, fsp->inode, fsp->file_id, True)) {
-                       if(file_find_fsp(fsp) == NULL) /* Did the oplock break close the file ? */
-                               return True;
-               }
+       struct share_mode_entry *msg = buf;
+       
+       if (buf == NULL) {
+               DEBUG(0, ("Got NULL buffer\n"));
+               return;
        }
 
-       return False;
-}
-
-/****************************************************************************
- Send an asynchronous oplock break message to another smbd process.
-****************************************************************************/
-
-static BOOL request_remote_level2_async_oplock_break(share_mode_entry *share_entry)
-{
-       char op_break_msg[OPLOCK_BREAK_MSG_LEN];
-       struct sockaddr_in addr_out;
-       pid_t pid = sys_getpid();
-       SMB_DEV_T dev = share_entry->dev;
-       SMB_INO_T inode = share_entry->inode;
-       unsigned long file_id = share_entry->share_file_id;
-
-       /* We need to send a ASYNC_LEVEL_II_OPLOCK_BREAK_CMD message to the port in the share mode entry. */
-
-       SSVAL(op_break_msg,OPBRK_MESSAGE_CMD_OFFSET,ASYNC_LEVEL_II_OPLOCK_BREAK_CMD);
-       memcpy(op_break_msg+OPLOCK_BREAK_PID_OFFSET,(char *)&pid,sizeof(pid));
-       memcpy(op_break_msg+OPLOCK_BREAK_DEV_OFFSET,(char *)&dev,sizeof(dev));
-       memcpy(op_break_msg+OPLOCK_BREAK_INODE_OFFSET,(char *)&inode,sizeof(inode));
-       memcpy(op_break_msg+OPLOCK_BREAK_FILEID_OFFSET,(char *)&file_id,sizeof(file_id));
-
-       /* Set the address and port. */
-       memset((char *)&addr_out,'\0',sizeof(addr_out));
-       addr_out.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
-       addr_out.sin_port = htons( share_entry->op_port );
-       addr_out.sin_family = AF_INET;
-   
-       if( DEBUGLVL( 3 ) ) {
-               dbgtext( "request_remote_level2_async_oplock_break: sending an asynchronous oplock break message to ");
-               dbgtext( "pid %d on port %d ", (int)share_entry->pid, share_entry->op_port );
-               dbgtext( "for dev = %x, inode = %.0f, file_id = %lu\n",
-            (unsigned int)dev, (double)inode, file_id );
+       if (len != sizeof(*msg)) {
+               DEBUG(0, ("Got invalid msg len %d\n", (int)len));
+               return;
        }
 
-       if(sys_sendto(oplock_sock,op_break_msg,OPLOCK_BREAK_MSG_LEN,0,
-                       (struct sockaddr *)&addr_out,sizeof(addr_out)) < 0) {
-               if( DEBUGLVL( 0 ) ) {
-                       dbgtext( "request_remote_level2_async_oplock_break: failed when sending a oplock " );
-                       dbgtext( "break message to pid %d ", (int)share_entry->pid );
-                       dbgtext( "on port %d ", share_entry->op_port );
-                       dbgtext( "for dev = %x, inode = %.0f, file_id = %lu\n",
-                               (unsigned int)dev, (double)inode, file_id );
-                       dbgtext( "Error was %s\n", strerror(errno) );
-               }
-               return False;
-       }
+       DEBUG(10, ("Got open retry msg from pid %d: %d/%d mid %d\n",
+                  (int)procid_to_pid(&src), (int)msg->dev, (int)msg->inode,
+                  (int)msg->op_mid));
 
-       DEBUG(3,("request_remote_level2_async_oplock_break: sent async break message to level II entry.\n"));
-       return True;
+       schedule_deferred_open_smb_message(msg->op_mid);
 }
 
 /****************************************************************************
  This function is called on any file modification or lock request. If a file
- is level 2 oplocked then it must tell all other level 2 holders to break to none.
+ is level 2 oplocked then it must tell all other level 2 holders to break to
+ none.
 ****************************************************************************/
 
 void release_level_2_oplocks_on_change(files_struct *fsp)
 {
-       share_mode_entry *share_list = NULL;
-       pid_t pid = sys_getpid();
-       int num_share_modes = 0;
        int i;
-       BOOL dummy;
+       struct share_mode_lock *lck;
 
        /*
         * If this file is level II oplocked then we need
@@ -1247,125 +627,71 @@ void release_level_2_oplocks_on_change(files_struct *fsp)
        if (!LEVEL_II_OPLOCK_TYPE(fsp->oplock_type))
                return;
 
-       if (lock_share_entry_fsp(fsp) == False) {
-               DEBUG(0,("release_level_2_oplocks_on_change: failed to lock share mode entry for file %s.\n", fsp->fsp_name ));
+       lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL);
+       if (lck == NULL) {
+               DEBUG(0,("release_level_2_oplocks_on_change: failed to lock "
+                        "share mode entry for file %s.\n", fsp->fsp_name ));
        }
 
-       num_share_modes = get_share_modes(fsp->dev, fsp->inode, &share_list,
-                                         &dummy);
-
        DEBUG(10,("release_level_2_oplocks_on_change: num_share_modes = %d\n", 
-                       num_share_modes ));
+                 lck->num_share_modes ));
+
+       if (fsp->oplock_type == FAKE_LEVEL_II_OPLOCK) {
+               /* See if someone else has already downgraded us, then we
+                  don't have to do anything */
+               for (i=0; i<lck->num_share_modes; i++) {
+                       struct share_mode_entry *e = &lck->share_modes[i];
+                       if ((e->op_type == NO_OPLOCK) &&
+                           (e->share_file_id == fsp->file_id) &&
+                           (e->dev == fsp->dev) &&
+                           (e->inode == fsp->inode) &&
+                           (procid_is_me(&e->pid))) {
+                               /* We're done */
+                               fsp->oplock_type = NO_OPLOCK;
+                               talloc_free(lck);
+                               return;
+                       }
+               }
+       }
 
-       for(i = 0; i < num_share_modes; i++) {
-               share_mode_entry *share_entry = &share_list[i];
+       for(i = 0; i < lck->num_share_modes; i++) {
+               struct share_mode_entry *share_entry = &lck->share_modes[i];
 
                /*
-                * As there could have been multiple writes waiting at the lock_share_entry
-                * gate we may not be the first to enter. Hence the state of the op_types
-                * in the share mode entries may be partly NO_OPLOCK and partly LEVEL_II
-                * oplock. It will do no harm to re-send break messages to those smbd's
-                * that are still waiting their turn to remove their LEVEL_II state, and
-                * also no harm to ignore existing NO_OPLOCK states. JRA.
+                * As there could have been multiple writes waiting at the
+                * lock_share_entry gate we may not be the first to
+                * enter. Hence the state of the op_types in the share mode
+                * entries may be partly NO_OPLOCK and partly LEVEL_II
+                * oplock. It will do no harm to re-send break messages to
+                * those smbd's that are still waiting their turn to remove
+                * their LEVEL_II state, and also no harm to ignore existing
+                * NO_OPLOCK states. JRA.
                 */
 
-               DEBUG(10,("release_level_2_oplocks_on_change: share_entry[%i]->op_type == %d\n",
-                               i, share_entry->op_type ));
+               DEBUG(10,("release_level_2_oplocks_on_change: "
+                         "share_entry[%i]->op_type == %d\n",
+                         i, share_entry->op_type ));
 
-               if (share_entry->op_type == NO_OPLOCK)
+               if ((share_entry->op_type == NO_OPLOCK) ||
+                   (share_entry->op_type == FAKE_LEVEL_II_OPLOCK)) {
                        continue;
+               }
 
                /* Paranoia .... */
                if (EXCLUSIVE_OPLOCK_TYPE(share_entry->op_type)) {
-                       DEBUG(0,("release_level_2_oplocks_on_change: PANIC. share mode entry %d is an exlusive oplock !\n", i ));
-                       unlock_share_entry(fsp->conn, fsp->dev, fsp->inode);
+                       DEBUG(0,("release_level_2_oplocks_on_change: PANIC. "
+                                "share mode entry %d is an exlusive "
+                                "oplock !\n", i ));
+                       talloc_free(lck);
                        abort();
                }
 
-               /*
-                * Check if this is a file we have open (including the
-                * file we've been called to do write_file on. If so
-                * then break it directly without releasing the lock.
-                */
-
-               if (pid == share_entry->pid) {
-                       files_struct *new_fsp = file_find_dif(share_entry->dev, share_entry->inode, share_entry->share_file_id);
-
-                       /* Paranoia check... */
-                       if(new_fsp == NULL) {
-                               DEBUG(0,("release_level_2_oplocks_on_change: PANIC. share mode entry %d is not a local file !\n", i ));
-                               unlock_share_entry(fsp->conn, fsp->dev, fsp->inode);
-                               abort();
-                       }
-
-                       DEBUG(10,("release_level_2_oplocks_on_change: breaking our own oplock.\n"));
-
-                       oplock_break_level2(new_fsp, True);
-
-               } else {
-
-                       /*
-                        * This is a remote file and so we send an asynchronous
-                        * message.
-                        */
-
-                       DEBUG(10,("release_level_2_oplocks_on_change: breaking remote oplock (async).\n"));
-                       request_remote_level2_async_oplock_break(share_entry);
-               }
-       }
-
-       SAFE_FREE(share_list);
-       unlock_share_entry_fsp(fsp);
-
-       /* Paranoia check... */
-       if (LEVEL_II_OPLOCK_TYPE(fsp->oplock_type)) {
-               DEBUG(0,("release_level_2_oplocks_on_change: PANIC. File %s still has a level II oplock.\n", fsp->fsp_name));
-               smb_panic("release_level_2_oplocks_on_change");
-       }
-}
-
-/****************************************************************************
- Send a 'retry your open' message to a process with a deferred open entry.
-****************************************************************************/
-
-BOOL send_deferred_open_retry_message(deferred_open_entry *entry)
-{
-       char de_msg[DEFERRED_OPEN_MSG_LEN];
-       struct sockaddr_in addr_out;
-       pid_t pid = sys_getpid();
-
-       memset(de_msg, '\0', DEFERRED_OPEN_MSG_LEN);
-       SSVAL(de_msg,DEFERRED_OPEN_CMD_OFFSET,RETRY_DEFERRED_OPEN_CMD);
-       memcpy(de_msg+DEFERRED_OPEN_PID_OFFSET,(char *)&pid,sizeof(pid));
-       memcpy(de_msg+DEFERRED_OPEN_DEV_OFFSET,(char *)&entry->dev,sizeof(entry->dev));
-       memcpy(de_msg+DEFERRED_OPEN_INODE_OFFSET,(char *)&entry->inode,sizeof(entry->inode));
-       memcpy(de_msg+DEFERRED_OPEN_MID_OFFSET,(char *)&entry->mid,sizeof(entry->mid));
-
-       /* Set the address and port. */
-       memset((char *)&addr_out,'\0',sizeof(addr_out));
-       addr_out.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
-       addr_out.sin_port = htons( entry->port );
-       addr_out.sin_family = AF_INET;
-   
-       if( DEBUGLVL( 3 ) ) {
-               dbgtext( "send_deferred_open_retry_message: sending a message to ");
-               dbgtext( "pid %d on port %d ", (int)entry->pid, entry->port );
-               dbgtext( "for dev = %x, inode = %.0f, mid = %u\n",
-                       (unsigned int)entry->dev, (double)entry->inode, (unsigned int)entry->mid );
+               message_send_pid(share_entry->pid, MSG_SMB_ASYNC_LEVEL2_BREAK,
+                                share_entry, sizeof(*share_entry), True);
        }
 
-       if(sys_sendto(oplock_sock,de_msg,DEFERRED_OPEN_MSG_LEN,0,
-                       (struct sockaddr *)&addr_out,sizeof(addr_out)) < 0) {
-               if( DEBUGLVL( 0 ) ) {
-                       dbgtext( "send_deferred_open_retry_message: failed sending a message to ");
-                       dbgtext( "pid %d on port %d ", (int)entry->pid, entry->port );
-                       dbgtext( "for dev = %x, inode = %.0f, mid = %u\n",
-                               (unsigned int)entry->dev, (double)entry->inode, (unsigned int)entry->mid );
-                       dbgtext( "Error was %s\n", strerror(errno) );
-               }
-               return False;
-       }
-       return True;
+       remove_all_share_oplocks(lck, fsp);
+       talloc_free(lck);
 }
 
 /****************************************************************************
@@ -1374,30 +700,18 @@ BOOL send_deferred_open_retry_message(deferred_open_entry *entry)
 
 BOOL init_oplocks(void)
 {
-       struct sockaddr_in sock_name;
-       socklen_t len = sizeof(sock_name);
-
        DEBUG(3,("open_oplock_ipc: opening loopback UDP socket.\n"));
 
-       /* Open a lookback UDP socket on a random port. */
-       oplock_sock = open_socket_in(SOCK_DGRAM, 0, 0, htonl(INADDR_LOOPBACK),False);
-       if (oplock_sock == -1) {
-               DEBUG(0,("open_oplock_ipc: Failed to get local UDP socket for \
-address %lx. Error was %s\n", (long)htonl(INADDR_LOOPBACK), strerror(errno)));
-               global_oplock_port = 0;
-               return(False);
-       }
-
-       /* Find out the transient UDP port we have been allocated. */
-       if(getsockname(oplock_sock, (struct sockaddr *)&sock_name, &len)<0) {
-               DEBUG(0,("open_oplock_ipc: Failed to get local UDP port. Error was %s\n",
-                        strerror(errno)));
-               close(oplock_sock);
-               oplock_sock = -1;
-               global_oplock_port = 0;
-               return False;
-       }
-       global_oplock_port = ntohs(sock_name.sin_port);
+       message_register(MSG_SMB_BREAK_REQUEST,
+                        process_oplock_break_message);
+       message_register(MSG_SMB_ASYNC_LEVEL2_BREAK,
+                        process_oplock_break_message);
+       message_register(MSG_SMB_BREAK_RESPONSE,
+                        process_oplock_break_response);
+       message_register(MSG_SMB_KERNEL_BREAK,
+                        process_kernel_oplock_break);
+       message_register(MSG_SMB_OPEN_RETRY,
+                        process_open_retry_message);
 
        if (lp_kernel_oplocks()) {
 #if HAVE_KERNEL_OPLOCKS_IRIX
@@ -1407,8 +721,5 @@ address %lx. Error was %s\n", (long)htonl(INADDR_LOOPBACK), strerror(errno)));
 #endif
        }
 
-       DEBUG(3,("open_oplock ipc: pid = %d, global_oplock_port = %u\n", 
-                (int)sys_getpid(), global_oplock_port));
-
        return True;
 }
index f4405a021e103bcdb03e0ee6dcb699cf6e96c0cb..f49aa297e45618011020017e09d55db18a9b3246 100644 (file)
@@ -86,7 +86,7 @@ Disabling kernel oplock support.\n", strerror(errno) ));
  * oplock break protocol.
 ****************************************************************************/
 
-static BOOL irix_oplock_receive_message(fd_set *fds, char *buffer, int buffer_len)
+static files_struct *irix_oplock_receive_message(fd_set *fds)
 {
        extern int smb_read_error;
        oplock_stat_t os;
@@ -102,7 +102,7 @@ static BOOL irix_oplock_receive_message(fd_set *fds, char *buffer, int buffer_le
                DEBUG(0,("irix_oplock_receive_message: read of kernel notification failed. \
 Error was %s.\n", strerror(errno) ));
                smb_read_error = READ_ERROR;
-               return False;
+               return NULL;
        }
 
        /*
@@ -122,7 +122,7 @@ Error was %s.\n", strerror(errno) ));
                        return True;
                }
                smb_read_error = READ_ERROR;
-               return False;
+               return NULL;
        }
 
        /*
@@ -138,24 +138,8 @@ Error was %s.\n", strerror(errno) ));
      
        DEBUG(5,("irix_oplock_receive_message: kernel oplock break request received for \
 dev = %x, inode = %.0f\n, file_id = %ul", (unsigned int)fsp->dev, (double)fsp->inode, fsp->file_id ));
-     
-       /*
-        * Create a kernel oplock break message.
-        */
-    
-       /* Setup the message header */
-       SIVAL(buffer,OPBRK_CMD_LEN_OFFSET,KERNEL_OPLOCK_BREAK_MSG_LEN);
-       SSVAL(buffer,OPBRK_CMD_PORT_OFFSET,0);
-   
-       buffer += OPBRK_CMD_HEADER_LEN;
-     
-       SSVAL(buffer,OPBRK_MESSAGE_CMD_OFFSET,KERNEL_OPLOCK_BREAK_CMD);
-   
-       memcpy(buffer + KERNEL_OPLOCK_BREAK_DEV_OFFSET, (char *)&fsp->dev, sizeof(fsp->dev));
-       memcpy(buffer + KERNEL_OPLOCK_BREAK_INODE_OFFSET, (char *)&fsp->inode, sizeof(fsp->inode));     
-       memcpy(buffer + KERNEL_OPLOCK_BREAK_FILEID_OFFSET, (char *)&fsp->file_id, sizeof(fsp->file_id));        
-   
-       return True;
+
+       return fsp;
 }
 
 /****************************************************************************
@@ -214,30 +198,6 @@ oplock state of %x.\n", fsp->fsp_name, (unsigned int)fsp->dev,
        }
 }
 
-/****************************************************************************
- Parse a kernel oplock message.
-****************************************************************************/
-
-static BOOL irix_kernel_oplock_parse(char *msg_start, int msg_len,
-               SMB_INO_T *inode, SMB_DEV_T *dev, unsigned long *file_id)
-{
-       /* Ensure that the msg length is correct. */
-       if(msg_len != KERNEL_OPLOCK_BREAK_MSG_LEN) {
-               DEBUG(0,("incorrect length for KERNEL_OPLOCK_BREAK_CMD (was %d, should be %d).\n", 
-                        msg_len, KERNEL_OPLOCK_BREAK_MSG_LEN));
-               return False;
-       }
-
-       memcpy((char *)inode, msg_start+KERNEL_OPLOCK_BREAK_INODE_OFFSET, sizeof(*inode));
-       memcpy((char *)dev, msg_start+KERNEL_OPLOCK_BREAK_DEV_OFFSET, sizeof(*dev));
-       memcpy((char *)file_id, msg_start+KERNEL_OPLOCK_BREAK_FILEID_OFFSET, sizeof(*file_id));
-
-       DEBUG(5,("kernel oplock break request for file dev = %x, inode = %.0f, file_id = %ul\n", 
-               (unsigned int)*dev, (double)*inode, *file_id));
-
-       return True;
-}
-
 /****************************************************************************
  Set *maxfd to include oplock read pipe.
 ****************************************************************************/
@@ -274,7 +234,6 @@ struct kernel_oplocks *irix_init_kernel_oplocks(void)
        koplocks.receive_message = irix_oplock_receive_message;
        koplocks.set_oplock = irix_set_kernel_oplock;
        koplocks.release_oplock = irix_release_kernel_oplock;
-       koplocks.parse_message = irix_kernel_oplock_parse;
        koplocks.msg_waiting = irix_oplock_msg_waiting;
        koplocks.notification_fd = oplock_pipe_read;
 
index 477832c6e8eaff4281ca35d3a3ff1c8e699b1dc6..ab0c08f7fcc524b3b74eccde5ea1646889617992 100644 (file)
@@ -128,10 +128,10 @@ static int linux_setlease(int fd, int leasetype)
  * oplock break protocol.
 ****************************************************************************/
 
-static BOOL linux_oplock_receive_message(fd_set *fds, char *buffer, int buffer_len)
+static files_struct *linux_oplock_receive_message(fd_set *fds)
 {
        int fd;
-       struct files_struct *fsp;
+       files_struct *fsp;
 
        BlockSignals(True, RT_SIGNAL_LEASE);
        fd = fd_pending_array[0];
@@ -145,32 +145,7 @@ static BOOL linux_oplock_receive_message(fd_set *fds, char *buffer, int buffer_l
        /* now we can receive more signals */
        BlockSignals(False, RT_SIGNAL_LEASE);
 
-       if (fsp == NULL) {
-               DEBUG(0,("Invalid file descriptor %d in kernel oplock break!\n", (int)fd));
-               return False;
-       }
-
-       DEBUG(3,("linux_oplock_receive_message: kernel oplock break request received for \
-dev = %x, inode = %.0f fd = %d, fileid = %lu \n", (unsigned int)fsp->dev, (double)fsp->inode,
-                       fd, fsp->file_id));
-     
-       /*
-        * Create a kernel oplock break message.
-        */
-     
-       /* Setup the message header */
-       SIVAL(buffer,OPBRK_CMD_LEN_OFFSET,KERNEL_OPLOCK_BREAK_MSG_LEN);
-       SSVAL(buffer,OPBRK_CMD_PORT_OFFSET,0);
-     
-       buffer += OPBRK_CMD_HEADER_LEN;
-     
-       SSVAL(buffer,OPBRK_MESSAGE_CMD_OFFSET,KERNEL_OPLOCK_BREAK_CMD);
-     
-       memcpy(buffer + KERNEL_OPLOCK_BREAK_DEV_OFFSET, (char *)&fsp->dev, sizeof(fsp->dev));
-       memcpy(buffer + KERNEL_OPLOCK_BREAK_INODE_OFFSET, (char *)&fsp->inode, sizeof(fsp->inode));     
-       memcpy(buffer + KERNEL_OPLOCK_BREAK_FILEID_OFFSET, (char *)&fsp->file_id, sizeof(fsp->file_id));        
-
-       return True;
+       return fsp;
 }
 
 /****************************************************************************
@@ -223,30 +198,6 @@ oplock state of %x.\n", fsp->fsp_name, (unsigned int)fsp->dev,
        }
 }
 
-/****************************************************************************
- Parse a kernel oplock message.
-****************************************************************************/
-
-static BOOL linux_kernel_oplock_parse(char *msg_start, int msg_len, SMB_INO_T *inode,
-               SMB_DEV_T *dev, unsigned long *file_id)
-{
-       /* Ensure that the msg length is correct. */
-       if (msg_len != KERNEL_OPLOCK_BREAK_MSG_LEN) {
-               DEBUG(0,("incorrect length for KERNEL_OPLOCK_BREAK_CMD (was %d, should be %lu).\n", 
-                        msg_len, (unsigned long)KERNEL_OPLOCK_BREAK_MSG_LEN));
-               return False;
-       }
-
-       memcpy((char *)inode, msg_start+KERNEL_OPLOCK_BREAK_INODE_OFFSET, sizeof(*inode));
-       memcpy((char *)dev, msg_start+KERNEL_OPLOCK_BREAK_DEV_OFFSET, sizeof(*dev));
-       memcpy((char *)file_id, msg_start+KERNEL_OPLOCK_BREAK_FILEID_OFFSET, sizeof(*file_id));
-
-       DEBUG(3,("kernel oplock break request for file dev = %x, inode = %.0f, file_id = %lu\n", 
-               (unsigned int)*dev, (double)*inode, *file_id));
-
-       return True;
-}
-
 /****************************************************************************
  See if a oplock message is waiting.
 ****************************************************************************/
@@ -299,7 +250,6 @@ struct kernel_oplocks *linux_init_kernel_oplocks(void)
        koplocks.receive_message = linux_oplock_receive_message;
        koplocks.set_oplock = linux_set_kernel_oplock;
        koplocks.release_oplock = linux_release_kernel_oplock;
-       koplocks.parse_message = linux_kernel_oplock_parse;
        koplocks.msg_waiting = linux_oplock_msg_waiting;
        koplocks.notification_fd = -1;
 
index 8f9cc5288217e16b08a1eaa395ead8118a1d64d3..0b7b94cce21152193c438178802701bfbff0995e 100644 (file)
@@ -2,6 +2,7 @@
    Unix SMB/CIFS implementation.
    process incoming packets - main loop
    Copyright (C) Andrew Tridgell 1992-1998
+   Copyright (C) Volker Lendecke 2005
    
    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
@@ -44,12 +45,11 @@ int max_send = BUFFER_SIZE;
 int max_recv = BUFFER_SIZE;
 
 extern int last_message;
-extern int global_oplock_break;
 extern userdom_struct current_user_info;
 extern int smb_read_error;
 SIG_ATOMIC_T reload_after_sighup = 0;
 SIG_ATOMIC_T got_sig_term = 0;
-BOOL global_machine_password_needs_changing = False;
+extern BOOL global_machine_password_needs_changing;
 extern int max_send;
 
 /****************************************************************************
@@ -66,106 +66,72 @@ uint16 get_current_mid(void)
  for processing.
 ****************************************************************************/
 
-static struct pending_message_list *smb_oplock_queue;
-static struct pending_message_list *smb_sharing_violation_queue;
-
-enum q_type { OPLOCK_QUEUE, SHARE_VIOLATION_QUEUE };
-
-/****************************************************************************
- Free up a message.
-****************************************************************************/
-
-static void free_queued_message(struct pending_message_list *msg)
-{
-       data_blob_free(&msg->buf);
-       data_blob_free(&msg->private_data);
-       SAFE_FREE(msg);
-}
+static struct pending_message_list *deferred_open_queue;
 
 /****************************************************************************
  Function to push a message onto the tail of a linked list of smb messages ready
  for processing.
 ****************************************************************************/
 
-static BOOL push_queued_message(enum q_type qt, char *buf, int msg_len, struct timeval *ptv, char *private_data, size_t private_len)
+static BOOL push_queued_message(char *buf, int msg_len,
+                               struct timeval request_time,
+                               struct timeval end_time,
+                               char *private_data, size_t private_len)
 {
        struct pending_message_list *tmp_msg;
-       struct pending_message_list *msg = SMB_MALLOC_P(struct pending_message_list);
+       struct pending_message_list *msg;
+
+       msg = TALLOC_ZERO_P(NULL, struct pending_message_list);
 
        if(msg == NULL) {
                DEBUG(0,("push_message: malloc fail (1)\n"));
                return False;
        }
 
-       memset(msg,'\0',sizeof(*msg));
-
-       msg->buf = data_blob(buf, msg_len);
+       msg->buf = data_blob_talloc(msg, buf, msg_len);
        if(msg->buf.data == NULL) {
                DEBUG(0,("push_message: malloc fail (2)\n"));
-               SAFE_FREE(msg);
+               talloc_free(msg);
                return False;
        }
 
-       if (ptv) {
-               msg->msg_time = *ptv;
-       }
+       msg->request_time = request_time;
+       msg->end_time = end_time;
 
        if (private_data) {
-               msg->private_data = data_blob(private_data, private_len);
+               msg->private_data = data_blob_talloc(msg, private_data,
+                                                    private_len);
                if (msg->private_data.data == NULL) {
                        DEBUG(0,("push_message: malloc fail (3)\n"));
-                       data_blob_free(&msg->buf);
-                       SAFE_FREE(msg);
+                       talloc_free(msg);
                        return False;
                }
        }
 
-       if (qt == OPLOCK_QUEUE) {
-               DLIST_ADD_END(smb_oplock_queue, msg, tmp_msg);
-       } else {
-               DLIST_ADD_END(smb_sharing_violation_queue, msg, tmp_msg);
-       }
+       DLIST_ADD_END(deferred_open_queue, msg, tmp_msg);
 
-       DEBUG(10,("push_message: pushed message length %u on queue %s\n",
-               (unsigned int)msg_len,
-               qt == OPLOCK_QUEUE ? "smb_oplock_queue" : "smb_sharing_violation_queue" ));
+       DEBUG(10,("push_message: pushed message length %u on "
+                 "deferred_open_queue\n", (unsigned int)msg_len));
 
        return True;
 }
 
-/****************************************************************************
- Function to push an oplock smb message onto a linked list of local smb messages ready
- for processing.
-****************************************************************************/
-
-BOOL push_oplock_pending_smb_message(char *buf, int msg_len)
-{
-       BOOL ret = push_queued_message(OPLOCK_QUEUE, buf, msg_len, NULL, NULL, 0);
-       if (ret) {
-               /* Push the MID of this packet on the signing queue. */
-               srv_defer_sign_response(SVAL(buf,smb_mid));
-       }
-       return ret;
-}
-
 /****************************************************************************
  Function to delete a sharing violation open message by mid.
 ****************************************************************************/
 
-void remove_sharing_violation_open_smb_message(uint16 mid)
+void remove_deferred_open_smb_message(uint16 mid)
 {
        struct pending_message_list *pml;
 
-       if (!lp_defer_sharing_violations()) {
-               return;
-       }
-
-       for (pml = smb_sharing_violation_queue; pml; pml = pml->next) {
+       for (pml = deferred_open_queue; pml; pml = pml->next) {
                if (mid == SVAL(pml->buf.data,smb_mid)) {
-                       DEBUG(10,("remove_sharing_violation_open_smb_message: deleting mid %u len %u\n",
-                               (unsigned int)mid, (unsigned int)pml->buf.length ));
-                       DLIST_REMOVE(smb_sharing_violation_queue, pml);
-                       free_queued_message(pml);
+                       DEBUG(10,("remove_sharing_violation_open_smb_message: "
+                                 "deleting mid %u len %u\n",
+                                 (unsigned int)mid,
+                                 (unsigned int)pml->buf.length ));
+                       DLIST_REMOVE(deferred_open_queue, pml);
+                       talloc_free(pml);
                        return;
                }
        }
@@ -176,30 +142,26 @@ void remove_sharing_violation_open_smb_message(uint16 mid)
  schedule it for immediate processing.
 ****************************************************************************/
 
-void schedule_sharing_violation_open_smb_message(uint16 mid)
+void schedule_deferred_open_smb_message(uint16 mid)
 {
        struct pending_message_list *pml;
        int i = 0;
 
-       if (!lp_defer_sharing_violations()) {
-               return;
-       }
-
-       for (pml = smb_sharing_violation_queue; pml; pml = pml->next) {
+       for (pml = deferred_open_queue; pml; pml = pml->next) {
                uint16 msg_mid = SVAL(pml->buf.data,smb_mid);
-               DEBUG(10,("schedule_sharing_violation_open_smb_message: [%d] msg_mid = %u\n", i++,
+               DEBUG(10,("schedule_deferred_open_smb_message: [%d] msg_mid = %u\n", i++,
                        (unsigned int)msg_mid ));
                if (mid == msg_mid) {
-                       DEBUG(10,("schedule_sharing_violation_open_smb_message: scheduling mid %u\n",
+                       DEBUG(10,("schedule_deferred_open_smb_message: scheduling mid %u\n",
                                mid ));
-                       pml->msg_time.tv_sec = 0;
-                       pml->msg_time.tv_usec = 0;
-                       DLIST_PROMOTE(smb_sharing_violation_queue, pml);
+                       pml->end_time.tv_sec = 0;
+                       pml->end_time.tv_usec = 0;
+                       DLIST_PROMOTE(deferred_open_queue, pml);
                        return;
                }
        }
 
-       DEBUG(10,("schedule_sharing_violation_open_smb_message: failed to find message mid %u\n",
+       DEBUG(10,("schedule_deferred_open_smb_message: failed to find message mid %u\n",
                mid ));
 }
 
@@ -211,13 +173,9 @@ BOOL open_was_deferred(uint16 mid)
 {
        struct pending_message_list *pml;
 
-       if (!lp_defer_sharing_violations()) {
-               return False;
-       }
-
-       for (pml = smb_sharing_violation_queue; pml; pml = pml->next) {
+       for (pml = deferred_open_queue; pml; pml = pml->next) {
                if (SVAL(pml->buf.data,smb_mid) == mid) {
-                       set_saved_error_triple(SMB_SUCCESS, 0, NT_STATUS_OK);
+                       set_saved_ntstatus(NT_STATUS_OK);
                        return True;
                }
        }
@@ -232,11 +190,7 @@ struct pending_message_list *get_open_deferred_message(uint16 mid)
 {
        struct pending_message_list *pml;
 
-       if (!lp_defer_sharing_violations()) {
-               return NULL;
-       }
-
-       for (pml = smb_sharing_violation_queue; pml; pml = pml->next) {
+       for (pml = deferred_open_queue; pml; pml = pml->next) {
                if (SVAL(pml->buf.data,smb_mid) == mid) {
                        return pml;
                }
@@ -245,57 +199,216 @@ struct pending_message_list *get_open_deferred_message(uint16 mid)
 }
 
 /****************************************************************************
- Function to push a sharing violation open smb message onto a linked list of local smb messages ready
- for processing. We must use current_inbuf here not Inbuf in case we're in a chained message set.
+ Function to push a deferred open smb message onto a linked list of local smb
+ messages ready for processing.
+****************************************************************************/
+
+BOOL push_deferred_smb_message(uint16 mid,
+                              struct timeval request_time,
+                              struct timeval timeout,
+                              char *private_data, size_t priv_len)
+{
+       struct timeval end_time;
+
+       end_time = timeval_sum(&request_time, &timeout);
+
+       DEBUG(10,("push_deferred_open_smb_message: pushing message len %u mid %u "
+                 "timeout time [%u.%06u]\n",
+                 (unsigned int) smb_len(current_inbuf)+4, (unsigned int)mid,
+                 (unsigned int)end_time.tv_sec,
+                 (unsigned int)end_time.tv_usec));
+
+       return push_queued_message(current_inbuf, smb_len(current_inbuf)+4,
+                                  request_time, end_time,
+                                  private_data, priv_len);
+}
+
+static struct timed_event *timed_events;
+
+struct timed_event {
+       struct timed_event *next, *prev;
+       struct timeval when;
+       const char *event_name;
+       void (*handler)(struct timed_event *te,
+                       const struct timeval *now,
+                       void *private_data);
+       void *private_data;
+};
+
+static int timed_event_destructor(void *p)
+{
+       struct timed_event *te = talloc_get_type_abort(p, struct timed_event);
+       DEBUG(10, ("Destroying timed event %lx \"%s\"\n", (unsigned long)te,
+                  te->event_name));
+       DLIST_REMOVE(timed_events, te);
+       return 0;
+}
+
+/****************************************************************************
+ Schedule a function for future calling, cancel with talloc_free().
+ It's the responsibility of the handler to call talloc_free() on the event 
+ handed to it.
 ****************************************************************************/
 
-BOOL push_sharing_violation_open_smb_message(struct timeval *ptv, char *private_data, size_t priv_len)
+struct timed_event *add_timed_event(TALLOC_CTX *mem_ctx,
+                                   struct timeval when,
+                                   const char *event_name,
+                                   void (*handler)(struct timed_event *te,
+                                                   const struct timeval *now,
+                                                   void *private_data),
+                                   void *private_data)
 {
-       uint16 mid = SVAL(current_inbuf,smb_mid);
-       struct timeval tv;
-       SMB_BIG_INT tdif;
+       struct timed_event *te, *last_te, *cur_te;
 
-       if (!lp_defer_sharing_violations()) {
-               return True;
+       te = TALLOC_P(mem_ctx, struct timed_event);
+       if (te == NULL) {
+               DEBUG(0, ("talloc failed\n"));
+               return NULL;
        }
 
-       tv = *ptv;
-       tdif = tv.tv_sec;
-       tdif *= 1000000;
-       tdif += tv.tv_usec;
+       te->when = when;
+       te->event_name = event_name;
+       te->handler = handler;
+       te->private_data = private_data;
+
+       /* keep the list ordered */
+       last_te = NULL;
+       for (cur_te = timed_events; cur_te; cur_te = cur_te->next) {
+               /* if the new event comes before the current one break */
+               if (!timeval_is_zero(&cur_te->when) &&
+                   timeval_compare(&te->when, &cur_te->when) < 0) {
+                       break;
+               }
+               last_te = cur_te;
+       }
 
-       /* Add on the timeout. */
-       tdif += SHARING_VIOLATION_USEC_WAIT;
-       
-       tv.tv_sec = tdif / 1000000;
-       tv.tv_usec = tdif % 1000000;
-       
-       DEBUG(10,("push_sharing_violation_open_smb_message: pushing message len %u mid %u\
- timeout time [%u.%06u]\n", (unsigned int) smb_len(current_inbuf)+4, (unsigned int)mid,
-               (unsigned int)tv.tv_sec, (unsigned int)tv.tv_usec));
+       DLIST_ADD_AFTER(timed_events, te, last_te);
+       talloc_set_destructor(te, timed_event_destructor);
 
-       return push_queued_message(SHARE_VIOLATION_QUEUE, current_inbuf,
-                       smb_len(current_inbuf)+4, &tv, private_data, priv_len);
+       DEBUG(10, ("Added timed event \"%s\": %lx\n", event_name,
+                  (unsigned long)te));
+       return te;
 }
 
+static void run_events(void)
+{
+       struct timeval now;
+
+       if (timed_events == NULL) {
+               /* No syscall if there are no events */
+               DEBUG(10, ("run_events: No events\n"));
+               return;
+       }
+
+       GetTimeOfDay(&now);
+
+       if (timeval_compare(&now, &timed_events->when) < 0) {
+               /* Nothing to do yet */
+               DEBUG(10, ("run_events: Nothing to do\n"));
+               return;
+       }
+
+       DEBUG(10, ("Running event \"%s\" %lx\n", timed_events->event_name,
+                  (unsigned long)timed_events));
+
+       timed_events->handler(timed_events, &now, timed_events->private_data);
+       return;
+}
+
+struct timeval timed_events_timeout(void)
+{
+       struct timeval now, timeout;
+
+       if (timed_events == NULL) {
+               return timeval_set(SMBD_SELECT_TIMEOUT, 0);
+       }
+
+       now = timeval_current();
+       timeout = timeval_until(&now, &timed_events->when);
+
+       DEBUG(10, ("timed_events_timeout: %d/%d\n", (int)timeout.tv_sec,
+                  (int)timeout.tv_usec));
+
+       return timeout;
+}
+
+struct idle_event {
+       struct timed_event *te;
+       struct timeval interval;
+       BOOL (*handler)(const struct timeval *now, void *private_data);
+       void *private_data;
+};
+
+static void idle_event_handler(struct timed_event *te,
+                              const struct timeval *now,
+                              void *private_data)
+{
+       struct idle_event *event =
+               talloc_get_type_abort(private_data, struct idle_event);
+
+       talloc_free(event->te);
+
+       if (!event->handler(now, event->private_data)) {
+               /* Don't repeat, delete ourselves */
+               talloc_free(event);
+               return;
+       }
+
+       event->te = add_timed_event(event, timeval_sum(now, &event->interval),
+                                   "idle_event_handler",
+                                   idle_event_handler, event);
+
+       /* We can't do much but fail here. */
+       SMB_ASSERT(event->te != NULL);
+}
+
+struct idle_event *add_idle_event(TALLOC_CTX *mem_ctx,
+                                 struct timeval interval,
+                                 BOOL (*handler)(const struct timeval *now,
+                                                 void *private_data),
+                                 void *private_data)
+{
+       struct idle_event *result;
+       struct timeval now = timeval_current();
+
+       result = TALLOC_P(mem_ctx, struct idle_event);
+       if (result == NULL) {
+               DEBUG(0, ("talloc failed\n"));
+               return NULL;
+       }
+
+       result->interval = interval;
+       result->handler = handler;
+       result->private_data = private_data;
+
+       result->te = add_timed_event(result, timeval_sum(&now, &interval),
+                                    "idle_event_handler",
+                                    idle_event_handler, result);
+       if (result->te == NULL) {
+               DEBUG(0, ("add_timed_event failed\n"));
+               talloc_free(result);
+               return NULL;
+       }
+
+       return result;
+}
+       
 /****************************************************************************
- Do all async processing in here. This includes UDB oplock messages, kernel
oplock messages, change notify events etc.
+ Do all async processing in here. This includes kernel oplock messages, change
+ notify events etc.
 ****************************************************************************/
 
-static void async_processing(char *buffer, int buffer_len)
+static void async_processing(void)
 {
        DEBUG(10,("async_processing: Doing async processing.\n"));
 
        process_aio_queue();
 
-       /* check for oplock messages (both UDP and kernel) */
-       if (receive_local_message(buffer, buffer_len, 1)) {
-               process_local_message(buffer, buffer_len);
-       }
+       process_kernel_oplocks();
 
-       /* Do the aio check again after receive_local_message as it does a select
-          and may have eaten our signal. */
+       /* Do the aio check again after receive_local_message as it does a
+          select and may have eaten our signal. */
+       /* Is this till true? -- vl */
        process_aio_queue();
 
        if (got_sig_term) {
@@ -339,17 +452,17 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout)
 {
        fd_set fds;
        int selrtn;
-       struct timeval to;
-       struct timeval *pto;
+       struct timeval to = timeval_set(SMBD_SELECT_TIMEOUT, 0);
        int maxfd;
 
        smb_read_error = 0;
 
  again:
 
-       to.tv_sec = timeout / 1000;
-       to.tv_usec = (timeout % 1000) * 1000;
-       pto = timeout > 0 ? &to : NULL;
+       if (timeout >= 0) {
+               to.tv_sec = timeout / 1000;
+               to.tv_usec = (timeout % 1000) * 1000;
+       }
 
        /*
         * Note that this call must be before processing any SMB
@@ -358,38 +471,22 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout)
         */
        message_dispatch();
 
-       /*
-        * Check to see if we already have a message on the smb queue.
-        * If so - copy and return it.
-        */
-       if(smb_oplock_queue != NULL) {
-               struct pending_message_list *msg = smb_oplock_queue;
-               memcpy(buffer, msg->buf.data, MIN(buffer_len, msg->buf.length));
-  
-               /* Free the message we just copied. */
-               DLIST_REMOVE(smb_oplock_queue, msg);
-               free_queued_message(msg);
-               
-               DEBUG(5,("receive_message_or_smb: returning queued smb message.\n"));
-               return True;
-       }
-
        /*
         * Check to see if we already have a message on the deferred open queue
         * and it's time to schedule.
         */
-       if(smb_sharing_violation_queue != NULL) {
+       if(deferred_open_queue != NULL) {
                BOOL pop_message = False;
-               struct pending_message_list *msg = smb_sharing_violation_queue;
+               struct pending_message_list *msg = deferred_open_queue;
 
-               if (msg->msg_time.tv_sec == 0 && msg->msg_time.tv_usec == 0) {
+               if (timeval_is_zero(&msg->end_time)) {
                        pop_message = True;
                } else {
                        struct timeval tv;
                        SMB_BIG_INT tdif;
 
                        GetTimeOfDay(&tv);
-                       tdif = usec_time_diff(&msg->msg_time, &tv);
+                       tdif = usec_time_diff(&msg->end_time, &tv);
                        if (tdif <= 0) {
                                /* Timed out. Schedule...*/
                                pop_message = True;
@@ -398,9 +495,8 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout)
                                /* Make a more accurate select timeout. */
                                to.tv_sec = tdif / 1000000;
                                to.tv_usec = tdif % 1000000;
-                               pto = &to;
                                DEBUG(10,("receive_message_or_smb: select with timeout of [%u.%06u]\n",
-                                       (unsigned int)pto->tv_sec, (unsigned int)pto->tv_usec ));
+                                       (unsigned int)to.tv_sec, (unsigned int)to.tv_usec ));
                        }
                }
 
@@ -431,7 +527,7 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout)
 
        if (oplock_message_waiting(&fds)) {
                DEBUG(10,("receive_message_or_smb: oplock_message is waiting.\n"));
-               async_processing(buffer, buffer_len);
+               async_processing();
                /*
                 * After async processing we must go and do the select again, as
                 * the state of the flag in fds for the server file descriptor is
@@ -439,18 +535,26 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout)
                 */
                goto again;
        }
+
+       {
+               struct timeval tmp = timed_events_timeout();
+               to = timeval_min(&to, &tmp);
+               if (timeval_is_zero(&to)) {
+                       return True;
+               }
+       }
        
        FD_SET(smbd_server_fd(),&fds);
        maxfd = setup_oplock_select_set(&fds);
 
-       selrtn = sys_select(MAX(maxfd,smbd_server_fd())+1,&fds,NULL,NULL,pto);
+       selrtn = sys_select(MAX(maxfd,smbd_server_fd())+1,&fds,NULL,NULL,&to);
 
        /* if we get EINTR then maybe we have received an oplock
           signal - treat this as select returning 1. This is ugly, but
           is the best we can do until the oplock code knows more about
           signals */
        if (selrtn == -1 && errno == EINTR) {
-               async_processing(buffer, buffer_len);
+               async_processing();
                /*
                 * After async processing we must go and do the select again, as
                 * the state of the flag in fds for the server file descriptor is
@@ -479,7 +583,7 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout)
         */
 
        if (oplock_message_waiting(&fds)) {
-               async_processing(buffer, buffer_len);
+               async_processing();
                /*
                 * After async processing we must go and do the select again, as
                 * the state of the flag in fds for the server file descriptor is
@@ -518,8 +622,6 @@ BOOL receive_next_smb(char *inbuf, int bufsize, int timeout)
 
 void respond_to_all_remaining_local_messages(void)
 {
-       char buffer[1024];
-
        /*
         * Assert we have no exclusive open oplocks.
         */
@@ -530,15 +632,7 @@ void respond_to_all_remaining_local_messages(void)
                return;
        }
 
-       /*
-        * Keep doing receive_local_message with a 1 ms timeout until
-        * we have no more messages.
-        */
-
-       while(receive_local_message(buffer, sizeof(buffer), 1)) {
-               /* Deal with oplock break requests from other smbd's. */
-               process_local_message(buffer, sizeof(buffer));
-       }
+       process_kernel_oplocks();
 
        return;
 }
@@ -556,8 +650,7 @@ force write permissions on print services.
 #define TIME_INIT (1<<2)
 #define CAN_IPC (1<<3)
 #define AS_GUEST (1<<5)
-#define QUEUE_IN_OPLOCK (1<<6)
-#define DO_CHDIR (1<<7)
+#define DO_CHDIR (1<<6)
 
 /* 
    define a list of possible SMB messages and their corresponding
@@ -572,19 +665,19 @@ static const struct smb_message_struct {
 
 /* 0x00 */ { "SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE},
 /* 0x01 */ { "SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE},
-/* 0x02 */ { "SMBopen",reply_open,AS_USER | QUEUE_IN_OPLOCK },
+/* 0x02 */ { "SMBopen",reply_open,AS_USER },
 /* 0x03 */ { "SMBcreate",reply_mknew,AS_USER},
 /* 0x04 */ { "SMBclose",reply_close,AS_USER | CAN_IPC },
 /* 0x05 */ { "SMBflush",reply_flush,AS_USER},
-/* 0x06 */ { "SMBunlink",reply_unlink,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK},
-/* 0x07 */ { "SMBmv",reply_mv,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK},
+/* 0x06 */ { "SMBunlink",reply_unlink,AS_USER | NEED_WRITE }, 
+/* 0x07 */ { "SMBmv",reply_mv,AS_USER | NEED_WRITE },
 /* 0x08 */ { "SMBgetatr",reply_getatr,AS_USER},
 /* 0x09 */ { "SMBsetatr",reply_setatr,AS_USER | NEED_WRITE},
 /* 0x0a */ { "SMBread",reply_read,AS_USER},
 /* 0x0b */ { "SMBwrite",reply_write,AS_USER | CAN_IPC },
 /* 0x0c */ { "SMBlock",reply_lock,AS_USER},
 /* 0x0d */ { "SMBunlock",reply_unlock,AS_USER},
-/* 0x0e */ { "SMBctemp",reply_ctemp,AS_USER | QUEUE_IN_OPLOCK },
+/* 0x0e */ { "SMBctemp",reply_ctemp,AS_USER },
 /* 0x0f */ { "SMBmknew",reply_mknew,AS_USER}, 
 /* 0x10 */ { "SMBchkpth",reply_chkpth,AS_USER},
 /* 0x11 */ { "SMBexit",reply_exit,DO_CHDIR},
@@ -611,11 +704,11 @@ static const struct smb_message_struct {
 /* 0x26 */ { "SMBtranss",NULL,AS_USER | CAN_IPC},
 /* 0x27 */ { "SMBioctl",reply_ioctl,0},
 /* 0x28 */ { "SMBioctls",NULL,AS_USER},
-/* 0x29 */ { "SMBcopy",reply_copy,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK },
-/* 0x2a */ { "SMBmove",NULL,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK },
+/* 0x29 */ { "SMBcopy",reply_copy,AS_USER | NEED_WRITE },
+/* 0x2a */ { "SMBmove",NULL,AS_USER | NEED_WRITE },
 /* 0x2b */ { "SMBecho",reply_echo,0},
 /* 0x2c */ { "SMBwriteclose",reply_writeclose,AS_USER},
-/* 0x2d */ { "SMBopenX",reply_open_and_X,AS_USER | CAN_IPC | QUEUE_IN_OPLOCK },
+/* 0x2d */ { "SMBopenX",reply_open_and_X,AS_USER | CAN_IPC },
 /* 0x2e */ { "SMBreadX",reply_read_and_X,AS_USER | CAN_IPC },
 /* 0x2f */ { "SMBwriteX",reply_write_and_X,AS_USER | CAN_IPC },
 /* 0x30 */ { NULL, NULL, 0 },
@@ -730,12 +823,12 @@ static const struct smb_message_struct {
 /* 0x9d */ { NULL, NULL, 0 },
 /* 0x9e */ { NULL, NULL, 0 },
 /* 0x9f */ { NULL, NULL, 0 },
-/* 0xa0 */ { "SMBnttrans", reply_nttrans, AS_USER | CAN_IPC | QUEUE_IN_OPLOCK},
+/* 0xa0 */ { "SMBnttrans", reply_nttrans, AS_USER | CAN_IPC },
 /* 0xa1 */ { "SMBnttranss", reply_nttranss, AS_USER | CAN_IPC },
-/* 0xa2 */ { "SMBntcreateX", reply_ntcreate_and_X, AS_USER | CAN_IPC | QUEUE_IN_OPLOCK },
+/* 0xa2 */ { "SMBntcreateX", reply_ntcreate_and_X, AS_USER | CAN_IPC },
 /* 0xa3 */ { NULL, NULL, 0 },
 /* 0xa4 */ { "SMBntcancel", reply_ntcancel, 0 },
-/* 0xa5 */ { "SMBntrename", reply_ntrename, AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK },
+/* 0xa5 */ { "SMBntrename", reply_ntrename, AS_USER | NEED_WRITE },
 /* 0xa6 */ { NULL, NULL, 0 },
 /* 0xa7 */ { NULL, NULL, 0 },
 /* 0xa8 */ { NULL, NULL, 0 },
@@ -762,7 +855,7 @@ static const struct smb_message_struct {
 /* 0xbd */ { NULL, NULL, 0 },
 /* 0xbe */ { NULL, NULL, 0 },
 /* 0xbf */ { NULL, NULL, 0 },
-/* 0xc0 */ { "SMBsplopen",reply_printopen,AS_USER | QUEUE_IN_OPLOCK },
+/* 0xc0 */ { "SMBsplopen",reply_printopen,AS_USER},
 /* 0xc1 */ { "SMBsplwr",reply_printwrite,AS_USER},
 /* 0xc2 */ { "SMBsplclose",reply_printclose,AS_USER},
 /* 0xc3 */ { "SMBsplretq",reply_printqueue,AS_USER},
@@ -871,7 +964,7 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize
                pid = sys_getpid();
 
        errno = 0;
-       set_saved_error_triple(0, 0, NT_STATUS_OK);
+       set_saved_ntstatus(NT_STATUS_OK);
 
        last_message = type;
 
@@ -900,19 +993,6 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize
                DEBUG(3,("switch message %s (pid %d) conn 0x%lx\n",smb_fn_name(type),(int)pid,(unsigned long)conn));
 
                smb_dump(smb_fn_name(type), 1, inbuf, size);
-               if(global_oplock_break) {
-                       if(flags & QUEUE_IN_OPLOCK) {
-                               /* 
-                                * Queue this message as we are the process of an oplock break.
-                                */
-
-                               DEBUG( 2, ( "switch_message: queueing message due to being in " ) );
-                               DEBUGADD( 2, ( "oplock break state.\n" ) );
-
-                               push_oplock_pending_smb_message( inbuf, size );
-                               return -1;
-                       }
-               }
 
                /* Ensure this value is replaced in the incoming packet. */
                SSVAL(inbuf,smb_uid,session_tag);
@@ -1289,6 +1369,7 @@ static int setup_select_timeout(void)
        select_timeout *= 1000;
 
        t = change_notify_timeout();
+       DEBUG(10, ("change_notify_timeout: %d\n", t));
        if (t != -1)
                select_timeout = MIN(select_timeout, t*1000);
 
@@ -1302,7 +1383,7 @@ static int setup_select_timeout(void)
  Check if services need reloading.
 ****************************************************************************/
 
-void check_reload(int t)
+void check_reload(time_t t)
 {
        static pid_t mypid = 0;
        static time_t last_smb_conf_reload_time = 0;
@@ -1644,6 +1725,8 @@ void smbd_process(void)
                        num_smbs = 0; /* Reset smb counter. */
                }
 
+               run_events();
+
 #if defined(DEVELOPER)
                clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, InBuffer, total_buffer_size);
 #endif
index 5572f47e427854ff511439466a4bf84125fb0cc2..ba22a56cfb4b9a2cdeded05518bec76ffc1a9f60 100644 (file)
@@ -30,7 +30,6 @@
 extern enum protocol_types Protocol;
 extern int max_send;
 extern int max_recv;
-extern int global_oplock_break;
 unsigned int smb_echo_count = 0;
 extern uint32 global_client_caps;
 
@@ -1779,7 +1778,7 @@ static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype,
        }
 
        /* We need a better way to return NT status codes from open... */
-       set_saved_error_triple(0, 0, NT_STATUS_OK);
+       set_saved_ntstatus(NT_STATUS_OK);
 
        fsp = open_file_ntcreate(conn, fname, pst,
                                DELETE_ACCESS,
@@ -1791,12 +1790,12 @@ static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype,
                                NULL);
 
        if (!fsp) {
-               NTSTATUS ret;
-               if (get_saved_error_triple(NULL, NULL, &ret)) {
-                       set_saved_error_triple(0, 0, NT_STATUS_OK);
+               NTSTATUS ret = get_saved_ntstatus();
+               if (!NT_STATUS_IS_OK(ret)) {
+                       set_saved_ntstatus(NT_STATUS_OK);
                        return ret;
                }
-               set_saved_error_triple(0, 0, NT_STATUS_OK);
+               set_saved_ntstatus(NT_STATUS_OK);
                return NT_STATUS_ACCESS_DENIED;
        }
        close_file(fsp,False);
@@ -1860,7 +1859,7 @@ NTSTATUS can_delete(connection_struct *conn, char *fname, uint32 dirtype, BOOL b
                   don't do it here as we'll get it wrong. */
 
                /* We need a better way to return NT status codes from open... */
-               set_saved_error_triple(0, 0, NT_STATUS_OK);
+               set_saved_ntstatus(NT_STATUS_OK);
 
                fsp = open_file_ntcreate(conn, fname, &sbuf,
                                        DELETE_ACCESS,
@@ -1872,12 +1871,12 @@ NTSTATUS can_delete(connection_struct *conn, char *fname, uint32 dirtype, BOOL b
                                        NULL);
 
                if (!fsp) {
-                       NTSTATUS ret;
-                       if (get_saved_error_triple(NULL, NULL, &ret)) {
-                               set_saved_error_triple(0, 0, NT_STATUS_OK);
+                       NTSTATUS ret = get_saved_ntstatus();
+                       if (!NT_STATUS_IS_OK(ret)) {
+                               set_saved_ntstatus(NT_STATUS_OK);
                                return ret;
                        }
-                       set_saved_error_triple(0, 0, NT_STATUS_OK);
+                       set_saved_ntstatus(NT_STATUS_OK);
                        return NT_STATUS_ACCESS_DENIED;
                }
                close_file(fsp,False);
@@ -2209,15 +2208,6 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s
         * return a zero length response here.
         */
 
-       if(global_oplock_break) {
-               _smb_setlen(header,0);
-               if (write_data(smbd_server_fd(),header,4) != 4)
-                       fail_readraw();
-               DEBUG(5,("readbraw - oplock break finished\n"));
-               END_PROFILE(SMBreadbraw);
-               return -1;
-       }
-
        fsp = file_fsp(inbuf,smb_vwv0);
 
        if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
@@ -2298,8 +2288,8 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s
                nread = 0;
 #endif
   
-       DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos,
-                               (int)maxcount, (int)mincount, (int)nread ) );
+       DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%lu min=%lu nread=%lu\n", fsp->fnum, (double)startpos,
+                               (unsigned long)maxcount, (unsigned long)mincount, (unsigned long)nread ) );
   
        send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf, out_buffsize);
 
@@ -3744,7 +3734,7 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
        if( is_ntfs_stream_name(directory)) {
                DEBUG(5,("reply_mkdir: failing create on filename %s with colon in name\n", directory));
                END_PROFILE(SMBmkdir);
-               return ERROR_FORCE_DOS(ERRDOS, ERRinvalidname);
+               return ERROR_NT(NT_STATUS_NOT_A_DIRECTORY);
        }
 
        status = mkdir_internal(conn, directory,bad_path);
@@ -5084,7 +5074,8 @@ SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_forma
  Reply to a lockingX request.
 ****************************************************************************/
 
-int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
+int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
+                  int length, int bufsize)
 {
        files_struct *fsp = file_fsp(inbuf,smb_vwv2);
        unsigned char locktype = CVAL(inbuf,smb_vwv3);
@@ -5096,7 +5087,8 @@ int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,
        int32 lock_timeout = IVAL(inbuf,smb_vwv4);
        int i;
        char *data;
-       BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
+       BOOL large_file_format =
+               (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
        BOOL err;
        BOOL my_lock_ctx = False;
        NTSTATUS status;
@@ -5125,19 +5117,25 @@ int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,
        if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
                /* Client can insist on breaking to none. */
                BOOL break_to_none = (oplocklevel == 0);
-               
-               DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
-                        (unsigned int)oplocklevel, fsp->fnum ));
+               BOOL result;
+
+               DEBUG(5,("reply_lockingX: oplock break reply (%u) from client "
+                        "for fnum = %d\n", (unsigned int)oplocklevel,
+                        fsp->fnum ));
 
                /*
-                * Make sure we have granted an exclusive or batch oplock on this file.
+                * Make sure we have granted an exclusive or batch oplock on
+                * this file.
                 */
                
-               if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
-                       DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
-no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
-
-                       /* if this is a pure oplock break request then don't send a reply */
+               if (fsp->oplock_type == 0) {
+                       DEBUG(0,("reply_lockingX: Error : oplock break from "
+                                "client for fnum = %d (oplock=%d) and no "
+                                "oplock granted on this file (%s).\n",
+                                fsp->fnum, fsp->oplock_type, fsp->fsp_name));
+
+                       /* if this is a pure oplock break request then don't
+                        * send a reply */
                        if (num_locks == 0 && num_ulocks == 0) {
                                END_PROFILE(SMBlockingX);
                                return -1;
@@ -5147,17 +5145,30 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
                        }
                }
 
-               if (remove_oplock(fsp, break_to_none) == False) {
-                       DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
-                                fsp->fsp_name ));
+               if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) ||
+                   (break_to_none)) {
+                       result = remove_oplock(fsp);
+               } else {
+                       result = downgrade_oplock(fsp);
                }
                
-               /* if this is a pure oplock break request then don't send a reply */
+               if (!result) {
+                       DEBUG(0, ("reply_lockingX: error in removing "
+                                 "oplock on file %s\n", fsp->fsp_name));
+                       /* Hmmm. Is this panic justified? */
+                       smb_panic("internal tdb error");
+               }
+
+               reply_to_oplock_break_requests(fsp);
+
+               /* if this is a pure oplock break request then don't send a
+                * reply */
                if (num_locks == 0 && num_ulocks == 0) {
                        /* Sanity check - ensure a pure oplock break is not a
                           chained request. */
                        if(CVAL(inbuf,smb_vwv0) != 0xff)
-                               DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
+                               DEBUG(0,("reply_lockingX: Error : pure oplock "
+                                        "break is a chained %d request !\n",
                                         (unsigned int)CVAL(inbuf,smb_vwv0) ));
                        END_PROFILE(SMBlockingX);
                        return -1;
@@ -5186,8 +5197,9 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
                        return ERROR_DOS(ERRDOS,ERRnoaccess);
                }
 
-               DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
-                         (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
+               DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for "
+                         "pid %u, file %s\n", (double)offset, (double)count,
+                         (unsigned int)lock_pid, fsp->fsp_name ));
                
                status = do_unlock(fsp,conn,lock_pid,count,offset);
                if (NT_STATUS_V(status)) {
@@ -5219,27 +5231,34 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
                        return ERROR_DOS(ERRDOS,ERRnoaccess);
                }
                
-               DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
-                       (double)offset, (double)count, (unsigned int)lock_pid,
-                       fsp->fsp_name, (int)lock_timeout ));
+               DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid "
+                         "%u, file %s timeout = %d\n", (double)offset,
+                         (double)count, (unsigned int)lock_pid,
+                         fsp->fsp_name, (int)lock_timeout ));
                
                status = do_lock_spin(fsp,conn,lock_pid, count,offset, 
-                                ((locktype & 1) ? READ_LOCK : WRITE_LOCK), &my_lock_ctx);
+                                     ((locktype & 1) ? READ_LOCK:WRITE_LOCK),
+                                     &my_lock_ctx);
                if (NT_STATUS_V(status)) {
                        /*
-                        * Interesting fact found by IFSTEST /t LockOverlappedTest...
-                        * Even if it's our own lock context, we need to wait here as
-                        * there may be an unlock on the way.
-                        * So I removed a "&& !my_lock_ctx" from the following
-                        * if statement. JRA.
+                        * Interesting fact found by IFSTEST /t
+                        * LockOverlappedTest...  Even if it's our own lock
+                        * context, we need to wait here as there may be an
+                        * unlock on the way.  So I removed a "&&
+                        * !my_lock_ctx" from the following if statement. JRA.
                         */
-                       if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
+                       if ((lock_timeout != 0) &&
+                           lp_blocking_locks(SNUM(conn)) &&
+                           ERROR_WAS_LOCK_DENIED(status)) {
                                /*
                                 * A blocking lock was requested. Package up
                                 * this smb into a queued request and push it
                                 * onto the blocking lock queue.
                                 */
-                               if(push_blocking_lock_request(inbuf, length, lock_timeout, i, lock_pid, offset, count)) {
+                               if(push_blocking_lock_request(inbuf, length,
+                                                             lock_timeout, i,
+                                                             lock_pid, offset,
+                                                             count)) {
                                        END_PROFILE(SMBlockingX);
                                        return -1;
                                }
@@ -5259,10 +5278,12 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
                for(i--; i >= 0; i--) {
                        lock_pid = get_lock_pid( data, i, large_file_format);
                        count = get_lock_count( data, i, large_file_format);
-                       offset = get_lock_offset( data, i, large_file_format, &err);
+                       offset = get_lock_offset( data, i, large_file_format,
+                                                 &err);
                        
                        /*
-                        * There is no error code marked "stupid client bug".... :-).
+                        * There is no error code marked "stupid client
+                        * bug".... :-).
                         */
                        if(err) {
                                END_PROFILE(SMBlockingX);
@@ -5277,8 +5298,8 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
 
        set_message(outbuf,2,0,True);
        
-       DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
-                   fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
+       DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
+                 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
        
        END_PROFILE(SMBlockingX);
        return chain_reply(inbuf,outbuf,length,bufsize);
index 1ff03174fe15b3dad287dee0dab4fff29f0677ea..8310b408d07d74a5a466b4afca49a1968b136924 100644 (file)
@@ -96,7 +96,7 @@ static void  killkids(void)
  somewhere else.
 ****************************************************************************/
 
-static void msg_sam_sync(int UNUSED(msg_type), pid_t UNUSED(pid),
+static void msg_sam_sync(int UNUSED(msg_type), struct process_id UNUSED(pid),
                         void *UNUSED(buf), size_t UNUSED(len))
 {
         DEBUG(10, ("** sam sync message received, ignoring\n"));
@@ -107,7 +107,8 @@ static void msg_sam_sync(int UNUSED(msg_type), pid_t UNUSED(pid),
  somewhere else.
 ****************************************************************************/
 
-static void msg_sam_repl(int msg_type, pid_t pid, void *buf, size_t len)
+static void msg_sam_repl(int msg_type, struct process_id pid,
+                        void *buf, size_t len)
 {
         uint32 low_serial;
 
@@ -140,7 +141,8 @@ static BOOL open_sockets_inetd(void)
        return True;
 }
 
-static void msg_exit_server(int msg_type, pid_t src, void *buf, size_t len)
+static void msg_exit_server(int msg_type, struct process_id src,
+                           void *buf, size_t len)
 {
        exit_server("Got a SHUTDOWN message");
 }
@@ -621,9 +623,6 @@ void exit_server(const char *reason)
 
        print_notify_send_messages(3); /* 3 second timeout. */
 
-       /* run all registered exit events */
-       smb_run_exit_events();
-
        /* delete our entry in the connections database. */
        yield_connection(NULL,"");
 
index bf7287aab9ca1ac40fbab5a40dc1e8b926a6a274..fc2d8b4abb47952e528bbd4726935c75b1d63289 100644 (file)
@@ -139,6 +139,7 @@ static int reply_spnego_kerberos(connection_struct *conn,
                                 int length, int bufsize,
                                 DATA_BLOB *secblob)
 {
+       TALLOC_CTX *mem_ctx;
        DATA_BLOB ticket;
        char *client, *p, *domain;
        fstring netbios_domain_name;
@@ -146,7 +147,7 @@ static int reply_spnego_kerberos(connection_struct *conn,
        fstring user;
        int sess_vuid;
        NTSTATUS ret;
-       DATA_BLOB auth_data;
+       PAC_DATA *pac_data;
        DATA_BLOB ap_rep, ap_rep_wrapped, response;
        auth_serversupplied_info *server_info = NULL;
        DATA_BLOB session_key = data_blob(NULL, 0);
@@ -154,18 +155,24 @@ static int reply_spnego_kerberos(connection_struct *conn,
        DATA_BLOB nullblob = data_blob(NULL, 0);
        fstring real_username;
        BOOL map_domainuser_to_guest = False;
+       PAC_LOGON_INFO *logon_info = NULL;
+       int i;
 
        ZERO_STRUCT(ticket);
-       ZERO_STRUCT(auth_data);
+       ZERO_STRUCT(pac_data);
        ZERO_STRUCT(ap_rep);
        ZERO_STRUCT(ap_rep_wrapped);
        ZERO_STRUCT(response);
 
+       mem_ctx = talloc_init("reply_spnego_kerberos");
+       if (mem_ctx == NULL)
+               return ERROR_NT(NT_STATUS_NO_MEMORY);
+
        if (!spnego_parse_krb5_wrap(*secblob, &ticket, tok_id)) {
                return ERROR_NT(NT_STATUS_LOGON_FAILURE);
        }
 
-       ret = ads_verify_ticket(lp_realm(), &ticket, &client, &auth_data, &ap_rep, &session_key);
+       ret = ads_verify_ticket(mem_ctx, lp_realm(), &ticket, &client, &pac_data, &ap_rep, &session_key);
 
        data_blob_free(&ticket);
 
@@ -174,7 +181,18 @@ static int reply_spnego_kerberos(connection_struct *conn,
                return ERROR_NT(NT_STATUS_LOGON_FAILURE);
        }
 
-       data_blob_free(&auth_data);
+       if (pac_data) {
+
+               /* get the logon_info */
+               for (i=0; i < pac_data->num_buffers; i++) {
+               
+                       if (pac_data->pac_buffer[i].type != PAC_TYPE_LOGON_INFO)
+                               continue;
+
+                       logon_info = pac_data->pac_buffer[i].ctr->pac.logon_info;
+                       break;
+               }
+       }
 
        DEBUG(3,("Ticket name is [%s]\n", client));
 
@@ -203,7 +221,14 @@ static int reply_spnego_kerberos(connection_struct *conn,
 
        domain = p+1;
 
-       {
+       if (logon_info && logon_info->info3.hdr_logon_dom.uni_str_len) {
+
+               unistr2_to_ascii(netbios_domain_name, &logon_info->info3.uni_logon_dom, -1);
+               domain = netbios_domain_name;
+               DEBUG(10, ("Mapped to [%s] (using PAC)\n", domain));
+
+       } else {
+
                /* If we have winbind running, we can (and must) shorten the
                   username by using the short netbios name. Otherwise we will
                   have inconsistent user names. With Kerberos, we get the
@@ -231,7 +256,7 @@ static int reply_spnego_kerberos(connection_struct *conn,
                                wb_response.data.domain_info.name);
                        domain = netbios_domain_name;
 
-                       DEBUG(10, ("Mapped to [%s]\n", domain));
+                       DEBUG(10, ("Mapped to [%s] (using Winbind)\n", domain));
                } else {
                        DEBUG(3, ("Could not find short name -- winbind "
                                  "not running?\n"));
@@ -274,8 +299,21 @@ static int reply_spnego_kerberos(connection_struct *conn,
        reload_services(True);
        if ( map_domainuser_to_guest ) {
                make_server_info_guest(&server_info);
+       } else if (logon_info) {
+               ret = make_server_info_pac(&server_info, real_username, pw, logon_info);
+
+               if ( !NT_STATUS_IS_OK(ret) ) {
+                       DEBUG(1,("make_server_info_pac failed!\n"));
+                       SAFE_FREE(client);
+                       data_blob_free(&ap_rep);
+                       data_blob_free(&session_key);
+                       passwd_free(&pw);
+                       return ERROR_NT(ret);
+               }
+
        } else {
                ret = make_server_info_pw(&server_info, real_username, pw);
+
                if ( !NT_STATUS_IS_OK(ret) ) {
                        DEBUG(1,("make_server_info_from_pw failed!\n"));
                        SAFE_FREE(client);
@@ -284,15 +322,17 @@ static int reply_spnego_kerberos(connection_struct *conn,
                        passwd_free(&pw);
                        return ERROR_NT(ret);
                }
+
+               /* make_server_info_pw does not set the domain. Without this we end up
+                * with the local netbios name in substitutions for %D. */
+
+               if (server_info->sam_account != NULL) {
+                       pdb_set_domain(server_info->sam_account, domain, PDB_SET);
+               }
        }
-       passwd_free(&pw);
 
-        /* make_server_info_pw does not set the domain. Without this we end up
-        * with the local netbios name in substitutions for %D. */
 
-        if (server_info->sam_account != NULL) {
-                pdb_set_domain(server_info->sam_account, domain, PDB_SET);
-        }
+       passwd_free(&pw);
 
        /* register_vuid keeps the server info */
        /* register_vuid takes ownership of session_key, no need to free after this.
@@ -339,6 +379,7 @@ static int reply_spnego_kerberos(connection_struct *conn,
        data_blob_free(&ap_rep);
        data_blob_free(&ap_rep_wrapped);
        data_blob_free(&response);
+       talloc_destroy(mem_ctx);
 
        return -1; /* already replied */
 }
@@ -348,6 +389,8 @@ static int reply_spnego_kerberos(connection_struct *conn,
  Send a session setup reply, wrapped in SPNEGO.
  Get vuid and check first.
  End the NTLMSSP exchange context if we are OK/complete fail
+ This should be split into two functions, one to handle each
+ leg of the NTLM auth steps.
 ***************************************************************************/
 
 static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *outbuf,
@@ -422,6 +465,7 @@ static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *out
           and the other end, that we are not finished yet. */
 
        if (!ret || !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
+               /* NB. This is *NOT* an error case. JRA */
                auth_ntlmssp_end(auth_ntlmssp_state);
                /* Kill the intermediate vuid */
                invalidate_vuid(vuid);
@@ -660,7 +704,7 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
                return ret;
        }
 
-       if (strncmp(blob1.data, "NTLMSSP", 7) == 0) {
+       if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {
                DATA_BLOB chal;
                NTSTATUS nt_status;
                if (!vuser->auth_ntlmssp_state) {
index 38363bf66ae05b3882e5a216784149a37ca1cbf8..f0b7812a1e04dd8d50afe2aac48c95ec27390738 100644 (file)
@@ -27,7 +27,6 @@
 extern int max_send;
 extern enum protocol_types Protocol;
 extern int smb_read_error;
-extern int global_oplock_break;
 extern uint32 global_client_caps;
 extern struct current_user current_user;
 
@@ -2789,7 +2788,8 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *
 
                        delete_pending =
                                get_delete_on_close_flag(sbuf.st_dev,
-                                                        sbuf.st_ino);
+                                                        sbuf.st_ino,
+                                                        fname);
                } else {
                        /*
                         * Original code - this is an open file.
@@ -2804,7 +2804,8 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *
                        pos = fsp->fh->position_information;
                        delete_pending = 
                                get_delete_on_close_flag(sbuf.st_dev,
-                                                        sbuf.st_ino);
+                                                        sbuf.st_ino,
+                                                        fname);
                        access_mask = fsp->access_mask;
                }
        } else {
@@ -2847,7 +2848,8 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *
                }
 
                delete_pending = get_delete_on_close_flag(sbuf.st_dev,
-                                                         sbuf.st_ino);
+                                                         sbuf.st_ino,
+                                                         fname);
                if (delete_pending) {
                        return ERROR_NT(NT_STATUS_DELETE_PENDING);
                }
@@ -3454,91 +3456,6 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
        return(-1);
 }
 
-/****************************************************************************
- Deal with the internal needs of setting the delete on close flag. Note that
- as the tdb locking is recursive, it is safe to call this from within 
- open_file_shared. JRA.
-****************************************************************************/
-
-NTSTATUS can_set_delete_on_close(files_struct *fsp, BOOL delete_on_close,
-                                uint32 dosmode)
-{
-       if (!delete_on_close) {
-               return NT_STATUS_OK;
-       }
-
-       /*
-        * Only allow delete on close for writable files.
-        */
-
-       if ((dosmode & aRONLY) &&
-           !lp_delete_readonly(SNUM(fsp->conn))) {
-               DEBUG(10,("can_set_delete_on_close: file %s delete on close "
-                         "flag set but file attribute is readonly.\n",
-                         fsp->fsp_name ));
-               return NT_STATUS_CANNOT_DELETE;
-       }
-
-       /*
-        * Only allow delete on close for writable shares.
-        */
-
-       if (!CAN_WRITE(fsp->conn)) {
-               DEBUG(10,("can_set_delete_on_close: file %s delete on "
-                         "close flag set but write access denied on share.\n",
-                         fsp->fsp_name ));
-               return NT_STATUS_ACCESS_DENIED;
-       }
-
-       /*
-        * Only allow delete on close for files/directories opened with delete
-        * intent.
-        */
-
-       if (!(fsp->access_mask & DELETE_ACCESS)) {
-               DEBUG(10,("can_set_delete_on_close: file %s delete on "
-                         "close flag set but delete access denied.\n",
-                         fsp->fsp_name ));
-               return NT_STATUS_ACCESS_DENIED;
-       }
-
-       return NT_STATUS_OK;
-}
-
-/****************************************************************************
- Sets the delete on close flag over all share modes on this file.
- Modify the share mode entry for all files open
- on this device and inode to tell other smbds we have
- changed the delete on close flag. This will be noticed
- in the close code, the last closer will delete the file
- if flag is set.
-****************************************************************************/
-
-NTSTATUS set_delete_on_close(files_struct *fsp, BOOL delete_on_close)
-{
-       DEBUG(10,("set_delete_on_close: %s delete on close flag for "
-                 "fnum = %d, file %s\n",
-                 delete_on_close ? "Adding" : "Removing", fsp->fnum,
-                 fsp->fsp_name ));
-
-       if (fsp->is_directory || fsp->is_stat)
-               return NT_STATUS_OK;
-
-       if (lock_share_entry_fsp(fsp) == False)
-               return NT_STATUS_ACCESS_DENIED;
-
-       if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) {
-               DEBUG(0,("set_delete_on_close: failed to change delete "
-                        "on close flag for file %s\n",
-                        fsp->fsp_name ));
-               unlock_share_entry_fsp(fsp);
-               return NT_STATUS_ACCESS_DENIED;
-       }
-
-       unlock_share_entry_fsp(fsp);
-       return NT_STATUS_OK;
-}
-
 /****************************************************************************
  Set a hard link (called by UNIX extensions and by NT rename with HARD link
  code.
@@ -3912,16 +3829,6 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char
                                if (fd == -1) {
                                        files_struct *new_fsp = NULL;
  
-                                       if(global_oplock_break) {
-                                               /* Queue this file modify as we are the process of an oplock break.  */
-                                               DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
-                                               DEBUGADD(2,( "in oplock break state.\n"));
-                                               push_oplock_pending_smb_message(inbuf, length);
-                                               return -1;
-                                       }
                                        new_fsp = open_file_ntcreate(conn, fname, &sbuf,
                                                                        FILE_WRITE_DATA,
                                                                        FILE_SHARE_READ|FILE_SHARE_WRITE,
@@ -4003,9 +3910,8 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char
                        }
 
                        /* The set is across all open files on this dev/inode pair. */
-                       status =set_delete_on_close(fsp, delete_on_close);
-                       if (!NT_STATUS_IS_OK(status)) {
-                               return ERROR_NT(status);
+                       if (!set_delete_on_close(fsp, delete_on_close)) {
+                               return ERROR_NT(NT_STATUS_ACCESS_DENIED);
                        }
 
                        SSVAL(params,0,0);
@@ -4456,16 +4362,6 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
                if (fd == -1) {
                        files_struct *new_fsp = NULL;
 
-                       if(global_oplock_break) {
-                               /* Queue this file modify as we are the process of an oplock break.  */
-
-                               DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being "));
-                               DEBUGADD(2,( "in oplock break state.\n"));
-
-                               push_oplock_pending_smb_message(inbuf, length);
-                               return -1;
-                       }
-
                        new_fsp = open_file_ntcreate(conn, fname, &sbuf,
                                                FILE_WRITE_DATA,
                                                FILE_SHARE_READ|FILE_SHARE_WRITE,
@@ -4859,18 +4755,6 @@ int reply_trans2(connection_struct *conn,
        unsigned int num_params, num_params_sofar, num_data, num_data_sofar;
        START_PROFILE(SMBtrans2);
 
-       if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) {
-               /* Queue this open message as we are the process of an
-                * oplock break.  */
-
-               DEBUG(2,("reply_trans2: queueing message trans2open due to being "));
-               DEBUGADD(2,( "in oplock break state.\n"));
-
-               push_oplock_pending_smb_message(inbuf, length);
-               END_PROFILE(SMBtrans2);
-               return -1;
-       }
-       
        if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
             && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
                END_PROFILE(SMBtrans2);
index 17ae536bc4a81875fee44cd6563e34b7da7611f9..3efb29e44c1bd2089b9f83f3e05bf43f429f88f6 100644 (file)
@@ -49,10 +49,10 @@ static void print_data(TDB_DATA d)
 static int traverse_fn(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
 {
        printf("{\n");
-       printf("key(%d) = \"",key.dsize);
+       printf("key(%d) = \"", (int)key.dsize);
        print_data(key);
        printf("\"\n");
-       printf("data(%d) = \"",dbuf.dsize);
+       printf("data(%d) = \"", (int)dbuf.dsize);
        print_data(dbuf);
        printf("\"\n");
        printf("}\n");
index d9e7b9315a05e7c7073494a0a3f603febb1e03ca..8aa57af7ab7ce69dfde836c99e0e5c6bf3cd857a 100644 (file)
@@ -331,7 +331,7 @@ static void move_rec(char *keyname, size_t keylen, char* tdbname)
 
 static int print_conn_key(TDB_DATA key)
 {
-       printf( "\nkey %d bytes\n", key.dsize);
+       printf( "\nkey %d bytes\n", (int)key.dsize);
        printf( "pid    =%5d   ", ((connections_key*)key.dptr)->pid);
        printf( "cnum   =%10d  ", ((connections_key*)key.dptr)->cnum);
        printf( "name   =[%s]\n", ((connections_key*)key.dptr)->name);
@@ -340,7 +340,7 @@ static int print_conn_key(TDB_DATA key)
 
 static int print_conn_data(TDB_DATA dbuf)
 {
-       printf( "\ndata %d bytes\n", dbuf.dsize);
+       printf( "\ndata %d bytes\n", (int)dbuf.dsize);
        printf( "pid    =%5d   ", ((connections_data*)dbuf.dptr)->pid);
        printf( "cnum   =%10d  ", ((connections_data*)dbuf.dptr)->cnum);
        printf( "name   =[%s]\n", ((connections_data*)dbuf.dptr)->name);
@@ -373,16 +373,16 @@ static int print_crec(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *s
 
 static int print_arec(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
 {
-       printf("\nkey %d bytes\n", key.dsize);
+       printf("\nkey %d bytes\n", (int)key.dsize);
        print_asc(key.dptr, key.dsize);
-       printf("\ndata %d bytes\n", dbuf.dsize);
+       printf("\ndata %d bytes\n", (int)dbuf.dsize);
        print_data(dbuf.dptr, dbuf.dsize);
        return 0;
 }
 
 static int print_key(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
 {
-       printf("key %d bytes: ", key.dsize);
+       printf("key %d bytes: ", (int)key.dsize);
        print_asc(key.dptr, key.dsize);
        printf("\n");
        return 0;
@@ -390,7 +390,7 @@ static int print_key(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *st
 
 static int print_hexkey(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state)
 {
-       printf("key %d bytes\n", key.dsize);
+       printf("key %d bytes\n", (int)key.dsize);
        print_data(key.dptr, key.dsize);
        printf("\n");
        return 0;
index 47f1bb2dc24d5df46d737dc1004d925063336a9a..e27880e5ea051ab71090e425466bfa3d3dce66c9 100644 (file)
@@ -566,7 +566,12 @@ int tdb_unpack(char *buf, int bufsize, const char *fmt, ...)
                        p = va_arg(ap, void **);
                        if (bufsize < len)
                                goto no_space;
-                       *p = (void *)IVAL(buf, 0);
+                       /* 
+                        * This isn't a real pointer - only a token (1 or 0)
+                        * to mark the fact a pointer is present.
+                        */
+
+                       *p = (void *)(IVAL(buf, 0) ? (void *)1 : NULL);
                        break;
                case 'P':
                        s = va_arg(ap,char *);
index d0b502c74e722f71f5027026840e07197fcee79a..fc180bfafe22513d35e6f096967c68dc10051031 100644 (file)
@@ -133,12 +133,12 @@ static BOOL try_unlock(struct cli_state *c, int fstype,
        return False;
 }      
 
-static void print_brl(SMB_DEV_T dev, SMB_INO_T ino, int pid, 
+static void print_brl(SMB_DEV_T dev, SMB_INO_T ino, struct process_id pid, 
                      enum brl_type lock_type,
                      br_off start, br_off size)
 {
        printf("%6d   %05x:%05x    %s  %.0f:%.0f(%.0f)\n", 
-              (int)pid, (int)dev, (int)ino, 
+              (int)procid_to_pid(&pid), (int)dev, (int)ino, 
               lock_type==READ_LOCK?"R":"W",
               (double)start, (double)start+size-1,(double)size);
 
index df0855d93d71e8784568dc63dd63323efc71f025..9ce6afa038f3d5b6e24957cd6b754e73329a4b9c 100644 (file)
@@ -98,7 +98,7 @@ static BOOL test_one(struct cli_state *cli, const char *name)
        } else {
                TDB_DATA namedata;
                /* store it for later */
-               namedata.dptr = name;
+               namedata.dptr = CONST_DISCARD(char *, name);
                namedata.dsize = strlen(name)+1;
                tdb_store_bystring(tdb, shortname, namedata, TDB_REPLACE);
        }
index ac55d703276f9a812238b5042a58889a6ca55f15..d691ab32f1db7e7574ca645a0f27f1e6f3b702ef 100644 (file)
@@ -28,7 +28,7 @@ static int pong_count;
 /****************************************************************************
 a useful function for testing the message system
 ****************************************************************************/
-void pong_message(int msg_type, pid_t src, void *buf, size_t len)
+void pong_message(int msg_type, struct process_id src, void *buf, size_t len)
 {
        pong_count++;
 }
@@ -56,7 +56,7 @@ void pong_message(int msg_type, pid_t src, void *buf, size_t len)
        message_register(MSG_PONG, pong_message);
 
        for (i=0;i<n;i++) {
-               message_send_pid(pid, MSG_PING, NULL, 0, True);
+               message_send_pid(pid_to_procid(pid), MSG_PING, NULL, 0, True);
        }
 
        while (pong_count < i) {
@@ -70,8 +70,10 @@ void pong_message(int msg_type, pid_t src, void *buf, size_t len)
        safe_strcpy(buf, "1234567890", sizeof(buf)-1);
 
        for (i=0;i<n;i++) {
-               message_send_pid(getpid(), MSG_PING, NULL, 0, False);
-               message_send_pid(getpid(), MSG_PING, buf, 11, False);
+               message_send_pid(pid_to_procid(getpid()), MSG_PING,
+                                NULL, 0, False);
+               message_send_pid(pid_to_procid(getpid()), MSG_PING,
+                                buf, 11, False);
        }
 
        for (i=0;i<n;i++) {
diff --git a/source3/torture/t_asn1.c b/source3/torture/t_asn1.c
new file mode 100644 (file)
index 0000000..98ee7ba
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2004 by Volker Lendecke
+ *
+ * Test harness for asn1_write_*, inspired by Love Hornquist Astrand
+ */
+
+#include "includes.h"
+
+static DATA_BLOB tests[] = {
+        {"\x02\x01\x00", 3, NULL},
+        {"\x02\x01\x7f", 3, NULL},
+        {"\x02\x02\x00\x80", 4, NULL},
+        {"\x02\x02\x01\x00", 4, NULL},
+        {"\x02\x01\x80", 3, NULL},
+        {"\x02\x02\xff\x7f", 4, NULL},
+        {"\x02\x01\xff", 3, NULL},
+        {"\x02\x02\xff\x01", 4, NULL},
+        {"\x02\x02\x00\xff", 4, NULL},
+        {"\x02\x04\x80\x00\x00\x00", 6, NULL},
+        {"\x02\x04\x7f\xff\xff\xff", 6, NULL},
+       {NULL, 0, NULL}
+};
+
+static int values[] = {0, 127, 128, 256, -128, -129, -1, -255, 255,
+                      0x80000000, 0x7fffffff};
+
+int main(void)
+{
+       int i = 0;
+       int val;
+       BOOL ok = True;
+
+       for (i=0; tests[i].data != NULL; i++) {
+               ASN1_DATA data;
+               DATA_BLOB blob;
+
+               ZERO_STRUCT(data);
+               asn1_write_Integer(&data, values[i]);
+
+               if ((data.length != tests[i].length) ||
+                   (memcmp(data.data, tests[i].data, data.length) != 0)) {
+                       printf("Test for %d failed\n", values[i]);
+                       ok = False;
+               }
+
+               blob.data = data.data;
+               blob.length = data.length;
+               asn1_load(&data, blob);
+               if (!asn1_read_Integer(&data, &val)) {
+                       printf("Could not read our own Integer for %d\n",
+                              values[i]);
+                       ok = False;
+               }
+               if (val != values[i]) {
+                       printf("%d -> ASN -> Int %d\n", values[i], val);
+                       ok = False;
+               }
+       }
+
+       return ok ? 0 : 1;
+}
diff --git a/source3/torture/t_strappend.c b/source3/torture/t_strappend.c
new file mode 100644 (file)
index 0000000..becc691
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2005 by Volker Lendecke
+ *
+ * Test harness for sprintf_append
+ */
+
+#include "includes.h"
+#include <assert.h>
+
+int main(int argc, char *argv[])
+{
+       TALLOC_CTX *mem_ctx;
+       char *string = NULL;
+       int len = 0;
+       int bufsize = 4;
+       int i;
+
+       mem_ctx = talloc_init("t_strappend");
+       if (mem_ctx == NULL) {
+               fprintf(stderr, "talloc_init failed\n");
+               return 1;
+       }
+
+       sprintf_append(mem_ctx, &string, &len, &bufsize, "");
+       assert(strlen(string) == len);
+       sprintf_append(mem_ctx, &string, &len, &bufsize, "");
+       assert(strlen(string) == len);
+       sprintf_append(mem_ctx, &string, &len, &bufsize,
+                      "01234567890123456789012345678901234567890123456789\n");
+       assert(strlen(string) == len);
+
+
+       for (i=0; i<(100000); i++) {
+               if (i%1000 == 0) {
+                       printf("%d %d\r", i, bufsize);
+                       fflush(stdout);
+               }
+               sprintf_append(mem_ctx, &string, &len, &bufsize, "%d\n", i);
+               assert(strlen(string) == len);
+       }
+
+       talloc_destroy(mem_ctx);
+
+       return 0;
+}
index 11cea53188f628013445863c0150a3540d8c8970..8ad567f17781c79682298d1317346afe43c2b3a7 100644 (file)
@@ -698,7 +698,6 @@ static BOOL run_netbench(int client)
 {
        struct cli_state *cli;
        int i;
-       fstring fname;
        pstring line;
        char cname[20];
        FILE *f;
index 69acd01c1a42be54bc6e4fdfcf7f839fba847b37..b5ccf930bc6a7c758387d0cb0aca5b9db98b81ee 100644 (file)
@@ -38,7 +38,7 @@ extern pstring user_socket_options;
 /****************************************************************************
 handle completion of commands for readline
 ****************************************************************************/
-static char **completion_fn(char *text, int start, int end)
+static char **completion_fn(const char *text, int start, int end)
 {
 #define MAX_COMPLETIONS 100
        char **matches;
index d07dc2a2115dd86cd0dce72509323a9e3fe202b2..24412cbe85e23d353d633925e0cb5754d3a127ee 100644 (file)
@@ -200,7 +200,7 @@ void read_log_msg(FILE *in, unsigned char **_buffer, long *buffersize, long *dat
 long read_log_data(FILE *in, unsigned char *buffer, long data_length)
 {
        long i, addr; char real[2][16]; int ret;
-       unsigned char tmp;
+       unsigned int tmp;
        for(i = 0; i < data_length; i++) {
                if(i % 16 == 0){
                        if(i != 0) { /* Read data after each line */
@@ -213,7 +213,7 @@ long read_log_data(FILE *in, unsigned char *buffer, long data_length)
                        }
                        assert(addr == i);
                }
-               if(!fscanf(in, "%02lX", &tmp)) {
+               if(!fscanf(in, "%02X", &tmp)) {
                        if(!quiet)fprintf(stderr, "Only first %ld bytes are logged, packet trace will be incomplete\nTry a higher log level\n", i-1);
                        return i-1;
                }
@@ -230,7 +230,7 @@ int main (int argc, char **argv)
        poptContext pc;
        char buffer[4096];
        long data_offset, data_length;
-       long data_bytes_read;
+       long data_bytes_read = 0;
        int in_packet = 0;
        struct poptOption long_options[] = {
                POPT_AUTOHELP
index e9332f58f7b9bcdea8dfa4504e6678fdac453228..4d9dec4b85b81cd046a2ea161bc98d9608327238 100644 (file)
@@ -219,36 +219,39 @@ NTSTATUS connect_to_ipc_anonymous(struct cli_state **c,
  *
  * @return Normal NTSTATUS return.
  **/
-NTSTATUS connect_dst_pipe(struct cli_state **cli_dst, int pipe_num, BOOL *got_pipe)
+NTSTATUS connect_dst_pipe(struct cli_state **cli_dst, struct rpc_pipe_client **pp_pipe_hnd, int pipe_num)
 {
        NTSTATUS nt_status;
        char *server_name = SMB_STRDUP("127.0.0.1");
        struct cli_state *cli_tmp = NULL;
+       struct rpc_pipe_client *pipe_hnd = NULL;
 
        if (opt_destination)
                server_name = SMB_STRDUP(opt_destination);
 
        /* make a connection to a named pipe */
        nt_status = connect_to_ipc(&cli_tmp, NULL, server_name);
-       if (!NT_STATUS_IS_OK(nt_status)) 
+       if (!NT_STATUS_IS_OK(nt_status)) {
                return nt_status;
+       }
 
-       if (!cli_nt_session_open(cli_tmp, pipe_num)) {
+       pipe_hnd = cli_rpc_pipe_open_noauth(cli_tmp, pipe_num, &nt_status);
+       if (!pipe_hnd) {
                DEBUG(0, ("couldn't not initialize pipe\n"));
                cli_shutdown(cli_tmp);
-               return NT_STATUS_UNSUCCESSFUL;
+               return nt_status;
        }
 
        *cli_dst = cli_tmp;
-       *got_pipe = True;
+       *pp_pipe_hnd = pipe_hnd;
 
        return nt_status;
 }
 
-
 /****************************************************************************
- Use the local machine's password for this session
+ Use the local machine's password for this session.
 ****************************************************************************/
+
 int net_use_machine_password(void) 
 {
        char *user_name = NULL;
index a2df6596b470b1d07cd948e23a4007eb84d48478..2df13cfb8f1248d85e0ded24ba8ac10148d23f83 100644 (file)
  * include
  */
 
-typedef NTSTATUS (*rpc_command_fn)(const DOM_SID *, const char *, 
-                                  struct cli_state *, TALLOC_CTX *, int, const char **);
-                                  
+typedef NTSTATUS (*rpc_command_fn)(const DOM_SID *,
+                               const char *, 
+                               struct cli_state *cli,
+                               struct rpc_pipe_client *,
+                               TALLOC_CTX *,
+                               int,
+                               const char **);
+
 typedef struct copy_clistate {
        TALLOC_CTX *mem_ctx;
        struct cli_state *cli_share_src;
        struct cli_state *cli_share_dst;
        char *cwd;
        uint16 attribute;
-}copy_clistate; 
+}copy_clistate;
 
 /* INCLUDE FILES */
 
index 6a58fa9fac4934e4c268dee1a800bfe96573ac5d..49a7f1cc2ddf7f4ad49af9bd556b5f72fa1223cd 100644 (file)
@@ -969,7 +969,8 @@ static int net_ads_printer_info(int argc, const char **argv)
        return 0;
 }
 
-void do_drv_upgrade_printer(int msg_type, pid_t src, void *buf, size_t len)
+void do_drv_upgrade_printer(int msg_type, struct process_id src,
+                           void *buf, size_t len)
 {
        return;
 }
@@ -980,6 +981,7 @@ static int net_ads_printer_publish(int argc, const char **argv)
         ADS_STATUS rc;
        const char *servername, *printername;
        struct cli_state *cli;
+       struct rpc_pipe_client *pipe_hnd;
        struct in_addr          server_ip;
        NTSTATUS nt_status;
        TALLOC_CTX *mem_ctx = talloc_init("net_ads_printer_publish");
@@ -1038,8 +1040,9 @@ static int net_ads_printer_publish(int argc, const char **argv)
 
        asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn[0], printername, srv_dn);
 
-       cli_nt_session_open(cli, PI_SPOOLSS);
-       get_remote_printer_publishing_data(cli, mem_ctx, &mods, printername);
+       pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_SPOOLSS, &nt_status);
+       get_remote_printer_publishing_data(pipe_hnd, mem_ctx, &mods,
+                                          printername);
 
         rc = ads_add_printer_entry(ads, prt_dn, mem_ctx, &mods);
         if (!ADS_ERR_OK(rc)) {
index e80e8e6f5c05b1c9360a503967c70539ed3e1968..f1522ef158297b248923fa0e800a810f0d08979c 100644 (file)
@@ -4,6 +4,7 @@
    Copyright (C) 2001 Andrew Bartlett (abartlet@samba.org)
    Copyright (C) 2002 Jim McDonough (jmcd@us.ibm.com)
    Copyright (C) 2004 Guenther Deschner (gd@samba.org)
+   Copyright (C) 2005 Jeremy Allison (jra@samba.org)
 
    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
@@ -50,24 +51,26 @@ static int net_mode_share;
 
 static DOM_SID *net_get_remote_domain_sid(struct cli_state *cli, TALLOC_CTX *mem_ctx, char **domain_name)
 {
+       struct rpc_pipe_client *lsa_pipe;
        DOM_SID *domain_sid;
        POLICY_HND pol;
        NTSTATUS result = NT_STATUS_OK;
        uint32 info_class = 5;
        
-       if (!cli_nt_session_open (cli, PI_LSARPC)) {
+       lsa_pipe = cli_rpc_pipe_open_noauth(cli, PI_LSARPC, &result);
+       if (!lsa_pipe) {
                fprintf(stderr, "could not initialise lsa pipe\n");
                goto error;
        }
        
-       result = cli_lsa_open_policy(cli, mem_ctx, False, 
+       result = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, False, 
                                     SEC_RIGHTS_MAXIMUM_ALLOWED,
                                     &pol);
        if (!NT_STATUS_IS_OK(result)) {
                goto error;
        }
 
-       result = cli_lsa_query_info_policy(cli, mem_ctx, &pol, info_class, 
+       result = rpccli_lsa_query_info_policy(lsa_pipe, mem_ctx, &pol, info_class, 
                                           domain_name, &domain_sid);
        if (!NT_STATUS_IS_OK(result)) {
  error:
@@ -80,8 +83,10 @@ static DOM_SID *net_get_remote_domain_sid(struct cli_state *cli, TALLOC_CTX *mem
                exit(1);
        }
 
-       cli_lsa_close(cli, mem_ctx, &pol);
-       cli_nt_session_close(cli);
+       if (lsa_pipe) {
+               rpccli_lsa_close(lsa_pipe, mem_ctx, &pol);
+               cli_rpc_pipe_close(lsa_pipe);
+       }
 
        return domain_sid;
 }
@@ -98,21 +103,26 @@ static DOM_SID *net_get_remote_domain_sid(struct cli_state *cli, TALLOC_CTX *mem
  * @return A shell status integer (0 for success)
  */
 
-int run_rpc_command(struct cli_state *cli_arg, const int pipe_idx, int conn_flags,
-                           rpc_command_fn fn,
-                           int argc, const char **argv) 
+int run_rpc_command(struct cli_state *cli_arg,
+                       const int pipe_idx,
+                       int conn_flags,
+                       rpc_command_fn fn,
+                       int argc,
+                       const char **argv) 
 {
        struct cli_state *cli = NULL;
+       struct rpc_pipe_client *pipe_hnd = NULL;
        TALLOC_CTX *mem_ctx;
        NTSTATUS nt_status;
        DOM_SID *domain_sid;
        char *domain_name;
 
        /* make use of cli_state handed over as an argument, if possible */
-       if (!cli_arg)
+       if (!cli_arg) {
                cli = net_make_ipc_connection(conn_flags);
-       else
+       } else {
                cli = cli_arg;
+       }
 
        if (!cli) {
                return -1;
@@ -129,14 +139,31 @@ int run_rpc_command(struct cli_state *cli_arg, const int pipe_idx, int conn_flag
        domain_sid = net_get_remote_domain_sid(cli, mem_ctx, &domain_name);
 
        if (!(conn_flags & NET_FLAGS_NO_PIPE)) {
-               if (!cli_nt_session_open(cli, pipe_idx)) {
-                       DEBUG(0, ("Could not initialise pipe\n"));
-                       cli_shutdown(cli);
-                       return -1;
+               if (lp_client_schannel() && (pipe_idx == PI_NETLOGON)) {
+                       /* Always try and create an schannel netlogon pipe. */
+                       pipe_hnd = cli_rpc_pipe_open_schannel(cli, pipe_idx,
+                                                       PIPE_AUTH_LEVEL_PRIVACY,
+                                                       domain_name,
+                                                       &nt_status);
+                       if (!pipe_hnd) {
+                               DEBUG(0, ("Could not initialise schannel netlogon pipe. Error was %s\n",
+                                       nt_errstr(nt_status) ));
+                               cli_shutdown(cli);
+                               return -1;
+                       }
+               } else {
+                       pipe_hnd = cli_rpc_pipe_open_noauth(cli, pipe_idx, &nt_status);
+                       if (!pipe_hnd) {
+                               DEBUG(0, ("Could not initialise pipe %s. Error was %s\n",
+                                       cli_get_pipe_name(pipe_idx),
+                                       nt_errstr(nt_status) ));
+                               cli_shutdown(cli);
+                               return -1;
+                       }
                }
        }
        
-       nt_status = fn(domain_sid, domain_name, cli, mem_ctx, argc, argv);
+       nt_status = fn(domain_sid, domain_name, cli, pipe_hnd, mem_ctx, argc, argv);
        
        if (!NT_STATUS_IS_OK(nt_status)) {
                DEBUG(1, ("rpc command function failed! (%s)\n", nt_errstr(nt_status)));
@@ -145,23 +172,20 @@ int run_rpc_command(struct cli_state *cli_arg, const int pipe_idx, int conn_flag
        }
                
        if (!(conn_flags & NET_FLAGS_NO_PIPE)) {
-               if (cli->pipes[cli->pipe_idx].fnum)
-                       cli_nt_session_close(cli);
+               if (pipe_hnd) {
+                       cli_rpc_pipe_close(pipe_hnd);
+               }
        }
 
        /* close the connection only if it was opened here */
-       if (!cli_arg)
+       if (!cli_arg) {
                cli_shutdown(cli);
+       }
        
        talloc_destroy(mem_ctx);
-
        return (!NT_STATUS_IS_OK(nt_status));
 }
 
-
-/****************************************************************************/
-
-
 /** 
  * Force a change of the trust acccount password.
  *
@@ -178,11 +202,16 @@ int run_rpc_command(struct cli_state *cli_arg, const int pipe_idx, int conn_flag
  * @return Normal NTSTATUS return.
  **/
 
-static NTSTATUS rpc_changetrustpw_internals(const DOM_SID *domain_sid, const char *domain_name, 
-                                           struct cli_state *cli, TALLOC_CTX *mem_ctx, 
-                                           int argc, const char **argv) {
+static NTSTATUS rpc_changetrustpw_internals(const DOM_SID *domain_sid,
+                                       const char *domain_name, 
+                                       struct cli_state *cli,
+                                       struct rpc_pipe_client *pipe_hnd,
+                                       TALLOC_CTX *mem_ctx, 
+                                       int argc,
+                                       const char **argv)
+{
        
-       return trust_pw_find_change_and_store_it(cli, mem_ctx, opt_target_workgroup);
+       return trust_pw_find_change_and_store_it(pipe_hnd, mem_ctx, opt_target_workgroup);
 }
 
 /** 
@@ -202,10 +231,6 @@ int net_rpc_changetrustpw(int argc, const char **argv)
                               argc, argv);
 }
 
-
-/****************************************************************************/
-
-
 /** 
  * Join a domain, the old way.
  *
@@ -226,16 +251,29 @@ int net_rpc_changetrustpw(int argc, const char **argv)
  * @return Normal NTSTATUS return.
  **/
 
-static NTSTATUS rpc_oldjoin_internals(const DOM_SID *domain_sid, const char *domain_name, 
-                                     struct cli_state *cli, 
-                                     TALLOC_CTX *mem_ctx, 
-                                     int argc, const char **argv) {
+static NTSTATUS rpc_oldjoin_internals(const DOM_SID *domain_sid,
+                                       const char *domain_name, 
+                                       struct cli_state *cli, 
+                                       struct rpc_pipe_client *pipe_hnd,
+                                       TALLOC_CTX *mem_ctx, 
+                                       int argc,
+                                       const char **argv)
+{
        
        fstring trust_passwd;
        unsigned char orig_trust_passwd_hash[16];
        NTSTATUS result;
        uint32 sec_channel_type;
 
+       pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_NETLOGON, &result);
+       if (!pipe_hnd) {
+               DEBUG(0,("rpc_oldjoin_internals: netlogon pipe open to machine %s failed. "
+                       "error was %s\n",
+                       cli->desthost,
+                       nt_errstr(result) ));
+               return result;
+       }
+
        /* 
           check what type of join - if the user want's to join as
           a BDC, the server must agree that we are a BDC.
@@ -258,7 +296,7 @@ static NTSTATUS rpc_oldjoin_internals(const DOM_SID *domain_sid, const char *dom
 
        E_md4hash(trust_passwd, orig_trust_passwd_hash);
 
-       result = trust_pw_change_and_store_it(cli, mem_ctx, opt_target_workgroup,
+       result = trust_pw_change_and_store_it(pipe_hnd, mem_ctx, opt_target_workgroup,
                                              orig_trust_passwd_hash,
                                              sec_channel_type);
 
@@ -287,7 +325,7 @@ static NTSTATUS rpc_oldjoin_internals(const DOM_SID *domain_sid, const char *dom
 static int net_rpc_perform_oldjoin(int argc, const char **argv)
 {
        return run_rpc_command(NULL, PI_NETLOGON, 
-                              NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC, 
+                              NET_FLAGS_NO_PIPE | NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC, 
                               rpc_oldjoin_internals,
                               argc, argv);
 }
@@ -356,8 +394,6 @@ int net_rpc_join(int argc, const char **argv)
        return net_rpc_join_newstyle(argc, argv);
 }
 
-
-
 /** 
  * display info about a rpc domain
  *
@@ -374,10 +410,13 @@ int net_rpc_join(int argc, const char **argv)
  * @return Normal NTSTATUS return.
  **/
 
-static NTSTATUS 
-rpc_info_internals(const DOM_SID *domain_sid, const char *domain_name, 
-                  struct cli_state *cli,
-                  TALLOC_CTX *mem_ctx, int argc, const char **argv)
+static NTSTATUS rpc_info_internals(const DOM_SID *domain_sid,
+                       const char *domain_name, 
+                       struct cli_state *cli,
+                       struct rpc_pipe_client *pipe_hnd,
+                       TALLOC_CTX *mem_ctx,
+                       int argc,
+                       const char **argv)
 {
        POLICY_HND connect_pol, domain_pol;
        NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
@@ -387,14 +426,14 @@ rpc_info_internals(const DOM_SID *domain_sid, const char *domain_name,
        sid_to_string(sid_str, domain_sid);
 
        /* Get sam policy handle */     
-       result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
+       result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
                                  &connect_pol);
        if (!NT_STATUS_IS_OK(result)) {
                goto done;
        }
        
        /* Get domain policy handle */
-       result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
+       result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
                                      MAXIMUM_ALLOWED_ACCESS,
                                      domain_sid, &domain_pol);
        if (!NT_STATUS_IS_OK(result)) {
@@ -402,7 +441,7 @@ rpc_info_internals(const DOM_SID *domain_sid, const char *domain_name,
        }
 
        ZERO_STRUCT(ctr);
-       result = cli_samr_query_dom_info(cli, mem_ctx, &domain_pol,
+       result = rpccli_samr_query_dom_info(pipe_hnd, mem_ctx, &domain_pol,
                                         2, &ctr);
        if (NT_STATUS_IS_OK(result)) {
                TALLOC_CTX *ctx = talloc_init("rpc_info_internals");
@@ -419,13 +458,13 @@ rpc_info_internals(const DOM_SID *domain_sid, const char *domain_name,
        return result;
 }
 
-
 /** 
  * 'net rpc info' entrypoint.
  * @param argc  Standard main() style argc
  * @param argc  Standard main() style argv.  Initial components are already
  *              stripped
  **/
+
 int net_rpc_info(int argc, const char **argv) 
 {
        return run_rpc_command(NULL, PI_SAMR, NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC, 
@@ -433,7 +472,6 @@ int net_rpc_info(int argc, const char **argv)
                               argc, argv);
 }
 
-
 /** 
  * Fetch domain SID into the local secrets.tdb
  *
@@ -450,10 +488,13 @@ int net_rpc_info(int argc, const char **argv)
  * @return Normal NTSTATUS return.
  **/
 
-static NTSTATUS 
-rpc_getsid_internals(const DOM_SID *domain_sid, const char *domain_name, 
-                    struct cli_state *cli,
-                    TALLOC_CTX *mem_ctx, int argc, const char **argv)
+static NTSTATUS rpc_getsid_internals(const DOM_SID *domain_sid,
+                       const char *domain_name, 
+                       struct cli_state *cli,
+                       struct rpc_pipe_client *pipe_hnd,
+                       TALLOC_CTX *mem_ctx,
+                       int argc,
+                       const char **argv)
 {
        fstring sid_str;
 
@@ -469,13 +510,13 @@ rpc_getsid_internals(const DOM_SID *domain_sid, const char *domain_name,
        return NT_STATUS_OK;
 }
 
-
 /** 
  * 'net rpc getsid' entrypoint.
  * @param argc  Standard main() style argc
  * @param argc  Standard main() style argv.  Initial components are already
  *              stripped
  **/
+
 int net_rpc_getsid(int argc, const char **argv) 
 {
        return run_rpc_command(NULL, PI_SAMR, NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC, 
@@ -483,7 +524,6 @@ int net_rpc_getsid(int argc, const char **argv)
                               argc, argv);
 }
 
-
 /****************************************************************************/
 
 /**
@@ -514,9 +554,13 @@ static int rpc_user_usage(int argc, const char **argv)
  * @return Normal NTSTATUS return.
  **/
 
-static NTSTATUS rpc_user_add_internals(const DOM_SID *domain_sid, const char *domain_name, 
-                                      struct cli_state *cli, TALLOC_CTX *mem_ctx, 
-                                      int argc, const char **argv) {
+static NTSTATUS rpc_user_add_internals(const DOM_SID *domain_sid,
+                               const char *domain_name, 
+                               struct cli_state *cli,
+                               struct rpc_pipe_client *pipe_hnd,
+                               TALLOC_CTX *mem_ctx, 
+                               int argc, const char **argv)
+{
        
        POLICY_HND connect_pol, domain_pol, user_pol;
        NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
@@ -534,7 +578,7 @@ static NTSTATUS rpc_user_add_internals(const DOM_SID *domain_sid, const char *do
 
        /* Get sam policy handle */
        
-       result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
+       result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
                                  &connect_pol);
        if (!NT_STATUS_IS_OK(result)) {
                goto done;
@@ -542,7 +586,7 @@ static NTSTATUS rpc_user_add_internals(const DOM_SID *domain_sid, const char *do
        
        /* Get domain policy handle */
        
-       result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
+       result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
                                      MAXIMUM_ALLOWED_ACCESS,
                                      domain_sid, &domain_pol);
        if (!NT_STATUS_IS_OK(result)) {
@@ -554,7 +598,7 @@ static NTSTATUS rpc_user_add_internals(const DOM_SID *domain_sid, const char *do
        acb_info = ACB_NORMAL;
        unknown = 0xe005000b; /* No idea what this is - a permission mask? */
 
-       result = cli_samr_create_dom_user(cli, mem_ctx, &domain_pol,
+       result = rpccli_samr_create_dom_user(pipe_hnd, mem_ctx, &domain_pol,
                                          acct_name, acb_info, unknown,
                                          &user_pol, &user_rid);
        if (!NT_STATUS_IS_OK(result)) {
@@ -604,10 +648,12 @@ static int rpc_user_add(int argc, const char **argv)
  **/
 
 static NTSTATUS rpc_user_del_internals(const DOM_SID *domain_sid, 
-                                      const char *domain_name, 
-                                      struct cli_state *cli, 
-                                      TALLOC_CTX *mem_ctx, 
-                                      int argc, const char **argv)
+                                       const char *domain_name, 
+                                       struct cli_state *cli, 
+                                       struct rpc_pipe_client *pipe_hnd,
+                                       TALLOC_CTX *mem_ctx, 
+                                       int argc,
+                                       const char **argv)
 {
        NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
        POLICY_HND connect_pol, domain_pol, user_pol;
@@ -619,14 +665,14 @@ static NTSTATUS rpc_user_del_internals(const DOM_SID *domain_sid,
        }
        /* Get sam policy and domain handles */
 
-       result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
+       result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
                                  &connect_pol);
 
        if (!NT_STATUS_IS_OK(result)) {
                goto done;
        }
 
-       result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
+       result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
                                      MAXIMUM_ALLOWED_ACCESS,
                                      domain_sid, &domain_pol);
 
@@ -640,7 +686,7 @@ static NTSTATUS rpc_user_del_internals(const DOM_SID *domain_sid,
                uint32 *user_rids, num_rids, *name_types;
                uint32 flags = 0x000003e8; /* Unknown */
 
-               result = cli_samr_lookup_names(cli, mem_ctx, &domain_pol,
+               result = rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol,
                                               flags, 1, &argv[0],
                                               &num_rids, &user_rids,
                                               &name_types);
@@ -649,7 +695,7 @@ static NTSTATUS rpc_user_del_internals(const DOM_SID *domain_sid,
                        goto done;
                }
 
-               result = cli_samr_open_user(cli, mem_ctx, &domain_pol,
+               result = rpccli_samr_open_user(pipe_hnd, mem_ctx, &domain_pol,
                                            MAXIMUM_ALLOWED_ACCESS,
                                            user_rids[0], &user_pol);
 
@@ -660,23 +706,22 @@ static NTSTATUS rpc_user_del_internals(const DOM_SID *domain_sid,
 
        /* Delete user */
 
-       result = cli_samr_delete_dom_user(cli, mem_ctx, &user_pol);
+       result = rpccli_samr_delete_dom_user(pipe_hnd, mem_ctx, &user_pol);
 
        if (!NT_STATUS_IS_OK(result)) {
                goto done;
        }
 
        /* Display results */
-    if (!NT_STATUS_IS_OK(result)) {
+       if (!NT_STATUS_IS_OK(result)) {
                d_printf("Failed to delete user account - %s\n", nt_errstr(result));
-    } else {
-        d_printf("Deleted user account\n");
-    }
+       } else {
+               d_printf("Deleted user account\n");
+       }
 
  done:
        return result;
-
-}      
+}
 
 /** 
  * Rename a user on a remote RPC server
@@ -694,10 +739,14 @@ static NTSTATUS rpc_user_del_internals(const DOM_SID *domain_sid,
  * @return Normal NTSTATUS return.
  **/
 
-static NTSTATUS rpc_user_rename_internals(const DOM_SID *domain_sid, const char *domain_name, 
-                                         struct cli_state *cli, TALLOC_CTX *mem_ctx, 
-                                         int argc, const char **argv) {
-       
+static NTSTATUS rpc_user_rename_internals(const DOM_SID *domain_sid,
+                                       const char *domain_name, 
+                                       struct cli_state *cli,
+                                       struct rpc_pipe_client *pipe_hnd,
+                                       TALLOC_CTX *mem_ctx, 
+                                       int argc,
+                                       const char **argv)
+{
        POLICY_HND connect_pol, domain_pol, user_pol;
        NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
        uint32 info_level = 7;
@@ -725,7 +774,7 @@ static NTSTATUS rpc_user_rename_internals(const DOM_SID *domain_sid, const char
 
        /* Get sam policy handle */
        
-       result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
+       result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
                                  &connect_pol);
        if (!NT_STATUS_IS_OK(result)) {
                goto done;
@@ -733,7 +782,7 @@ static NTSTATUS rpc_user_rename_internals(const DOM_SID *domain_sid, const char
        
        /* Get domain policy handle */
        
-       result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
+       result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
                                      MAXIMUM_ALLOWED_ACCESS,
                                      domain_sid, &domain_pol);
        if (!NT_STATUS_IS_OK(result)) {
@@ -742,7 +791,7 @@ static NTSTATUS rpc_user_rename_internals(const DOM_SID *domain_sid, const char
 
        names = TALLOC_ARRAY(mem_ctx, const char *, num_names);
        names[0] = old_name;
-       result = cli_samr_lookup_names(cli, mem_ctx, &domain_pol,
+       result = rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol,
                                       flags, num_names, names,
                                       &num_rids, &user_rid, &name_types);
        if (!NT_STATUS_IS_OK(result)) {
@@ -750,7 +799,7 @@ static NTSTATUS rpc_user_rename_internals(const DOM_SID *domain_sid, const char
        }
 
        /* Open domain user */
-       result = cli_samr_open_user(cli, mem_ctx, &domain_pol,
+       result = rpccli_samr_open_user(pipe_hnd, mem_ctx, &domain_pol,
                                    MAXIMUM_ALLOWED_ACCESS, user_rid[0], &user_pol);
 
        if (!NT_STATUS_IS_OK(result)) {
@@ -758,7 +807,7 @@ static NTSTATUS rpc_user_rename_internals(const DOM_SID *domain_sid, const char
        }
 
        /* Query user info */
-       result = cli_samr_query_userinfo(cli, mem_ctx, &user_pol,
+       result = rpccli_samr_query_userinfo(pipe_hnd, mem_ctx, &user_pol,
                                         info_level, &user_ctr);
 
        if (!NT_STATUS_IS_OK(result)) {
@@ -771,7 +820,7 @@ static NTSTATUS rpc_user_rename_internals(const DOM_SID *domain_sid, const char
        init_sam_user_info7(&info7, new_name);
 
        /* Set new name */
-       result = cli_samr_set_userinfo(cli, mem_ctx, &user_pol,
+       result = rpccli_samr_set_userinfo(pipe_hnd, mem_ctx, &user_pol,
                                       info_level, &cli->user_session_key, &ctr);
 
        if (!NT_STATUS_IS_OK(result)) {
@@ -788,7 +837,6 @@ static NTSTATUS rpc_user_rename_internals(const DOM_SID *domain_sid, const char
        return result;
 }
 
-
 /** 
  * Rename a user on a remote RPC server
  *
@@ -838,10 +886,12 @@ static int rpc_user_delete(int argc, const char **argv)
  **/
 
 static NTSTATUS rpc_user_password_internals(const DOM_SID *domain_sid, 
-                                           const char *domain_name, 
-                                           struct cli_state *cli, 
-                                           TALLOC_CTX *mem_ctx, 
-                                           int argc, const char **argv)
+                                       const char *domain_name, 
+                                       struct cli_state *cli, 
+                                       struct rpc_pipe_client *pipe_hnd,
+                                       TALLOC_CTX *mem_ctx, 
+                                       int argc,
+                                       const char **argv)
 {
        NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
        POLICY_HND connect_pol, domain_pol, user_pol;
@@ -870,14 +920,14 @@ static NTSTATUS rpc_user_password_internals(const DOM_SID *domain_sid,
 
        /* Get sam policy and domain handles */
 
-       result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
+       result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
                                  &connect_pol);
 
        if (!NT_STATUS_IS_OK(result)) {
                goto done;
        }
 
-       result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
+       result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
                                      MAXIMUM_ALLOWED_ACCESS,
                                      domain_sid, &domain_pol);
 
@@ -891,7 +941,7 @@ static NTSTATUS rpc_user_password_internals(const DOM_SID *domain_sid,
                uint32 *user_rids, num_rids, *name_types;
                uint32 flags = 0x000003e8; /* Unknown */
 
-               result = cli_samr_lookup_names(cli, mem_ctx, &domain_pol,
+               result = rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol,
                                               flags, 1, &user,
                                               &num_rids, &user_rids,
                                               &name_types);
@@ -900,7 +950,7 @@ static NTSTATUS rpc_user_password_internals(const DOM_SID *domain_sid,
                        goto done;
                }
 
-               result = cli_samr_open_user(cli, mem_ctx, &domain_pol,
+               result = rpccli_samr_open_user(pipe_hnd, mem_ctx, &domain_pol,
                                            MAXIMUM_ALLOWED_ACCESS,
                                            user_rids[0], &user_pol);
 
@@ -921,7 +971,7 @@ static NTSTATUS rpc_user_password_internals(const DOM_SID *domain_sid,
        ctr.switch_value = 24;
        ctr.info.id24 = &p24;
 
-       result = cli_samr_set_userinfo(cli, mem_ctx, &user_pol, 24, 
+       result = rpccli_samr_set_userinfo(pipe_hnd, mem_ctx, &user_pol, 24, 
                                       &cli->user_session_key, &ctr);
 
        if (!NT_STATUS_IS_OK(result)) {
@@ -967,10 +1017,13 @@ static int rpc_user_password(int argc, const char **argv)
  * @return Normal NTSTATUS return.
  **/
 
-static NTSTATUS 
-rpc_user_info_internals(const DOM_SID *domain_sid, const char *domain_name, 
+static NTSTATUS rpc_user_info_internals(const DOM_SID *domain_sid,
+                       const char *domain_name, 
                        struct cli_state *cli,
-                       TALLOC_CTX *mem_ctx, int argc, const char **argv)
+                       struct rpc_pipe_client *pipe_hnd,
+                       TALLOC_CTX *mem_ctx,
+                       int argc,
+                       const char **argv)
 {
        POLICY_HND connect_pol, domain_pol, user_pol;
        NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
@@ -987,31 +1040,31 @@ rpc_user_info_internals(const DOM_SID *domain_sid, const char *domain_name,
        }
        /* Get sam policy handle */
        
-       result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
+       result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
                                  &connect_pol);
        if (!NT_STATUS_IS_OK(result)) goto done;
        
        /* Get domain policy handle */
        
-       result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
+       result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
                                      MAXIMUM_ALLOWED_ACCESS,
                                      domain_sid, &domain_pol);
        if (!NT_STATUS_IS_OK(result)) goto done;
 
        /* Get handle on user */
 
-       result = cli_samr_lookup_names(cli, mem_ctx, &domain_pol,
+       result = rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol,
                                       flags, 1, &argv[0],
                                       &num_rids, &rids, &name_types);
 
        if (!NT_STATUS_IS_OK(result)) goto done;
 
-       result = cli_samr_open_user(cli, mem_ctx, &domain_pol,
+       result = rpccli_samr_open_user(pipe_hnd, mem_ctx, &domain_pol,
                                    MAXIMUM_ALLOWED_ACCESS,
                                    rids[0], &user_pol);
        if (!NT_STATUS_IS_OK(result)) goto done;
 
-       result = cli_samr_query_usergroups(cli, mem_ctx, &user_pol,
+       result = rpccli_samr_query_usergroups(pipe_hnd, mem_ctx, &user_pol,
                                           &num_rids, &user_gids);
 
        if (!NT_STATUS_IS_OK(result)) goto done;
@@ -1024,7 +1077,7 @@ rpc_user_info_internals(const DOM_SID *domain_sid, const char *domain_name,
                for (i = 0; i < num_rids; i++)
                        rids[i] = user_gids[i].g_rid;
 
-               result = cli_samr_lookup_rids(cli, mem_ctx, &domain_pol,
+               result = rpccli_samr_lookup_rids(pipe_hnd, mem_ctx, &domain_pol,
                                              num_rids, rids,
                                              &num_names, &names, &name_types);
 
@@ -1073,10 +1126,13 @@ static int rpc_user_info(int argc, const char **argv)
  * @return Normal NTSTATUS return.
  **/
 
-static NTSTATUS 
-rpc_user_list_internals(const DOM_SID *domain_sid, const char *domain_name, 
-                       struct cli_state *cli,
-                       TALLOC_CTX *mem_ctx, int argc, const char **argv)
+static NTSTATUS rpc_user_list_internals(const DOM_SID *domain_sid,
+                                       const char *domain_name, 
+                                       struct cli_state *cli,
+                                       struct rpc_pipe_client *pipe_hnd,
+                                       TALLOC_CTX *mem_ctx,
+                                       int argc,
+                                       const char **argv)
 {
        POLICY_HND connect_pol, domain_pol;
        NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
@@ -1086,7 +1142,7 @@ rpc_user_list_internals(const DOM_SID *domain_sid, const char *domain_name,
 
        /* Get sam policy handle */
        
-       result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
+       result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
                                  &connect_pol);
        if (!NT_STATUS_IS_OK(result)) {
                goto done;
@@ -1094,7 +1150,7 @@ rpc_user_list_internals(const DOM_SID *domain_sid, const char *domain_name,
        
        /* Get domain policy handle */
        
-       result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
+       result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
                                      MAXIMUM_ALLOWED_ACCESS,
                                      domain_sid, &domain_pol);
        if (!NT_STATUS_IS_OK(result)) {
@@ -1115,7 +1171,7 @@ rpc_user_list_internals(const DOM_SID *domain_sid, const char *domain_name,
                get_query_dispinfo_params(
                        loop_count, &max_entries, &max_size);
 
-               result = cli_samr_query_dispinfo(cli, mem_ctx, &domain_pol,
+               result = rpccli_samr_query_dispinfo(pipe_hnd, mem_ctx, &domain_pol,
                                                 &start_idx, 1, &num_entries,
                                                 max_entries, max_size, &ctr);
                loop_count++;
@@ -1163,7 +1219,6 @@ int net_rpc_user(int argc, const char **argv)
        return net_run_function(argc, argv, func, rpc_user_usage);
 }
 
-
 /****************************************************************************/
 
 /**
@@ -1195,10 +1250,12 @@ static int rpc_group_usage(int argc, const char **argv)
  **/
                                                                                                              
 static NTSTATUS rpc_group_delete_internals(const DOM_SID *domain_sid,
-                                           const char *domain_name,
-                                           struct cli_state *cli,
-                                           TALLOC_CTX *mem_ctx,
-                                           int argc, const char **argv)
+                                       const char *domain_name,
+                                       struct cli_state *cli,
+                                       struct rpc_pipe_client *pipe_hnd,
+                                       TALLOC_CTX *mem_ctx,
+                                       int argc,
+                                       const char **argv)
 {
        POLICY_HND connect_pol, domain_pol, group_pol, user_pol;
        BOOL group_is_primary = False;
@@ -1219,7 +1276,7 @@ static NTSTATUS rpc_group_delete_internals(const DOM_SID *domain_sid,
                return NT_STATUS_OK; /* ok? */
        }
 
-        result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
+        result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
                                   &connect_pol);
 
         if (!NT_STATUS_IS_OK(result)) {
@@ -1227,7 +1284,7 @@ static NTSTATUS rpc_group_delete_internals(const DOM_SID *domain_sid,
                goto done;
         }
         
-        result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
+        result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
                                       MAXIMUM_ALLOWED_ACCESS,
                                       domain_sid, &domain_pol);
         
@@ -1236,7 +1293,7 @@ static NTSTATUS rpc_group_delete_internals(const DOM_SID *domain_sid,
                goto done;
         }
        
-       result = cli_samr_lookup_names(cli, mem_ctx, &domain_pol,
+       result = rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol,
                                       flags, 1, &argv[0],
                                       &num_rids, &group_rids,
                                       &name_types);
@@ -1249,7 +1306,7 @@ static NTSTATUS rpc_group_delete_internals(const DOM_SID *domain_sid,
        switch (name_types[0])
        {
        case SID_NAME_DOM_GRP:
-               result = cli_samr_open_group(cli, mem_ctx, &domain_pol,
+               result = rpccli_samr_open_group(pipe_hnd, mem_ctx, &domain_pol,
                                             MAXIMUM_ALLOWED_ACCESS,
                                             group_rids[0], &group_pol);
                if (!NT_STATUS_IS_OK(result)) {
@@ -1259,7 +1316,7 @@ static NTSTATUS rpc_group_delete_internals(const DOM_SID *domain_sid,
                 
                group_rid = group_rids[0];
                 
-               result = cli_samr_query_groupmem(cli, mem_ctx, &group_pol,
+               result = rpccli_samr_query_groupmem(pipe_hnd, mem_ctx, &group_pol,
                                  &num_members, &group_rids,
                                  &group_attrs);
                
@@ -1276,7 +1333,7 @@ static NTSTATUS rpc_group_delete_internals(const DOM_SID *domain_sid,
                /* Check if group is anyone's primary group */
                 for (i = 0; i < num_members; i++)
                {
-                       result = cli_samr_open_user(cli, mem_ctx, &domain_pol,
+                       result = rpccli_samr_open_user(pipe_hnd, mem_ctx, &domain_pol,
                                                    MAXIMUM_ALLOWED_ACCESS,
                                                    group_rids[i], &user_pol);
        
@@ -1287,7 +1344,7 @@ static NTSTATUS rpc_group_delete_internals(const DOM_SID *domain_sid,
        
                        ZERO_STRUCT(user_ctr);
 
-                       result = cli_samr_query_userinfo(cli, mem_ctx, &user_pol,
+                       result = rpccli_samr_query_userinfo(pipe_hnd, mem_ctx, &user_pol,
                                                         21, &user_ctr);
        
                        if (!NT_STATUS_IS_OK(result)) {
@@ -1303,7 +1360,7 @@ static NTSTATUS rpc_group_delete_internals(const DOM_SID *domain_sid,
                                group_is_primary = True;
                         }
 
-                       cli_samr_close(cli, mem_ctx, &user_pol);
+                       rpccli_samr_close(pipe_hnd, mem_ctx, &user_pol);
                }
                 
                if (group_is_primary) {
@@ -1318,7 +1375,7 @@ static NTSTATUS rpc_group_delete_internals(const DOM_SID *domain_sid,
                {
                        if (opt_verbose) 
                                d_printf("Remove group member %d...",group_rids[i]);
-                       result = cli_samr_del_groupmem(cli, mem_ctx, &group_pol, group_rids[i]);
+                       result = rpccli_samr_del_groupmem(pipe_hnd, mem_ctx, &group_pol, group_rids[i]);
 
                        if (NT_STATUS_IS_OK(result)) {
                                if (opt_verbose)
@@ -1330,12 +1387,12 @@ static NTSTATUS rpc_group_delete_internals(const DOM_SID *domain_sid,
                        }       
                }
 
-               result = cli_samr_delete_dom_group(cli, mem_ctx, &group_pol);
+               result = rpccli_samr_delete_dom_group(pipe_hnd, mem_ctx, &group_pol);
 
                break;
        /* removing a local group is easier... */
        case SID_NAME_ALIAS:
-               result = cli_samr_open_alias(cli, mem_ctx, &domain_pol,
+               result = rpccli_samr_open_alias(pipe_hnd, mem_ctx, &domain_pol,
                                             MAXIMUM_ALLOWED_ACCESS,
                                             group_rids[0], &group_pol);
 
@@ -1344,7 +1401,7 @@ static NTSTATUS rpc_group_delete_internals(const DOM_SID *domain_sid,
                        goto done;
                }
                
-               result = cli_samr_delete_dom_alias(cli, mem_ctx, &group_pol);
+               result = rpccli_samr_delete_dom_alias(pipe_hnd, mem_ctx, &group_pol);
                break;
        default:
                d_printf("%s is of type %s. This command is only for deleting local or global groups\n",
@@ -1373,10 +1430,13 @@ static int rpc_group_delete(int argc, const char **argv)
                                argc,argv);
 }
 
-static NTSTATUS 
-rpc_group_add_internals(const DOM_SID *domain_sid, const char *domain_name, 
-                       struct cli_state *cli,
-                       TALLOC_CTX *mem_ctx, int argc, const char **argv)
+static NTSTATUS rpc_group_add_internals(const DOM_SID *domain_sid,
+                                       const char *domain_name, 
+                                       struct cli_state *cli,
+                                       struct rpc_pipe_client *pipe_hnd,
+                                       TALLOC_CTX *mem_ctx,
+                                       int argc,
+                                       const char **argv)
 {
        POLICY_HND connect_pol, domain_pol, group_pol;
        NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
@@ -1390,20 +1450,20 @@ rpc_group_add_internals(const DOM_SID *domain_sid, const char *domain_name,
 
        /* Get sam policy handle */
        
-       result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
+       result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
                                  &connect_pol);
        if (!NT_STATUS_IS_OK(result)) goto done;
        
        /* Get domain policy handle */
        
-       result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
+       result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
                                      MAXIMUM_ALLOWED_ACCESS,
                                      domain_sid, &domain_pol);
        if (!NT_STATUS_IS_OK(result)) goto done;
 
        /* Create the group */
 
-       result = cli_samr_create_dom_group(cli, mem_ctx, &domain_pol,
+       result = rpccli_samr_create_dom_group(pipe_hnd, mem_ctx, &domain_pol,
                                           argv[0], MAXIMUM_ALLOWED_ACCESS,
                                           &group_pol);
        if (!NT_STATUS_IS_OK(result)) goto done;
@@ -1415,7 +1475,7 @@ rpc_group_add_internals(const DOM_SID *domain_sid, const char *domain_name,
        group_info.switch_value1 = 4;
        init_samr_group_info4(&group_info.group.info4, opt_comment);
 
-       result = cli_samr_set_groupinfo(cli, mem_ctx, &group_pol, &group_info);
+       result = rpccli_samr_set_groupinfo(pipe_hnd, mem_ctx, &group_pol, &group_info);
        if (!NT_STATUS_IS_OK(result)) goto done;
        
  done:
@@ -1427,10 +1487,13 @@ rpc_group_add_internals(const DOM_SID *domain_sid, const char *domain_name,
        return result;
 }
 
-static NTSTATUS 
-rpc_alias_add_internals(const DOM_SID *domain_sid, const char *domain_name, 
-                       struct cli_state *cli,
-                       TALLOC_CTX *mem_ctx, int argc, const char **argv)
+static NTSTATUS rpc_alias_add_internals(const DOM_SID *domain_sid,
+                                       const char *domain_name, 
+                                       struct cli_state *cli,
+                                       struct rpc_pipe_client *pipe_hnd,
+                                       TALLOC_CTX *mem_ctx,
+                                       int argc,
+                                       const char **argv)
 {
        POLICY_HND connect_pol, domain_pol, alias_pol;
        NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
@@ -1444,20 +1507,20 @@ rpc_alias_add_internals(const DOM_SID *domain_sid, const char *domain_name,
 
        /* Get sam policy handle */
        
-       result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
+       result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
                                  &connect_pol);
        if (!NT_STATUS_IS_OK(result)) goto done;
        
        /* Get domain policy handle */
        
-       result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
+       result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
                                      MAXIMUM_ALLOWED_ACCESS,
                                      domain_sid, &domain_pol);
        if (!NT_STATUS_IS_OK(result)) goto done;
 
        /* Create the group */
 
-       result = cli_samr_create_dom_alias(cli, mem_ctx, &domain_pol,
+       result = rpccli_samr_create_dom_alias(pipe_hnd, mem_ctx, &domain_pol,
                                           argv[0], &alias_pol);
        if (!NT_STATUS_IS_OK(result)) goto done;
 
@@ -1468,7 +1531,7 @@ rpc_alias_add_internals(const DOM_SID *domain_sid, const char *domain_name,
        alias_info.level = 3;
        init_samr_alias_info3(&alias_info.alias.info3, opt_comment);
 
-       result = cli_samr_set_aliasinfo(cli, mem_ctx, &alias_pol, &alias_info);
+       result = rpccli_samr_set_aliasinfo(pipe_hnd, mem_ctx, &alias_pol, &alias_info);
        if (!NT_STATUS_IS_OK(result)) goto done;
        
  done:
@@ -1492,33 +1555,31 @@ static int rpc_group_add(int argc, const char **argv)
                               argc, argv);
 }
 
-static NTSTATUS
-get_sid_from_name(struct cli_state *cli, TALLOC_CTX *mem_ctx, const char *name,
-                 DOM_SID *sid, enum SID_NAME_USE *type)
+static NTSTATUS get_sid_from_name(struct cli_state *cli,
+                               TALLOC_CTX *mem_ctx,
+                               const char *name,
+                               DOM_SID *sid,
+                               enum SID_NAME_USE *type)
 {
-       int current_pipe = cli->pipe_idx;
-
        DOM_SID *sids = NULL;
        uint32 *types = NULL;
+       struct rpc_pipe_client *pipe_hnd;
        POLICY_HND lsa_pol;
        NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
 
-       if (current_pipe != PI_LSARPC) {
-
-               if (current_pipe != -1)
-                       cli_nt_session_close(cli);
-
-               if (!cli_nt_session_open(cli, PI_LSARPC))
-                       goto done;
+       pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_LSARPC, &result);
+       if (!pipe_hnd) {
+               goto done;
        }
 
-       result = cli_lsa_open_policy(cli, mem_ctx, False,
+       result = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, False,
                                     SEC_RIGHTS_MAXIMUM_ALLOWED, &lsa_pol);
 
-       if (!NT_STATUS_IS_OK(result))
+       if (!NT_STATUS_IS_OK(result)) {
                goto done;
+       }
 
-       result = cli_lsa_lookup_names(cli, mem_ctx, &lsa_pol, 1,
+       result = rpccli_lsa_lookup_names(pipe_hnd, mem_ctx, &lsa_pol, 1,
                                      &name, &sids, &types);
 
        if (NT_STATUS_IS_OK(result)) {
@@ -1526,13 +1587,11 @@ get_sid_from_name(struct cli_state *cli, TALLOC_CTX *mem_ctx, const char *name,
                *type = types[0];
        }
 
-       cli_lsa_close(cli, mem_ctx, &lsa_pol);
+       rpccli_lsa_close(pipe_hnd, mem_ctx, &lsa_pol);
 
  done:
-       if (current_pipe != PI_LSARPC) {
-               cli_nt_session_close(cli);
-               if (current_pipe != -1)
-                       cli_nt_session_open(cli, current_pipe);
+       if (pipe_hnd) {
+               cli_rpc_pipe_close(pipe_hnd);
        }
 
        if (!NT_STATUS_IS_OK(result) && (StrnCaseCmp(name, "S-", 2) == 0)) {
@@ -1551,9 +1610,10 @@ get_sid_from_name(struct cli_state *cli, TALLOC_CTX *mem_ctx, const char *name,
        return result;
 }
 
-static NTSTATUS
-rpc_add_groupmem(struct cli_state *cli, TALLOC_CTX *mem_ctx,
-                const DOM_SID *group_sid, const char *member)
+static NTSTATUS rpc_add_groupmem(struct rpc_pipe_client *pipe_hnd,
+                               TALLOC_CTX *mem_ctx,
+                               const DOM_SID *group_sid,
+                               const char *member)
 {
        POLICY_HND connect_pol, domain_pol;
        NTSTATUS result;
@@ -1568,23 +1628,26 @@ rpc_add_groupmem(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 
        sid_copy(&sid, group_sid);
 
-       if (!sid_split_rid(&sid, &group_rid))
+       if (!sid_split_rid(&sid, &group_rid)) {
                return NT_STATUS_UNSUCCESSFUL;
+       }
 
        /* Get sam policy handle */     
-       result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
+       result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
                                  &connect_pol);
-       if (!NT_STATUS_IS_OK(result))
+       if (!NT_STATUS_IS_OK(result)) {
                return result;
+       }
        
        /* Get domain policy handle */
-       result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
+       result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
                                      MAXIMUM_ALLOWED_ACCESS,
                                      &sid, &domain_pol);
-       if (!NT_STATUS_IS_OK(result))
+       if (!NT_STATUS_IS_OK(result)) {
                return result;
+       }
 
-       result = cli_samr_lookup_names(cli, mem_ctx, &domain_pol, 1000,
+       result = rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol, 1000,
                                       1, &member,
                                       &num_rids, &rids, &rid_types);
 
@@ -1593,23 +1656,25 @@ rpc_add_groupmem(struct cli_state *cli, TALLOC_CTX *mem_ctx,
                goto done;
        }
 
-       result = cli_samr_open_group(cli, mem_ctx, &domain_pol,
+       result = rpccli_samr_open_group(pipe_hnd, mem_ctx, &domain_pol,
                                     MAXIMUM_ALLOWED_ACCESS,
                                     group_rid, &group_pol);
 
-       if (!NT_STATUS_IS_OK(result))
+       if (!NT_STATUS_IS_OK(result)) {
                goto done;
+       }
 
-       result = cli_samr_add_groupmem(cli, mem_ctx, &group_pol, rids[0]);
+       result = rpccli_samr_add_groupmem(pipe_hnd, mem_ctx, &group_pol, rids[0]);
 
  done:
-       cli_samr_close(cli, mem_ctx, &connect_pol);
+       rpccli_samr_close(pipe_hnd, mem_ctx, &connect_pol);
        return result;
 }
 
-static NTSTATUS
-rpc_add_aliasmem(struct cli_state *cli, TALLOC_CTX *mem_ctx,
-                const DOM_SID *alias_sid, const char *member)
+static NTSTATUS rpc_add_aliasmem(struct rpc_pipe_client *pipe_hnd,
+                               TALLOC_CTX *mem_ctx,
+                               const DOM_SID *alias_sid,
+                               const char *member)
 {
        POLICY_HND connect_pol, domain_pol;
        NTSTATUS result;
@@ -1623,10 +1688,11 @@ rpc_add_aliasmem(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 
        sid_copy(&sid, alias_sid);
 
-       if (!sid_split_rid(&sid, &alias_rid))
+       if (!sid_split_rid(&sid, &alias_rid)) {
                return NT_STATUS_UNSUCCESSFUL;
+       }
 
-       result = get_sid_from_name(cli, mem_ctx, member,
+       result = get_sid_from_name(pipe_hnd->cli, mem_ctx, member,
                                   &member_sid, &member_type);
 
        if (!NT_STATUS_IS_OK(result)) {
@@ -1635,41 +1701,46 @@ rpc_add_aliasmem(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        }
 
        /* Get sam policy handle */     
-       result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
+       result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
                                  &connect_pol);
        if (!NT_STATUS_IS_OK(result)) {
                goto done;
        }
        
        /* Get domain policy handle */
-       result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
+       result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
                                      MAXIMUM_ALLOWED_ACCESS,
                                      &sid, &domain_pol);
        if (!NT_STATUS_IS_OK(result)) {
                goto done;
        }
 
-       result = cli_samr_open_alias(cli, mem_ctx, &domain_pol,
+       result = rpccli_samr_open_alias(pipe_hnd, mem_ctx, &domain_pol,
                                     MAXIMUM_ALLOWED_ACCESS,
                                     alias_rid, &alias_pol);
 
-       if (!NT_STATUS_IS_OK(result))
+       if (!NT_STATUS_IS_OK(result)) {
                return result;
+       }
 
-       result = cli_samr_add_aliasmem(cli, mem_ctx, &alias_pol, &member_sid);
+       result = rpccli_samr_add_aliasmem(pipe_hnd, mem_ctx, &alias_pol, &member_sid);
 
-       if (!NT_STATUS_IS_OK(result))
+       if (!NT_STATUS_IS_OK(result)) {
                return result;
+       }
 
  done:
-       cli_samr_close(cli, mem_ctx, &connect_pol);
+       rpccli_samr_close(pipe_hnd, mem_ctx, &connect_pol);
        return result;
 }
 
-static NTSTATUS 
-rpc_group_addmem_internals(const DOM_SID *domain_sid, const char *domain_name, 
-                          struct cli_state *cli,
-                          TALLOC_CTX *mem_ctx, int argc, const char **argv)
+static NTSTATUS rpc_group_addmem_internals(const DOM_SID *domain_sid,
+                                       const char *domain_name, 
+                                       struct cli_state *cli,
+                                       struct rpc_pipe_client *pipe_hnd,
+                                       TALLOC_CTX *mem_ctx,
+                                       int argc,
+                                       const char **argv)
 {
        DOM_SID group_sid;
        enum SID_NAME_USE group_type;
@@ -1686,7 +1757,7 @@ rpc_group_addmem_internals(const DOM_SID *domain_sid, const char *domain_name,
        }
 
        if (group_type == SID_NAME_DOM_GRP) {
-               NTSTATUS result = rpc_add_groupmem(cli, mem_ctx,
+               NTSTATUS result = rpc_add_groupmem(pipe_hnd, mem_ctx,
                                                   &group_sid, argv[1]);
 
                if (!NT_STATUS_IS_OK(result)) {
@@ -1697,7 +1768,7 @@ rpc_group_addmem_internals(const DOM_SID *domain_sid, const char *domain_name,
        }
 
        if (group_type == SID_NAME_ALIAS) {
-               NTSTATUS result = rpc_add_aliasmem(cli, mem_ctx,
+               NTSTATUS result = rpc_add_aliasmem(pipe_hnd, mem_ctx,
                                                   &group_sid, argv[1]);
 
                if (!NT_STATUS_IS_OK(result)) {
@@ -1720,9 +1791,10 @@ static int rpc_group_addmem(int argc, const char **argv)
                               argc, argv);
 }
 
-static NTSTATUS
-rpc_del_groupmem(struct cli_state *cli, TALLOC_CTX *mem_ctx,
-                const DOM_SID *group_sid, const char *member)
+static NTSTATUS rpc_del_groupmem(struct rpc_pipe_client *pipe_hnd,
+                               TALLOC_CTX *mem_ctx,
+                               const DOM_SID *group_sid,
+                               const char *member)
 {
        POLICY_HND connect_pol, domain_pol;
        NTSTATUS result;
@@ -1741,19 +1813,19 @@ rpc_del_groupmem(struct cli_state *cli, TALLOC_CTX *mem_ctx,
                return NT_STATUS_UNSUCCESSFUL;
 
        /* Get sam policy handle */     
-       result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
+       result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
                                  &connect_pol);
        if (!NT_STATUS_IS_OK(result))
                return result;
        
        /* Get domain policy handle */
-       result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
+       result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
                                      MAXIMUM_ALLOWED_ACCESS,
                                      &sid, &domain_pol);
        if (!NT_STATUS_IS_OK(result))
                return result;
 
-       result = cli_samr_lookup_names(cli, mem_ctx, &domain_pol, 1000,
+       result = rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol, 1000,
                                       1, &member,
                                       &num_rids, &rids, &rid_types);
 
@@ -1762,23 +1834,24 @@ rpc_del_groupmem(struct cli_state *cli, TALLOC_CTX *mem_ctx,
                goto done;
        }
 
-       result = cli_samr_open_group(cli, mem_ctx, &domain_pol,
+       result = rpccli_samr_open_group(pipe_hnd, mem_ctx, &domain_pol,
                                     MAXIMUM_ALLOWED_ACCESS,
                                     group_rid, &group_pol);
 
        if (!NT_STATUS_IS_OK(result))
                goto done;
 
-       result = cli_samr_del_groupmem(cli, mem_ctx, &group_pol, rids[0]);
+       result = rpccli_samr_del_groupmem(pipe_hnd, mem_ctx, &group_pol, rids[0]);
 
  done:
-       cli_samr_close(cli, mem_ctx, &connect_pol);
+       rpccli_samr_close(pipe_hnd, mem_ctx, &connect_pol);
        return result;
 }
 
-static NTSTATUS
-rpc_del_aliasmem(struct cli_state *cli, TALLOC_CTX *mem_ctx,
-                const DOM_SID *alias_sid, const char *member)
+static NTSTATUS rpc_del_aliasmem(struct rpc_pipe_client *pipe_hnd,
+                               TALLOC_CTX *mem_ctx,
+                               const DOM_SID *alias_sid,
+                               const char *member)
 {
        POLICY_HND connect_pol, domain_pol;
        NTSTATUS result;
@@ -1795,7 +1868,7 @@ rpc_del_aliasmem(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        if (!sid_split_rid(&sid, &alias_rid))
                return NT_STATUS_UNSUCCESSFUL;
 
-       result = get_sid_from_name(cli, mem_ctx, member,
+       result = get_sid_from_name(pipe_hnd->cli, mem_ctx, member,
                                   &member_sid, &member_type);
 
        if (!NT_STATUS_IS_OK(result)) {
@@ -1804,41 +1877,44 @@ rpc_del_aliasmem(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        }
 
        /* Get sam policy handle */     
-       result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
+       result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
                                  &connect_pol);
        if (!NT_STATUS_IS_OK(result)) {
                goto done;
        }
        
        /* Get domain policy handle */
-       result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
+       result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
                                      MAXIMUM_ALLOWED_ACCESS,
                                      &sid, &domain_pol);
        if (!NT_STATUS_IS_OK(result)) {
                goto done;
        }
 
-       result = cli_samr_open_alias(cli, mem_ctx, &domain_pol,
+       result = rpccli_samr_open_alias(pipe_hnd, mem_ctx, &domain_pol,
                                     MAXIMUM_ALLOWED_ACCESS,
                                     alias_rid, &alias_pol);
 
        if (!NT_STATUS_IS_OK(result))
                return result;
 
-       result = cli_samr_del_aliasmem(cli, mem_ctx, &alias_pol, &member_sid);
+       result = rpccli_samr_del_aliasmem(pipe_hnd, mem_ctx, &alias_pol, &member_sid);
 
        if (!NT_STATUS_IS_OK(result))
                return result;
 
  done:
-       cli_samr_close(cli, mem_ctx, &connect_pol);
+       rpccli_samr_close(pipe_hnd, mem_ctx, &connect_pol);
        return result;
 }
 
-static NTSTATUS 
-rpc_group_delmem_internals(const DOM_SID *domain_sid, const char *domain_name, 
-                          struct cli_state *cli,
-                          TALLOC_CTX *mem_ctx, int argc, const char **argv)
+static NTSTATUS rpc_group_delmem_internals(const DOM_SID *domain_sid,
+                                       const char *domain_name, 
+                                       struct cli_state *cli,
+                                       struct rpc_pipe_client *pipe_hnd,
+                                       TALLOC_CTX *mem_ctx,
+                                       int argc,
+                                       const char **argv)
 {
        DOM_SID group_sid;
        enum SID_NAME_USE group_type;
@@ -1855,7 +1931,7 @@ rpc_group_delmem_internals(const DOM_SID *domain_sid, const char *domain_name,
        }
 
        if (group_type == SID_NAME_DOM_GRP) {
-               NTSTATUS result = rpc_del_groupmem(cli, mem_ctx,
+               NTSTATUS result = rpc_del_groupmem(pipe_hnd, mem_ctx,
                                                   &group_sid, argv[1]);
 
                if (!NT_STATUS_IS_OK(result)) {
@@ -1866,7 +1942,7 @@ rpc_group_delmem_internals(const DOM_SID *domain_sid, const char *domain_name,
        }
 
        if (group_type == SID_NAME_ALIAS) {
-               NTSTATUS result = rpc_del_aliasmem(cli, mem_ctx, 
+               NTSTATUS result = rpc_del_aliasmem(pipe_hnd, mem_ctx, 
                                                   &group_sid, argv[1]);
 
                if (!NT_STATUS_IS_OK(result)) {
@@ -1905,10 +1981,13 @@ static int rpc_group_delmem(int argc, const char **argv)
  * @return Normal NTSTATUS return.
  **/
 
-static NTSTATUS 
-rpc_group_list_internals(const DOM_SID *domain_sid, const char *domain_name, 
-                        struct cli_state *cli,
-                        TALLOC_CTX *mem_ctx, int argc, const char **argv)
+static NTSTATUS rpc_group_list_internals(const DOM_SID *domain_sid,
+                                       const char *domain_name, 
+                                       struct cli_state *cli,
+                                       struct rpc_pipe_client *pipe_hnd,
+                                       TALLOC_CTX *mem_ctx,
+                                       int argc,
+                                       const char **argv)
 {
        POLICY_HND connect_pol, domain_pol;
        NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
@@ -1937,7 +2016,7 @@ rpc_group_list_internals(const DOM_SID *domain_sid, const char *domain_name,
 
        /* Get sam policy handle */
        
-       result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
+       result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
                                  &connect_pol);
        if (!NT_STATUS_IS_OK(result)) {
                goto done;
@@ -1945,7 +2024,7 @@ rpc_group_list_internals(const DOM_SID *domain_sid, const char *domain_name,
        
        /* Get domain policy handle */
        
-       result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
+       result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
                                      MAXIMUM_ALLOWED_ACCESS,
                                      domain_sid, &domain_pol);
        if (!NT_STATUS_IS_OK(result)) {
@@ -1970,7 +2049,7 @@ rpc_group_list_internals(const DOM_SID *domain_sid, const char *domain_name,
                get_query_dispinfo_params(
                        loop_count, &max_entries, &max_size);
 
-               result = cli_samr_query_dispinfo(cli, mem_ctx, &domain_pol,
+               result = rpccli_samr_query_dispinfo(pipe_hnd, mem_ctx, &domain_pol,
                                                 &start_idx, 3, &num_entries,
                                                 max_entries, max_size, &ctr);
 
@@ -2003,7 +2082,7 @@ rpc_group_list_internals(const DOM_SID *domain_sid, const char *domain_name,
                 * everything. I'm too lazy (sorry) to get this through to
                 * rpc_parse/ etc.  Volker */
 
-               result = cli_samr_enum_als_groups(cli, mem_ctx, &domain_pol,
+               result = rpccli_samr_enum_als_groups(pipe_hnd, mem_ctx, &domain_pol,
                                                  &start_idx, 0xffff,
                                                  &groups, &num_entries);
 
@@ -2020,15 +2099,15 @@ rpc_group_list_internals(const DOM_SID *domain_sid, const char *domain_name,
                                POLICY_HND alias_pol;
                                ALIAS_INFO_CTR ctr;
 
-                               if ((NT_STATUS_IS_OK(cli_samr_open_alias(cli, mem_ctx,
+                               if ((NT_STATUS_IS_OK(rpccli_samr_open_alias(pipe_hnd, mem_ctx,
                                                                         &domain_pol,
                                                                         0x8,
                                                                         groups[i].rid,
                                                                         &alias_pol))) &&
-                                   (NT_STATUS_IS_OK(cli_samr_query_alias_info(cli, mem_ctx,
+                                   (NT_STATUS_IS_OK(rpccli_samr_query_alias_info(pipe_hnd, mem_ctx,
                                                                               &alias_pol, 3,
                                                                               &ctr))) &&
-                                   (NT_STATUS_IS_OK(cli_samr_close(cli, mem_ctx,
+                                   (NT_STATUS_IS_OK(rpccli_samr_close(pipe_hnd, mem_ctx,
                                                                    &alias_pol)))) {
                                        description = unistr2_tdup(mem_ctx,
                                                                   ctr.alias.info3.description.string);
@@ -2044,10 +2123,10 @@ rpc_group_list_internals(const DOM_SID *domain_sid, const char *domain_name,
                        }
                }
        } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES));
-       cli_samr_close(cli, mem_ctx, &domain_pol);
+       rpccli_samr_close(pipe_hnd, mem_ctx, &domain_pol);
        /* Get builtin policy handle */
        
-       result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
+       result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
                                      MAXIMUM_ALLOWED_ACCESS,
                                      &global_sid_Builtin, &domain_pol);
        if (!NT_STATUS_IS_OK(result)) {
@@ -2058,7 +2137,7 @@ rpc_group_list_internals(const DOM_SID *domain_sid, const char *domain_name,
        do {
                if (!builtin) break;
 
-               result = cli_samr_enum_als_groups(cli, mem_ctx, &domain_pol,
+               result = rpccli_samr_enum_als_groups(pipe_hnd, mem_ctx, &domain_pol,
                                                  &start_idx, max_entries,
                                                  &groups, &num_entries);
                                                 
@@ -2075,15 +2154,15 @@ rpc_group_list_internals(const DOM_SID *domain_sid, const char *domain_name,
                                POLICY_HND alias_pol;
                                ALIAS_INFO_CTR ctr;
 
-                               if ((NT_STATUS_IS_OK(cli_samr_open_alias(cli, mem_ctx,
+                               if ((NT_STATUS_IS_OK(rpccli_samr_open_alias(pipe_hnd, mem_ctx,
                                                                         &domain_pol,
                                                                         0x8,
                                                                         groups[i].rid,
                                                                         &alias_pol))) &&
-                                   (NT_STATUS_IS_OK(cli_samr_query_alias_info(cli, mem_ctx,
+                                   (NT_STATUS_IS_OK(rpccli_samr_query_alias_info(pipe_hnd, mem_ctx,
                                                                               &alias_pol, 3,
                                                                               &ctr))) &&
-                                   (NT_STATUS_IS_OK(cli_samr_close(cli, mem_ctx,
+                                   (NT_STATUS_IS_OK(rpccli_samr_close(pipe_hnd, mem_ctx,
                                                                    &alias_pol)))) {
                                        description = unistr2_tdup(mem_ctx,
                                                                   ctr.alias.info3.description.string);
@@ -2111,10 +2190,12 @@ static int rpc_group_list(int argc, const char **argv)
                               argc, argv);
 }
 
-static NTSTATUS
-rpc_list_group_members(struct cli_state *cli, TALLOC_CTX *mem_ctx,
-                      const char *domain_name, const DOM_SID *domain_sid,
-                      POLICY_HND *domain_pol, uint32 rid)
+static NTSTATUS rpc_list_group_members(struct rpc_pipe_client *pipe_hnd,
+                                       TALLOC_CTX *mem_ctx,
+                                       const char *domain_name,
+                                       const DOM_SID *domain_sid,
+                                       POLICY_HND *domain_pol,
+                                       uint32 rid)
 {
        NTSTATUS result;
        POLICY_HND group_pol;
@@ -2127,14 +2208,14 @@ rpc_list_group_members(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        fstring sid_str;
        sid_to_string(sid_str, domain_sid);
 
-       result = cli_samr_open_group(cli, mem_ctx, domain_pol,
+       result = rpccli_samr_open_group(pipe_hnd, mem_ctx, domain_pol,
                                     MAXIMUM_ALLOWED_ACCESS,
                                     rid, &group_pol);
 
        if (!NT_STATUS_IS_OK(result))
                return result;
 
-       result = cli_samr_query_groupmem(cli, mem_ctx, &group_pol,
+       result = rpccli_samr_query_groupmem(pipe_hnd, mem_ctx, &group_pol,
                                         &num_members, &group_rids,
                                         &group_attrs);
 
@@ -2147,7 +2228,7 @@ rpc_list_group_members(struct cli_state *cli, TALLOC_CTX *mem_ctx,
                if (num_members < this_time)
                        this_time = num_members;
 
-               result = cli_samr_lookup_rids(cli, mem_ctx, domain_pol,
+               result = rpccli_samr_lookup_rids(pipe_hnd, mem_ctx, domain_pol,
                                              this_time, group_rids,
                                              &num_names, &names, &name_types);
 
@@ -2175,11 +2256,13 @@ rpc_list_group_members(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        return NT_STATUS_OK;
 }
 
-static NTSTATUS
-rpc_list_alias_members(struct cli_state *cli, TALLOC_CTX *mem_ctx,
-                      POLICY_HND *domain_pol, uint32 rid)
+static NTSTATUS rpc_list_alias_members(struct rpc_pipe_client *pipe_hnd,
+                                       TALLOC_CTX *mem_ctx,
+                                       POLICY_HND *domain_pol,
+                                       uint32 rid)
 {
        NTSTATUS result;
+       struct rpc_pipe_client *lsa_pipe;
        POLICY_HND alias_pol, lsa_pol;
        uint32 num_members;
        DOM_SID *alias_sids;
@@ -2188,13 +2271,13 @@ rpc_list_alias_members(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        uint32 *types;
        int i;
 
-       result = cli_samr_open_alias(cli, mem_ctx, domain_pol,
+       result = rpccli_samr_open_alias(pipe_hnd, mem_ctx, domain_pol,
                                     MAXIMUM_ALLOWED_ACCESS, rid, &alias_pol);
 
        if (!NT_STATUS_IS_OK(result))
                return result;
 
-       result = cli_samr_query_aliasmem(cli, mem_ctx, &alias_pol,
+       result = rpccli_samr_query_aliasmem(pipe_hnd, mem_ctx, &alias_pol,
                                         &num_members, &alias_sids);
 
        if (!NT_STATUS_IS_OK(result)) {
@@ -2206,28 +2289,30 @@ rpc_list_alias_members(struct cli_state *cli, TALLOC_CTX *mem_ctx,
                return NT_STATUS_OK;
        }
 
-       cli_nt_session_close(cli);
-
-       if (!cli_nt_session_open(cli, PI_LSARPC)) {
-               d_printf("Couldn't open LSA pipe\n");
+       lsa_pipe = cli_rpc_pipe_open_noauth(pipe_hnd->cli, PI_LSARPC, &result);
+       if (!lsa_pipe) {
+               d_printf("Couldn't open LSA pipe. Error was %s\n",
+                       nt_errstr(result) );
                return result;
        }
 
-       result = cli_lsa_open_policy(cli, mem_ctx, True,
+       result = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, True,
                                     SEC_RIGHTS_MAXIMUM_ALLOWED, &lsa_pol);
 
        if (!NT_STATUS_IS_OK(result)) {
                d_printf("Couldn't open LSA policy handle\n");
+               cli_rpc_pipe_close(lsa_pipe);
                return result;
        }
 
-       result = cli_lsa_lookup_sids(cli, mem_ctx, &lsa_pol, num_members,
+       result = rpccli_lsa_lookup_sids(lsa_pipe, mem_ctx, &lsa_pol, num_members,
                                     alias_sids, 
                                     &domains, &names, &types);
 
        if (!NT_STATUS_IS_OK(result) &&
            !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
                d_printf("Couldn't lookup SIDs\n");
+               cli_rpc_pipe_close(lsa_pipe);
                return result;
        }
 
@@ -2247,14 +2332,17 @@ rpc_list_alias_members(struct cli_state *cli, TALLOC_CTX *mem_ctx,
                }
        }
 
+       cli_rpc_pipe_close(lsa_pipe);
        return NT_STATUS_OK;
 }
  
-static NTSTATUS 
-rpc_group_members_internals(const DOM_SID *domain_sid,
-                           const char *domain_name, 
-                           struct cli_state *cli,
-                           TALLOC_CTX *mem_ctx, int argc, const char **argv)
+static NTSTATUS rpc_group_members_internals(const DOM_SID *domain_sid,
+                                       const char *domain_name, 
+                                       struct cli_state *cli,
+                                       struct rpc_pipe_client *pipe_hnd,
+                                       TALLOC_CTX *mem_ctx,
+                                       int argc,
+                                       const char **argv)
 {
        NTSTATUS result;
        POLICY_HND connect_pol, domain_pol;
@@ -2262,7 +2350,7 @@ rpc_group_members_internals(const DOM_SID *domain_sid,
 
        /* Get sam policy handle */
        
-       result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
+       result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
                                  &connect_pol);
 
        if (!NT_STATUS_IS_OK(result))
@@ -2270,14 +2358,14 @@ rpc_group_members_internals(const DOM_SID *domain_sid,
        
        /* Get domain policy handle */
        
-       result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
+       result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
                                      MAXIMUM_ALLOWED_ACCESS,
                                      domain_sid, &domain_pol);
 
        if (!NT_STATUS_IS_OK(result))
                return result;
 
-       result = cli_samr_lookup_names(cli, mem_ctx, &domain_pol, 1000,
+       result = rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol, 1000,
                                       1, argv, &num_rids, &rids, &rid_types);
 
        if (!NT_STATUS_IS_OK(result)) {
@@ -2286,11 +2374,11 @@ rpc_group_members_internals(const DOM_SID *domain_sid,
 
                DOM_SID sid_Builtin;
 
-               cli_samr_close(cli, mem_ctx, &domain_pol);
+               rpccli_samr_close(pipe_hnd, mem_ctx, &domain_pol);
 
                string_to_sid(&sid_Builtin, "S-1-5-32");                
 
-               result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
+               result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
                                              MAXIMUM_ALLOWED_ACCESS,
                                              &sid_Builtin, &domain_pol);
 
@@ -2299,7 +2387,7 @@ rpc_group_members_internals(const DOM_SID *domain_sid,
                        return result;
                }
 
-               result = cli_samr_lookup_names(cli, mem_ctx, &domain_pol, 1000,
+               result = rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol, 1000,
                                               1, argv, &num_rids,
                                               &rids, &rid_types);
 
@@ -2315,13 +2403,13 @@ rpc_group_members_internals(const DOM_SID *domain_sid,
        }
 
        if (rid_types[0] == SID_NAME_DOM_GRP) {
-               return rpc_list_group_members(cli, mem_ctx, domain_name,
+               return rpc_list_group_members(pipe_hnd, mem_ctx, domain_name,
                                              domain_sid, &domain_pol,
                                              rids[0]);
        }
 
        if (rid_types[0] == SID_NAME_ALIAS) {
-               return rpc_list_alias_members(cli, mem_ctx, &domain_pol,
+               return rpc_list_alias_members(pipe_hnd, mem_ctx, &domain_pol,
                                              rids[0]);
        }
 
@@ -2339,11 +2427,13 @@ static int rpc_group_members(int argc, const char **argv)
                               argc, argv);
 }
 
-static NTSTATUS 
-rpc_group_rename_internals(const DOM_SID *domain_sid,
-                           const char *domain_name, 
-                           struct cli_state *cli,
-                           TALLOC_CTX *mem_ctx, int argc, const char **argv)
+static NTSTATUS rpc_group_rename_internals(const DOM_SID *domain_sid,
+                                       const char *domain_name, 
+                                       struct cli_state *cli,
+                                       struct rpc_pipe_client *pipe_hnd,
+                                       TALLOC_CTX *mem_ctx,
+                                       int argc,
+                                       const char **argv)
 {
        NTSTATUS result;
        POLICY_HND connect_pol, domain_pol, group_pol;
@@ -2357,7 +2447,7 @@ rpc_group_rename_internals(const DOM_SID *domain_sid,
 
        /* Get sam policy handle */
        
-       result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
+       result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
                                  &connect_pol);
 
        if (!NT_STATUS_IS_OK(result))
@@ -2365,14 +2455,14 @@ rpc_group_rename_internals(const DOM_SID *domain_sid,
        
        /* Get domain policy handle */
        
-       result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
+       result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
                                      MAXIMUM_ALLOWED_ACCESS,
                                      domain_sid, &domain_pol);
 
        if (!NT_STATUS_IS_OK(result))
                return result;
 
-       result = cli_samr_lookup_names(cli, mem_ctx, &domain_pol, 1000,
+       result = rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol, 1000,
                                       1, argv, &num_rids, &rids, &rid_types);
 
        if (num_rids != 1) {
@@ -2385,7 +2475,7 @@ rpc_group_rename_internals(const DOM_SID *domain_sid,
                return NT_STATUS_UNSUCCESSFUL;
        }
 
-       result = cli_samr_open_group(cli, mem_ctx, &domain_pol,
+       result = rpccli_samr_open_group(pipe_hnd, mem_ctx, &domain_pol,
                                     MAXIMUM_ALLOWED_ACCESS,
                                     rids[0], &group_pol);
 
@@ -2397,7 +2487,7 @@ rpc_group_rename_internals(const DOM_SID *domain_sid,
        ctr.switch_value1 = 2;
        init_samr_group_info2(&ctr.group.info2, argv[1]);
 
-       result = cli_samr_set_groupinfo(cli, mem_ctx, &group_pol, &ctr);
+       result = rpccli_samr_set_groupinfo(pipe_hnd, mem_ctx, &group_pol, &ctr);
 
        if (!NT_STATUS_IS_OK(result))
                return result;
@@ -2467,10 +2557,12 @@ static int rpc_share_usage(int argc, const char **argv)
  *
  * @return Normal NTSTATUS return.
  **/
-static NTSTATUS 
-rpc_share_add_internals(const DOM_SID *domain_sid, const char *domain_name, 
-                       struct cli_state *cli,
-                       TALLOC_CTX *mem_ctx,int argc, const char **argv)
+static NTSTATUS rpc_share_add_internals(const DOM_SID *domain_sid,
+                                       const char *domain_name, 
+                                       struct cli_state *cli,
+                                       struct rpc_pipe_client *pipe_hnd,
+                                       TALLOC_CTX *mem_ctx,int argc,
+                                       const char **argv)
 {
        WERROR result;
        char *sharename=talloc_strdup(mem_ctx, argv[0]);
@@ -2485,7 +2577,7 @@ rpc_share_add_internals(const DOM_SID *domain_sid, const char *domain_name,
                return NT_STATUS_UNSUCCESSFUL;
        *path++ = '\0';
 
-       result = cli_srvsvc_net_share_add(cli, mem_ctx, sharename, type,
+       result = rpccli_srvsvc_net_share_add(pipe_hnd, mem_ctx, sharename, type,
                                          opt_comment, perms, opt_maxusers,
                                          num_users, path, password, 
                                          level, NULL);
@@ -2518,14 +2610,17 @@ static int rpc_share_add(int argc, const char **argv)
  *
  * @return Normal NTSTATUS return.
  **/
-static NTSTATUS 
-rpc_share_del_internals(const DOM_SID *domain_sid, const char *domain_name, 
-                       struct cli_state *cli,
-                       TALLOC_CTX *mem_ctx,int argc, const char **argv)
+static NTSTATUS rpc_share_del_internals(const DOM_SID *domain_sid,
+                                       const char *domain_name, 
+                                       struct cli_state *cli,
+                                       struct rpc_pipe_client *pipe_hnd,
+                                       TALLOC_CTX *mem_ctx,
+                                       int argc,
+                                       const char **argv)
 {
        WERROR result;
 
-       result = cli_srvsvc_net_share_del(cli, mem_ctx, argv[0]);
+       result = rpccli_srvsvc_net_share_del(pipe_hnd, mem_ctx, argv[0]);
        return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
 }
 
@@ -2572,10 +2667,12 @@ static void display_share_info_1(SRV_SHARE_INFO_1 *info1)
 
 }
 
-
-static WERROR get_share_info(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
-                            uint32 level, int argc, const char **argv, 
-                            SRV_SHARE_INFO_CTR *ctr)
+static WERROR get_share_info(struct rpc_pipe_client *pipe_hnd,
+                               TALLOC_CTX *mem_ctx, 
+                               uint32 level,
+                               int argc,
+                               const char **argv, 
+                               SRV_SHARE_INFO_CTR *ctr)
 {
        WERROR result;
        SRV_SHARE_INFO info;
@@ -2588,12 +2685,12 @@ static WERROR get_share_info(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 
                init_enum_hnd(&hnd, 0);
 
-               return cli_srvsvc_net_share_enum(cli, mem_ctx, level, ctr, 
+               return rpccli_srvsvc_net_share_enum(pipe_hnd, mem_ctx, level, ctr, 
                                                 preferred_len, &hnd);
        }
 
        /* request just one share */
-       result = cli_srvsvc_net_share_get_info(cli, mem_ctx, argv[0], level, &info);
+       result = rpccli_srvsvc_net_share_get_info(pipe_hnd, mem_ctx, argv[0], level, &info);
 
        if (!W_ERROR_IS_OK(result))
                goto done;
@@ -2720,16 +2817,19 @@ done:
  * @return Normal NTSTATUS return.
  **/
 
-static NTSTATUS 
-rpc_share_list_internals(const DOM_SID *domain_sid, const char *domain_name, 
-                        struct cli_state *cli,
-                        TALLOC_CTX *mem_ctx, int argc, const char **argv)
+static NTSTATUS rpc_share_list_internals(const DOM_SID *domain_sid,
+                                       const char *domain_name, 
+                                       struct cli_state *cli,
+                                       struct rpc_pipe_client *pipe_hnd,
+                                       TALLOC_CTX *mem_ctx,
+                                       int argc,
+                                       const char **argv)
 {
        SRV_SHARE_INFO_CTR ctr;
        WERROR result;
        uint32 i, level = 1;
 
-       result = get_share_info(cli, mem_ctx, level, argc, argv, &ctr);
+       result = get_share_info(pipe_hnd, mem_ctx, level, argc, argv, &ctr);
        if (!W_ERROR_IS_OK(result))
                goto done;
 
@@ -2808,10 +2908,14 @@ static BOOL check_share_sanity(struct cli_state *cli, fstring netname, uint32 ty
  *
  * @return Normal NTSTATUS return.
  **/
-static NTSTATUS 
-rpc_share_migrate_shares_internals(const DOM_SID *domain_sid, const char *domain_name, 
-                                  struct cli_state *cli, TALLOC_CTX *mem_ctx, 
-                                  int argc, const char **argv)
+
+static NTSTATUS rpc_share_migrate_shares_internals(const DOM_SID *domain_sid,
+                                               const char *domain_name, 
+                                               struct cli_state *cli,
+                                               struct rpc_pipe_client *pipe_hnd,
+                                               TALLOC_CTX *mem_ctx, 
+                                               int argc,
+                                               const char **argv)
 {
        WERROR result;
        NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
@@ -2819,16 +2923,16 @@ rpc_share_migrate_shares_internals(const DOM_SID *domain_sid, const char *domain
        uint32 type = STYPE_DISKTREE; /* only allow disk shares to be added */
        char *password = NULL; /* don't allow a share password */
        uint32 i;
-       BOOL got_dst_srvsvc_pipe = False;
+       struct rpc_pipe_client *srvsvc_pipe = NULL;
        struct cli_state *cli_dst = NULL;
        uint32 level = 502; /* includes secdesc */
 
-       result = get_share_info(cli, mem_ctx, level, argc, argv, &ctr_src);
+       result = get_share_info(pipe_hnd, mem_ctx, level, argc, argv, &ctr_src);
        if (!W_ERROR_IS_OK(result))
                goto done;
 
        /* connect destination PI_SRVSVC */
-        nt_status = connect_dst_pipe(&cli_dst, PI_SRVSVC, &got_dst_srvsvc_pipe);
+        nt_status = connect_dst_pipe(&cli_dst, &srvsvc_pipe, PI_SRVSVC);
         if (!NT_STATUS_IS_OK(nt_status))
                 return nt_status;
 
@@ -2854,7 +2958,7 @@ rpc_share_migrate_shares_internals(const DOM_SID *domain_sid, const char *domain
                printf("migrating: [%s], path: %s, comment: %s, without share-ACLs\n", 
                        netname, path, remark);
 
-               result = cli_srvsvc_net_share_add(cli_dst, mem_ctx, netname, type, remark,
+               result = rpccli_srvsvc_net_share_add(srvsvc_pipe, mem_ctx, netname, type, remark,
                                                  ctr_src.share.info502[i].info_502.perms,
                                                  ctr_src.share.info502[i].info_502.max_uses,
                                                  ctr_src.share.info502[i].info_502.num_uses,
@@ -2876,8 +2980,7 @@ rpc_share_migrate_shares_internals(const DOM_SID *domain_sid, const char *domain
        nt_status = NT_STATUS_OK;
 
 done:
-       if (got_dst_srvsvc_pipe) {
-               cli_nt_session_close(cli_dst);
+       if (cli_dst) {
                cli_shutdown(cli_dst);
        }
 
@@ -3038,7 +3141,7 @@ BOOL sync_files(struct copy_clistate *cp_clistate, pstring mask)
 BOOL copy_top_level_perms(struct copy_clistate *cp_clistate, 
                                const char *sharename)
 {
-       NTSTATUS nt_status;
+       NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
 
        switch (net_mode_share) {
        case NET_MODE_SHARE_MIGRATE:
@@ -3066,7 +3169,6 @@ BOOL copy_top_level_perms(struct copy_clistate *cp_clistate,
        return True;
 }
 
-
 /** 
  * Sync all files inside a remote share to another share (over smb)
  *
@@ -3082,10 +3184,14 @@ BOOL copy_top_level_perms(struct copy_clistate *cp_clistate,
  *
  * @return Normal NTSTATUS return.
  **/
-static NTSTATUS 
-rpc_share_migrate_files_internals(const DOM_SID *domain_sid, const char *domain_name, 
-                                 struct cli_state *cli, TALLOC_CTX *mem_ctx,
-                                 int argc, const char **argv)
+
+static NTSTATUS rpc_share_migrate_files_internals(const DOM_SID *domain_sid,
+                                               const char *domain_name, 
+                                               struct cli_state *cli,
+                                               struct rpc_pipe_client *pipe_hnd,
+                                               TALLOC_CTX *mem_ctx,
+                                               int argc,
+                                               const char **argv)
 {
        WERROR result;
        NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
@@ -3100,7 +3206,7 @@ rpc_share_migrate_files_internals(const DOM_SID *domain_sid, const char *domain_
 
        dst = SMB_STRDUP(opt_destination?opt_destination:"127.0.0.1");
 
-       result = get_share_info(cli, mem_ctx, level, argc, argv, &ctr_src);
+       result = get_share_info(pipe_hnd, mem_ctx, level, argc, argv, &ctr_src);
 
        if (!W_ERROR_IS_OK(result))
                goto done;
@@ -3216,27 +3322,31 @@ static int rpc_share_migrate_files(int argc, const char **argv)
  *
  * @return Normal NTSTATUS return.
  **/
-static NTSTATUS 
-rpc_share_migrate_security_internals(const DOM_SID *domain_sid, const char *domain_name, 
-                                    struct cli_state *cli, TALLOC_CTX *mem_ctx, 
-                                    int argc, const char **argv)
+
+static NTSTATUS rpc_share_migrate_security_internals(const DOM_SID *domain_sid,
+                                               const char *domain_name, 
+                                               struct cli_state *cli,
+                                               struct rpc_pipe_client *pipe_hnd,
+                                               TALLOC_CTX *mem_ctx, 
+                                               int argc,
+                                               const char **argv)
 {
        WERROR result;
        NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
        SRV_SHARE_INFO_CTR ctr_src;
        SRV_SHARE_INFO info;
        uint32 i;
-       BOOL got_dst_srvsvc_pipe = False;
+       struct rpc_pipe_client *srvsvc_pipe = NULL;
        struct cli_state *cli_dst = NULL;
        uint32 level = 502; /* includes secdesc */
 
-       result = get_share_info(cli, mem_ctx, level, argc, argv, &ctr_src);
+       result = get_share_info(pipe_hnd, mem_ctx, level, argc, argv, &ctr_src);
 
        if (!W_ERROR_IS_OK(result))
                goto done;
 
        /* connect destination PI_SRVSVC */
-        nt_status = connect_dst_pipe(&cli_dst, PI_SRVSVC, &got_dst_srvsvc_pipe);
+        nt_status = connect_dst_pipe(&cli_dst, &srvsvc_pipe, PI_SRVSVC);
         if (!NT_STATUS_IS_OK(nt_status))
                 return nt_status;
 
@@ -3273,7 +3383,7 @@ rpc_share_migrate_security_internals(const DOM_SID *domain_sid, const char *doma
                info.share.info502 = ctr_src.share.info502[i];
 
                /* finally modify the share on the dst server */
-               result = cli_srvsvc_net_share_set_info(cli_dst, mem_ctx, netname, level, &info);
+               result = rpccli_srvsvc_net_share_set_info(srvsvc_pipe, mem_ctx, netname, level, &info);
        
                if (!W_ERROR_IS_OK(result)) {
                        printf("cannot set share-acl: %s\n", dos_errstr(result));
@@ -3285,8 +3395,7 @@ rpc_share_migrate_security_internals(const DOM_SID *domain_sid, const char *doma
        nt_status = NT_STATUS_OK;
 
 done:
-       if (got_dst_srvsvc_pipe) {
-               cli_nt_session_close(cli_dst);
+       if (cli_dst) {
                cli_shutdown(cli_dst);
        }
 
@@ -3399,10 +3508,11 @@ static void push_alias(TALLOC_CTX *mem_ctx, struct full_alias *alias)
  * For a specific domain on the server, fetch all the aliases
  * and their members. Add all of them to the server_aliases.
  */
-static NTSTATUS
-rpc_fetch_domain_aliases(struct cli_state *cli, TALLOC_CTX *mem_ctx,
-                        POLICY_HND *connect_pol,
-                        const DOM_SID *domain_sid)
+
+static NTSTATUS rpc_fetch_domain_aliases(struct rpc_pipe_client *pipe_hnd,
+                                       TALLOC_CTX *mem_ctx,
+                                       POLICY_HND *connect_pol,
+                                       const DOM_SID *domain_sid)
 {
        uint32 start_idx, max_entries, num_entries, i;
        struct acct_info *groups;
@@ -3411,7 +3521,7 @@ rpc_fetch_domain_aliases(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 
        /* Get domain policy handle */
        
-       result = cli_samr_open_domain(cli, mem_ctx, connect_pol,
+       result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, connect_pol,
                                      MAXIMUM_ALLOWED_ACCESS,
                                      domain_sid, &domain_pol);
        if (!NT_STATUS_IS_OK(result))
@@ -3421,7 +3531,7 @@ rpc_fetch_domain_aliases(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        max_entries = 250;
 
        do {
-               result = cli_samr_enum_als_groups(cli, mem_ctx, &domain_pol,
+               result = rpccli_samr_enum_als_groups(pipe_hnd, mem_ctx, &domain_pol,
                                                  &start_idx, max_entries,
                                                  &groups, &num_entries);
 
@@ -3432,21 +3542,21 @@ rpc_fetch_domain_aliases(struct cli_state *cli, TALLOC_CTX *mem_ctx,
                        DOM_SID *members;
                        int j;
 
-                       result = cli_samr_open_alias(cli, mem_ctx, &domain_pol,
+                       result = rpccli_samr_open_alias(pipe_hnd, mem_ctx, &domain_pol,
                                                     MAXIMUM_ALLOWED_ACCESS,
                                                     groups[i].rid,
                                                     &alias_pol);
                        if (!NT_STATUS_IS_OK(result))
                                goto done;
 
-                       result = cli_samr_query_aliasmem(cli, mem_ctx,
+                       result = rpccli_samr_query_aliasmem(pipe_hnd, mem_ctx,
                                                         &alias_pol,
                                                         &alias.num_members,
                                                         &members);
                        if (!NT_STATUS_IS_OK(result))
                                goto done;
 
-                       result = cli_samr_close(cli, mem_ctx, &alias_pol);
+                       result = rpccli_samr_close(pipe_hnd, mem_ctx, &alias_pol);
                        if (!NT_STATUS_IS_OK(result))
                                goto done;
 
@@ -3470,7 +3580,7 @@ rpc_fetch_domain_aliases(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        result = NT_STATUS_OK;
 
  done:
-       cli_samr_close(cli, mem_ctx, &domain_pol);
+       rpccli_samr_close(pipe_hnd, mem_ctx, &domain_pol);
 
        return result;
 }
@@ -3478,16 +3588,20 @@ rpc_fetch_domain_aliases(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 /*
  * Dump server_aliases as names for debugging purposes.
  */
-static NTSTATUS
-rpc_aliaslist_dump(const DOM_SID *domain_sid, const char *domain_name,
-                  struct cli_state *cli, TALLOC_CTX *mem_ctx, 
-                  int argc, const char **argv)
+
+static NTSTATUS rpc_aliaslist_dump(const DOM_SID *domain_sid,
+                               const char *domain_name,
+                               struct cli_state *cli,
+                               struct rpc_pipe_client *pipe_hnd,
+                               TALLOC_CTX *mem_ctx, 
+                               int argc,
+                               const char **argv)
 {
        int i;
        NTSTATUS result;
        POLICY_HND lsa_pol;
 
-       result = cli_lsa_open_policy(cli, mem_ctx, True, 
+       result = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, True, 
                                     SEC_RIGHTS_MAXIMUM_ALLOWED,
                                     &lsa_pol);
        if (!NT_STATUS_IS_OK(result))
@@ -3501,7 +3615,7 @@ rpc_aliaslist_dump(const DOM_SID *domain_sid, const char *domain_name,
 
                struct full_alias *alias = &server_aliases[i];
 
-               result = cli_lsa_lookup_sids(cli, mem_ctx, &lsa_pol, 1,
+               result = rpccli_lsa_lookup_sids(pipe_hnd, mem_ctx, &lsa_pol, 1,
                                             &alias->sid,
                                             &domains, &names, &types);
                if (!NT_STATUS_IS_OK(result))
@@ -3514,7 +3628,7 @@ rpc_aliaslist_dump(const DOM_SID *domain_sid, const char *domain_name,
                        continue;
                }
 
-               result = cli_lsa_lookup_sids(cli, mem_ctx, &lsa_pol,
+               result = rpccli_lsa_lookup_sids(pipe_hnd, mem_ctx, &lsa_pol,
                                             alias->num_members,
                                             alias->members,
                                             &domains, &names, &types);
@@ -3530,7 +3644,7 @@ rpc_aliaslist_dump(const DOM_SID *domain_sid, const char *domain_name,
                DEBUG(1, ("\n"));
        }
 
-       cli_lsa_close(cli, mem_ctx, &lsa_pol);
+       rpccli_lsa_close(pipe_hnd, mem_ctx, &lsa_pol);
 
        return NT_STATUS_OK;
 }
@@ -3539,30 +3653,34 @@ rpc_aliaslist_dump(const DOM_SID *domain_sid, const char *domain_name,
  * Fetch a list of all server aliases and their members into
  * server_aliases.
  */
-static NTSTATUS
-rpc_aliaslist_internals(const DOM_SID *domain_sid, const char *domain_name,
-                       struct cli_state *cli, TALLOC_CTX *mem_ctx, 
-                       int argc, const char **argv)
+
+static NTSTATUS rpc_aliaslist_internals(const DOM_SID *domain_sid,
+                                       const char *domain_name,
+                                       struct cli_state *cli,
+                                       struct rpc_pipe_client *pipe_hnd,
+                                       TALLOC_CTX *mem_ctx, 
+                                       int argc,
+                                       const char **argv)
 {
        NTSTATUS result;
        POLICY_HND connect_pol;
 
-       result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
+       result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
                                  &connect_pol);
 
        if (!NT_STATUS_IS_OK(result))
                goto done;
        
-       result = rpc_fetch_domain_aliases(cli, mem_ctx, &connect_pol,
+       result = rpc_fetch_domain_aliases(pipe_hnd, mem_ctx, &connect_pol,
                                          &global_sid_Builtin);
 
        if (!NT_STATUS_IS_OK(result))
                goto done;
        
-       result = rpc_fetch_domain_aliases(cli, mem_ctx, &connect_pol,
+       result = rpc_fetch_domain_aliases(pipe_hnd, mem_ctx, &connect_pol,
                                          domain_sid);
 
-       cli_samr_close(cli, mem_ctx, &connect_pol);
+       rpccli_samr_close(pipe_hnd, mem_ctx, &connect_pol);
  done:
        return result;
 }
@@ -3662,8 +3780,7 @@ static void collect_alias_memberships(NT_USER_TOKEN *token)
        }
 }
 
-static BOOL get_user_sids(const char *domain, const char *user,
-                         NT_USER_TOKEN *token)
+static BOOL get_user_sids(const char *domain, const char *user, NT_USER_TOKEN *token)
 {
        struct winbindd_request request;
        struct winbindd_response response;
@@ -3749,6 +3866,7 @@ static BOOL get_user_sids(const char *domain, const char *user,
 /**
  * Get a list of all user tokens we want to look at
  **/
+
 static BOOL get_user_tokens(int *num_tokens, struct user_token **user_tokens)
 {
        struct winbindd_request request;
@@ -3884,19 +4002,22 @@ static BOOL get_user_tokens_from_file(FILE *f,
  * Show the list of all users that have access to a share
  */
 
-static void show_userlist(struct cli_state *cli,
-                         TALLOC_CTX *mem_ctx, const char *netname,
-                         int num_tokens, struct user_token *tokens)
+static void show_userlist(struct rpc_pipe_client *pipe_hnd,
+                       TALLOC_CTX *mem_ctx,
+                       const char *netname,
+                       int num_tokens,
+                       struct user_token *tokens)
 {
        int fnum;
        SEC_DESC *share_sd = NULL;
        SEC_DESC *root_sd = NULL;
+       struct cli_state *cli = pipe_hnd->cli;
        int i;
        SRV_SHARE_INFO info;
        WERROR result;
        uint16 cnum;
 
-       result = cli_srvsvc_net_share_get_info(cli, mem_ctx, netname,
+       result = rpccli_srvsvc_net_share_get_info(pipe_hnd, mem_ctx, netname,
                                               502, &info);
 
        if (!W_ERROR_IS_OK(result)) {
@@ -4005,12 +4126,13 @@ static void rpc_share_userlist_usage(void)
  * @return Normal NTSTATUS return.
  **/
 
-static NTSTATUS 
-rpc_share_allowedusers_internals(const DOM_SID *domain_sid,
-                                const char *domain_name,
-                                struct cli_state *cli,
-                                TALLOC_CTX *mem_ctx,
-                                int argc, const char **argv)
+static NTSTATUS rpc_share_allowedusers_internals(const DOM_SID *domain_sid,
+                                               const char *domain_name,
+                                               struct cli_state *cli,
+                                               struct rpc_pipe_client *pipe_hnd,
+                                               TALLOC_CTX *mem_ctx,
+                                               int argc,
+                                               const char **argv)
 {
        int ret;
        BOOL r;
@@ -4073,7 +4195,7 @@ rpc_share_allowedusers_internals(const DOM_SID *domain_sid,
 
                d_printf("%s\n", netname);
 
-               show_userlist(cli, mem_ctx, netname,
+               show_userlist(pipe_hnd, mem_ctx, netname,
                              num_tokens, tokens);
        }
  done:
@@ -4086,8 +4208,7 @@ rpc_share_allowedusers_internals(const DOM_SID *domain_sid,
        return NT_STATUS_OK;
 }
 
-static int
-rpc_share_allowedusers(int argc, const char **argv)
+static int rpc_share_allowedusers(int argc, const char **argv)
 {
        int result;
 
@@ -4192,13 +4313,16 @@ static int rpc_file_usage(int argc, const char **argv)
  *
  * @return Normal NTSTATUS return.
  **/
-static NTSTATUS 
-rpc_file_close_internals(const DOM_SID *domain_sid, const char *domain_name, 
-                        struct cli_state *cli,
-                        TALLOC_CTX *mem_ctx, int argc, const char **argv)
+static NTSTATUS rpc_file_close_internals(const DOM_SID *domain_sid,
+                                       const char *domain_name, 
+                                       struct cli_state *cli,
+                                       struct rpc_pipe_client *pipe_hnd,
+                                       TALLOC_CTX *mem_ctx,
+                                       int argc,
+                                       const char **argv)
 {
        WERROR result;
-       result = cli_srvsvc_net_file_close(cli, mem_ctx, atoi(argv[0]));
+       result = rpccli_srvsvc_net_file_close(pipe_hnd, mem_ctx, atoi(argv[0]));
        return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
 }
 
@@ -4257,10 +4381,13 @@ static void display_file_info_3(FILE_INFO_3 *info3, FILE_INFO_3_STR *str3)
  * @return Normal NTSTATUS return.
  **/
 
-static NTSTATUS 
-rpc_file_list_internals(const DOM_SID *domain_sid, const char *domain_name, 
-                       struct cli_state *cli,
-                       TALLOC_CTX *mem_ctx, int argc, const char **argv)
+static NTSTATUS rpc_file_list_internals(const DOM_SID *domain_sid,
+                                       const char *domain_name, 
+                                       struct cli_state *cli,
+                                       struct rpc_pipe_client *pipe_hnd,
+                                       TALLOC_CTX *mem_ctx,
+                                       int argc,
+                                       const char **argv)
 {
        SRV_FILE_INFO_CTR ctr;
        WERROR result;
@@ -4274,8 +4401,8 @@ rpc_file_list_internals(const DOM_SID *domain_sid, const char *domain_name,
        if (argc > 0)
                username = smb_xstrdup(argv[0]);
                
-       result = cli_srvsvc_net_file_enum(
-               cli, mem_ctx, 3, username, &ctr, preferred_len, &hnd);
+       result = rpccli_srvsvc_net_file_enum(pipe_hnd,
+                                       mem_ctx, 3, username, &ctr, preferred_len, &hnd);
 
        if (!W_ERROR_IS_OK(result))
                goto done;
@@ -4293,7 +4420,6 @@ rpc_file_list_internals(const DOM_SID *domain_sid, const char *domain_name,
        return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
 }
 
-
 /** 
  * List files for a user on a remote RPC server
  *
@@ -4303,6 +4429,7 @@ rpc_file_list_internals(const DOM_SID *domain_sid, const char *domain_name,
  *
  * @return A shell status integer (0 for success)
  **/
+
 static int rpc_file_user(int argc, const char **argv)
 {
        if (argc < 1) {
@@ -4315,7 +4442,6 @@ static int rpc_file_user(int argc, const char **argv)
                               argc, argv);
 }
 
-
 /** 
  * 'net rpc file' entrypoint.
  * @param argc  Standard main() style argc
@@ -4342,10 +4468,6 @@ int net_rpc_file(int argc, const char **argv)
        return net_run_function(argc, argv, func, rpc_file_usage);
 }
 
-/****************************************************************************/
-
-
-
 /** 
  * ABORT the shutdown of a remote RPC Server over, initshutdown pipe
  *
@@ -4363,14 +4485,16 @@ int net_rpc_file(int argc, const char **argv)
  **/
 
 static NTSTATUS rpc_shutdown_abort_internals(const DOM_SID *domain_sid, 
-                                            const char *domain_name, 
-                                            struct cli_state *cli, 
-                                            TALLOC_CTX *mem_ctx, 
-                                            int argc, const char **argv) 
+                                       const char *domain_name, 
+                                       struct cli_state *cli, 
+                                       struct rpc_pipe_client *pipe_hnd,
+                                       TALLOC_CTX *mem_ctx, 
+                                       int argc,
+                                       const char **argv) 
 {
        NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
        
-       result = cli_shutdown_abort(cli, mem_ctx);
+       result = rpccli_shutdown_abort(pipe_hnd, mem_ctx);
        
        if (NT_STATUS_IS_OK(result)) {
                d_printf("\nShutdown successfully aborted\n");
@@ -4381,7 +4505,6 @@ static NTSTATUS rpc_shutdown_abort_internals(const DOM_SID *domain_sid,
        return result;
 }
 
-
 /** 
  * ABORT the shutdown of a remote RPC Server,  over winreg pipe
  *
@@ -4399,14 +4522,16 @@ static NTSTATUS rpc_shutdown_abort_internals(const DOM_SID *domain_sid,
  **/
 
 static NTSTATUS rpc_reg_shutdown_abort_internals(const DOM_SID *domain_sid, 
-                                                const char *domain_name, 
-                                                struct cli_state *cli, 
-                                                TALLOC_CTX *mem_ctx, 
-                                                int argc, const char **argv) 
+                                               const char *domain_name, 
+                                               struct cli_state *cli, 
+                                               struct rpc_pipe_client *pipe_hnd,
+                                               TALLOC_CTX *mem_ctx, 
+                                               int argc,
+                                               const char **argv) 
 {
        NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
        
-       result = werror_to_ntstatus(cli_reg_abort_shutdown(cli, mem_ctx));
+       result = werror_to_ntstatus(rpccli_reg_abort_shutdown(pipe_hnd, mem_ctx));
        
        if (NT_STATUS_IS_OK(result)) {
                d_printf("\nShutdown successfully aborted\n");
@@ -4460,10 +4585,12 @@ static int rpc_shutdown_abort(int argc, const char **argv)
  **/
 
 static NTSTATUS rpc_init_shutdown_internals(const DOM_SID *domain_sid, 
-                                           const char *domain_name, 
-                                           struct cli_state *cli, 
-                                           TALLOC_CTX *mem_ctx, 
-                                           int argc, const char **argv) 
+                                               const char *domain_name, 
+                                               struct cli_state *cli, 
+                                               struct rpc_pipe_client *pipe_hnd,
+                                               TALLOC_CTX *mem_ctx, 
+                                               int argc,
+                                               const char **argv) 
 {
        NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
         const char *msg = "This machine will be shutdown shortly";
@@ -4471,16 +4598,13 @@ static NTSTATUS rpc_init_shutdown_internals(const DOM_SID *domain_sid,
 
        if (opt_comment) {
                msg = opt_comment;
-       } else {
-               msg = "";
        }
-
        if (opt_timeout) {
                timeout = opt_timeout;
        }
 
        /* create an entry */
-       result = cli_shutdown_init(cli, mem_ctx, msg, timeout, opt_reboot, 
+       result = rpccli_shutdown_init(pipe_hnd, mem_ctx, msg, timeout, opt_reboot, 
                                   opt_force);
 
        if (NT_STATUS_IS_OK(result)) {
@@ -4509,10 +4633,12 @@ static NTSTATUS rpc_init_shutdown_internals(const DOM_SID *domain_sid,
  **/
 
 static NTSTATUS rpc_reg_shutdown_internals(const DOM_SID *domain_sid, 
-                                          const char *domain_name, 
-                                          struct cli_state *cli, 
-                                          TALLOC_CTX *mem_ctx, 
-                                          int argc, const char **argv) 
+                                               const char *domain_name, 
+                                               struct cli_state *cli, 
+                                               struct rpc_pipe_client *pipe_hnd,
+                                               TALLOC_CTX *mem_ctx, 
+                                               int argc,
+                                               const char **argv) 
 {
        NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
         const char *msg = "This machine will be shutdown shortly";
@@ -4550,7 +4676,7 @@ static NTSTATUS rpc_reg_shutdown_internals(const DOM_SID *domain_sid,
        }
 
        /* create an entry */
-       result = werror_to_ntstatus(cli_reg_shutdown(cli, mem_ctx, msg, timeout, opt_reboot, opt_force));
+       result = werror_to_ntstatus(rpccli_reg_shutdown(pipe_hnd, mem_ctx, msg, timeout, opt_reboot, opt_force));
 
        if (NT_STATUS_IS_OK(result)) {
                d_printf("\nShutdown of remote machine succeeded\n");
@@ -4607,10 +4733,13 @@ static int rpc_shutdown(int argc, const char **argv)
  */
 
 static NTSTATUS rpc_trustdom_add_internals(const DOM_SID *domain_sid, 
-                                          const char *domain_name, 
-                                          struct cli_state *cli, TALLOC_CTX *mem_ctx, 
-                                           int argc, const char **argv) {
-
+                                               const char *domain_name, 
+                                               struct cli_state *cli,
+                                               struct rpc_pipe_client *pipe_hnd,
+                                               TALLOC_CTX *mem_ctx, 
+                                               int argc,
+                                               const char **argv)
+{
        POLICY_HND connect_pol, domain_pol, user_pol;
        NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
        char *acct_name;
@@ -4633,14 +4762,14 @@ static NTSTATUS rpc_trustdom_add_internals(const DOM_SID *domain_sid,
        strupper_m(acct_name);
 
        /* Get samr policy handle */
-       result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
+       result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
                                  &connect_pol);
        if (!NT_STATUS_IS_OK(result)) {
                goto done;
        }
        
        /* Get domain policy handle */
-       result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
+       result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
                                      MAXIMUM_ALLOWED_ACCESS,
                                      domain_sid, &domain_pol);
        if (!NT_STATUS_IS_OK(result)) {
@@ -4652,7 +4781,7 @@ static NTSTATUS rpc_trustdom_add_internals(const DOM_SID *domain_sid,
        unknown = 0xe00500b0; /* No idea what this is - a permission mask?
                                 mimir: yes, most probably it is */
 
-       result = cli_samr_create_dom_user(cli, mem_ctx, &domain_pol,
+       result = rpccli_samr_create_dom_user(pipe_hnd, mem_ctx, &domain_pol,
                                          acct_name, acb_info, unknown,
                                          &user_pol, &user_rid);
        if (!NT_STATUS_IS_OK(result)) {
@@ -4688,7 +4817,7 @@ static NTSTATUS rpc_trustdom_add_internals(const DOM_SID *domain_sid,
                ctr.info.id23 = &p23;
                p23.passmustchange = 0;
 
-               result = cli_samr_set_userinfo(cli, mem_ctx, &user_pol, 23,
+               result = rpccli_samr_set_userinfo(pipe_hnd, mem_ctx, &user_pol, 23,
                                               &cli->user_session_key, &ctr);
 
                if (!NT_STATUS_IS_OK(result)) {
@@ -4740,10 +4869,13 @@ static int rpc_trustdom_add(int argc, const char **argv)
  */
 
 static NTSTATUS rpc_trustdom_del_internals(const DOM_SID *domain_sid, 
-                                          const char *domain_name, 
-                                          struct cli_state *cli, TALLOC_CTX *mem_ctx, 
-                                           int argc, const char **argv) {
-
+                                       const char *domain_name, 
+                                       struct cli_state *cli,
+                                       struct rpc_pipe_client *pipe_hnd,
+                                       TALLOC_CTX *mem_ctx, 
+                                       int argc,
+                                       const char **argv)
+{
        POLICY_HND connect_pol, domain_pol, user_pol;
        NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
        char *acct_name;
@@ -4772,21 +4904,21 @@ static NTSTATUS rpc_trustdom_del_internals(const DOM_SID *domain_sid,
 
 
        /* Get samr policy handle */
-       result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
+       result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS,
                                  &connect_pol);
        if (!NT_STATUS_IS_OK(result)) {
                goto done;
        }
        
        /* Get domain policy handle */
-       result = cli_samr_open_domain(cli, mem_ctx, &connect_pol,
+       result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
                                      MAXIMUM_ALLOWED_ACCESS,
                                      domain_sid, &domain_pol);
        if (!NT_STATUS_IS_OK(result)) {
                goto done;
        }
 
-       result = cli_samr_lookup_names(cli, mem_ctx, &domain_pol, flags, 1,
+       result = rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol, flags, 1,
                                       names, &num_rids,
                                       &user_rids, &name_types);
        
@@ -4794,7 +4926,7 @@ static NTSTATUS rpc_trustdom_del_internals(const DOM_SID *domain_sid,
                goto done;
        }
 
-       result = cli_samr_open_user(cli, mem_ctx, &domain_pol,
+       result = rpccli_samr_open_user(pipe_hnd, mem_ctx, &domain_pol,
                                    MAXIMUM_ALLOWED_ACCESS,
                                    user_rids[0], &user_pol);
 
@@ -4810,7 +4942,7 @@ static NTSTATUS rpc_trustdom_del_internals(const DOM_SID *domain_sid,
 
        /* remove the sid */
 
-       result = cli_samr_remove_sid_foreign_domain(cli, mem_ctx, &user_pol,
+       result = rpccli_samr_remove_sid_foreign_domain(pipe_hnd, mem_ctx, &user_pol,
                                                    &trust_acct_sid);
 
        if (!NT_STATUS_IS_OK(result)) {
@@ -4819,7 +4951,7 @@ static NTSTATUS rpc_trustdom_del_internals(const DOM_SID *domain_sid,
 
        /* Delete user */
 
-       result = cli_samr_delete_dom_user(cli, mem_ctx, &user_pol);
+       result = rpccli_samr_delete_dom_user(pipe_hnd, mem_ctx, &user_pol);
 
        if (!NT_STATUS_IS_OK(result)) {
                goto done;
@@ -4868,8 +5000,9 @@ static int rpc_trustdom_del(int argc, const char **argv)
 
 static int rpc_trustdom_establish(int argc, const char **argv)
 {
-       struct cli_state *cli;
+       struct cli_state *cli = NULL;
        struct in_addr server_ip;
+       struct rpc_pipe_client *pipe_hnd = NULL;
        POLICY_HND connect_hnd;
        TALLOC_CTX *mem_ctx;
        NTSTATUS nt_status;
@@ -4954,34 +5087,38 @@ static int rpc_trustdom_establish(int argc, const char **argv)
         * Call LsaOpenPolicy and LsaQueryInfo
         */
         
-       if (!cli_nt_session_open(cli, PI_LSARPC)) {
-               DEBUG(0, ("Could not initialise lsa pipe\n"));
+       pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_LSARPC, &nt_status);
+       if (!pipe_hnd) {
+               DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n", nt_errstr(nt_status) ));
                cli_shutdown(cli);
                return -1;
        }
 
-       nt_status = cli_lsa_open_policy2(cli, mem_ctx, True, SEC_RIGHTS_QUERY_VALUE,
+       nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, True, SEC_RIGHTS_QUERY_VALUE,
                                         &connect_hnd);
        if (NT_STATUS_IS_ERR(nt_status)) {
                DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
                        nt_errstr(nt_status)));
+               cli_shutdown(cli);
                return -1;
        }
 
        /* Querying info level 5 */
        
-       nt_status = cli_lsa_query_info_policy(cli, mem_ctx, &connect_hnd,
+       nt_status = rpccli_lsa_query_info_policy(pipe_hnd, mem_ctx, &connect_hnd,
                                              5 /* info level */,
                                              &domain_name_pol, &domain_sid);
        if (NT_STATUS_IS_ERR(nt_status)) {
                DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
                        nt_errstr(nt_status)));
+               cli_shutdown(cli);
                return -1;
        }
 
        if (push_ucs2_talloc(mem_ctx, &uni_domain_name, domain_name_pol) == (size_t)-1) {
                DEBUG(0, ("Could not convert domain name %s to unicode\n",
                          domain_name_pol));
+               cli_shutdown(cli);
                return -1;
        }
 
@@ -4998,6 +5135,7 @@ static int rpc_trustdom_establish(int argc, const char **argv)
                                                   opt_password,
                                                   *domain_sid)) {
                DEBUG(0, ("Storing password for trusted domain failed.\n"));
+               cli_shutdown(cli);
                return -1;
        }
        
@@ -5005,16 +5143,14 @@ static int rpc_trustdom_establish(int argc, const char **argv)
         * Close the pipes and clean up
         */
         
-       nt_status = cli_lsa_close(cli, mem_ctx, &connect_hnd);
+       nt_status = rpccli_lsa_close(pipe_hnd, mem_ctx, &connect_hnd);
        if (NT_STATUS_IS_ERR(nt_status)) {
                DEBUG(0, ("Couldn't close LSA pipe. Error was %s\n",
                        nt_errstr(nt_status)));
+               cli_shutdown(cli);
                return -1;
        }
 
-       if (cli->pipes[cli->pipe_idx].fnum)
-               cli_nt_session_close(cli);
-
        cli_shutdown(cli);
         
        talloc_destroy(mem_ctx);
@@ -5074,9 +5210,12 @@ static int rpc_trustdom_usage(int argc, const char **argv)
 
 
 static NTSTATUS rpc_query_domain_sid(const DOM_SID *domain_sid, 
-                                    const char *domain_name, 
-                                    struct cli_state *cli, TALLOC_CTX *mem_ctx,
-                                    int argc, const char **argv)
+                                       const char *domain_name, 
+                                       struct cli_state *cli,
+                                       struct rpc_pipe_client *pipe_hnd,
+                                       TALLOC_CTX *mem_ctx,
+                                       int argc,
+                                       const char **argv)
 {
        fstring str_sid;
        sid_to_string(str_sid, domain_sid);
@@ -5100,7 +5239,7 @@ static void print_trusted_domain(DOM_SID *dom_sid, const char *trusted_dom_name)
        d_printf("%s%s%s\n", trusted_dom_name, padding, ascii_sid);
 }
 
-static NTSTATUS vampire_trusted_domain(struct cli_state *cli, 
+static NTSTATUS vampire_trusted_domain(struct rpc_pipe_client *pipe_hnd,
                                      TALLOC_CTX *mem_ctx, 
                                      POLICY_HND *pol, 
                                      DOM_SID dom_sid, 
@@ -5112,7 +5251,7 @@ static NTSTATUS vampire_trusted_domain(struct cli_state *cli,
        DATA_BLOB data;
        smb_ucs2_t *uni_dom_name;
 
-       nt_status = cli_lsa_query_trusted_domain_info_by_sid(cli, mem_ctx, pol, 4, &dom_sid, &info);
+       nt_status = rpccli_lsa_query_trusted_domain_info_by_sid(pipe_hnd, mem_ctx, pol, 4, &dom_sid, &info);
        
        if (NT_STATUS_IS_ERR(nt_status)) {
                DEBUG(0,("Could not query trusted domain info. Error was %s\n",
@@ -5125,7 +5264,7 @@ static NTSTATUS vampire_trusted_domain(struct cli_state *cli,
        memcpy(data.data, info->password.password.data, info->password.password.length);
        data.length     = info->password.password.length;
                                
-       cleartextpwd = decrypt_trustdom_secret(cli->pwd.password, &data);
+       cleartextpwd = decrypt_trustdom_secret(pipe_hnd->cli->pwd.password, &data);
 
        if (cleartextpwd == NULL) {
                DEBUG(0,("retrieved NULL password\n"));
@@ -5164,7 +5303,8 @@ static int rpc_trustdom_vampire(int argc, const char **argv)
 {
        /* common variables */
        TALLOC_CTX* mem_ctx;
-       struct cli_state *cli;
+       struct cli_state *cli = NULL;
+       struct rpc_pipe_client *pipe_hnd = NULL;
        NTSTATUS nt_status;
        const char *domain_name = NULL;
        DOM_SID *queried_dom_sid;
@@ -5204,27 +5344,32 @@ static int rpc_trustdom_vampire(int argc, const char **argv)
                return -1;
        };
 
-       if (!cli_nt_session_open(cli, PI_LSARPC)) {
-               DEBUG(0, ("Could not initialise lsa pipe\n"));
+       pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_LSARPC, &nt_status);
+       if (!pipe_hnd) {
+               DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n",
+                       nt_errstr(nt_status) ));
+               cli_shutdown(cli);
                return -1;
        };
 
-       nt_status = cli_lsa_open_policy2(cli, mem_ctx, False, SEC_RIGHTS_QUERY_VALUE,
+       nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, False, SEC_RIGHTS_QUERY_VALUE,
                                        &connect_hnd);
        if (NT_STATUS_IS_ERR(nt_status)) {
                DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
                        nt_errstr(nt_status)));
+               cli_shutdown(cli);
                return -1;
        };
 
        /* query info level 5 to obtain sid of a domain being queried */
-       nt_status = cli_lsa_query_info_policy(
-               cli, mem_ctx, &connect_hnd, 5 /* info level */, 
+       nt_status = rpccli_lsa_query_info_policy(
+               pipe_hnd, mem_ctx, &connect_hnd, 5 /* info level */, 
                &dummy, &queried_dom_sid);
 
        if (NT_STATUS_IS_ERR(nt_status)) {
                DEBUG(0, ("LSA Query Info failed. Returned error was %s\n",
                        nt_errstr(nt_status)));
+               cli_shutdown(cli);
                return -1;
        }
 
@@ -5236,13 +5381,14 @@ static int rpc_trustdom_vampire(int argc, const char **argv)
        d_printf("Vampire trusted domains:\n\n");
 
        do {
-               nt_status = cli_lsa_enum_trust_dom(cli, mem_ctx, &connect_hnd, &enum_ctx,
+               nt_status = rpccli_lsa_enum_trust_dom(pipe_hnd, mem_ctx, &connect_hnd, &enum_ctx,
                                                   &num_domains,
                                                   &trusted_dom_names, &domain_sids);
                
                if (NT_STATUS_IS_ERR(nt_status)) {
                        DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n",
                                nt_errstr(nt_status)));
+                       cli_shutdown(cli);
                        return -1;
                };
                
@@ -5250,10 +5396,12 @@ static int rpc_trustdom_vampire(int argc, const char **argv)
 
                        print_trusted_domain(&(domain_sids[i]), trusted_dom_names[i]);
 
-                       nt_status = vampire_trusted_domain(cli, mem_ctx, &connect_hnd, 
+                       nt_status = vampire_trusted_domain(pipe_hnd, mem_ctx, &connect_hnd, 
                                                           domain_sids[i], trusted_dom_names[i]);
-                       if (!NT_STATUS_IS_OK(nt_status))
+                       if (!NT_STATUS_IS_OK(nt_status)) {
+                               cli_shutdown(cli);
                                return -1;
+                       }
                };
 
                /*
@@ -5265,15 +5413,15 @@ static int rpc_trustdom_vampire(int argc, const char **argv)
        } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
 
        /* close this connection before doing next one */
-       nt_status = cli_lsa_close(cli, mem_ctx, &connect_hnd);
+       nt_status = rpccli_lsa_close(pipe_hnd, mem_ctx, &connect_hnd);
        if (NT_STATUS_IS_ERR(nt_status)) {
                DEBUG(0, ("Couldn't properly close lsa policy handle. Error was %s\n",
                        nt_errstr(nt_status)));
+               cli_shutdown(cli);
                return -1;
        };
 
        /* close lsarpc pipe and connection to IPC$ */
-       cli_nt_session_close(cli);
        cli_shutdown(cli);
 
        talloc_destroy(mem_ctx);         
@@ -5284,7 +5432,8 @@ static int rpc_trustdom_list(int argc, const char **argv)
 {
        /* common variables */
        TALLOC_CTX* mem_ctx;
-       struct cli_state *cli, *remote_cli;
+       struct cli_state *cli = NULL, *remote_cli = NULL;
+       struct rpc_pipe_client *pipe_hnd = NULL;
        NTSTATUS nt_status;
        const char *domain_name = NULL;
        DOM_SID *queried_dom_sid;
@@ -5331,12 +5480,14 @@ static int rpc_trustdom_list(int argc, const char **argv)
                return -1;
        };
 
-       if (!cli_nt_session_open(cli, PI_LSARPC)) {
-               DEBUG(0, ("Could not initialise lsa pipe\n"));
+       pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_LSARPC, &nt_status);
+       if (!pipe_hnd) {
+               DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n",
+                       nt_errstr(nt_status) ));
                return -1;
        };
 
-       nt_status = cli_lsa_open_policy2(cli, mem_ctx, False, SEC_RIGHTS_QUERY_VALUE,
+       nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, False, SEC_RIGHTS_QUERY_VALUE,
                                        &connect_hnd);
        if (NT_STATUS_IS_ERR(nt_status)) {
                DEBUG(0, ("Couldn't open policy handle. Error was %s\n",
@@ -5345,8 +5496,8 @@ static int rpc_trustdom_list(int argc, const char **argv)
        };
        
        /* query info level 5 to obtain sid of a domain being queried */
-       nt_status = cli_lsa_query_info_policy(
-               cli, mem_ctx, &connect_hnd, 5 /* info level */, 
+       nt_status = rpccli_lsa_query_info_policy(
+               pipe_hnd, mem_ctx, &connect_hnd, 5 /* info level */, 
                &dummy, &queried_dom_sid);
 
        if (NT_STATUS_IS_ERR(nt_status)) {
@@ -5363,7 +5514,7 @@ static int rpc_trustdom_list(int argc, const char **argv)
        d_printf("Trusted domains list:\n\n");
 
        do {
-               nt_status = cli_lsa_enum_trust_dom(cli, mem_ctx, &connect_hnd, &enum_ctx,
+               nt_status = rpccli_lsa_enum_trust_dom(pipe_hnd, mem_ctx, &connect_hnd, &enum_ctx,
                                                   &num_domains,
                                                   &trusted_dom_names, &domain_sids);
                
@@ -5386,14 +5537,14 @@ static int rpc_trustdom_list(int argc, const char **argv)
        } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
 
        /* close this connection before doing next one */
-       nt_status = cli_lsa_close(cli, mem_ctx, &connect_hnd);
+       nt_status = rpccli_lsa_close(pipe_hnd, mem_ctx, &connect_hnd);
        if (NT_STATUS_IS_ERR(nt_status)) {
                DEBUG(0, ("Couldn't properly close lsa policy handle. Error was %s\n",
                        nt_errstr(nt_status)));
                return -1;
        };
        
-       cli_nt_session_close(cli);
+       cli_rpc_pipe_close(pipe_hnd);
 
        /*
         * Listing trusting domains (stored in passdb backend, if local)
@@ -5404,13 +5555,14 @@ static int rpc_trustdom_list(int argc, const char **argv)
        /*
         * Open \PIPE\samr and get needed policy handles
         */
-       if (!cli_nt_session_open(cli, PI_SAMR)) {
-               DEBUG(0, ("Could not initialise samr pipe\n"));
+       pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_SAMR, &nt_status);
+       if (!pipe_hnd) {
+               DEBUG(0, ("Could not initialise samr pipe. Error was %s\n", nt_errstr(nt_status)));
                return -1;
        };
        
        /* SamrConnect */
-       nt_status = cli_samr_connect(cli, mem_ctx, SA_RIGHT_SAM_OPEN_DOMAIN,
+       nt_status = rpccli_samr_connect(pipe_hnd, mem_ctx, SA_RIGHT_SAM_OPEN_DOMAIN,
                                                                 &connect_hnd);
        if (!NT_STATUS_IS_OK(nt_status)) {
                DEBUG(0, ("Couldn't open SAMR policy handle. Error was %s\n",
@@ -5420,7 +5572,7 @@ static int rpc_trustdom_list(int argc, const char **argv)
        
        /* SamrOpenDomain - we have to open domain policy handle in order to be
           able to enumerate accounts*/
-       nt_status = cli_samr_open_domain(cli, mem_ctx, &connect_hnd,
+       nt_status = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_hnd,
                                         SA_RIGHT_DOMAIN_ENUM_ACCOUNTS,
                                         queried_dom_sid, &domain_hnd);                                                                  
        if (!NT_STATUS_IS_OK(nt_status)) {
@@ -5436,7 +5588,7 @@ static int rpc_trustdom_list(int argc, const char **argv)
        enum_ctx = 0;   /* reset enumeration context from last enumeration */
        do {
                        
-               nt_status = cli_samr_enum_dom_users(cli, mem_ctx, &domain_hnd,
+               nt_status = rpccli_samr_enum_dom_users(pipe_hnd, mem_ctx, &domain_hnd,
                                                    &enum_ctx, ACB_DOMTRUST, 0xffff,
                                                    &trusting_dom_names, &trusting_dom_rids,
                                                    &num_domains);
@@ -5490,18 +5642,17 @@ static int rpc_trustdom_list(int argc, const char **argv)
        } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
 
        /* close opened samr and domain policy handles */
-       nt_status = cli_samr_close(cli, mem_ctx, &domain_hnd);
+       nt_status = rpccli_samr_close(pipe_hnd, mem_ctx, &domain_hnd);
        if (!NT_STATUS_IS_OK(nt_status)) {
                DEBUG(0, ("Couldn't properly close domain policy handle for domain %s\n", domain_name));
        };
        
-       nt_status = cli_samr_close(cli, mem_ctx, &connect_hnd);
+       nt_status = rpccli_samr_close(pipe_hnd, mem_ctx, &connect_hnd);
        if (!NT_STATUS_IS_OK(nt_status)) {
                DEBUG(0, ("Couldn't properly close samr policy handle for domain %s\n", domain_name));
        };
        
        /* close samr pipe and connection to IPC$ */
-       cli_nt_session_close(cli);
        cli_shutdown(cli);
 
        talloc_destroy(mem_ctx);         
@@ -5577,7 +5728,7 @@ BOOL net_rpc_check(unsigned flags)
 
 /* dump sam database via samsync rpc calls */
 static int rpc_samdump(int argc, const char **argv) {
-       return run_rpc_command(NULL, PI_NETLOGON, NET_FLAGS_ANONYMOUS, rpc_samdump_internals,
+               return run_rpc_command(NULL, PI_NETLOGON, NET_FLAGS_ANONYMOUS, rpc_samdump_internals,
                               argc, argv);
 }
 
index 8d19ad888fc4e4ce7a1102f0f2d97edab88bcd7d..6b762563b3b2ae8e4fc247d296af7e34e1196b9d 100644 (file)
@@ -35,7 +35,6 @@
                 goto done; \
         }
 
-
 /**
  * confirm that a domain join is still valid
  *
  **/
 static int net_rpc_join_ok(const char *domain)
 {
-       struct cli_state *cli;
-       uchar stored_md4_trust_password[16];
+       struct cli_state *cli = NULL;
+       struct rpc_pipe_client *pipe_hnd = NULL;
        int retval = 1;
-       uint32 channel;
+       NTSTATUS ret;
 
        /* Connect to remote machine */
        if (!(cli = net_make_ipc_connection(NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC))) {
                return 1;
        }
 
-       if (!cli_nt_session_open(cli, PI_NETLOGON)) {
-               DEBUG(0,("Error connecting to NETLOGON pipe\n"));
-               goto done;
-       }
+       pipe_hnd = cli_rpc_pipe_open_schannel(cli, PI_NETLOGON,
+                                               PIPE_AUTH_LEVEL_PRIVACY,
+                                               domain, &ret);
 
-       if (!secrets_fetch_trust_account_password(domain,
-                                                 stored_md4_trust_password, 
-                                                 NULL, &channel)) {
-               DEBUG(0,("Could not retreive domain trust secret"));
+       if (!pipe_hnd) {
+               DEBUG(0,("Error connecting to NETLOGON pipe. Error was %s\n", nt_errstr(ret) ));
                goto done;
        }
-       
-       /* ensure that schannel uses the right domain */
-       fstrcpy(cli->domain, domain);
-       if (! NT_STATUS_IS_OK(cli_nt_establish_netlogon(cli, channel, stored_md4_trust_password))) {
-               DEBUG(0,("Error in domain join verfication (fresh connection)\n"));
-               goto done;
-       }
-       
+
        retval = 0;             /* Success! */
        
 done:
-       /* Close down pipe - this will clean up open policy handles */
-       if (cli->pipes[cli->pipe_idx].fnum)
-               cli_nt_session_close(cli);
 
        cli_shutdown(cli);
-
        return retval;
 }
 
@@ -103,7 +88,10 @@ int net_rpc_join_newstyle(int argc, const char **argv)
        struct cli_state *cli;
        TALLOC_CTX *mem_ctx;
         uint32 acb_info = ACB_WSTRUST;
+       uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS|NETLOGON_NEG_SCHANNEL;
        uint32 sec_channel_type;
+       struct rpc_pipe_client *pipe_hnd = NULL;
+       struct rpc_pipe_client *netlogon_schannel_pipe = NULL;
 
        /* rpc variables */
 
@@ -151,7 +139,7 @@ int net_rpc_join_newstyle(int argc, const char **argv)
 #endif
        }
 
-       /* Connect to remote machine */
+       /* Make authenticated connection to remote machine */
 
        if (!(cli = net_make_ipc_connection(NET_FLAGS_PDC))) 
                return 1;
@@ -163,38 +151,41 @@ int net_rpc_join_newstyle(int argc, const char **argv)
 
        /* Fetch domain sid */
 
-       if (!cli_nt_session_open(cli, PI_LSARPC)) {
-               DEBUG(0, ("Error connecting to LSA pipe\n"));
+       pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_LSARPC, &result);
+       if (!pipe_hnd) {
+               DEBUG(0, ("Error connecting to LSA pipe. Error was %s\n",
+                       nt_errstr(result) ));
                goto done;
        }
 
 
-       CHECK_RPC_ERR(cli_lsa_open_policy(cli, mem_ctx, True,
+       CHECK_RPC_ERR(rpccli_lsa_open_policy(pipe_hnd, mem_ctx, True,
                                          SEC_RIGHTS_MAXIMUM_ALLOWED,
                                          &lsa_pol),
                      "error opening lsa policy handle");
 
-       CHECK_RPC_ERR(cli_lsa_query_info_policy(cli, mem_ctx, &lsa_pol,
+       CHECK_RPC_ERR(rpccli_lsa_query_info_policy(pipe_hnd, mem_ctx, &lsa_pol,
                                                5, &domain, &domain_sid),
                      "error querying info policy");
 
-       cli_lsa_close(cli, mem_ctx, &lsa_pol);
-
-       cli_nt_session_close(cli); /* Done with this pipe */
+       rpccli_lsa_close(pipe_hnd, mem_ctx, &lsa_pol);
+       cli_rpc_pipe_close(pipe_hnd); /* Done with this pipe */
 
        /* Create domain user */
-       if (!cli_nt_session_open(cli, PI_SAMR)) {
-               DEBUG(0, ("Error connecting to SAM pipe\n"));
+       pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_SAMR, &result);
+       if (!pipe_hnd) {
+               DEBUG(0, ("Error connecting to SAM pipe. Error was %s\n",
+                       nt_errstr(result) ));
                goto done;
        }
 
-       CHECK_RPC_ERR(cli_samr_connect(cli, mem_ctx, 
+       CHECK_RPC_ERR(rpccli_samr_connect(pipe_hnd, mem_ctx, 
                                       SEC_RIGHTS_MAXIMUM_ALLOWED,
                                       &sam_pol),
                      "could not connect to SAM database");
 
        
-       CHECK_RPC_ERR(cli_samr_open_domain(cli, mem_ctx, &sam_pol,
+       CHECK_RPC_ERR(rpccli_samr_open_domain(pipe_hnd, mem_ctx, &sam_pol,
                                           SEC_RIGHTS_MAXIMUM_ALLOWED,
                                           domain_sid, &domain_pol),
                      "could not open domain");
@@ -204,7 +195,7 @@ int net_rpc_join_newstyle(int argc, const char **argv)
        strlower_m(acct_name);
        const_acct_name = acct_name;
 
-       result = cli_samr_create_dom_user(cli, mem_ctx, &domain_pol,
+       result = rpccli_samr_create_dom_user(pipe_hnd, mem_ctx, &domain_pol,
                                          acct_name, acb_info,
                                          0xe005000b, &user_pol, 
                                          &user_rid);
@@ -225,10 +216,11 @@ int net_rpc_join_newstyle(int argc, const char **argv)
 
        /* We *must* do this.... don't ask... */
 
-       if (NT_STATUS_IS_OK(result))
-               cli_samr_close(cli, mem_ctx, &user_pol);
+       if (NT_STATUS_IS_OK(result)) {
+               rpccli_samr_close(pipe_hnd, mem_ctx, &user_pol);
+       }
 
-       CHECK_RPC_ERR_DEBUG(cli_samr_lookup_names(cli, mem_ctx,
+       CHECK_RPC_ERR_DEBUG(rpccli_samr_lookup_names(pipe_hnd, mem_ctx,
                                                  &domain_pol, flags,
                                                  1, &const_acct_name, 
                                                  &num_rids,
@@ -246,7 +238,7 @@ int net_rpc_join_newstyle(int argc, const char **argv)
        /* Open handle on user */
 
        CHECK_RPC_ERR_DEBUG(
-               cli_samr_open_user(cli, mem_ctx, &domain_pol,
+               rpccli_samr_open_user(pipe_hnd, mem_ctx, &domain_pol,
                                   SEC_RIGHTS_MAXIMUM_ALLOWED,
                                   user_rid, &user_pol),
                ("could not re-open existing user %s: %s\n",
@@ -273,7 +265,7 @@ int net_rpc_join_newstyle(int argc, const char **argv)
        ctr.switch_value = 24;
        ctr.info.id24 = &p24;
 
-       CHECK_RPC_ERR(cli_samr_set_userinfo(cli, mem_ctx, &user_pol, 24, 
+       CHECK_RPC_ERR(rpccli_samr_set_userinfo(pipe_hnd, mem_ctx, &user_pol, 24, 
                                            &cli->user_session_key, &ctr),
                      "error setting trust account password");
 
@@ -295,26 +287,52 @@ int net_rpc_join_newstyle(int argc, const char **argv)
        /* Ignoring the return value is necessary for joining a domain
           as a normal user with "Add workstation to domain" privilege. */
 
-       result = cli_samr_set_userinfo2(cli, mem_ctx, &user_pol, 16, 
+       result = rpccli_samr_set_userinfo2(pipe_hnd, mem_ctx, &user_pol, 16, 
                                        &cli->user_session_key, &ctr);
 
+       rpccli_samr_close(pipe_hnd, mem_ctx, &user_pol);
+       cli_rpc_pipe_close(pipe_hnd); /* Done with this pipe */
+
        /* Now check the whole process from top-to-bottom */
-       cli_samr_close(cli, mem_ctx, &user_pol);
-       cli_nt_session_close(cli); /* Done with this pipe */
 
-       if (!cli_nt_session_open(cli, PI_NETLOGON)) {
-               DEBUG(0,("Error connecting to NETLOGON pipe\n"));
+       pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_NETLOGON, &result);
+       if (!pipe_hnd) {
+               DEBUG(0,("Error connecting to NETLOGON pipe. Error was %s\n",
+                       nt_errstr(result) ));
                goto done;
        }
 
-       /* ensure that schannel uses the right domain */
-       fstrcpy(cli->domain, domain);
+       result = rpccli_netlogon_setup_creds(pipe_hnd,
+                                       cli->desthost,
+                                       domain,
+                                       global_myname(),
+                                        md4_trust_password,
+                                        sec_channel_type,
+                                        &neg_flags);
+
+       if (!NT_STATUS_IS_OK(result)) {
+               DEBUG(0, ("Error in domain join verification (credential setup failed): %s\n\n",
+                         nt_errstr(result)));
 
-       result = cli_nt_establish_netlogon(cli, sec_channel_type, 
-                                          md4_trust_password);
+               if ( NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED) &&
+                    (sec_channel_type == SEC_CHAN_BDC) ) {
+                       d_printf("Please make sure that no computer account\n"
+                                "named like this machine (%s) exists in the domain\n",
+                                global_myname());
+               }
+
+               goto done;
+       }
+
+       netlogon_schannel_pipe = cli_rpc_pipe_open_schannel_with_key(cli,
+                                                       PI_NETLOGON,
+                                                       PIPE_AUTH_LEVEL_PRIVACY,
+                                                       domain,
+                                                       pipe_hnd->dc,
+                                                       &result);
 
        if (!NT_STATUS_IS_OK(result)) {
-               DEBUG(0, ("Error domain join verification (reused connection): %s\n\n",
+               DEBUG(0, ("Error in domain join verification (schannel setup failed): %s\n\n",
                          nt_errstr(result)));
 
                if ( NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED) &&
@@ -327,6 +345,9 @@ int net_rpc_join_newstyle(int argc, const char **argv)
                goto done;
        }
 
+       cli_rpc_pipe_close(pipe_hnd);
+       cli_rpc_pipe_close(netlogon_schannel_pipe);
+
        /* Now store the secret in the secrets database */
 
        strupper_m(domain);
@@ -344,10 +365,6 @@ int net_rpc_join_newstyle(int argc, const char **argv)
        retval = net_rpc_join_ok(domain);
        
 done:
-       /* Close down pipe - this will clean up open policy handles */
-
-       if (cli->pipes[cli->pipe_idx].fnum)
-               cli_nt_session_close(cli);
 
        /* Display success or failure */
 
@@ -364,7 +381,6 @@ done:
        return retval;
 }
 
-
 /**
  * check that a join is OK
  *
index e82db46b9f4210cd984b827a5b2172dc301cffe8..d8f3099dec86a53ccd6f129c1ea56da330392d23 100644 (file)
@@ -49,9 +49,11 @@ static const struct table_node archi_table[]= {
  * possibly be removed later on
  *
  **/
+
 /****************************************************************************
-convert a security permissions into a string
+ Convert a security permissions into a string.
 ****************************************************************************/
+
 char *get_sec_mask_str(uint32 type)
 {
        static fstring typestr="";
@@ -86,10 +88,10 @@ char *get_sec_mask_str(uint32 type)
        return typestr;
 }
 
-
 /****************************************************************************
- display sec_ace structure
+ Display sec_ace structure.
  ****************************************************************************/
+
 void display_sec_ace(SEC_ACE *ace)
 {
        fstring sid_str;
@@ -119,10 +121,10 @@ void display_sec_ace(SEC_ACE *ace)
        printf("\t\tSID: %s\n\n", sid_str);
 }
 
-
 /****************************************************************************
- display sec_acl structure
+ Display sec_acl structure.
  ****************************************************************************/
+
 void display_sec_acl(SEC_ACL *sec_acl)
 {
        int i;
@@ -138,8 +140,9 @@ void display_sec_acl(SEC_ACL *sec_acl)
 }
 
 /****************************************************************************
- display sec_desc structure
+ Display sec_desc structure.
  ****************************************************************************/
+
 void display_sec_desc(SEC_DESC *sec)
 {
        fstring sid_str;
@@ -175,8 +178,9 @@ void display_sec_desc(SEC_DESC *sec)
  **/
 
 /****************************************************************************
-printer info level 3 display function
+ Printer info level 3 display function.
 ****************************************************************************/
+
 static void display_print_driver_3(DRIVER_INFO_3 *i1)
 {
        fstring name = "";
@@ -233,7 +237,6 @@ static void display_print_driver_3(DRIVER_INFO_3 *i1)
        return; 
 }
 
-
 static void display_reg_value(const char *subkey, REGISTRY_VALUE value)
 {
        pstring text;
@@ -275,7 +278,6 @@ static void display_reg_value(const char *subkey, REGISTRY_VALUE value)
        
 }
 
-
 /**
  * Copies ACLs, DOS-attributes and timestamps from one 
  * file or directory from one connected share to another connected share 
@@ -292,6 +294,7 @@ static void display_reg_value(const char *subkey, REGISTRY_VALUE value)
  *
  * @return Normal NTSTATUS return.
  **/ 
+
 NTSTATUS net_copy_fileattr(TALLOC_CTX *mem_ctx,
                  struct cli_state *cli_share_src,
                  struct cli_state *cli_share_dst, 
@@ -310,7 +313,6 @@ NTSTATUS net_copy_fileattr(TALLOC_CTX *mem_ctx,
        if (!copy_timestamps && !copy_acls && !copy_attrs)
                return NT_STATUS_OK;
 
-
        /* open file/dir on the originating server */
 
        DEBUGADD(3,("opening %s %s on originating server\n", 
@@ -429,7 +431,6 @@ out:
        return nt_status;
 }
 
-
 /**
  * Copy a file or directory from a connected share to another connected share 
  *
@@ -445,6 +446,7 @@ out:
  *
  * @return Normal NTSTATUS return.
  **/ 
+
 NTSTATUS net_copy_file(TALLOC_CTX *mem_ctx,
                       struct cli_state *cli_share_src,
                       struct cli_state *cli_share_dst, 
@@ -605,7 +607,6 @@ out:
        return nt_status;
 }
 
-
 /**
  * Copy a driverfile from on connected share to another connected share 
  * This silently assumes that a driver-file is picked up from 
@@ -625,6 +626,7 @@ out:
  *
  * @return Normal NTSTATUS return.
  **/ 
+
 static NTSTATUS net_copy_driverfile(TALLOC_CTX *mem_ctx,
                                    struct cli_state *cli_share_src,
                                    struct cli_state *cli_share_dst, 
@@ -673,7 +675,6 @@ out:
        return nt_status;
 }
 
-
 /**
  * Check for existing Architecture directory on a given server
  *
@@ -682,8 +683,8 @@ out:
  *
  * @return Normal NTSTATUS return.
  **/
-static NTSTATUS 
-check_arch_dir(struct cli_state *cli_share, const char *short_archi)
+
+static NTSTATUS check_arch_dir(struct cli_state *cli_share, const char *short_archi)
 {
 
        NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
@@ -715,7 +716,6 @@ out:
        return nt_status;
 }
 
-
 /**
  * Copy a print-driver (level 3) from one connected print$-share to another 
  * connected print$-share
@@ -728,8 +728,8 @@ out:
  *
  * @return Normal NTSTATUS return.
  **/
-static NTSTATUS 
-copy_print_driver_3(TALLOC_CTX *mem_ctx,
+
+static NTSTATUS copy_print_driver_3(TALLOC_CTX *mem_ctx,
                    struct cli_state *cli_share_src, 
                    struct cli_state *cli_share_dst, 
                    const char *short_archi, DRIVER_INFO_3 *i1)
@@ -799,7 +799,6 @@ copy_print_driver_3(TALLOC_CTX *mem_ctx,
        return NT_STATUS_OK;
 }
 
-
 /**
  * net_spoolss-functions
  * =====================
@@ -812,16 +811,18 @@ copy_print_driver_3(TALLOC_CTX *mem_ctx,
  *
  **/
 
-static BOOL
-net_spoolss_enum_printers(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
-                         char *name, uint32 flags, uint32 level, 
-                         uint32 *num_printers, PRINTER_INFO_CTR *ctr)
+static BOOL net_spoolss_enum_printers(struct rpc_pipe_client *pipe_hnd,
+                                       TALLOC_CTX *mem_ctx, 
+                                       char *name,
+                                       uint32 flags,
+                                       uint32 level, 
+                                       uint32 *num_printers,
+                                       PRINTER_INFO_CTR *ctr)
 {
-
        WERROR result;
 
        /* enum printers */
-       result = cli_spoolss_enum_printers(cli, mem_ctx, name, flags,
+       result = rpccli_spoolss_enum_printers(pipe_hnd, mem_ctx, name, flags,
                level, num_printers, ctr);
 
        if (!W_ERROR_IS_OK(result)) {
@@ -832,16 +833,17 @@ net_spoolss_enum_printers(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        return True;
 }
 
-
-static BOOL
-net_spoolss_open_printer_ex(struct cli_state *cli, TALLOC_CTX *mem_ctx,
-                           const char *printername, uint32 access_required, 
-                           const char *username, POLICY_HND *hnd)
+static BOOL net_spoolss_open_printer_ex(struct rpc_pipe_client *pipe_hnd,
+                                       TALLOC_CTX *mem_ctx,
+                                       const char *printername,
+                                       uint32 access_required, 
+                                       const char *username,
+                                       POLICY_HND *hnd)
 {
        WERROR result;
        fstring servername, printername2;
 
-       slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
+       slprintf(servername, sizeof(servername)-1, "\\\\%s", pipe_hnd->cli->desthost);
 
        fstrcpy(printername2, servername);
        fstrcat(printername2, "\\");
@@ -851,7 +853,7 @@ net_spoolss_open_printer_ex(struct cli_state *cli, TALLOC_CTX *mem_ctx,
                servername, username, printername2, access_required));
 
        /* open printer */
-       result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername2,
+       result = rpccli_spoolss_open_printer_ex(pipe_hnd, mem_ctx, printername2,
                        "", access_required,
                        servername, username, hnd);
 
@@ -874,16 +876,16 @@ net_spoolss_open_printer_ex(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        return True;
 }
 
-
-static BOOL
-net_spoolss_getprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx,
-                      POLICY_HND *hnd, uint32 level, 
-                      PRINTER_INFO_CTR *ctr)
+static BOOL net_spoolss_getprinter(struct rpc_pipe_client *pipe_hnd,
+                               TALLOC_CTX *mem_ctx,
+                               POLICY_HND *hnd,
+                               uint32 level, 
+                               PRINTER_INFO_CTR *ctr)
 {
        WERROR result;
 
        /* getprinter call */
-       result = cli_spoolss_getprinter(cli, mem_ctx, hnd, level, ctr);
+       result = rpccli_spoolss_getprinter(pipe_hnd, mem_ctx, hnd, level, ctr);
 
        if (!W_ERROR_IS_OK(result)) {
                printf("cannot get printer-info: %s\n", dos_errstr(result));
@@ -893,16 +895,16 @@ net_spoolss_getprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        return True;
 }
 
-
-static BOOL
-net_spoolss_setprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx,
-                      POLICY_HND *hnd, uint32 level, 
-                      PRINTER_INFO_CTR *ctr)
+static BOOL net_spoolss_setprinter(struct rpc_pipe_client *pipe_hnd,
+                               TALLOC_CTX *mem_ctx,
+                               POLICY_HND *hnd,
+                               uint32 level, 
+                               PRINTER_INFO_CTR *ctr)
 {
        WERROR result;
 
        /* setprinter call */
-       result = cli_spoolss_setprinter(cli, mem_ctx, hnd, level, ctr, 0);
+       result = rpccli_spoolss_setprinter(pipe_hnd, mem_ctx, hnd, level, ctr, 0);
 
        if (!W_ERROR_IS_OK(result)) {
                printf("cannot set printer-info: %s\n", dos_errstr(result));
@@ -913,14 +915,15 @@ net_spoolss_setprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 }
 
 
-static BOOL
-net_spoolss_setprinterdata(struct cli_state *cli, TALLOC_CTX *mem_ctx,
-                          POLICY_HND *hnd, REGISTRY_VALUE *value)
+static BOOL net_spoolss_setprinterdata(struct rpc_pipe_client *pipe_hnd,
+                                       TALLOC_CTX *mem_ctx,
+                                       POLICY_HND *hnd,
+                                       REGISTRY_VALUE *value)
 {
        WERROR result;
        
        /* setprinterdata call */
-       result = cli_spoolss_setprinterdata(cli, mem_ctx, hnd, value);
+       result = rpccli_spoolss_setprinterdata(pipe_hnd, mem_ctx, hnd, value);
 
        if (!W_ERROR_IS_OK(result)) {
                printf ("unable to set printerdata: %s\n", dos_errstr(result));
@@ -931,15 +934,16 @@ net_spoolss_setprinterdata(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 }
 
 
-static BOOL
-net_spoolss_enumprinterkey(struct cli_state *cli, TALLOC_CTX *mem_ctx,
-                          POLICY_HND *hnd, const char *keyname,
-                          uint16 **keylist)
+static BOOL net_spoolss_enumprinterkey(struct rpc_pipe_client *pipe_hnd,
+                                       TALLOC_CTX *mem_ctx,
+                                       POLICY_HND *hnd,
+                                       const char *keyname,
+                                       uint16 **keylist)
 {
        WERROR result;
 
        /* enumprinterkey call */
-       result = cli_spoolss_enumprinterkey(cli, mem_ctx, hnd, keyname, keylist, NULL);
+       result = rpccli_spoolss_enumprinterkey(pipe_hnd, mem_ctx, hnd, keyname, keylist, NULL);
                
        if (!W_ERROR_IS_OK(result)) {
                printf("enumprinterkey failed: %s\n", dos_errstr(result));
@@ -949,17 +953,17 @@ net_spoolss_enumprinterkey(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        return True;
 }
 
-
-static BOOL
-net_spoolss_enumprinterdataex(struct cli_state *cli, TALLOC_CTX *mem_ctx,
-                             uint32 offered, 
-                             POLICY_HND *hnd, const char *keyname, 
-                             REGVAL_CTR *ctr) 
+static BOOL net_spoolss_enumprinterdataex(struct rpc_pipe_client *pipe_hnd,
+                                       TALLOC_CTX *mem_ctx,
+                                       uint32 offered, 
+                                       POLICY_HND *hnd,
+                                       const char *keyname, 
+                                       REGVAL_CTR *ctr) 
 {
        WERROR result;
 
        /* enumprinterdataex call */
-       result = cli_spoolss_enumprinterdataex(cli, mem_ctx, hnd, keyname, ctr);
+       result = rpccli_spoolss_enumprinterdataex(pipe_hnd, mem_ctx, hnd, keyname, ctr);
                        
        if (!W_ERROR_IS_OK(result)) {
                printf("enumprinterdataex failed: %s\n", dos_errstr(result));
@@ -970,15 +974,16 @@ net_spoolss_enumprinterdataex(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 }
 
 
-static BOOL 
-net_spoolss_setprinterdataex(struct cli_state *cli, TALLOC_CTX *mem_ctx,
-                            POLICY_HND *hnd, char *keyname, 
-                            REGISTRY_VALUE *value)
+static BOOL net_spoolss_setprinterdataex(struct rpc_pipe_client *pipe_hnd,
+                                       TALLOC_CTX *mem_ctx,
+                                       POLICY_HND *hnd,
+                                       char *keyname, 
+                                       REGISTRY_VALUE *value)
 {
        WERROR result;
 
        /* setprinterdataex call */
-       result = cli_spoolss_setprinterdataex(cli, mem_ctx, hnd, 
+       result = rpccli_spoolss_setprinterdataex(pipe_hnd, mem_ctx, hnd, 
                                              keyname, value);
        
        if (!W_ERROR_IS_OK(result)) {
@@ -989,17 +994,18 @@ net_spoolss_setprinterdataex(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        return True;
 }
 
-
-static BOOL
-net_spoolss_enumforms(struct cli_state *cli, TALLOC_CTX *mem_ctx,
-                     POLICY_HND *hnd, int level, uint32 *num_forms,
-                     FORM_1 **forms)
+static BOOL net_spoolss_enumforms(struct rpc_pipe_client *pipe_hnd,
+                               TALLOC_CTX *mem_ctx,
+                               POLICY_HND *hnd,
+                               int level,
+                               uint32 *num_forms,
+                               FORM_1 **forms)
                                                                                       
 {
        WERROR result;
 
        /* enumforms call */
-       result = cli_spoolss_enumforms(cli, mem_ctx, hnd, level, num_forms, forms);
+       result = rpccli_spoolss_enumforms(pipe_hnd, mem_ctx, hnd, level, num_forms, forms);
 
        if (!W_ERROR_IS_OK(result)) {
                printf("could not enum forms: %s\n", dos_errstr(result));
@@ -1009,18 +1015,17 @@ net_spoolss_enumforms(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        return True;
 }
 
-
-static BOOL
-net_spoolss_enumprinterdrivers (struct cli_state *cli, TALLOC_CTX *mem_ctx,
-                               uint32 level, const char *env,
-                               uint32 *num_drivers,
-                               PRINTER_DRIVER_CTR *ctr)
+static BOOL net_spoolss_enumprinterdrivers (struct rpc_pipe_client *pipe_hnd,
+                                       TALLOC_CTX *mem_ctx,
+                                       uint32 level, const char *env,
+                                       uint32 *num_drivers,
+                                       PRINTER_DRIVER_CTR *ctr)
 {
        WERROR result;
 
        /* enumprinterdrivers call */
-       result = cli_spoolss_enumprinterdrivers(
-                       cli, mem_ctx, level,
+       result = rpccli_spoolss_enumprinterdrivers(
+                       pipe_hnd, mem_ctx, level,
                        env, num_drivers, ctr);
 
        if (!W_ERROR_IS_OK(result)) {
@@ -1031,9 +1036,7 @@ net_spoolss_enumprinterdrivers (struct cli_state *cli, TALLOC_CTX *mem_ctx,
        return True;
 }
 
-
-static BOOL
-net_spoolss_getprinterdriver(struct cli_state *cli, 
+static BOOL net_spoolss_getprinterdriver(struct rpc_pipe_client *pipe_hnd,
                             TALLOC_CTX *mem_ctx, 
                             POLICY_HND *hnd, uint32 level, 
                             const char *env, int version, 
@@ -1042,8 +1045,8 @@ net_spoolss_getprinterdriver(struct cli_state *cli,
        WERROR result;
        
        /* getprinterdriver call */
-       result = cli_spoolss_getprinterdriver(
-                       cli, mem_ctx, hnd, level,
+       result = rpccli_spoolss_getprinterdriver(
+                       pipe_hnd, mem_ctx, hnd, level,
                        env, version, ctr);
 
        if (!W_ERROR_IS_OK(result)) {
@@ -1060,15 +1063,14 @@ net_spoolss_getprinterdriver(struct cli_state *cli,
 }
 
 
-static BOOL
-net_spoolss_addprinterdriver(struct cli_state *cli, 
+static BOOL net_spoolss_addprinterdriver(struct rpc_pipe_client *pipe_hnd,
                             TALLOC_CTX *mem_ctx, uint32 level,
                             PRINTER_DRIVER_CTR *ctr)
 {
        WERROR result;
 
        /* addprinterdriver call */
-       result = cli_spoolss_addprinterdriver(cli, mem_ctx, level, ctr);
+       result = rpccli_spoolss_addprinterdriver(pipe_hnd, mem_ctx, level, ctr);
 
        /* be more verbose */
        if (W_ERROR_V(result) == W_ERROR_V(WERR_ACCESS_DENIED)) {
@@ -1087,10 +1089,14 @@ net_spoolss_addprinterdriver(struct cli_state *cli,
  * abstraction function to get uint32 num_printers and PRINTER_INFO_CTR ctr 
  * for a single printer or for all printers depending on argc/argv 
  **/
-static BOOL
-get_printer_info(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
-                int level, int argc, const char **argv, 
-                uint32 *num_printers, PRINTER_INFO_CTR *ctr)
+
+static BOOL get_printer_info(struct rpc_pipe_client *pipe_hnd,
+                       TALLOC_CTX *mem_ctx, 
+                       int level,
+                       int argc,
+                       const char **argv, 
+                       uint32 *num_printers,
+                       PRINTER_INFO_CTR *ctr)
 {
 
        POLICY_HND hnd;
@@ -1098,7 +1104,7 @@ get_printer_info(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        /* no arguments given, enumerate all printers */
        if (argc == 0) {
 
-               if (!net_spoolss_enum_printers(cli, mem_ctx, NULL, 
+               if (!net_spoolss_enum_printers(pipe_hnd, mem_ctx, NULL, 
                                PRINTER_ENUM_LOCAL|PRINTER_ENUM_SHARED, 
                                level, num_printers, ctr)) 
                        return False;
@@ -1108,16 +1114,16 @@ get_printer_info(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 
 
        /* argument given, get a single printer by name */
-       if (!net_spoolss_open_printer_ex(cli, mem_ctx, argv[0],
-                       MAXIMUM_ALLOWED_ACCESS, cli->user_name, &hnd)) 
+       if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, argv[0],
+                       MAXIMUM_ALLOWED_ACCESS, pipe_hnd->cli->user_name, &hnd)) 
                return False;
 
-       if (!net_spoolss_getprinter(cli, mem_ctx, &hnd, level, ctr)) {
-               cli_spoolss_close_printer(cli, mem_ctx, &hnd);
+       if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd, level, ctr)) {
+               rpccli_spoolss_close_printer(pipe_hnd, mem_ctx, &hnd);
                return False;
        }
 
-       cli_spoolss_close_printer(cli, mem_ctx, &hnd);
+       rpccli_spoolss_close_printer(pipe_hnd, mem_ctx, &hnd);
 
        *num_printers = 1;
 
@@ -1128,7 +1134,6 @@ out:
 
 }
 
-
 /** 
  * List print-queues (including local printers that are not shared)
  *
@@ -1144,9 +1149,14 @@ out:
  *
  * @return Normal NTSTATUS return.
  **/
-NTSTATUS rpc_printer_list_internals(const DOM_SID *domain_sid, const char *domain_name, 
-                                   struct cli_state *cli, TALLOC_CTX *mem_ctx, 
-                                   int argc, const char **argv)
+
+NTSTATUS rpc_printer_list_internals(const DOM_SID *domain_sid,
+                                       const char *domain_name, 
+                                       struct cli_state *cli,
+                                       struct rpc_pipe_client *pipe_hnd,
+                                       TALLOC_CTX *mem_ctx, 
+                                       int argc,
+                                       const char **argv)
 {
        NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
        uint32 i, num_printers; 
@@ -1156,7 +1166,7 @@ NTSTATUS rpc_printer_list_internals(const DOM_SID *domain_sid, const char *domai
 
        printf("listing printers\n");
 
-       if (!get_printer_info(cli, mem_ctx, level, argc, argv, &num_printers, &ctr))
+       if (!get_printer_info(pipe_hnd, mem_ctx, level, argc, argv, &num_printers, &ctr))
                return nt_status;
 
        for (i = 0; i < num_printers; i++) {
@@ -1174,7 +1184,6 @@ NTSTATUS rpc_printer_list_internals(const DOM_SID *domain_sid, const char *domai
        return NT_STATUS_OK;
 }
 
-
 /** 
  * List printer-drivers from a server 
  *
@@ -1190,9 +1199,14 @@ NTSTATUS rpc_printer_list_internals(const DOM_SID *domain_sid, const char *domai
  *
  * @return Normal NTSTATUS return.
  **/
-NTSTATUS rpc_printer_driver_list_internals(const DOM_SID *domain_sid, const char *domain_name, 
-                                          struct cli_state *cli, TALLOC_CTX *mem_ctx, 
-                                          int argc, const char **argv)
+
+NTSTATUS rpc_printer_driver_list_internals(const DOM_SID *domain_sid,
+                                               const char *domain_name, 
+                                               struct cli_state *cli,
+                                               struct rpc_pipe_client *pipe_hnd,
+                                               TALLOC_CTX *mem_ctx, 
+                                               int argc,
+                                               const char **argv)
 {
        NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
        uint32 i;
@@ -1202,7 +1216,6 @@ NTSTATUS rpc_printer_driver_list_internals(const DOM_SID *domain_sid, const char
        
        ZERO_STRUCT(drv_ctr_enum);
 
-
        printf("listing printer-drivers\n");
 
         for (i=0; archi_table[i].long_archi!=NULL; i++) {
@@ -1210,7 +1223,7 @@ NTSTATUS rpc_printer_driver_list_internals(const DOM_SID *domain_sid, const char
                uint32 num_drivers;
 
                /* enum remote drivers */
-               if (!net_spoolss_enumprinterdrivers(cli, mem_ctx, level,
+               if (!net_spoolss_enumprinterdrivers(pipe_hnd, mem_ctx, level,
                                archi_table[i].long_archi, 
                                &num_drivers, &drv_ctr_enum)) {
                                                                                
@@ -1254,8 +1267,11 @@ done:
  * @return Normal NTSTATUS return.
  **/
 
-static NTSTATUS rpc_printer_publish_internals_args(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
-                                                  int argc, const char **argv, uint32 action)
+static NTSTATUS rpc_printer_publish_internals_args(struct rpc_pipe_client *pipe_hnd,
+                                       TALLOC_CTX *mem_ctx, 
+                                       int argc,
+                                       const char **argv,
+                                       uint32 action)
 {
        NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
        uint32 i, num_printers; 
@@ -1267,7 +1283,7 @@ static NTSTATUS rpc_printer_publish_internals_args(struct cli_state *cli, TALLOC
        WERROR result;
        const char *action_str;
 
-       if (!get_printer_info(cli, mem_ctx, 2, argc, argv, &num_printers, &ctr))
+       if (!get_printer_info(pipe_hnd, mem_ctx, 2, argc, argv, &num_printers, &ctr))
                return nt_status;
 
        for (i = 0; i < num_printers; i++) {
@@ -1279,14 +1295,14 @@ static NTSTATUS rpc_printer_publish_internals_args(struct cli_state *cli, TALLOC
                        sizeof(sharename), -1, STR_TERMINATE);
 
                /* open printer handle */
-               if (!net_spoolss_open_printer_ex(cli, mem_ctx, sharename,
-                       PRINTER_ALL_ACCESS, cli->user_name, &hnd)) 
+               if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
+                       PRINTER_ALL_ACCESS, pipe_hnd->cli->user_name, &hnd)) 
                        goto done;
 
                got_hnd = True;
 
                /* check for existing dst printer */
-               if (!net_spoolss_getprinter(cli, mem_ctx, &hnd, level, &ctr_pub)) 
+               if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd, level, &ctr_pub)) 
                        goto done;
 
                /* check action and set string */
@@ -1308,7 +1324,7 @@ static NTSTATUS rpc_printer_publish_internals_args(struct cli_state *cli, TALLOC
 
                ctr_pub.printers_7->action = action;
 
-               result = cli_spoolss_setprinter(cli, mem_ctx, &hnd, level, &ctr_pub, 0);
+               result = rpccli_spoolss_setprinter(pipe_hnd, mem_ctx, &hnd, level, &ctr_pub, 0);
                if (!W_ERROR_IS_OK(result) && (W_ERROR_V(result) != W_ERROR_V(WERR_IO_PENDING))) {
                        printf("cannot set printer-info: %s\n", dos_errstr(result));
                        goto done;
@@ -1321,30 +1337,42 @@ static NTSTATUS rpc_printer_publish_internals_args(struct cli_state *cli, TALLOC
 
 done:
        if (got_hnd) 
-               cli_spoolss_close_printer(cli, mem_ctx, &hnd);
+               rpccli_spoolss_close_printer(pipe_hnd, mem_ctx, &hnd);
        
        return nt_status;
 }
 
-NTSTATUS rpc_printer_publish_publish_internals(const DOM_SID *domain_sid, const char *domain_name, 
-                                              struct cli_state *cli, TALLOC_CTX *mem_ctx, 
-                                              int argc, const char **argv)
+NTSTATUS rpc_printer_publish_publish_internals(const DOM_SID *domain_sid,
+                                               const char *domain_name, 
+                                               struct cli_state *cli,
+                                               struct rpc_pipe_client *pipe_hnd,
+                                               TALLOC_CTX *mem_ctx, 
+                                               int argc,
+                                               const char **argv)
 {
-       return rpc_printer_publish_internals_args(cli, mem_ctx, argc, argv, SPOOL_DS_PUBLISH);
+       return rpc_printer_publish_internals_args(pipe_hnd, mem_ctx, argc, argv, SPOOL_DS_PUBLISH);
 }
 
-NTSTATUS rpc_printer_publish_unpublish_internals(const DOM_SID *domain_sid, const char *domain_name, 
-                                                struct cli_state *cli, TALLOC_CTX *mem_ctx, 
-                                                int argc, const char **argv)
+NTSTATUS rpc_printer_publish_unpublish_internals(const DOM_SID *domain_sid,
+                                               const char *domain_name, 
+                                               struct cli_state *cli,
+                                               struct rpc_pipe_client *pipe_hnd,
+                                               TALLOC_CTX *mem_ctx, 
+                                               int argc,
+                                               const char **argv)
 {
-       return rpc_printer_publish_internals_args(cli, mem_ctx, argc, argv, SPOOL_DS_UNPUBLISH);
+       return rpc_printer_publish_internals_args(pipe_hnd, mem_ctx, argc, argv, SPOOL_DS_UNPUBLISH);
 }
 
-NTSTATUS rpc_printer_publish_update_internals(const DOM_SID *domain_sid, const char *domain_name, 
-                                             struct cli_state *cli, TALLOC_CTX *mem_ctx, 
-                                             int argc, const char **argv)
+NTSTATUS rpc_printer_publish_update_internals(const DOM_SID *domain_sid,
+                                               const char *domain_name, 
+                                               struct cli_state *cli,
+                                               struct rpc_pipe_client *pipe_hnd,
+                                               TALLOC_CTX *mem_ctx, 
+                                               int argc,
+                                               const char **argv)
 {
-       return rpc_printer_publish_internals_args(cli, mem_ctx, argc, argv, SPOOL_DS_UPDATE);
+       return rpc_printer_publish_internals_args(pipe_hnd, mem_ctx, argc, argv, SPOOL_DS_UPDATE);
 }
 
 /** 
@@ -1362,9 +1390,14 @@ NTSTATUS rpc_printer_publish_update_internals(const DOM_SID *domain_sid, const c
  *
  * @return Normal NTSTATUS return.
  **/
-NTSTATUS rpc_printer_publish_list_internals(const DOM_SID *domain_sid, const char *domain_name, 
-                                           struct cli_state *cli, TALLOC_CTX *mem_ctx,
-                                           int argc, const char **argv)
+
+NTSTATUS rpc_printer_publish_list_internals(const DOM_SID *domain_sid,
+                                               const char *domain_name, 
+                                               struct cli_state *cli,
+                                               struct rpc_pipe_client *pipe_hnd,
+                                               TALLOC_CTX *mem_ctx, 
+                                               int argc,
+                                               const char **argv)
 {
        NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
        uint32 i, num_printers; 
@@ -1376,7 +1409,7 @@ NTSTATUS rpc_printer_publish_list_internals(const DOM_SID *domain_sid, const cha
        BOOL got_hnd = False;
        int state;
 
-       if (!get_printer_info(cli, mem_ctx, 2, argc, argv, &num_printers, &ctr))
+       if (!get_printer_info(pipe_hnd, mem_ctx, 2, argc, argv, &num_printers, &ctr))
                return nt_status;
 
        for (i = 0; i < num_printers; i++) {
@@ -1390,14 +1423,14 @@ NTSTATUS rpc_printer_publish_list_internals(const DOM_SID *domain_sid, const cha
                        sizeof(sharename), -1, STR_TERMINATE);
 
                /* open printer handle */
-               if (!net_spoolss_open_printer_ex(cli, mem_ctx, sharename,
+               if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
                        PRINTER_ALL_ACCESS, cli->user_name, &hnd)) 
                        goto done;
 
                got_hnd = True;
 
                /* check for existing dst printer */
-               if (!net_spoolss_getprinter(cli, mem_ctx, &hnd, level, &ctr_pub)) 
+               if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd, level, &ctr_pub)) 
                        goto done;
 
                rpcstr_pull(guid, ctr_pub.printers_7->guid.buffer, sizeof(guid), -1, STR_TERMINATE);
@@ -1426,7 +1459,7 @@ NTSTATUS rpc_printer_publish_list_internals(const DOM_SID *domain_sid, const cha
 
 done:
        if (got_hnd) 
-               cli_spoolss_close_printer(cli, mem_ctx, &hnd);
+               rpccli_spoolss_close_printer(pipe_hnd, mem_ctx, &hnd);
        
        return nt_status;
 }
@@ -1446,9 +1479,14 @@ done:
  *
  * @return Normal NTSTATUS return.
  **/
-NTSTATUS rpc_printer_migrate_security_internals(const DOM_SID *domain_sid, const char *domain_name, 
-                                               struct cli_state *cli, TALLOC_CTX *mem_ctx, 
-                                               int argc, const char **argv)
+
+NTSTATUS rpc_printer_migrate_security_internals(const DOM_SID *domain_sid,
+                                               const char *domain_name, 
+                                               struct cli_state *cli,
+                                               struct rpc_pipe_client *pipe_hnd,
+                                               TALLOC_CTX *mem_ctx, 
+                                               int argc,
+                                               const char **argv)
 {
        /* TODO: what now, info2 or info3 ? 
           convince jerry that we should add clientside setacls level 3 at least
@@ -1460,7 +1498,7 @@ NTSTATUS rpc_printer_migrate_security_internals(const DOM_SID *domain_sid, const
        pstring printername = "", sharename = "";
        BOOL got_hnd_src = False;
        BOOL got_hnd_dst = False;
-       BOOL got_dst_spoolss_pipe = False;
+       struct rpc_pipe_client *pipe_hnd_dst = NULL;
        POLICY_HND hnd_src, hnd_dst;
        PRINTER_INFO_CTR ctr_src, ctr_dst, ctr_enum;
        struct cli_state *cli_dst = NULL;
@@ -1470,13 +1508,13 @@ NTSTATUS rpc_printer_migrate_security_internals(const DOM_SID *domain_sid, const
        DEBUG(3,("copying printer ACLs\n"));
 
        /* connect destination PI_SPOOLSS */
-       nt_status = connect_dst_pipe(&cli_dst, PI_SPOOLSS, &got_dst_spoolss_pipe);
+       nt_status = connect_dst_pipe(&cli_dst, &pipe_hnd_dst, PI_SPOOLSS);
        if (!NT_STATUS_IS_OK(nt_status))
                return nt_status;
 
 
        /* enum source printers */
-       if (!get_printer_info(cli, mem_ctx, level, argc, argv, &num_printers, &ctr_enum)) {
+       if (!get_printer_info(pipe_hnd, mem_ctx, level, argc, argv, &num_printers, &ctr_enum)) {
                nt_status = NT_STATUS_UNSUCCESSFUL;
                goto done;
        }
@@ -1487,7 +1525,6 @@ NTSTATUS rpc_printer_migrate_security_internals(const DOM_SID *domain_sid, const
                goto done;
        } 
        
-
        /* do something for all printers */
        for (i = 0; i < num_printers; i++) {
 
@@ -1510,30 +1547,27 @@ NTSTATUS rpc_printer_migrate_security_internals(const DOM_SID *domain_sid, const
                */
 
                /* open src printer handle */
-               if (!net_spoolss_open_printer_ex(cli, mem_ctx, sharename,
+               if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
                        MAXIMUM_ALLOWED_ACCESS, cli->user_name, &hnd_src)) 
                        goto done;
 
                got_hnd_src = True;
 
-
                /* open dst printer handle */
-               if (!net_spoolss_open_printer_ex(cli_dst, mem_ctx, sharename,
+               if (!net_spoolss_open_printer_ex(pipe_hnd_dst, mem_ctx, sharename,
                        PRINTER_ALL_ACCESS, cli_dst->user_name, &hnd_dst)) 
                        goto done;
 
                got_hnd_dst = True;
 
-
                /* check for existing dst printer */
-               if (!net_spoolss_getprinter(cli_dst, mem_ctx, &hnd_dst, level, &ctr_dst)) 
+               if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, level, &ctr_dst)) 
                        goto done;
 
                /* check for existing src printer */
-               if (!net_spoolss_getprinter(cli, mem_ctx, &hnd_src, 3, &ctr_src)) 
+               if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd_src, 3, &ctr_src)) 
                        goto done;
 
-
                /* Copy Security Descriptor */
 
                /* copy secdesc (info level 2) */
@@ -1543,7 +1577,7 @@ NTSTATUS rpc_printer_migrate_security_internals(const DOM_SID *domain_sid, const
                if (opt_verbose)
                        display_sec_desc(ctr_dst.printers_2->secdesc);
                
-               if (!net_spoolss_setprinter(cli_dst, mem_ctx, &hnd_dst, 2, &ctr_dst)) 
+               if (!net_spoolss_setprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 2, &ctr_dst)) 
                        goto done;
                
                DEBUGADD(1,("\tSetPrinter of SECDESC succeeded\n"));
@@ -1551,12 +1585,12 @@ NTSTATUS rpc_printer_migrate_security_internals(const DOM_SID *domain_sid, const
 
                /* close printer handles here */
                if (got_hnd_src) {
-                       cli_spoolss_close_printer(cli, mem_ctx, &hnd_src);
+                       rpccli_spoolss_close_printer(pipe_hnd, mem_ctx, &hnd_src);
                        got_hnd_src = False;
                }
 
                if (got_hnd_dst) {
-                       cli_spoolss_close_printer(cli_dst, mem_ctx, &hnd_dst);
+                       rpccli_spoolss_close_printer(pipe_hnd_dst, mem_ctx, &hnd_dst);
                        got_hnd_dst = False;
                }
 
@@ -1566,20 +1600,20 @@ NTSTATUS rpc_printer_migrate_security_internals(const DOM_SID *domain_sid, const
 
 done:
 
-       if (got_hnd_src)
-               cli_spoolss_close_printer(cli, mem_ctx, &hnd_src);
+       if (got_hnd_src) {
+               rpccli_spoolss_close_printer(pipe_hnd, mem_ctx, &hnd_src);
+       }
 
-       if (got_hnd_dst)
-               cli_spoolss_close_printer(cli_dst, mem_ctx, &hnd_dst);
+       if (got_hnd_dst) {
+               rpccli_spoolss_close_printer(pipe_hnd_dst, mem_ctx, &hnd_dst);
+       }
 
-       if (got_dst_spoolss_pipe) {
-               cli_nt_session_close(cli_dst);
+       if (cli_dst) {
                cli_shutdown(cli_dst);
        }
        return nt_status;
 }
 
-
 /** 
  * Migrate printer-forms from a src server to the dst server
  *
@@ -1595,9 +1629,14 @@ done:
  *
  * @return Normal NTSTATUS return.
  **/
-NTSTATUS rpc_printer_migrate_forms_internals(const DOM_SID *domain_sid, const char *domain_name, 
-                                            struct cli_state *cli, TALLOC_CTX *mem_ctx, 
-                                            int argc, const char **argv)
+
+NTSTATUS rpc_printer_migrate_forms_internals(const DOM_SID *domain_sid,
+                                               const char *domain_name, 
+                                               struct cli_state *cli,
+                                               struct rpc_pipe_client *pipe_hnd,
+                                               TALLOC_CTX *mem_ctx, 
+                                               int argc,
+                                               const char **argv)
 {
        NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
        WERROR result;
@@ -1607,7 +1646,7 @@ NTSTATUS rpc_printer_migrate_forms_internals(const DOM_SID *domain_sid, const ch
        pstring printername = "", sharename = "";
        BOOL got_hnd_src = False;
        BOOL got_hnd_dst = False;
-       BOOL got_dst_spoolss_pipe = False;
+       struct rpc_pipe_client *pipe_hnd_dst = NULL;
        POLICY_HND hnd_src, hnd_dst;
        PRINTER_INFO_CTR ctr_enum, ctr_dst;
        uint32 num_forms;
@@ -1619,13 +1658,13 @@ NTSTATUS rpc_printer_migrate_forms_internals(const DOM_SID *domain_sid, const ch
        DEBUG(3,("copying forms\n"));
        
        /* connect destination PI_SPOOLSS */
-       nt_status = connect_dst_pipe(&cli_dst, PI_SPOOLSS, &got_dst_spoolss_pipe);
+       nt_status = connect_dst_pipe(&cli_dst, &pipe_hnd_dst, PI_SPOOLSS);
        if (!NT_STATUS_IS_OK(nt_status))
                return nt_status;
        
 
        /* enum src printers */
-       if (!get_printer_info(cli, mem_ctx, 2, argc, argv, &num_printers, &ctr_enum)) {
+       if (!get_printer_info(pipe_hnd, mem_ctx, 2, argc, argv, &num_printers, &ctr_enum)) {
                nt_status = NT_STATUS_UNSUCCESSFUL;
                goto done;
        }
@@ -1654,7 +1693,7 @@ NTSTATUS rpc_printer_migrate_forms_internals(const DOM_SID *domain_sid, const ch
 
 
                /* open src printer handle */
-               if (!net_spoolss_open_printer_ex(cli, mem_ctx, sharename,
+               if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
                        MAXIMUM_ALLOWED_ACCESS, cli->user_name, &hnd_src)) 
                        goto done;
 
@@ -1662,7 +1701,7 @@ NTSTATUS rpc_printer_migrate_forms_internals(const DOM_SID *domain_sid, const ch
 
 
                /* open dst printer handle */
-               if (!net_spoolss_open_printer_ex(cli_dst, mem_ctx, sharename,
+               if (!net_spoolss_open_printer_ex(pipe_hnd_dst, mem_ctx, sharename,
                        PRINTER_ALL_ACCESS, cli->user_name, &hnd_dst)) 
                        goto done;
 
@@ -1670,11 +1709,11 @@ NTSTATUS rpc_printer_migrate_forms_internals(const DOM_SID *domain_sid, const ch
 
 
                /* check for existing dst printer */
-               if (!net_spoolss_getprinter(cli_dst, mem_ctx, &hnd_dst, level, &ctr_dst)) 
+               if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, level, &ctr_dst)) 
                        goto done;
 
                /* finally migrate forms */
-               if (!net_spoolss_enumforms(cli, mem_ctx, &hnd_src, level, &num_forms, &forms))
+               if (!net_spoolss_enumforms(pipe_hnd, mem_ctx, &hnd_src, level, &num_forms, &forms))
                        goto done;
 
                DEBUG(1,("got %d forms for printer\n", num_forms));
@@ -1711,7 +1750,7 @@ NTSTATUS rpc_printer_migrate_forms_internals(const DOM_SID *domain_sid, const ch
 
                        /* FIXME: there might be something wrong with samba's 
                           builtin-forms */
-                       result = cli_spoolss_addform(cli_dst, mem_ctx, 
+                       result = rpccli_spoolss_addform(pipe_hnd_dst, mem_ctx, 
                                &hnd_dst, 1, &form);
                        if (!W_ERROR_IS_OK(result)) {
                                d_printf("\tAddForm form %d: [%s] refused.\n", 
@@ -1725,12 +1764,12 @@ NTSTATUS rpc_printer_migrate_forms_internals(const DOM_SID *domain_sid, const ch
 
                /* close printer handles here */
                if (got_hnd_src) {
-                       cli_spoolss_close_printer(cli, mem_ctx, &hnd_src);
+                       rpccli_spoolss_close_printer(pipe_hnd, mem_ctx, &hnd_src);
                        got_hnd_src = False;
                }
 
                if (got_hnd_dst) {
-                       cli_spoolss_close_printer(cli_dst, mem_ctx, &hnd_dst);
+                       rpccli_spoolss_close_printer(pipe_hnd_dst, mem_ctx, &hnd_dst);
                        got_hnd_dst = False;
                }
        }
@@ -1740,20 +1779,17 @@ NTSTATUS rpc_printer_migrate_forms_internals(const DOM_SID *domain_sid, const ch
 done:
 
        if (got_hnd_src)
-               cli_spoolss_close_printer(cli, mem_ctx, &hnd_src);
+               rpccli_spoolss_close_printer(pipe_hnd, mem_ctx, &hnd_src);
 
        if (got_hnd_dst)
-               cli_spoolss_close_printer(cli_dst, mem_ctx, &hnd_dst);
+               rpccli_spoolss_close_printer(pipe_hnd_dst, mem_ctx, &hnd_dst);
 
-       if (got_dst_spoolss_pipe) {
-               cli_nt_session_close(cli_dst);
+       if (cli_dst) {
                cli_shutdown(cli_dst);
        }
        return nt_status;
-
 }
 
-
 /** 
  * Migrate printer-drivers from a src server to the dst server
  *
@@ -1769,9 +1805,14 @@ done:
  *
  * @return Normal NTSTATUS return.
  **/
-NTSTATUS rpc_printer_migrate_drivers_internals(const DOM_SID *domain_sid, const char *domain_name, 
-                                              struct cli_state *cli, TALLOC_CTX *mem_ctx, 
-                                              int argc, const char **argv)
+
+NTSTATUS rpc_printer_migrate_drivers_internals(const DOM_SID *domain_sid,
+                                               const char *domain_name, 
+                                               struct cli_state *cli,
+                                               struct rpc_pipe_client *pipe_hnd,
+                                               TALLOC_CTX *mem_ctx, 
+                                               int argc,
+                                               const char **argv)
 {
        NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
        uint32 i, p;
@@ -1780,9 +1821,9 @@ NTSTATUS rpc_printer_migrate_drivers_internals(const DOM_SID *domain_sid, const
        pstring printername = "", sharename = "";
        BOOL got_hnd_src = False;
        BOOL got_hnd_dst = False;
-       BOOL got_dst_spoolss_pipe = False;
        BOOL got_src_driver_share = False;
        BOOL got_dst_driver_share = False;
+       struct rpc_pipe_client *pipe_hnd_dst = NULL;
        POLICY_HND hnd_src, hnd_dst;
        PRINTER_DRIVER_CTR drv_ctr_src, drv_ctr_dst;
        PRINTER_INFO_CTR info_ctr_enum, info_ctr_dst;
@@ -1799,7 +1840,7 @@ NTSTATUS rpc_printer_migrate_drivers_internals(const DOM_SID *domain_sid, const
 
        DEBUG(3,("copying printer-drivers\n"));
 
-       nt_status = connect_dst_pipe(&cli_dst, PI_SPOOLSS, &got_dst_spoolss_pipe);
+       nt_status = connect_dst_pipe(&cli_dst, &pipe_hnd_dst, PI_SPOOLSS);
        if (!NT_STATUS_IS_OK(nt_status))
                return nt_status;
        
@@ -1823,7 +1864,7 @@ NTSTATUS rpc_printer_migrate_drivers_internals(const DOM_SID *domain_sid, const
 
 
        /* enum src printers */
-       if (!get_printer_info(cli, mem_ctx, 2, argc, argv, &num_printers, &info_ctr_enum)) {
+       if (!get_printer_info(pipe_hnd, mem_ctx, 2, argc, argv, &num_printers, &info_ctr_enum)) {
                nt_status = NT_STATUS_UNSUCCESSFUL;
                goto done;
        }
@@ -1851,20 +1892,20 @@ NTSTATUS rpc_printer_migrate_drivers_internals(const DOM_SID *domain_sid, const
                        printername, sharename);
 
                /* open dst printer handle */
-               if (!net_spoolss_open_printer_ex(cli_dst, mem_ctx, sharename,
+               if (!net_spoolss_open_printer_ex(pipe_hnd_dst, mem_ctx, sharename,
                        PRINTER_ALL_ACCESS, cli->user_name, &hnd_dst)) 
                        goto done;
                        
                got_hnd_dst = True;
 
                /* check for existing dst printer */
-               if (!net_spoolss_getprinter(cli_dst, mem_ctx, &hnd_dst, 2, &info_ctr_dst)) 
+               if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 2, &info_ctr_dst)) 
                        goto done;
 
 
                /* open src printer handle */
-               if (!net_spoolss_open_printer_ex(cli, mem_ctx, sharename,
-                       MAXIMUM_ALLOWED_ACCESS, cli->user_name, &hnd_src)) 
+               if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
+                       MAXIMUM_ALLOWED_ACCESS, pipe_hnd->cli->user_name, &hnd_src)) 
                        goto done;
 
                got_hnd_src = True;
@@ -1876,7 +1917,7 @@ NTSTATUS rpc_printer_migrate_drivers_internals(const DOM_SID *domain_sid, const
                for (i=0; archi_table[i].long_archi!=NULL; i++) {
 
                        /* getdriver src */
-                       if (!net_spoolss_getprinterdriver(cli, mem_ctx, &hnd_src, 
+                       if (!net_spoolss_getprinterdriver(pipe_hnd, mem_ctx, &hnd_src, 
                                        level, archi_table[i].long_archi, 
                                        archi_table[i].version, &drv_ctr_src)) 
                                continue;
@@ -1903,7 +1944,7 @@ NTSTATUS rpc_printer_migrate_drivers_internals(const DOM_SID *domain_sid, const
 
 
                        /* adddriver dst */
-                       if (!net_spoolss_addprinterdriver(cli_dst, mem_ctx, level, &drv_ctr_src)) { 
+                       if (!net_spoolss_addprinterdriver(pipe_hnd_dst, mem_ctx, level, &drv_ctr_src)) { 
                                nt_status = NT_STATUS_UNSUCCESSFUL;
                                goto done;
                        }
@@ -1922,7 +1963,7 @@ NTSTATUS rpc_printer_migrate_drivers_internals(const DOM_SID *domain_sid, const
                /* setdriver dst */
                init_unistr(&info_ctr_dst.printers_2->drivername, drivername);
                
-               if (!net_spoolss_setprinter(cli_dst, mem_ctx, &hnd_dst, 2, &info_ctr_dst)) { 
+               if (!net_spoolss_setprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 2, &info_ctr_dst)) { 
                        nt_status = NT_STATUS_UNSUCCESSFUL;
                        goto done;
                }
@@ -1932,13 +1973,13 @@ NTSTATUS rpc_printer_migrate_drivers_internals(const DOM_SID *domain_sid, const
 
                /* close dst */
                if (got_hnd_dst) {
-                       cli_spoolss_close_printer(cli_dst, mem_ctx, &hnd_dst);
+                       rpccli_spoolss_close_printer(pipe_hnd_dst, mem_ctx, &hnd_dst);
                        got_hnd_dst = False;
                }
 
                /* close src */
                if (got_hnd_src) {
-                       cli_spoolss_close_printer(cli, mem_ctx, &hnd_src);
+                       rpccli_spoolss_close_printer(pipe_hnd, mem_ctx, &hnd_src);
                        got_hnd_src = False;
                }
        }
@@ -1948,13 +1989,12 @@ NTSTATUS rpc_printer_migrate_drivers_internals(const DOM_SID *domain_sid, const
 done:
 
        if (got_hnd_src)
-               cli_spoolss_close_printer(cli, mem_ctx, &hnd_src);
+               rpccli_spoolss_close_printer(pipe_hnd, mem_ctx, &hnd_src);
 
        if (got_hnd_dst)
-               cli_spoolss_close_printer(cli_dst, mem_ctx, &hnd_dst);
+               rpccli_spoolss_close_printer(pipe_hnd_dst, mem_ctx, &hnd_dst);
 
-       if (got_dst_spoolss_pipe) {
-               cli_nt_session_close(cli_dst);
+       if (cli_dst) {
                cli_shutdown(cli_dst);
        }
 
@@ -1968,7 +2008,6 @@ done:
 
 }
 
-
 /** 
  * Migrate printer-queues from a src to the dst server
  * (requires a working "addprinter command" to be installed for the local smbd)
@@ -1985,9 +2024,14 @@ done:
  *
  * @return Normal NTSTATUS return.
  **/
-NTSTATUS rpc_printer_migrate_printers_internals(const DOM_SID *domain_sid, const char *domain_name, 
-                                               struct cli_state *cli, TALLOC_CTX *mem_ctx, 
-                                               int argc, const char **argv)
+
+NTSTATUS rpc_printer_migrate_printers_internals(const DOM_SID *domain_sid,
+                                               const char *domain_name, 
+                                               struct cli_state *cli,
+                                               struct rpc_pipe_client *pipe_hnd,
+                                               TALLOC_CTX *mem_ctx, 
+                                               int argc,
+                                               const char **argv)
 {
        WERROR result;
        NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
@@ -1999,18 +2043,18 @@ NTSTATUS rpc_printer_migrate_printers_internals(const DOM_SID *domain_sid, const
        pstring printername, sharename;
        BOOL got_hnd_src = False;
        BOOL got_hnd_dst = False;
-       BOOL got_dst_spoolss_pipe = False;
+       struct rpc_pipe_client *pipe_hnd_dst = NULL;
 
        DEBUG(3,("copying printers\n"));
 
        /* connect destination PI_SPOOLSS */
-       nt_status = connect_dst_pipe(&cli_dst, PI_SPOOLSS, &got_dst_spoolss_pipe);
+       nt_status = connect_dst_pipe(&cli_dst, &pipe_hnd_dst, PI_SPOOLSS);
        if (!NT_STATUS_IS_OK(nt_status))
                return nt_status;
 
 
        /* enum printers */
-       if (!get_printer_info(cli, mem_ctx, level, argc, argv, &num_printers, &ctr_enum)) {
+       if (!get_printer_info(pipe_hnd, mem_ctx, level, argc, argv, &num_printers, &ctr_enum)) {
                nt_status = NT_STATUS_UNSUCCESSFUL;
                goto done;
        }
@@ -2039,7 +2083,7 @@ NTSTATUS rpc_printer_migrate_printers_internals(const DOM_SID *domain_sid, const
 
 
                /* open dst printer handle */
-               if (!net_spoolss_open_printer_ex(cli_dst, mem_ctx, sharename, 
+               if (!net_spoolss_open_printer_ex(pipe_hnd_dst, mem_ctx, sharename, 
                        PRINTER_ALL_ACCESS, cli->user_name, &hnd_dst)) {
                        
                        DEBUG(1,("could not open printer: %s\n", sharename));
@@ -2049,18 +2093,18 @@ NTSTATUS rpc_printer_migrate_printers_internals(const DOM_SID *domain_sid, const
 
 
                /* check for existing dst printer */
-               if (!net_spoolss_getprinter(cli_dst, mem_ctx, &hnd_dst, level, &ctr_dst)) {
+               if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, level, &ctr_dst)) {
                        printf ("could not get printer, creating printer.\n");
                } else {
                        DEBUG(1,("printer already exists: %s\n", sharename));
                        /* close printer handles here */
                        if (got_hnd_src) {
-                               cli_spoolss_close_printer(cli, mem_ctx, &hnd_src);
+                               rpccli_spoolss_close_printer(pipe_hnd, mem_ctx, &hnd_src);
                                got_hnd_src = False;
                        }
 
                        if (got_hnd_dst) {
-                               cli_spoolss_close_printer(cli_dst, mem_ctx, &hnd_dst);
+                               rpccli_spoolss_close_printer(pipe_hnd_dst, mem_ctx, &hnd_dst);
                                got_hnd_dst = False;
                        }
                        continue;
@@ -2071,21 +2115,21 @@ NTSTATUS rpc_printer_migrate_printers_internals(const DOM_SID *domain_sid, const
                   we first need a handle for that */
 
                /* open src printer handle */
-               if (!net_spoolss_open_printer_ex(cli, mem_ctx, sharename,
+               if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
                        MAXIMUM_ALLOWED_ACCESS, cli->user_name, &hnd_src)) 
                        goto done;
 
                got_hnd_src = True;
 
                /* getprinter on the src server */
-               if (!net_spoolss_getprinter(cli, mem_ctx, &hnd_src, level, &ctr_src)) 
+               if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd_src, level, &ctr_src)) 
                        goto done;
 
 
                /* copy each src printer to a dst printer 1:1, 
                   maybe some values have to be changed though */
                d_printf("creating printer: %s\n", printername);
-               result = cli_spoolss_addprinterex (cli_dst, mem_ctx, level, &ctr_src);
+               result = rpccli_spoolss_addprinterex (pipe_hnd_dst, mem_ctx, level, &ctr_src);
 
                if (W_ERROR_IS_OK(result))
                        d_printf ("printer [%s] successfully added.\n", printername);
@@ -2098,12 +2142,12 @@ NTSTATUS rpc_printer_migrate_printers_internals(const DOM_SID *domain_sid, const
 
                /* close printer handles here */
                if (got_hnd_src) {
-                       cli_spoolss_close_printer(cli, mem_ctx, &hnd_src);
+                       rpccli_spoolss_close_printer(pipe_hnd, mem_ctx, &hnd_src);
                        got_hnd_src = False;
                }
 
                if (got_hnd_dst) {
-                       cli_spoolss_close_printer(cli_dst, mem_ctx, &hnd_dst);
+                       rpccli_spoolss_close_printer(pipe_hnd_dst, mem_ctx, &hnd_dst);
                        got_hnd_dst = False;
                }
        }
@@ -2112,19 +2156,17 @@ NTSTATUS rpc_printer_migrate_printers_internals(const DOM_SID *domain_sid, const
 
 done:
        if (got_hnd_src)
-               cli_spoolss_close_printer(cli, mem_ctx, &hnd_src);
+               rpccli_spoolss_close_printer(pipe_hnd, mem_ctx, &hnd_src);
 
        if (got_hnd_dst)
-               cli_spoolss_close_printer(cli_dst, mem_ctx, &hnd_dst);
+               rpccli_spoolss_close_printer(pipe_hnd_dst, mem_ctx, &hnd_dst);
 
-       if (got_dst_spoolss_pipe) {
-               cli_nt_session_close(cli_dst);
+       if (cli_dst) {
                cli_shutdown(cli_dst);
        }
        return nt_status;
 }
 
-
 /** 
  * Migrate Printer-Settings from a src server to the dst server
  * (for this to work, printers and drivers already have to be migrated earlier)
@@ -2141,9 +2183,14 @@ done:
  *
  * @return Normal NTSTATUS return.
  **/
-NTSTATUS rpc_printer_migrate_settings_internals(const DOM_SID *domain_sid, const char *domain_name, 
-                                               struct cli_state *cli, TALLOC_CTX *mem_ctx, 
-                                               int argc, const char **argv)
+
+NTSTATUS rpc_printer_migrate_settings_internals(const DOM_SID *domain_sid,
+                                               const char *domain_name, 
+                                               struct cli_state *cli,
+                                               struct rpc_pipe_client *pipe_hnd,
+                                               TALLOC_CTX *mem_ctx, 
+                                               int argc,
+                                               const char **argv)
 {
 
        /* FIXME: Here the nightmare begins */
@@ -2156,7 +2203,7 @@ NTSTATUS rpc_printer_migrate_settings_internals(const DOM_SID *domain_sid, const
        pstring printername = "", sharename = "";
        BOOL got_hnd_src = False;
        BOOL got_hnd_dst = False;
-       BOOL got_dst_spoolss_pipe = False;
+       struct rpc_pipe_client *pipe_hnd_dst = NULL;
        POLICY_HND hnd_src, hnd_dst;
        PRINTER_INFO_CTR ctr_enum, ctr_dst, ctr_dst_publish;
        REGVAL_CTR *reg_ctr;
@@ -2171,13 +2218,13 @@ NTSTATUS rpc_printer_migrate_settings_internals(const DOM_SID *domain_sid, const
        DEBUG(3,("copying printer settings\n"));
 
        /* connect destination PI_SPOOLSS */
-       nt_status = connect_dst_pipe(&cli_dst, PI_SPOOLSS, &got_dst_spoolss_pipe);
+       nt_status = connect_dst_pipe(&cli_dst, &pipe_hnd_dst, PI_SPOOLSS);
        if (!NT_STATUS_IS_OK(nt_status))
                return nt_status;
 
 
        /* enum src printers */
-       if (!get_printer_info(cli, mem_ctx, level, argc, argv, &num_printers, &ctr_enum)) {
+       if (!get_printer_info(pipe_hnd, mem_ctx, level, argc, argv, &num_printers, &ctr_enum)) {
                nt_status = NT_STATUS_UNSUCCESSFUL;
                goto done;
        }
@@ -2210,7 +2257,7 @@ NTSTATUS rpc_printer_migrate_settings_internals(const DOM_SID *domain_sid, const
 
 
                /* open src printer handle */
-               if (!net_spoolss_open_printer_ex(cli, mem_ctx, sharename,
+               if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename,
                        MAXIMUM_ALLOWED_ACCESS, cli->user_name, &hnd_src)) 
                        goto done;
 
@@ -2218,7 +2265,7 @@ NTSTATUS rpc_printer_migrate_settings_internals(const DOM_SID *domain_sid, const
 
 
                /* open dst printer handle */
-               if (!net_spoolss_open_printer_ex(cli_dst, mem_ctx, sharename,
+               if (!net_spoolss_open_printer_ex(pipe_hnd_dst, mem_ctx, sharename,
                        PRINTER_ALL_ACCESS, cli_dst->user_name, &hnd_dst)) 
                        goto done;
 
@@ -2226,7 +2273,7 @@ NTSTATUS rpc_printer_migrate_settings_internals(const DOM_SID *domain_sid, const
 
 
                /* check for existing dst printer */
-               if (!net_spoolss_getprinter(cli_dst, mem_ctx, &hnd_dst, 
+               if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 
                                level, &ctr_dst)) 
                        goto done;
 
@@ -2245,13 +2292,13 @@ NTSTATUS rpc_printer_migrate_settings_internals(const DOM_SID *domain_sid, const
                if (ctr_enum.printers_2[i].attributes & PRINTER_ATTRIBUTE_PUBLISHED) {
 
                        /* check for existing dst printer */
-                       if (!net_spoolss_getprinter(cli_dst, mem_ctx, &hnd_dst, 7, &ctr_dst_publish))
+                       if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 7, &ctr_dst_publish))
                                goto done;
 
                        ctr_dst_publish.printers_7->action = SPOOL_DS_PUBLISH;
 
                        /* ignore False from setprinter due to WERR_IO_PENDING */
-                       net_spoolss_setprinter(cli_dst, mem_ctx, &hnd_dst, 7, &ctr_dst_publish);
+                       net_spoolss_setprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 7, &ctr_dst_publish);
 
                        DEBUG(3,("republished printer\n"));
                }
@@ -2278,7 +2325,7 @@ NTSTATUS rpc_printer_migrate_settings_internals(const DOM_SID *domain_sid, const
                        init_unistr(&ctr_dst.printers_2->devmode->devicename,
                                    devicename); 
 #endif
-                       if (!net_spoolss_setprinter(cli_dst, mem_ctx, &hnd_dst,
+                       if (!net_spoolss_setprinter(pipe_hnd_dst, mem_ctx, &hnd_dst,
                                                    level, &ctr_dst)) 
                                goto done;
                
@@ -2288,13 +2335,13 @@ NTSTATUS rpc_printer_migrate_settings_internals(const DOM_SID *domain_sid, const
                /* STEP 2: COPY REGISTRY VALUES */
        
                /* please keep in mind that samba parse_spools gives horribly 
-                  crippled results when used to cli_spoolss_enumprinterdataex 
+                  crippled results when used to rpccli_spoolss_enumprinterdataex 
                   a win2k3-server.  (Bugzilla #1851)
                   FIXME: IIRC I've seen it too on a win2k-server 
                */
 
                /* enumerate data on src handle */
-               result = cli_spoolss_enumprinterdata(cli, mem_ctx, &hnd_src, p, 0, 0,
+               result = rpccli_spoolss_enumprinterdata(pipe_hnd, mem_ctx, &hnd_src, p, 0, 0,
                        &val_needed, &data_needed, NULL);
 
                /* loop for all printerdata of "PrinterDriverData" */
@@ -2302,8 +2349,8 @@ NTSTATUS rpc_printer_migrate_settings_internals(const DOM_SID *domain_sid, const
                        
                        REGISTRY_VALUE value;
                        
-                       result = cli_spoolss_enumprinterdata(
-                               cli, mem_ctx, &hnd_src, p++, val_needed,
+                       result = rpccli_spoolss_enumprinterdata(
+                               pipe_hnd, mem_ctx, &hnd_src, p++, val_needed,
                                data_needed, 0, 0, &value);
 
                        /* loop for all reg_keys */
@@ -2314,7 +2361,7 @@ NTSTATUS rpc_printer_migrate_settings_internals(const DOM_SID *domain_sid, const
                                        display_reg_value(SPOOL_PRINTERDATA_KEY, value);
 
                                /* set_value */
-                               if (!net_spoolss_setprinterdata(cli_dst, mem_ctx, 
+                               if (!net_spoolss_setprinterdata(pipe_hnd_dst, mem_ctx, 
                                                                &hnd_dst, &value)) 
                                        goto done;
 
@@ -2330,7 +2377,7 @@ NTSTATUS rpc_printer_migrate_settings_internals(const DOM_SID *domain_sid, const
                   respond to enumprinterkey, win2k does, so continue 
                   in case of an error */
 
-               if (!net_spoolss_enumprinterkey(cli, mem_ctx, &hnd_src, "", &keylist)) {
+               if (!net_spoolss_enumprinterkey(pipe_hnd, mem_ctx, &hnd_src, "", &keylist)) {
                        printf("got no key-data\n");
                        continue;
                }
@@ -2355,7 +2402,7 @@ NTSTATUS rpc_printer_migrate_settings_internals(const DOM_SID *domain_sid, const
                                return NT_STATUS_NO_MEMORY;
 
                        /* enumerate all src subkeys */
-                       if (!net_spoolss_enumprinterdataex(cli, mem_ctx, 0, 
+                       if (!net_spoolss_enumprinterdataex(pipe_hnd, mem_ctx, 0, 
                                                           &hnd_src, subkey, 
                                                           reg_ctr)) 
                                goto done;
@@ -2426,7 +2473,7 @@ NTSTATUS rpc_printer_migrate_settings_internals(const DOM_SID *domain_sid, const
                                                display_reg_value(subkey, value);
 
                                        /* here we have to set all subkeys on the dst server */
-                                       if (!net_spoolss_setprinterdataex(cli_dst, mem_ctx, &hnd_dst, 
+                                       if (!net_spoolss_setprinterdataex(pipe_hnd_dst, mem_ctx, &hnd_dst, 
                                                        subkey, &value)) 
                                                goto done;
                                                        
@@ -2436,7 +2483,7 @@ NTSTATUS rpc_printer_migrate_settings_internals(const DOM_SID *domain_sid, const
                                                display_reg_value(subkey, *(reg_ctr->values[j]));
 
                                        /* here we have to set all subkeys on the dst server */
-                                       if (!net_spoolss_setprinterdataex(cli_dst, mem_ctx, &hnd_dst, 
+                                       if (!net_spoolss_setprinterdataex(pipe_hnd_dst, mem_ctx, &hnd_dst, 
                                                        subkey, reg_ctr->values[j])) 
                                                goto done;
 
@@ -2446,7 +2493,7 @@ NTSTATUS rpc_printer_migrate_settings_internals(const DOM_SID *domain_sid, const
                                                subkey, reg_ctr->values[j]->valuename));
 
                        }
-                                               
+
                        TALLOC_FREE( reg_ctr );
                }
 
@@ -2454,12 +2501,12 @@ NTSTATUS rpc_printer_migrate_settings_internals(const DOM_SID *domain_sid, const
 
                /* close printer handles here */
                if (got_hnd_src) {
-                       cli_spoolss_close_printer(cli, mem_ctx, &hnd_src);
+                       rpccli_spoolss_close_printer(pipe_hnd, mem_ctx, &hnd_src);
                        got_hnd_src = False;
                }
 
                if (got_hnd_dst) {
-                       cli_spoolss_close_printer(cli_dst, mem_ctx, &hnd_dst);
+                       rpccli_spoolss_close_printer(pipe_hnd_dst, mem_ctx, &hnd_dst);
                        got_hnd_dst = False;
                }
 
@@ -2473,13 +2520,12 @@ done:
        SAFE_FREE(unc_name);
 
        if (got_hnd_src)
-               cli_spoolss_close_printer(cli, mem_ctx, &hnd_src);
+               rpccli_spoolss_close_printer(pipe_hnd, mem_ctx, &hnd_src);
 
        if (got_hnd_dst)
-               cli_spoolss_close_printer(cli_dst, mem_ctx, &hnd_dst);
+               rpccli_spoolss_close_printer(pipe_hnd_dst, mem_ctx, &hnd_dst);
 
-       if (got_dst_spoolss_pipe) {
-               cli_nt_session_close(cli_dst);
+       if (cli_dst) {
                cli_shutdown(cli_dst);
        }
        return nt_status;
index 8bb01cd89a87dfca5a23f706736e21902b8a17ba..33ccb6c1b7f0deb7a2c8476e145036a45e30c733 100644 (file)
@@ -22,7 +22,6 @@
 #include "regfio.h"
 #include "reg_objects.h"
 
-
 /********************************************************************
 ********************************************************************/
 
@@ -85,9 +84,13 @@ void dump_regval_buffer( uint32 type, REGVAL_BUFFER *buffer )
 /********************************************************************
 ********************************************************************/
 
-static NTSTATUS rpc_registry_enumerate_internal( const DOM_SID *domain_sid, const char *domain_name, 
-                                           struct cli_state *cli, TALLOC_CTX *mem_ctx, 
-                                           int argc, const char **argv )
+static NTSTATUS rpc_registry_enumerate_internal(const DOM_SID *domain_sid,
+                                               const char *domain_name, 
+                                               struct cli_state *cli,
+                                               struct rpc_pipe_client *pipe_hnd,
+                                               TALLOC_CTX *mem_ctx, 
+                                               int argc,
+                                               const char **argv )
 {
        WERROR result = WERR_GENERAL_FAILURE;
        uint32 hive;
@@ -108,13 +111,13 @@ static NTSTATUS rpc_registry_enumerate_internal( const DOM_SID *domain_sid, cons
        
        /* open the top level hive and then the registry key */
        
-       result = cli_reg_connect( cli, mem_ctx, hive, MAXIMUM_ALLOWED_ACCESS, &pol_hive );
+       result = rpccli_reg_connect(pipe_hnd, mem_ctx, hive, MAXIMUM_ALLOWED_ACCESS, &pol_hive );
        if ( !W_ERROR_IS_OK(result) ) {
                d_printf("Unable to connect to remote registry\n");
                return werror_to_ntstatus(result);
        }
        
-       result = cli_reg_open_entry( cli, mem_ctx, &pol_hive, subpath, MAXIMUM_ALLOWED_ACCESS, &pol_key );
+       result = rpccli_reg_open_entry(pipe_hnd, mem_ctx, &pol_hive, subpath, MAXIMUM_ALLOWED_ACCESS, &pol_key );
        if ( !W_ERROR_IS_OK(result) ) {
                d_printf("Unable to open [%s]\n", argv[0]);
                return werror_to_ntstatus(result);
@@ -128,7 +131,7 @@ static NTSTATUS rpc_registry_enumerate_internal( const DOM_SID *domain_sid, cons
                time_t modtime;
                fstring keyname, classname;
                
-               result = cli_reg_enum_key( cli, mem_ctx, &pol_key, idx, 
+               result = rpccli_reg_enum_key(pipe_hnd, mem_ctx, &pol_key, idx, 
                        keyname, classname, &modtime );
                        
                if ( W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS) ) {
@@ -159,7 +162,7 @@ static NTSTATUS rpc_registry_enumerate_internal( const DOM_SID *domain_sid, cons
                fstrcpy( name, "" );
                ZERO_STRUCT( value );
                
-               result = cli_reg_enum_val( cli, mem_ctx, &pol_key, idx, 
+               result = rpccli_reg_enum_val(pipe_hnd, mem_ctx, &pol_key, idx, 
                        name, &type, &value );
                        
                if ( W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS) ) {
@@ -180,8 +183,8 @@ static NTSTATUS rpc_registry_enumerate_internal( const DOM_SID *domain_sid, cons
 out:
        /* cleanup */
        
-       cli_reg_close( cli, mem_ctx, &pol_key );
-       cli_reg_close( cli, mem_ctx, &pol_hive );
+       rpccli_reg_close(pipe_hnd, mem_ctx, &pol_key );
+       rpccli_reg_close(pipe_hnd, mem_ctx, &pol_hive );
 
        return werror_to_ntstatus(result);
 }
@@ -198,9 +201,13 @@ static int rpc_registry_enumerate( int argc, const char **argv )
 /********************************************************************
 ********************************************************************/
 
-static NTSTATUS rpc_registry_save_internal( const DOM_SID *domain_sid, const char *domain_name, 
-                                           struct cli_state *cli, TALLOC_CTX *mem_ctx, 
-                                           int argc, const char **argv )
+static NTSTATUS rpc_registry_save_internal(const DOM_SID *domain_sid,
+                                       const char *domain_name, 
+                                       struct cli_state *cli,
+                                       struct rpc_pipe_client *pipe_hnd,
+                                       TALLOC_CTX *mem_ctx, 
+                                       int argc,
+                                       const char **argv )
 {
        WERROR result = WERR_GENERAL_FAILURE;
        uint32 hive;
@@ -219,19 +226,19 @@ static NTSTATUS rpc_registry_save_internal( const DOM_SID *domain_sid, const cha
        
        /* open the top level hive and then the registry key */
        
-       result = cli_reg_connect( cli, mem_ctx, hive, MAXIMUM_ALLOWED_ACCESS, &pol_hive );
+       result = rpccli_reg_connect(pipe_hnd, mem_ctx, hive, MAXIMUM_ALLOWED_ACCESS, &pol_hive );
        if ( !W_ERROR_IS_OK(result) ) {
                d_printf("Unable to connect to remote registry\n");
                return werror_to_ntstatus(result);
        }
        
-       result = cli_reg_open_entry( cli, mem_ctx, &pol_hive, subpath, MAXIMUM_ALLOWED_ACCESS, &pol_key );
+       result = rpccli_reg_open_entry(pipe_hnd, mem_ctx, &pol_hive, subpath, MAXIMUM_ALLOWED_ACCESS, &pol_key );
        if ( !W_ERROR_IS_OK(result) ) {
                d_printf("Unable to open [%s]\n", argv[0]);
                return werror_to_ntstatus(result);
        }
        
-       result = cli_reg_save_key( cli, mem_ctx, &pol_key, argv[1] );
+       result = rpccli_reg_save_key(pipe_hnd, mem_ctx, &pol_key, argv[1] );
        if ( !W_ERROR_IS_OK(result) ) {
                d_printf("Unable to save [%s] to %s:%s\n", argv[0], cli->desthost, argv[1]);
        }
@@ -239,8 +246,8 @@ static NTSTATUS rpc_registry_save_internal( const DOM_SID *domain_sid, const cha
        
        /* cleanup */
        
-       cli_reg_close( cli, mem_ctx, &pol_key );
-       cli_reg_close( cli, mem_ctx, &pol_hive );
+       rpccli_reg_close(pipe_hnd, mem_ctx, &pol_key );
+       rpccli_reg_close(pipe_hnd, mem_ctx, &pol_hive );
 
        return werror_to_ntstatus(result);
 }
@@ -490,5 +497,3 @@ int net_rpc_registry(int argc, const char **argv)
                
        return net_help_registry( argc, argv );
 }
-
-
index 3a986ed2516d13ee5a63bf533cbb84af1af9c9f9..a563475ee10fbf28c21997eb40166271ec5677b8 100644 (file)
 /********************************************************************
 ********************************************************************/
 
-static NTSTATUS sid_to_name(struct cli_state *cli, 
-                           TALLOC_CTX *mem_ctx,
-                           DOM_SID *sid, fstring name)
+static NTSTATUS sid_to_name(struct rpc_pipe_client *pipe_hnd,
+                               TALLOC_CTX *mem_ctx,
+                               DOM_SID *sid,
+                               fstring name)
 {
        POLICY_HND pol;
        uint32 *sid_types;
        NTSTATUS result;
        char **domains, **names;
 
-       result = cli_lsa_open_policy(cli, mem_ctx, True, 
+       result = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, True, 
                SEC_RIGHTS_MAXIMUM_ALLOWED, &pol);
                
        if ( !NT_STATUS_IS_OK(result) )
                return result;
 
-       result = cli_lsa_lookup_sids(cli, mem_ctx, &pol, 1, sid, &domains, &names, &sid_types);
+       result = rpccli_lsa_lookup_sids(pipe_hnd, mem_ctx, &pol, 1, sid, &domains, &names, &sid_types);
        
        if ( NT_STATUS_IS_OK(result) ) {
                if ( *domains[0] )
@@ -47,14 +48,14 @@ static NTSTATUS sid_to_name(struct cli_state *cli,
                        fstrcpy( name, names[0] );
        }
 
-       cli_lsa_close(cli, mem_ctx, &pol);
+       rpccli_lsa_close(pipe_hnd, mem_ctx, &pol);
        return result;
 }
 
 /********************************************************************
 ********************************************************************/
 
-static NTSTATUS name_to_sid(struct cli_state *cli, 
+static NTSTATUS name_to_sid(struct rpc_pipe_client *pipe_hnd,
                            TALLOC_CTX *mem_ctx,
                            DOM_SID *sid, const char *name)
 {
@@ -64,31 +65,31 @@ static NTSTATUS name_to_sid(struct cli_state *cli,
        DOM_SID *sids;
 
        /* maybe its a raw SID */
-       if ( strncmp(name, "S-", 2) == 0 && string_to_sid(sid, name) ) 
-       {
+       if ( strncmp(name, "S-", 2) == 0 && string_to_sid(sid, name) ) {
                return NT_STATUS_OK;
        }
 
-       result = cli_lsa_open_policy(cli, mem_ctx, True, 
+       result = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, True, 
                SEC_RIGHTS_MAXIMUM_ALLOWED, &pol);
                
        if ( !NT_STATUS_IS_OK(result) )
                return result;
 
-       result = cli_lsa_lookup_names(cli, mem_ctx, &pol, 1, &name, &sids, &sid_types);
+       result = rpccli_lsa_lookup_names(pipe_hnd, mem_ctx, &pol, 1, &name, &sids, &sid_types);
        
        if ( NT_STATUS_IS_OK(result) )
                sid_copy( sid, &sids[0] );
 
-       cli_lsa_close(cli, mem_ctx, &pol);
+       rpccli_lsa_close(pipe_hnd, mem_ctx, &pol);
        return result;
 }
 
 /********************************************************************
 ********************************************************************/
 
-static NTSTATUS enum_privileges( TALLOC_CTX *ctx, struct cli_state *cli, 
-                                 POLICY_HND *pol )
+static NTSTATUS enum_privileges(struct rpc_pipe_client *pipe_hnd,
+                               TALLOC_CTX *ctx,
+                               POLICY_HND *pol )
 {
        NTSTATUS result;
        uint32 enum_context = 0;
@@ -103,7 +104,7 @@ static NTSTATUS enum_privileges( TALLOC_CTX *ctx, struct cli_state *cli,
        uint16 lang_id_desc;
        fstring description;
 
-       result = cli_lsa_enum_privilege(cli, ctx, pol, &enum_context, 
+       result = rpccli_lsa_enum_privilege(pipe_hnd, ctx, pol, &enum_context, 
                pref_max_length, &count, &privs_name, &privs_high, &privs_low);
 
        if ( !NT_STATUS_IS_OK(result) )
@@ -116,7 +117,7 @@ static NTSTATUS enum_privileges( TALLOC_CTX *ctx, struct cli_state *cli,
                
                /* try to get the description */
                
-               if ( !NT_STATUS_IS_OK(cli_lsa_get_dispname(cli, ctx, pol, 
+               if ( !NT_STATUS_IS_OK(rpccli_lsa_get_dispname(pipe_hnd, ctx, pol, 
                        privs_name[i], lang_id, lang_id_sys, description, &lang_id_desc)) )
                {
                        d_printf("??????\n");
@@ -127,21 +128,23 @@ static NTSTATUS enum_privileges( TALLOC_CTX *ctx, struct cli_state *cli,
        }
 
        return NT_STATUS_OK;
-
 }
 
 /********************************************************************
 ********************************************************************/
 
-static NTSTATUS check_privilege_for_user( TALLOC_CTX *ctx, struct cli_state *cli,
-                                          POLICY_HND *pol, DOM_SID *sid, const char *right)
+static NTSTATUS check_privilege_for_user(struct rpc_pipe_client *pipe_hnd,
+                                       TALLOC_CTX *ctx,
+                                       POLICY_HND *pol,
+                                       DOM_SID *sid,
+                                       const char *right)
 {
        NTSTATUS result;
        uint32 count;
        char **rights;
        int i;
 
-       result = cli_lsa_enum_account_rights(cli, ctx, pol, sid, &count, &rights);
+       result = rpccli_lsa_enum_account_rights(pipe_hnd, ctx, pol, sid, &count, &rights);
 
        if (!NT_STATUS_IS_OK(result)) {
                return result;
@@ -163,15 +166,17 @@ static NTSTATUS check_privilege_for_user( TALLOC_CTX *ctx, struct cli_state *cli
 /********************************************************************
 ********************************************************************/
 
-static NTSTATUS enum_privileges_for_user( TALLOC_CTX *ctx, struct cli_state *cli,
-                                          POLICY_HND *pol, DOM_SID *sid )
+static NTSTATUS enum_privileges_for_user(struct rpc_pipe_client *pipe_hnd,
+                                       TALLOC_CTX *ctx,
+                                       POLICY_HND *pol,
+                                       DOM_SID *sid )
 {
        NTSTATUS result;
        uint32 count;
        char **rights;
        int i;
 
-       result = cli_lsa_enum_account_rights(cli, ctx, pol, sid, &count, &rights);
+       result = rpccli_lsa_enum_account_rights(pipe_hnd, ctx, pol, sid, &count, &rights);
 
        if (!NT_STATUS_IS_OK(result))
                return result;
@@ -189,8 +194,10 @@ static NTSTATUS enum_privileges_for_user( TALLOC_CTX *ctx, struct cli_state *cli
 /********************************************************************
 ********************************************************************/
 
-static NTSTATUS enum_accounts_for_privilege(TALLOC_CTX *ctx, struct cli_state *cli,
-                                           POLICY_HND *pol, const char *privilege)
+static NTSTATUS enum_accounts_for_privilege(struct rpc_pipe_client *pipe_hnd,
+                                               TALLOC_CTX *ctx,
+                                               POLICY_HND *pol,
+                                               const char *privilege)
 {
        NTSTATUS result;
        uint32 enum_context=0;
@@ -200,7 +207,7 @@ static NTSTATUS enum_accounts_for_privilege(TALLOC_CTX *ctx, struct cli_state *c
        int i;
        fstring name;
 
-       result = cli_lsa_enum_sids(cli, ctx, pol, &enum_context, 
+       result = rpccli_lsa_enum_sids(pipe_hnd, ctx, pol, &enum_context, 
                pref_max_length, &count, &sids);
 
        if (!NT_STATUS_IS_OK(result))
@@ -211,7 +218,7 @@ static NTSTATUS enum_accounts_for_privilege(TALLOC_CTX *ctx, struct cli_state *c
        for ( i=0; i<count; i++ ) {
        
                   
-               result = check_privilege_for_user( ctx, cli, pol, &sids[i], privilege);
+               result = check_privilege_for_user( pipe_hnd, ctx, pol, &sids[i], privilege);
                
                if ( ! NT_STATUS_IS_OK(result)) {
                        if ( ! NT_STATUS_EQUAL(result, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
@@ -222,7 +229,7 @@ static NTSTATUS enum_accounts_for_privilege(TALLOC_CTX *ctx, struct cli_state *c
 
                /* try to convert the SID to a name.  Fall back to 
                   printing the raw SID if necessary */
-               result = sid_to_name( cli, ctx, &sids[i], name );
+               result = sid_to_name( pipe_hnd, ctx, &sids[i], name );
                if ( !NT_STATUS_IS_OK (result) )
                        fstrcpy( name, sid_string_static(&sids[i]) );
                        
@@ -235,8 +242,9 @@ static NTSTATUS enum_accounts_for_privilege(TALLOC_CTX *ctx, struct cli_state *c
 /********************************************************************
 ********************************************************************/
 
-static NTSTATUS enum_privileges_for_accounts( TALLOC_CTX *ctx, struct cli_state *cli,
-                                              POLICY_HND *pol )
+static NTSTATUS enum_privileges_for_accounts(struct rpc_pipe_client *pipe_hnd,
+                                               TALLOC_CTX *ctx,
+                                               POLICY_HND *pol)
 {
        NTSTATUS result;
        uint32 enum_context=0;
@@ -246,7 +254,7 @@ static NTSTATUS enum_privileges_for_accounts( TALLOC_CTX *ctx, struct cli_state
        int i;
        fstring name;
 
-       result = cli_lsa_enum_sids(cli, ctx, pol, &enum_context, 
+       result = rpccli_lsa_enum_sids(pipe_hnd, ctx, pol, &enum_context, 
                pref_max_length, &count, &sids);
 
        if (!NT_STATUS_IS_OK(result))
@@ -257,13 +265,13 @@ static NTSTATUS enum_privileges_for_accounts( TALLOC_CTX *ctx, struct cli_state
                /* try to convert the SID to a name.  Fall back to 
                   printing the raw SID if necessary */
                   
-               result = sid_to_name( cli, ctx, &sids[i], name );
+               result = sid_to_name(pipe_hnd, ctx, &sids[i], name );
                if ( !NT_STATUS_IS_OK (result) )
                        fstrcpy( name, sid_string_static(&sids[i]) );
                        
                d_printf("%s\n", name);
                
-               result = enum_privileges_for_user( ctx, cli, pol, &sids[i] );
+               result = enum_privileges_for_user(pipe_hnd, ctx, pol, &sids[i] );
                
                if ( !NT_STATUS_IS_OK(result) )
                        return result;
@@ -277,9 +285,13 @@ static NTSTATUS enum_privileges_for_accounts( TALLOC_CTX *ctx, struct cli_state
 /********************************************************************
 ********************************************************************/
 
-static NTSTATUS rpc_rights_list_internal( const DOM_SID *domain_sid, const char *domain_name, 
-                            struct cli_state *cli, TALLOC_CTX *mem_ctx, 
-                            int argc, const char **argv )
+static NTSTATUS rpc_rights_list_internal(const DOM_SID *domain_sid,
+                                       const char *domain_name, 
+                                       struct cli_state *cli,
+                                       struct rpc_pipe_client *pipe_hnd,
+                                       TALLOC_CTX *mem_ctx, 
+                                       int argc,
+                                       const char **argv )
 {
        POLICY_HND pol;
        NTSTATUS result;
@@ -291,7 +303,7 @@ static NTSTATUS rpc_rights_list_internal( const DOM_SID *domain_sid, const char
        uint16 lang_id_desc;
        
        
-       result = cli_lsa_open_policy(cli, mem_ctx, True, 
+       result = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, True, 
                SEC_RIGHTS_MAXIMUM_ALLOWED, &pol);
 
        if ( !NT_STATUS_IS_OK(result) )
@@ -300,7 +312,7 @@ static NTSTATUS rpc_rights_list_internal( const DOM_SID *domain_sid, const char
        /* backwards compatibility; just list available privileges if no arguement */
           
        if (argc == 0) {
-               result = enum_privileges( mem_ctx, cli, &pol );
+               result = enum_privileges(pipe_hnd, mem_ctx, &pol );
                goto done;
        }
 
@@ -308,18 +320,17 @@ static NTSTATUS rpc_rights_list_internal( const DOM_SID *domain_sid, const char
                int i = 1;
 
                if (argv[1] == NULL) {
-                       result = enum_privileges( mem_ctx, cli, &pol );
+                       result = enum_privileges(pipe_hnd, mem_ctx, &pol );
                        goto done;
                }
 
-               while ( argv[i] != NULL ) 
-               {
+               while ( argv[i] != NULL ) {
                        fstrcpy( privname, argv[i] );
                        i++;
                
                        /* verify that this is a valid privilege for error reporting */
                        
-                       result = cli_lsa_get_dispname(cli, mem_ctx, &pol, privname, lang_id, 
+                       result = rpccli_lsa_get_dispname(pipe_hnd, mem_ctx, &pol, privname, lang_id, 
                                lang_id_sys, description, &lang_id_desc);
                        
                        if ( !NT_STATUS_IS_OK(result) ) {
@@ -330,7 +341,7 @@ static NTSTATUS rpc_rights_list_internal( const DOM_SID *domain_sid, const char
                                continue;
                        }
                        
-                       result = enum_accounts_for_privilege(mem_ctx, cli, &pol, privname);
+                       result = enum_accounts_for_privilege(pipe_hnd, mem_ctx, &pol, privname);
                        if (!NT_STATUS_IS_OK(result)) {
                                d_printf("Error enumerating accounts for privilege %s [%s].\n", 
                                        privname, nt_errstr(result));
@@ -346,16 +357,16 @@ static NTSTATUS rpc_rights_list_internal( const DOM_SID *domain_sid, const char
                int i = 1;
 
                if (argv[1] == NULL) {
-                       result = enum_privileges_for_accounts(mem_ctx, cli, &pol);
+                       result = enum_privileges_for_accounts(pipe_hnd, mem_ctx, &pol);
                        goto done;
                }
 
                while (argv[i] != NULL) {
-                       result = name_to_sid(cli, mem_ctx, &sid, argv[i]);
+                       result = name_to_sid(pipe_hnd, mem_ctx, &sid, argv[i]);
                        if (!NT_STATUS_IS_OK(result)) {
                                goto done;
                        }
-                       result = enum_privileges_for_user(mem_ctx, cli, &pol, &sid);
+                       result = enum_privileges_for_user(pipe_hnd, mem_ctx, &pol, &sid);
                        if (!NT_STATUS_IS_OK(result)) {
                                goto done;
                        }
@@ -372,14 +383,14 @@ static NTSTATUS rpc_rights_list_internal( const DOM_SID *domain_sid, const char
                goto done;
        }
 
-       result = name_to_sid(cli, mem_ctx, &sid, argv[0]);
+       result = name_to_sid(pipe_hnd, mem_ctx, &sid, argv[0]);
        if (!NT_STATUS_IS_OK(result)) {
                goto done;
        }
-       result = enum_privileges_for_user( mem_ctx, cli, &pol, &sid );
+       result = enum_privileges_for_user(pipe_hnd, mem_ctx, &pol, &sid );
 
 done:
-       cli_lsa_close(cli, mem_ctx, &pol);
+       rpccli_lsa_close(pipe_hnd, mem_ctx, &pol);
 
        return result;
 }
@@ -387,9 +398,13 @@ done:
 /********************************************************************
 ********************************************************************/
 
-static NTSTATUS rpc_rights_grant_internal( const DOM_SID *domain_sid, const char *domain_name, 
-                            struct cli_state *cli, TALLOC_CTX *mem_ctx, 
-                            int argc, const char **argv )
+static NTSTATUS rpc_rights_grant_internal(const DOM_SID *domain_sid,
+                                       const char *domain_name, 
+                                       struct cli_state *cli,
+                                       struct rpc_pipe_client *pipe_hnd,
+                                       TALLOC_CTX *mem_ctx, 
+                                       int argc,
+                                       const char **argv )
 {
        POLICY_HND dom_pol;
        NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
@@ -401,18 +416,18 @@ static NTSTATUS rpc_rights_grant_internal( const DOM_SID *domain_sid, const char
                return NT_STATUS_OK;
        }
 
-       result = name_to_sid(cli, mem_ctx, &sid, argv[0]);
+       result = name_to_sid(pipe_hnd, mem_ctx, &sid, argv[0]);
        if (!NT_STATUS_IS_OK(result))
                return result;  
 
-       result = cli_lsa_open_policy2(cli, mem_ctx, True, 
+       result = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, True, 
                                     SEC_RIGHTS_MAXIMUM_ALLOWED,
                                     &dom_pol);
 
        if (!NT_STATUS_IS_OK(result))
                return result;  
 
-       result = cli_lsa_add_account_rights(cli, mem_ctx, &dom_pol, sid, 
+       result = rpccli_lsa_add_account_rights(pipe_hnd, mem_ctx, &dom_pol, sid, 
                                            argc-1, argv+1);
 
        if (!NT_STATUS_IS_OK(result))
@@ -426,7 +441,7 @@ static NTSTATUS rpc_rights_grant_internal( const DOM_SID *domain_sid, const char
                        argv[0], nt_errstr(result));
        }
                
-       cli_lsa_close(cli, mem_ctx, &dom_pol);
+       rpccli_lsa_close(pipe_hnd, mem_ctx, &dom_pol);
        
        return result;
 }
@@ -434,9 +449,13 @@ static NTSTATUS rpc_rights_grant_internal( const DOM_SID *domain_sid, const char
 /********************************************************************
 ********************************************************************/
 
-static NTSTATUS rpc_rights_revoke_internal( const DOM_SID *domain_sid, const char *domain_name, 
-                              struct cli_state *cli, TALLOC_CTX *mem_ctx, 
-                              int argc, const char **argv )
+static NTSTATUS rpc_rights_revoke_internal(const DOM_SID *domain_sid,
+                                       const char *domain_name, 
+                                       struct cli_state *cli,
+                                       struct rpc_pipe_client *pipe_hnd,
+                                       TALLOC_CTX *mem_ctx, 
+                                       int argc,
+                                       const char **argv )
 {
        POLICY_HND dom_pol;
        NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
@@ -448,18 +467,18 @@ static NTSTATUS rpc_rights_revoke_internal( const DOM_SID *domain_sid, const cha
                return NT_STATUS_OK;
        }
 
-       result = name_to_sid(cli, mem_ctx, &sid, argv[0]);
+       result = name_to_sid(pipe_hnd, mem_ctx, &sid, argv[0]);
        if (!NT_STATUS_IS_OK(result))
                return result;  
 
-       result = cli_lsa_open_policy2(cli, mem_ctx, True, 
+       result = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, True, 
                                     SEC_RIGHTS_MAXIMUM_ALLOWED,
                                     &dom_pol);
 
        if (!NT_STATUS_IS_OK(result))
                return result;  
 
-       result = cli_lsa_remove_account_rights(cli, mem_ctx, &dom_pol, sid, 
+       result = rpccli_lsa_remove_account_rights(pipe_hnd, mem_ctx, &dom_pol, sid, 
                                               False, argc-1, argv+1);
 
        if (!NT_STATUS_IS_OK(result))
@@ -473,7 +492,7 @@ done:
                        argv[0], nt_errstr(result));
        }
        
-       cli_lsa_close(cli, mem_ctx, &dom_pol);
+       rpccli_lsa_close(pipe_hnd, mem_ctx, &dom_pol);
 
        return result;
 }      
@@ -541,5 +560,3 @@ int net_rpc_rights(int argc, const char **argv)
                
        return net_help_rights( argc, argv );
 }
-
-
index 403250675a5b7df5d9a455aac422f6a2f8adc3a7..f4a0ab90e8f54c663a942ef5f6f0a93c086af036 100644 (file)
@@ -6,6 +6,7 @@
    Copyright (C) Tim Potter 2001,2002
    Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2005
    Modified by Volker Lendecke 2002
+   Copyright (C) Jeremy Allison 2005.
 
    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
@@ -41,7 +42,6 @@ static void display_group_mem_info(uint32 rid, SAM_GROUP_MEM_INFO *g)
        d_printf("\n");
 }
 
-
 static const char *display_time(NTTIME *nttime)
 {
        static fstring string;
@@ -210,10 +210,9 @@ static void display_sam_entry(SAM_DELTA_HDR *hdr_delta, SAM_DELTA_CTR *delta)
        }
 }
 
-
-static void dump_database(struct cli_state *cli, unsigned db_type, DOM_CRED *ret_creds)
+static void dump_database(struct rpc_pipe_client *pipe_hnd, uint32 db_type)
 {
-       unsigned sync_context = 0;
+       uint32 sync_context = 0;
         NTSTATUS result;
        int i;
         TALLOC_CTX *mem_ctx;
@@ -241,13 +240,12 @@ static void dump_database(struct cli_state *cli, unsigned db_type, DOM_CRED *ret
        }
 
        do {
-               result = cli_netlogon_sam_sync(cli, mem_ctx, ret_creds, db_type,
+               result = rpccli_netlogon_sam_sync(pipe_hnd, mem_ctx, db_type,
                                               sync_context,
                                               &num_deltas, &hdr_deltas, &deltas);
                if (NT_STATUS_IS_ERR(result))
                        break;
 
-               clnt_deal_with_creds(cli->sess_key, &(cli->clnt_cred), ret_creds);
                 for (i = 0; i < num_deltas; i++) {
                        display_sam_entry(&hdr_deltas[i], &deltas[i]);
                 }
@@ -259,41 +257,47 @@ static void dump_database(struct cli_state *cli, unsigned db_type, DOM_CRED *ret
 
 /* dump sam database via samsync rpc calls */
 NTSTATUS rpc_samdump_internals(const DOM_SID *domain_sid, 
-                              const char *domain_name, 
-                              struct cli_state *cli, TALLOC_CTX *mem_ctx, 
-                              int argc, const char **argv) 
+                               const char *domain_name, 
+                               struct cli_state *cli,
+                               struct rpc_pipe_client *pipe_hnd,
+                               TALLOC_CTX *mem_ctx, 
+                               int argc,
+                               const char **argv) 
 {
+#if 0
+       /* net_rpc.c now always tries to create an schannel pipe.. */
+
        NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
        uchar trust_password[16];
-       DOM_CRED ret_creds;
-       uint32 sec_channel;
-
-       ZERO_STRUCT(ret_creds);
-
-       fstrcpy(cli->domain, domain_name);
+       uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS;
+       uint32 sec_channel_type = 0;
 
        if (!secrets_fetch_trust_account_password(domain_name,
                                                  trust_password,
-                                                 NULL, &sec_channel)) {
+                                                 NULL, &sec_channel_type)) {
                DEBUG(0,("Could not fetch trust account password\n"));
                goto fail;
        }
 
-       if (!NT_STATUS_IS_OK(nt_status = cli_nt_establish_netlogon(cli, sec_channel,
-                                                                  trust_password))) {
+       nt_status = rpccli_netlogon_setup_creds(pipe_hnd,
+                                               cli->desthost,
+                                               domain_name,
+                                                global_myname(),
+                                                trust_password,
+                                                sec_channel_type,
+                                                &neg_flags);
+
+       if (!NT_STATUS_IS_OK(nt_status)) {
                DEBUG(0,("Error connecting to NETLOGON pipe\n"));
                goto fail;
        }
+#endif
 
-       dump_database(cli, SAM_DATABASE_DOMAIN, &ret_creds);
-       dump_database(cli, SAM_DATABASE_BUILTIN, &ret_creds);
-       dump_database(cli, SAM_DATABASE_PRIVS, &ret_creds);
-
-        nt_status = NT_STATUS_OK;
+       dump_database(pipe_hnd, SAM_DATABASE_DOMAIN);
+       dump_database(pipe_hnd, SAM_DATABASE_BUILTIN);
+       dump_database(pipe_hnd, SAM_DATABASE_PRIVS);
 
-fail:
-       cli_nt_session_close(cli);
-       return nt_status;
+       return NT_STATUS_OK;
 }
 
 /* Convert a SAM_ACCOUNT_DELTA to a SAM_ACCOUNT. */
@@ -301,8 +305,7 @@ fail:
                    (!old_string && new_string) ||\
                (old_string && new_string && (strcmp(old_string, new_string) != 0))
 
-static NTSTATUS
-sam_account_from_delta(SAM_ACCOUNT *account, SAM_ACCOUNT_INFO *delta)
+static NTSTATUS sam_account_from_delta(SAM_ACCOUNT *account, SAM_ACCOUNT_INFO *delta)
 {
        const char *old_string, *new_string;
        time_t unix_time, stored_time;
@@ -529,7 +532,7 @@ static NTSTATUS fetch_account_info(uint32 rid, SAM_ACCOUNT_INFO *delta)
                        add_ret = smbrun(add_script,NULL);
                        DEBUG(add_ret ? 0 : 1,("fetch_account: Running the command `%s' "
                                 "gave %d\n", add_script, add_ret));
-               } 
+               }
                
                /* try and find the possible unix account again */
                if ( !(passwd = Get_Pwnam(account)) ) {
@@ -590,8 +593,7 @@ static NTSTATUS fetch_account_info(uint32 rid, SAM_ACCOUNT_INFO *delta)
        return nt_ret;
 }
 
-static NTSTATUS
-fetch_group_info(uint32 rid, SAM_GROUP_INFO *delta)
+static NTSTATUS fetch_group_info(uint32 rid, SAM_GROUP_INFO *delta)
 {
        fstring name;
        fstring comment;
@@ -651,8 +653,7 @@ fetch_group_info(uint32 rid, SAM_GROUP_INFO *delta)
        return NT_STATUS_OK;
 }
 
-static NTSTATUS
-fetch_group_mem_info(uint32 rid, SAM_GROUP_MEM_INFO *delta)
+static NTSTATUS fetch_group_mem_info(uint32 rid, SAM_GROUP_MEM_INFO *delta)
 {
        int i;
        TALLOC_CTX *t = NULL;
@@ -832,8 +833,7 @@ static NTSTATUS fetch_alias_info(uint32 rid, SAM_ALIAS_INFO *delta,
        return NT_STATUS_OK;
 }
 
-static NTSTATUS
-fetch_alias_mem(uint32 rid, SAM_ALIAS_MEM_INFO *delta, DOM_SID dom_sid)
+static NTSTATUS fetch_alias_mem(uint32 rid, SAM_ALIAS_MEM_INFO *delta, DOM_SID dom_sid)
 {
 #if 0  /* 
         * commented out right now after talking to Volker.  Can't
@@ -998,42 +998,41 @@ static NTSTATUS fetch_domain_info(uint32 rid, SAM_DOMAIN_INFO *delta)
        }
 
 
-       if (!account_policy_set(AP_PASSWORD_HISTORY, delta->pwd_history_len))
+       if (!pdb_set_account_policy(AP_PASSWORD_HISTORY, delta->pwd_history_len))
                return nt_status;
 
-       if (!account_policy_set(AP_MIN_PASSWORD_LEN, delta->min_pwd_len))
+       if (!pdb_set_account_policy(AP_MIN_PASSWORD_LEN, delta->min_pwd_len))
                return nt_status;
 
-       if (!account_policy_set(AP_MAX_PASSWORD_AGE, (uint32)u_max_age))
+       if (!pdb_set_account_policy(AP_MAX_PASSWORD_AGE, (uint32)u_max_age))
                return nt_status;
 
-       if (!account_policy_set(AP_MIN_PASSWORD_AGE, (uint32)u_min_age))
+       if (!pdb_set_account_policy(AP_MIN_PASSWORD_AGE, (uint32)u_min_age))
                return nt_status;
 
-       if (!account_policy_set(AP_TIME_TO_LOGOUT, (uint32)u_logout))
+       if (!pdb_set_account_policy(AP_TIME_TO_LOGOUT, (uint32)u_logout))
                return nt_status;
 
-       if (!account_policy_set(AP_BAD_ATTEMPT_LOCKOUT, delta->account_lockout.bad_attempt_lockout))
+       if (!pdb_set_account_policy(AP_BAD_ATTEMPT_LOCKOUT, delta->account_lockout.bad_attempt_lockout))
                return nt_status;
 
-       if (!account_policy_set(AP_RESET_COUNT_TIME, (uint32)u_lockoutreset/60))
+       if (!pdb_set_account_policy(AP_RESET_COUNT_TIME, (uint32)u_lockoutreset/60))
                return nt_status;
 
        if (u_lockouttime != -1)
                u_lockouttime /= 60;
 
-       if (!account_policy_set(AP_LOCK_ACCOUNT_DURATION, (uint32)u_lockouttime))
+       if (!pdb_set_account_policy(AP_LOCK_ACCOUNT_DURATION, (uint32)u_lockouttime))
                return nt_status;
 
-       if (!account_policy_set(AP_USER_MUST_LOGON_TO_CHG_PASS, delta->logon_chgpass))
+       if (!pdb_set_account_policy(AP_USER_MUST_LOGON_TO_CHG_PASS, delta->logon_chgpass))
                return nt_status;
 
        return NT_STATUS_OK;
 }
 
 
-static void
-fetch_sam_entry(SAM_DELTA_HDR *hdr_delta, SAM_DELTA_CTR *delta,
+static void fetch_sam_entry(SAM_DELTA_HDR *hdr_delta, SAM_DELTA_CTR *delta,
                DOM_SID dom_sid)
 {
        switch(hdr_delta->type) {
@@ -1098,11 +1097,9 @@ fetch_sam_entry(SAM_DELTA_HDR *hdr_delta, SAM_DELTA_CTR *delta,
        }
 }
 
-static NTSTATUS
-fetch_database(struct cli_state *cli, unsigned db_type, DOM_CRED *ret_creds,
-              DOM_SID dom_sid)
+static NTSTATUS fetch_database(struct rpc_pipe_client *pipe_hnd, uint32 db_type, DOM_SID dom_sid)
 {
-       unsigned sync_context = 0;
+       uint32 sync_context = 0;
         NTSTATUS result;
        int i;
         TALLOC_CTX *mem_ctx;
@@ -1129,17 +1126,13 @@ fetch_database(struct cli_state *cli, unsigned db_type, DOM_CRED *ret_creds,
        }
 
        do {
-               result = cli_netlogon_sam_sync(cli, mem_ctx, ret_creds,
+               result = rpccli_netlogon_sam_sync(pipe_hnd, mem_ctx,
                                               db_type, sync_context,
                                               &num_deltas,
                                               &hdr_deltas, &deltas);
 
                if (NT_STATUS_IS_OK(result) ||
                    NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) {
-
-                       clnt_deal_with_creds(cli->sess_key, &(cli->clnt_cred),
-                                            ret_creds);
-
                        for (i = 0; i < num_deltas; i++) {
                                fetch_sam_entry(&hdr_deltas[i], &deltas[i], dom_sid);
                        }
@@ -1154,8 +1147,7 @@ fetch_database(struct cli_state *cli, unsigned db_type, DOM_CRED *ret_creds,
        return result;
 }
 
-static NTSTATUS
-populate_ldap_for_ldif(fstring sid, const char *suffix, const char 
+static NTSTATUS populate_ldap_for_ldif(fstring sid, const char *suffix, const char 
                       *builtin_sid, FILE *add_fd)
 {
        char *user_suffix, *group_suffix, *machine_suffix, *idmap_suffix;
@@ -1448,8 +1440,7 @@ populate_ldap_for_ldif(fstring sid, const char *suffix, const char
        return NT_STATUS_OK;
 }
 
-static NTSTATUS
-map_populate_groups(GROUPMAP *groupmap, ACCOUNTMAP *accountmap, fstring sid, 
+static NTSTATUS map_populate_groups(GROUPMAP *groupmap, ACCOUNTMAP *accountmap, fstring sid, 
                    const char *suffix, const char *builtin_sid)
 {
        char *group_attr = sstring_sub(lp_ldap_group_suffix(), '=', ',');
@@ -1521,8 +1512,7 @@ map_populate_groups(GROUPMAP *groupmap, ACCOUNTMAP *accountmap, fstring sid,
        return NT_STATUS_OK;
 }
 
-static NTSTATUS
-fetch_group_info_to_ldif(SAM_DELTA_CTR *delta, GROUPMAP *groupmap,
+static NTSTATUS fetch_group_info_to_ldif(SAM_DELTA_CTR *delta, GROUPMAP *groupmap,
                         FILE *add_fd, fstring sid, char *suffix)
 {
        fstring groupname;
@@ -1579,8 +1569,7 @@ fetch_group_info_to_ldif(SAM_DELTA_CTR *delta, GROUPMAP *groupmap,
        return NT_STATUS_OK;
 }
 
-static NTSTATUS
-fetch_account_info_to_ldif(SAM_DELTA_CTR *delta, GROUPMAP *groupmap,
+static NTSTATUS fetch_account_info_to_ldif(SAM_DELTA_CTR *delta, GROUPMAP *groupmap,
                           ACCOUNTMAP *accountmap, FILE *add_fd,
                           fstring sid, char *suffix, int alloced)
 {
@@ -1724,8 +1713,7 @@ fetch_account_info_to_ldif(SAM_DELTA_CTR *delta, GROUPMAP *groupmap,
        return NT_STATUS_OK;
 }
 
-static NTSTATUS
-fetch_alias_info_to_ldif(SAM_DELTA_CTR *delta, GROUPMAP *groupmap,
+static NTSTATUS fetch_alias_info_to_ldif(SAM_DELTA_CTR *delta, GROUPMAP *groupmap,
                         FILE *add_fd, fstring sid, char *suffix, 
                         unsigned db_type)
 {
@@ -1798,8 +1786,7 @@ fetch_alias_info_to_ldif(SAM_DELTA_CTR *delta, GROUPMAP *groupmap,
        return NT_STATUS_OK;
 }
 
-static NTSTATUS
-fetch_groupmem_info_to_ldif(SAM_DELTA_CTR *delta, SAM_DELTA_HDR *hdr_delta,
+static NTSTATUS fetch_groupmem_info_to_ldif(SAM_DELTA_CTR *delta, SAM_DELTA_HDR *hdr_delta,
                            GROUPMAP *groupmap, ACCOUNTMAP *accountmap, 
                            FILE *mod_fd, int alloced)
 {
@@ -1841,16 +1828,16 @@ fetch_groupmem_info_to_ldif(SAM_DELTA_CTR *delta, SAM_DELTA_HDR *hdr_delta,
        return NT_STATUS_OK;
 }
 
-static NTSTATUS
-fetch_database_to_ldif(struct cli_state *cli, unsigned db_type, 
-                       DOM_CRED *ret_creds, DOM_SID dom_sid,
-                      const char *user_file)
+static NTSTATUS fetch_database_to_ldif(struct rpc_pipe_client *pipe_hnd,
+                                       uint32 db_type,
+                                       DOM_SID dom_sid,
+                                       const char *user_file)
 {
        char *suffix;
        const char *builtin_sid = "S-1-5-32";
        char *ldif_file;
        fstring sid, domainname;
-       unsigned sync_context = 0;
+       uint32 sync_context = 0;
        NTSTATUS result;
        int k;
        TALLOC_CTX *mem_ctx;
@@ -1956,7 +1943,7 @@ fetch_database_to_ldif(struct cli_state *cli, unsigned db_type,
        }
 
        do {
-               result = cli_netlogon_sam_sync(cli, mem_ctx, ret_creds,
+               result = rpccli_netlogon_sam_sync(pipe_hnd, mem_ctx,
                                               db_type, sync_context,
                                               &num_deltas, &hdr_deltas, 
                                               &deltas);
@@ -1965,9 +1952,6 @@ fetch_database_to_ldif(struct cli_state *cli, unsigned db_type,
                        return NT_STATUS_OK;
                }
 
-               clnt_deal_with_creds(cli->sess_key, &(cli->clnt_cred),
-                                    ret_creds);
-
                /* Re-allocate memory for groupmap and accountmap arrays */
                groupmap = SMB_REALLOC_ARRAY(groupmap, GROUPMAP,
                                        num_deltas+num_alloced);
@@ -2138,18 +2122,16 @@ int rpc_vampire_usage(int argc, const char **argv)
 
 /* dump sam database via samsync rpc calls */
 NTSTATUS rpc_vampire_internals(const DOM_SID *domain_sid, 
-                              const char *domain_name, 
-                              struct cli_state *cli, TALLOC_CTX *mem_ctx, 
-                              int argc, const char **argv) 
+                               const char *domain_name, 
+                               struct cli_state *cli,
+                               struct rpc_pipe_client *pipe_hnd,
+                               TALLOC_CTX *mem_ctx, 
+                               int argc,
+                               const char **argv) 
 {
         NTSTATUS result;
-       uchar trust_password[16];
-       DOM_CRED ret_creds;
        fstring my_dom_sid_str;
        fstring rem_dom_sid_str;
-       uint32 sec_channel;
-
-       ZERO_STRUCT(ret_creds);
 
        if (!sid_equal(domain_sid, get_global_sam_sid())) {
                d_printf("Cannot import users from %s at this time, "
@@ -2164,29 +2146,11 @@ NTSTATUS rpc_vampire_internals(const DOM_SID *domain_sid,
                return NT_STATUS_UNSUCCESSFUL;
        }
 
-       fstrcpy(cli->domain, domain_name);
-
-       if (!secrets_fetch_trust_account_password(domain_name,
-                                                 trust_password, NULL,
-                                                 &sec_channel)) {
-               result = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
-               d_printf("Could not retrieve domain trust secret\n");
-               goto fail;
-       }
-       
-       result = cli_nt_establish_netlogon(cli, sec_channel, trust_password);
-
-       if (!NT_STATUS_IS_OK(result)) {
-               d_printf("Failed to setup BDC creds\n");
-               goto fail;
-       }
-
         if (argc >= 1 && (strcmp(argv[0], "ldif") == 0)) {
-               result = fetch_database_to_ldif(cli, SAM_DATABASE_DOMAIN,
-                                       &ret_creds, *domain_sid, argv[1]);
+               result = fetch_database_to_ldif(pipe_hnd, SAM_DATABASE_DOMAIN,
+                                       *domain_sid, argv[1]);
         } else {
-               result = fetch_database(cli, SAM_DATABASE_DOMAIN, &ret_creds,
-                                       *domain_sid);
+               result = fetch_database(pipe_hnd, SAM_DATABASE_DOMAIN, *domain_sid);
         }
 
        if (!NT_STATUS_IS_OK(result)) {
@@ -2199,12 +2163,10 @@ NTSTATUS rpc_vampire_internals(const DOM_SID *domain_sid,
        }
 
         if (argc >= 1 && (strcmp(argv[0], "ldif") == 0)) {
-               result = fetch_database_to_ldif(cli, SAM_DATABASE_BUILTIN, 
-                                            &ret_creds, global_sid_Builtin,
-                                           argv[1]);
+               result = fetch_database_to_ldif(pipe_hnd, SAM_DATABASE_BUILTIN, 
+                                       global_sid_Builtin, argv[1]);
         } else {
-               result = fetch_database(cli, SAM_DATABASE_BUILTIN, &ret_creds, 
-                                           global_sid_Builtin);
+               result = fetch_database(pipe_hnd, SAM_DATABASE_BUILTIN, global_sid_Builtin);
         }
 
        if (!NT_STATUS_IS_OK(result)) {
@@ -2219,4 +2181,3 @@ NTSTATUS rpc_vampire_internals(const DOM_SID *domain_sid,
 fail:
        return result;
 }
-
index 8f93ab3d060842f6f45f01c806f25a0e9adcf946..3cc4790884cc10e1802371b60a815cf88fe4a507 100644 (file)
 /********************************************************************
 ********************************************************************/
 
-static WERROR query_service_state( struct cli_state *cli, TALLOC_CTX *mem_ctx, 
-                             POLICY_HND *hSCM, const char *service, uint32 *state )
+static WERROR query_service_state(struct rpc_pipe_client *pipe_hnd,
+                               TALLOC_CTX *mem_ctx, 
+                               POLICY_HND *hSCM,
+                               const char *service,
+                               uint32 *state )
 {
        POLICY_HND hService;
        SERVICE_STATUS service_status;
@@ -33,7 +36,7 @@ static WERROR query_service_state( struct cli_state *cli, TALLOC_CTX *mem_ctx,
        
        /* now cycle until the status is actually 'watch_state' */
        
-       result = cli_svcctl_open_service( cli, mem_ctx, hSCM, &hService, 
+       result = rpccli_svcctl_open_service(pipe_hnd, mem_ctx, hSCM, &hService, 
                service, SC_RIGHT_SVC_QUERY_STATUS );
 
        if ( !W_ERROR_IS_OK(result) ) {
@@ -41,12 +44,12 @@ static WERROR query_service_state( struct cli_state *cli, TALLOC_CTX *mem_ctx,
                return result;
        }
 
-       result = cli_svcctl_query_status( cli, mem_ctx, &hService, &service_status  );
+       result = rpccli_svcctl_query_status(pipe_hnd, mem_ctx, &hService, &service_status  );
        if ( W_ERROR_IS_OK(result) ) {
                *state = service_status.state;
        }
        
-       cli_svcctl_close_service( cli, mem_ctx, &hService );
+       rpccli_svcctl_close_service(pipe_hnd, mem_ctx, &hService );
        
        return result;
 }
@@ -54,9 +57,12 @@ static WERROR query_service_state( struct cli_state *cli, TALLOC_CTX *mem_ctx,
 /********************************************************************
 ********************************************************************/
 
-static WERROR watch_service_state( struct cli_state *cli, TALLOC_CTX *mem_ctx, 
-                                   POLICY_HND *hSCM, const char *service, 
-                                  uint32 watch_state, uint32 *final_state )
+static WERROR watch_service_state(struct rpc_pipe_client *pipe_hnd,
+                               TALLOC_CTX *mem_ctx, 
+                               POLICY_HND *hSCM,
+                               const char *service, 
+                               uint32 watch_state,
+                               uint32 *final_state )
 {
        uint32 i;
        uint32 state = 0;
@@ -67,7 +73,7 @@ static WERROR watch_service_state( struct cli_state *cli, TALLOC_CTX *mem_ctx,
        while ( (state != watch_state ) && i<30 ) {
                /* get the status */
 
-               result = query_service_state( cli, mem_ctx, hSCM, service, &state  );
+               result = query_service_state(pipe_hnd, mem_ctx, hSCM, service, &state  );
                if ( !W_ERROR_IS_OK(result) ) {
                        break;
                }
@@ -86,9 +92,12 @@ static WERROR watch_service_state( struct cli_state *cli, TALLOC_CTX *mem_ctx,
 /********************************************************************
 ********************************************************************/
 
-static WERROR control_service( struct cli_state *cli, TALLOC_CTX *mem_ctx, 
-                             POLICY_HND *hSCM, const char *service, 
-                            uint32 control, uint32 watch_state )
+static WERROR control_service(struct rpc_pipe_client *pipe_hnd,
+                               TALLOC_CTX *mem_ctx, 
+                               POLICY_HND *hSCM,
+                               const char *service, 
+                               uint32 control,
+                               uint32 watch_state )
 {
        POLICY_HND hService;
        WERROR result = WERR_GENERAL_FAILURE;
@@ -97,7 +106,7 @@ static WERROR control_service( struct cli_state *cli, TALLOC_CTX *mem_ctx,
        
        /* Open the Service */
        
-       result = cli_svcctl_open_service( cli, mem_ctx, hSCM, &hService, 
+       result = rpccli_svcctl_open_service(pipe_hnd, mem_ctx, hSCM, &hService, 
                service, (SC_RIGHT_SVC_STOP|SC_RIGHT_SVC_PAUSE_CONTINUE) );
 
        if ( !W_ERROR_IS_OK(result) ) {
@@ -107,7 +116,7 @@ static WERROR control_service( struct cli_state *cli, TALLOC_CTX *mem_ctx,
        
        /* get the status */
 
-       result = cli_svcctl_control_service( cli, mem_ctx, &hService, 
+       result = rpccli_svcctl_control_service(pipe_hnd, mem_ctx, &hService, 
                control, &service_status  );
                
        if ( !W_ERROR_IS_OK(result) ) {
@@ -117,12 +126,12 @@ static WERROR control_service( struct cli_state *cli, TALLOC_CTX *mem_ctx,
        
        /* loop -- checking the state until we are where we want to be */
        
-       result = watch_service_state( cli, mem_ctx, hSCM, service, watch_state, &state );
+       result = watch_service_state(pipe_hnd, mem_ctx, hSCM, service, watch_state, &state );
                
        d_printf("%s service is %s.\n", service, svc_status_string(state));
 
 done:  
-       cli_svcctl_close_service( cli, mem_ctx, &hService  );
+       rpccli_svcctl_close_service(pipe_hnd, mem_ctx, &hService  );
                
        return result;
 }      
@@ -130,9 +139,13 @@ done:
 /********************************************************************
 ********************************************************************/
 
-static NTSTATUS rpc_service_list_internal( const DOM_SID *domain_sid, const char *domain_name, 
-                                           struct cli_state *cli, TALLOC_CTX *mem_ctx, 
-                                           int argc, const char **argv )
+static NTSTATUS rpc_service_list_internal(const DOM_SID *domain_sid,
+                                       const char *domain_name, 
+                                       struct cli_state *cli,
+                                       struct rpc_pipe_client *pipe_hnd,
+                                       TALLOC_CTX *mem_ctx, 
+                                       int argc,
+                                       const char **argv )
 {
        POLICY_HND hSCM;
        ENUM_SERVICES_STATUS *services;
@@ -147,13 +160,13 @@ static NTSTATUS rpc_service_list_internal( const DOM_SID *domain_sid, const char
                return NT_STATUS_OK;
        }
 
-       result = cli_svcctl_open_scm( cli, mem_ctx, &hSCM, SC_RIGHT_MGR_ENUMERATE_SERVICE  );
+       result = rpccli_svcctl_open_scm(pipe_hnd, mem_ctx, &hSCM, SC_RIGHT_MGR_ENUMERATE_SERVICE  );
        if ( !W_ERROR_IS_OK(result) ) {
                d_printf("Failed to open Service Control Manager.  [%s]\n", dos_errstr(result));
                return werror_to_ntstatus(result);
        }
        
-       result = cli_svcctl_enumerate_services( cli, mem_ctx, &hSCM, SVCCTL_TYPE_WIN32,
+       result = rpccli_svcctl_enumerate_services(pipe_hnd, mem_ctx, &hSCM, SVCCTL_TYPE_WIN32,
                SVCCTL_STATE_ALL, &num_services, &services );
        
        if ( !W_ERROR_IS_OK(result) ) {
@@ -172,7 +185,7 @@ static NTSTATUS rpc_service_list_internal( const DOM_SID *domain_sid, const char
        }
 
 done:  
-       cli_svcctl_close_service( cli, mem_ctx, &hSCM  );
+       rpccli_svcctl_close_service(pipe_hnd, mem_ctx, &hSCM  );
                
        return werror_to_ntstatus(result);
 }      
@@ -180,9 +193,13 @@ done:
 /********************************************************************
 ********************************************************************/
 
-static NTSTATUS rpc_service_status_internal( const DOM_SID *domain_sid, const char *domain_name, 
-                                           struct cli_state *cli, TALLOC_CTX *mem_ctx, 
-                                           int argc, const char **argv )
+static NTSTATUS rpc_service_status_internal(const DOM_SID *domain_sid,
+                                               const char *domain_name, 
+                                               struct cli_state *cli,
+                                               struct rpc_pipe_client *pipe_hnd,
+                                               TALLOC_CTX *mem_ctx, 
+                                               int argc,
+                                               const char **argv )
 {
        POLICY_HND hSCM, hService;
        WERROR result = WERR_GENERAL_FAILURE;
@@ -200,7 +217,7 @@ static NTSTATUS rpc_service_status_internal( const DOM_SID *domain_sid, const ch
 
        /* Open the Service Control Manager */
        
-       result = cli_svcctl_open_scm( cli, mem_ctx, &hSCM, SC_RIGHT_MGR_ENUMERATE_SERVICE  );
+       result = rpccli_svcctl_open_scm(pipe_hnd, mem_ctx, &hSCM, SC_RIGHT_MGR_ENUMERATE_SERVICE  );
        if ( !W_ERROR_IS_OK(result) ) {
                d_printf("Failed to open Service Control Manager.  [%s]\n", dos_errstr(result));
                return werror_to_ntstatus(result);
@@ -208,7 +225,7 @@ static NTSTATUS rpc_service_status_internal( const DOM_SID *domain_sid, const ch
        
        /* Open the Service */
        
-       result = cli_svcctl_open_service( cli, mem_ctx, &hSCM, &hService, servicename, 
+       result = rpccli_svcctl_open_service(pipe_hnd, mem_ctx, &hSCM, &hService, servicename, 
                (SC_RIGHT_SVC_QUERY_STATUS|SC_RIGHT_SVC_QUERY_CONFIG) );
 
        if ( !W_ERROR_IS_OK(result) ) {
@@ -218,7 +235,7 @@ static NTSTATUS rpc_service_status_internal( const DOM_SID *domain_sid, const ch
        
        /* get the status */
 
-       result = cli_svcctl_query_status( cli, mem_ctx, &hService, &service_status  );
+       result = rpccli_svcctl_query_status(pipe_hnd, mem_ctx, &hService, &service_status  );
        if ( !W_ERROR_IS_OK(result) ) {
                d_printf("Query status request failed.  [%s]\n", dos_errstr(result));
                goto done;
@@ -228,7 +245,7 @@ static NTSTATUS rpc_service_status_internal( const DOM_SID *domain_sid, const ch
 
        /* get the config */
 
-       result = cli_svcctl_query_config( cli, mem_ctx, &hService, &config  );
+       result = rpccli_svcctl_query_config(pipe_hnd, mem_ctx, &hService, &config  );
        if ( !W_ERROR_IS_OK(result) ) {
                d_printf("Query config request failed.  [%s]\n", dos_errstr(result));
                goto done;
@@ -268,19 +285,22 @@ static NTSTATUS rpc_service_status_internal( const DOM_SID *domain_sid, const ch
        }
 
 done:  
-       cli_svcctl_close_service( cli, mem_ctx, &hService  );
-       cli_svcctl_close_service( cli, mem_ctx, &hSCM  );
-               
+       rpccli_svcctl_close_service(pipe_hnd, mem_ctx, &hService  );
+       rpccli_svcctl_close_service(pipe_hnd, mem_ctx, &hSCM  );
+
        return werror_to_ntstatus(result);
 }      
 
-
 /********************************************************************
 ********************************************************************/
 
-static NTSTATUS rpc_service_stop_internal( const DOM_SID *domain_sid, const char *domain_name, 
-                                           struct cli_state *cli, TALLOC_CTX *mem_ctx, 
-                                           int argc, const char **argv )
+static NTSTATUS rpc_service_stop_internal(const DOM_SID *domain_sid,
+                                       const char *domain_name, 
+                                       struct cli_state *cli,
+                                       struct rpc_pipe_client *pipe_hnd,
+                                       TALLOC_CTX *mem_ctx, 
+                                       int argc,
+                                       const char **argv )
 {
        POLICY_HND hSCM;
        WERROR result = WERR_GENERAL_FAILURE;
@@ -295,16 +315,16 @@ static NTSTATUS rpc_service_stop_internal( const DOM_SID *domain_sid, const char
 
        /* Open the Service Control Manager */
        
-       result = cli_svcctl_open_scm( cli, mem_ctx, &hSCM, SC_RIGHT_MGR_ENUMERATE_SERVICE  );
+       result = rpccli_svcctl_open_scm(pipe_hnd, mem_ctx, &hSCM, SC_RIGHT_MGR_ENUMERATE_SERVICE  );
        if ( !W_ERROR_IS_OK(result) ) {
                d_printf("Failed to open Service Control Manager.  [%s]\n", dos_errstr(result));
                return werror_to_ntstatus(result);
        }
        
-       result = control_service( cli, mem_ctx, &hSCM, servicename, 
+       result = control_service(pipe_hnd, mem_ctx, &hSCM, servicename, 
                SVCCTL_CONTROL_STOP, SVCCTL_STOPPED );
                
-       cli_svcctl_close_service( cli, mem_ctx, &hSCM  );
+       rpccli_svcctl_close_service(pipe_hnd, mem_ctx, &hSCM  );
                
        return werror_to_ntstatus(result);
 }      
@@ -312,9 +332,13 @@ static NTSTATUS rpc_service_stop_internal( const DOM_SID *domain_sid, const char
 /********************************************************************
 ********************************************************************/
 
-static NTSTATUS rpc_service_pause_internal( const DOM_SID *domain_sid, const char *domain_name, 
-                                           struct cli_state *cli, TALLOC_CTX *mem_ctx, 
-                                           int argc, const char **argv )
+static NTSTATUS rpc_service_pause_internal(const DOM_SID *domain_sid,
+                                       const char *domain_name, 
+                                       struct cli_state *cli,
+                                       struct rpc_pipe_client *pipe_hnd,
+                                       TALLOC_CTX *mem_ctx, 
+                                       int argc,
+                                       const char **argv )
 {
        POLICY_HND hSCM;
        WERROR result = WERR_GENERAL_FAILURE;
@@ -329,16 +353,16 @@ static NTSTATUS rpc_service_pause_internal( const DOM_SID *domain_sid, const cha
 
        /* Open the Service Control Manager */
        
-       result = cli_svcctl_open_scm( cli, mem_ctx, &hSCM, SC_RIGHT_MGR_ENUMERATE_SERVICE  );
+       result = rpccli_svcctl_open_scm(pipe_hnd, mem_ctx, &hSCM, SC_RIGHT_MGR_ENUMERATE_SERVICE  );
        if ( !W_ERROR_IS_OK(result) ) {
                d_printf("Failed to open Service Control Manager.  [%s]\n", dos_errstr(result));
                return werror_to_ntstatus(result);
        }
        
-       result = control_service( cli, mem_ctx, &hSCM, servicename, 
+       result = control_service(pipe_hnd, mem_ctx, &hSCM, servicename, 
                SVCCTL_CONTROL_PAUSE, SVCCTL_PAUSED );
                
-       cli_svcctl_close_service( cli, mem_ctx, &hSCM  );
+       rpccli_svcctl_close_service(pipe_hnd, mem_ctx, &hSCM  );
                
        return werror_to_ntstatus(result);
 }      
@@ -346,9 +370,13 @@ static NTSTATUS rpc_service_pause_internal( const DOM_SID *domain_sid, const cha
 /********************************************************************
 ********************************************************************/
 
-static NTSTATUS rpc_service_resume_internal( const DOM_SID *domain_sid, const char *domain_name, 
-                                           struct cli_state *cli, TALLOC_CTX *mem_ctx, 
-                                           int argc, const char **argv )
+static NTSTATUS rpc_service_resume_internal(const DOM_SID *domain_sid,
+                                       const char *domain_name, 
+                                       struct cli_state *cli,
+                                       struct rpc_pipe_client *pipe_hnd,
+                                       TALLOC_CTX *mem_ctx, 
+                                       int argc,
+                                       const char **argv )
 {
        POLICY_HND hSCM;
        WERROR result = WERR_GENERAL_FAILURE;
@@ -363,16 +391,16 @@ static NTSTATUS rpc_service_resume_internal( const DOM_SID *domain_sid, const ch
 
        /* Open the Service Control Manager */
        
-       result = cli_svcctl_open_scm( cli, mem_ctx, &hSCM, SC_RIGHT_MGR_ENUMERATE_SERVICE  );
+       result = rpccli_svcctl_open_scm(pipe_hnd, mem_ctx, &hSCM, SC_RIGHT_MGR_ENUMERATE_SERVICE  );
        if ( !W_ERROR_IS_OK(result) ) {
                d_printf("Failed to open Service Control Manager.  [%s]\n", dos_errstr(result));
                return werror_to_ntstatus(result);
        }
        
-       result = control_service( cli, mem_ctx, &hSCM, servicename, 
+       result = control_service(pipe_hnd, mem_ctx, &hSCM, servicename, 
                SVCCTL_CONTROL_CONTINUE, SVCCTL_RUNNING );
                
-       cli_svcctl_close_service( cli, mem_ctx, &hSCM  );
+       rpccli_svcctl_close_service(pipe_hnd, mem_ctx, &hSCM  );
                
        return werror_to_ntstatus(result);
 }      
@@ -380,9 +408,13 @@ static NTSTATUS rpc_service_resume_internal( const DOM_SID *domain_sid, const ch
 /********************************************************************
 ********************************************************************/
 
-static NTSTATUS rpc_service_start_internal( const DOM_SID *domain_sid, const char *domain_name, 
-                                           struct cli_state *cli, TALLOC_CTX *mem_ctx, 
-                                           int argc, const char **argv )
+static NTSTATUS rpc_service_start_internal(const DOM_SID *domain_sid,
+                                       const char *domain_name, 
+                                       struct cli_state *cli,
+                                       struct rpc_pipe_client *pipe_hnd,
+                                       TALLOC_CTX *mem_ctx, 
+                                       int argc,
+                                       const char **argv )
 {
        POLICY_HND hSCM, hService;
        WERROR result = WERR_GENERAL_FAILURE;
@@ -398,7 +430,7 @@ static NTSTATUS rpc_service_start_internal( const DOM_SID *domain_sid, const cha
 
        /* Open the Service Control Manager */
        
-       result = cli_svcctl_open_scm( cli, mem_ctx, &hSCM, SC_RIGHT_MGR_ENUMERATE_SERVICE  );
+       result = rpccli_svcctl_open_scm( pipe_hnd, mem_ctx, &hSCM, SC_RIGHT_MGR_ENUMERATE_SERVICE  );
        if ( !W_ERROR_IS_OK(result) ) {
                d_printf("Failed to open Service Control Manager.  [%s]\n", dos_errstr(result));
                return werror_to_ntstatus(result);
@@ -406,7 +438,7 @@ static NTSTATUS rpc_service_start_internal( const DOM_SID *domain_sid, const cha
        
        /* Open the Service */
        
-       result = cli_svcctl_open_service( cli, mem_ctx, &hSCM, &hService, 
+       result = rpccli_svcctl_open_service(pipe_hnd, mem_ctx, &hSCM, &hService, 
                servicename, SC_RIGHT_SVC_START );
 
        if ( !W_ERROR_IS_OK(result) ) {
@@ -416,13 +448,13 @@ static NTSTATUS rpc_service_start_internal( const DOM_SID *domain_sid, const cha
        
        /* get the status */
 
-       result = cli_svcctl_start_service( cli, mem_ctx, &hService, NULL, 0 );
+       result = rpccli_svcctl_start_service(pipe_hnd, mem_ctx, &hService, NULL, 0 );
        if ( !W_ERROR_IS_OK(result) ) {
                d_printf("Query status request failed.  [%s]\n", dos_errstr(result));
                goto done;
        }
        
-       result = watch_service_state( cli, mem_ctx, &hSCM, servicename, SVCCTL_RUNNING, &state  );
+       result = watch_service_state(pipe_hnd, mem_ctx, &hSCM, servicename, SVCCTL_RUNNING, &state  );
        
        if ( W_ERROR_IS_OK(result) && (state == SVCCTL_RUNNING) )
                d_printf("Successfully started service: %s\n", servicename );
@@ -430,9 +462,9 @@ static NTSTATUS rpc_service_start_internal( const DOM_SID *domain_sid, const cha
                d_printf("Failed to start service: %s [%s]\n", servicename, dos_errstr(result) );
        
 done:  
-       cli_svcctl_close_service( cli, mem_ctx, &hService  );
-       cli_svcctl_close_service( cli, mem_ctx, &hSCM  );
-               
+       rpccli_svcctl_close_service(pipe_hnd, mem_ctx, &hService  );
+       rpccli_svcctl_close_service(pipe_hnd, mem_ctx, &hSCM  );
+
        return werror_to_ntstatus(result);
 }
 
@@ -525,5 +557,3 @@ int net_rpc_service(int argc, const char **argv)
                
        return net_help_service( argc, argv );
 }
-
-
index d5845972730a3af914170d9402d063d71726131c..960379b3838e01e533a95bc9c54702a7d7f865c8 100644 (file)
@@ -31,7 +31,7 @@ static int show_session(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf,
 
        memcpy(&sessionid, dbuf.dptr, sizeof(sessionid));
 
-       if (!process_exists(sessionid.pid)) {
+       if (!process_exists_by_pid(sessionid.pid)) {
                return 0;
        }
 
@@ -101,8 +101,8 @@ static int show_share(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf,
                return 0;
        }
 
-       d_printf("%-10.10s   %5d   %-12s  %s",
-              crec.name,(int)crec.pid,
+       d_printf("%-10.10s   %s   %-12s  %s",
+              crec.name,procid_str_static(&crec.pid),
               crec.machine,
               asctime(LocalTime(&crec.start)));
 
@@ -125,7 +125,7 @@ static int collect_pid(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf,
 
        memcpy(&sessionid, dbuf.dptr, sizeof(sessionid));
 
-       if (!process_exists(sessionid.pid))
+       if (!process_exists_by_pid(sessionid.pid)) 
                return 0;
 
        ids->num_entries += 1;
@@ -156,14 +156,15 @@ static int show_share_parseable(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf,
        }
 
        for (i=0; i<ids->num_entries; i++) {
-               if (ids->entries[i].pid == crec.pid) {
+               struct process_id id = pid_to_procid(ids->entries[i].pid);
+               if (procid_equal(&id, &crec.pid)) {
                        guest = False;
                        break;
                }
        }
 
-       d_printf("%s\\%d\\%s\\%s\\%s\\%s\\%s",
-                crec.name,(int)crec.pid,
+       d_printf("%s\\%s\\%s\\%s\\%s\\%s\\%s",
+                crec.name,procid_str_static(&crec.pid),
                 guest ? "" : uidtoname(ids->entries[i].uid),
                 guest ? "" : gidtoname(ids->entries[i].gid),
                 crec.machine, 
index 3fdd657a2da0f919842f4f42557d74b68272f4df..4f3bb4d41468ff1e8237ac1ab4f6c3ce74420229 100644 (file)
@@ -465,6 +465,7 @@ static NTSTATUS ntlm_auth_start_ntlmssp_client(NTLMSSP_STATE **client_ntlmssp_st
 {
        NTSTATUS status;
        if ( (opt_username == NULL) || (opt_domain == NULL) ) {
+               status = NT_STATUS_UNSUCCESSFUL;
                DEBUG(1, ("Need username and domain for NTLMSSP\n"));
                return NT_STATUS_INVALID_PARAMETER;
        }
@@ -693,7 +694,8 @@ static void manage_client_ntlmssp_request(enum stdio_helper_mode stdio_helper_mo
                data_blob_free(&reply);
                DEBUG(10, ("NTLMSSP challenge\n"));
        } else if (NT_STATUS_IS_OK(nt_status)) {
-               x_fprintf(x_stdout, "AF\n");
+               char *reply_base64 = base64_encode_data_blob(reply);
+               x_fprintf(x_stdout, "AF %s\n", reply_base64);
                DEBUG(10, ("NTLMSSP OK!\n"));
                if (ntlmssp_state)
                        ntlmssp_end(&ntlmssp_state);
@@ -753,7 +755,7 @@ static void offer_gss_spnego_mechs(void) {
 
        /* Server negTokenInit (mech offerings) */
        spnego.type = SPNEGO_NEG_TOKEN_INIT;
-       spnego.negTokenInit.mechTypes = SMB_XMALLOC_ARRAY(const char *, 3);
+       spnego.negTokenInit.mechTypes = SMB_XMALLOC_ARRAY(char *, 2);
 #ifdef HAVE_KRB5
        spnego.negTokenInit.mechTypes[0] = smb_xstrdup(OID_KERBEROS5_OLD);
        spnego.negTokenInit.mechTypes[1] = smb_xstrdup(OID_NTLMSSP);
@@ -793,6 +795,7 @@ static void manage_gss_spnego_request(enum stdio_helper_mode stdio_helper_mode,
        DATA_BLOB token;
        NTSTATUS status;
        ssize_t len;
+       TALLOC_CTX *mem_ctx = talloc_init("manage_gss_spnego_request");
 
        char *user = NULL;
        char *domain = NULL;
@@ -857,6 +860,7 @@ static void manage_gss_spnego_request(enum stdio_helper_mode stdio_helper_mode,
                        return;
                }
 
+               status = NT_STATUS_UNSUCCESSFUL;
                if (strcmp(request.negTokenInit.mechTypes[0], OID_NTLMSSP) == 0) {
 
                        if ( request.negTokenInit.mechToken.data == NULL ) {
@@ -895,7 +899,6 @@ static void manage_gss_spnego_request(enum stdio_helper_mode stdio_helper_mode,
                if (strcmp(request.negTokenInit.mechTypes[0], OID_KERBEROS5_OLD) == 0) {
 
                        char *principal;
-                       DATA_BLOB auth_data;
                        DATA_BLOB ap_rep;
                        DATA_BLOB session_key;
 
@@ -910,11 +913,13 @@ static void manage_gss_spnego_request(enum stdio_helper_mode stdio_helper_mode,
                        response.negTokenTarg.mechListMIC = data_blob(NULL, 0);
                        response.negTokenTarg.responseToken = data_blob(NULL, 0);
 
-                       status = ads_verify_ticket(lp_realm(),
+                       status = ads_verify_ticket(mem_ctx, lp_realm(),
                                                   &request.negTokenInit.mechToken,
-                                                  &principal, &auth_data, &ap_rep,
+                                                  &principal, NULL, &ap_rep,
                                                   &session_key);
 
+                       talloc_destroy(mem_ctx);
+
                        /* Now in "principal" we have the name we are
                            authenticated as. */
 
@@ -934,7 +939,6 @@ static void manage_gss_spnego_request(enum stdio_helper_mode stdio_helper_mode,
                                user = SMB_STRDUP(principal);
 
                                data_blob_free(&ap_rep);
-                               data_blob_free(&auth_data);
 
                                SAFE_FREE(principal);
                        }
@@ -1052,15 +1056,16 @@ static BOOL manage_client_ntlmssp_init(SPNEGO_DATA spnego)
        }
 
        spnego.type = SPNEGO_NEG_TOKEN_INIT;
-       spnego.negTokenInit.mechTypes = my_mechs;
+       spnego.negTokenInit.mechTypes = CONST_DISCARD(char **,my_mechs);
        spnego.negTokenInit.reqFlags = 0;
        spnego.negTokenInit.mechListMIC = null_blob;
 
        status = ntlmssp_update(client_ntlmssp_state, null_blob,
                                       &spnego.negTokenInit.mechToken);
 
-       if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
-               DEBUG(1, ("Expected MORE_PROCESSING_REQUIRED, got: %s\n",
+       if ( !(NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) ||
+                       NT_STATUS_IS_OK(status)) ) {
+               DEBUG(1, ("Expected OK or MORE_PROCESSING_REQUIRED, got: %s\n",
                          nt_errstr(status)));
                ntlmssp_end(&client_ntlmssp_state);
                return False;
@@ -1121,7 +1126,7 @@ static void manage_client_ntlmssp_targ(SPNEGO_DATA spnego)
 
        spnego.type = SPNEGO_NEG_TOKEN_TARG;
        spnego.negTokenTarg.negResult = SPNEGO_ACCEPT_INCOMPLETE;
-       spnego.negTokenTarg.supportedMech = OID_NTLMSSP;
+       spnego.negTokenTarg.supportedMech = (char *)OID_NTLMSSP;
        spnego.negTokenTarg.responseToken = request;
        spnego.negTokenTarg.mechListMIC = null_blob;
        
@@ -1166,7 +1171,7 @@ static BOOL manage_client_krb5_init(SPNEGO_DATA spnego)
               spnego.negTokenInit.mechListMIC.length);
        principal[spnego.negTokenInit.mechListMIC.length] = '\0';
 
-       retval = cli_krb5_get_ticket(principal, 0, &tkt, &session_key_krb5);
+       retval = cli_krb5_get_ticket(principal, 0, &tkt, &session_key_krb5, 0);
 
        if (retval) {
 
@@ -1189,7 +1194,7 @@ static BOOL manage_client_krb5_init(SPNEGO_DATA spnego)
                        return False;
                }
 
-               retval = cli_krb5_get_ticket(principal, 0, &tkt, &session_key_krb5);
+               retval = cli_krb5_get_ticket(principal, 0, &tkt, &session_key_krb5, 0);
 
                if (retval) {
                        DEBUG(10, ("Kinit suceeded, but getting a ticket failed: %s\n", error_message(retval)));
@@ -1305,7 +1310,7 @@ static void manage_gss_spnego_client_request(enum stdio_helper_mode stdio_helper
 
                /* The server offers a list of mechanisms */
 
-               const char **mechType = spnego.negTokenInit.mechTypes;
+               const char **mechType = (const char **)spnego.negTokenInit.mechTypes;
 
                while (*mechType != NULL) {
 
index c88c0d75797011290791b18280a512bbcd45d897..dacaa1e26f26a0a47ec29959ed2830b89632e01c 100644 (file)
@@ -118,6 +118,27 @@ static int export_groups (struct pdb_context *in, struct pdb_context *out) {
        return 0;
 }
 
+/*********************************************************
+ Add all currently available account policy from tdb to one backend
+ ********************************************************/
+
+static int export_account_policies (struct pdb_context *in, struct pdb_context *out) 
+{
+       int i;
+
+       for (i=1; decode_account_policy_name(i) != NULL; i++) {
+               uint32 policy_value;
+               if (NT_STATUS_IS_ERR(in->pdb_get_account_policy(in, i, &policy_value))) {
+                       fprintf(stderr, "Can't get account policy from tdb\n");
+                       return -1;
+               }
+               out->pdb_set_account_policy(out, i, policy_value);
+       }
+
+       return 0;
+}
+
+
 /*********************************************************
  Print info from sam structure
 **********************************************************/
@@ -652,6 +673,7 @@ int main (int argc, char **argv)
        static char *backend_in = NULL;
        static char *backend_out = NULL;
        static BOOL transfer_groups = False;
+       static BOOL transfer_account_policies = False;
        static BOOL  force_initialised_password = False;
        static char *logon_script = NULL;
        static char *profile_path = NULL;
@@ -683,8 +705,8 @@ int main (int argc, char **argv)
                {"drive",       'D', POPT_ARG_STRING, &home_drive, 0, "set home drive", NULL},
                {"script",      'S', POPT_ARG_STRING, &logon_script, 0, "set logon script", NULL},
                {"profile",     'p', POPT_ARG_STRING, &profile_path, 0, "set profile path", NULL},
-               {"user-SID",    'U', POPT_ARG_STRING, &user_sid, 0, "set user SID or RID", NULL},
-               {"group-SID",   'G', POPT_ARG_STRING, &group_sid, 0, "set group SID or RID", NULL},
+               {"user SID",    'U', POPT_ARG_STRING, &user_sid, 0, "set user SID or RID", NULL},
+               {"group SID",   'G', POPT_ARG_STRING, &group_sid, 0, "set group SID or RID", NULL},
                {"create",      'a', POPT_ARG_NONE, &add_user, 0, "create user", NULL},
                {"modify",      'r', POPT_ARG_NONE, &modify_user, 0, "modify user", NULL},
                {"machine",     'm', POPT_ARG_NONE, &machine, 0, "account is a machine account", NULL},
@@ -693,6 +715,7 @@ int main (int argc, char **argv)
                {"import",      'i', POPT_ARG_STRING, &backend_in, 0, "import user accounts from this backend", NULL},
                {"export",      'e', POPT_ARG_STRING, &backend_out, 0, "export user accounts to this backend", NULL},
                {"group",       'g', POPT_ARG_NONE, &transfer_groups, 0, "use -i and -e for groups", NULL},
+               {"policies",    'y', POPT_ARG_NONE, &transfer_account_policies, 0, "use -i and -e to move account policies between backends", NULL},
                {"account-policy",      'P', POPT_ARG_STRING, &account_policy, 0,"value of an account policy (like maximum password age)",NULL},
                {"value",       'C', POPT_ARG_LONG, &account_policy_value, 'C',"set the account policy to this value", NULL},
                {"account-control",     'c', POPT_ARG_STRING, &account_control, 0, "Values of account control", NULL},
@@ -792,20 +815,22 @@ int main (int argc, char **argv)
                        SAFE_FREE(apn);
                        exit(1);
                }
-               if (!account_policy_get(field, &value)) {
+               if (!pdb_get_account_policy(field, &value)) {
                        fprintf(stderr, "valid account policy, but unable to fetch value!\n");
-                       exit(1);
+                       if (!account_policy_value_set)
+                               exit(1);
                }
+               printf("account policy \"%s\" description: %s\n", account_policy, account_policy_get_desc(field));
                if (account_policy_value_set) {
-                       printf("account policy value for %s was %u\n", account_policy, value);
-                       if (!account_policy_set(field, account_policy_value)) {
+                       printf("account policy \"%s\" value was: %u\n", account_policy, value);
+                       if (!pdb_set_account_policy(field, account_policy_value)) {
                                fprintf(stderr, "valid account policy, but unable to set value!\n");
                                exit(1);
                        }
-                       printf("account policy value for %s is now %lu\n", account_policy, account_policy_value);
+                       printf("account policy \"%s\" value is now: %lu\n", account_policy, account_policy_value);
                        exit(0);
                } else {
-                       printf("account policy value for %s is %u\n", account_policy, value);
+                       printf("account policy \"%s\" value is: %u\n", account_policy, value);
                        exit(0);
                }
        }
@@ -829,7 +854,10 @@ int main (int argc, char **argv)
                } else {
                        bout = bdef;
                }
-               if (transfer_groups) {
+               if (transfer_account_policies) {
+                       if (!(checkparms & BIT_USER))
+                               return export_account_policies(bin, bout);
+               } else  if (transfer_groups) {
                        if (!(checkparms & BIT_USER))
                                return export_groups(bin, bout);
                } else {
index 00000b5cfbe51095d40fc09daad94c08a6029378..36efcc247d56bd364120b849ade959d55ffeb86c 100644 (file)
@@ -64,6 +64,7 @@ static const struct perm_value standard_values[] = {
 };
 
 static struct cli_state *global_hack_cli;
+static struct rpc_pipe_client *global_pipe_hnd;
 static POLICY_HND pol;
 static BOOL got_policy_hnd;
 
@@ -76,8 +77,10 @@ static BOOL cacls_open_policy_hnd(void)
        /* Initialise cli LSA connection */
 
        if (!global_hack_cli) {
+               NTSTATUS ret;
                global_hack_cli = connect_one("IPC$");
-               if (!cli_nt_session_open (global_hack_cli, PI_LSARPC)) {
+               global_pipe_hnd = cli_rpc_pipe_open_noauth(global_hack_cli, PI_LSARPC, &ret);
+               if (!global_pipe_hnd) {
                                return False;
                }
        }
@@ -89,7 +92,7 @@ static BOOL cacls_open_policy_hnd(void)
                /* Some systems don't support SEC_RIGHTS_MAXIMUM_ALLOWED,
                   but NT sends 0x2000000 so we might as well do it too. */
 
-               if (!NT_STATUS_IS_OK(cli_lsa_open_policy(global_hack_cli, global_hack_cli->mem_ctx, True, 
+               if (!NT_STATUS_IS_OK(rpccli_lsa_open_policy(global_pipe_hnd, global_hack_cli->mem_ctx, True, 
                                                         GENERIC_EXECUTE_ACCESS, &pol))) {
                        return False;
                }
@@ -114,7 +117,7 @@ static void SidToString(fstring str, DOM_SID *sid)
        /* Ask LSA to convert the sid to a name */
 
        if (!cacls_open_policy_hnd() ||
-           !NT_STATUS_IS_OK(cli_lsa_lookup_sids(global_hack_cli, global_hack_cli->mem_ctx,  
+           !NT_STATUS_IS_OK(rpccli_lsa_lookup_sids(global_pipe_hnd, global_hack_cli->mem_ctx,  
                                                 &pol, 1, sid, &domains, 
                                                 &names, &types)) ||
            !domains || !domains[0] || !names || !names[0]) {
@@ -141,7 +144,7 @@ static BOOL StringToSid(DOM_SID *sid, const char *str)
        }
 
        if (!cacls_open_policy_hnd() ||
-           !NT_STATUS_IS_OK(cli_lsa_lookup_names(global_hack_cli, global_hack_cli->mem_ctx, 
+           !NT_STATUS_IS_OK(rpccli_lsa_lookup_names(global_pipe_hnd, global_hack_cli->mem_ctx, 
                                                  &pol, 1, &str, &sids, 
                                                  &types))) {
                result = False;
index c0de85cea5d4eac826e567a4b0968e5ba28e71cd..a0304eb89a9636a504762e2a8a0855f52759e7f0 100644 (file)
@@ -34,7 +34,8 @@ static int num_replies;               /* Used by message callback fns */
 
 /* Send a message to a destination pid.  Zero means broadcast smbd. */
 
-static BOOL send_message(pid_t pid, int msg_type, const void *buf, int len,
+static BOOL send_message(struct process_id pid, int msg_type,
+                        const void *buf, int len,
                         BOOL duplicates)
 {
        TDB_CONTEXT *tdb;
@@ -44,7 +45,7 @@ static BOOL send_message(pid_t pid, int msg_type, const void *buf, int len,
        if (!message_init())
                return False;
 
-       if (pid != 0)
+       if (procid_to_pid(&pid) != 0)
                return message_send_pid(pid, msg_type, buf, len, duplicates);
 
        tdb = tdb_open_log(lock_path("connections.tdb"), 0, 
@@ -84,15 +85,17 @@ static void wait_replies(BOOL multiple_replies)
 
 /* Message handler callback that displays the PID and a string on stdout */
 
-static void print_pid_string_cb(int msg_type, pid_t pid, void *buf, size_t len)
+static void print_pid_string_cb(int msg_type, struct process_id pid, void *buf, size_t len)
 {
-       printf("PID %u: %.*s", (unsigned int)pid, (int)len, (const char *)buf);
+       printf("PID %u: %.*s", (unsigned int)procid_to_pid(&pid),
+              (int)len, (const char *)buf);
        num_replies++;
 }
 
 /* Message handler callback that displays a string on stdout */
 
-static void print_string_cb(int msg_type, pid_t pid, void *buf, size_t len)
+static void print_string_cb(int msg_type, struct process_id pid,
+                           void *buf, size_t len)
 {
        printf("%.*s", (int)len, (const char *)buf);
        num_replies++;
@@ -100,7 +103,8 @@ static void print_string_cb(int msg_type, pid_t pid, void *buf, size_t len)
 
 /* Send no message.  Useful for testing. */
 
-static BOOL do_noop(const pid_t pid, const int argc, const char **argv)
+static BOOL do_noop(const struct process_id pid,
+                   const int argc, const char **argv)
 {
        if (argc != 1) {
                fprintf(stderr, "Usage: smbcontrol <dest> noop\n");
@@ -114,7 +118,8 @@ static BOOL do_noop(const pid_t pid, const int argc, const char **argv)
 
 /* Send a debug string */
 
-static BOOL do_debug(const pid_t pid, const int argc, const char **argv)
+static BOOL do_debug(const struct process_id pid,
+                    const int argc, const char **argv)
 {
        if (argc != 2) {
                fprintf(stderr, "Usage: smbcontrol <dest> debug "
@@ -128,7 +133,8 @@ static BOOL do_debug(const pid_t pid, const int argc, const char **argv)
 
 /* Force a browser election */
 
-static BOOL do_election(const pid_t pid, const int argc, const char **argv)
+static BOOL do_election(const struct process_id pid,
+                       const int argc, const char **argv)
 {
        if (argc != 1) {
                fprintf(stderr, "Usage: smbcontrol <dest> force-election\n");
@@ -141,13 +147,15 @@ static BOOL do_election(const pid_t pid, const int argc, const char **argv)
 
 /* Ping a samba daemon process */
 
-static void pong_cb(int msg_type, pid_t pid, void *buf, size_t len)
+static void pong_cb(int msg_type, struct process_id pid, void *buf, size_t len)
 {
-       printf("PONG from pid %u\n", (unsigned int)pid);
+       char *src_string = procid_str(NULL, &pid);
+       printf("PONG from pid %s\n", src_string);
+       talloc_free(src_string);
        num_replies++;
 }
 
-static BOOL do_ping(const pid_t pid, const int argc, const char **argv)
+static BOOL do_ping(const struct process_id pid, const int argc, const char **argv)
 {
        if (argc != 1) {
                fprintf(stderr, "Usage: smbcontrol <dest> ping\n");
@@ -161,7 +169,7 @@ static BOOL do_ping(const pid_t pid, const int argc, const char **argv)
 
        message_register(MSG_PONG, pong_cb);
 
-       wait_replies(pid == 0);
+       wait_replies(procid_to_pid(&pid) == 0);
 
        /* No replies were received within the timeout period */
 
@@ -175,7 +183,8 @@ static BOOL do_ping(const pid_t pid, const int argc, const char **argv)
 
 /* Set profiling options */
 
-static BOOL do_profile(const pid_t pid, const int argc, const char **argv)
+static BOOL do_profile(const struct process_id pid,
+                      const int argc, const char **argv)
 {
        int v;
 
@@ -203,7 +212,7 @@ static BOOL do_profile(const pid_t pid, const int argc, const char **argv)
 
 /* Return the profiling level */
 
-static void profilelevel_cb(int msg_type, pid_t pid, void *buf, size_t len)
+static void profilelevel_cb(int msg_type, struct process_id pid, void *buf, size_t len)
 {
        int level;
        const char *s;
@@ -236,10 +245,11 @@ static void profilelevel_cb(int msg_type, pid_t pid, void *buf, size_t len)
                break;
        }
        
-       printf("Profiling %s on pid %u\n",s,(unsigned int)pid);
+       printf("Profiling %s on pid %u\n",s,(unsigned int)procid_to_pid(&pid));
 }
 
-static void profilelevel_rqst(int msg_type, pid_t pid, void *buf, size_t len)
+static void profilelevel_rqst(int msg_type, struct process_id pid,
+                             void *buf, size_t len)
 {
        int v = 0;
 
@@ -248,7 +258,8 @@ static void profilelevel_rqst(int msg_type, pid_t pid, void *buf, size_t len)
        send_message(pid, MSG_PROFILELEVEL, &v, sizeof(int), False);
 }
 
-static BOOL do_profilelevel(const pid_t pid, const int argc, const char **argv)
+static BOOL do_profilelevel(const struct process_id pid,
+                           const int argc, const char **argv)
 {
        if (argc != 1) {
                fprintf(stderr, "Usage: smbcontrol <dest> profilelevel\n");
@@ -263,7 +274,7 @@ static BOOL do_profilelevel(const pid_t pid, const int argc, const char **argv)
        message_register(MSG_PROFILELEVEL, profilelevel_cb);
        message_register(MSG_REQ_PROFILELEVEL, profilelevel_rqst);
 
-       wait_replies(pid == 0);
+       wait_replies(procid_to_pid(&pid) == 0);
 
        /* No replies were received within the timeout period */
 
@@ -277,7 +288,8 @@ static BOOL do_profilelevel(const pid_t pid, const int argc, const char **argv)
 
 /* Display debug level settings */
 
-static BOOL do_debuglevel(const pid_t pid, const int argc, const char **argv)
+static BOOL do_debuglevel(const struct process_id pid,
+                         const int argc, const char **argv)
 {
        if (argc != 1) {
                fprintf(stderr, "Usage: smbcontrol <dest> debuglevel\n");
@@ -291,7 +303,7 @@ static BOOL do_debuglevel(const pid_t pid, const int argc, const char **argv)
 
        message_register(MSG_DEBUGLEVEL, print_pid_string_cb);
 
-       wait_replies(pid == 0);
+       wait_replies(procid_to_pid(&pid) == 0);
 
        /* No replies were received within the timeout period */
 
@@ -305,7 +317,8 @@ static BOOL do_debuglevel(const pid_t pid, const int argc, const char **argv)
 
 /* Send a print notify message */
 
-static BOOL do_printnotify(const pid_t pid, const int argc, const char **argv)
+static BOOL do_printnotify(const struct process_id pid,
+                          const int argc, const char **argv)
 {
        const char *cmd;
 
@@ -428,7 +441,8 @@ static BOOL do_printnotify(const pid_t pid, const int argc, const char **argv)
                        return False;
                }
 
-               notify_printer_byname(argv[2], attribute, argv[4]);
+               notify_printer_byname(argv[2], attribute,
+                                     CONST_DISCARD(char *, argv[4]));
 
                goto send;
        }
@@ -443,7 +457,8 @@ send:
 
 /* Close a share */
 
-static BOOL do_closeshare(const pid_t pid, const int argc, const char **argv)
+static BOOL do_closeshare(const struct process_id pid,
+                         const int argc, const char **argv)
 {
        if (argc != 2) {
                fprintf(stderr, "Usage: smbcontrol <dest> close-share "
@@ -457,7 +472,8 @@ static BOOL do_closeshare(const pid_t pid, const int argc, const char **argv)
 
 /* Force a SAM synchronisation */
 
-static BOOL do_samsync(const pid_t pid, const int argc, const char **argv)
+static BOOL do_samsync(const struct process_id pid,
+                      const int argc, const char **argv)
 {
        if (argc != 1) {
                fprintf(stderr, "Usage: smbcontrol <dest> samsync\n");
@@ -470,7 +486,8 @@ static BOOL do_samsync(const pid_t pid, const int argc, const char **argv)
 
 /* Force a SAM replication */
 
-static BOOL do_samrepl(const pid_t pid, const int argc, const char **argv)
+static BOOL do_samrepl(const struct process_id pid,
+                      const int argc, const char **argv)
 {
        if (argc != 1) {
                fprintf(stderr, "Usage: smbcontrol <dest> samrepl\n");
@@ -483,7 +500,8 @@ static BOOL do_samrepl(const pid_t pid, const int argc, const char **argv)
 
 /* Display talloc pool usage */
 
-static BOOL do_poolusage(const pid_t pid, const int argc, const char **argv)
+static BOOL do_poolusage(const struct process_id pid,
+                        const int argc, const char **argv)
 {
        if (argc != 1) {
                fprintf(stderr, "Usage: smbcontrol <dest> pool-usage\n");
@@ -497,7 +515,7 @@ static BOOL do_poolusage(const pid_t pid, const int argc, const char **argv)
 
        message_register(MSG_POOL_USAGE, print_string_cb);
 
-       wait_replies(pid == 0);
+       wait_replies(procid_to_pid(&pid) == 0);
 
        /* No replies were received within the timeout period */
 
@@ -511,7 +529,8 @@ static BOOL do_poolusage(const pid_t pid, const int argc, const char **argv)
 
 /* Perform a dmalloc mark */
 
-static BOOL do_dmalloc_mark(const pid_t pid, const int argc, const char **argv)
+static BOOL do_dmalloc_mark(const struct process_id pid,
+                           const int argc, const char **argv)
 {
        if (argc != 1) {
                fprintf(stderr, "Usage: smbcontrol <dest> dmalloc-mark\n");
@@ -524,7 +543,8 @@ static BOOL do_dmalloc_mark(const pid_t pid, const int argc, const char **argv)
 
 /* Perform a dmalloc changed */
 
-static BOOL do_dmalloc_changed(const pid_t pid, const int argc, const char **argv)
+static BOOL do_dmalloc_changed(const struct process_id pid,
+                              const int argc, const char **argv)
 {
        if (argc != 1) {
                fprintf(stderr, "Usage: smbcontrol <dest> "
@@ -538,7 +558,8 @@ static BOOL do_dmalloc_changed(const pid_t pid, const int argc, const char **arg
 
 /* Shutdown a server process */
 
-static BOOL do_shutdown(const pid_t pid, const int argc, const char **argv)
+static BOOL do_shutdown(const struct process_id pid,
+                       const int argc, const char **argv)
 {
        if (argc != 1) {
                fprintf(stderr, "Usage: smbcontrol <dest> shutdown\n");
@@ -550,7 +571,8 @@ static BOOL do_shutdown(const pid_t pid, const int argc, const char **argv)
 
 /* Notify a driver upgrade */
 
-static BOOL do_drvupgrade(const pid_t pid, const int argc, const char **argv)
+static BOOL do_drvupgrade(const struct process_id pid,
+                         const int argc, const char **argv)
 {
        if (argc != 2) {
                fprintf(stderr, "Usage: smbcontrol <dest> drvupgrade "
@@ -562,7 +584,8 @@ static BOOL do_drvupgrade(const pid_t pid, const int argc, const char **argv)
                pid, MSG_DEBUG, argv[1], strlen(argv[1]) + 1, False);
 }
 
-static BOOL do_reload_config(const pid_t pid, const int argc, const char **argv)
+static BOOL do_reload_config(const struct process_id pid,
+                            const int argc, const char **argv)
 {
        if (argc != 1) {
                fprintf(stderr, "Usage: smbcontrol <dest> reload-config\n");
@@ -583,8 +606,8 @@ static void my_make_nmb_name( struct nmb_name *n, const char *name, int type)
        push_ascii(n->scope,  global_scope(), 64, STR_TERMINATE);
 }
 
-static BOOL do_nodestatus(const pid_t pid, const int argc,
-                         const char **argv)
+static BOOL do_nodestatus(const struct process_id pid,
+                         const int argc, const char **argv)
 {
        struct packet_struct p;
 
@@ -623,7 +646,8 @@ static BOOL do_nodestatus(const pid_t pid, const int argc,
 
 static const struct {
        const char *name;       /* Option name */
-       BOOL (*fn)(const pid_t pid, const int argc, const char **argv);
+       BOOL (*fn)(const struct process_id pid,
+                  const int argc, const char **argv);
        const char *help;       /* Short help text */
 } msg_types[] = {
        { "debug", do_debug, "Set debuglevel"  },
@@ -674,33 +698,39 @@ static void usage(poptContext *pc)
 
 /* Return the pid number for a string destination */
 
-static pid_t parse_dest(const char *dest)
+static struct process_id parse_dest(const char *dest)
 {
+       struct process_id result;
        pid_t pid;
 
        /* Zero is a special return value for broadcast smbd */
 
-       if (strequal(dest, "smbd"))
-               return 0;
+       if (strequal(dest, "smbd")) {
+               return interpret_pid("0");
+       }
 
        /* Try self - useful for testing */
 
-       if (strequal(dest, "self"))
-               return sys_getpid();
+       if (strequal(dest, "self")) {
+               return pid_to_procid(sys_getpid());
+       }
 
        /* Check for numeric pid number */
 
-       if ((pid = atoi(dest)) != 0)
-               return pid;
+       result = interpret_pid(dest);
+       if (procid_valid(&result)) {
+               return result;
+       }
 
        /* Look up other destinations in pidfile directory */
 
-       if ((pid = pidfile_pid(dest)) != 0)
-               return pid;
+       if ((pid = pidfile_pid(dest)) != 0) {
+               return pid_to_procid(pid);
+       }
 
        fprintf(stderr,"Can't find pid for destination '%s'\n", dest);
 
-       return -1;
+       return result;
 }      
 
 /* Execute smbcontrol command */
@@ -708,13 +738,15 @@ static pid_t parse_dest(const char *dest)
 static BOOL do_command(int argc, const char **argv)
 {
        const char *dest = argv[0], *command = argv[1];
-       pid_t pid;
+       struct process_id pid;
        int i;
 
        /* Check destination */
 
-       if ((pid = parse_dest(dest)) == -1)
+       pid = parse_dest(dest);
+       if (!procid_valid(&pid)) {
                return False;
+       }
 
        /* Check command */
 
index 81f7dd42bbc2c56f014d32577c090693d00c825e..c516fbb2187aa1ef7241ab86319d2b90fffc2e53 100644 (file)
@@ -34,7 +34,8 @@ static BOOL verbose;
 enum todo_values {NOOP_QUOTA=0,FS_QUOTA,USER_QUOTA,LIST_QUOTA,SET_QUOTA};
 enum exit_values {EXIT_OK, EXIT_FAILED, EXIT_PARSE_ERROR};
 
-static struct cli_state *cli_ipc = NULL;
+static struct cli_state *cli_ipc;
+static struct rpc_pipe_client *global_pipe_hnd;
 static POLICY_HND pol;
 static BOOL got_policy_hnd;
 
@@ -47,8 +48,10 @@ static BOOL cli_open_policy_hnd(void)
        /* Initialise cli LSA connection */
 
        if (!cli_ipc) {
+               NTSTATUS ret;
                cli_ipc = connect_one("IPC$");
-               if (!cli_nt_session_open (cli_ipc, PI_LSARPC)) {
+               global_pipe_hnd = cli_rpc_pipe_open_noauth(cli_ipc, PI_LSARPC, &ret);
+               if (!global_pipe_hnd) {
                                return False;
                }
        }
@@ -60,7 +63,7 @@ static BOOL cli_open_policy_hnd(void)
                /* Some systems don't support SEC_RIGHTS_MAXIMUM_ALLOWED,
                   but NT sends 0x2000000 so we might as well do it too. */
 
-               if (!NT_STATUS_IS_OK(cli_lsa_open_policy(cli_ipc, cli_ipc->mem_ctx, True, 
+               if (!NT_STATUS_IS_OK(rpccli_lsa_open_policy(global_pipe_hnd, cli_ipc->mem_ctx, True, 
                                                         GENERIC_EXECUTE_ACCESS, &pol))) {
                        return False;
                }
@@ -85,7 +88,7 @@ static void SidToString(fstring str, DOM_SID *sid, BOOL _numeric)
        /* Ask LSA to convert the sid to a name */
 
        if (!cli_open_policy_hnd() ||
-           !NT_STATUS_IS_OK(cli_lsa_lookup_sids(cli_ipc, cli_ipc->mem_ctx,  
+           !NT_STATUS_IS_OK(rpccli_lsa_lookup_sids(global_pipe_hnd, cli_ipc->mem_ctx,  
                                                 &pol, 1, sid, &domains, 
                                                 &names, &types)) ||
            !domains || !domains[0] || !names || !names[0]) {
@@ -112,7 +115,7 @@ static BOOL StringToSid(DOM_SID *sid, const char *str)
        }
 
        if (!cli_open_policy_hnd() ||
-           !NT_STATUS_IS_OK(cli_lsa_lookup_names(cli_ipc, cli_ipc->mem_ctx, 
+           !NT_STATUS_IS_OK(rpccli_lsa_lookup_names(global_pipe_hnd, cli_ipc->mem_ctx, 
                                                  &pol, 1, &str, &sids, 
                                                  &types))) {
                result = False;
index 96e4bd266b9e13cdc882039a0575071a88ed84b7..4709cfbaee105840c3c3935535ab6ea8bb19b105 100644 (file)
@@ -98,7 +98,7 @@ static BOOL Ucrit_addPid( pid_t pid )
        return True;
 }
 
-static void print_share_mode(share_mode_entry *e, char *fname)
+static void print_share_mode(const struct share_mode_entry *e, char *fname)
 {
        static int count;
        if (count==0) {
@@ -108,8 +108,8 @@ static void print_share_mode(share_mode_entry *e, char *fname)
        }
        count++;
 
-       if (Ucrit_checkPid(e->pid)) {
-               d_printf("%-5d  ",(int)e->pid);
+       if (Ucrit_checkPid(procid_to_pid(&e->pid))) {
+               d_printf("%s  ",procid_str_static(&e->pid));
                switch (map_share_mode_to_deny_mode(e->share_access,
                                                    e->private_options)) {
                        case DENY_NONE: d_printf("DENY_NONE  "); break;
@@ -154,7 +154,7 @@ static void print_share_mode(share_mode_entry *e, char *fname)
        }
 }
 
-static void print_brl(SMB_DEV_T dev, SMB_INO_T ino, int pid, 
+static void print_brl(SMB_DEV_T dev, SMB_INO_T ino, struct process_id pid, 
                      enum brl_type lock_type,
                      br_off start, br_off size)
 {
@@ -166,8 +166,8 @@ static void print_brl(SMB_DEV_T dev, SMB_INO_T ino, int pid,
        }
        count++;
 
-       d_printf("%6d   %05x:%05x    %s  %9.0f   %9.0f\n", 
-              (int)pid, (int)dev, (int)ino, 
+       d_printf("%s   %05x:%05x    %s  %9.0f   %9.0f\n", 
+              procid_str_static(&pid), (int)dev, (int)ino, 
               lock_type==READ_LOCK?"R":"W",
               (double)start, (double)size);
 }
@@ -550,8 +550,8 @@ static int traverse_fn1(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *st
                return 0;
        }
 
-       d_printf("%-10s   %5d   %-12s  %s",
-              crec.name,(int)crec.pid,
+       d_printf("%-10s   %s   %-12s  %s",
+              crec.name,procid_str_static(&crec.pid),
               crec.machine,
               asctime(LocalTime(&crec.start)));
 
@@ -568,7 +568,7 @@ static int traverse_sessionid(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, vo
 
        memcpy(&sessionid, dbuf.dptr, sizeof(sessionid));
 
-       if (!process_exists(sessionid.pid) || !Ucrit_checkUid(sessionid.uid)) {
+       if (!process_exists_by_pid(sessionid.pid) || !Ucrit_checkUid(sessionid.uid)) {
                return 0;
        }
 
index 2b72479ac0762082b564388a201465c17611339a..b4561b58deb4b0ce516ae5f559891d39779f82e4 100644 (file)
@@ -206,7 +206,7 @@ via the %%o substitution. With encrypted passwords this is not possible.\n", lp_
        poptContext pc;
        static const char *term_code = "";
        static char *parameter_name = NULL;
-       static char *section_name = NULL;
+       static const char *section_name = NULL;
        static char *new_local_machine = NULL;
        const char *cname;
        const char *caddr;
index d259717da0bfd25208812e7404cb9ca48281bd97..c7a7a3598ee4fe0ed71dbd44e12db152f3856819 100644 (file)
@@ -21,8 +21,6 @@
 #include "includes.h"
 #include "web/swat_proto.h"
 
-extern struct in_addr loopback_ip;
-
 #ifdef WITH_WINBIND
 
 /* check to see if winbind is running by pinging it */
@@ -37,6 +35,7 @@ BOOL winbindd_running(void)
    response */
 BOOL nmbd_running(void)
 {
+       extern struct in_addr loopback_ip;
        int fd, count, flags;
        struct in_addr *ip_list;
 
@@ -61,6 +60,7 @@ BOOL nmbd_running(void)
 BOOL smbd_running(void)
 {
        static struct cli_state cli;
+       extern struct in_addr loopback_ip;
 
        if (!cli_initialise(&cli))
                return False;
index cc2924afde6982da66fdbed8ae8a9c66099abd98..ca671822d87a7f3301049fba276e55addd735b8c 100644 (file)
@@ -54,8 +54,8 @@ struct pri_list {
 };
 
 static int qsort_cmp_list(const void *x, const void *y) {
-        struct pri_list *a = CONST_DISCARD(struct pri_list *, x);
-       struct pri_list *b = CONST_DISCARD(struct pri_list *, y);
+       struct pri_list *a = (struct pri_list *)x;
+       struct pri_list *b = (struct pri_list *)y;
        if (a->pri > b->pri) return -1;
        if (a->pri == b->pri) return 0;
        return 1;
index 9ffda5bb941bdcba9adc69d12b16b32d0107213d..8f28748918f3535282ec540782b764c4ee2b2978 100644 (file)
@@ -121,11 +121,11 @@ void stop_winbindd(void)
 }
 #endif
 /* kill a specified process */
-void kill_pid(pid_t pid)
+void kill_pid(struct process_id pid)
 {
        if (geteuid() != 0) return;
 
-       if (pid <= 0) return;
+       if (procid_to_pid(&pid) <= 0) return;
 
-       kill(pid, SIGTERM);
+       kill(procid_to_pid(&pid), SIGTERM);
 }
index 871e07b5d063a7a42bb194da3028c0c832d5b3f7..edc03183730d14c97a7eabf7bd772c1d65cfae0a 100644 (file)
 
 PIDMAP {
        PIDMAP  *next, *prev;
-       pid_t   pid;
+       struct process_id pid;
        char    *machine;
 };
 
 static PIDMAP  *pidmap;
 static int     PID_or_Machine;         /* 0 = show PID, else show Machine name */
 
-static pid_t smbd_pid;
+static struct process_id smbd_pid;
 
 /* from 2nd call on, remove old list */
 static void initPid2Machine (void)
@@ -55,7 +55,7 @@ static void initPid2Machine (void)
 }
 
 /* add new PID <-> Machine name mapping */
-static void addPid2Machine (pid_t pid, char *machine)
+static void addPid2Machine (struct process_id pid, char *machine)
 {
        /* show machine name rather PID on table "Open Files"? */
        if (PID_or_Machine) {
@@ -75,7 +75,7 @@ static void addPid2Machine (pid_t pid, char *machine)
 }
 
 /* lookup PID <-> Machine name mapping */
-static char *mapPid2Machine (pid_t pid)
+static char *mapPid2Machine (struct process_id pid)
 {
        static char pidbuf [64];
        PIDMAP *map;
@@ -83,7 +83,7 @@ static char *mapPid2Machine (pid_t pid)
        /* show machine name rather PID on table "Open Files"? */
        if (PID_or_Machine) {
                for (map = pidmap; map != NULL; map = map->next) {
-                       if (pid == map->pid) {
+                       if (procid_equal(&pid, &map->pid)) {
                                if (map->machine == NULL)       /* no machine name */
                                        break;                  /* show PID */
 
@@ -93,7 +93,8 @@ static char *mapPid2Machine (pid_t pid)
        }
 
        /* PID not in list or machine name NULL? return pid as string */
-       snprintf (pidbuf, sizeof (pidbuf) - 1, "%lu", (unsigned long)pid);
+       snprintf (pidbuf, sizeof (pidbuf) - 1, "%s",
+                 procid_str_static(&pid));
        return pidbuf;
 }
 
@@ -105,7 +106,7 @@ static char *tstring(time_t t)
        return buf;
 }
 
-static void print_share_mode(share_mode_entry *e, char *fname)
+static void print_share_mode(const struct share_mode_entry *e, char *fname)
 {
        char           *utf8_fname;
        int deny_mode = map_share_mode_to_deny_mode(e->share_access,
@@ -167,7 +168,7 @@ static int traverse_fn1(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void* st
 
        if (crec.cnum == -1 && process_exists(crec.pid)) {
                char buf[30];
-               slprintf(buf,sizeof(buf)-1,"kill_%d", (int)crec.pid);
+               slprintf(buf,sizeof(buf)-1,"kill_%s", procid_str_static(&crec.pid));
                if (cgi_variable(buf)) {
                        kill_pid(crec.pid);
                        sleep(SLEEP_TIME);
@@ -186,18 +187,19 @@ static int traverse_fn2(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void* st
 
        memcpy(&crec, dbuf.dptr, sizeof(crec));
        
-       if (crec.cnum == -1 || !process_exists(crec.pid) || (crec.pid == smbd_pid))
+       if (crec.cnum == -1 || !process_exists(crec.pid) ||
+           procid_equal(&crec.pid, &smbd_pid))
                return 0;
 
        addPid2Machine (crec.pid, crec.machine);
 
-       printf("<tr><td>%d</td><td>%s</td><td>%s</td><td>%s</td>\n",
-              (int)crec.pid,
+       printf("<tr><td>%s</td><td>%s</td><td>%s</td><td>%s</td>\n",
+              procid_str_static(&crec.pid),
               crec.machine,crec.addr,
               tstring(crec.start));
        if (geteuid() == 0) {
-               printf("<td><input type=submit value=\"X\" name=\"kill_%d\"></td>\n",
-                      (int)crec.pid);
+               printf("<td><input type=submit value=\"X\" name=\"kill_%s\"></td>\n",
+                      procid_str_static(&crec.pid));
        }
        printf("</tr>\n");
 
@@ -217,9 +219,9 @@ static int traverse_fn3(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void* st
        if (crec.cnum == -1 || !process_exists(crec.pid))
                return 0;
 
-       printf("<tr><td>%s</td><td>%s</td><td>%s</td><td>%d</td><td>%s</td><td>%s</td></tr>\n",
+       printf("<tr><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td></tr>\n",
               crec.name,uidtoname(crec.uid),
-              gidtoname(crec.gid),(int)crec.pid,
+              gidtoname(crec.gid),procid_str_static(&crec.pid),
               crec.machine,
               tstring(crec.start));
        return 0;
@@ -236,7 +238,7 @@ void status_page(void)
        int nr_running=0;
        BOOL waitup = False;
 
-       smbd_pid = pidfile_pid("smbd");
+       smbd_pid = pid_to_procid(pidfile_pid("smbd"));
 
        if (cgi_variable("smbd_restart") || cgi_variable("all_restart")) {
                stop_smbd();
index 15612484a354bccb35665c1f6888a5564ba6bb30..4082574e442fc7345d92386e8b255a305dd62ed8 100644 (file)
@@ -188,12 +188,12 @@ static const char* get_parm_translated(
        if(strcmp(pLabel, pTranslated) != 0)
        {
                pstr_sprintf(output,
-                 "<A HREF=\"/swat/help/manpages/smb.conf.5.html#%s\" target=\"docs\"> %s</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; %s <br><span class=\"i18n_translated_parm\">%s</span>",
+                 "<A HREF=\"/swat/help/smb.conf.5.html#%s\" target=\"docs\"> %s</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; %s <br><span class=\"i18n_translated_parm\">%s</span>",
                   pAnchor, pHelp, pLabel, pTranslated);
                return output;
        }
        pstr_sprintf(output, 
-         "<A HREF=\"/swat/help/manpages/smb.conf.5.html#%s\" target=\"docs\"> %s</A>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; %s",
+         "<a href=\"/swat/help/smb.conf.5.html#%s\" target=\"docs\" class=\"help_link\"> %s</a> %s",
          pAnchor, pHelp, pLabel);
        return output;
 }
@@ -220,7 +220,7 @@ static void show_parameter(int snum, struct parm_struct *parm)
                ptr = lp_local_ptr(snum, ptr);
        }
 
-       printf("<tr><td>%s</td><td>", get_parm_translated(stripspaceupper(parm->label), _("Help"), parm->label));
+       printf("<tr><td width=\"230\">%s</td><td>", get_parm_translated(stripspaceupper(parm->label), _("Help"), parm->label));
        switch (parm->type) {
        case P_CHAR:
                printf("<input type=text size=2 name=\"parm_%s\" value=\"%c\">",
@@ -230,7 +230,7 @@ static void show_parameter(int snum, struct parm_struct *parm)
                break;
 
        case P_LIST:
-               printf("<input type=text size=40 name=\"parm_%s\" value=\"",
+               printf("<input type=text size=30 name=\"parm_%s\" value=\"",
                        make_parm_name(parm->label));
                if ((char ***)ptr && *(char ***)ptr && **(char ***)ptr) {
                        char **list = *(char ***)ptr;
@@ -268,7 +268,7 @@ static void show_parameter(int snum, struct parm_struct *parm)
        case P_STRING:
        case P_USTRING:
                push_utf8_allocate(&utf8_s1, *(char **)ptr);
-               printf("<input type=text size=40 name=\"parm_%s\" value=\"%s\">",
+               printf("<input type=text size=30 name=\"parm_%s\" value=\"%s\">",
                       make_parm_name(parm->label), fix_quotes(utf8_s1));
                SAFE_FREE(utf8_s1);
                printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.value=\'%s\'\">",
@@ -278,7 +278,7 @@ static void show_parameter(int snum, struct parm_struct *parm)
        case P_GSTRING:
        case P_UGSTRING:
                push_utf8_allocate(&utf8_s1, (char *)ptr);
-               printf("<input type=text size=40 name=\"parm_%s\" value=\"%s\">",
+               printf("<input type=text size=30 name=\"parm_%s\" value=\"%s\">",
                       make_parm_name(parm->label), fix_quotes(utf8_s1));
                SAFE_FREE(utf8_s1);
                printf("<input type=button value=\"%s\" onClick=\"swatform.parm_%s.value=\'%s\'\">",
@@ -523,42 +523,50 @@ static void commit_parameters(int snum)
 }
 
 /****************************************************************************
-  spit out the html for a link with an image 
+  generate html for rollovers
 ****************************************************************************/
-static void image_link(const char *name, const char *hlink, const char *src)
+static void rollover_link(const char *name, const char *id, const char *page)
 {
-       printf("<A HREF=\"%s/%s\"><img border=\"0\" src=\"/swat/%s\" alt=\"%s\"></A>\n", 
-              cgi_baseurl(), hlink, src, name);
+       if ( strcmp(page, id)==0 ) {
+               printf("    <img src=\"/swat/images/%s_flat.png\" alt=\"%s\" />\n", 
+                  id, name);
+       } else {
+               printf("    <a href=\"%s/%s\" onmouseover=\"swapImg('%s','%sOver')\" onmouseout=\"swapImg('%s','%sLink')\"><img src=\"/swat/images/%s_link.png\" name=\"%s\" alt=\"%s\" /></a>\n",
+              cgi_baseurl(), id, id, id, id, id, id, id, name);
+       }
 }
 
 /****************************************************************************
   display the main navigation controls at the top of each page along
   with a title 
 ****************************************************************************/
-static void show_main_buttons(void)
+static void show_main_buttons(const char *page)
 {
        char *p;
        
-       if ((p = cgi_user_name()) && strcmp(p, "root")) {
-               printf(_("Logged in as <b>%s</b>"), p);
-               printf("<p>\n");
-       }
+       printf("  <div id=\"nav\">\n");
 
-       image_link(_("Home"), "", "images/home.gif");
        if (have_write_access) {
-               image_link(_("Globals"), "globals", "images/globals.gif");
-               image_link(_("Shares"), "shares", "images/shares.gif");
-               image_link(_("Printers"), "printers", "images/printers.gif");
-               image_link(_("Wizard"), "wizard", "images/wizard.gif");
+               rollover_link(_("Configure"), "conf", page);
+               rollover_link(_("Services"), "services", page);
        }
-   /* root always gets all buttons, otherwise look for -P */
+   
+       /* root always gets all buttons, otherwise look for -P */
        if ( have_write_access || (!passwd_only && have_read_access) ) {
-               image_link(_("Status"), "status", "images/status.gif");
-               image_link(_("View Config"), "viewconfig", "images/viewconfig.gif");
+               rollover_link(_("Status"), "status", page);
+       }
+       rollover_link(_("Password Management"), "passwd", page);
+       
+       printf("  </div>\n\n");
+       
+       /* Wrap the rest in a control div */
+       printf("  <div id=\"controls\">\n\n");
+
+       if ((p = cgi_user_name()) && strcmp(p, "root")) {
+               printf(_("Logged in as <b>%s</b>"), p);
+               printf("<p>\n");
        }
-       image_link(_("Password Management"), "passwd", "images/passwd.gif");
 
-       printf("<HR>\n");
 }
 
 /****************************************************************************
@@ -576,11 +584,47 @@ static void ViewModeBoxes(int mode)
 }
 
 /****************************************************************************
-  display a welcome page  
+  display a welcome page (Read-only users under passwd only get a unique welcome)
 ****************************************************************************/
 static void welcome_page(void)
 {
-       include_html("help/welcome.html");
+       if (passwd_only && !have_write_access) {
+               include_html("help/welcome_passwd_only.html");
+       } else {
+               include_html("help/welcome.html");
+       }
+}
+
+/****************************************************************************
+  display help page  
+****************************************************************************/
+static void help_page(void)
+{
+       include_html("help/docs.html");
+}
+
+/****************************************************************************
+  display shares and printers links from an overall services page
+****************************************************************************/
+static void services_page(void)
+{
+       printf("  <div class=\"whereto\">\n");
+       printf("    <h2>File and Printer Shares</h2>\n\n");
+       printf("    <p>Follow the links below to edit service-level parameters for file and printer shares.</p>\n");
+       printf("  </div>\n\n");
+
+       printf("  <div class=\"view_conf\"><a href=\"viewconfig\" onclick=\"openHelp(this.href); return false\">View smb.conf file</a></div>\n\n");
+
+       printf("  <div class=\"services_opts\">\n");
+       printf("    <ul>\n");
+       printf("      <li><a href=\"shares\">File Shares</a></li>\n");
+       printf("      <li><a href=\"printers\">Printer Shares</a></li>\n");
+       printf("    </ul>\n");
+       printf("  </div>\n\n");
+
+       printf("  <div>\n");
+       printf("    <p>Shares may also be added via the links above.</p>\n");
+       printf("  </div>\n\n");
 }
 
 /****************************************************************************
@@ -648,7 +692,9 @@ static void rewritecfg_file(void)
 {
        commit_parameters(GLOBAL_SECTION_SNUM);
        save_reload(0);
-       printf("<H2>%s</H2>\n", _("Note: smb.conf file has been read and rewritten"));
+       printf("<h2>Samba Configuration Saved</h2>");
+       printf("<p>%s</p>\n", _("Note: smb.conf file has been read and rewritten"));
+       printf("<p>Return to the <a href=\"javascript:history.go(-1)\">previous page</a>.\n");
 }
 
 /****************************************************************************
@@ -760,7 +806,7 @@ static void wizard_page(void)
        printf("<form method=post action=wizard>\n");
 
        if (have_write_access) {
-               printf("%s\n", _("The \"Rewrite smb.conf file\" button will clear the smb.conf file of all default values and of comments."));
+               printf("%s\n", _("The &quot;Rewrite smb.conf file&quot; button will clear the smb.conf file of all default values and of comments."));
                printf("%s", _("The same will happen if you press the commit button."));
                printf("<br><br>\n");
                printf("<center>");
@@ -820,14 +866,19 @@ static void wizard_page(void)
 
 
 /****************************************************************************
-  display a globals editing page  
+  display a conf page for editing global parameters 
 ****************************************************************************/
-static void globals_page(void)
+static void conf_page(void)
 {
        unsigned int parm_filter = FLAG_BASIC;
        int mode = 0;
 
-       printf("<H2>%s</H2>\n", _("Global Parameters"));
+       printf("  <div class=\"whereto\">\n");
+       printf("    <h2>Configuring Samba</h2>\n\n");
+       printf("    <p>The following menu allows for editing of global parameters affecting your Samba configuration.</p>\n");
+       printf("  </div>\n\n");
+
+       printf("  <div class=\"view_conf\"><a href=\"viewconfig\" onclick=\"openHelp(this.href); return false\">View smb.conf file</a></div>\n\n");
 
        if (cgi_variable("Commit")) {
                commit_parameters(GLOBAL_SECTION_SNUM);
@@ -841,7 +892,7 @@ static void globals_page(void)
        if ( cgi_variable("AdvMode"))
                mode = 1;
 
-       printf("<form name=\"swatform\" method=post action=globals>\n");
+       printf("<form name=\"swatform\" method=post action=conf>\n");
 
        ViewModeBoxes( mode );
        switch ( mode ) {
@@ -885,6 +936,8 @@ static void shares_page(void)
                snum = lp_servicenumber(share);
 
        printf("<H2>%s</H2>\n", _("Share Parameters"));
+       
+       printf("  <div class=\"view_conf\"><a href=\"services\">Return to Services Page</a><a href=\"viewconfig\" onclick=\"openHelp(this.href); return false\">View smb.conf file</a></div>\n\n");
 
        if (cgi_variable("Commit") && snum >= 0) {
                commit_parameters(snum);
@@ -1226,6 +1279,8 @@ static void printers_page(void)
                snum = lp_servicenumber(share);
 
         printf("<H2>%s</H2>\n", _("Printer Parameters"));
+
+       printf("  <div class=\"view_conf\"><a href=\"services\">Return to Services Page</a><a href=\"viewconfig\" onclick=\"openHelp(this.href); return false\">View smb.conf file</a></div>\n\n");
  
         printf("<H3>%s</H3>\n", _("Important Note:"));
         printf(_("Printer names marked with [*] in the Choose Printer drop-down box "));
@@ -1395,29 +1450,32 @@ static void printers_page(void)
                have_read_access = (access(dyn_CONFIGFILE,R_OK) == 0);
        }
 
-       show_main_buttons();
-
        page = cgi_pathinfo();
 
-       /* Root gets full functionality */
-       if (have_read_access && strcmp(page, "globals")==0) {
-               globals_page();
+       show_main_buttons(page);
+
+       if (have_read_access && strcmp(page,"conf")==0) { 
+               conf_page();
+       } else if (have_read_access && strcmp(page,"viewconfig")==0) {
+               viewconfig_page();
+       } else if (have_read_access && strcmp(page,"rewritecfg")==0) {
+               rewritecfg_file();
+       } else if (have_read_access && strcmp(page,"services")==0) {
+               services_page();
        } else if (have_read_access && strcmp(page,"shares")==0) {
                shares_page();
        } else if (have_read_access && strcmp(page,"printers")==0) {
                printers_page();
        } else if (have_read_access && strcmp(page,"status")==0) {
                status_page();
-       } else if (have_read_access && strcmp(page,"viewconfig")==0) {
-               viewconfig_page();
        } else if (strcmp(page,"passwd")==0) {
                passwd_page();
        } else if (have_read_access && strcmp(page,"wizard")==0) {
                wizard_page();
        } else if (have_read_access && strcmp(page,"wizard_params")==0) {
                wizard_params_page();
-       } else if (have_read_access && strcmp(page,"rewritecfg")==0) {
-               rewritecfg_file();
+       } else if (have_read_access && strcmp(page,"help")==0) {
+               help_page();
        } else {
                welcome_page();
        }