sync'ing up for 3.0alpha20 release
authorGerald Carter <jerry@samba.org>
Wed, 25 Sep 2002 15:19:00 +0000 (15:19 +0000)
committerGerald Carter <jerry@samba.org>
Wed, 25 Sep 2002 15:19:00 +0000 (15:19 +0000)
(This used to be commit 65e7b5273bb58802bf0c389b77f7fcae0a1f6139)

176 files changed:
source3/CodingSuggestions
source3/Makefile.in
source3/acconfig.h
source3/auth/auth_builtin.c
source3/auth/auth_domain.c
source3/auth/auth_sam.c
source3/auth/auth_server.c
source3/auth/auth_util.c
source3/auth/auth_winbind.c
source3/client/client.c
source3/client/smbmnt.c
source3/configure
source3/configure.in
source3/groupdb/aliasdb.c
source3/groupdb/groupdb.c
source3/groupdb/mapping.c
source3/include/ads.h
source3/include/asn_1.h
source3/include/client.h
source3/include/config.h.in
source3/include/debug.h
source3/include/doserr.h
source3/include/includes.h
source3/include/libsmbclient.h
source3/include/local.h
source3/include/messages.h
source3/include/nt_printing.h
source3/include/printing.h
source3/include/rpc_netlogon.h
source3/include/rpc_spoolss.h
source3/include/smb.h
source3/include/smb_acls.h
source3/include/smb_macros.h
source3/include/smbprofile.h
source3/include/trans2.h
source3/include/version.h
source3/include/vfs.h
source3/lib/account_pol.c
source3/lib/charcnv.c
source3/lib/debug.c
source3/lib/error.c
source3/lib/messages.c
source3/lib/popt_common.c
source3/lib/readline.c
source3/lib/server_mutex.c
source3/lib/substitute.c
source3/lib/system.c
source3/lib/system_smbd.c
source3/lib/time.c
source3/lib/username.c
source3/lib/util.c
source3/lib/util_seaccess.c
source3/lib/util_sid.c
source3/lib/util_sock.c
source3/lib/util_unistr.c
source3/lib/xfile.c
source3/libads/ads_status.c
source3/libads/kerberos.c
source3/libads/krb5_setpw.c
source3/libads/ldap.c
source3/libads/ldap_printer.c
source3/libads/sasl.c
source3/libads/util.c
source3/libsmb/asn1.c
source3/libsmb/cliconnect.c
source3/libsmb/clientgen.c
source3/libsmb/clierror.c
source3/libsmb/clifile.c
source3/libsmb/clikrb5.c
source3/libsmb/clilist.c
source3/libsmb/clireadwrite.c
source3/libsmb/clispnego.c
source3/libsmb/libsmb_cache.c
source3/libsmb/libsmbclient.c
source3/libsmb/namecache.c
source3/libsmb/nterr.c
source3/libsmb/smbencrypt.c
source3/libsmb/trust_passwd.c
source3/locking/locking.c
source3/nmbd/nmbd_processlogon.c
source3/nmbd/nmbd_synclists.c
source3/nsswitch/pam_winbind.c
source3/nsswitch/pam_winbind.h
source3/nsswitch/wb_common.c
source3/nsswitch/wbinfo.c
source3/nsswitch/winbind_nss.c
source3/nsswitch/winbind_nss_config.h
source3/nsswitch/winbindd.c
source3/nsswitch/winbindd_ads.c
source3/nsswitch/winbindd_cm.c
source3/nsswitch/winbindd_nss.h
source3/nsswitch/winbindd_pam.c
source3/nsswitch/winbindd_rpc.c
source3/nsswitch/winbindd_util.c
source3/pam_smbpass/pam_smb_passwd.c
source3/param/loadparm.c
source3/passdb/machine_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_nisplus.c
source3/passdb/pdb_plugin.c
source3/passdb/pdb_smbpasswd.c
source3/passdb/secrets.c
source3/printing/notify.c
source3/printing/nt_printing.c
source3/printing/print_cups.c
source3/printing/printfsp.c
source3/printing/printing.c
source3/profile/profile.c
source3/registry/reg_frontend.c
source3/registry/reg_printing.c
source3/rpc_client/cli_netlogon.c
source3/rpc_client/cli_pipe.c
source3/rpc_client/cli_spoolss.c
source3/rpc_client/cli_spoolss_notify.c
source3/rpc_parse/parse_misc.c
source3/rpc_parse/parse_net.c
source3/rpc_parse/parse_prs.c
source3/rpc_parse/parse_reg.c
source3/rpc_parse/parse_spoolss.c
source3/rpc_parse/parse_srv.c
source3/rpc_server/srv_lsa_nt.c
source3/rpc_server/srv_netlog_nt.c
source3/rpc_server/srv_pipe.c
source3/rpc_server/srv_reg_nt.c
source3/rpc_server/srv_samr_nt.c
source3/rpc_server/srv_spoolss_nt.c
source3/rpc_server/srv_srvsvc_nt.c
source3/rpcclient/cmd_lsarpc.c
source3/rpcclient/cmd_netlogon.c
source3/rpcclient/cmd_spoolss.c
source3/rpcclient/rpcclient.c
source3/rpcclient/samsync.c
source3/smbd/blocking.c
source3/smbd/conn.c
source3/smbd/connection.c
source3/smbd/dir.c
source3/smbd/filename.c
source3/smbd/mangle_hash.c
source3/smbd/mangle_hash2.c
source3/smbd/negprot.c
source3/smbd/nttrans.c
source3/smbd/open.c
source3/smbd/password.c
source3/smbd/posix_acls.c
source3/smbd/process.c
source3/smbd/reply.c
source3/smbd/sec_ctx.c
source3/smbd/server.c
source3/smbd/service.c
source3/smbd/sesssetup.c
source3/smbd/trans2.c
source3/smbd/uid.c
source3/smbd/vfs-wrap.c
source3/smbd/vfs.c
source3/tdb/spinlock.c
source3/tdb/tdb.c
source3/tdb/tdb.h
source3/tdb/tdbbackup.c
source3/tdb/tdbdump.c
source3/tdb/tdbtest.c
source3/tdb/tdbtool.c
source3/torture/torture.c
source3/utils/net.c
source3/utils/net_ads.c
source3/utils/net_help.c
source3/utils/net_rpc.c
source3/utils/net_rpc_join.c
source3/utils/pdbedit.c
source3/utils/smbcontrol.c
source3/utils/smbpasswd.c
source3/utils/status.c
source3/utils/testparm.c
source3/web/swat.c

index e5f366ec7106ae2658a9f8472c63fdb322e0a11f..5e99bc54caefe37fe3b3cd053593666581899ba8 100644 (file)
@@ -29,7 +29,7 @@ programmers who have contributed.
 
 The indent utility can be used to format C files in the general 
 samba coding style. The arguments you should give to indent are:
--bad -bap -br -ce -cdw -nbc -brs -bbb -nbc -npsl
+-bad -bap -br -ce -cdw -nbc -brs -bbb -nbc -npsl -ut -i8
 
 Following are some considerations you should use when adding new code to
 Samba.  First and foremost remember that:
index 2db6d550113c5d2feeaa0d0fc803ed0cadb689f8..f3d9b7ec09956774df5e15bd5b60c82cd03b0a15 100644 (file)
@@ -18,9 +18,11 @@ LDFLAGS=@LDFLAGS@
 LDSHFLAGS=@LDSHFLAGS@ @LDFLAGS@ @CFLAGS@
 AWK=@AWK@
 DYNEXP=@DYNEXP@
+PYTHON=@PYTHON@
 
 TERMLDFLAGS=@TERMLDFLAGS@
 TERMLIBS=@TERMLIBS@
+PRINTLIBS=@PRINTLIBS@
 
 LINK=$(CC) $(FLAGS) $(LDFLAGS)
 
@@ -106,7 +108,7 @@ LPROGS = $(WINBIND_PAM_PROGS) $(WINBIND_LPROGS)
 
 PROGS = $(PROGS1) $(PROGS2) $(MPROGS) bin/nmblookup bin/pdbedit bin/smbgroupedit
 TORTURE_PROGS = bin/smbtorture bin/msgtest bin/masktest bin/locktest \
-       bin/locktest2 bin/nsstest
+       bin/locktest2 bin/nsstest bin/vfstest
 SHLIBS = @LIBSMBCLIENT@
 
 SCRIPTS = $(srcdir)/script/smbtar $(srcdir)/script/addtosmbpass $(srcdir)/script/convert_smbpasswd \
@@ -124,7 +126,7 @@ TDB_OBJ = $(TDBBASE_OBJ) tdb/tdbutil.o
 LIB_OBJ = lib/charcnv.o lib/debug.o lib/fault.o \
           lib/getsmbpass.o lib/interface.o lib/md4.o \
           lib/interfaces.o lib/pidfile.o lib/replace.o \
-          lib/signal.o lib/system.o lib/time.o \
+          lib/signal.o lib/system.o lib/sendfile.o lib/time.o \
          lib/ufc.o lib/genrand.o lib/username.o \
          lib/util_getent.o lib/util_pw.o lib/access.o lib/smbrun.o \
          lib/bitmap.o lib/crc32.o lib/snprintf.o lib/dprintf.o \
@@ -134,11 +136,11 @@ LIB_OBJ = lib/charcnv.o lib/debug.o lib/fault.o \
          lib/util.o lib/util_sock.o lib/util_sec.o \
          lib/talloc.o lib/hash.o lib/substitute.o lib/fsusage.o \
          lib/ms_fnmatch.o lib/select.o lib/error.o lib/messages.o \
-         lib/server_mutex.o lib/tallocmsg.o lib/dmallocmsg.o \
+         lib/tallocmsg.o lib/dmallocmsg.o \
          lib/md5.o lib/hmacmd5.o lib/iconv.o lib/smbpasswd.o \
          nsswitch/wb_client.o nsswitch/wb_common.o \
          lib/pam_errors.o intl/lang_tdb.o lib/account_pol.o \
-         lib/adt_tree.o lib/popt_common.o $(TDB_OBJ) 
+         lib/adt_tree.o lib/popt_common.o lib/gencache.o $(TDB_OBJ) 
 
 LIB_SMBD_OBJ = lib/system_smbd.o lib/util_smbd.o
 
@@ -152,7 +154,7 @@ PARAM_OBJ = param/loadparm.o param/params.o dynconfig.o
 LIBADS_OBJ = libads/ldap.o libads/ldap_printer.o libads/sasl.o \
             libads/krb5_setpw.o libads/kerberos.o libads/ldap_user.o \
             libads/ads_struct.o libads/ads_status.o \
-             libads/disp_sec.o
+             libads/disp_sec.o libads/ads_utils.o
 
 LIBADS_SERVER_OBJ = libads/util.o libads/kerberos_verify.o
 
@@ -180,8 +182,9 @@ LIBMSRPC_SERVER_OBJ = libsmb/trust_passwd.o
 
 LIBMSRPC_PICOBJ = $(LIBMSRPC_OBJ:.o=.po)
 
+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_db.o 
 
 RPC_SERVER_OBJ = rpc_server/srv_lsa.o rpc_server/srv_lsa_nt.o \
                  rpc_server/srv_lsa_hnd.o rpc_server/srv_netlog.o rpc_server/srv_netlog_nt.o \
@@ -190,7 +193,7 @@ RPC_SERVER_OBJ = rpc_server/srv_lsa.o rpc_server/srv_lsa_nt.o \
                 rpc_server/srv_srvsvc.o rpc_server/srv_srvsvc_nt.o \
                  rpc_server/srv_util.o rpc_server/srv_wkssvc.o rpc_server/srv_wkssvc_nt.o \
                  rpc_server/srv_pipe.o rpc_server/srv_dfs.o rpc_server/srv_dfs_nt.o \
-                 rpc_server/srv_spoolss.o rpc_server/srv_spoolss_nt.o $(REGISTRY_OBJ)
+                 rpc_server/srv_spoolss.o rpc_server/srv_spoolss_nt.o 
 
 # this includes only the low level parse code, not stuff
 # that requires knowledge of security contexts
@@ -201,7 +204,8 @@ RPC_PARSE_OBJ = rpc_parse/parse_lsa.o rpc_parse/parse_net.o \
                 rpc_parse/parse_reg.o rpc_parse/parse_rpc.o \
                 rpc_parse/parse_samr.o rpc_parse/parse_srv.o \
                 rpc_parse/parse_wks.o \
-               rpc_parse/parse_spoolss.o rpc_parse/parse_dfs.o
+               rpc_parse/parse_spoolss.o rpc_parse/parse_dfs.o \
+               $(REGOBJS_OBJ)
 
 
 RPC_CLIENT_OBJ = rpc_client/cli_pipe.o
@@ -213,8 +217,15 @@ PASSDB_GET_SET_OBJ = passdb/pdb_get_set.o
 PASSDB_OBJ = $(PASSDB_GET_SET_OBJ) passdb/passdb.o passdb/pdb_interface.o \
                passdb/machine_sid.o passdb/pdb_smbpasswd.o \
                passdb/pdb_tdb.o passdb/pdb_ldap.o passdb/pdb_plugin.o \
-               passdb/pdb_nisplus.o passdb/pdb_unix.o passdb/util_sam_sid.o \
-               passdb/pdb_compat.o
+               passdb/pdb_unix.o passdb/util_sam_sid.o \
+               passdb/pdb_compat.o passdb/pdb_nisplus.o
+
+SAM_STATIC_MODULES = sam/sam_plugin.o
+
+SAM_OBJ = sam/account.o sam/get_set_account.o sam/get_set_group.o \
+               sam/get_set_domain.o sam/interface.o sam/api.o $(SAM_STATIC_MODULES)
+
+SAMTEST_OBJ = torture/samtest.o torture/cmd_sam.o $(SAM_OBJ) $(LIB_OBJ) $(PARAM_OBJ) $(LIBSMB_OBJ) $(UBIQX_OBJ) $(READLINE_OBJ) lib/util_seaccess.o $(LIBADS_OBJ) $(PASSDB_OBJ) $(SECRETS_OBJ) $(GROUPDB_OBJ)
 
 GROUPDB_OBJ = groupdb/mapping.o
 
@@ -232,25 +243,37 @@ UNIGRP_OBJ = libsmb/netlogon_unigrp.o
 
 AUTH_OBJ = auth/auth.o auth/auth_sam.o auth/auth_server.o auth/auth_domain.o \
           auth/auth_rhosts.o auth/auth_unix.o auth/auth_util.o auth/auth_winbind.o \
-          auth/auth_builtin.o auth/auth_compat.o $(PLAINTEXT_AUTH_OBJ) $(UNIGRP_OBJ)
+          auth/auth_builtin.o auth/auth_compat.o \
+          $(PLAINTEXT_AUTH_OBJ) $(UNIGRP_OBJ)
 
 MANGLE_OBJ = smbd/mangle.o smbd/mangle_hash.o smbd/mangle_map.o smbd/mangle_hash2.o
 
-SMBD_OBJ1 = smbd/server.o smbd/files.o smbd/chgpasswd.o smbd/connection.o \
-           smbd/utmp.o smbd/session.o \
-            smbd/dfree.o smbd/dir.o smbd/password.o smbd/conn.o smbd/fileio.o \
-            smbd/ipc.o smbd/lanman.o smbd/negprot.o \
-            smbd/message.o smbd/nttrans.o smbd/pipes.o \
-            smbd/reply.o smbd/sesssetup.o smbd/trans2.o smbd/uid.o \
-           smbd/dosmode.o smbd/filename.o smbd/open.o smbd/close.o \
-           smbd/blocking.o smbd/sec_ctx.o \
-           smbd/vfs.o smbd/vfs-wrap.o smbd/statcache.o \
-            smbd/posix_acls.o lib/sysacls.o \
-           smbd/process.o smbd/service.o smbd/error.o \
-           printing/printfsp.o lib/util_seaccess.o smbd/srvstr.o \
-            smbd/build_options.o \
-           smbd/change_trust_pw.o \
-           $(MANGLE_OBJ)
+SMBD_OBJ_MAIN = smbd/server.o
+
+SMBD_OBJ_SRV = smbd/files.o smbd/chgpasswd.o smbd/connection.o \
+              smbd/utmp.o smbd/session.o \
+               smbd/dfree.o smbd/dir.o smbd/password.o smbd/conn.o smbd/fileio.o \
+               smbd/ipc.o smbd/lanman.o smbd/negprot.o \
+               smbd/message.o smbd/nttrans.o smbd/pipes.o \
+               smbd/reply.o smbd/sesssetup.o smbd/trans2.o smbd/uid.o \
+              smbd/dosmode.o smbd/filename.o smbd/open.o smbd/close.o \
+              smbd/blocking.o smbd/sec_ctx.o \
+              smbd/vfs.o smbd/vfs-wrap.o smbd/statcache.o \
+               smbd/posix_acls.o lib/sysacls.o lib/server_mutex.o \
+              smbd/process.o smbd/service.o smbd/error.o \
+              printing/printfsp.o lib/util_seaccess.o smbd/srvstr.o \
+               smbd/build_options.o \
+              smbd/change_trust_pw.o \
+              $(MANGLE_OBJ)
+
+SMBD_OBJ_BASE = $(SMBD_OBJ_SRV) $(MSDFS_OBJ) $(PARAM_OBJ) $(LIBSMB_OBJ) $(UBIQX_OBJ) \
+               $(RPC_SERVER_OBJ) $(RPC_PARSE_OBJ) $(SECRETS_OBJ) \
+               $(LOCKING_OBJ) $(PASSDB_OBJ) $(PRINTING_OBJ) $(PROFILE_OBJ) \
+               $(LIB_OBJ) $(PRINTBACKEND_OBJ) $(QUOTAOBJS) $(OPLOCK_OBJ) \
+               $(NOTIFY_OBJ) $(GROUPDB_OBJ) $(AUTH_OBJ) \
+               $(LIBMSRPC_OBJ) $(LIBMSRPC_SERVER_OBJ) \
+               $(LIBADS_OBJ) $(LIBADS_SERVER_OBJ) \
+               $(LIB_SMBD_OBJ) $(REGISTRY_OBJ)
 
 
 PRINTING_OBJ = printing/pcap.o printing/print_svid.o \
@@ -261,15 +284,7 @@ PRINTBACKEND_OBJ = printing/printing.o printing/nt_printing.o printing/notify.o
 
 MSDFS_OBJ = msdfs/msdfs.o 
 
-SMBD_OBJ = $(SMBD_OBJ1) $(MSDFS_OBJ) $(PARAM_OBJ) $(LIBSMB_OBJ) $(UBIQX_OBJ) \
-           $(RPC_SERVER_OBJ) $(RPC_PARSE_OBJ) $(SECRETS_OBJ) \
-           $(LOCKING_OBJ) $(PASSDB_OBJ) $(PRINTING_OBJ) $(PROFILE_OBJ) \
-          $(LIB_OBJ) $(PRINTBACKEND_OBJ) $(QUOTAOBJS) $(OPLOCK_OBJ) \
-          $(NOTIFY_OBJ) $(GROUPDB_OBJ) $(AUTH_OBJ) \
-          $(LIBMSRPC_OBJ) $(LIBMSRPC_SERVER_OBJ) \
-          $(LIBADS_OBJ) $(LIBADS_SERVER_OBJ) \
-          $(LIB_SMBD_OBJ)
-
+SMBD_OBJ = $(SMBD_OBJ_MAIN) $(SMBD_OBJ_BASE)
 
 NMBD_OBJ1 = nmbd/asyncdns.o nmbd/nmbd.o nmbd/nmbd_become_dmb.o \
             nmbd/nmbd_become_lmb.o nmbd/nmbd_browserdb.o \
@@ -343,13 +358,6 @@ RPCCLIENT_OBJ = $(RPCCLIENT_OBJ1) \
              $(READLINE_OBJ) $(GROUPDB_OBJ) \
             $(LIBADS_OBJ) $(SECRETS_OBJ)
 
-SAMSYNC_OBJ1 = rpcclient/samsync.o rpcclient/display_sec.o
-
-SAMSYNC_OBJ = $(SAMSYNC_OBJ1) \
-             $(PARAM_OBJ) $(LIBSMB_OBJ) $(UBIQX_OBJ) $(LIB_OBJ) \
-             $(RPC_PARSE_OBJ) $(PASSDB_OBJ) $(LIBMSRPC_OBJ) \
-             $(GROUPDB_OBJ) $(SECRETS_OBJ)
-
 PAM_WINBIND_OBJ = nsswitch/pam_winbind.po nsswitch/wb_common.po lib/snprintf.po
 
 SMBW_OBJ1 = smbwrapper/smbw.o \
@@ -373,12 +381,13 @@ CLIENT_OBJ1 = client/client.o client/clitar.o
 CLIENT_OBJ = $(CLIENT_OBJ1) $(PARAM_OBJ) $(LIBSMB_OBJ) $(UBIQX_OBJ) $(LIB_OBJ) \
              $(READLINE_OBJ) 
 
-NET_OBJ1 = utils/net.o utils/net_ads.o utils/net_help.o \
-          utils/net_rap.o utils/net_rpc.o \
-          utils/net_rpc_join.o utils/net_time.o utils/net_lookup.o
+NET_OBJ1 = utils/net.o utils/net_ads.o utils/net_ads_cldap.o utils/net_help.o \
+          utils/net_rap.o utils/net_rpc.o utils/net_rpc_samsync.o \
+          utils/net_rpc_join.o utils/net_time.o utils/net_lookup.o \
+          utils/net_cache.o
 
 NET_OBJ = $(NET_OBJ1) $(SECRETS_OBJ) $(LIBSMB_OBJ) \
-         $(RPC_PARSE_OBJ) $(PASSDB_GET_SET_OBJ) \
+         $(RPC_PARSE_OBJ) $(PASSDB_OBJ) $(GROUPDB_OBJ) \
          $(PARAM_OBJ) $(UBIQX_OBJ) $(LIB_OBJ) \
          $(LIBMSRPC_OBJ) $(LIBMSRPC_SERVER_OBJ) \
          $(LIBADS_OBJ) $(LIBADS_SERVER_OBJ)
@@ -414,6 +423,8 @@ LOCKTEST_OBJ = torture/locktest.o $(LOCKING_OBJ) $(LIBSMB_OBJ) $(PARAM_OBJ) \
 NSSTEST_OBJ = torture/nsstest.o $(LIBSMB_OBJ) $(PARAM_OBJ) \
                  $(UBIQX_OBJ) $(LIB_OBJ)
 
+VFSTEST_OBJ = torture/cmd_vfs.o torture/vfstest.o $(SMBD_OBJ_BASE) $(READLINE_OBJ)
+
 LOCKTEST2_OBJ = torture/locktest2.o $(LOCKING_OBJ) $(LIBSMB_OBJ) $(PARAM_OBJ) \
                  $(UBIQX_OBJ) $(LIB_OBJ)
 
@@ -438,15 +449,16 @@ DEBUG2HTML_OBJ = utils/debug2html.o ubiqx/debugparse.o
 SMBFILTER_OBJ = utils/smbfilter.o $(LIBSMB_OBJ) $(PARAM_OBJ) \
                  $(UBIQX_OBJ) $(LIB_OBJ)
 
-PROTO_OBJ = $(SMBD_OBJ1) $(NMBD_OBJ1) $(SWAT_OBJ1) $(LIB_OBJ) $(LIBSMB_OBJ) \
-           $(SMBWRAPPER_OBJ1) $(SMBTORTURE_OBJ1) $(RPCCLIENT_OBJ1) \
+PROTO_OBJ = $(SMBD_OBJ_MAIN) \
+           $(SMBD_OBJ_SRV) $(NMBD_OBJ1) $(SWAT_OBJ1) $(LIB_OBJ) $(LIBSMB_OBJ) \
+           $(SMBW_OBJ1) $(SMBWRAPPER_OBJ1) $(SMBTORTURE_OBJ1) $(RPCCLIENT_OBJ1) \
            $(LIBMSRPC_OBJ) $(LIBMSRPC_SERVER_OBJ) $(RPC_CLIENT_OBJ) \
            $(RPC_SERVER_OBJ) $(RPC_PARSE_OBJ) \
            $(AUTH_OBJ) $(PARAM_OBJ) $(LOCKING_OBJ) $(SECRETS_OBJ) \
            $(PRINTING_OBJ) $(PRINTBACKEND_OBJ) $(OPLOCK_OBJ) $(NOTIFY_OBJ) \
            $(QUOTAOBJS) $(PASSDB_OBJ) $(GROUPDB_OBJ) $(MSDFS_OBJ) \
            $(READLINE_OBJ) $(PROFILE_OBJ) $(LIBADS_OBJ) $(LIBADS_SERVER_OBJ) \
-           $(LIB_SMBD_OBJ) 
+           $(LIB_SMBD_OBJ) $(SAM_OBJ) $(REGISTRY_OBJ)
 
 NSS_OBJ_0 = nsswitch/wins.o $(PARAM_OBJ) $(UBIQX_OBJ) $(LIBSMB_OBJ) \
            $(LIB_OBJ) $(NSSWINS_OBJ)
@@ -486,7 +498,7 @@ WINBINDD_OBJ = \
                $(LIBNMB_OBJ) $(PARAM_OBJ) $(UBIQX_OBJ) $(LIB_OBJ) \
                $(LIBSMB_OBJ) $(LIBMSRPC_OBJ) $(RPC_PARSE_OBJ) \
                $(PROFILE_OBJ) $(UNIGRP_OBJ) \
-               $(SECRETS_OBJ) $(LIBADS_OBJ)
+               $(SECRETS_OBJ) $(LIBADS_OBJ) 
 
 WBINFO_OBJ = nsswitch/wbinfo.o libsmb/smbencrypt.o libsmb/smbdes.o
 
@@ -534,7 +546,7 @@ nsswitch : SHOWFLAGS $(WINBIND_PROGS) $(WINBIND_SPROGS) $(LPROGS)
 
 wins : SHOWFLAGS nsswitch/libnss_wins.so
 
-everything: all libsmbclient debug2html smbfilter talloctort bin/samsync bin/make_printerdef
+everything: all libsmbclient debug2html smbfilter talloctort bin/make_printerdef
 
 .SUFFIXES:
 .SUFFIXES: .c .o .po .po32 .lo
@@ -605,7 +617,7 @@ bin/.dummy:
 
 bin/smbd: $(SMBD_OBJ) bin/.dummy
        @echo Linking $@
-       @$(CC) $(FLAGS) -o $@ $(SMBD_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) 
+       @$(CC) $(FLAGS) -o $@ $(SMBD_OBJ) $(LDFLAGS) $(DYNEXP) $(PRINTLIBS) $(LIBS) 
 
 bin/nmbd: $(NMBD_OBJ) bin/.dummy
        @echo Linking $@
@@ -617,16 +629,12 @@ bin/wrepld: $(WREPL_OBJ) bin/.dummy
 
 bin/swat: $(SWAT_OBJ) bin/.dummy
        @echo Linking $@
-       @$(CC) $(FLAGS) -o $@ $(SWAT_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) 
+       @$(CC) $(FLAGS) -o $@ $(SWAT_OBJ) $(LDFLAGS) $(DYNEXP) $(PRINTLIBS) $(LIBS) 
 
 bin/rpcclient: $(RPCCLIENT_OBJ) @BUILD_POPT@ bin/.dummy
        @echo Linking $@
        @$(CC) $(FLAGS) -o $@ $(RPCCLIENT_OBJ) $(LDFLAGS) $(DYNEXP) $(TERMLDFLAGS) $(TERMLIBS) $(LIBS) @BUILD_POPT@
 
-bin/samsync: $(SAMSYNC_OBJ) bin/.dummy
-       @echo Linking $@
-       @$(CC) $(FLAGS) -o $@ $(SAMSYNC_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS)
-
 bin/smbclient: $(CLIENT_OBJ) bin/.dummy
        @echo Linking $@
        @$(CC) $(FLAGS) -o $@ $(CLIENT_OBJ) $(LDFLAGS) $(TERMLDFLAGS) $(TERMLIBS) $(LIBS)
@@ -657,7 +665,7 @@ bin/testparm: $(TESTPARM_OBJ) bin/.dummy
 
 bin/testprns: $(TESTPRNS_OBJ) bin/.dummy
        @echo Linking $@
-       @$(CC) $(FLAGS) -o $@ $(TESTPRNS_OBJ) $(LDFLAGS) $(LIBS)
+       @$(CC) $(FLAGS) -o $@ $(TESTPRNS_OBJ) $(LDFLAGS) $(PRINTLIBS) $(LIBS)
 
 bin/smbstatus: $(STATUS_OBJ) @BUILD_POPT@ bin/.dummy
        @echo Linking $@
@@ -679,6 +687,10 @@ bin/pdbedit: $(PDBEDIT_OBJ) bin/.dummy
        @echo Linking $@
        @$(CC) $(FLAGS) -o $@ $(PDBEDIT_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) @BUILD_POPT@
 
+bin/samtest: $(SAMTEST_OBJ) bin/.dummy
+       @echo Linking $@
+       @$(CC) $(FLAGS) -o $@ $(SAMTEST_OBJ) $(LDFLAGS) $(DYNEXP) $(TERMLDFLAGS) $(TERMLIBS) $(DYNEXP) $(LIBS) @BUILD_POPT@
+
 bin/smbgroupedit: $(SMBGROUPEDIT_OBJ) bin/.dummy
        @echo Linking $@
        @$(CC) $(FLAGS) -o $@ $(SMBGROUPEDIT_OBJ) $(LDFLAGS) $(LIBS)
@@ -719,6 +731,10 @@ bin/nsstest: $(NSSTEST_OBJ) bin/.dummy
        @echo Linking $@
        @$(CC) $(FLAGS) -o $@ $(NSSTEST_OBJ) $(LDFLAGS) $(LIBS)
 
+bin/vfstest: $(VFSTEST_OBJ) bin/.dummy
+       @echo Linking $@
+       @$(CC) $(FLAGS) -o $@ $(VFSTEST_OBJ) $(LDFLAGS) $(TERMLDFLAGS) $(TERMLIBS) $(DYNEXP) $(PRINTLIBS) $(LIBS) @BUILD_POPT@
+
 bin/locktest2: $(LOCKTEST2_OBJ) bin/.dummy
        @echo Linking $@
        @$(CC) $(FLAGS) -o $@ $(LOCKTEST2_OBJ) $(LDFLAGS) $(LIBS)
@@ -802,10 +818,6 @@ bin/pam_smbpass.@SHLIBEXT@: $(PAM_SMBPASS_PICOOBJ)
 bin/libmsrpc.a: $(LIBMSRPC_PICOBJ)
        -$(AR) -rc $@ $(LIBMSRPC_PICOBJ) 
 
-bin/spamsync: rpcclient/samsync.o bin/libmsrpc.a
-       @$(LINK) -o $@ rpcclient/samsync.o bin/libmsrpc.a \
-               $(UBIQX_OBJ) $(LIBS)
-
 bin/tdbbackup: $(TDBBACKUP_OBJ) bin/.dummy
        @echo Linking $@
        @$(CC) $(FLAGS) -o $@ $(TDBBACKUP_OBJ)
@@ -836,6 +848,53 @@ installclientlib:
        -$(INSTALLCMD) -d ${prefix}/include
        -$(INSTALLCMD) include/libsmbclient.h ${prefix}/include
 
+# Python extensions
+
+PYTHON_OBJS = $(LIB_OBJ) $(LIBSMB_OBJ) $(RPC_PARSE_OBJ) $(UBIQX_OBJ) \
+       $(PARAM_OBJ) $(LIBMSRPC_OBJ) $(PASSDB_OBJ) $(GROUPDB_OBJ) $(SECRETS_OBJ)
+
+PY_SPOOLSS_PROTO_OBJ = python/py_spoolss.o \
+               python/py_spoolss_printers.o python/py_spoolss_printers_conv.o\
+               python/py_spoolss_forms.o python/py_spoolss_forms_conv.o \
+               python/py_spoolss_ports.o python/py_spoolss_ports_conv.o \
+               python/py_spoolss_drivers.o python/py_spoolss_drivers_conv.o \
+               python/py_spoolss_jobs.o python/py_spoolss_jobs_conv.o \
+               python/py_spoolss_printerdata.o
+
+PY_LSA_PROTO_OBJ = python/py_lsa.o
+
+PY_COMMON_PROTO_OBJ = python/py_common.c python/py_ntsec.c
+
+python_proto: python_spoolss_proto python_lsa_proto python_common_proto
+
+python_spoolss_proto:
+       @cd $(srcdir) && $(SHELL) script/mkproto.sh $(AWK) \
+               -h _PY_SPOOLSS_PROTO_H python/py_spoolss_proto.h \
+               $(PY_SPOOLSS_PROTO_OBJ)
+
+python_lsa_proto:
+       @cd $(srcdir) && $(SHELL) script/mkproto.sh $(AWK) \
+               -h _PY_LSA_PROTO_H python/py_lsa_proto.h \
+               $(PY_LSA_PROTO_OBJ)
+
+python_common_proto:
+       @cd $(srcdir) && $(SHELL) script/mkproto.sh $(AWK) \
+               -h _PY_COMMON_PROTO_H python/py_common_proto.h \
+               $(PY_COMMON_PROTO_OBJ)
+
+python_ext: $(PYTHON_OBJS)
+       PYTHON_OBJS="$(PYTHON_OBJS)" PYTHON_CFLAGS="$(CFLAGS) $(CPPFLAGS) $(FLAGS)" \
+       LIBS="$(LIBS)" \
+               $(PYTHON) python/setup.py build
+
+python_install: $(PYTHON_OBJS)
+       PYTHON_OBJS="$(PYTHON_OBJS)" PYTHON_CFLAGS="$(CFLAGS) $(CPPFLAGS)" \
+       LIBS="$(LIBS)" \
+               $(PYTHON) python/setup.py install
+
+python_clean:
+       @if test -n "$(PYTHON)"; then $(PYTHON) python/setup.py clean; fi
+
 # revert to the previously installed version
 revert:
        @$(SHELL) $(srcdir)/script/revert.sh $(SBINDIR) $(SPROGS) 
@@ -871,9 +930,9 @@ uninstallscripts:
 # Toplevel clean files
 TOPFILES=dynconfig.o dynconfig.po
 
-clean: delheaders
+clean: delheaders python_clean
        -rm -f core */*~ *~ */*.o */*.po */*.po32 */*.@SHLIBEXT@ \
-       $(TOPFILES) $(PROGS) $(SPROGS) .headers.stamp
+               $(TOPFILES) $(PROGS) $(SPROGS) .headers.stamp
 
 # Making this target will just make sure that the prototype files
 # exist, not necessarily that they are up to date.  Since they're
@@ -949,7 +1008,7 @@ etags:
 ctags:
        ctags `find $(srcdir) -name "*.[ch]" | grep -v /CVS/`
 
-realclean: clean
+realclean: clean delheaders
        -rm -f config.log $(PROGS) $(SPROGS) bin/.dummy
        -rmdir bin
 
index 274bc4aaadd861e7c0e810c182bfdc9fd53b83db..45d63669354d077e2cb8ba7a34ccfc16af7c8354 100644 (file)
 #undef MMAP_BLACKLIST
 #undef HAVE_IMMEDIATE_STRUCTURES
 #undef HAVE_CUPS
+#undef WITH_SAM
 #undef WITH_LDAP_SAM
 #undef WITH_NISPLUS_SAM
 #undef WITH_TDB_SAM
 #undef HAVE_LDAP
 #undef HAVE_STAT_ST_BLOCKS
 #undef STAT_ST_BLOCKSIZE
+#undef HAVE_STAT_ST_BLKSIZE
 #undef HAVE_DEVICE_MAJOR_FN
 #undef HAVE_DEVICE_MINOR_FN
 #undef HAVE_PASSWD_PW_COMMENT
 #endif
 
 #undef LDAP_SET_REBIND_PROC_ARGS
-
+#undef HAVE_SENDFILE
+#undef HAVE_SENDFILE64
+#undef LINUX_SENDFILE_API
+#undef LINUX_BROKEN_SENDFILE_API
+#undef WITH_SENDFILE
+#undef FREEBSD_SENDFILE_API
+#undef HPUX_SENDFILE_API
+#undef WITH_ADS
index 5ce7075ab9f9379a35a6bdc23242d711ad055f11..d54a8660b35d5e827f33bc62b0987b767ca95134 100644 (file)
@@ -41,13 +41,8 @@ static NTSTATUS check_guest_security(const struct auth_context *auth_context,
        NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE;
 
        if (!(user_info->internal_username.str 
-             && *user_info->internal_username.str)) { 
-               if (make_server_info_guest(server_info)) {
-                       nt_status = NT_STATUS_OK;
-               } else {
-                       nt_status = NT_STATUS_NO_SUCH_USER;
-               }
-       }
+             && *user_info->internal_username.str)) 
+               nt_status = make_server_info_guest(server_info);
 
        return nt_status;
 }
@@ -194,7 +189,7 @@ NTSTATUS auth_init_plugin(struct auth_context *auth_context, const char *param,
        trim_string(plugin_name, " ", " ");
 
        DEBUG(5, ("Trying to load auth plugin %s\n", plugin_name));
-       dl_handle = sys_dlopen(plugin_name, RTLD_NOW | RTLD_GLOBAL );
+       dl_handle = sys_dlopen(plugin_name, RTLD_NOW );
        if (!dl_handle) {
                DEBUG(0, ("Failed to load auth plugin %s using sys_dlopen (%s)\n", plugin_name, sys_dlerror()));
                return NT_STATUS_UNSUCCESSFUL;
index d48cec5b2932444b7e102f90410bf7c7c6614501..2e51a852816474dcdcd247bcc29b17ee984cec8f 100644 (file)
@@ -48,7 +48,7 @@ static NTSTATUS ads_resolve_dc(fstring remote_machine,
 
        DEBUG(4,("ads_resolve_dc: realm=%s\n", ads->config.realm));
 
-       ads->auth.no_bind = 1;
+       ads->auth.flags |= ADS_AUTH_NO_BIND;
 
 #ifdef HAVE_ADS
        /* a full ads_connect() is actually overkill, as we don't srictly need
@@ -131,6 +131,7 @@ static NTSTATUS connect_to_domain_password_server(struct cli_state **cli,
        struct in_addr dest_ip;
        fstring remote_machine;
         NTSTATUS result;
+       uint32 neg_flags = 0x000001ff;
 
        if (lp_security() == SEC_ADS) {
                result = ads_resolve_dc(remote_machine, &dest_ip);
@@ -206,7 +207,7 @@ machine %s. Error was : %s.\n", remote_machine, cli_errstr(*cli)));
                return NT_STATUS_NO_MEMORY;
        }
 
-       result = cli_nt_setup_creds(*cli, sec_chan, trust_passwd);
+       result = cli_nt_setup_creds(*cli, sec_chan, trust_passwd, &neg_flags, 2);
 
         if (!NT_STATUS_IS_OK(result)) {
                DEBUG(0,("connect_to_domain_password_server: unable to setup the PDC credentials to machine \
@@ -250,7 +251,7 @@ static NTSTATUS attempt_connect_to_dc(struct cli_state **cli,
 }
 
 /***********************************************************************
- We have been asked to dynamcially determine the IP addresses of
+ We have been asked to dynamically determine the IP addresses of
  the PDC and BDC's for DOMAIN, and query them in turn.
 ************************************************************************/
 static NTSTATUS find_connect_pdc(struct cli_state **cli, 
index 155370546a5b3827f56f85ecbbd4b8c766c305e5..bc98f46dc2f4676af5cec7e4f148256e96814ae9 100644 (file)
@@ -106,7 +106,10 @@ static BOOL smb_pwd_check_ntlmv2(const DATA_BLOB ntv2_response,
        client_key_data = data_blob(ntv2_response.data+16, ntv2_response.length-16);
        memcpy(client_response, ntv2_response.data, sizeof(client_response));
 
-       ntv2_owf_gen(part_passwd, user, domain, kr);
+       if (!ntv2_owf_gen(part_passwd, user, domain, kr)) {
+               return False;
+       }
+
        SMBOWFencrypt_ntv2(kr, sec_blob, client_key_data, value_from_encryption);
        if (user_sess_key != NULL)
        {
@@ -233,17 +236,17 @@ static NTSTATUS sam_password_ok(const struct auth_context *auth_context,
                        return NT_STATUS_OK;
                } else {
                        if (lp_ntlm_auth()) {                           
-                               /* Apparently NT accepts NT responses in the LM feild
-                                  - I think this is related to Win9X pass-though authenticaion
+                               /* Apparently NT accepts NT responses in the LM field
+                                  - I think this is related to Win9X pass-though authentication
                                */
-                               DEBUG(4,("sam_password_ok: Checking NT MD4 password in LM feild\n"));
+                               DEBUG(4,("sam_password_ok: Checking NT MD4 password in LM field\n"));
                                if (smb_pwd_check_ntlmv1(user_info->lm_resp, 
                                                         nt_pw, auth_context->challenge,
                                                         user_sess_key)) 
                                {
                                        return NT_STATUS_OK;
                                } else {
-                                       DEBUG(3,("sam_password_ok: NT MD4 password in LM feild failed for user %s\n",pdb_get_username(sampass)));
+                                       DEBUG(3,("sam_password_ok: NT MD4 password in LM field failed for user %s\n",pdb_get_username(sampass)));
                                        return NT_STATUS_WRONG_PASSWORD;
                                }
                        }
@@ -403,9 +406,9 @@ static NTSTATUS check_sam_security(const struct auth_context *auth_context,
                return nt_status;
        }
 
-       if (!make_server_info_sam(server_info, sampass)) {              
-               DEBUG(0,("failed to malloc memory for server_info\n"));
-               return NT_STATUS_NO_MEMORY;
+       if (!NT_STATUS_IS_OK(nt_status = make_server_info_sam(server_info, sampass))) {         
+               DEBUG(0,("check_sam_security: make_server_info_sam() failed with '%s'\n", nt_errstr(nt_status)));
+               return nt_status;
        }
 
        lm_hash = pdb_get_lanman_passwd((*server_info)->sam_account);
index 23faedc0bac91bde554256783aa6306b8fa46971..0ed905e79c849f89048374a7920a25eb85ccad8d 100644 (file)
@@ -285,7 +285,7 @@ static NTSTATUS check_smbserver_security(const struct auth_context *auth_context
         * need to detect this as some versions of NT4.x are broken. JRA.
         */
 
-       /* I sure as hell hope that there arn't servers out there that take 
+       /* I sure as hell hope that there aren't servers out there that take 
         * NTLMv2 and have this bug, as we don't test for that... 
         *  - abartlet@samba.org
         */
@@ -375,9 +375,7 @@ use this machine as the password server.\n"));
        if NT_STATUS_IS_OK(nt_status) {
                struct passwd *pass = Get_Pwnam(user_info->internal_username.str);
                if (pass) {
-                       if (!make_server_info_pw(server_info, pass)) { 
-                               nt_status = NT_STATUS_NO_MEMORY;
-                       }
+                       nt_status = make_server_info_pw(server_info, pass);
                } else {
                        nt_status = NT_STATUS_NO_SUCH_USER;
                }
index f914d918715dd7dfc3a7a1e14db91109ee546785..ce5fd32337b0891217130c1083c1f5b31ed8f1b1 100644 (file)
@@ -4,6 +4,7 @@
    Copyright (C) Andrew Tridgell 1992-1998
    Copyright (C) Andrew Bartlett 2001
    Copyright (C) Jeremy Allison 2000-2001
+   Copyright (C) Rafal Szczesniak 2002
 
    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 DBGC_CLASS DBGC_AUTH
 
 extern pstring global_myname;
+extern DOM_SID global_sid_World;
+extern DOM_SID global_sid_Network;
+extern DOM_SID global_sid_Builtin_Guests;
+extern DOM_SID global_sid_Authenticated_Users;
+
 
 /****************************************************************************
  Create a UNIX user on demand.
@@ -51,7 +57,7 @@ static int smb_create_user(const char *unix_user, const char *homedir)
  Add and Delete UNIX users on demand, based on NTSTATUS codes.
 ****************************************************************************/
 
-void smb_user_control(const auth_usersupplied_info *user_info, auth_serversupplied_info *server_info, NTSTATUS nt_status) 
+void smb_user_control(const auth_usersupplied_info *user_info, auth_serversupplied_info *server_info, NTSTATUS nt_status)
 {
        struct passwd *pwd=NULL;
 
@@ -76,15 +82,15 @@ void smb_user_control(const auth_usersupplied_info *user_info, auth_serversuppli
  Create an auth_usersupplied_data structure
 ****************************************************************************/
 
-static BOOL make_user_info(auth_usersupplied_info **user_info, 
-                          const char *smb_name, 
-                          const char *internal_username,
-                          const char *client_domain, 
-                          const char *domain,
-                          const char *wksta_name, 
-                          DATA_BLOB lm_pwd, DATA_BLOB nt_pwd,
-                          DATA_BLOB plaintext, 
-                          uint32 auth_flags, BOOL encrypted)
+static NTSTATUS make_user_info(auth_usersupplied_info **user_info, 
+                               const char *smb_name, 
+                               const char *internal_username,
+                               const char *client_domain, 
+                               const char *domain,
+                               const char *wksta_name, 
+                               DATA_BLOB lm_pwd, DATA_BLOB nt_pwd,
+                               DATA_BLOB plaintext, 
+                               uint32 auth_flags, BOOL encrypted)
 {
 
        DEBUG(5,("attempting to make a user_info for %s (%s)\n", internal_username, smb_name));
@@ -92,7 +98,7 @@ static BOOL make_user_info(auth_usersupplied_info **user_info,
        *user_info = malloc(sizeof(**user_info));
        if (!user_info) {
                DEBUG(0,("malloc failed for user_info (size %d)\n", sizeof(*user_info)));
-               return False;
+               return NT_STATUS_NO_MEMORY;
        }
 
        ZERO_STRUCTP(*user_info);
@@ -104,7 +110,7 @@ static BOOL make_user_info(auth_usersupplied_info **user_info,
                (*user_info)->smb_name.len = strlen(smb_name);
        } else {
                free_user_info(user_info);
-               return False;
+               return NT_STATUS_NO_MEMORY;
        }
        
        (*user_info)->internal_username.str = strdup(internal_username);
@@ -112,7 +118,7 @@ static BOOL make_user_info(auth_usersupplied_info **user_info,
                (*user_info)->internal_username.len = strlen(internal_username);
        } else {
                free_user_info(user_info);
-               return False;
+               return NT_STATUS_NO_MEMORY;
        }
 
        (*user_info)->domain.str = strdup(domain);
@@ -120,7 +126,7 @@ static BOOL make_user_info(auth_usersupplied_info **user_info,
                (*user_info)->domain.len = strlen(domain);
        } else {
                free_user_info(user_info);
-               return False;
+               return NT_STATUS_NO_MEMORY;
        }
 
        (*user_info)->client_domain.str = strdup(client_domain);
@@ -128,7 +134,7 @@ static BOOL make_user_info(auth_usersupplied_info **user_info,
                (*user_info)->client_domain.len = strlen(client_domain);
        } else {
                free_user_info(user_info);
-               return False;
+               return NT_STATUS_NO_MEMORY;
        }
 
        (*user_info)->wksta_name.str = strdup(wksta_name);
@@ -136,7 +142,7 @@ static BOOL make_user_info(auth_usersupplied_info **user_info,
                (*user_info)->wksta_name.len = strlen(wksta_name);
        } else {
                free_user_info(user_info);
-               return False;
+               return NT_STATUS_NO_MEMORY;
        }
 
        DEBUG(5,("making blobs for %s's user_info struct\n", internal_username));
@@ -150,26 +156,26 @@ static BOOL make_user_info(auth_usersupplied_info **user_info,
 
        DEBUG(10,("made an %sencrypted user_info for %s (%s)\n", encrypted ? "":"un" , internal_username, smb_name));
 
-       return True;
+       return NT_STATUS_OK;
 }
 
 /****************************************************************************
  Create an auth_usersupplied_data structure after appropriate mapping.
 ****************************************************************************/
 
-BOOL make_user_info_map(auth_usersupplied_info **user_info, 
-                       const char *smb_name, 
-                       const char *client_domain, 
-                       const char *wksta_name, 
-                       DATA_BLOB lm_pwd, DATA_BLOB nt_pwd,
-                       DATA_BLOB plaintext, 
-                       uint32 ntlmssp_flags, BOOL encrypted)
+NTSTATUS make_user_info_map(auth_usersupplied_info **user_info, 
+                           const char *smb_name, 
+                           const char *client_domain, 
+                           const char *wksta_name, 
+                           DATA_BLOB lm_pwd, DATA_BLOB nt_pwd,
+                           DATA_BLOB plaintext, 
+                           uint32 ntlmssp_flags, BOOL encrypted)
 {
        const char *domain;
        fstring internal_username;
        fstrcpy(internal_username, smb_name);
        map_username(internal_username); 
-
+       
        DEBUG(5, ("make_user_info_map: Mapping user [%s]\\[%s] from workstation [%s]\n",
              client_domain, smb_name, wksta_name));
        
@@ -198,7 +204,7 @@ BOOL make_user_info_map(auth_usersupplied_info **user_info,
                                 client_domain, lp_winbind_separator(), 
                                 smb_name) < 0) {
                                DEBUG(0, ("make_user_info_map: asprintf() failed!\n"));
-                               return False;
+                               return NT_STATUS_NO_MEMORY;
                        }
 
                        DEBUG(5, ("make_user_info_map: testing for user %s\n", user));
@@ -240,6 +246,7 @@ BOOL make_user_info_netlogon_network(auth_usersupplied_info **user_info,
                                     const uchar *nt_network_pwd, int nt_pwd_len)
 {
        BOOL ret;
+       NTSTATUS nt_status;
        DATA_BLOB lm_blob = data_blob(lm_network_pwd, lm_pwd_len);
        DATA_BLOB nt_blob = data_blob(nt_network_pwd, nt_pwd_len);
        DATA_BLOB plaintext_blob = data_blob(NULL, 0);
@@ -253,12 +260,14 @@ BOOL make_user_info_netlogon_network(auth_usersupplied_info **user_info,
                auth_flags |= AUTH_FLAG_NTLMv2_RESP; 
        }
 
-       ret = make_user_info_map(user_info, 
-                                smb_name, client_domain, 
-                                wksta_name, 
-                                lm_blob, nt_blob,
-                                plaintext_blob, 
-                                auth_flags, True);
+       nt_status = make_user_info_map(user_info,
+                                     smb_name, client_domain, 
+                                  wksta_name, 
+                                     lm_blob, nt_blob,
+                                     plaintext_blob, 
+                                     auth_flags, True);
+       
+       ret = NT_STATUS_IS_OK(nt_status) ? True : False;
                
        data_blob_free(&lm_blob);
        data_blob_free(&nt_blob);
@@ -324,6 +333,7 @@ BOOL make_user_info_netlogon_interactive(auth_usersupplied_info **user_info,
 
        {
                BOOL ret;
+               NTSTATUS nt_status;
                DATA_BLOB local_lm_blob = data_blob(local_lm_response, sizeof(local_lm_response));
                DATA_BLOB local_nt_blob = data_blob(local_nt_response, sizeof(local_nt_response));
                DATA_BLOB plaintext_blob = data_blob(NULL, 0);
@@ -333,14 +343,15 @@ BOOL make_user_info_netlogon_interactive(auth_usersupplied_info **user_info,
                if (nt_interactive_pwd)
                        auth_flags |= AUTH_FLAG_NTLM_RESP; 
 
-               ret = make_user_info_map(user_info, 
-                                        smb_name, client_domain, 
-                                        wksta_name, 
-                                        local_lm_blob,
-                                        local_nt_blob,
-                                        plaintext_blob, 
-                                        auth_flags, True);
+               nt_status = make_user_info_map(user_info, 
+                                              smb_name, client_domain, 
+                                              wksta_name, 
+                                              local_lm_blob,
+                                              local_nt_blob,
+                                              plaintext_blob, 
+                                              auth_flags, True);
                
+               ret = NT_STATUS_IS_OK(nt_status) ? True : False;
                data_blob_free(&local_lm_blob);
                data_blob_free(&local_nt_blob);
                return ret;
@@ -361,7 +372,7 @@ BOOL make_user_info_for_reply(auth_usersupplied_info **user_info,
 
        DATA_BLOB local_lm_blob;
        DATA_BLOB local_nt_blob;
-       BOOL ret = False;
+       NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
        uint32 auth_flags = AUTH_FLAG_NONE;
                        
        /*
@@ -392,25 +403,25 @@ BOOL make_user_info_for_reply(auth_usersupplied_info **user_info,
        }
        
        ret = make_user_info_map(user_info, smb_name,
-                                client_domain, 
-                                get_remote_machine_name(),
-                                local_lm_blob,
-                                local_nt_blob,
-                                plaintext_password, 
-                                auth_flags, False);
+                                client_domain, 
+                                get_remote_machine_name(),
+                                local_lm_blob,
+                                local_nt_blob,
+                                plaintext_password, 
+                                auth_flags, False);
        
        data_blob_free(&local_lm_blob);
-       return ret;
+       return NT_STATUS_IS_OK(ret) ? True : False;
 }
 
 /****************************************************************************
  Create an auth_usersupplied_data structure
 ****************************************************************************/
 
-BOOL make_user_info_for_reply_enc(auth_usersupplied_info **user_info, 
-                                 const char *smb_name,
-                                 const char *client_domain, 
-                                 DATA_BLOB lm_resp, DATA_BLOB nt_resp)
+NTSTATUS make_user_info_for_reply_enc(auth_usersupplied_info **user_info, 
+                                      const char *smb_name,
+                                      const char *client_domain, 
+                                      DATA_BLOB lm_resp, DATA_BLOB nt_resp)
 {
        uint32 auth_flags = AUTH_FLAG_NONE;
 
@@ -445,47 +456,338 @@ BOOL make_user_info_guest(auth_usersupplied_info **user_info)
        DATA_BLOB nt_blob = data_blob(NULL, 0);
        DATA_BLOB plaintext_blob = data_blob(NULL, 0);
        uint32 auth_flags = AUTH_FLAG_NONE;
+       NTSTATUS nt_status;
 
-       return make_user_info(user_info, 
+       nt_status = make_user_info(user_info, 
                              "","", 
                              "","", 
                              "", 
                              nt_blob, lm_blob,
                              plaintext_blob, 
                              auth_flags, True);
+                             
+       return NT_STATUS_IS_OK(nt_status) ? True : False;
+}
+
+/****************************************************************************
+ prints a NT_USER_TOKEN to debug output.
+****************************************************************************/
+
+void debug_nt_user_token(int dbg_class, int dbg_lev, NT_USER_TOKEN *token)
+{
+       fstring sid_str;
+       int     i;
+       
+       if (!token) {
+               DEBUGC(dbg_class, dbg_lev, ("NT user token: (NULL)\n"));
+               return;
+       }
+       
+       DEBUGC(dbg_class, dbg_lev, ("NT user token of user %s\n",
+                                   sid_to_string(sid_str, &token->user_sids[0]) ));
+       DEBUGADDC(dbg_class, dbg_lev, ("contains %i SIDs\n", token->num_sids));
+       for (i = 0; i < token->num_sids; i++)
+               DEBUGADDC(dbg_class, dbg_lev, ("SID[%3i]: %s\n", i, 
+                                              sid_to_string(sid_str, &token->user_sids[i])));
+}
+
+/****************************************************************************
+ prints a UNIX 'token' to debug output.
+****************************************************************************/
+
+void debug_unix_user_token(int dbg_class, int dbg_lev, uid_t uid, gid_t gid, int n_groups, gid_t *groups)
+{
+       int     i;
+       DEBUGC(dbg_class, dbg_lev, ("UNIX token of user %ld\n", (long int)uid));
+
+       DEBUGADDC(dbg_class, dbg_lev, ("Primary group is %ld and contains %i supplementary groups\n", (long int)gid, n_groups));
+       for (i = 0; i < n_groups; i++)
+               DEBUGADDC(dbg_class, dbg_lev, ("Group[%3i]: %ld\n", i, 
+                       (long int)groups[i]));
+}
+
+/****************************************************************************
+ Create the SID list for this user.
+****************************************************************************/
+
+static NTSTATUS create_nt_user_token(const DOM_SID *user_sid, const DOM_SID *group_sid, 
+                                    int n_groupSIDs, DOM_SID *groupSIDs, 
+                                    BOOL is_guest, NT_USER_TOKEN **token)
+{
+       NTSTATUS       nt_status = NT_STATUS_OK;
+       NT_USER_TOKEN *ptoken;
+       int i;
+       int sid_ndx;
+       
+       if ((ptoken = malloc( sizeof(NT_USER_TOKEN) ) ) == NULL) {
+               DEBUG(0, ("create_nt_token: Out of memory allocating token\n"));
+               nt_status = NT_STATUS_NO_MEMORY;
+               return nt_status;
+       }
+
+       ZERO_STRUCTP(ptoken);
+
+       ptoken->num_sids = n_groupSIDs + 5;
+
+       if ((ptoken->user_sids = (DOM_SID *)malloc( sizeof(DOM_SID) * ptoken->num_sids )) == NULL) {
+               DEBUG(0, ("create_nt_token: Out of memory allocating SIDs\n"));
+               nt_status = NT_STATUS_NO_MEMORY;
+               return nt_status;
+       }
+       
+       memset((char*)ptoken->user_sids,0,sizeof(DOM_SID) * ptoken->num_sids);
+       
+       /*
+        * Note - user SID *MUST* be first in token !
+        * se_access_check depends on this.
+        *
+        * Primary group SID is second in token. Convention.
+        */
+
+       sid_copy(&ptoken->user_sids[PRIMARY_USER_SID_INDEX], user_sid);
+       if (group_sid)
+               sid_copy(&ptoken->user_sids[PRIMARY_GROUP_SID_INDEX], group_sid);
+
+       /*
+        * Finally add the "standard" SIDs.
+        * The only difference between guest and "anonymous" (which we
+        * don't really support) is the addition of Authenticated_Users.
+        */
+
+       sid_copy(&ptoken->user_sids[2], &global_sid_World);
+       sid_copy(&ptoken->user_sids[3], &global_sid_Network);
+
+       if (is_guest)
+               sid_copy(&ptoken->user_sids[4], &global_sid_Builtin_Guests);
+       else
+               sid_copy(&ptoken->user_sids[4], &global_sid_Authenticated_Users);
+       
+       sid_ndx = 5; /* next available spot */
+
+       for (i = 0; i < n_groupSIDs; i++) {
+               int check_sid_idx;
+               for (check_sid_idx = 1; check_sid_idx < ptoken->num_sids; check_sid_idx++) {
+                       if (sid_equal(&ptoken->user_sids[check_sid_idx], 
+                                     &groupSIDs[i])) {
+                               break;
+                       }
+               }
+               
+               if (check_sid_idx >= ptoken->num_sids) /* Not found already */ {
+                       sid_copy(&ptoken->user_sids[sid_ndx++], &groupSIDs[i]);
+               } else {
+                       ptoken->num_sids--;
+               }
+       }
+       
+       debug_nt_user_token(DBGC_AUTH, 10, ptoken);
+       
+       *token = ptoken;
+
+       return nt_status;
+}
+
+/****************************************************************************
+ Create the SID list for this user.
+****************************************************************************/
+
+NT_USER_TOKEN *create_nt_token(uid_t uid, gid_t gid, int ngroups, gid_t *groups, BOOL is_guest)
+{
+       DOM_SID user_sid;
+       DOM_SID group_sid;
+       DOM_SID *group_sids;
+       NT_USER_TOKEN *token;
+       int i;
+
+       if (!uid_to_sid(&user_sid, uid)) {
+               return NULL;
+       }
+       if (!gid_to_sid(&group_sid, gid)) {
+               return NULL;
+       }
+
+       group_sids   = malloc(sizeof(DOM_SID) * ngroups);
+       if (!group_sids) {
+               DEBUG(0, ("create_nt_token: malloc() failed for DOM_SID list!\n"));
+               return NULL;
+       }
+
+       for (i = 0; i < ngroups; i++) {
+               if (!gid_to_sid(&(group_sids)[i], (groups)[i])) {
+                       DEBUG(1, ("create_nt_token: failed to convert gid %ld to a sid!\n", (long int)groups[i]));
+                       SAFE_FREE(group_sids);
+                       return NULL;
+               }
+       }
+
+       if (!NT_STATUS_IS_OK(create_nt_user_token(&user_sid, &group_sid, 
+                                                 ngroups, group_sids, is_guest, &token))) {
+               SAFE_FREE(group_sids);
+               return NULL;
+       }
+
+       SAFE_FREE(group_sids);
+
+       return token;
+}
+
+/******************************************************************************
+ * 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 
+ * both domain groups and local / builtin groups. If the user is in a trusted
+ * domain, or samba is a member server of a domain, then this function returns
+ * local and builtin groups the user is a member of. 
+ *
+ * currently this is a hack, as there is no sam implementation that is capable
+ * of groups.
+ ******************************************************************************/
+
+static NTSTATUS get_user_groups_from_local_sam(const DOM_SID *user_sid, 
+                                              int *n_groups, DOM_SID **groups, gid_t **unix_groups)
+{
+       uid_t             uid;
+       enum SID_NAME_USE snu;
+       fstring           str;
+       int               n_unix_groups;
+       int               i;
+       struct passwd    *usr;  
+       
+       *n_groups = 0;
+       *groups   = NULL;
+       
+       if (!sid_to_uid(user_sid,  &uid, &snu)) {
+               DEBUG(2, ("get_user_groups_from_local_sam: Failed to convert user SID %s to a uid!\n", 
+                         sid_to_string(str, user_sid)));
+               /* This might be a non-unix account */
+               return NT_STATUS_OK;
+       }
+
+       /*
+        * This is _essential_ to prevent occasional segfaults when
+        * winbind can't find uid -> username mapping
+        */
+       if (!(usr = getpwuid_alloc(uid))) {
+               DEBUG(0, ("Couldn't find passdb structure for UID = %d ! Aborting.\n", uid));
+               return NT_STATUS_NO_SUCH_USER;
+       };
+       
+       n_unix_groups = groups_max();
+       if ((*unix_groups = malloc( sizeof(gid_t) * groups_max() ) ) == NULL) {
+               DEBUG(0, ("get_user_groups_from_local_sam: Out of memory allocating unix group list\n"));
+               passwd_free(&usr);
+               return NT_STATUS_NO_MEMORY;
+       }
+       
+       if (sys_getgrouplist(usr->pw_name, usr->pw_gid, *unix_groups, &n_unix_groups) == -1) {
+               *unix_groups = Realloc(unix_groups, sizeof(gid_t) * n_unix_groups);
+               if (sys_getgrouplist(usr->pw_name, usr->pw_gid, *unix_groups, &n_unix_groups) == -1) {
+                       DEBUG(0, ("get_user_groups_from_local_sam: failed to get the unix group list\n"));
+                       SAFE_FREE(unix_groups);
+                       passwd_free(&usr);
+                       return NT_STATUS_NO_SUCH_USER; /* what should this return value be? */
+               }
+       }
+
+       debug_unix_user_token(DBGC_CLASS, 5, usr->pw_uid, usr->pw_gid, n_unix_groups, *unix_groups);
+
+       passwd_free(&usr);
+       
+       if (n_unix_groups > 0) {
+               *groups   = malloc(sizeof(DOM_SID) * n_unix_groups);
+               if (!*groups) {
+                       DEBUG(0, ("get_user_group_from_local_sam: malloc() failed for DOM_SID list!\n"));
+                       SAFE_FREE(unix_groups);
+                       return NT_STATUS_NO_MEMORY;
+               }
+       }
+
+       *n_groups = n_unix_groups;
+
+       for (i = 0; i < *n_groups; i++) {
+               if (!gid_to_sid(&(*groups)[i], (*unix_groups)[i])) {
+                       DEBUG(1, ("get_user_groups_from_local_sam: failed to convert gid %ld to a sid!\n", (long int)unix_groups[i+1]));
+                       SAFE_FREE(groups);
+                       SAFE_FREE(unix_groups);
+                       return NT_STATUS_NO_SUCH_USER;
+               }
+       }
+                    
+       return NT_STATUS_OK;
 }
 
 /***************************************************************************
  Make a user_info struct
 ***************************************************************************/
 
-static BOOL make_server_info(auth_serversupplied_info **server_info) 
+static NTSTATUS make_server_info(auth_serversupplied_info **server_info, SAM_ACCOUNT *sampass)
 {
        *server_info = malloc(sizeof(**server_info));
        if (!*server_info) {
                DEBUG(0,("make_server_info: malloc failed!\n"));
-               return False;
+               return NT_STATUS_NO_MEMORY;
        }
        ZERO_STRUCTP(*server_info);
-       return True;
+
+       (*server_info)->sam_fill_level = SAM_FILL_ALL;
+       (*server_info)->sam_account    = sampass;
+
+       return NT_STATUS_OK;
 }
 
 /***************************************************************************
  Make (and fill) a user_info struct from a SAM_ACCOUNT
 ***************************************************************************/
 
-BOOL make_server_info_sam(auth_serversupplied_info **server_info, SAM_ACCOUNT *sampass) 
+NTSTATUS make_server_info_sam(auth_serversupplied_info **server_info, 
+                             SAM_ACCOUNT *sampass)
 {
-       if (!make_server_info(server_info)) {
-               return False;
+       NTSTATUS nt_status = NT_STATUS_OK;
+       const DOM_SID *user_sid = pdb_get_user_sid(sampass);
+       const DOM_SID *group_sid = pdb_get_group_sid(sampass);
+       int       n_groupSIDs = 0;
+       DOM_SID  *groupSIDs   = NULL;
+       gid_t    *unix_groups = NULL;
+       NT_USER_TOKEN *token;
+       BOOL is_guest;
+       uint32 rid;
+
+       if (!NT_STATUS_IS_OK(nt_status = make_server_info(server_info, sampass))) {
+               return nt_status;
        }
+       
+       if (!NT_STATUS_IS_OK(nt_status 
+                            = get_user_groups_from_local_sam(pdb_get_user_sid(sampass), 
+               &n_groupSIDs, &groupSIDs, &unix_groups)))
+       {
+               DEBUG(4,("get_user_groups_from_local_sam failed\n"));
+               free_server_info(server_info);
+               return nt_status;
+       }
+       
+       is_guest = (sid_peek_rid(user_sid, &rid) && rid == DOMAIN_USER_RID_GUEST);
 
-       (*server_info)->sam_fill_level = SAM_FILL_ALL;
-       (*server_info)->sam_account = sampass;
+       if (!NT_STATUS_IS_OK(nt_status = create_nt_user_token(user_sid, group_sid,
+                                                             n_groupSIDs, groupSIDs, is_guest, 
+                                                             &token)))
+       {
+               DEBUG(4,("create_nt_user_token failed\n"));
+               SAFE_FREE(groupSIDs);
+               SAFE_FREE(unix_groups);
+               free_server_info(server_info);
+               return nt_status;
+       }
+       
+       SAFE_FREE(groupSIDs);
 
+       (*server_info)->n_groups = n_groupSIDs;
+       (*server_info)->groups = unix_groups;
+
+       (*server_info)->ptok = token;
+       
        DEBUG(5,("make_server_info_sam: made server info for user %s\n",
                 pdb_get_username((*server_info)->sam_account)));
-       return True;
+
+       return nt_status;
 }
 
 /***************************************************************************
@@ -493,75 +795,42 @@ BOOL make_server_info_sam(auth_serversupplied_info **server_info, SAM_ACCOUNT *s
  to a SAM_ACCOUNT
 ***************************************************************************/
 
-BOOL make_server_info_pw(auth_serversupplied_info **server_info, const struct passwd *pwd)
+NTSTATUS make_server_info_pw(auth_serversupplied_info **server_info, const struct passwd *pwd)
 {
+       NTSTATUS nt_status;
        SAM_ACCOUNT *sampass = NULL;
-       if (!NT_STATUS_IS_OK(pdb_init_sam_pw(&sampass, pwd))) {         
-               return False;
+       if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam_pw(&sampass, pwd))) {             
+               return nt_status;
        }
        return make_server_info_sam(server_info, sampass);
 }
 
 /***************************************************************************
- Free a user_info struct
+ Make (and fill) a user_info struct for a guest login.
 ***************************************************************************/
 
-void free_user_info(auth_usersupplied_info **user_info)
+NTSTATUS make_server_info_guest(auth_serversupplied_info **server_info)
 {
-       DEBUG(5,("attempting to free (and zero) a user_info structure\n"));
-       if (*user_info != NULL) {
-               if ((*user_info)->smb_name.str) {
-                       DEBUG(10,("structure was created for %s\n", (*user_info)->smb_name.str));
-               }
-               SAFE_FREE((*user_info)->smb_name.str);
-               SAFE_FREE((*user_info)->internal_username.str);
-               SAFE_FREE((*user_info)->client_domain.str);
-               SAFE_FREE((*user_info)->domain.str);
-               SAFE_FREE((*user_info)->wksta_name.str);
-               data_blob_free(&(*user_info)->lm_resp);
-               data_blob_free(&(*user_info)->nt_resp);
-               SAFE_FREE((*user_info)->interactive_password);
-               data_blob_clear_free(&(*user_info)->plaintext_password);
-               ZERO_STRUCT(**user_info);
+       NTSTATUS nt_status;
+       SAM_ACCOUNT *sampass = NULL;
+       DOM_SID guest_sid;
+
+       if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam(&sampass))) {
+               return nt_status;
        }
-       SAFE_FREE(*user_info);
-}
 
-/***************************************************************************
- Clear out a server_info struct that has been allocated
-***************************************************************************/
+       sid_copy(&guest_sid, get_global_sam_sid());
+       sid_append_rid(&guest_sid, DOMAIN_USER_RID_GUEST);
 
-void free_server_info(auth_serversupplied_info **server_info)
-{
-       if (*server_info != NULL) {
-               pdb_free_sam(&(*server_info)->sam_account);
-               
-               /* call pam_end here, unless we know we are keeping it */
-               delete_nt_token( &(*server_info)->ptok );
-               ZERO_STRUCT(**server_info);
+       if (!pdb_getsampwsid(sampass, &guest_sid)) {
+               return NT_STATUS_NO_SUCH_USER;
        }
-       SAFE_FREE(*server_info);
-}
 
-/***************************************************************************
- Make a server_info struct for a guest user 
-***************************************************************************/
+       nt_status = make_server_info_sam(server_info, sampass);
 
-BOOL make_server_info_guest(auth_serversupplied_info **server_info) 
-{
-       struct passwd *pass = getpwnam_alloc(lp_guestaccount());
-       
-       if (pass) {
-               if (!make_server_info_pw(server_info, pass)) {
-                       passwd_free(&pass);
-                       return False;
-               }
-               (*server_info)->guest = True;
-               passwd_free(&pass);
-               return True;
-       }
-       DEBUG(0,("make_server_info_guest: getpwnam_alloc() failed on guest account!\n")); 
-       return False;
+       (*server_info)->guest = True;
+
+       return nt_status;
 }
 
 /***************************************************************************
@@ -589,6 +858,15 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx,
        uid_t uid;
        gid_t gid;
 
+       int n_lgroupSIDs;
+       DOM_SID *lgroupSIDs   = NULL;
+
+       gid_t *unix_groups = NULL;
+       NT_USER_TOKEN *token;
+
+       DOM_SID *all_group_SIDs;
+       int i;
+
        /* 
           Here is where we should check the list of
           trusted domains, and verify that the SID 
@@ -698,49 +976,128 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx,
                return NT_STATUS_NO_MEMORY;
        }
 
-       if (!make_server_info_sam(server_info, sam_account)) { 
-               DEBUG(0, ("make_server_info_info3: make_server_info_sam failed!\n"));
+       if (!NT_STATUS_IS_OK(nt_status = make_server_info(server_info, sam_account))) {
+               DEBUG(4, ("make_server_info failed!\n"));
                pdb_free_sam(&sam_account);
-               return NT_STATUS_NO_MEMORY;
+               return nt_status;
        }
 
        /* Store the user group information in the server_info 
           returned to the caller. */
        
-       if (info3->num_groups2 != 0) {
-               int i;
-               NT_USER_TOKEN *ptok;
-               auth_serversupplied_info *pserver_info = *server_info;
-               
-               if ((pserver_info->ptok = malloc( sizeof(NT_USER_TOKEN) ) ) == NULL) {
-                       DEBUG(0, ("domain_client_validate: out of memory allocating rid group membership\n"));
-                       nt_status = NT_STATUS_NO_MEMORY;
-                       free_server_info(server_info);
-                       return nt_status;
-               }
-               
-               ptok = pserver_info->ptok;
-               ptok->num_sids = (size_t)info3->num_groups2;
-               
-               if ((ptok->user_sids = (DOM_SID *)malloc( sizeof(DOM_SID) * ptok->num_sids )) == NULL) {
-                       DEBUG(0, ("domain_client_validate: Out of memory allocating group SIDS\n"));
-                       nt_status = NT_STATUS_NO_MEMORY;
-                       free_server_info(server_info);
+       if (!NT_STATUS_IS_OK(nt_status 
+                            = get_user_groups_from_local_sam(&user_sid, 
+                                                             &n_lgroupSIDs, 
+                                                             &lgroupSIDs, 
+                                                             &unix_groups)))
+       {
+               DEBUG(4,("get_user_groups_from_local_sam failed\n"));
+               return nt_status;
+       }
+
+       (*server_info)->groups = unix_groups;
+       (*server_info)->n_groups = n_lgroupSIDs;
+       
+       /* Create a 'combined' list of all SIDs we might want in the SD */
+       all_group_SIDs   = malloc(sizeof(DOM_SID) * 
+                                 (n_lgroupSIDs + info3->num_groups2 +
+                                  info3->num_other_sids));
+       if (!all_group_SIDs) {
+               DEBUG(0, ("create_nt_token_info3: malloc() failed for DOM_SID list!\n"));
+               SAFE_FREE(lgroupSIDs);
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       /* Copy the 'local' sids */
+       memcpy(all_group_SIDs, lgroupSIDs, sizeof(DOM_SID) * n_lgroupSIDs);
+       SAFE_FREE(lgroupSIDs);
+
+       /* and create (by appending rids) the 'domain' sids */
+       for (i = 0; i < info3->num_groups2; i++) {
+               sid_copy(&all_group_SIDs[i+n_lgroupSIDs], &(info3->dom_sid.sid));
+               if (!sid_append_rid(&all_group_SIDs[i+n_lgroupSIDs], info3->gids[i].g_rid)) {
+                       nt_status = NT_STATUS_INVALID_PARAMETER;
+                       DEBUG(3,("create_nt_token_info3: could not append additional group rid 0x%x\n",
+                               info3->gids[i].g_rid));                 
+                       SAFE_FREE(lgroupSIDs);
                        return nt_status;
                }
-               
-               for (i = 0; i < ptok->num_sids; i++) {
-                       sid_copy(&ptok->user_sids[i], &(info3->dom_sid.sid));
-                       if (!sid_append_rid(&ptok->user_sids[i], info3->gids[i].g_rid)) {
-                               nt_status = NT_STATUS_INVALID_PARAMETER;
-                               free_server_info(server_info);
-                               return nt_status;
-                       }
-               }
        }
+
+       /* Copy 'other' sids.  We need to do sid filtering here to
+          prevent possible elevation of privileges.  See:
+
+           http://www.microsoft.com/windows2000/techinfo/administration/security/sidfilter.asp
+         */
+
+       for (i = 0; i < info3->num_other_sids; i++) 
+               sid_copy(&all_group_SIDs[
+                                n_lgroupSIDs + info3->num_groups2 + i],
+                        &info3->other_sids[i].sid);
+       
+       /* Where are the 'global' sids... */
+
+       /* can the user be guest? if yes, where is it stored? */
+       if (!NT_STATUS_IS_OK(
+                   nt_status = create_nt_user_token(
+                           &user_sid, &group_sid,
+                           n_lgroupSIDs + info3->num_groups2 + info3->num_other_sids, 
+                           all_group_SIDs, False, &token))) {
+               DEBUG(4,("create_nt_user_token failed\n"));
+               SAFE_FREE(all_group_SIDs);
+               return nt_status;
+       }
+
+       (*server_info)->ptok = token; 
+
+       SAFE_FREE(all_group_SIDs);
+       
        return NT_STATUS_OK;
 }
 
+/***************************************************************************
+ Free a user_info struct
+***************************************************************************/
+
+void free_user_info(auth_usersupplied_info **user_info)
+{
+       DEBUG(5,("attempting to free (and zero) a user_info structure\n"));
+       if (*user_info != NULL) {
+               if ((*user_info)->smb_name.str) {
+                       DEBUG(10,("structure was created for %s\n", (*user_info)->smb_name.str));
+               }
+               SAFE_FREE((*user_info)->smb_name.str);
+               SAFE_FREE((*user_info)->internal_username.str);
+               SAFE_FREE((*user_info)->client_domain.str);
+               SAFE_FREE((*user_info)->domain.str);
+               SAFE_FREE((*user_info)->wksta_name.str);
+               data_blob_free(&(*user_info)->lm_resp);
+               data_blob_free(&(*user_info)->nt_resp);
+               SAFE_FREE((*user_info)->interactive_password);
+               data_blob_clear_free(&(*user_info)->plaintext_password);
+               ZERO_STRUCT(**user_info);
+       }
+       SAFE_FREE(*user_info);
+}
+
+/***************************************************************************
+ Clear out a server_info struct that has been allocated
+***************************************************************************/
+
+void free_server_info(auth_serversupplied_info **server_info)
+{
+       DEBUG(5,("attempting to free (and zero) a server_info structure\n"));
+       if (*server_info != NULL) {
+               pdb_free_sam(&(*server_info)->sam_account);
+
+               /* call pam_end here, unless we know we are keeping it */
+               delete_nt_token( &(*server_info)->ptok );
+               SAFE_FREE((*server_info)->groups);
+               ZERO_STRUCT(**server_info);
+       }
+       SAFE_FREE(*server_info);
+}
+
 /***************************************************************************
  Make an auth_methods struct
 ***************************************************************************/
index 5bdccd39f3e88543689091e12ba3a5c2bea42881..10788721fdebec9893161765909ffbde349748d5 100644 (file)
@@ -4,7 +4,7 @@
    Winbind authentication mechnism
 
    Copyright (C) Tim Potter 2000
-   Copyright (C) Andrew Bartlett 2001
+   Copyright (C) Andrew Bartlett 2001 - 2002
    
    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
index a421f36d8092e9c309f422f095984a3e19f04ac0..eb6b57276089a6407f374bc08b734d15b908c6ba 100644 (file)
@@ -2,7 +2,7 @@
    Unix SMB/CIFS implementation.
    SMB client
    Copyright (C) Andrew Tridgell 1994-1998
-   Copyright (C) Simo Sorce 2001
+   Copyright (C) Simo Sorce 2001-2002
    
    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
@@ -307,7 +307,7 @@ static BOOL do_this_one(file_info *finfo)
 
        if (*fileselection && 
            !mask_match(finfo->name,fileselection,False)) {
-               DEBUG(3,("match_match %s failed\n", finfo->name));
+               DEBUG(3,("mask_match %s failed\n", finfo->name));
                return False;
        }
 
@@ -649,15 +649,16 @@ static int cmd_du(void)
 /****************************************************************************
   get a file from rname to lname
   ****************************************************************************/
-static int do_get(char *rname,char *lname)
+static int do_get(char *rname, char *lname, BOOL reget)
 {  
-       int handle=0,fnum;
+       int handle = 0, fnum;
        BOOL newhandle = False;
        char *data;
        struct timeval tp_start;
        int read_size = io_bufsize;
        uint16 attr;
        size_t size;
+       off_t start = 0;
        off_t nread = 0;
        int rc = 0;
 
@@ -677,7 +678,18 @@ static int do_get(char *rname,char *lname)
        if(!strcmp(lname,"-")) {
                handle = fileno(stdout);
        } else {
-               handle = sys_open(lname,O_WRONLY|O_CREAT|O_TRUNC,0644);
+               if (reget) {
+                       handle = sys_open(lname, O_WRONLY|O_CREAT, 0644);
+                       if (handle >= 0) {
+                               start = sys_lseek(handle, 0, SEEK_END);
+                               if (start == -1) {
+                                       d_printf("Error seeking local file\n");
+                                       return 1;
+                               }
+                       }
+               } else {
+                       handle = sys_open(lname, O_WRONLY|O_CREAT|O_TRUNC, 0644);
+               }
                newhandle = True;
        }
        if (handle < 0) {
@@ -695,7 +707,7 @@ static int do_get(char *rname,char *lname)
        }
 
        DEBUG(2,("getting file %s of size %.0f as %s ", 
-                lname, (double)size, lname));
+                rname, (double)size, lname));
 
        if(!(data = (char *)malloc(read_size))) { 
                d_printf("malloc fail for size %d\n", read_size);
@@ -704,7 +716,7 @@ static int do_get(char *rname,char *lname)
        }
 
        while (1) {
-               int n = cli_read(cli, fnum, data, nread, read_size);
+               int n = cli_read(cli, fnum, data, nread + start, read_size);
 
                if (n <= 0) break;
  
@@ -717,7 +729,7 @@ static int do_get(char *rname,char *lname)
                nread += n;
        }
 
-       if (nread < size) {
+       if (nread + start < size) {
                DEBUG (0, ("Short read when getting file %s. Only got %ld bytes.\n",
                            rname, (long)nread));
 
@@ -782,7 +794,7 @@ static int cmd_get(void)
        
        next_token_nr(NULL,lname,NULL,sizeof(lname));
        
-       return do_get(rname, lname);
+       return do_get(rname, lname, False);
 }
 
 
@@ -816,7 +828,7 @@ static void do_mget(file_info *finfo)
        if (!(finfo->mode & aDIR)) {
                pstrcpy(rname,cur_dir);
                pstrcat(rname,finfo->name);
-               do_get(rname,finfo->name);
+               do_get(rname, finfo->name, False);
                return;
        }
 
@@ -880,7 +892,7 @@ static int cmd_more(void)
        }
        dos_clean_name(rname);
 
-       rc = do_get(rname,lname);
+       rc = do_get(rname, lname, False);
 
        pager=getenv("PAGER");
 
@@ -1046,19 +1058,31 @@ static int cmd_altname(void)
 /****************************************************************************
   put a single file
   ****************************************************************************/
-static int do_put(char *rname,char *lname)
+static int do_put(char *rname, char *lname, BOOL reput)
 {
        int fnum;
        XFILE *f;
-       int nread=0;
-       char *buf=NULL;
-       int maxwrite=io_bufsize;
+       int start = 0;
+       int nread = 0;
+       char *buf = NULL;
+       int maxwrite = io_bufsize;
        int rc = 0;
        
        struct timeval tp_start;
        GetTimeOfDay(&tp_start);
 
-       fnum = cli_open(cli, rname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE);
+       if (reput) {
+               fnum = cli_open(cli, rname, O_RDWR|O_CREAT, DENY_NONE);
+               if (fnum >= 0) {
+                       if (!cli_qfileinfo(cli, fnum, NULL, &start, NULL, NULL, NULL, NULL, NULL) &&
+                           !cli_getattrE(cli, fnum, NULL, &start, NULL, NULL, NULL)) {
+                               d_printf("getattrib: %s\n",cli_errstr(cli));
+                               return 1;
+                       }
+               }
+       } else {
+               fnum = cli_open(cli, rname, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE);
+       }
   
        if (fnum == -1) {
                d_printf("%s opening remote file %s\n",cli_errstr(cli),rname);
@@ -1075,6 +1099,12 @@ static int do_put(char *rname,char *lname)
                /* size of file is not known */
        } else {
                f = x_fopen(lname,O_RDONLY, 0);
+               if (f && reput) {
+                       if (x_tseek(f, start, SEEK_SET) == -1) {
+                               d_printf("Error seeking local file\n");
+                               return 1;
+                       }
+               }
        }
 
        if (!f) {
@@ -1104,7 +1134,7 @@ static int do_put(char *rname,char *lname)
                        break;
                }
 
-               ret = cli_write(cli, fnum, 0, buf, nread, n);
+               ret = cli_write(cli, fnum, 0, buf, nread + start, n);
 
                if (n != ret) {
                        d_printf("Error writing file: %s\n", cli_errstr(cli));
@@ -1192,7 +1222,7 @@ static int cmd_put(void)
                }
        }
 
-       return do_put(rname,lname);
+       return do_put(rname, lname, False);
 }
 
 /*************************************
@@ -1384,7 +1414,7 @@ static int cmd_mput(void)
 
                        dos_format(rname);
 
-                       do_put(rname, lname);
+                       do_put(rname, lname, False);
                }
                free_file_list(file_list);
                SAFE_FREE(quest);
@@ -1456,7 +1486,7 @@ static int cmd_print(void)
                slprintf(rname, sizeof(rname)-1, "stdin-%d", (int)sys_getpid());
        }
 
-       return do_put(rname, lname);
+       return do_put(rname, lname, False);
 }
 
 
@@ -1866,8 +1896,8 @@ static int cmd_printmode(void)
 }
 
 /****************************************************************************
-do the lcd command
-****************************************************************************/
+ do the lcd command
+ ****************************************************************************/
 static int cmd_lcd(void)
 {
        fstring buf;
@@ -1881,8 +1911,70 @@ static int cmd_lcd(void)
 }
 
 /****************************************************************************
-list a share name
-****************************************************************************/
+ get a file restarting at end of local file
+ ****************************************************************************/
+static int cmd_reget(void)
+{
+       pstring local_name;
+       pstring remote_name;
+       char *p;
+
+       pstrcpy(remote_name, cur_dir);
+       pstrcat(remote_name, "\\");
+       
+       p = remote_name + strlen(remote_name);
+       
+       if (!next_token_nr(NULL, p, NULL, sizeof(remote_name) - strlen(remote_name))) {
+               d_printf("reget <filename>\n");
+               return 1;
+       }
+       pstrcpy(local_name, p);
+       dos_clean_name(remote_name);
+       
+       next_token_nr(NULL, local_name, NULL, sizeof(local_name));
+       
+       return do_get(remote_name, local_name, True);
+}
+
+/****************************************************************************
+ put a file restarting at end of local file
+ ****************************************************************************/
+static int cmd_reput(void)
+{
+       pstring local_name;
+       pstring remote_name;
+       fstring buf;
+       char *p = buf;
+       SMB_STRUCT_STAT st;
+       
+       pstrcpy(remote_name, cur_dir);
+       pstrcat(remote_name, "\\");
+  
+       if (!next_token_nr(NULL, p, NULL, sizeof(buf))) {
+               d_printf("reput <filename>\n");
+               return 1;
+       }
+       pstrcpy(local_name, p);
+  
+       if (!file_exist(local_name, &st)) {
+               d_printf("%s does not exist\n", local_name);
+               return 1;
+       }
+
+       if (next_token_nr(NULL, p, NULL, sizeof(buf)))
+               pstrcat(remote_name, p);
+       else
+               pstrcat(remote_name, local_name);
+       
+       dos_clean_name(remote_name);
+
+       return do_put(remote_name, local_name, True);
+}
+
+
+/****************************************************************************
+ list a share name
+ ****************************************************************************/
 static void browse_fn(const char *name, uint32 m, 
                       const char *comment, void *state)
 {
@@ -2009,7 +2101,9 @@ static struct
   {"quit",cmd_quit,"logoff the server",{COMPL_NONE,COMPL_NONE}},
   {"rd",cmd_rmdir,"<directory> remove a directory",{COMPL_NONE,COMPL_NONE}},
   {"recurse",cmd_recurse,"toggle directory recursion for mget and mput",{COMPL_NONE,COMPL_NONE}},  
+  {"reget",cmd_reget,"<remote name> [local name] get a file restarting at end of local file",{COMPL_REMOTE,COMPL_LOCAL}},
   {"rename",cmd_rename,"<src> <dest> rename some files",{COMPL_REMOTE,COMPL_REMOTE}},
+  {"reput",cmd_reput,"<local name> [remote name] put a file restarting at end of remote file",{COMPL_LOCAL,COMPL_REMOTE}},
   {"rm",cmd_del,"<mask> delete all matching files",{COMPL_REMOTE,COMPL_NONE}},
   {"rmdir",cmd_rmdir,"<directory> remove a directory",{COMPL_NONE,COMPL_NONE}},
   {"setmode",cmd_setmode,"filename <setmode string> change modes of file",{COMPL_REMOTE,COMPL_NONE}},
@@ -2524,16 +2618,21 @@ static int do_message_op(void)
 {
        struct in_addr ip;
        struct nmb_name called, calling;
-
-        zero_ip(&ip);
+       fstring server_name;
+       char name_type_hex[10];
 
        make_nmb_name(&calling, global_myname, 0x0);
        make_nmb_name(&called , desthost, name_type);
 
+       safe_strcpy(server_name, desthost, sizeof(server_name));
+       snprintf(name_type_hex, sizeof(name_type_hex), "#%X", name_type);
+       safe_strcat(server_name, name_type_hex, sizeof(server_name));
+
         zero_ip(&ip);
        if (have_ip) ip = dest_ip;
 
-       if (!(cli=cli_initialise(NULL)) || (cli_set_port(cli, port) != port) || !cli_connect(cli, desthost, &ip)) {
+       if (!(cli=cli_initialise(NULL)) || (cli_set_port(cli, port) != port) ||
+           !cli_connect(cli, server_name, &ip)) {
                d_printf("Connection to %s failed\n", desthost);
                return 1;
        }
@@ -2659,7 +2758,6 @@ static void remember_query_host(const char *arg,
                        got_pass = True;
                        memset(strchr_m(getenv("USER"),'%')+1,'X',strlen(password));
                }
-               strupper(username);
        }
 
        /* modification to support PASSWD environmental var
@@ -2676,7 +2774,6 @@ static void remember_query_host(const char *arg,
 
        if (*username == 0 && getenv("LOGNAME")) {
                pstrcpy(username,getenv("LOGNAME"));
-               strupper(username);
        }
 
        if (*username == 0) {
index ba2b1e9435d722d0fd8ae3e361f6985b2e0adba5..ce406179cfdd9d71f2e56f0a49f4e9616a52d17c 100644 (file)
@@ -148,8 +148,8 @@ do_mount(char *share_name, unsigned int flags, struct smb_mount_data *data)
 
        uname(&uts);
        release = uts.release;
-       major = strsep(&release, ".");
-       minor = strsep(&release, ".");
+       major = strtok(release, ".");
+       minor = strtok(NULL, ".");
        if (major && minor && atoi(major) == 2 && atoi(minor) < 4) {
                /* < 2.4, assume struct */
                data1 = (char *) data;
index 06694c8e64a87c6c042a806bde5c704b2e26af9d..538f44621c85a3fbbf283113136808825a33dd2e 100755 (executable)
@@ -46,8 +46,12 @@ ac_help="$ac_help
   --with-afs              Include AFS clear-text auth support (default=no) "
 ac_help="$ac_help
   --with-dce-dfs          Include DCE/DFS clear-text auth support (default=no)"
+ac_help="$ac_help
+   --with-ads  Active Directory support (default yes)"
 ac_help="$ac_help
   --with-krb5=base-dir    Locate Kerberos 5 support (default=/usr)"
+ac_help="$ac_help
+   --with-ldap  LDAP support (default yes)"
 ac_help="$ac_help
   --with-automount        Include AUTOMOUNT support (default=no)"
 ac_help="$ac_help
@@ -56,6 +60,8 @@ ac_help="$ac_help
   --with-pam              Include PAM support (default=no)"
 ac_help="$ac_help
   --with-pam_smbpass      Build a PAM module to allow other applications to use our smbpasswd file (default=no)"
+ac_help="$ac_help
+  --with-sam              Build new (experimental) SAM database (default=no)"
 ac_help="$ac_help
   --with-tdbsam           Include experimental TDB SAM support (default=no)"
 ac_help="$ac_help
@@ -78,10 +84,14 @@ ac_help="$ac_help
   --with-spinlocks        Use spin locks instead of fcntl locks (default=no) "
 ac_help="$ac_help
   --with-acl-support      Include ACL support (default=no)"
+ac_help="$ac_help
+  --with-sendfile-support      Include sendfile support (default=no)"
 ac_help="$ac_help
   --with-winbind          Build winbind (default, if supported by OS)"
 ac_help="$ac_help
   --with-included-popt    use bundled popt library, not from system"
+ac_help="$ac_help
+  --with-python=PYTHONNAME  build Python libraries"
 
 # Initialize some variables set by options.
 # The variables have the same names as the options, with
@@ -758,6 +768,7 @@ fi
 
 
 
+
 
 
 # compile with optimization and without debugging by default
@@ -813,7 +824,7 @@ fi
 # Extract the first word of "gcc", so it can be a program name with args.
 set dummy gcc; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:817: checking for $ac_word" >&5
+echo "configure:828: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -843,7 +854,7 @@ if test -z "$CC"; then
   # Extract the first word of "cc", so it can be a program name with args.
 set dummy cc; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:847: checking for $ac_word" >&5
+echo "configure:858: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -894,7 +905,7 @@ fi
       # Extract the first word of "cl", so it can be a program name with args.
 set dummy cl; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:898: checking for $ac_word" >&5
+echo "configure:909: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -926,7 +937,7 @@ fi
 fi
 
 echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
-echo "configure:930: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
+echo "configure:941: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
 
 ac_ext=c
 # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
@@ -937,12 +948,12 @@ cross_compiling=$ac_cv_prog_cc_cross
 
 cat > conftest.$ac_ext << EOF
 
-#line 941 "configure"
+#line 952 "configure"
 #include "confdefs.h"
 
 main(){return(0);}
 EOF
-if { (eval echo configure:946: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:957: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   ac_cv_prog_cc_works=yes
   # If we can't run a trivial program, we are probably using a cross compiler.
   if (./conftest; exit) 2>/dev/null; then
@@ -968,12 +979,12 @@ if test $ac_cv_prog_cc_works = no; then
   { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
 fi
 echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
-echo "configure:972: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "configure:983: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
 echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
 cross_compiling=$ac_cv_prog_cc_cross
 
 echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
-echo "configure:977: checking whether we are using GNU C" >&5
+echo "configure:988: checking whether we are using GNU C" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -982,7 +993,7 @@ else
   yes;
 #endif
 EOF
-if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:986: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:997: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
   ac_cv_prog_gcc=yes
 else
   ac_cv_prog_gcc=no
@@ -1001,7 +1012,7 @@ ac_test_CFLAGS="${CFLAGS+set}"
 ac_save_CFLAGS="$CFLAGS"
 CFLAGS=
 echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
-echo "configure:1005: checking whether ${CC-cc} accepts -g" >&5
+echo "configure:1016: checking whether ${CC-cc} accepts -g" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -1063,7 +1074,7 @@ ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
 # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
 # ./install, which can be erroneously created by make from ./install.sh.
 echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
-echo "configure:1067: checking for a BSD compatible install" >&5
+echo "configure:1078: checking for a BSD compatible install" >&5
 if test -z "$INSTALL"; then
 if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -1120,7 +1131,7 @@ do
 # Extract the first word of "$ac_prog", so it can be a program name with args.
 set dummy $ac_prog; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:1124: checking for $ac_word" >&5
+echo "configure:1135: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_AWK'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -1152,7 +1163,7 @@ done
 
 LD=ld
 echo $ac_n "checking if the linker ($LD) is GNU ld""... $ac_c" 1>&6
-echo "configure:1156: checking if the linker ($LD) is GNU ld" >&5
+echo "configure:1167: checking if the linker ($LD) is GNU ld" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_gnu_ld'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -1168,7 +1179,7 @@ echo "$ac_t""$ac_cv_prog_gnu_ld" 1>&6
 
 
 echo $ac_n "checking for POSIXized ISC""... $ac_c" 1>&6
-echo "configure:1172: checking for POSIXized ISC" >&5
+echo "configure:1183: checking for POSIXized ISC" >&5
 if test -d /etc/conf/kconfig.d &&
   grep _POSIX_VERSION /usr/include/sys/unistd.h >/dev/null 2>&1
 then
@@ -1191,10 +1202,10 @@ fi
 
 if test "x$CC" != xcc; then
   echo $ac_n "checking whether $CC and cc understand -c and -o together""... $ac_c" 1>&6
-echo "configure:1195: checking whether $CC and cc understand -c and -o together" >&5
+echo "configure:1206: checking whether $CC and cc understand -c and -o together" >&5
 else
   echo $ac_n "checking whether cc understands -c and -o together""... $ac_c" 1>&6
-echo "configure:1198: checking whether cc understands -c and -o together" >&5
+echo "configure:1209: checking whether cc understands -c and -o together" >&5
 fi
 set dummy $CC; ac_cc="`echo $2 |
                       sed -e 's/[^a-zA-Z0-9_]/_/g' -e 's/^[0-9]/_/'`"
@@ -1206,16 +1217,16 @@ else
 # We do the test twice because some compilers refuse to overwrite an
 # existing .o file with -o, though they will create one.
 ac_try='${CC-cc} -c conftest.c -o conftest.o 1>&5'
-if { (eval echo configure:1210: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } &&
-   test -f conftest.o && { (eval echo configure:1211: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; };
+if { (eval echo configure:1221: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } &&
+   test -f conftest.o && { (eval echo configure:1222: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; };
 then
   eval ac_cv_prog_cc_${ac_cc}_c_o=yes
   if test "x$CC" != xcc; then
     # Test first that cc exists at all.
-    if { ac_try='cc -c conftest.c 1>&5'; { (eval echo configure:1216: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then
+    if { ac_try='cc -c conftest.c 1>&5'; { (eval echo configure:1227: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then
       ac_try='cc -c conftest.c -o conftest.o 1>&5'
-      if { (eval echo configure:1218: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } &&
-        test -f conftest.o && { (eval echo configure:1219: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; };
+      if { (eval echo configure:1229: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } &&
+        test -f conftest.o && { (eval echo configure:1230: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; };
       then
         # cc works too.
         :
@@ -1249,20 +1260,20 @@ fi
 
 
 echo $ac_n "checking that the C compiler understands volatile""... $ac_c" 1>&6
-echo "configure:1253: checking that the C compiler understands volatile" >&5
+echo "configure:1264: checking that the C compiler understands volatile" >&5
 if eval "test \"`echo '$''{'samba_cv_volatile'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   
     cat > conftest.$ac_ext <<EOF
-#line 1259 "configure"
+#line 1270 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 int main() {
 volatile int i = 0
 ; return 0; }
 EOF
-if { (eval echo configure:1266: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1277: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   samba_cv_volatile=yes
 else
@@ -1311,7 +1322,7 @@ else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; }
 fi
 
 echo $ac_n "checking host system type""... $ac_c" 1>&6
-echo "configure:1315: checking host system type" >&5
+echo "configure:1326: checking host system type" >&5
 
 host_alias=$host
 case "$host_alias" in
@@ -1332,7 +1343,7 @@ host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
 echo "$ac_t""$host" 1>&6
 
 echo $ac_n "checking target system type""... $ac_c" 1>&6
-echo "configure:1336: checking target system type" >&5
+echo "configure:1347: checking target system type" >&5
 
 target_alias=$target
 case "$target_alias" in
@@ -1350,7 +1361,7 @@ target_os=`echo $target | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
 echo "$ac_t""$target" 1>&6
 
 echo $ac_n "checking build system type""... $ac_c" 1>&6
-echo "configure:1354: checking build system type" >&5
+echo "configure:1365: checking build system type" >&5
 
 build_alias=$build
 case "$build_alias" in
@@ -1384,7 +1395,7 @@ esac
 
     
     echo $ac_n "checking config.cache system type""... $ac_c" 1>&6
-echo "configure:1388: checking config.cache system type" >&5
+echo "configure:1399: checking config.cache system type" >&5
     if { test x"${ac_cv_host_system_type+set}" = x"set" &&
          test x"$ac_cv_host_system_type" != x"$host"; } ||
        { test x"${ac_cv_build_system_type+set}" = x"set" &&
@@ -1412,7 +1423,7 @@ case "$host_os" in
     *hpux*)
     
       echo $ac_n "checking whether ${CC-cc} accepts -Ae""... $ac_c" 1>&6
-echo "configure:1416: checking whether ${CC-cc} accepts -Ae" >&5
+echo "configure:1427: checking whether ${CC-cc} accepts -Ae" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_cc_Ae'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -1573,14 +1584,14 @@ EOF
     *sysv4*)
       if test $host = mips-sni-sysv4 ; then
         echo $ac_n "checking for LFS support""... $ac_c" 1>&6
-echo "configure:1577: checking for LFS support" >&5
+echo "configure:1588: checking for LFS support" >&5
         old_CPPFLAGS="$CPPFLAGS"
         CPPFLAGS="-D_LARGEFILE64_SOURCE $CPPFLAGS"
         if test "$cross_compiling" = yes; then
   SINIX_LFS_SUPPORT=cross
 else
   cat > conftest.$ac_ext <<EOF
-#line 1584 "configure"
+#line 1595 "configure"
 #include "confdefs.h"
 
 #include <unistd.h>
@@ -1592,7 +1603,7 @@ exit(1);
 #endif
 }
 EOF
-if { (eval echo configure:1596: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:1607: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   SINIX_LFS_SUPPORT=yes
 else
@@ -1623,14 +1634,14 @@ EOF
 #
     *linux*)
         echo $ac_n "checking for LFS support""... $ac_c" 1>&6
-echo "configure:1627: checking for LFS support" >&5
+echo "configure:1638: checking for LFS support" >&5
         old_CPPFLAGS="$CPPFLAGS"
         CPPFLAGS="-D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE $CPPFLAGS"
        if test "$cross_compiling" = yes; then
   LINUX_LFS_SUPPORT=cross
 else
   cat > conftest.$ac_ext <<EOF
-#line 1634 "configure"
+#line 1645 "configure"
 #include "confdefs.h"
 
 #include <unistd.h>
@@ -1668,7 +1679,7 @@ main() {
 }
 
 EOF
-if { (eval echo configure:1672: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:1683: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   LINUX_LFS_SUPPORT=yes
 else
@@ -1701,14 +1712,14 @@ EOF
 
     *hurd*)
         echo $ac_n "checking for LFS support""... $ac_c" 1>&6
-echo "configure:1705: checking for LFS support" >&5
+echo "configure:1716: checking for LFS support" >&5
         old_CPPFLAGS="$CPPFLAGS"
         CPPFLAGS="-D_LARGEFILE64_SOURCE -D_GNU_SOURCE $CPPFLAGS"
         if test "$cross_compiling" = yes; then
   GLIBC_LFS_SUPPORT=cross
 else
   cat > conftest.$ac_ext <<EOF
-#line 1712 "configure"
+#line 1723 "configure"
 #include "confdefs.h"
 
 #include <unistd.h>
@@ -1720,7 +1731,7 @@ exit(1);
 #endif
 }
 EOF
-if { (eval echo configure:1724: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:1735: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   GLIBC_LFS_SUPPORT=yes
 else
@@ -1750,21 +1761,21 @@ EOF
 esac
 
 echo $ac_n "checking for inline""... $ac_c" 1>&6
-echo "configure:1754: checking for inline" >&5
+echo "configure:1765: checking for inline" >&5
 if eval "test \"`echo '$''{'ac_cv_c_inline'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   ac_cv_c_inline=no
 for ac_kw in inline __inline__ __inline; do
   cat > conftest.$ac_ext <<EOF
-#line 1761 "configure"
+#line 1772 "configure"
 #include "confdefs.h"
 
 int main() {
 } $ac_kw foo() {
 ; return 0; }
 EOF
-if { (eval echo configure:1768: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1779: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_c_inline=$ac_kw; break
 else
@@ -1790,7 +1801,7 @@ EOF
 esac
 
 echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
-echo "configure:1794: checking how to run the C preprocessor" >&5
+echo "configure:1805: checking how to run the C preprocessor" >&5
 # On Suns, sometimes $CPP names a directory.
 if test -n "$CPP" && test -d "$CPP"; then
   CPP=
@@ -1805,13 +1816,13 @@ else
   # On the NeXT, cc -E runs the code through the compiler's parser,
   # not just through cpp.
   cat > conftest.$ac_ext <<EOF
-#line 1809 "configure"
+#line 1820 "configure"
 #include "confdefs.h"
 #include <assert.h>
 Syntax Error
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1815: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1826: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   :
@@ -1822,13 +1833,13 @@ else
   rm -rf conftest*
   CPP="${CC-cc} -E -traditional-cpp"
   cat > conftest.$ac_ext <<EOF
-#line 1826 "configure"
+#line 1837 "configure"
 #include "confdefs.h"
 #include <assert.h>
 Syntax Error
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1832: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1843: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   :
@@ -1839,13 +1850,13 @@ else
   rm -rf conftest*
   CPP="${CC-cc} -nologo -E"
   cat > conftest.$ac_ext <<EOF
-#line 1843 "configure"
+#line 1854 "configure"
 #include "confdefs.h"
 #include <assert.h>
 Syntax Error
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1849: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1860: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   :
@@ -1870,12 +1881,12 @@ fi
 echo "$ac_t""$CPP" 1>&6
 
 echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
-echo "configure:1874: checking for ANSI C header files" >&5
+echo "configure:1885: checking for ANSI C header files" >&5
 if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1879 "configure"
+#line 1890 "configure"
 #include "confdefs.h"
 #include <stdlib.h>
 #include <stdarg.h>
@@ -1883,7 +1894,7 @@ else
 #include <float.h>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1887: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1898: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -1900,7 +1911,7 @@ rm -f conftest*
 if test $ac_cv_header_stdc = yes; then
   # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
 cat > conftest.$ac_ext <<EOF
-#line 1904 "configure"
+#line 1915 "configure"
 #include "confdefs.h"
 #include <string.h>
 EOF
@@ -1918,7 +1929,7 @@ fi
 if test $ac_cv_header_stdc = yes; then
   # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
 cat > conftest.$ac_ext <<EOF
-#line 1922 "configure"
+#line 1933 "configure"
 #include "confdefs.h"
 #include <stdlib.h>
 EOF
@@ -1939,7 +1950,7 @@ if test "$cross_compiling" = yes; then
   :
 else
   cat > conftest.$ac_ext <<EOF
-#line 1943 "configure"
+#line 1954 "configure"
 #include "confdefs.h"
 #include <ctype.h>
 #define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
@@ -1950,7 +1961,7 @@ if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2);
 exit (0); }
 
 EOF
-if { (eval echo configure:1954: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:1965: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   :
 else
@@ -1978,12 +1989,12 @@ for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr that defines DIR""... $ac_c" 1>&6
-echo "configure:1982: checking for $ac_hdr that defines DIR" >&5
+echo "configure:1993: checking for $ac_hdr that defines DIR" >&5
 if eval "test \"`echo '$''{'ac_cv_header_dirent_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1987 "configure"
+#line 1998 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <$ac_hdr>
@@ -1991,7 +2002,7 @@ int main() {
 DIR *dirp = 0;
 ; return 0; }
 EOF
-if { (eval echo configure:1995: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:2006: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   eval "ac_cv_header_dirent_$ac_safe=yes"
 else
@@ -2016,7 +2027,7 @@ done
 # Two versions of opendir et al. are in -ldir and -lx on SCO Xenix.
 if test $ac_header_dirent = dirent.h; then
 echo $ac_n "checking for opendir in -ldir""... $ac_c" 1>&6
-echo "configure:2020: checking for opendir in -ldir" >&5
+echo "configure:2031: checking for opendir in -ldir" >&5
 ac_lib_var=`echo dir'_'opendir | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -2024,7 +2035,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-ldir  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 2028 "configure"
+#line 2039 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -2035,7 +2046,7 @@ int main() {
 opendir()
 ; return 0; }
 EOF
-if { (eval echo configure:2039: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:2050: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -2057,7 +2068,7 @@ fi
 
 else
 echo $ac_n "checking for opendir in -lx""... $ac_c" 1>&6
-echo "configure:2061: checking for opendir in -lx" >&5
+echo "configure:2072: checking for opendir in -lx" >&5
 ac_lib_var=`echo x'_'opendir | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -2065,7 +2076,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lx  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 2069 "configure"
+#line 2080 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -2076,7 +2087,7 @@ int main() {
 opendir()
 ; return 0; }
 EOF
-if { (eval echo configure:2080: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:2091: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -2099,12 +2110,12 @@ fi
 fi
 
 echo $ac_n "checking whether time.h and sys/time.h may both be included""... $ac_c" 1>&6
-echo "configure:2103: checking whether time.h and sys/time.h may both be included" >&5
+echo "configure:2114: checking whether time.h and sys/time.h may both be included" >&5
 if eval "test \"`echo '$''{'ac_cv_header_time'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 2108 "configure"
+#line 2119 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <sys/time.h>
@@ -2113,7 +2124,7 @@ int main() {
 struct tm *tp;
 ; return 0; }
 EOF
-if { (eval echo configure:2117: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:2128: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_header_time=yes
 else
@@ -2134,12 +2145,12 @@ EOF
 fi
 
 echo $ac_n "checking for sys/wait.h that is POSIX.1 compatible""... $ac_c" 1>&6
-echo "configure:2138: checking for sys/wait.h that is POSIX.1 compatible" >&5
+echo "configure:2149: checking for sys/wait.h that is POSIX.1 compatible" >&5
 if eval "test \"`echo '$''{'ac_cv_header_sys_wait_h'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 2143 "configure"
+#line 2154 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <sys/wait.h>
@@ -2155,7 +2166,7 @@ wait (&s);
 s = WIFEXITED (s) ? WEXITSTATUS (s) : 1;
 ; return 0; }
 EOF
-if { (eval echo configure:2159: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:2170: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_header_sys_wait_h=yes
 else
@@ -2179,17 +2190,17 @@ for ac_hdr in arpa/inet.h sys/fcntl.h sys/select.h fcntl.h sys/time.h sys/unistd
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:2183: checking for $ac_hdr" >&5
+echo "configure:2194: checking for $ac_hdr" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 2188 "configure"
+#line 2199 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:2193: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:2204: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -2219,17 +2230,17 @@ for ac_hdr in unistd.h utime.h grp.h sys/id.h limits.h memory.h net/if.h
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:2223: checking for $ac_hdr" >&5
+echo "configure:2234: checking for $ac_hdr" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 2228 "configure"
+#line 2239 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:2233: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:2244: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -2259,17 +2270,17 @@ for ac_hdr in compat.h rpc/rpc.h rpcsvc/nis.h rpcsvc/yp_prot.h rpcsvc/ypclnt.h
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:2263: checking for $ac_hdr" >&5
+echo "configure:2274: checking for $ac_hdr" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 2268 "configure"
+#line 2279 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:2273: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:2284: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -2299,17 +2310,17 @@ for ac_hdr in sys/param.h ctype.h sys/wait.h sys/resource.h sys/ioctl.h sys/ipc.
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:2303: checking for $ac_hdr" >&5
+echo "configure:2314: checking for $ac_hdr" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 2308 "configure"
+#line 2319 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:2313: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:2324: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -2339,17 +2350,17 @@ for ac_hdr in sys/mman.h sys/filio.h sys/priv.h sys/shm.h string.h strings.h std
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:2343: checking for $ac_hdr" >&5
+echo "configure:2354: checking for $ac_hdr" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 2348 "configure"
+#line 2359 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:2353: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:2364: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -2379,17 +2390,17 @@ for ac_hdr in sys/mount.h sys/vfs.h sys/fs/s5param.h sys/filsys.h termios.h term
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:2383: checking for $ac_hdr" >&5
+echo "configure:2394: checking for $ac_hdr" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 2388 "configure"
+#line 2399 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:2393: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:2404: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -2419,17 +2430,17 @@ for ac_hdr in sys/termio.h sys/statfs.h sys/dustat.h sys/statvfs.h stdarg.h sys/
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:2423: checking for $ac_hdr" >&5
+echo "configure:2434: checking for $ac_hdr" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 2428 "configure"
+#line 2439 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:2433: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:2444: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -2459,17 +2470,57 @@ for ac_hdr in security/pam_modules.h security/_pam_macros.h ldap.h lber.h dlfcn.
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:2463: checking for $ac_hdr" >&5
+echo "configure:2474: checking for $ac_hdr" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 2468 "configure"
+#line 2479 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:2473: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:2484: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=yes"
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+else
+  echo "$ac_t""no" 1>&6
+fi
+done
+
+for ac_hdr in sys/syslog.h syslog.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:2514: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 2519 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:2524: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -2503,14 +2554,14 @@ done
 case "$host_os" in
     *hpux*)
                cat > conftest.$ac_ext <<EOF
-#line 2507 "configure"
+#line 2558 "configure"
 #include "confdefs.h"
 #include <shadow.h>
 int main() {
 struct spwd testme
 ; return 0; }
 EOF
-if { (eval echo configure:2514: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:2565: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_header_shadow_h=yes
 else
@@ -2532,17 +2583,17 @@ for ac_hdr in shadow.h netinet/ip.h netinet/tcp.h netinet/in_systm.h netinet/in_
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:2536: checking for $ac_hdr" >&5
+echo "configure:2587: checking for $ac_hdr" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 2541 "configure"
+#line 2592 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:2546: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:2597: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -2572,17 +2623,17 @@ for ac_hdr in nss.h nss_common.h ns_api.h sys/security.h security/pam_appl.h sec
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:2576: checking for $ac_hdr" >&5
+echo "configure:2627: checking for $ac_hdr" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 2581 "configure"
+#line 2632 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:2586: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:2637: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -2612,17 +2663,17 @@ for ac_hdr in stropts.h poll.h
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:2616: checking for $ac_hdr" >&5
+echo "configure:2667: checking for $ac_hdr" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 2621 "configure"
+#line 2672 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:2626: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:2677: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -2652,17 +2703,17 @@ for ac_hdr in sys/capability.h syscall.h sys/syscall.h
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:2656: checking for $ac_hdr" >&5
+echo "configure:2707: checking for $ac_hdr" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 2661 "configure"
+#line 2712 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:2666: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:2717: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -2692,17 +2743,17 @@ for ac_hdr in sys/acl.h sys/cdefs.h glob.h
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:2696: checking for $ac_hdr" >&5
+echo "configure:2747: checking for $ac_hdr" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 2701 "configure"
+#line 2752 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:2706: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:2757: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -2734,17 +2785,17 @@ for ac_hdr in utmp.h utmpx.h lastlog.h
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:2738: checking for $ac_hdr" >&5
+echo "configure:2789: checking for $ac_hdr" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 2743 "configure"
+#line 2794 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:2748: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:2799: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -2776,17 +2827,17 @@ for ac_hdr in sys/fs/vx_quota.h
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:2780: checking for $ac_hdr" >&5
+echo "configure:2831: checking for $ac_hdr" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 2785 "configure"
+#line 2836 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:2790: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:2841: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -2818,17 +2869,17 @@ for ac_hdr in linux/xqm.h
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:2822: checking for $ac_hdr" >&5
+echo "configure:2873: checking for $ac_hdr" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 2827 "configure"
+#line 2878 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:2832: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:2883: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -2856,7 +2907,7 @@ done
 
 
 echo $ac_n "checking size of int""... $ac_c" 1>&6
-echo "configure:2860: checking size of int" >&5
+echo "configure:2911: checking size of int" >&5
 if eval "test \"`echo '$''{'ac_cv_sizeof_int'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -2864,7 +2915,7 @@ else
   ac_cv_sizeof_int=cross
 else
   cat > conftest.$ac_ext <<EOF
-#line 2868 "configure"
+#line 2919 "configure"
 #include "confdefs.h"
 #include <stdio.h>
 int main()
@@ -2875,7 +2926,7 @@ int main()
   return(0);
 }
 EOF
-if { (eval echo configure:2879: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:2930: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   ac_cv_sizeof_int=`cat conftestval`
 else
@@ -2895,7 +2946,7 @@ EOF
 
 
 echo $ac_n "checking size of long""... $ac_c" 1>&6
-echo "configure:2899: checking size of long" >&5
+echo "configure:2950: checking size of long" >&5
 if eval "test \"`echo '$''{'ac_cv_sizeof_long'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -2903,7 +2954,7 @@ else
   ac_cv_sizeof_long=cross
 else
   cat > conftest.$ac_ext <<EOF
-#line 2907 "configure"
+#line 2958 "configure"
 #include "confdefs.h"
 #include <stdio.h>
 int main()
@@ -2914,7 +2965,7 @@ int main()
   return(0);
 }
 EOF
-if { (eval echo configure:2918: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:2969: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   ac_cv_sizeof_long=`cat conftestval`
 else
@@ -2934,7 +2985,7 @@ EOF
 
 
 echo $ac_n "checking size of short""... $ac_c" 1>&6
-echo "configure:2938: checking size of short" >&5
+echo "configure:2989: checking size of short" >&5
 if eval "test \"`echo '$''{'ac_cv_sizeof_short'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -2942,7 +2993,7 @@ else
   ac_cv_sizeof_short=cross
 else
   cat > conftest.$ac_ext <<EOF
-#line 2946 "configure"
+#line 2997 "configure"
 #include "confdefs.h"
 #include <stdio.h>
 int main()
@@ -2953,7 +3004,7 @@ int main()
   return(0);
 }
 EOF
-if { (eval echo configure:2957: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:3008: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   ac_cv_sizeof_short=`cat conftestval`
 else
@@ -2974,12 +3025,12 @@ EOF
 
 
 echo $ac_n "checking for working const""... $ac_c" 1>&6
-echo "configure:2978: checking for working const" >&5
+echo "configure:3029: checking for working const" >&5
 if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 2983 "configure"
+#line 3034 "configure"
 #include "confdefs.h"
 
 int main() {
@@ -3028,7 +3079,7 @@ ccp = (char const *const *) p;
 
 ; return 0; }
 EOF
-if { (eval echo configure:3032: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:3083: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_c_const=yes
 else
@@ -3049,21 +3100,21 @@ EOF
 fi
 
 echo $ac_n "checking for inline""... $ac_c" 1>&6
-echo "configure:3053: checking for inline" >&5
+echo "configure:3104: checking for inline" >&5
 if eval "test \"`echo '$''{'ac_cv_c_inline'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   ac_cv_c_inline=no
 for ac_kw in inline __inline__ __inline; do
   cat > conftest.$ac_ext <<EOF
-#line 3060 "configure"
+#line 3111 "configure"
 #include "confdefs.h"
 
 int main() {
 } $ac_kw foo() {
 ; return 0; }
 EOF
-if { (eval echo configure:3067: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:3118: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_c_inline=$ac_kw; break
 else
@@ -3089,14 +3140,14 @@ EOF
 esac
 
 echo $ac_n "checking whether byte ordering is bigendian""... $ac_c" 1>&6
-echo "configure:3093: checking whether byte ordering is bigendian" >&5
+echo "configure:3144: checking whether byte ordering is bigendian" >&5
 if eval "test \"`echo '$''{'ac_cv_c_bigendian'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   ac_cv_c_bigendian=unknown
 # See if sys/param.h defines the BYTE_ORDER macro.
 cat > conftest.$ac_ext <<EOF
-#line 3100 "configure"
+#line 3151 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <sys/param.h>
@@ -3107,11 +3158,11 @@ int main() {
 #endif
 ; return 0; }
 EOF
-if { (eval echo configure:3111: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:3162: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   # It does; now see whether it defined to BIG_ENDIAN or not.
 cat > conftest.$ac_ext <<EOF
-#line 3115 "configure"
+#line 3166 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <sys/param.h>
@@ -3122,7 +3173,7 @@ int main() {
 #endif
 ; return 0; }
 EOF
-if { (eval echo configure:3126: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:3177: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_c_bigendian=yes
 else
@@ -3142,7 +3193,7 @@ if test "$cross_compiling" = yes; then
     { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
 else
   cat > conftest.$ac_ext <<EOF
-#line 3146 "configure"
+#line 3197 "configure"
 #include "confdefs.h"
 main () {
   /* Are we little or big endian?  From Harbison&Steele.  */
@@ -3155,7 +3206,7 @@ main () {
   exit (u.c[sizeof (long) - 1] == 1);
 }
 EOF
-if { (eval echo configure:3159: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:3210: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   ac_cv_c_bigendian=no
 else
@@ -3179,14 +3230,14 @@ EOF
 fi
 
 echo $ac_n "checking whether char is unsigned""... $ac_c" 1>&6
-echo "configure:3183: checking whether char is unsigned" >&5
+echo "configure:3234: checking whether char is unsigned" >&5
 if eval "test \"`echo '$''{'ac_cv_c_char_unsigned'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   if test "$GCC" = yes; then
   # GCC predefines this symbol on systems where it applies.
 cat > conftest.$ac_ext <<EOF
-#line 3190 "configure"
+#line 3241 "configure"
 #include "confdefs.h"
 #ifdef __CHAR_UNSIGNED__
   yes
@@ -3208,7 +3259,7 @@ if test "$cross_compiling" = yes; then
     { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
 else
   cat > conftest.$ac_ext <<EOF
-#line 3212 "configure"
+#line 3263 "configure"
 #include "confdefs.h"
 /* volatile prevents gcc2 from optimizing the test away on sparcs.  */
 #if !defined(__STDC__) || __STDC__ != 1
@@ -3218,7 +3269,7 @@ main() {
   volatile char c = 255; exit(c < 0);
 }
 EOF
-if { (eval echo configure:3222: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:3273: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   ac_cv_c_char_unsigned=yes
 else
@@ -3243,12 +3294,12 @@ fi
 
 
 echo $ac_n "checking return type of signal handlers""... $ac_c" 1>&6
-echo "configure:3247: checking return type of signal handlers" >&5
+echo "configure:3298: checking return type of signal handlers" >&5
 if eval "test \"`echo '$''{'ac_cv_type_signal'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 3252 "configure"
+#line 3303 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <signal.h>
@@ -3265,7 +3316,7 @@ int main() {
 int i;
 ; return 0; }
 EOF
-if { (eval echo configure:3269: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:3320: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_type_signal=void
 else
@@ -3284,12 +3335,12 @@ EOF
 
 
 echo $ac_n "checking for uid_t in sys/types.h""... $ac_c" 1>&6
-echo "configure:3288: checking for uid_t in sys/types.h" >&5
+echo "configure:3339: checking for uid_t in sys/types.h" >&5
 if eval "test \"`echo '$''{'ac_cv_type_uid_t'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 3293 "configure"
+#line 3344 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 EOF
@@ -3318,12 +3369,12 @@ EOF
 fi
 
 echo $ac_n "checking for mode_t""... $ac_c" 1>&6
-echo "configure:3322: checking for mode_t" >&5
+echo "configure:3373: checking for mode_t" >&5
 if eval "test \"`echo '$''{'ac_cv_type_mode_t'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 3327 "configure"
+#line 3378 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #if STDC_HEADERS
@@ -3351,12 +3402,12 @@ EOF
 fi
 
 echo $ac_n "checking for off_t""... $ac_c" 1>&6
-echo "configure:3355: checking for off_t" >&5
+echo "configure:3406: checking for off_t" >&5
 if eval "test \"`echo '$''{'ac_cv_type_off_t'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 3360 "configure"
+#line 3411 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #if STDC_HEADERS
@@ -3384,12 +3435,12 @@ EOF
 fi
 
 echo $ac_n "checking for size_t""... $ac_c" 1>&6
-echo "configure:3388: checking for size_t" >&5
+echo "configure:3439: checking for size_t" >&5
 if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 3393 "configure"
+#line 3444 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #if STDC_HEADERS
@@ -3417,12 +3468,12 @@ EOF
 fi
 
 echo $ac_n "checking for pid_t""... $ac_c" 1>&6
-echo "configure:3421: checking for pid_t" >&5
+echo "configure:3472: checking for pid_t" >&5
 if eval "test \"`echo '$''{'ac_cv_type_pid_t'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 3426 "configure"
+#line 3477 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #if STDC_HEADERS
@@ -3450,12 +3501,12 @@ EOF
 fi
 
 echo $ac_n "checking for st_rdev in struct stat""... $ac_c" 1>&6
-echo "configure:3454: checking for st_rdev in struct stat" >&5
+echo "configure:3505: checking for st_rdev in struct stat" >&5
 if eval "test \"`echo '$''{'ac_cv_struct_st_rdev'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 3459 "configure"
+#line 3510 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -3463,7 +3514,7 @@ int main() {
 struct stat s; s.st_rdev;
 ; return 0; }
 EOF
-if { (eval echo configure:3467: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:3518: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_struct_st_rdev=yes
 else
@@ -3484,12 +3535,12 @@ EOF
 fi
 
 echo $ac_n "checking for d_off in dirent""... $ac_c" 1>&6
-echo "configure:3488: checking for d_off in dirent" >&5
+echo "configure:3539: checking for d_off in dirent" >&5
 if eval "test \"`echo '$''{'ac_cv_dirent_d_off'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 3493 "configure"
+#line 3544 "configure"
 #include "confdefs.h"
 
 #include <unistd.h>
@@ -3499,7 +3550,7 @@ int main() {
 struct dirent d; d.d_off;
 ; return 0; }
 EOF
-if { (eval echo configure:3503: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:3554: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_dirent_d_off=yes
 else
@@ -3520,12 +3571,12 @@ EOF
 fi
 
 echo $ac_n "checking for ino_t""... $ac_c" 1>&6
-echo "configure:3524: checking for ino_t" >&5
+echo "configure:3575: checking for ino_t" >&5
 if eval "test \"`echo '$''{'ac_cv_type_ino_t'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 3529 "configure"
+#line 3580 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #if STDC_HEADERS
@@ -3553,12 +3604,12 @@ EOF
 fi
 
 echo $ac_n "checking for loff_t""... $ac_c" 1>&6
-echo "configure:3557: checking for loff_t" >&5
+echo "configure:3608: checking for loff_t" >&5
 if eval "test \"`echo '$''{'ac_cv_type_loff_t'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 3562 "configure"
+#line 3613 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #if STDC_HEADERS
@@ -3586,12 +3637,12 @@ EOF
 fi
 
 echo $ac_n "checking for offset_t""... $ac_c" 1>&6
-echo "configure:3590: checking for offset_t" >&5
+echo "configure:3641: checking for offset_t" >&5
 if eval "test \"`echo '$''{'ac_cv_type_offset_t'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 3595 "configure"
+#line 3646 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #if STDC_HEADERS
@@ -3619,12 +3670,12 @@ EOF
 fi
 
 echo $ac_n "checking for ssize_t""... $ac_c" 1>&6
-echo "configure:3623: checking for ssize_t" >&5
+echo "configure:3674: checking for ssize_t" >&5
 if eval "test \"`echo '$''{'ac_cv_type_ssize_t'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 3628 "configure"
+#line 3679 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #if STDC_HEADERS
@@ -3652,12 +3703,12 @@ EOF
 fi
 
 echo $ac_n "checking for wchar_t""... $ac_c" 1>&6
-echo "configure:3656: checking for wchar_t" >&5
+echo "configure:3707: checking for wchar_t" >&5
 if eval "test \"`echo '$''{'ac_cv_type_wchar_t'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 3661 "configure"
+#line 3712 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #if STDC_HEADERS
@@ -3699,7 +3750,7 @@ if test x$enable_cups != xno; then
        # Extract the first word of "cups-config", so it can be a program name with args.
 set dummy cups-config; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:3703: checking for $ac_word" >&5
+echo "configure:3754: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_path_CUPS_CONFIG'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -3739,7 +3790,7 @@ EOF
 
                CFLAGS="$CFLAGS `$CUPS_CONFIG --cflags`"
                LDFLAGS="$LDFLAGS `$CUPS_CONFIG --ldflags`"
-               LIBS="$LIBS `$CUPS_CONFIG --libs`"
+               PRINTLIBS="$PRINTLIBS `$CUPS_CONFIG --libs`"
         fi
 fi
 
@@ -3748,12 +3799,12 @@ fi
 for ac_func in dlopen
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:3752: checking for $ac_func" >&5
+echo "configure:3803: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 3757 "configure"
+#line 3808 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -3776,7 +3827,7 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:3780: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:3831: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -3802,7 +3853,7 @@ done
 
 if test x"$ac_cv_func_dlopen" = x"no"; then
     echo $ac_n "checking for dlopen in -ldl""... $ac_c" 1>&6
-echo "configure:3806: checking for dlopen in -ldl" >&5
+echo "configure:3857: checking for dlopen in -ldl" >&5
 ac_lib_var=`echo dl'_'dlopen | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -3810,7 +3861,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-ldl  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 3814 "configure"
+#line 3865 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -3821,7 +3872,7 @@ int main() {
 dlopen()
 ; return 0; }
 EOF
-if { (eval echo configure:3825: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:3876: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -3851,13 +3902,13 @@ fi
 ############################################
 # check if the compiler can do immediate structures
 echo $ac_n "checking for immediate structures""... $ac_c" 1>&6
-echo "configure:3855: checking for immediate structures" >&5
+echo "configure:3906: checking for immediate structures" >&5
 if eval "test \"`echo '$''{'samba_cv_immediate_structures'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   
     cat > conftest.$ac_ext <<EOF
-#line 3861 "configure"
+#line 3912 "configure"
 #include "confdefs.h"
 
 #include <stdio.h>
@@ -3875,7 +3926,7 @@ int main() {
 
 ; return 0; }
 EOF
-if { (eval echo configure:3879: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:3930: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   samba_cv_immediate_structures=yes
 else
@@ -3898,13 +3949,13 @@ fi
 ############################################
 # check for unix domain sockets
 echo $ac_n "checking for unix domain sockets""... $ac_c" 1>&6
-echo "configure:3902: checking for unix domain sockets" >&5
+echo "configure:3953: checking for unix domain sockets" >&5
 if eval "test \"`echo '$''{'samba_cv_unixsocket'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   
     cat > conftest.$ac_ext <<EOF
-#line 3908 "configure"
+#line 3959 "configure"
 #include "confdefs.h"
 
 #include <sys/types.h>
@@ -3919,7 +3970,7 @@ int main() {
 
 ; return 0; }
 EOF
-if { (eval echo configure:3923: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:3974: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   samba_cv_unixsocket=yes
 else
@@ -3941,13 +3992,13 @@ fi
 
 
 echo $ac_n "checking for socklen_t type""... $ac_c" 1>&6
-echo "configure:3945: checking for socklen_t type" >&5
+echo "configure:3996: checking for socklen_t type" >&5
 if eval "test \"`echo '$''{'samba_cv_socklen_t'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   
     cat > conftest.$ac_ext <<EOF
-#line 3951 "configure"
+#line 4002 "configure"
 #include "confdefs.h"
 
 #include <sys/types.h>
@@ -3960,7 +4011,7 @@ int main() {
 socklen_t i = 0
 ; return 0; }
 EOF
-if { (eval echo configure:3964: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:4015: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   samba_cv_socklen_t=yes
 else
@@ -3981,13 +4032,13 @@ EOF
 fi
 
 echo $ac_n "checking for sig_atomic_t type""... $ac_c" 1>&6
-echo "configure:3985: checking for sig_atomic_t type" >&5
+echo "configure:4036: checking for sig_atomic_t type" >&5
 if eval "test \"`echo '$''{'samba_cv_sig_atomic_t'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   
     cat > conftest.$ac_ext <<EOF
-#line 3991 "configure"
+#line 4042 "configure"
 #include "confdefs.h"
 
 #include <sys/types.h>
@@ -4000,7 +4051,7 @@ int main() {
 sig_atomic_t i = 0
 ; return 0; }
 EOF
-if { (eval echo configure:4004: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:4055: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   samba_cv_sig_atomic_t=yes
 else
@@ -4023,20 +4074,20 @@ fi
 # stupid headers have the functions but no declaration. grrrr.
 
  echo $ac_n "checking for errno declaration""... $ac_c" 1>&6
-echo "configure:4027: checking for errno declaration" >&5
+echo "configure:4078: checking for errno declaration" >&5
 if eval "test \"`echo '$''{'ac_cv_have_errno_decl'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   
     cat > conftest.$ac_ext <<EOF
-#line 4033 "configure"
+#line 4084 "configure"
 #include "confdefs.h"
 #include <errno.h>
 int main() {
 int i = (int)errno
 ; return 0; }
 EOF
-if { (eval echo configure:4040: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:4091: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_have_errno_decl=yes
 else
@@ -4058,20 +4109,20 @@ EOF
 
 
  echo $ac_n "checking for setresuid declaration""... $ac_c" 1>&6
-echo "configure:4062: checking for setresuid declaration" >&5
+echo "configure:4113: checking for setresuid declaration" >&5
 if eval "test \"`echo '$''{'ac_cv_have_setresuid_decl'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   
     cat > conftest.$ac_ext <<EOF
-#line 4068 "configure"
+#line 4119 "configure"
 #include "confdefs.h"
 #include <unistd.h>
 int main() {
 int i = (int)setresuid
 ; return 0; }
 EOF
-if { (eval echo configure:4075: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:4126: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_have_setresuid_decl=yes
 else
@@ -4093,20 +4144,20 @@ EOF
 
 
  echo $ac_n "checking for setresgid declaration""... $ac_c" 1>&6
-echo "configure:4097: checking for setresgid declaration" >&5
+echo "configure:4148: checking for setresgid declaration" >&5
 if eval "test \"`echo '$''{'ac_cv_have_setresgid_decl'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   
     cat > conftest.$ac_ext <<EOF
-#line 4103 "configure"
+#line 4154 "configure"
 #include "confdefs.h"
 #include <unistd.h>
 int main() {
 int i = (int)setresgid
 ; return 0; }
 EOF
-if { (eval echo configure:4110: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:4161: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_have_setresgid_decl=yes
 else
@@ -4128,20 +4179,20 @@ EOF
 
 
  echo $ac_n "checking for asprintf declaration""... $ac_c" 1>&6
-echo "configure:4132: checking for asprintf declaration" >&5
+echo "configure:4183: checking for asprintf declaration" >&5
 if eval "test \"`echo '$''{'ac_cv_have_asprintf_decl'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   
     cat > conftest.$ac_ext <<EOF
-#line 4138 "configure"
+#line 4189 "configure"
 #include "confdefs.h"
 #include <stdio.h>
 int main() {
 int i = (int)asprintf
 ; return 0; }
 EOF
-if { (eval echo configure:4145: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:4196: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_have_asprintf_decl=yes
 else
@@ -4163,20 +4214,20 @@ EOF
 
 
  echo $ac_n "checking for vasprintf declaration""... $ac_c" 1>&6
-echo "configure:4167: checking for vasprintf declaration" >&5
+echo "configure:4218: checking for vasprintf declaration" >&5
 if eval "test \"`echo '$''{'ac_cv_have_vasprintf_decl'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   
     cat > conftest.$ac_ext <<EOF
-#line 4173 "configure"
+#line 4224 "configure"
 #include "confdefs.h"
 #include <stdio.h>
 int main() {
 int i = (int)vasprintf
 ; return 0; }
 EOF
-if { (eval echo configure:4180: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:4231: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_have_vasprintf_decl=yes
 else
@@ -4198,20 +4249,20 @@ EOF
 
 
  echo $ac_n "checking for vsnprintf declaration""... $ac_c" 1>&6
-echo "configure:4202: checking for vsnprintf declaration" >&5
+echo "configure:4253: checking for vsnprintf declaration" >&5
 if eval "test \"`echo '$''{'ac_cv_have_vsnprintf_decl'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   
     cat > conftest.$ac_ext <<EOF
-#line 4208 "configure"
+#line 4259 "configure"
 #include "confdefs.h"
 #include <stdio.h>
 int main() {
 int i = (int)vsnprintf
 ; return 0; }
 EOF
-if { (eval echo configure:4215: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:4266: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_have_vsnprintf_decl=yes
 else
@@ -4233,20 +4284,20 @@ EOF
 
 
  echo $ac_n "checking for snprintf declaration""... $ac_c" 1>&6
-echo "configure:4237: checking for snprintf declaration" >&5
+echo "configure:4288: checking for snprintf declaration" >&5
 if eval "test \"`echo '$''{'ac_cv_have_snprintf_decl'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   
     cat > conftest.$ac_ext <<EOF
-#line 4243 "configure"
+#line 4294 "configure"
 #include "confdefs.h"
 #include <stdio.h>
 int main() {
 int i = (int)snprintf
 ; return 0; }
 EOF
-if { (eval echo configure:4250: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:4301: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_have_snprintf_decl=yes
 else
@@ -4270,7 +4321,7 @@ EOF
 # and glibc has setresuid under linux but the function does
 # nothing until kernel 2.1.44! very dumb.
 echo $ac_n "checking for real setresuid""... $ac_c" 1>&6
-echo "configure:4274: checking for real setresuid" >&5
+echo "configure:4325: checking for real setresuid" >&5
 if eval "test \"`echo '$''{'samba_cv_have_setresuid'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -4279,12 +4330,12 @@ else
   samba_cv_have_setresuid=cross
 else
   cat > conftest.$ac_ext <<EOF
-#line 4283 "configure"
+#line 4334 "configure"
 #include "confdefs.h"
 #include <errno.h>
 main() { setresuid(1,1,1); setresuid(2,2,2); exit(errno==EPERM?0:1);}
 EOF
-if { (eval echo configure:4288: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:4339: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   samba_cv_have_setresuid=yes
 else
@@ -4309,7 +4360,7 @@ fi
 # Do the same check for setresguid...
 #
 echo $ac_n "checking for real setresgid""... $ac_c" 1>&6
-echo "configure:4313: checking for real setresgid" >&5
+echo "configure:4364: checking for real setresgid" >&5
 if eval "test \"`echo '$''{'samba_cv_have_setresgid'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -4318,13 +4369,13 @@ else
   samba_cv_have_setresgid=cross
 else
   cat > conftest.$ac_ext <<EOF
-#line 4322 "configure"
+#line 4373 "configure"
 #include "confdefs.h"
 #include <unistd.h>
 #include <errno.h>
 main() { errno = 0; setresgid(1,1,1); exit(errno != 0 ? (errno==EPERM ? 0 : 1) : 0);}
 EOF
-if { (eval echo configure:4328: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:4379: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   samba_cv_have_setresgid=yes
 else
@@ -4347,7 +4398,7 @@ EOF
 fi
 
 echo $ac_n "checking for 8-bit clean memcmp""... $ac_c" 1>&6
-echo "configure:4351: checking for 8-bit clean memcmp" >&5
+echo "configure:4402: checking for 8-bit clean memcmp" >&5
 if eval "test \"`echo '$''{'ac_cv_func_memcmp_clean'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -4355,7 +4406,7 @@ else
   ac_cv_func_memcmp_clean=no
 else
   cat > conftest.$ac_ext <<EOF
-#line 4359 "configure"
+#line 4410 "configure"
 #include "confdefs.h"
 
 main()
@@ -4365,7 +4416,7 @@ main()
 }
 
 EOF
-if { (eval echo configure:4369: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:4420: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   ac_cv_func_memcmp_clean=yes
 else
@@ -4388,12 +4439,12 @@ test $ac_cv_func_memcmp_clean = no && LIBOBJS="$LIBOBJS memcmp.${ac_objext}"
 for ac_func in crypt
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:4392: checking for $ac_func" >&5
+echo "configure:4443: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 4397 "configure"
+#line 4448 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -4416,7 +4467,7 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:4420: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:4471: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -4442,7 +4493,7 @@ done
 
 if test x"$ac_cv_func_crypt" = x"no"; then
     echo $ac_n "checking for crypt in -lcrypt""... $ac_c" 1>&6
-echo "configure:4446: checking for crypt in -lcrypt" >&5
+echo "configure:4497: checking for crypt in -lcrypt" >&5
 ac_lib_var=`echo crypt'_'crypt | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -4450,7 +4501,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lcrypt  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 4454 "configure"
+#line 4505 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -4461,7 +4512,7 @@ int main() {
 crypt()
 ; return 0; }
 EOF
-if { (eval echo configure:4465: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:4516: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -4494,7 +4545,7 @@ test "${with_readline+set}" != "set" && with_readline=yes
 
 # test for where we get readline() from
 echo $ac_n "checking whether to use readline""... $ac_c" 1>&6
-echo "configure:4498: checking whether to use readline" >&5
+echo "configure:4549: checking whether to use readline" >&5
 # Check whether --with-readline or --without-readline was given.
 if test "${with_readline+set}" = set; then
   withval="$with_readline"
@@ -4506,17 +4557,17 @@ if test "${with_readline+set}" = set; then
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:4510: checking for $ac_hdr" >&5
+echo "configure:4561: checking for $ac_hdr" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 4515 "configure"
+#line 4566 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:4520: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:4571: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -4546,17 +4597,17 @@ done
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:4550: checking for $ac_hdr" >&5
+echo "configure:4601: checking for $ac_hdr" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 4555 "configure"
+#line 4606 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:4560: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:4611: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -4587,17 +4638,17 @@ done
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:4591: checking for $ac_hdr" >&5
+echo "configure:4642: checking for $ac_hdr" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 4596 "configure"
+#line 4647 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:4601: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:4652: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -4620,7 +4671,7 @@ EOF
  
       for termlib in ncurses curses termcap terminfo termlib; do
        echo $ac_n "checking for tgetent in -l${termlib}""... $ac_c" 1>&6
-echo "configure:4624: checking for tgetent in -l${termlib}" >&5
+echo "configure:4675: checking for tgetent in -l${termlib}" >&5
 ac_lib_var=`echo ${termlib}'_'tgetent | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -4628,7 +4679,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-l${termlib}  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 4632 "configure"
+#line 4683 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -4639,7 +4690,7 @@ int main() {
 tgetent()
 ; return 0; }
 EOF
-if { (eval echo configure:4643: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:4694: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -4661,7 +4712,7 @@ fi
 
       done
       echo $ac_n "checking for rl_callback_handler_install in -lreadline""... $ac_c" 1>&6
-echo "configure:4665: checking for rl_callback_handler_install in -lreadline" >&5
+echo "configure:4716: checking for rl_callback_handler_install in -lreadline" >&5
 ac_lib_var=`echo readline'_'rl_callback_handler_install | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -4669,7 +4720,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lreadline $TERMLIBS $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 4673 "configure"
+#line 4724 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -4680,7 +4731,7 @@ int main() {
 rl_callback_handler_install()
 ; return 0; }
 EOF
-if { (eval echo configure:4684: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:4735: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -4731,17 +4782,17 @@ done
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:4735: checking for $ac_hdr" >&5
+echo "configure:4786: checking for $ac_hdr" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 4740 "configure"
+#line 4791 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:4745: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:4796: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -4771,17 +4822,17 @@ done
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:4775: checking for $ac_hdr" >&5
+echo "configure:4826: checking for $ac_hdr" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 4780 "configure"
+#line 4831 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:4785: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:4836: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -4812,17 +4863,17 @@ done
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:4816: checking for $ac_hdr" >&5
+echo "configure:4867: checking for $ac_hdr" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 4821 "configure"
+#line 4872 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:4826: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:4877: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -4845,7 +4896,7 @@ EOF
  
       for termlib in ncurses curses termcap terminfo termlib; do
        echo $ac_n "checking for tgetent in -l${termlib}""... $ac_c" 1>&6
-echo "configure:4849: checking for tgetent in -l${termlib}" >&5
+echo "configure:4900: checking for tgetent in -l${termlib}" >&5
 ac_lib_var=`echo ${termlib}'_'tgetent | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -4853,7 +4904,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-l${termlib}  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 4857 "configure"
+#line 4908 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -4864,7 +4915,7 @@ int main() {
 tgetent()
 ; return 0; }
 EOF
-if { (eval echo configure:4868: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:4919: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -4886,7 +4937,7 @@ fi
 
       done
       echo $ac_n "checking for rl_callback_handler_install in -lreadline""... $ac_c" 1>&6
-echo "configure:4890: checking for rl_callback_handler_install in -lreadline" >&5
+echo "configure:4941: checking for rl_callback_handler_install in -lreadline" >&5
 ac_lib_var=`echo readline'_'rl_callback_handler_install | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -4894,7 +4945,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lreadline $TERMLIBS $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 4898 "configure"
+#line 4949 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -4905,7 +4956,7 @@ int main() {
 rl_callback_handler_install()
 ; return 0; }
 EOF
-if { (eval echo configure:4909: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:4960: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -4955,7 +5006,7 @@ fi
 # code will generate warnings on one of them unless we have a few
 # special cases.
 echo $ac_n "checking for rl_completion_matches in -lreadline""... $ac_c" 1>&6
-echo "configure:4959: checking for rl_completion_matches in -lreadline" >&5
+echo "configure:5010: checking for rl_completion_matches in -lreadline" >&5
 ac_lib_var=`echo readline'_'rl_completion_matches | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -4963,7 +5014,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lreadline $TERMLIBS $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 4967 "configure"
+#line 5018 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -4974,7 +5025,7 @@ int main() {
 rl_completion_matches()
 ; return 0; }
 EOF
-if { (eval echo configure:4978: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:5029: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -5007,12 +5058,12 @@ fi
 for ac_func in connect
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:5011: checking for $ac_func" >&5
+echo "configure:5062: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 5016 "configure"
+#line 5067 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -5035,7 +5086,7 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:5039: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:5090: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -5063,7 +5114,7 @@ if test x"$ac_cv_func_connect" = x"no"; then
     case "$LIBS" in
     *-lnsl*) ;;
     *) echo $ac_n "checking for printf in -lnsl_s""... $ac_c" 1>&6
-echo "configure:5067: checking for printf in -lnsl_s" >&5
+echo "configure:5118: checking for printf in -lnsl_s" >&5
 ac_lib_var=`echo nsl_s'_'printf | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -5071,7 +5122,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lnsl_s  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 5075 "configure"
+#line 5126 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -5082,7 +5133,7 @@ int main() {
 printf()
 ; return 0; }
 EOF
-if { (eval echo configure:5086: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:5137: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -5113,7 +5164,7 @@ fi
     case "$LIBS" in
     *-lnsl*) ;;
     *) echo $ac_n "checking for printf in -lnsl""... $ac_c" 1>&6
-echo "configure:5117: checking for printf in -lnsl" >&5
+echo "configure:5168: checking for printf in -lnsl" >&5
 ac_lib_var=`echo nsl'_'printf | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -5121,7 +5172,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lnsl  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 5125 "configure"
+#line 5176 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -5132,7 +5183,7 @@ int main() {
 printf()
 ; return 0; }
 EOF
-if { (eval echo configure:5136: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:5187: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -5163,7 +5214,7 @@ fi
     case "$LIBS" in
     *-lsocket*) ;;
     *) echo $ac_n "checking for connect in -lsocket""... $ac_c" 1>&6
-echo "configure:5167: checking for connect in -lsocket" >&5
+echo "configure:5218: checking for connect in -lsocket" >&5
 ac_lib_var=`echo socket'_'connect | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -5171,7 +5222,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lsocket  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 5175 "configure"
+#line 5226 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -5182,7 +5233,7 @@ int main() {
 connect()
 ; return 0; }
 EOF
-if { (eval echo configure:5186: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:5237: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -5213,7 +5264,7 @@ fi
     case "$LIBS" in
     *-linet*) ;;
     *) echo $ac_n "checking for connect in -linet""... $ac_c" 1>&6
-echo "configure:5217: checking for connect in -linet" >&5
+echo "configure:5268: checking for connect in -linet" >&5
 ac_lib_var=`echo inet'_'connect | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -5221,7 +5272,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-linet  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 5225 "configure"
+#line 5276 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -5232,7 +5283,7 @@ int main() {
 connect()
 ; return 0; }
 EOF
-if { (eval echo configure:5236: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:5287: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -5276,12 +5327,12 @@ fi
 for ac_func in yp_get_default_domain
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:5280: checking for $ac_func" >&5
+echo "configure:5331: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 5285 "configure"
+#line 5336 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -5304,7 +5355,7 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:5308: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:5359: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -5330,7 +5381,7 @@ done
 
 if test x"$ac_cv_func_yp_get_default_domain" = x"no"; then
        echo $ac_n "checking for yp_get_default_domain in -lnsl""... $ac_c" 1>&6
-echo "configure:5334: checking for yp_get_default_domain in -lnsl" >&5
+echo "configure:5385: checking for yp_get_default_domain in -lnsl" >&5
 ac_lib_var=`echo nsl'_'yp_get_default_domain | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -5338,7 +5389,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lnsl  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 5342 "configure"
+#line 5393 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -5349,7 +5400,7 @@ int main() {
 yp_get_default_domain()
 ; return 0; }
 EOF
-if { (eval echo configure:5353: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:5404: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -5379,12 +5430,12 @@ fi
 for ac_func in execl
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:5383: checking for $ac_func" >&5
+echo "configure:5434: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 5388 "configure"
+#line 5439 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -5407,7 +5458,7 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:5411: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:5462: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -5440,12 +5491,12 @@ fi
 for ac_func in dlopen dlclose dlsym dlerror waitpid getcwd strdup strndup strnlen strtoul strerror chown fchown chmod fchmod chroot link mknod mknod64
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:5444: checking for $ac_func" >&5
+echo "configure:5495: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 5449 "configure"
+#line 5500 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -5468,7 +5519,7 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:5472: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:5523: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -5495,12 +5546,12 @@ done
 for ac_func in fstat strchr utime utimes getrlimit fsync bzero memset strlcpy strlcat setpgid
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:5499: checking for $ac_func" >&5
+echo "configure:5550: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 5504 "configure"
+#line 5555 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -5523,7 +5574,7 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:5527: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:5578: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -5550,12 +5601,12 @@ done
 for ac_func in memmove vsnprintf snprintf asprintf vasprintf setsid glob strpbrk pipe crypt16 getauthuid
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:5554: checking for $ac_func" >&5
+echo "configure:5605: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 5559 "configure"
+#line 5610 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -5578,7 +5629,7 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:5582: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:5633: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -5605,12 +5656,12 @@ done
 for ac_func in strftime sigprocmask sigblock sigaction sigset innetgr setnetgrent getnetgrent endnetgrent
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:5609: checking for $ac_func" >&5
+echo "configure:5660: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 5614 "configure"
+#line 5665 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -5633,7 +5684,7 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:5637: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:5688: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -5660,12 +5711,12 @@ done
 for ac_func in initgroups select poll rdchk getgrnam getgrent pathconf realpath
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:5664: checking for $ac_func" >&5
+echo "configure:5715: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 5669 "configure"
+#line 5720 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -5688,7 +5739,7 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:5692: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:5743: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -5715,12 +5766,12 @@ done
 for ac_func in setpriv setgidx setuidx setgroups sysconf mktime rename ftruncate stat64 fstat64
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:5719: checking for $ac_func" >&5
+echo "configure:5770: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 5724 "configure"
+#line 5775 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -5743,7 +5794,7 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:5747: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:5798: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -5770,12 +5821,12 @@ done
 for ac_func in lstat64 fopen64 atexit grantpt dup2 lseek64 ftruncate64 readdir64
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:5774: checking for $ac_func" >&5
+echo "configure:5825: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 5779 "configure"
+#line 5830 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -5798,7 +5849,7 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:5802: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:5853: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -5825,12 +5876,12 @@ done
 for ac_func in fseek64 fseeko64 ftell64 ftello64 setluid getpwanam setlinebuf
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:5829: checking for $ac_func" >&5
+echo "configure:5880: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 5834 "configure"
+#line 5885 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -5853,7 +5904,7 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:5857: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:5908: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -5880,12 +5931,12 @@ done
 for ac_func in srandom random srand rand setenv usleep strcasecmp fcvt fcvtl symlink readlink
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:5884: checking for $ac_func" >&5
+echo "configure:5935: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 5889 "configure"
+#line 5940 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -5908,7 +5959,7 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:5912: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:5963: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -5935,12 +5986,12 @@ done
 for ac_func in syslog vsyslog getgrouplist
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:5939: checking for $ac_func" >&5
+echo "configure:5990: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 5944 "configure"
+#line 5995 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -5963,7 +6014,7 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:5967: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:6018: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -5991,12 +6042,12 @@ done
 for ac_func in setbuffer
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:5995: checking for $ac_func" >&5
+echo "configure:6046: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 6000 "configure"
+#line 6051 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -6019,7 +6070,7 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:6023: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:6074: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -6048,12 +6099,12 @@ done
 for ac_func in syscall
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:6052: checking for $ac_func" >&5
+echo "configure:6103: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 6057 "configure"
+#line 6108 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -6076,7 +6127,7 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:6080: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:6131: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -6104,12 +6155,12 @@ done
 for ac_func in _dup _dup2 _opendir _readdir _seekdir _telldir _closedir
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:6108: checking for $ac_func" >&5
+echo "configure:6159: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 6113 "configure"
+#line 6164 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -6132,7 +6183,7 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:6136: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:6187: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -6159,12 +6210,12 @@ done
 for ac_func in __dup __dup2 __opendir __readdir __seekdir __telldir __closedir
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:6163: checking for $ac_func" >&5
+echo "configure:6214: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 6168 "configure"
+#line 6219 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -6187,7 +6238,7 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:6191: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:6242: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -6214,12 +6265,12 @@ done
 for ac_func in __getcwd _getcwd
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:6218: checking for $ac_func" >&5
+echo "configure:6269: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 6223 "configure"
+#line 6274 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -6242,7 +6293,7 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:6246: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:6297: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -6269,12 +6320,12 @@ done
 for ac_func in __xstat __fxstat __lxstat
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:6273: checking for $ac_func" >&5
+echo "configure:6324: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 6278 "configure"
+#line 6329 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -6297,7 +6348,7 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:6301: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:6352: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -6324,12 +6375,12 @@ done
 for ac_func in _stat _lstat _fstat __stat __lstat __fstat
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:6328: checking for $ac_func" >&5
+echo "configure:6379: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 6333 "configure"
+#line 6384 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -6352,7 +6403,7 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:6356: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:6407: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -6379,12 +6430,12 @@ done
 for ac_func in _acl __acl _facl __facl _open __open _chdir __chdir
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:6383: checking for $ac_func" >&5
+echo "configure:6434: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 6388 "configure"
+#line 6439 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -6407,7 +6458,7 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:6411: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:6462: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -6434,12 +6485,12 @@ done
 for ac_func in _close __close _fchdir __fchdir _fcntl __fcntl
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:6438: checking for $ac_func" >&5
+echo "configure:6489: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 6443 "configure"
+#line 6494 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -6462,7 +6513,7 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:6466: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:6517: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -6489,12 +6540,12 @@ done
 for ac_func in getdents _getdents __getdents _lseek __lseek _read __read
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:6493: checking for $ac_func" >&5
+echo "configure:6544: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 6498 "configure"
+#line 6549 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -6517,7 +6568,7 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:6521: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:6572: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -6544,12 +6595,12 @@ done
 for ac_func in _write __write _fork __fork
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:6548: checking for $ac_func" >&5
+echo "configure:6599: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 6553 "configure"
+#line 6604 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -6572,7 +6623,7 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:6576: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:6627: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -6599,12 +6650,12 @@ done
 for ac_func in _stat64 __stat64 _fstat64 __fstat64 _lstat64 __lstat64
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:6603: checking for $ac_func" >&5
+echo "configure:6654: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 6608 "configure"
+#line 6659 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -6627,7 +6678,7 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:6631: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:6682: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -6654,12 +6705,12 @@ done
 for ac_func in __sys_llseek llseek _llseek __llseek readdir64 _readdir64 __readdir64
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:6658: checking for $ac_func" >&5
+echo "configure:6709: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 6663 "configure"
+#line 6714 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -6682,7 +6733,7 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:6686: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:6737: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -6709,12 +6760,12 @@ done
 for ac_func in pread _pread __pread pread64 _pread64 __pread64
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:6713: checking for $ac_func" >&5
+echo "configure:6764: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 6718 "configure"
+#line 6769 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -6737,7 +6788,7 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:6741: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:6792: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -6764,12 +6815,12 @@ done
 for ac_func in pwrite _pwrite __pwrite pwrite64 _pwrite64 __pwrite64
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:6768: checking for $ac_func" >&5
+echo "configure:6819: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 6773 "configure"
+#line 6824 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -6792,7 +6843,7 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:6796: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:6847: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -6819,12 +6870,12 @@ done
 for ac_func in open64 _open64 __open64 creat64
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:6823: checking for $ac_func" >&5
+echo "configure:6874: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 6828 "configure"
+#line 6879 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -6847,7 +6898,7 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:6851: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:6902: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -6878,9 +6929,9 @@ done
 
 if test x$ac_cv_func_stat64 = xno ; then
   echo $ac_n "checking for stat64 in <sys/stat.h>""... $ac_c" 1>&6
-echo "configure:6882: checking for stat64 in <sys/stat.h>" >&5
+echo "configure:6933: checking for stat64 in <sys/stat.h>" >&5
   cat > conftest.$ac_ext <<EOF
-#line 6884 "configure"
+#line 6935 "configure"
 #include "confdefs.h"
 
 #if defined(HAVE_UNISTD_H)
@@ -6892,7 +6943,7 @@ int main() {
 struct stat64 st64; exit(stat64(".",&st64));
 ; return 0; }
 EOF
-if { (eval echo configure:6896: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:6947: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   ac_cv_func_stat64=yes
 else
@@ -6911,9 +6962,9 @@ fi
 
 if test x$ac_cv_func_lstat64 = xno ; then
   echo $ac_n "checking for lstat64 in <sys/stat.h>""... $ac_c" 1>&6
-echo "configure:6915: checking for lstat64 in <sys/stat.h>" >&5
+echo "configure:6966: checking for lstat64 in <sys/stat.h>" >&5
   cat > conftest.$ac_ext <<EOF
-#line 6917 "configure"
+#line 6968 "configure"
 #include "confdefs.h"
 
 #if defined(HAVE_UNISTD_H)
@@ -6925,7 +6976,7 @@ int main() {
 struct stat64 st64; exit(lstat64(".",&st64));
 ; return 0; }
 EOF
-if { (eval echo configure:6929: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:6980: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   ac_cv_func_lstat64=yes
 else
@@ -6944,9 +6995,9 @@ fi
 
 if test x$ac_cv_func_fstat64 = xno ; then
   echo $ac_n "checking for fstat64 in <sys/stat.h>""... $ac_c" 1>&6
-echo "configure:6948: checking for fstat64 in <sys/stat.h>" >&5
+echo "configure:6999: checking for fstat64 in <sys/stat.h>" >&5
   cat > conftest.$ac_ext <<EOF
-#line 6950 "configure"
+#line 7001 "configure"
 #include "confdefs.h"
 
 #if defined(HAVE_UNISTD_H)
@@ -6958,7 +7009,7 @@ int main() {
 struct stat64 st64; exit(fstat64(0,&st64));
 ; return 0; }
 EOF
-if { (eval echo configure:6962: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:7013: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   ac_cv_func_fstat64=yes
 else
@@ -6978,7 +7029,7 @@ fi
 #####################################
 # we might need the resolv library on some systems
 echo $ac_n "checking for dn_expand in -lresolv""... $ac_c" 1>&6
-echo "configure:6982: checking for dn_expand in -lresolv" >&5
+echo "configure:7033: checking for dn_expand in -lresolv" >&5
 ac_lib_var=`echo resolv'_'dn_expand | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -6986,7 +7037,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lresolv  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 6990 "configure"
+#line 7041 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -6997,7 +7048,7 @@ int main() {
 dn_expand()
 ; return 0; }
 EOF
-if { (eval echo configure:7001: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:7052: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -7035,12 +7086,12 @@ case "$LIBS" in
   *-lsecurity*) for ac_func in putprpwnam
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:7039: checking for $ac_func" >&5
+echo "configure:7090: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 7044 "configure"
+#line 7095 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -7063,7 +7114,7 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:7067: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:7118: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -7088,7 +7139,7 @@ fi
 done
  ;;
   *) echo $ac_n "checking for putprpwnam in -lsecurity""... $ac_c" 1>&6
-echo "configure:7092: checking for putprpwnam in -lsecurity" >&5
+echo "configure:7143: checking for putprpwnam in -lsecurity" >&5
 ac_lib_var=`echo security'_'putprpwnam | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -7096,7 +7147,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lsecurity  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 7100 "configure"
+#line 7151 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -7107,7 +7158,7 @@ int main() {
 putprpwnam()
 ; return 0; }
 EOF
-if { (eval echo configure:7111: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:7162: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -7137,12 +7188,12 @@ fi
      for ac_func in putprpwnam
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:7141: checking for $ac_func" >&5
+echo "configure:7192: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 7146 "configure"
+#line 7197 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -7165,7 +7216,7 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:7169: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:7220: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -7196,12 +7247,12 @@ case "$LIBS" in
   *-lsec*) for ac_func in putprpwnam
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:7200: checking for $ac_func" >&5
+echo "configure:7251: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 7205 "configure"
+#line 7256 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -7224,7 +7275,7 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:7228: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:7279: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -7249,7 +7300,7 @@ fi
 done
  ;;
   *) echo $ac_n "checking for putprpwnam in -lsec""... $ac_c" 1>&6
-echo "configure:7253: checking for putprpwnam in -lsec" >&5
+echo "configure:7304: checking for putprpwnam in -lsec" >&5
 ac_lib_var=`echo sec'_'putprpwnam | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -7257,7 +7308,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lsec  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 7261 "configure"
+#line 7312 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -7268,7 +7319,7 @@ int main() {
 putprpwnam()
 ; return 0; }
 EOF
-if { (eval echo configure:7272: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:7323: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -7298,12 +7349,12 @@ fi
      for ac_func in putprpwnam
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:7302: checking for $ac_func" >&5
+echo "configure:7353: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 7307 "configure"
+#line 7358 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -7326,7 +7377,7 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:7330: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:7381: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -7358,12 +7409,12 @@ case "$LIBS" in
   *-lsecurity*) for ac_func in set_auth_parameters
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:7362: checking for $ac_func" >&5
+echo "configure:7413: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 7367 "configure"
+#line 7418 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -7386,7 +7437,7 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:7390: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:7441: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -7411,7 +7462,7 @@ fi
 done
  ;;
   *) echo $ac_n "checking for set_auth_parameters in -lsecurity""... $ac_c" 1>&6
-echo "configure:7415: checking for set_auth_parameters in -lsecurity" >&5
+echo "configure:7466: checking for set_auth_parameters in -lsecurity" >&5
 ac_lib_var=`echo security'_'set_auth_parameters | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -7419,7 +7470,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lsecurity  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 7423 "configure"
+#line 7474 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -7430,7 +7481,7 @@ int main() {
 set_auth_parameters()
 ; return 0; }
 EOF
-if { (eval echo configure:7434: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:7485: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -7460,12 +7511,12 @@ fi
      for ac_func in set_auth_parameters
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:7464: checking for $ac_func" >&5
+echo "configure:7515: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 7469 "configure"
+#line 7520 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -7488,7 +7539,7 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:7492: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:7543: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -7519,12 +7570,12 @@ case "$LIBS" in
   *-lsec*) for ac_func in set_auth_parameters
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:7523: checking for $ac_func" >&5
+echo "configure:7574: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 7528 "configure"
+#line 7579 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -7547,7 +7598,7 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:7551: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:7602: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -7572,7 +7623,7 @@ fi
 done
  ;;
   *) echo $ac_n "checking for set_auth_parameters in -lsec""... $ac_c" 1>&6
-echo "configure:7576: checking for set_auth_parameters in -lsec" >&5
+echo "configure:7627: checking for set_auth_parameters in -lsec" >&5
 ac_lib_var=`echo sec'_'set_auth_parameters | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -7580,7 +7631,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lsec  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 7584 "configure"
+#line 7635 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -7591,7 +7642,7 @@ int main() {
 set_auth_parameters()
 ; return 0; }
 EOF
-if { (eval echo configure:7595: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:7646: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -7621,12 +7672,12 @@ fi
      for ac_func in set_auth_parameters
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:7625: checking for $ac_func" >&5
+echo "configure:7676: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 7630 "configure"
+#line 7681 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -7649,7 +7700,7 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:7653: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:7704: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -7682,12 +7733,12 @@ case "$LIBS" in
   *-lgen*) for ac_func in getspnam
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:7686: checking for $ac_func" >&5
+echo "configure:7737: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 7691 "configure"
+#line 7742 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -7710,7 +7761,7 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:7714: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:7765: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -7735,7 +7786,7 @@ fi
 done
  ;;
   *) echo $ac_n "checking for getspnam in -lgen""... $ac_c" 1>&6
-echo "configure:7739: checking for getspnam in -lgen" >&5
+echo "configure:7790: checking for getspnam in -lgen" >&5
 ac_lib_var=`echo gen'_'getspnam | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -7743,7 +7794,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lgen  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 7747 "configure"
+#line 7798 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -7754,7 +7805,7 @@ int main() {
 getspnam()
 ; return 0; }
 EOF
-if { (eval echo configure:7758: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:7809: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -7784,12 +7835,12 @@ fi
      for ac_func in getspnam
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:7788: checking for $ac_func" >&5
+echo "configure:7839: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 7793 "configure"
+#line 7844 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -7812,7 +7863,7 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:7816: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:7867: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -7844,12 +7895,12 @@ case "$LIBS" in
   *-lsecurity*) for ac_func in getspnam
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:7848: checking for $ac_func" >&5
+echo "configure:7899: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 7853 "configure"
+#line 7904 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -7872,7 +7923,7 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:7876: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:7927: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -7897,7 +7948,7 @@ fi
 done
  ;;
   *) echo $ac_n "checking for getspnam in -lsecurity""... $ac_c" 1>&6
-echo "configure:7901: checking for getspnam in -lsecurity" >&5
+echo "configure:7952: checking for getspnam in -lsecurity" >&5
 ac_lib_var=`echo security'_'getspnam | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -7905,7 +7956,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lsecurity  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 7909 "configure"
+#line 7960 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -7916,7 +7967,7 @@ int main() {
 getspnam()
 ; return 0; }
 EOF
-if { (eval echo configure:7920: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:7971: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -7946,12 +7997,12 @@ fi
      for ac_func in getspnam
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:7950: checking for $ac_func" >&5
+echo "configure:8001: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 7955 "configure"
+#line 8006 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -7974,7 +8025,7 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:7978: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:8029: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -8005,12 +8056,12 @@ case "$LIBS" in
   *-lsec*) for ac_func in getspnam
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:8009: checking for $ac_func" >&5
+echo "configure:8060: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 8014 "configure"
+#line 8065 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -8033,7 +8084,7 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:8037: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:8088: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -8058,7 +8109,7 @@ fi
 done
  ;;
   *) echo $ac_n "checking for getspnam in -lsec""... $ac_c" 1>&6
-echo "configure:8062: checking for getspnam in -lsec" >&5
+echo "configure:8113: checking for getspnam in -lsec" >&5
 ac_lib_var=`echo sec'_'getspnam | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -8066,7 +8117,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lsec  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 8070 "configure"
+#line 8121 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -8077,7 +8128,7 @@ int main() {
 getspnam()
 ; return 0; }
 EOF
-if { (eval echo configure:8081: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:8132: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -8107,12 +8158,12 @@ fi
      for ac_func in getspnam
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:8111: checking for $ac_func" >&5
+echo "configure:8162: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 8116 "configure"
+#line 8167 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -8135,7 +8186,7 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:8139: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:8190: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -8167,12 +8218,12 @@ case "$LIBS" in
   *-lsecurity*) for ac_func in bigcrypt
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:8171: checking for $ac_func" >&5
+echo "configure:8222: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 8176 "configure"
+#line 8227 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -8195,7 +8246,7 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:8199: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:8250: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -8220,7 +8271,7 @@ fi
 done
  ;;
   *) echo $ac_n "checking for bigcrypt in -lsecurity""... $ac_c" 1>&6
-echo "configure:8224: checking for bigcrypt in -lsecurity" >&5
+echo "configure:8275: checking for bigcrypt in -lsecurity" >&5
 ac_lib_var=`echo security'_'bigcrypt | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -8228,7 +8279,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lsecurity  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 8232 "configure"
+#line 8283 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -8239,7 +8290,7 @@ int main() {
 bigcrypt()
 ; return 0; }
 EOF
-if { (eval echo configure:8243: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:8294: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -8269,12 +8320,12 @@ fi
      for ac_func in bigcrypt
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:8273: checking for $ac_func" >&5
+echo "configure:8324: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 8278 "configure"
+#line 8329 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -8297,7 +8348,7 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:8301: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:8352: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -8328,12 +8379,12 @@ case "$LIBS" in
   *-lsec*) for ac_func in bigcrypt
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:8332: checking for $ac_func" >&5
+echo "configure:8383: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 8337 "configure"
+#line 8388 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -8356,7 +8407,7 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:8360: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:8411: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -8381,7 +8432,7 @@ fi
 done
  ;;
   *) echo $ac_n "checking for bigcrypt in -lsec""... $ac_c" 1>&6
-echo "configure:8385: checking for bigcrypt in -lsec" >&5
+echo "configure:8436: checking for bigcrypt in -lsec" >&5
 ac_lib_var=`echo sec'_'bigcrypt | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -8389,7 +8440,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lsec  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 8393 "configure"
+#line 8444 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -8400,7 +8451,7 @@ int main() {
 bigcrypt()
 ; return 0; }
 EOF
-if { (eval echo configure:8404: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:8455: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -8430,12 +8481,12 @@ fi
      for ac_func in bigcrypt
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:8434: checking for $ac_func" >&5
+echo "configure:8485: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 8439 "configure"
+#line 8490 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -8458,7 +8509,7 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:8462: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:8513: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -8490,12 +8541,12 @@ case "$LIBS" in
   *-lsecurity*) for ac_func in getprpwnam
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:8494: checking for $ac_func" >&5
+echo "configure:8545: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 8499 "configure"
+#line 8550 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -8518,7 +8569,7 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:8522: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:8573: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -8543,7 +8594,7 @@ fi
 done
  ;;
   *) echo $ac_n "checking for getprpwnam in -lsecurity""... $ac_c" 1>&6
-echo "configure:8547: checking for getprpwnam in -lsecurity" >&5
+echo "configure:8598: checking for getprpwnam in -lsecurity" >&5
 ac_lib_var=`echo security'_'getprpwnam | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -8551,7 +8602,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lsecurity  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 8555 "configure"
+#line 8606 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -8562,7 +8613,7 @@ int main() {
 getprpwnam()
 ; return 0; }
 EOF
-if { (eval echo configure:8566: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:8617: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -8592,12 +8643,12 @@ fi
      for ac_func in getprpwnam
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:8596: checking for $ac_func" >&5
+echo "configure:8647: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 8601 "configure"
+#line 8652 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -8620,7 +8671,7 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:8624: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:8675: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -8651,12 +8702,12 @@ case "$LIBS" in
   *-lsec*) for ac_func in getprpwnam
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:8655: checking for $ac_func" >&5
+echo "configure:8706: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 8660 "configure"
+#line 8711 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -8679,7 +8730,7 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:8683: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:8734: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -8704,7 +8755,7 @@ fi
 done
  ;;
   *) echo $ac_n "checking for getprpwnam in -lsec""... $ac_c" 1>&6
-echo "configure:8708: checking for getprpwnam in -lsec" >&5
+echo "configure:8759: checking for getprpwnam in -lsec" >&5
 ac_lib_var=`echo sec'_'getprpwnam | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -8712,7 +8763,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lsec  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 8716 "configure"
+#line 8767 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -8723,7 +8774,7 @@ int main() {
 getprpwnam()
 ; return 0; }
 EOF
-if { (eval echo configure:8727: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:8778: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -8753,12 +8804,12 @@ fi
      for ac_func in getprpwnam
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:8757: checking for $ac_func" >&5
+echo "configure:8808: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 8762 "configure"
+#line 8813 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -8781,7 +8832,7 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:8785: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:8836: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -8825,7 +8876,7 @@ SHLIBEXT="so"
 # Assume non-shared by default and override below
 BLDSHARED="false"
 echo $ac_n "checking ability to build shared libraries""... $ac_c" 1>&6
-echo "configure:8829: checking ability to build shared libraries" >&5
+echo "configure:8880: checking ability to build shared libraries" >&5
 
 # and these are for particular systems
 case "$host_os" in
@@ -8877,7 +8928,17 @@ EOF
                        SONAMEFLAG="-Wl,-h,"
                        PICFLAG="-KPIC"   # Is this correct for SunOS
                ;;
-               *bsd*)  BLDSHARED="true"
+               *freebsd*)  BLDSHARED="true"
+                       LDSHFLAGS="-shared"
+                       DYNEXP="-Wl,--export-dynamic"
+                       SONAMEFLAG="-Wl,-soname,"
+                       PICFLAG="-fPIC -DPIC"
+                       cat >> confdefs.h <<\EOF
+#define STAT_ST_BLOCKSIZE 512
+EOF
+
+               ;;
+               *openbsd*)  BLDSHARED="true"
                        LDSHFLAGS="-shared"
                        DYNEXP="-Wl,-Bdynamic"
                        SONAMEFLAG="-Wl,-soname,"
@@ -8920,12 +8981,10 @@ EOF
                        BLDSHARED="true"
                        LDSHFLAGS="-Wl,-bexpall,-bM:SRE,-bnoentry"
                        DYNEXP="-Wl,-brtl,-bexpall"
-                       if test "${GCC}" = "yes"; then
-                               PICFLAG="-O2"
-                       else
-                       PICFLAG="-O2 -qmaxmem=6000"
+                       PICFLAG="-O2"
+                       if test "${GCC}" != "yes"; then
                                ## for funky AIX compiler using strncpy()
-                               CFLAGS="$CFLAGS -D_LINUX_SOURCE_COMPAT"
+                               CFLAGS="$CFLAGS -D_LINUX_SOURCE_COMPAT -qmaxmem=32000"
                        fi
 
                        cat >> confdefs.h <<\EOF
@@ -8985,7 +9044,7 @@ EOF
                *dgux*) # Extract the first word of "groff", so it can be a program name with args.
 set dummy groff; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:8989: checking for $ac_word" >&5
+echo "configure:9048: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_ROFF'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -9042,17 +9101,17 @@ esac
 
 echo "$ac_t""$BLDSHARED" 1>&6
 echo $ac_n "checking linker flags for shared libraries""... $ac_c" 1>&6
-echo "configure:9046: checking linker flags for shared libraries" >&5
+echo "configure:9105: checking linker flags for shared libraries" >&5
 echo "$ac_t""$LDSHFLAGS" 1>&6
 echo $ac_n "checking compiler flags for position-independent code""... $ac_c" 1>&6
-echo "configure:9049: checking compiler flags for position-independent code" >&5
+echo "configure:9108: checking compiler flags for position-independent code" >&5
 echo "$ac_t""$PICFLAGS" 1>&6
 
 #######################################################
 # test whether building a shared library actually works
 if test $BLDSHARED = true; then
 echo $ac_n "checking whether building shared libraries actually works""... $ac_c" 1>&6
-echo "configure:9056: checking whether building shared libraries actually works" >&5
+echo "configure:9115: checking whether building shared libraries actually works" >&5
 if eval "test \"`echo '$''{'ac_cv_shlib_works'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -9083,7 +9142,7 @@ fi
 ################
 
 echo $ac_n "checking for long long""... $ac_c" 1>&6
-echo "configure:9087: checking for long long" >&5
+echo "configure:9146: checking for long long" >&5
 if eval "test \"`echo '$''{'samba_cv_have_longlong'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -9092,12 +9151,12 @@ if test "$cross_compiling" = yes; then
   samba_cv_have_longlong=cross
 else
   cat > conftest.$ac_ext <<EOF
-#line 9096 "configure"
+#line 9155 "configure"
 #include "confdefs.h"
 #include <stdio.h>
 main() { long long x = 1000000; x *= x; exit(((x/1000000) == 1000000)? 0: 1); }
 EOF
-if { (eval echo configure:9101: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:9160: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   samba_cv_have_longlong=yes
 else
@@ -9124,20 +9183,20 @@ fi
 # AIX needs this.
 
 echo $ac_n "checking for LL suffix on long long integers""... $ac_c" 1>&6
-echo "configure:9128: checking for LL suffix on long long integers" >&5
+echo "configure:9187: checking for LL suffix on long long integers" >&5
 if eval "test \"`echo '$''{'samba_cv_compiler_supports_ll'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   
     cat > conftest.$ac_ext <<EOF
-#line 9134 "configure"
+#line 9193 "configure"
 #include "confdefs.h"
 #include <stdio.h>
 int main() {
 long long i = 0x8000000000LL
 ; return 0; }
 EOF
-if { (eval echo configure:9141: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:9200: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   samba_cv_compiler_supports_ll=yes
 else
@@ -9159,7 +9218,7 @@ fi
 
   
 echo $ac_n "checking for 64 bit off_t""... $ac_c" 1>&6
-echo "configure:9163: checking for 64 bit off_t" >&5
+echo "configure:9222: checking for 64 bit off_t" >&5
 if eval "test \"`echo '$''{'samba_cv_SIZEOF_OFF_T'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -9168,13 +9227,13 @@ if test "$cross_compiling" = yes; then
   samba_cv_SIZEOF_OFF_T=cross
 else
   cat > conftest.$ac_ext <<EOF
-#line 9172 "configure"
+#line 9231 "configure"
 #include "confdefs.h"
 #include <stdio.h>
 #include <sys/stat.h>
 main() { exit((sizeof(off_t) == 8) ? 0 : 1); }
 EOF
-if { (eval echo configure:9178: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:9237: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   samba_cv_SIZEOF_OFF_T=yes
 else
@@ -9197,7 +9256,7 @@ EOF
 fi
 
 echo $ac_n "checking for off64_t""... $ac_c" 1>&6
-echo "configure:9201: checking for off64_t" >&5
+echo "configure:9260: checking for off64_t" >&5
 if eval "test \"`echo '$''{'samba_cv_HAVE_OFF64_T'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -9206,7 +9265,7 @@ if test "$cross_compiling" = yes; then
   samba_cv_HAVE_OFF64_T=cross
 else
   cat > conftest.$ac_ext <<EOF
-#line 9210 "configure"
+#line 9269 "configure"
 #include "confdefs.h"
 
 #if defined(HAVE_UNISTD_H)
@@ -9216,7 +9275,7 @@ else
 #include <sys/stat.h>
 main() { struct stat64 st; off64_t s; if (sizeof(off_t) == sizeof(off64_t)) exit(1); exit((lstat64("/dev/null", &st)==0)?0:1); }
 EOF
-if { (eval echo configure:9220: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:9279: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   samba_cv_HAVE_OFF64_T=yes
 else
@@ -9239,7 +9298,7 @@ EOF
 fi
 
 echo $ac_n "checking for 64 bit ino_t""... $ac_c" 1>&6
-echo "configure:9243: checking for 64 bit ino_t" >&5
+echo "configure:9302: checking for 64 bit ino_t" >&5
 if eval "test \"`echo '$''{'samba_cv_SIZEOF_INO_T'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -9248,13 +9307,13 @@ if test "$cross_compiling" = yes; then
   samba_cv_SIZEOF_INO_T=cross
 else
   cat > conftest.$ac_ext <<EOF
-#line 9252 "configure"
+#line 9311 "configure"
 #include "confdefs.h"
 #include <stdio.h>
 #include <sys/stat.h>
 main() { exit((sizeof(ino_t) == 8) ? 0 : 1); }
 EOF
-if { (eval echo configure:9258: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:9317: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   samba_cv_SIZEOF_INO_T=yes
 else
@@ -9277,7 +9336,7 @@ EOF
 fi
 
 echo $ac_n "checking for ino64_t""... $ac_c" 1>&6
-echo "configure:9281: checking for ino64_t" >&5
+echo "configure:9340: checking for ino64_t" >&5
 if eval "test \"`echo '$''{'samba_cv_HAVE_INO64_T'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -9286,7 +9345,7 @@ if test "$cross_compiling" = yes; then
   samba_cv_HAVE_INO64_T=cross
 else
   cat > conftest.$ac_ext <<EOF
-#line 9290 "configure"
+#line 9349 "configure"
 #include "confdefs.h"
 
 #if defined(HAVE_UNISTD_H)
@@ -9296,7 +9355,7 @@ else
 #include <sys/stat.h>
 main() { struct stat64 st; ino64_t s; if (sizeof(ino_t) == sizeof(ino64_t)) exit(1); exit((lstat64("/dev/null", &st)==0)?0:1); }
 EOF
-if { (eval echo configure:9300: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:9359: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   samba_cv_HAVE_INO64_T=yes
 else
@@ -9319,7 +9378,7 @@ EOF
 fi
 
 echo $ac_n "checking for dev64_t""... $ac_c" 1>&6
-echo "configure:9323: checking for dev64_t" >&5
+echo "configure:9382: checking for dev64_t" >&5
 if eval "test \"`echo '$''{'samba_cv_HAVE_DEV64_T'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -9328,7 +9387,7 @@ if test "$cross_compiling" = yes; then
   samba_cv_HAVE_DEV64_T=cross
 else
   cat > conftest.$ac_ext <<EOF
-#line 9332 "configure"
+#line 9391 "configure"
 #include "confdefs.h"
 
 #if defined(HAVE_UNISTD_H)
@@ -9338,7 +9397,7 @@ else
 #include <sys/stat.h>
 main() { struct stat64 st; dev64_t s; if (sizeof(dev_t) == sizeof(dev64_t)) exit(1); exit((lstat64("/dev/null", &st)==0)?0:1); }
 EOF
-if { (eval echo configure:9342: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:9401: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   samba_cv_HAVE_DEV64_T=yes
 else
@@ -9361,13 +9420,13 @@ EOF
 fi
 
 echo $ac_n "checking for struct dirent64""... $ac_c" 1>&6
-echo "configure:9365: checking for struct dirent64" >&5
+echo "configure:9424: checking for struct dirent64" >&5
 if eval "test \"`echo '$''{'samba_cv_HAVE_STRUCT_DIRENT64'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   
 cat > conftest.$ac_ext <<EOF
-#line 9371 "configure"
+#line 9430 "configure"
 #include "confdefs.h"
 
 #if defined(HAVE_UNISTD_H)
@@ -9379,7 +9438,7 @@ int main() {
 struct dirent64 de;
 ; return 0; }
 EOF
-if { (eval echo configure:9383: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:9442: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   samba_cv_HAVE_STRUCT_DIRENT64=yes
 else
@@ -9400,7 +9459,7 @@ EOF
 fi
 
 echo $ac_n "checking for major macro""... $ac_c" 1>&6
-echo "configure:9404: checking for major macro" >&5
+echo "configure:9463: checking for major macro" >&5
 if eval "test \"`echo '$''{'samba_cv_HAVE_DEVICE_MAJOR_FN'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -9409,7 +9468,7 @@ if test "$cross_compiling" = yes; then
   samba_cv_HAVE_DEVICE_MAJOR_FN=cross
 else
   cat > conftest.$ac_ext <<EOF
-#line 9413 "configure"
+#line 9472 "configure"
 #include "confdefs.h"
 
 #if defined(HAVE_UNISTD_H)
@@ -9418,7 +9477,7 @@ else
 #include <sys/types.h>
 main() { dev_t dev; int i = major(dev); return 0; }
 EOF
-if { (eval echo configure:9422: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:9481: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   samba_cv_HAVE_DEVICE_MAJOR_FN=yes
 else
@@ -9441,7 +9500,7 @@ EOF
 fi
 
 echo $ac_n "checking for minor macro""... $ac_c" 1>&6
-echo "configure:9445: checking for minor macro" >&5
+echo "configure:9504: checking for minor macro" >&5
 if eval "test \"`echo '$''{'samba_cv_HAVE_DEVICE_MINOR_FN'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -9450,7 +9509,7 @@ if test "$cross_compiling" = yes; then
   samba_cv_HAVE_DEVICE_MINOR_FN=cross
 else
   cat > conftest.$ac_ext <<EOF
-#line 9454 "configure"
+#line 9513 "configure"
 #include "confdefs.h"
 
 #if defined(HAVE_UNISTD_H)
@@ -9459,7 +9518,7 @@ else
 #include <sys/types.h>
 main() { dev_t dev; int i = minor(dev); return 0; }
 EOF
-if { (eval echo configure:9463: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:9522: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   samba_cv_HAVE_DEVICE_MINOR_FN=yes
 else
@@ -9482,7 +9541,7 @@ EOF
 fi
 
 echo $ac_n "checking for unsigned char""... $ac_c" 1>&6
-echo "configure:9486: checking for unsigned char" >&5
+echo "configure:9545: checking for unsigned char" >&5
 if eval "test \"`echo '$''{'samba_cv_HAVE_UNSIGNED_CHAR'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -9491,12 +9550,12 @@ if test "$cross_compiling" = yes; then
   samba_cv_HAVE_UNSIGNED_CHAR=cross
 else
   cat > conftest.$ac_ext <<EOF
-#line 9495 "configure"
+#line 9554 "configure"
 #include "confdefs.h"
 #include <stdio.h>
 main() { char c; c=250; exit((c > 0)?0:1); }
 EOF
-if { (eval echo configure:9500: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:9559: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   samba_cv_HAVE_UNSIGNED_CHAR=yes
 else
@@ -9519,13 +9578,13 @@ EOF
 fi
 
 echo $ac_n "checking for sin_len in sock""... $ac_c" 1>&6
-echo "configure:9523: checking for sin_len in sock" >&5
+echo "configure:9582: checking for sin_len in sock" >&5
 if eval "test \"`echo '$''{'samba_cv_HAVE_SOCK_SIN_LEN'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   
 cat > conftest.$ac_ext <<EOF
-#line 9529 "configure"
+#line 9588 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <sys/socket.h>
@@ -9534,7 +9593,7 @@ int main() {
 struct sockaddr_in sock; sock.sin_len = sizeof(sock);
 ; return 0; }
 EOF
-if { (eval echo configure:9538: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:9597: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   samba_cv_HAVE_SOCK_SIN_LEN=yes
 else
@@ -9555,13 +9614,13 @@ EOF
 fi
 
 echo $ac_n "checking whether seekdir returns void""... $ac_c" 1>&6
-echo "configure:9559: checking whether seekdir returns void" >&5
+echo "configure:9618: checking whether seekdir returns void" >&5
 if eval "test \"`echo '$''{'samba_cv_SEEKDIR_RETURNS_VOID'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   
 cat > conftest.$ac_ext <<EOF
-#line 9565 "configure"
+#line 9624 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <dirent.h>
@@ -9570,7 +9629,7 @@ int main() {
 return 0;
 ; return 0; }
 EOF
-if { (eval echo configure:9574: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:9633: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   samba_cv_SEEKDIR_RETURNS_VOID=yes
 else
@@ -9591,20 +9650,20 @@ EOF
 fi
 
 echo $ac_n "checking for __FILE__ macro""... $ac_c" 1>&6
-echo "configure:9595: checking for __FILE__ macro" >&5
+echo "configure:9654: checking for __FILE__ macro" >&5
 if eval "test \"`echo '$''{'samba_cv_HAVE_FILE_MACRO'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   
 cat > conftest.$ac_ext <<EOF
-#line 9601 "configure"
+#line 9660 "configure"
 #include "confdefs.h"
 #include <stdio.h>
 int main() {
 printf("%s\n", __FILE__);
 ; return 0; }
 EOF
-if { (eval echo configure:9608: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:9667: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   samba_cv_HAVE_FILE_MACRO=yes
 else
@@ -9625,20 +9684,20 @@ EOF
 fi
 
 echo $ac_n "checking for __FUNCTION__ macro""... $ac_c" 1>&6
-echo "configure:9629: checking for __FUNCTION__ macro" >&5
+echo "configure:9688: checking for __FUNCTION__ macro" >&5
 if eval "test \"`echo '$''{'samba_cv_HAVE_FUNCTION_MACRO'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   
 cat > conftest.$ac_ext <<EOF
-#line 9635 "configure"
+#line 9694 "configure"
 #include "confdefs.h"
 #include <stdio.h>
 int main() {
 printf("%s\n", __FUNCTION__);
 ; return 0; }
 EOF
-if { (eval echo configure:9642: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:9701: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   samba_cv_HAVE_FUNCTION_MACRO=yes
 else
@@ -9659,7 +9718,7 @@ EOF
 fi
 
 echo $ac_n "checking if gettimeofday takes tz argument""... $ac_c" 1>&6
-echo "configure:9663: checking if gettimeofday takes tz argument" >&5
+echo "configure:9722: checking if gettimeofday takes tz argument" >&5
 if eval "test \"`echo '$''{'samba_cv_HAVE_GETTIMEOFDAY_TZ'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -9668,14 +9727,14 @@ if test "$cross_compiling" = yes; then
   samba_cv_HAVE_GETTIMEOFDAY_TZ=cross
 else
   cat > conftest.$ac_ext <<EOF
-#line 9672 "configure"
+#line 9731 "configure"
 #include "confdefs.h"
 
 #include <sys/time.h>
 #include <unistd.h>
 main() { struct timeval tv; exit(gettimeofday(&tv, NULL));}
 EOF
-if { (eval echo configure:9679: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:9738: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   samba_cv_HAVE_GETTIMEOFDAY_TZ=yes
 else
@@ -9698,13 +9757,13 @@ EOF
 fi
 
 echo $ac_n "checking for __va_copy""... $ac_c" 1>&6
-echo "configure:9702: checking for __va_copy" >&5
+echo "configure:9761: checking for __va_copy" >&5
 if eval "test \"`echo '$''{'samba_cv_HAVE_VA_COPY'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   
 cat > conftest.$ac_ext <<EOF
-#line 9708 "configure"
+#line 9767 "configure"
 #include "confdefs.h"
 #include <stdarg.h>
 va_list ap1,ap2;
@@ -9712,7 +9771,7 @@ int main() {
 __va_copy(ap1,ap2);
 ; return 0; }
 EOF
-if { (eval echo configure:9716: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:9775: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   samba_cv_HAVE_VA_COPY=yes
 else
@@ -9733,7 +9792,7 @@ EOF
 fi
 
 echo $ac_n "checking for C99 vsnprintf""... $ac_c" 1>&6
-echo "configure:9737: checking for C99 vsnprintf" >&5
+echo "configure:9796: checking for C99 vsnprintf" >&5
 if eval "test \"`echo '$''{'samba_cv_HAVE_C99_VSNPRINTF'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -9742,7 +9801,7 @@ if test "$cross_compiling" = yes; then
   samba_cv_HAVE_C99_VSNPRINTF=cross
 else
   cat > conftest.$ac_ext <<EOF
-#line 9746 "configure"
+#line 9805 "configure"
 #include "confdefs.h"
 
 #include <sys/types.h>
@@ -9769,7 +9828,7 @@ void foo(const char *format, ...) {
 main() { foo("hello"); }
 
 EOF
-if { (eval echo configure:9773: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:9832: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   samba_cv_HAVE_C99_VSNPRINTF=yes
 else
@@ -9792,7 +9851,7 @@ EOF
 fi
 
 echo $ac_n "checking for broken readdir""... $ac_c" 1>&6
-echo "configure:9796: checking for broken readdir" >&5
+echo "configure:9855: checking for broken readdir" >&5
 if eval "test \"`echo '$''{'samba_cv_HAVE_BROKEN_READDIR'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -9801,7 +9860,7 @@ if test "$cross_compiling" = yes; then
   samba_cv_HAVE_BROKEN_READDIR=cross
 else
   cat > conftest.$ac_ext <<EOF
-#line 9805 "configure"
+#line 9864 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <dirent.h>
@@ -9809,7 +9868,7 @@ main() { struct dirent *di; DIR *d = opendir("."); di = readdir(d);
 if (di && di->d_name[-2] == '.' && di->d_name[-1] == 0 &&
 di->d_name[0] == 0) exit(0); exit(1);} 
 EOF
-if { (eval echo configure:9813: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:9872: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   samba_cv_HAVE_BROKEN_READDIR=yes
 else
@@ -9832,13 +9891,13 @@ EOF
 fi
 
 echo $ac_n "checking for utimbuf""... $ac_c" 1>&6
-echo "configure:9836: checking for utimbuf" >&5
+echo "configure:9895: checking for utimbuf" >&5
 if eval "test \"`echo '$''{'samba_cv_HAVE_UTIMBUF'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   
 cat > conftest.$ac_ext <<EOF
-#line 9842 "configure"
+#line 9901 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <utime.h>
@@ -9846,7 +9905,7 @@ int main() {
 struct utimbuf tbuf;  tbuf.actime = 0; tbuf.modtime = 1; exit(utime("foo.c",&tbuf));
 ; return 0; }
 EOF
-if { (eval echo configure:9850: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:9909: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   samba_cv_HAVE_UTIMBUF=yes
 else
@@ -9870,12 +9929,12 @@ fi
 for ac_func in pututline pututxline updwtmp updwtmpx getutmpx
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:9874: checking for $ac_func" >&5
+echo "configure:9933: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 9879 "configure"
+#line 9938 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -9898,7 +9957,7 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:9902: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:9961: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -9924,13 +9983,13 @@ done
 
 
 echo $ac_n "checking for ut_name in utmp""... $ac_c" 1>&6
-echo "configure:9928: checking for ut_name in utmp" >&5
+echo "configure:9987: checking for ut_name in utmp" >&5
 if eval "test \"`echo '$''{'samba_cv_HAVE_UT_UT_NAME'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   
 cat > conftest.$ac_ext <<EOF
-#line 9934 "configure"
+#line 9993 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <utmp.h>
@@ -9938,7 +9997,7 @@ int main() {
 struct utmp ut;  ut.ut_name[0] = 'a';
 ; return 0; }
 EOF
-if { (eval echo configure:9942: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:10001: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   samba_cv_HAVE_UT_UT_NAME=yes
 else
@@ -9959,13 +10018,13 @@ EOF
 fi 
 
 echo $ac_n "checking for ut_user in utmp""... $ac_c" 1>&6
-echo "configure:9963: checking for ut_user in utmp" >&5
+echo "configure:10022: checking for ut_user in utmp" >&5
 if eval "test \"`echo '$''{'samba_cv_HAVE_UT_UT_USER'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   
 cat > conftest.$ac_ext <<EOF
-#line 9969 "configure"
+#line 10028 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <utmp.h>
@@ -9973,7 +10032,7 @@ int main() {
 struct utmp ut;  ut.ut_user[0] = 'a';
 ; return 0; }
 EOF
-if { (eval echo configure:9977: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:10036: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   samba_cv_HAVE_UT_UT_USER=yes
 else
@@ -9994,13 +10053,13 @@ EOF
 fi 
 
 echo $ac_n "checking for ut_id in utmp""... $ac_c" 1>&6
-echo "configure:9998: checking for ut_id in utmp" >&5
+echo "configure:10057: checking for ut_id in utmp" >&5
 if eval "test \"`echo '$''{'samba_cv_HAVE_UT_UT_ID'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   
 cat > conftest.$ac_ext <<EOF
-#line 10004 "configure"
+#line 10063 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <utmp.h>
@@ -10008,7 +10067,7 @@ int main() {
 struct utmp ut;  ut.ut_id[0] = 'a';
 ; return 0; }
 EOF
-if { (eval echo configure:10012: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:10071: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   samba_cv_HAVE_UT_UT_ID=yes
 else
@@ -10029,13 +10088,13 @@ EOF
 fi 
 
 echo $ac_n "checking for ut_host in utmp""... $ac_c" 1>&6
-echo "configure:10033: checking for ut_host in utmp" >&5
+echo "configure:10092: checking for ut_host in utmp" >&5
 if eval "test \"`echo '$''{'samba_cv_HAVE_UT_UT_HOST'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   
 cat > conftest.$ac_ext <<EOF
-#line 10039 "configure"
+#line 10098 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <utmp.h>
@@ -10043,7 +10102,7 @@ int main() {
 struct utmp ut;  ut.ut_host[0] = 'a';
 ; return 0; }
 EOF
-if { (eval echo configure:10047: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:10106: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   samba_cv_HAVE_UT_UT_HOST=yes
 else
@@ -10064,13 +10123,13 @@ EOF
 fi 
 
 echo $ac_n "checking for ut_time in utmp""... $ac_c" 1>&6
-echo "configure:10068: checking for ut_time in utmp" >&5
+echo "configure:10127: checking for ut_time in utmp" >&5
 if eval "test \"`echo '$''{'samba_cv_HAVE_UT_UT_TIME'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   
 cat > conftest.$ac_ext <<EOF
-#line 10074 "configure"
+#line 10133 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <utmp.h>
@@ -10078,7 +10137,7 @@ int main() {
 struct utmp ut;  time_t t; ut.ut_time = t;
 ; return 0; }
 EOF
-if { (eval echo configure:10082: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:10141: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   samba_cv_HAVE_UT_UT_TIME=yes
 else
@@ -10099,13 +10158,13 @@ EOF
 fi 
 
 echo $ac_n "checking for ut_tv in utmp""... $ac_c" 1>&6
-echo "configure:10103: checking for ut_tv in utmp" >&5
+echo "configure:10162: checking for ut_tv in utmp" >&5
 if eval "test \"`echo '$''{'samba_cv_HAVE_UT_UT_TV'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   
 cat > conftest.$ac_ext <<EOF
-#line 10109 "configure"
+#line 10168 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <utmp.h>
@@ -10113,7 +10172,7 @@ int main() {
 struct utmp ut;  struct timeval tv; ut.ut_tv = tv;
 ; return 0; }
 EOF
-if { (eval echo configure:10117: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:10176: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   samba_cv_HAVE_UT_UT_TV=yes
 else
@@ -10134,13 +10193,13 @@ EOF
 fi 
 
 echo $ac_n "checking for ut_type in utmp""... $ac_c" 1>&6
-echo "configure:10138: checking for ut_type in utmp" >&5
+echo "configure:10197: checking for ut_type in utmp" >&5
 if eval "test \"`echo '$''{'samba_cv_HAVE_UT_UT_TYPE'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   
 cat > conftest.$ac_ext <<EOF
-#line 10144 "configure"
+#line 10203 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <utmp.h>
@@ -10148,7 +10207,7 @@ int main() {
 struct utmp ut;  ut.ut_type = 0;
 ; return 0; }
 EOF
-if { (eval echo configure:10152: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:10211: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   samba_cv_HAVE_UT_UT_TYPE=yes
 else
@@ -10169,13 +10228,13 @@ EOF
 fi 
 
 echo $ac_n "checking for ut_pid in utmp""... $ac_c" 1>&6
-echo "configure:10173: checking for ut_pid in utmp" >&5
+echo "configure:10232: checking for ut_pid in utmp" >&5
 if eval "test \"`echo '$''{'samba_cv_HAVE_UT_UT_PID'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   
 cat > conftest.$ac_ext <<EOF
-#line 10179 "configure"
+#line 10238 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <utmp.h>
@@ -10183,7 +10242,7 @@ int main() {
 struct utmp ut;  ut.ut_pid = 0;
 ; return 0; }
 EOF
-if { (eval echo configure:10187: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:10246: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   samba_cv_HAVE_UT_UT_PID=yes
 else
@@ -10204,13 +10263,13 @@ EOF
 fi 
 
 echo $ac_n "checking for ut_exit in utmp""... $ac_c" 1>&6
-echo "configure:10208: checking for ut_exit in utmp" >&5
+echo "configure:10267: checking for ut_exit in utmp" >&5
 if eval "test \"`echo '$''{'samba_cv_HAVE_UT_UT_EXIT'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   
 cat > conftest.$ac_ext <<EOF
-#line 10214 "configure"
+#line 10273 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <utmp.h>
@@ -10218,7 +10277,7 @@ int main() {
 struct utmp ut;  ut.ut_exit.e_exit = 0;
 ; return 0; }
 EOF
-if { (eval echo configure:10222: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:10281: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   samba_cv_HAVE_UT_UT_EXIT=yes
 else
@@ -10239,13 +10298,13 @@ EOF
 fi 
 
 echo $ac_n "checking for ut_addr in utmp""... $ac_c" 1>&6
-echo "configure:10243: checking for ut_addr in utmp" >&5
+echo "configure:10302: checking for ut_addr in utmp" >&5
 if eval "test \"`echo '$''{'samba_cv_HAVE_UT_UT_ADDR'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   
 cat > conftest.$ac_ext <<EOF
-#line 10249 "configure"
+#line 10308 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <utmp.h>
@@ -10253,7 +10312,7 @@ int main() {
 struct utmp ut;  ut.ut_addr = 0;
 ; return 0; }
 EOF
-if { (eval echo configure:10257: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:10316: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   samba_cv_HAVE_UT_UT_ADDR=yes
 else
 
 if test x$ac_cv_func_pututline = xyes ; then
   echo $ac_n "checking whether pututline returns pointer""... $ac_c" 1>&6
-echo "configure:10279: checking whether pututline returns pointer" >&5
+echo "configure:10338: checking whether pututline returns pointer" >&5
 if eval "test \"`echo '$''{'samba_cv_PUTUTLINE_RETURNS_UTMP'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   
   cat > conftest.$ac_ext <<EOF
-#line 10285 "configure"
+#line 10344 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <utmp.h>
@@ -10289,7 +10348,7 @@ int main() {
 struct utmp utarg; struct utmp *utreturn; utreturn = pututline(&utarg);
 ; return 0; }
 EOF
-if { (eval echo configure:10293: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:10352: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   samba_cv_PUTUTLINE_RETURNS_UTMP=yes
 else
@@ -10311,13 +10370,13 @@ EOF
 fi
 
 echo $ac_n "checking for ut_syslen in utmpx""... $ac_c" 1>&6
-echo "configure:10315: checking for ut_syslen in utmpx" >&5
+echo "configure:10374: checking for ut_syslen in utmpx" >&5
 if eval "test \"`echo '$''{'samba_cv_HAVE_UX_UT_SYSLEN'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   
 cat > conftest.$ac_ext <<EOF
-#line 10321 "configure"
+#line 10380 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <utmpx.h>
@@ -10325,7 +10384,7 @@ int main() {
 struct utmpx ux;  ux.ut_syslen = 0;
 ; return 0; }
 EOF
-if { (eval echo configure:10329: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:10388: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   samba_cv_HAVE_UX_UT_SYSLEN=yes
 else
@@ -10349,7 +10408,7 @@ fi
 #################################################
 # check for libiconv support
 echo $ac_n "checking whether to use libiconv""... $ac_c" 1>&6
-echo "configure:10353: checking whether to use libiconv" >&5
+echo "configure:10412: checking whether to use libiconv" >&5
 # Check whether --with-libiconv or --without-libiconv was given.
 if test "${with_libiconv+set}" = set; then
   withval="$with_libiconv"
@@ -10362,7 +10421,7 @@ if test "${with_libiconv+set}" = set; then
     CFLAGS="$CFLAGS -I$withval/include"
     LDFLAGS="$LDFLAGS -L$withval/lib"
     echo $ac_n "checking for iconv_open in -liconv""... $ac_c" 1>&6
-echo "configure:10366: checking for iconv_open in -liconv" >&5
+echo "configure:10425: checking for iconv_open in -liconv" >&5
 ac_lib_var=`echo iconv'_'iconv_open | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -10370,7 +10429,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-liconv  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 10374 "configure"
+#line 10433 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -10381,7 +10440,7 @@ int main() {
 iconv_open()
 ; return 0; }
 EOF
-if { (eval echo configure:10385: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:10444: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -10424,7 +10483,7 @@ fi
 ############
 # check for iconv in libc
 echo $ac_n "checking for working iconv""... $ac_c" 1>&6
-echo "configure:10428: checking for working iconv" >&5
+echo "configure:10487: checking for working iconv" >&5
 if eval "test \"`echo '$''{'samba_cv_HAVE_NATIVE_ICONV'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -10433,7 +10492,7 @@ if test "$cross_compiling" = yes; then
   samba_cv_HAVE_NATIVE_ICONV=cross
 else
   cat > conftest.$ac_ext <<EOF
-#line 10437 "configure"
+#line 10496 "configure"
 #include "confdefs.h"
 
 #include <iconv.h>
@@ -10444,7 +10503,7 @@ main() {
 }
 
 EOF
-if { (eval echo configure:10448: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:10507: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   samba_cv_HAVE_NATIVE_ICONV=yes
 else
@@ -10468,7 +10527,7 @@ fi
 
 
 echo $ac_n "checking for Linux kernel oplocks""... $ac_c" 1>&6
-echo "configure:10472: checking for Linux kernel oplocks" >&5
+echo "configure:10531: checking for Linux kernel oplocks" >&5
 if eval "test \"`echo '$''{'samba_cv_HAVE_KERNEL_OPLOCKS_LINUX'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -10477,7 +10536,7 @@ if test "$cross_compiling" = yes; then
   samba_cv_HAVE_KERNEL_OPLOCKS_LINUX=cross
 else
   cat > conftest.$ac_ext <<EOF
-#line 10481 "configure"
+#line 10540 "configure"
 #include "confdefs.h"
 
 #include <sys/types.h>
@@ -10491,7 +10550,7 @@ main() {
 }
 
 EOF
-if { (eval echo configure:10495: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:10554: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   samba_cv_HAVE_KERNEL_OPLOCKS_LINUX=yes
 else
@@ -10514,7 +10573,7 @@ EOF
 fi
 
 echo $ac_n "checking for kernel change notify support""... $ac_c" 1>&6
-echo "configure:10518: checking for kernel change notify support" >&5
+echo "configure:10577: checking for kernel change notify support" >&5
 if eval "test \"`echo '$''{'samba_cv_HAVE_KERNEL_CHANGE_NOTIFY'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -10523,7 +10582,7 @@ if test "$cross_compiling" = yes; then
   samba_cv_HAVE_KERNEL_CHANGE_NOTIFY=cross
 else
   cat > conftest.$ac_ext <<EOF
-#line 10527 "configure"
+#line 10586 "configure"
 #include "confdefs.h"
 
 #include <sys/types.h>
@@ -10537,7 +10596,7 @@ main() {
 }
 
 EOF
-if { (eval echo configure:10541: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:10600: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   samba_cv_HAVE_KERNEL_CHANGE_NOTIFY=yes
 else
@@ -10560,7 +10619,7 @@ EOF
 fi
 
 echo $ac_n "checking for kernel share modes""... $ac_c" 1>&6
-echo "configure:10564: checking for kernel share modes" >&5
+echo "configure:10623: checking for kernel share modes" >&5
 if eval "test \"`echo '$''{'samba_cv_HAVE_KERNEL_SHARE_MODES'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -10569,7 +10628,7 @@ if test "$cross_compiling" = yes; then
   samba_cv_HAVE_KERNEL_SHARE_MODES=cross
 else
   cat > conftest.$ac_ext <<EOF
-#line 10573 "configure"
+#line 10632 "configure"
 #include "confdefs.h"
 
 #include <sys/types.h>
@@ -10585,7 +10644,7 @@ main() {
 }
 
 EOF
-if { (eval echo configure:10589: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:10648: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   samba_cv_HAVE_KERNEL_SHARE_MODES=yes
 else
 
 
 echo $ac_n "checking for IRIX kernel oplock type definitions""... $ac_c" 1>&6
-echo "configure:10615: checking for IRIX kernel oplock type definitions" >&5
+echo "configure:10674: checking for IRIX kernel oplock type definitions" >&5
 if eval "test \"`echo '$''{'samba_cv_HAVE_KERNEL_OPLOCKS_IRIX'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   
 cat > conftest.$ac_ext <<EOF
-#line 10621 "configure"
+#line 10680 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <fcntl.h>
@@ -10625,7 +10684,7 @@ int main() {
 oplock_stat_t t; t.os_state = OP_REVOKE; t.os_dev = 1; t.os_ino = 1;
 ; return 0; }
 EOF
-if { (eval echo configure:10629: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:10688: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   samba_cv_HAVE_KERNEL_OPLOCKS_IRIX=yes
 else
@@ -10646,7 +10705,7 @@ EOF
 fi
 
 echo $ac_n "checking for irix specific capabilities""... $ac_c" 1>&6
-echo "configure:10650: checking for irix specific capabilities" >&5
+echo "configure:10709: checking for irix specific capabilities" >&5
 if eval "test \"`echo '$''{'samba_cv_HAVE_IRIX_SPECIFIC_CAPABILITIES'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -10655,7 +10714,7 @@ if test "$cross_compiling" = yes; then
   samba_cv_HAVE_IRIX_SPECIFIC_CAPABILITIES=cross
 else
   cat > conftest.$ac_ext <<EOF
-#line 10659 "configure"
+#line 10718 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <sys/capability.h>
@@ -10670,7 +10729,7 @@ main() {
 }
 
 EOF
-if { (eval echo configure:10674: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:10733: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   samba_cv_HAVE_IRIX_SPECIFIC_CAPABILITIES=yes
 else
 #
 
 echo $ac_n "checking for int16 typedef included by rpc/rpc.h""... $ac_c" 1>&6
-echo "configure:10702: checking for int16 typedef included by rpc/rpc.h" >&5
+echo "configure:10761: checking for int16 typedef included by rpc/rpc.h" >&5
 if eval "test \"`echo '$''{'samba_cv_HAVE_INT16_FROM_RPC_RPC_H'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   
 cat > conftest.$ac_ext <<EOF
-#line 10708 "configure"
+#line 10767 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #if defined(HAVE_RPC_RPC_H)
@@ -10714,7 +10773,7 @@ int main() {
 int16 testvar;
 ; return 0; }
 EOF
-if { (eval echo configure:10718: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:10777: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   samba_cv_HAVE_INT16_FROM_RPC_RPC_H=yes
 else
@@ -10735,13 +10794,13 @@ EOF
 fi
 
 echo $ac_n "checking for uint16 typedef included by rpc/rpc.h""... $ac_c" 1>&6
-echo "configure:10739: checking for uint16 typedef included by rpc/rpc.h" >&5
+echo "configure:10798: checking for uint16 typedef included by rpc/rpc.h" >&5
 if eval "test \"`echo '$''{'samba_cv_HAVE_UINT16_FROM_RPC_RPC_H'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   
 cat > conftest.$ac_ext <<EOF
-#line 10745 "configure"
+#line 10804 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #if defined(HAVE_RPC_RPC_H)
@@ -10751,7 +10810,7 @@ int main() {
 uint16 testvar;
 ; return 0; }
 EOF
-if { (eval echo configure:10755: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:10814: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   samba_cv_HAVE_UINT16_FROM_RPC_RPC_H=yes
 else
@@ -10772,13 +10831,13 @@ EOF
 fi
 
 echo $ac_n "checking for int32 typedef included by rpc/rpc.h""... $ac_c" 1>&6
-echo "configure:10776: checking for int32 typedef included by rpc/rpc.h" >&5
+echo "configure:10835: checking for int32 typedef included by rpc/rpc.h" >&5
 if eval "test \"`echo '$''{'samba_cv_HAVE_INT32_FROM_RPC_RPC_H'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   
 cat > conftest.$ac_ext <<EOF
-#line 10782 "configure"
+#line 10841 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #if defined(HAVE_RPC_RPC_H)
@@ -10788,7 +10847,7 @@ int main() {
 int32 testvar;
 ; return 0; }
 EOF
-if { (eval echo configure:10792: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:10851: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   samba_cv_HAVE_INT32_FROM_RPC_RPC_H=yes
 else
@@ -10809,13 +10868,13 @@ EOF
 fi
 
 echo $ac_n "checking for uint32 typedef included by rpc/rpc.h""... $ac_c" 1>&6
-echo "configure:10813: checking for uint32 typedef included by rpc/rpc.h" >&5
+echo "configure:10872: checking for uint32 typedef included by rpc/rpc.h" >&5
 if eval "test \"`echo '$''{'samba_cv_HAVE_UINT32_FROM_RPC_RPC_H'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   
 cat > conftest.$ac_ext <<EOF
-#line 10819 "configure"
+#line 10878 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #if defined(HAVE_RPC_RPC_H)
@@ -10825,7 +10884,7 @@ int main() {
 uint32 testvar;
 ; return 0; }
 EOF
-if { (eval echo configure:10829: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:10888: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   samba_cv_HAVE_UINT32_FROM_RPC_RPC_H=yes
 else
 
 
 echo $ac_n "checking for conflicting AUTH_ERROR define in rpc/rpc.h""... $ac_c" 1>&6
-echo "configure:10851: checking for conflicting AUTH_ERROR define in rpc/rpc.h" >&5
+echo "configure:10910: checking for conflicting AUTH_ERROR define in rpc/rpc.h" >&5
 if eval "test \"`echo '$''{'samba_cv_HAVE_RPC_AUTH_ERROR_CONFLICT'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   
 cat > conftest.$ac_ext <<EOF
-#line 10857 "configure"
+#line 10916 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #ifdef HAVE_SYS_SECURITY_H
@@ -10867,7 +10926,7 @@ int main() {
 int testvar;
 ; return 0; }
 EOF
-if { (eval echo configure:10871: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:10930: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   samba_cv_HAVE_RPC_AUTH_ERROR_CONFLICT=no
 else
@@ -10888,16 +10947,16 @@ EOF
 fi
 
 echo $ac_n "checking for test routines""... $ac_c" 1>&6
-echo "configure:10892: checking for test routines" >&5
+echo "configure:10951: checking for test routines" >&5
 if test "$cross_compiling" = yes; then
   echo "configure: warning: cannot run when cross-compiling" 1>&2
 else
   cat > conftest.$ac_ext <<EOF
-#line 10897 "configure"
+#line 10956 "configure"
 #include "confdefs.h"
 #include "${srcdir-.}/tests/trivial.c"
 EOF
-if { (eval echo configure:10901: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:10960: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   echo "$ac_t""yes" 1>&6
 else
@@ -10911,7 +10970,7 @@ fi
 
 
 echo $ac_n "checking for ftruncate extend""... $ac_c" 1>&6
-echo "configure:10915: checking for ftruncate extend" >&5
+echo "configure:10974: checking for ftruncate extend" >&5
 if eval "test \"`echo '$''{'samba_cv_HAVE_FTRUNCATE_EXTEND'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -10920,11 +10979,11 @@ if test "$cross_compiling" = yes; then
   samba_cv_HAVE_FTRUNCATE_EXTEND=cross
 else
   cat > conftest.$ac_ext <<EOF
-#line 10924 "configure"
+#line 10983 "configure"
 #include "confdefs.h"
 #include "${srcdir-.}/tests/ftruncate.c"
 EOF
-if { (eval echo configure:10928: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:10987: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   samba_cv_HAVE_FTRUNCATE_EXTEND=yes
 else
@@ -10947,7 +11006,7 @@ EOF
 fi
 
 echo $ac_n "checking for AF_LOCAL socket support""... $ac_c" 1>&6
-echo "configure:10951: checking for AF_LOCAL socket support" >&5
+echo "configure:11010: checking for AF_LOCAL socket support" >&5
 if eval "test \"`echo '$''{'samba_cv_HAVE_WORKING_AF_LOCAL'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -10956,11 +11015,11 @@ if test "$cross_compiling" = yes; then
   samba_cv_HAVE_WORKING_AF_LOCAL=cross
 else
   cat > conftest.$ac_ext <<EOF
-#line 10960 "configure"
+#line 11019 "configure"
 #include "confdefs.h"
 #include "${srcdir-.}/tests/unixsock.c"
 EOF
-if { (eval echo configure:10964: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:11023: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   samba_cv_HAVE_WORKING_AF_LOCAL=yes
 else
@@ -10984,7 +11043,7 @@ EOF
 fi
 
 echo $ac_n "checking for broken getgroups""... $ac_c" 1>&6
-echo "configure:10988: checking for broken getgroups" >&5
+echo "configure:11047: checking for broken getgroups" >&5
 if eval "test \"`echo '$''{'samba_cv_HAVE_BROKEN_GETGROUPS'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -10993,11 +11052,11 @@ if test "$cross_compiling" = yes; then
   samba_cv_HAVE_BROKEN_GETGROUPS=cross
 else
   cat > conftest.$ac_ext <<EOF
-#line 10997 "configure"
+#line 11056 "configure"
 #include "confdefs.h"
 #include "${srcdir-.}/tests/getgroups.c"
 EOF
-if { (eval echo configure:11001: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:11060: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   samba_cv_HAVE_BROKEN_GETGROUPS=yes
 else
@@ -11020,7 +11079,7 @@ EOF
 fi
 
 echo $ac_n "checking whether getpass should be replaced""... $ac_c" 1>&6
-echo "configure:11024: checking whether getpass should be replaced" >&5
+echo "configure:11083: checking whether getpass should be replaced" >&5
 if eval "test \"`echo '$''{'samba_cv_REPLACE_GETPASS'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -11028,7 +11087,7 @@ else
 SAVE_CPPFLAGS="$CPPFLAGS"
 CPPFLAGS="$CPPFLAGS -I${srcdir-.}/ -I${srcdir-.}/include -I${srcdir-.}/ubiqx -I${srcdir-.}/popt  -I${srcdir-.}/smbwrapper"
 cat > conftest.$ac_ext <<EOF
-#line 11032 "configure"
+#line 11091 "configure"
 #include "confdefs.h"
 
 #define REPLACE_GETPASS 1
@@ -11041,7 +11100,7 @@ int main() {
 
 ; return 0; }
 EOF
-if { (eval echo configure:11045: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:11104: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   samba_cv_REPLACE_GETPASS=yes
 else
@@ -11064,7 +11123,7 @@ EOF
 fi
 
 echo $ac_n "checking for broken inet_ntoa""... $ac_c" 1>&6
-echo "configure:11068: checking for broken inet_ntoa" >&5
+echo "configure:11127: checking for broken inet_ntoa" >&5
 if eval "test \"`echo '$''{'samba_cv_REPLACE_INET_NTOA'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -11073,7 +11132,7 @@ if test "$cross_compiling" = yes; then
   samba_cv_REPLACE_INET_NTOA=cross
 else
   cat > conftest.$ac_ext <<EOF
-#line 11077 "configure"
+#line 11136 "configure"
 #include "confdefs.h"
 
 #include <stdio.h>
@@ -11087,7 +11146,7 @@ if (strcmp(inet_ntoa(ip),"18.52.86.120") &&
     strcmp(inet_ntoa(ip),"120.86.52.18")) { exit(0); } 
 exit(1);}
 EOF
-if { (eval echo configure:11091: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:11150: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   samba_cv_REPLACE_INET_NTOA=yes
 else
@@ -11110,7 +11169,7 @@ EOF
 fi
 
 echo $ac_n "checking for secure mkstemp""... $ac_c" 1>&6
-echo "configure:11114: checking for secure mkstemp" >&5
+echo "configure:11173: checking for secure mkstemp" >&5
 if eval "test \"`echo '$''{'samba_cv_HAVE_SECURE_MKSTEMP'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -11119,7 +11178,7 @@ if test "$cross_compiling" = yes; then
   samba_cv_HAVE_SECURE_MKSTEMP=cross
 else
   cat > conftest.$ac_ext <<EOF
-#line 11123 "configure"
+#line 11182 "configure"
 #include "confdefs.h"
 #include <stdlib.h>
 #include <sys/types.h>
@@ -11136,7 +11195,7 @@ main() {
   exit(0);
 }
 EOF
-if { (eval echo configure:11140: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:11199: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   samba_cv_HAVE_SECURE_MKSTEMP=yes
 else
@@ -11159,7 +11218,7 @@ EOF
 fi
 
 echo $ac_n "checking for sysconf(_SC_NGROUPS_MAX)""... $ac_c" 1>&6
-echo "configure:11163: checking for sysconf(_SC_NGROUPS_MAX)" >&5
+echo "configure:11222: checking for sysconf(_SC_NGROUPS_MAX)" >&5
 if eval "test \"`echo '$''{'samba_cv_SYSCONF_SC_NGROUPS_MAX'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -11168,12 +11227,12 @@ if test "$cross_compiling" = yes; then
   samba_cv_SYSCONF_SC_NGROUPS_MAX=cross
 else
   cat > conftest.$ac_ext <<EOF
-#line 11172 "configure"
+#line 11231 "configure"
 #include "confdefs.h"
 #include <unistd.h>
 main() { exit(sysconf(_SC_NGROUPS_MAX) == -1 ? 1 : 0); }
 EOF
-if { (eval echo configure:11177: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:11236: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   samba_cv_SYSCONF_SC_NGROUPS_MAX=yes
 else
@@ -11196,7 +11255,7 @@ EOF
 fi
 
 echo $ac_n "checking for root""... $ac_c" 1>&6
-echo "configure:11200: checking for root" >&5
+echo "configure:11259: checking for root" >&5
 if eval "test \"`echo '$''{'samba_cv_HAVE_ROOT'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -11205,11 +11264,11 @@ if test "$cross_compiling" = yes; then
   samba_cv_HAVE_ROOT=cross
 else
   cat > conftest.$ac_ext <<EOF
-#line 11209 "configure"
+#line 11268 "configure"
 #include "confdefs.h"
 main() { exit(getuid() != 0); }
 EOF
-if { (eval echo configure:11213: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:11272: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   samba_cv_HAVE_ROOT=yes
 else
@@ -11237,7 +11296,7 @@ fi
 # look for a method of finding the list of network interfaces
 iface=no;
 echo $ac_n "checking for iface AIX""... $ac_c" 1>&6
-echo "configure:11241: checking for iface AIX" >&5
+echo "configure:11300: checking for iface AIX" >&5
 if eval "test \"`echo '$''{'samba_cv_HAVE_IFACE_AIX'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -11246,7 +11305,7 @@ if test "$cross_compiling" = yes; then
   samba_cv_HAVE_IFACE_AIX=cross
 else
   cat > conftest.$ac_ext <<EOF
-#line 11250 "configure"
+#line 11309 "configure"
 #include "confdefs.h"
 
 #define HAVE_IFACE_AIX 1
@@ -11254,7 +11313,7 @@ else
 #include "confdefs.h"
 #include "${srcdir-.}/lib/interfaces.c"
 EOF
-if { (eval echo configure:11258: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:11317: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   samba_cv_HAVE_IFACE_AIX=yes
 else
@@ -11278,7 +11337,7 @@ fi
 
 if test $iface = no; then
 echo $ac_n "checking for iface ifconf""... $ac_c" 1>&6
-echo "configure:11282: checking for iface ifconf" >&5
+echo "configure:11341: checking for iface ifconf" >&5
 if eval "test \"`echo '$''{'samba_cv_HAVE_IFACE_IFCONF'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -11287,7 +11346,7 @@ if test "$cross_compiling" = yes; then
   samba_cv_HAVE_IFACE_IFCONF=cross
 else
   cat > conftest.$ac_ext <<EOF
-#line 11291 "configure"
+#line 11350 "configure"
 #include "confdefs.h"
 
 #define HAVE_IFACE_IFCONF 1
@@ -11295,7 +11354,7 @@ else
 #include "confdefs.h"
 #include "${srcdir-.}/lib/interfaces.c"
 EOF
-if { (eval echo configure:11299: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:11358: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   samba_cv_HAVE_IFACE_IFCONF=yes
 else
@@ -11320,7 +11379,7 @@ fi
 
 if test $iface = no; then
 echo $ac_n "checking for iface ifreq""... $ac_c" 1>&6
-echo "configure:11324: checking for iface ifreq" >&5
+echo "configure:11383: checking for iface ifreq" >&5
 if eval "test \"`echo '$''{'samba_cv_HAVE_IFACE_IFREQ'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -11329,7 +11388,7 @@ if test "$cross_compiling" = yes; then
   samba_cv_HAVE_IFACE_IFREQ=cross
 else
   cat > conftest.$ac_ext <<EOF
-#line 11333 "configure"
+#line 11392 "configure"
 #include "confdefs.h"
 
 #define HAVE_IFACE_IFREQ 1
@@ -11337,7 +11396,7 @@ else
 #include "confdefs.h"
 #include "${srcdir-.}/lib/interfaces.c"
 EOF
-if { (eval echo configure:11341: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:11400: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   samba_cv_HAVE_IFACE_IFREQ=yes
 else
@@ -11366,7 +11425,7 @@ fi
 seteuid=no;
 if test $seteuid = no; then
 echo $ac_n "checking for setresuid""... $ac_c" 1>&6
-echo "configure:11370: checking for setresuid" >&5
+echo "configure:11429: checking for setresuid" >&5
 if eval "test \"`echo '$''{'samba_cv_USE_SETRESUID'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -11375,7 +11434,7 @@ if test "$cross_compiling" = yes; then
   samba_cv_USE_SETRESUID=cross
 else
   cat > conftest.$ac_ext <<EOF
-#line 11379 "configure"
+#line 11438 "configure"
 #include "confdefs.h"
 
 #define AUTOCONF_TEST 1
@@ -11383,7 +11442,7 @@ else
 #include "confdefs.h"
 #include "${srcdir-.}/lib/util_sec.c"
 EOF
-if { (eval echo configure:11387: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:11446: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   samba_cv_USE_SETRESUID=yes
 else
@@ -11409,7 +11468,7 @@ fi
 
 if test $seteuid = no; then
 echo $ac_n "checking for setreuid""... $ac_c" 1>&6
-echo "configure:11413: checking for setreuid" >&5
+echo "configure:11472: checking for setreuid" >&5
 if eval "test \"`echo '$''{'samba_cv_USE_SETREUID'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -11418,7 +11477,7 @@ if test "$cross_compiling" = yes; then
   samba_cv_USE_SETREUID=cross
 else
   cat > conftest.$ac_ext <<EOF
-#line 11422 "configure"
+#line 11481 "configure"
 #include "confdefs.h"
 
 #define AUTOCONF_TEST 1
@@ -11426,7 +11485,7 @@ else
 #include "confdefs.h"
 #include "${srcdir-.}/lib/util_sec.c"
 EOF
-if { (eval echo configure:11430: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:11489: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   samba_cv_USE_SETREUID=yes
 else
@@ -11451,7 +11510,7 @@ fi
 
 if test $seteuid = no; then
 echo $ac_n "checking for seteuid""... $ac_c" 1>&6
-echo "configure:11455: checking for seteuid" >&5
+echo "configure:11514: checking for seteuid" >&5
 if eval "test \"`echo '$''{'samba_cv_USE_SETEUID'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -11460,7 +11519,7 @@ if test "$cross_compiling" = yes; then
   samba_cv_USE_SETEUID=cross
 else
   cat > conftest.$ac_ext <<EOF
-#line 11464 "configure"
+#line 11523 "configure"
 #include "confdefs.h"
 
 #define AUTOCONF_TEST 1
@@ -11468,7 +11527,7 @@ else
 #include "confdefs.h"
 #include "${srcdir-.}/lib/util_sec.c"
 EOF
-if { (eval echo configure:11472: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:11531: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   samba_cv_USE_SETEUID=yes
 else
@@ -11493,7 +11552,7 @@ fi
 
 if test $seteuid = no; then
 echo $ac_n "checking for setuidx""... $ac_c" 1>&6
-echo "configure:11497: checking for setuidx" >&5
+echo "configure:11556: checking for setuidx" >&5
 if eval "test \"`echo '$''{'samba_cv_USE_SETUIDX'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -11502,7 +11561,7 @@ if test "$cross_compiling" = yes; then
   samba_cv_USE_SETUIDX=cross
 else
   cat > conftest.$ac_ext <<EOF
-#line 11506 "configure"
+#line 11565 "configure"
 #include "confdefs.h"
 
 #define AUTOCONF_TEST 1
@@ -11510,7 +11569,7 @@ else
 #include "confdefs.h"
 #include "${srcdir-.}/lib/util_sec.c"
 EOF
-if { (eval echo configure:11514: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:11573: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   samba_cv_USE_SETUIDX=yes
 else
@@ -11535,7 +11594,7 @@ fi
 
 
 echo $ac_n "checking for working mmap""... $ac_c" 1>&6
-echo "configure:11539: checking for working mmap" >&5
+echo "configure:11598: checking for working mmap" >&5
 if eval "test \"`echo '$''{'samba_cv_HAVE_MMAP'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -11544,11 +11603,11 @@ if test "$cross_compiling" = yes; then
   samba_cv_HAVE_MMAP=cross
 else
   cat > conftest.$ac_ext <<EOF
-#line 11548 "configure"
+#line 11607 "configure"
 #include "confdefs.h"
 #include "${srcdir-.}/tests/shared_mmap.c"
 EOF
-if { (eval echo configure:11552: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:11611: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   samba_cv_HAVE_MMAP=yes
 else
@@ -11571,7 +11630,7 @@ EOF
 fi
 
 echo $ac_n "checking for ftruncate needs root""... $ac_c" 1>&6
-echo "configure:11575: checking for ftruncate needs root" >&5
+echo "configure:11634: checking for ftruncate needs root" >&5
 if eval "test \"`echo '$''{'samba_cv_FTRUNCATE_NEEDS_ROOT'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -11580,11 +11639,11 @@ if test "$cross_compiling" = yes; then
   samba_cv_FTRUNCATE_NEEDS_ROOT=cross
 else
   cat > conftest.$ac_ext <<EOF
-#line 11584 "configure"
+#line 11643 "configure"
 #include "confdefs.h"
 #include "${srcdir-.}/tests/ftruncroot.c"
 EOF
-if { (eval echo configure:11588: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:11647: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   samba_cv_FTRUNCATE_NEEDS_ROOT=yes
 else
@@ -11607,7 +11666,7 @@ EOF
 fi
 
 echo $ac_n "checking for fcntl locking""... $ac_c" 1>&6
-echo "configure:11611: checking for fcntl locking" >&5
+echo "configure:11670: checking for fcntl locking" >&5
 if eval "test \"`echo '$''{'samba_cv_HAVE_FCNTL_LOCK'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -11616,11 +11675,11 @@ if test "$cross_compiling" = yes; then
   samba_cv_HAVE_FCNTL_LOCK=cross
 else
   cat > conftest.$ac_ext <<EOF
-#line 11620 "configure"
+#line 11679 "configure"
 #include "confdefs.h"
 #include "${srcdir-.}/tests/fcntl_lock.c"
 EOF
-if { (eval echo configure:11624: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:11683: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   samba_cv_HAVE_FCNTL_LOCK=yes
 else
@@ -11643,7 +11702,7 @@ EOF
 fi
 
 echo $ac_n "checking for broken (glibc2.1/x86) 64 bit fcntl locking""... $ac_c" 1>&6
-echo "configure:11647: checking for broken (glibc2.1/x86) 64 bit fcntl locking" >&5
+echo "configure:11706: checking for broken (glibc2.1/x86) 64 bit fcntl locking" >&5
 if eval "test \"`echo '$''{'samba_cv_HAVE_BROKEN_FCNTL64_LOCKS'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -11652,11 +11711,11 @@ if test "$cross_compiling" = yes; then
   samba_cv_HAVE_BROKEN_FCNTL64_LOCKS=cross
 else
   cat > conftest.$ac_ext <<EOF
-#line 11656 "configure"
+#line 11715 "configure"
 #include "confdefs.h"
 #include "${srcdir-.}/tests/fcntl_lock64.c"
 EOF
-if { (eval echo configure:11660: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:11719: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   samba_cv_HAVE_BROKEN_FCNTL64_LOCKS=yes
 else
@@ -11681,7 +11740,7 @@ else
 
 
   echo $ac_n "checking for 64 bit fcntl locking""... $ac_c" 1>&6
-echo "configure:11685: checking for 64 bit fcntl locking" >&5
+echo "configure:11744: checking for 64 bit fcntl locking" >&5
 if eval "test \"`echo '$''{'samba_cv_HAVE_STRUCT_FLOCK64'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -11690,7 +11749,7 @@ else
   samba_cv_HAVE_STRUCT_FLOCK64=cross
 else
   cat > conftest.$ac_ext <<EOF
-#line 11694 "configure"
+#line 11753 "configure"
 #include "confdefs.h"
 
 #if defined(HAVE_UNISTD_H)
@@ -11714,7 +11773,7 @@ exit(1);
 #endif
 }
 EOF
-if { (eval echo configure:11718: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:11777: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   samba_cv_HAVE_STRUCT_FLOCK64=yes
 else
@@ -11739,13 +11798,13 @@ EOF
 fi
 
 echo $ac_n "checking for st_blocks in struct stat""... $ac_c" 1>&6
-echo "configure:11743: checking for st_blocks in struct stat" >&5
+echo "configure:11802: checking for st_blocks in struct stat" >&5
 if eval "test \"`echo '$''{'samba_cv_HAVE_STAT_ST_BLOCKS'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   
 cat > conftest.$ac_ext <<EOF
-#line 11749 "configure"
+#line 11808 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -11754,7 +11813,7 @@ int main() {
 struct stat st;  st.st_blocks = 0;
 ; return 0; }
 EOF
-if { (eval echo configure:11758: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:11817: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   samba_cv_HAVE_STAT_ST_BLOCKS=yes
 else
@@ -11774,16 +11833,52 @@ EOF
 
 fi 
 
+echo $ac_n "checking for st_blksize in struct stat""... $ac_c" 1>&6
+echo "configure:11838: checking for st_blksize in struct stat" >&5
+if eval "test \"`echo '$''{'samba_cv_HAVE_STAT_ST_BLKSIZE'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  
+cat > conftest.$ac_ext <<EOF
+#line 11844 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+int main() {
+struct stat st;  st.st_blksize = 0;
+; return 0; }
+EOF
+if { (eval echo configure:11853: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+  rm -rf conftest*
+  samba_cv_HAVE_STAT_ST_BLKSIZE=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  samba_cv_HAVE_STAT_ST_BLKSIZE=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$samba_cv_HAVE_STAT_ST_BLKSIZE" 1>&6
+if test x"$samba_cv_HAVE_STAT_ST_BLKSIZE" = x"yes"; then
+    cat >> confdefs.h <<\EOF
+#define HAVE_STAT_ST_BLKSIZE 1
+EOF
+
+fi
+
 case "$host_os" in
 *linux*)
 echo $ac_n "checking for broken RedHat 7.2 system header files""... $ac_c" 1>&6
-echo "configure:11781: checking for broken RedHat 7.2 system header files" >&5
+echo "configure:11876: checking for broken RedHat 7.2 system header files" >&5
 if eval "test \"`echo '$''{'samba_cv_BROKEN_REDHAT_7_SYSTEM_HEADERS'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   
 cat > conftest.$ac_ext <<EOF
-#line 11787 "configure"
+#line 11882 "configure"
 #include "confdefs.h"
 
 #ifdef HAVE_SYS_VFS_H
@@ -11797,7 +11892,7 @@ int main() {
 int i;
 ; return 0; }
 EOF
-if { (eval echo configure:11801: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:11896: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   samba_cv_BROKEN_REDHAT_7_SYSTEM_HEADERS=no
 else
 esac
 
 echo $ac_n "checking for broken nisplus include files""... $ac_c" 1>&6
-echo "configure:11824: checking for broken nisplus include files" >&5
+echo "configure:11919: checking for broken nisplus include files" >&5
 if eval "test \"`echo '$''{'samba_cv_BROKEN_NISPLUS_INCLUDE_FILES'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   
 cat > conftest.$ac_ext <<EOF
-#line 11830 "configure"
+#line 11925 "configure"
 #include "confdefs.h"
 #include <sys/acl.h>
 #if defined(HAVE_RPCSVC_NIS_H)
@@ -11836,7 +11931,7 @@ int main() {
 int i;
 ; return 0; }
 EOF
-if { (eval echo configure:11840: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:11935: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   samba_cv_BROKEN_NISPLUS_INCLUDE_FILES=no
 else
@@ -11860,7 +11955,7 @@ fi
 #################################################
 # check for smbwrapper support
 echo $ac_n "checking whether to use smbwrapper""... $ac_c" 1>&6
-echo "configure:11864: checking whether to use smbwrapper" >&5
+echo "configure:11959: checking whether to use smbwrapper" >&5
 # Check whether --with-smbwrapper or --without-smbwrapper was given.
 if test "${with_smbwrapper+set}" = set; then
   withval="$with_smbwrapper"
@@ -11907,7 +12002,7 @@ fi
 #################################################
 # check for AFS clear-text auth support
 echo $ac_n "checking whether to use AFS clear-text auth""... $ac_c" 1>&6
-echo "configure:11911: checking whether to use AFS clear-text auth" >&5
+echo "configure:12006: checking whether to use AFS clear-text auth" >&5
 # Check whether --with-afs or --without-afs was given.
 if test "${with_afs+set}" = set; then
   withval="$with_afs"
@@ -11933,7 +12028,7 @@ fi
 #################################################
 # check for the DFS clear-text auth system
 echo $ac_n "checking whether to use DFS clear-text auth""... $ac_c" 1>&6
-echo "configure:11937: checking whether to use DFS clear-text auth" >&5
+echo "configure:12032: checking whether to use DFS clear-text auth" >&5
 # Check whether --with-dfs or --without-dfs was given.
 if test "${with_dfs+set}" = set; then
   withval="$with_dfs"
@@ -11955,11 +12050,68 @@ else
 fi
 
 
+#################################################
+# active directory support
+
+with_ads_support=yes
+echo $ac_n "checking whether to use Active Directory""... $ac_c" 1>&6
+echo "configure:12059: checking whether to use Active Directory" >&5
+
+# Check whether --with-ads or --without-ads was given.
+if test "${with_ads+set}" = set; then
+  withval="$with_ads"
+   case "$withval" in
+    no)
+       with_ads_support=no
+       ;;
+  esac 
+fi
+
+
+if test x"$with_ads_support" = x"yes"; then
+   cat >> confdefs.h <<\EOF
+#define WITH_ADS 1
+EOF
+
+fi
+
+echo "$ac_t""$with_ads_support" 1>&6
+
+FOUND_KRB5=no
+if test x"$with_ads_support" = x"yes"; then
 
+  #################################################
+  # check for location of Kerberos 5 install
+  echo $ac_n "checking for kerberos 5 install path""... $ac_c" 1>&6
+echo "configure:12087: checking for kerberos 5 install path" >&5
+  # Check whether --with-krb5 or --without-krb5 was given.
+if test "${with_krb5+set}" = set; then
+  withval="$with_krb5"
+   case "$withval" in
+    no)
+      echo "$ac_t""no" 1>&6
+      ;;
+    *)
+      echo "$ac_t""yes" 1>&6
+      LIBS="$LIBS -lkrb5"
+      CFLAGS="$CFLAGS -I$withval/include"
+      CPPFLAGS="$CPPFLAGS -I$withval/include"
+      LDFLAGS="$LDFLAGS -L$withval/lib"
+      FOUND_KRB5=yes
+      ;;
+    esac 
+else
+  echo "$ac_t""no" 1>&6
+  
+fi
+
+
+
+if test x$FOUND_KRB5 = x"no"; then
 #################################################
 # see if this box has the RedHat location for kerberos
 echo $ac_n "checking for /usr/kerberos""... $ac_c" 1>&6
-echo "configure:11963: checking for /usr/kerberos" >&5
+echo "configure:12115: checking for /usr/kerberos" >&5
 if test -d /usr/kerberos; then
     LDFLAGS="$LDFLAGS -L/usr/kerberos/lib"
     CFLAGS="$CFLAGS -I/usr/kerberos/include"
@@ -11968,50 +12120,27 @@ if test -d /usr/kerberos; then
 else
     echo "$ac_t""no" 1>&6
 fi
-
-#################################################
-# check for location of Kerberos 5 install
-echo $ac_n "checking for kerberos 5 install path""... $ac_c" 1>&6
-echo "configure:11976: checking for kerberos 5 install path" >&5
-# Check whether --with-krb5 or --without-krb5 was given.
-if test "${with_krb5+set}" = set; then
-  withval="$with_krb5"
-   case "$withval" in
-  no)
-    echo "$ac_t""no" 1>&6
-    ;;
-  *)
-    echo "$ac_t""yes" 1>&6
-    LIBS="$LIBS -lkrb5"
-    CFLAGS="$CFLAGS -I$withval/include"
-    CPPFLAGS="$CPPFLAGS -I$withval/include"
-    LDFLAGS="$LDFLAGS -L$withval/lib"
-    ;;
-  esac 
-else
-  echo "$ac_t""no" 1>&6
-
 fi
 
 
-# now check for krb5.h. Some systems have the libraries without the headers!
-# note that this check is done here to allow for different kerberos
-# include paths
-for ac_hdr in krb5.h
+  # now check for krb5.h. Some systems have the libraries without the headers!
+  # note that this check is done here to allow for different kerberos
+  # include paths
+  for ac_hdr in krb5.h
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:12005: checking for $ac_hdr" >&5
+echo "configure:12134: checking for $ac_hdr" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 12010 "configure"
+#line 12139 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:12015: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:12144: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
 done
 
 
-# now check for gssapi headers.  This is also done here to allow for
-# different kerberos include paths
-for ac_hdr in gssapi/gssapi_generic.h gssapi/gssapi.h
+  # now check for gssapi headers.  This is also done here to allow for
+  # different kerberos include paths
+  for ac_hdr in gssapi/gssapi_generic.h gssapi/gssapi.h
 do
 ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
 echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:12048: checking for $ac_hdr" >&5
+echo "configure:12177: checking for $ac_hdr" >&5
 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 12053 "configure"
+#line 12182 "configure"
 #include "confdefs.h"
 #include <$ac_hdr>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:12058: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:12187: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
 if test -z "$ac_err"; then
   rm -rf conftest*
 done
 
 
-##################################################################
-# we might need the k5crypto and com_err libraries on some systems
-echo $ac_n "checking for _et_list in -lcom_err""... $ac_c" 1>&6
-echo "configure:12088: checking for _et_list in -lcom_err" >&5
+  ##################################################################
+  # we might need the k5crypto and com_err libraries on some systems
+  echo $ac_n "checking for _et_list in -lcom_err""... $ac_c" 1>&6
+echo "configure:12217: checking for _et_list in -lcom_err" >&5
 ac_lib_var=`echo com_err'_'_et_list | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -12092,7 +12221,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lcom_err  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 12096 "configure"
+#line 12225 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -12103,7 +12232,7 @@ int main() {
 _et_list()
 ; return 0; }
 EOF
-if { (eval echo configure:12107: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:12236: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -12123,8 +12252,8 @@ else
   echo "$ac_t""no" 1>&6
 fi
 
-echo $ac_n "checking for krb5_encrypt_data in -lk5crypto""... $ac_c" 1>&6
-echo "configure:12128: checking for krb5_encrypt_data in -lk5crypto" >&5
+  echo $ac_n "checking for krb5_encrypt_data in -lk5crypto""... $ac_c" 1>&6
+echo "configure:12257: checking for krb5_encrypt_data in -lk5crypto" >&5
 ac_lib_var=`echo k5crypto'_'krb5_encrypt_data | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -12132,7 +12261,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lk5crypto  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 12136 "configure"
+#line 12265 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -12143,7 +12272,7 @@ int main() {
 krb5_encrypt_data()
 ; return 0; }
 EOF
-if { (eval echo configure:12147: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:12276: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -12164,11 +12293,11 @@ else
 fi
 
 
-########################################################
-# now see if we can find the krb5 libs in standard paths
-# or as specified above
-echo $ac_n "checking for krb5_mk_req_extended in -lkrb5""... $ac_c" 1>&6
-echo "configure:12172: checking for krb5_mk_req_extended in -lkrb5" >&5
+  ########################################################
+  # now see if we can find the krb5 libs in standard paths
+  # or as specified above
+  echo $ac_n "checking for krb5_mk_req_extended in -lkrb5""... $ac_c" 1>&6
+echo "configure:12301: checking for krb5_mk_req_extended in -lkrb5" >&5
 ac_lib_var=`echo krb5'_'krb5_mk_req_extended | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -12176,7 +12305,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lkrb5  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 12180 "configure"
+#line 12309 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -12187,7 +12316,7 @@ int main() {
 krb5_mk_req_extended()
 ; return 0; }
 EOF
-if { (eval echo configure:12191: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:12320: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -12212,10 +12341,10 @@ else
 fi
 
 
-########################################################
-# now see if we can find the gssapi libs in standard paths
-echo $ac_n "checking for gss_display_status in -lgssapi_krb5""... $ac_c" 1>&6
-echo "configure:12219: checking for gss_display_status in -lgssapi_krb5" >&5
+  ########################################################
+  # now see if we can find the gssapi libs in standard paths
+  echo $ac_n "checking for gss_display_status in -lgssapi_krb5""... $ac_c" 1>&6
+echo "configure:12348: checking for gss_display_status in -lgssapi_krb5" >&5
 ac_lib_var=`echo gssapi_krb5'_'gss_display_status | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -12223,7 +12352,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lgssapi_krb5  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 12227 "configure"
+#line 12356 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -12234,7 +12363,7 @@ int main() {
 gss_display_status()
 ; return 0; }
 EOF
-if { (eval echo configure:12238: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:12367: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -12258,12 +12387,35 @@ else
   echo "$ac_t""no" 1>&6
 fi
 
+fi
+
+########################################################
+# Compile with LDAP support?
+
+with_ldap_support=yes
+echo $ac_n "checking whether to use LDAP""... $ac_c" 1>&6
+echo "configure:12398: checking whether to use LDAP" >&5
 
-##################################################################
-# we might need the lber lib on some systems. To avoid link errors
-# this test must be before the libldap test
-echo $ac_n "checking for ber_scanf in -llber""... $ac_c" 1>&6
-echo "configure:12267: checking for ber_scanf in -llber" >&5
+# Check whether --with-ldap or --without-ldap was given.
+if test "${with_ldap+set}" = set; then
+  withval="$with_ldap"
+   case "$withval" in
+    no)
+       with_ldap_support=no
+       ;;
+  esac 
+fi
+
+
+echo "$ac_t""$with_ldap_support" 1>&6
+
+if test x"$with_ldap_support" = x"yes"; then
+
+  ##################################################################
+  # we might need the lber lib on some systems. To avoid link errors
+  # this test must be before the libldap test
+  echo $ac_n "checking for ber_scanf in -llber""... $ac_c" 1>&6
+echo "configure:12419: checking for ber_scanf in -llber" >&5
 ac_lib_var=`echo lber'_'ber_scanf | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -12271,7 +12423,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-llber  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 12275 "configure"
+#line 12427 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -12282,7 +12434,7 @@ int main() {
 ber_scanf()
 ; return 0; }
 EOF
-if { (eval echo configure:12286: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:12438: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -12303,11 +12455,11 @@ else
 fi
 
 
-########################################################
-# now see if we can find the ldap libs in standard paths
-if test x$have_ldap != xyes; then
-echo $ac_n "checking for ldap_domain2hostlist in -lldap""... $ac_c" 1>&6
-echo "configure:12311: checking for ldap_domain2hostlist in -lldap" >&5
+  ########################################################
+  # now see if we can find the ldap libs in standard paths
+  if test x$have_ldap != xyes; then
+  echo $ac_n "checking for ldap_domain2hostlist in -lldap""... $ac_c" 1>&6
+echo "configure:12463: checking for ldap_domain2hostlist in -lldap" >&5
 ac_lib_var=`echo ldap'_'ldap_domain2hostlist | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -12315,7 +12467,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lldap  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 12319 "configure"
+#line 12471 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -12326,7 +12478,7 @@ int main() {
 ldap_domain2hostlist()
 ; return 0; }
 EOF
-if { (eval echo configure:12330: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:12482: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
        for ac_func in ldap_set_rebind_proc
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:12361: checking for $ac_func" >&5
+echo "configure:12513: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 12366 "configure"
+#line 12518 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -12385,7 +12537,7 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:12389: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:12541: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
 done
 
        echo $ac_n "checking whether ldap_set_rebind_proc takes 3 arguments""... $ac_c" 1>&6
-echo "configure:12414: checking whether ldap_set_rebind_proc takes 3 arguments" >&5
+echo "configure:12566: checking whether ldap_set_rebind_proc takes 3 arguments" >&5
 if eval "test \"`echo '$''{'pam_ldap_cv_ldap_set_rebind_proc'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   
        cat > conftest.$ac_ext <<EOF
-#line 12420 "configure"
+#line 12572 "configure"
 #include "confdefs.h"
 
        #include <lber.h>
@@ -12425,7 +12577,7 @@ int main() {
 ldap_set_rebind_proc(0, 0, 0);
 ; return 0; }
 EOF
-if { (eval echo configure:12429: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:12581: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   pam_ldap_cv_ldap_set_rebind_proc=3
 else
@@ -12442,12 +12594,13 @@ echo "$ac_t""$pam_ldap_cv_ldap_set_rebind_proc" 1>&6
 #define LDAP_SET_REBIND_PROC_ARGS $pam_ldap_cv_ldap_set_rebind_proc
 EOF
 
+  fi
 fi
 
 #################################################
 # check for automount support
 echo $ac_n "checking whether to use AUTOMOUNT""... $ac_c" 1>&6
-echo "configure:12451: checking whether to use AUTOMOUNT" >&5
+echo "configure:12604: checking whether to use AUTOMOUNT" >&5
 # Check whether --with-automount or --without-automount was given.
 if test "${with_automount+set}" = set; then
   withval="$with_automount"
@@ -12472,7 +12625,7 @@ fi
 #################################################
 # check for smbmount support
 echo $ac_n "checking whether to use SMBMOUNT""... $ac_c" 1>&6
-echo "configure:12476: checking whether to use SMBMOUNT" >&5
+echo "configure:12629: checking whether to use SMBMOUNT" >&5
 # Check whether --with-smbmount or --without-smbmount was given.
 if test "${with_smbmount+set}" = set; then
   withval="$with_smbmount"
@@ -12509,7 +12662,7 @@ fi
 # check for a PAM clear-text auth, accounts, password and session support
 with_pam_for_crypt=no
 echo $ac_n "checking whether to use PAM""... $ac_c" 1>&6
-echo "configure:12513: checking whether to use PAM" >&5
+echo "configure:12666: checking whether to use PAM" >&5
 # Check whether --with-pam or --without-pam was given.
 if test "${with_pam+set}" = set; then
   withval="$with_pam"
@@ -12535,7 +12688,7 @@ fi
 
 # we can't build a pam module if we don't have pam.
 echo $ac_n "checking for pam_get_data in -lpam""... $ac_c" 1>&6
-echo "configure:12539: checking for pam_get_data in -lpam" >&5
+echo "configure:12692: checking for pam_get_data in -lpam" >&5
 ac_lib_var=`echo pam'_'pam_get_data | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -12543,7 +12696,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lpam  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 12547 "configure"
+#line 12700 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -12554,7 +12707,7 @@ int main() {
 pam_get_data()
 ; return 0; }
 EOF
-if { (eval echo configure:12558: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:12711: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -12581,7 +12734,7 @@ fi
 #################################################
 # check for pam_smbpass support
 echo $ac_n "checking whether to use pam_smbpass""... $ac_c" 1>&6
-echo "configure:12585: checking whether to use pam_smbpass" >&5
+echo "configure:12738: checking whether to use pam_smbpass" >&5
 # Check whether --with-pam_smbpass or --without-pam_smbpass was given.
 if test "${with_pam_smbpass+set}" = set; then
   withval="$with_pam_smbpass"
 ###############################################
 # test for where we get crypt() from, but only
 # if not using PAM
-if test $with_pam_for_crypt = no; then
+if test x"$with_pam_for_crypt" = x"no"; then
 for ac_func in crypt
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:12623: checking for $ac_func" >&5
+echo "configure:12776: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 12628 "configure"
+#line 12781 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -12647,7 +12800,7 @@ $ac_func();
 
 ; return 0; }
 EOF
-if { (eval echo configure:12651: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:12804: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -12673,7 +12826,7 @@ done
 
 if test x"$ac_cv_func_crypt" = x"no"; then
     echo $ac_n "checking for crypt in -lcrypt""... $ac_c" 1>&6
-echo "configure:12677: checking for crypt in -lcrypt" >&5
+echo "configure:12830: checking for crypt in -lcrypt" >&5
 ac_lib_var=`echo crypt'_'crypt | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -12681,7 +12834,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lcrypt  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 12685 "configure"
+#line 12838 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -12692,7 +12845,7 @@ int main() {
 crypt()
 ; return 0; }
 EOF
-if { (eval echo configure:12696: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:12849: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -12727,7 +12880,7 @@ fi
 ##
 if test $with_pam_for_crypt = no; then
 echo $ac_n "checking for a crypt that needs truncated salt""... $ac_c" 1>&6
-echo "configure:12731: checking for a crypt that needs truncated salt" >&5
+echo "configure:12884: checking for a crypt that needs truncated salt" >&5
 if eval "test \"`echo '$''{'samba_cv_HAVE_TRUNCATED_SALT'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -12736,11 +12889,11 @@ if test "$cross_compiling" = yes; then
   samba_cv_HAVE_TRUNCATED_SALT=cross
 else
   cat > conftest.$ac_ext <<EOF
-#line 12740 "configure"
+#line 12893 "configure"
 #include "confdefs.h"
 #include "${srcdir-.}/tests/crypttest.c"
 EOF
-if { (eval echo configure:12744: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:12897: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   samba_cv_HAVE_TRUNCATED_SALT=no
 else
@@ -12763,6 +12916,30 @@ EOF
 fi
 fi
 
+# New experimental SAM system
+
+echo $ac_n "checking whether to build the new (experimental) SAM database""... $ac_c" 1>&6
+echo "configure:12923: checking whether to build the new (experimental) SAM database" >&5
+# Check whether --with-sam or --without-sam was given.
+if test "${with_sam+set}" = set; then
+  withval="$with_sam"
+   case "$withval" in
+  yes)
+    echo "$ac_t""yes" 1>&6
+    cat >> confdefs.h <<\EOF
+#define WITH_SAM 1
+EOF
+
+    ;;
+  *)
+    echo "$ac_t""no" 1>&6
+    ;;
+  esac 
+else
+  echo "$ac_t""no" 1>&6
+
+fi
+
 
 
 ########################################################################################
@@ -12774,7 +12951,7 @@ fi
 #################################################
 # check for a TDB password database
 echo $ac_n "checking whether to use TDB SAM database""... $ac_c" 1>&6
-echo "configure:12778: checking whether to use TDB SAM database" >&5
+echo "configure:12955: checking whether to use TDB SAM database" >&5
 # Check whether --with-tdbsam or --without-tdbsam was given.
 if test "${with_tdbsam+set}" = set; then
   withval="$with_tdbsam"
@@ -12799,7 +12976,7 @@ fi
 #################################################
 # check for a NISPLUS password database
 echo $ac_n "checking whether to use NISPLUS SAM database""... $ac_c" 1>&6
-echo "configure:12803: checking whether to use NISPLUS SAM database" >&5
+echo "configure:12980: checking whether to use NISPLUS SAM database" >&5
 # Check whether --with-nisplussam or --without-nisplussam was given.
 if test "${with_nisplussam+set}" = set; then
   withval="$with_nisplussam"
@@ -12830,7 +13007,7 @@ fi
 #################################################
 # check for a NISPLUS_HOME support 
 echo $ac_n "checking whether to use NISPLUS_HOME""... $ac_c" 1>&6
-echo "configure:12834: checking whether to use NISPLUS_HOME" >&5
+echo "configure:13011: checking whether to use NISPLUS_HOME" >&5
 # Check whether --with-nisplus-home or --without-nisplus-home was given.
 if test "${with_nisplus_home+set}" = set; then
   withval="$with_nisplus_home"
@@ -12855,7 +13032,7 @@ fi
 #################################################
 # check for syslog logging
 echo $ac_n "checking whether to use syslog logging""... $ac_c" 1>&6
-echo "configure:12859: checking whether to use syslog logging" >&5
+echo "configure:13036: checking whether to use syslog logging" >&5
 # Check whether --with-syslog or --without-syslog was given.
 if test "${with_syslog+set}" = set; then
   withval="$with_syslog"
@@ -12880,7 +13057,7 @@ fi
 #################################################
 # check for a shared memory profiling support
 echo $ac_n "checking whether to use profiling""... $ac_c" 1>&6
-echo "configure:12884: checking whether to use profiling" >&5
+echo "configure:13061: checking whether to use profiling" >&5
 # Check whether --with-profiling-data or --without-profiling-data was given.
 if test "${with_profiling_data+set}" = set; then
   withval="$with_profiling_data"
@@ -12908,7 +13085,7 @@ fi
 QUOTAOBJS=smbd/noquotas.o
 
 echo $ac_n "checking whether to support disk-quotas""... $ac_c" 1>&6
-echo "configure:12912: checking whether to support disk-quotas" >&5
+echo "configure:13089: checking whether to support disk-quotas" >&5
 # Check whether --with-quotas or --without-quotas was given.
 if test "${with_quotas+set}" = set; then
   withval="$with_quotas"
@@ -12919,13 +13096,13 @@ if test "${with_quotas+set}" = set; then
       *linux*)
         # Check for kernel 2.4.x quota braindamage...
         echo $ac_n "checking for linux 2.4.x quota braindamage..""... $ac_c" 1>&6
-echo "configure:12923: checking for linux 2.4.x quota braindamage.." >&5
+echo "configure:13100: checking for linux 2.4.x quota braindamage.." >&5
 if eval "test \"`echo '$''{'samba_cv_linux_2_4_quota_braindamage'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   
         cat > conftest.$ac_ext <<EOF
-#line 12929 "configure"
+#line 13106 "configure"
 #include "confdefs.h"
 #include <stdio.h>
 #include <sys/types.h>
@@ -12937,7 +13114,7 @@ int main() {
 struct mem_dqblk D;
 ; return 0; }
 EOF
-if { (eval echo configure:12941: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:13118: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   samba_cv_linux_2_4_quota_braindamage=yes
 else
@@ -12986,7 +13163,7 @@ fi
 # check for experimental utmp accounting
 
 echo $ac_n "checking whether to support utmp accounting""... $ac_c" 1>&6
-echo "configure:12990: checking whether to support utmp accounting" >&5
+echo "configure:13167: checking whether to support utmp accounting" >&5
 # Check whether --with-utmp or --without-utmp was given.
 if test "${with_utmp+set}" = set; then
   withval="$with_utmp"
@@ -13011,7 +13188,7 @@ fi
 #################################################
 # choose native language(s) of man pages
 echo $ac_n "checking chosen man pages' language(s)""... $ac_c" 1>&6
-echo "configure:13015: checking chosen man pages' language(s)" >&5
+echo "configure:13192: checking chosen man pages' language(s)" >&5
 # Check whether --with-manpages-langs or --without-manpages-langs was given.
 if test "${with_manpages_langs+set}" = set; then
   withval="$with_manpages_langs"
@@ -13042,7 +13219,7 @@ fi
 LIBSMBCLIENT_SHARED=
 LIBSMBCLIENT=
 echo $ac_n "checking whether to build the libsmbclient shared library""... $ac_c" 1>&6
-echo "configure:13046: checking whether to build the libsmbclient shared library" >&5
+echo "configure:13223: checking whether to build the libsmbclient shared library" >&5
 # Check whether --with-libsmbclient or --without-libsmbclient was given.
 if test "${with_libsmbclient+set}" = set; then
   withval="$with_libsmbclient"
 #################################################
 # these tests are taken from the GNU fileutils package
 echo "checking how to get filesystem space usage" 1>&6
-echo "configure:13074: checking how to get filesystem space usage" >&5
+echo "configure:13251: checking how to get filesystem space usage" >&5
 space=no
 
 # Test for statvfs64.
 if test $space = no; then
   # SVR4
   echo $ac_n "checking statvfs64 function (SVR4)""... $ac_c" 1>&6
-echo "configure:13081: checking statvfs64 function (SVR4)" >&5
+echo "configure:13258: checking statvfs64 function (SVR4)" >&5
 if eval "test \"`echo '$''{'fu_cv_sys_stat_statvfs64'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -13085,7 +13262,7 @@ else
   fu_cv_sys_stat_statvfs64=cross
 else
   cat > conftest.$ac_ext <<EOF
-#line 13089 "configure"
+#line 13266 "configure"
 #include "confdefs.h"
 
 #if defined(HAVE_UNISTD_H)
@@ -13099,7 +13276,7 @@ else
     exit (statvfs64 (".", &fsd));
   }
 EOF
-if { (eval echo configure:13103: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:13280: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   fu_cv_sys_stat_statvfs64=yes
 else
 if test $space = no; then
   # SVR4
   echo $ac_n "checking statvfs function (SVR4)""... $ac_c" 1>&6
-echo "configure:13136: checking statvfs function (SVR4)" >&5
+echo "configure:13313: checking statvfs function (SVR4)" >&5
 if eval "test \"`echo '$''{'fu_cv_sys_stat_statvfs'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 13141 "configure"
+#line 13318 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <sys/statvfs.h>
@@ -13145,7 +13322,7 @@ int main() {
 struct statvfs fsd; statvfs (0, &fsd);
 ; return 0; }
 EOF
-if { (eval echo configure:13149: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:13326: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   fu_cv_sys_stat_statvfs=yes
 else
@@ -13170,7 +13347,7 @@ fi
 if test $space = no; then
   # DEC Alpha running OSF/1
   echo $ac_n "checking for 3-argument statfs function (DEC OSF/1)""... $ac_c" 1>&6
-echo "configure:13174: checking for 3-argument statfs function (DEC OSF/1)" >&5
+echo "configure:13351: checking for 3-argument statfs function (DEC OSF/1)" >&5
   if eval "test \"`echo '$''{'fu_cv_sys_stat_statfs3_osf1'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -13178,7 +13355,7 @@ else
   fu_cv_sys_stat_statfs3_osf1=no
 else
   cat > conftest.$ac_ext <<EOF
-#line 13182 "configure"
+#line 13359 "configure"
 #include "confdefs.h"
 
 #include <sys/param.h>
@@ -13191,7 +13368,7 @@ else
     exit (statfs (".", &fsd, sizeof (struct statfs)));
   }
 EOF
-if { (eval echo configure:13195: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:13372: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   fu_cv_sys_stat_statfs3_osf1=yes
 else
@@ -13218,7 +13395,7 @@ fi
 if test $space = no; then
 # AIX
   echo $ac_n "checking for two-argument statfs with statfs.bsize member (AIX, 4.3BSD)""... $ac_c" 1>&6
-echo "configure:13222: checking for two-argument statfs with statfs.bsize member (AIX, 4.3BSD)" >&5
+echo "configure:13399: checking for two-argument statfs with statfs.bsize member (AIX, 4.3BSD)" >&5
   if eval "test \"`echo '$''{'fu_cv_sys_stat_statfs2_bsize'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -13226,7 +13403,7 @@ else
   fu_cv_sys_stat_statfs2_bsize=no
 else
   cat > conftest.$ac_ext <<EOF
-#line 13230 "configure"
+#line 13407 "configure"
 #include "confdefs.h"
 
 #ifdef HAVE_SYS_PARAM_H
@@ -13245,7 +13422,7 @@ else
   exit (statfs (".", &fsd));
   }
 EOF
-if { (eval echo configure:13249: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:13426: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   fu_cv_sys_stat_statfs2_bsize=yes
 else
@@ -13272,7 +13449,7 @@ fi
 if test $space = no; then
 # SVR3
   echo $ac_n "checking for four-argument statfs (AIX-3.2.5, SVR3)""... $ac_c" 1>&6
-echo "configure:13276: checking for four-argument statfs (AIX-3.2.5, SVR3)" >&5
+echo "configure:13453: checking for four-argument statfs (AIX-3.2.5, SVR3)" >&5
   if eval "test \"`echo '$''{'fu_cv_sys_stat_statfs4'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -13280,7 +13457,7 @@ else
   fu_cv_sys_stat_statfs4=no
 else
   cat > conftest.$ac_ext <<EOF
-#line 13284 "configure"
+#line 13461 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <sys/statfs.h>
@@ -13290,7 +13467,7 @@ else
   exit (statfs (".", &fsd, sizeof fsd, 0));
   }
 EOF
-if { (eval echo configure:13294: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:13471: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   fu_cv_sys_stat_statfs4=yes
 else
@@ -13317,7 +13494,7 @@ fi
 if test $space = no; then
 # 4.4BSD and NetBSD
   echo $ac_n "checking for two-argument statfs with statfs.fsize member (4.4BSD and NetBSD)""... $ac_c" 1>&6
-echo "configure:13321: checking for two-argument statfs with statfs.fsize member (4.4BSD and NetBSD)" >&5
+echo "configure:13498: checking for two-argument statfs with statfs.fsize member (4.4BSD and NetBSD)" >&5
   if eval "test \"`echo '$''{'fu_cv_sys_stat_statfs2_fsize'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -13325,7 +13502,7 @@ else
   fu_cv_sys_stat_statfs2_fsize=no
 else
   cat > conftest.$ac_ext <<EOF
-#line 13329 "configure"
+#line 13506 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #ifdef HAVE_SYS_PARAM_H
@@ -13341,7 +13518,7 @@ else
   exit (statfs (".", &fsd));
   }
 EOF
-if { (eval echo configure:13345: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:13522: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   fu_cv_sys_stat_statfs2_fsize=yes
 else
@@ -13368,7 +13545,7 @@ fi
 if test $space = no; then
   # Ultrix
   echo $ac_n "checking for two-argument statfs with struct fs_data (Ultrix)""... $ac_c" 1>&6
-echo "configure:13372: checking for two-argument statfs with struct fs_data (Ultrix)" >&5
+echo "configure:13549: checking for two-argument statfs with struct fs_data (Ultrix)" >&5
   if eval "test \"`echo '$''{'fu_cv_sys_stat_fs_data'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -13376,7 +13553,7 @@ else
   fu_cv_sys_stat_fs_data=no
 else
   cat > conftest.$ac_ext <<EOF
-#line 13380 "configure"
+#line 13557 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #ifdef HAVE_SYS_PARAM_H
@@ -13396,7 +13573,7 @@ else
   exit (statfs (".", &fsd) != 1);
   }
 EOF
-if { (eval echo configure:13400: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:13577: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   fu_cv_sys_stat_fs_data=yes
 else
@@ -13429,9 +13606,9 @@ fi
 # file support.
 #
 echo $ac_n "checking if large file support can be enabled""... $ac_c" 1>&6
-echo "configure:13433: checking if large file support can be enabled" >&5
+echo "configure:13610: checking if large file support can be enabled" >&5
 cat > conftest.$ac_ext <<EOF
-#line 13435 "configure"
+#line 13612 "configure"
 #include "confdefs.h"
 
 #if defined(HAVE_LONGLONG) && (defined(HAVE_OFF64_T) || (defined(SIZEOF_OFF_T) && (SIZEOF_OFF_T == 8)))
@@ -13444,7 +13621,7 @@ int main() {
 int i
 ; return 0; }
 EOF
-if { (eval echo configure:13448: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:13625: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   samba_cv_HAVE_EXPLICIT_LARGEFILE_SUPPORT=yes
 else
@@ -13509,7 +13686,7 @@ fi
 # check for ACL support
 
 echo $ac_n "checking whether to support ACLs""... $ac_c" 1>&6
-echo "configure:13513: checking whether to support ACLs" >&5
+echo "configure:13690: checking whether to support ACLs" >&5
 # Check whether --with-acl-support or --without-acl-support was given.
 if test "${with_acl_support+set}" = set; then
   withval="$with_acl_support"
@@ -13562,7 +13739,7 @@ EOF
                ;;
         *)
                echo $ac_n "checking for acl_get_file in -lacl""... $ac_c" 1>&6
-echo "configure:13566: checking for acl_get_file in -lacl" >&5
+echo "configure:13743: checking for acl_get_file in -lacl" >&5
 ac_lib_var=`echo acl'_'acl_get_file | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -13570,7 +13747,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lacl  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 13574 "configure"
+#line 13751 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -13581,7 +13758,7 @@ int main() {
 acl_get_file()
 ; return 0; }
 EOF
-if { (eval echo configure:13585: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:13762: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -13609,13 +13786,13 @@ else
 fi
 
                echo $ac_n "checking for ACL support""... $ac_c" 1>&6
-echo "configure:13613: checking for ACL support" >&5
+echo "configure:13790: checking for ACL support" >&5
 if eval "test \"`echo '$''{'samba_cv_HAVE_POSIX_ACLS'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   
                cat > conftest.$ac_ext <<EOF
-#line 13619 "configure"
+#line 13796 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <sys/acl.h>
@@ -13623,7 +13800,7 @@ int main() {
  acl_t acl; int entry_id; acl_entry_t *entry_p; return acl_get_entry( acl, entry_id, entry_p);
 ; return 0; }
 EOF
-if { (eval echo configure:13627: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:13804: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   samba_cv_HAVE_POSIX_ACLS=yes
 else
@@ -13643,13 +13820,13 @@ echo "$ac_t""$samba_cv_HAVE_POSIX_ACLS" 1>&6
 EOF
 
                                echo $ac_n "checking for acl_get_perm_np""... $ac_c" 1>&6
-echo "configure:13647: checking for acl_get_perm_np" >&5
+echo "configure:13824: checking for acl_get_perm_np" >&5
 if eval "test \"`echo '$''{'samba_cv_HAVE_ACL_GET_PERM_NP'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   
                                cat > conftest.$ac_ext <<EOF
-#line 13653 "configure"
+#line 13830 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <sys/acl.h>
@@ -13657,7 +13834,7 @@ int main() {
  acl_permset_t permset_d; acl_perm_t perm; return acl_get_perm_np( permset_d, perm);
 ; return 0; }
 EOF
-if { (eval echo configure:13661: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:13838: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   samba_cv_HAVE_ACL_GET_PERM_NP=yes
 else
 fi
 
 
+#################################################
+# check for sendfile support
+
+echo $ac_n "checking whether to support sendfile""... $ac_c" 1>&6
+echo "configure:13883: checking whether to support sendfile" >&5
+# Check whether --with-sendfile-support or --without-sendfile-support was given.
+if test "${with_sendfile_support+set}" = set; then
+  withval="$with_sendfile_support"
+   case "$withval" in
+  yes)
+
+       case "$host_os" in
+       *linux*)
+               echo $ac_n "checking for linux sendfile64 support""... $ac_c" 1>&6
+echo "configure:13893: checking for linux sendfile64 support" >&5
+if eval "test \"`echo '$''{'samba_cv_HAVE_SENDFILE64'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  
+               cat > conftest.$ac_ext <<EOF
+#line 13899 "configure"
+#include "confdefs.h"
+#include <sys/sendfile.h>
+int main() {
+\
+int tofd, fromfd;
+off64_t offset;
+size_t total;
+ssize_t nwritten = sendfile64(tofd, fromfd, &offset, total);
+
+; return 0; }
+EOF
+if { (eval echo configure:13911: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  samba_cv_HAVE_SENDFILE64=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  samba_cv_HAVE_SENDFILE64=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$samba_cv_HAVE_SENDFILE64" 1>&6
+
+               echo $ac_n "checking for linux sendfile support""... $ac_c" 1>&6
+echo "configure:13926: checking for linux sendfile support" >&5
+if eval "test \"`echo '$''{'samba_cv_HAVE_SENDFILE'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  
+               cat > conftest.$ac_ext <<EOF
+#line 13932 "configure"
+#include "confdefs.h"
+#include <sys/sendfile.h>
+int main() {
+\
+int tofd, fromfd;
+off_t offset;
+size_t total;
+ssize_t nwritten = sendfile(tofd, fromfd, &offset, total);
+
+; return 0; }
+EOF
+if { (eval echo configure:13944: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  samba_cv_HAVE_SENDFILE=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  samba_cv_HAVE_SENDFILE=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$samba_cv_HAVE_SENDFILE" 1>&6
+
+# Try and cope with broken Linux sendfile....
+               echo $ac_n "checking for broken linux sendfile support""... $ac_c" 1>&6
+echo "configure:13960: checking for broken linux sendfile support" >&5
+if eval "test \"`echo '$''{'samba_cv_HAVE_BROKEN_LINUX_SENDFILE'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  
+               cat > conftest.$ac_ext <<EOF
+#line 13966 "configure"
+#include "confdefs.h"
+\
+#if defined(_FILE_OFFSET_BITS) && (_FILE_OFFSET_BITS == 64)
+#undef _FILE_OFFSET_BITS
+#endif
+#include <sys/sendfile.h>
+int main() {
+\
+int tofd, fromfd;
+off_t offset;
+size_t total;
+ssize_t nwritten = sendfile(tofd, fromfd, &offset, total);
+
+; return 0; }
+EOF
+if { (eval echo configure:13982: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  samba_cv_HAVE_BROKEN_LINUX_SENDFILE=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  samba_cv_HAVE_BROKEN_LINUX_SENDFILE=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$samba_cv_HAVE_BROKEN_LINUX_SENDFILE" 1>&6
+
+       if test x"$samba_cv_HAVE_SENDFILE64" = x"yes"; then
+               cat >> confdefs.h <<\EOF
+#define HAVE_SENDFILE64 1
+EOF
+
+               cat >> confdefs.h <<\EOF
+#define LINUX_SENDFILE_API 1
+EOF
+
+               cat >> confdefs.h <<\EOF
+#define WITH_SENDFILE 1
+EOF
+
+       elif test x"$samba_cv_HAVE_SENDFILE" = x"yes"; then
+               cat >> confdefs.h <<\EOF
+#define HAVE_SENDFILE 1
+EOF
+
+               cat >> confdefs.h <<\EOF
+#define LINUX_SENDFILE_API 1
+EOF
+
+               cat >> confdefs.h <<\EOF
+#define WITH_SENDFILE 1
+EOF
+
+       elif test x"$samba_cv_HAVE_BROKEN_LINUX_SENDFILE" = x"yes"; then
+               cat >> confdefs.h <<\EOF
+#define LINUX_BROKEN_SENDFILE_API 1
+EOF
+
+               cat >> confdefs.h <<\EOF
+#define WITH_SENDFILE 1
+EOF
+
+       else
+               echo "$ac_t""no" 1>&6;
+       fi
+
+       ;;
+       *freebsd*)
+               echo $ac_n "checking for freebsd sendfile support""... $ac_c" 1>&6
+echo "configure:14038: checking for freebsd sendfile support" >&5
+if eval "test \"`echo '$''{'samba_cv_HAVE_SENDFILE'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  
+               cat > conftest.$ac_ext <<EOF
+#line 14044 "configure"
+#include "confdefs.h"
+\
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+int main() {
+\
+       int fromfd, tofd;
+       off_t offset, nwritten;
+       struct sf_hdtr hdr;
+       struct iovec hdtrl;
+       hdr->headers = &hdtrl;
+       hdr->hdr_cnt = 1;
+       hdr->trailers = NULL;
+       hdr->trl_cnt = 0;
+       hdtrl.iov_base = NULL;
+       hdtrl.iov_len = 0;
+       int ret = sendfile(fromfd, tofd, offset, total, &hdr, &nwritten, 0);
+
+; return 0; }
+EOF
+if { (eval echo configure:14066: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  samba_cv_HAVE_SENDFILE=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  samba_cv_HAVE_SENDFILE=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$samba_cv_HAVE_SENDFILE" 1>&6
+
+       if test x"$samba_cv_HAVE_SENDFILE" = x"yes"; then
+               cat >> confdefs.h <<\EOF
+#define HAVE_SENDFILE 1
+EOF
+
+               cat >> confdefs.h <<\EOF
+#define FREEBSD_SENDFILE_API 1
+EOF
+
+               cat >> confdefs.h <<\EOF
+#define WITH_SENDFILE 1
+EOF
+
+       else
+               echo "$ac_t""no" 1>&6;
+       fi
+       ;;
+
+       *hpux*)
+               echo $ac_n "checking for hpux sendfile64 support""... $ac_c" 1>&6
+echo "configure:14100: checking for hpux sendfile64 support" >&5
+if eval "test \"`echo '$''{'samba_cv_HAVE_SENDFILE64'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  
+               cat > conftest.$ac_ext <<EOF
+#line 14106 "configure"
+#include "confdefs.h"
+\
+#include <sys/socket.h>
+#include <sys/uio.h>
+int main() {
+\
+       int fromfd, tofd;
+       size_t total=0;
+       struct iovec hdtrl[2];
+       ssize_t nwritten;
+       off64_t offset;
+
+       hdtrl[0].iov_base = 0;
+       hdtrl[0].iov_len = 0;
+
+       nwritten = sendfile64(tofd, fromfd, offset, total, &hdtrl[0], 0);
+
+; return 0; }
+EOF
+if { (eval echo configure:14126: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  samba_cv_HAVE_SENDFILE64=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  samba_cv_HAVE_SENDFILE64=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$samba_cv_HAVE_SENDFILE64" 1>&6
+       if test x"$samba_cv_HAVE_SENDFILE64" = x"yes"; then
+               cat >> confdefs.h <<\EOF
+#define HAVE_SENDFILE64 1
+EOF
+
+               cat >> confdefs.h <<\EOF
+#define HPUX_SENDFILE_API 1
+EOF
+
+               cat >> confdefs.h <<\EOF
+#define WITH_SENDFILE 1
+EOF
+
+       else
+               echo "$ac_t""no" 1>&6;
+       fi
+
+               echo $ac_n "checking for hpux sendfile support""... $ac_c" 1>&6
+echo "configure:14157: checking for hpux sendfile support" >&5
+if eval "test \"`echo '$''{'samba_cv_HAVE_SENDFILE'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  
+               cat > conftest.$ac_ext <<EOF
+#line 14163 "configure"
+#include "confdefs.h"
+\
+#include <sys/socket.h>
+#include <sys/uio.h>
+int main() {
+\
+       int fromfd, tofd;
+       size_t total=0;
+       struct iovec hdtrl[2];
+       ssize_t nwritten;
+       off_t offset;
+
+       hdtrl[0].iov_base = 0;
+       hdtrl[0].iov_len = 0;
+
+       nwritten = sendfile(tofd, fromfd, offset, total, &hdtrl[0], 0);
+
+; return 0; }
+EOF
+if { (eval echo configure:14183: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+  rm -rf conftest*
+  samba_cv_HAVE_SENDFILE=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  samba_cv_HAVE_SENDFILE=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$samba_cv_HAVE_SENDFILE" 1>&6
+       if test x"$samba_cv_HAVE_SENDFILE" = x"yes"; then
+               cat >> confdefs.h <<\EOF
+#define HAVE_SENDFILE 1
+EOF
+
+               cat >> confdefs.h <<\EOF
+#define HPUX_SENDFILE_API 1
+EOF
+
+               cat >> confdefs.h <<\EOF
+#define WITH_SENDFILE 1
+EOF
+
+       else
+               echo "$ac_t""no" 1>&6;
+       fi
+
+       ;;
+
+       *)
+       ;;
+        esac
+        ;;
+  *)
+    echo "$ac_t""no" 1>&6
+    ;;
+  esac 
+else
+  echo "$ac_t""no" 1>&6
+
+fi
+
+
+
 #################################################
 # Check whether winbind is supported on this platform.  If so we need to
 # build and install client programs (WINBIND_TARGETS), sbin programs
 # (WINBIND_STARGETS) and shared libraries (WINBIND_LTARGETS).
 
 echo $ac_n "checking whether to build winbind""... $ac_c" 1>&6
-echo "configure:13708: checking whether to build winbind" >&5
+echo "configure:14236: checking whether to build winbind" >&5
 
 # Initially, the value of $host_os decides whether winbind is supported
 
 #              [#include <pwd.h>])
 
 echo $ac_n "checking whether struct passwd has pw_comment""... $ac_c" 1>&6
-echo "configure:13804: checking whether struct passwd has pw_comment" >&5
+echo "configure:14332: checking whether struct passwd has pw_comment" >&5
 if eval "test \"`echo '$''{'samba_cv_passwd_pw_comment'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   
     cat > conftest.$ac_ext <<EOF
-#line 13810 "configure"
+#line 14338 "configure"
 #include "confdefs.h"
 #include <pwd.h>
 int main() {
 struct passwd p; p.pw_comment;
 ; return 0; }
 EOF
-if { (eval echo configure:13817: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:14345: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   samba_cv_passwd_pw_comment=yes
 else
 #              [#include <pwd.h>])
 
 echo $ac_n "checking whether struct passwd has pw_age""... $ac_c" 1>&6
-echo "configure:13842: checking whether struct passwd has pw_age" >&5
+echo "configure:14370: checking whether struct passwd has pw_age" >&5
 if eval "test \"`echo '$''{'samba_cv_passwd_pw_age'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   
     cat > conftest.$ac_ext <<EOF
-#line 13848 "configure"
+#line 14376 "configure"
 #include "confdefs.h"
 #include <pwd.h>
 int main() {
 struct passwd p; p.pw_age;
 ; return 0; }
 EOF
-if { (eval echo configure:13855: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:14383: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   samba_cv_passwd_pw_age=yes
 else
@@ -13890,7 +14418,7 @@ fi
 
 if test x"$INCLUDED_POPT" != x"yes"; then
     echo $ac_n "checking for poptGetContext in -lpopt""... $ac_c" 1>&6
-echo "configure:13894: checking for poptGetContext in -lpopt" >&5
+echo "configure:14422: checking for poptGetContext in -lpopt" >&5
 ac_lib_var=`echo popt'_'poptGetContext | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -13898,7 +14426,7 @@ else
   ac_save_LIBS="$LIBS"
 LIBS="-lpopt  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 13902 "configure"
+#line 14430 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -13909,7 +14437,7 @@ int main() {
 poptGetContext()
 ; return 0; }
 EOF
-if { (eval echo configure:13913: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:14441: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -13933,7 +14461,7 @@ fi
 fi
 
 echo $ac_n "checking whether to use included popt""... $ac_c" 1>&6
-echo "configure:13937: checking whether to use included popt" >&5
+echo "configure:14465: checking whether to use included popt" >&5
 if test x"$INCLUDED_POPT" = x"yes"; then
     echo "$ac_t""yes" 1>&6
     BUILD_POPT='$(POPT_OBJS)'
 
 
 
+#################################################
+# Check if the user wants Python
+
+# At the moment, you can use this to set which Python binary to link
+# against.  (Libraries built for Python2.2 can't be used by 2.1,
+# though they can coexist in different directories.)  In the future
+# this might make the Python stuff be built by default.
+
+# Check whether --with-python or --without-python was given.
+if test "${with_python+set}" = set; then
+  withval="$with_python"
+   case "${withval-python}" in
+  yes)
+       PYTHON=python
+       ;;
+  *)
+       PYTHON=${withval-python}
+       ;;
+  esac 
+fi
+
+
+
 #################################################
 # do extra things if we are running insure
 
 # final configure stuff
 
 echo $ac_n "checking configure summary""... $ac_c" 1>&6
-echo "configure:13960: checking configure summary" >&5
+echo "configure:14511: checking configure summary" >&5
 if test "$cross_compiling" = yes; then
   echo "configure: warning: cannot run when cross-compiling" 1>&2
 else
   cat > conftest.$ac_ext <<EOF
-#line 13965 "configure"
+#line 14516 "configure"
 #include "confdefs.h"
 #include "${srcdir-.}/tests/summary.c"
 EOF
-if { (eval echo configure:13969: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:14520: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
 then
   echo "$ac_t""yes" 1>&6
 else
@@ -13981,6 +14532,9 @@ fi
 builddir=`pwd`
 
 
+# I added make files that are outside /source directory.
+# I know this is not a good solution, will work out a better
+# solution soon.                       --simo
 trap '' 1 2 15
 cat > confcache <<\EOF
 # This file is a shell script that caches the results of configure
@@ -14082,7 +14636,7 @@ done
 ac_given_srcdir=$srcdir
 ac_given_INSTALL="$INSTALL"
 
-trap 'rm -fr `echo "include/stamp-h Makefile script/findsmb ../examples/VFS/Makefile ../examples/VFS/block/Makefile include/config.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
+trap 'rm -fr `echo "include/stamp-h Makefile script/findsmb ../examples/VFS/Makefile ../examples/pdb/mysql/Makefile ../examples/pdb/xml/Makefile ../examples/sam/Makefile include/config.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
 EOF
 cat >> $CONFIG_STATUS <<EOF
 
@@ -14136,6 +14690,7 @@ s%@POBAD_CC@%$POBAD_CC%g
 s%@SHLIBEXT@%$SHLIBEXT%g
 s%@LIBSMBCLIENT_SHARED@%$LIBSMBCLIENT_SHARED%g
 s%@LIBSMBCLIENT@%$LIBSMBCLIENT%g
+s%@PRINTLIBS@%$PRINTLIBS%g
 s%@CC@%$CC%g
 s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g
 s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g
@@ -14174,6 +14729,7 @@ s%@WINBIND_NSS_EXTRA_OBJS@%$WINBIND_NSS_EXTRA_OBJS%g
 s%@WINBIND_NSS_EXTRA_LIBS@%$WINBIND_NSS_EXTRA_LIBS%g
 s%@BUILD_POPT@%$BUILD_POPT%g
 s%@FLAGS1@%$FLAGS1%g
+s%@PYTHON@%$PYTHON%g
 s%@builddir@%$builddir%g
 
 CEOF
@@ -14216,7 +14772,7 @@ EOF
 
 cat >> $CONFIG_STATUS <<EOF
 
-CONFIG_FILES=\${CONFIG_FILES-"include/stamp-h Makefile script/findsmb ../examples/VFS/Makefile ../examples/VFS/block/Makefile"}
+CONFIG_FILES=\${CONFIG_FILES-"include/stamp-h Makefile script/findsmb ../examples/VFS/Makefile ../examples/pdb/mysql/Makefile ../examples/pdb/xml/Makefile ../examples/sam/Makefile"}
 EOF
 cat >> $CONFIG_STATUS <<\EOF
 for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
index db34c266c584a72442e06b518b066e1e8da48638..5221b8ec2b4279ef91d5ed6f384d160ec9372e4f 100644 (file)
@@ -147,6 +147,7 @@ AC_SUBST(POBAD_CC)
 AC_SUBST(SHLIBEXT)
 AC_SUBST(LIBSMBCLIENT_SHARED)
 AC_SUBST(LIBSMBCLIENT)
+AC_SUBST(PRINTLIBS)
 
 # compile with optimization and without debugging by default
 CFLAGS="-O ${CFLAGS}"
@@ -431,6 +432,7 @@ AC_CHECK_HEADERS(sys/mman.h sys/filio.h sys/priv.h sys/shm.h string.h strings.h
 AC_CHECK_HEADERS(sys/mount.h sys/vfs.h sys/fs/s5param.h sys/filsys.h termios.h termio.h)
 AC_CHECK_HEADERS(sys/termio.h sys/statfs.h sys/dustat.h sys/statvfs.h stdarg.h sys/sockio.h)
 AC_CHECK_HEADERS(security/pam_modules.h security/_pam_macros.h ldap.h lber.h dlfcn.h)
+AC_CHECK_HEADERS(sys/syslog.h syslog.h)
 
 #
 # HPUX has a bug in that including shadow.h causes a re-definition of MAXINT.
@@ -496,7 +498,7 @@ if test x$enable_cups != xno; then
                         AC_DEFINE(HAVE_CUPS)
                CFLAGS="$CFLAGS `$CUPS_CONFIG --cflags`"
                LDFLAGS="$LDFLAGS `$CUPS_CONFIG --ldflags`"
-               LIBS="$LIBS `$CUPS_CONFIG --libs`"
+               PRINTLIBS="$PRINTLIBS `$CUPS_CONFIG --libs`"
         fi
 fi
 
@@ -894,7 +896,14 @@ case "$host_os" in
                        SONAMEFLAG="-Wl,-h,"
                        PICFLAG="-KPIC"   # Is this correct for SunOS
                ;;
-               *bsd*)  BLDSHARED="true"
+               *freebsd*)  BLDSHARED="true"
+                       LDSHFLAGS="-shared"
+                       DYNEXP="-Wl,--export-dynamic"
+                       SONAMEFLAG="-Wl,-soname,"
+                       PICFLAG="-fPIC -DPIC"
+                       AC_DEFINE(STAT_ST_BLOCKSIZE,512)
+               ;;
+               *openbsd*)  BLDSHARED="true"
                        LDSHFLAGS="-shared"
                        DYNEXP="-Wl,-Bdynamic"
                        SONAMEFLAG="-Wl,-soname,"
@@ -922,12 +931,10 @@ case "$host_os" in
                        BLDSHARED="true"
                        LDSHFLAGS="-Wl,-bexpall,-bM:SRE,-bnoentry"
                        DYNEXP="-Wl,-brtl,-bexpall"
-                       if test "${GCC}" = "yes"; then
-                               PICFLAG="-O2"
-                       else
-                       PICFLAG="-O2 -qmaxmem=6000"
+                       PICFLAG="-O2"
+                       if test "${GCC}" != "yes"; then
                                ## for funky AIX compiler using strncpy()
-                               CFLAGS="$CFLAGS -D_LINUX_SOURCE_COMPAT"
+                               CFLAGS="$CFLAGS -D_LINUX_SOURCE_COMPAT -qmaxmem=32000"
                        fi
 
                        AC_DEFINE(STAT_ST_BLOCKSIZE,DEV_BSIZE)
@@ -1820,6 +1827,16 @@ if test x"$samba_cv_HAVE_STAT_ST_BLOCKS" = x"yes"; then
     AC_DEFINE(HAVE_STAT_ST_BLOCKS)
 fi 
 
+AC_CACHE_CHECK([for st_blksize in struct stat],samba_cv_HAVE_STAT_ST_BLKSIZE,[
+AC_TRY_COMPILE([#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>],
+[struct stat st;  st.st_blksize = 0;],
+samba_cv_HAVE_STAT_ST_BLKSIZE=yes,samba_cv_HAVE_STAT_ST_BLKSIZE=no,samba_cv_HAVE_STAT_ST_BLKSIZE=cross)])
+if test x"$samba_cv_HAVE_STAT_ST_BLKSIZE" = x"yes"; then
+    AC_DEFINE(HAVE_STAT_ST_BLKSIZE)
+fi
+
 case "$host_os" in
 *linux*)
 AC_CACHE_CHECK([for broken RedHat 7.2 system header files],samba_cv_BROKEN_REDHAT_7_SYSTEM_HEADERS,[
@@ -1924,7 +1941,52 @@ AC_ARG_WITH(dfs,
   AC_MSG_RESULT(no)
 )
 
+#################################################
+# active directory support
+
+with_ads_support=yes
+AC_MSG_CHECKING([whether to use Active Directory])
 
+AC_ARG_WITH(ads,
+[   --with-ads  Active Directory support (default yes)],
+[ case "$withval" in
+    no)
+       with_ads_support=no
+       ;;
+  esac ])
+
+if test x"$with_ads_support" = x"yes"; then
+   AC_DEFINE(WITH_ADS)
+fi
+
+AC_MSG_RESULT($with_ads_support)
+
+FOUND_KRB5=no
+if test x"$with_ads_support" = x"yes"; then
+
+  #################################################
+  # check for location of Kerberos 5 install
+  AC_MSG_CHECKING(for kerberos 5 install path)
+  AC_ARG_WITH(krb5,
+  [  --with-krb5=base-dir    Locate Kerberos 5 support (default=/usr)],
+  [ case "$withval" in
+    no)
+      AC_MSG_RESULT(no)
+      ;;
+    *)
+      AC_MSG_RESULT(yes)
+      LIBS="$LIBS -lkrb5"
+      CFLAGS="$CFLAGS -I$withval/include"
+      CPPFLAGS="$CPPFLAGS -I$withval/include"
+      LDFLAGS="$LDFLAGS -L$withval/lib"
+      FOUND_KRB5=yes
+      ;;
+    esac ],
+    AC_MSG_RESULT(no)
+  )
+
+
+if test x$FOUND_KRB5 = x"no"; then
 #################################################
 # see if this box has the RedHat location for kerberos
 AC_MSG_CHECKING(for /usr/kerberos)
@@ -1936,61 +1998,62 @@ if test -d /usr/kerberos; then
 else
     AC_MSG_RESULT(no)
 fi
+fi
 
-#################################################
-# check for location of Kerberos 5 install
-AC_MSG_CHECKING(for kerberos 5 install path)
-AC_ARG_WITH(krb5,
-[  --with-krb5=base-dir    Locate Kerberos 5 support (default=/usr)],
-[ case "$withval" in
-  no)
-    AC_MSG_RESULT(no)
-    ;;
-  *)
-    AC_MSG_RESULT(yes)
-    LIBS="$LIBS -lkrb5"
-    CFLAGS="$CFLAGS -I$withval/include"
-    CPPFLAGS="$CPPFLAGS -I$withval/include"
-    LDFLAGS="$LDFLAGS -L$withval/lib"
-    ;;
-  esac ],
-  AC_MSG_RESULT(no)
-)
 
-# now check for krb5.h. Some systems have the libraries without the headers!
-# note that this check is done here to allow for different kerberos
-# include paths
-AC_CHECK_HEADERS(krb5.h)
+  # now check for krb5.h. Some systems have the libraries without the headers!
+  # note that this check is done here to allow for different kerberos
+  # include paths
+  AC_CHECK_HEADERS(krb5.h)
 
-# now check for gssapi headers.  This is also done here to allow for
-# different kerberos include paths
-AC_CHECK_HEADERS(gssapi/gssapi_generic.h gssapi/gssapi.h)
+  # now check for gssapi headers.  This is also done here to allow for
+  # different kerberos include paths
+  AC_CHECK_HEADERS(gssapi/gssapi_generic.h gssapi/gssapi.h)
 
-##################################################################
-# we might need the k5crypto and com_err libraries on some systems
-AC_CHECK_LIB(com_err, _et_list, [LIBS="$LIBS -lcom_err"])
-AC_CHECK_LIB(k5crypto, krb5_encrypt_data, [LIBS="$LIBS -lk5crypto"])
+  ##################################################################
+  # we might need the k5crypto and com_err libraries on some systems
+  AC_CHECK_LIB(com_err, _et_list, [LIBS="$LIBS -lcom_err"])
+  AC_CHECK_LIB(k5crypto, krb5_encrypt_data, [LIBS="$LIBS -lk5crypto"])
 
-########################################################
-# now see if we can find the krb5 libs in standard paths
-# or as specified above
-AC_CHECK_LIB(krb5, krb5_mk_req_extended, [LIBS="$LIBS -lkrb5";
+  ########################################################
+  # now see if we can find the krb5 libs in standard paths
+  # or as specified above
+  AC_CHECK_LIB(krb5, krb5_mk_req_extended, [LIBS="$LIBS -lkrb5";
        AC_DEFINE(HAVE_KRB5)])
 
-########################################################
-# now see if we can find the gssapi libs in standard paths
-AC_CHECK_LIB(gssapi_krb5, gss_display_status, [LIBS="$LIBS -lgssapi_krb5";
+  ########################################################
+  # now see if we can find the gssapi libs in standard paths
+  AC_CHECK_LIB(gssapi_krb5, gss_display_status, [LIBS="$LIBS -lgssapi_krb5";
        AC_DEFINE(HAVE_GSSAPI)])
-
-##################################################################
-# we might need the lber lib on some systems. To avoid link errors
-# this test must be before the libldap test
-AC_CHECK_LIB(lber, ber_scanf, [LIBS="$LIBS -llber"])
+fi
 
 ########################################################
-# now see if we can find the ldap libs in standard paths
-if test x$have_ldap != xyes; then
-AC_CHECK_LIB(ldap, ldap_domain2hostlist, [LIBS="$LIBS -lldap";
+# Compile with LDAP support?
+
+with_ldap_support=yes
+AC_MSG_CHECKING([whether to use LDAP])
+
+AC_ARG_WITH(ldap,
+[   --with-ldap  LDAP support (default yes)],
+[ case "$withval" in
+    no)
+       with_ldap_support=no
+       ;;
+  esac ])
+
+AC_MSG_RESULT($with_ldap_support)
+
+if test x"$with_ldap_support" = x"yes"; then
+
+  ##################################################################
+  # we might need the lber lib on some systems. To avoid link errors
+  # this test must be before the libldap test
+  AC_CHECK_LIB(lber, ber_scanf, [LIBS="$LIBS -llber"])
+
+  ########################################################
+  # now see if we can find the ldap libs in standard paths
+  if test x$have_ldap != xyes; then
+  AC_CHECK_LIB(ldap, ldap_domain2hostlist, [LIBS="$LIBS -lldap";
        AC_DEFINE(HAVE_LDAP)])
 
        ########################################################
@@ -2002,6 +2065,7 @@ AC_CHECK_LIB(ldap, ldap_domain2hostlist, [LIBS="$LIBS -lldap";
        #include <lber.h>
        #include <ldap.h>], [ldap_set_rebind_proc(0, 0, 0);], [pam_ldap_cv_ldap_set_rebind_proc=3], [pam_ldap_cv_ldap_set_rebind_proc=2]) ])
        AC_DEFINE_UNQUOTED(LDAP_SET_REBIND_PROC_ARGS, $pam_ldap_cv_ldap_set_rebind_proc)
+  fi
 fi
 
 #################################################
@@ -2104,7 +2168,7 @@ AC_ARG_WITH(pam_smbpass,
 ###############################################
 # test for where we get crypt() from, but only
 # if not using PAM
-if test $with_pam_for_crypt = no; then
+if test x"$with_pam_for_crypt" = x"no"; then
 AC_CHECK_FUNCS(crypt)
 if test x"$ac_cv_func_crypt" = x"no"; then
     AC_CHECK_LIB(crypt, crypt, [LIBS="$LIBS -lcrypt";
@@ -2127,6 +2191,22 @@ if test x"$samba_cv_HAVE_TRUNCATED_SALT" = x"yes"; then
 fi
 fi
 
+# New experimental SAM system
+
+AC_MSG_CHECKING([whether to build the new (experimental) SAM database])
+AC_ARG_WITH(sam,
+[  --with-sam              Build new (experimental) SAM database (default=no)],
+[ case "$withval" in
+  yes)
+    AC_MSG_RESULT(yes)
+    AC_DEFINE(WITH_SAM)
+    ;;
+  *)
+    AC_MSG_RESULT(no)
+    ;;
+  esac ],
+  AC_MSG_RESULT(no)
+)
 
 
 ########################################################################################
@@ -2633,6 +2713,163 @@ samba_cv_HAVE_ACL_GET_PERM_NP=yes,samba_cv_HAVE_ACL_GET_PERM_NP=no)])
   AC_MSG_RESULT(no)
 )
 
+#################################################
+# check for sendfile support
+
+AC_MSG_CHECKING(whether to support sendfile)
+AC_ARG_WITH(sendfile-support,
+[  --with-sendfile-support      Include sendfile support (default=no)],
+[ case "$withval" in
+  yes)
+
+       case "$host_os" in
+       *linux*)
+               AC_CACHE_CHECK([for linux sendfile64 support],samba_cv_HAVE_SENDFILE64,[
+               AC_TRY_LINK([#include <sys/sendfile.h>],
+[\
+int tofd, fromfd;
+off64_t offset;
+size_t total;
+ssize_t nwritten = sendfile64(tofd, fromfd, &offset, total);
+],
+samba_cv_HAVE_SENDFILE64=yes,samba_cv_HAVE_SENDFILE64=no)])
+
+               AC_CACHE_CHECK([for linux sendfile support],samba_cv_HAVE_SENDFILE,[
+               AC_TRY_LINK([#include <sys/sendfile.h>],
+[\
+int tofd, fromfd;
+off_t offset;
+size_t total;
+ssize_t nwritten = sendfile(tofd, fromfd, &offset, total);
+],
+samba_cv_HAVE_SENDFILE=yes,samba_cv_HAVE_SENDFILE=no)])
+
+# Try and cope with broken Linux sendfile....
+               AC_CACHE_CHECK([for broken linux sendfile support],samba_cv_HAVE_BROKEN_LINUX_SENDFILE,[
+               AC_TRY_LINK([\
+#if defined(_FILE_OFFSET_BITS) && (_FILE_OFFSET_BITS == 64)
+#undef _FILE_OFFSET_BITS
+#endif
+#include <sys/sendfile.h>],
+[\
+int tofd, fromfd;
+off_t offset;
+size_t total;
+ssize_t nwritten = sendfile(tofd, fromfd, &offset, total);
+],
+samba_cv_HAVE_BROKEN_LINUX_SENDFILE=yes,samba_cv_HAVE_BROKEN_LINUX_SENDFILE=no)])
+
+       if test x"$samba_cv_HAVE_SENDFILE64" = x"yes"; then
+               AC_DEFINE(HAVE_SENDFILE64)
+               AC_DEFINE(LINUX_SENDFILE_API)
+               AC_DEFINE(WITH_SENDFILE)
+       elif test x"$samba_cv_HAVE_SENDFILE" = x"yes"; then
+               AC_DEFINE(HAVE_SENDFILE)
+               AC_DEFINE(LINUX_SENDFILE_API)
+               AC_DEFINE(WITH_SENDFILE)
+       elif test x"$samba_cv_HAVE_BROKEN_LINUX_SENDFILE" = x"yes"; then
+               AC_DEFINE(LINUX_BROKEN_SENDFILE_API)
+               AC_DEFINE(WITH_SENDFILE)
+       else
+               AC_MSG_RESULT(no);
+       fi
+
+       ;;
+       *freebsd*)
+               AC_CACHE_CHECK([for freebsd sendfile support],samba_cv_HAVE_SENDFILE,[
+               AC_TRY_LINK([\
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/uio.h>],
+[\
+       int fromfd, tofd;
+       off_t offset, nwritten;
+       struct sf_hdtr hdr;
+       struct iovec hdtrl;
+       hdr->headers = &hdtrl;
+       hdr->hdr_cnt = 1;
+       hdr->trailers = NULL;
+       hdr->trl_cnt = 0;
+       hdtrl.iov_base = NULL;
+       hdtrl.iov_len = 0;
+       int ret = sendfile(fromfd, tofd, offset, total, &hdr, &nwritten, 0);
+],
+samba_cv_HAVE_SENDFILE=yes,samba_cv_HAVE_SENDFILE=no)])
+
+       if test x"$samba_cv_HAVE_SENDFILE" = x"yes"; then
+               AC_DEFINE(HAVE_SENDFILE)
+               AC_DEFINE(FREEBSD_SENDFILE_API)
+               AC_DEFINE(WITH_SENDFILE)
+       else
+               AC_MSG_RESULT(no);
+       fi
+       ;;
+
+       *hpux*)
+               AC_CACHE_CHECK([for hpux sendfile64 support],samba_cv_HAVE_SENDFILE64,[
+               AC_TRY_LINK([\
+#include <sys/socket.h>
+#include <sys/uio.h>],
+[\
+       int fromfd, tofd;
+       size_t total=0;
+       struct iovec hdtrl[2];
+       ssize_t nwritten;
+       off64_t offset;
+
+       hdtrl[0].iov_base = 0;
+       hdtrl[0].iov_len = 0;
+
+       nwritten = sendfile64(tofd, fromfd, offset, total, &hdtrl[0], 0);
+],
+samba_cv_HAVE_SENDFILE64=yes,samba_cv_HAVE_SENDFILE64=no)])
+       if test x"$samba_cv_HAVE_SENDFILE64" = x"yes"; then
+               AC_DEFINE(HAVE_SENDFILE64)
+               AC_DEFINE(HPUX_SENDFILE_API)
+               AC_DEFINE(WITH_SENDFILE)
+       else
+               AC_MSG_RESULT(no);
+       fi
+
+               AC_CACHE_CHECK([for hpux sendfile support],samba_cv_HAVE_SENDFILE,[
+               AC_TRY_LINK([\
+#include <sys/socket.h>
+#include <sys/uio.h>],
+[\
+       int fromfd, tofd;
+       size_t total=0;
+       struct iovec hdtrl[2];
+       ssize_t nwritten;
+       off_t offset;
+
+       hdtrl[0].iov_base = 0;
+       hdtrl[0].iov_len = 0;
+
+       nwritten = sendfile(tofd, fromfd, offset, total, &hdtrl[0], 0);
+],
+samba_cv_HAVE_SENDFILE=yes,samba_cv_HAVE_SENDFILE=no)])
+       if test x"$samba_cv_HAVE_SENDFILE" = x"yes"; then
+               AC_DEFINE(HAVE_SENDFILE)
+               AC_DEFINE(HPUX_SENDFILE_API)
+               AC_DEFINE(WITH_SENDFILE)
+       else
+               AC_MSG_RESULT(no);
+       fi
+
+       ;;
+
+       *)
+       ;;
+        esac
+        ;;
+  *)
+    AC_MSG_RESULT(no)
+    ;;
+  esac ],
+  AC_MSG_RESULT(no)
+)
+
+
 #################################################
 # Check whether winbind is supported on this platform.  If so we need to
 # build and install client programs (WINBIND_TARGETS), sbin programs
@@ -2778,6 +3015,26 @@ fi
 AC_SUBST(BUILD_POPT)
 AC_SUBST(FLAGS1)
 
+#################################################
+# Check if the user wants Python
+
+# At the moment, you can use this to set which Python binary to link
+# against.  (Libraries built for Python2.2 can't be used by 2.1,
+# though they can coexist in different directories.)  In the future
+# this might make the Python stuff be built by default.
+
+AC_ARG_WITH(python,
+[  --with-python=PYTHONNAME  build Python libraries],
+[ case "${withval-python}" in
+  yes)
+       PYTHON=python
+       ;;
+  *)
+       PYTHON=${withval-python}
+       ;;
+  esac ])
+AC_SUBST(PYTHON)
+
 #################################################
 # do extra things if we are running insure
 
@@ -2797,7 +3054,10 @@ AC_TRY_RUN([#include "${srcdir-.}/tests/summary.c"],
 builddir=`pwd`
 AC_SUBST(builddir)
 
-AC_OUTPUT(include/stamp-h Makefile script/findsmb ../examples/VFS/Makefile ../examples/VFS/block/Makefile)
+# I added make files that are outside /source directory.
+# I know this is not a good solution, will work out a better
+# solution soon.                       --simo
+AC_OUTPUT(include/stamp-h Makefile script/findsmb ../examples/VFS/Makefile ../examples/pdb/mysql/Makefile ../examples/pdb/xml/Makefile ../examples/sam/Makefile)
 
 #################################################
 # Print very concise instructions on building/use
index 718bf1d7ce15259c938d1631ee86be0a9e50663b..05f584f980d592e563abe4c5ea46d5b861d1a24b 100644 (file)
@@ -41,9 +41,7 @@ BOOL initialise_alias_db(void)
     return True;
   }
 
-#ifdef WITH_NISPLUS
-  aldb_ops =  nisplus_initialise_alias_db();
-#elif defined(WITH_LDAP)
+#ifdef WITH_LDAP
   aldb_ops = ldap_initialise_alias_db();
 #else 
   aldb_ops = file_initialise_alias_db();
index c18463741d9230ccf331d0912a399ae89d9509df..d50e4f7322dc5b4e7c7dcea5274c77d7bbae0ca8 100644 (file)
@@ -39,9 +39,7 @@ BOOL initialise_group_db(void)
     return True;
   }
 
-#ifdef WITH_NISPLUS
-  gpdb_ops =  nisplus_initialise_group_db();
-#elif defined(WITH_LDAP)
+#ifdef WITH_LDAP
   gpdb_ops = ldap_initialise_group_db();
 #else 
   gpdb_ops = file_initialise_group_db();
index 70d6317a77a70606b600d9100cadc1ac0496aa0b..56414312465446b02e2e855e2b02bfa879dbdd4e 100644 (file)
@@ -434,7 +434,7 @@ BOOL check_priv_in_privilege(PRIVILEGE_SET *priv_set, LUID_ATTR set)
 }
 
 /****************************************************************************
-remove a privilege to a privilege array
+remove a privilege from a privilege array
 ****************************************************************************/
 BOOL remove_privilege(PRIVILEGE_SET *priv_set, LUID_ATTR set)
 {
@@ -1156,16 +1156,42 @@ BOOL get_uid_list_of_group(gid_t gid, uid_t **uid, int *num_uids)
  Create a UNIX group on demand.
 ****************************************************************************/
 
-int smb_create_group(char *unix_group)
+int smb_create_group(char *unix_group, gid_t *new_gid)
 {
        pstring add_script;
        int ret;
+       int fd = 0;
 
        pstrcpy(add_script, lp_addgroup_script());
        if (! *add_script) return -1;
        pstring_sub(add_script, "%g", unix_group);
-       ret = smbrun(add_script,NULL);
+       ret = smbrun(add_script, (new_gid!=NULL) ? &fd : NULL);
        DEBUG(3,("smb_create_group: Running the command `%s' gave %d\n",add_script,ret));
+       if (ret != 0)
+               return ret;
+
+       if (fd != 0) {
+               fstring output;
+
+               *new_gid = 0;
+               if (read(fd, output, sizeof(output)) > 0) {
+                       *new_gid = (gid_t)strtoul(output, NULL, 10);
+               }
+               close(fd);
+
+               if (*new_gid == 0) {
+                       /* The output was garbage. We assume nobody
+                           will create group 0 via smbd. Now we try to
+                           get the group via getgrnam. */
+
+                       struct group *grp = getgrnam(unix_group);
+                       if (grp != NULL)
+                               *new_gid = grp->gr_gid;
+                       else
+                               return 1;
+               }
+       }
+
        return ret;
 }
 
@@ -1187,7 +1213,25 @@ int smb_delete_group(char *unix_group)
 }
 
 /****************************************************************************
- Create a UNIX group on demand.
+ Set a user's primary UNIX group.
+****************************************************************************/
+int smb_set_primary_group(const char *unix_group, const char* unix_user)
+{
+       pstring add_script;
+       int ret;
+
+       pstrcpy(add_script, lp_setprimarygroup_script());
+       if (! *add_script) return -1;
+       all_string_sub(add_script, "%g", unix_group, sizeof(add_script));
+       all_string_sub(add_script, "%u", unix_user, sizeof(add_script));
+       ret = smbrun(add_script,NULL);
+       DEBUG(3,("smb_set_primary_group: "
+                "Running the command `%s' gave %d\n",add_script,ret));
+       return ret;
+}
+
+/****************************************************************************
+ Add a user to a UNIX group.
 ****************************************************************************/
 
 int smb_add_user_group(char *unix_group, char *unix_user)
@@ -1205,7 +1249,7 @@ int smb_add_user_group(char *unix_group, char *unix_user)
 }
 
 /****************************************************************************
- Delete a UNIX group on demand.
+ Delete a user from a UNIX group
 ****************************************************************************/
 
 int smb_delete_user_group(const char *unix_group, const char *unix_user)
index 7504a369b4b9aab5d8803b81d34f53a904239e55..0181ae535e02e4560f2c3a0a2083655a71b7211d 100644 (file)
@@ -24,7 +24,8 @@ typedef struct {
                char *password;
                char *user_name;
                char *kdc_server;
-               int no_bind;
+               unsigned flags;
+               int time_offset;
        } auth;
 
        /* info derived from the servers config */
@@ -32,6 +33,7 @@ typedef struct {
                char *realm;
                char *bind_path;
                char *ldap_server_name;
+               time_t current_time;
        } config;
 } ADS_STRUCT;
 
@@ -92,11 +94,14 @@ typedef struct {
 
 /* there are 4 possible types of errors the ads subsystem can produce */
 enum ads_error_type {ADS_ERROR_KRB5, ADS_ERROR_GSS, 
-                    ADS_ERROR_LDAP, ADS_ERROR_SYSTEM};
+                    ADS_ERROR_LDAP, ADS_ERROR_SYSTEM, ADS_ERROR_NT};
 
 typedef struct {
        enum ads_error_type error_type;
-       int rc;
+       union err_state{                
+               int rc;
+               NTSTATUS nt_status;
+       } err;
        /* For error_type = ADS_ERROR_GSS minor_status describe GSS API error */
        /* Where rc represents major_status of GSS API error */
        int minor_status;
@@ -109,12 +114,14 @@ typedef void **ADS_MODLIST;
 #endif
 
 /* macros to simplify error returning */
-#define ADS_ERROR(rc) ads_build_error(ADS_ERROR_LDAP, rc, 0)
+#define ADS_ERROR(rc) ADS_ERROR_LDAP(rc)
+#define ADS_ERROR_LDAP(rc) ads_build_error(ADS_ERROR_LDAP, rc, 0)
 #define ADS_ERROR_SYSTEM(rc) ads_build_error(ADS_ERROR_SYSTEM, rc?rc:EINVAL, 0)
 #define ADS_ERROR_KRB5(rc) ads_build_error(ADS_ERROR_KRB5, rc, 0)
 #define ADS_ERROR_GSS(rc, minor) ads_build_error(ADS_ERROR_GSS, rc, minor)
+#define ADS_ERROR_NT(rc) ads_build_nt_error(ADS_ERROR_NT,rc)
 
-#define ADS_ERR_OK(status) ((status).rc == 0)
+#define ADS_ERR_OK(status) ((status.error_type == ADS_ERROR_NT) ? NT_STATUS_IS_OK(status.err.nt_status):(status.err.rc == 0))
 #define ADS_SUCCESS ADS_ERROR(0)
 
 /* time between reconnect attempts */
@@ -127,24 +134,102 @@ typedef void **ADS_MODLIST;
 #define ADS_PAGE_CTL_OID "1.2.840.113556.1.4.319"
 #define ADS_NO_REFERRALS_OID "1.2.840.113556.1.4.1339"
 #define ADS_SERVER_SORT_OID "1.2.840.113556.1.4.473"
+#define ADS_PERMIT_MODIFY_OID "1.2.840.113556.1.4.1413"
 
-#define UF_DONT_EXPIRE_PASSWD           0x10000
-#define UF_MNS_LOGON_ACCOUNT            0x20000
-#define UF_SMARTCARD_REQUIRED           0x40000
-#define UF_TRUSTED_FOR_DELEGATION       0x80000
-#define UF_NOT_DELEGATED               0x100000
-#define UF_USE_DES_KEY_ONLY            0x200000
-#define UF_DONT_REQUIRE_PREAUTH        0x400000
+/* UserFlags for userAccountControl */
+#define UF_SCRIPT                              0x00000001
+#define UF_ACCOUNTDISABLE                      0x00000002
+#define UF_UNUSED_1                            0x00000004
+#define UF_HOMEDIR_REQUIRED                    0x00000008
 
-#define UF_TEMP_DUPLICATE_ACCOUNT       0x0100
-#define UF_NORMAL_ACCOUNT               0x0200
-#define UF_INTERDOMAIN_TRUST_ACCOUNT    0x0800
-#define UF_WORKSTATION_TRUST_ACCOUNT    0x1000
-#define UF_SERVER_TRUST_ACCOUNT         0x2000
+#define UF_LOCKOUT                             0x00000010
+#define UF_PASSWD_NOTREQD                      0x00000020
+#define UF_PASSWD_CANT_CHANGE                  0x00000040
+#define UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED     0x00000080
 
-/* account types */
-#define ATYPE_GROUP               0x10000000
-#define ATYPE_USER                0x30000000
+#define UF_TEMP_DUPLICATE_ACCOUNT              0x00000100
+#define UF_NORMAL_ACCOUNT                      0x00000200
+#define UF_UNUSED_2                            0x00000400
+#define UF_INTERDOMAIN_TRUST_ACCOUNT           0x00000800
+
+#define UF_WORKSTATION_TRUST_ACCOUNT           0x00001000
+#define UF_SERVER_TRUST_ACCOUNT                0x00002000
+#define UF_UNUSED_3                            0x00004000
+#define UF_UNUSED_4                            0x00008000
+
+#define UF_DONT_EXPIRE_PASSWD                  0x00010000
+#define UF_MNS_LOGON_ACCOUNT                   0x00020000
+#define UF_SMARTCARD_REQUIRED                  0x00040000
+#define UF_TRUSTED_FOR_DELEGATION              0x00080000
+
+#define UF_NOT_DELEGATED                       0x00100000
+#define UF_USE_DES_KEY_ONLY                    0x00200000
+#define UF_DONT_REQUIRE_PREAUTH                        0x00400000
+#define UF_UNUSED_5                            0x00800000
+
+#define UF_UNUSED_6                            0x01000000
+#define UF_UNUSED_7                            0x02000000
+#define UF_UNUSED_8                            0x04000000
+#define UF_UNUSED_9                            0x08000000
+
+#define UF_UNUSED_10                           0x10000000
+#define UF_UNUSED_11                           0x20000000
+#define UF_UNUSED_12                           0x40000000
+#define UF_UNUSED_13                           0x80000000
+
+#define UF_MACHINE_ACCOUNT_MASK (\
+               UF_INTERDOMAIN_TRUST_ACCOUNT |\
+               UF_WORKSTATION_TRUST_ACCOUNT |\
+               UF_SERVER_TRUST_ACCOUNT \
+               )
+
+#define UF_ACCOUNT_TYPE_MASK (\
+               UF_TEMP_DUPLICATE_ACCOUNT |\
+               UF_NORMAL_ACCOUNT |\
+               UF_INTERDOMAIN_TRUST_ACCOUNT |\
+               UF_WORKSTATION_TRUST_ACCOUNT |\
+               UF_SERVER_TRUST_ACCOUNT \
+                )
+
+#define UF_SETTABLE_BITS (\
+               UF_SCRIPT |\
+               UF_ACCOUNTDISABLE |\
+               UF_HOMEDIR_REQUIRED  |\
+               UF_LOCKOUT |\
+               UF_PASSWD_NOTREQD |\
+               UF_PASSWD_CANT_CHANGE |\
+               UF_ACCOUNT_TYPE_MASK | \
+               UF_DONT_EXPIRE_PASSWD | \
+               UF_MNS_LOGON_ACCOUNT |\
+               UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED |\
+               UF_SMARTCARD_REQUIRED |\
+               UF_TRUSTED_FOR_DELEGATION |\
+               UF_NOT_DELEGATED |\
+               UF_USE_DES_KEY_ONLY  |\
+               UF_DONT_REQUIRE_PREAUTH \
+               )
+
+/* sAMAccountType */
+#define ATYPE_NORMAL_ACCOUNT                   0x30000000 /* 805306368 */
+#define ATYPE_WORKSTATION_TRUST                        0x30000001 /* 805306369 */
+#define ATYPE_INTERDOMAIN_TRUST                        0x30000002 /* 805306370 */ 
+#define ATYPE_SECURITY_GLOBAL_GROUP            0x10000000 /* 268435456 */
+#define ATYPE_DISTRIBUTION_GLOBAL_GROUP                0x10000001 /* 268435457 */
+#define ATYPE_DISTRIBUTION_UNIVERSAL_GROUP     ATYPE_DISTRIBUTION_GLOBAL_GROUP
+#define ATYPE_SECURITY_LOCAL_GROUP             0x20000000 /* 536870912 */
+#define ATYPE_DISTRIBUTION_LOCAL_GROUP         0x20000001 /* 536870913 */
+
+#define ATYPE_ACCOUNT          ATYPE_NORMAL_ACCOUNT            /* 0x30000000 805306368 */
+#define ATYPE_GLOBAL_GROUP     ATYPE_SECURITY_GLOBAL_GROUP     /* 0x10000000 268435456 */
+#define ATYPE_LOCAL_GROUP      ATYPE_SECURITY_LOCAL_GROUP      /* 0x20000000 536870912 */
+
+/* groupType */
+#define GTYPE_SECURITY_BUILTIN_LOCAL_GROUP     0x80000005      /* -2147483643 */
+#define GTYPE_SECURITY_DOMAIN_LOCAL_GROUP      0x80000004      /* -2147483644 */
+#define GTYPE_SECURITY_GLOBAL_GROUP            0x80000002      /* -2147483646 */
+#define GTYPE_DISTRIBUTION_GLOBAL_GROUP                0x00000002      /* 2 */
+#define GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP  0x00000004      /* 4 */
+#define GTYPE_DISTRIBUTION_UNIVERSAL_GROUP     0x00000008      /* 8 */
 
 /* Mailslot or cldap getdcname response flags */
 #define ADS_PDC            0x00000001  /* DC is PDC */
@@ -167,3 +252,8 @@ typedef void **ADS_MODLIST;
 /* DomainCntrollerAddressType */
 #define ADS_INET_ADDRESS      0x00000001
 #define ADS_NETBIOS_ADDRESS   0x00000002
+
+
+/* ads auth control flags */
+#define ADS_AUTH_DISABLE_KERBEROS 1
+#define ADS_AUTH_NO_BIND 2
index 090c5459d1879290b0916128553d432e5586395b..7783ab4c2f66dbe61ccff212fc059568e652726b 100644 (file)
@@ -45,6 +45,7 @@ typedef struct {
 #define ASN1_BOOLEAN 0x1
 #define ASN1_INTEGER 0x2
 #define ASN1_ENUMERATED 0xa
+#define ASN1_SET 0x31
 
 #define ASN1_MAX_OIDS 20
 
index 711ae1fd196d1d52f2bad78a020dda8946de48ed..1e8d1c3d2932f79f50ea8b6ffe87fefb3913f570 100644 (file)
@@ -60,6 +60,7 @@ struct print_job_info
 typedef struct smb_sign_info {
        BOOL use_smb_signing;
        BOOL negotiated_smb_signing;
+       BOOL temp_smb_signing;
        size_t mac_key_len;
        uint8 mac_key[44];
        uint32 send_seq_num;
index 4a138b6db6ad5d97c52e1f930b9d503f539b6cab..770af1a6b562e42ef4cb7aa592e47f4c324f6b98 100644 (file)
 #undef MMAP_BLACKLIST
 #undef HAVE_IMMEDIATE_STRUCTURES
 #undef HAVE_CUPS
+#undef WITH_SAM
 #undef WITH_LDAP_SAM
 #undef WITH_NISPLUS_SAM
 #undef WITH_TDB_SAM
 #undef HAVE_LDAP
 #undef HAVE_STAT_ST_BLOCKS
 #undef STAT_ST_BLOCKSIZE
+#undef HAVE_STAT_ST_BLKSIZE
 #undef HAVE_DEVICE_MAJOR_FN
 #undef HAVE_DEVICE_MINOR_FN
 #undef HAVE_PASSWD_PW_COMMENT
 #endif
 
 #undef LDAP_SET_REBIND_PROC_ARGS
+#undef HAVE_SENDFILE
+#undef HAVE_SENDFILE64
+#undef LINUX_SENDFILE_API
+#undef LINUX_BROKEN_SENDFILE_API
+#undef WITH_SENDFILE
+#undef FREEBSD_SENDFILE_API
+#undef HPUX_SENDFILE_API
+#undef WITH_ADS
 
 /* The number of bytes in a int.  */
 #undef SIZEOF_INT
 /* Define if you have the <sys/syscall.h> header file.  */
 #undef HAVE_SYS_SYSCALL_H
 
+/* Define if you have the <sys/syslog.h> header file.  */
+#undef HAVE_SYS_SYSLOG_H
+
 /* Define if you have the <sys/termio.h> header file.  */
 #undef HAVE_SYS_TERMIO_H
 
 /* Define if you have the <syscall.h> header file.  */
 #undef HAVE_SYSCALL_H
 
+/* Define if you have the <syslog.h> header file.  */
+#undef HAVE_SYSLOG_H
+
 /* Define if you have the <termio.h> header file.  */
 #undef HAVE_TERMIO_H
 
index 08858274337ca073b7421e06d444ec022b06c662..4b0b4b1ac47770b639b84651491349062bbda92c 100644 (file)
@@ -89,9 +89,10 @@ extern int DEBUGLEVEL;
 #define DBGC_RPC_SRV           6
 #define DBGC_RPC_CLI           7
 #define DBGC_PASSDB            8
-#define DBGC_AUTH              9
-#define DBGC_WINBIND           10
-
+#define DBGC_SAM               9
+#define DBGC_AUTH              10
+#define DBGC_WINBIND           11
+#define DBGC_VFS               12
 
 /* So you can define DBGC_CLASS before including debug.h */
 #ifndef DBGC_CLASS
index 135d799596c2ce1c01c40709a90446020301e28d..93936463e68fc517e5d03ceaaa0557d5ea554b8e 100644 (file)
 /* these are win32 error codes. There are only a few places where
    these matter for Samba, primarily in the NT printing code */
 #define WERR_OK W_ERROR(0)
+#define WERR_BADFUNC W_ERROR(1)
 #define WERR_BADFILE W_ERROR(2)
 #define WERR_ACCESS_DENIED W_ERROR(5)
 #define WERR_BADFID W_ERROR(6)
-#define WERR_BADFUNC W_ERROR(1)
-#define WERR_INSUFFICIENT_BUFFER W_ERROR(122)
+#define WERR_NOMEM W_ERROR(8)
+#define WERR_GENERAL_FAILURE W_ERROR(31)
+#define WERR_NOT_SUPPORTED W_ERROR(50)
+#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_ALREADY_EXISTS W_ERROR(80)
-#define WERR_INVALID_PARAM W_ERROR(87)
-#define WERR_NOT_SUPPORTED W_ERROR(50)
 #define WERR_BAD_PASSWORD W_ERROR(86)
-#define WERR_NOMEM W_ERROR(8)
+#define WERR_INVALID_PARAM W_ERROR(87)
+#define WERR_INSUFFICIENT_BUFFER W_ERROR(122)
 #define WERR_INVALID_NAME W_ERROR(123)
 #define WERR_UNKNOWN_LEVEL W_ERROR(124)
 #define WERR_OBJECT_PATH_INVALID W_ERROR(161)
index 6084d583ed6aa5b5235f520f16a76ce39bc81188..56b8357831268b454c332e907819ae219903c709 100644 (file)
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <netdb.h>
+
+#ifdef HAVE_SYSLOG_H
 #include <syslog.h>
+#else
+#ifdef HAVE_SYS_SYSLOG_H
+#include <sys/syslog.h>
+#endif
+#endif
+
 #include <sys/file.h>
 
 #ifdef HAVE_NETINET_TCP_H
 
 #if HAVE_GSSAPI_GSSAPI_H
 #include <gssapi/gssapi.h>
-#else
-#undef HAVE_KRB5
 #endif
 
 #if HAVE_GSSAPI_GSSAPI_GENERIC_H
 #include <gssapi/gssapi_generic.h>
-#else
-#undef HAVE_KRB5
 #endif
 
-/* we support ADS if we have krb5 and ldap libs */
-#if defined(HAVE_KRB5) && defined(HAVE_LDAP) && defined(HAVE_GSSAPI)
+/* we support ADS if we want it and have krb5 and ldap libs */
+#if defined(WITH_ADS) && defined(HAVE_KRB5) && defined(HAVE_LDAP)
 #define HAVE_ADS
 #endif
 
@@ -702,6 +706,7 @@ extern int errno;
 #include "../tdb/spinlock.h"
 #include "../tdb/tdbutil.h"
 #include "talloc.h"
+#include "nt_status.h"
 #include "ads.h"
 #include "interfaces.h"
 #include "hash.h"
@@ -747,6 +752,8 @@ extern int errno;
 
 #include "passdb.h"
 
+#include "sam.h"
+
 #include "session.h"
 
 #include "asn_1.h"
@@ -755,6 +762,8 @@ extern int errno;
 
 #include "mangle.h"
 
+#include "nsswitch/winbind_client.h"
+
 /*
  * Type for wide character dirent structure.
  * Only d_name is defined by POSIX.
@@ -794,6 +803,11 @@ struct functable {
 
 #include "nsswitch/nss.h"
 
+/* forward declaration from printing.h to get around 
+   header file dependencies */
+
+struct printjob;
+
 /***** automatically generated prototypes *****/
 #include "proto.h"
 
@@ -895,24 +909,6 @@ struct functable {
 #define ULTRIX_AUTH 1
 #endif
 
-#ifdef HAVE_LIBREADLINE
-#  ifdef HAVE_READLINE_READLINE_H
-#    include <readline/readline.h>
-#    ifdef HAVE_READLINE_HISTORY_H
-#      include <readline/history.h>
-#    endif
-#  else
-#    ifdef HAVE_READLINE_H
-#      include <readline.h>
-#      ifdef HAVE_HISTORY_H
-#        include <history.h>
-#      endif
-#    else
-#      undef HAVE_LIBREADLINE
-#    endif
-#  endif
-#endif
-
 #ifndef HAVE_STRDUP
 char *strdup(const char *s);
 #endif
index f26956399693f5e3df329ae0a3dc61b298cd0859..2b45709a5e8583440d6b1f6477531d5b835f9b09 100644 (file)
@@ -333,7 +333,7 @@ typedef struct _SMBCCTX {
 
        /** Space to store private data of the server cache.
         */
-       void * server_cache;
+       struct smbc_server_cache * server_cache;
 
        /** INTERNAL functions
         * do _NOT_ touch these from your program !
index 2538715c4122985046f1368e7478e3be99db7053..5096e13fc3931230f64dbf445440d159315cd0f4 100644 (file)
 #define MAX_OPEN_FILES 10000
 #endif
  
-/* the max number of simultanous connections to the server by all clients */
-/* zero means no limit. */
-#define MAXSTATUS 0
-
 #define WORDMAX 0xFFFF
 
 /* the maximum password length before we declare a likely attack */
 #endif
 
 /* the size of the uid cache used to reduce valid user checks */
-#define UID_CACHE_SIZE 4
+#define VUID_CACHE_SIZE 32
 
 /* the following control timings of various actions. Don't change 
    them unless you know what you are doing. These are all in seconds */
 #define IDLE_CLOSED_TIMEOUT (60)
 #define DPTR_IDLE_TIMEOUT (120)
 #define SMBD_SELECT_TIMEOUT (60)
-#define SMBD_SELECT_TIMEOUT_WITH_PENDING_LOCKS (10)
 #define NMBD_SELECT_LOOP (10)
 #define BROWSE_INTERVAL (60)
 #define REGISTRATION_INTERVAL (10*60)
index 58e606b40fa453c0242319082edc501610e4a69a..0e995039ff51ea97269c44eb5f694d16d421b12c 100644 (file)
 #define MSG_SMB_SAM_SYNC     3003
 #define MSG_SMB_SAM_REPL     3004
 
+/* Flags to classify messages - used in message_send_all() */
+/* Sender will filter by flag. */
+
+#define FLAG_MSG_GENERAL       0x0001
+#define FLAG_MSG_SMBD          0x0002
+#define FLAG_MSG_NMBD          0x0004
+#define FLAG_MSG_PRINTING      0x0008
+
 #endif
index 5e2b8f7f64a35825eb5e729af363402c0fd770b7..57767fc3c6b883de72cb5bf71ad617b8c84ffaa9 100644 (file)
@@ -181,6 +181,7 @@ typedef struct nt_printer_driver_info_level
 #define SPOOL_DSDRIVER_KEY             "DsDriver"
 #define SPOOL_DSUSER_KEY               "DsUser"
 #define SPOOL_PNPDATA_KEY              "PnPData"
+#define SPOOL_OID_KEY                  "OID"
 
 /* container for a single registry key */
 
@@ -350,7 +351,7 @@ typedef struct _form
 
 #define SPOOLSS_NOTIFY_MSG_UNIX_JOBID 0x0001    /* Job id is unix  */
 
-struct spoolss_notify_msg {
+typedef struct spoolss_notify_msg {
        fstring printer;        /* Name of printer notified */
        uint32 type;            /* Printer or job notify */
        uint32 field;           /* Notify field changed */
@@ -361,6 +362,18 @@ struct spoolss_notify_msg {
                uint32 value[2];
                char *data;
        } notify;
-};
+} SPOOLSS_NOTIFY_MSG;
+
+typedef struct {
+       fstring                 printername;
+       uint32                  num_msgs;
+       SPOOLSS_NOTIFY_MSG      *msgs;
+} SPOOLSS_NOTIFY_MSG_GROUP;
+
+typedef struct {
+       TALLOC_CTX                      *ctx;
+       uint32                          num_groups;
+       SPOOLSS_NOTIFY_MSG_GROUP        *msg_groups;
+} SPOOLSS_NOTIFY_MSG_CTR;
 
 #endif /* NT_PRINTING_H_ */
index ecf603b8fcc9f35db321db98c6be88285f757a60..9774a6acd95d401c4195e910d2abed79cbcd5880 100644 (file)
@@ -43,6 +43,7 @@ struct printjob {
        fstring jobname; /* the job name given to us by the client */
        fstring user; /* the user who started the job */
        fstring queuename; /* service number of printer for this job */
+       NT_DEVICEMODE *nt_devmode;
 };
 
 /* Information for print interfaces */
index 80b00fbaad4801a303322f5bd3bffbc3a6957ace..fb849f82380600154408d72c247e5c581ad61e60 100644 (file)
@@ -4,6 +4,7 @@
    Copyright (C) Andrew Tridgell 1992-1997
    Copyright (C) Luke Kenneth Casson Leighton 1996-1997
    Copyright (C) Paul Ashton 1997
+   Copyright (C) Jean François Micouleau 2002
    
    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
 
 
 /* NETLOGON pipe */
-#define NET_SAMLOGON           0x02
-#define NET_SAMLOGOFF          0x03
-#define NET_REQCHAL            0x04
-#define NET_AUTH               0x05
-#define NET_SRVPWSET           0x06
-#define NET_SAM_DELTAS         0x07
-#define NET_LOGON_CTRL         0x0c
-#define NET_AUTH2              0x0f
-#define NET_LOGON_CTRL2        0x0e
-#define NET_SAM_SYNC           0x10
-#define NET_TRUST_DOM_LIST     0x13
+#define NET_SAMLOGON           0x02
+#define NET_SAMLOGOFF          0x03
+#define NET_REQCHAL            0x04
+#define NET_AUTH               0x05
+#define NET_SRVPWSET           0x06
+#define NET_SAM_DELTAS         0x07
+#define NET_LOGON_CTRL         0x0c
+#define NET_AUTH2              0x0f
+#define NET_LOGON_CTRL2                0x0e
+#define NET_SAM_SYNC           0x10
+#define NET_TRUST_DOM_LIST     0x13
+#define NET_AUTH3              0x1a
 
 /* Secure Channel types.  used in NetrServerAuthenticate negotiation */
 #define SEC_CHAN_WKSTA   2
 #define SEC_CHAN_BDC     6
 
 /* Returned delta types */
-#define SAM_DELTA_DOMAIN_INFO  0x01 /* Domain */
-#define SAM_DELTA_GROUP_INFO   0x02 /* Domain groups */
-#define SAM_DELTA_ACCOUNT_INFO 0x05 /* Users */
-#define SAM_DELTA_GROUP_MEM    0x08 /* Group membership */
-#define SAM_DELTA_ALIAS_INFO   0x09 /* Local groups */
-#define SAM_DELTA_ALIAS_MEM    0x0C /* Local group membership */
-#define SAM_DELTA_DOM_INFO     0x0D /* Privilige stuff */
-#define SAM_DELTA_UNK0E_INFO   0x0e /* Privilige stuff */
-#define SAM_DELTA_PRIVS_INFO   0x10 /* Privilige stuff */
-#define SAM_DELTA_UNK12_INFO   0x12 /* Privilige stuff */
-#define SAM_DELTA_SAM_STAMP    0x16 /* Some kind of journal record? */
+#define SAM_DELTA_DOMAIN_INFO    0x01
+#define SAM_DELTA_GROUP_INFO     0x02
+#define SAM_DELTA_RENAME_GROUP   0x04
+#define SAM_DELTA_ACCOUNT_INFO   0x05
+#define SAM_DELTA_RENAME_USER    0x07
+#define SAM_DELTA_GROUP_MEM      0x08
+#define SAM_DELTA_ALIAS_INFO     0x09
+#define SAM_DELTA_RENAME_ALIAS   0x0b
+#define SAM_DELTA_ALIAS_MEM      0x0c
+#define SAM_DELTA_POLICY_INFO    0x0d
+#define SAM_DELTA_TRUST_DOMS     0x0e
+#define SAM_DELTA_PRIVS_INFO     0x10 /* DT_DELTA_ACCOUNTS */
+#define SAM_DELTA_SECRET_INFO    0x12
+#define SAM_DELTA_DELETE_GROUP   0x14
+#define SAM_DELTA_DELETE_USER    0x15
+#define SAM_DELTA_MODIFIED_COUNT 0x16
 
 /* SAM database types */
 #define SAM_DATABASE_DOMAIN    0x00 /* Domain users and groups */
 #define SAM_DATABASE_BUILTIN   0x01 /* BUILTIN users and groups */
-#define SAM_DATABASE_PRIVS     0x02 /* Priviliges? */
+#define SAM_DATABASE_PRIVS     0x02 /* Privileges */
 
 #if 0
 /* I think this is correct - it's what gets parsed on the wire. JRA. */
@@ -157,8 +164,8 @@ typedef struct net_user_info_3
        uint32 buffer_dom_id; /* undocumented logon domain id pointer */
        uint8 padding[40];    /* unused padding bytes.  expansion room */
 
-       uint32 num_other_sids; /* 0 - num_sids */
-       uint32 buffer_other_sids; /* NULL - undocumented pointer to SIDs. */
+       uint32 num_other_sids; /* number of foreign/trusted domain sids */
+       uint32 buffer_other_sids;
        
        UNISTR2 uni_user_name;    /* username unicode string */
        UNISTR2 uni_full_name;    /* user's full name unicode string */
@@ -177,7 +184,7 @@ typedef struct net_user_info_3
 
        uint32 num_other_groups;        /* other groups */
        DOM_GID *other_gids; /* group info */
-       DOM_SID2 *other_sids; /* undocumented - domain SIDs */
+       DOM_SID2 *other_sids; /* foreign/trusted domain SIDs */
 
 } NET_USER_INFO_3;
 
@@ -370,6 +377,23 @@ typedef struct net_r_auth2_info
        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 */
+} NET_Q_AUTH_3;
+
+/* NET_R_AUTH_3 */
+typedef struct net_r_auth3_info
+{
+       DOM_CHAL srv_chal;      /* server-calculated credentials */
+       NEG_FLAGS srv_flgs;     /* usually 0x6007 ffff */
+       uint32 unknown;         /* 0x0000045b */
+       NTSTATUS status;        /* return code */
+} NET_R_AUTH_3;
+
 
 /* NET_Q_SRV_PWSET */
 typedef struct net_q_srv_pwset_info
@@ -692,51 +716,37 @@ typedef struct sam_alias_mem_info_info
 } SAM_ALIAS_MEM_INFO;
 
 
-/* SAM_DELTA_DOM (0x0D) */
+/* SAM_DELTA_POLICY (0x0D) */
 typedef struct
 {
-       uint32 unknown1; /* 0x5000 */
-       uint32 unknown2; /* 0 */
-       uint32 unknown3; /* 0 */
-       uint32 unknown4; /* 0 */
-       uint32 count1;
-       uint32 ptr1;
-       uint16 count2;
-       uint16 count3;
-       uint32 ptr2;
-       uint32 ptr3;
-
-       uint32 unknown4b; /* 0x02000000 */
-       uint32 unknown5; /* 0x00100000 */
-       uint32 unknown6; /* 0x00010000 */
-       uint32 unknown7; /* 0x0f000000 */
-       uint32 unknown8; /* 0 */
-       uint32 unknown9; /* 0 */
-       uint32 unknown10; /* 0 */
-       uint32 unknown11; /* 0x3c*/
-       uint32 unknown12; /* 0*/
-
-       uint32 unknown13; /* a7080110 */
-       uint32 unknown14; /* 01bfb0dd */
-       uint32 unknown15; /* 0f */
-       uint32 unknown16; /* 68 */
-       uint32 unknown17; /* 00169000 */
-
-       uint32 count4;
-       uint32 unknown18; /* 0  times count4 */
-       
-       uint32 unknown19; /* 8 */
-
-       uint32 unknown20; /* 0x04 times count1 */
-       
-       uint32 ptr4;
-       
-       UNISTR2 domain_name;
+       uint32   max_log_size; /* 0x5000 */
+       UINT64_S audit_retention_period; /* 0 */
+       uint32   auditing_mode; /* 0 */
+       uint32   num_events;
+       uint32   ptr_events;
+       UNIHDR   hdr_dom_name;
+       uint32   sid_ptr;
+
+       uint32   paged_pool_limit; /* 0x02000000 */
+       uint32   non_paged_pool_limit; /* 0x00100000 */
+       uint32   min_workset_size; /* 0x00010000 */
+       uint32   max_workset_size; /* 0x0f000000 */
+       uint32   page_file_limit; /* 0 */
+       UINT64_S time_limit; /* 0 */
+       NTTIME   modify_time; /* 0x3c*/
+       NTTIME   create_time; /* a7080110 */
+       BUFHDR2  hdr_sec_desc;
+
+       uint32   num_event_audit_options;
+       uint32   event_audit_option;
+
+       UNISTR2  domain_name;
        DOM_SID2 domain_sid;
 
-} SAM_DELTA_DOM;
+       BUFFER4  buf_sec_desc;
+} SAM_DELTA_POLICY;
 
-/* SAM_DELTA_UNK0E (0x0e) */
+/* SAM_DELTA_TRUST_DOMS */
 typedef struct
 {
        uint32 buf_size;
@@ -754,34 +764,29 @@ typedef struct
        uint32 unknown3;
        UNISTR2 domain;
 
-} SAM_DELTA_UNK0E;
+} SAM_DELTA_TRUSTDOMS;
 
 /* SAM_DELTA_PRIVS (0x10) */
 typedef struct
 {
-       uint32 buf_size;
-       SEC_DESC *sec_desc;
        DOM_SID2 sid;
 
        uint32 priv_count;
-       uint32 reserved1; /* 0x0 */
-
-       uint32 ptr1;
-       uint32 ptr2;
-
-       uint32 unknown1;
-       uint32 unknown2;
-       uint32 unknown3;
-       uint32 unknown4;
-       uint32 unknown5;
-       uint32 unknown6;
-       uint32 unknown7;
-       uint32 unknown8;
-       uint32 unknown9;
+       uint32 priv_control;
+
+       uint32 priv_attr_ptr;
+       uint32 priv_name_ptr;
+
+       uint32   paged_pool_limit; /* 0x02000000 */
+       uint32   non_paged_pool_limit; /* 0x00100000 */
+       uint32   min_workset_size; /* 0x00010000 */
+       uint32   max_workset_size; /* 0x0f000000 */
+       uint32   page_file_limit; /* 0 */
+       UINT64_S time_limit; /* 0 */
+       uint32   system_flags; /* 1 */
+       BUFHDR2  hdr_sec_desc;
        
        uint32 buf_size2;
-       uint32 ptr3;
-       uint32 unknown10; /* 48 bytes 0x0*/
        
        uint32 attribute_count;
        uint32 *attributes;
@@ -790,10 +795,10 @@ typedef struct
        UNIHDR *hdr_privslist;
        UNISTR2 *uni_privslist;
 
-
+       BUFFER4 buf_sec_desc;
 } SAM_DELTA_PRIVS;
 
-/* SAM_DELTA_UNK12 (0x12) */
+/* SAM_DELTA_SECRET */
 typedef struct
 {
        uint32 buf_size;
@@ -827,15 +832,15 @@ typedef struct
        uint32 buf_size3;
        SEC_DESC *sec_desc2;
 
-} SAM_DELTA_UNK12;
+} SAM_DELTA_SECRET;
 
-/* SAM_DELTA_STAMP (0x16) */
+/* SAM_DELTA_MOD_COUNT (0x16) */
 typedef struct
 {
         uint32 seqnum;
         uint32 dom_mod_count_ptr;
        UINT64_S dom_mod_count;  /* domain mod count at last sync */
-} SAM_DELTA_STAMP;
+} SAM_DELTA_MOD_COUNT;
 
 typedef union sam_delta_ctr_info
 {
@@ -845,11 +850,11 @@ typedef union sam_delta_ctr_info
        SAM_GROUP_MEM_INFO grp_mem_info;
        SAM_ALIAS_INFO     alias_info  ;
        SAM_ALIAS_MEM_INFO als_mem_info;
-       SAM_DELTA_DOM      dom_info;
+       SAM_DELTA_POLICY   policy_info;
        SAM_DELTA_PRIVS    privs_info;
-       SAM_DELTA_STAMP    stamp;
-       SAM_DELTA_UNK0E    unk0e_info;
-       SAM_DELTA_UNK12    unk12_info;
+       SAM_DELTA_MOD_COUNT mod_count;
+       SAM_DELTA_TRUSTDOMS trustdoms_info;
+       SAM_DELTA_SECRET   secret_info;
 } SAM_DELTA_CTR;
 
 /* NET_R_SAM_SYNC */
index b7acf44c5de65e036591b499581a1e7829cbbe80..456825a5f5c645668a14d0813a6fbecb7f872e91 100755 (executable)
@@ -1240,8 +1240,8 @@ typedef struct job_info_ctr_info
 {
        union
        {
-               JOB_INFO_1 **job_info_1;
-               JOB_INFO_2 **job_info_2;
+               JOB_INFO_1 *job_info_1;
+               JOB_INFO_2 *job_info_2;
                void *info;
        } job;
 
index 263dd67c548197e42fda5510a951dcedbe560d0c..c39ebed950f1e97f5ab94ebfd862ee474a48c069 100644 (file)
@@ -3,7 +3,7 @@
    SMB parameters and setup, plus a whole lot more.
    
    Copyright (C) Andrew Tridgell              1992-2000
-   Copyright (C) John H Terpstra              1996-2000
+   Copyright (C) John H Terpstra              1996-2002
    Copyright (C) Luke Kenneth Casson Leighton 1996-2000
    Copyright (C) Paul Ashton                  1998-2000
    Copyright (C) Simo Sorce                   2001-2002
@@ -193,44 +193,6 @@ typedef struct nttime_info
 } NTTIME;
 
 
-/* The Splint code analysis tool doesn't like immediate structures. */
-
-#ifdef _SPLINT_                      /* http://www.splint.org */
-#undef HAVE_IMMEDIATE_STRUCTURES
-#endif
-
-/* the following rather strange looking definitions of NTSTATUS and WERROR
-   and there in order to catch common coding errors where different error types
-   are mixed up. This is especially important as we slowly convert Samba
-   from using BOOL for internal functions 
-*/
-
-#if defined(HAVE_IMMEDIATE_STRUCTURES)
-typedef struct {uint32 v;} NTSTATUS;
-#define NT_STATUS(x) ((NTSTATUS) { x })
-#define NT_STATUS_V(x) ((x).v)
-#else
-typedef uint32 NTSTATUS;
-#define NT_STATUS(x) (x)
-#define NT_STATUS_V(x) (x)
-#endif
-
-#if defined(HAVE_IMMEDIATE_STRUCTURES)
-typedef struct {uint32 v;} WERROR;
-#define W_ERROR(x) ((WERROR) { x })
-#define W_ERROR_V(x) ((x).v)
-#else
-typedef uint32 WERROR;
-#define W_ERROR(x) (x)
-#define W_ERROR_V(x) (x)
-#endif
-
-#define NT_STATUS_IS_OK(x) (NT_STATUS_V(x) == 0)
-#define NT_STATUS_IS_ERR(x) ((NT_STATUS_V(x) & 0xc0000000) == 0xc0000000)
-#define NT_STATUS_EQUAL(x,y) (NT_STATUS_V(x) == NT_STATUS_V(y))
-#define W_ERROR_IS_OK(x) (W_ERROR_V(x) == 0)
-
-
 /* Allowable account control bits */
 #define ACB_DISABLED   0x0001  /* 1 = User account disabled */
 #define ACB_HOMDIRREQ  0x0002  /* 1 = Home directory required */
@@ -391,6 +353,7 @@ typedef struct files_struct
        BOOL delete_on_close;
        SMB_OFF_T pos;
        SMB_OFF_T size;
+       SMB_OFF_T initial_allocation_size; /* Faked up initial allocation on disk. */
        mode_t mode;
        uint16 vuid;
        write_bmpx_struct *wbmpx_ptr;
@@ -430,9 +393,9 @@ typedef struct
   time_t status_time;
 } dir_status_struct;
 
-struct uid_cache {
-  int entries;
-  uid_t list[UID_CACHE_SIZE];
+struct vuid_cache {
+  unsigned int entries;
+  uint16 list[VUID_CACHE_SIZE];
 };
 
 typedef struct
@@ -461,7 +424,8 @@ typedef struct connection_struct
        unsigned cnum; /* an index passed over the wire */
        int service;
        BOOL force_user;
-       struct uid_cache uid_cache;
+       BOOL force_group;
+       struct vuid_cache vuid_cache;
        void *dirptr;
        BOOL printer;
        BOOL ipc;
@@ -652,7 +616,7 @@ typedef struct sam_passwd
                
                DATA_BLOB lm_pw; /* .data is Null if no password */
                DATA_BLOB nt_pw; /* .data is Null if no password */
-               DATA_BLOB plaintext_pw; /* .data is Null if not available */
+               char* plaintext_pw; /* is Null if not available */
                
                uint16 acct_ctrl; /* account info (ACB_xxxx bit-mask) */
                uint32 unknown_3; /* 0x00ff ffff */
@@ -716,6 +680,7 @@ struct connections_data {
        char addr[24];
        char machine[FSTRING_LEN];
        time_t start;
+       uint32 bcast_msg_flags;
 };
 
 
@@ -788,12 +753,16 @@ struct bitmap {
        int n;
 };
 
-#define FLAG_BASIC     0x01 /* fundamental options */
-#define FLAG_SHARE     0x02 /* file sharing options */
-#define FLAG_PRINT     0x04 /* printing options */
-#define FLAG_GLOBAL    0x08 /* local options that should be globally settable in SWAT */
-#define FLAG_DEPRECATED 0x10 /* options that should no longer be used */
-#define FLAG_HIDE      0x20 /* options that should be hidden in SWAT */
+#define FLAG_BASIC     0x0001 /* fundamental options */
+#define FLAG_SHARE     0x0002 /* file sharing options */
+#define FLAG_PRINT     0x0004 /* printing options */
+#define FLAG_GLOBAL    0x0008 /* local options that should be globally settable in SWAT */
+#define FLAG_WIZARD    0x0010 /* Parameters that the wizard will operate on */
+#define FLAG_ADVANCED  0x0020 /* Parameters that the wizard will operate on */
+#define FLAG_DEVELOPER         0x0040 /* Parameters that the wizard will operate on */
+#define FLAG_DEPRECATED 0x1000 /* options that should no longer be used */
+#define FLAG_HIDE      0x2000 /* options that should be hidden in SWAT */
+#define FLAG_DOS_STRING 0x4000 /* convert from UNIX to DOS codepage when reading this string. */
 
 #ifndef LOCKING_VERSION
 #define LOCKING_VERSION 4
@@ -1147,17 +1116,17 @@ struct bitmap {
 #define FILE_SHARE_DELETE 4
 
 /* FileAttributesField */
-#define FILE_ATTRIBUTE_READONLY aRONLY
-#define FILE_ATTRIBUTE_HIDDEN aHIDDEN
-#define FILE_ATTRIBUTE_SYSTEM aSYSTEM
-#define FILE_ATTRIBUTE_DIRECTORY aDIR
-#define FILE_ATTRIBUTE_ARCHIVE aARCH
-#define FILE_ATTRIBUTE_NORMAL 0x80L
-#define FILE_ATTRIBUTE_TEMPORARY 0x100L
-#define FILE_ATTRIBUTE_SPARSE 0x200L
-#define FILE_ATTRIBUTE_COMPRESSED 0x800L
-#define FILE_ATTRIBUTE_NONINDEXED 0x2000L
-#define SAMBA_ATTRIBUTES_MASK 0x7F
+#define FILE_ATTRIBUTE_READONLY                0x001L
+#define FILE_ATTRIBUTE_HIDDEN          0x002L
+#define FILE_ATTRIBUTE_SYSTEM          0x004L
+#define FILE_ATTRIBUTE_DIRECTORY       0x010L
+#define FILE_ATTRIBUTE_ARCHIVE         0x020L
+#define FILE_ATTRIBUTE_NORMAL          0x080L
+#define FILE_ATTRIBUTE_TEMPORARY       0x100L
+#define FILE_ATTRIBUTE_SPARSE          0x200L
+#define FILE_ATTRIBUTE_COMPRESSED      0x800L
+#define FILE_ATTRIBUTE_NONINDEXED      0x2000L
+#define SAMBA_ATTRIBUTES_MASK          0x7F
 
 /* Flags - combined with attributes. */
 #define FILE_FLAG_WRITE_THROUGH    0x80000000L
@@ -1185,8 +1154,10 @@ struct bitmap {
 #define FILE_EIGHT_DOT_THREE_ONLY 0x0400
 #define FILE_RANDOM_ACCESS        0x0800
 #define FILE_DELETE_ON_CLOSE      0x1000
+#define FILE_OPEN_BY_FILE_ID     0x2000
 
 /* Responses when opening a file. */
+#define FILE_WAS_SUPERSEDED 0
 #define FILE_WAS_OPENED 1
 #define FILE_WAS_CREATED 2
 #define FILE_WAS_OVERWRITTEN 3
@@ -1299,7 +1270,7 @@ char *strdup(char *s);
  */
  
 #define DEFAULT_MAJOR_VERSION 0x04
-#define DEFAULT_MINOR_VERSION 0x05
+#define DEFAULT_MINOR_VERSION 0x09
 
 /* Browser Election Values */
 #define BROWSER_ELECTION_VERSION       0x010f
@@ -1375,6 +1346,9 @@ enum schema_types {SCHEMA_COMPAT, SCHEMA_AD, SCHEMA_SAMBA};
 /* LDAP SSL options */
 enum ldap_ssl_types {LDAP_SSL_ON, LDAP_SSL_OFF, LDAP_SSL_START_TLS};
 
+/* LDAP PASSWD SYNC methods */
+enum ldap_passwd_sync_types {LDAP_PASSWD_SYNC_ON, LDAP_PASSWD_SYNC_OFF, LDAP_PASSWD_SYNC_ONLY};
+
 /* Remote architectures we know about. */
 enum remote_arch_types {RA_UNKNOWN, RA_WFWG, RA_OS2, RA_WIN95, RA_WINNT, RA_WIN2K, RA_SAMBA};
 
@@ -1656,8 +1630,6 @@ struct unix_error_map {
 
 #define SAFE_NETBIOS_CHARS ". -_"
 
-#include "nsswitch/winbindd_nss.h"
-
 /* generic iconv conversion structure */
 typedef struct {
        size_t (*direct)(void *cd, char **inbuf, size_t *inbytesleft,
index 3ed670d38ba81c126cf704f8768e489cacdfae1d..e7edb62bde2ca23e97cbacd8fef3b011bdff3966 100644 (file)
@@ -20,9 +20,6 @@
 
 #ifndef _SMB_ACLS_H
 #define _SMB_ACLS_H
-
-#include "includes.h"
-
 #if defined(HAVE_POSIX_ACLS)
 
 /* This is an identity mapping (just remove the SMB_). */
index a2351c705eaede2d1e14f8f71e894540ea38fe8d..71d4bac795243a0a5e84ef631a35547bcc7084be 100644 (file)
 #define FNUM_OK(fsp,c) (OPEN_FSP(fsp) && (c)==(fsp)->conn)
 
 #define CHECK_FSP(fsp,conn) if (!FNUM_OK(fsp,conn)) \
-                               return(ERROR_DOS(ERRDOS,ERRbadfid)); \
-                            else if((fsp)->fd == -1) \
-                               return(ERROR_DOS(ERRDOS,ERRbadaccess))
+                               return(ERROR_DOS(ERRDOS,ERRbadfid)); \
+                       else if((fsp)->fd == -1) \
+                               return(ERROR_DOS(ERRDOS,ERRbadaccess))
 
 #define CHECK_READ(fsp) if (!(fsp)->can_read) \
-                               return(ERROR_DOS(ERRDOS,ERRbadaccess))
+                               return(ERROR_DOS(ERRDOS,ERRbadaccess))
 #define CHECK_WRITE(fsp) if (!(fsp)->can_write) \
-                               return(ERROR_DOS(ERRDOS,ERRbadaccess))
+                               return(ERROR_DOS(ERRDOS,ERRbadaccess))
 
 #define CHECK_ERROR(fsp) if (HAS_CACHED_ERROR(fsp)) \
-                                                               return(CACHED_ERROR(fsp))
+                               return(CACHED_ERROR(fsp))
+
+#define ERROR_WAS_LOCK_DENIED(status) (NT_STATUS_EQUAL((status), NT_STATUS_LOCK_NOT_GRANTED) || \
+                               NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT) )
 
 /* translates a connection number into a service number */
 #define SNUM(conn)         ((conn)?(conn)->service:-1)
 /* this is how errors are generated */
 #define UNIXERROR(defclass,deferror) unix_error_packet(outbuf,defclass,deferror,__LINE__,__FILE__)
 
-#define SMB_ROUNDUP(x,g) (((x)+((g)-1))&~((g)-1))
-#define SMB_ROUNDUP_ALLOCATION(s) ((s) ? (SMB_ROUNDUP((SMB_OFF_T)((s)+1), ((SMB_OFF_T)SMB_ROUNDUP_ALLOCATION_SIZE))) : 0 )
+#define SMB_ROUNDUP(x,r) ( ((x)%(r)) ? ( (((x)+(r))/(r))*(r) ) : (x))
 
 /* Extra macros added by Ying Chen at IBM - speed increase by inlining. */
 #define smb_buf(buf) (((char *)(buf)) + smb_size + CVAL(buf,smb_wct)*2)
index 82017cee85400be8173ef1c57328ba43e4a2bb65..e501de8c0e2566a8127c0540b4415a35044c6912 100644 (file)
@@ -34,7 +34,7 @@ enum flush_reason_enum { SEEK_FLUSH, READ_FLUSH, WRITE_FLUSH, READRAW_FLUSH,
 
 #define PROF_SHMEM_KEY ((key_t)0x07021999)
 #define PROF_SHM_MAGIC 0x6349985
-#define PROF_SHM_VERSION 6
+#define PROF_SHM_VERSION 7
 
 /* time values in the following structure are in microseconds */
 
@@ -65,6 +65,9 @@ struct profile_stats {
        unsigned syscall_write_bytes;   /* bytes written with write syscall */
        unsigned syscall_lseek_count;
        unsigned syscall_lseek_time;
+       unsigned syscall_sendfile_count;
+       unsigned syscall_sendfile_time;
+       unsigned syscall_sendfile_bytes; /* bytes read with sendfile syscall */
        unsigned syscall_rename_count;
        unsigned syscall_rename_time;
        unsigned syscall_fsync_count;
index fb265fdb1a88d5a27a71543c9d06b0b67cad5de0..3468d3b9950a1647629b4d713fe4ff129bcc84df 100644 (file)
@@ -193,16 +193,19 @@ Byte offset   Type     name                description
 } FSINFO;
 *************************************************************/
 
-#define SMB_INFO_STANDARD               1
-#define SMB_INFO_QUERY_EA_SIZE          2
-#define SMB_INFO_QUERY_EAS_FROM_LIST    3
-#define SMB_INFO_QUERY_ALL_EAS          4
+#define SMB_INFO_STANDARD               1  /* FILESTATUS3 struct */
+#define SMB_INFO_SET_EA                 2  /* EAOP2 struct, only valid on set not query */
+#define SMB_INFO_QUERY_EA_SIZE          2  /* FILESTATUS4 struct, only valid on query not set */
+#define SMB_INFO_QUERY_EAS_FROM_LIST    3  /* only valid on query not set */
+#define SMB_INFO_QUERY_ALL_EAS          4  /* only valid on query not set */
 #define SMB_INFO_IS_NAME_VALID          6
-#define SMB_QUERY_FS_LABEL_INFO                        0x101
-#define SMB_QUERY_FS_VOLUME_INFO               0x102
-#define SMB_QUERY_FS_SIZE_INFO                 0x103
-#define SMB_QUERY_FS_DEVICE_INFO               0x104
-#define SMB_QUERY_FS_ATTRIBUTE_INFO            0x105
+#define SMB_INFO_STANDARD_LONG          11  /* similar to level 1, ie struct FileStatus3 */
+#define SMB_QUERY_EA_SIZE_LONG          12  /* similar to level 2, ie struct FileStatus4 */
+#define SMB_QUERY_FS_LABEL_INFO         0x101
+#define SMB_QUERY_FS_VOLUME_INFO        0x102
+#define SMB_QUERY_FS_SIZE_INFO          0x103
+#define SMB_QUERY_FS_DEVICE_INFO        0x104
+#define SMB_QUERY_FS_ATTRIBUTE_INFO     0x105
 
 
 #define l2_vol_fdateCreation 0
index 74df1c99141c4c7adee3b3cf9fd809f87affddf0..87e3673a7f69656e853e7353dbdd926cdd6a8e65 100644 (file)
@@ -1 +1 @@
-#define VERSION "3.0-alpha18"
+#define VERSION "3.0-alpha19"
index 1b1a13d7c125c43ee453812903a8403bb0354725..9a0676437138a45fc5d81188d1c525c1b2b2411e 100644 (file)
 /* Changed to version 2 for CIFS UNIX extensions (mknod and link added). JRA. */
 /* Changed to version 3 for POSIX acl extensions. JRA. */
 /* Changed to version 4 for cascaded VFS interface. Alexander Bokovoy. */
+/* Changed to version 5 for sendfile addition. JRA. */
 #define SMB_VFS_INTERFACE_VERSION 5
 
 
 /* Version of supported cascaded interface backward copmatibility.
-   (version 4 corresponds to SMB_VFS_INTERFACE_VERSION 4)
+   (version 5 corresponds to SMB_VFS_INTERFACE_VERSION 5)
    It is used in vfs_init_custom() to detect VFS modules which conform to cascaded 
    VFS interface but implement elder version than current version of Samba uses.
    This allows to use old modules with new VFS interface as far as combined VFS operation
    set is coherent (will be in most cases). 
 */
-#define SMB_VFS_INTERFACE_CASCADED 4
+#define SMB_VFS_INTERFACE_CASCADED 5
 
 /*
     Each VFS module must provide following global functions:
@@ -116,6 +117,7 @@ struct vfs_ops {
        ssize_t (*read)(struct files_struct *fsp, int fd, void *data, size_t n);
        ssize_t (*write)(struct files_struct *fsp, int fd, const void *data, size_t n);
        SMB_OFF_T (*lseek)(struct files_struct *fsp, int filedes, SMB_OFF_T offset, int whence);
+       ssize_t (*sendfile)(int tofd, files_struct *fsp, int fromfd, const DATA_BLOB *header, SMB_OFF_T offset, size_t count);
        int (*rename)(struct connection_struct *conn, const char *old, const char *new);
        int (*fsync)(struct files_struct *fsp, int fd);
        int (*stat)(struct connection_struct *conn, const char *fname, SMB_STRUCT_STAT *sbuf);
@@ -210,6 +212,7 @@ typedef enum _vfs_op_type {
        SMB_VFS_OP_READ,
        SMB_VFS_OP_WRITE,
        SMB_VFS_OP_LSEEK,
+       SMB_VFS_OP_SENDFILE,
        SMB_VFS_OP_RENAME,
        SMB_VFS_OP_FSYNC,
        SMB_VFS_OP_STAT,
index 07b5e2ecfc649066ff90afbfd0b088a03d036fb1..b5f205c508687628aed45abade2f8eb6921a6d94 100644 (file)
@@ -128,7 +128,7 @@ BOOL account_policy_get(int field, uint32 *value)
                return False;
        }
        if (!tdb_fetch_uint32(tdb, name, value)) {
-               DEBUG(1, ("account_policy_get: tdb_fetch_uint32 failed for feild %d (%s), returning 0", field, name));
+               DEBUG(1, ("account_policy_get: tdb_fetch_uint32 failed for efild %d (%s), returning 0", field, name));
                return False;
        }
        DEBUG(10,("account_policy_get: %s:%d\n", name, *value));
@@ -151,7 +151,7 @@ BOOL account_policy_set(int field, uint32 value)
        }
 
        if (!tdb_store_uint32(tdb, name, value)) {
-               DEBUG(1, ("tdb_store_uint32 failed for feild %d (%s) on value %u", field, name, value));
+               DEBUG(1, ("tdb_store_uint32 failed for field %d (%s) on value %u", field, name, value));
                return False;
        }
 
index 6e961366435b983e528b3a45181cbce10bec8e8e..cd8aa4fe55f75f823c6b1b2107e69156f95bc466 100644 (file)
@@ -432,13 +432,14 @@ int push_ucs2(const void *base_ptr, void *dest, const char *src, int dest_len, i
  * @param dest always set at least to NULL 
  *
  * @retval The number of bytes occupied by the string in the destination
+ *         or -1 in case of error.
  **/
-int push_ucs2_talloc(TALLOC_CTX *ctx, void **dest, const char *src)
+int push_ucs2_talloc(TALLOC_CTX *ctx, smb_ucs2_t **dest, const char *src)
 {
        int src_len = strlen(src)+1;
 
        *dest = NULL;
-       return convert_string_talloc(ctx, CH_UNIX, CH_UCS2, src, src_len, dest);
+       return convert_string_talloc(ctx, CH_UNIX, CH_UCS2, src, src_len, (void **)dest);
 }
 
 /**
@@ -447,13 +448,14 @@ int push_ucs2_talloc(TALLOC_CTX *ctx, void **dest, const char *src)
  * @param dest always set at least to NULL 
  *
  * @retval The number of bytes occupied by the string in the destination
+ *         or -1 in case of error.
  **/
-int push_ucs2_allocate(void **dest, const char *src)
+int push_ucs2_allocate(smb_ucs2_t **dest, const char *src)
 {
        int src_len = strlen(src)+1;
 
        *dest = NULL;
-       return convert_string_allocate(CH_UNIX, CH_UCS2, src, src_len, dest);   
+       return convert_string_allocate(CH_UNIX, CH_UCS2, src, src_len, (void **)dest);  
 }
 
 /****************************************************************************
index 842d2dac1d62650b431de0ec459397c855c5006c..f4f3ee2f9f94c9ac7f28d6b7385286d0a42f58ce 100644 (file)
@@ -153,8 +153,10 @@ static const char *default_classname_table[] = {
        "rpc_srv",           /* DBGC_RPC_SRV      */
        "rpc_cli",           /* DBGC_RPC_CLI      */
        "passdb",            /* DBGC_PASSDB       */
+       "sam",               /* DBGC_SAM          */
        "auth",              /* DBGC_AUTH         */
        "winbind",           /* DBGC_WINBIND      */
+       "vfs",               /* DBGC_VFS          */
        NULL
 };
 
@@ -350,7 +352,7 @@ int debug_lookup_classname(const char *classname)
 
 
 /****************************************************************************
-dump the current registered denug levels
+dump the current registered debug levels
 ****************************************************************************/
 static void debug_dump_status(int level)
 {
@@ -371,8 +373,7 @@ static void debug_dump_status(int level)
 parse the debug levels from smbcontrol. Example debug level parameter:
   printdrivers:7
 ****************************************************************************/
-BOOL debug_parse_params(char **params, int *debuglevel_class,
-                       BOOL *debuglevel_class_isset)
+static BOOL debug_parse_params(char **params)
 {
        int   i, ndx;
        char *class_name;
@@ -385,8 +386,8 @@ BOOL debug_parse_params(char **params, int *debuglevel_class,
         * v.s. "all:10", this is the traditional way to set DEBUGLEVEL 
         */
        if (isdigit((int)params[0][0])) {
-               debuglevel_class[DBGC_ALL] = atoi(params[0]);
-               debuglevel_class_isset[DBGC_ALL] = True;
+               DEBUGLEVEL_CLASS[DBGC_ALL] = atoi(params[0]);
+               DEBUGLEVEL_CLASS_ISSET[DBGC_ALL] = True;
                i = 1; /* start processing at the next params */
        }
        else
@@ -397,8 +398,8 @@ BOOL debug_parse_params(char **params, int *debuglevel_class,
                if ((class_name=strtok(params[i],":")) &&
                        (class_level=strtok(NULL, "\0")) &&
             ((ndx = debug_lookup_classname(class_name)) != -1)) {
-                               debuglevel_class[ndx] = atoi(class_level);
-                               debuglevel_class_isset[ndx] = True;
+                               DEBUGLEVEL_CLASS[ndx] = atoi(class_level);
+                               DEBUGLEVEL_CLASS_ISSET[ndx] = True;
                } else {
                        DEBUG(0,("debug_parse_params: unrecognized debug class name or format [%s]\n", params[i]));
                        return False;
@@ -425,8 +426,7 @@ BOOL debug_parse_levels(const char *params_str)
 
        params = str_list_make(params_str, NULL);
 
-       if (debug_parse_params(params, DEBUGLEVEL_CLASS,
-                              DEBUGLEVEL_CLASS_ISSET))
+       if (debug_parse_params(params))
        {
                debug_dump_status(5);
                str_list_free(&params);
index 608d2b89bad4ed951cdb9747eee4488b40ab3b9c..af8cf960e8f2aee91f5776f6253b983bd03f02d5 100644 (file)
@@ -45,6 +45,9 @@ const struct unix_error_map unix_dos_nt_errmap[] = {
 #endif
 #ifdef EROFS
        { EROFS, ERRHRD, ERRnowrite, NT_STATUS_ACCESS_DENIED },
+#endif
+#ifdef ENAMETOOLONG
+       { ENAMETOOLONG, ERRDOS, 206, NT_STATUS_OBJECT_NAME_INVALID },
 #endif
        { 0, 0, 0, NT_STATUS_OK }
 };
index e6d2de4a58bb26f51da7d03fe4da95d813d3b28d..d9886a54daf66d602ed849c09df20f49138cc4cc 100644 (file)
@@ -382,10 +382,11 @@ void message_deregister(int msg_type)
 
 struct msg_all {
        int msg_type;
+       uint32 msg_flag;
        const void *buf;
        size_t len;
        BOOL duplicates;
-       int             n_sent;
+       int n_sent;
 };
 
 /****************************************************************************
@@ -405,13 +406,20 @@ static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, void
        if (crec.cnum != -1)
                return 0;
 
-       /* if the msg send fails because the pid was not found (i.e. smbd died), 
+       /* Don't send if the receiver hasn't registered an interest. */
+
+       if(!(crec.bcast_msg_flags & msg_all->msg_flag))
+               return 0;
+
+       /* If the msg send fails because the pid was not found (i.e. smbd died), 
         * the msg has already been deleted from the messages.tdb.*/
+
        if (!message_send_pid(crec.pid, msg_all->msg_type,
                              msg_all->buf, msg_all->len,
                              msg_all->duplicates)) {
                
-               /* if the pid was not found delete the entry from connections.tdb */
+               /* 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));
@@ -442,6 +450,17 @@ BOOL message_send_all(TDB_CONTEXT *conn_tdb, int msg_type,
        struct msg_all msg_all;
 
        msg_all.msg_type = msg_type;
+       if (msg_type < 1000)
+               msg_all.msg_flag = FLAG_MSG_GENERAL;
+       else if (msg_type > 1000 && msg_type < 2000)
+               msg_all.msg_flag = FLAG_MSG_NMBD;
+       else if (msg_type > 2000 && msg_type < 3000)
+               msg_all.msg_flag = FLAG_MSG_PRINTING;
+       else if (msg_type > 3000 && msg_type < 4000)
+               msg_all.msg_flag = FLAG_MSG_SMBD;
+       else
+               return False;
+
        msg_all.buf = buf;
        msg_all.len = len;
        msg_all.duplicates = duplicates_allowed;
@@ -452,73 +471,4 @@ BOOL message_send_all(TDB_CONTEXT *conn_tdb, int msg_type,
                *n_sent = msg_all.n_sent;
        return True;
 }
-
-static SIG_ATOMIC_T gotalarm;
-
-/***************************************************************
- Signal function to tell us we timed out.
-****************************************************************/
-
-static void gotalarm_sig(void)
-{
-       gotalarm = 1;
-}
-
-/**
- * Lock the messaging tdb based on a string - this is used as a primitive
- * form of mutex between smbd instances. 
- *
- * @param name A string identifying the name of the mutex.
- */
-
-BOOL message_named_mutex(char *name, unsigned int timeout)
-{
-       TDB_DATA key;
-       int ret;
-       void (*oldsig_handler)(int) = NULL;
-
-       if (!message_init())
-               return False;
-
-       key.dptr = name;
-       key.dsize = strlen(name)+1;
-
-       if (timeout) {
-               gotalarm = 0;
-               oldsig_handler = CatchSignal(SIGALRM, SIGNAL_CAST gotalarm_sig);
-               alarm(timeout);
-       }
-
-       ret = tdb_chainlock(tdb, key);
-
-       if (timeout) {
-               alarm(0);
-               CatchSignal(SIGALRM, SIGNAL_CAST oldsig_handler);
-               if (gotalarm)
-                       return False;
-       }
-
-       if (ret == 0)
-               DEBUG(10,("message_named_mutex: got mutex for %s\n", name ));
-
-       return (ret == 0);
-}
-
-/**
- * Unlock a named mutex.
- *
- * @param name A string identifying the name of the mutex.
- */
-
-void message_named_mutex_release(char *name)
-{
-       TDB_DATA key;
-
-       key.dptr = name;
-       key.dsize = strlen(name)+1;
-
-       tdb_chainunlock(tdb, key);
-       DEBUG(10,("message_named_mutex: released mutex for %s\n", name ));
-}
-
 /** @} **/
index a3d6af4fbc1a6a766690d0402adcf47cf89a2fb2..bbc17cb704de8520fac1be8ff5e4aad3cd572c84 100644 (file)
@@ -33,7 +33,7 @@ static void debug_callback(poptContext con,
        switch(opt->val) {
        case 'd':
                if (arg) {
-                       DEBUGLEVEL = atoi(arg);
+                       debug_parse_levels(arg);
                        AllowDebugChange = False;
                }
 
@@ -43,7 +43,7 @@ static void debug_callback(poptContext con,
 
 struct poptOption popt_common_debug[] = {
        { NULL, 0, POPT_ARG_CALLBACK, debug_callback },
-       { "debuglevel", 'd', POPT_ARG_INT, NULL, 'd', "Set debug level", 
+       { "debuglevel", 'd', POPT_ARG_STRING, NULL, 'd', "Set debug level", 
          "DEBUGLEVEL" },
        { 0 }
 };
index d80c571dd3bb8d1aabf2b1139b8059c0420b81da..58c4ecf482dbb4c30f8690473501bff9371316d7 100644 (file)
 
 #include "includes.h"
 
+#ifdef HAVE_LIBREADLINE
+#  ifdef HAVE_READLINE_READLINE_H
+#    include <readline/readline.h>
+#    ifdef HAVE_READLINE_HISTORY_H
+#      include <readline/history.h>
+#    endif
+#  else
+#    ifdef HAVE_READLINE_H
+#      include <readline.h>
+#      ifdef HAVE_HISTORY_H
+#        include <history.h>
+#      endif
+#    else
+#      undef HAVE_LIBREADLINE
+#    endif
+#  endif
+#endif
+
 #ifdef HAVE_NEW_LIBREADLINE
 #  define RL_COMPLETION_CAST (rl_completion_func_t *)
 #else
index 416d77564d76f00cf1e29d3fac906efa3c0e138a..3e5512c734205d77720525cab9dc89af7af0972a 100644 (file)
@@ -38,7 +38,7 @@ BOOL grab_server_mutex(const char *name)
                DEBUG(0,("grab_server_mutex: malloc failed for %s\n", name));
                return False;
        }
-       if (!message_named_mutex(mutex_server_name, 20)) {
+       if (!secrets_named_mutex(mutex_server_name, 10)) {
                DEBUG(10,("grab_server_mutex: failed for %s\n", name));
                SAFE_FREE(mutex_server_name);
                return False;
@@ -50,8 +50,7 @@ BOOL grab_server_mutex(const char *name)
 void release_server_mutex(void)
 {
        if (mutex_server_name) {
-               message_named_mutex_release(mutex_server_name);
+               secrets_named_mutex_release(mutex_server_name);
                SAFE_FREE(mutex_server_name);
        }
 }
-
index 026df0f67f1518ae2a76bced7e347f1db855cc9c..2550d00d14c7318015433147a968d6862bb5afcb 100644 (file)
@@ -297,8 +297,13 @@ void standard_sub_basic(const char *smb_name, char *str,size_t len)
                case 'L' : 
                        if (local_machine_name && *local_machine_name)
                                string_sub(p,"%L", local_machine_name,l); 
-                       else
-                               string_sub(p,"%L", global_myname,l); 
+                       else {
+                               pstring temp_name;
+
+                               pstrcpy(temp_name, global_myname);
+                               strlower(temp_name);
+                               string_sub(p,"%L", temp_name,l); 
+                       }
                        break;
                case 'M' :
                        string_sub(p,"%M", client_name(),l);
@@ -675,6 +680,19 @@ void standard_sub_conn(connection_struct *conn, char *str, size_t len)
                        conn->gid, current_user_info.smb_name, str, len);
 }
 
+char *talloc_sub_conn(TALLOC_CTX *mem_ctx, connection_struct *conn, char *str)
+{
+       return talloc_sub_advanced(mem_ctx, SNUM(conn), conn->user,
+                       conn->connectpath, conn->gid,
+                       current_user_info.smb_name, str);
+}
+
+char *alloc_sub_conn(connection_struct *conn, char *str)
+{
+       return alloc_sub_advanced(SNUM(conn), conn->user, conn->connectpath,
+                       conn->gid, current_user_info.smb_name, str);
+}
+
 /****************************************************************************
  Like standard_sub but by snum.
 ****************************************************************************/
index edda54a78d2745f04c557becbf82982ec25ee7ca..873b8737d506399d7e36d46df7351329947275a7 100644 (file)
@@ -1233,26 +1233,23 @@ int sys_dup2(int oldfd, int newfd)
  Wrapper for Admin Logs.
 ****************************************************************************/
 
-void sys_adminlog(int priority, const char *format_str, ...)
+void sys_adminlog(int priority, char *format_str, ...)
 {
        va_list ap;
        int ret;
-       char **msgbuf = NULL;
-
-       if (!lp_admin_log())
-               return;
+       char *msgbuf = NULL;
 
        va_start( ap, format_str );
-       ret = vasprintf( msgbuf, format_str, ap );
+       ret = vasprintf( &msgbuf, format_str, ap );
        va_end( ap );
 
        if (ret == -1)
                return;
 
 #if defined(HAVE_SYSLOG)
-       syslog( priority, "%s", *msgbuf );
+       syslog( priority, "%s", msgbuf );
 #else
-       DEBUG(0,("%s", *msgbuf ));
+       DEBUG(0,("%s", msgbuf ));
 #endif
-       SAFE_FREE(*msgbuf);
+       SAFE_FREE(msgbuf);
 }
index 28ceaf393905ab58319bda46bbe632c89a0110a5..0cd308694533934c131df10b197a82276de8ab82 100644 (file)
@@ -41,6 +41,11 @@ static int getgrouplist_internals(const char *user, gid_t gid, gid_t *groups, in
        gid_t *gids_saved;
        int ret, ngrp_saved;
 
+       if (non_root_mode()) {
+               *grpcnt = 0;
+               return 0;
+       }
+
        /* work out how many groups we need to save */
        ngrp_saved = getgroups(0, NULL);
        if (ngrp_saved == -1) {
@@ -56,13 +61,14 @@ static int getgrouplist_internals(const char *user, gid_t gid, gid_t *groups, in
 
        ngrp_saved = getgroups(ngrp_saved, gids_saved);
        if (ngrp_saved == -1) {
-               free(gids_saved);
+               SAFE_FREE(gids_saved);
                /* very strange! */
                return -1;
        }
 
        if (initgroups(user, gid) != 0) {
-               free(gids_saved);
+               DEBUG(0, ("getgrouplist_internals: initgroups() failed!\n"));
+               SAFE_FREE(gids_saved);
                return -1;
        }
 
@@ -101,5 +107,6 @@ int sys_getgrouplist(const char *user, gid_t gid, gid_t *groups, int *grpcnt)
        become_root();
        retval = getgrouplist_internals(user, gid, groups, grpcnt);
        unbecome_root();
+       return retval;
 #endif
 }
index 9d87414aea058f01e612a64039754a936a792884..ef12dc15f3443bdbdaaa0ea050357d2497131200 100644 (file)
@@ -40,6 +40,12 @@ int extra_time_offset = 0;
 #define TIME_T_MAX (~ (time_t) 0 - TIME_T_MIN)
 #endif
 
+void get_nttime_max(NTTIME *t)
+{
+       /* FIXME: This is incorrect */
+       unix_to_nt_time(t, get_time_t_max());
+}
+
 /*******************************************************************
  External access to time_t_min and time_t_max.
 ********************************************************************/
index 5db7f58b1e254dd42346b33270bc84e9f11ce00c..ef11542ab194afa8bd51fa3c3fa774a45caa09e2 100644 (file)
@@ -273,27 +273,6 @@ done:
        return ret;
 }
 
-/****************************************************************************
- Get_Pwnam wrapper for modification.
-  NOTE: This can potentially modify 'user'! 
-****************************************************************************/
-
-struct passwd *Get_Pwnam_Modify(fstring user)
-{
-       fstring user2;
-       struct passwd *ret;
-
-       fstrcpy(user2, user);
-
-       ret = Get_Pwnam_internals(user, user2);
-       
-       /* If caller wants the modified username, ensure they get it  */
-       fstrcpy(user,user2);
-
-       /* We can safely assume ret is NULL if none of the above succeed */
-       return(ret);  
-}
-
 /****************************************************************************
  Get_Pwnam wrapper without modification.
   NOTE: This with NOT modify 'user'! 
@@ -636,39 +615,3 @@ static struct passwd * uname_string_combinations(char *s,struct passwd * (*fn)(c
        return(NULL);
 }
 
-/****************************************************************************
- These wrappers allow appliance mode to work. In appliance mode the username
- takes the form DOMAIN/user.
-****************************************************************************/
-
-struct passwd *smb_getpwnam(char *user, BOOL allow_change)
-{
-       struct passwd *pw;
-       char *p;
-       char *sep;
-       extern pstring global_myname;
-
-       if (allow_change)
-               pw = Get_Pwnam_Modify(user);
-       else
-               pw = Get_Pwnam(user);
-
-       if (pw)
-               return pw;
-
-       /*
-        * If it is a domain qualified name and it isn't in our password
-        * database but the domain portion matches our local machine name then
-        * lookup just the username portion locally.
-        */
-
-       sep = lp_winbind_separator();
-       p = strchr_m(user,*sep);
-       if (p && strncasecmp(global_myname, user, strlen(global_myname))==0) {
-               if (allow_change)
-                       pw = Get_Pwnam_Modify(p+1);
-               else
-                       pw = Get_Pwnam(p+1);
-       }
-       return NULL;
-}
index ae94b710b2cbabc2603294bab617c9678a5f4d40..51b92568b4dffb7232ac9eeb6dac6a40e7b72f39 100644 (file)
@@ -260,8 +260,8 @@ void show_msg(char *buf)
        int i;
        int bcc=0;
 
-       if (DEBUGLEVEL < 5) return;
-
+       if (!DEBUGLVL(5)) return;
+       
        DEBUG(5,("size=%d\nsmb_com=0x%x\nsmb_rcls=%d\nsmb_reh=%d\nsmb_err=%d\nsmb_flg=%d\nsmb_flg2=%d\n",
                        smb_len(buf),
                        (int)CVAL(buf,smb_com),
@@ -270,31 +270,26 @@ void show_msg(char *buf)
                        (int)SVAL(buf,smb_err),
                        (int)CVAL(buf,smb_flg),
                        (int)SVAL(buf,smb_flg2)));
-       DEBUG(5,("smb_tid=%d\nsmb_pid=%d\nsmb_uid=%d\nsmb_mid=%d\nsmt_wct=%d\n",
+       DEBUGADD(5,("smb_tid=%d\nsmb_pid=%d\nsmb_uid=%d\nsmb_mid=%d\n",
                        (int)SVAL(buf,smb_tid),
                        (int)SVAL(buf,smb_pid),
                        (int)SVAL(buf,smb_uid),
-                       (int)SVAL(buf,smb_mid),
-                       (int)CVAL(buf,smb_wct)));
+                       (int)SVAL(buf,smb_mid)));
+       DEBUGADD(5,("smt_wct=%d\n",(int)CVAL(buf,smb_wct)));
 
        for (i=0;i<(int)CVAL(buf,smb_wct);i++)
-       {
-               DEBUG(5,("smb_vwv[%d]=%d (0x%X)\n",i,
+               DEBUGADD(5,("smb_vwv[%2d]=%5d (0x%X)\n",i,
                        SVAL(buf,smb_vwv+2*i),SVAL(buf,smb_vwv+2*i)));
-       }
-
+       
        bcc = (int)SVAL(buf,smb_vwv+2*(CVAL(buf,smb_wct)));
 
-       DEBUG(5,("smb_bcc=%d\n",bcc));
+       DEBUGADD(5,("smb_bcc=%d\n",bcc));
 
        if (DEBUGLEVEL < 10) return;
 
-       if (DEBUGLEVEL < 50)
-       {
-               bcc = MIN(bcc, 512);
-       }
+       if (DEBUGLEVEL < 50) bcc = MIN(bcc, 512);
 
-       dump_data(10, smb_buf(buf), bcc);
+       dump_data(10, smb_buf(buf), bcc);       
 }
 
 /*******************************************************************
@@ -1140,8 +1135,18 @@ something really nasty happened - panic!
 void smb_panic(char *why)
 {
        char *cmd = lp_panic_action();
+       int result;
+
        if (cmd && *cmd) {
-               system(cmd);
+               DEBUG(0, ("smb_panic(): calling panic action [%s]\n", cmd));
+               result = system(cmd);
+
+               if (result == -1)
+                       DEBUG(0, ("smb_panic(): fork failed in panic action: %s\n",
+                                 strerror(errno)));
+               else
+                       DEBUG(0, ("smb_panic(): action returned status %d\n",
+                                 WEXITSTATUS(result)));
        }
        DEBUG(0,("PANIC: %s\n", why));
        dbgflush();
@@ -1564,35 +1569,35 @@ void print_asc(int level, const unsigned char *buf,int len)
 
 void dump_data(int level, const char *buf1,int len)
 {
-  const unsigned char *buf = (const unsigned char *)buf1;
-  int i=0;
-  if (len<=0) return;
-
-  DEBUG(level,("[%03X] ",i));
-  for (i=0;i<len;) {
-    DEBUG(level,("%02X ",(int)buf[i]));
-    i++;
-    if (i%8 == 0) DEBUG(level,(" "));
-    if (i%16 == 0) {      
-      print_asc(level,&buf[i-16],8); DEBUG(level,(" "));
-      print_asc(level,&buf[i-8],8); DEBUG(level,("\n"));
-      if (i<len) DEBUG(level,("[%03X] ",i));
-    }
-  }
-  if (i%16) {
-    int n;
-
-    n = 16 - (i%16);
-    DEBUG(level,(" "));
-    if (n>8) DEBUG(level,(" "));
-    while (n--) DEBUG(level,("   "));
-
-    n = MIN(8,i%16);
-    print_asc(level,&buf[i-(i%16)],n); DEBUG(level,(" "));
-    n = (i%16) - n;
-    if (n>0) print_asc(level,&buf[i-n],n); 
-    DEBUG(level,("\n"));    
-  }
+       const unsigned char *buf = (const unsigned char *)buf1;
+       int i=0;
+       if (len<=0) return;
+
+       if (!DEBUGLVL(level)) return;
+       
+       DEBUGADD(level,("[%03X] ",i));
+       for (i=0;i<len;) {
+               DEBUGADD(level,("%02X ",(int)buf[i]));
+               i++;
+               if (i%8 == 0) DEBUGADD(level,(" "));
+               if (i%16 == 0) {      
+                       print_asc(level,&buf[i-16],8); DEBUGADD(level,(" "));
+                       print_asc(level,&buf[i-8],8); DEBUGADD(level,("\n"));
+                       if (i<len) DEBUGADD(level,("[%03X] ",i));
+               }
+       }
+       if (i%16) {
+               int n;
+               n = 16 - (i%16);
+               DEBUGADD(level,(" "));
+               if (n>8) DEBUGADD(level,(" "));
+               while (n--) DEBUGADD(level,("   "));
+               n = MIN(8,i%16);
+               print_asc(level,&buf[i-(i%16)],n); DEBUGADD(level,( " " ));
+               n = (i%16) - n;
+               if (n>0) print_asc(level,&buf[i-n],n); 
+               DEBUGADD(level,("\n"));    
+       }       
 }
 
 char *tab_depth(int depth)
@@ -1819,6 +1824,17 @@ char *smb_xstrdup(const char *s)
        return s1;
 }
 
+/**
+ strndup that aborts on malloc fail.
+**/
+char *smb_xstrndup(const char *s, size_t n)
+{
+       char *s1 = strndup(s, n);
+       if (!s1)
+               smb_panic("smb_xstrndup: malloc fail\n");
+       return s1;
+}
+
 /*
   vasprintf that aborts on malloc fail
 */
index 9fdf03adfc8b13c0eb79ada6b9c86146628adfca..b137023e55cfa5b83ae581d8b61109e12df1dd3b 100644 (file)
@@ -21,6 +21,8 @@
 
 #include "includes.h"
 
+extern DOM_SID global_sid_Builtin;
+
 /**********************************************************************************
  Check if this ACE has a SID in common with the token.
 **********************************************************************************/
@@ -42,7 +44,7 @@ static BOOL token_sid_in_ace(const NT_USER_TOKEN *token, const SEC_ACE *ace)
  bits not yet granted. Zero means permission allowed (no more needed bits).
 **********************************************************************************/
 
-static uint32 check_ace(SEC_ACE *ace, NT_USER_TOKEN *token, uint32 acc_desired, 
+static uint32 check_ace(SEC_ACE *ace, const NT_USER_TOKEN *token, uint32 acc_desired, 
                        NTSTATUS *status)
 {
        uint32 mask = ace->info.mask;
@@ -102,7 +104,7 @@ static uint32 check_ace(SEC_ACE *ace, NT_USER_TOKEN *token, uint32 acc_desired,
  include other bits requested.
 **********************************************************************************/ 
 
-static BOOL get_max_access( SEC_ACL *the_acl, NT_USER_TOKEN *token, uint32 *granted, 
+static BOOL get_max_access( SEC_ACL *the_acl, const NT_USER_TOKEN *token, uint32 *granted, 
                            uint32 desired, 
                            NTSTATUS *status)
 {
@@ -224,7 +226,7 @@ void se_map_standard(uint32 *access_mask, struct standard_mapping *mapping)
  "Access-Checking" document in MSDN.
 *****************************************************************************/ 
 
-BOOL se_access_check(SEC_DESC *sd, NT_USER_TOKEN *token,
+BOOL se_access_check(SEC_DESC *sd, const NT_USER_TOKEN *token,
                     uint32 acc_desired, uint32 *acc_granted, 
                     NTSTATUS *status)
 {
@@ -262,12 +264,13 @@ BOOL se_access_check(SEC_DESC *sd, NT_USER_TOKEN *token,
        }
 
        /* The user sid is the first in the token */
-
-       DEBUG(3, ("se_access_check: user sid is %s\n", sid_to_string(sid_str, &token->user_sids[PRIMARY_USER_SID_INDEX]) ));
-
-       for (i = 1; i < token->num_sids; i++) {
-               DEBUG(3, ("se_access_check: also %s\n",
-                         sid_to_string(sid_str, &token->user_sids[i])));
+       if (DEBUGLVL(3)) {
+               DEBUG(3, ("se_access_check: user sid is %s\n", sid_to_string(sid_str, &token->user_sids[PRIMARY_USER_SID_INDEX]) ));
+               
+               for (i = 1; i < token->num_sids; i++) {
+                       DEBUGADD(3, ("se_access_check: also %s\n",
+                                 sid_to_string(sid_str, &token->user_sids[i])));
+               }
        }
 
        /* Is the token the owner of the SID ? */
@@ -297,7 +300,7 @@ BOOL se_access_check(SEC_DESC *sd, NT_USER_TOKEN *token,
        for ( i = 0 ; i < the_acl->num_aces && tmp_acc_desired != 0; i++) {
                SEC_ACE *ace = &the_acl->ace[i];
 
-               DEBUG(10,("se_access_check: ACE %u: type %d, flags = 0x%02x, SID = %s mask = %x, current desired = %x\n",
+               DEBUGADD(10,("se_access_check: ACE %u: type %d, flags = 0x%02x, SID = %s mask = %x, current desired = %x\n",
                          (unsigned int)i, ace->type, ace->flags,
                          sid_to_string(sid_str, &ace->trustee),
                          (unsigned int) ace->info.mask, 
@@ -442,3 +445,42 @@ SEC_DESC_BUF *se_create_child_secdesc(TALLOC_CTX *ctx, SEC_DESC *parent_ctr,
 
        return sdb;
 }
+
+/*******************************************************************
+ samr_make_sam_obj_sd
+ ********************************************************************/
+
+NTSTATUS samr_make_sam_obj_sd(TALLOC_CTX *ctx, SEC_DESC **psd, size_t *sd_size)
+{
+       extern DOM_SID global_sid_World;
+       DOM_SID adm_sid;
+       DOM_SID act_sid;
+
+       SEC_ACE ace[3];
+       SEC_ACCESS mask;
+
+       SEC_ACL *psa = NULL;
+
+       sid_copy(&adm_sid, &global_sid_Builtin);
+       sid_append_rid(&adm_sid, BUILTIN_ALIAS_RID_ADMINS);
+
+       sid_copy(&act_sid, &global_sid_Builtin);
+       sid_append_rid(&act_sid, BUILTIN_ALIAS_RID_ACCOUNT_OPS);
+
+       /*basic access for every one*/
+       init_sec_access(&mask, SAMR_EXECUTE | SAMR_READ);
+       init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
+
+       /*full access for builtin aliases Administrators and Account Operators*/
+       init_sec_access(&mask, SAMR_ALL_ACCESS);
+       init_sec_ace(&ace[1], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
+       init_sec_ace(&ace[2], &act_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
+
+       if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 3, ace)) == NULL)
+               return NT_STATUS_NO_MEMORY;
+
+       if ((*psd = make_sec_desc(ctx, SEC_DESC_REVISION, NULL, NULL, NULL, psa, sd_size)) == NULL)
+               return NT_STATUS_NO_MEMORY;
+
+       return NT_STATUS_OK;
+}
index ad09f9123460d937250cf0f53c86d703768a4b25..e9635fc7f84b20dfb5af4a2563e34701cf912312 100644 (file)
@@ -30,13 +30,11 @@ extern fstring global_myworkgroup;
  * Some useful sids
  */
 
-DOM_SID global_sid_Builtin;                            /* Local well-known domain */
 DOM_SID global_sid_World_Domain;               /* Everyone domain */
 DOM_SID global_sid_World;                              /* Everyone */
 DOM_SID global_sid_Creator_Owner_Domain;    /* Creator Owner domain */
 DOM_SID global_sid_NT_Authority;               /* NT Authority */
 DOM_SID global_sid_NULL;                       /* NULL sid */
-DOM_SID global_sid_Builtin_Guests;                     /* Builtin guest users */
 DOM_SID global_sid_Authenticated_Users;                /* All authenticated rids */
 DOM_SID global_sid_Network;                                    /* Network rids */
 
@@ -44,6 +42,11 @@ static DOM_SID global_sid_Creator_Owner;             /* Creator Owner */
 static DOM_SID global_sid_Creator_Group;              /* Creator Group */
 static DOM_SID global_sid_Anonymous;                           /* Anonymous login */
 
+DOM_SID global_sid_Builtin;                            /* Local well-known domain */
+DOM_SID global_sid_Builtin_Administrators;
+DOM_SID global_sid_Builtin_Users;
+DOM_SID global_sid_Builtin_Guests;                     /* Builtin guest users */
+
 /*
  * An NT compatible anonymous token.
  */
@@ -99,6 +102,8 @@ const char *sid_type_lookup(uint32 sid_type)
 void generate_wellknown_sids(void)
 {
        string_to_sid(&global_sid_Builtin, "S-1-5-32");
+       string_to_sid(&global_sid_Builtin_Administrators, "S-1-5-32-544");
+       string_to_sid(&global_sid_Builtin_Users, "S-1-5-32-545");
        string_to_sid(&global_sid_Builtin_Guests, "S-1-5-32-546");
        string_to_sid(&global_sid_World_Domain, "S-1-1");
        string_to_sid(&global_sid_World, "S-1-1-0");
@@ -525,3 +530,18 @@ char *sid_binstring(DOM_SID *sid)
        return s;
 }
 
+
+/*
+  print a GUID structure for debugging
+*/
+void print_guid(GUID *guid)
+{
+       int i;
+
+       d_printf("%08x-%04x-%04x", 
+                IVAL(guid->info, 0), SVAL(guid->info, 4), SVAL(guid->info, 6));
+       d_printf("-%02x%02x-", guid->info[8], guid->info[9]);
+       for (i=10;i<GUID_SIZE;i++)
+               d_printf("%02x", guid->info[i]);
+       d_printf("\n");
+}
index 5e2b7c5ed97f1c2bfba6785502b174dc1864ee44..fc2abf976f45512b299c5a7152e000e3127ff9de 100644 (file)
@@ -871,7 +871,7 @@ static BOOL matchname(char *remotehost,struct in_addr  addr)
        
        /* Look up the host address in the address list we just got. */
        for (i = 0; hp->h_addr_list[i]; i++) {
-               if (memcmp(hp->h_addr_list[i], (caddr_t) & addr, sizeof(addr)) == 0)
+               if (memcmp(hp->h_addr_list[i], (char *) & addr, sizeof(addr)) == 0)
                        return True;
        }
        
@@ -976,6 +976,7 @@ int create_pipe_sock(const char *socket_dir,
                     const char *socket_name,
                     mode_t dir_perms)
 {
+#ifdef HAVE_UNIXSOCKET
         struct sockaddr_un sunaddr;
         struct stat st;
         int sock;
@@ -1064,6 +1065,10 @@ int create_pipe_sock(const char *socket_dir,
         /* Success! */
         
         return sock;
+#else
+        DEBUG(0, ("create_pipe_sock: No Unix sockets on this system\n"));
+        return -1;
+#endif /* HAVE_UNIXSOCKET */
 }
 
 /*******************************************************************
index ba02819bdc6553264562a648cbb159c56a4b0d81..eb47252413133928590182abdbaaceb22daa25e9 100644 (file)
@@ -218,6 +218,16 @@ void unistr2_to_ascii(char *dest, const UNISTR2 *str, size_t maxlen)
        pull_ucs2(NULL, dest, str->buffer, maxlen, str->uni_str_len*2, STR_NOALIGN);
 }
 
+/*******************************************************************
+give a static string for displaying a UNISTR2
+********************************************************************/
+const char *unistr2_static(const UNISTR2 *str)
+{
+       static pstring ret;
+       unistr2_to_ascii(ret, str, sizeof(ret));
+       return ret;
+}
+
 
 /*******************************************************************
  duplicate a UNISTR2 string into a null terminated char*
index b5710f3a39e15e648f349c21f379d11eaa87489b..7621712e9ad31192f93d97917b7ec61b82de306b 100644 (file)
@@ -43,6 +43,7 @@ XFILE *x_stderr = &_x_stderr;
 
 #define X_FLAG_EOF 1
 #define X_FLAG_ERROR 2
+#define X_FLAG_EINVAL 3
 
 /* simulate setvbuf() */
 int x_setvbuf(XFILE *f, char *buf, int mode, size_t size)
@@ -341,3 +342,36 @@ char *x_fgets(char *s, int size, XFILE *stream)
        *s = 0;
        return s0;
 }
+
+/* trivial seek, works only for SEEK_SET and SEEK_END if SEEK_CUR is
+ * set then an error is returned */
+off_t x_tseek(XFILE *f, off_t offset, int whence)
+{
+       if (f->flags & X_FLAG_ERROR)
+               return -1;
+
+       /* only SEEK_SET and SEEK_END are supported */
+       /* SEEK_CUR needs internal offset counter */
+       if (whence != SEEK_SET && whence != SEEK_END) {
+               f->flags |= X_FLAG_EINVAL;
+               errno = EINVAL;
+               return -1;
+       }
+
+       /* empty the buffer */
+       switch (f->open_flags & O_ACCMODE) {
+       case O_RDONLY:
+               f->bufused = 0;
+               break;
+       case O_WRONLY:
+               if (x_fflush(f) != 0)
+                       return -1;
+               break;
+       default:
+               errno = EINVAL;
+               return -1;
+       }
+
+       f->flags &= ~X_FLAG_EOF;
+       return (off_t)sys_lseek(f->fd, offset, whence);
+}
index 2d1830435fef4202b5993ab002c656f39d155844..d85f9c9b58a557e58eaa2281a0b54b0b93da8cde 100644 (file)
@@ -30,19 +30,49 @@ ADS_STATUS ads_build_error(enum ads_error_type etype,
                           int rc, int minor_status)
 {
        ADS_STATUS ret;
-       ret.error_type = etype;
-       ret.rc = rc;
+
+       if (etype == ADS_ERROR_NT) {
+               DEBUG(0,("don't use ads_build_error with ADS_ERROR_NT!\n"));
+               ret.err.rc = -1;
+               ret.error_type = ADS_ERROR_SYSTEM;
+               ret.minor_status = 0;
+               return ret;     
+       }       
+               
+       ret.err.rc = rc;
+       ret.error_type = etype;         
        ret.minor_status = minor_status;
        return ret;
 }
 
+ADS_STATUS ads_build_nt_error(enum ads_error_type etype, 
+                          NTSTATUS nt_status)
+{
+       ADS_STATUS ret;
+
+       if (etype != ADS_ERROR_NT) {
+               DEBUG(0,("don't use ads_build_nt_error without ADS_ERROR_NT!\n"));
+               ret.err.rc = -1;
+               ret.error_type = ADS_ERROR_SYSTEM;
+               ret.minor_status = 0;
+               return ret;     
+       }
+       ret.err.nt_status = nt_status;
+       ret.error_type = etype;         
+       ret.minor_status = 0;
+       return ret;
+}
+
 /*
   do a rough conversion between ads error codes and NT status codes
   we'll need to fill this in more
 */
-NTSTATUS ads_ntstatus(ADS_STATUS rc)
+NTSTATUS ads_ntstatus(ADS_STATUS status)
 {
-       if (ADS_ERR_OK(rc)) return NT_STATUS_OK;
+       if (status.error_type == ADS_ERROR_NT){
+               return status.err.nt_status;    
+       }
+       if (ADS_ERR_OK(status)) return NT_STATUS_OK;
        return NT_STATUS_UNSUCCESSFUL;
 }
 
@@ -59,14 +89,14 @@ const char *ads_errstr(ADS_STATUS status)
 
        switch (status.error_type) {
        case ADS_ERROR_SYSTEM:
-               return strerror(status.rc);
+               return strerror(status.err.rc);
 #ifdef HAVE_LDAP
        case ADS_ERROR_LDAP:
-               return ldap_err2string(status.rc);
+               return ldap_err2string(status.err.rc);
 #endif
 #ifdef HAVE_KRB5
        case ADS_ERROR_KRB5: 
-               return error_message(status.rc);
+               return error_message(status.err.rc);
 #endif
 #ifdef HAVE_GSSAPI
        case ADS_ERROR_GSS:
@@ -76,7 +106,7 @@ const char *ads_errstr(ADS_STATUS status)
                gss_buffer_desc msg1, msg2;
                msg1.value = NULL;
                msg2.value = NULL;
-               gss_display_status(&minor, status.rc, GSS_C_GSS_CODE,
+               gss_display_status(&minor, status.err.rc, GSS_C_GSS_CODE,
                                   GSS_C_NULL_OID, &msg_ctx, &msg1);
                gss_display_status(&minor, status.minor_status, GSS_C_MECH_CODE,
                                   GSS_C_NULL_OID, &msg_ctx, &msg2);
@@ -86,6 +116,8 @@ const char *ads_errstr(ADS_STATUS status)
                return ret;
        }
 #endif
+       case ADS_ERROR_NT: 
+               return nt_errstr(ads_ntstatus(status));
        default:
                return "Unknown ADS error type!? (not compiled in?)";
        }
index 9a486237c9fe9a65c198bd924f96aab0b8163a50..a80837cf4df478a45247888171e3ad7606acbd06 100644 (file)
@@ -50,7 +50,7 @@ kerb_prompter(krb5_context ctx, void *data,
   simulate a kinit, putting the tgt in the default cache location
   remus@snapserver.com
 */
-int kerberos_kinit_password(const char *principal, const char *password)
+int kerberos_kinit_password(const char *principal, const char *password, int time_offset)
 {
        krb5_context ctx;
        krb5_error_code code = 0;
@@ -60,6 +60,10 @@ int kerberos_kinit_password(const char *principal, const char *password)
 
        if ((code = krb5_init_context(&ctx)))
                return code;
+
+       if (time_offset != 0) {
+               krb5_set_real_time(ctx, time(NULL) + time_offset, 0);
+       }
        
        if ((code = krb5_cc_default(ctx, &cc))) {
                krb5_free_context(ctx);
@@ -111,7 +115,7 @@ int ads_kinit_password(ADS_STRUCT *ads)
        int ret;
 
        asprintf(&s, "%s@%s", ads->auth.user_name, ads->auth.realm);
-       ret = kerberos_kinit_password(s, ads->auth.password);
+       ret = kerberos_kinit_password(s, ads->auth.password, ads->auth.time_offset);
 
        if (ret) {
                DEBUG(0,("kerberos_kinit_password %s failed: %s\n", 
index ec79a8658fe721e6accbf05ad64534738ea0a0b3..a49b6cbe3b0ee8a01ed6ec30286544d0e175921c 100644 (file)
@@ -248,7 +248,8 @@ static krb5_error_code parse_setpw_reply(krb5_context context,
        return 0;
 }
 
-ADS_STATUS krb5_set_password(const char *kdc_host, const char *princ, const char *newpw)
+ADS_STATUS krb5_set_password(const char *kdc_host, const char *princ, const char *newpw, 
+                            int time_offset)
 {
        krb5_context context;
        krb5_auth_context auth_context = NULL;
@@ -268,6 +269,10 @@ ADS_STATUS krb5_set_password(const char *kdc_host, const char *princ, const char
                return ADS_ERROR_KRB5(ret);
        }
        
+       if (time_offset != 0) {
+               krb5_set_real_time(context, time(NULL) + time_offset, 0);
+       }
+
        ret = krb5_cc_default(context, &ccache);
        if (ret) {
                krb5_free_context(context);
@@ -452,16 +457,17 @@ ADS_STATUS krb5_set_password(const char *kdc_host, const char *princ, const char
 
 ADS_STATUS kerberos_set_password(const char *kpasswd_server, 
                                 const char *auth_principal, const char *auth_password,
-                                const char *target_principal, const char *new_password)
+                                const char *target_principal, const char *new_password,
+                                int time_offset)
 {
     int ret;
 
-    if ((ret = kerberos_kinit_password(auth_principal, auth_password))) {
+    if ((ret = kerberos_kinit_password(auth_principal, auth_password, time_offset))) {
        DEBUG(1,("Failed kinit for principal %s (%s)\n", auth_principal, error_message(ret)));
        return ADS_ERROR_KRB5(ret);
     }
 
-    return krb5_set_password(kpasswd_server, target_principal, new_password);
+    return krb5_set_password(kpasswd_server, target_principal, new_password, time_offset);
 }
 
 
index 26724894829c2ffa2087f399904f081b0846fa40..7a0afb1a8167d29d6920b6f70f60495facdfd76f 100644 (file)
@@ -63,6 +63,7 @@ static BOOL ads_try_connect(ADS_STRUCT *ads, const char *server, unsigned port)
        ads->ldap_port = port;
        ads->ldap_ip = *interpret_addr2(srv);
        free(srv);
+
        return True;
 }
 
@@ -204,7 +205,6 @@ static BOOL ads_try_netbios(ADS_STRUCT *ads)
 ADS_STATUS ads_connect(ADS_STRUCT *ads)
 {
        int version = LDAP_VERSION3;
-       int code;
        ADS_STATUS status;
 
        ads->last_attempt = time(NULL);
@@ -226,7 +226,7 @@ ADS_STATUS ads_connect(ADS_STRUCT *ads)
        /* try via DNS */
        if (ads_try_dns(ads)) {
                goto got_connection;
-               }
+       }
 
        /* try via netbios lookups */
        if (!lp_disable_netbios() && ads_try_netbios(ads)) {
@@ -274,12 +274,7 @@ got_connection:
        }
 #endif
 
-       if (ads->auth.password) {
-               if ((code = ads_kinit_password(ads)))
-                       return ADS_ERROR_KRB5(code);
-       }
-
-       if (ads->auth.no_bind) {
+       if (ads->auth.flags & ADS_AUTH_NO_BIND) {
                return ADS_SUCCESS;
        }
 
@@ -613,14 +608,17 @@ ADS_STATUS ads_do_search(ADS_STRUCT *ads, const char *bind_path, int scope,
        char *utf8_exp, *utf8_path, **search_attrs = NULL;
        TALLOC_CTX *ctx;
 
-       if (!(ctx = talloc_init()))
+       if (!(ctx = talloc_init())) {
+               DEBUG(1,("ads_do_search: talloc_init() failed!"));
                return ADS_ERROR(LDAP_NO_MEMORY);
+       }
 
        /* 0 means the conversion worked but the result was empty 
           so we only fail if it's negative.  In any case, it always 
           at least nulls out the dest */
        if ((push_utf8_talloc(ctx, &utf8_exp, exp) < 0) ||
            (push_utf8_talloc(ctx, &utf8_path, bind_path) < 0)) {
+               DEBUG(1,("ads_do_search: push_utf8_talloc() failed!"));
                rc = LDAP_NO_MEMORY;
                goto done;
        }
@@ -632,6 +630,7 @@ ADS_STATUS ads_do_search(ADS_STRUCT *ads, const char *bind_path, int scope,
                /* if (!(search_attrs = ads_push_strvals(ctx, attrs)))  */
                if (!(str_list_copy(&search_attrs, attrs)))
                {
+                       DEBUG(1,("ads_do_search: str_list_copy() failed!"));
                        rc = LDAP_NO_MEMORY;
                        goto done;
                }
@@ -826,7 +825,11 @@ static ADS_STATUS ads_modlist_add(TALLOC_CTX *ctx, ADS_MODLIST *mods,
 ADS_STATUS ads_mod_str(TALLOC_CTX *ctx, ADS_MODLIST *mods, 
                       const char *name, const char *val)
 {
-       const char *values[2] = {val, NULL};
+       const char *values[2];
+
+       values[0] = val;
+       values[1] = NULL;
+
        if (!val)
                return ads_modlist_add(ctx, mods, LDAP_MOD_DELETE, name, NULL);
        return ads_modlist_add(ctx, mods, LDAP_MOD_REPLACE, name, 
@@ -861,7 +864,10 @@ ADS_STATUS ads_mod_strlist(TALLOC_CTX *ctx, ADS_MODLIST *mods,
 static ADS_STATUS ads_mod_ber(TALLOC_CTX *ctx, ADS_MODLIST *mods, 
                              const char *name, const struct berval *val)
 {
-       const struct berval *values[2] = {val, NULL};
+       const struct berval *values[2];
+
+       values[0] = val;
+       values[1] = NULL;
        if (!val)
                return ads_modlist_add(ctx, mods, LDAP_MOD_DELETE, name, NULL);
        return ads_modlist_add(ctx, mods, LDAP_MOD_REPLACE|LDAP_MOD_BVALUES,
@@ -884,7 +890,7 @@ ADS_STATUS ads_gen_mod(ADS_STRUCT *ads, const char *mod_dn, ADS_MODLIST mods)
           non-existent attribute (but allowable for the object) to run
        */
        LDAPControl PermitModify = {
-               "1.2.840.113556.1.4.1413",
+               ADS_PERMIT_MODIFY_OID,
                {0, NULL},
                (char) 1};
        LDAPControl *controls[2];
@@ -1410,7 +1416,7 @@ ADS_STATUS ads_set_machine_password(ADS_STRUCT *ads,
         */
        asprintf(&principal, "%s$@%s", host, ads->auth.realm);
        
-       status = krb5_set_password(ads->auth.kdc_server, principal, password);
+       status = krb5_set_password(ads->auth.kdc_server, principal, password, ads->auth.time_offset);
        
        free(host);
        free(principal);
@@ -1616,6 +1622,26 @@ ADS_STATUS ads_USN(ADS_STRUCT *ads, uint32 *usn)
        return ADS_SUCCESS;
 }
 
+/* parse a ADS timestring - typical string is
+   '20020917091222.0Z0' which means 09:12.22 17th September
+   2002, timezone 0 */
+static time_t ads_parse_time(const char *str)
+{
+       struct tm tm;
+
+       ZERO_STRUCT(tm);
+
+       if (sscanf(str, "%4d%2d%2d%2d%2d%2d", 
+                  &tm.tm_year, &tm.tm_mon, &tm.tm_mday, 
+                  &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
+               return 0;
+       }
+       tm.tm_year -= 1900;
+       tm.tm_mon -= 1;
+
+       return timegm(&tm);
+}
+
 
 /**
  * Find the servers name and realm - this can be done before authentication 
@@ -1626,22 +1652,37 @@ ADS_STATUS ads_USN(ADS_STRUCT *ads, uint32 *usn)
  **/
 ADS_STATUS ads_server_info(ADS_STRUCT *ads)
 {
-       const char *attrs[] = {"ldapServiceName", NULL};
+       const char *attrs[] = {"ldapServiceName", "currentTime", NULL};
        ADS_STATUS status;
        void *res;
-       char **values;
+       char *value;
        char *p;
+       char *timestr;
+       TALLOC_CTX *ctx;
+
+       if (!(ctx = talloc_init())) {
+               return ADS_ERROR(LDAP_NO_MEMORY);
+       }
 
        status = ads_do_search(ads, "", LDAP_SCOPE_BASE, "(objectclass=*)", attrs, &res);
        if (!ADS_ERR_OK(status)) return status;
 
-       values = ldap_get_values(ads->ld, res, "ldapServiceName");
-       if (!values || !values[0]) return ADS_ERROR(LDAP_NO_RESULTS_RETURNED);
+       value = ads_pull_string(ads, ctx, res, "ldapServiceName");
+       if (!value) {
+               return ADS_ERROR(LDAP_NO_RESULTS_RETURNED);
+       }
+
+       timestr = ads_pull_string(ads, ctx, res, "currentTime");
+       if (!timestr) {
+               return ADS_ERROR(LDAP_NO_RESULTS_RETURNED);
+       }
+
+       ldap_msgfree(res);
 
-       p = strchr(values[0], ':');
+       p = strchr(value, ':');
        if (!p) {
-               ldap_value_free(values);
-               ldap_msgfree(res);
+               talloc_destroy(ctx);
+               DEBUG(1, ("ads_server_info: returned ldap server name did not contain a ':' so was deemed invalid\n"));
                return ADS_ERROR(LDAP_DECODING_ERROR);
        }
 
@@ -1650,9 +1691,9 @@ ADS_STATUS ads_server_info(ADS_STRUCT *ads)
        ads->config.ldap_server_name = strdup(p+1);
        p = strchr(ads->config.ldap_server_name, '$');
        if (!p || p[1] != '@') {
-               ldap_value_free(values);
-               ldap_msgfree(res);
+               talloc_destroy(ctx);
                SAFE_FREE(ads->config.ldap_server_name);
+               DEBUG(1, ("ads_server_info: returned ldap server name did not contain '$@' so was deemed invalid\n"));
                return ADS_ERROR(LDAP_DECODING_ERROR);
        }
 
@@ -1667,6 +1708,15 @@ ADS_STATUS ads_server_info(ADS_STRUCT *ads)
        DEBUG(3,("got ldap server name %s@%s\n", 
                 ads->config.ldap_server_name, ads->config.realm));
 
+       ads->config.current_time = ads_parse_time(timestr);
+
+       if (ads->config.current_time != 0) {
+               ads->auth.time_offset = ads->config.current_time - time(NULL);
+               DEBUG(4,("time offset is %d seconds\n", ads->auth.time_offset));
+       }
+
+       talloc_destroy(ctx);
+
        return ADS_SUCCESS;
 }
 
index 64ae8252c818c65b384d77f564704d92a43db712..66984477b815fce4bf56c0cd4d218f38b3cfc1dd 100644 (file)
@@ -28,7 +28,7 @@
     results can be used.  It should be freed using ads_msgfree.
 */
 ADS_STATUS ads_find_printer_on_server(ADS_STRUCT *ads, void **res,
-                                     char *printer, char *servername)
+                                     const char *printer, char *servername)
 {
        ADS_STATUS status;
        char *srv_dn, **srv_cn, *exp;
index 81dedb0a81e7c257c2fd27bef5fcad5157c6c634..f7dd01084a2f9c1fc70ec685522200ac39dd97dd 100644 (file)
 
 #ifdef HAVE_ADS
 
-#if USE_CYRUS_SASL
-/*
-  this is a minimal interact function, just enough for SASL to talk
-  GSSAPI/kerberos to W2K
-  Error handling is a bit of a problem. I can't see how to get Cyrus-sasl
-  to give sensible errors
+/* 
+   perform a LDAP/SASL/SPNEGO/NTLMSSP bind (just how many layers can
+   we fit on one socket??)
 */
-static int sasl_interact(LDAP *ld,unsigned flags,void *defaults,void *in)
+static ADS_STATUS ads_sasl_spnego_ntlmssp_bind(ADS_STRUCT *ads)
 {
-       sasl_interact_t *interact = in;
+       const char *mechs[] = {OID_NTLMSSP, NULL};
+       DATA_BLOB msg1;
+       DATA_BLOB blob, chal1, chal2, auth;
+       uint8 challenge[8];
+       uint8 nthash[24], lmhash[24], sess_key[16];
+       uint32 neg_flags;
+       struct berval cred, *scred;
+       ADS_STATUS status;
+       extern pstring global_myname;
+       int rc;
 
-       while (interact->id != SASL_CB_LIST_END) {
-               interact->result = strdup("");
-               interact->len = strlen(interact->result);
-               interact++;
+       if (!ads->auth.password) {
+               /* No password, don't segfault below... */
+               return ADS_ERROR_NT(NT_STATUS_LOGON_FAILURE);
        }
-       
-       return LDAP_SUCCESS;
+
+       neg_flags = NTLMSSP_NEGOTIATE_UNICODE | 
+               NTLMSSP_NEGOTIATE_128 | 
+               NTLMSSP_NEGOTIATE_NTLM;
+
+       memset(sess_key, 0, 16);
+
+       /* generate the ntlmssp negotiate packet */
+       msrpc_gen(&blob, "CddB",
+                 "NTLMSSP",
+                 NTLMSSP_NEGOTIATE,
+                 neg_flags,
+                 sess_key, 16);
+
+       /* and wrap it in a SPNEGO wrapper */
+       msg1 = gen_negTokenTarg(mechs, blob);
+       data_blob_free(&blob);
+
+       cred.bv_val = msg1.data;
+       cred.bv_len = msg1.length;
+
+       rc = ldap_sasl_bind_s(ads->ld, NULL, "GSS-SPNEGO", &cred, NULL, NULL, &scred);
+       if (rc != LDAP_SASL_BIND_IN_PROGRESS) {
+               status = ADS_ERROR(rc);
+               goto failed;
+       }
+
+       blob = data_blob(scred->bv_val, scred->bv_len);
+
+       /* the server gives us back two challenges */
+       if (!spnego_parse_challenge(blob, &chal1, &chal2)) {
+               DEBUG(3,("Failed to parse challenges\n"));
+               status = ADS_ERROR(LDAP_OPERATIONS_ERROR);
+               goto failed;
+       }
+
+       data_blob_free(&blob);
+
+       /* encrypt the password with the challenge */
+       memcpy(challenge, chal1.data + 24, 8);
+       SMBencrypt(ads->auth.password, challenge,lmhash);
+       SMBNTencrypt(ads->auth.password, challenge,nthash);
+
+       data_blob_free(&chal1);
+       data_blob_free(&chal2);
+
+       /* this generates the actual auth packet */
+       msrpc_gen(&blob, "CdBBUUUBd", 
+                 "NTLMSSP", 
+                 NTLMSSP_AUTH, 
+                 lmhash, 24,
+                 nthash, 24,
+                 lp_workgroup(), 
+                 ads->auth.user_name, 
+                 global_myname,
+                 sess_key, 16,
+                 neg_flags);
+
+       /* wrap it in SPNEGO */
+       auth = spnego_gen_auth(blob);
+
+       data_blob_free(&blob);
+
+       /* now send the auth packet and we should be done */
+       cred.bv_val = auth.data;
+       cred.bv_len = auth.length;
+
+       rc = ldap_sasl_bind_s(ads->ld, NULL, "GSS-SPNEGO", &cred, NULL, NULL, &scred);
+
+       return ADS_ERROR(rc);
+
+failed:
+       return status;
 }
+
+/* 
+   perform a LDAP/SASL/SPNEGO/KRB5 bind
+*/
+static ADS_STATUS ads_sasl_spnego_krb5_bind(ADS_STRUCT *ads, const char *principal)
+{
+       DATA_BLOB blob;
+       struct berval cred, *scred;
+       int rc;
+
+       blob = spnego_gen_negTokenTarg(principal, ads->auth.time_offset);
+
+       if (!blob.data) {
+               return ADS_ERROR(LDAP_OPERATIONS_ERROR);
+       }
+
+       /* now send the auth packet and we should be done */
+       cred.bv_val = blob.data;
+       cred.bv_len = blob.length;
+
+       rc = ldap_sasl_bind_s(ads->ld, NULL, "GSS-SPNEGO", &cred, NULL, NULL, &scred);
+
+       data_blob_free(&blob);
+
+       return ADS_ERROR(rc);
+}
+
+/* 
+   this performs a SASL/SPNEGO bind
+*/
+static ADS_STATUS ads_sasl_spnego_bind(ADS_STRUCT *ads)
+{
+       struct berval *scred=NULL;
+       int rc, i;
+       ADS_STATUS status;
+       DATA_BLOB blob;
+       char *principal;
+       char *OIDs[ASN1_MAX_OIDS];
+       BOOL got_kerberos_mechanism = False;
+
+       rc = ldap_sasl_bind_s(ads->ld, NULL, "GSS-SPNEGO", NULL, NULL, NULL, &scred);
+
+       if (rc != LDAP_SASL_BIND_IN_PROGRESS) {
+               status = ADS_ERROR(rc);
+               goto failed;
+       }
+
+       blob = data_blob(scred->bv_val, scred->bv_len);
+
+#if 0
+       file_save("sasl_spnego.dat", blob.data, blob.length);
 #endif
 
+       /* the server sent us the first part of the SPNEGO exchange in the negprot 
+          reply */
+       if (!spnego_parse_negTokenInit(blob, OIDs, &principal)) {
+               data_blob_free(&blob);
+               status = ADS_ERROR(LDAP_OPERATIONS_ERROR);
+               goto failed;
+       }
+       data_blob_free(&blob);
+
+       /* make sure the server understands kerberos */
+       for (i=0;OIDs[i];i++) {
+               DEBUG(3,("got OID=%s\n", OIDs[i]));
+               if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
+                   strcmp(OIDs[i], OID_KERBEROS5) == 0) {
+                       got_kerberos_mechanism = True;
+               }
+               free(OIDs[i]);
+       }
+       DEBUG(3,("got principal=%s\n", principal));
 
+       if (!(ads->auth.flags & ADS_AUTH_DISABLE_KERBEROS) &&
+           got_kerberos_mechanism && ads_kinit_password(ads) == 0) {
+               return ads_sasl_spnego_krb5_bind(ads, principal);
+       }
+
+       /* lets do NTLMSSP ... this has the big advantage that we don't need
+          to sync clocks, and we don't rely on special versions of the krb5 
+          library for HMAC_MD4 encryption */
+       return ads_sasl_spnego_ntlmssp_bind(ads);
+
+failed:
+       return status;
+}
+
+#ifdef HAVE_GSSAPI
 #define MAX_GSS_PASSES 3
 
 /* this performs a SASL/gssapi bind
    we avoid using cyrus-sasl to make Samba more robust. cyrus-sasl
    is very dependent on correctly configured DNS whereas
    this routine is much less fragile
-   see RFC2078 for details
+   see RFC2078 and RFC2222 for details
 */
-ADS_STATUS ads_sasl_gssapi_bind(ADS_STRUCT *ads)
+static ADS_STATUS ads_sasl_gssapi_bind(ADS_STRUCT *ads)
 {
        int minor_status;
        gss_name_t serv_name;
@@ -68,6 +229,7 @@ ADS_STATUS ads_sasl_gssapi_bind(ADS_STRUCT *ads)
        uint8 *p;
        uint32 max_msg_size;
        char *sname;
+       unsigned sec_layer;
        ADS_STATUS status;
        krb5_principal principal;
        krb5_context ctx;
@@ -159,22 +321,25 @@ ADS_STATUS ads_sasl_gssapi_bind(ADS_STRUCT *ads)
 
        p = (uint8 *)output_token.value;
 
+       file_save("sasl_gssapi.dat", output_token.value, output_token.length);
+
        max_msg_size = (p[1]<<16) | (p[2]<<8) | p[3];
+       sec_layer = *p;
 
        gss_release_buffer(&minor_status, &output_token);
 
        output_token.value = malloc(strlen(ads->config.bind_path) + 8);
        p = output_token.value;
 
-       *p++ = 1; /* no sign or seal */
+       *p++ = 1; /* no sign & seal selection */
        /* choose the same size as the server gave us */
        *p++ = max_msg_size>>16;
        *p++ = max_msg_size>>8;
        *p++ = max_msg_size;
        snprintf(p, strlen(ads->config.bind_path)+4, "dn:%s", ads->config.bind_path);
-       p += strlen(ads->config.bind_path);
+       p += strlen(p);
 
-       output_token.length = strlen(ads->config.bind_path) + 8;
+       output_token.length = PTR_DIFF(p, output_token.value);
 
        gss_rc = gss_wrap(&minor_status, context_handle,0,GSS_C_QOP_DEFAULT,
                          &output_token, &conf_state,
@@ -198,18 +363,51 @@ ADS_STATUS ads_sasl_gssapi_bind(ADS_STRUCT *ads)
 failed:
        return status;
 }
+#endif
+
+/* mapping between SASL mechanisms and functions */
+static struct {
+       const char *name;
+       ADS_STATUS (*fn)(ADS_STRUCT *);
+} sasl_mechanisms[] = {
+       {"GSS-SPNEGO", ads_sasl_spnego_bind},
+#ifdef HAVE_GSSAPI
+       {"GSSAPI", ads_sasl_gssapi_bind}, /* doesn't work with .NET RC1. No idea why */
+#endif
+       {NULL, NULL}
+};
 
 ADS_STATUS ads_sasl_bind(ADS_STRUCT *ads)
 {
-#if USE_CYRUS_SASL
-       int rc;
-       rc = ldap_sasl_interactive_bind_s(ads->ld, NULL, NULL, NULL, NULL, 
-                                         LDAP_SASL_QUIET,
-                                         sasl_interact, NULL);
-       return ADS_ERROR(rc);
-#else
-       return ads_sasl_gssapi_bind(ads);
-#endif
+       const char *attrs[] = {"supportedSASLMechanisms", NULL};
+       char **values;
+       ADS_STATUS status;
+       int i, j;
+       void *res;
+
+       /* get a list of supported SASL mechanisms */
+       status = ads_do_search(ads, "", LDAP_SCOPE_BASE, "(objectclass=*)", attrs, &res);
+       if (!ADS_ERR_OK(status)) return status;
+
+       values = ldap_get_values(ads->ld, res, "supportedSASLMechanisms");
+
+       /* try our supported mechanisms in order */
+       for (i=0;sasl_mechanisms[i].name;i++) {
+               /* see if the server supports it */
+               for (j=0;values && values[j];j++) {
+                       if (strcmp(values[j], sasl_mechanisms[i].name) == 0) {
+                               DEBUG(4,("Found SASL mechanism %s\n", values[j]));
+                               status = sasl_mechanisms[i].fn(ads);
+                               ldap_value_free(values);
+                               ldap_msgfree(res);
+                               return status;
+                       }
+               }
+       }
+
+       ldap_value_free(values);
+       ldap_msgfree(res);
+       return ADS_ERROR(LDAP_AUTH_METHOD_NOT_SUPPORTED);
 }
 
 #endif
index b10b130a313bea604c90aca6cabea30d4b69f83f..021f2d93e4aad7039beb1d7524513e8645d19f47 100644 (file)
@@ -40,7 +40,7 @@ ADS_STATUS ads_change_trust_account_password(ADS_STRUCT *ads, char *host_princip
     asprintf(&service_principal, "HOST/%s", host_principal);
     
     ret = kerberos_set_password(ads->auth.kdc_server, host_principal, password, 
-                               service_principal, new_password);
+                               service_principal, new_password, ads->auth.time_offset);
 
     if (!secrets_store_machine_password(new_password)) {
            DEBUG(1,("Failed to save machine password\n"));
index b4ad3ad0b8998467121a6bca669ae196acd8ade4..b7cfca41fbf19facfeadde3688cf38a493d09e21 100644 (file)
@@ -174,6 +174,16 @@ BOOL asn1_write_BOOLEAN(ASN1_DATA *data, BOOL v)
        return !data->has_error;
 }
 
+/* write a BOOLEAN - hmm, I suspect this one is the correct one, and the 
+   above boolean is bogus. Need to check */
+BOOL asn1_write_BOOLEAN2(ASN1_DATA *data, BOOL v)
+{
+       asn1_push_tag(data, ASN1_BOOLEAN);
+       asn1_write_uint8(data, v);
+       asn1_pop_tag(data);
+       return !data->has_error;
+}
+
 /* check a BOOLEAN */
 BOOL asn1_check_BOOLEAN(ASN1_DATA *data, BOOL v)
 {
@@ -244,15 +254,12 @@ BOOL asn1_start_tag(ASN1_DATA *data, uint8 tag)
        asn1_read_uint8(data, &b);
        if (b & 0x80) {
                int n = b & 0x7f;
-               if (n > 2) {
-                       data->has_error = True;
-                       return False;
-               }
                asn1_read_uint8(data, &b);
                nesting->taglen = b;
-               if (n == 2) {
+               while (n > 1) {
                        asn1_read_uint8(data, &b);
                        nesting->taglen = (nesting->taglen << 8) | b;
+                       n--;
                }
        } else {
                nesting->taglen = b;
@@ -366,6 +373,7 @@ BOOL asn1_read_GeneralString(ASN1_DATA *data, char **s)
 BOOL asn1_read_OctetString(ASN1_DATA *data, DATA_BLOB *blob)
 {
        int len;
+       ZERO_STRUCTP(blob);
        if (!asn1_start_tag(data, ASN1_OCTET_STRING)) return False;
        len = asn1_tag_remaining(data);
        *blob = data_blob(NULL, len);
@@ -382,7 +390,8 @@ BOOL asn1_read_Integer(ASN1_DATA *data, int *i)
        
        if (!asn1_start_tag(data, ASN1_INTEGER)) return False;
        while (asn1_tag_remaining(data)>0) {
-               *i = (*i << 8) + asn1_read_uint8(data, &b);
+               asn1_read_uint8(data, &b);
+               *i = (*i << 8) + b;
        }
        return asn1_end_tag(data);      
        
index 93cf3d95db71e11b3f1078c2e4514fdfa0bcd3a5..62acccdfb772001e03d3b328eef4c6acc1011dbe 100644 (file)
@@ -50,14 +50,12 @@ static BOOL cli_session_setup_lanman2(struct cli_state *cli, char *user,
        fstring pword;
        char *p;
 
-       if (passlen > sizeof(pword)-1) {
+       if (passlen > sizeof(pword)-1)
                return False;
-       }
 
        /* if in share level security then don't send a password now */
-       if (!(cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL)) {
+       if (!(cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL))
                passlen = 0;
-       }
 
        if (passlen > 0 && (cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) && passlen != 24) {
                /* Encrypted mode needed, and non encrypted password supplied. */
@@ -99,9 +97,8 @@ static BOOL cli_session_setup_lanman2(struct cli_state *cli, char *user,
 
        show_msg(cli->inbuf);
 
-       if (cli_is_error(cli)) {
+       if (cli_is_error(cli))
                return False;
-       }
        
        /* use the returned vuid from now on */
        cli->vuid = SVAL(cli->inbuf,smb_uid);   
@@ -118,17 +115,14 @@ static uint32 cli_session_setup_capabilities(struct cli_state *cli)
 {
        uint32 capabilities = CAP_NT_SMBS;
 
-       if (!cli->force_dos_errors) {
+       if (!cli->force_dos_errors)
                capabilities |= CAP_STATUS32;
-       }
 
-       if (cli->use_level_II_oplocks) {
+       if (cli->use_level_II_oplocks)
                capabilities |= CAP_LEVEL_II_OPLOCKS;
-       }
 
-       if (cli->capabilities & CAP_UNICODE) {
+       if (cli->capabilities & CAP_UNICODE)
                capabilities |= CAP_UNICODE;
-       }
 
        return capabilities;
 }
@@ -167,9 +161,8 @@ static BOOL cli_session_setup_guest(struct cli_state *cli)
        
        show_msg(cli->inbuf);
        
-       if (cli_is_error(cli)) {
+       if (cli_is_error(cli))
                return False;
-       }
 
        cli->vuid = SVAL(cli->inbuf,smb_uid);
 
@@ -223,9 +216,8 @@ static BOOL cli_session_setup_plaintext(struct cli_state *cli, char *user,
        
        show_msg(cli->inbuf);
        
-       if (cli_is_error(cli)) {
+       if (cli_is_error(cli))
                return False;
-       }
 
        cli->vuid = SVAL(cli->inbuf,smb_uid);
        p = smb_buf(cli->inbuf);
@@ -237,15 +229,41 @@ static BOOL cli_session_setup_plaintext(struct cli_state *cli, char *user,
        return True;
 }
 
+static void set_signing_on_cli (struct cli_state *cli, char* pass, uint8 response[24]) 
+{
+       uint8 zero_sig[8];
+       ZERO_STRUCT(zero_sig);
+
+       DEBUG(5, ("Server returned security sig:\n"));
+       dump_data(5, &cli->inbuf[smb_ss_field], 8);
 
-/**
+       if (cli->sign_info.use_smb_signing) {
+               DEBUG(5, ("smb signing already active on connection\n"));
+       } else if (memcmp(&cli->inbuf[smb_ss_field], zero_sig, 8) != 0) {
+
+               DEBUG(3, ("smb signing enabled!\n"));
+               cli->sign_info.use_smb_signing = True;
+               cli_calculate_mac_key(cli, pass, response);
+       } else {
+               DEBUG(5, ("smb signing NOT enabled!\n"));
+       }
+}
+
+static void set_temp_signing_on_cli(struct cli_state *cli) 
+{
+       if (cli->sign_info.negotiated_smb_signing)
+               cli->sign_info.temp_smb_signing = True;
+}
+
+
+/****************************************************************************
    do a NT1 NTLM/LM encrypted session setup
    @param cli client state to create do session setup on
    @param user username
    @param pass *either* cleartext password (passlen !=24) or LM response.
    @param ntpass NT response, implies ntpasslen >=24, implies pass is not clear
    @param workgroup The user's domain.
-*/
+****************************************************************************/
 
 static BOOL cli_session_setup_nt1(struct cli_state *cli, char *user, 
                                  char *pass, int passlen,
@@ -256,11 +274,10 @@ static BOOL cli_session_setup_nt1(struct cli_state *cli, char *user,
        uchar pword[24];
        uchar ntpword[24];
        char *p;
-       BOOL tried_signing = False;
+       BOOL have_plaintext = False;
 
-       if (passlen > sizeof(pword) || ntpasslen > sizeof(ntpword)) {
+       if (passlen > sizeof(pword) || ntpasslen > sizeof(ntpword))
                return False;
-       }
 
        if (passlen != 24) {
                /* non encrypted password supplied. Ignore ntpass. */
@@ -268,19 +285,18 @@ static BOOL cli_session_setup_nt1(struct cli_state *cli, char *user,
                ntpasslen = 24;
                SMBencrypt(pass,cli->secblob.data,pword);
                SMBNTencrypt(pass,cli->secblob.data,ntpword);
-               if (!cli->sign_info.use_smb_signing && cli->sign_info.negotiated_smb_signing) {
-                       cli_calculate_mac_key(cli, pass, ntpword);
-                       tried_signing = True;
-               }
+
+               have_plaintext = True;
+               set_temp_signing_on_cli(cli);
        } else {
-               /* pre-encrypted password supplied.  Only used for security=server, can't do
+               /* pre-encrypted password supplied.  Only used for 
+                  security=server, can't do
                   signing becouse we don't have oringial key */
                memcpy(pword, pass, 24);
-               if (ntpasslen == 24) {
+               if (ntpasslen == 24)
                        memcpy(ntpword, ntpass, 24);
-               } else {
+               else
                        ZERO_STRUCT(ntpword);
-               }
        }
 
        /* send a session setup command */
@@ -301,31 +317,22 @@ static BOOL cli_session_setup_nt1(struct cli_state *cli, char *user,
        p = smb_buf(cli->outbuf);
        memcpy(p,pword,passlen); p += passlen;
        memcpy(p,ntpword,ntpasslen); p += ntpasslen;
-       p += clistr_push(cli, p, user, -1, STR_TERMINATE|STR_UPPER);
-       p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE|STR_UPPER);
+       p += clistr_push(cli, p, user, -1, STR_TERMINATE);
+       p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE);
        p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
        p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
        cli_setup_bcc(cli, p);
 
-       cli_send_smb(cli);
-       if (!cli_receive_smb(cli)) {
-               if (tried_signing) {
-                       /* We only use it if we have a successful non-guest connect */
-                       cli->sign_info.use_smb_signing = False;
-               }
+       if (!cli_send_smb(cli))
                return False;
-       }
 
-       show_msg(cli->inbuf);
+       if (!cli_receive_smb(cli))
+               return False;
 
-       if (tried_signing && (cli_is_error(cli) || SVAL(cli->inbuf,smb_vwv2) /* guest */)) {
-               /* We only use it if we have a successful non-guest connect */
-               cli->sign_info.use_smb_signing = False;
-       }
+       show_msg(cli->inbuf);
 
-       if (cli_is_error(cli)) {
+       if (cli_is_error(cli))
                return False;
-       }
 
        /* use the returned vuid from now on */
        cli->vuid = SVAL(cli->inbuf,smb_uid);
@@ -337,6 +344,11 @@ static BOOL cli_session_setup_nt1(struct cli_state *cli, char *user,
 
        fstrcpy(cli->user_name, user);
 
+       if (have_plaintext) {
+               /* Have plaintext orginal */
+               set_signing_on_cli(cli, pass, ntpword);
+       }
+
        return True;
 }
 
@@ -360,6 +372,9 @@ static DATA_BLOB cli_session_setup_blob(struct cli_state *cli, DATA_BLOB blob)
 
        set_message(cli->outbuf,12,0,True);
        SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
+
+       set_temp_signing_on_cli(cli);
+
        cli_setup_packet(cli);
                        
        SCVAL(cli->outbuf,smb_vwv0,0xFF);
@@ -375,8 +390,8 @@ static DATA_BLOB cli_session_setup_blob(struct cli_state *cli, DATA_BLOB blob)
        p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE);
        p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE);
        cli_setup_bcc(cli, p);
-
        cli_send_smb(cli);
+
        if (!cli_receive_smb(cli))
                return blob2;
 
@@ -404,7 +419,6 @@ static DATA_BLOB cli_session_setup_blob(struct cli_state *cli, DATA_BLOB blob)
        return blob2;
 }
 
-
 #ifdef HAVE_KRB5
 /****************************************************************************
  Do a spnego/kerberos encrypted session setup.
@@ -417,7 +431,7 @@ static BOOL cli_session_setup_kerberos(struct cli_state *cli, char *principal, c
        DEBUG(2,("Doing kerberos session setup\n"));
 
        /* generate the encapsulated kerberos5 ticket */
-       negTokenTarg = spnego_gen_negTokenTarg(cli, principal);
+       negTokenTarg = spnego_gen_negTokenTarg(principal, 0);
 
        if (!negTokenTarg.data) return False;
 
@@ -443,28 +457,32 @@ static BOOL cli_session_setup_kerberos(struct cli_state *cli, char *principal, c
 static BOOL cli_session_setup_ntlmssp(struct cli_state *cli, char *user, 
                                      char *pass, char *workgroup)
 {
-       const char *mechs[] = {OID_NTLMSSP, NULL};
-       DATA_BLOB msg1;
-       DATA_BLOB blob, chal1, chal2, auth;
+       DATA_BLOB msg1, struct_blob;
+       DATA_BLOB blob, chal1, chal2, auth, challenge_blob;
        uint8 challenge[8];
        uint8 nthash[24], lmhash[24], sess_key[16];
-       uint32 neg_flags;
+       uint32 neg_flags, chal_flags, ntlmssp_command, unkn1, unkn2;
+       pstring server_domain;  /* FIX THIS, SHOULD be UCS2-LE */
 
        neg_flags = NTLMSSP_NEGOTIATE_UNICODE | 
-               NTLMSSP_NEGOTIATE_LM_KEY | 
+               NTLMSSP_NEGOTIATE_128 | 
                NTLMSSP_NEGOTIATE_NTLM;
 
        memset(sess_key, 0, 16);
 
+       DEBUG(10, ("sending NTLMSSP_NEGOTIATE\n"));
+
        /* generate the ntlmssp negotiate packet */
-       msrpc_gen(&blob, "CddB",
+       msrpc_gen(&blob, "CddAA",
                  "NTLMSSP",
                  NTLMSSP_NEGOTIATE,
                  neg_flags,
-                 sess_key, 16);
-
+                 workgroup, strlen(workgroup),
+                 cli->calling.name, strlen(cli->calling.name) + 1);
+       DEBUG(10, ("neg_flags: %0X, workgroup: %s, calling name %s\n",
+                 neg_flags, workgroup, cli->calling.name));
        /* and wrap it in a SPNEGO wrapper */
-       msg1 = gen_negTokenTarg(mechs, blob);
+       msg1 = gen_negTokenInit(OID_NTLMSSP, blob);
        data_blob_free(&blob);
 
        /* now send that blob on its way */
@@ -472,9 +490,8 @@ static BOOL cli_session_setup_ntlmssp(struct cli_state *cli, char *user,
 
        data_blob_free(&msg1);
 
-       if (!NT_STATUS_EQUAL(cli_nt_error(cli), NT_STATUS_MORE_PROCESSING_REQUIRED)) {
+       if (!NT_STATUS_EQUAL(cli_nt_error(cli), NT_STATUS_MORE_PROCESSING_REQUIRED))
                return False;
-       }
 
 #if 0
        file_save("chal.dat", blob.data, blob.length);
@@ -488,10 +505,38 @@ static BOOL cli_session_setup_ntlmssp(struct cli_state *cli, char *user,
 
        data_blob_free(&blob);
 
-       /* encrypt the password with the challenge */
-       memcpy(challenge, chal1.data + 24, 8);
+       /*
+        * Ok, chal1 and chal2 are actually two identical copies of
+        * the NTLMSSP Challenge BLOB, and they contain, encoded in them
+        * the challenge to use.
+        */
+
+       if (!msrpc_parse(&chal1, "CdUdbddB",
+                        "NTLMSSP",
+                        &ntlmssp_command, 
+                        &server_domain,
+                        &chal_flags,
+                        &challenge_blob, 8,
+                        &unkn1, &unkn2,
+                        &struct_blob)) {
+         DEBUG(0, ("Failed to parse the NTLMSSP Challenge\n"));
+         return False;
+       }
+                       
+       if (ntlmssp_command != NTLMSSP_CHALLENGE) {
+               DEBUG(0, ("NTLMSSP Response != NTLMSSP_CHALLENGE. Got %0X\n", 
+                       ntlmssp_command));
+               return False;
+       }
+       DEBUG(10, ("Challenge:\n"));
+       dump_data(10, challenge_blob.data, 8);
+
+       /* encrypt the password with the challenge which is in the blob */
+       memcpy(challenge, challenge_blob.data, 8); 
        SMBencrypt(pass, challenge,lmhash);
        SMBNTencrypt(pass, challenge,nthash);
+       data_blob_free(&challenge_blob);
 
 #if 0
        file_save("nthash.dat", nthash, 24);
@@ -511,7 +556,7 @@ static BOOL cli_session_setup_ntlmssp(struct cli_state *cli, char *user,
                  workgroup, 
                  user, 
                  cli->calling.name,
-                 sess_key, 16,
+                 sess_key, 0,
                  neg_flags);
 
        /* wrap it in SPNEGO */
@@ -525,7 +570,12 @@ static BOOL cli_session_setup_ntlmssp(struct cli_state *cli, char *user,
        data_blob_free(&auth);
        data_blob_free(&blob);
 
-       return !cli_is_error(cli);
+       if (cli_is_error(cli))
+               return False;
+
+       set_signing_on_cli(cli, pass, nthash);
+
+       return True;
 }
 
 /****************************************************************************
@@ -537,17 +587,14 @@ static BOOL cli_session_setup_spnego(struct cli_state *cli, char *user,
 {
        char *principal;
        char *OIDs[ASN1_MAX_OIDS];
-       uint8 guid[16];
        int i;
        BOOL got_kerberos_mechanism = False;
-
-       /* spnego security cannot use SMB signing (for now). */
-       cli->sign_info.use_smb_signing = False;
+       DATA_BLOB blob;
 
        DEBUG(2,("Doing spnego session setup (blob length=%d)\n", cli->secblob.length));
 
        /* the server might not even do spnego */
-       if (cli->secblob.length == 16) {
+       if (cli->secblob.length <= 16) {
                DEBUG(3,("server didn't supply a full spnego negprot\n"));
                goto ntlmssp;
        }
@@ -556,11 +603,16 @@ static BOOL cli_session_setup_spnego(struct cli_state *cli, char *user,
        file_save("negprot.dat", cli->secblob.data, cli->secblob.length);
 #endif
 
+       /* there is 16 bytes of GUID before the real spnego packet starts */
+       blob = data_blob(cli->secblob.data+16, cli->secblob.length-16);
+
        /* the server sent us the first part of the SPNEGO exchange in the negprot 
           reply */
-       if (!spnego_parse_negTokenInit(cli->secblob, guid, OIDs, &principal)) {
+       if (!spnego_parse_negTokenInit(blob, OIDs, &principal)) {
+               data_blob_free(&blob);
                return False;
        }
+       data_blob_free(&blob);
 
        /* make sure the server understands kerberos */
        for (i=0;OIDs[i];i++) {
@@ -620,35 +672,38 @@ BOOL cli_session_setup(struct cli_state *cli,
            flow a bit easier to understand (tridge) */
 
        /* if its an older server then we have to use the older request format */
-       if (cli->protocol < PROTOCOL_NT1) {
+
+       if (cli->protocol < PROTOCOL_NT1)
                return cli_session_setup_lanman2(cli, user, pass, passlen, workgroup);
-       }
 
        /* if no user is supplied then we have to do an anonymous connection.
           passwords are ignored */
-       if (!user || !*user) {
+
+       if (!user || !*user)
                return cli_session_setup_guest(cli);
-       }
 
        /* if the server is share level then send a plaintext null
            password at this point. The password is sent in the tree
            connect */
-       if ((cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0) {
+
+       if ((cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL) == 0)
                return cli_session_setup_plaintext(cli, user, "", workgroup);
-       }
 
        /* if the server doesn't support encryption then we have to use 
           plaintext. The second password is ignored */
-       if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0) {
+
+       if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0)
                return cli_session_setup_plaintext(cli, user, pass, workgroup);
-       }
 
+       /* Indidicate signing */
+       
        /* if the server supports extended security then use SPNEGO */
-       if (cli->capabilities & CAP_EXTENDED_SECURITY) {
+
+       if (cli->capabilities & CAP_EXTENDED_SECURITY)
                return cli_session_setup_spnego(cli, user, pass, workgroup);
-       }
 
        /* otherwise do a NT1 style session setup */
+
        return cli_session_setup_nt1(cli, user, 
                                     pass, passlen, ntpass, ntpasslen,
                                     workgroup);        
@@ -738,15 +793,13 @@ BOOL cli_send_tconX(struct cli_state *cli,
        if (!cli_receive_smb(cli))
                return False;
 
-       if (cli_is_error(cli)) {
+       if (cli_is_error(cli))
                return False;
-       }
 
        clistr_pull(cli, cli->dev, smb_buf(cli->inbuf), sizeof(fstring), -1, STR_TERMINATE|STR_ASCII);
 
-       if (strcasecmp(share,"IPC$")==0) {
+       if (strcasecmp(share,"IPC$")==0)
                fstrcpy(cli->dev, "IPC");
-       }
 
        if (cli->protocol >= PROTOCOL_NT1 &&
            smb_buflen(cli->inbuf) == 3) {
@@ -786,9 +839,8 @@ void cli_negprot_send(struct cli_state *cli)
        char *p;
        int numprots;
 
-       if (cli->protocol < PROTOCOL_NT1) {
+       if (cli->protocol < PROTOCOL_NT1)
                cli->use_spnego = False;
-       }
 
        memset(cli->outbuf,'\0',smb_size);
 
@@ -827,9 +879,8 @@ BOOL cli_negprot(struct cli_state *cli)
                return False;
        }
 
-       if (cli->protocol < PROTOCOL_NT1) {
+       if (cli->protocol < PROTOCOL_NT1)
                cli->use_spnego = False;
-       }
 
        memset(cli->outbuf,'\0',smb_size);
 
@@ -891,12 +942,8 @@ BOOL cli_negprot(struct cli_state *cli)
                                    smb_buflen(cli->inbuf)-8, STR_UNICODE|STR_NOALIGN);
                }
 
-               /* A way to attempt to force SMB signing */
-               if (getenv("CLI_FORCE_SMB_SIGNING"))
+               if ((cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED))
                        cli->sign_info.negotiated_smb_signing = True;
-                                   
-               if (cli->sign_info.negotiated_smb_signing && !(cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED))
-                       cli->sign_info.negotiated_smb_signing = False;
 
        } else if (cli->protocol >= PROTOCOL_LANMAN1) {
                cli->use_spnego = False;
@@ -920,9 +967,8 @@ BOOL cli_negprot(struct cli_state *cli)
        cli->max_xmit = MIN(cli->max_xmit, CLI_BUFFER_SIZE);
 
        /* a way to force ascii SMB */
-       if (getenv("CLI_FORCE_ASCII")) {
+       if (getenv("CLI_FORCE_ASCII"))
                cli->capabilities &= ~CAP_UNICODE;
-       }
 
        return True;
 }
@@ -938,15 +984,6 @@ BOOL cli_session_request(struct cli_state *cli,
        int len = 4;
        extern pstring user_socket_options;
 
-       /* 445 doesn't have session request */
-       if (cli->port == 445) return True;
-
-       if (cli->sign_info.use_smb_signing) {
-               DEBUG(0, ("Cannot send session resquest again, particularly after setting up SMB Signing\n"));
-               return False;
-       }
-
-       /* send a session request (RFC 1002) */
        memcpy(&(cli->calling), calling, sizeof(*calling));
        memcpy(&(cli->called ), called , sizeof(*called ));
   
@@ -960,6 +997,16 @@ BOOL cli_session_request(struct cli_state *cli,
        name_mangle(cli->calling.name, p, cli->calling.name_type);
        len += name_len(p);
 
+       /* 445 doesn't have session request */
+       if (cli->port == 445)
+               return True;
+
+       if (cli->sign_info.use_smb_signing) {
+               DEBUG(0, ("Cannot send session resquest again, particularly after setting up SMB Signing\n"));
+               return False;
+       }
+
+       /* send a session request (RFC 1002) */
        /* setup the packet length
          * Remove four bytes from the length count, since the length
          * field in the NBT Session Service header counts the number
@@ -1066,7 +1113,8 @@ BOOL cli_connect(struct cli_state *cli, const char *host, struct in_addr *ip)
                        cli->fd = open_socket_out(SOCK_STREAM, &cli->dest_ip, 
                                                  port, cli->timeout);
                }
-               if (cli->fd != -1) cli->port = port;
+               if (cli->fd != -1)
+                       cli->port = port;
        }
        if (cli->fd == -1) {
                DEBUG(1,("Error connecting to %s (%s)\n",
@@ -1141,11 +1189,10 @@ NTSTATUS cli_full_connection(struct cli_state **output_cli,
                return NT_STATUS_UNSUCCESSFUL;
        }
 
-       if (dest_ip) {
+       if (dest_ip)
                ip = *dest_ip;
-       } else {
+       else
                ZERO_STRUCT(ip);
-       }
 
 again:
 
@@ -1162,8 +1209,7 @@ again:
                char *p;
                DEBUG(1,("session request to %s failed (%s)\n", 
                         called.name, cli_errstr(cli)));
-               cli_shutdown(cli);
-               if ((p=strchr(called.name, '.'))) {
+               if ((p=strchr(called.name, '.')) && !is_ipaddress(called.name)) {
                        *p = 0;
                        goto again;
                }
@@ -1174,11 +1220,10 @@ again:
                return NT_STATUS_UNSUCCESSFUL;
        }
 
-       if (flags & CLI_FULL_CONNECTION_DONT_SPNEGO) {
+       if (flags & CLI_FULL_CONNECTION_DONT_SPNEGO)
                cli->use_spnego = False;
-       } else if (flags & CLI_FULL_CONNECTION_USE_KERBEROS) {
+       else if (flags & CLI_FULL_CONNECTION_USE_KERBEROS)
                cli->use_kerberos = True;
-       }
 
        if (!cli_negprot(cli)) {
                DEBUG(1,("failed negprot\n"));
@@ -1261,18 +1306,22 @@ BOOL attempt_netbios_session_request(struct cli_state *cli, char *srchost, char
 
                        DEBUG(0,("attempt_netbios_session_request: %s rejected the session for name *SMBSERVER \
 with error %s.\n", desthost, cli_errstr(cli) ));
-                       cli_shutdown(cli);
                        return False;
                }
 
-               cli_shutdown(cli);
+               /*
+                * We need to close the connection here but can't call cli_shutdown as
+                * will free an allocated cli struct. cli_close_connection was invented
+                * for this purpose. JRA. Based on work by "Kim R. Pedersen" <krp@filanet.dk>.
+                */
+
+               cli_close_connection(cli);
 
                if (!cli_initialise(cli) ||
                                !cli_connect(cli, desthost, pdest_ip) ||
                                !cli_session_request(cli, &calling, &smbservername)) {
                        DEBUG(0,("attempt_netbios_session_request: %s rejected the session for \
 name *SMBSERVER with error %s\n", desthost, cli_errstr(cli) ));
-                       cli_shutdown(cli);
                        return False;
                }
        }
index c9500ead5d23c1a87de7443d60716acbc0872ac8..793dd19644f2de91e8c22041bdddd4daa4f4c27a 100644 (file)
@@ -32,49 +32,48 @@ int cli_set_port(struct cli_state *cli, int port)
 }
 
 /****************************************************************************
 read an smb from a fd ignoring all keepalive packets. Note that the buffer 
 *MUST* be of size BUFFER_SIZE+SAFETY_MARGIN.
 The timeout is in milliseconds
-
 This is exactly the same as receive_smb except that it never returns
 a session keepalive packet (just as receive_smb used to do).
 receive_smb was changed to return keepalives as the oplock processing means this call
 should never go into a blocking read.
Read an smb from a fd ignoring all keepalive packets. Note that the buffer 
+ *MUST* be of size BUFFER_SIZE+SAFETY_MARGIN.
+ The timeout is in milliseconds
+
+ This is exactly the same as receive_smb except that it never returns
+ a session keepalive packet (just as receive_smb used to do).
+ receive_smb was changed to return keepalives as the oplock processing means this call
+ should never go into a blocking read.
 ****************************************************************************/
 
 static BOOL client_receive_smb(int fd,char *buffer, unsigned int timeout)
 {
-  BOOL ret;
-
-  for(;;)
-  {
-    ret = receive_smb(fd, buffer, timeout);
-
-    if (!ret)
-    {
-      DEBUG(10,("client_receive_smb failed\n"));
-      show_msg(buffer);
-      return ret;
-    }
-
-    /* Ignore session keepalive packets. */
-    if(CVAL(buffer,0) != SMBkeepalive)
-      break;
-  }
-  show_msg(buffer);
-  return ret;
-}
+       BOOL ret;
+
+       for(;;) {
+               ret = receive_smb(fd, buffer, timeout);
 
+               if (!ret) {
+                       DEBUG(10,("client_receive_smb failed\n"));
+                       show_msg(buffer);
+                       return ret;
+               }
+
+               /* Ignore session keepalive packets. */
+               if(CVAL(buffer,0) != SMBkeepalive)
+                       break;
+       }
+       show_msg(buffer);
+       return ret;
+}
 
 /****************************************************************************
-recv an smb
+ Recv an smb.
 ****************************************************************************/
+
 BOOL cli_receive_smb(struct cli_state *cli)
 {
        BOOL ret;
 
        /* fd == -1 causes segfaults -- Tom (tom@ninja.nl) */
-       if (cli->fd == -1) return False; 
+       if (cli->fd == -1)
+               return False; 
 
  again:
        ret = client_receive_smb(cli->fd,cli->inbuf,cli->timeout);
@@ -151,34 +150,32 @@ void cli_setup_packet(struct cli_state *cli)
                uint16 flags2;
                SCVAL(cli->outbuf,smb_flg,0x8);
                flags2 = FLAGS2_LONG_PATH_COMPONENTS;
-               if (cli->capabilities & CAP_UNICODE) {
+               if (cli->capabilities & CAP_UNICODE)
                        flags2 |= FLAGS2_UNICODE_STRINGS;
-               }
-               if (cli->capabilities & CAP_STATUS32) {
+               if (cli->capabilities & CAP_STATUS32)
                        flags2 |= FLAGS2_32_BIT_ERROR_CODES;
-               }
-               if (cli->use_spnego) {
+               if (cli->use_spnego)
                        flags2 |= FLAGS2_EXTENDED_SECURITY;
-               }
-               if (cli->sign_info.use_smb_signing)
+               if (cli->sign_info.use_smb_signing 
+                   || cli->sign_info.temp_smb_signing)
                        flags2 |= FLAGS2_SMB_SECURITY_SIGNATURES;
                SSVAL(cli->outbuf,smb_flg2, flags2);
        }
 }
 
 /****************************************************************************
-setup the bcc length of the packet from a pointer to the end of the data
+ Setup the bcc length of the packet from a pointer to the end of the data.
 ****************************************************************************/
+
 void cli_setup_bcc(struct cli_state *cli, void *p)
 {
        set_message_bcc(cli->outbuf, PTR_DIFF(p, smb_buf(cli->outbuf)));
 }
 
-
-
 /****************************************************************************
-initialise credentials of a client structure
+ Initialise credentials of a client structure.
 ****************************************************************************/
+
 void cli_init_creds(struct cli_state *cli, const struct ntuser_creds *usr)
 {
         /* copy_nt_creds(&cli->usr, usr); */
@@ -193,10 +190,10 @@ void cli_init_creds(struct cli_state *cli, const struct ntuser_creds *usr)
                cli->ntlmssp_flags,cli->ntlmssp_cli_flgs));
 }
 
-
 /****************************************************************************
-initialise a client structure
+ Initialise a client structure.
 ****************************************************************************/
+
 struct cli_state *cli_initialise(struct cli_state *cli)
 {
         BOOL alloced_cli = False;
@@ -215,9 +212,8 @@ struct cli_state *cli_initialise(struct cli_state *cli)
                 alloced_cli = True;
        }
 
-       if (cli->initialised) {
-               cli_shutdown(cli);
-       }
+       if (cli->initialised)
+               cli_close_connection(cli);
 
        ZERO_STRUCTP(cli);
 
@@ -234,7 +230,9 @@ struct cli_state *cli_initialise(struct cli_state *cli)
        cli->outbuf = (char *)malloc(cli->bufsize);
        cli->inbuf = (char *)malloc(cli->bufsize);
        cli->oplock_handler = cli_oplock_ack;
-       cli->use_spnego = True;
+       if (lp_use_spnego()) {
+               cli->use_spnego = True;
+       }
 
        /* Set the CLI_FORCE_DOSERR environment variable to test
           client routines using DOS errors instead of STATUS32
@@ -243,6 +241,10 @@ struct cli_state *cli_initialise(struct cli_state *cli)
                cli->force_dos_errors = True;
        }
 
+       /* A way to attempt to force SMB signing */
+       if (getenv("CLI_FORCE_SMB_SIGNING"))
+               cli->sign_info.negotiated_smb_signing = True;
+                                   
        if (!cli->outbuf || !cli->inbuf)
                 goto error;
 
@@ -273,43 +275,75 @@ struct cli_state *cli_initialise(struct cli_state *cli)
 }
 
 /****************************************************************************
-shutdown a client structure
+ Close a client connection and free the memory without destroying cli itself.
 ****************************************************************************/
-void cli_shutdown(struct cli_state *cli)
+
+void cli_close_connection(struct cli_state *cli)
 {
-       BOOL allocated;
        SAFE_FREE(cli->outbuf);
        SAFE_FREE(cli->inbuf);
 
        data_blob_free(&cli->secblob);
 
-       if (cli->mem_ctx)
+       if (cli->mem_ctx) {
                talloc_destroy(cli->mem_ctx);
+               cli->mem_ctx = NULL;
+       }
 
        if (cli->fd != -1) 
                close(cli->fd);
-       allocated = cli->allocated;
+       cli->fd = -1;
+}
+
+/****************************************************************************
+ Shutdown a client structure.
+****************************************************************************/
+
+void cli_shutdown(struct cli_state *cli)
+{
+       BOOL allocated = cli->allocated;
+       cli_close_connection(cli);
        ZERO_STRUCTP(cli);
        if (allocated) {
                free(cli);
        } 
 }
 
-
 /****************************************************************************
-set socket options on a open connection
+ Set socket options on a open connection.
 ****************************************************************************/
+
 void cli_sockopt(struct cli_state *cli, char *options)
 {
        set_socket_options(cli->fd, options);
 }
 
 /****************************************************************************
-set the PID to use for smb messages. Return the old pid.
+ Set the PID to use for smb messages. Return the old pid.
 ****************************************************************************/
+
 uint16 cli_setpid(struct cli_state *cli, uint16 pid)
 {
        uint16 ret = cli->pid;
        cli->pid = pid;
        return ret;
 }
+
+/****************************************************************************
+Send a keepalive packet to the server
+****************************************************************************/
+BOOL cli_send_keepalive(struct cli_state *cli)
+{
+        if (cli->fd == -1) {
+                DEBUG(3, ("cli_send_keepalive: fd == -1\n"));
+                return False;
+        }
+        if (!send_keepalive(cli->fd)) {
+                close(cli->fd);
+                cli->fd = -1;
+                DEBUG(0,("Error sending keepalive packet to client.\n"));
+                return False;
+        }
+        return True;
+}
+
index 591c04db22dd00dcd71c54c0a4eed2fea218b6d8..e1507c6048e6a4c0c2f9e1d26e855145781a59fb 100644 (file)
@@ -156,7 +156,7 @@ void cli_dos_error(struct cli_state *cli, uint8 *eclass, uint32 *ecode)
 
 /* Return a UNIX errno from a dos error class, error number tuple */
 
-int cli_errno_from_dos(uint8 eclass, uint32 num)
+static int cli_errno_from_dos(uint8 eclass, uint32 num)
 {
        if (eclass == ERRDOS) {
                switch (num) {
@@ -205,7 +205,7 @@ static struct {
        {NT_STATUS(0), 0}
 };
 
-int cli_errno_from_nt(NTSTATUS status)
+static int cli_errno_from_nt(NTSTATUS status)
 {
        int i;
         DEBUG(10,("cli_errno_from_nt: 32 bit codes: code=%08x\n", NT_STATUS_V(status)));
index a47c956a55541b2ed34fad5982fb4c9f867dba49..07b1ff6b6f5dce750b5f2522da19f2900d24a878 100644 (file)
@@ -94,7 +94,7 @@ uint32  unix_perms_to_wire(mode_t perms)
         ret |= ((perms & S_ISGID) ?  UNIX_SET_GID : 0);
 #endif
 #ifdef S_ISUID
-        ret |= ((perms & S_ISVTX) ?  UNIX_SET_UID : 0);
+        ret |= ((perms & S_ISUID) ?  UNIX_SET_UID : 0);
 #endif
         return ret;
 }
index 685c4a25e0400a30b13b4b3fe7c172da120aad4b..e7143d065d71e41beaa5e93e52fbed223a736d10 100644 (file)
@@ -64,6 +64,14 @@ static krb5_error_code krb5_mk_req2(krb5_context context,
                goto cleanup_creds;
        }
 
+       /* cope with the ticket being in the future due to clock skew */
+       if ((unsigned)credsp->times.starttime > time(NULL)) {
+               time_t t = time(NULL);
+               int time_offset = (unsigned)credsp->times.starttime - t;
+               DEBUG(4,("Advancing clock by %d seconds to cope with clock skew\n", time_offset));
+               krb5_set_real_time(context, t + time_offset + 1, 0);
+       }
+
        in_data.length = 0;
        retval = krb5_mk_req_extended(context, auth_context, ap_req_options, 
                                      &in_data, credsp, outbuf);
@@ -86,7 +94,7 @@ cleanup_princ:
 /*
   get a kerberos5 ticket for the given service 
 */
-DATA_BLOB krb5_get_ticket(char *principal)
+DATA_BLOB krb5_get_ticket(char *principal, time_t time_offset)
 {
        krb5_error_code retval;
        krb5_data packet;
@@ -94,7 +102,12 @@ DATA_BLOB krb5_get_ticket(char *principal)
        krb5_context context;
        krb5_auth_context auth_context = NULL;
        DATA_BLOB ret;
-       krb5_enctype enc_types[] = {ENCTYPE_DES_CBC_MD5, ENCTYPE_NULL};
+       krb5_enctype enc_types[] = {
+#ifdef ENCTYPE_ARCFOUR_HMAC
+               ENCTYPE_ARCFOUR_HMAC, 
+#endif
+                                   ENCTYPE_DES_CBC_MD5, 
+                                   ENCTYPE_NULL};
 
        retval = krb5_init_context(&context);
        if (retval) {
@@ -103,6 +116,10 @@ DATA_BLOB krb5_get_ticket(char *principal)
                goto failed;
        }
 
+       if (time_offset != 0) {
+               krb5_set_real_time(context, time(NULL) + time_offset, 0);
+       }
+
        if ((retval = krb5_cc_default(context, &ccdef))) {
                DEBUG(1,("krb5_cc_default failed (%s)\n",
                         error_message(retval)));
@@ -137,7 +154,7 @@ failed:
 
 #else /* HAVE_KRB5 */
  /* this saves a few linking headaches */
- DATA_BLOB krb5_get_ticket(char *principal)
+ DATA_BLOB krb5_get_ticket(char *principal, time_t time_offset)
  {
         DEBUG(0,("NO KERBEROS SUPPORT\n"));
         return data_blob(NULL, 0);
index 17a759f9e39371455fdb39ea116e64425eddbfbb..3eacc25380aba4605378b308ac4641ac3059dead 100644 (file)
 
 #include "includes.h"
 
-
 /****************************************************************************
-interpret a long filename structure - this is mostly guesses at the moment
-The length of the structure is returned
-The structure of a long filename depends on the info level. 260 is used
-by NT and 2 is used by OS/2
+ Interpret a long filename structure - this is mostly guesses at the moment.
+ The length of the structure is returned
+ The structure of a long filename depends on the info level. 260 is used
+ by NT and 2 is used by OS/2
 ****************************************************************************/
+
 static int interpret_long_filename(struct cli_state *cli,
                                   int level,char *p,file_info *finfo)
 {
@@ -41,8 +41,7 @@ static int interpret_long_filename(struct cli_state *cli,
 
        memcpy(finfo,&def_finfo,sizeof(*finfo));
 
-       switch (level)
-               {
+       switch (level) {
                case 1: /* OS/2 understands this */
                        /* these dates are converted to GMT by
                            make_unix_date */
@@ -126,16 +125,16 @@ static int interpret_long_filename(struct cli_state *cli,
                                    namelen, 0);
                        return SVAL(base, 0);
                }
-               }
+       }
        
        DEBUG(1,("Unknown long filename format %d\n",level));
        return(SVAL(p,0));
 }
 
-
 /****************************************************************************
-  do a directory listing, calling fn on each file found
-  ****************************************************************************/
+ Do a directory listing, calling fn on each file found.
+****************************************************************************/
+
 int cli_list_new(struct cli_state *cli,const char *Mask,uint16 attribute, 
                 void (*fn)(file_info *, const char *, void *), void *state)
 {
@@ -307,12 +306,11 @@ int cli_list_new(struct cli_state *cli,const char *Mask,uint16 attribute,
        return(total_received);
 }
 
-
-
 /****************************************************************************
-interpret a short filename structure
-The length of the structure is returned
+ Interpret a short filename structure.
+ The length of the structure is returned.
 ****************************************************************************/
+
 static int interpret_short_filename(struct cli_state *cli, char *p,file_info *finfo)
 {
        extern file_info def_finfo;
@@ -334,10 +332,11 @@ static int interpret_short_filename(struct cli_state *cli, char *p,file_info *fi
 
 
 /****************************************************************************
-  do a directory listing, calling fn on each file found
-  this uses the old SMBsearch interface. It is needed for testing Samba,
-  but should otherwise not be used
-  ****************************************************************************/
+ Do a directory listing, calling fn on each file found.
+ this uses the old SMBsearch interface. It is needed for testing Samba,
+ but should otherwise not be used.
+****************************************************************************/
+
 int cli_list_old(struct cli_state *cli,const char *Mask,uint16 attribute, 
                 void (*fn)(file_info *, const char *, void *), void *state)
 {
@@ -453,16 +452,15 @@ int cli_list_old(struct cli_state *cli,const char *Mask,uint16 attribute,
        return(num_received);
 }
 
-
 /****************************************************************************
-  do a directory listing, calling fn on each file found
-  this auto-switches between old and new style
-  ****************************************************************************/
+ Do a directory listing, calling fn on each file found.
+ This auto-switches between old and new style.
+****************************************************************************/
+
 int cli_list(struct cli_state *cli,const char *Mask,uint16 attribute, 
             void (*fn)(file_info *, const char *, void *), void *state)
 {
-       if (cli->protocol <= PROTOCOL_LANMAN1) {
+       if (cli->protocol <= PROTOCOL_LANMAN1)
                return cli_list_old(cli, Mask, attribute, fn, state);
-       }
        return cli_list_new(cli, Mask, attribute, fn, state);
 }
index 756a6cce2f9ef9bf10cdad11670ed470b69fccef..875df11dca46387dd37557506cc0d072deea9c13 100644 (file)
@@ -127,7 +127,7 @@ ssize_t cli_read(struct cli_state *cli, int fnum, char *buf, off_t offset, size_
        return total;
 }
 
-#if 0  /* relies on client_recieve_smb(), now a static in libsmb/clientgen.c */
+#if 0  /* relies on client_receive_smb(), now a static in libsmb/clientgen.c */
 
 /* This call is INCOMPATIBLE with SMB signing.  If you remove the #if 0
    you must fix ensure you don't attempt to sign the packets - data
index 16702c375b25d41c67b7ce7380ff15e8e3aca5bb..55f49c5987111af4c1e8f1f9eb1fda6691b1a2c0 100644 (file)
@@ -73,13 +73,56 @@ DATA_BLOB spnego_gen_negTokenInit(uint8 guid[16],
        return ret;
 }
 
+/*
+  Generate a negTokenInit as used by the client side ... It has a mechType
+  (OID), and a mechToken (a security blob) ... 
+
+  Really, we need to break out the NTLMSSP stuff as well, because it could be
+  raw in the packets!
+*/
+DATA_BLOB gen_negTokenInit(const char *OID, DATA_BLOB blob)
+{
+       ASN1_DATA data;
+       DATA_BLOB ret;
+
+       memset(&data, 0, sizeof(data));
+
+       asn1_push_tag(&data, ASN1_APPLICATION(0));
+       asn1_write_OID(&data,OID_SPNEGO);
+       asn1_push_tag(&data, ASN1_CONTEXT(0));
+       asn1_push_tag(&data, ASN1_SEQUENCE(0));
+
+       asn1_push_tag(&data, ASN1_CONTEXT(0));
+       asn1_push_tag(&data, ASN1_SEQUENCE(0));
+       asn1_write_OID(&data, OID);
+       asn1_pop_tag(&data);
+       asn1_pop_tag(&data);
+
+       asn1_push_tag(&data, ASN1_CONTEXT(2));
+       asn1_write_OctetString(&data,blob.data,blob.length);
+       asn1_pop_tag(&data);
+
+       asn1_pop_tag(&data);
+       asn1_pop_tag(&data);
+
+       asn1_pop_tag(&data);
+
+       if (data.has_error) {
+               DEBUG(1,("Failed to build negTokenInit at offset %d\n", (int)data.ofs));
+               asn1_free(&data);
+       }
+
+       ret = data_blob(data.data, data.length);
+       asn1_free(&data);
+
+       return ret;
+}
 
 /*
   parse a negTokenInit packet giving a GUID, a list of supported
   OIDs (the mechanisms) and a principal name string 
 */
 BOOL spnego_parse_negTokenInit(DATA_BLOB blob,
-                              uint8 guid[16], 
                               char *OIDs[ASN1_MAX_OIDS], 
                               char **principal)
 {
@@ -89,7 +132,6 @@ BOOL spnego_parse_negTokenInit(DATA_BLOB blob,
 
        asn1_load(&data, blob);
 
-       asn1_read(&data, guid, 16);
        asn1_start_tag(&data,ASN1_APPLICATION(0));
        asn1_check_OID(&data,OID_SPNEGO);
        asn1_start_tag(&data,ASN1_CONTEXT(0));
@@ -279,13 +321,13 @@ BOOL spnego_parse_krb5_wrap(DATA_BLOB blob, DATA_BLOB *ticket)
    generate a SPNEGO negTokenTarg packet, ready for a EXTENDED_SECURITY
    kerberos session setup 
 */
-DATA_BLOB spnego_gen_negTokenTarg(struct cli_state *cli, char *principal)
+DATA_BLOB spnego_gen_negTokenTarg(const char *principal, int time_offset)
 {
        DATA_BLOB tkt, tkt_wrapped, targ;
        const char *krb_mechs[] = {OID_KERBEROS5_OLD, OID_NTLMSSP, NULL};
 
        /* get a kerberos ticket for the service */
-       tkt = krb5_get_ticket(principal);
+       tkt = krb5_get_ticket(principal, time_offset);
 
        /* wrap that up in a nice GSS-API wrapping */
        tkt_wrapped = spnego_gen_krb5_wrap(tkt);
@@ -473,8 +515,10 @@ DATA_BLOB spnego_gen_auth_response(void)
 
   U = unicode string (input is unix string)
   a = address (1 byte type, 1 byte length, unicode string, all inline)
+  A = ASCII string (pointer + length) Actually same as B
   B = data blob (pointer + length)
   b = data blob in header (pointer + length)
+  D
   d = word (4 bytes)
   C = constant ascii string
  */
@@ -502,6 +546,7 @@ BOOL msrpc_gen(DATA_BLOB *blob,
                        s = va_arg(ap, char *);
                        data_size += (str_charnum(s) * 2) + 4;
                        break;
+               case 'A':
                case 'B':
                        b = va_arg(ap, uint8 *);
                        head_size += 8;
@@ -553,7 +598,8 @@ BOOL msrpc_gen(DATA_BLOB *blob,
                        }
                        data_ofs += n*2;
                        break;
-                       
+
+               case 'A':
                case 'B':
                        b = va_arg(ap, uint8 *);
                        n = va_arg(ap, int);
@@ -688,37 +734,39 @@ BOOL msrpc_parse(DATA_BLOB *blob,
 
 void debug_ntlmssp_flags(uint32 neg_flags)
 {
+       DEBUG(3,("Got NTLMSSP neg_flags=0x%08x\n", neg_flags));
+       
        if (neg_flags & NTLMSSP_NEGOTIATE_UNICODE) 
-               DEBUG(4, ("  NTLMSSP_NEGOTIATE_UNICODE\n"));
+               DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_UNICODE\n"));
        if (neg_flags & NTLMSSP_NEGOTIATE_OEM) 
-               DEBUG(4, ("  NTLMSSP_NEGOTIATE_OEM\n"));
+               DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_OEM\n"));
        if (neg_flags & NTLMSSP_REQUEST_TARGET) 
-               DEBUG(4, ("  NTLMSSP_REQUEST_TARGET\n"));
-       if (neg_flags & NTLMSSP_NEGOTIATE_SIGN) 
-               DEBUG(4, ("  NTLMSSP_NEGOTIATE_SIGN\n"));
+               DEBUGADD(4, ("  NTLMSSP_REQUEST_TARGET\n"));
        if (neg_flags & NTLMSSP_NEGOTIATE_SIGN) 
-               DEBUG(4, ("  NTLMSSP_NEGOTIATE_SEAL\n"));
+               DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_SIGN\n"));
+       if (neg_flags & NTLMSSP_NEGOTIATE_SEAL) 
+               DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_SEAL\n"));
        if (neg_flags & NTLMSSP_NEGOTIATE_LM_KEY) 
-               DEBUG(4, ("  NTLMSSP_NEGOTIATE_LM_KEY\n"));
+               DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_LM_KEY\n"));
        if (neg_flags & NTLMSSP_NEGOTIATE_NETWARE) 
-               DEBUG(4, ("  NTLMSSP_NEGOTIATE_NETWARE\n"));
+               DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_NETWARE\n"));
        if (neg_flags & NTLMSSP_NEGOTIATE_NTLM) 
-               DEBUG(4, ("  NTLMSSP_NEGOTIATE_NTLM\n"));
+               DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_NTLM\n"));
        if (neg_flags & NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED) 
-               DEBUG(4, ("  NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED\n"));
+               DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED\n"));
        if (neg_flags & NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED) 
-               DEBUG(4, ("  NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED\n"));
+               DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED\n"));
        if (neg_flags & NTLMSSP_NEGOTIATE_THIS_IS_LOCAL_CALL) 
-               DEBUG(4, ("  NTLMSSP_NEGOTIATE_THIS_IS_LOCAL_CALL\n"));
+               DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_THIS_IS_LOCAL_CALL\n"));
        if (neg_flags & NTLMSSP_NEGOTIATE_ALWAYS_SIGN) 
-               DEBUG(4, ("  NTLMSSP_NEGOTIATE_ALWAYS_SIGN\n"));
+               DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_ALWAYS_SIGN\n"));
        if (neg_flags & NTLMSSP_NEGOTIATE_NTLM2) 
-               DEBUG(4, ("  NTLMSSP_NEGOTIATE_NTLM2\n"));
+               DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_NTLM2\n"));
        if (neg_flags & NTLMSSP_CHAL_TARGET_INFO) 
-               DEBUG(4, ("  NTLMSSP_CHAL_TARGET_INFO\n"));
+               DEBUGADD(4, ("  NTLMSSP_CHAL_TARGET_INFO\n"));
        if (neg_flags & NTLMSSP_NEGOTIATE_128) 
-               DEBUG(4, ("  NTLMSSP_NEGOTIATE_128\n"));
+               DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_128\n"));
        if (neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) 
-               DEBUG(4, ("  NTLMSSP_NEGOTIATE_KEY_EXCH\n"));
+               DEBUGADD(4, ("  NTLMSSP_NEGOTIATE_KEY_EXCH\n"));
 }
 
index 34b818ee7480c631f53d8264641d13e42f20a819..df02cf3718f464471c68929097a76136111821de 100644 (file)
@@ -89,7 +89,7 @@ static int smbc_add_cached_server(SMBCCTX * context, SMBCSRV * new,
                goto failed;
        }
 
-       DLIST_ADD(((struct smbc_server_cache *)context->server_cache), srvcache);
+       DLIST_ADD((context->server_cache), srvcache);
        return 0;
 
  failed:
@@ -139,7 +139,7 @@ static int smbc_remove_cached_server(SMBCCTX * context, SMBCSRV * server)
                if (server == srv->server) { 
 
                        /* remove this sucker */
-                       DLIST_REMOVE(((struct smbc_server_cache *)context->server_cache), srv);
+                       DLIST_REMOVE(context->server_cache, srv);
                        SAFE_FREE(srv->server_name);
                        SAFE_FREE(srv->share_name);
                        SAFE_FREE(srv->workgroup);
index 0ffc1c1378eed9cfbbb8902a02103d3f505e6d5e..44cba611d2f147ad1f1b9c2a2cb78559b854e2cd 100644 (file)
@@ -180,14 +180,13 @@ smbc_parse_path(SMBCCTX *context, const char *fname, char *server, char *share,
 
 static int smbc_errno(SMBCCTX *context, struct cli_state *c)
 {
-       int ret;
-
+       int ret = cli_errno(c);
+       
         if (cli_is_dos_error(c)) {
                 uint8 eclass;
                 uint32 ecode;
 
                 cli_dos_error(c, &eclass, &ecode);
-                ret = cli_errno_from_dos(eclass, ecode);
                 
                 DEBUG(3,("smbc_error %d %d (0x%x) -> %d\n", 
                          (int)eclass, (int)ecode, (int)ecode, ret));
@@ -195,10 +194,9 @@ static int smbc_errno(SMBCCTX *context, struct cli_state *c)
                 NTSTATUS status;
 
                 status = cli_nt_error(c);
-                ret = cli_errno_from_nt(status);
 
                 DEBUG(3,("smbc errno %s -> %d\n",
-                         get_nt_error_msg(status), ret));
+                         nt_errstr(status), ret));
         }
 
        return ret;
@@ -213,7 +211,7 @@ static int smbc_errno(SMBCCTX *context, struct cli_state *c)
  */
 int smbc_check_server(SMBCCTX * context, SMBCSRV * server) 
 {
-       if ( cli_send_keepalive(&server->cli) == False )
+       if ( send_keepalive(server->cli.fd) == False )
                return 1;
 
        /* connection is ok */
@@ -380,7 +378,7 @@ SMBCSRV *smbc_server(SMBCCTX *context,
                    fstring remote_name;
                    struct in_addr rem_ip;
 
-                   if (!inet_aton(server, &rem_ip)) {
+                   if ((rem_ip.s_addr=inet_addr(server)) == INADDR_NONE) {
                      DEBUG(4, ("Could not convert IP address %s to struct in_addr\n", server));
                      errno = ENOENT;
                      return NULL;
index fc09d8eac2a0f264230214965c351876e7f02453..2252e8e59cebd58e68207e716bd7c7d00cf8b0ba 100644 (file)
@@ -29,24 +29,24 @@ static TDB_CONTEXT *namecache_tdb;
 struct nc_value {
        time_t expiry;               /* When entry expires */
        int count;                   /* Number of addresses */
-       struct in_addr ip_list[0];   /* Address list */
+       struct in_addr ip_list[1];   /* Address list */
 };
 
 /* Initialise namecache system */
 
-void namecache_enable(void)
+BOOL namecache_enable(void)
 {
        /* Check if we have been here before, or name caching disabled
            by setting the name cache timeout to zero. */ 
 
        if (done_namecache_init)
-               return;
+               return False;
 
        done_namecache_init = True;
 
        if (lp_name_cache_timeout() == 0) {
                DEBUG(5, ("namecache_init: disabling netbios name cache\n"));
-               return;
+               return False;
        }
 
        /* Open namecache tdb in read/write or readonly mode */
@@ -58,13 +58,15 @@ void namecache_enable(void)
        if (!namecache_tdb) {
                DEBUG(5, ("namecache_init: could not open %s\n",
                          lock_path("namecache.tdb")));
-               return;
+               return False;
        }
 
        DEBUG(5, ("namecache_init: enabling netbios namecache, timeout %d "
                  "seconds\n", lp_name_cache_timeout()));
 
        enable_namecache = True;
+
+       return True;
 }
 
 /* Return a key for a name and name type.  The caller must free
@@ -91,17 +93,20 @@ static TDB_DATA namecache_value(struct in_addr *ip_list, int num_names,
 {
        TDB_DATA retval;
        struct nc_value *value;
-       int size;
+       int size = sizeof(struct nc_value);
 
-       size = sizeof(struct nc_value) + sizeof(struct in_addr) *
-               num_names;
+       if (num_names > 0)
+               size += sizeof(struct in_addr) * (num_names-1);
 
        value = (struct nc_value *)malloc(size);
-               
+
+       memset(value, 0, size);
+
        value->expiry = expiry;
        value->count = num_names;
 
-       memcpy(value->ip_list, ip_list, num_names * sizeof(struct in_addr));
+       if (ip_list)
+               memcpy(value->ip_list, ip_list, sizeof(struct in_addr) * num_names);
 
        retval.dptr = (char *)value;
        retval.dsize = size;
@@ -160,6 +165,9 @@ BOOL namecache_fetch(const char *name, int name_type, struct in_addr **ip_list,
        time_t now;
        int i;
 
+       *ip_list = NULL;
+       *num_names = 0;
+
        if (!enable_namecache)
                return False;
 
@@ -209,20 +217,23 @@ BOOL namecache_fetch(const char *name, int name_type, struct in_addr **ip_list,
 
        /* Extract and return namelist */
 
-       *ip_list = (struct in_addr *)malloc(
-               sizeof(struct in_addr) * data->count);
-       
-       memcpy(*ip_list, data->ip_list, sizeof(struct in_addr) *
-              data->count);
+       DEBUG(5, ("namecache_fetch: returning %d address%s for %s#%02x: ",
+                 data->count, data->count == 1 ? "" : "es", name, name_type));
 
-       *num_names = data->count;
+       if (data->count) {
 
-       DEBUG(5, ("namecache_fetch: returning %d address%s for %s#%02x: ",
-                 *num_names, *num_names == 1 ? "" : "es", name, name_type));
+               *ip_list = (struct in_addr *)malloc(
+                       sizeof(struct in_addr) * data->count);
+               
+               memcpy(*ip_list, data->ip_list, sizeof(struct in_addr) * data->count);
+               
+               *num_names = data->count;
+               
+               for (i = 0; i < *num_names; i++)
+                       DEBUGADD(5, ("%s%s", inet_ntoa((*ip_list)[i]),
+                                    i == (*num_names - 1) ? "" : ", "));
 
-       for (i = 0; i < *num_names; i++)
-               DEBUGADD(5, ("%s%s", inet_ntoa((*ip_list)[i]),
-                            i == (*num_names - 1) ? "" : ", "));
+       }
 
        DEBUGADD(5, ("\n"));
 
index e2da6318e1dbd906cad9ddd13005ace8cf5c872d..02fd53fc056a23c667aded3fe8da40d8b78a2602 100644 (file)
@@ -28,7 +28,7 @@ typedef const struct
        NTSTATUS nt_errcode;
 } nt_err_code_struct;
 
-nt_err_code_struct nt_errs[] =
+static nt_err_code_struct nt_errs[] =
 {
        { "NT_STATUS_OK", NT_STATUS_OK },
        { "NT_STATUS_UNSUCCESSFUL", NT_STATUS_UNSUCCESSFUL },
index dfa355a7ec611f84a9c69a0a12718d3672d7dc17..db265c4bf7c0f0688831ef94472ab40a46828f44 100644 (file)
@@ -116,39 +116,63 @@ void nt_lm_owf_gen(const char *pwd, uchar nt_p16[16], uchar p16[16])
 }
 
 /* Does both the NTLMv2 owfs of a user's password */
-void ntv2_owf_gen(const uchar owf[16],
-                 const char *user_n, const char *domain_n, uchar kr_buf[16])
+BOOL ntv2_owf_gen(const uchar owf[16],
+                 const char *user_in, const char *domain_in, uchar kr_buf[16])
 {
-       pstring user_u;
-       pstring dom_u;
+       smb_ucs2_t *user;
+       smb_ucs2_t *domain;
+       
+       int user_byte_len;
+       int domain_byte_len;
+
        HMACMD5Context ctx;
 
-       int user_l = strlen(user_n);
-       int domain_l = strlen(domain_n);
+       user_byte_len = push_ucs2_allocate(&user, user_in);
+       if (user_byte_len < 0) {
+               DEBUG(0, ("push_uss2_allocate() for user returned %d (probably malloc() failure)\n", user_byte_len));
+               return False;
+       }
 
-       push_ucs2(NULL, user_u, user_n, (user_l+1)*2, STR_UNICODE|STR_NOALIGN|STR_TERMINATE|STR_UPPER);
-       push_ucs2(NULL, dom_u, domain_n, (domain_l+1)*2, STR_UNICODE|STR_NOALIGN|STR_TERMINATE|STR_UPPER);
+       domain_byte_len = push_ucs2_allocate(&domain, domain_in);
+       if (domain_byte_len < 0) {
+               DEBUG(0, ("push_uss2_allocate() for domain returned %d (probably malloc() failure)\n", user_byte_len));
+               return False;
+       }
+
+       strupper_w(user);
+       strupper_w(domain);
+
+       /* We don't want null termination */
+       user_byte_len = user_byte_len - 2;
+       domain_byte_len = domain_byte_len - 2;
+       
+       SMB_ASSERT(user_byte_len >= 0);
+       SMB_ASSERT(domain_byte_len >= 0);
 
        hmac_md5_init_limK_to_64(owf, 16, &ctx);
-       hmac_md5_update((const unsigned char *)user_u, user_l * 2, &ctx);
-       hmac_md5_update((const unsigned char *)dom_u, domain_l * 2, &ctx);
+       hmac_md5_update((const unsigned char *)user, user_byte_len, &ctx);
+       hmac_md5_update((const unsigned char *)domain, domain_byte_len, &ctx);
        hmac_md5_final(kr_buf, &ctx);
 
 #ifdef DEBUG_PASSWORD
        DEBUG(100, ("ntv2_owf_gen: user, domain, owfkey, kr\n"));
-       dump_data(100, user_u, user_l * 2);
-       dump_data(100, dom_u, domain_l * 2);
+       dump_data(100, (const char *)user, user_byte_len);
+       dump_data(100, (const char *)domain, domain_byte_len);
        dump_data(100, owf, 16);
        dump_data(100, kr_buf, 16);
 #endif
+
+       SAFE_FREE(user);
+       SAFE_FREE(domain);
+       return True;
 }
 
 /* Does the des encryption from the NT or LM MD4 hash. */
 void SMBOWFencrypt(const uchar passwd[16], const uchar *c8, uchar p24[24])
 {
        uchar p21[21];
-       memset(p21,'\0',21);
+
+       ZERO_STRUCT(p21);
  
        memcpy(p21, passwd, 16);    
        E_P24(p21, c8, p24);
@@ -362,6 +386,12 @@ void cli_caclulate_sign_mac(struct cli_state *cli)
        unsigned char calc_md5_mac[16];
        struct MD5Context md5_ctx;
 
+       if (cli->sign_info.temp_smb_signing) {
+               memcpy(&cli->outbuf[smb_ss_field], "SignRequest", 8);
+               cli->sign_info.temp_smb_signing = False;
+               return;
+       }
+
        if (!cli->sign_info.use_smb_signing) {
                return;
        }
@@ -380,6 +410,8 @@ void cli_caclulate_sign_mac(struct cli_state *cli)
        MD5Final(calc_md5_mac, &md5_ctx);
 
        memcpy(&cli->outbuf[smb_ss_field], calc_md5_mac, 8);
+/*     cli->outbuf[smb_ss_field+2]=0; 
+       Uncomment this to test if the remote server actually verifies signitures...*/
        cli->sign_info.send_seq_num++;
        cli->sign_info.reply_seq_num = cli->sign_info.send_seq_num;
        cli->sign_info.send_seq_num++;
index fe6b673e39e9acbb2c57867a760f8ca3db5673f4..4d7acd198889439de43dbadc8a50d2f2d4252f8c 100644 (file)
@@ -35,8 +35,9 @@ static NTSTATUS just_change_the_password(struct cli_state *cli, TALLOC_CTX *mem_
                                         unsigned char new_trust_passwd_hash[16])
 {
        NTSTATUS result;
-       result = cli_nt_setup_creds(cli, (lp_server_role() == ROLE_DOMAIN_MEMBER) ?
-                                  SEC_CHAN_WKSTA : SEC_CHAN_BDC, orig_trust_passwd_hash);
+       uint32 neg_flags = 0x000001ff;
+
+       result = cli_nt_setup_creds(cli, get_sec_chan(), orig_trust_passwd_hash, &neg_flags, 2);
        
        if (!NT_STATUS_IS_OK(result)) {
                DEBUG(1,("just_change_the_password: unable to setup creds (%s)!\n",
index d42d041b79049c5ef42881e55490a1947269230c..3eb7ca478321415c047940cff6796fec3403e222 100644 (file)
@@ -142,7 +142,7 @@ static NTSTATUS do_lock(files_struct *fsp,connection_struct *conn, uint16 lock_p
 }
 
 /****************************************************************************
- Utility function called by locking requests. This is *DISGISTING*. It also
+ Utility function called by locking requests. This is *DISGUSTING*. It also
  appears to be "What Windows Does" (tm). Andrew, ever wonder why Windows 2000
  is so slow on the locking tests...... ? This is the reason. Much though I hate
  it, we need this. JRA.
index d6605d08f56c92bcc8cd456ef7bc2ce34c217357..b65cebe2035fbcf086a495b45c753d784456721e 100644 (file)
@@ -334,7 +334,8 @@ reporting %s domain %s 0x%x ntversion=%x lm_nt token=%x lm_20 token=%x\n",
        /* Push domain components */
        dc = domain;
        q1 = q;
-       while ((component = strsep(&dc, "."))) {
+       while ((component = strtok(dc, "."))) {
+         dc = NULL;
          size = push_ascii(&q[1], component, -1, 0);
          SCVAL(q, 0, size);
          q += (size + 1);
index bf03d4d1cf279e335e53054e77d80fa6771f5233..24adf4e69f2a07e58e1af3d467df68cd867aed82 100644 (file)
@@ -70,7 +70,11 @@ static void sync_child(char *name, int nm_type,
        uint32 local_type = local ? SV_TYPE_LOCAL_LIST_ONLY : 0;
        struct nmb_name called, calling;
 
-       if (!cli_initialise(&cli) || !cli_connect(&cli, name, &ip)) {
+       /* W2K DMB's return empty browse lists on port 445. Use 139.
+        * Patch from Andy Levine andyl@epicrealm.com.
+        */
+
+       if (!cli_initialise(&cli) || !cli_set_port(&cli, 139) || !cli_connect(&cli, name, &ip)) {
                return;
        }
 
index 29ceca4e79ef877e2aede66a4a70af7ffef3fb01..f95caefb4cd409fd63ba20666ff5f7ca06939f64 100644 (file)
 
 #include "pam_winbind.h"
 
-/* prototypes from common.c */
-void init_request(struct winbindd_request *req,int rq_type);
-int write_sock(void *buffer, int count);
-int read_reply(struct winbindd_response *response);
-
 /* data tokens */
 
 #define MAX_PASSWD_TRIES       3
@@ -99,24 +94,30 @@ static int _make_remark(pam_handle_t * pamh, int type, const char *text)
        return retval;
 }
 
-static int winbind_request(enum winbindd_cmd req_type,
-                           struct winbindd_request *request,
-                           struct winbindd_response *response)
+static int pam_winbind_request(enum winbindd_cmd req_type,
+                              struct winbindd_request *request,
+                              struct winbindd_response *response)
 {
+
        /* Fill in request and send down pipe */
        init_request(request, req_type);
        
        if (write_sock(request, sizeof(*request)) == -1) {
                _pam_log(LOG_ERR, "write to socket failed!");
+               close_sock();
                return PAM_SERVICE_ERR;
        }
        
        /* Wait for reply */
        if (read_reply(response) == -1) {
                _pam_log(LOG_ERR, "read from socket failed!");
+               close_sock();
                return PAM_SERVICE_ERR;
        }
 
+       /* We are done with the socket - close it and avoid mischeif */
+       close_sock();
+
        /* Copy reply data from socket */
        if (response->result != WINBINDD_OK) {
                if (response->data.auth.pam_error != PAM_SUCCESS) {
@@ -148,7 +149,7 @@ static int winbind_auth_request(const char *user, const char *pass, int ctrl)
        strncpy(request.data.auth.pass, pass, 
                 sizeof(request.data.auth.pass)-1);
        
-        retval = winbind_request(WINBINDD_PAM_AUTH, &request, &response);
+        retval = pam_winbind_request(WINBINDD_PAM_AUTH, &request, &response);
 
        switch (retval) {
        case PAM_AUTH_ERR:
@@ -217,7 +218,7 @@ static int winbind_chauthtok_request(const char *user, const char *oldpass,
             request.data.chauthtok.newpass[0] = '\0';
         }
        
-        return winbind_request(WINBINDD_PAM_CHAUTHTOK, &request, &response);
+        return pam_winbind_request(WINBINDD_PAM_CHAUTHTOK, &request, &response);
 }
 
 /*
index 9897249e164101a19c78304785c87c4f045d8739..fae635d8067fde692d967a415c1db1d4056cf08a 100644 (file)
@@ -90,5 +90,4 @@ do {                             \
 #define on(x, y) (x & y)
 #define off(x, y) (!(x & y))
 
-#include "winbind_nss_config.h"
-#include "winbindd_nss.h"
+#include "winbind_client.h"
index 9bc9faafb50e62794c6e71f8f43605e763843662..51792f63fe2ef768b543032529bd75f81d1d4a74 100644 (file)
@@ -5,6 +5,8 @@
 
    Copyright (C) Tim Potter 2000
    Copyright (C) Andrew Tridgell 2000
+   Copyright (C) Andrew Bartlett 2002
+   
    
    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
@@ -75,7 +77,7 @@ void init_response(struct winbindd_response *response)
 
 /* Close established socket */
 
-static void close_sock(void)
+void close_sock(void)
 {
        if (winbindd_fd != -1) {
                close(winbindd_fd);
@@ -83,14 +85,75 @@ static void close_sock(void)
        }
 }
 
+/* Make sure socket handle isn't stdin, stdout or stderr */
+#define RECURSION_LIMIT 3
+
+static int make_nonstd_fd_internals(int fd, int limit /* Recursion limiter */) 
+{
+       int new_fd;
+       if (fd >= 0 && fd <= 2) {
+#ifdef F_DUPFD 
+               if ((new_fd = fcntl(fd, F_DUPFD, 3)) == -1) {
+                       return -1;
+               }
+               /* Parinoia */
+               if (new_fd < 3) {
+                       close(new_fd);
+                       return -1;
+               }
+               close(fd);
+               return new_fd;
+#else
+               if (limit <= 0)
+                       return -1;
+               
+               new_fd = dup(fd);
+               if (new_fd == -1) 
+                       return -1;
+
+               /* use the program stack to hold our list of FDs to close */
+               new_fd = make_nonstd_fd_internals(new_fd, limit - 1);
+               close(fd);
+               return new_fd;
+#endif
+       }
+       return fd;
+}
+
+static int make_safe_fd(int fd) 
+{
+       int result, flags;
+       int new_fd = make_nonstd_fd_internals(fd, RECURSION_LIMIT);
+       if (new_fd == -1) {
+               close(fd);
+               return -1;
+       }
+       /* Socket should be closed on exec() */
+       
+#ifdef FD_CLOEXEC
+       result = flags = fcntl(new_fd, F_GETFD, 0);
+       if (flags >= 0) {
+               flags |= FD_CLOEXEC;
+               result = fcntl( new_fd, F_SETFD, flags );
+       }
+       if (result < 0) {
+               close(new_fd);
+               return -1;
+       }
+#endif
+       return new_fd;
+}
+
 /* Connect to winbindd socket */
 
 int winbind_open_pipe_sock(void)
 {
+#ifdef HAVE_UNIXSOCKET
        struct sockaddr_un sunaddr;
        static pid_t our_pid;
        struct stat st;
        pstring path;
+       int fd;
        
        if (our_pid != getpid()) {
                close_sock();
@@ -144,9 +207,13 @@ int winbind_open_pipe_sock(void)
        
        /* Connect to socket */
        
-       if ((winbindd_fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
+       if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
                return -1;
        }
+
+       if ((winbindd_fd = make_safe_fd( fd)) == -1) {
+               return winbindd_fd;
+       }
        
        if (connect(winbindd_fd, (struct sockaddr *)&sunaddr, 
                    sizeof(sunaddr)) == -1) {
@@ -155,6 +222,9 @@ int winbind_open_pipe_sock(void)
        }
         
        return winbindd_fd;
+#else
+       return -1;
+#endif /* HAVE_UNIXSOCKET */
 }
 
 /* Write data to winbindd socket */
@@ -366,8 +436,8 @@ NSS_STATUS winbindd_get_response(struct winbindd_response *response)
 /* Handle simple types of requests */
 
 NSS_STATUS winbindd_request(int req_type, 
-                                struct winbindd_request *request,
-                                struct winbindd_response *response)
+                           struct winbindd_request *request,
+                           struct winbindd_response *response)
 {
        NSS_STATUS status;
 
index 4d36acc51b3259ded314598b8c61a3bc842240d3..875df231dca56694e5d98b2b702579c557213ca4 100644 (file)
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_WINBIND
 
-/* Prototypes from common.h */
-
-NSS_STATUS winbindd_request(int req_type, 
-                           struct winbindd_request *request,
-                           struct winbindd_response *response);
+extern int winbindd_fd;
 
 static char winbind_separator(void)
 {
@@ -450,9 +446,10 @@ static BOOL wbinfo_auth(char *username)
         d_printf("plaintext password authentication %s\n", 
                (result == NSS_STATUS_SUCCESS) ? "succeeded" : "failed");
 
-       d_printf("error code was %s (0x%x)\n", 
-                response.data.auth.nt_status_string, 
-                response.data.auth.nt_status);
+       if (response.data.auth.nt_status)
+               d_printf("error code was %s (0x%x)\n", 
+                        response.data.auth.nt_status_string, 
+                        response.data.auth.nt_status);
 
         return result == NSS_STATUS_SUCCESS;
 }
@@ -504,9 +501,10 @@ static BOOL wbinfo_auth_crap(char *username)
         d_printf("challenge/response password authentication %s\n", 
                (result == NSS_STATUS_SUCCESS) ? "succeeded" : "failed");
 
-       d_printf("error code was %s (0x%x)\n", 
-              response.data.auth.nt_status_string, 
-              response.data.auth.nt_status);
+       if (response.data.auth.nt_status)
+               d_printf("error code was %s (0x%x)\n", 
+                        response.data.auth.nt_status_string, 
+                        response.data.auth.nt_status);
 
         return result == NSS_STATUS_SUCCESS;
 }
@@ -608,43 +606,17 @@ static BOOL wbinfo_set_auth_user(char *username)
 static BOOL wbinfo_ping(void)
 {
         NSS_STATUS result;
-       
+
        result = winbindd_request(WINBINDD_PING, NULL, NULL);
 
        /* Display response */
 
-        d_printf("'ping' to winbindd %s\n", 
-               (result == NSS_STATUS_SUCCESS) ? "succeeded" : "failed");
+        d_printf("'ping' to winbindd %s on fd %d\n", 
+               (result == NSS_STATUS_SUCCESS) ? "succeeded" : "failed", winbindd_fd);
 
         return result == NSS_STATUS_SUCCESS;
 }
 
-/* Print program usage */
-
-static void usage(void)
-{
-       d_printf("Usage: wbinfo -ug | -n name | -sSY sid | -UG uid/gid | -tm "
-               "| -[aA] user%%password\n");
-       d_printf("\t-u\t\t\tlists all domain users\n");
-       d_printf("\t-g\t\t\tlists all domain groups\n");
-       d_printf("\t-n name\t\t\tconverts name to sid\n");
-       d_printf("\t-s sid\t\t\tconverts sid to name\n");
-       d_printf("\t-N name\t\t\tconverts NetBIOS name to IP (WINS)\n");
-       d_printf("\t-I name\t\t\tconverts IP address to NetBIOS name (WINS)\n");
-       d_printf("\t-U uid\t\t\tconverts uid to sid\n");
-       d_printf("\t-G gid\t\t\tconverts gid to sid\n");
-       d_printf("\t-S sid\t\t\tconverts sid to uid\n");
-       d_printf("\t-Y sid\t\t\tconverts sid to gid\n");
-       d_printf("\t-t\t\t\tcheck shared secret\n");
-       d_printf("\t-m\t\t\tlist trusted domains\n");
-       d_printf("\t-r user\t\t\tget user groups\n");
-       d_printf("\t-a user%%password\tauthenticate user\n");
-       d_printf("\t-A user%%password\tstore user and password used by winbindd (root only)\n");
-       d_printf("\t-p\t\t\t'ping' winbindd to see if it is alive\n");
-       d_printf("\t--sequence\t\tshow sequence numbers of all domains\n");
-       d_printf("\t--set-auth-user DOMAIN\\user%%password\tset password for restrict anonymous\n");
-}
-
 /* Main program */
 
 enum {
@@ -664,28 +636,28 @@ int main(int argc, char **argv)
        int result = 1;
 
        struct poptOption long_options[] = {
+               POPT_AUTOHELP
 
                /* longName, shortName, argInfo, argPtr, value, descrip, 
                   argDesc */
 
-               { "help", 'h', POPT_ARG_NONE, 0, 'h' },
-               { "domain-users", 'u', POPT_ARG_NONE, 0, 'u' },
-               { "domain-groups", 'g', POPT_ARG_NONE, 0, 'g' },
-               { "WINS-by-name", 'N', POPT_ARG_STRING, &string_arg, 'N' },
-               { "WINS-by-ip", 'I', POPT_ARG_STRING, &string_arg, 'I' },
-               { "name-to-sid", 'n', POPT_ARG_STRING, &string_arg, 'n' },
-               { "sid-to-name", 's', POPT_ARG_STRING, &string_arg, 's' },
-               { "uid-to-sid", 'U', POPT_ARG_INT, &int_arg, 'U' },
-               { "gid-to-sid", 'G', POPT_ARG_INT, &int_arg, 'G' },
-               { "sid-to-uid", 'S', POPT_ARG_STRING, &string_arg, 'S' },
-               { "sid-to-gid", 'Y', POPT_ARG_STRING, &string_arg, 'Y' },
-               { "check-secret", 't', POPT_ARG_NONE, 0, 't' },
-               { "trusted-domains", 'm', POPT_ARG_NONE, 0, 'm' },
-               { "sequence", 0, POPT_ARG_NONE, 0, OPT_SEQUENCE },
-               { "user-groups", 'r', POPT_ARG_STRING, &string_arg, 'r' },
-               { "authenticate", 'a', POPT_ARG_STRING, &string_arg, 'a' },
-               { "set-auth-user", 'A', POPT_ARG_STRING, &string_arg, OPT_SET_AUTH_USER },
-               { "ping", 'p', POPT_ARG_NONE, 0, 'p' },
+               { "domain-users", 'u', POPT_ARG_NONE, 0, 'u', "Lists all domain users"},
+               { "domain-groups", 'g', POPT_ARG_NONE, 0, 'g', "Lists all domain groups" },
+               { "WINS-by-name", 'N', POPT_ARG_STRING, &string_arg, 'N', "Converts NetBIOS name to IP (WINS)" },
+               { "WINS-by-ip", 'I', POPT_ARG_STRING, &string_arg, 'I', "Converts IP address to NetBIOS name (WINS)" },
+               { "name-to-sid", 'n', POPT_ARG_STRING, &string_arg, 'n', "Converts name to sid" },
+               { "sid-to-name", 's', POPT_ARG_STRING, &string_arg, 's', "Converts sid to name" },
+               { "uid-to-sid", 'U', POPT_ARG_INT, &int_arg, 'U', "Converts uid to sid" },
+               { "gid-to-sid", 'G', POPT_ARG_INT, &int_arg, 'G', "Converts gid to sid" },
+               { "sid-to-uid", 'S', POPT_ARG_STRING, &string_arg, 'S', "Converts sid to uid" },
+               { "sid-to-gid", 'Y', POPT_ARG_STRING, &string_arg, 'Y', "Converts sid to gid" },
+               { "check-secret", 't', POPT_ARG_NONE, 0, 't', "Check shared secret" },
+               { "trusted-domains", 'm', POPT_ARG_NONE, 0, 'm', "List trusted domains" },
+               { "sequence", 0, POPT_ARG_NONE, 0, OPT_SEQUENCE, "show sequence numbers of all domains" },
+               { "user-groups", 'r', POPT_ARG_STRING, &string_arg, 'r', "Get user groups" },
+               { "authenticate", 'a', POPT_ARG_STRING, &string_arg, 'a', "authenticate user", "user%password" },
+               { "set-auth-user", 'A', POPT_ARG_STRING, &string_arg, OPT_SET_AUTH_USER, "Store user and password used by winbindd (root only)", "user%password" },
+               { "ping", 'p', POPT_ARG_NONE, 0, 'p', "'ping' winbindd to see if it is alive" },
                { 0, 0, 0, 0 }
        };
 
@@ -708,17 +680,17 @@ int main(int argc, char **argv)
 
        load_interfaces();
 
+       /* Parse options */
+
+       pc = poptGetContext("wbinfo", argc, (const char **)argv, long_options, 0);
+
        /* Parse command line options */
 
        if (argc == 1) {
-               usage();
+               poptPrintHelp(pc, stderr, 0);
                return 1;
        }
 
-       /* Parse options */
-
-       pc = poptGetContext("wbinfo", argc, (const char **)argv, long_options, 0);
-
        while((opt = poptGetNextOpt(pc)) != -1) {
                if (got_command) {
                        d_fprintf(stderr, "No more than one command may be specified at once.\n");
@@ -734,10 +706,6 @@ int main(int argc, char **argv)
 
        while((opt = poptGetNextOpt(pc)) != -1) {
                switch (opt) {
-               case 'h':
-                       usage();
-                       result = 0;
-                       goto done;
                case 'u':
                        if (!print_domain_users()) {
                                d_printf("Error looking up domain users\n");
@@ -859,7 +827,7 @@ int main(int argc, char **argv)
                        break;
                default:
                        d_fprintf(stderr, "Invalid option\n");
-                       usage();
+                       poptPrintHelp(pc, stderr, 0);
                        goto done;
                }
        }
index 594b5fbadb29fad20028def2850c033b6a7399ca..0b4c0ce1d087786d97dc4b6f6a7378ff1b29a544 100644 (file)
@@ -21,8 +21,7 @@
    Boston, MA  02111-1307, USA.   
 */
 
-#include "winbind_nss_config.h"
-#include "winbindd_nss.h"
+#include "winbind_client.h"
 
 #ifdef HAVE_NS_API_H
 #undef VOLATILE
 
 extern int winbindd_fd;
 
-void init_request(struct winbindd_request *req,int rq_type);
-NSS_STATUS winbindd_send_request(int req_type,
-                                struct winbindd_request *request);
-NSS_STATUS winbindd_get_response(struct winbindd_response *response);
-NSS_STATUS winbindd_request(int req_type, 
-                                struct winbindd_request *request,
-                                struct winbindd_response *response);
-int winbind_open_pipe_sock(void);
-int write_sock(void *buffer, int count);
-int read_reply(struct winbindd_response *response);
-void free_response(struct winbindd_response *response);
 
 #ifdef HAVE_NS_API_H
 /* IRIX version */
index b9c738211e174dfb56b604a751cee479c34d1392..d9a9b8aaaefe07a250b89cc79070febc212940ef 100644 (file)
 #include <unistd.h>
 #endif
 
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+
 #ifdef HAVE_SYS_SOCKET_H
 #include <sys/socket.h>
 #endif
 #include <string.h>
 #endif
 
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#else
+#ifdef HAVE_SYS_FCNTL_H
+#include <sys/fcntl.h>
+#endif
+#endif
+
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <errno.h>
index 256c0203c0e2c2bb9dff2f139c55ac0e47b44fde..bb4a1b78ec5509aec5fa40e0468b6e6e30c064a1 100644 (file)
@@ -628,8 +628,8 @@ static void process_loop(int accept_sock)
 
                                        if (state->read_buf_len >= sizeof(uint32)
                                            && *(uint32 *) &state->request != sizeof(state->request)) {
-                                               DEBUG(0,("process_loop: Invalid request size (%d) send, should be (%d)\n",
-                                                               *(uint32 *) &state->request, sizeof(state->request)));
+                                               DEBUG(0,("process_loop: Invalid request size from pid %d: %d bytes sent, should be %d\n",
+                                                               state->request.pid, *(uint32 *) &state->request, sizeof(state->request)));
 
                                                remove_client(state);
                                                break;
@@ -858,6 +858,7 @@ static void usage(void)
                pidfile_create("winbindd");
        }
 
+
 #if HAVE_SETPGID
        /*
         * If we're interactive we want to set our own process group for
index b0b70178a45ca9ea2e07cfbd5111fdc5ff1a3524..4f91ed0f20c31c325b6e1a4a1672c10c22436d24 100644 (file)
@@ -143,7 +143,7 @@ static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain)
                /* if we get ECONNREFUSED then it might be a NT4
                    server, fall back to MSRPC */
                if (status.error_type == ADS_ERROR_SYSTEM &&
-                   status.rc == ECONNREFUSED) {
+                   status.err.rc == ECONNREFUSED) {
                        DEBUG(1,("Trying MSRPC methods\n"));
                        domain->methods = &msrpc_methods;
                }
@@ -170,9 +170,9 @@ static void sid_from_rid(struct winbindd_domain *domain, uint32 rid, DOM_SID *si
 static enum SID_NAME_USE ads_atype_map(uint32 atype)
 {
        switch (atype & 0xF0000000) {
-       case ATYPE_GROUP:
+       case ATYPE_GLOBAL_GROUP:
                return SID_NAME_DOM_GRP;
-       case ATYPE_USER:
+       case ATYPE_ACCOUNT:
                return SID_NAME_USER;
        default:
                DEBUG(1,("hmm, need to map account type 0x%x\n", atype));
@@ -339,7 +339,7 @@ static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
 
                if (!ads_pull_uint32(ads, msg, "sAMAccountType", 
                                     &account_type) ||
-                   !(account_type & ATYPE_GROUP)) continue;
+                   !(account_type & ATYPE_GLOBAL_GROUP)) continue;
 
                name = pull_username(ads, mem_ctx, msg);
                gecos = ads_pull_string(ads, mem_ctx, msg, "name");
index 2dec9f0558606ca33fdc24fecac34679f28d2af4..01f556988930463a2db301e2725f0ddd876c24e7 100644 (file)
@@ -109,7 +109,7 @@ static BOOL cm_ads_find_dc(const char *domain, struct in_addr *dc_ip, fstring sr
        }
 
        /* we don't need to bind, just connect */
-       ads->auth.no_bind = 1;
+       ads->auth.flags |= ADS_AUTH_NO_BIND;
 
        DEBUG(4,("cm_ads_find_dc: domain=%s\n", domain));
 
@@ -145,11 +145,16 @@ static BOOL cm_rpc_find_dc(const char *domain, struct in_addr *dc_ip, fstring sr
 
        /* Lookup domain controller name. Try the real PDC first to avoid
           SAM sync delays */
-       if (!get_dc_list(True, domain, &ip_list, &count)) {
-               if (!get_dc_list(False, domain, &ip_list, &count)) {
-                       DEBUG(3, ("Could not look up dc's for domain %s\n", domain));
-                       return False;
-               }
+       if (get_dc_list(True, domain, &ip_list, &count) &&
+           name_status_find(domain, 0x1c, 0x20, ip_list[0], srv_name)) {
+               *dc_ip = ip_list[0];
+               SAFE_FREE(ip_list);
+               return True;
+       }
+
+       if (!get_dc_list(False, domain, &ip_list, &count)) {
+               DEBUG(3, ("Could not look up dc's for domain %s\n", domain));
+               return False;
        }
 
        /* Pick a nice close server */
@@ -377,16 +382,6 @@ static NTSTATUS cm_open_connection(const char *domain,const char *pipe_name,
        fstrcpy(new_conn->domain, domain);
        fstrcpy(new_conn->pipe_name, pipe_name);
        
-       /* Look for a domain controller for this domain.  Negative results
-          are cached so don't bother applying the caching for this
-          function just yet.  */
-
-       if (!cm_get_dc_name(domain, new_conn->controller, &dc_ip)) {
-               result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
-               add_failed_connection_entry(new_conn, result);
-               return result;
-       }
-               
        /* Return false if we have tried to look up this domain and netbios
           name before and failed. */
 
@@ -418,6 +413,16 @@ static NTSTATUS cm_open_connection(const char *domain,const char *pipe_name,
                return result;
        }
 
+       /* Look for a domain controller for this domain.  Negative results
+          are cached so don't bother applying the caching for this
+          function just yet.  */
+
+       if (!cm_get_dc_name(domain, new_conn->controller, &dc_ip)) {
+               result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
+               add_failed_connection_entry(new_conn, result);
+               return result;
+       }
+               
        /* Initialise SMB connection */
 
        cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password);
@@ -859,6 +864,7 @@ NTSTATUS cm_get_netlogon_cli(char *domain, unsigned char *trust_passwd,
 {
        NTSTATUS result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
        struct winbindd_cm_conn *conn;
+       uint32 neg_flags = 0x000001ff;
 
        if (!cli) {
                return NT_STATUS_INVALID_PARAMETER;
@@ -870,8 +876,7 @@ NTSTATUS cm_get_netlogon_cli(char *domain, unsigned char *trust_passwd,
                return result;
        }
        
-       result = cli_nt_setup_creds(conn->cli, (lp_server_role() == ROLE_DOMAIN_MEMBER) ?
-                                       SEC_CHAN_WKSTA : SEC_CHAN_BDC, trust_passwd);
+       result = cli_nt_setup_creds(conn->cli, get_sec_chan(), trust_passwd, &neg_flags, 2);
 
        if (!NT_STATUS_IS_OK(result)) {
                DEBUG(0, ("error connecting to domain password server: %s\n",
@@ -884,8 +889,7 @@ NTSTATUS cm_get_netlogon_cli(char *domain, unsigned char *trust_passwd,
                        }
                        
                        /* Try again */
-                       result = cli_nt_setup_creds(conn->cli, (lp_server_role() == ROLE_DOMAIN_MEMBER) ?
-                                                       SEC_CHAN_WKSTA : SEC_CHAN_BDC, trust_passwd);
+                       result = cli_nt_setup_creds( conn->cli, get_sec_chan(),trust_passwd, &neg_flags, 2);
                }
                
                if (!NT_STATUS_IS_OK(result)) {
index 9eea94e7c0d60cbeed27fe04eca6ad0d4c4a7c3d..368bf10cea5b40770a71fdf973bffb9dfe0e15a2 100644 (file)
@@ -127,6 +127,9 @@ struct winbindd_request {
                uid_t uid;           /* getpwuid, uid_to_sid */
                gid_t gid;           /* getgrgid, gid_to_sid */
                struct {
+                       /* We deliberatedly don't split into domain/user to
+                           avoid having the client know what the separator
+                           character is. */    
                        fstring user;
                        fstring pass;
                } auth;              /* pam_winbind auth module */
index a8b508a49c6b93ae4f374b460dc30a57fc0b247c..3e7a8ad97139fada6e6423df24b476a09e67846f 100644 (file)
@@ -147,7 +147,7 @@ done:
        fstrcpy(state->response.data.auth.error_string, nt_errstr(result));
        state->response.data.auth.pam_error = nt_status_to_pam(result);
 
-       DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, ("Plain-text authenticaion for user %s returned %s (PAM: %d)\n", 
+       DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, ("Plain-text authentication for user %s returned %s (PAM: %d)\n", 
              state->request.data.auth.user, 
              state->response.data.auth.nt_status_string,
              state->response.data.auth.pam_error));          
@@ -183,7 +183,7 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state)
        /* Ensure null termination */
        state->request.data.auth_crap.domain[sizeof(state->request.data.auth_crap.domain)-1]='\0';
 
-       if (!(mem_ctx = talloc_init_named("winbind pam auth crap for (utf8) %s", state->request.data.auth.user))) {
+       if (!(mem_ctx = talloc_init_named("winbind pam auth crap for (utf8) %s", state->request.data.auth_crap.user))) {
                DEBUG(0, ("winbindd_pam_auth_crap: could not talloc_init()!\n"));
                result = NT_STATUS_NO_MEMORY;
                goto done;
@@ -292,7 +292,7 @@ done:
        state->response.data.auth.pam_error = nt_status_to_pam(result);
 
        DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, 
-             ("NTLM CRAP authenticaion for user [%s]\\[%s] returned %s (PAM: %d)\n", 
+             ("NTLM CRAP authentication for user [%s]\\[%s] returned %s (PAM: %d)\n", 
               domain,
               user,
               state->response.data.auth.nt_status_string,
index 5ec34f663d8ee583020f28da821a279fa49402a5..047280e21e48bc2c31a1c7a77dc4ea19e6192401 100644 (file)
@@ -315,6 +315,7 @@ static NTSTATUS query_user(struct winbindd_domain *domain,
        cli_samr_close(hnd->cli, mem_ctx, &user_pol);
        got_user_pol = False;
 
+       user_info->user_rid = user_rid;
        user_info->group_rid = ctr->info.id21->group_rid;
        user_info->acct_name = unistr2_tdup(mem_ctx, 
                                            &ctr->info.id21->uni_user_name);
@@ -419,7 +420,7 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
         uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
         BOOL got_dom_pol = False, got_group_pol = False;
 
-       DEBUG(3,("rpc: lookup_groupmem rid=%u\n", group_rid));
+       DEBUG(10,("rpc: lookup_groupmem %s rid=%u\n", domain->name, group_rid));
 
        *num_names = 0;
 
@@ -523,7 +524,7 @@ static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
        BOOL got_dom_pol = False;
        uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED;
 
-       DEBUG(3,("rpc: sequence_number\n"));
+       DEBUG(10,("rpc: fetch sequence_number for %s\n", domain->name));
 
        *seq = DOM_SEQUENCE_NONE;
 
index daa3abb3400529179ca1fdb3f21b462df6c15bea..2016c27881ddf369a229c0fd5ff8915ad23548e0 100644 (file)
@@ -83,10 +83,16 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const
        /* We can't call domain_list() as this function is called from
           init_domain_list() and we'll get stuck in a loop. */
        for (domain = _domain_list; domain; domain = domain->next) {
-               if (strcmp(domain_name, domain->name) == 0 ||
-                   strcmp(domain_name, domain->alt_name) == 0) {
+               if (strcasecmp(domain_name, domain->name) == 0 ||
+                   strcasecmp(domain_name, domain->alt_name) == 0) {
                        return domain;
                }
+               if (alt_name && *alt_name) {
+                       if (strcasecmp(alt_name, domain->name) == 0 ||
+                           strcasecmp(alt_name, domain->alt_name) == 0) {
+                               return domain;
+                       }
+               }
        }
         
        /* Create new domain entry */
index 0f527552525c88515ecb8a715bb0f6e68c9d75ec..91eae3c7a1960712a8810a5e9b5394a6de47af5b 100644 (file)
@@ -96,6 +96,8 @@ int pam_sm_chauthtok(pam_handle_t *pamh, int flags,
     char *pass_old;
     char *pass_new;
 
+    NTSTATUS nt_status;
+
     /* Samba initialization. */
     setup_logging( "pam_smbpass", False );
     in_client = True;
@@ -124,10 +126,11 @@ int pam_sm_chauthtok(pam_handle_t *pamh, int flags,
     }
 
     /* obtain user record */
-    pdb_init_sam(&sampass);
-    pdb_getsampwnam(sampass,user);
+    if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam(&sampass))) {
+           return nt_status_to_pam(nt_status);
+    }
 
-    if (sampass == NULL) {
+    if (!pdb_getsampwnam(sampass,user)) {
         _log_err( LOG_ALERT, "Failed to find entry for user %s.", user );
         return PAM_USER_UNKNOWN;
     }
index b16f4483f842547e56bcbe629386bb7ec10d6e3d..c484439837046a5a4626f2b327113942bbf61188 100644 (file)
@@ -112,6 +112,7 @@ typedef struct
        char *szSMBPasswdFile;
        char *szPrivateDir;
        char **szPassdbBackend;
+       char **szSamBackend;
        char *szPasswordServer;
        char *szSocketOptions;
        char *szWorkGroup;
@@ -139,6 +140,7 @@ typedef struct
        char *szDelGroupScript;
        char *szAddUserToGroupScript;
        char *szDelUserFromGroupScript;
+       char *szSetPrimaryGroupScript;
        char *szAddMachineScript;
        char *szShutdownScript;
        char *szAbortShutdownScript;
@@ -171,7 +173,6 @@ typedef struct
        int max_xmit;
        int max_mux;
        int max_open_files;
-       int max_packet;
        int pwordlevel;
        int unamelevel;
        int deadtime;
@@ -206,11 +207,11 @@ typedef struct
        int iLockSpinTime;
        char *szLdapMachineSuffix;
        char *szLdapUserSuffix;
-       int ldap_port;
        int ldap_ssl;
        char *szLdapSuffix;
        char *szLdapFilter;
        char *szLdapAdminDn;
+       int ldap_passwd_sync; 
        BOOL bMsAddPrinterWizard;
        BOOL bDNSproxy;
        BOOL bWINSsupport;
@@ -231,7 +232,6 @@ typedef struct
        BOOL bReadPrediction;
        BOOL bReadbmpx;
        BOOL bSyslogOnly;
-       BOOL bAdminLog;
        BOOL bBrowseList;
        BOOL bNISHomeMap;
        BOOL bTimeServer;
@@ -335,7 +335,6 @@ typedef struct
        int iOplockContentionLimit;
        int iCSCPolicy;
        int iBlock_size;
-       BOOL bAlternatePerm;
        BOOL bPreexecClose;
        BOOL bRootpreexecClose;
        BOOL bCaseSensitive;
@@ -343,6 +342,7 @@ typedef struct
        BOOL bShortCasePreserve;
        BOOL bCaseMangle;
        BOOL bHideDotFiles;
+       BOOL bHideSpecialFiles;
        BOOL bHideUnReadable;
        BOOL bHideUnWriteableFiles;
        BOOL bBrowseable;
@@ -385,6 +385,10 @@ typedef struct
        BOOL bUseClientDriver;
        BOOL bDefaultDevmode;
        BOOL bNTAclSupport;
+#ifdef WITH_SENDFILE
+       BOOL bUseSendfile;
+#endif
+       BOOL bProfileAcls;
 
        char dummy[3];          /* for alignment */
 }
@@ -455,7 +459,6 @@ static service sDefault = {
        2,                      /* iOplockContentionLimit */
        0,                      /* iCSCPolicy */
        1024,           /* iBlock_size */
-       False,                  /* bAlternatePerm */
        False,                  /* bPreexecClose */
        False,                  /* bRootpreexecClose */
        False,                  /* case sensitive */
@@ -463,6 +466,7 @@ static service sDefault = {
        True,                   /* short case preserve */
        False,                  /* case mangle */
        True,                   /* bHideDotFiles */
+       False,                  /* bHideSpecialFiles */
        False,                  /* bHideUnReadable */
        False,                  /* bHideUnWriteableFiles */
        True,                   /* bBrowseable */
@@ -505,6 +509,10 @@ static service sDefault = {
        False,                  /* bUseClientDriver */
        False,                  /* bDefaultDevmode */
        True,                   /* bNTAclSupport */
+#ifdef WITH_SENDFILE
+       False,                  /* bUseSendfile */
+#endif
+       False,                  /* bProfileAcls */
 
        ""                      /* dummy */
 };
@@ -592,6 +600,22 @@ static struct enum_list enum_ldap_ssl[] = {
        {-1, NULL}
 };
 
+static struct enum_list enum_ldap_passwd_sync[] = {
+       {LDAP_PASSWD_SYNC_ON, "Yes"},
+       {LDAP_PASSWD_SYNC_ON, "yes"},
+       {LDAP_PASSWD_SYNC_ON, "on"},
+       {LDAP_PASSWD_SYNC_ON, "On"},
+       {LDAP_PASSWD_SYNC_OFF, "no"},
+       {LDAP_PASSWD_SYNC_OFF, "No"},
+       {LDAP_PASSWD_SYNC_OFF, "off"},
+       {LDAP_PASSWD_SYNC_OFF, "Off"},
+#ifdef LDAP_EXOP_X_MODIFY_PASSWD       
+       {LDAP_PASSWD_SYNC_ONLY, "Only"},
+       {LDAP_PASSWD_SYNC_ONLY, "only"},
+#endif /* LDAP_EXOP_X_MODIFY_PASSWD */ 
+       {-1, NULL}
+};
+
 /* Types of machine we can announce as. */
 #define ANNOUNCE_AS_NT_SERVER 1
 #define ANNOUNCE_AS_WIN95 2
@@ -666,66 +690,75 @@ static struct enum_list enum_map_to_guest[] = {
        {-1, NULL}
 };
 
-/* note that we do not initialise the defaults union - it is not allowed in ANSI C */
+/* Note: We do not initialise the defaults union - it is not allowed in ANSI C
+ *
+ * Note: We have a flag called FLAG_DEVELOPER but is not used at this time, it
+ * is implied in current control logic. This may change at some later time. A
+ * flag value of 0 means - show as development option only.
+ *
+ * The FLAG_HIDE is explicit. Paramters set this way do NOT appear in any edit
+ * screen in SWAT. This is used to exclude parameters as well as to squash all
+ * parameters that have been duplicated by pseudonyms.
+ */
 static struct parm_struct parm_table[] = {
        {"Base Options", P_SEP, P_SEPARATOR},
 
-       {"dos charset", P_STRING, P_GLOBAL, &Globals.dos_charset, NULL, NULL, 0},
-       {"unix charset", P_STRING, P_GLOBAL, &Globals.unix_charset, NULL, NULL, 0},
-       {"display charset", P_STRING, P_GLOBAL, &Globals.display_charset, NULL, NULL, 0},
-       {"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL, NULL, FLAG_BASIC | FLAG_SHARE | FLAG_PRINT},
-       {"path", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, FLAG_BASIC | FLAG_SHARE | FLAG_PRINT},
-       {"directory", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, 0},
-       {"workgroup", P_USTRING, P_GLOBAL, &Globals.szWorkGroup, NULL, NULL, FLAG_BASIC},
-       {"realm", P_USTRING, P_GLOBAL, &Globals.szRealm, NULL, NULL, FLAG_BASIC},
-       {"ADS server", P_STRING, P_GLOBAL, &Globals.szADSserver, NULL, NULL, FLAG_BASIC},
-       {"netbios name", P_UGSTRING, P_GLOBAL, global_myname, handle_netbios_name, NULL, FLAG_BASIC},
-       {"netbios aliases", P_LIST, P_GLOBAL, &Globals.szNetbiosAliases, NULL, NULL, 0},
-       {"netbios scope", P_UGSTRING, P_GLOBAL, global_scope, NULL, NULL, 0},
-       {"server string", P_STRING, P_GLOBAL, &Globals.szServerString, NULL, NULL, FLAG_BASIC },
-       {"interfaces", P_LIST, P_GLOBAL, &Globals.szInterfaces, NULL, NULL, FLAG_BASIC},
-       {"bind interfaces only", P_BOOL, P_GLOBAL, &Globals.bBindInterfacesOnly, NULL, NULL, 0},
+       {"dos charset", P_STRING, P_GLOBAL, &Globals.dos_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"unix charset", P_STRING, P_GLOBAL, &Globals.unix_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"display charset", P_STRING, P_GLOBAL, &Globals.display_charset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
+       {"path", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
+       {"directory", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, FLAG_HIDE},
+       {"workgroup", P_USTRING, P_GLOBAL, &Globals.szWorkGroup, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
+       {"realm", P_USTRING, P_GLOBAL, &Globals.szRealm, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
+       {"ADS server", P_STRING, P_GLOBAL, &Globals.szADSserver, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
+       {"netbios name", P_UGSTRING, P_GLOBAL, global_myname, handle_netbios_name, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
+       {"netbios aliases", P_LIST, P_GLOBAL, &Globals.szNetbiosAliases, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
+       {"netbios scope", P_UGSTRING, P_GLOBAL, global_scope, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"server string", P_STRING, P_GLOBAL, &Globals.szServerString, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED  | FLAG_DEVELOPER},
+       {"interfaces", P_LIST, P_GLOBAL, &Globals.szInterfaces, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
+       {"bind interfaces only", P_BOOL, P_GLOBAL, &Globals.bBindInterfacesOnly, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
 
        {"Security Options", P_SEP, P_SEPARATOR},
        
-       {"security", P_ENUM, P_GLOBAL, &Globals.security, NULL, enum_security, FLAG_BASIC},
-       {"auth methods", P_LIST, P_GLOBAL, &Globals.AuthMethods, NULL, NULL, FLAG_BASIC},
-       {"encrypt passwords", P_BOOL, P_GLOBAL, &Globals.bEncryptPasswords, NULL, NULL, FLAG_BASIC},
-       {"update encrypted", P_BOOL, P_GLOBAL, &Globals.bUpdateEncrypt, NULL, NULL, FLAG_BASIC},
-       {"allow trusted domains", P_BOOL, P_GLOBAL, &Globals.bAllowTrustedDomains, NULL, NULL, 0},
-       {"alternate permissions", P_BOOL, P_LOCAL, &sDefault.bAlternatePerm, NULL, NULL, FLAG_GLOBAL | FLAG_DEPRECATED},
-       {"hosts equiv", P_STRING, P_GLOBAL, &Globals.szHostsEquiv, NULL, NULL, 0},
-       {"min passwd length", P_INTEGER, P_GLOBAL, &Globals.min_passwd_length, NULL, NULL, 0},
-       {"min password length", P_INTEGER, P_GLOBAL, &Globals.min_passwd_length, NULL, NULL, 0},
-       {"map to guest", P_ENUM, P_GLOBAL, &Globals.map_to_guest, NULL, enum_map_to_guest, 0},
-       {"null passwords", P_BOOL, P_GLOBAL, &Globals.bNullPasswords, NULL, NULL, 0},
-       {"obey pam restrictions", P_BOOL, P_GLOBAL, &Globals.bObeyPamRestrictions, NULL, NULL, 0},
-       {"password server", P_STRING, P_GLOBAL, &Globals.szPasswordServer, NULL, NULL, 0},
-       {"smb passwd file", P_STRING, P_GLOBAL, &Globals.szSMBPasswdFile, NULL, NULL, 0},
-       {"private dir", P_STRING, P_GLOBAL, &Globals.szPrivateDir, NULL, NULL, 0},
-       {"passdb backend", P_LIST, P_GLOBAL, &Globals.szPassdbBackend, NULL, NULL, 0},
-       {"non unix account range", P_STRING, P_GLOBAL, &Globals.szNonUnixAccountRange, handle_non_unix_account_range, NULL, 0},
-       {"algorithmic rid base", P_INTEGER, P_GLOBAL, &Globals.bAlgorithmicRidBase, NULL, NULL, 0},
-       {"root directory", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL, NULL, 0},
-       {"root dir", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL, NULL, 0},
-       {"root", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL, NULL, 0},
-       {"guest account", P_STRING, P_GLOBAL, &Globals.szGuestaccount, NULL, NULL, FLAG_BASIC},
+       {"security", P_ENUM, P_GLOBAL, &Globals.security, NULL, enum_security, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
+       {"auth methods", P_LIST, P_GLOBAL, &Globals.AuthMethods, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
+       {"encrypt passwords", P_BOOL, P_GLOBAL, &Globals.bEncryptPasswords, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
+       {"update encrypted", P_BOOL, P_GLOBAL, &Globals.bUpdateEncrypt, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"allow trusted domains", P_BOOL, P_GLOBAL, &Globals.bAllowTrustedDomains, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"hosts equiv", P_STRING, P_GLOBAL, &Globals.szHostsEquiv, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"min passwd length", P_INTEGER, P_GLOBAL, &Globals.min_passwd_length, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"min password length", P_INTEGER, P_GLOBAL, &Globals.min_passwd_length, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"map to guest", P_ENUM, P_GLOBAL, &Globals.map_to_guest, NULL, enum_map_to_guest, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"null passwords", P_BOOL, P_GLOBAL, &Globals.bNullPasswords, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"obey pam restrictions", P_BOOL, P_GLOBAL, &Globals.bObeyPamRestrictions, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"password server", P_STRING, P_GLOBAL, &Globals.szPasswordServer, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
+       {"smb passwd file", P_STRING, P_GLOBAL, &Globals.szSMBPasswdFile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"private dir", P_STRING, P_GLOBAL, &Globals.szPrivateDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"passdb backend", P_LIST, P_GLOBAL, &Globals.szPassdbBackend, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"sam backend", P_LIST, P_GLOBAL, &Globals.szSamBackend, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"non unix account range", P_STRING, P_GLOBAL, &Globals.szNonUnixAccountRange, handle_non_unix_account_range, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"algorithmic rid base", P_INTEGER, P_GLOBAL, &Globals.bAlgorithmicRidBase, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"root directory", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"root dir", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"root", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL, NULL, FLAG_HIDE | FLAG_DEVELOPER},
+       {"guest account", P_STRING, P_GLOBAL, &Globals.szGuestaccount, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
        
-       {"pam password change", P_BOOL, P_GLOBAL, &Globals.bPamPasswordChange, NULL, NULL, 0},
-       {"passwd program", P_STRING, P_GLOBAL, &Globals.szPasswdProgram, NULL, NULL, 0},
-       {"passwd chat", P_STRING, P_GLOBAL, &Globals.szPasswdChat, NULL, NULL, 0},
-       {"passwd chat debug", P_BOOL, P_GLOBAL, &Globals.bPasswdChatDebug, NULL, NULL, 0},
-       {"username map", P_STRING, P_GLOBAL, &Globals.szUsernameMap, NULL, NULL, 0},
-       {"password level", P_INTEGER, P_GLOBAL, &Globals.pwordlevel, NULL, NULL, 0},
-       {"username level", P_INTEGER, P_GLOBAL, &Globals.unamelevel, NULL, NULL, 0},
-       {"unix password sync", P_BOOL, P_GLOBAL, &Globals.bUnixPasswdSync, NULL, NULL, 0},
-       {"restrict anonymous", P_INTEGER, P_GLOBAL, &Globals.restrict_anonymous, NULL, NULL, 0},
-       {"lanman auth", P_BOOL, P_GLOBAL, &Globals.bLanmanAuth, NULL, NULL, 0},
-       {"ntlm auth", P_BOOL, P_GLOBAL, &Globals.bNTLMAuth, NULL, NULL, 0},
+       {"pam password change", P_BOOL, P_GLOBAL, &Globals.bPamPasswordChange, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"passwd program", P_STRING, P_GLOBAL, &Globals.szPasswdProgram, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"passwd chat", P_STRING, P_GLOBAL, &Globals.szPasswdChat, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"passwd chat debug", P_BOOL, P_GLOBAL, &Globals.bPasswdChatDebug, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"username map", P_STRING, P_GLOBAL, &Globals.szUsernameMap, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER | FLAG_DEVELOPER},
+       {"password level", P_INTEGER, P_GLOBAL, &Globals.pwordlevel, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"username level", P_INTEGER, P_GLOBAL, &Globals.unamelevel, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"unix password sync", P_BOOL, P_GLOBAL, &Globals.bUnixPasswdSync, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"restrict anonymous", P_INTEGER, P_GLOBAL, &Globals.restrict_anonymous, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"lanman auth", P_BOOL, P_GLOBAL, &Globals.bLanmanAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"ntlm auth", P_BOOL, P_GLOBAL, &Globals.bNTLMAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
        
        {"username", P_STRING, P_LOCAL, &sDefault.szUsername, NULL, NULL, FLAG_GLOBAL | FLAG_SHARE},
-       {"user", P_STRING, P_LOCAL, &sDefault.szUsername, NULL, NULL, 0},
-       {"users", P_STRING, P_LOCAL, &sDefault.szUsername, NULL, NULL, 0},
+       {"user", P_STRING, P_LOCAL, &sDefault.szUsername, NULL, NULL, FLAG_HIDE},
+       {"users", P_STRING, P_LOCAL, &sDefault.szUsername, NULL, NULL, FLAG_HIDE},
        
        {"invalid users", P_LIST, P_LOCAL, &sDefault.szInvalidUsers, NULL, NULL, FLAG_GLOBAL | FLAG_SHARE},
        {"valid users", P_LIST, P_LOCAL, &sDefault.szValidUsers, NULL, NULL, FLAG_GLOBAL | FLAG_SHARE},
@@ -735,12 +768,12 @@ static struct parm_struct parm_table[] = {
        {"printer admin", P_LIST, P_LOCAL, &sDefault.printer_admin, NULL, NULL, FLAG_GLOBAL | FLAG_PRINT},
        {"force user", P_STRING, P_LOCAL, &sDefault.force_user, NULL, NULL, FLAG_SHARE},
        {"force group", P_STRING, P_LOCAL, &sDefault.force_group, NULL, NULL, FLAG_SHARE},
-       {"group", P_STRING, P_LOCAL, &sDefault.force_group, NULL, NULL, 0},
+       {"group", P_STRING, P_LOCAL, &sDefault.force_group, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
        
-       {"read only", P_BOOL, P_LOCAL, &sDefault.bRead_only, NULL, NULL, FLAG_BASIC | FLAG_SHARE},
-       {"write ok", P_BOOLREV, P_LOCAL, &sDefault.bRead_only, NULL, NULL, 0},
-       {"writeable", P_BOOLREV, P_LOCAL, &sDefault.bRead_only, NULL, NULL, 0},
-       {"writable", P_BOOLREV, P_LOCAL, &sDefault.bRead_only, NULL, NULL, 0},
+       {"read only", P_BOOL, P_LOCAL, &sDefault.bRead_only, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE},
+       {"write ok", P_BOOLREV, P_LOCAL, &sDefault.bRead_only, NULL, NULL, FLAG_HIDE},
+       {"writeable", P_BOOLREV, P_LOCAL, &sDefault.bRead_only, NULL, NULL, FLAG_HIDE},
+       {"writable", P_BOOLREV, P_LOCAL, &sDefault.bRead_only, NULL, NULL, FLAG_HIDE},
        
        {"create mask", P_OCTAL, P_LOCAL, &sDefault.iCreate_mask, NULL, NULL, FLAG_GLOBAL | FLAG_SHARE},
        {"create mode", P_OCTAL, P_LOCAL, &sDefault.iCreate_mask, NULL, NULL, FLAG_GLOBAL},
@@ -755,101 +788,103 @@ static struct parm_struct parm_table[] = {
        {"inherit permissions", P_BOOL, P_LOCAL, &sDefault.bInheritPerms, NULL, NULL, FLAG_SHARE},
        {"inherit acls", P_BOOL, P_LOCAL, &sDefault.bInheritACLS, NULL, NULL, FLAG_SHARE},
        {"guest only", P_BOOL, P_LOCAL, &sDefault.bGuest_only, NULL, NULL, FLAG_SHARE},
-       {"only guest", P_BOOL, P_LOCAL, &sDefault.bGuest_only, NULL, NULL, 0},
+       {"only guest", P_BOOL, P_LOCAL, &sDefault.bGuest_only, NULL, NULL, FLAG_HIDE},
 
-       {"guest ok", P_BOOL, P_LOCAL, &sDefault.bGuest_ok, NULL, NULL, FLAG_BASIC | FLAG_SHARE | FLAG_PRINT},
-       {"public", P_BOOL, P_LOCAL, &sDefault.bGuest_ok, NULL, NULL, 0},
+       {"guest ok", P_BOOL, P_LOCAL, &sDefault.bGuest_ok, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
+       {"public", P_BOOL, P_LOCAL, &sDefault.bGuest_ok, NULL, NULL, FLAG_HIDE},
        
        {"only user", P_BOOL, P_LOCAL, &sDefault.bOnlyUser, NULL, NULL, FLAG_SHARE},
-       {"hosts allow", P_LIST, P_LOCAL, &sDefault.szHostsallow, NULL, NULL, FLAG_GLOBAL | FLAG_BASIC | FLAG_SHARE | FLAG_PRINT},
-       {"allow hosts", P_LIST, P_LOCAL, &sDefault.szHostsallow, NULL, NULL, 0},
-       {"hosts deny", P_LIST, P_LOCAL, &sDefault.szHostsdeny, NULL, NULL, FLAG_GLOBAL | FLAG_BASIC | FLAG_SHARE | FLAG_PRINT},
-       {"deny hosts", P_LIST, P_LOCAL, &sDefault.szHostsdeny, NULL, NULL, 0},
+       {"hosts allow", P_LIST, P_LOCAL, &sDefault.szHostsallow, NULL, NULL, FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
+       {"allow hosts", P_LIST, P_LOCAL, &sDefault.szHostsallow, NULL, NULL, FLAG_HIDE},
+       {"hosts deny", P_LIST, P_LOCAL, &sDefault.szHostsdeny, NULL, NULL, FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
+       {"deny hosts", P_LIST, P_LOCAL, &sDefault.szHostsdeny, NULL, NULL, FLAG_HIDE},
 
        {"Logging Options", P_SEP, P_SEPARATOR},
 
-       {"admin log", P_BOOL, P_GLOBAL, &Globals.bAdminLog, NULL, NULL, 0},
-       {"log level", P_STRING, P_GLOBAL, &Globals.szLogLevel, handle_debug_list, NULL, 0},
-       {"debuglevel", P_STRING, P_GLOBAL, &Globals.szLogLevel, handle_debug_list, NULL, 0},
-       {"syslog", P_INTEGER, P_GLOBAL, &Globals.syslog, NULL, NULL, 0},
-       {"syslog only", P_BOOL, P_GLOBAL, &Globals.bSyslogOnly, NULL, NULL, 0},
-       {"log file", P_STRING, P_GLOBAL, &Globals.szLogFile, NULL, NULL, 0},
+       {"log level", P_STRING, P_GLOBAL, &Globals.szLogLevel, handle_debug_list, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"debuglevel", P_STRING, P_GLOBAL, &Globals.szLogLevel, handle_debug_list, NULL, FLAG_HIDE},
+       {"syslog", P_INTEGER, P_GLOBAL, &Globals.syslog, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"syslog only", P_BOOL, P_GLOBAL, &Globals.bSyslogOnly, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"log file", P_STRING, P_GLOBAL, &Globals.szLogFile, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
        
-       {"max log size", P_INTEGER, P_GLOBAL, &Globals.max_log_size, NULL, NULL, 0},
-       {"timestamp logs", P_BOOL, P_GLOBAL, &Globals.bTimestampLogs, NULL, NULL, 0},
-       {"debug timestamp", P_BOOL, P_GLOBAL, &Globals.bTimestampLogs, NULL, NULL, 0},
-       {"debug hires timestamp", P_BOOL, P_GLOBAL, &Globals.bDebugHiresTimestamp, NULL, NULL, 0},
-       {"debug pid", P_BOOL, P_GLOBAL, &Globals.bDebugPid, NULL, NULL, 0},
-       {"debug uid", P_BOOL, P_GLOBAL, &Globals.bDebugUid, NULL, NULL, 0},
+       {"max log size", P_INTEGER, P_GLOBAL, &Globals.max_log_size, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"timestamp logs", P_BOOL, P_GLOBAL, &Globals.bTimestampLogs, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"debug timestamp", P_BOOL, P_GLOBAL, &Globals.bTimestampLogs, NULL, NULL, FLAG_DEVELOPER},
+       {"debug hires timestamp", P_BOOL, P_GLOBAL, &Globals.bDebugHiresTimestamp, NULL, NULL, FLAG_DEVELOPER},
+       {"debug pid", P_BOOL, P_GLOBAL, &Globals.bDebugPid, NULL, NULL, FLAG_DEVELOPER},
+       {"debug uid", P_BOOL, P_GLOBAL, &Globals.bDebugUid, NULL, NULL, FLAG_DEVELOPER},
        
        {"Protocol Options", P_SEP, P_SEPARATOR},
        
-       {"smb ports", P_STRING, P_GLOBAL, &Globals.smb_ports, NULL, NULL, 0},
-       {"protocol", P_ENUM, P_GLOBAL, &Globals.maxprotocol, NULL, enum_protocol, 0},
-       {"large readwrite", P_BOOL, P_GLOBAL, &Globals.bLargeReadwrite, NULL, NULL, 0},
-       {"max protocol", P_ENUM, P_GLOBAL, &Globals.maxprotocol, NULL, enum_protocol, 0},
-       {"min protocol", P_ENUM, P_GLOBAL, &Globals.minprotocol, NULL, enum_protocol, 0},
-       {"unicode", P_BOOL, P_GLOBAL, &Globals.bUnicode, NULL, NULL, 0},
-       {"read bmpx", P_BOOL, P_GLOBAL, &Globals.bReadbmpx, NULL, NULL, 0},
-       {"read raw", P_BOOL, P_GLOBAL, &Globals.bReadRaw, NULL, NULL, 0},
-       {"write raw", P_BOOL, P_GLOBAL, &Globals.bWriteRaw, NULL, NULL, 0},
-       {"disable netbios", P_BOOL, P_GLOBAL, &Globals.bDisableNetbios, NULL, NULL, 0},
+       {"smb ports", P_STRING, P_GLOBAL, &Globals.smb_ports, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"protocol", P_ENUM, P_GLOBAL, &Globals.maxprotocol, NULL, enum_protocol, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"large readwrite", P_BOOL, P_GLOBAL, &Globals.bLargeReadwrite, NULL, NULL, FLAG_DEVELOPER},
+       {"max protocol", P_ENUM, P_GLOBAL, &Globals.maxprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
+       {"min protocol", P_ENUM, P_GLOBAL, &Globals.minprotocol, NULL, enum_protocol, FLAG_DEVELOPER},
+       {"unicode", P_BOOL, P_GLOBAL, &Globals.bUnicode, NULL, NULL, FLAG_DEVELOPER},
+       {"read bmpx", P_BOOL, P_GLOBAL, &Globals.bReadbmpx, NULL, NULL, FLAG_DEVELOPER},
+       {"read raw", P_BOOL, P_GLOBAL, &Globals.bReadRaw, NULL, NULL, FLAG_DEVELOPER},
+       {"write raw", P_BOOL, P_GLOBAL, &Globals.bWriteRaw, NULL, NULL, FLAG_DEVELOPER},
+       {"disable netbios", P_BOOL, P_GLOBAL, &Globals.bDisableNetbios, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       
+       {"nt pipe support", P_BOOL, P_GLOBAL, &Globals.bNTPipeSupport, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"nt acl support", P_BOOL,  P_LOCAL, &sDefault.bNTAclSupport, NULL, NULL, FLAG_GLOBAL | FLAG_SHARE  | FLAG_ADVANCED | FLAG_WIZARD},
+       {"nt status support", P_BOOL, P_GLOBAL, &Globals.bNTStatusSupport, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"profile acls", P_BOOL,  P_LOCAL, &sDefault.bProfileAcls, NULL, NULL, FLAG_GLOBAL | FLAG_SHARE  | FLAG_ADVANCED | FLAG_WIZARD},
        
-       {"nt pipe support", P_BOOL, P_GLOBAL, &Globals.bNTPipeSupport, NULL, NULL, 0},
-       {"nt acl support", P_BOOL,  P_LOCAL, &sDefault.bNTAclSupport, NULL, NULL, FLAG_GLOBAL | FLAG_SHARE },
-       {"nt status support", P_BOOL, P_GLOBAL, &Globals.bNTStatusSupport, NULL, NULL, 0},
-       {"announce version", P_STRING, P_GLOBAL, &Globals.szAnnounceVersion, NULL, NULL, 0},
-       {"announce as", P_ENUM, P_GLOBAL, &Globals.announce_as, NULL, enum_announce_as, 0},
-       {"max mux", P_INTEGER, P_GLOBAL, &Globals.max_mux, NULL, NULL, 0},
-       {"max xmit", P_INTEGER, P_GLOBAL, &Globals.max_xmit, NULL, NULL, 0},
+       {"announce version", P_STRING, P_GLOBAL, &Globals.szAnnounceVersion, NULL, NULL, FLAG_DEVELOPER},
+       {"announce as", P_ENUM, P_GLOBAL, &Globals.announce_as, NULL, enum_announce_as, FLAG_DEVELOPER},
+       {"max mux", P_INTEGER, P_GLOBAL, &Globals.max_mux, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"max xmit", P_INTEGER, P_GLOBAL, &Globals.max_xmit, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
        
-       {"name resolve order", P_STRING, P_GLOBAL, &Globals.szNameResolveOrder, NULL, NULL, 0},
-       {"max packet", P_INTEGER, P_GLOBAL, &Globals.max_packet, NULL, NULL, 0},
-       {"packet size", P_INTEGER, P_GLOBAL, &Globals.max_packet, NULL, NULL, 0},
-       {"max ttl", P_INTEGER, P_GLOBAL, &Globals.max_ttl, NULL, NULL, 0}, 
-       {"max wins ttl", P_INTEGER, P_GLOBAL, &Globals.max_wins_ttl, NULL, NULL, 0},
-       {"min wins ttl", P_INTEGER, P_GLOBAL, &Globals.min_wins_ttl, NULL, NULL, 0},
-       {"time server", P_BOOL, P_GLOBAL, &Globals.bTimeServer, NULL, NULL, 0},
-       {"unix extensions", P_BOOL, P_GLOBAL, &Globals.bUnixExtensions, NULL, NULL, 0},
-       {"use spnego", P_BOOL, P_GLOBAL, &Globals.bUseSpnego, NULL, NULL, 0},
+       {"name resolve order", P_STRING, P_GLOBAL, &Globals.szNameResolveOrder, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
+       {"max ttl", P_INTEGER, P_GLOBAL, &Globals.max_ttl, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, 
+       {"max wins ttl", P_INTEGER, P_GLOBAL, &Globals.max_wins_ttl, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"min wins ttl", P_INTEGER, P_GLOBAL, &Globals.min_wins_ttl, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"time server", P_BOOL, P_GLOBAL, &Globals.bTimeServer, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"unix extensions", P_BOOL, P_GLOBAL, &Globals.bUnixExtensions, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"use spnego", P_BOOL, P_GLOBAL, &Globals.bUseSpnego, NULL, NULL, FLAG_DEVELOPER},
 
        {"Tuning Options", P_SEP, P_SEPARATOR},
        
        {"block size", P_INTEGER, P_LOCAL, &sDefault.iBlock_size, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
-       {"change notify timeout", P_INTEGER, P_GLOBAL, &Globals.change_notify_timeout, NULL, NULL, 0},
-       {"deadtime", P_INTEGER, P_GLOBAL, &Globals.deadtime, NULL, NULL, 0},
-       {"getwd cache", P_BOOL, P_GLOBAL, &use_getwd_cache, NULL, NULL, 0},
-       {"keepalive", P_INTEGER, P_GLOBAL, &keepalive, NULL, NULL, 0},
+       {"change notify timeout", P_INTEGER, P_GLOBAL, &Globals.change_notify_timeout, NULL, NULL, FLAG_DEVELOPER},
+       {"deadtime", P_INTEGER, P_GLOBAL, &Globals.deadtime, NULL, NULL, FLAG_DEVELOPER},
+       {"getwd cache", P_BOOL, P_GLOBAL, &use_getwd_cache, NULL, NULL, FLAG_DEVELOPER},
+       {"keepalive", P_INTEGER, P_GLOBAL, &keepalive, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
        
-       {"lpq cache time", P_INTEGER, P_GLOBAL, &Globals.lpqcachetime, NULL, NULL, 0},
-       {"max smbd processes", P_INTEGER, P_GLOBAL, &Globals.iMaxSmbdProcesses, NULL, NULL, 0},
+       {"lpq cache time", P_INTEGER, P_GLOBAL, &Globals.lpqcachetime, NULL, NULL, FLAG_DEVELOPER},
+       {"max smbd processes", P_INTEGER, P_GLOBAL, &Globals.iMaxSmbdProcesses, NULL, NULL, FLAG_DEVELOPER},
        {"max connections", P_INTEGER, P_LOCAL, &sDefault.iMaxConnections, NULL, NULL, FLAG_SHARE},
-       {"paranoid server security", P_BOOL, P_GLOBAL, &Globals.paranoid_server_security, NULL, NULL, 0},
-       {"max disk size", P_INTEGER, P_GLOBAL, &Globals.maxdisksize, NULL, NULL, 0},
-       {"max open files", P_INTEGER, P_GLOBAL, &Globals.max_open_files, NULL, NULL, 0},
+       {"paranoid server security", P_BOOL, P_GLOBAL, &Globals.paranoid_server_security, NULL, NULL, FLAG_DEVELOPER},
+       {"max disk size", P_INTEGER, P_GLOBAL, &Globals.maxdisksize, NULL, NULL, FLAG_DEVELOPER},
+       {"max open files", P_INTEGER, P_GLOBAL, &Globals.max_open_files, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
        {"min print space", P_INTEGER, P_LOCAL, &sDefault.iMinPrintSpace, NULL, NULL, FLAG_PRINT},
-       {"read size", P_INTEGER, P_GLOBAL, &Globals.ReadSize, NULL, NULL, 0},
+       {"read size", P_INTEGER, P_GLOBAL, &Globals.ReadSize, NULL, NULL, FLAG_DEVELOPER},
        
-       {"socket options", P_GSTRING, P_GLOBAL, user_socket_options, NULL, NULL, 0},
-       {"stat cache size", P_INTEGER, P_GLOBAL, &Globals.stat_cache_size, NULL, NULL, 0},
+       {"socket options", P_GSTRING, P_GLOBAL, user_socket_options, NULL, NULL, FLAG_DEVELOPER},
+       {"stat cache size", P_INTEGER, P_GLOBAL, &Globals.stat_cache_size, NULL, NULL, FLAG_DEVELOPER},
        {"strict allocate", P_BOOL, P_LOCAL, &sDefault.bStrictAllocate, NULL, NULL, FLAG_SHARE},
        {"strict sync", P_BOOL, P_LOCAL, &sDefault.bStrictSync, NULL, NULL, FLAG_SHARE},
        {"sync always", P_BOOL, P_LOCAL, &sDefault.bSyncAlways, NULL, NULL, FLAG_SHARE},
-       {"use mmap", P_BOOL, P_GLOBAL, &Globals.bUseMmap, NULL, NULL, 0},
-       {"hostname lookups", P_BOOL, P_GLOBAL, &Globals.bHostnameLookups, NULL, NULL, 0},
+       {"use mmap", P_BOOL, P_GLOBAL, &Globals.bUseMmap, NULL, NULL, FLAG_DEVELOPER},
+#ifdef WITH_SENDFILE
+       {"use sendfile", P_BOOL, P_LOCAL, &sDefault.bUseSendfile, NULL, NULL, FLAG_SHARE},
+#endif
+       {"hostname lookups", P_BOOL, P_GLOBAL, &Globals.bHostnameLookups, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
        {"write cache size", P_INTEGER, P_LOCAL, &sDefault.iWriteCacheSize, NULL, NULL, FLAG_SHARE},
 
-       {"name cache timeout", P_INTEGER, P_GLOBAL, &Globals.name_cache_timeout, NULL, NULL, 0},
+       {"name cache timeout", P_INTEGER, P_GLOBAL, &Globals.name_cache_timeout, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
 
        {"Printing Options", P_SEP, P_SEPARATOR},
        
        {"total print jobs", P_INTEGER, P_GLOBAL, &Globals.iTotalPrintJobs, NULL, NULL, FLAG_PRINT},
        {"max print jobs", P_INTEGER, P_LOCAL, &sDefault.iMaxPrintJobs, NULL, NULL, FLAG_PRINT},
        {"load printers", P_BOOL, P_GLOBAL, &Globals.bLoadPrinters, NULL, NULL, FLAG_PRINT},
-       {"printcap name", P_STRING, P_GLOBAL, &Globals.szPrintcapname, NULL, NULL, FLAG_PRINT},
-       {"printcap", P_STRING, P_GLOBAL, &Globals.szPrintcapname, NULL, NULL, 0},
+       {"printcap name", P_STRING, P_GLOBAL, &Globals.szPrintcapname, NULL, NULL, FLAG_PRINT | FLAG_DEVELOPER},
+       {"printcap", P_STRING, P_GLOBAL, &Globals.szPrintcapname, NULL, NULL, FLAG_HIDE},
        {"printable", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL, NULL, FLAG_PRINT},
-       {"print ok", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL, NULL, 0},
+       {"print ok", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL, NULL, FLAG_HIDE},
        {"postscript", P_BOOL, P_LOCAL, &sDefault.bPostscript, NULL, NULL, FLAG_PRINT | FLAG_DEPRECATED},
        {"printing", P_ENUM, P_LOCAL, &sDefault.iPrinting, NULL, enum_printing, FLAG_PRINT | FLAG_GLOBAL},
        {"print command", P_STRING, P_LOCAL, &sDefault.szPrintcommand, NULL, NULL, FLAG_PRINT | FLAG_GLOBAL},
@@ -861,14 +896,14 @@ static struct parm_struct parm_table[] = {
        {"queuepause command", P_STRING, P_LOCAL, &sDefault.szQueuepausecommand, NULL, NULL, FLAG_PRINT | FLAG_GLOBAL},
        {"queueresume command", P_STRING, P_LOCAL, &sDefault.szQueueresumecommand, NULL, NULL, FLAG_PRINT | FLAG_GLOBAL},
 
-       {"enumports command", P_STRING, P_GLOBAL, &Globals.szEnumPortsCommand, NULL, NULL, 0},
-       {"addprinter command", P_STRING, P_GLOBAL, &Globals.szAddPrinterCommand, NULL, NULL, 0},
-       {"deleteprinter command", P_STRING, P_GLOBAL, &Globals.szDeletePrinterCommand, NULL, NULL, 0},
-       {"show add printer wizard", P_BOOL, P_GLOBAL, &Globals.bMsAddPrinterWizard, NULL, NULL, 0},
-       {"os2 driver map", P_STRING, P_GLOBAL, &Globals.szOs2DriverMap, NULL, NULL, 0},
+       {"enumports command", P_STRING, P_GLOBAL, &Globals.szEnumPortsCommand, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"addprinter command", P_STRING, P_GLOBAL, &Globals.szAddPrinterCommand, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"deleteprinter command", P_STRING, P_GLOBAL, &Globals.szDeletePrinterCommand, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"show add printer wizard", P_BOOL, P_GLOBAL, &Globals.bMsAddPrinterWizard, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"os2 driver map", P_STRING, P_GLOBAL, &Globals.szOs2DriverMap, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
        
        {"printer name", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL, NULL, FLAG_PRINT},
-       {"printer", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL, NULL, 0},
+       {"printer", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL, NULL, FLAG_HIDE},
        {"use client driver", P_BOOL, P_LOCAL, &sDefault.bUseClientDriver, NULL, NULL, FLAG_PRINT},
        {"default devmode", P_BOOL, P_LOCAL, &sDefault.bDefaultDevmode, NULL, NULL, FLAG_PRINT},
        {"printer driver", P_STRING, P_LOCAL, &sDefault.szPrinterDriver, NULL, NULL, FLAG_PRINT | FLAG_DEPRECATED},
@@ -876,18 +911,19 @@ static struct parm_struct parm_table[] = {
        {"printer driver location", P_STRING, P_LOCAL, &sDefault.szPrinterDriverLocation, NULL, NULL, FLAG_PRINT | FLAG_GLOBAL | FLAG_DEPRECATED},
 
        {"Filename Handling", P_SEP, P_SEPARATOR},
-       {"strip dot", P_BOOL, P_GLOBAL, &Globals.bStripDot, NULL, NULL, 0},
-       {"mangling method", P_STRING, P_GLOBAL, &Globals.szManglingMethod, NULL, NULL, 0},
+       {"strip dot", P_BOOL, P_GLOBAL, &Globals.bStripDot, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"mangling method", P_STRING, P_GLOBAL, &Globals.szManglingMethod, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
        
-       {"mangled stack", P_INTEGER, P_GLOBAL, &Globals.mangled_stack, NULL, NULL, 0},
+       {"mangled stack", P_INTEGER, P_GLOBAL, &Globals.mangled_stack, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
        {"default case", P_ENUM, P_LOCAL, &sDefault.iDefaultCase, NULL, enum_case, FLAG_SHARE},
        {"case sensitive", P_BOOL, P_LOCAL, &sDefault.bCaseSensitive, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
-       {"casesignames", P_BOOL, P_LOCAL, &sDefault.bCaseSensitive, NULL, NULL, 0},
+       {"casesignames", P_BOOL, P_LOCAL, &sDefault.bCaseSensitive, NULL, NULL, FLAG_HIDE},
        {"preserve case", P_BOOL, P_LOCAL, &sDefault.bCasePreserve, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
        {"short preserve case", P_BOOL, P_LOCAL, &sDefault.bShortCasePreserve, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
        {"mangle case", P_BOOL, P_LOCAL, &sDefault.bCaseMangle, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
        {"mangling char", P_CHAR, P_LOCAL, &sDefault.magic_char, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
        {"hide dot files", P_BOOL, P_LOCAL, &sDefault.bHideDotFiles, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
+       {"hide special files", P_BOOL, P_LOCAL, &sDefault.bHideSpecialFiles, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
        {"hide unreadable", P_BOOL, P_LOCAL, &sDefault.bHideUnReadable, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
        {"hide unwriteable files", P_BOOL, P_LOCAL, &sDefault.bHideUnWriteableFiles, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
        {"delete veto files", P_BOOL, P_LOCAL, &sDefault.bDeleteVetoFiles, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
@@ -899,52 +935,53 @@ static struct parm_struct parm_table[] = {
        {"map archive", P_BOOL, P_LOCAL, &sDefault.bMap_archive, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
        {"mangled names", P_BOOL, P_LOCAL, &sDefault.bMangledNames, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
        {"mangled map", P_STRING, P_LOCAL, &sDefault.szMangledMap, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
-       {"stat cache", P_BOOL, P_GLOBAL, &Globals.bStatCache, NULL, NULL, 0},
+       {"stat cache", P_BOOL, P_GLOBAL, &Globals.bStatCache, NULL, NULL, FLAG_DEVELOPER},
 
        {"Domain Options", P_SEP, P_SEPARATOR},
        
-       {"machine password timeout", P_INTEGER, P_GLOBAL, &Globals.machine_password_timeout, NULL, NULL, 0},
+       {"machine password timeout", P_INTEGER, P_GLOBAL, &Globals.machine_password_timeout, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
 
        {"Logon Options", P_SEP, P_SEPARATOR},
 
-       {"add user script", P_STRING, P_GLOBAL, &Globals.szAddUserScript, NULL, NULL, 0},
-       {"delete user script", P_STRING, P_GLOBAL, &Globals.szDelUserScript, NULL, NULL, 0},
-       {"add group script", P_STRING, P_GLOBAL, &Globals.szAddGroupScript, NULL, NULL, 0},
-       {"delete group script", P_STRING, P_GLOBAL, &Globals.szDelGroupScript, NULL, NULL, 0},
-       {"add user to group script", P_STRING, P_GLOBAL, &Globals.szAddUserToGroupScript, NULL, NULL, 0},
-       {"delete user from group script", P_STRING, P_GLOBAL, &Globals.szDelUserFromGroupScript, NULL, NULL, 0},
-       {"add machine script", P_STRING, P_GLOBAL, &Globals.szAddMachineScript, NULL, NULL, 0},
-       {"shutdown script", P_STRING, P_GLOBAL, &Globals.szShutdownScript, NULL, NULL, 0},
-       {"abort shutdown script", P_STRING, P_GLOBAL, &Globals.szAbortShutdownScript, NULL, NULL, 0},
-
-       {"logon script", P_STRING, P_GLOBAL, &Globals.szLogonScript, NULL, NULL, 0},
-       {"logon path", P_STRING, P_GLOBAL, &Globals.szLogonPath, NULL, NULL, 0},
-       {"logon drive", P_STRING, P_GLOBAL, &Globals.szLogonDrive, NULL, NULL, 0},
-       {"logon home", P_STRING, P_GLOBAL, &Globals.szLogonHome, NULL, NULL, 0},
-       {"domain logons", P_BOOL, P_GLOBAL, &Globals.bDomainLogons, NULL, NULL, 0},
+       {"add user script", P_STRING, P_GLOBAL, &Globals.szAddUserScript, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"delete user script", P_STRING, P_GLOBAL, &Globals.szDelUserScript, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"add group script", P_STRING, P_GLOBAL, &Globals.szAddGroupScript, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"delete group script", P_STRING, P_GLOBAL, &Globals.szDelGroupScript, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"add user to group script", P_STRING, P_GLOBAL, &Globals.szAddUserToGroupScript, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"delete user from group script", P_STRING, P_GLOBAL, &Globals.szDelUserFromGroupScript, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"set primary group script", P_STRING, P_GLOBAL, &Globals.szSetPrimaryGroupScript, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"add machine script", P_STRING, P_GLOBAL, &Globals.szAddMachineScript, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"shutdown script", P_STRING, P_GLOBAL, &Globals.szShutdownScript, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"abort shutdown script", P_STRING, P_GLOBAL, &Globals.szAbortShutdownScript, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+
+       {"logon script", P_STRING, P_GLOBAL, &Globals.szLogonScript, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"logon path", P_STRING, P_GLOBAL, &Globals.szLogonPath, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"logon drive", P_STRING, P_GLOBAL, &Globals.szLogonDrive, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"logon home", P_STRING, P_GLOBAL, &Globals.szLogonHome, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"domain logons", P_BOOL, P_GLOBAL, &Globals.bDomainLogons, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
 
        {"Browse Options", P_SEP, P_SEPARATOR},
        
-       {"os level", P_INTEGER, P_GLOBAL, &Globals.os_level, NULL, NULL, FLAG_BASIC},
-       {"lm announce", P_ENUM, P_GLOBAL, &Globals.lm_announce, NULL, enum_bool_auto, 0},
-       {"lm interval", P_INTEGER, P_GLOBAL, &Globals.lm_interval, NULL, NULL, 0},
-       {"preferred master", P_ENUM, P_GLOBAL, &Globals.bPreferredMaster, NULL, enum_bool_auto, FLAG_BASIC},
+       {"os level", P_INTEGER, P_GLOBAL, &Globals.os_level, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"lm announce", P_ENUM, P_GLOBAL, &Globals.lm_announce, NULL, enum_bool_auto, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"lm interval", P_INTEGER, P_GLOBAL, &Globals.lm_interval, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"preferred master", P_ENUM, P_GLOBAL, &Globals.bPreferredMaster, NULL, enum_bool_auto, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
        {"prefered master", P_ENUM, P_GLOBAL, &Globals.bPreferredMaster, NULL, enum_bool_auto, FLAG_HIDE},
-       {"local master", P_BOOL, P_GLOBAL, &Globals.bLocalMaster, NULL, NULL, FLAG_BASIC},
-       {"domain master", P_ENUM, P_GLOBAL, &Globals.bDomainMaster, NULL, enum_bool_auto, FLAG_BASIC},
-       {"browse list", P_BOOL, P_GLOBAL, &Globals.bBrowseList, NULL, NULL, 0},
-       {"browseable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL, NULL, FLAG_BASIC | FLAG_SHARE | FLAG_PRINT},
-       {"browsable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL, NULL, 0},
-       {"enhanced browsing", P_BOOL, P_GLOBAL, &Globals.enhanced_browsing, NULL, NULL},
+       {"local master", P_BOOL, P_GLOBAL, &Globals.bLocalMaster, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"domain master", P_ENUM, P_GLOBAL, &Globals.bDomainMaster, NULL, enum_bool_auto, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"browse list", P_BOOL, P_GLOBAL, &Globals.bBrowseList, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"browseable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT | FLAG_DEVELOPER},
+       {"browsable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL, NULL, FLAG_HIDE},
+       {"enhanced browsing", P_BOOL, P_GLOBAL, &Globals.enhanced_browsing, NULL, NULL, FLAG_DEVELOPER | FLAG_ADVANCED},
 
        {"WINS Options", P_SEP, P_SEPARATOR},
-       {"dns proxy", P_BOOL, P_GLOBAL, &Globals.bDNSproxy, NULL, NULL, 0},
-       {"wins proxy", P_BOOL, P_GLOBAL, &Globals.bWINSproxy, NULL, NULL, 0},
+       {"dns proxy", P_BOOL, P_GLOBAL, &Globals.bDNSproxy, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"wins proxy", P_BOOL, P_GLOBAL, &Globals.bWINSproxy, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
        
-       {"wins server", P_LIST, P_GLOBAL, &Globals.szWINSservers, NULL, NULL, FLAG_BASIC},
-       {"wins support", P_BOOL, P_GLOBAL, &Globals.bWINSsupport, NULL, NULL, FLAG_BASIC},
-       {"wins hook", P_STRING, P_GLOBAL, &Globals.szWINSHook, NULL, NULL, 0},
-       {"wins partners", P_STRING, P_GLOBAL, &Globals.szWINSPartners, NULL, NULL, 0},
+       {"wins server", P_LIST, P_GLOBAL, &Globals.szWINSservers, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
+       {"wins support", P_BOOL, P_GLOBAL, &Globals.bWINSsupport, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
+       {"wins hook", P_STRING, P_GLOBAL, &Globals.szWINSHook, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"wins partners", P_STRING, P_GLOBAL, &Globals.szWINSPartners, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER},
 
        {"Locking Options", P_SEP, P_SEPARATOR},
        
@@ -966,57 +1003,58 @@ static struct parm_struct parm_table[] = {
 
        {"Ldap Options", P_SEP, P_SEPARATOR},
        
-        {"ldap suffix", P_STRING, P_GLOBAL, &Globals.szLdapSuffix, handle_ldap_suffix, NULL, 0},
-        {"ldap machine suffix", P_STRING, P_GLOBAL, &Globals.szLdapMachineSuffix, handle_ldap_machine_suffix, NULL, 0},
-        {"ldap user suffix", P_STRING, P_GLOBAL, &Globals.szLdapUserSuffix, handle_ldap_user_suffix, NULL, 0},
-       {"ldap filter", P_STRING, P_GLOBAL, &Globals.szLdapFilter, NULL, NULL, 0},
-       {"ldap admin dn", P_STRING, P_GLOBAL, &Globals.szLdapAdminDn, NULL, NULL, 0},
-       {"ldap ssl", P_ENUM, P_GLOBAL, &Globals.ldap_ssl, NULL, enum_ldap_ssl, 0},
+       {"ldap suffix", P_STRING, P_GLOBAL, &Globals.szLdapSuffix, handle_ldap_suffix, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"ldap machine suffix", P_STRING, P_GLOBAL, &Globals.szLdapMachineSuffix, handle_ldap_machine_suffix, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"ldap user suffix", P_STRING, P_GLOBAL, &Globals.szLdapUserSuffix, handle_ldap_user_suffix, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"ldap filter", P_STRING, P_GLOBAL, &Globals.szLdapFilter, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"ldap admin dn", P_STRING, P_GLOBAL, &Globals.szLdapAdminDn, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"ldap ssl", P_ENUM, P_GLOBAL, &Globals.ldap_ssl, NULL, enum_ldap_ssl, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"ldap passwd sync", P_ENUM, P_GLOBAL, &Globals.ldap_passwd_sync, NULL, enum_ldap_passwd_sync, FLAG_ADVANCED | FLAG_DEVELOPER},
 
        {"Miscellaneous Options", P_SEP, P_SEPARATOR},
-       {"add share command", P_STRING, P_GLOBAL, &Globals.szAddShareCommand, NULL, NULL, 0},
-       {"change share command", P_STRING, P_GLOBAL, &Globals.szChangeShareCommand, NULL, NULL, 0},
-       {"delete share command", P_STRING, P_GLOBAL, &Globals.szDeleteShareCommand, NULL, NULL, 0},
+       {"add share command", P_STRING, P_GLOBAL, &Globals.szAddShareCommand, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"change share command", P_STRING, P_GLOBAL, &Globals.szChangeShareCommand, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"delete share command", P_STRING, P_GLOBAL, &Globals.szDeleteShareCommand, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
        
        {"config file", P_STRING, P_GLOBAL, &Globals.szConfigFile, NULL, NULL, FLAG_HIDE},
-       {"preload", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL, NULL, 0},
-       {"auto services", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL, NULL, 0},
-       {"lock dir", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL, NULL, 0}, 
-       {"lock directory", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL, NULL, 0},
-       {"pid directory", P_STRING, P_GLOBAL, &Globals.szPidDir, NULL, NULL, 0}, 
+       {"preload", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"auto services", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"lock dir", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL, NULL, FLAG_HIDE}, 
+       {"lock directory", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"pid directory", P_STRING, P_GLOBAL, &Globals.szPidDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, 
 #ifdef WITH_UTMP
-       {"utmp directory", P_STRING, P_GLOBAL, &Globals.szUtmpDir, NULL, NULL, 0},
-       {"wtmp directory", P_STRING, P_GLOBAL, &Globals.szWtmpDir, NULL, NULL, 0},
-       {"utmp",          P_BOOL, P_GLOBAL, &Globals.bUtmp, NULL, NULL, 0},
+       {"utmp directory", P_STRING, P_GLOBAL, &Globals.szUtmpDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"wtmp directory", P_STRING, P_GLOBAL, &Globals.szWtmpDir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"utmp",          P_BOOL, P_GLOBAL, &Globals.bUtmp, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
 #endif
        
-       {"default service", P_STRING, P_GLOBAL, &Globals.szDefaultService, NULL, NULL, 0},
-       {"default", P_STRING, P_GLOBAL, &Globals.szDefaultService, NULL, NULL, 0},
-       {"message command", P_STRING, P_GLOBAL, &Globals.szMsgCommand, NULL, NULL, 0},
-       {"dfree command", P_STRING, P_GLOBAL, &Globals.szDfree, NULL, NULL, 0},
-       {"remote announce", P_STRING, P_GLOBAL, &Globals.szRemoteAnnounce, NULL, NULL, 0},
-       {"remote browse sync", P_STRING, P_GLOBAL, &Globals.szRemoteBrowseSync, NULL, NULL, 0},
-       {"socket address", P_STRING, P_GLOBAL, &Globals.szSocketAddress, NULL, NULL, 0},
-       {"homedir map", P_STRING, P_GLOBAL, &Globals.szNISHomeMapName, NULL, NULL, 0},
-       {"time offset", P_INTEGER, P_GLOBAL, &extra_time_offset, NULL, NULL, 0},
-       {"NIS homedir", P_BOOL, P_GLOBAL, &Globals.bNISHomeMap, NULL, NULL, 0},
+       {"default service", P_STRING, P_GLOBAL, &Globals.szDefaultService, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"default", P_STRING, P_GLOBAL, &Globals.szDefaultService, NULL, NULL,  FLAG_DEVELOPER},
+       {"message command", P_STRING, P_GLOBAL, &Globals.szMsgCommand, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"dfree command", P_STRING, P_GLOBAL, &Globals.szDfree, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"remote announce", P_STRING, P_GLOBAL, &Globals.szRemoteAnnounce, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"remote browse sync", P_STRING, P_GLOBAL, &Globals.szRemoteBrowseSync, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"socket address", P_STRING, P_GLOBAL, &Globals.szSocketAddress, NULL, NULL, FLAG_DEVELOPER},
+       {"homedir map", P_STRING, P_GLOBAL, &Globals.szNISHomeMapName, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"time offset", P_INTEGER, P_GLOBAL, &extra_time_offset, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"NIS homedir", P_BOOL, P_GLOBAL, &Globals.bNISHomeMap, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
        {"-valid", P_BOOL, P_LOCAL, &sDefault.valid, NULL, NULL, FLAG_HIDE},
        
        {"copy", P_STRING, P_LOCAL, &sDefault.szCopy, handle_copy, NULL, FLAG_HIDE},
        {"include", P_STRING, P_LOCAL, &sDefault.szInclude, handle_include, NULL, FLAG_HIDE},
        {"exec", P_STRING, P_LOCAL, &sDefault.szPreExec, NULL, NULL, FLAG_SHARE | FLAG_PRINT},
-       {"preexec", P_STRING, P_LOCAL, &sDefault.szPreExec, NULL, NULL, 0},
+       {"preexec", P_STRING, P_LOCAL, &sDefault.szPreExec, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
        
        {"preexec close", P_BOOL, P_LOCAL, &sDefault.bPreexecClose, NULL, NULL, FLAG_SHARE},
        {"postexec", P_STRING, P_LOCAL, &sDefault.szPostExec, NULL, NULL, FLAG_SHARE | FLAG_PRINT},
        {"root preexec", P_STRING, P_LOCAL, &sDefault.szRootPreExec, NULL, NULL, FLAG_SHARE | FLAG_PRINT},
        {"root preexec close", P_BOOL, P_LOCAL, &sDefault.bRootpreexecClose, NULL, NULL, FLAG_SHARE},
        {"root postexec", P_STRING, P_LOCAL, &sDefault.szRootPostExec, NULL, NULL, FLAG_SHARE | FLAG_PRINT},
-       {"available", P_BOOL, P_LOCAL, &sDefault.bAvailable, NULL, NULL, FLAG_BASIC | FLAG_SHARE | FLAG_PRINT},
+       {"available", P_BOOL, P_LOCAL, &sDefault.bAvailable, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT},
        {"volume", P_STRING, P_LOCAL, &sDefault.volume, NULL, NULL, FLAG_SHARE },
        {"fstype", P_STRING, P_LOCAL, &sDefault.fstype, NULL, NULL, FLAG_SHARE},
        {"set directory", P_BOOLREV, P_LOCAL, &sDefault.bNo_set_dir, NULL, NULL, FLAG_SHARE},
-       {"source environment", P_STRING, P_GLOBAL, &Globals.szSourceEnv, handle_source_env, NULL, 0},
+       {"source environment", P_STRING, P_GLOBAL, &Globals.szSourceEnv, handle_source_env, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
        {"wide links", P_BOOL, P_LOCAL, &sDefault.bWidelinks, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
        {"follow symlinks", P_BOOL, P_LOCAL, &sDefault.bSymlinks, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
        {"dont descend", P_STRING, P_LOCAL, &sDefault.szDontdescend, NULL, NULL, FLAG_SHARE},
@@ -1028,9 +1066,8 @@ static struct parm_struct parm_table[] = {
        {"dos filetime resolution", P_BOOL, P_LOCAL, &sDefault.bDosFiletimeResolution, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
 
        {"fake directory create times", P_BOOL, P_LOCAL, &sDefault.bFakeDirCreateTimes, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL},
-       {"panic action", P_STRING, P_GLOBAL, &Globals.szPanicAction, NULL, NULL, 0},
-       {"hide local users", P_BOOL, P_GLOBAL, &Globals.bHideLocalUsers, NULL,
-        NULL, 0},
+       {"panic action", P_STRING, P_GLOBAL, &Globals.szPanicAction, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"hide local users", P_BOOL, P_GLOBAL, &Globals.bHideLocalUsers, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
 
        {"VFS module options", P_SEP, P_SEPARATOR},
        
@@ -1040,19 +1077,19 @@ static struct parm_struct parm_table[] = {
 
        
        {"msdfs root", P_BOOL, P_LOCAL, &sDefault.bMSDfsRoot, NULL, NULL, FLAG_SHARE},
-       {"host msdfs", P_BOOL, P_GLOBAL, &Globals.bHostMSDfs, NULL, NULL, 0},
+       {"host msdfs", P_BOOL, P_GLOBAL, &Globals.bHostMSDfs, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
 
        {"Winbind options", P_SEP, P_SEPARATOR},
 
-       {"winbind uid", P_STRING, P_GLOBAL, &Globals.szWinbindUID, handle_winbind_uid, NULL, 0},
-       {"winbind gid", P_STRING, P_GLOBAL, &Globals.szWinbindGID, handle_winbind_gid, NULL, 0},
-       {"template homedir", P_STRING, P_GLOBAL, &Globals.szTemplateHomedir, NULL, NULL, 0},
-       {"template shell", P_STRING, P_GLOBAL, &Globals.szTemplateShell, NULL, NULL, 0},
-       {"winbind separator", P_STRING, P_GLOBAL, &Globals.szWinbindSeparator, NULL, NULL, 0},
-       {"winbind cache time", P_INTEGER, P_GLOBAL, &Globals.winbind_cache_time, NULL, NULL, 0},
-       {"winbind enum users", P_BOOL, P_GLOBAL, &Globals.bWinbindEnumUsers, NULL, NULL, 0},
-       {"winbind enum groups", P_BOOL, P_GLOBAL, &Globals.bWinbindEnumGroups, NULL, NULL, 0},
-       {"winbind use default domain", P_BOOL, P_GLOBAL, &Globals.bWinbindUseDefaultDomain, NULL, NULL, 0},
+       {"winbind uid", P_STRING, P_GLOBAL, &Globals.szWinbindUID, handle_winbind_uid, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"winbind gid", P_STRING, P_GLOBAL, &Globals.szWinbindGID, handle_winbind_gid, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"template homedir", P_STRING, P_GLOBAL, &Globals.szTemplateHomedir, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"template shell", P_STRING, P_GLOBAL, &Globals.szTemplateShell, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"winbind separator", P_STRING, P_GLOBAL, &Globals.szWinbindSeparator, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"winbind cache time", P_INTEGER, P_GLOBAL, &Globals.winbind_cache_time, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"winbind enum users", P_BOOL, P_GLOBAL, &Globals.bWinbindEnumUsers, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"winbind enum groups", P_BOOL, P_GLOBAL, &Globals.bWinbindEnumGroups, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
+       {"winbind use default domain", P_BOOL, P_GLOBAL, &Globals.bWinbindUseDefaultDomain, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER},
 
        {NULL, P_BOOL, P_NONE, NULL, NULL, NULL, 0}
 };
@@ -1250,7 +1287,6 @@ static void init_globals(void)
        Globals.bAlgorithmicRidBase = BASE_RID;
 
        Globals.bLoadPrinters = True;
-       Globals.max_packet = 65535;
        Globals.mangled_stack = 50;
        Globals.max_xmit = 65535;
        Globals.max_mux = 50;   /* This is *needed* for profile support. */
@@ -1279,7 +1315,6 @@ static void init_globals(void)
        Globals.bStripDot = False;
        Globals.syslog = 1;
        Globals.bSyslogOnly = False;
-       Globals.bAdminLog = False;
        Globals.bTimestampLogs = True;
        string_set(&Globals.szLogLevel, "0");
        Globals.bDebugHiresTimestamp = False;
@@ -1339,6 +1374,7 @@ static void init_globals(void)
        string_set(&Globals.szLdapFilter, "(&(uid=%u)(objectclass=sambaAccount))");
        string_set(&Globals.szLdapAdminDn, "");
        Globals.ldap_ssl = LDAP_SSL_ON;
+       Globals.ldap_passwd_sync = LDAP_PASSWD_SYNC_OFF;
 
 /* these parameters are set to defaults that are more appropriate
    for the increasing samba install base:
@@ -1521,6 +1557,7 @@ FN_GLOBAL_STRING(lp_nis_home_map_name, &Globals.szNISHomeMapName)
 static FN_GLOBAL_STRING(lp_announce_version, &Globals.szAnnounceVersion)
 FN_GLOBAL_LIST(lp_netbios_aliases, &Globals.szNetbiosAliases)
 FN_GLOBAL_LIST(lp_passdb_backend, &Globals.szPassdbBackend)
+FN_GLOBAL_LIST(lp_sam_backend, &Globals.szSamBackend)
 FN_GLOBAL_STRING(lp_panic_action, &Globals.szPanicAction)
 FN_GLOBAL_STRING(lp_adduser_script, &Globals.szAddUserScript)
 FN_GLOBAL_STRING(lp_deluser_script, &Globals.szDelUserScript)
@@ -1530,6 +1567,7 @@ FN_GLOBAL_STRING(lp_addgroup_script, &Globals.szAddGroupScript)
 FN_GLOBAL_STRING(lp_delgroup_script, &Globals.szDelGroupScript)
 FN_GLOBAL_STRING(lp_addusertogroup_script, &Globals.szAddUserToGroupScript)
 FN_GLOBAL_STRING(lp_deluserfromgroup_script, &Globals.szDelUserFromGroupScript)
+FN_GLOBAL_STRING(lp_setprimarygroup_script, &Globals.szSetPrimaryGroupScript)
 
 FN_GLOBAL_STRING(lp_addmachine_script, &Globals.szAddMachineScript)
 
@@ -1550,6 +1588,7 @@ FN_GLOBAL_STRING(lp_ldap_user_suffix, &Globals.szLdapUserSuffix)
 FN_GLOBAL_STRING(lp_ldap_filter, &Globals.szLdapFilter)
 FN_GLOBAL_STRING(lp_ldap_admin_dn, &Globals.szLdapAdminDn)
 FN_GLOBAL_INTEGER(lp_ldap_ssl, &Globals.ldap_ssl)
+FN_GLOBAL_INTEGER(lp_ldap_passwd_sync, &Globals.ldap_passwd_sync)
 FN_GLOBAL_STRING(lp_add_share_cmd, &Globals.szAddShareCommand)
 FN_GLOBAL_STRING(lp_change_share_cmd, &Globals.szChangeShareCommand)
 FN_GLOBAL_STRING(lp_delete_share_cmd, &Globals.szDeleteShareCommand)
@@ -1574,7 +1613,6 @@ FN_GLOBAL_BOOL(lp_strip_dot, &Globals.bStripDot)
 FN_GLOBAL_BOOL(lp_encrypted_passwords, &Globals.bEncryptPasswords)
 FN_GLOBAL_BOOL(lp_update_encrypted, &Globals.bUpdateEncrypt)
 FN_GLOBAL_BOOL(lp_syslog_only, &Globals.bSyslogOnly)
-FN_GLOBAL_BOOL(lp_admin_log, &Globals.bAdminLog)
 FN_GLOBAL_BOOL(lp_timestamp_logs, &Globals.bTimestampLogs)
 FN_GLOBAL_BOOL(lp_debug_hires_timestamp, &Globals.bDebugHiresTimestamp)
 FN_GLOBAL_BOOL(lp_debug_pid, &Globals.bDebugPid)
@@ -1686,6 +1724,7 @@ FN_LOCAL_BOOL(lp_preservecase, bCasePreserve)
 FN_LOCAL_BOOL(lp_shortpreservecase, bShortCasePreserve)
 FN_LOCAL_BOOL(lp_casemangle, bCaseMangle)
 FN_LOCAL_BOOL(lp_hide_dot_files, bHideDotFiles)
+FN_LOCAL_BOOL(lp_hide_special_files, bHideSpecialFiles)
 FN_LOCAL_BOOL(lp_hideunreadable, bHideUnReadable)
 FN_LOCAL_BOOL(lp_hideunwriteable_files, bHideUnWriteableFiles)
 FN_LOCAL_BOOL(lp_browseable, bBrowseable)
@@ -1724,6 +1763,10 @@ FN_LOCAL_BOOL(lp_inherit_acls, bInheritACLS)
 FN_LOCAL_BOOL(lp_use_client_driver, bUseClientDriver)
 FN_LOCAL_BOOL(lp_default_devmode, bDefaultDevmode)
 FN_LOCAL_BOOL(lp_nt_acl_support, bNTAclSupport)
+#ifdef WITH_SENDFILE
+FN_LOCAL_BOOL(lp_use_sendfile, bUseSendfile)
+#endif
+FN_LOCAL_BOOL(lp_profile_acls, bProfileAcls)
 FN_LOCAL_INTEGER(lp_create_mask, iCreate_mask)
 FN_LOCAL_INTEGER(lp_force_create_mode, iCreate_force_mode)
 FN_LOCAL_INTEGER(lp_security_mask, iSecurity_mask)
@@ -3507,32 +3550,46 @@ static void set_server_role(void)
                case SEC_SHARE:
                        if (lp_domain_logons())
                                DEBUG(0, ("Server's Role (logon server) conflicts with share-level security\n"));
-                       DEBUG(10,("set_server_role: ROLE_STANDALONE\n"));
                        break;
                case SEC_SERVER:
                case SEC_DOMAIN:
                case SEC_ADS:
                        if (lp_domain_logons()) {
                                server_role = ROLE_DOMAIN_PDC;
-                               DEBUG(10,("set_server_role:ROLE_DOMAIN_PDC\n"));
                                break;
                        }
                        server_role = ROLE_DOMAIN_MEMBER;
-                       DEBUG(10,("set_server_role: ROLE_DOMAIN_MEMBER\n"));
                        break;
                case SEC_USER:
                        if (lp_domain_logons()) {
-                               server_role = ROLE_DOMAIN_PDC;
-                               DEBUG(10,("set_server_role: ROLE_DOMAIN_PDC\n"));
-                               break;
+
+                               if (Globals.bDomainMaster) /* auto or yes */ 
+                                       server_role = ROLE_DOMAIN_PDC;
+                               else
+                                       server_role = ROLE_DOMAIN_BDC;
                        }
-                       DEBUG(10,("set_server_role: ROLE_STANDALONE\n"));
                        break;
                default:
                        DEBUG(0, ("Server's Role undefined due to unknown security mode\n"));
-                       DEBUG(10,("set_server_role: ROLE_STANDALONE\n"));
                        break;
        }
+
+       DEBUG(10, ("set_server_role: role = "));
+
+       switch(server_role) {
+       case ROLE_STANDALONE:
+               DEBUGADD(10, ("ROLE_STANDALONE\n"));
+               break;
+       case ROLE_DOMAIN_MEMBER:
+               DEBUGADD(10, ("ROLE_DOMAIN_MEMBER\n"));
+               break;
+       case ROLE_DOMAIN_BDC:
+               DEBUGADD(10, ("ROLE_DOMAIN_BDC\n"));
+               break;
+       case ROLE_DOMAIN_PDC:
+               DEBUGADD(10, ("ROLE_DOMAIN_PDC\n"));
+               break;
+       }
 }
 
 
@@ -3555,12 +3612,13 @@ BOOL lp_load(const char *pszFname, BOOL global_only, BOOL save_defaults,
 
        bRetval = False;
 
-       DEBUG(3, ("lp_load: refreshing parmaters\n"));
+       DEBUG(3, ("lp_load: refreshing parameters\n"));
        
        bInGlobalSection = True;
        bGlobalOnly = global_only;
 
        init_globals();
+       debug_init();
 
        if (save_defaults)
        {
index e1f7dec2a9bfa46222aa6c090e2327a5ab7d6000..e1a1de83a6037a55c96b8af1119baf5b7bce0de3 100644 (file)
@@ -80,7 +80,6 @@ static BOOL pdb_generate_sam_sid(void)
 {
        char *fname = NULL;
        extern pstring global_myname;
-       extern fstring global_myworkgroup;
        BOOL is_dc = False;
 
        if(global_sam_sid==NULL)
@@ -106,11 +105,11 @@ static BOOL pdb_generate_sam_sid(void)
                if (!is_dc)
                        return True;
 
-               if (!secrets_fetch_domain_sid(global_myworkgroup, &domain_sid)) {
+               if (!secrets_fetch_domain_sid(lp_workgroup(), &domain_sid)) {
 
                        /* No domain sid and we're a pdc/bdc. Store it */
 
-                       if (!secrets_store_domain_sid(global_myworkgroup, global_sam_sid)) {
+                       if (!secrets_store_domain_sid(lp_workgroup(), global_sam_sid)) {
                                DEBUG(0,("pdb_generate_sam_sid: Can't store domain SID as a pdc/bdc.\n"));
                                return False;
                        }
@@ -122,7 +121,7 @@ static BOOL pdb_generate_sam_sid(void)
                        /* Domain name sid doesn't match global sam sid. Re-store global sam sid as domain sid. */
 
                        DEBUG(0,("pdb_generate_sam_sid: Mismatched SIDs as a pdc/bdc.\n"));
-                       if (!secrets_store_domain_sid(global_myworkgroup, global_sam_sid)) {
+                       if (!secrets_store_domain_sid(lp_workgroup(), global_sam_sid)) {
                                DEBUG(0,("pdb_generate_sam_sid: Can't re-store domain SID as a pdc/bdc.\n"));
                                return False;
                        }
@@ -145,7 +144,7 @@ static BOOL pdb_generate_sam_sid(void)
                }
                unlink(fname);
                if (is_dc) {
-                       if (!secrets_store_domain_sid(global_myworkgroup, global_sam_sid)) {
+                       if (!secrets_store_domain_sid(lp_workgroup(), global_sam_sid)) {
                                DEBUG(0,("pdb_generate_sam_sid: Failed to store domain SID from file.\n"));
                                SAFE_FREE(fname);
                                return False;
@@ -168,7 +167,7 @@ static BOOL pdb_generate_sam_sid(void)
                return False;
        }
        if (is_dc) {
-               if (!secrets_store_domain_sid(global_myworkgroup, global_sam_sid)) {
+               if (!secrets_store_domain_sid(lp_workgroup(), global_sam_sid)) {
                        DEBUG(0,("pdb_generate_sam_sid: Failed to store generated domain SID.\n"));
                        return False;
                }
index a9c6f0729bd0e60627c5880b461c4de7e03c24bb..b78f26a8e81704308a47032ae0be611f840211c9 100644 (file)
@@ -75,11 +75,19 @@ static void pdb_fill_default_sam(SAM_ACCOUNT *user)
        user->private.workstations = "";
        user->private.unknown_str = "";
        user->private.munged_dial = "";
+
+       user->private.plaintext_pw = NULL;
+
 }      
 
 static void destroy_pdb_talloc(SAM_ACCOUNT **user) 
 {
        if (*user) {
+               data_blob_clear_free(&((*user)->private.lm_pw));
+               data_blob_clear_free(&((*user)->private.nt_pw));
+
+               if((*user)->private.plaintext_pw!=NULL)
+                       memset((*user)->private.plaintext_pw,'\0',strlen((*user)->private.plaintext_pw));
                talloc_destroy((*user)->mem_ctx);
                *user = NULL;
        }
@@ -251,6 +259,15 @@ NTSTATUS pdb_fill_sam_pw(SAM_ACCOUNT *sam_account, const struct passwd *pwd)
                                                            pwd->pw_name, global_myname, 
                                                            pwd->pw_uid, pwd->pw_gid), 
                                     False);
+               if (!pdb_set_acct_ctrl(sam_account, ACB_NORMAL)) {
+                       DEBUG(1, ("Failed to set 'normal account' flags for user %s.\n", pwd->pw_name));
+                       return NT_STATUS_UNSUCCESSFUL;
+               }
+       } else {
+               if (!pdb_set_acct_ctrl(sam_account, ACB_WSTRUST)) {
+                       DEBUG(1, ("Failed to set 'trusted workstation account' flags for user %s.\n", pwd->pw_name));
+                       return NT_STATUS_UNSUCCESSFUL;
+               }
        }
        return NT_STATUS_OK;
 }
@@ -301,7 +318,8 @@ static void pdb_free_sam_contents(SAM_ACCOUNT *user)
 
        data_blob_clear_free(&(user->private.lm_pw));
        data_blob_clear_free(&(user->private.nt_pw));
-       data_blob_clear_free(&(user->private.plaintext_pw));
+       if (user->private.plaintext_pw!=NULL)
+               memset(user->private.plaintext_pw,'\0',strlen(user->private.plaintext_pw));
 }
 
 
@@ -823,11 +841,14 @@ BOOL local_sid_to_uid(uid_t *puid, const DOM_SID *psid, enum SID_NAME_USE *name_
                return False;
        
        if (pdb_getsampwsid(sam_user, psid)) {
-               *puid = pdb_get_uid(sam_user);
-               if (*puid == -1) {
+               
+               if (!(pdb_get_init_flag(sam_user) & FLAG_SAM_UID)) { 
                        pdb_free_sam(&sam_user);
                        return False;
                }
+
+               *puid = pdb_get_uid(sam_user);
+                       
                DEBUG(10,("local_sid_to_uid: SID %s -> uid (%u) (%s).\n", sid_to_string( str, psid),
                          (unsigned int)*puid, pdb_get_username(sam_user)));
                pdb_free_sam(&sam_user);
@@ -982,6 +1003,7 @@ BOOL local_password_change(const char *user_name, int local_flags,
 {
        struct passwd  *pwd = NULL;
        SAM_ACCOUNT     *sam_pass=NULL;
+       uint16 other_acb;
 
        *err_str = '\0';
        *msg_str = '\0';
@@ -1021,31 +1043,33 @@ BOOL local_password_change(const char *user_name, int local_flags,
                                return False;
                        }
                }
-               if (local_flags & LOCAL_TRUST_ACCOUNT) {
-                       if (!pdb_set_acct_ctrl(sam_pass, ACB_WSTRUST)) {
-                               slprintf(err_str, err_str_len - 1, "Failed to set 'trusted workstation account' flags for user %s.\n", user_name);
-                               pdb_free_sam(&sam_pass);
-                               return False;
-                       }
-               } else if (local_flags & LOCAL_INTERDOM_ACCOUNT) {
-                       if (!pdb_set_acct_ctrl(sam_pass, ACB_DOMTRUST)) {
-                               slprintf(err_str, err_str_len - 1, "Failed to set 'domain trust account' flags for user %s.\n", user_name);
-                               pdb_free_sam(&sam_pass);
-                               return False;
-                       }
-               } else {
-                       if (!pdb_set_acct_ctrl(sam_pass, ACB_NORMAL)) {
-                               slprintf(err_str, err_str_len - 1, "Failed to set 'normal account' flags for user %s.\n", user_name);
-                               pdb_free_sam(&sam_pass);
-                               return False;
-                       }
-               }
-
        } else {
                /* the entry already existed */
                local_flags &= ~LOCAL_ADD_USER;
        }
 
+       /* the 'other' acb bits not being changed here */
+       other_acb =  (pdb_get_acct_ctrl(sam_pass) & (!(ACB_WSTRUST|ACB_DOMTRUST|ACB_SVRTRUST|ACB_NORMAL)));
+       if (local_flags & LOCAL_TRUST_ACCOUNT) {
+               if (!pdb_set_acct_ctrl(sam_pass, ACB_WSTRUST | other_acb) ) {
+                       slprintf(err_str, err_str_len - 1, "Failed to set 'trusted workstation account' flags for user %s.\n", user_name);
+                       pdb_free_sam(&sam_pass);
+                       return False;
+               }
+       } else if (local_flags & LOCAL_INTERDOM_ACCOUNT) {
+               if (!pdb_set_acct_ctrl(sam_pass, ACB_DOMTRUST | other_acb)) {
+                       slprintf(err_str, err_str_len - 1, "Failed to set 'domain trust account' flags for user %s.\n", user_name);
+                       pdb_free_sam(&sam_pass);
+                       return False;
+               }
+       } else {
+               if (!pdb_set_acct_ctrl(sam_pass, ACB_NORMAL | other_acb)) {
+                       slprintf(err_str, err_str_len - 1, "Failed to set 'normal account' flags for user %s.\n", user_name);
+                       pdb_free_sam(&sam_pass);
+                       return False;
+               }
+       }
+
        /*
         * We are root - just write the new password
         * and the valid last change time.
index 2da6de7270113b9c9117eb20d12132815482c276..0c338f317ecd665c2c01d41f174668f6b63a9449 100644 (file)
@@ -151,7 +151,7 @@ const uint8* pdb_get_lanman_passwd (const SAM_ACCOUNT *sampass)
 const char* pdb_get_plaintext_passwd (const SAM_ACCOUNT *sampass)
 {
        if (sampass) {
-               return ((char*)sampass->private.plaintext_pw.data);
+               return (sampass->private.plaintext_pw);
        }
        else
                return (NULL);
@@ -956,14 +956,24 @@ BOOL pdb_set_lanman_passwd (SAM_ACCOUNT *sampass, const uint8 pwd[16])
  below)
  ********************************************************************/
 
-BOOL pdb_set_plaintext_pw_only (SAM_ACCOUNT *sampass, const uint8 *password, size_t len)
+BOOL pdb_set_plaintext_pw_only (SAM_ACCOUNT *sampass, const char *password)
 {
        if (!sampass)
                return False;
 
-       data_blob_clear_free(&sampass->private.plaintext_pw);
-       
-       sampass->private.plaintext_pw = data_blob(password, len);
+       if (password) { 
+               if (sampass->private.plaintext_pw!=NULL) 
+                       memset(sampass->private.plaintext_pw,'\0',strlen(sampass->private.plaintext_pw)+1);
+               sampass->private.plaintext_pw = talloc_strdup(sampass->mem_ctx, password);
+               
+               if (!sampass->private.plaintext_pw) {
+                       DEBUG(0, ("pdb_set_unknown_str: talloc_strdup() failed!\n"));
+                       return False;
+               }
+
+       } else {
+               sampass->private.plaintext_pw = NULL;
+       }
 
        return True;
 }
@@ -1062,7 +1072,10 @@ BOOL pdb_set_plaintext_passwd (SAM_ACCOUNT *sampass, const char *plaintext)
 
        if (!pdb_set_lanman_passwd (sampass, new_lanman_p16)) 
                return False;
-       
+
+       if (!pdb_set_plaintext_pw_only (sampass, plaintext)) 
+               return False;
+
        if (!pdb_set_pass_changed_now (sampass))
                return False;
 
index f311223d772c63c7bd8725a7112e79d0573d4d49..f965dd727cce7d7c912bc989466aa7c44e7cd89a 100644 (file)
@@ -34,13 +34,14 @@ const struct pdb_init_function_entry builtin_pdb_init_functions[] = {
        { "ldapsam", pdb_init_ldapsam },
        { "ldapsam_nua", pdb_init_ldapsam_nua },
        { "unixsam", pdb_init_unixsam },
+       { "nisplussam", pdb_init_nisplussam },
        { "plugin", pdb_init_plugin },
        { NULL, NULL}
 };
 
 static BOOL context_setsampwent(struct pdb_context *context, BOOL update)
 {
-       if ((!context) || (!context->pdb_methods) || (!context->pdb_methods->setsampwent)) {
+       if (!context) {
                DEBUG(0, ("invalid pdb_context specified!\n"));
                return False;
        }
@@ -52,7 +53,7 @@ static BOOL context_setsampwent(struct pdb_context *context, BOOL update)
                return True;
        }
 
-       while (!(context->pwent_methods->setsampwent(context->pwent_methods, update))) {
+       while (!(context->pwent_methods->setsampwent) || !(context->pwent_methods->setsampwent(context->pwent_methods, update))) {
                context->pwent_methods = context->pwent_methods->next;
                if (context->pwent_methods == NULL) 
                        return False;
index f82cb4488fc59ff298a9c0520b0233409341f4f5..71a8c256a3aae719bc3edd394bd875694b2c0125 100644 (file)
@@ -1,11 +1,11 @@
 /* 
    Unix SMB/CIFS implementation.
    LDAP protocol helper functions for SAMBA
-   Copyright (C) Jean François Micouleau       1998
-   Copyright (C) Gerald Carter                         2001
-   Copyright (C) Shahms King                   2001
-   Copyright (C) Andrew Bartlett               2002
-   Copyright (C) Stefan (metze) Metzmacher     2002
+   Copyright (C) Jean François Micouleau       1998
+   Copyright (C) Gerald Carter                 2001
+   Copyright (C) Shahms King                   2001
+   Copyright (C) Andrew Bartlett               2002
+   Copyright (C) Stefan (metze) Metzmacher     2002
     
    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
@@ -273,7 +273,8 @@ static BOOL ldapsam_open_connection (struct ldapsam_privates *ldap_state, LDAP *
  a rebind function for authenticated referrals
  This version takes a void* that we can shove useful stuff in :-)
 ******************************************************************/
-
+#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
+#else
 static int rebindproc_with_state  (LDAP * ld, char **whop, char **credp, 
                                   int *methodp, int freeit, void *arg)
 {
@@ -304,13 +305,14 @@ static int rebindproc_with_state  (LDAP * ld, char **whop, char **credp,
        }
        return 0;
 }
+#endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
 
 /*******************************************************************
  a rebind function for authenticated referrals
  This version takes a void* that we can shove useful stuff in :-)
  and actually does the connection.
 ******************************************************************/
-
+#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
 static int rebindproc_connect_with_state (LDAP *ldap_struct, 
                                          LDAP_CONST char *url, 
                                          ber_tag_t request,
@@ -329,11 +331,14 @@ static int rebindproc_connect_with_state (LDAP *ldap_struct,
        
        return rc;
 }
+#endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
 
 /*******************************************************************
  Add a rebind function for authenticated referrals
 ******************************************************************/
-
+#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
+#else
+# if LDAP_SET_REBIND_PROC_ARGS == 2
 static int rebindproc (LDAP *ldap_struct, char **whop, char **credp,
                       int *method, int freeit )
 {
@@ -341,19 +346,23 @@ static int rebindproc (LDAP *ldap_struct, char **whop, char **credp,
                                   method, freeit, static_ldap_state);
        
 }
+# endif /*LDAP_SET_REBIND_PROC_ARGS == 2*/
+#endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
 
 /*******************************************************************
  a rebind function for authenticated referrals
  this also does the connection, but no void*.
 ******************************************************************/
-
+#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
+# if LDAP_SET_REBIND_PROC_ARGS == 2
 static int rebindproc_connect (LDAP * ld, LDAP_CONST char *url, int request,
                               ber_int_t msgid)
 {
        return rebindproc_connect_with_state(ld, url, (ber_tag_t)request, msgid, 
                                             static_ldap_state);
 }
-
+# endif /*LDAP_SET_REBIND_PROC_ARGS == 2*/
+#endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
 
 /*******************************************************************
  connect to the ldap server under system privilege.
@@ -391,18 +400,18 @@ static BOOL ldapsam_connect_system(struct ldapsam_privates *ldap_state, LDAP * l
 # if LDAP_SET_REBIND_PROC_ARGS == 3    
        ldap_set_rebind_proc(ldap_struct, &rebindproc_connect_with_state, (void *)ldap_state);  
 # endif
-#else
+#else /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
 # if LDAP_SET_REBIND_PROC_ARGS == 2    
        ldap_set_rebind_proc(ldap_struct, &rebindproc); 
 # endif
 # if LDAP_SET_REBIND_PROC_ARGS == 3    
        ldap_set_rebind_proc(ldap_struct, &rebindproc_with_state, (void *)ldap_state);  
 # endif
-#endif
+#endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/
+
        rc = ldap_simple_bind_s(ldap_struct, ldap_dn, ldap_secret);
 
-       if (rc != LDAP_SUCCESS)
-       {
+       if (rc != LDAP_SUCCESS) {
                DEBUG(0, ("Bind failed: %s\n", ldap_err2string(rc)));
                return False;
        }
@@ -421,7 +430,7 @@ static int ldapsam_search_one_user (struct ldapsam_privates *ldap_state, LDAP *
 
        DEBUG(2, ("ldapsam_search_one_user: searching for:[%s]\n", filter));
 
-       rc = ldap_search_s(ldap_struct, lp_ldap_suffix (), scope, filter, attr, 0, result);
+       rc = ldap_search_s(ldap_struct, lp_ldap_suffix (), scope, filter, (char **)attr, 0, result);
 
        if (rc != LDAP_SUCCESS) {
                DEBUG(0,("ldapsam_search_one_user: Problem during the LDAP search: %s\n", 
@@ -944,9 +953,6 @@ static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state,
        slprintf(temp, sizeof(temp) - 1, "%i", rid);
        make_a_mod(mods, ldap_op, "primaryGroupID", temp);
 
-       slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_last_set_time(sampass));
-       make_a_mod(mods, ldap_op, "pwdLastSet", temp);
-
        /* displayName, cn, and gecos should all be the same
           *  most easily accomplished by giving them the same OID
           *  gecos isn't set here b/c it should be handled by the 
@@ -989,6 +995,7 @@ static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state,
                make_a_mod(mods, ldap_op, "kickoffTime", temp);
        }
 
+
        if (IS_SAM_SET(sampass, FLAG_SAM_CANCHANGETIME)) {
                slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_can_change_time(sampass));
                make_a_mod(mods, ldap_op, "pwdCanChange", temp);
@@ -999,13 +1006,22 @@ static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state,
                make_a_mod(mods, ldap_op, "pwdMustChange", temp);
        }
 
-       /* FIXME: Hours stuff goes in LDAP  */
-       pdb_sethexpwd (temp, pdb_get_lanman_passwd(sampass), pdb_get_acct_ctrl(sampass));
-       make_a_mod (mods, ldap_op, "lmPassword", temp);
+       if ((pdb_get_acct_ctrl(sampass)&(ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST))||
+               (lp_ldap_passwd_sync()!=LDAP_PASSWD_SYNC_ONLY)) {
+
+               pdb_sethexpwd (temp, pdb_get_lanman_passwd(sampass), pdb_get_acct_ctrl(sampass));
+               make_a_mod (mods, ldap_op, "lmPassword", temp);
        
-       pdb_sethexpwd (temp, pdb_get_nt_passwd(sampass), pdb_get_acct_ctrl(sampass));
-       make_a_mod (mods, ldap_op, "ntPassword", temp);
+               pdb_sethexpwd (temp, pdb_get_nt_passwd(sampass), pdb_get_acct_ctrl(sampass));
+               make_a_mod (mods, ldap_op, "ntPassword", temp);
        
+               slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_last_set_time(sampass));
+               make_a_mod(mods, ldap_op, "pwdLastSet", temp);
+
+       }
+
+       /* FIXME: Hours stuff goes in LDAP  */
+
        make_a_mod (mods, ldap_op, "acctFlags", pdb_encode_acct_ctrl (pdb_get_acct_ctrl(sampass),
                NEW_PW_FORMAT_SPACE_PADDED_LEN));
 
@@ -1030,18 +1046,18 @@ static uint32 check_nua_rid_is_avail(struct ldapsam_privates *ldap_state, uint32
 
        if (ldapsam_search_one_user_by_rid(ldap_state, ldap_struct, final_rid, &result) != LDAP_SUCCESS) {
                DEBUG(0, ("Cannot allocate NUA RID %d (0x%x), as the confirmation search failed!\n", final_rid, final_rid));
-               final_rid = 0;
                ldap_msgfree(result);
+               return 0;
        }
 
-       if (ldap_count_entries(ldap_struct, result) != 0)
-       {
+       if (ldap_count_entries(ldap_struct, result) != 0) {
                DEBUG(0, ("Cannot allocate NUA RID %d (0x%x), as the RID is already in use!!\n", final_rid, final_rid));
-               final_rid = 0;
                ldap_msgfree(result);
+               return 0;
        }
 
        DEBUG(5, ("NUA RID %d (0x%x), declared valid\n", final_rid, final_rid));
+       ldap_msgfree(result);
        return final_rid;
 }
 
@@ -1093,12 +1109,10 @@ static uint32 search_top_nua_rid(struct ldapsam_privates *ldap_state, LDAP *ldap
        DEBUG(2, ("ldapsam_get_next_available_nua_rid: searching for:[%s]\n", final_filter));
 
        rc = ldap_search_s(ldap_struct, lp_ldap_suffix(),
-                          LDAP_SCOPE_SUBTREE, final_filter, attr, 0,
+                          LDAP_SCOPE_SUBTREE, final_filter, (char **)attr, 0,
                           &result);
 
-       if (rc != LDAP_SUCCESS)
-       {
-               
+       if (rc != LDAP_SUCCESS) {
                DEBUG(3, ("LDAP search failed! cannot find base for NUA RIDs: %s\n", ldap_err2string(rc)));
                DEBUGADD(3, ("Query was: %s, %s\n", lp_ldap_suffix(), final_filter));
 
@@ -1149,12 +1163,10 @@ static uint32 ldapsam_get_next_available_nua_rid(struct ldapsam_privates *ldap_s
        uint32 next_nua_rid;
        uint32 top_nua_rid;
 
-       if (!ldapsam_open_connection(ldap_state, &ldap_struct))
-       {
+       if (!ldapsam_open_connection(ldap_state, &ldap_struct)) {
                return 0;
        }
-       if (!ldapsam_connect_system(ldap_state, ldap_struct))
-       {
+       if (!ldapsam_connect_system(ldap_state, ldap_struct)) {
                ldap_unbind(ldap_struct);
                return 0;
        }
@@ -1177,12 +1189,10 @@ static BOOL ldapsam_setsampwent(struct pdb_methods *my_methods, BOOL update)
        int rc;
        pstring filter;
 
-       if (!ldapsam_open_connection(ldap_state, &ldap_state->ldap_struct))
-       {
+       if (!ldapsam_open_connection(ldap_state, &ldap_state->ldap_struct)) {
                return False;
        }
-       if (!ldapsam_connect_system(ldap_state, ldap_state->ldap_struct))
-       {
+       if (!ldapsam_connect_system(ldap_state, ldap_state->ldap_struct)) {
                ldap_unbind(ldap_state->ldap_struct);
                return False;
        }
@@ -1191,11 +1201,10 @@ static BOOL ldapsam_setsampwent(struct pdb_methods *my_methods, BOOL update)
        all_string_sub(filter, "%u", "*", sizeof(pstring));
 
        rc = ldap_search_s(ldap_state->ldap_struct, lp_ldap_suffix(),
-                          LDAP_SCOPE_SUBTREE, filter, attr, 0,
+                          LDAP_SCOPE_SUBTREE, filter, (char **)attr, 0,
                           &ldap_state->result);
 
-       if (rc != LDAP_SUCCESS)
-       {
+       if (rc != LDAP_SUCCESS) {
                DEBUG(0, ("LDAP search failed: %s\n", ldap_err2string(rc)));
                DEBUG(3, ("Query was: %s, %s\n", lp_ldap_suffix(), filter));
                ldap_msgfree(ldap_state->result);
@@ -1222,8 +1231,7 @@ End enumeration of the LDAP password list
 static void ldapsam_endsampwent(struct pdb_methods *my_methods)
 {
        struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
-       if (ldap_state->ldap_struct && ldap_state->result)
-       {
+       if (ldap_state->ldap_struct && ldap_state->result) {
                ldap_msgfree(ldap_state->result);
                ldap_unbind(ldap_state->ldap_struct);
                ldap_state->ldap_struct = NULL;
@@ -1234,7 +1242,7 @@ static void ldapsam_endsampwent(struct pdb_methods *my_methods)
 /**********************************************************************
 Get the next entry in the LDAP password database 
 *********************************************************************/
-static BOOL ldapsam_getsampwent(struct pdb_methods *my_methods, SAM_ACCOUNT * user)
+static BOOL ldapsam_getsampwent(struct pdb_methods *my_methods, SAM_ACCOUNT *user)
 {
        struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
        BOOL ret = False;
@@ -1252,8 +1260,7 @@ static BOOL ldapsam_getsampwent(struct pdb_methods *my_methods, SAM_ACCOUNT * us
                                         ldap_state->entry);
                
                ldap_state->entry = ldap_next_entry(ldap_state->ldap_struct,
-                                           ldap_state->entry);
-               
+                                           ldap_state->entry); 
        }
 
        return True;
@@ -1262,7 +1269,7 @@ static BOOL ldapsam_getsampwent(struct pdb_methods *my_methods, SAM_ACCOUNT * us
 /**********************************************************************
 Get SAM_ACCOUNT entry from LDAP by username 
 *********************************************************************/
-static BOOL ldapsam_getsampwnam(struct pdb_methods *my_methods, SAM_ACCOUNT * user, const char *sname)
+static BOOL ldapsam_getsampwnam(struct pdb_methods *my_methods, SAM_ACCOUNT *user, const char *sname)
 {
        struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
        LDAP *ldap_struct;
@@ -1271,18 +1278,15 @@ static BOOL ldapsam_getsampwnam(struct pdb_methods *my_methods, SAM_ACCOUNT * us
 
        if (!ldapsam_open_connection(ldap_state, &ldap_struct))
                return False;
-       if (!ldapsam_connect_system(ldap_state, ldap_struct))
-       {
+       if (!ldapsam_connect_system(ldap_state, ldap_struct)) {
                ldap_unbind(ldap_struct);
                return False;
        }
-       if (ldapsam_search_one_user_by_name(ldap_state, ldap_struct, sname, &result) != LDAP_SUCCESS)
-       {
+       if (ldapsam_search_one_user_by_name(ldap_state, ldap_struct, sname, &result) != LDAP_SUCCESS) {
                ldap_unbind(ldap_struct);
                return False;
        }
-       if (ldap_count_entries(ldap_struct, result) < 1)
-       {
+       if (ldap_count_entries(ldap_struct, result) < 1) {
                DEBUG(4,
                      ("We don't find this user [%s] count=%d\n", sname,
                       ldap_count_entries(ldap_struct, result)));
@@ -1290,8 +1294,7 @@ static BOOL ldapsam_getsampwnam(struct pdb_methods *my_methods, SAM_ACCOUNT * us
                return False;
        }
        entry = ldap_first_entry(ldap_struct, result);
-       if (entry)
-       {
+       if (entry) {
                if (!init_sam_from_ldap(ldap_state, user, ldap_struct, entry)) {
                        DEBUG(1,("ldapsam_getsampwnam: init_sam_from_ldap failed for user '%s'!\n", sname));
                        ldap_msgfree(result);
@@ -1301,9 +1304,7 @@ static BOOL ldapsam_getsampwnam(struct pdb_methods *my_methods, SAM_ACCOUNT * us
                ldap_msgfree(result);
                ldap_unbind(ldap_struct);
                return True;
-       }
-       else
-       {
+       } else {
                ldap_msgfree(result);
                ldap_unbind(ldap_struct);
                return False;
@@ -1313,7 +1314,7 @@ static BOOL ldapsam_getsampwnam(struct pdb_methods *my_methods, SAM_ACCOUNT * us
 /**********************************************************************
 Get SAM_ACCOUNT entry from LDAP by rid 
 *********************************************************************/
-static BOOL ldapsam_getsampwrid(struct pdb_methods *my_methods, SAM_ACCOUNT * user, uint32 rid)
+static BOOL ldapsam_getsampwrid(struct pdb_methods *my_methods, SAM_ACCOUNT *user, uint32 rid)
 {
        struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
        LDAP *ldap_struct;
@@ -1323,20 +1324,17 @@ static BOOL ldapsam_getsampwrid(struct pdb_methods *my_methods, SAM_ACCOUNT * us
        if (!ldapsam_open_connection(ldap_state, &ldap_struct))
                return False;
 
-       if (!ldapsam_connect_system(ldap_state, ldap_struct))
-       {
+       if (!ldapsam_connect_system(ldap_state, ldap_struct)) {
                ldap_unbind(ldap_struct);
                return False;
        }
        if (ldapsam_search_one_user_by_rid(ldap_state, ldap_struct, rid, &result) !=
-           LDAP_SUCCESS)
-       {
+           LDAP_SUCCESS) {
                ldap_unbind(ldap_struct);
                return False;
        }
 
-       if (ldap_count_entries(ldap_struct, result) < 1)
-       {
+       if (ldap_count_entries(ldap_struct, result) < 1) {
                DEBUG(4,
                      ("We don't find this rid [%i] count=%d\n", rid,
                       ldap_count_entries(ldap_struct, result)));
@@ -1345,8 +1343,7 @@ static BOOL ldapsam_getsampwrid(struct pdb_methods *my_methods, SAM_ACCOUNT * us
        }
 
        entry = ldap_first_entry(ldap_struct, result);
-       if (entry)
-       {
+       if (entry) {
                if (!init_sam_from_ldap(ldap_state, user, ldap_struct, entry)) {
                        DEBUG(1,("ldapsam_getsampwrid: init_sam_from_ldap failed!\n"));
                        ldap_msgfree(result);
@@ -1356,9 +1353,7 @@ static BOOL ldapsam_getsampwrid(struct pdb_methods *my_methods, SAM_ACCOUNT * us
                ldap_msgfree(result);
                ldap_unbind(ldap_struct);
                return True;
-       }
-       else
-       {
+       } else {
                ldap_msgfree(result);
                ldap_unbind(ldap_struct);
                return False;
@@ -1373,6 +1368,95 @@ static BOOL ldapsam_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUNT * us
        return ldapsam_getsampwrid(my_methods, user, rid);
 }      
 
+static BOOL ldapsam_modify_entry(LDAP *ldap_struct,SAM_ACCOUNT *newpwd,char *dn,LDAPMod **mods,int ldap_op)
+{
+       int version;
+       int rc;
+       
+       switch(ldap_op)
+       {
+               case LDAP_MOD_ADD: 
+                               make_a_mod(&mods, LDAP_MOD_ADD, "objectclass", "account");
+                               if((rc = ldap_add_s(ldap_struct,dn,mods))!=LDAP_SUCCESS) {
+                                       char *ld_error;
+                                       ldap_get_option(ldap_struct, LDAP_OPT_ERROR_STRING,
+                                       &ld_error);
+                                       DEBUG(0,
+                                               ("failed to add user with uid = %s with: %s\n\t%s\n",
+                                               pdb_get_username(newpwd), ldap_err2string(rc),
+                                               ld_error));
+                                       free(ld_error);
+                                       return False;
+                               }  
+                               break;
+               case LDAP_MOD_REPLACE:  
+                               if((rc = ldap_modify_s(ldap_struct,dn,mods))!=LDAP_SUCCESS) {
+                                       char *ld_error;
+                                       ldap_get_option(ldap_struct, LDAP_OPT_ERROR_STRING,
+                                       &ld_error);
+                                       DEBUG(0,
+                                               ("failed to modify user with uid = %s with: %s\n\t%s\n",
+                                               pdb_get_username(newpwd), ldap_err2string(rc),
+                                               ld_error));
+                                       free(ld_error);
+                                       return False;
+                               }  
+                               break;
+               default:        
+                               DEBUG(0,("Wrong LDAP operation type: %d!\n",ldap_op));
+                               return False;
+       }
+       
+#ifdef LDAP_EXOP_X_MODIFY_PASSWD
+       if (!(pdb_get_acct_ctrl(newpwd)&(ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST))&&
+               (lp_ldap_passwd_sync()!=LDAP_PASSWD_SYNC_OFF)&&
+               (pdb_get_plaintext_passwd(newpwd)!=NULL)) {
+               BerElement *ber;
+               struct berval *bv;
+               char *retoid;
+               struct berval *retdata;
+
+               if (ldap_get_option(ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version) == LDAP_OPT_SUCCESS) {
+                       if (version != LDAP_VERSION3) {
+                               version = LDAP_VERSION3;
+                               ldap_set_option (ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version);
+                       }
+               }
+
+               if ((ber = ber_alloc_t(LBER_USE_DER))==NULL) {
+                       DEBUG(0,("ber_alloc_t returns NULL\n"));
+                       return False;
+               }
+               ber_printf (ber, "{");
+               ber_printf (ber, "ts", LDAP_TAG_EXOP_X_MODIFY_PASSWD_ID,dn);
+               ber_printf (ber, "ts", LDAP_TAG_EXOP_X_MODIFY_PASSWD_NEW, pdb_get_plaintext_passwd(newpwd));
+               ber_printf (ber, "N}");
+
+               if ((rc = ber_flatten (ber, &bv))<0) {
+                       DEBUG(0,("ber_flatten returns a value <0\n"));
+                       return False;
+               }
+               
+               ber_free(ber,1);
+               
+               if ((rc = ldap_extended_operation_s(ldap_struct, LDAP_EXOP_X_MODIFY_PASSWD,
+                                                   bv, NULL, NULL, &retoid, &retdata))!=LDAP_SUCCESS) {
+                       DEBUG(0,("LDAP Password could not be changed for user %s: %s\n",
+                               pdb_get_username(newpwd),ldap_err2string(rc)));
+               } else {
+                       DEBUG(3,("LDAP Password changed for user %s\n",pdb_get_username(newpwd)));
+    
+                       ber_bvfree(retdata);
+                       ber_memfree(retoid);
+               }
+               ber_bvfree(bv);
+       }
+#else
+       DEBUG(10,("LDAP PASSWORD SYNC is not supported!\n"));
+#endif /* LDAP_EXOP_X_MODIFY_PASSWD */
+       return True;
+}
+
 /**********************************************************************
 Delete entry from LDAP for username 
 *********************************************************************/
@@ -1414,7 +1498,8 @@ static BOOL ldapsam_delete_sam_account(struct pdb_methods *my_methods, SAM_ACCOU
 
        entry = ldap_first_entry (ldap_struct, result);
        dn = ldap_get_dn (ldap_struct, entry);
-
+       ldap_msgfree(result);
+       
        rc = ldap_delete_s (ldap_struct, dn);
 
        ldap_memfree (dn);
@@ -1449,8 +1534,7 @@ static BOOL ldapsam_update_sam_account(struct pdb_methods *my_methods, SAM_ACCOU
        if (!ldapsam_open_connection(ldap_state, &ldap_struct)) /* open a connection to the server */
                return False;
 
-       if (!ldapsam_connect_system(ldap_state, ldap_struct))   /* connect as system account */
-       {
+       if (!ldapsam_connect_system(ldap_state, ldap_struct)) { /* connect as system account */
                ldap_unbind(ldap_struct);
                return False;
        }
@@ -1458,8 +1542,7 @@ static BOOL ldapsam_update_sam_account(struct pdb_methods *my_methods, SAM_ACCOU
        rc = ldapsam_search_one_user_by_name(ldap_state, ldap_struct,
                                             pdb_get_username(newpwd), &result);
 
-       if (ldap_count_entries(ldap_struct, result) == 0)
-       {
+       if (ldap_count_entries(ldap_struct, result) == 0) {
                DEBUG(0, ("No user to modify!\n"));
                ldap_msgfree(result);
                ldap_unbind(ldap_struct);
@@ -1475,23 +1558,17 @@ static BOOL ldapsam_update_sam_account(struct pdb_methods *my_methods, SAM_ACCOU
 
        entry = ldap_first_entry(ldap_struct, result);
        dn = ldap_get_dn(ldap_struct, entry);
-
-       rc = ldap_modify_s(ldap_struct, dn, mods);
-
-       if (rc != LDAP_SUCCESS)
-       {
-               char *ld_error;
-               ldap_get_option(ldap_struct, LDAP_OPT_ERROR_STRING,
-                               &ld_error);
-               DEBUG(0,
-                     ("failed to modify user with uid = %s with: %s\n\t%s\n",
-                      pdb_get_username(newpwd), ldap_err2string(rc),
-                      ld_error));
-               free(ld_error);
+        ldap_msgfree(result);
+       
+       if (!ldapsam_modify_entry(ldap_struct,newpwd,dn,mods,LDAP_MOD_REPLACE)) {
+               DEBUG(0,("failed to modify user with uid = %s\n",
+                                       pdb_get_username(newpwd)));
+               ldap_mods_free(mods,1);
                ldap_unbind(ldap_struct);
                return False;
        }
 
+
        DEBUG(2,
              ("successfully modified uid = %s in the LDAP database\n",
               pdb_get_username(newpwd)));
@@ -1514,7 +1591,7 @@ static BOOL ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT
        LDAPMod **mods = NULL;
        int             ldap_op;
        uint32          num_result;
-
+       
        const char *username = pdb_get_username(newpwd);
        if (!username || !*username) {
                DEBUG(0, ("Cannot add user without a username!\n"));
@@ -1522,20 +1599,16 @@ static BOOL ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT
        }
 
        if (!ldapsam_open_connection(ldap_state, &ldap_struct)) /* open a connection to the server */
-       {
                return False;
-       }
 
-       if (!ldapsam_connect_system(ldap_state, ldap_struct))   /* connect as system account */
-       {
+       if (!ldapsam_connect_system(ldap_state, ldap_struct)) { /* connect as system account */
                ldap_unbind(ldap_struct);
                return False;
        }
 
        rc = ldapsam_search_one_user_by_name (ldap_state, ldap_struct, username, &result);
 
-       if (ldap_count_entries(ldap_struct, result) != 0)
-       {
+       if (ldap_count_entries(ldap_struct, result) != 0) {
                DEBUG(0,("User already in the base, with samba properties\n"));
                ldap_msgfree(result);
                ldap_unbind(ldap_struct);
@@ -1564,8 +1637,7 @@ static BOOL ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT
                tmp = ldap_get_dn (ldap_struct, entry);
                slprintf (dn, sizeof (dn) - 1, "%s", tmp);
                ldap_memfree (tmp);
-       }
-       else {
+       } else {
                /* Check if we need to add an entry */
                DEBUG(3,("Adding new user\n"));
                ldap_op = LDAP_MOD_ADD;
@@ -1586,26 +1658,14 @@ static BOOL ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT
        }
        make_a_mod(&mods, LDAP_MOD_ADD, "objectclass", "sambaAccount");
 
-       if (ldap_op == LDAP_MOD_REPLACE) {
-               rc = ldap_modify_s(ldap_struct, dn, mods);
-       }
-       else {
-               rc = ldap_add_s(ldap_struct, dn, mods);
-       }
-
-       if (rc != LDAP_SUCCESS)
-       {
-               char *ld_error;
-
-               ldap_get_option (ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error);
-               DEBUG(0,("failed to modify/add user with uid = %s (dn = %s) with: %s\n\t%s\n",
-                       pdb_get_username(newpwd), dn, ldap_err2string (rc), ld_error));
-               free(ld_error);
-               ldap_mods_free(mods, 1);
+       if (!ldapsam_modify_entry(ldap_struct,newpwd,dn,mods,ldap_op)) {
+               DEBUG(0,("failed to modify/add user with uid = %s (dn = %s)\n",
+                                       pdb_get_username(newpwd),dn));
+               ldap_mods_free(mods,1);
                ldap_unbind(ldap_struct);
                return False;
        }
-       
+
        DEBUG(2,("added: uid = %s in the LDAP database\n", pdb_get_username(newpwd)));
        ldap_mods_free(mods, 1);
        ldap_unbind(ldap_struct);
index 2d37c3b8fbba5967e01d10cc4dbf582f153c6dc1..484e8986e42f57fa64ddd01fd04df6b3e8332014 100644 (file)
@@ -1,10 +1,11 @@
+
 /*
- * Unix SMB/CIFS implementation.
- * SMB parameters and setup
+ * NIS+ Passdb Backend
  * Copyright (C) Andrew Tridgell 1992-1998 Modified by Jeremy Allison 1995.
  * Copyright (C) Benny Holmgren 1998 <bigfoot@astrakan.hgs.se> 
  * Copyright (C) Luke Kenneth Casson Leighton 1996-1998.
  * Copyright (C) Toomas Soome <tsoome@ut.ee> 2001
+ * Copyright (C) Jelmer Vernooij 2002
  * 
  * 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
@@ -35,6 +36,7 @@
  * an enum in /usr/include/rpcsvc/nis.h.
  */
 
+
 #if defined(GROUP)
 #undef GROUP
 #endif
 
 #include <rpcsvc/nis.h>
 
-extern int      DEBUGLEVEL;
-
-struct nisp_enum_info
-{
-       nis_result *result;
-       int enum_entry;
-};
-
-static struct nisp_enum_info global_nisp_ent;
-static SIG_ATOMIC_T gotalarm;
-
 /***************************************************************
 
  the fields for the NIS+ table, generated from mknissmbpwtbl.sh, are:
 
-       name=S,nogw=r 
-       uid=S,nogw=r 
+               name=S,nogw=r 
+               uid=S,nogw=r 
                user_rid=S,nogw=r
                smb_grpid=,nw+r
                group_rid=,nw+r
                acb=,nw+r
-                         
-       lmpwd=C,nw=,g=r,o=rm 
-       ntpwd=C,nw=,g=r,o=rm 
-                                    
+
+               lmpwd=C,nw=,g=r,o=rm 
+               ntpwd=C,nw=,g=r,o=rm 
+
                logon_t=,nw+r 
                logoff_t=,nw+r 
                kick_t=,nw+r 
@@ -114,59 +105,576 @@ static SIG_ATOMIC_T gotalarm;
 #define NPF_WORKSTATIONS  20
 #define NPF_HOURS         21
 
+struct nisplus_private_info {
+       nis_result *result;
+       int enum_entry;
+       char *location;
+};
+
+static char *make_nisname_from_user_rid (uint32 rid, char *pfile);
+static char *make_nisname_from_name (const char *user_name, char *pfile);
+static void get_single_attribute (const nis_object * new_obj, int col,
+                                 char *val, int len);;
+static BOOL make_sam_from_nisp_object (SAM_ACCOUNT * pw_buf,
+                                      const nis_object * obj);
+static BOOL make_sam_from_nisresult (SAM_ACCOUNT * pw_buf,
+                                    const nis_result * result);;
+static void set_single_attribute (nis_object * new_obj, int col,
+                                 const char *val, int len, int flags);
+static BOOL init_nisp_from_sam (nis_object * obj, const SAM_ACCOUNT * sampass,
+                               nis_object * old);
+static nis_result *nisp_get_nis_list (const char *nisname,
+                                     unsigned int flags);
 
-/*******************************************************************
Converts NT user RID to a UNIX uid.
- ********************************************************************/
+/***************************************************************
Start enumeration of the passwd list.
+****************************************************************/
 
-static uid_t pdb_user_rid_to_uid(uint32 user_rid)
+static BOOL nisplussam_setsampwent (struct pdb_methods *methods, BOOL update)
 {
-       return (uid_t)(((user_rid & (~USER_RID_TYPE))- 1000)/RID_MULTIPLIER);
-}
+       struct nisplus_private_info *private =
+               (struct nisplus_private_info *) methods->private_data;
 
-/*******************************************************************
- converts UNIX uid to an NT User RID.
- ********************************************************************/
+       char *sp;
+       pstring pfiletmp;
 
-static uint32 pdb_uid_to_user_rid(uid_t uid)
-{
-       return (((((uint32)uid)*RID_MULTIPLIER) + 1000) | USER_RID_TYPE);
+       if ((sp = strrchr (private->location, '/')))
+               safe_strcpy (pfiletmp, sp + 1, sizeof (pfiletmp) - 1);
+       else
+               safe_strcpy (pfiletmp, p, sizeof (pfiletmp) - 1);
+       safe_strcat (pfiletmp, ".org_dir",
+                    sizeof (pfiletmp) - strlen (pfiletmp) - 1);
+
+       pdb_endsampwent ();     /* just in case */
+       global_nisp_ent->result = nisp_get_nis_list (pfiletmp, 0);
+       global_nisp_ent->enum_entry = 0;
+       return global_nisp_ent->result != NULL ? True : False;
 }
 
 /***************************************************************
Signal function to tell us we timed out.
End enumeration of the passwd list.
 ****************************************************************/
-static void gotalarm_sig(void)
+
+static void nisplussam_endsampwent (struct pdb_methods *methods)
 {
-  gotalarm = 1;
+       struct nisplus_private_info *global_nisp_ent =
+               (struct nisplus_private_info *) methods->private_data;
+       if (global_nisp_ent->result)
+               nis_freeresult (global_nisp_ent->result);
+       global_nisp_ent->result = NULL;
+       global_nisp_ent->enum_entry = 0;
 }
 
-/***************************************************************
- make_nisname_from_user_rid
- ****************************************************************/
-static char *make_nisname_from_user_rid(uint32 rid, char *pfile)
+/*****************************************************************
+ Get one SAM_ACCOUNT from the list (next in line)
+*****************************************************************/
+
+static BOOL nisplussam_getsampwent (struct pdb_methods *methods,
+                                   SAM_ACCOUNT * user)
 {
-       static pstring nisname;
 
-       safe_strcpy(nisname, "[user_rid=", sizeof(nisname)-1);
-       slprintf(nisname, sizeof(nisname)-1, "%s%d", nisname, rid);
-       safe_strcat(nisname, "],", sizeof(nisname)-strlen(nisname)-1);
-       safe_strcat(nisname, pfile, sizeof(nisname)-strlen(nisname)-1);
+       struct nisplus_private_info *global_nisp_ent =
+               (struct nisplus_private_info *) methods->private_data;
+       int enum_entry = (int) (global_nisp_ent->enum_entry);
+       nis_result *result = global_nisp_ent->result;
 
-       return nisname;
+       if (user == NULL) {
+               DEBUG (0, ("SAM_ACCOUNT is NULL.\n"));
+               return False;
+       }
+
+       if (result == NULL ||
+           enum_entry < 0 || enum_entry >= (NIS_RES_NUMOBJ (result) - 1)) {
+               return False;
+       }
+
+       if (!make_sam_from_nisp_object
+           (user, &NIS_RES_OBJECT (result)[enum_entry])) {
+               DEBUG (0, ("Bad SAM_ACCOUNT entry returned from NIS+!\n"));
+               return False;
+       }
+       (int) (global_nisp_ent->enum_entry)++;
+       return True;
+       DEBUG (10, ("nisplussam_getsampwent called\n"));
+       return False;
+}
+
+/******************************************************************
+ Lookup a name in the SAM database
+******************************************************************/
+
+static BOOL nisplussam_getsampwnam (struct pdb_methods *methods,
+                                   SAM_ACCOUNT * user, const char *sname)
+{
+       /* Static buffers we will return. */
+       nis_result *result = NULL;
+       pstring nisname;
+       BOOL ret;
+       struct nisplus_private_info *private =
+               (struct nisplus_private_info *) methods->private_data;
+
+       if (!private->location || !(*private->location)) {
+               DEBUG (0, ("No SMB password file set\n"));
+               return False;
+       }
+       if (strrchr (private->location, '/'))
+               private->location = strrchr (private->location, '/') + 1;
+
+       slprintf (nisname, sizeof (nisname) - 1, "[name=%s],%s.org_dir",
+                 sname, private->location);
+       DEBUG (10, ("search by nisname: %s\n", nisname));
+
+       /* Search the table. */
+
+       if (!(result = nisp_get_nis_list (nisname, 0))) {
+               return False;
+       }
+
+       ret = make_sam_from_nisresult (user, result);
+       nis_freeresult (result);
+
+       return ret;
+
+       DEBUG (10, ("nisplussam_getsampwnam called\n"));
+       return False;
+}
+
+/***************************************************************************
+ Search by sid
+ **************************************************************************/
+
+static BOOL nisplussam_getsampwrid (struct pdb_methods *methods,
+                                   SAM_ACCOUNT * user, uint32 rid)
+{
+       nis_result *result;
+       char *nisname;
+       BOOL ret;
+       char *sp;
+       pstring pfiletmp;
+       struct nisplus_private_info *private =
+               (struct nisplus_private_info *) methods->private_data;
+
+       if (!private->location || !(*private->location)) {
+               DEBUG (0, ("no SMB password file set\n"));
+               return False;
+       }
+
+       if ((sp = strrchr (private->location, '/')))
+               safe_strcpy (pfiletmp, sp + 1, sizeof (pfiletmp) - 1);
+       else
+               safe_strcpy (pfiletmp, private->location, sizeof (pfiletmp) - 1);
+       safe_strcat (pfiletmp, ".org_dir",
+                    sizeof (pfiletmp) - strlen (pfiletmp) - 1);
+
+       nisname = make_nisname_from_user_rid (rid, pfiletmp);
+
+       DEBUG (10, ("search by rid: %s\n", nisname));
+
+       /* Search the table. */
+
+       if (!(result = nisp_get_nis_list (nisname, 0))) {
+               return False;
+       }
+
+       ret = make_sam_from_nisresult (user, result);
+       nis_freeresult (result);
+
+       return ret;
+}
+
+static BOOL nisplussam_getsampwsid (struct pdb_methods *methods,
+                                   SAM_ACCOUNT * user, const DOM_SID * sid)
+{
+       uint32 rid;
+
+       if (!sid_peek_check_rid (get_global_sam_sid (), sid, &rid))
+               return False;
+       return nisplussam_getsampwrid (methods, user, rid);
+}
+
+
+
+/***************************************************************************
+ Delete a SAM_ACCOUNT
+****************************************************************************/
+
+static BOOL nisplussam_delete_sam_account (struct pdb_methods *methods,
+                                          SAM_ACCOUNT * user)
+{
+       const char *sname;
+       pstring nisname;
+       nis_result *result, *delresult;
+       nis_object *obj;
+       struct nisplus_private_info *private =
+               (struct nisplus_private_info *) methods->private_data;
+
+       if (!user) {
+               DEBUG (0, ("no SAM_ACCOUNT specified!\n"));
+               return False;
+       }
+
+       sname = pdb_get_username (user);
+
+       if (!private->location || !(*private->location)) {
+               DEBUG (0, ("no SMB password file set\n"));
+               return False;
+       }
+
+       if (strrchr (private->location, '/'))
+               private->location = strrchr (private->location, '/') + 1;
+
+       slprintf (nisname, sizeof (nisname) - 1, "[name=%s],%s.org_dir",
+                 sname, private->location);
+
+       /* Search the table. */
+
+       if (!(result = nisp_get_nis_list (nisname,
+                                         MASTER_ONLY | FOLLOW_LINKS |
+                                         FOLLOW_PATH | EXPAND_NAME |
+                                         HARD_LOOKUP))) {
+               return False;
+       }
+
+       if (result->status != NIS_SUCCESS || NIS_RES_NUMOBJ (result) <= 0) {
+               /* User not found. */
+               DEBUG (0, ("user not found in NIS+\n"));
+               nis_freeresult (result);
+               return False;
+       }
+
+       obj = NIS_RES_OBJECT (result);
+       slprintf (nisname, sizeof (nisname) - 1, "[name=%s],%s.%s", sname,
+                 obj->zo_name, obj->zo_domain);
+
+       DEBUG (10, ("removing name: %s\n", nisname));
+       delresult = nis_remove_entry (nisname, obj,
+                                     MASTER_ONLY | REM_MULTIPLE | ALL_RESULTS
+                                     | FOLLOW_PATH | EXPAND_NAME |
+                                     HARD_LOOKUP);
+
+       nis_freeresult (result);
+
+       if (delresult->status != NIS_SUCCESS) {
+               DEBUG (0, ("NIS+ table update failed: %s %s\n",
+                          nisname, nis_sperrno (delresult->status)));
+               nis_freeresult (delresult);
+               return False;
+       }
+       nis_freeresult (delresult);
+       return True;
+       DEBUG (10, ("nisplussam_delete_sam_account called\n"));
+       return False;
+}
+
+/***************************************************************************
+ Modifies an existing SAM_ACCOUNT
+****************************************************************************/
+
+static BOOL nisplussam_update_sam_account (struct pdb_methods *methods,
+                                          SAM_ACCOUNT * newpwd)
+{
+       nis_result *result, *addresult;
+       nis_object *obj;
+       nis_object new_obj;
+       entry_col *ecol;
+       int ta_maxcol;
+       struct nisplus_private_info *private =
+               (struct nisplus_private_info *) methods->private_data;
+       pstring nisname;
+
+       if (!private->location || !(*private->location)) {
+               DEBUG (0, ("no SMB password file set\n"));
+               return False;
+       }
+       if (strrchr (private->location, '/'))
+               private->location = strrchr (private->location, '/') + 1;
+
+       slprintf (nisname, sizeof (nisname) - 1, "[name=%s],%s.org_dir",
+                 pdb_get_username (newpwd), private->location);
+
+       DEBUG (10, ("search by name: %s\n", nisname));
+
+       /* Search the table. */
+
+       if (!
+           (result =
+            nisp_get_nis_list (nisname,
+                               MASTER_ONLY | FOLLOW_LINKS | FOLLOW_PATH |
+                               EXPAND_NAME | HARD_LOOKUP))) {
+               return False;
+       }
+
+       if (result->status != NIS_SUCCESS || NIS_RES_NUMOBJ (result) <= 0) {
+               /* User not found. */
+               DEBUG (0, ("user not found in NIS+\n"));
+               nis_freeresult (result);
+               return False;
+       }
+
+       obj = NIS_RES_OBJECT (result);
+       DEBUG (6, ("entry found in %s\n", obj->zo_domain));
+
+       /* we must create new stub object with EN_MODIFIED flag.
+          this is because obj from result is going to be freed and
+          we do not want to break it or cause memory leaks or corruption.
+        */
+
+       memmove ((char *) &new_obj, obj, sizeof (new_obj));
+       ta_maxcol = obj->TA_data.ta_maxcol;
+
+       if (!(ecol = (entry_col *) malloc (ta_maxcol * sizeof (entry_col)))) {
+               DEBUG (0, ("memory allocation failure\n"));
+               nis_freeresult (result);
+               return False;
+       }
+
+       memmove ((char *) ecol, obj->EN_data.en_cols.en_cols_val,
+                ta_maxcol * sizeof (entry_col));
+       new_obj.EN_data.en_cols.en_cols_val = ecol;
+       new_obj.EN_data.en_cols.en_cols_len = ta_maxcol;
+
+       if (init_nisp_from_sam (&new_obj, newpwd, obj) == True) {
+               slprintf (nisname, sizeof (nisname) - 1, "[name=%s],%s.%s",
+                         pdb_get_username (newpwd), private->location, obj->zo_domain);
+
+               DEBUG (10, ("NIS+ table update: %s\n", nisname));
+               addresult =
+                       nis_modify_entry (nisname, &new_obj,
+                                         MOD_SAMEOBJ | FOLLOW_PATH |
+                                         EXPAND_NAME | HARD_LOOKUP);
+
+               if (addresult->status != NIS_SUCCESS) {
+                       DEBUG (0, ("NIS+ table update failed: %s %s\n",
+                                  nisname, nis_sperrno (addresult->status)));
+                       nis_freeresult (addresult);
+                       nis_freeresult (result);
+                       free (ecol);
+                       return False;
+               }
+
+               DEBUG (6, ("password changed\n"));
+               nis_freeresult (addresult);
+       } else {
+               DEBUG (6, ("nothing to change!\n"));
+       }
+
+       free (ecol);
+       nis_freeresult (result);
+
+       return True;
+}
+
+/***************************************************************************
+ Adds an existing SAM_ACCOUNT
+****************************************************************************/
+
+static BOOL nisplussam_add_sam_account (struct pdb_methods *methods,
+                                       SAM_ACCOUNT * newpwd)
+{
+       int local_user = 0;
+       char *pfile;
+       pstring pfiletmp;
+       char *nisname;
+       nis_result *result = NULL, *tblresult = NULL;
+       nis_object new_obj;
+       entry_col *ecol;
+       int ta_maxcol;
+
+       /*
+        * 1. find user domain.
+        *   a. try nis search in passwd.org_dir - if found use domain from result.
+        *   b. try getpwnam. this may be needed if user is defined
+        *      in /etc/passwd file (or elsewere) and not in passwd.org_dir.
+        *      if found, use host default domain.
+        *   c. exit with False - no such user.
+        *
+        * 2. add user
+        *   a. find smbpasswd table
+        *      search pfile in user domain if not found, try host default
+        *      domain. 
+        *   b. smbpasswd domain is found, fill data and add entry.
+        *
+        * pfile should contain ONLY table name, org_dir will be concated.
+        * so, at first we will clear path prefix from pfile, and
+        * then we will use pfiletmp as playground to put together full
+        * nisname string.
+        * such approach will make it possible to specify samba private dir
+        * AND still use NIS+ table. as all domain related data is normally
+        * stored in org_dir.DOMAIN, this should be ok do do.
+        */
+
+       pfile = private->location;
+       if (strrchr (pfile, '/'))
+               pfile = strrchr (pfile, '/') + 1;
+
+       /*
+        * Check if user is already there.
+        */
+       safe_strcpy (pfiletmp, pfile, sizeof (pfiletmp) - 1);
+       safe_strcat (pfiletmp, ".org_dir",
+                    sizeof (pfiletmp) - strlen (pfiletmp) - 1);
+
+       if (pdb_get_username (newpwd) != NULL) {
+               nisname = make_nisname_from_name (pdb_get_username (newpwd),
+                                                 pfiletmp);
+       } else {
+               return False;
+       }
+
+       if (!
+           (result =
+            nisp_get_nis_list (nisname,
+                               MASTER_ONLY | FOLLOW_LINKS | FOLLOW_PATH |
+                               EXPAND_NAME | HARD_LOOKUP))) {
+               return False;
+       }
+       if (result->status != NIS_SUCCESS && result->status != NIS_NOTFOUND) {
+               DEBUG (3, ("nis_list failure: %s: %s\n",
+                          nisname, nis_sperrno (result->status)));
+               nis_freeresult (result);
+               return False;
+       }
+
+       if (result->status == NIS_SUCCESS && NIS_RES_NUMOBJ (result) > 0) {
+               DEBUG (3, ("User already exists in NIS+ password db: %s\n",
+                          pfile));
+               nis_freeresult (result);
+               return False;
+       }
+
+       nis_freeresult (result);        /* no such user, free results */
+
+       /*
+        * check for user in unix password database. we need this to get
+        * domain, where smbpasswd entry should be stored.
+        */
+
+       nisname = make_nisname_from_name (pdb_get_username (newpwd),
+                                         "passwd.org_dir");
+
+       result = nisp_get_nis_list (nisname,
+                                   MASTER_ONLY | FOLLOW_LINKS | FOLLOW_PATH |
+                                   EXPAND_NAME | HARD_LOOKUP);
+
+       if (result->status != NIS_SUCCESS || NIS_RES_NUMOBJ (result) <= 0) {
+               struct passwd *passwd;
+
+               DEBUG (3, ("nis_list failure: %s: %s\n",
+                          nisname, nis_sperrno (result->status)));
+               nis_freeresult (result);
+
+               if (!(passwd = getpwnam_alloc (pdb_get_username (newpwd)))) {
+                       /* no such user in system! */
+                       return False;
+               }
+               passwd_free (&passwd);
+
+               /* 
+                * user is defined, but not in passwd.org_dir.
+                */
+               local_user = 1;
+       } else {
+               safe_strcpy (pfiletmp, pfile, sizeof (pfiletmp) - 1);
+               safe_strcat (pfiletmp, ".",
+                            sizeof (pfiletmp) - strlen (pfiletmp) - 1);
+               safe_strcat (pfiletmp, NIS_RES_OBJECT (result)->zo_domain,
+                            sizeof (pfiletmp) - strlen (pfiletmp) - 1);
+               nis_freeresult (result);        /* not needed any more */
+
+               tblresult = nisp_get_nis_list (pfiletmp,
+                                              MASTER_ONLY | FOLLOW_LINKS |
+                                              FOLLOW_PATH | EXPAND_NAME |
+                                              HARD_LOOKUP);
+       }
+
+       if (local_user || tblresult->status != NIS_SUCCESS) {
+               /*
+                * no user domain or
+                * smbpasswd table not found in user domain, fallback to
+                * default domain.
+                */
+               if (!local_user)        /* free previous failed search result */
+                       nis_freeresult (tblresult);
+
+               safe_strcpy (pfiletmp, pfile, sizeof (pfiletmp) - 1);
+               safe_strcat (pfiletmp, ".org_dir",
+                            sizeof (pfiletmp) - strlen (pfiletmp) - 1);
+               tblresult = nis_lookup (pfiletmp, MASTER_ONLY | FOLLOW_LINKS |
+                                       FOLLOW_PATH | EXPAND_NAME |
+                                       HARD_LOOKUP);
+               if (tblresult->status != NIS_SUCCESS) {
+                       /* still nothing. bail out */
+                       nis_freeresult (tblresult);
+                       DEBUG (3, ("nis_lookup failure: %s\n",
+                                  nis_sperrno (tblresult->status)));
+                       return False;
+               }
+               /* we need full name for nis_add_entry() */
+               safe_strcpy (pfiletmp, pfile, sizeof (pfiletmp) - 1);
+               safe_strcat (pfiletmp, ".",
+                            sizeof (pfiletmp) - strlen (pfiletmp) - 1);
+               safe_strcat (pfiletmp, NIS_RES_OBJECT (tblresult)->zo_domain,
+                            sizeof (pfiletmp) - strlen (pfiletmp) - 1);
+       }
+
+       memset ((char *) &new_obj, 0, sizeof (new_obj));
+       /* fill entry headers */
+       /* we do not free these. */
+       new_obj.zo_name = NIS_RES_OBJECT (tblresult)->zo_name;
+       new_obj.zo_owner = NIS_RES_OBJECT (tblresult)->zo_owner;
+       new_obj.zo_group = NIS_RES_OBJECT (tblresult)->zo_group;
+       new_obj.zo_domain = NIS_RES_OBJECT (tblresult)->zo_domain;
+       /* uints */
+       new_obj.zo_access = NIS_RES_OBJECT (tblresult)->zo_access;
+       new_obj.zo_ttl = NIS_RES_OBJECT (tblresult)->zo_ttl;
+
+       new_obj.zo_data.zo_type = ENTRY_OBJ;
+       new_obj.EN_data.en_type = NIS_RES_OBJECT (tblresult)->TA_data.ta_type;
+
+       ta_maxcol = NIS_RES_OBJECT (tblresult)->TA_data.ta_maxcol;
+
+       if (!(ecol = (entry_col *) malloc (ta_maxcol * sizeof (entry_col)))) {
+               DEBUG (0, ("memory allocation failure\n"));
+               nis_freeresult (tblresult);
+               return False;
+       }
+
+       memset ((char *) ecol, 0, ta_maxcol * sizeof (entry_col));
+       new_obj.EN_data.en_cols.en_cols_val = ecol;
+       new_obj.EN_data.en_cols.en_cols_len = ta_maxcol;
+
+       init_nisp_from_sam (&new_obj, newpwd, NULL);
+
+       DEBUG (10, ("add NIS+ entry: %s\n", nisname));
+       result = nis_add_entry (pfiletmp, &new_obj, 0);
+
+       free (ecol);            /* free allocated entry space */
+
+       if (result->status != NIS_SUCCESS) {
+               DEBUG (3, ("NIS+ table update failed: %s,%s\n",
+                          nisname, nis_sperrno (result->status)));
+               nis_freeresult (tblresult);
+               nis_freeresult (result);
+               return False;
+       }
+
+       nis_freeresult (tblresult);
+       nis_freeresult (result);
+
+       return True;
 }
 
 /***************************************************************
- make_nisname_from_uid
+ make_nisname_from_user_rid
  ****************************************************************/
-static char *make_nisname_from_uid(int uid, char *pfile)
+static char *make_nisname_from_user_rid (uint32 rid, char *pfile)
 {
        static pstring nisname;
 
-       safe_strcpy(nisname, "[uid=", sizeof(nisname)-1);
-       slprintf(nisname, sizeof(nisname)-1, "%s%d", nisname, uid);
-       safe_strcat(nisname, "],", sizeof(nisname)-strlen(nisname)-1);
-       safe_strcat(nisname, pfile, sizeof(nisname)-strlen(nisname)-1);
+       safe_strcpy (nisname, "[user_rid=", sizeof (nisname) - 1);
+       slprintf (nisname, sizeof (nisname) - 1, "%s%d", nisname, rid);
+       safe_strcat (nisname, "],", sizeof (nisname) - strlen (nisname) - 1);
+       safe_strcat (nisname, pfile, sizeof (nisname) - strlen (nisname) - 1);
 
        return nisname;
 }
@@ -174,14 +682,15 @@ static char *make_nisname_from_uid(int uid, char *pfile)
 /***************************************************************
  make_nisname_from_name
  ****************************************************************/
-static char *make_nisname_from_name(const char *user_name, char *pfile)
+static char *make_nisname_from_name (const char *user_name, char *pfile)
 {
        static pstring nisname;
 
-       safe_strcpy(nisname, "[name=", sizeof(nisname)-1);
-       safe_strcat(nisname, user_name, sizeof(nisname) - strlen(nisname) - 1);
-       safe_strcat(nisname, "],", sizeof(nisname)-strlen(nisname)-1);
-       safe_strcat(nisname, pfile, sizeof(nisname)-strlen(nisname)-1);
+       safe_strcpy (nisname, "[name=", sizeof (nisname) - 1);
+       safe_strcat (nisname, user_name,
+                    sizeof (nisname) - strlen (nisname) - 1);
+       safe_strcat (nisname, "],", sizeof (nisname) - strlen (nisname) - 1);
+       safe_strcat (nisname, pfile, sizeof (nisname) - strlen (nisname) - 1);
 
        return nisname;
 }
@@ -189,297 +698,323 @@ static char *make_nisname_from_name(const char *user_name, char *pfile)
 /*************************************************************************
  gets a NIS+ attribute
  *************************************************************************/
-static void get_single_attribute(const nis_object *new_obj, int col,
-                               char *val, int len)
+static void get_single_attribute (const nis_object * new_obj, int col,
+                                 char *val, int len)
 {
        int entry_len;
 
-       if (new_obj == NULL || val == NULL) return;
-       
-       entry_len = ENTRY_LEN(new_obj, col);
-       if (len > entry_len)
-       {
+       if (new_obj == NULL || val == NULL)
+               return;
+
+       entry_len = ENTRY_LEN (new_obj, col);
+       if (len > entry_len) {
                len = entry_len;
        }
 
-       safe_strcpy(val, ENTRY_VAL(new_obj, col), len-1);
+       safe_strcpy (val, ENTRY_VAL (new_obj, col), len - 1);
 }
 
 /************************************************************************
  makes a struct sam_passwd from a NIS+ object.
  ************************************************************************/
-static BOOL make_sam_from_nisp_object(SAM_ACCOUNT *pw_buf, const nis_object *obj)
+static BOOL make_sam_from_nisp_object (SAM_ACCOUNT * pw_buf,
+                                      const nis_object * obj)
 {
-  char *ptr;
-  pstring full_name;    /* this must be translated to dos code page */
-  pstring acct_desc;    /* this must be translated to dos code page */
-  pstring home_dir;     /* set default value from smb.conf for user */
-  pstring home_drive;   /* set default value from smb.conf for user */
-  pstring logon_script; /* set default value from smb.conf for user */
-  pstring profile_path; /* set default value from smb.conf for user */
-  pstring hours;
-  int hours_len;
-  unsigned char smbpwd[16];
-  unsigned char smbntpwd[16];
-  
-
-  /*
-   * time values. note: this code assumes 32bit time_t!
-   */
-
-  /* Don't change these timestamp settings without a good reason.  They are
-     important for NT member server compatibility. */
-
-  pdb_set_logon_time(pw_buf, (time_t)0, True);
-  ptr = (uchar *)ENTRY_VAL(obj, NPF_LOGON_T);
-  if(ptr && *ptr && (StrnCaseCmp(ptr, "LNT-", 4)==0)) {
-    int i;
-    ptr += 4;
-    for(i = 0; i < 8; i++) {
-      if(ptr[i] == '\0' || !isxdigit(ptr[i]))
-       break;
-    }
-    if(i == 8) {
-      pdb_set_logon_time(pw_buf, (time_t)strtol(ptr, NULL, 16), True);
-    }
-  }
-
-  pdb_set_logoff_time(pw_buf, get_time_t_max(), True);
-  ptr = (uchar *)ENTRY_VAL(obj, NPF_LOGOFF_T);
-  if(ptr && *ptr && (StrnCaseCmp(ptr, "LOT-", 4)==0)) {
-    int i;
-    ptr += 4;
-    for(i = 0; i < 8; i++) {
-      if(ptr[i] == '\0' || !isxdigit(ptr[i]))
-       break;
-    }
-    if(i == 8) {
-      pdb_set_logoff_time(pw_buf, (time_t)strtol(ptr, NULL, 16), True);
-    }
-  }
-
-  pdb_set_kickoff_time(pw_buf, get_time_t_max(), True);
-  ptr = (uchar *)ENTRY_VAL(obj, NPF_KICK_T);
-  if(ptr && *ptr && (StrnCaseCmp(ptr, "KOT-", 4)==0)) {
-    int i;
-    ptr += 4;
-    for(i = 0; i < 8; i++) {
-      if(ptr[i] == '\0' || !isxdigit(ptr[i]))
-       break;
-    }
-    if(i == 8) {
-      pdb_set_kickoff_time(pw_buf, (time_t)strtol(ptr, NULL, 16), True);
-    }
-  }
-
-  pdb_set_pass_last_set_time(pw_buf, (time_t)0);
-  ptr = (uchar *)ENTRY_VAL(obj, NPF_PWDLSET_T);
-  if(ptr && *ptr && (StrnCaseCmp(ptr, "LCT-", 4)==0)) {
-    int i;
-    ptr += 4;
-    for(i = 0; i < 8; i++) {
-      if(ptr[i] == '\0' || !isxdigit(ptr[i]))
-       break;
-    }
-    if(i == 8) {
-      pdb_set_pass_last_set_time(pw_buf, (time_t)strtol(ptr, NULL, 16));
-    }
-  }
-  
-  pdb_set_pass_can_change_time(pw_buf, (time_t)0, True);
-  ptr = (uchar *)ENTRY_VAL(obj, NPF_PWDCCHG_T);
-  if(ptr && *ptr && (StrnCaseCmp(ptr, "CCT-", 4)==0)) {
-    int i;
-    ptr += 4;
-    for(i = 0; i < 8; i++) {
-      if(ptr[i] == '\0' || !isxdigit(ptr[i]))
-       break;
-    }
-    if(i == 8) {
-      pdb_set_pass_can_change_time(pw_buf, (time_t)strtol(ptr, NULL, 16), True);
-    }
-  }
-  
-  pdb_set_pass_must_change_time(pw_buf, get_time_t_max(), True); /* Password never expires. */
-  ptr = (uchar *)ENTRY_VAL(obj, NPF_PWDMCHG_T);
-  if(ptr && *ptr && (StrnCaseCmp(ptr, "MCT-", 4)==0)) {
-    int i;
-    ptr += 4;
-    for(i = 0; i < 8; i++) {
-      if(ptr[i] == '\0' || !isxdigit(ptr[i]))
-       break;
-    }
-    if(i == 8) {
-      pdb_set_pass_must_change_time(pw_buf, (time_t)strtol(ptr, NULL, 16), True);
-    }
-  }
-
-  /* string values */
-  pdb_set_username(pw_buf, ENTRY_VAL(obj, NPF_NAME));
-  pdb_set_domain(pw_buf, lp_workgroup());
-  /* pdb_set_nt_username() -- cant set it here... */
-
-  get_single_attribute(obj, NPF_FULL_NAME, full_name, sizeof(pstring));
+       char *ptr;
+       pstring full_name;      /* this must be translated to dos code page */
+       pstring acct_desc;      /* this must be translated to dos code page */
+       pstring home_dir;       /* set default value from smb.conf for user */
+       pstring home_drive;     /* set default value from smb.conf for user */
+       pstring logon_script;   /* set default value from smb.conf for user */
+       pstring profile_path;   /* set default value from smb.conf for user */
+       pstring hours;
+       int hours_len;
+       unsigned char smbpwd[16];
+       unsigned char smbntpwd[16];
+
+
+       /*
+        * time values. note: this code assumes 32bit time_t!
+        */
+
+       /* Don't change these timestamp settings without a good reason.  They are
+          important for NT member server compatibility. */
+
+       pdb_set_logon_time (pw_buf, (time_t) 0, True);
+       ptr = (uchar *) ENTRY_VAL (obj, NPF_LOGON_T);
+       if (ptr && *ptr && (StrnCaseCmp (ptr, "LNT-", 4) == 0)) {
+               int i;
+
+               ptr += 4;
+               for (i = 0; i < 8; i++) {
+                       if (ptr[i] == '\0' || !isxdigit (ptr[i]))
+                               break;
+               }
+               if (i == 8) {
+                       pdb_set_logon_time (pw_buf,
+                                           (time_t) strtol (ptr, NULL, 16),
+                                           True);
+               }
+       }
+
+       pdb_set_logoff_time (pw_buf, get_time_t_max (), True);
+       ptr = (uchar *) ENTRY_VAL (obj, NPF_LOGOFF_T);
+       if (ptr && *ptr && (StrnCaseCmp (ptr, "LOT-", 4) == 0)) {
+               int i;
+
+               ptr += 4;
+               for (i = 0; i < 8; i++) {
+                       if (ptr[i] == '\0' || !isxdigit (ptr[i]))
+                               break;
+               }
+               if (i == 8) {
+                       pdb_set_logoff_time (pw_buf,
+                                            (time_t) strtol (ptr, NULL, 16),
+                                            True);
+               }
+       }
+
+       pdb_set_kickoff_time (pw_buf, get_time_t_max (), True);
+       ptr = (uchar *) ENTRY_VAL (obj, NPF_KICK_T);
+       if (ptr && *ptr && (StrnCaseCmp (ptr, "KOT-", 4) == 0)) {
+               int i;
+
+               ptr += 4;
+               for (i = 0; i < 8; i++) {
+                       if (ptr[i] == '\0' || !isxdigit (ptr[i]))
+                               break;
+               }
+               if (i == 8) {
+                       pdb_set_kickoff_time (pw_buf,
+                                             (time_t) strtol (ptr, NULL, 16),
+                                             True);
+               }
+       }
+
+       pdb_set_pass_last_set_time (pw_buf, (time_t) 0);
+       ptr = (uchar *) ENTRY_VAL (obj, NPF_PWDLSET_T);
+       if (ptr && *ptr && (StrnCaseCmp (ptr, "LCT-", 4) == 0)) {
+               int i;
+
+               ptr += 4;
+               for (i = 0; i < 8; i++) {
+                       if (ptr[i] == '\0' || !isxdigit (ptr[i]))
+                               break;
+               }
+               if (i == 8) {
+                       pdb_set_pass_last_set_time (pw_buf,
+                                                   (time_t) strtol (ptr,
+                                                                    NULL,
+                                                                    16));
+               }
+       }
+
+       pdb_set_pass_can_change_time (pw_buf, (time_t) 0, True);
+       ptr = (uchar *) ENTRY_VAL (obj, NPF_PWDCCHG_T);
+       if (ptr && *ptr && (StrnCaseCmp (ptr, "CCT-", 4) == 0)) {
+               int i;
+
+               ptr += 4;
+               for (i = 0; i < 8; i++) {
+                       if (ptr[i] == '\0' || !isxdigit (ptr[i]))
+                               break;
+               }
+               if (i == 8) {
+                       pdb_set_pass_can_change_time (pw_buf,
+                                                     (time_t) strtol (ptr,
+                                                                      NULL,
+                                                                      16),
+                                                     True);
+               }
+       }
+
+       pdb_set_pass_must_change_time (pw_buf, get_time_t_max (), True);        /* Password never expires. */
+       ptr = (uchar *) ENTRY_VAL (obj, NPF_PWDMCHG_T);
+       if (ptr && *ptr && (StrnCaseCmp (ptr, "MCT-", 4) == 0)) {
+               int i;
+
+               ptr += 4;
+               for (i = 0; i < 8; i++) {
+                       if (ptr[i] == '\0' || !isxdigit (ptr[i]))
+                               break;
+               }
+               if (i == 8) {
+                       pdb_set_pass_must_change_time (pw_buf,
+                                                      (time_t) strtol (ptr,
+                                                                       NULL,
+                                                                       16),
+                                                      True);
+               }
+       }
+
+       /* string values */
+       pdb_set_username (pw_buf, ENTRY_VAL (obj, NPF_NAME));
+       pdb_set_domain (pw_buf, lp_workgroup ());
+       /* pdb_set_nt_username() -- cant set it here... */
+
+       get_single_attribute (obj, NPF_FULL_NAME, full_name,
+                             sizeof (pstring));
 #if 0
-  unix_to_dos(full_name, True);
+       unix_to_dos (full_name, True);
 #endif
-  pdb_set_fullname(pw_buf, full_name);
+       pdb_set_fullname (pw_buf, full_name);
 
-  pdb_set_acct_ctrl(pw_buf, pdb_decode_acct_ctrl(ENTRY_VAL(obj,
-                                                          NPF_ACB)));
+       pdb_set_acct_ctrl (pw_buf, pdb_decode_acct_ctrl (ENTRY_VAL (obj,
+                                                                   NPF_ACB)));
 
-  get_single_attribute(obj, NPF_ACCT_DESC, acct_desc, sizeof(pstring));
+       get_single_attribute (obj, NPF_ACCT_DESC, acct_desc,
+                             sizeof (pstring));
 #if 0
-  unix_to_dos(acct_desc, True);
+       unix_to_dos (acct_desc, True);
 #endif
-  pdb_set_acct_desc(pw_buf, acct_desc);
-
-  pdb_set_workstations(pw_buf, ENTRY_VAL(obj, NPF_WORKSTATIONS));
-  pdb_set_munged_dial(pw_buf, NULL);
-
-  pdb_set_uid(pw_buf, atoi(ENTRY_VAL(obj, NPF_UID)));
-  pdb_set_gid(pw_buf, atoi(ENTRY_VAL(obj, NPF_SMB_GRPID)));
-  pdb_set_user_sid_from_rid(pw_buf, atoi(ENTRY_VAL(obj, NPF_USER_RID)));
-  pdb_set_group_sid_from_rid(pw_buf, atoi(ENTRY_VAL(obj, NPF_GROUP_RID)));
-
-  /* values, must exist for user */
-  if( !(pdb_get_acct_ctrl(pw_buf) & ACB_WSTRUST) ) {
-    
-    get_single_attribute(obj, NPF_HOME_DIR, home_dir, sizeof(pstring));
-    if( !(home_dir && *home_dir) ) {
-      pstrcpy(home_dir, lp_logon_home());
-      pdb_set_homedir(pw_buf, home_dir, False);
-    }
-    else
-      pdb_set_homedir(pw_buf, home_dir, True);
-
-    get_single_attribute(obj, NPF_DIR_DRIVE, home_drive, sizeof(pstring));
-    if( !(home_drive && *home_drive) ) {
-      pstrcpy(home_drive, lp_logon_drive());
-      pdb_set_dir_drive(pw_buf, home_drive, False);
-    }
-    else
-      pdb_set_dir_drive(pw_buf, home_drive, True);
-
-    get_single_attribute(obj, NPF_LOGON_SCRIPT, logon_script,
-                        sizeof(pstring));
-    if( !(logon_script && *logon_script) ) {
-      pstrcpy(logon_script, lp_logon_script());
-    }
-    else
-      pdb_set_logon_script(pw_buf, logon_script, True);
-
-    get_single_attribute(obj, NPF_PROFILE_PATH, profile_path, sizeof(pstring));
-    if( !(profile_path && *profile_path) ) {
-      pstrcpy(profile_path, lp_logon_path());
-      pdb_set_profile_path(pw_buf, profile_path, False);
-    }
-    else
-      pdb_set_profile_path(pw_buf, profile_path, True);
-
-  } 
-  else 
-  {
-    /* lkclXXXX this is OBSERVED behaviour by NT PDCs, enforced here. */
-    pdb_set_group_sid_from_rid (pw_buf, DOMAIN_GROUP_RID_USERS); 
-  }
-
-  /* Check the lanman password column. */
-  ptr = (char *)ENTRY_VAL(obj, NPF_LMPWD);
-  if (!pdb_set_lanman_passwd(pw_buf, NULL))
-       return False;
+       pdb_set_acct_desc (pw_buf, acct_desc);
+
+       pdb_set_workstations (pw_buf, ENTRY_VAL (obj, NPF_WORKSTATIONS));
+       pdb_set_munged_dial (pw_buf, NULL);
+
+       pdb_set_uid (pw_buf, atoi (ENTRY_VAL (obj, NPF_UID)));
+       pdb_set_gid (pw_buf, atoi (ENTRY_VAL (obj, NPF_SMB_GRPID)));
+       pdb_set_user_sid_from_rid (pw_buf,
+                                  atoi (ENTRY_VAL (obj, NPF_USER_RID)));
+       pdb_set_group_sid_from_rid (pw_buf,
+                                   atoi (ENTRY_VAL (obj, NPF_GROUP_RID)));
+
+       /* values, must exist for user */
+       if (!(pdb_get_acct_ctrl (pw_buf) & ACB_WSTRUST)) {
+
+               get_single_attribute (obj, NPF_HOME_DIR, home_dir,
+                                     sizeof (pstring));
+               if (!(home_dir && *home_dir)) {
+                       pstrcpy (home_dir, lp_logon_home ());
+                       pdb_set_homedir (pw_buf, home_dir, False);
+               } else
+                       pdb_set_homedir (pw_buf, home_dir, True);
+
+               get_single_attribute (obj, NPF_DIR_DRIVE, home_drive,
+                                     sizeof (pstring));
+               if (!(home_drive && *home_drive)) {
+                       pstrcpy (home_drive, lp_logon_drive ());
+                       pdb_set_dir_drive (pw_buf, home_drive, False);
+               } else
+                       pdb_set_dir_drive (pw_buf, home_drive, True);
+
+               get_single_attribute (obj, NPF_LOGON_SCRIPT, logon_script,
+                                     sizeof (pstring));
+               if (!(logon_script && *logon_script)) {
+                       pstrcpy (logon_script, lp_logon_script ());
+               } else
+                       pdb_set_logon_script (pw_buf, logon_script, True);
+
+               get_single_attribute (obj, NPF_PROFILE_PATH, profile_path,
+                                     sizeof (pstring));
+               if (!(profile_path && *profile_path)) {
+                       pstrcpy (profile_path, lp_logon_path ());
+                       pdb_set_profile_path (pw_buf, profile_path, False);
+               } else
+                       pdb_set_profile_path (pw_buf, profile_path, True);
+
+       } else {
+               /* lkclXXXX this is OBSERVED behaviour by NT PDCs, enforced here. */
+               pdb_set_group_sid_from_rid (pw_buf, DOMAIN_GROUP_RID_USERS);
+       }
 
-  if (!strncasecmp(ptr, "NO PASSWORD", 11)) {
-    pdb_set_acct_ctrl(pw_buf, pdb_get_acct_ctrl(pw_buf) | ACB_PWNOTREQ);
-  } else {
-    if (strlen(ptr) != 32 || !pdb_gethexpwd(ptr, smbpwd)) {
-      DEBUG(0, ("malformed LM pwd entry: %s.\n",
-               pdb_get_username(pw_buf)));
-      return False;
-    } 
-    if (!pdb_set_lanman_passwd(pw_buf, smbpwd))
+       /* Check the lanman password column. */
+       ptr = (char *) ENTRY_VAL (obj, NPF_LMPWD);
+       if (!pdb_set_lanman_passwd (pw_buf, NULL))
                return False;
-  }
-  
-  /* Check the NT password column. */
-  ptr = ENTRY_VAL(obj, NPF_NTPWD);
-  if (!pdb_set_nt_passwd(pw_buf, NULL))
-       return False;
-  
-  if (!(pdb_get_acct_ctrl(pw_buf) & ACB_PWNOTREQ) &&
-      strncasecmp(ptr, "NO PASSWORD", 11)) {
-    if (strlen(ptr) != 32 || !pdb_gethexpwd(ptr, smbntpwd)) {
-      DEBUG(0, ("malformed NT pwd entry:\
- uid = %d.\n",
-               pdb_get_uid(pw_buf)));
-      return False;
-    }
-    if (!pdb_set_nt_passwd(pw_buf, smbntpwd))
+
+       if (!strncasecmp (ptr, "NO PASSWORD", 11)) {
+               pdb_set_acct_ctrl (pw_buf,
+                                  pdb_get_acct_ctrl (pw_buf) | ACB_PWNOTREQ);
+       } else {
+               if (strlen (ptr) != 32 || !pdb_gethexpwd (ptr, smbpwd)) {
+                       DEBUG (0, ("malformed LM pwd entry: %s.\n",
+                                  pdb_get_username (pw_buf)));
+                       return False;
+               }
+               if (!pdb_set_lanman_passwd (pw_buf, smbpwd))
+                       return False;
+       }
+
+       /* Check the NT password column. */
+       ptr = ENTRY_VAL (obj, NPF_NTPWD);
+       if (!pdb_set_nt_passwd (pw_buf, NULL))
                return False;
-  }
-  
-  pdb_set_unknown_3(pw_buf, 0xffffff); /* don't know */
-  pdb_set_logon_divs(pw_buf, 168);     /* hours per week */
-                     
-                     if( (hours_len = ENTRY_LEN(obj, NPF_HOURS)) == 21 ) {
-    memcpy(hours, ENTRY_VAL(obj, NPF_HOURS), hours_len);
-  } else {
-    hours_len = 21; /* 21 times 8 bits = 168 */
-    /* available at all hours */
-    memset(hours, 0xff, hours_len);
-  }
-  pdb_set_hours_len(pw_buf, hours_len);
-  pdb_set_hours(pw_buf, hours);
-
-  pdb_set_unknown_5(pw_buf, 0x00020000); /* don't know */
-  pdb_set_unknown_6(pw_buf, 0x000004ec); /* don't know */
-
-  return True;
+
+       if (!(pdb_get_acct_ctrl (pw_buf) & ACB_PWNOTREQ) &&
+           strncasecmp (ptr, "NO PASSWORD", 11)) {
+               if (strlen (ptr) != 32 || !pdb_gethexpwd (ptr, smbntpwd)) {
+                       DEBUG (0, ("malformed NT pwd entry:\
+ uid = %d.\n", pdb_get_uid (pw_buf)));
+                       return False;
+               }
+               if (!pdb_set_nt_passwd (pw_buf, smbntpwd))
+                       return False;
+       }
+
+       pdb_set_unknown_3 (pw_buf, 0xffffff);   /* don't know */
+       pdb_set_logon_divs (pw_buf, 168);       /* hours per week */
+
+       if ((hours_len = ENTRY_LEN (obj, NPF_HOURS)) == 21) {
+               memcpy (hours, ENTRY_VAL (obj, NPF_HOURS), hours_len);
+       } else {
+               hours_len = 21; /* 21 times 8 bits = 168 */
+               /* available at all hours */
+               memset (hours, 0xff, hours_len);
+       }
+       pdb_set_hours_len (pw_buf, hours_len);
+       pdb_set_hours (pw_buf, hours);
+
+       pdb_set_unknown_5 (pw_buf, 0x00020000); /* don't know */
+       pdb_set_unknown_6 (pw_buf, 0x000004ec); /* don't know */
+
+       return True;
 }
 
 /************************************************************************
  makes a struct sam_passwd from a NIS+ result.
  ************************************************************************/
-static BOOL make_sam_from_nisresult(SAM_ACCOUNT *pw_buf, const nis_result *result)
+static BOOL make_sam_from_nisresult (SAM_ACCOUNT * pw_buf,
+                                    const nis_result * result)
 {
-       if (pw_buf == NULL || result == NULL) return False;
+       if (pw_buf == NULL || result == NULL)
+               return False;
 
-       if (result->status != NIS_SUCCESS && result->status != NIS_NOTFOUND)
-       {
-               DEBUG(0, ("NIS+ lookup failure: %s\n",
-                          nis_sperrno(result->status)));
+       if (result->status != NIS_SUCCESS && result->status != NIS_NOTFOUND) {
+               DEBUG (0, ("NIS+ lookup failure: %s\n",
+                          nis_sperrno (result->status)));
                return False;
        }
 
        /* User not found. */
-       if (NIS_RES_NUMOBJ(result) <= 0)
-       {
-               DEBUG(10, ("user not found in NIS+\n"));
+       if (NIS_RES_NUMOBJ (result) <= 0) {
+               DEBUG (10, ("user not found in NIS+\n"));
                return False;
        }
 
-       if (NIS_RES_NUMOBJ(result) > 1)
-       {
-               DEBUG(10, ("WARNING: Multiple entries for user in NIS+ table!\n"));
+       if (NIS_RES_NUMOBJ (result) > 1) {
+               DEBUG (10,
+                      ("WARNING: Multiple entries for user in NIS+ table!\n"));
        }
 
        /* Grab the first hit. */
-       return make_sam_from_nisp_object(pw_buf, &NIS_RES_OBJECT(result)[0]);
+       return make_sam_from_nisp_object (pw_buf,
+                                         &NIS_RES_OBJECT (result)[0]);
 }
 
 /*************************************************************************
  sets a NIS+ attribute
  *************************************************************************/
-static void set_single_attribute(nis_object *new_obj, int col,
-                               const char *val, int len, int flags)
+static void set_single_attribute (nis_object * new_obj, int col,
+                                 const char *val, int len, int flags)
 {
-       if (new_obj == NULL) return;
+       if (new_obj == NULL)
+               return;
 
-       ENTRY_VAL(new_obj, col) = val;
-       ENTRY_LEN(new_obj, col) = len+1;
+       ENTRY_VAL (new_obj, col) = val;
+       ENTRY_LEN (new_obj, col) = len + 1;
 
-       if (flags != 0)
-       {
+       if (flags != 0) {
                new_obj->EN_data.en_cols.en_cols_val[col].ec_flags = flags;
        }
 }
@@ -488,951 +1023,523 @@ static void set_single_attribute(nis_object *new_obj, int col,
  copy or modify nis object. this object is used to add or update
  nisplus table entry.
  ****************************************************************/
-static BOOL init_nisp_from_sam(nis_object *obj, const SAM_ACCOUNT *sampass,
-                              nis_object *old)
+static BOOL init_nisp_from_sam (nis_object * obj, const SAM_ACCOUNT * sampass,
+                               nis_object * old)
 {
-  /*
-   * Fill nis_object for entry add or update.
-   * if we are updateing, we have to find out differences and set
-   * EN_MODIFIED flag. also set need_to_modify to trigger
-   * nis_modify_entry() call in pdb_update_sam_account().
-   *
-   * TODO:
-   *   get data from SAM
-   *   if (modify) get data from nis_object, compare and store if
-   *               different + set EN_MODIFIED and need_to_modify
-   *   else
-   *               store
-   */
-  BOOL need_to_modify = False;
-  const char *name = pdb_get_username(sampass);       /* from SAM */
-  /* these must be static or allocate and free entry columns! */
-  static fstring uid;                     /* from SAM */
-  static fstring user_rid;                /* from SAM */
-  static fstring gid;                     /* from SAM */
-  static fstring group_rid;               /* from SAM */
-  char *acb;                       /* from SAM */
-  static fstring smb_passwd;              /* from SAM */
-  static fstring smb_nt_passwd;           /* from SAM */
-  static fstring logon_t;                 /* from SAM */
-  static fstring logoff_t;                /* from SAM */
-  static fstring kickoff_t;               /* from SAM */
-  static fstring pwdlset_t;               /* from SAM */
-  static fstring pwdlchg_t;               /* from SAM */
-  static fstring pwdmchg_t;               /* from SAM */
-  static fstring full_name;               /* from SAM */
-  static fstring acct_desc;               /* from SAM */
-  static char empty[1];                   /* just an empty string */
-
-  slprintf(uid, sizeof(uid)-1, "%u", pdb_get_uid(sampass));
-  slprintf(user_rid, sizeof(user_rid)-1, "%u",
-          pdb_get_user_rid(sampass)? pdb_get_user_rid(sampass):
-          pdb_uid_to_user_rid(pdb_get_uid(sampass))); 
-  slprintf(gid, sizeof(gid)-1, "%u", pdb_get_gid(sampass));
+       /*
+        * Fill nis_object for entry add or update.
+        * if we are updateing, we have to find out differences and set
+        * EN_MODIFIED flag. also set need_to_modify to trigger
+        * nis_modify_entry() call in pdb_update_sam_account().
+        *
+        * TODO:
+        *   get data from SAM
+        *   if (modify) get data from nis_object, compare and store if
+        *               different + set EN_MODIFIED and need_to_modify
+        *   else
+        *               store
+        */
+       BOOL need_to_modify = False;
+       const char *name = pdb_get_username (sampass);  /* from SAM */
+
+       /* these must be static or allocate and free entry columns! */
+       static fstring uid;     /* from SAM */
+       static fstring user_rid;        /* from SAM */
+       static fstring gid;     /* from SAM */
+       static fstring group_rid;       /* from SAM */
+       char *acb;              /* from SAM */
+       static fstring smb_passwd;      /* from SAM */
+       static fstring smb_nt_passwd;   /* from SAM */
+       static fstring logon_t; /* from SAM */
+       static fstring logoff_t;        /* from SAM */
+       static fstring kickoff_t;       /* from SAM */
+       static fstring pwdlset_t;       /* from SAM */
+       static fstring pwdlchg_t;       /* from SAM */
+       static fstring pwdmchg_t;       /* from SAM */
+       static fstring full_name;       /* from SAM */
+       static fstring acct_desc;       /* from SAM */
+       static char empty[1];   /* just an empty string */
+
+       slprintf (uid, sizeof (uid) - 1, "%u", pdb_get_uid (sampass));
+       slprintf (user_rid, sizeof (user_rid) - 1, "%u",
+                 pdb_get_user_rid (sampass) ? pdb_get_user_rid (sampass) :
+                 fallback_pdb_uid_to_user_rid (pdb_get_uid (sampass)));
+       slprintf (gid, sizeof (gid) - 1, "%u", pdb_get_gid (sampass));
 
        {
                uint32 rid;
                GROUP_MAP map;
-       
-               rid=pdb_get_group_rid(sampass);
 
-               if (rid==0) {
-                       if (get_group_map_from_gid(pdb_get_gid(sampass), &map, MAPPING_WITHOUT_PRIV)) {
-                               if (!sid_peek_check_rid(get_global_sam_sid(), &map.sid, &rid))
+               rid = pdb_get_group_rid (sampass);
+
+               if (rid == 0) {
+                       if (get_group_map_from_gid
+                           (pdb_get_gid (sampass), &map,
+                            MAPPING_WITHOUT_PRIV)) {
+                               if (!sid_peek_check_rid
+                                   (get_global_sam_sid (), &map.sid, &rid))
                                        return False;
-                       } else 
-                               rid=pdb_gid_to_group_rid(pdb_get_gid(sampass));
+                       } else
+                               rid = pdb_gid_to_group_rid (pdb_get_gid
+                                                           (sampass));
                }
 
-               slprintf(group_rid, sizeof(group_rid)-1, "%u", rid);
+               slprintf (group_rid, sizeof (group_rid) - 1, "%u", rid);
        }
-        
-  acb = pdb_encode_acct_ctrl(pdb_get_acct_ctrl(sampass),
-                            NEW_PW_FORMAT_SPACE_PADDED_LEN);
-  pdb_sethexpwd (smb_passwd, pdb_get_lanman_passwd(sampass),
-                pdb_get_acct_ctrl(sampass));
-  pdb_sethexpwd (smb_nt_passwd, pdb_get_nt_passwd(sampass),
-                pdb_get_acct_ctrl(sampass));
-  slprintf(logon_t, 13, "LNT-%08X",
-          (uint32)pdb_get_logon_time(sampass));
-  slprintf(logoff_t, 13, "LOT-%08X",
-          (uint32)pdb_get_logoff_time(sampass));
-  slprintf(kickoff_t, 13, "KOT-%08X",
-          (uint32)pdb_get_kickoff_time(sampass));
-  slprintf(pwdlset_t, 13, "LCT-%08X",
-          (uint32)pdb_get_pass_last_set_time(sampass));
-  slprintf(pwdlchg_t, 13, "CCT-%08X",
-          (uint32)pdb_get_pass_can_change_time(sampass));
-  slprintf(pwdmchg_t, 13, "MCT-%08X",
-          (uint32)pdb_get_pass_must_change_time(sampass));
-  safe_strcpy(full_name, pdb_get_fullname(sampass), sizeof(full_name)-1);
-  safe_strcpy(acct_desc, pdb_get_acct_desc(sampass), sizeof(acct_desc)-1);
+
+       acb = pdb_encode_acct_ctrl (pdb_get_acct_ctrl (sampass),
+                                   NEW_PW_FORMAT_SPACE_PADDED_LEN);
+       pdb_sethexpwd (smb_passwd, pdb_get_lanman_passwd (sampass),
+                      pdb_get_acct_ctrl (sampass));
+       pdb_sethexpwd (smb_nt_passwd, pdb_get_nt_passwd (sampass),
+                      pdb_get_acct_ctrl (sampass));
+       slprintf (logon_t, 13, "LNT-%08X",
+                 (uint32) pdb_get_logon_time (sampass));
+       slprintf (logoff_t, 13, "LOT-%08X",
+                 (uint32) pdb_get_logoff_time (sampass));
+       slprintf (kickoff_t, 13, "KOT-%08X",
+                 (uint32) pdb_get_kickoff_time (sampass));
+       slprintf (pwdlset_t, 13, "LCT-%08X",
+                 (uint32) pdb_get_pass_last_set_time (sampass));
+       slprintf (pwdlchg_t, 13, "CCT-%08X",
+                 (uint32) pdb_get_pass_can_change_time (sampass));
+       slprintf (pwdmchg_t, 13, "MCT-%08X",
+                 (uint32) pdb_get_pass_must_change_time (sampass));
+       safe_strcpy (full_name, pdb_get_fullname (sampass),
+                    sizeof (full_name) - 1);
+       safe_strcpy (acct_desc, pdb_get_acct_desc (sampass),
+                    sizeof (acct_desc) - 1);
 
 #if 0
 
-  /* Not sure what to do with these guys. -tpot */
+       /* Not sure what to do with these guys. -tpot */
 
-  dos_to_unix(full_name, True);
-  dos_to_unix(acct_desc, True);
+       dos_to_unix (full_name, True);
+       dos_to_unix (acct_desc, True);
 
 #endif
 
-  if( old ) {
-    /* name */
-    if(strcmp(ENTRY_VAL(old, NPF_NAME), name))
-      {
-       need_to_modify = True;
-       set_single_attribute(obj, NPF_NAME, name, strlen(name),
-                            EN_MODIFIED);
-      }
+       if (old) {
+               /* name */
+               if (strcmp (ENTRY_VAL (old, NPF_NAME), name)) {
+                       need_to_modify = True;
+                       set_single_attribute (obj, NPF_NAME, name,
+                                             strlen (name), EN_MODIFIED);
+               }
 
 
-    /* uid */
-    if(pdb_get_uid(sampass) != -1) {
-      if(!ENTRY_VAL(old, NPF_UID) || strcmp(ENTRY_VAL(old, NPF_UID), uid)) 
-       {
-         need_to_modify = True;
-         set_single_attribute(obj, NPF_UID, uid,
-                              strlen(uid), EN_MODIFIED);
-       }
-    }
-      
-    /* user_rid */
-    if (pdb_get_user_rid(sampass)) {
-      if(!ENTRY_VAL(old, NPF_USER_RID) ||
-        strcmp(ENTRY_VAL(old, NPF_USER_RID), user_rid) ) {
-       need_to_modify = True;
-       set_single_attribute(obj, NPF_USER_RID, user_rid,
-                            strlen(user_rid), EN_MODIFIED);
-      }
-    }
-    
-    /* smb_grpid */
-    if (pdb_get_gid(sampass) != -1) {
-      if(!ENTRY_VAL(old, NPF_SMB_GRPID) ||
-        strcmp(ENTRY_VAL(old, NPF_SMB_GRPID), gid) ) {
-       need_to_modify = True;
-       set_single_attribute(obj, NPF_SMB_GRPID, gid,
-                            strlen(gid), EN_MODIFIED);
-      }
-    }
-
-    /* group_rid */
-    if (pdb_get_group_rid(sampass)) {
-      if(!ENTRY_VAL(old, NPF_GROUP_RID) ||
-        strcmp(ENTRY_VAL(old, NPF_GROUP_RID), group_rid) ) {
-       need_to_modify = True;
-       set_single_attribute(obj, NPF_GROUP_RID, group_rid,
-                            strlen(group_rid), EN_MODIFIED);
-      }
-    }
-
-    /* acb */
-    if (!ENTRY_VAL(old, NPF_ACB) || 
-       strcmp(ENTRY_VAL(old, NPF_ACB), acb)) {
-      need_to_modify = True;
-      set_single_attribute(obj, NPF_ACB, acb, strlen(acb), EN_MODIFIED);
-    }
-    
-    /* lmpwd */
-    if(!ENTRY_VAL(old, NPF_LMPWD) || 
-       strcmp(ENTRY_VAL(old, NPF_LMPWD), smb_passwd) ) {
-      need_to_modify = True;
-      set_single_attribute(obj, NPF_LMPWD, smb_passwd,
-                          strlen(smb_passwd), EN_CRYPT|EN_MODIFIED);
-    }
-
-    /* ntpwd */
-    if(!ENTRY_VAL(old, NPF_NTPWD) ||
-       strcmp(ENTRY_VAL(old, NPF_NTPWD), smb_nt_passwd) ) {
-      need_to_modify = True;
-      set_single_attribute(obj, NPF_NTPWD, smb_nt_passwd,
-                          strlen(smb_nt_passwd), EN_CRYPT|EN_MODIFIED);
-    }
-
-    /* logon_t */
-    if( pdb_get_logon_time(sampass) && 
-       (!ENTRY_VAL(old, NPF_LOGON_T) ||
-        strcmp(ENTRY_VAL(old, NPF_LOGON_T), logon_t ))) {
-      need_to_modify = True;
-      set_single_attribute(obj, NPF_LOGON_T, logon_t,
-                          strlen(logon_t), EN_MODIFIED);
-    }
-
-    /* logoff_t */
-    if( pdb_get_logoff_time(sampass) && 
-       (!ENTRY_VAL(old, NPF_LOGOFF_T) ||
-        strcmp(ENTRY_VAL(old, NPF_LOGOFF_T), logoff_t))) {
-      need_to_modify = True;
-      set_single_attribute(obj, NPF_LOGOFF_T, logoff_t,
-                          strlen(logoff_t), EN_MODIFIED);
-    }
-
-    /* kick_t */
-    if( pdb_get_kickoff_time(sampass) &&
-       (!ENTRY_VAL(old, NPF_KICK_T) ||
-        strcmp(ENTRY_VAL(old, NPF_KICK_T), kickoff_t))) {
-      need_to_modify = True;
-      set_single_attribute(obj, NPF_KICK_T, kickoff_t,
-                          strlen(kickoff_t), EN_MODIFIED);
-    }
-    
-    /* pwdlset_t */
-    if( pdb_get_pass_last_set_time(sampass) &&
-       (!ENTRY_VAL(old, NPF_PWDLSET_T) ||
-        strcmp(ENTRY_VAL(old, NPF_PWDLSET_T), pwdlset_t))) {
-      need_to_modify = True;
-      set_single_attribute(obj, NPF_PWDLSET_T, pwdlset_t,
-                          strlen(pwdlset_t), EN_MODIFIED);
-    }
-
-    /* pwdlchg_t */
-    if( pdb_get_pass_can_change_time(sampass) &&
-       (!ENTRY_VAL(old, NPF_PWDCCHG_T) ||
-        strcmp(ENTRY_VAL(old, NPF_PWDCCHG_T), pwdlchg_t))) {
-      need_to_modify = True;
-      set_single_attribute(obj, NPF_PWDCCHG_T, pwdlchg_t,
-                          strlen(pwdlchg_t), EN_MODIFIED);
-    }
-
-    /* pwdmchg_t */
-    if( pdb_get_pass_must_change_time(sampass) &&
-       (!ENTRY_VAL(old, NPF_PWDMCHG_T) ||
-        strcmp(ENTRY_VAL(old, NPF_PWDMCHG_T), pwdmchg_t))) {
-      need_to_modify = True;
-      set_single_attribute(obj, NPF_PWDMCHG_T, pwdmchg_t,
-                          strlen(pwdmchg_t), EN_MODIFIED);
-    }
-    
-    /* full_name */
-    /* must support set, unset and change */
-    if ( (pdb_get_fullname(sampass) &&
-         !ENTRY_VAL(old, NPF_FULL_NAME)) ||
-        (ENTRY_VAL(old, NPF_FULL_NAME) &&
-         !pdb_get_fullname(sampass))  ||
-        (ENTRY_VAL(old, NPF_FULL_NAME) &&
-         pdb_get_fullname(sampass) && 
-         strcmp( ENTRY_VAL(old, NPF_FULL_NAME), full_name ))) {
-      need_to_modify = True;
-      set_single_attribute(obj, NPF_FULL_NAME, full_name,
-                          strlen(full_name), EN_MODIFIED);
-    }
-    
-    /* home_dir */
-    /* must support set, unset and change */
-    if( (pdb_get_homedir(sampass) && 
-        !ENTRY_VAL(old, NPF_HOME_DIR)) ||
-       (ENTRY_VAL(old, NPF_HOME_DIR) && 
-        !pdb_get_homedir(sampass)) ||
-       (ENTRY_VAL(old, NPF_HOME_DIR) && 
-        pdb_get_homedir(sampass) &&
-        strcmp( ENTRY_VAL(old, NPF_HOME_DIR),
-                pdb_get_homedir(sampass)))) {
-      need_to_modify = True;
-      set_single_attribute(obj, NPF_HOME_DIR, pdb_get_homedir(sampass),
-                          strlen(pdb_get_homedir(sampass)), EN_MODIFIED);
-    }
-    
-    /* dir_drive */
-    /* must support set, unset and change */
-    if( (pdb_get_dir_drive(sampass) && 
-        !ENTRY_VAL(old, NPF_DIR_DRIVE)) ||
-       (ENTRY_VAL(old, NPF_DIR_DRIVE) && 
-        !pdb_get_dir_drive(sampass)) ||
-       (ENTRY_VAL(old, NPF_DIR_DRIVE) && 
-        pdb_get_dir_drive(sampass) &&
-        strcmp( ENTRY_VAL(old, NPF_DIR_DRIVE),
-                pdb_get_dir_drive(sampass)))) {
-      need_to_modify = True;
-      set_single_attribute(obj, NPF_DIR_DRIVE, pdb_get_dir_drive(sampass),
-                          strlen(pdb_get_dir_drive(sampass)), EN_MODIFIED);
-    }
-    
-    /* logon_script */
-    /* must support set, unset and change */
-    if( (pdb_get_logon_script(sampass) && 
-        !ENTRY_VAL(old, NPF_LOGON_SCRIPT) ||
-        (ENTRY_VAL(old, NPF_LOGON_SCRIPT) &&
-         !pdb_get_logon_script(sampass)) ||
-        ( ENTRY_VAL(old, NPF_LOGON_SCRIPT) &&
-          pdb_get_logon_script(sampass) &&
-          strcmp( ENTRY_VAL(old, NPF_LOGON_SCRIPT),
-                  pdb_get_logon_script(sampass))))) {
-      need_to_modify = True;
-      set_single_attribute(obj, NPF_LOGON_SCRIPT,
-                          pdb_get_logon_script(sampass),
-                          strlen(pdb_get_logon_script(sampass)),
-                          EN_MODIFIED);
-    }
-    
-    /* profile_path */
-    /* must support set, unset and change */
-    if( (pdb_get_profile_path(sampass) && 
-        !ENTRY_VAL(old, NPF_PROFILE_PATH)) || 
-       (ENTRY_VAL(old, NPF_PROFILE_PATH) &&
-        !pdb_get_profile_path(sampass)) ||
-       (ENTRY_VAL(old, NPF_PROFILE_PATH) &&
-        pdb_get_profile_path(sampass) &&
-        strcmp( ENTRY_VAL(old, NPF_PROFILE_PATH),
-                pdb_get_profile_path(sampass) ) )) {
-      need_to_modify = True;
-      set_single_attribute(obj, NPF_PROFILE_PATH,
-                          pdb_get_profile_path(sampass),
-                          strlen(pdb_get_profile_path(sampass)),
-                          EN_MODIFIED);
-    }
-    
-    /* acct_desc */
-    /* must support set, unset and change */
-    if( (pdb_get_acct_desc(sampass) &&
-        !ENTRY_VAL(old, NPF_ACCT_DESC)) || 
-       (ENTRY_VAL(old, NPF_ACCT_DESC) && 
-        !pdb_get_acct_desc(sampass)) ||
-       (ENTRY_VAL(old, NPF_ACCT_DESC) && 
-        pdb_get_acct_desc(sampass) &&
-        strcmp( ENTRY_VAL(old, NPF_ACCT_DESC), acct_desc ) )) {
-      need_to_modify = True;
-      set_single_attribute(obj, NPF_ACCT_DESC, acct_desc,
-                          strlen(acct_desc), EN_MODIFIED);
-    }
-
-    /* workstations */
-    /* must support set, unset and change */
-    if ( (pdb_get_workstations(sampass) &&
-         !ENTRY_VAL(old, NPF_WORKSTATIONS) ) ||
-        (ENTRY_VAL(old, NPF_WORKSTATIONS) &&
-         !pdb_get_workstations(sampass)) ||
-        (ENTRY_VAL(old, NPF_WORKSTATIONS) &&
-         pdb_get_workstations(sampass)) &&
-        strcmp( ENTRY_VAL(old, NPF_WORKSTATIONS), 
-                pdb_get_workstations(sampass))) {
-      need_to_modify = True;
-      set_single_attribute(obj, NPF_WORKSTATIONS,
-                          pdb_get_workstations(sampass),
-                          strlen(pdb_get_workstations(sampass)),
-                          EN_MODIFIED);
-    }
-    
-    /* hours */
-    if ((pdb_get_hours_len(sampass) != ENTRY_LEN(old, NPF_HOURS)) ||
-       memcmp(pdb_get_hours(sampass), ENTRY_VAL(old, NPF_HOURS),
-              ENTRY_LEN(old, NPF_HOURS))) {
-      need_to_modify = True;
-      /* set_single_attribute will add 1 for len ... */
-      set_single_attribute(obj, NPF_HOURS, pdb_get_hours(sampass), 
-                          pdb_get_hours_len(sampass)-1, EN_MODIFIED);
-    }  
-  } else {
-    const char *homedir, *dirdrive, *logon_script, *profile_path, *workstations;
-
-    *empty = '\0'; /* empty string */
-
-    set_single_attribute(obj, NPF_NAME, name, strlen(name), 0);
-    set_single_attribute(obj, NPF_UID, uid, strlen(uid), 0);
-    set_single_attribute(obj, NPF_USER_RID, user_rid,
-                        strlen(user_rid), 0);
-    set_single_attribute(obj, NPF_SMB_GRPID, gid, strlen(gid), 0);
-    set_single_attribute(obj, NPF_GROUP_RID, group_rid,
-                        strlen(group_rid), 0);
-    set_single_attribute(obj, NPF_ACB, acb, strlen(acb), 0);
-    set_single_attribute(obj, NPF_LMPWD, smb_passwd,
-                        strlen(smb_passwd), EN_CRYPT);
-    set_single_attribute(obj, NPF_NTPWD, smb_nt_passwd,
-                        strlen(smb_nt_passwd), EN_CRYPT);
-    set_single_attribute(obj, NPF_LOGON_T, logon_t,
-                        strlen(logon_t), 0);
-    set_single_attribute(obj, NPF_LOGOFF_T, logoff_t,
-                        strlen(logoff_t), 0);
-    set_single_attribute(obj, NPF_KICK_T, kickoff_t,
-                        strlen(kickoff_t),0);
-    set_single_attribute(obj, NPF_PWDLSET_T, pwdlset_t, 
-                        strlen(pwdlset_t), 0);
-    set_single_attribute(obj, NPF_PWDCCHG_T, pwdlchg_t,
-                        strlen(pwdlchg_t), 0);
-    set_single_attribute(obj, NPF_PWDMCHG_T, pwdmchg_t,
-                        strlen(pwdmchg_t), 0);
-    set_single_attribute(obj, NPF_FULL_NAME     , 
-                        full_name, strlen(full_name), 0);
-
-    if(!(homedir = pdb_get_homedir(sampass)))
-      homedir = empty;
-
-    set_single_attribute(obj, NPF_HOME_DIR,
-                        homedir, strlen(homedir), 0);
-    
-    if(!(dirdrive = pdb_get_dir_drive(sampass)))
-       dirdrive = empty;
-       
-    set_single_attribute(obj, NPF_DIR_DRIVE,
-                        dirdrive, strlen(dirdrive), 0);
-    
-    if(!(logon_script = pdb_get_logon_script(sampass)))
-       logon_script = empty;
-    
-    set_single_attribute(obj, NPF_LOGON_SCRIPT,
-                        logon_script, strlen(logon_script), 0);
-    
-    if(!(profile_path = pdb_get_profile_path(sampass)))
-      profile_path = empty;
-
-    set_single_attribute(obj, NPF_PROFILE_PATH,
-                        profile_path, strlen(profile_path), 0);
-    
-    set_single_attribute(obj, NPF_ACCT_DESC,
-                        acct_desc, strlen(acct_desc), 0);
-    
-    if(!(workstations = pdb_get_workstations(sampass)))
-      workstations = empty;
-    
-    set_single_attribute(obj, NPF_WORKSTATIONS,        
-                        workstations, strlen(workstations), 0);
-    
-    /* set_single_attribute will add 1 for len ... */
-    set_single_attribute(obj, NPF_HOURS,
-                        pdb_get_hours(sampass),
-                        pdb_get_hours_len(sampass)-1, 0);
-  }
-  
-  return need_to_modify;
-}
+               /* uid */
+               if (pdb_get_uid (sampass) != -1) {
+                       if (!ENTRY_VAL (old, NPF_UID)
+                           || strcmp (ENTRY_VAL (old, NPF_UID), uid)) {
+                               need_to_modify = True;
+                               set_single_attribute (obj, NPF_UID, uid,
+                                                     strlen (uid),
+                                                     EN_MODIFIED);
+                       }
+               }
 
-/***************************************************************
- calls nis_list, returns results.
- ****************************************************************/
-static nis_result *nisp_get_nis_list(const char *nis_name, unsigned int flags)
-{
-       nis_result *result;
-       int i;
+               /* user_rid */
+               if (pdb_get_user_rid (sampass)) {
+                       if (!ENTRY_VAL (old, NPF_USER_RID) ||
+                           strcmp (ENTRY_VAL (old, NPF_USER_RID),
+                                   user_rid)) {
+                               need_to_modify = True;
+                               set_single_attribute (obj, NPF_USER_RID,
+                                                     user_rid,
+                                                     strlen (user_rid),
+                                                     EN_MODIFIED);
+                       }
+               }
 
-       if( ! flags)
-         flags = FOLLOW_LINKS|FOLLOW_PATH|EXPAND_NAME|HARD_LOOKUP;
-
-       for(i = 0; i<2;i++ ) {
-         alarm(60);            /* hopefully ok for long searches */
-         result = nis_list(nis_name, flags,NULL,NULL);
-
-         alarm(0);
-         CatchSignal(SIGALRM, SIGNAL_CAST SIG_DFL);
-
-         if (gotalarm)
-         {
-               DEBUG(0,("NIS+ lookup time out\n"));
-               nis_freeresult(result);
-               return NULL;
-         }
-         if( !(flags & MASTER_ONLY) && NIS_RES_NUMOBJ(result) <= 0 ) {
-           /* nis replicas are not in sync perhaps?
-             * this can happen, if account was just added.
-             */
-           DEBUG(10,("will try master only\n"));
-            nis_freeresult(result);
-            flags |= MASTER_ONLY;
-          } else
-            break;
-       }
-       return result;
-}
+               /* smb_grpid */
+               if (pdb_get_gid (sampass) != -1) {
+                       if (!ENTRY_VAL (old, NPF_SMB_GRPID) ||
+                           strcmp (ENTRY_VAL (old, NPF_SMB_GRPID), gid)) {
+                               need_to_modify = True;
+                               set_single_attribute (obj, NPF_SMB_GRPID, gid,
+                                                     strlen (gid),
+                                                     EN_MODIFIED);
+                       }
+               }
 
-/***************************************************************
- Start to enumerate the nisplus passwd list.
- ****************************************************************/
-BOOL pdb_setsampwent(BOOL update)
-{
-       char *sp, * p = lp_smb_passwd_file();
-       pstring pfiletmp;
+               /* group_rid */
+               if (pdb_get_group_rid (sampass)) {
+                       if (!ENTRY_VAL (old, NPF_GROUP_RID) ||
+                           strcmp (ENTRY_VAL (old, NPF_GROUP_RID),
+                                   group_rid)) {
+                               need_to_modify = True;
+                               set_single_attribute (obj, NPF_GROUP_RID,
+                                                     group_rid,
+                                                     strlen (group_rid),
+                                                     EN_MODIFIED);
+                       }
+               }
 
-       if( (sp = strrchr( p, '/' )) )
-         safe_strcpy(pfiletmp, sp+1, sizeof(pfiletmp)-1);
-       else
-         safe_strcpy(pfiletmp, p, sizeof(pfiletmp)-1);
-       safe_strcat(pfiletmp, ".org_dir", sizeof(pfiletmp)-strlen(pfiletmp)-1);
+               /* acb */
+               if (!ENTRY_VAL (old, NPF_ACB) ||
+                   strcmp (ENTRY_VAL (old, NPF_ACB), acb)) {
+                       need_to_modify = True;
+                       set_single_attribute (obj, NPF_ACB, acb, strlen (acb),
+                                             EN_MODIFIED);
+               }
 
-       pdb_endsampwent();      /* just in case */
-       global_nisp_ent.result = nisp_get_nis_list( pfiletmp, 0 );
-       global_nisp_ent.enum_entry = 0;
-       return global_nisp_ent.result != NULL ? True : False;
-}
+               /* lmpwd */
+               if (!ENTRY_VAL (old, NPF_LMPWD) ||
+                   strcmp (ENTRY_VAL (old, NPF_LMPWD), smb_passwd)) {
+                       need_to_modify = True;
+                       set_single_attribute (obj, NPF_LMPWD, smb_passwd,
+                                             strlen (smb_passwd),
+                                             EN_CRYPT | EN_MODIFIED);
+               }
 
-/***************************************************************
- End enumeration of the nisplus passwd list.
-****************************************************************/
-void pdb_endsampwent(void)
-{
-  if( global_nisp_ent.result )
-    nis_freeresult(global_nisp_ent.result);
-  global_nisp_ent.result = NULL;
-  global_nisp_ent.enum_entry = 0;
-}
+               /* ntpwd */
+               if (!ENTRY_VAL (old, NPF_NTPWD) ||
+                   strcmp (ENTRY_VAL (old, NPF_NTPWD), smb_nt_passwd)) {
+                       need_to_modify = True;
+                       set_single_attribute (obj, NPF_NTPWD, smb_nt_passwd,
+                                             strlen (smb_nt_passwd),
+                                             EN_CRYPT | EN_MODIFIED);
+               }
 
-/*************************************************************************
- Routine to return the next entry in the nisplus passwd list.
- *************************************************************************/
-BOOL pdb_getsampwent(SAM_ACCOUNT *user)
-{
-  int enum_entry = (int)(global_nisp_ent.enum_entry);
-  nis_result *result = global_nisp_ent.result;
-  
-  if (user==NULL) {
-       DEBUG(0,("SAM_ACCOUNT is NULL.\n"));
-       return False;
-  }
+               /* logon_t */
+               if (pdb_get_logon_time (sampass) &&
+                   (!ENTRY_VAL (old, NPF_LOGON_T) ||
+                    strcmp (ENTRY_VAL (old, NPF_LOGON_T), logon_t))) {
+                       need_to_modify = True;
+                       set_single_attribute (obj, NPF_LOGON_T, logon_t,
+                                             strlen (logon_t), EN_MODIFIED);
+               }
 
-  if (result == NULL ||
-      enum_entry < 0 || enum_entry >= (NIS_RES_NUMOBJ(result) - 1))
-  {
-       return False;
-  } 
+               /* logoff_t */
+               if (pdb_get_logoff_time (sampass) &&
+                   (!ENTRY_VAL (old, NPF_LOGOFF_T) ||
+                    strcmp (ENTRY_VAL (old, NPF_LOGOFF_T), logoff_t))) {
+                       need_to_modify = True;
+                       set_single_attribute (obj, NPF_LOGOFF_T, logoff_t,
+                                             strlen (logoff_t), EN_MODIFIED);
+               }
 
-  if(!make_sam_from_nisp_object(user, &NIS_RES_OBJECT(result)[enum_entry]) )
-  {
-    DEBUG(0,("Bad SAM_ACCOUNT entry returned from NIS+!\n"));
-       return False;
-  }
-  (int)(global_nisp_ent.enum_entry)++;
-  return True;
-}
+               /* kick_t */
+               if (pdb_get_kickoff_time (sampass) &&
+                   (!ENTRY_VAL (old, NPF_KICK_T) ||
+                    strcmp (ENTRY_VAL (old, NPF_KICK_T), kickoff_t))) {
+                       need_to_modify = True;
+                       set_single_attribute (obj, NPF_KICK_T, kickoff_t,
+                                             strlen (kickoff_t),
+                                             EN_MODIFIED);
+               }
 
-/*************************************************************************
- Routine to search the nisplus passwd file for an entry matching the username
- *************************************************************************/
-BOOL pdb_getsampwnam(SAM_ACCOUNT * user, const char *sname)
-{
-       /* Static buffers we will return. */
-       nis_result *result = NULL;
-       pstring nisname;
-       BOOL ret;
-       char *pfile = lp_smb_passwd_file();
-        int i;
+               /* pwdlset_t */
+               if (pdb_get_pass_last_set_time (sampass) &&
+                   (!ENTRY_VAL (old, NPF_PWDLSET_T) ||
+                    strcmp (ENTRY_VAL (old, NPF_PWDLSET_T), pwdlset_t))) {
+                       need_to_modify = True;
+                       set_single_attribute (obj, NPF_PWDLSET_T, pwdlset_t,
+                                             strlen (pwdlset_t),
+                                             EN_MODIFIED);
+               }
 
-       if (!*pfile)
-       {
-               DEBUG(0, ("No SMB password file set\n"));
-               return False;
-       }
-       if( strrchr( pfile, '/') )
-                pfile = strrchr( pfile, '/') + 1;
+               /* pwdlchg_t */
+               if (pdb_get_pass_can_change_time (sampass) &&
+                   (!ENTRY_VAL (old, NPF_PWDCCHG_T) ||
+                    strcmp (ENTRY_VAL (old, NPF_PWDCCHG_T), pwdlchg_t))) {
+                       need_to_modify = True;
+                       set_single_attribute (obj, NPF_PWDCCHG_T, pwdlchg_t,
+                                             strlen (pwdlchg_t),
+                                             EN_MODIFIED);
+               }
 
-       slprintf(nisname, sizeof(nisname)-1, "[name=%s],%s.org_dir", sname, pfile);
-       DEBUG(10, ("search by nisname: %s\n", nisname));
+               /* pwdmchg_t */
+               if (pdb_get_pass_must_change_time (sampass) &&
+                   (!ENTRY_VAL (old, NPF_PWDMCHG_T) ||
+                    strcmp (ENTRY_VAL (old, NPF_PWDMCHG_T), pwdmchg_t))) {
+                       need_to_modify = True;
+                       set_single_attribute (obj, NPF_PWDMCHG_T, pwdmchg_t,
+                                             strlen (pwdmchg_t),
+                                             EN_MODIFIED);
+               }
 
-       /* Search the table. */
+               /* full_name */
+               /* must support set, unset and change */
+               if ((pdb_get_fullname (sampass) &&
+                    !ENTRY_VAL (old, NPF_FULL_NAME)) ||
+                   (ENTRY_VAL (old, NPF_FULL_NAME) &&
+                    !pdb_get_fullname (sampass)) ||
+                   (ENTRY_VAL (old, NPF_FULL_NAME) &&
+                    pdb_get_fullname (sampass) &&
+                    strcmp (ENTRY_VAL (old, NPF_FULL_NAME), full_name))) {
+                       need_to_modify = True;
+                       set_single_attribute (obj, NPF_FULL_NAME, full_name,
+                                             strlen (full_name),
+                                             EN_MODIFIED);
+               }
 
-       if(!(result = nisp_get_nis_list(nisname, 0)))
-       {
-               return False;
-       }
+               /* home_dir */
+               /* must support set, unset and change */
+               if ((pdb_get_homedir (sampass) &&
+                    !ENTRY_VAL (old, NPF_HOME_DIR)) ||
+                   (ENTRY_VAL (old, NPF_HOME_DIR) &&
+                    !pdb_get_homedir (sampass)) ||
+                   (ENTRY_VAL (old, NPF_HOME_DIR) &&
+                    pdb_get_homedir (sampass) &&
+                    strcmp (ENTRY_VAL (old, NPF_HOME_DIR),
+                            pdb_get_homedir (sampass)))) {
+                       need_to_modify = True;
+                       set_single_attribute (obj, NPF_HOME_DIR,
+                                             pdb_get_homedir (sampass),
+                                             strlen (pdb_get_homedir
+                                                     (sampass)),
+                                             EN_MODIFIED);
+               }
 
-       ret = make_sam_from_nisresult(user, result);
-       nis_freeresult(result);
+               /* dir_drive */
+               /* must support set, unset and change */
+               if ((pdb_get_dir_drive (sampass) &&
+                    !ENTRY_VAL (old, NPF_DIR_DRIVE)) ||
+                   (ENTRY_VAL (old, NPF_DIR_DRIVE) &&
+                    !pdb_get_dir_drive (sampass)) ||
+                   (ENTRY_VAL (old, NPF_DIR_DRIVE) &&
+                    pdb_get_dir_drive (sampass) &&
+                    strcmp (ENTRY_VAL (old, NPF_DIR_DRIVE),
+                            pdb_get_dir_drive (sampass)))) {
+                       need_to_modify = True;
+                       set_single_attribute (obj, NPF_DIR_DRIVE,
+                                             pdb_get_dir_drive (sampass),
+                                             strlen (pdb_get_dir_drive
+                                                     (sampass)),
+                                             EN_MODIFIED);
+               }
 
-       return ret;
-}
+               /* logon_script */
+               /* must support set, unset and change */
+               if (((pdb_get_logon_script (sampass) &&
+                     !ENTRY_VAL (old, NPF_LOGON_SCRIPT)) ||
+                    ((ENTRY_VAL (old, NPF_LOGON_SCRIPT) &&
+                      (!pdb_get_logon_script (sampass)))) ||
+                    ((ENTRY_VAL (old, NPF_LOGON_SCRIPT) &&
+                      pdb_get_logon_script (sampass) &&
+                      strcmp (ENTRY_VAL (old, NPF_LOGON_SCRIPT),
+                              pdb_get_logon_script (sampass)))))) {
+                       need_to_modify = True;
+                       set_single_attribute (obj, NPF_LOGON_SCRIPT,
+                                             pdb_get_logon_script (sampass),
+                                             strlen (pdb_get_logon_script
+                                                     (sampass)),
+                                             EN_MODIFIED);
+               }
 
-/*************************************************************************
- Routine to search the nisplus passwd file for an entry matching the username
- *************************************************************************/
+               /* profile_path */
+               /* must support set, unset and change */
+               if ((pdb_get_profile_path (sampass) &&
+                    !ENTRY_VAL (old, NPF_PROFILE_PATH)) ||
+                   (ENTRY_VAL (old, NPF_PROFILE_PATH) &&
+                    !pdb_get_profile_path (sampass)) ||
+                   (ENTRY_VAL (old, NPF_PROFILE_PATH) &&
+                    pdb_get_profile_path (sampass) &&
+                    strcmp (ENTRY_VAL (old, NPF_PROFILE_PATH),
+                            pdb_get_profile_path (sampass)))) {
+                       need_to_modify = True;
+                       set_single_attribute (obj, NPF_PROFILE_PATH,
+                                             pdb_get_profile_path (sampass),
+                                             strlen (pdb_get_profile_path
+                                                     (sampass)),
+                                             EN_MODIFIED);
+               }
 
-BOOL pdb_getsampwsid(SAM_ACCOUNT * user, const DOM_SID *sid)
-{
-       uint32 rid;
-       if (!sid_peek_check_rid(get_global_sam_sid(), sid, &rid))
-               return False;
-       return pdb_getsampwrid(user, rid);
+               /* acct_desc */
+               /* must support set, unset and change */
+               if ((pdb_get_acct_desc (sampass) &&
+                    !ENTRY_VAL (old, NPF_ACCT_DESC)) ||
+                   (ENTRY_VAL (old, NPF_ACCT_DESC) &&
+                    !pdb_get_acct_desc (sampass)) ||
+                   (ENTRY_VAL (old, NPF_ACCT_DESC) &&
+                    pdb_get_acct_desc (sampass) &&
+                    strcmp (ENTRY_VAL (old, NPF_ACCT_DESC), acct_desc))) {
+                       need_to_modify = True;
+                       set_single_attribute (obj, NPF_ACCT_DESC, acct_desc,
+                                             strlen (acct_desc),
+                                             EN_MODIFIED);
+               }
+
+               /* workstations */
+               /* must support set, unset and change */
+               if ((pdb_get_workstations (sampass) &&
+                    !ENTRY_VAL (old, NPF_WORKSTATIONS)) ||
+                   (ENTRY_VAL (old, NPF_WORKSTATIONS) &&
+                    !pdb_get_workstations (sampass)) ||
+                   (ENTRY_VAL (old, NPF_WORKSTATIONS) &&
+                    (pdb_get_workstations (sampass)) &&
+                    strcmp (ENTRY_VAL (old, NPF_WORKSTATIONS),
+                            pdb_get_workstations (sampass)))) {
+                       need_to_modify = True;
+                       set_single_attribute (obj, NPF_WORKSTATIONS,
+                                             pdb_get_workstations (sampass),
+                                             strlen (pdb_get_workstations
+                                                     (sampass)),
+                                             EN_MODIFIED);
+               }
+
+               /* hours */
+               if ((pdb_get_hours_len (sampass) !=
+                    ENTRY_LEN (old, NPF_HOURS))
+                   || memcmp (pdb_get_hours (sampass),
+                              ENTRY_VAL (old, NPF_HOURS), ENTRY_LEN (old,
+                                                                     NPF_HOURS)))
+               {
+                       need_to_modify = True;
+                       /* set_single_attribute will add 1 for len ... */
+                       set_single_attribute (obj, NPF_HOURS,
+                                             pdb_get_hours (sampass),
+                                             pdb_get_hours_len (sampass) - 1,
+                                             EN_MODIFIED);
+               }
+       } else {
+               const char *homedir, *dirdrive, *logon_script, *profile_path,
+                       *workstations;
+
+               *empty = '\0';  /* empty string */
+
+               set_single_attribute (obj, NPF_NAME, name, strlen (name), 0);
+               set_single_attribute (obj, NPF_UID, uid, strlen (uid), 0);
+               set_single_attribute (obj, NPF_USER_RID, user_rid,
+                                     strlen (user_rid), 0);
+               set_single_attribute (obj, NPF_SMB_GRPID, gid, strlen (gid),
+                                     0);
+               set_single_attribute (obj, NPF_GROUP_RID, group_rid,
+                                     strlen (group_rid), 0);
+               set_single_attribute (obj, NPF_ACB, acb, strlen (acb), 0);
+               set_single_attribute (obj, NPF_LMPWD, smb_passwd,
+                                     strlen (smb_passwd), EN_CRYPT);
+               set_single_attribute (obj, NPF_NTPWD, smb_nt_passwd,
+                                     strlen (smb_nt_passwd), EN_CRYPT);
+               set_single_attribute (obj, NPF_LOGON_T, logon_t,
+                                     strlen (logon_t), 0);
+               set_single_attribute (obj, NPF_LOGOFF_T, logoff_t,
+                                     strlen (logoff_t), 0);
+               set_single_attribute (obj, NPF_KICK_T, kickoff_t,
+                                     strlen (kickoff_t), 0);
+               set_single_attribute (obj, NPF_PWDLSET_T, pwdlset_t,
+                                     strlen (pwdlset_t), 0);
+               set_single_attribute (obj, NPF_PWDCCHG_T, pwdlchg_t,
+                                     strlen (pwdlchg_t), 0);
+               set_single_attribute (obj, NPF_PWDMCHG_T, pwdmchg_t,
+                                     strlen (pwdmchg_t), 0);
+               set_single_attribute (obj, NPF_FULL_NAME,
+                                     full_name, strlen (full_name), 0);
+
+               if (!(homedir = pdb_get_homedir (sampass)))
+                       homedir = empty;
+
+               set_single_attribute (obj, NPF_HOME_DIR,
+                                     homedir, strlen (homedir), 0);
+
+               if (!(dirdrive = pdb_get_dir_drive (sampass)))
+                       dirdrive = empty;
+
+               set_single_attribute (obj, NPF_DIR_DRIVE,
+                                     dirdrive, strlen (dirdrive), 0);
+
+               if (!(logon_script = pdb_get_logon_script (sampass)))
+                       logon_script = empty;
+
+               set_single_attribute (obj, NPF_LOGON_SCRIPT,
+                                     logon_script, strlen (logon_script), 0);
+
+               if (!(profile_path = pdb_get_profile_path (sampass)))
+                       profile_path = empty;
+
+               set_single_attribute (obj, NPF_PROFILE_PATH,
+                                     profile_path, strlen (profile_path), 0);
+
+               set_single_attribute (obj, NPF_ACCT_DESC,
+                                     acct_desc, strlen (acct_desc), 0);
+
+               if (!(workstations = pdb_get_workstations (sampass)))
+                       workstations = empty;
+
+               set_single_attribute (obj, NPF_WORKSTATIONS,
+                                     workstations, strlen (workstations), 0);
+
+               /* set_single_attribute will add 1 for len ... */
+               set_single_attribute (obj, NPF_HOURS,
+                                     pdb_get_hours (sampass),
+                                     pdb_get_hours_len (sampass) - 1, 0);
+       }
+
+       return need_to_modify;
 }
 
-static BOOL pdb_getsampwrid(SAM_ACCOUNT * user, uint32 rid)
+/***************************************************************
+ calls nis_list, returns results.
+ ****************************************************************/
+static nis_result *nisp_get_nis_list (const char *nisname, unsigned int flags)
 {
        nis_result *result;
-       char *nisname;
-       BOOL ret;
-       char *sp, *p = lp_smb_passwd_file();
-       pstring pfiletmp;
+       int i;
 
-       if (!*p)
-       {
-               DEBUG(0, ("no SMB password file set\n"));
-               return False;
+       if (!flags)
+               flags = FOLLOW_LINKS | FOLLOW_PATH | EXPAND_NAME |
+                       HARD_LOOKUP;
+
+       for (i = 0; i < 2; i++) {
+               alarm (60);     /* hopefully ok for long searches */
+               result = nis_list (nisname, flags, NULL, NULL);
+
+               alarm (0);
+               CatchSignal (SIGALRM, SIGNAL_CAST SIG_DFL);
+
+               if (!(flags & MASTER_ONLY) && NIS_RES_NUMOBJ (result) <= 0) {
+                       /* nis replicas are not in sync perhaps?
+                        * this can happen, if account was just added.
+                        */
+                       DEBUG (10, ("will try master only\n"));
+                       nis_freeresult (result);
+                       flags |= MASTER_ONLY;
+               } else
+                       break;
        }
+       return result;
+}
 
-       if( (sp = strrchr( p, '/' )) )
-          safe_strcpy(pfiletmp, sp+1, sizeof(pfiletmp)-1);
-        else
-          safe_strcpy(pfiletmp, p, sizeof(pfiletmp)-1);
-        safe_strcat(pfiletmp, ".org_dir", sizeof(pfiletmp)-strlen(pfiletmp)-1);
-
-       nisname = make_nisname_from_user_rid(rid, pfiletmp);
-
-       DEBUG(10, ("search by rid: %s\n", nisname));
+NTSTATUS pdb_init_nisplussam (PDB_CONTEXT * pdb_context,
+                             PDB_METHODS ** pdb_method, const char *location)
+{
+       NTSTATUS nt_status;
+       struct nisplus_private_info *private = malloc (sizeof (struct nisplus_private_info));
 
-       /* Search the table. */
+       ZERO_STRUCT(private);
+       p->location = talloc_strdup(pdb_context->mem_ctx, location);
 
-       if(!(result = nisp_get_nis_list(nisname, 0)))
-       {
-               return False;
+       if (!NT_STATUS_IS_OK
+           (nt_status =
+            make_pdb_methods (pdb_context->mem_ctx, pdb_method))) {
+               return nt_status;
        }
 
-       ret = make_sam_from_nisresult(user, result);
-       nis_freeresult(result);
+       (*pdb_method)->name = "nisplussam";
 
-       return ret;
-}
-
-/*************************************************************************
- Routine to remove entry from the nisplus smbpasswd table
- *************************************************************************/
-BOOL pdb_delete_sam_account(SAM_ACCOUNT * user)
-{
-  const char *sname;
-  char *pfile = lp_smb_passwd_file();
-  pstring nisname;
-  nis_result *result, *delresult;
-  nis_object *obj;
-  int i;
-  if (!user) {
-         DEBUG(0, ("no SAM_ACCOUNT specified!\n"));
-         return False;
-  }
-
-  sname = pdb_get_username(user);
-
-  if (!*pfile)
-    {
-      DEBUG(0, ("no SMB password file set\n"));
-      return False;
-    }
-  if( strrchr( pfile, '/') )
-         pfile = strrchr( pfile, '/') + 1;
-  
-  slprintf(nisname, sizeof(nisname)-1, "[name=%s],%s.org_dir", sname, pfile);
-  
-  /* Search the table. */
-  
-  if( !(result = nisp_get_nis_list(nisname,
-                                  MASTER_ONLY|FOLLOW_LINKS|FOLLOW_PATH|\
-                                  EXPAND_NAME|HARD_LOOKUP))) {
-    return False;
-  }
-  
-  if(result->status != NIS_SUCCESS || NIS_RES_NUMOBJ(result) <= 0) {
-    /* User not found. */
-    DEBUG(0,("user not found in NIS+\n"));
-    nis_freeresult(result);
-    return False;
-  }
-
-  obj = NIS_RES_OBJECT(result);
-  slprintf(nisname, sizeof(nisname)-1, "[name=%s],%s.%s", sname, obj->zo_name,
-          obj->zo_domain);
-
-  DEBUG(10, ("removing name: %s\n", nisname));
-  delresult = nis_remove_entry(nisname, obj, 
-    MASTER_ONLY|REM_MULTIPLE|ALL_RESULTS|FOLLOW_PATH|EXPAND_NAME|HARD_LOOKUP);
-  
-  nis_freeresult(result);
-
-  if(delresult->status != NIS_SUCCESS) {
-    DEBUG(0, ("NIS+ table update failed: %s %s\n",
-          nisname, nis_sperrno(delresult->status)));
-    nis_freeresult(delresult);
-    return False;
-  }
-  nis_freeresult(delresult);
-  return True;
-}
+       /* Functions your pdb module doesn't provide should be set 
+        * to NULL */
 
-/************************************************************************
- Routine to add an entry to the nisplus passwd file.
-*************************************************************************/
-BOOL pdb_add_sam_account(SAM_ACCOUNT * newpwd)
-{
-  int local_user = 0;
-  char           *pfile;
-  pstring        pfiletmp;
-  char           *nisname;
-  nis_result     *result = NULL,
-    *tblresult = NULL;
-  nis_object new_obj;
-  entry_col *ecol;
-  int ta_maxcol;
-  
-  /*
-   * 1. find user domain.
-   *   a. try nis search in passwd.org_dir - if found use domain from result.
-   *   b. try getpwnam. this may be needed if user is defined
-   *      in /etc/passwd file (or elsewere) and not in passwd.org_dir.
-   *      if found, use host default domain.
-   *   c. exit with False - no such user.
-   *
-   * 2. add user
-   *   a. find smbpasswd table
-   *      search pfile in user domain if not found, try host default
-   *      domain. 
-   *   b. smbpasswd domain is found, fill data and add entry.
-   *
-   * pfile should contain ONLY table name, org_dir will be concated.
-   * so, at first we will clear path prefix from pfile, and
-   * then we will use pfiletmp as playground to put together full
-   * nisname string.
-   * such approach will make it possible to specify samba private dir
-   * AND still use NIS+ table. as all domain related data is normally
-   * stored in org_dir.DOMAIN, this should be ok do do.
-   */
-
-  pfile = lp_smb_passwd_file();
-  if( strrchr( pfile, '/') )
-    pfile = strrchr( pfile, '/') + 1;
-
-  /*
-   * Check if user is already there.
-   */
-  safe_strcpy(pfiletmp, pfile, sizeof(pfiletmp)-1);
-  safe_strcat(pfiletmp, ".org_dir",
-             sizeof(pfiletmp)-strlen(pfiletmp)-1);
-
-  if(pdb_get_username(newpwd) != NULL) {
-    nisname = make_nisname_from_name(pdb_get_username(newpwd),
-                                    pfiletmp);
-  } else {
-    return False;
-  }
-
-  if(!(result = nisp_get_nis_list(nisname, MASTER_ONLY|FOLLOW_LINKS|\
-                                 FOLLOW_PATH|EXPAND_NAME|HARD_LOOKUP))) {
-    return False;
-  }
-  if (result->status != NIS_SUCCESS && 
-      result->status != NIS_NOTFOUND) {
-    DEBUG(3, ( "nis_list failure: %s: %s\n",
-              nisname,  nis_sperrno(result->status)));
-    nis_freeresult(result);
-    return False;
-  }   
-
-  if (result->status == NIS_SUCCESS && NIS_RES_NUMOBJ(result) > 0)
-    {
-      DEBUG(3, ("User already exists in NIS+ password db: %s\n",
-               pfile));
-      nis_freeresult(result);
-      return False;
-    }
-
-  nis_freeresult(result); /* no such user, free results */
-
-  /*
-   * check for user in unix password database. we need this to get
-   * domain, where smbpasswd entry should be stored.
-   */
-
-  nisname = make_nisname_from_name(pdb_get_username(newpwd),
-                                    "passwd.org_dir");
-  
-  result = nisp_get_nis_list(nisname,
-                            MASTER_ONLY|FOLLOW_LINKS|FOLLOW_PATH|\
-                            EXPAND_NAME|HARD_LOOKUP);
-  
-  if (result->status != NIS_SUCCESS || NIS_RES_NUMOBJ(result) <= 0)
-    {
-      struct passwd *passwd;
-      DEBUG(3, ("nis_list failure: %s: %s\n", 
-               nisname,  nis_sperrno(result->status)));
-      nis_freeresult(result);
-
-      if (!(passwd = getpwnam_alloc(pdb_get_username(newpwd)))) {
-       /* no such user in system! */
-       return False;
-      }
-      passwd_free(&passwd);
+       (*pdb_method)->setsampwent = nisplussam_setsampwent;
+       (*pdb_method)->endsampwent = nisplussam_endsampwent;
+       (*pdb_method)->getsampwent = nisplussam_getsampwent;
+       (*pdb_method)->getsampwnam = nisplussam_getsampwnam;
+       (*pdb_method)->getsampwsid = nisplussam_getsampwsid;
+       (*pdb_method)->add_sam_account = nisplussam_add_sam_account;
+       (*pdb_method)->update_sam_account = nisplussam_update_sam_account;
+       (*pdb_method)->delete_sam_account = nisplussam_delete_sam_account;
+       (*pdb_method)->private_data = private;
 
-       /* 
-        * user is defined, but not in passwd.org_dir.
-        */
-      local_user = 1;
-    } else {
-      safe_strcpy(pfiletmp, pfile, sizeof(pfiletmp)-1);
-      safe_strcat(pfiletmp, ".", sizeof(pfiletmp)-strlen(pfiletmp)-1);
-      safe_strcat(pfiletmp, NIS_RES_OBJECT(result)->zo_domain,
-                 sizeof(pfiletmp)-strlen(pfiletmp)-1);
-      nis_freeresult(result); /* not needed any more */
-
-      tblresult = nisp_get_nis_list(pfiletmp,
-                                   MASTER_ONLY|FOLLOW_LINKS|\
-                                   FOLLOW_PATH|EXPAND_NAME|HARD_LOOKUP); 
-    }
-
-  if (local_user || tblresult->status != NIS_SUCCESS)
-    {
-      /*
-       * no user domain or
-       * smbpasswd table not found in user domain, fallback to
-       * default domain.
-       */
-      if (!local_user) /* free previous failed search result */
-       nis_freeresult(tblresult);
-      
-      safe_strcpy(pfiletmp, pfile, sizeof(pfiletmp)-1);
-      safe_strcat(pfiletmp, ".org_dir",
-                 sizeof(pfiletmp)-strlen(pfiletmp)-1);
-      tblresult = nis_lookup(pfiletmp, MASTER_ONLY|FOLLOW_LINKS|\
-                            FOLLOW_PATH|EXPAND_NAME|HARD_LOOKUP);
-      if (tblresult->status != NIS_SUCCESS)
-       {
-           /* still nothing. bail out */
-         nis_freeresult(tblresult);
-         DEBUG(3, ( "nis_lookup failure: %s\n",
-                    nis_sperrno(tblresult->status)));
-         return False;
-       }
-      /* we need full name for nis_add_entry() */
-      safe_strcpy(pfiletmp, pfile, sizeof(pfiletmp)-1);
-      safe_strcat(pfiletmp, ".", sizeof(pfiletmp)-strlen(pfiletmp)-1);
-      safe_strcat(pfiletmp, NIS_RES_OBJECT(tblresult)->zo_domain,
-                 sizeof(pfiletmp)-strlen(pfiletmp)-1);
-    }
-
-  memset((char *)&new_obj, 0, sizeof (new_obj));
-  /* fill entry headers */
-  /* we do not free these. */
-  new_obj.zo_name   = NIS_RES_OBJECT(tblresult)->zo_name;
-  new_obj.zo_owner  = NIS_RES_OBJECT(tblresult)->zo_owner;
-  new_obj.zo_group  = NIS_RES_OBJECT(tblresult)->zo_group;
-  new_obj.zo_domain = NIS_RES_OBJECT(tblresult)->zo_domain;
-  /* uints */
-  new_obj.zo_access = NIS_RES_OBJECT(tblresult)->zo_access;
-  new_obj.zo_ttl    = NIS_RES_OBJECT(tblresult)->zo_ttl;
-
-  new_obj.zo_data.zo_type = ENTRY_OBJ;
-  new_obj.EN_data.en_type =
-    NIS_RES_OBJECT(tblresult)->TA_data.ta_type;
-
-  ta_maxcol = NIS_RES_OBJECT(tblresult)->TA_data.ta_maxcol;
-  
-  if(!(ecol = (entry_col*)malloc(ta_maxcol*sizeof(entry_col)))) {
-    DEBUG(0, ("memory allocation failure\n"));
-    nis_freeresult(tblresult);
-    return False;
-  }
-  
-  memset((char *)ecol, 0, ta_maxcol*sizeof (entry_col));
-  new_obj.EN_data.en_cols.en_cols_val = ecol;
-  new_obj.EN_data.en_cols.en_cols_len = ta_maxcol;
-  
-  init_nisp_from_sam(&new_obj, newpwd, NULL);
-  
-  DEBUG(10, ( "add NIS+ entry: %s\n", nisname));
-  result = nis_add_entry(pfiletmp, &new_obj, 0);
-
-  free(ecol); /* free allocated entry space */
-  
-  if (result->status != NIS_SUCCESS)
-    {
-      DEBUG(3, ( "NIS+ table update failed: %s\n",
-                nisname, nis_sperrno(result->status)));
-      nis_freeresult(tblresult);
-      nis_freeresult(result);
-      return False;
-    }
-  
-  nis_freeresult(tblresult);
-  nis_freeresult(result);
-  
-  return True;
+       return NT_STATUS_OK;
 }
 
-/************************************************************************
- Routine to modify the nisplus passwd entry.
-************************************************************************/
-BOOL pdb_update_sam_account(SAM_ACCOUNT * newpwd)
+#else
+NTSTATUS pdb_init_nisplussam (PDB_CONTEXT * c, PDB_METHODS ** m,
+                             const char *l)
 {
-  nis_result *result, *addresult;
-  nis_object *obj;
-  nis_object new_obj;
-  entry_col *ecol;
-  int ta_maxcol;
-  char *pfile = lp_smb_passwd_file();
-  pstring nisname;
-  int i;
-
-  if (!*pfile)
-    {
-      DEBUG(0, ("no SMB password file set\n"));
-      return False;
-    }
-  if( strrchr( pfile, '/') )
-         pfile = strrchr( pfile, '/') + 1;
-  
-  slprintf(nisname, sizeof(nisname)-1, "[name=%s],%s.org_dir",
-          pdb_get_username(newpwd), pfile);
-  
-  DEBUG(10, ("search by name: %s\n", nisname));
-  
-  /* Search the table. */
-  
-  if( !(result = nisp_get_nis_list(nisname, MASTER_ONLY|FOLLOW_LINKS|\
-                                  FOLLOW_PATH|EXPAND_NAME|HARD_LOOKUP))) {
-    return False;
-  }
-  
-  if(result->status != NIS_SUCCESS || NIS_RES_NUMOBJ(result) <= 0) {
-    /* User not found. */
-    DEBUG(0,("user not found in NIS+\n"));
-    nis_freeresult(result);
-    return False;
-  }
-
-  obj = NIS_RES_OBJECT(result);
-  DEBUG(6,("entry found in %s\n", obj->zo_domain));
-
-  /* we must create new stub object with EN_MODIFIED flag.
-     this is because obj from result is going to be freed and
-     we do not want to break it or cause memory leaks or corruption.
-  */
-  
-  memmove((char *)&new_obj, obj, sizeof (new_obj));
-  ta_maxcol = obj->TA_data.ta_maxcol;
-  
-  if(!(ecol = (entry_col*)malloc(ta_maxcol*sizeof(entry_col)))) {
-    DEBUG(0, ("memory allocation failure\n"));
-    nis_freeresult(result);
-    return False;
-  }
-
-  memmove((char *)ecol, obj->EN_data.en_cols.en_cols_val,
-         ta_maxcol*sizeof (entry_col));
-  new_obj.EN_data.en_cols.en_cols_val = ecol;
-  new_obj.EN_data.en_cols.en_cols_len = ta_maxcol;
-
-  if ( init_nisp_from_sam(&new_obj, newpwd, obj) == True ) {
-    slprintf(nisname, sizeof(nisname)-1, "[name=%s],%s.%s",
-          pdb_get_username(newpwd), pfile, obj->zo_domain);
-
-    DEBUG(10, ("NIS+ table update: %s\n", nisname));
-    addresult =
-      nis_modify_entry(nisname, &new_obj, 
-                 MOD_SAMEOBJ | FOLLOW_PATH | EXPAND_NAME | HARD_LOOKUP);
-  
-    if(addresult->status != NIS_SUCCESS) {
-      DEBUG(0, ("NIS+ table update failed: %s %s\n",
-               nisname, nis_sperrno(addresult->status)));
-      nis_freeresult(addresult);
-      nis_freeresult(result);
-      free(ecol);
-      return False;
-    }
-    
-    DEBUG(6,("password changed\n"));
-    nis_freeresult(addresult);
-  } else {
-    DEBUG(6,("nothing to change!\n"));
-  }
-
-  free(ecol);
-  nis_freeresult(result);
-  
-  return True;
+       DEBUG (0, ("nisplus sam not compiled in!\n"));
+       return NT_STATUS_UNSUCCESSFUL;
 }
-#else
- void nisplus_dummy_function(void);
- void nisplus_dummy_function(void) { } /* stop some compilers complaining */
-#endif /* WITH_NISPLUSSAM */
+#endif /* WITH_NISPLUS_SAM */
index 1a246631fe73f95be018b75e2ca682a12829e9f5..ea67da23a552a04de4a76a6dab9dc7bc69991e04 100644 (file)
@@ -46,7 +46,7 @@ NTSTATUS pdb_init_plugin(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, con
        trim_string(plugin_name, " ", " ");
 
        DEBUG(5, ("Trying to load sam plugin %s\n", plugin_name));
-       dl_handle = sys_dlopen(plugin_name, RTLD_NOW | RTLD_GLOBAL );
+       dl_handle = sys_dlopen(plugin_name, RTLD_NOW );
        if (!dl_handle) {
                DEBUG(0, ("Failed to load sam plugin %s using sys_dlopen (%s)\n", plugin_name, sys_dlerror()));
                return NT_STATUS_UNSUCCESSFUL;
@@ -59,7 +59,7 @@ NTSTATUS pdb_init_plugin(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, con
                return NT_STATUS_UNSUCCESSFUL;
        }
 
-       if (plugin_version()!=PASSDB_INTERFACE_VERSION) {
+       if (plugin_version() != PASSDB_INTERFACE_VERSION) {
                sys_dlclose(dl_handle);
                DEBUG(0, ("Wrong PASSDB_INTERFACE_VERSION! sam plugin has version %d and version %d is needed! Please update!\n",
                            plugin_version(),PASSDB_INTERFACE_VERSION));
index d40ea03511cd2aaef81e78fe0ef27c45e7b6b659..04c0d333e43527f13b9461b57b9d2788198e02c3 100644 (file)
@@ -1327,7 +1327,8 @@ static BOOL smbpasswd_getsampwent(struct pdb_methods *my_methods, SAM_ACCOUNT *u
  call getpwnam() for unix account information until we have found
  the correct entry
  ***************************************************************/
-static BOOL smbpasswd_getsampwnam(struct pdb_methods *my_methods, SAM_ACCOUNT *sam_acct, const char *username)
+static BOOL smbpasswd_getsampwnam(struct pdb_methods *my_methods, 
+                                 SAM_ACCOUNT *sam_acct, const char *username)
 {
        struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)my_methods->private_data;
        struct smb_passwd *smb_pw;
@@ -1381,6 +1382,16 @@ static BOOL smbpasswd_getsampwrid(struct pdb_methods *my_methods, SAM_ACCOUNT *s
 
        DEBUG(10, ("pdb_getsampwrid: search by rid: %d\n", rid));
 
+       /* More special case 'guest account' hacks... */
+       if (rid == DOMAIN_USER_RID_GUEST) {
+               const char *guest_account = lp_guestaccount();
+               if (!(guest_account && *guest_account)) {
+                       DEBUG(1, ("Guest account not specfied!\n"));
+                       return False;
+               }
+               return smbpasswd_getsampwnam(my_methods, sam_acct, guest_account);
+       }
+
        /* Open the sam password file - not for update. */
        fp = startsmbfilepwent(smbpasswd_state->smbpasswd_file, PWF_READ, &(smbpasswd_state->pw_file_lock_depth));
 
index ec67b74390030dbf63560932b23892d5681bfa39..08a0e9c9acfa9a7b1d704498744e4f1f1cd0fa4b 100644 (file)
@@ -68,7 +68,7 @@ void *secrets_fetch(const char *key, size_t *size)
 
 /* store a secrets entry 
  */
-BOOL secrets_store(const char *key, void *data, size_t size)
+BOOL secrets_store(const char *key, const void *data, size_t size)
 {
        TDB_DATA kbuf, dbuf;
        secrets_init();
@@ -95,7 +95,7 @@ BOOL secrets_delete(const char *key)
        return tdb_delete(tdb, kbuf) == 0;
 }
 
-BOOL secrets_store_domain_sid(char *domain, DOM_SID *sid)
+BOOL secrets_store_domain_sid(char *domain, const DOM_SID *sid)
 {
        fstring key;
 
@@ -148,7 +148,7 @@ BOOL secrets_fetch_domain_guid(char *domain, GUID *guid)
        strupper(key);
        dyn_guid = (GUID *)secrets_fetch(key, &size);
 
-       DEBUG(6,("key is %s, guid is at %x, size is %d\n", key, dyn_guid, size));
+       DEBUG(6,("key is %s, size is %d\n", key, (int)size));
 
        if ((NULL == dyn_guid) && (ROLE_DOMAIN_PDC == lp_server_role())) {
                uuid_generate_random(&new_guid);
@@ -206,8 +206,27 @@ char *trustdom_keystr(const char *domain)
 }
 
 /************************************************************************
Routine to get the machine trust account password for a domain.
Lock the trust password entry.
 ************************************************************************/
+
+BOOL secrets_lock_trust_account_password(char *domain, BOOL dolock)
+{
+       if (!tdb)
+               return False;
+
+       if (dolock)
+               return (tdb_lock_bystring(tdb, trust_keystr(domain)) == 0);
+       else
+               tdb_unlock_bystring(tdb, trust_keystr(domain));
+       return True;
+}
+
+/************************************************************************
+ Routine to get the trust account password for a domain.
+ The user of this function must have locked the trust password file using
+ the above call.
+************************************************************************/
+
 BOOL secrets_fetch_trust_account_password(char *domain, uint8 ret_pwd[16],
                                          time_t *pass_last_set_time)
 {
@@ -243,6 +262,7 @@ BOOL secrets_fetch_trust_account_password(char *domain, uint8 ret_pwd[16],
 /************************************************************************
  Routine to get account password to trusted domain
 ************************************************************************/
+
 BOOL secrets_fetch_trusted_domain_password(char *domain, char** pwd,
                                           DOM_SID *sid, time_t *pass_last_set_time)
 {
@@ -559,3 +579,69 @@ NTSTATUS secrets_get_trusted_domains(TALLOC_CTX* ctx, int* enum_ctx, int max_num
        return status;
 }
 
+static SIG_ATOMIC_T gotalarm;
+
+/***************************************************************
+ Signal function to tell us we timed out.
+****************************************************************/
+
+static void gotalarm_sig(void)
+{
+       gotalarm = 1;
+}
+
+/*
+  lock the secrets tdb based on a string - this is used as a primitive form of mutex
+  between smbd instances. 
+*/
+BOOL secrets_named_mutex(const char *name, unsigned int timeout)
+{
+       TDB_DATA key;
+       int ret;
+
+       if (!message_init())
+               return False;
+
+       key.dptr = (char *)name;
+       key.dsize = strlen(name)+1;
+
+       /* Allow tdb_chainlock to be interrupted by an alarm. */
+       gotalarm = 0;
+       tdb_set_lock_alarm(&gotalarm);
+
+       if (timeout) {
+               CatchSignal(SIGALRM, SIGNAL_CAST gotalarm_sig);
+               alarm(timeout);
+       }
+
+       ret = tdb_chainlock(tdb, key);
+
+       /* Prevent tdb_chainlock from being interrupted by an alarm. */
+       tdb_set_lock_alarm(NULL);
+
+       if (timeout) {
+               alarm(0);
+               CatchSignal(SIGALRM, SIGNAL_CAST SIG_IGN);
+               if (gotalarm)
+                       return False;
+       }
+
+       if (ret == 0)
+               DEBUG(10,("secrets_named_mutex: got mutex for %s\n", name ));
+
+       return (ret == 0);
+}
+
+/*
+  unlock a named mutex
+*/
+void secrets_named_mutex_release(char *name)
+{
+       TDB_DATA key;
+
+       key.dptr = name;
+       key.dsize = strlen(name)+1;
+
+       tdb_chainunlock(tdb, key);
+       DEBUG(10,("secrets_named_mutex: released mutex for %s\n", name ));
+}
index 925d49a21d6abaf4db43ae3fbff36f673cad341f..003718ed72499c2221e4a607ad1654fe32c1a63e 100644 (file)
 
 #include "printing.h"
 
-/*
- * Print notification routines
- */
+static TALLOC_CTX *send_ctx;
+
+static struct notify_queue {
+       struct notify_queue *next, *prev;
+       void *buf;
+       size_t buflen;
+} *notify_queue_head = NULL;
+
+/*******************************************************************
+ Used to decide if we need a short select timeout.
+*******************************************************************/
+
+BOOL print_notify_messages_pending(void)
+{
+       return (notify_queue_head != NULL);
+}
+
+/*******************************************************************
+ Actually send the batched messages.
+*******************************************************************/
+
+void print_notify_send_messages(void)
+{
+       TDB_CONTEXT *tdb;
+       char *buf;
+       struct notify_queue *pq;
+       size_t msg_count = 0, offset = 0;
+
+       if (!print_notify_messages_pending())
+               return;
+
+       if (!send_ctx)
+               return;
+
+       tdb = conn_tdb_ctx();
+
+       if (!tdb) {
+               DEBUG(3, ("Failed to open connections database in send_spoolss_notify2_msg\n"));
+               return;
+       }
+       
+       /* Count the space needed to send the messages. */
+       for (pq = notify_queue_head; pq; pq = pq->next, msg_count++)
+               offset += (pq->buflen + 4);
+               
+       offset += 4; /* For count. */
+
+       buf = talloc(send_ctx, offset);
+       if (!buf) {
+               DEBUG(0,("print_notify_send_messages: Out of memory\n"));
+               talloc_destroy_pool(send_ctx);
+               return;
+       }
+
+       offset = 0;
+       SIVAL(buf,offset,msg_count);
+       offset += 4;
+       for (pq = notify_queue_head; pq; pq = pq->next) {
+               SIVAL(buf,offset,pq->buflen);
+               offset += 4;
+               memcpy(buf + offset, pq->buf, pq->buflen);
+               offset += pq->buflen;
+       }
+
+       DEBUG(5, ("print_notify_send_messages: sending %d print notify message%s\n", 
+                 msg_count, msg_count != 1 ? "s" : ""));
+
+       message_send_all(tdb, MSG_PRINTER_NOTIFY2, buf, offset, False, NULL);
+       talloc_destroy_pool(send_ctx);
+       notify_queue_head = NULL;
+}
+
+/*******************************************************************
+ Batch up print notify messages.
+*******************************************************************/
 
 static void send_spoolss_notify2_msg(struct spoolss_notify_msg *msg)
 {
        char *buf = NULL;
-       int buflen = 0, len;
-       TDB_CONTEXT *tdb;
+       size_t buflen = 0, len;
+       struct notify_queue *pnqueue, *tmp_ptr;
 
        /* Let's not waste any time with this */
 
        if (lp_disable_spoolss())
                return;
 
+       if (!send_ctx)
+               send_ctx = talloc_init_named("print notify queue");
+
+       if (!send_ctx)
+               goto fail;
+
        /* Flatten data into a message */
 
 again:
@@ -59,24 +137,34 @@ again:
                                msg->len, msg->notify.data);
 
        if (buflen != len) {
-               buf = Realloc(buf, len);
+               buf = talloc_realloc(send_ctx, buf, len);
+               if (!buf)
+                       goto fail;
                buflen = len;
                goto again;
        }
 
-       /* Send message */
+       /* Store the message on the pending queue. */
 
-       tdb = conn_tdb_ctx();
+       pnqueue = talloc(send_ctx, sizeof(*pnqueue));
+       if (!pnqueue)
+               goto fail;
 
-       if (!tdb) {
-               DEBUG(3, ("Failed to open connections database in send_spoolss_notify2_msg\n"));
-               goto done;
-       }
-       
-       message_send_all(tdb, MSG_PRINTER_NOTIFY2, buf, buflen, False, NULL);
+       pnqueue->buf = buf;
+       pnqueue->buflen = buflen;
+
+       DEBUG(5, ("send_spoolss_notify2_msg: appending message 0x%02x/0x%02x to notify_queue_head\n", msg->type, msg->field));
+                 
+       /* Note we add to the end of the list to ensure
+        * the messages are sent in the order they were received. JRA.
+        */
+       DLIST_ADD_END(notify_queue_head, pnqueue, tmp_ptr);
+
+       return;
+
+  fail:
 
-done:
-       SAFE_FREE(buf);
+       DEBUG(0,("send_spoolss_notify2_msg: Out of memory.\n"));
 }
 
 static void send_notify_field_values(const char *printer_name, uint32 type,
index 3b85fce0200beba4cdf70d5f0ed767c28ff8dea9..58eba9d87e8cd4ef014965b54c20c85222d4583b 100644 (file)
@@ -1745,7 +1745,7 @@ static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr,
        
        dbuf = tdb_fetch(tdb_drivers, kbuf);
        if (!dbuf.dptr) 
-               return WERR_ACCESS_DENIED;
+               return WERR_UNKNOWN_PRINTER_DRIVER;
 
        len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
                          &driver.cversion,
@@ -1864,7 +1864,7 @@ static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32
        NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
        int i;
        
-       DEBUG(106,("Dumping printer driver at level [%d]\n", level));
+       DEBUG(20,("Dumping printer driver at level [%d]\n", level));
        
        switch (level)
        {
@@ -1905,7 +1905,7 @@ static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32
 
 /****************************************************************************
 ****************************************************************************/
-static int pack_devicemode(NT_DEVICEMODE *nt_devmode, char *buf, int buflen)
+int pack_devicemode(NT_DEVICEMODE *nt_devmode, char *buf, int buflen)
 {
        int len = 0;
 
@@ -2282,7 +2282,7 @@ static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr)
 
 /****************************************************************************
 ****************************************************************************/
-static int unpack_devicemode(NT_DEVICEMODE **nt_devmode, char *buf, int buflen)
+int unpack_devicemode(NT_DEVICEMODE **nt_devmode, char *buf, int buflen)
 {
        int len = 0;
        int extra_len = 0;
@@ -2407,7 +2407,7 @@ int lookup_printerkey( NT_PRINTER_DATA *data, char *name )
        
        for ( i=0; i<data->num_keys; i++ ) 
        {
-               if ( strcmp(data->keys[i].name, name) == 0 ) {
+               if ( strequal(data->keys[i].name, name) ) {
                        DEBUG(12,("lookup_printerkey: Found [%s]!\n", name));
                        key_index = i;
                        break;
@@ -2420,32 +2420,169 @@ int lookup_printerkey( NT_PRINTER_DATA *data, char *name )
 
 /****************************************************************************
  ***************************************************************************/
+
+uint32 get_printer_subkeys( NT_PRINTER_DATA *data, char* key, fstring **subkeys )
+{
+       int     i, j;
+       int     key_len;
+       int     num_subkeys = 0;
+       char    *p;
+       fstring *ptr, *subkeys_ptr = NULL;
+       fstring subkeyname;
+       
+       if ( !data )
+               return 0;
+               
+       for ( i=0; i<data->num_keys; i++ ) 
+       {
+               if ( StrnCaseCmp(data->keys[i].name, key, strlen(key)) == 0 )
+               {
+                       /* match sure it is a subkey and not the key itself */
+                       
+                       key_len = strlen( key );
+                       if ( strlen(data->keys[i].name) == key_len )
+                               continue;
+                       
+                       /* get subkey path */
+
+                       p = data->keys[i].name + key_len;
+                       if ( *p == '\\' )
+                               p++;
+                       fstrcpy( subkeyname, p );
+                       if ( (p = strchr( subkeyname, '\\' )) )
+                               *p = '\0';
+                       
+                       /* don't add a key more than once */
+                       
+                       for ( j=0; j<num_subkeys; j++ ) {
+                               if ( strequal( subkeys_ptr[j], subkeyname ) )
+                                       break;
+                       }
+                       
+                       if ( j != num_subkeys )
+                               continue;
+
+                       /* found a match, so allocate space and copy the name */
+                       
+                       if ( !(ptr = Realloc( subkeys_ptr, (num_subkeys+2)*sizeof(fstring))) ) {
+                               DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n", 
+                                       num_subkeys+1));
+                               SAFE_FREE( subkeys );
+                               return 0;
+                       }
+                       
+                       subkeys_ptr = ptr;
+                       fstrcpy( subkeys_ptr[num_subkeys], subkeyname );
+                       num_subkeys++;
+               }
+               
+       }
+       
+       /* tag of the end */
+       
+       fstrcpy( subkeys_ptr[num_subkeys], "" );
+       
+       *subkeys = subkeys_ptr;
+
+       return num_subkeys;
+}
  
-WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2 )
+/****************************************************************************
+ ***************************************************************************/
+WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, char *key )
 {
-       WERROR          result = WERR_OK;
        NT_PRINTER_DATA *data;
        int             i;
+       int             removed_keys = 0;
+       int             empty_slot;
        
        data = &p2->data;
+       empty_slot = data->num_keys;
+
+       if ( !key )
+               return WERR_INVALID_PARAM;
        
-       for ( i=0; i<data->num_keys; i++ ) 
+       /* remove all keys */
+
+       if ( !strlen(key) ) 
        {
-               DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
-                       data->keys[i].name));
+               for ( i=0; i<data->num_keys; i++ ) 
+               {
+                       DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
+                               data->keys[i].name));
                
-               SAFE_FREE( data->keys[i].name );
-               regval_ctr_destroy( &data->keys[i].values );
-       }
+                       SAFE_FREE( data->keys[i].name );
+                       regval_ctr_destroy( &data->keys[i].values );
+               }
        
-       SAFE_FREE( data->keys );
+               DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
+                       p2->printername ));
+       
+               SAFE_FREE( data->keys );
+               ZERO_STRUCTP( data );
 
-       DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
-               p2->printername ));
+               return WERR_OK;
+       }
+
+       /* remove a specific key (and all subkeys) */
        
-       ZERO_STRUCTP( data );
+       for ( i=0; i<data->num_keys; i++ ) 
+       {
+               if ( StrnCaseCmp( data->keys[i].name, key, strlen(key)) == 0 )
+               {
+                       DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
+                               data->keys[i].name));
+               
+                       SAFE_FREE( data->keys[i].name );
+                       regval_ctr_destroy( &data->keys[i].values );
+               
+                       /* mark the slot as empty */
+
+                       ZERO_STRUCTP( &data->keys[i] );
+               }
+       }
+
+       /* find the first empty slot */
+
+       for ( i=0; i<data->num_keys; i++ ) {
+               if ( !data->keys[i].name ) {
+                       empty_slot = i;
+                       removed_keys++;
+                       break;
+               }
+       }
+
+       if ( i == data->num_keys )
+               /* nothing was removed */
+               return WERR_INVALID_PARAM;
+
+       /* move everything down */
        
-       return result;
+       for ( i=empty_slot+1; i<data->num_keys; i++ ) {
+               if ( data->keys[i].name ) {
+                       memcpy( &data->keys[empty_slot], &data->keys[i], sizeof(NT_PRINTER_KEY) ); 
+                       ZERO_STRUCTP( &data->keys[i] );
+                       empty_slot++;
+                       removed_keys++;
+               }
+       }
+
+       /* update count */
+               
+       data->num_keys -= removed_keys;
+
+       /* sanity check to see if anything is left */
+
+       if ( !data->num_keys )
+       {
+               DEBUG(8,("delete_all_printer_data: No keys left for printer [%s]\n", p2->printername ));
+
+               SAFE_FREE( data->keys );
+               ZERO_STRUCTP( data );
+       }
+
+       return WERR_OK;
 }
 
 /****************************************************************************
@@ -2465,11 +2602,8 @@ WERROR delete_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, char *key, char *value
 
        key_index = lookup_printerkey( &p2->data, key );
        if ( key_index == -1 )
-               key_index = add_new_printer_key( &p2->data, key );
+               return WERR_OK;
                
-       if ( key_index == -1 )
-               return WERR_NOMEM;
-       
        regval_ctr_delvalue( &p2->data.keys[key_index].values, value );
        
        DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
@@ -2504,8 +2638,8 @@ WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, char *key, char *value,
        regval_ctr_addvalue( &p2->data.keys[key_index].values, value,
                type, data, real_len );
        
-       DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], size => [%d]\n",
-               key, value, real_len ));
+       DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
+               key, value, type, real_len  ));
        
        return result;
 }
@@ -2569,7 +2703,7 @@ static int unpack_values(NT_PRINTER_DATA *printer_data, char *buf, int buflen)
                 * Should only be one '\' in the string returned.
                 */     
                 
-               str = strchr( string, '\\');
+               str = strrchr( string, '\\');
                
                /* Put in "PrinterDriverData" is no key specified */
                
@@ -2598,7 +2732,7 @@ static int unpack_values(NT_PRINTER_DATA *printer_data, char *buf, int buflen)
                
                regval_ctr_addvalue( &printer_data->keys[key_index].values, valuename, type, data_p, size );
 
-               DEBUG(8,("specific: [%s\\%s], len: %d\n", keyname, valuename, size));
+               DEBUG(8,("specific: [%s:%s], len: %d\n", keyname, valuename, size));
        }
 
        return len;
@@ -3046,7 +3180,7 @@ static BOOL set_driver_init_2( NT_PRINTER_INFO_LEVEL_2 *info_ptr )
         * should not be any (if there are delete them).
         */
         
-       delete_all_printer_data( info_ptr );
+       delete_all_printer_data( info_ptr, "" );
        
        slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info_ptr->drivername);
 
@@ -3074,16 +3208,17 @@ static BOOL set_driver_init_2( NT_PRINTER_INFO_LEVEL_2 *info_ptr )
         * the initialization save. Change it to reflect the new printer.
         */
         
+       if ( info.devmode ) {
        ZERO_STRUCT(info.devmode->devicename);
        fstrcpy(info.devmode->devicename, info_ptr->printername);
-
+       }
 
        /*
         * NT/2k does not change out the entire DeviceMode of a printer
         * when changing the driver.  Only the driverextra, private, & 
         * driverversion fields.   --jerry  (Thu Mar 14 08:58:43 CST 2002)
         *
-        * Later e4xamination revealed that Windows NT/2k does reset the
+        * Later examination revealed that Windows NT/2k does reset the
         * the printer's device mode, bit **only** when you change a 
         * property of the device mode such as the page orientation.
         * --jerry
@@ -3095,9 +3230,8 @@ static BOOL set_driver_init_2( NT_PRINTER_INFO_LEVEL_2 *info_ptr )
        free_nt_devicemode(&info_ptr->devmode);
        info_ptr->devmode = info.devmode;
 
-
-       DEBUG(10,("set_driver_init_2: Set printer [%s] init DEVMODE for driver [%s]\n",
-                       info_ptr->printername, info_ptr->drivername));
+       DEBUG(10,("set_driver_init_2: Set printer [%s] init %s DEVMODE for driver [%s]\n",
+               info_ptr->printername, info_ptr->devmode?"VALID":"NULL", info_ptr->drivername));
 
        /* Add the printer data 'values' to the new printer */
         
@@ -3232,17 +3366,162 @@ uint32 update_driver_init(NT_PRINTER_INFO_LEVEL printer, uint32 level)
        {
                case 2:
                {
-                       result=update_driver_init_2(printer.info_2);
+                       result = update_driver_init_2(printer.info_2);
                        break;
                }
                default:
-                       result=1;
+                       result = 1;
                        break;
        }
        
        return result;
 }
 
+/****************************************************************************
+ Convert the printer data value, a REG_BINARY array, into an initialization 
+ DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
+ got to keep the endians happy :).
+****************************************************************************/
+
+static BOOL convert_driver_init( TALLOC_CTX *ctx, NT_DEVICEMODE *nt_devmode, uint8 *data, uint32 data_len )
+{
+       BOOL       result = False;
+       prs_struct ps;
+       DEVICEMODE devmode;
+
+       ZERO_STRUCT(devmode);
+
+       prs_init(&ps, 0, ctx, UNMARSHALL);
+       ps.data_p      = (char *)data;
+       ps.buffer_size = data_len;
+
+       if (spoolss_io_devmode("phantom DEVMODE", &ps, 0, &devmode))
+               result = convert_devicemode("", &devmode, &nt_devmode);
+       else
+               DEBUG(10,("convert_driver_init: error parsing DEVMODE\n"));
+
+       return result;
+}
+
+/****************************************************************************
+ Set the DRIVER_INIT info in the tdb. Requires Win32 client code that:
+
+ 1. Use the driver's config DLL to this UNC printername and:
+    a. Call DrvPrintEvent with PRINTER_EVENT_INITIALIZE
+    b. Call DrvConvertDevMode with CDM_DRIVER_DEFAULT to get default DEVMODE
+ 2. Call SetPrinterData with the 'magic' key and the DEVMODE as data.
+
+ The last step triggers saving the "driver initialization" information for
+ this printer into the tdb. Later, new printers that use this driver will
+ have this initialization information bound to them. This simulates the
+ driver initialization, as if it had run on the Samba server (as it would
+ have done on NT).
+
+ The Win32 client side code requirement sucks! But until we can run arbitrary
+ Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
+ It would have been easier to use SetPrinter because all the UNMARSHALLING of
+ the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
+ about it and you will realize why.  JRR 010720
+****************************************************************************/
+
+static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, uint8 *data, uint32 data_len )
+{
+       WERROR        status       = WERR_OK;
+       TALLOC_CTX    *ctx         = NULL;
+       NT_DEVICEMODE *nt_devmode  = NULL;
+       NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode;
+       
+       /*
+        * When the DEVMODE is already set on the printer, don't try to unpack it.
+        */
+       DEBUG(8,("save_driver_init_2: Enter...\n"));
+       
+       if ( !printer->info_2->devmode && data_len ) 
+       {
+               /*
+                * Set devmode on printer info, so entire printer initialization can be
+                * saved to tdb.
+                */
+
+               if ((ctx = talloc_init()) == NULL)
+                       return WERR_NOMEM;
+
+               if ((nt_devmode = (NT_DEVICEMODE*)malloc(sizeof(NT_DEVICEMODE))) == NULL) {
+                       status = WERR_NOMEM;
+                       goto done;
+               }
+       
+               ZERO_STRUCTP(nt_devmode);
+
+               /*
+                * The DEVMODE is held in the 'data' component of the param in raw binary.
+                * Convert it to to a devmode structure
+                */
+               if ( !convert_driver_init( ctx, nt_devmode, data, data_len )) {
+                       DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
+                       status = WERR_INVALID_PARAM;
+                       goto done;
+               }
+
+               printer->info_2->devmode = nt_devmode;
+       }
+
+       /*
+        * Pack up and add (or update) the DEVMODE and any current printer data to
+        * a 'driver init' element in the tdb
+        * 
+        */
+
+       if ( update_driver_init(*printer, 2) != 0 ) {
+               DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
+               status = WERR_NOMEM;
+               goto done;
+       }
+       
+       /*
+        * If driver initialization info was successfully saved, set the current 
+        * printer to match it. This allows initialization of the current printer 
+        * as well as the driver.
+        */
+       status = mod_a_printer(*printer, 2);
+       if (!W_ERROR_IS_OK(status)) {
+               DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
+                                 printer->info_2->printername));
+       }
+       
+  done:
+       talloc_destroy(ctx);
+       free_nt_devicemode( &nt_devmode );
+       
+       printer->info_2->devmode = tmp_devmode;
+
+       return status;
+}
+
+/****************************************************************************
+ Update the driver init info (DEVMODE and specifics) for a printer
+****************************************************************************/
+
+WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, uint8 *data, uint32 data_len)
+{
+       WERROR status = WERR_OK;
+       
+       switch (level)
+       {
+               case 2:
+               {
+                       status = save_driver_init_2( printer, data, data_len );
+                       break;
+               }
+               default:
+                       status = WERR_UNKNOWN_LEVEL;
+                       break;
+       }
+       
+       return status;
+}
+
 /****************************************************************************
  Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
 ****************************************************************************/
@@ -3445,13 +3724,13 @@ uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
   to a printer
 ****************************************************************************/
 
-BOOL printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *i )
+BOOL printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3 )
 {
        int snum;
        int n_services = lp_numservices();
        NT_PRINTER_INFO_LEVEL *printer = NULL;
 
-       if ( !i ) 
+       if ( !info_3 ) 
                return False;
 
        DEBUG(5,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
@@ -3466,7 +3745,7 @@ BOOL printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *i )
                if ( !W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))) )
                        continue;
                
-               if ( !StrCaseCmp(i->name, printer->info_2->drivername) ) {
+               if ( !StrCaseCmp(info_3->name, printer->info_2->drivername) ) {
                        free_a_printer( &printer, 2 );
                        return True;
                }
@@ -3488,7 +3767,7 @@ BOOL printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *i )
  
 static BOOL drv_file_in_use( char* file, NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
 {
-       char *s;
+       int i = 0;
        
        if ( !info )
                return False;
@@ -3504,16 +3783,18 @@ static BOOL drv_file_in_use( char* file, NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
 
        if ( strequal(file, info->helpfile) )
                return True;
-               
-       s = (char*) info->dependentfiles;
        
-       if ( s ) {
-               while ( *s )
-               {
-                       if ( strequal(file, s) )
-                               return True;
-                       s += strlen(s) + 1;
-               }
+       /* see of there are any dependent files to examine */
+       
+       if ( !info->dependentfiles )
+               return False;
+       
+       while ( *info->dependentfiles[i] ) 
+       {
+               if ( strequal(file, info->dependentfiles[i]) )
+                       return True;
+                       
+               i++;
        }
        
        return False;
@@ -3525,27 +3806,20 @@ static BOOL drv_file_in_use( char* file, NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
  input parameter from the list 
  *********************************************************************/
 
-static void trim_dependent_file( char* s )
+static void trim_dependent_file( fstring files[], int idx )
 {
-       char *p;
-       
-       /* set p to the next character string in the list */
-       
-       p = s + strlen( s ) + 1;
-       
-       /* check to see that we have another string to copy back */
        
-       if ( *p == '\0' ) 
+       /* bump everything down a slot */
+
+       while( *files[idx+1] ) 
        {
-               /* loop over s copying characters from p to s */
-               while ( *p!='\0' && *(p+1)!='\0' )
-                       *s++ = *p++;
+               fstrcpy( files[idx], files[idx+1] );
+               idx++;
        }
        
-       /* add the two trailing NULL's */
-       
-       *s      = '\0';
-       *(s+1)  = '\0';
+       *files[idx] = '\0';
+
+       return; 
 }
 
 /**********************************************************************
@@ -3555,8 +3829,8 @@ static void trim_dependent_file( char* s )
 static BOOL trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *src, 
                                       NT_PRINTER_DRIVER_INFO_LEVEL_3 *drv )
 {
-       BOOL in_use = False;
-       char *s;
+       BOOL    in_use = False;
+       int     i = 0;
        
        if ( !src || !drv )
                return False;
@@ -3565,33 +3839,43 @@ static BOOL trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *src,
        
        if ( drv_file_in_use(src->driverpath, drv) ) {
                in_use = True;
+               DEBUG(10,("Removing driverfile [%s] from list\n", src->driverpath));
                fstrcpy( src->driverpath, "" );
        }
                
        if ( drv_file_in_use(src->datafile, drv) ) {
                in_use = True;
+               DEBUG(10,("Removing datafile [%s] from list\n", src->datafile));
                fstrcpy( src->datafile, "" );
        }
                
        if ( drv_file_in_use(src->configfile, drv) ) {
                in_use = True;
+               DEBUG(10,("Removing configfile [%s] from list\n", src->configfile));
                fstrcpy( src->configfile, "" );
        }
                
-       s = (char*)src->dependentfiles;
-       
-       if ( s ) {
-               while ( *s ) 
-               {
-                       if ( drv_file_in_use(s, drv) ) {
-                               in_use = True;
-                               trim_dependent_file( s );
-                       }
-                       else
-                               s += strlen(s) + 1;     
-               } 
+       if ( drv_file_in_use(src->helpfile, drv) ) {
+               in_use = True;
+               DEBUG(10,("Removing helpfile [%s] from list\n", src->helpfile));
+               fstrcpy( src->helpfile, "" );
        }
+       
+       /* are there any dependentfiles to examine? */
+       
+       if ( !src->dependentfiles )
+               return in_use;
                
+       while ( *src->dependentfiles[i] ) 
+       {
+               if ( drv_file_in_use(src->dependentfiles[i], drv) ) {
+                       in_use = True;
+                       DEBUG(10,("Removing [%s] from dependent file list\n", src->dependentfiles[i]));
+                       trim_dependent_file( src->dependentfiles, i );
+               }
+               else
+                       i++;
+       }               
                
        return in_use;
 }
@@ -3615,59 +3899,62 @@ BOOL printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
        fstring                         *list = NULL;
        NT_PRINTER_DRIVER_INFO_LEVEL    driver;
        
+       if ( !info )
+               return False;
+       
+       version = info->cversion;
+       
        /* loop over all driver versions */
        
        DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
        
-       for ( version=0; version<DRIVER_MAX_VERSION; version++ )
-       {
-               /* get the list of drivers */
+       /* get the list of drivers */
                
-               list = NULL;
-               ndrivers = get_ntdrivers(&list, info->environment, version);
+       list = NULL;
+       ndrivers = get_ntdrivers(&list, info->environment, version);
                
-               DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", 
-                       ndrivers, info->environment, version));
+       DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", 
+               ndrivers, info->environment, version));
 
-               if (ndrivers == -1)
-                       continue;
-                       
-               /* check each driver for overlap in files */
+       /* check each driver for overlap in files */
                
-               for (i=0; i<ndrivers; i++) 
-               {
-                       DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
+       for (i=0; i<ndrivers; i++) 
+       {
+               DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
                        
-                       ZERO_STRUCT(driver);
+               ZERO_STRUCT(driver);
                        
-                       if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, list[i], 
-                               info->environment, version)) )
-                       {
-                               SAFE_FREE(list);
-                               return True;
-                       }
+               if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, list[i], 
+                       info->environment, version)) )
+               {
+                       SAFE_FREE(list);
+                       return True;
+               }
                        
-                       /* check if d2 uses any files from d1 */
-                       /* only if this is a different driver than the one being deleted */
+               /* check if d2 uses any files from d1 */
+               /* only if this is a different driver than the one being deleted */
                        
-                       if ( !strequal(info->name, driver.info_3->name) 
-                               || (info->cversion != driver.info_3->cversion) )
-                       {
-                               if ( trim_overlap_drv_files(info, driver.info_3) ) {
-                                       free_a_printer_driver(driver, 3);
-                                       SAFE_FREE( list );
-                                       return True;
-                               }
+               if ( !strequal(info->name, driver.info_3->name) )
+               {
+                       if ( trim_overlap_drv_files(info, driver.info_3) ) {
+                               free_a_printer_driver(driver, 3);
+                               SAFE_FREE( list );
+                               return True;
                        }
+               }
        
-                       free_a_printer_driver(driver, 3);
-               }       
-               
-               SAFE_FREE(list);
-       }
+               free_a_printer_driver(driver, 3);
+       }       
+       
+       SAFE_FREE(list);
        
        DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
        
+       driver.info_3 = info;
+       
+       if ( DEBUGLEVEL >= 20 )
+               dump_a_printer_driver( driver, 3 );
+       
        return False;
 }
 
@@ -3677,17 +3964,18 @@ BOOL printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
   this.
 ****************************************************************************/
 
-static BOOL delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *i, struct current_user *user )
+static BOOL delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user )
 {
+       int i = 0;
        char *s;
        connection_struct *conn;
        DATA_BLOB null_pw;
        NTSTATUS nt_status;
        
-       if ( !i )
+       if ( !info_3 )
                return False;
                
-       DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", i->name, i->cversion));
+       DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", info_3->name, info_3->cversion));
        
        /*
         * Connect to the print$ share under the same account as the 
@@ -3715,49 +4003,55 @@ static BOOL delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *i, struct curre
        /* now delete the files; must strip the '\print$' string from 
           fron of path                                                */
        
-       if ( *i->driverpath ) {
-               if ( (s = strchr( &i->driverpath[1], '\\' )) != NULL ) {
+       if ( *info_3->driverpath ) {
+               if ( (s = strchr( &info_3->driverpath[1], '\\' )) != NULL ) {
                        DEBUG(10,("deleting driverfile [%s]\n", s));
                        unlink_internals(conn, 0, s);
                }
        }
                
-       if ( *i->configfile ) {
-               if ( (s = strchr( &i->configfile[1], '\\' )) != NULL ) {
+       if ( *info_3->configfile ) {
+               if ( (s = strchr( &info_3->configfile[1], '\\' )) != NULL ) {
                        DEBUG(10,("deleting configfile [%s]\n", s));
                        unlink_internals(conn, 0, s);
                }
        }
        
-       if ( *i->datafile ) {
-               if ( (s = strchr( &i->datafile[1], '\\' )) != NULL ) {
+       if ( *info_3->datafile ) {
+               if ( (s = strchr( &info_3->datafile[1], '\\' )) != NULL ) {
                        DEBUG(10,("deleting datafile [%s]\n", s));
                        unlink_internals(conn, 0, s);
                }
        }
        
-       if ( *i->helpfile ) {
-               if ( (s = strchr( &i->helpfile[1], '\\' )) != NULL ) {
+       if ( *info_3->helpfile ) {
+               if ( (s = strchr( &info_3->helpfile[1], '\\' )) != NULL ) {
                        DEBUG(10,("deleting helpfile [%s]\n", s));
                        unlink_internals(conn, 0, s);
                }
        }
        
-       s = (char*)i->dependentfiles;
+       /* check if we are done removing files */
        
-       while ( s && *s ) {
-               char *file;
+       if ( info_3->dependentfiles )
+       {
+               while ( *info_3->dependentfiles[i] ) {
+                       char *file;
 
-               if ( (file = strchr( s+1, '\\' )) != NULL )
-               {
-                       DEBUG(10,("deleting dependent file [%s]\n", file));
-                       unlink_internals(conn, 0, file );
-                       file += strlen( file ) + 1;
+                       /* bypass the "\print$" portion of the path */
+                       
+                       if ( (file = strchr( info_3->dependentfiles[i]+1, '\\' )) != NULL )
+                       {
+                               DEBUG(10,("deleting dependent file [%s]\n", file));
+                               unlink_internals(conn, 0, file );
+                       }
+                       
+                       i++;
                }
-
-               s = file;
        }
 
+       unbecome_user();
+       
        return True;
 }
 
@@ -3766,7 +4060,7 @@ static BOOL delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *i, struct curre
  previously looked up.
  ***************************************************************************/
 
-static WERROR delete_printer_driver_internal( NT_PRINTER_DRIVER_INFO_LEVEL_3 *i, struct current_user *user,
+WERROR delete_printer_driver( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user,
                               uint32 version, BOOL delete_files )
 {
        pstring         key;
@@ -3776,14 +4070,14 @@ static WERROR delete_printer_driver_internal( NT_PRINTER_DRIVER_INFO_LEVEL_3 *i,
 
        /* delete the tdb data first */
 
-       get_short_archi(arch, i->environment);
+       get_short_archi(arch, info_3->environment);
        slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX,
-               arch, version, i->name);
+               arch, version, info_3->name);
 
        DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
                key, delete_files ? "TRUE" : "FALSE" ));
 
-       ctr.info_3 = i;
+       ctr.info_3 = info_3;
        dump_a_printer_driver( ctr, 3 );
 
        kbuf.dptr=key;
@@ -3793,7 +4087,7 @@ static WERROR delete_printer_driver_internal( NT_PRINTER_DRIVER_INFO_LEVEL_3 *i,
        
        dbuf = tdb_fetch( tdb_drivers, kbuf );
        if ( !dbuf.dptr ) {
-               DEBUG(8,("delete_printer_driver_internal: Driver unknown [%s]\n", key));
+               DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key));
                return WERR_UNKNOWN_PRINTER_DRIVER;
        }
                
@@ -3802,7 +4096,7 @@ static WERROR delete_printer_driver_internal( NT_PRINTER_DRIVER_INFO_LEVEL_3 *i,
        /* ok... the driver exists so the delete should return success */
                
        if (tdb_delete(tdb_drivers, kbuf) == -1) {
-               DEBUG (0,("delete_printer_driver_internal: fail to delete %s!\n", key));
+               DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
                return WERR_ACCESS_DENIED;
        }
 
@@ -3813,51 +4107,14 @@ static WERROR delete_printer_driver_internal( NT_PRINTER_DRIVER_INFO_LEVEL_3 *i,
         */
 
        if ( delete_files )
-               delete_driver_files( i, user );
-
-
-       DEBUG(5,("delete_printer_driver_internal: driver delete successful [%s]\n", key));
-
-       return WERR_OK;
-}
-
-/****************************************************************************
- Remove a printer driver from the TDB.  This assumes that the the driver was
- previously looked up.
- ***************************************************************************/
-
-WERROR delete_printer_driver( NT_PRINTER_DRIVER_INFO_LEVEL_3 *i, struct current_user *user,
-                              uint32 version, BOOL delete_files )
-{
-       WERROR err;
-
-       /*
-        * see if we should delete all versions of this driver 
-        * (DRIVER_ANY_VERSION uis only set for "Windows NT x86")
-        */
-
-       if ( version == DRIVER_ANY_VERSION ) 
-       {
-               /* Windows NT 4.0 */
-               
-               err = delete_printer_driver_internal(i, user, 2, delete_files );
-               if ( !W_ERROR_IS_OK(err) && (W_ERROR_V(err) != ERRunknownprinterdriver ) )
-                       return err;
+               delete_driver_files( info_3, user );
                        
-               /* Windows 2000/XP  */
                
-               err = delete_printer_driver_internal(i, user, 3, delete_files );
-               if ( !W_ERROR_IS_OK(err) && (W_ERROR_V(err) != ERRunknownprinterdriver ) )
-                               return err;
+       DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key));
 
        return WERR_OK;
        }
        
-       /* just delete what they asked for */
-       
-       return delete_printer_driver_internal(i, user, version, delete_files );
-}
-
 /****************************************************************************
  Store a security desc for a printer.
 ****************************************************************************/
index 51ebb739a33afda78ff8b3cf4f316e037e65c700..2df846aa5798c8f2d1e8ffede2adfc30eb865dd4 100644 (file)
@@ -73,9 +73,9 @@ cups_passwd_cb(const char *prompt)    /* I - Prompt */
  *                       system.
  */
 
-void
-cups_printer_fn(void (*fn)(char *, char *))    /* I - Function to call */
+void cups_printer_fn(void (*fn)(char *, char *))
 {
+       /* I - Function to call */
        http_t          *http;          /* HTTP connection to server */
        ipp_t           *request,       /* IPP Request */
                        *response;      /* IPP Response */
@@ -665,6 +665,10 @@ cups_job_submit(int snum, struct printjob *pjob)
 
        httpClose(http);
 
+       if ( ret == 0 )
+               unlink(pjob->filename);
+       /* else print_job_end will do it for us */
+
        return (ret);
 }
 
index ff50ac47c492e18d6e939935e55ccc6705c49bd2..8a4e7ea073b0cda26b10d6df9c7574d25da72290 100644 (file)
@@ -46,7 +46,7 @@ files_struct *print_fsp_open(connection_struct *conn, char *fname)
                fstrcat(name, p);
        }
 
-       jobid = print_job_start(&current_user, SNUM(conn), name);
+       jobid = print_job_start(&current_user, SNUM(conn), name, NULL);
        if (jobid == -1) {
                file_free(fsp);
                return NULL;
index cb689c05d6636bec15f554424db2c55f67009fe9..6474c92c692c5a16cd6a64fc0bcb01bc94a3985a 100644 (file)
@@ -132,11 +132,13 @@ static pid_t local_pid;
 
 static int get_queue_status(int, print_status_struct *);
 
+/* There can be this many printing tdb's open, plus any locked ones. */
 #define MAX_PRINT_DBS_OPEN 1
 
 struct tdb_print_db {
        struct tdb_print_db *next, *prev;
        TDB_CONTEXT *tdb;
+       int ref_count;
        fstring printer_name;
 };
 
@@ -149,32 +151,45 @@ static struct tdb_print_db *print_db_head;
 
 static struct tdb_print_db *get_print_db_byname(const char *printername)
 {
-       struct tdb_print_db *p, *last_entry;
+       struct tdb_print_db *p = NULL, *last_entry = NULL;
        int num_open = 0;
        pstring printdb_path;
 
        for (p = print_db_head, last_entry = print_db_head; p; p = p->next) {
                if (p->tdb && strequal(p->printer_name, printername)) {
                        DLIST_PROMOTE(print_db_head, p);
+                       p->ref_count++;
                        return p;
                }
                num_open++;
                last_entry = p;
        }
+
        /* Not found. */
        if (num_open >= MAX_PRINT_DBS_OPEN) {
-               /* Recycle the last entry. */
+               /* Try and recycle the last entry. */
                DLIST_PROMOTE(print_db_head, last_entry);
-               if (print_db_head->tdb) {
-                       if (tdb_close(print_db_head->tdb)) {
-                               DEBUG(0,("get_print_db: Failed to close tdb for printer %s\n",
-                                                       print_db_head->printer_name ));
-                               return NULL;
+
+               for (p = print_db_head; p; p = p->next) {
+                       if (p->ref_count)
+                               continue;
+                       if (p->tdb) {
+                               if (tdb_close(print_db_head->tdb)) {
+                                       DEBUG(0,("get_print_db: Failed to close tdb for printer %s\n",
+                                                               print_db_head->printer_name ));
+                                       return NULL;
+                               }
                        }
+                       ZERO_STRUCTP(p);
+                       break;
                }
-               p = print_db_head;
-               ZERO_STRUCTP(p);
-       } else {
+               if (p) {
+                       DLIST_PROMOTE(print_db_head, p);
+                       p = print_db_head;
+               }
+       }
+       
+       if (!p) {
                /* Create one. */
                p = (struct tdb_print_db *)malloc(sizeof(struct tdb_print_db));
                if (!p) {
@@ -201,9 +216,16 @@ static struct tdb_print_db *get_print_db_byname(const char *printername)
                return NULL;
        }
        fstrcpy(p->printer_name, printername);
+       p->ref_count++;
        return p;
 }
 
+static void release_print_db( struct tdb_print_db *pdb)
+{
+       pdb->ref_count--;
+       SMB_ASSERT(pdb->ref_count >= 0);
+}
+
 /****************************************************************************
  Initialise the printing backend. Called once at startup. 
  Does not survive a fork
@@ -235,7 +257,10 @@ BOOL print_backend_init(void)
                pdb = get_print_db_byname(lp_const_servicename(snum));
                if (!pdb)
                        continue;
-               tdb_lock_bystring(pdb->tdb, sversion);
+               if (tdb_lock_bystring(pdb->tdb, sversion) == -1) {
+                       DEBUG(0,("print_backend_init: Failed to open printer %s database\n", lp_const_servicename(snum) ));
+                       return False;
+               }
                if (tdb_fetch_int32(pdb->tdb, sversion) != PRINT_DATABASE_VERSION) {
                        tdb_traverse(pdb->tdb, tdb_traverse_delete_fn, NULL);
                        tdb_store_int32(pdb->tdb, sversion, PRINT_DATABASE_VERSION);
@@ -286,25 +311,74 @@ static TDB_DATA print_key(uint32 jobid)
        return ret;
 }
 
+/***********************************************************************
+ unpack a pjob from a tdb buffer 
+***********************************************************************/
+int unpack_pjob( char* buf, int buflen, struct printjob *pjob )
+{
+       int     len = 0;
+       int     used;
+       
+       if ( !buf || !pjob )
+               return -1;
+               
+       len += tdb_unpack(buf+len, buflen-len, "dddddddddffff",
+                               &pjob->pid,
+                               &pjob->sysjob,
+                               &pjob->fd,
+                               &pjob->starttime,
+                               &pjob->status,
+                               &pjob->size,
+                               &pjob->page_count,
+                               &pjob->spooled,
+                               &pjob->smbjob,
+                               pjob->filename,
+                               pjob->jobname,
+                               pjob->user,
+                               pjob->queuename);
+                               
+       if ( len == -1 )
+               return -1;
+               
+       if ( (used = unpack_devicemode(&pjob->nt_devmode, buf+len, buflen-len)) == -1 )
+               return -1;
+       
+       len += used;
+       
+       return len;
+
+}
+
 /****************************************************************************
  Useful function to find a print job in the database.
 ****************************************************************************/
 
 static struct printjob *print_job_find(int snum, uint32 jobid)
 {
-       static struct printjob pjob;
-       TDB_DATA ret;
-       struct tdb_print_db *pdb = get_print_db_byname(lp_const_servicename(snum));
+       static struct printjob  pjob;
+       TDB_DATA                ret;
+       struct tdb_print_db     *pdb = get_print_db_byname(lp_const_servicename(snum));
+       
 
        if (!pdb)
                return NULL;
 
        ret = tdb_fetch(pdb->tdb, print_key(jobid));
-       if (!ret.dptr || ret.dsize != sizeof(pjob))
-               return NULL;
+       release_print_db(pdb);
 
-       memcpy(&pjob, ret.dptr, sizeof(pjob));
-       SAFE_FREE(ret.dptr);
+       if (!ret.dptr)
+               return NULL;
+       
+       if ( pjob.nt_devmode )
+               free_nt_devicemode( &pjob.nt_devmode );
+               
+       ZERO_STRUCT( pjob );
+       
+       if ( unpack_pjob( ret.dptr, ret.dsize, &pjob ) == -1 )
+               return NULL;
+       
+       SAFE_FREE(ret.dptr);    
        return &pjob;
 }
 
@@ -315,9 +389,13 @@ static uint32 sysjob_to_jobid_value;
 static int unixjob_traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA key,
                               TDB_DATA data, void *state)
 {
-       struct printjob *pjob = (struct printjob *)data.dptr;
+       struct printjob *pjob;
        int *sysjob = (int *)state;
 
+       if (!data.dptr || data.dsize == 0)
+               return 0;
+
+       pjob = (struct printjob *)data.dptr;
        if (key.dsize != sizeof(uint32))
                return 0;
 
@@ -350,6 +428,7 @@ uint32 sysjob_to_jobid(int unix_jobid)
                pdb = get_print_db_byname(lp_const_servicename(snum));
                if (pdb)
                        tdb_traverse(pdb->tdb, unixjob_traverse_fn, &unix_jobid);
+               release_print_db(pdb);
                if (sysjob_to_jobid_value != (uint32)-1)
                        return sysjob_to_jobid_value;
        }
@@ -434,9 +513,12 @@ static void pjob_store_notify(int snum, uint32 jobid, struct printjob *old_data,
 
 static BOOL pjob_store(int snum, uint32 jobid, struct printjob *pjob)
 {
-       TDB_DATA old_data, new_data;
-       BOOL ret;
-       struct tdb_print_db *pdb = get_print_db_byname(lp_const_servicename(snum));
+       TDB_DATA                old_data, new_data;
+       BOOL                    ret = False;
+       struct tdb_print_db     *pdb = get_print_db_byname(lp_const_servicename(snum));
+       char                    *buf = NULL;
+       int                     len, newlen, buflen;
+       
 
        if (!pdb)
                return False;
@@ -445,20 +527,63 @@ static BOOL pjob_store(int snum, uint32 jobid, struct printjob *pjob)
 
        old_data = tdb_fetch(pdb->tdb, print_key(jobid));
 
+       /* Doh!  Now we have to pack/unpack data since the NT_DEVICEMODE was added */
+
+       newlen = 0;
+       
+       do {
+               len = 0;
+               buflen = newlen;
+               len += tdb_pack(buf+len, buflen-len, "dddddddddffff",
+                               pjob->pid,
+                               pjob->sysjob,
+                               pjob->fd,
+                               pjob->starttime,
+                               pjob->status,
+                               pjob->size,
+                               pjob->page_count,
+                               pjob->spooled,
+                               pjob->smbjob,
+                               pjob->filename,
+                               pjob->jobname,
+                               pjob->user,
+                               pjob->queuename);
+
+               len += pack_devicemode(pjob->nt_devmode, buf+len, buflen-len);
+       
+               if (buflen != len) 
+               {
+                       char *tb;
+
+                       tb = (char *)Realloc(buf, len);
+                       if (!tb) {
+                               DEBUG(0,("pjob_store: failed to enlarge buffer!\n"));
+                               goto done;
+                       }
+                       else 
+                               buf = tb;
+                       newlen = len;
+               }
+       }
+       while ( buflen != len );
+               
+       
        /* Store new data */
 
-       new_data.dptr = (void *)pjob;
-       new_data.dsize = sizeof(*pjob);
+       new_data.dptr = buf;
+       new_data.dsize = len;
        ret = (tdb_store(pdb->tdb, print_key(jobid), new_data, TDB_REPLACE) == 0);
 
+       release_print_db(pdb);
+
        /* Send notify updates for what has changed */
 
-       if (ret && (old_data.dsize == 0 || old_data.dsize == sizeof(*pjob))) {
-               pjob_store_notify(
-                       snum, jobid, (struct printjob *)old_data.dptr,
-                       (struct printjob *)new_data.dptr);
-               free(old_data.dptr);
-       }
+       if ( ret && (old_data.dsize == 0 || old_data.dsize == sizeof(*pjob)) )
+               pjob_store_notify( snum, jobid, (struct printjob *)old_data.dptr, pjob );
+
+done:
+       SAFE_FREE( old_data.dptr );
+       SAFE_FREE( buf );
 
        return ret;
 }
@@ -479,6 +604,7 @@ static void pjob_delete(int snum, uint32 jobid)
        if (!pjob) {
                DEBUG(5, ("pjob_delete(): we were asked to delete nonexistent job %u\n",
                                        (unsigned int)jobid));
+               release_print_db(pdb);
                return;
        }
 
@@ -499,6 +625,7 @@ static void pjob_delete(int snum, uint32 jobid)
        /* Remove from printing.tdb */
 
        tdb_delete(pdb->tdb, print_key(jobid));
+       release_print_db(pdb);
        rap_jobid_delete(snum, jobid);
 }
 
@@ -569,10 +696,14 @@ static int traverse_fn_delete(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void
        uint32 jobid;
        int i;
 
-       if (data.dsize != sizeof(pjob) || key.dsize != sizeof(jobid))
+       if (  key.dsize != sizeof(jobid) )
                return 0;
+               
        memcpy(&jobid, key.dptr, sizeof(jobid));
-       memcpy(&pjob,  data.dptr, sizeof(pjob));
+       if ( unpack_pjob( data.dptr, data.dsize, &pjob ) == -1 )
+               return 0;
+       free_nt_devicemode( &pjob.nt_devmode );
+
 
        if (ts->snum != lp_servicenumber(pjob.queuename)) {
                /* this isn't for the queue we are looking at - this cannot happen with the split tdb's. JRA */
@@ -651,6 +782,7 @@ static void print_cache_flush(int snum)
                return;
        slprintf(key, sizeof(key)-1, "CACHE/%s", printername);
        tdb_store_int32(pdb->tdb, key, -1);
+       release_print_db(pdb);
 }
 
 /****************************************************************************
@@ -671,6 +803,7 @@ static pid_t get_updating_pid(fstring printer_name)
        key.dsize = strlen(keystr);
 
        data = tdb_fetch(pdb->tdb, key);
+       release_print_db(pdb);
        if (!data.dptr || data.dsize != sizeof(pid_t))
                return (pid_t)-1;
 
@@ -705,6 +838,7 @@ static void set_updating_pid(const fstring printer_name, BOOL delete)
 
        if (delete) {
                tdb_delete(pdb->tdb, key);
+               release_print_db(pdb);
                return;
        }
        
@@ -712,6 +846,7 @@ static void set_updating_pid(const fstring printer_name, BOOL delete)
        data.dsize = sizeof(pid_t);
 
        tdb_store(pdb->tdb, key, data, TDB_REPLACE);    
+       release_print_db(pdb);
 }
 
 /****************************************************************************
@@ -740,13 +875,19 @@ static void print_queue_update(int snum)
         * This is essentially a mutex on the update.
         */
 
-       if (get_updating_pid(printer_name) != -1)
+       if (get_updating_pid(printer_name) != -1) {
+               release_print_db(pdb);
                return;
+       }
 
        /* Lock the queue for the database update */
 
        slprintf(keystr, sizeof(keystr) - 1, "LOCK/%s", printer_name);
-       tdb_lock_bystring(pdb->tdb, keystr);
+       if (tdb_lock_bystring(pdb->tdb, keystr) == -1) {
+               DEBUG(0,("print_queue_update: Failed to lock printer %s database\n", printer_name));
+               release_print_db(pdb);
+               return;
+       }
 
        /*
         * Ensure that no one else got in here.
@@ -759,6 +900,7 @@ static void print_queue_update(int snum)
                 * Someone else is doing the update, exit.
                 */
                tdb_unlock_bystring(pdb->tdb, keystr);
+               release_print_db(pdb);
                return;
        }
 
@@ -865,6 +1007,7 @@ static void print_queue_update(int snum)
 
        /* Delete our pid from the db. */
        set_updating_pid(printer_name, True);
+       release_print_db(pdb);
 }
 
 /****************************************************************************
@@ -874,9 +1017,13 @@ static void print_queue_update(int snum)
 BOOL print_job_exists(int snum, uint32 jobid)
 {
        struct tdb_print_db *pdb = get_print_db_byname(lp_const_servicename(snum));
+       BOOL ret;
+
        if (!pdb)
                return False;
-       return tdb_exists(pdb->tdb, print_key(jobid));
+       ret = tdb_exists(pdb->tdb, print_key(jobid));
+       release_print_db(pdb);
+       return ret;
 }
 
 /****************************************************************************
@@ -908,6 +1055,23 @@ char *print_job_fname(int snum, uint32 jobid)
        return pjob->filename;
 }
 
+
+/****************************************************************************
+ Give the filename used for a jobid.
+ Only valid for the process doing the spooling and when the job
+ has not been spooled.
+****************************************************************************/
+
+NT_DEVICEMODE *print_job_devmode(int snum, uint32 jobid)
+{
+       struct printjob *pjob = print_job_find(snum, jobid);
+       
+       if ( !pjob )
+               return NULL;
+               
+       return pjob->nt_devmode;
+}
+
 /****************************************************************************
  Set the place in the queue for a job.
 ****************************************************************************/
@@ -1000,8 +1164,11 @@ 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)
 {
-       BOOL owner;
+       BOOL    owner, deleted;
+       char    *fname;
 
+       *errcode = WERR_OK;
+               
        owner = is_owner(user, snum, jobid);
        
        /* Check access against security descriptor or whether the user
@@ -1014,15 +1181,40 @@ BOOL print_job_delete(struct current_user *user, int snum, uint32 jobid, WERROR
                return False;
        }
 
-       if (!print_job_delete1(snum, jobid)) 
+       /* 
+        * get the spooled filename of the print job
+        * if this works, then the file has not been spooled
+        * to the underlying print system.  Just delete the 
+        * spool file & return.
+        */
+        
+       if ( (fname = print_job_fname( snum, jobid )) != NULL )
+       {
+               /* remove the spool file */
+               DEBUG(10,("print_job_delete: Removing spool file [%s]\n", fname ));
+               if ( unlink( fname ) == -1 ) {
+                       *errcode = map_werror_from_unix(errno);
+                       return False;
+               }
+               
+               return True;
+       }
+       
+       if (!print_job_delete1(snum, jobid)) {
+               *errcode = WERR_ACCESS_DENIED;
                return False;
+       }
 
        /* force update the database and say the delete failed if the
            job still exists */
 
        print_queue_update(snum);
+       
+       deleted = !print_job_exists(snum, jobid);
+       if ( !deleted )
+               *errcode = WERR_ACCESS_DENIED;
 
-       return !print_job_exists(snum, jobid);
+       return deleted;
 }
 
 /****************************************************************************
@@ -1161,8 +1353,10 @@ static BOOL print_cache_expired(int snum)
                DEBUG(3, ("print cache expired for queue %s \
 (last_qscan_time = %d, time now = %d, qcachetime = %d)\n", printername,
                        (int)last_qscan_time, (int)time_now, (int)lp_lpqcachetime() ));
+               release_print_db(pdb);
                return True;
        }
+       release_print_db(pdb);
        return False;
 }
 
@@ -1184,6 +1378,7 @@ static int get_queue_status(int snum, print_status_struct *status)
        key.dptr = keystr;
        key.dsize = strlen(keystr);
        data = tdb_fetch(pdb->tdb, key);
+       release_print_db(pdb);
        if (data.dptr) {
                if (data.dsize == sizeof(print_status_struct)) {
                        memcpy(status, data.dptr, sizeof(print_status_struct));
@@ -1214,44 +1409,11 @@ int print_queue_length(int snum, print_status_struct *pstatus)
        return len;
 }
 
-/****************************************************************************
- Determine the number of jobs in all queues. This is very expensive. Don't
- call ! JRA.
-****************************************************************************/
-
-static int get_total_jobs(void)
-{
-       int total_jobs = 0;
-       int snum;
-       int services = lp_numservices();
-
-       for (snum = 0; snum < services; snum++) {
-               struct tdb_print_db *pdb;
-               int jobs;
-
-               if (!lp_print_ok(snum))
-                       continue;
-
-               pdb = get_print_db_byname(lp_const_servicename(snum));
-               if (!pdb)
-                       continue;
-
-               /* make sure the database is up to date */
-               if (print_cache_expired(snum))
-                       print_queue_update(snum);
-
-               jobs = tdb_fetch_int32(pdb->tdb, "INFO/total_jobs");
-               if (jobs > 0)
-                       total_jobs += jobs;
-       }
-       return total_jobs;
-}
-
 /***************************************************************************
  Start spooling a job - return the jobid.
 ***************************************************************************/
 
-uint32 print_job_start(struct current_user *user, int snum, char *jobname)
+uint32 print_job_start(struct current_user *user, int snum, char *jobname, NT_DEVICEMODE *nt_devmode )
 {
        uint32 jobid;
        char *path;
@@ -1261,6 +1423,7 @@ uint32 print_job_start(struct current_user *user, int snum, char *jobname)
        int njobs = 0;
        const char *printername = lp_const_servicename(snum);
        struct tdb_print_db *pdb = get_print_db_byname(printername);
+       BOOL pdb_locked = False;
 
        errno = 0;
 
@@ -1269,11 +1432,13 @@ uint32 print_job_start(struct current_user *user, int snum, char *jobname)
 
        if (!print_access_check(user, snum, PRINTER_ACCESS_USE)) {
                DEBUG(3, ("print_job_start: job start denied by security descriptor\n"));
+               release_print_db(pdb);
                return (uint32)-1;
        }
 
        if (!print_time_access_check(snum)) {
                DEBUG(3, ("print_job_start: job start denied by time check\n"));
+               release_print_db(pdb);
                return (uint32)-1;
        }
 
@@ -1285,6 +1450,7 @@ uint32 print_job_start(struct current_user *user, int snum, char *jobname)
                if (sys_fsusage(path, &dspace, &dsize) == 0 &&
                    dspace < 2*(SMB_BIG_UINT)lp_minprintspace(snum)) {
                        DEBUG(3, ("print_job_start: disk space check failed.\n"));
+                       release_print_db(pdb);
                        errno = ENOSPC;
                        return (uint32)-1;
                }
@@ -1293,6 +1459,7 @@ uint32 print_job_start(struct current_user *user, int snum, char *jobname)
        /* for autoloaded printers, check that the printcap entry still exists */
        if (lp_autoloaded(snum) && !pcap_printername_ok(lp_const_servicename(snum), NULL)) {
                DEBUG(3, ("print_job_start: printer name %s check failed.\n", lp_const_servicename(snum) ));
+               release_print_db(pdb);
                errno = ENOENT;
                return (uint32)-1;
        }
@@ -1301,41 +1468,19 @@ uint32 print_job_start(struct current_user *user, int snum, char *jobname)
        if (lp_maxprintjobs(snum) && (njobs = print_queue_length(snum,NULL)) > lp_maxprintjobs(snum)) {
                DEBUG(3, ("print_job_start: number of jobs (%d) larger than max printjobs per queue (%d).\n",
                        njobs, lp_maxprintjobs(snum) ));
+               release_print_db(pdb);
                errno = ENOSPC;
                return (uint32)-1;
        }
 
-       /* Insure the maximum print jobs in the system is not violated */
-       if (lp_totalprintjobs() && get_total_jobs() > lp_totalprintjobs()) {
-               DEBUG(3, ("print_job_start: number of jobs (%d) larger than max printjobs per system (%d).\n",
-                       njobs, lp_totalprintjobs() ));
-               errno = ENOSPC;
+       /* Lock the database */
+       if (tdb_lock_bystring(pdb->tdb, "INFO/nextjob") == -1) {
+               DEBUG(0,("print_job_start: failed to lock printing database %s\n", printername ));
+               release_print_db(pdb);
                return (uint32)-1;
        }
 
-       /* create the database entry */
-       ZERO_STRUCT(pjob);
-       pjob.pid = local_pid;
-       pjob.sysjob = -1;
-       pjob.fd = -1;
-       pjob.starttime = time(NULL);
-       pjob.status = LPQ_SPOOLING;
-       pjob.size = 0;
-       pjob.spooled = False;
-       pjob.smbjob = True;
-
-       fstrcpy(pjob.jobname, jobname);
-
-       if ((vuser = get_valid_user_struct(user->vuid)) != NULL) {
-               fstrcpy(pjob.user, vuser->user.smb_name);
-       } else {
-               fstrcpy(pjob.user, uidtoname(user->uid));
-       }
-
-       fstrcpy(pjob.queuename, lp_const_servicename(snum));
-
-       /* lock the database */
-       tdb_lock_bystring(pdb->tdb, "INFO/nextjob");
+       pdb_locked = True;
 
        next_jobid = tdb_fetch_int32(pdb->tdb, "INFO/nextjob");
        if (next_jobid == -1)
@@ -1345,19 +1490,61 @@ uint32 print_job_start(struct current_user *user, int snum, char *jobname)
                if (!print_job_exists(snum, jobid))
                        break;
        }
-       if (jobid == next_jobid || !pjob_store(snum, jobid, &pjob)) {
-               DEBUG(3, ("print_job_start: either jobid (%d)==next_jobid(%d) or pjob_store failed.\n",
+                               
+       if (jobid == next_jobid) {
+               DEBUG(3, ("print_job_start: jobid (%d)==next_jobid(%d).\n",
                                jobid, next_jobid ));
                jobid = -1;
                goto fail;
        }
 
+       /* Store a dummy placeholder. This must be quick as we have the lock. */
+       {
+               TDB_DATA dum;
+               dum.dptr = NULL;
+               dum.dsize = 0;
+               if (tdb_store(pdb->tdb, print_key(jobid), dum, TDB_INSERT) == -1) {
+                       DEBUG(3, ("print_job_start: jobid (%d) failed to store placeholder.\n",
+                               jobid ));
+                       jobid = -1;
+                       goto fail;
+               }
+       }
+
        if (tdb_store_int32(pdb->tdb, "INFO/nextjob", jobid)==-1) {
                DEBUG(3, ("print_job_start: failed to store INFO/nextjob.\n"));
                jobid = -1;
                goto fail;
        }
 
+       /* We've finished with the INFO/nextjob lock. */
+       tdb_unlock_bystring(pdb->tdb, "INFO/nextjob");
+       pdb_locked = False;
+
+       /* create the database entry */
+       
+       ZERO_STRUCT(pjob);
+       
+       pjob.pid = local_pid;
+       pjob.sysjob = -1;
+       pjob.fd = -1;
+       pjob.starttime = time(NULL);
+       pjob.status = LPQ_SPOOLING;
+       pjob.size = 0;
+       pjob.spooled = False;
+       pjob.smbjob = True;
+       pjob.nt_devmode = nt_devmode;
+       
+       fstrcpy(pjob.jobname, jobname);
+
+       if ((vuser = get_valid_user_struct(user->vuid)) != NULL) {
+               fstrcpy(pjob.user, vuser->user.smb_name);
+       } else {
+               fstrcpy(pjob.user, uidtoname(user->uid));
+       }
+
+       fstrcpy(pjob.queuename, lp_const_servicename(snum));
+
        /* we have a job entry - now create the spool file */
        slprintf(pjob.filename, sizeof(pjob.filename)-1, "%s/%s%.8u.XXXXXX", 
                 path, PRINT_SPOOL_PREFIX, (unsigned int)jobid);
@@ -1378,7 +1565,7 @@ to open spool file %s.\n", pjob.filename));
 
        pjob_store(snum, jobid, &pjob);
 
-       tdb_unlock_bystring(pdb->tdb, "INFO/nextjob");
+       release_print_db(pdb);
 
        /*
         * If the printer is marked as postscript output a leading
@@ -1397,7 +1584,9 @@ to open spool file %s.\n", pjob.filename));
        if (jobid != -1)
                pjob_delete(snum, jobid);
 
-       tdb_unlock_bystring(pdb->tdb, "INFO/nextjob");
+       if (pdb_locked)
+               tdb_unlock_bystring(pdb->tdb, "INFO/nextjob");
+       release_print_db(pdb);
 
        DEBUG(3, ("print_job_start: returning fail. Error = %s\n", strerror(errno) ));
        return -1;
@@ -1503,10 +1692,16 @@ static int traverse_fn_queue(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *
        int i;
        uint32 jobid;
 
-       if (data.dsize != sizeof(pjob) || key.dsize != sizeof(int))
+       /* sanity checks */
+       
+       if ( key.dsize != sizeof(jobid) )
                return 0;
+               
        memcpy(&jobid, key.dptr, sizeof(jobid));
-       memcpy(&pjob,  data.dptr, sizeof(pjob));
+       
+       if ( unpack_pjob( data.dptr, data.dsize, &pjob ) == -1 )
+               return 0;
+       free_nt_devicemode( &pjob.nt_devmode );
 
        /* maybe it isn't for this queue */
        if (ts->snum != lp_servicenumber(pjob.queuename))
@@ -1545,10 +1740,17 @@ static int traverse_count_fn_queue(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data,
        struct printjob pjob;
        uint32 jobid;
 
-       if (data.dsize != sizeof(pjob) || key.dsize != sizeof(int))
+       /* sanity checks */
+       
+       if (  key.dsize != sizeof(jobid) )
                return 0;
+               
        memcpy(&jobid, key.dptr, sizeof(jobid));
-       memcpy(&pjob,  data.dptr, sizeof(pjob));
+       
+       if ( unpack_pjob( data.dptr, data.dsize, &pjob ) == -1 )
+               return 0;
+               
+       free_nt_devicemode( &pjob.nt_devmode );
 
        /* maybe it isn't for this queue - this cannot happen with the tdb/printer code. JRA */
        if (ts->snum != lp_servicenumber(pjob.queuename))
@@ -1630,13 +1832,17 @@ int print_queue_status(int snum,
        
        tdb_traverse(pdb->tdb, traverse_count_fn_queue, (void *)&tsc);
 
-       if (tsc.count == 0)
+       if (tsc.count == 0) {
+               release_print_db(pdb);
                return 0;
+       }
 
        /* Allocate the queue size. */
        if ((tstruct.queue = (print_queue_struct *)
-            malloc(sizeof(print_queue_struct)*tsc.count)) == NULL)
+            malloc(sizeof(print_queue_struct)*tsc.count)) == NULL) {
+               release_print_db(pdb);
                return 0;
+       }
 
        /*
         * Fill in the queue.
@@ -1648,6 +1854,7 @@ int print_queue_status(int snum,
        tstruct.snum = snum;
 
        tdb_traverse(pdb->tdb, traverse_fn_queue, (void *)&tstruct);
+       release_print_db(pdb);
 
        /* Sort the queue by submission time otherwise they are displayed
           in hash order. */
index 595593c6f0d554eae4b0363df9299d99b0530337..689f67da997d558208da04afabe3011440c535d5 100644 (file)
 
 #include "includes.h"
 
+#ifdef WITH_PROFILE
 #define IPC_PERMS ((SHM_R | SHM_W) | (SHM_R>>3) | (SHM_R>>6))
+#endif /* WITH_PROFILE */
 
+#ifdef WITH_PROFILE
 static int shm_id;
 static BOOL read_only;
+#endif
 
 struct profile_header *profile_h;
 struct profile_stats *profile_p;
@@ -45,6 +49,7 @@ void profile_message(int msg_type, pid_t src, void *buf, size_t len)
         int level;
 
        memcpy(&level, buf, sizeof(int));
+#ifdef WITH_PROFILE
        switch (level) {
        case 0:         /* turn off profiling */
                do_profile_flag = False;
@@ -66,6 +71,9 @@ void profile_message(int msg_type, pid_t src, void *buf, size_t len)
                DEBUG(1,("INFO: Profiling values cleared from pid %d\n", (int)src));
                break;
        }
+#else /* WITH_PROFILE */
+       DEBUG(1,("INFO: Profiling support unavailable in this build.\n"));
+#endif /* WITH_PROFILE */
 }
 
 /****************************************************************************
@@ -87,6 +95,7 @@ void reqprofile_message(int msg_type, pid_t src, void *buf, size_t len)
 /*******************************************************************
   open the profiling shared memory area
   ******************************************************************/
+#ifdef WITH_PROFILE
 BOOL profile_setup(BOOL rdonly)
 {
        struct shmid_ds shm_ds;
@@ -154,3 +163,4 @@ BOOL profile_setup(BOOL rdonly)
        message_register(MSG_REQ_PROFILELEVEL, reqprofile_message);
        return True;
 }
+#endif /* WITH_PROFILE */
index 45c1f24001070d10e1eab1db0606613eccff0260..a9dfb52f011b36250f129b075ed0871632df6b3c 100644 (file)
@@ -37,321 +37,6 @@ REGISTRY_HOOK reg_hooks[] = {
 };
 
 
-/*
- * Utility functions for REGSUBKEY_CTR
- */
-
-/***********************************************************************
- Init the talloc context held by a REGSUBKEY_CTR structure
- **********************************************************************/
-
-void regsubkey_ctr_init( REGSUBKEY_CTR *ctr )
-{
-       if ( !ctr->ctx )
-               ctr->ctx = talloc_init();
-}
-
-/***********************************************************************
- Add a new key to the array
- **********************************************************************/
-
-int regsubkey_ctr_addkey( REGSUBKEY_CTR *ctr, char *keyname )
-{
-       uint32 len;
-       char **pp;
-       
-       if ( keyname )
-       {
-               len = strlen( keyname );
-
-               /* allocate a space for the char* in the array */
-               
-               if (  ctr->subkeys == 0 )
-                       ctr->subkeys = talloc( ctr->ctx, sizeof(char*) );
-               else {
-                       pp = talloc_realloc( ctr->ctx, ctr->subkeys, sizeof(char*)*(ctr->num_subkeys+1) );
-                       if ( pp )
-                               ctr->subkeys = pp;
-               }
-
-               /* allocate the string and save it in the array */
-               
-               ctr->subkeys[ctr->num_subkeys] = talloc( ctr->ctx, len+1 );
-               strncpy( ctr->subkeys[ctr->num_subkeys], keyname, len+1 );
-               ctr->num_subkeys++;
-       }
-       
-       return ctr->num_subkeys;
-}
-/***********************************************************************
- How many keys does the container hold ?
- **********************************************************************/
-
-int regsubkey_ctr_numkeys( REGSUBKEY_CTR *ctr )
-{
-       return ctr->num_subkeys;
-}
-
-/***********************************************************************
- Retreive a specific key string
- **********************************************************************/
-
-char* regsubkey_ctr_specific_key( REGSUBKEY_CTR *ctr, uint32 key_index )
-{
-       if ( ! (key_index < ctr->num_subkeys) )
-               return NULL;
-               
-       return ctr->subkeys[key_index];
-}
-
-/***********************************************************************
- free memory held by a REGSUBKEY_CTR structure
- **********************************************************************/
-
-void regsubkey_ctr_destroy( REGSUBKEY_CTR *ctr )
-{
-       if ( ctr ) {
-               talloc_destroy( ctr->ctx );     
-               ZERO_STRUCTP( ctr );
-       }
-}
-
-
-/*
- * Utility functions for REGVAL_CTR
- */
-
-/***********************************************************************
- Init the talloc context held by a REGSUBKEY_CTR structure
- **********************************************************************/
-
-void regval_ctr_init( REGVAL_CTR *ctr )
-{
-       if ( !ctr->ctx )
-               ctr->ctx = talloc_init();
-}
-
-/***********************************************************************
- How many keys does the container hold ?
- **********************************************************************/
-
-int regval_ctr_numvals( REGVAL_CTR *ctr )
-{
-       return ctr->num_values;
-}
-
-/***********************************************************************
- allocate memory for and duplicate a REGISTRY_VALUE.
- This is malloc'd memory so the caller should free it when done
- **********************************************************************/
-
-REGISTRY_VALUE* dup_registry_value( REGISTRY_VALUE *val )
-{
-       REGISTRY_VALUE  *copy = NULL;
-       
-       if ( !val )
-               return NULL;
-       
-       if ( !(copy = malloc( sizeof(REGISTRY_VALUE) )) ) {
-               DEBUG(0,("dup_registry_value: malloc() failed!\n"));
-               return NULL;
-       }
-       
-       /* copy all the non-pointer initial data */
-       
-       memcpy( copy, val, sizeof(REGISTRY_VALUE) );
-       if ( val->data_p ) 
-       {
-               if ( !(copy->data_p = memdup( val->data_p, val->size )) ) {
-                       DEBUG(0,("dup_registry_value: memdup() failed for [%d] bytes!\n",
-                               val->size));
-                       SAFE_FREE( copy );
-               }
-       }
-       
-       return copy;    
-}
-
-/**********************************************************************
- free the memory allocated to a REGISTRY_VALUE 
- *********************************************************************/
-void free_registry_value( REGISTRY_VALUE *val )
-{
-       if ( !val )
-               return;
-               
-       SAFE_FREE( val->data_p );
-       SAFE_FREE( val );
-       
-       return;
-}
-
-/**********************************************************************
- *********************************************************************/
-
-uint8* regval_data_p( REGISTRY_VALUE *val )
-{
-       return val->data_p;
-}
-
-/**********************************************************************
- *********************************************************************/
-
-int regval_size( REGISTRY_VALUE *val )
-{
-       return val->size;
-}
-
-/**********************************************************************
- *********************************************************************/
-
-char* regval_name( REGISTRY_VALUE *val )
-{
-       return val->valuename;
-}
-
-/**********************************************************************
- *********************************************************************/
-
-uint32 regval_type( REGISTRY_VALUE *val )
-{
-       return val->type;
-}
-
-/***********************************************************************
- Retreive a pointer to a specific value.  Caller shoud dup the structure
- since this memory may go away with a regval_ctr_destroy()
- **********************************************************************/
-
-REGISTRY_VALUE* regval_ctr_specific_value( REGVAL_CTR *ctr, uint32 idx )
-{
-       if ( !(idx < ctr->num_values) )
-               return NULL;
-               
-       return ctr->values[idx];
-}
-
-/***********************************************************************
- Retrive the TALLOC_CTX associated with a REGISTRY_VALUE 
- **********************************************************************/
-
-TALLOC_CTX* regval_ctr_getctx( REGVAL_CTR *val )
-{
-       if ( !val )
-               return NULL;
-
-       return val->ctx;
-}
-
-/***********************************************************************
- Add a new registry value to the array
- **********************************************************************/
-
-int regval_ctr_addvalue( REGVAL_CTR *ctr, char *name, uint16 type, 
-                         char *data_p, size_t size )
-{
-       REGISTRY_VALUE **ppreg;
-       uint16 len;
-       
-       if ( name )
-       {
-               len = strlen( name );
-
-               /* allocate a slot in the array of pointers */
-               
-               if (  ctr->num_values == 0 )
-                       ctr->values = talloc( ctr->ctx, sizeof(REGISTRY_VALUE*) );
-               else {
-                       ppreg = talloc_realloc( ctr->ctx, ctr->values, sizeof(REGISTRY_VALUE*)*(ctr->num_values+1) );
-                       if ( ppreg )
-                               ctr->values = ppreg;
-               }
-
-               /* allocate a new value and store the pointer in the arrya */
-               
-               ctr->values[ctr->num_values] = talloc( ctr->ctx, sizeof(REGISTRY_VALUE) );
-
-               /* init the value */
-       
-               fstrcpy( ctr->values[ctr->num_values]->valuename, name );
-               ctr->values[ctr->num_values]->type = type;
-               ctr->values[ctr->num_values]->data_p = talloc_memdup( ctr->ctx, data_p, size );
-               ctr->values[ctr->num_values]->size = size;
-               ctr->num_values++;
-       }
-
-       return ctr->num_values;
-}
-
-/***********************************************************************
- Delete a single value from the registry container.
- No need to free memory since it is talloc'd.
- **********************************************************************/
-
-int regval_ctr_delvalue( REGVAL_CTR *ctr, char *name )
-{
-       int     i;
-       
-       /* search for the value */
-       
-       for ( i=0; i<ctr->num_values; i++ ) {
-               if ( strcmp( ctr->values[i]->valuename, name ) == 0)
-                       break;
-       }
-       
-       /* just return if we don't find it */
-       
-       if ( i == ctr->num_values )
-               return ctr->num_values;
-       
-       /* just shift everything down one */
-       
-       for ( /* use previous i */; i<(ctr->num_values-1); i++ )
-               memcpy( ctr->values[i], ctr->values[i+1], sizeof(REGISTRY_VALUE) );
-               
-       /* paranoia */
-       
-       ZERO_STRUCTP( ctr->values[i] );
-       
-       ctr->num_values--;
-       
-       return ctr->num_values;
-}
-
-/***********************************************************************
- Delete a single value from the registry container.
- No need to free memory since it is talloc'd.
- **********************************************************************/
-
-REGISTRY_VALUE* regval_ctr_getvalue( REGVAL_CTR *ctr, char *name )
-{
-       int     i;
-       
-       /* search for the value */
-       
-       for ( i=0; i<ctr->num_values; i++ ) {
-               if ( strcmp( ctr->values[i]->valuename, name ) == 0)
-                       return ctr->values[i];
-               
-       }
-       
-       return NULL;
-}
-
-/***********************************************************************
- free memory held by a REGVAL_CTR structure
- **********************************************************************/
-
-void regval_ctr_destroy( REGVAL_CTR *ctr )
-{
-       if ( ctr ) {
-               talloc_destroy( ctr->ctx );
-               ZERO_STRUCTP( ctr );
-       }
-}
-
 /***********************************************************************
  Open the registry database and initialize the REGISTRY_HOOK cache
  ***********************************************************************/
index 8f53fe9ea5c3834601f902ed03ca973a8e033e11..a58a91a0a8979c3fd98a60881bd4e9b53b6d93d7 100644 (file)
@@ -240,6 +240,7 @@ static int print_subpath_values_environments( char *key, REGVAL_CTR *val )
        int             buffer_size = 0;
        int             i, length;
        char            *filename;
+       UNISTR2         data;;
        
        DEBUG(8,("print_subpath_values_environments: Enter key => [%s]\n", key ? key : "NULL"));
        
@@ -287,15 +288,23 @@ static int print_subpath_values_environments( char *key, REGVAL_CTR *val )
        info3 = driver_ctr.info_3;
        
        filename = dos_basename( info3->driverpath );
-       regval_ctr_addvalue( val, "Driver",             REG_SZ,       filename, strlen(filename)+1 );
+       init_unistr2( &data, filename, strlen(filename)+1 ); 
+       regval_ctr_addvalue( val, "Driver",             REG_SZ,       (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
+       
        filename = dos_basename( info3->configfile );
-       regval_ctr_addvalue( val, "Configuration File", REG_SZ,       filename, strlen(filename)+1 );
+       init_unistr2( &data, filename, strlen(filename)+1 );
+       regval_ctr_addvalue( val, "Configuration File", REG_SZ,       (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
+       
        filename = dos_basename( info3->datafile );
-       regval_ctr_addvalue( val, "Data File",          REG_SZ,       filename, strlen(filename)+1 );
+       init_unistr2( &data, filename, strlen(filename)+1 );
+       regval_ctr_addvalue( val, "Data File",          REG_SZ,       (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
+       
        filename = dos_basename( info3->helpfile );
-       regval_ctr_addvalue( val, "Help File",          REG_SZ,       filename, strlen(filename)+1 );
-               
-       regval_ctr_addvalue( val, "Data Type",          REG_SZ,       info3->defaultdatatype, strlen(info3->defaultdatatype)+1 );
+       init_unistr2( &data, filename, strlen(filename)+1 );
+       regval_ctr_addvalue( val, "Help File",          REG_SZ,       (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
+       
+       init_unistr2( &data, info3->defaultdatatype, strlen(info3->defaultdatatype)+1 );
+       regval_ctr_addvalue( val, "Data Type",          REG_SZ,       (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
        
        regval_ctr_addvalue( val, "Version",            REG_DWORD,    (char*)&info3->cversion, sizeof(info3->cversion) );
        
@@ -313,19 +322,20 @@ static int print_subpath_values_environments( char *key, REGVAL_CTR *val )
                        
                        length = strlen(filename);
                
-                       buffer2 = Realloc( buffer, buffer_size + length + 1 );
+                       buffer2 = Realloc( buffer, buffer_size + (length + 1)*sizeof(uint16) );
                        if ( !buffer2 )
                                break;
                        buffer = buffer2;
+                       
+                       init_unistr2( &data, filename, length+1 );
+                       memcpy( buffer+buffer_size, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
                
-                       memcpy( buffer+buffer_size, filename, length+1 );
-               
-                       buffer_size += length + 1;
+                       buffer_size += (length + 1)*sizeof(uint16);
                }
                
                /* terminated by double NULL.  Add the final one here */
                
-               buffer2 = Realloc( buffer, buffer_size + 1 );
+               buffer2 = Realloc( buffer, buffer_size + 2 );
                if ( !buffer2 ) {
                        SAFE_FREE( buffer );
                        buffer_size = 0;
@@ -333,12 +343,14 @@ static int print_subpath_values_environments( char *key, REGVAL_CTR *val )
                else {
                        buffer = buffer2;
                        buffer[buffer_size++] = '\0';
+                       buffer[buffer_size++] = '\0';
                }
        }
        
        regval_ctr_addvalue( val, "Dependent Files",    REG_MULTI_SZ, buffer, buffer_size );
        
        free_a_printer_driver( driver_ctr, 3 );
+       
        SAFE_FREE( key2 );
        SAFE_FREE( buffer );
                
@@ -453,11 +465,12 @@ static int print_subpath_printers( char *key, REGSUBKEY_CTR *subkeys )
        int n_services = lp_numservices();      
        int snum;
        fstring sname;
+       int i;
        int num_subkeys = 0;
        char *keystr, *key2 = NULL;
        char *base, *new_path;
        NT_PRINTER_INFO_LEVEL *printer = NULL;
-       
+       fstring *subkey_names = NULL;
        
        DEBUG(10,("print_subpath_printers: key=>[%s]\n", key ? key : "NULL" ));
        
@@ -483,22 +496,23 @@ static int print_subpath_printers( char *key, REGSUBKEY_CTR *subkeys )
        key2 = strdup( key );
        keystr = key2;
        reg_split_path( keystr, &base, &new_path );
+
+       if ( !W_ERROR_IS_OK( get_a_printer(&printer, 2, base) ) )
+               goto done;
+
+       num_subkeys = get_printer_subkeys( &printer->info_2->data, new_path?new_path:"", &subkey_names );
        
+       for ( i=0; i<num_subkeys; i++ )
+               regsubkey_ctr_addkey( subkeys, subkey_names[i] );
        
-       if ( !new_path ) {
-               /* sanity check on the printer name */
-               if ( !W_ERROR_IS_OK( get_a_printer(&printer, 2, base) ) )
-                       goto done;
-               
-               free_a_printer( &printer, 2 );
-               
-               regsubkey_ctr_addkey( subkeys, SPOOL_PRINTERDATA_KEY );
-       }
-       
+       free_a_printer( &printer, 2 );
+                       
        /* no other subkeys below here */
 
 done:  
        SAFE_FREE( key2 );
+       SAFE_FREE( subkey_names );
+       
        return num_subkeys;
 }
 
@@ -517,14 +531,13 @@ static int print_subpath_values_printers( char *key, REGVAL_CTR *val )
        prs_struct      prs;
        uint32          offset;
        int             snum;
-       int             i;
-       fstring         valuename;
-       uint8           *data;
-       uint32          type, data_len;
-       fstring         printername;
+       fstring         printername; 
+       NT_PRINTER_DATA *p_data;
+       int             i, key_index;
+       UNISTR2         data;
        
        /* 
-        * There are tw cases to deal with here
+        * Theres are tw cases to deal with here
         * (1) enumeration of printer_info_2 values
         * (2) enumeration of the PrinterDriverData subney
         */
@@ -559,17 +572,27 @@ static int print_subpath_values_printers( char *key, REGVAL_CTR *val )
                regval_ctr_addvalue( val, "UntilTime",        REG_DWORD, (char*)&info2->untiltime,        sizeof(info2->untiltime) );
                regval_ctr_addvalue( val, "cjobs",            REG_DWORD, (char*)&info2->cjobs,            sizeof(info2->cjobs) );
                regval_ctr_addvalue( val, "AveragePPM",       REG_DWORD, (char*)&info2->averageppm,       sizeof(info2->averageppm) );
-               
-               regval_ctr_addvalue( val, "Name",             REG_SZ, info2->printername,     sizeof(info2->printername)+1 );
-               regval_ctr_addvalue( val, "Location",         REG_SZ, info2->location,        sizeof(info2->location)+1 );
-               regval_ctr_addvalue( val, "Comment",          REG_SZ, info2->comment,         sizeof(info2->comment)+1 );
-               regval_ctr_addvalue( val, "Parameters",       REG_SZ, info2->parameters,      sizeof(info2->parameters)+1 );
-               regval_ctr_addvalue( val, "Port",             REG_SZ, info2->portname,        sizeof(info2->portname)+1 );
-               regval_ctr_addvalue( val, "Server",           REG_SZ, info2->servername,      sizeof(info2->servername)+1 );
-               regval_ctr_addvalue( val, "Share",            REG_SZ, info2->sharename,       sizeof(info2->sharename)+1 );
-               regval_ctr_addvalue( val, "Driver",           REG_SZ, info2->drivername,      sizeof(info2->drivername)+1 );
-               regval_ctr_addvalue( val, "Separator File",   REG_SZ, info2->sepfile,         sizeof(info2->sepfile)+1 );
-               regval_ctr_addvalue( val, "Print Processor",  REG_SZ, "winprint",             sizeof("winprint")+1 );
+
+               init_unistr2( &data, info2->printername, strlen(info2->printername)+1 );
+               regval_ctr_addvalue( val, "Name",             REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
+               init_unistr2( &data, info2->location, strlen(info2->location)+1 );
+               regval_ctr_addvalue( val, "Location",         REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
+               init_unistr2( &data, info2->comment, strlen(info2->comment)+1 );
+               regval_ctr_addvalue( val, "Comment",          REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
+               init_unistr2( &data, info2->parameters, strlen(info2->parameters)+1 );
+               regval_ctr_addvalue( val, "Parameters",       REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
+               init_unistr2( &data, info2->portname, strlen(info2->portname)+1 );
+               regval_ctr_addvalue( val, "Port",             REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
+               init_unistr2( &data, info2->servername, strlen(info2->servername)+1 );
+               regval_ctr_addvalue( val, "Server",           REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
+               init_unistr2( &data, info2->sharename, strlen(info2->sharename)+1 );
+               regval_ctr_addvalue( val, "Share",            REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
+               init_unistr2( &data, info2->drivername, strlen(info2->drivername)+1 );
+               regval_ctr_addvalue( val, "Driver",           REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
+               init_unistr2( &data, info2->sepfile, strlen(info2->sepfile)+1 );
+               regval_ctr_addvalue( val, "Separator File",   REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
+               init_unistr2( &data, "winprint", strlen("winprint")+1 );
+               regval_ctr_addvalue( val, "Print Processor",  REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) );
                
                
                /* use a prs_struct for converting the devmode and security 
@@ -607,43 +630,36 @@ static int print_subpath_values_printers( char *key, REGVAL_CTR *val )
 
                                
                prs_mem_free( &prs );
-               free_a_printer( &printer, 2 );  
                
                num_values = regval_ctr_numvals( val ); 
+               
                goto done;
                
        }
-       
-       
-       keystr = new_path;
-       reg_split_path( keystr, &base, &new_path );
-       
-       /* here should be no more path components here */
-       
-       if ( new_path || strcmp(base, SPOOL_PRINTERDATA_KEY) )
-               goto done;
                
-       /* now enumerate the PrinterDriverData key */
+       /* now enumerate the key */
+       
        if ( !W_ERROR_IS_OK( get_a_printer(&printer, 2, printername) ) )
                goto done;
-
-       info2 = printer->info_2;
-               
        
        /* iterate over all printer data and fill the regval container */
        
-#if 0  /* JERRY */
-       for ( i=0; get_specific_param_by_index(*printer, 2, i, valuename, &data, &type, &data_len); i++ )
-       {
-               regval_ctr_addvalue( val, valuename, type, data, data_len );
+       p_data = &printer->info_2->data;
+       if ( (key_index = lookup_printerkey( p_data, new_path )) == -1  ) {
+               DEBUG(10,("print_subpath_values_printer: Unknown keyname [%s]\n", new_path));
+               goto done;
        }
-#endif
-               
-       free_a_printer( &printer, 2 );
-
-       num_values = regval_ctr_numvals( val );
        
+       num_values = regval_ctr_numvals( &p_data->keys[key_index].values );
+       
+       for ( i=0; i<num_values; i++ )
+               regval_ctr_copyvalue( val, regval_ctr_specific_value(&p_data->keys[key_index].values, i) );
+                       
+
 done:
+       if ( printer )
+               free_a_printer( &printer, 2 );
+               
        SAFE_FREE( key2 ); 
        
        return num_values;
index acc913554283148ebac67bbd32a9d33cda4f6bd3..eaee3c26e7c829fb00ac789c6ef3ff034e3a7d03 100644 (file)
@@ -152,11 +152,106 @@ password ?).\n", cli->desthost ));
         return result;
 }
 
+/****************************************************************************
+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.
+****************************************************************************/
+
+NTSTATUS cli_net_auth3(struct cli_state *cli, 
+                      uint16 sec_chan, 
+                      uint32 *neg_flags, DOM_CHAL *srv_chal)
+{
+        prs_struct qbuf, rbuf;
+        NET_Q_AUTH_3 q;
+        NET_R_AUTH_3 r;
+        NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+       extern pstring global_myname;
+
+        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));
+
+        /* 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);
+
+        /* turn parameters into data stream */
+
+        if (!net_io_q_auth_3("", &q,  &qbuf, 0) ||
+            !rpc_api_pipe_req(cli, NET_AUTH3, &qbuf, &rbuf)) {
+                goto done;
+        }
+        
+        /* Unmarshall response */
+        
+        if (!net_io_r_auth_3("", &r, &rbuf, 0)) {
+                goto done;
+        }
+
+        result = r.status;
+       *neg_flags = r.srv_flgs.neg_flags;
+
+        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;
+                }
+        }
+
+ done:
+        prs_mem_free(&qbuf);
+        prs_mem_free(&rbuf);
+        
+        return result;
+}
+
+/* Return the secure channel type depending on the server role. */
+
+uint16 get_sec_chan(void)
+{
+       uint16 sec_chan = SEC_CHAN_WKSTA;
+
+       switch (lp_server_role()) {
+       case ROLE_DOMAIN_PDC:
+               sec_chan = SEC_CHAN_DOMAIN;
+               break;
+       case ROLE_DOMAIN_BDC:
+               sec_chan = SEC_CHAN_BDC;
+               break;
+       }
+
+       return sec_chan;
+}
+
 /* Initialize domain session credentials */
 
 NTSTATUS cli_nt_setup_creds(struct cli_state *cli, 
                            uint16 sec_chan,
-                           const unsigned char mach_pwd[16])
+                           const unsigned char mach_pwd[16], uint32 *neg_flags, int level)
 {
         DOM_CHAL clnt_chal;
         DOM_CHAL srv_chal;
@@ -182,24 +277,30 @@ NTSTATUS cli_nt_setup_creds(struct cli_state *cli,
                          cli->sess_key);
         memset((char *)cli->sess_key+8, '\0', 8);
 
-        /******************* Authenticate 2 ********************/
+        /******************* Authenticate 2/3 ********************/
 
-        /* calculate auth-2 credentials */
+        /* calculate auth-2/3 credentials */
         zerotime.time = 0;
-        cred_create(cli->sess_key, &clnt_chal, zerotime, 
-                    &cli->clnt_cred.challenge);
+        cred_create(cli->sess_key, &clnt_chal, zerotime, &cli->clnt_cred.challenge);
 
         /*  
-         * Send client auth-2 challenge.
-         * Receive an auth-2 challenge response and check it.
+         * Send client auth-2/3 challenge.
+         * Receive an auth-2/3 challenge response and check it.
          */
-        
-       result = cli_net_auth2(cli, sec_chan, 0x000001ff, &srv_chal);
+        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;
+       }
 
-       if (!NT_STATUS_IS_OK(result)) {
-                DEBUG(1,("cli_nt_setup_creds: auth2 challenge failed %s\n",
-                        nt_errstr(result)));
-        }
+       if (!NT_STATUS_IS_OK(result))
+                DEBUG(1,("cli_nt_setup_creds: auth%d challenge failed %s\n", level, nt_errstr(result)));
 
         return result;
 }
@@ -257,24 +358,23 @@ file.  They should be combined at some stage.  )-:
 
 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));
+       /*
+        * 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,
-                               uint32 database_id, uint32 *num_deltas,
+                               uint32 database_id, uint32 next_rid, uint32 *num_deltas,
                                SAM_DELTA_HDR **hdr_deltas, 
                                SAM_DELTA_CTR **deltas)
 {
@@ -297,7 +397,7 @@ NTSTATUS cli_netlogon_sam_sync(struct cli_state *cli, TALLOC_CTX *mem_ctx, DOM_C
         gen_next_creds(cli, &clnt_creds);
 
        init_net_q_sam_sync(&q, cli->srv_name_slash, cli->clnt_name_slash + 2,
-                            &clnt_creds, ret_creds, database_id);
+                            &clnt_creds, ret_creds, database_id, next_rid);
 
        /* Marshall data and send request */
 
index eae6be512825ef37c7d675fdcfd81511e0343f58..0416ed3b9ba44480559f382f0c28fe8cdb20563e 100644 (file)
@@ -354,7 +354,7 @@ static BOOL rpc_api_pipe(struct cli_state *cli, uint16 cmd, prs_struct *data, pr
        if (!cli_api_pipe(cli, "\\PIPE\\",
                  setup, 2, 0,                     /* Setup, length, max */
                  NULL, 0, 0,                      /* Params, length, max */
-                 pdata, data_len, data_len,       /* data, length, max */                  
+                 pdata, data_len, 1024,           /* data, length, max */                  
                  &rparam, &rparam_len,            /* return params, len */
                  &prdata, &rdata_len))            /* return data, len */
        {
index 18e17758d6d9c963e9477f562f7625bb62424f2c..ca24d95e33628bdeaf6511c96d7aeea17ece24b2 100644 (file)
@@ -393,7 +393,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,
                                 uint32 offered, uint32 *needed,
-                                uint32 flags, uint32 level,
+                                char *name, uint32 flags, uint32 level,
                                 uint32 *num_printers, PRINTER_INFO_CTR *ctr)
 {
        prs_struct qbuf, rbuf;
@@ -401,14 +401,10 @@ WERROR cli_spoolss_enum_printers(struct cli_state *cli, TALLOC_CTX *mem_ctx,
         SPOOL_R_ENUMPRINTERS r;
        NEW_BUFFER buffer;
        WERROR result = W_ERROR(ERRgeneral);
-       fstring server;
 
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
 
-        slprintf (server, sizeof(fstring)-1, "\\\\%s", cli->desthost);
-        strupper (server);
-       
        /* Initialise input parameters */
 
        init_buffer(&buffer, offered, mem_ctx);
@@ -416,7 +412,7 @@ WERROR cli_spoolss_enum_printers(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
        prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
 
-       make_spoolss_q_enumprinters(&q, flags, server, level, &buffer, 
+       make_spoolss_q_enumprinters(&q, flags, name, level, &buffer, 
                                    offered);
 
        /* Marshall data and send request */
@@ -665,7 +661,8 @@ WERROR cli_spoolss_setprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
        prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
                
-       make_spoolss_q_setprinter(mem_ctx, &q, pol, level, ctr, command);
+       if (!make_spoolss_q_setprinter(mem_ctx, &q, pol, level, ctr, command))
+               goto done;
 
        /* Marshall data and send request */
 
@@ -771,6 +768,9 @@ WERROR cli_spoolss_getprinterdriver(struct cli_state *cli,
        case 3:
                decode_printer_driver_3(mem_ctx, r.buffer, 1, &ctr->info3);
                break;
+       default:
+               DEBUG(10, ("cli_spoolss_getprinterdriver: unknown info level %d", level));
+               return WERR_UNKNOWN_LEVEL;
        }
 
  done:
@@ -852,6 +852,10 @@ WERROR cli_spoolss_enumprinterdrivers (struct cli_state *cli,
                case 3:
                        decode_printer_driver_3(mem_ctx, r.buffer, r.returned, &ctr->info3);
                        break;
+               default:
+                       DEBUG(10, ("cli_spoolss_enumprinterdrivers: unknown info level %d\n",
+                                  level));
+                       return WERR_UNKNOWN_LEVEL;
                }
        }
 
@@ -1332,8 +1336,16 @@ WERROR cli_spoolss_getform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        if (needed)
                *needed = r.needed;
 
-       if (W_ERROR_IS_OK(result)) 
-               smb_io_form_1("", r.buffer, form, 0);
+       if (W_ERROR_IS_OK(result)) {
+               switch(level) {
+               case 1:
+                       smb_io_form_1("", r.buffer, form, 0);
+                       break;
+               default:
+                       DEBUG(10, ("cli_spoolss_getform: unknown info level %d", level));
+                       return WERR_UNKNOWN_LEVEL;
+               }
+       }
 
  done:
        prs_mem_free(&qbuf);
@@ -1556,11 +1568,11 @@ WERROR cli_spoolss_enumjobs(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        switch(level) {
        case 1:
                decode_jobs_1(mem_ctx, r.buffer, r.returned,
-                               ctr->job.job_info_1);
+                             &ctr->job.job_info_1);
                break;
        case 2:
                decode_jobs_2(mem_ctx, r.buffer, r.returned,
-                               ctr->job.job_info_2);
+                             &ctr->job.job_info_2);
                break;
        default:
                DEBUG(3, ("unsupported info level %d", level));
@@ -1669,10 +1681,10 @@ WERROR cli_spoolss_getjob(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 
        switch(level) {
        case 1:
-               decode_jobs_1(mem_ctx, r.buffer, 1, ctr->job.job_info_1);
+               decode_jobs_1(mem_ctx, r.buffer, 1, &ctr->job.job_info_1);
                break;
        case 2:
-               decode_jobs_2(mem_ctx, r.buffer, 1, ctr->job.job_info_2);
+               decode_jobs_2(mem_ctx, r.buffer, 1, &ctr->job.job_info_2);
                break;
        default:
                DEBUG(3, ("unsupported info level %d", level));
@@ -1878,8 +1890,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,
                                  uint32 offered, uint32 *needed,
                                  POLICY_HND *hnd, char *valuename, 
-                                 uint32 *data_type, char **data, 
-                                 uint32 *data_size)
+                                 REGISTRY_VALUE *value)
 {
        prs_struct qbuf, rbuf;
        SPOOL_Q_GETPRINTERDATA q;
@@ -1919,16 +1930,63 @@ WERROR cli_spoolss_getprinterdata(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 
        /* Return output parameters */
 
-       if (data_type)
-               *data_type = r.type;
+       value->data_p = talloc_memdup(mem_ctx, r.data, r.needed);
+       value->type = r.type;
+       value->size = r.size;
 
-       if (data) {
-               *data = (char *)talloc(mem_ctx, r.needed);
-               memcpy(*data, r.data, r.needed);
-       }
+ done:
+       prs_mem_free(&qbuf);
+       prs_mem_free(&rbuf);
+
+       return result;
+}
+
+WERROR cli_spoolss_getprinterdataex(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+                                   uint32 offered, uint32 *needed,
+                                   POLICY_HND *hnd, char *keyname, 
+                                   char *valuename, REGISTRY_VALUE *value)
+{
+       prs_struct qbuf, rbuf;
+       SPOOL_Q_GETPRINTERDATAEX q;
+       SPOOL_R_GETPRINTERDATAEX r;
+       WERROR result = W_ERROR(ERRgeneral);
+
+       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_getprinterdataex(&q, hnd, keyname, valuename, offered);
+
+       /* Marshall data and send request */
+
+       if (!spoolss_io_q_getprinterdataex("", &q, &qbuf, 0) ||
+           !rpc_api_pipe_req(cli, SPOOLSS_GETPRINTERDATAEX, &qbuf, &rbuf))
+               goto done;
+
+       /* Unmarshall response */
+
+       if (!spoolss_io_r_getprinterdataex("", &r, &rbuf, 0))
+               goto done;
+       
+       result = r.status;
+
+       if (needed)
+               *needed = r.needed;
 
-       if (data_size) 
-               *data_size = r.needed;
+       if (!W_ERROR_IS_OK(r.status))
+               goto done;      
+
+       /* Return output parameters */
+
+       value->data_p = talloc_memdup(mem_ctx, r.data, r.needed);
+       value->type = r.type;
+       value->size = r.needed;
 
  done:
        prs_mem_free(&qbuf);
@@ -1940,9 +1998,7 @@ WERROR cli_spoolss_getprinterdata(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 /* Set printer data */
 
 WERROR cli_spoolss_setprinterdata(struct cli_state *cli, TALLOC_CTX *mem_ctx,
-                                 POLICY_HND *hnd, char *value, 
-                                 uint32 data_type, char *data, 
-                                 uint32 data_size)
+                                 POLICY_HND *hnd, REGISTRY_VALUE *value)
 {
        prs_struct qbuf, rbuf;
        SPOOL_Q_SETPRINTERDATA q;
@@ -1959,7 +2015,8 @@ WERROR cli_spoolss_setprinterdata(struct cli_state *cli, TALLOC_CTX *mem_ctx,
 
        /* Initialise input parameters */
 
-        make_spoolss_q_setprinterdata(&q, hnd, value, data, data_size);
+        make_spoolss_q_setprinterdata(
+               &q, hnd, value->valuename, value->type, value->data_p, value->size);
 
        /* Marshall data and send request */
 
@@ -1984,14 +2041,59 @@ WERROR cli_spoolss_setprinterdata(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        return result;
 }
 
+WERROR cli_spoolss_setprinterdataex(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+                                   POLICY_HND *hnd, char *keyname, 
+                                   REGISTRY_VALUE *value)
+{
+       prs_struct qbuf, rbuf;
+       SPOOL_Q_SETPRINTERDATAEX q;
+       SPOOL_R_SETPRINTERDATAEX r;
+       WERROR result = W_ERROR(ERRgeneral);
+
+       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_setprinterdataex(
+               &q, hnd, keyname, value->valuename, value->type, value->data_p, 
+               value->size);
+
+       /* Marshall data and send request */
+
+       if (!spoolss_io_q_setprinterdataex("", &q, &qbuf, 0) ||
+           !rpc_api_pipe_req(cli, SPOOLSS_SETPRINTERDATAEX, &qbuf, &rbuf))
+               goto done;
+
+       /* Unmarshall response */
+
+       if (!spoolss_io_r_setprinterdataex("", &r, &rbuf, 0))
+               goto done;
+       
+       result = r.status;
+
+       if (!W_ERROR_IS_OK(r.status))
+               goto done;      
+
+ done:
+       prs_mem_free(&qbuf);
+       prs_mem_free(&rbuf);
+
+       return result;
+}
+
 /* Enum printer data */
 
 WERROR cli_spoolss_enumprinterdata(struct cli_state *cli, TALLOC_CTX *mem_ctx,
                                   POLICY_HND *hnd, uint32 ndx,
                                   uint32 value_offered, uint32 data_offered,
                                   uint32 *value_needed, uint32 *data_needed,
-                                  char **value, uint32 *data_type, char **data, 
-                                  uint32 *data_size)
+                                  REGISTRY_VALUE *value)
 {
        prs_struct qbuf, rbuf;
        SPOOL_Q_ENUMPRINTERDATA q;
@@ -2027,30 +2129,83 @@ WERROR cli_spoolss_enumprinterdata(struct cli_state *cli, TALLOC_CTX *mem_ctx,
                goto done;
 
        /* Return data */
-
+       
        if (value_needed)
                *value_needed = r.realvaluesize;
 
        if (data_needed)
                *data_needed = r.realdatasize;
 
-       if (data_type) 
-               *data_type = r.type;
-
        if (value) {
-               fstring the_value;
-
-               rpcstr_pull(the_value, r.value, sizeof(the_value), -1, 
+               rpcstr_pull(value->valuename, r.value, sizeof(value->valuename), -1,
                            STR_TERMINATE);
-               
-               *value = talloc_strdup(mem_ctx, the_value);
+               value->data_p = talloc_memdup(mem_ctx, r.data, r.realdatasize);
+               value->type = r.type;
+               value->size = r.realdatasize;
        }
 
-       if (data)
-               *data = talloc_memdup(mem_ctx, r.data, r.realdatasize);
+ done:
+       prs_mem_free(&qbuf);
+       prs_mem_free(&rbuf);
+
+       return result;
+}
+
+WERROR cli_spoolss_enumprinterdataex(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+                                    uint32 offered, uint32 *needed,
+                                    POLICY_HND *hnd, char *keyname, 
+                                    REGVAL_CTR *ctr)
+{
+       prs_struct qbuf, rbuf;
+       SPOOL_Q_ENUMPRINTERDATAEX q;
+       SPOOL_R_ENUMPRINTERDATAEX r;
+       WERROR result = W_ERROR(ERRgeneral);
+       int i;
+
+       ZERO_STRUCT(q);
+       ZERO_STRUCT(r);
+
+       /* Initialise parse structures */
 
-       if (data_size)
-               *data_size = r.realdatasize;
+       prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
+       prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
+
+       /* Initialise input parameters */
+
+        make_spoolss_q_enumprinterdataex(&q, hnd, keyname, offered);
+
+       /* Marshall data and send request */
+
+       if (!spoolss_io_q_enumprinterdataex("", &q, &qbuf, 0) ||
+           !rpc_api_pipe_req(cli, SPOOLSS_ENUMPRINTERDATAEX, &qbuf, &rbuf))
+               goto done;
+
+       /* Unmarshall response */
+
+       if (!spoolss_io_r_enumprinterdataex("", &r, &rbuf, 0))
+               goto done;
+       
+       result = r.status;
+       
+       if (needed)
+               *needed = r.needed;
+       
+       if (!W_ERROR_IS_OK(r.status))
+               goto done;
+
+       /* Return data */
+
+       ZERO_STRUCTP(ctr);
+       regval_ctr_init(ctr);
+
+       for (i = 0; i < r.returned; i++) {
+               PRINTER_ENUM_VALUES *v = &r.ctr.values[i];
+               fstring name;
+
+               rpcstr_pull(name, v->valuename.buffer, sizeof(name), -1, 
+                           STR_TERMINATE);
+               regval_ctr_addvalue(ctr, name, v->type, v->data, v->data_len);
+       }
 
  done:
        prs_mem_free(&qbuf);
@@ -2153,4 +2308,48 @@ WERROR cli_spoolss_deleteprinterdata(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        return result;
 }
 
+WERROR cli_spoolss_deleteprinterdataex(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+                                      POLICY_HND *hnd, char *keyname, 
+                                      char *valuename)
+{
+       prs_struct qbuf, rbuf;
+       SPOOL_Q_DELETEPRINTERDATAEX q;
+       SPOOL_R_DELETEPRINTERDATAEX r;
+       WERROR result = W_ERROR(ERRgeneral);
+
+       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_deleteprinterdataex(&q, hnd, keyname, valuename);
+
+       /* Marshall data and send request */
+
+       if (!spoolss_io_q_deleteprinterdataex("", &q, &qbuf, 0) ||
+           !rpc_api_pipe_req(cli, SPOOLSS_DELETEPRINTERDATAEX, &qbuf, &rbuf))
+               goto done;
+
+       /* Unmarshall response */
+
+       if (!spoolss_io_r_deleteprinterdataex("", &r, &rbuf, 0))
+               goto done;
+       
+       result = r.status;
+
+       if (!W_ERROR_IS_OK(r.status))
+               goto done;      
+
+ done:
+       prs_mem_free(&qbuf);
+       prs_mem_free(&rbuf);
+
+       return result;
+}
+
 /** @} **/
index f03046558ee5a15ef5190928ac7c76f9736fd2bd..d07ace8e0cd4b7042882cd4b6d646d270738cfb0 100644 (file)
@@ -222,6 +222,9 @@ done:
        return result;
 }
 
+/*********************************************************************
+ *********************************************************************/
 WERROR cli_spoolss_rffpcnex(struct cli_state *cli, TALLOC_CTX *mem_ctx,
                            POLICY_HND *pol, uint32 flags, uint32 options,
                            char *localmachine, uint32 printerlocal,
index 01d76981736f5bb9e7c610b3b35b2a21de99c29a..3dd9c3bc2a3be3c4fdc9612f6ef44ac102054eef 100644 (file)
@@ -1255,9 +1255,6 @@ BOOL smb_io_chal(char *desc, DOM_CHAL *chal, prs_struct *ps, int depth)
 
        prs_debug(ps, depth, desc, "smb_io_chal");
        depth++;
-
-       if(!prs_align(ps))
-               return False;
        
        if(!prs_uint8s (False, "data", ps, depth, chal->data, 8))
                return False;
index da49a6531d057d715e1bb5fd4822c95c952269d5..e0f710b2d75362857ba11630185f0beb396c86e7 100644 (file)
@@ -4,7 +4,8 @@
  *  Copyright (C) Andrew Tridgell              1992-1997,
  *  Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
  *  Copyright (C) Paul Ashton                       1997.
- *  
+ *  Copyright (C) Jean François Micouleau           2002.
+ *
  *  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
@@ -552,8 +553,6 @@ void init_q_req_chal(NET_Q_REQ_CHAL *q_c,
 
 BOOL net_io_q_req_chal(char *desc,  NET_Q_REQ_CHAL *q_c, prs_struct *ps, int depth)
 {
-       int old_align;
-
        if (q_c == NULL)
                return False;
 
@@ -571,15 +570,8 @@ BOOL net_io_q_req_chal(char *desc,  NET_Q_REQ_CHAL *q_c, prs_struct *ps, int dep
        if(!smb_io_unistr2("", &q_c->uni_logon_clnt, True, ps, depth)) /* logon client unicode string */
                return False;
 
-       old_align = ps->align;
-       ps->align = 0;
-       /* client challenge is _not_ aligned after the unicode strings */
-       if(!smb_io_chal("", &q_c->clnt_chal, ps, depth)) {
-               /* client challenge */
-               ps->align = old_align;
+       if(!smb_io_chal("", &q_c->clnt_chal, ps, depth))
                return False;
-       }
-       ps->align = old_align;
 
        return True;
 }
@@ -615,7 +607,6 @@ BOOL net_io_r_req_chal(char *desc, NET_R_REQ_CHAL *r_c, prs_struct *ps, int dept
 
 BOOL net_io_q_auth(char *desc, NET_Q_AUTH *q_a, prs_struct *ps, int depth)
 {
-       int old_align;
        if (q_a == NULL)
                return False;
 
@@ -627,15 +618,8 @@ BOOL net_io_q_auth(char *desc, NET_Q_AUTH *q_a, prs_struct *ps, int depth)
     
        if(!smb_io_log_info ("", &q_a->clnt_id, ps, depth)) /* client identification info */
                return False;
-       /* client challenge is _not_ aligned */
-       old_align = ps->align;
-       ps->align = 0;
-       if(!smb_io_chal("", &q_a->clnt_chal, ps, depth)) {
-               /* client-calculated credentials */
-               ps->align = old_align;
+       if(!smb_io_chal("", &q_a->clnt_chal, ps, depth))
                return False;
-       }
-       ps->align = old_align;
 
        return True;
 }
@@ -687,7 +671,6 @@ void init_q_auth_2(NET_Q_AUTH_2 *q_a,
 
 BOOL net_io_q_auth_2(char *desc, NET_Q_AUTH_2 *q_a, prs_struct *ps, int depth)
 {
-       int old_align;
        if (q_a == NULL)
                return False;
 
@@ -699,15 +682,8 @@ BOOL net_io_q_auth_2(char *desc, NET_Q_AUTH_2 *q_a, prs_struct *ps, int depth)
     
        if(!smb_io_log_info ("", &q_a->clnt_id, ps, depth)) /* client identification info */
                return False;
-       /* client challenge is _not_ aligned */
-       old_align = ps->align;
-       ps->align = 0;
-       if(!smb_io_chal("", &q_a->clnt_chal, ps, depth)) {
-               /* client-calculated credentials */
-               ps->align = old_align;
+       if(!smb_io_chal("", &q_a->clnt_chal, ps, depth))
                return False;
-       }
-       ps->align = old_align;
        if(!net_io_neg_flags("", &q_a->clnt_flgs, ps, depth))
                return False;
 
@@ -740,6 +716,76 @@ BOOL net_io_r_auth_2(char *desc, NET_R_AUTH_2 *r_a, prs_struct *ps, int depth)
        return True;
 }
 
+/*******************************************************************
+ Inits a NET_Q_AUTH_3 struct.
+********************************************************************/
+
+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)
+{
+       DEBUG(5,("init_q_auth_3: %d\n", __LINE__));
+
+       init_log_info(&q_a->clnt_id, logon_srv, acct_name, sec_chan, comp_name);
+       memcpy(q_a->clnt_chal.data, clnt_chal->data, sizeof(clnt_chal->data));
+       q_a->clnt_flgs.neg_flags = clnt_flgs;
+
+       DEBUG(5,("init_q_auth_3: %d\n", __LINE__));
+}
+
+/*******************************************************************
+ Reads or writes a structure.
+********************************************************************/
+
+BOOL net_io_q_auth_3(char *desc, NET_Q_AUTH_3 *q_a, prs_struct *ps, int depth)
+{
+       if (q_a == NULL)
+               return False;
+
+       prs_debug(ps, depth, desc, "net_io_q_auth_3");
+       depth++;
+
+       if(!prs_align(ps))
+               return False;
+    
+       if(!smb_io_log_info ("", &q_a->clnt_id, ps, depth)) /* client identification info */
+               return False;
+       if(!smb_io_chal("", &q_a->clnt_chal, ps, depth))
+               return False;
+       if(!net_io_neg_flags("", &q_a->clnt_flgs, ps, depth))
+               return False;
+
+       return True;
+}
+
+/*******************************************************************
+ Reads or writes a structure.
+********************************************************************/
+
+BOOL net_io_r_auth_3(char *desc, NET_R_AUTH_3 *r_a, prs_struct *ps, int depth)
+{
+       if (r_a == NULL)
+               return False;
+
+       prs_debug(ps, depth, desc, "net_io_r_auth_3");
+       depth++;
+
+       if(!prs_align(ps))
+               return False;
+    
+       if(!smb_io_chal("srv_chal", &r_a->srv_chal, ps, depth)) /* server challenge */
+               return False;
+       if(!net_io_neg_flags("srv_flgs", &r_a->srv_flgs, ps, depth))
+               return False;
+       if (!prs_uint32("unknown", ps, depth, &r_a->unknown))
+               return False;
+
+       if(!prs_ntstatus("status", ps, depth, &r_a->status))
+               return False;
+
+       return True;
+}
+
 
 /*******************************************************************
  Inits a NET_Q_SRV_PWSET.
@@ -1611,7 +1657,8 @@ makes a NET_Q_SAM_SYNC structure.
 ********************************************************************/
 BOOL init_net_q_sam_sync(NET_Q_SAM_SYNC * q_s, const char *srv_name,
                          const char *cli_name, DOM_CRED *cli_creds, 
-                         DOM_CRED *ret_creds, uint32 database_id)
+                         DOM_CRED *ret_creds, uint32 database_id, 
+                        uint32 next_rid)
 {
        DEBUG(5, ("init_q_sam_sync\n"));
 
@@ -1628,7 +1675,7 @@ BOOL init_net_q_sam_sync(NET_Q_SAM_SYNC * q_s, const char *srv_name,
 
        q_s->database_id = database_id;
        q_s->restart_state = 0;
-       q_s->sync_context = 0;
+       q_s->sync_context = next_rid;
        q_s->max_size = 0xffff;
 
        return True;
@@ -1699,7 +1746,7 @@ static BOOL net_io_sam_delta_hdr(char *desc, SAM_DELTA_HDR * delta,
 /*******************************************************************
 reads or writes a structure.
 ********************************************************************/
-static BOOL net_io_sam_delta_stamp(char *desc, SAM_DELTA_STAMP *info,
+static BOOL net_io_sam_delta_mod_count(char *desc, SAM_DELTA_MOD_COUNT *info,
                                    prs_struct *ps, int depth)
 {
        prs_debug(ps, depth, desc, "net_io_sam_delta_stamp");
@@ -2306,83 +2353,74 @@ static BOOL net_io_sam_alias_mem_info(char *desc, SAM_ALIAS_MEM_INFO * info,
 /*******************************************************************
 reads or writes a structure.
 ********************************************************************/
-static BOOL net_io_sam_dom_info(char *desc, SAM_DELTA_DOM *info,
+static BOOL net_io_sam_policy_info(char *desc, SAM_DELTA_POLICY *info,
                                      prs_struct *ps, int depth)
 {
        int i;
-
-       prs_debug(ps, depth, desc, "net_io_sam_dom_info");
+       prs_debug(ps, depth, desc, "net_io_sam_policy_info");
        depth++;
 
        if(!prs_align(ps))
                return False;
 
-       if (!prs_uint32("unknown1", ps, depth, &info->unknown1))
-                return False;
-       if (!prs_uint32("unknown2", ps, depth, &info->unknown2))
+       if (!prs_uint32("max_log_size", ps, depth, &info->max_log_size))
                 return False;
-       if (!prs_uint32("unknown3", ps, depth, &info->unknown3))
+       if (!prs_uint64("audit_retention_period", ps, depth,
+                       &info->audit_retention_period))
                 return False;
-       if (!prs_uint32("unknown4", ps, depth, &info->unknown4))
+       if (!prs_uint32("auditing_mode", ps, depth, &info->auditing_mode))
                 return False;
-       if (!prs_uint32("count1", ps, depth, &info->count1))
+       if (!prs_uint32("num_events", ps, depth, &info->num_events))
                 return False;
-       if (!prs_uint32("ptr1", ps, depth, &info->ptr1))
+       if (!prs_uint32("ptr_events", ps, depth, &info->ptr_events))
                 return False;
 
-       if (!prs_uint16("count2", ps, depth, &info->count2))
-                return False;
-       if (!prs_uint16("count3", ps, depth, &info->count3))
-                return False;
+       if (!smb_io_unihdr("hdr_dom_name", &info->hdr_dom_name, ps, depth))
+               return False;
 
-       if (!prs_uint32("ptr2", ps, depth, &info->ptr2))
-                return False;
-       if (!prs_uint32("ptr3", ps, depth, &info->ptr3))
+       if (!prs_uint32("sid_ptr", ps, depth, &info->sid_ptr))
                 return False;
 
-       if (!prs_uint32("unknown4b", ps, depth, &info->unknown4b))
+       if (!prs_uint32("paged_pool_limit", ps, depth, &info->paged_pool_limit))
                 return False;
-       if (!prs_uint32("unknown5", ps, depth, &info->unknown5))
+       if (!prs_uint32("non_paged_pool_limit", ps, depth,
+                       &info->non_paged_pool_limit))
                 return False;
-       if (!prs_uint32("unknown6", ps, depth, &info->unknown6))
+       if (!prs_uint32("min_workset_size", ps, depth, &info->min_workset_size))
                 return False;
-       if (!prs_uint32("unknown7", ps, depth, &info->unknown7))
+       if (!prs_uint32("max_workset_size", ps, depth, &info->max_workset_size))
                 return False;
-       if (!prs_uint32("unknown8", ps, depth, &info->unknown8))
+       if (!prs_uint32("page_file_limit", ps, depth, &info->page_file_limit))
                 return False;
-       if (!prs_uint32("unknown9", ps, depth, &info->unknown9))
+       if (!prs_uint64("time_limit", ps, depth, &info->time_limit))
                 return False;
-       if (!prs_uint32("unknown10", ps, depth, &info->unknown10))
+       if (!smb_io_time("modify_time", &info->modify_time, ps, depth))
                 return False;
-       if (!prs_uint32("unknown11", ps, depth, &info->unknown11))
+       if (!smb_io_time("create_time", &info->create_time, ps, depth))
                 return False;
-       if (!prs_uint32("unknown12", ps, depth, &info->unknown12))
+       if (!smb_io_bufhdr2("hdr_sec_desc", &info->hdr_sec_desc, ps, depth))
                 return False;
 
-       if (!prs_uint32("unknown13", ps, depth, &info->unknown13))
-                return False;
-       if (!prs_uint32("unknown14", ps, depth, &info->unknown14))
-                return False;
-       if (!prs_uint32("unknown15", ps, depth, &info->unknown15))
-                return False;
-       if (!prs_uint32("unknown16", ps, depth, &info->unknown16))
-                return False;
-       if (!prs_uint32("unknown17", ps, depth, &info->unknown17))
-                return False;
+       for (i=0; i<4; i++) {
+               UNIHDR dummy;
+               if (!smb_io_unihdr("dummy", &dummy, ps, depth))
+                       return False;
+       }
 
-       for (i=0; i<info->count2; i++)
-               if (!prs_uint32("unknown18", ps, depth, &info->unknown18))
-                       return False;
+       for (i=0; i<4; i++) {
+               uint32 reserved;
+               if (!prs_uint32("reserved", ps, depth, &reserved))
+                       return False;
+       }
 
-       if (!prs_uint32("unknown19", ps, depth, &info->unknown19))
+       if (!prs_uint32("num_event_audit_options", ps, depth,
+                       &info->num_event_audit_options))
                 return False;
 
-       for (i=0; i<info->count1; i++)
-               if (!prs_uint32("unknown20", ps, depth, &info->unknown20))
-                       return False;
-
-       if (!prs_uint32("ptr4", ps, depth, &info->ptr4))
-                return False;
+       for (i=0; i<info->num_event_audit_options; i++)
+               if (!prs_uint32("event_audit_option", ps, depth,
+                               &info->event_audit_option))
+                       return False;
 
        if (!smb_io_unistr2("domain_name", &info->domain_name, True, ps, depth))
                 return False;
@@ -2390,18 +2428,23 @@ static BOOL net_io_sam_dom_info(char *desc, SAM_DELTA_DOM *info,
        if(!smb_io_dom_sid2("domain_sid", &info->domain_sid, ps, depth))
                return False;
 
+       if (!smb_io_buffer4("buf_sec_desc", &info->buf_sec_desc,
+                            info->hdr_sec_desc.buffer, ps, depth))
+
+               return False;
+
        return True;
 }
 
 /*******************************************************************
 reads or writes a structure.
 ********************************************************************/
-static BOOL net_io_sam_unk0e_info(char *desc, SAM_DELTA_UNK0E *info,
+static BOOL net_io_sam_trustdoms_info(char *desc, SAM_DELTA_TRUSTDOMS *info,
                                      prs_struct *ps, int depth)
 {
        int i;
 
-       prs_debug(ps, depth, desc, "net_io_sam_unk0e_info");
+       prs_debug(ps, depth, desc, "net_io_sam_trustdoms_info");
        depth++;
 
        if(!prs_align(ps))
@@ -2444,12 +2487,12 @@ static BOOL net_io_sam_unk0e_info(char *desc, SAM_DELTA_UNK0E *info,
 /*******************************************************************
 reads or writes a structure.
 ********************************************************************/
-static BOOL net_io_sam_unk12_info(char *desc, SAM_DELTA_UNK12 *info,
-                                     prs_struct *ps, int depth)
+static BOOL net_io_sam_secret_info(char *desc, SAM_DELTA_SECRET *info,
+                                  prs_struct *ps, int depth)
 {
        int i;
 
-       prs_debug(ps, depth, desc, "net_io_sam_unk12_info");
+       prs_debug(ps, depth, desc, "net_io_sam_secret_info");
        depth++;
 
        if(!prs_align(ps))
@@ -2542,52 +2585,48 @@ static BOOL net_io_sam_privs_info(char *desc, SAM_DELTA_PRIVS *info,
        if(!prs_align(ps))
                return False;
 
-       if(!prs_uint32("buf_size", ps, depth, &info->buf_size))
-                return False;
-
-       if(!sec_io_desc("sec_desc", &info->sec_desc, ps, depth))
-               return False;
-
        if(!smb_io_dom_sid2("sid", &info->sid, ps, depth))
                return False;
 
        if(!prs_uint32("priv_count", ps, depth, &info->priv_count))
                 return False;
-       if(!prs_uint32("reserved1", ps, depth, &info->reserved1))
+       if(!prs_uint32("priv_control", ps, depth, &info->priv_control))
                 return False;
 
-       if(!prs_uint32("ptr1", ps, depth, &info->ptr1))
+       if(!prs_uint32("priv_attr_ptr", ps, depth, &info->priv_attr_ptr))
                 return False;
-       if(!prs_uint32("ptr2", ps, depth, &info->ptr2))
+       if(!prs_uint32("priv_name_ptr", ps, depth, &info->priv_name_ptr))
                 return False;
 
-       if(!prs_uint32("unknown1", ps, depth, &info->unknown1))
+       if (!prs_uint32("paged_pool_limit", ps, depth, &info->paged_pool_limit))
                 return False;
-       if(!prs_uint32("unknown2", ps, depth, &info->unknown2))
-                return False;
-       if(!prs_uint32("unknown3", ps, depth, &info->unknown3))
+       if (!prs_uint32("non_paged_pool_limit", ps, depth,
+                       &info->non_paged_pool_limit))
                 return False;
-       if(!prs_uint32("unknown4", ps, depth, &info->unknown4))
+       if (!prs_uint32("min_workset_size", ps, depth, &info->min_workset_size))
                 return False;
-       if(!prs_uint32("unknown5", ps, depth, &info->unknown5))
+       if (!prs_uint32("max_workset_size", ps, depth, &info->max_workset_size))
                 return False;
-       if(!prs_uint32("unknown6", ps, depth, &info->unknown6))
+       if (!prs_uint32("page_file_limit", ps, depth, &info->page_file_limit))
                 return False;
-       if(!prs_uint32("unknown7", ps, depth, &info->unknown7))
+       if (!prs_uint64("time_limit", ps, depth, &info->time_limit))
                 return False;
-       if(!prs_uint32("unknown8", ps, depth, &info->unknown8))
+       if (!prs_uint32("system_flags", ps, depth, &info->system_flags))
                 return False;
-       if(!prs_uint32("unknown9", ps, depth, &info->unknown9))
+       if (!smb_io_bufhdr2("hdr_sec_desc", &info->hdr_sec_desc, ps, depth))
                 return False;
 
-       if(!prs_uint32("buf_size2", ps, depth, &info->buf_size2))
-                return False;
-       if(!prs_uint32("ptr3", ps, depth, &info->ptr3))
-                return False;
+       for (i=0; i<4; i++) {
+               UNIHDR dummy;
+               if (!smb_io_unihdr("dummy", &dummy, ps, depth))
+                       return False;
+       }
 
-       for (i=0; i<12; i++)
-               if(!prs_uint32("unknown10", ps, depth, &info->unknown10))
-                       return False;
+       for (i=0; i<4; i++) {
+               uint32 reserved;
+               if (!prs_uint32("reserved", ps, depth, &reserved))
+                       return False;
+       }
 
        if(!prs_uint32("attribute_count", ps, depth, &info->attribute_count))
                 return False;
@@ -2612,6 +2651,10 @@ static BOOL net_io_sam_privs_info(char *desc, SAM_DELTA_PRIVS *info,
                if (!smb_io_unistr2("uni_privslist", &info->uni_privslist[i], True, ps, depth))
                        return False;
 
+       if (!smb_io_buffer4("buf_sec_desc", &info->buf_sec_desc,
+                            info->hdr_sec_desc.buffer, ps, depth))
+                return False;
+
        return True;
 }
 
@@ -2627,8 +2670,8 @@ static BOOL net_io_sam_delta_ctr(char *desc, uint8 sess_key[16],
 
        switch (type) {
                 /* Seen in sam deltas */
-                case SAM_DELTA_SAM_STAMP:
-                        if (!net_io_sam_delta_stamp("", &delta->stamp, ps, depth))
+                case SAM_DELTA_MODIFIED_COUNT:
+                        if (!net_io_sam_delta_mod_count("", &delta->mod_count, ps, depth))
                                 return False;
                         break;
 
@@ -2657,8 +2700,8 @@ static BOOL net_io_sam_delta_ctr(char *desc, uint8 sess_key[16],
                                 return False;
                        break;
 
-               case SAM_DELTA_DOM_INFO:
-                        if (!net_io_sam_dom_info("", &delta->dom_info, ps, depth))
+               case SAM_DELTA_POLICY_INFO:
+                        if (!net_io_sam_policy_info("", &delta->policy_info, ps, depth))
                                 return False;
                        break;
 
@@ -2672,16 +2715,23 @@ static BOOL net_io_sam_delta_ctr(char *desc, uint8 sess_key[16],
                                 return False;
                        break;
 
-               case SAM_DELTA_UNK0E_INFO:
-                       if (!net_io_sam_unk0e_info("", &delta->unk0e_info, ps, depth))
+               case SAM_DELTA_TRUST_DOMS:
+                       if (!net_io_sam_trustdoms_info("", &delta->trustdoms_info, ps, depth))
                                 return False;
                        break;
 
-               case SAM_DELTA_UNK12_INFO:
-                       if (!net_io_sam_unk12_info("", &delta->unk12_info, ps, depth))
+               case SAM_DELTA_SECRET_INFO:
+                       if (!net_io_sam_secret_info("", &delta->secret_info, ps, depth))
                                 return False;
                        break;
 
+                       /* These guys are not implemented yet */
+
+               case SAM_DELTA_RENAME_GROUP:
+               case SAM_DELTA_RENAME_USER:
+               case SAM_DELTA_RENAME_ALIAS:
+               case SAM_DELTA_DELETE_GROUP:
+               case SAM_DELTA_DELETE_USER:
                default:
                        DEBUG(0, ("Replication error: Unknown delta type 0x%x\n", type));
                        break;
index 4de6b88e9ccae430cc5752c620e328086cde7a14..843be331877a78eaca3f76065c3bc4609a6b9b4a 100644 (file)
@@ -1061,7 +1061,9 @@ BOOL prs_unistr(char *name, prs_struct *ps, int depth, UNISTR *str)
 
                len++;
 
-               dump_data(5+depth, (char *)start, len * 2);
+               DEBUG(5,("%s%04x %s: ", tab_depth(depth), ps->data_offset, name));
+               print_asc(5, (unsigned char*)start, 2*len);     
+               DEBUG(5, ("\n"));
        }
        else { /* unmarshalling */
        
@@ -1114,6 +1116,10 @@ BOOL prs_unistr(char *name, prs_struct *ps, int depth, UNISTR *str)
                        /* NULL terminate the UNISTR */
                        str->buffer[len++] = '\0';
                }
+
+               DEBUG(5,("%s%04x %s: ", tab_depth(depth), ps->data_offset, name));
+               print_asc(5, (unsigned char*)str->buffer, 2*len);       
+               DEBUG(5, ("\n"));
        }
 
        /* set the offset in the prs_struct; 'len' points to the
index 365ad2dc70be13817448b51498cddd6e34826559..2698e8244076a50ebf748293f4ea269ec2af39c2 100644 (file)
 
 static uint32 reg_init_buffer2( BUFFER2 *buf2, REGISTRY_VALUE *val )
 {
-       UNISTR2         unistr;
        uint32          real_size = 0;
-       char            *string;
-       char            *list = NULL;
-       char            *list2 = NULL;
        
        if ( !buf2 || !val )
                return 0;
                
-       real_size = val->size;
-               
-       switch (val->type )
-       {
-               case REG_SZ:
-                       string = (char*)val->data_p;
-                       DEBUG(10,("reg_init_buffer2: REG_SZ string => [%s]\n", string));
-                       
-                       init_unistr2( &unistr, (char*)val->data_p, strlen((char*)val->data_p)+1 );
-                       init_buffer2( buf2, (char*)unistr.buffer, unistr.uni_str_len*2 );
-                       real_size = unistr.uni_str_len*2;
-                       break;
-                       
-               case REG_MULTI_SZ:
-                       string = (char*)val->data_p;
-                       real_size = 0;
-                       while ( string && *string )
-                       {
-                               DEBUG(10,("reg_init_buffer2: REG_MULTI_SZ string => [%s], size => [%d]\n", string, real_size ));
-                               
-                               init_unistr2( &unistr, string, strlen(string)+1 );
-                               
-                               list2 = Realloc( list, real_size + unistr.uni_str_len*2 );
-                               if ( !list2 )
-                                       break;
-                               list = list2;
-                               
-                               memcpy( list+real_size, unistr.buffer, unistr.uni_str_len*2 );
-                               
-                               real_size += unistr.uni_str_len*2;
-                               
-                               string += strlen(string)+1;
-                       }
-                       
-                       list2 = Realloc( list, real_size + 2 );
-                       if ( !list2 )
-                               break;
-                       list = list2;
-                       list[real_size++] = 0x0;
-                       list[real_size++] = 0x0;
-                       
-                       init_buffer2( buf2, (char*)list, real_size );
-                       
-                       DEBUG(10,("reg_init_buffer2: REG_MULTI_SZ size => [%d]\n", real_size ));
-                       
-                       break;
-                       
-               case REG_BINARY:
-                       DEBUG(10,("reg_init_buffer2: REG_BINARY size => [%d]\n", val->size ));
-                       
-                       init_buffer2( buf2, val->data_p, val->size );
-                       break;
-                       
-               case REG_DWORD: 
-                       DEBUG(10,("reg_init_buffer2: REG_DWORD value => [%d]\n", *(uint32*)val->data_p));
-                       init_buffer2( buf2, val->data_p, val->size );
-                       break;
-                       
-               default:
-                       DEBUG(0,("reg_init_buffer2: Unsupported registry data type [%d]\n", val->type));
-                       break;
-       }
-       
-       SAFE_FREE( list );
+       real_size = regval_size(val);
+       init_buffer2( buf2, (char*)regval_data_p(val), real_size );
 
        return real_size;
 }
@@ -1767,7 +1701,11 @@ BOOL reg_io_q_open_entry(char *desc,  REG_Q_OPEN_ENTRY *r_q, prs_struct *ps, int
 void init_reg_r_open_entry(REG_R_OPEN_ENTRY *r_r,
                           POLICY_HND *pol, NTSTATUS status)
 {
-       memcpy(&r_r->pol, pol, sizeof(r_r->pol));
+       if (NT_STATUS_IS_OK(status)) {
+               memcpy(&r_r->pol, pol, sizeof(r_r->pol));
+       } else {
+               ZERO_STRUCT(r_r->pol);
+       }
        r_r->status = status;
 }
 
index 3a7f4b57ae61c04c8f27f8de88d8a0444a87bb00..36b00ff55db76adaffaa5a1f4f7f7ba0010934c7 100644 (file)
@@ -659,7 +659,7 @@ BOOL spoolss_io_devmode(char *desc, prs_struct *ps, int depth, DEVICEMODE *devmo
                { "panningheight",      NULL }
        };
 
-       /* assign at run time to keep non-gcc vompilers happy */
+       /* assign at run time to keep non-gcc compilers happy */
 
        opt_fields[0].field = &devmode->icmmethod;
        opt_fields[1].field = &devmode->icmintent;
@@ -1211,6 +1211,26 @@ BOOL make_spoolss_q_getprinterdata(SPOOL_Q_GETPRINTERDATA *q_u,
         return True;
 }
 
+/*******************************************************************
+ * make a structure.
+ ********************************************************************/
+
+BOOL make_spoolss_q_getprinterdataex(SPOOL_Q_GETPRINTERDATAEX *q_u,
+                                    const POLICY_HND *handle,
+                                    char *keyname, char *valuename, uint32 size)
+{
+        if (q_u == NULL) return False;
+
+        DEBUG(5,("make_spoolss_q_getprinterdataex\n"));
+
+        q_u->handle = *handle;
+       init_unistr2(&q_u->valuename, valuename, strlen(valuename) + 1);
+       init_unistr2(&q_u->keyname, keyname, strlen(keyname) + 1);
+        q_u->size = size;
+
+        return True;
+}
+
 /*******************************************************************
  * read a structure.
  * called from spoolss_q_getprinterdata (srv_spoolss.c)
@@ -1344,7 +1364,7 @@ BOOL spoolss_io_r_getprinterdata(char *desc, SPOOL_R_GETPRINTERDATA *r_u, prs_st
        
        if (UNMARSHALLING(ps) && r_u->size) {
                r_u->data = prs_alloc_mem(ps, r_u->size);
-               if(r_u->data)
+               if(!r_u->data)
                        return False;
        }
 
@@ -3346,7 +3366,9 @@ uint32 spoolss_size_printer_info_2(PRINTER_INFO_2 *info)
         * it is easier to maintain the calculation here and
         * not place the burden on the caller to remember.   --jerry
         */
-       size += size % 4;
+       if ((size % 4) != 0) {
+               size += 4 - (size % 4);
+       }
        
        return size;
 }
@@ -3678,7 +3700,7 @@ uint32 spoolss_size_printer_enum_values(PRINTER_ENUM_VALUES *p)
        
        /* uint32(offset) + uint32(length) + length) */
        size += (size_of_uint32(&p->value_len)*2) + p->value_len;
-       size += (size_of_uint32(&p->data_len)*2) + p->data_len;
+       size += (size_of_uint32(&p->data_len)*2) + p->data_len + (p->data_len%2) ;
        
        size += size_of_uint32(&p->type);
                       
@@ -6065,20 +6087,52 @@ BOOL make_spoolss_q_enumprinterdata(SPOOL_Q_ENUMPRINTERDATA *q_u,
        return True;
 }
 
+/*******************************************************************
+********************************************************************/  
+
+BOOL make_spoolss_q_enumprinterdataex(SPOOL_Q_ENUMPRINTERDATAEX *q_u,
+                                     const POLICY_HND *hnd, char *key,
+                                     uint32 size)
+{
+       memcpy(&q_u->handle, hnd, sizeof(q_u->handle));
+       init_unistr2(&q_u->key, key, strlen(key)+1);
+       q_u->size = size;
+
+       return True;
+}
+
 /*******************************************************************
 ********************************************************************/  
 BOOL make_spoolss_q_setprinterdata(SPOOL_Q_SETPRINTERDATA *q_u, const POLICY_HND *hnd,
-                                  char* value, char* data, uint32 data_size)
+                                  char* value, uint32 data_type, char* data, uint32 data_size)
+{
+       memcpy(&q_u->handle, hnd, sizeof(q_u->handle));
+       q_u->type = data_type;
+       init_unistr2(&q_u->value, value, strlen(value)+1);
+
+       q_u->max_len = q_u->real_len = data_size;
+       q_u->data = data;
+       
+       return True;
+}
+
+/*******************************************************************
+********************************************************************/  
+BOOL make_spoolss_q_setprinterdataex(SPOOL_Q_SETPRINTERDATAEX *q_u, const POLICY_HND *hnd,
+                                    char *key, char* value, uint32 data_type, char* data, 
+                                    uint32 data_size)
 {
        memcpy(&q_u->handle, hnd, sizeof(q_u->handle));
-       q_u->type = REG_SZ;
+       q_u->type = data_type;
        init_unistr2(&q_u->value, value, strlen(value)+1);
+       init_unistr2(&q_u->key, key, strlen(key)+1);
 
        q_u->max_len = q_u->real_len = data_size;
        q_u->data = data;
        
        return True;
 }
+
 /*******************************************************************
 ********************************************************************/  
 
@@ -6863,6 +6917,12 @@ BOOL spoolss_io_r_getprinterdataex(char *desc, SPOOL_R_GETPRINTERDATAEX *r_u, pr
        if (!prs_uint32("size", ps, depth, &r_u->size))
                return False;
        
+       if (UNMARSHALLING(ps) && r_u->size) {
+               r_u->data = prs_alloc_mem(ps, r_u->size);
+               if(!r_u->data)
+                       return False;
+       }
+
        if (!prs_uint8s(False,"data", ps, depth, r_u->data, r_u->size))
                return False;
                
@@ -7083,16 +7143,22 @@ static BOOL spoolss_io_printer_enum_values_ctr(char *desc, prs_struct *ps,
        prs_debug(ps, depth, desc, "spoolss_io_printer_enum_values_ctr");
        depth++;        
        
-       if (!prs_uint32("size", ps, depth, &ctr->size))
-               return False;
-       
-       /* offset data begins at 20 bytes per structure * size_of_array.
-          Don't forget the uint32 at the beginning */
+       /* 
+        * offset data begins at 20 bytes per structure * size_of_array.
+        * Don't forget the uint32 at the beginning 
+        * */
        
        current_offset = basic_unit * ctr->size_of_array;
        
        /* first loop to write basic enum_value information */
        
+       if (UNMARSHALLING(ps)) {
+               ctr->values = (PRINTER_ENUM_VALUES *)prs_alloc_mem(
+                       ps, ctr->size_of_array * sizeof(PRINTER_ENUM_VALUES));
+               if (!ctr->values)
+                       return False;
+       }
+
        for (i=0; i<ctr->size_of_array; i++) 
        {
                valuename_offset = current_offset;
@@ -7106,18 +7172,22 @@ static BOOL spoolss_io_printer_enum_values_ctr(char *desc, prs_struct *ps,
                        return False;
        
                data_offset = ctr->values[i].value_len + valuename_offset;
+               
                if (!prs_uint32("data_offset", ps, depth, &data_offset))
                        return False;
 
                if (!prs_uint32("data_len", ps, depth, &ctr->values[i].data_len))
                        return False;
                        
-               current_offset = data_offset + ctr->values[i].data_len - basic_unit;
+               current_offset  = data_offset + ctr->values[i].data_len - basic_unit;
+               /* account for 2 byte alignment */
+               current_offset += (current_offset % 2);
        }
 
-       /* loop #2 for writing the dynamically size objects
-          while viewing conversations between Win2k -> Win2k,
-          4-byte alignment does not seem to matter here   --jerry */
+       /* 
+        * loop #2 for writing the dynamically size objects; pay 
+        * attention to 2-byte alignment here....
+        */
        
        for (i=0; i<ctr->size_of_array; i++) 
        {
@@ -7125,12 +7195,20 @@ static BOOL spoolss_io_printer_enum_values_ctr(char *desc, prs_struct *ps,
                if (!prs_unistr("valuename", ps, depth, &ctr->values[i].valuename))
                        return False;
                
+               if (UNMARSHALLING(ps)) {
+                       ctr->values[i].data = (uint8 *)prs_alloc_mem(
+                               ps, ctr->values[i].data_len);
+                       if (!ctr->values[i].data)
+                               return False;
+               }
+
                if (!prs_uint8s(False, "data", ps, depth, ctr->values[i].data, ctr->values[i].data_len))
                        return False;
+                       
+               if ( !prs_align_uint16(ps) )
+                       return False;
        }
 
-               
-
        return True;    
 }
 
@@ -7141,15 +7219,21 @@ static BOOL spoolss_io_printer_enum_values_ctr(char *desc, prs_struct *ps,
 
 BOOL spoolss_io_r_enumprinterdataex(char *desc, SPOOL_R_ENUMPRINTERDATAEX *r_u, prs_struct *ps, int depth)
 {
+       int data_offset, end_offset;
        prs_debug(ps, depth, desc, "spoolss_io_r_enumprinterdataex");
        depth++;
 
        if(!prs_align(ps))
                return False;
                
-       if (!spoolss_io_printer_enum_values_ctr("", ps, &r_u->ctr, depth ))
+       if (!prs_uint32("size", ps, depth, &r_u->ctr.size))
                return False;
        
+       data_offset = prs_offset(ps);
+
+       if (!prs_set_offset(ps, data_offset + r_u->ctr.size))
+               return False;
+
        if(!prs_align(ps))
                return False;
 
@@ -7162,6 +7246,20 @@ BOOL spoolss_io_r_enumprinterdataex(char *desc, SPOOL_R_ENUMPRINTERDATAEX *r_u,
        if(!prs_werror("status",     ps, depth, &r_u->status))
                return False;
 
+       r_u->ctr.size_of_array = r_u->returned;
+
+       end_offset = prs_offset(ps);
+
+       if (!prs_set_offset(ps, data_offset))
+               return False;
+
+       if (r_u->ctr.size)
+               if (!spoolss_io_printer_enum_values_ctr("", ps, &r_u->ctr, depth ))
+                       return False;
+
+       if (!prs_set_offset(ps, end_offset))
+               return False;
+       
        return True;
 }
 
@@ -7510,6 +7608,21 @@ BOOL make_spoolss_q_deleteprinterdata(SPOOL_Q_DELETEPRINTERDATA *q_u,
        return True;
 }
 
+/*******************************************************************
+ * init a structure.
+ ********************************************************************/
+
+BOOL make_spoolss_q_deleteprinterdataex(SPOOL_Q_DELETEPRINTERDATAEX *q_u, 
+                                       POLICY_HND *handle, char *key,
+                                       char *value)
+{
+        memcpy(&q_u->handle, handle, sizeof(POLICY_HND));
+       init_unistr2(&q_u->valuename, value, strlen(value) + 1);
+       init_unistr2(&q_u->keyname, key, strlen(key) + 1);
+
+       return True;
+}
+
 /*******************************************************************
  * init a structure.
  ********************************************************************/
index 531267c308c822ab82815be311a409cb66e6275d..672db36a288f5bdbebe93515c74f5954ec3505af 100644 (file)
@@ -1119,10 +1119,8 @@ BOOL srv_io_r_net_share_enum(char *desc, SRV_R_NET_SHARE_ENUM *r_n, prs_struct *
        if(!prs_uint32("total_entries", ps, depth, &r_n->total_entries))
                return False;
 
-       if(r_n->total_entries != 0) {
-               if(!smb_io_enum_hnd("enum_hnd", &r_n->enum_hnd, ps, depth))
-                       return False;
-       }
+       if(!smb_io_enum_hnd("enum_hnd", &r_n->enum_hnd, ps, depth))
+               return False;
 
        if(!prs_werror("status", ps, depth, &r_n->status))
                return False;
index f28441886a53cd7ba3e778c2b7a0c2752c4bd326..e187e1556eff510d79226f56e147ad5ee0f366aa 100644 (file)
@@ -473,6 +473,8 @@ NTSTATUS _lsa_enum_trust_dom(pipes_struct *p, LSA_Q_ENUM_TRUST_DOM *q_u, LSA_R_E
        /*
         * preferred length is set to 5 as a "our" preferred length
         * nt sets this parameter to 2
+        * update (20.08.2002): it's not preferred length, but preferred size!
+        * it needs further investigation how to optimally choose this value
         */
        uint32 max_num_domains = q_u->preferred_len < 5 ? q_u->preferred_len : 10;
        TRUSTDOM **trust_doms;
index 8f6011826aa3cb3bd0b9477339beacc55d7d2482..4478729e4d96c95b43e6d1654a74e7947d493a32 100644 (file)
@@ -712,8 +712,8 @@ NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON *
                                    pdb_get_logon_script(sampw),
                                    pdb_get_profile_path(sampw),
                                    pdb_get_logon_time(sampw),
-                                   pdb_get_logoff_time(sampw),
-                                   pdb_get_kickoff_time(sampw),
+                                   get_time_t_max(),
+                                   get_time_t_max(),
                                    pdb_get_pass_last_set_time(sampw),
                                    pdb_get_pass_can_change_time(sampw),
                                    pdb_get_pass_must_change_time(sampw),
index b7be415abcd01cfd676858c27d8535b2ade75a5a..1947d5514e5d500f625482a5cc8f93c006cdcaf4 100644 (file)
@@ -276,9 +276,6 @@ static BOOL api_pipe_ntlmssp_verify(pipes_struct *p, RPC_AUTH_NTLMSSP_RESP *ntlm
        auth_usersupplied_info *user_info = NULL;
        auth_serversupplied_info *server_info = NULL;
 
-       uid_t uid;
-       uid_t gid;
-
        DEBUG(5,("api_pipe_ntlmssp_verify: checking user details\n"));
 
        memset(p->user_name, '\0', sizeof(p->user_name));
@@ -427,27 +424,30 @@ failed authentication on named pipe %s.\n", domain, user_name, wks, p->name ));
        
        memcpy(p->session_key, server_info->session_key, sizeof(p->session_key));
 
-       uid = pdb_get_uid(server_info->sam_account);
-       gid = pdb_get_gid(server_info->sam_account);
-
-       p->pipe_user.uid = uid;
-       p->pipe_user.gid = gid;
-
-       /* Set up pipe user group membership. */
-       initialise_groups(p->pipe_user_name, p->pipe_user.uid, p->pipe_user.gid);
-       get_current_groups(p->pipe_user.gid, &p->pipe_user.ngroups, &p->pipe_user.groups);
+       p->pipe_user.uid = pdb_get_uid(server_info->sam_account);
+       p->pipe_user.gid = pdb_get_gid(server_info->sam_account);
+       
+       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);
+                       return False;
+               }
+       }
 
        if (server_info->ptok)
-               add_supplementary_nt_login_groups(&p->pipe_user.ngroups, &p->pipe_user.groups, &server_info->ptok);
-
-       /* Create an NT_USER_TOKEN struct for this user. */
-       p->pipe_user.nt_user_token = create_nt_token(p->pipe_user.uid,p->pipe_user.gid,
-                                                    p->pipe_user.ngroups, p->pipe_user.groups,
-                                                    server_info->guest, 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->ntlmssp_auth_validated = True;
 
-       pdb_free_sam(&server_info->sam_account);
+       free_server_info(&server_info);
        return True;
 }
 
index cd9596d2a7280df2b0e473afbeb901d31bec4d97..f96de7e5339c894fa421e54008bdf3804df2b84b 100644 (file)
@@ -342,6 +342,9 @@ NTSTATUS _reg_info(pipes_struct *p, REG_Q_INFO *q_u, REG_R_INFO *r_u)
 {
        NTSTATUS                status = NT_STATUS_NO_SUCH_FILE;
        fstring                 name;
+       char                    *value_ascii = "";
+       fstring                 value;
+       int                     value_length;
        REGISTRY_KEY            *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
        REGISTRY_VALUE          *val = NULL;
        REGISTRY_VALUE          emptyval;
@@ -380,15 +383,20 @@ NTSTATUS _reg_info(pipes_struct *p, REG_Q_INFO *q_u, REG_R_INFO *r_u)
                switch (lp_server_role()) {
                        case ROLE_DOMAIN_PDC:
                        case ROLE_DOMAIN_BDC:
-                               regval_ctr_addvalue( &regvals, REGSTR_PRODUCTTYPE, REG_SZ, REG_PT_LANMANNT, strlen(REG_PT_LANMANNT)+1 );
+                               value_ascii = REG_PT_LANMANNT;
                                break;
                        case ROLE_STANDALONE:
-                               regval_ctr_addvalue( &regvals, REGSTR_PRODUCTTYPE, REG_SZ, REG_PT_SERVERNT, strlen(REG_PT_SERVERNT)+1 );
+                               value_ascii = REG_PT_SERVERNT;
                                break;
                        case ROLE_DOMAIN_MEMBER:
-                               regval_ctr_addvalue( &regvals, REGSTR_PRODUCTTYPE, REG_SZ, REG_PT_WINNT, strlen(REG_PT_WINNT)+1 );
+                               value_ascii = REG_PT_WINNT;
                                break;
                }
+               value_length = push_ucs2(value, value, value_ascii,
+                                        sizeof(value),
+                                        STR_TERMINATE|STR_NOALIGN);
+               regval_ctr_addvalue(&regvals, REGSTR_PRODUCTTYPE, REG_SZ,
+                                   value, value_length);
                
                val = dup_registry_value( regval_ctr_specific_value( &regvals, 0 ) );
                
index a30622c600823786cf45c0b960ad80626466ff09..ea631838dab30f729764f040aee388c53a960cb3 100644 (file)
@@ -57,6 +57,8 @@ struct samr_info {
        DOM_SID sid;
        uint32 status; /* some sort of flag.  best to record it.  comes from opnum 0x39 */
        uint32 acc_granted;
+       uint16 acb_mask;
+       BOOL all_machines;
        DISP_INFO disp_info;
 
        TALLOC_CTX *mem_ctx;
@@ -68,8 +70,7 @@ struct generic_mapping usr_generic_mapping = {USER_READ, USER_WRITE, USER_EXECUT
 struct generic_mapping grp_generic_mapping = {GROUP_READ, GROUP_WRITE, GROUP_EXECUTE, GROUP_ALL_ACCESS};
 struct generic_mapping ali_generic_mapping = {ALIAS_READ, ALIAS_WRITE, ALIAS_EXECUTE, ALIAS_ALL_ACCESS};
 
-static NTSTATUS samr_make_dom_obj_sd(TALLOC_CTX *ctx, SEC_DESC **psd, size_t *d_size);
-
+static NTSTATUS samr_make_dom_obj_sd(TALLOC_CTX *ctx, SEC_DESC **psd, size_t *sd_size);
 
 /*******************************************************************
  Checks if access to an object should be granted, and returns that
@@ -151,26 +152,36 @@ static struct samr_info *get_samr_info_by_sid(DOM_SID *psid)
        return info;
 }
 
+
 /*******************************************************************
  Function to free the per handle data.
  ********************************************************************/
-static void free_samr_db(struct samr_info *info)
+static void free_samr_users(struct samr_info *info) 
 {
        int i;
 
-       /* Groups are talloced */
-
        if (info->disp_info.user_dbloaded){
                for (i=0; i<info->disp_info.num_user_account; i++) {
                        /* Not really a free, actually a 'clear' */
                        pdb_free_sam(&info->disp_info.disp_user_info[i].sam);
                }
        }
-
        info->disp_info.user_dbloaded=False;
+       info->disp_info.num_user_account=0;
+}
+
+
+/*******************************************************************
+ Function to free the per handle data.
+ ********************************************************************/
+static void free_samr_db(struct samr_info *info)
+{
+       /* Groups are talloced */
+
+       free_samr_users(info);
+
        info->disp_info.group_dbloaded=False;
        info->disp_info.num_group_account=0;
-       info->disp_info.num_user_account=0;
 }
 
 
@@ -199,7 +210,7 @@ static void samr_clear_sam_passwd(SAM_ACCOUNT *sam_pass)
 }
 
 
-static NTSTATUS load_sampwd_entries(struct samr_info *info, uint16 acb_mask)
+static NTSTATUS load_sampwd_entries(struct samr_info *info, uint16 acb_mask, BOOL all_machines)
 {
        SAM_ACCOUNT *pwd = NULL;
        DISP_USER_INFO *pwd_array = NULL;
@@ -209,11 +220,15 @@ static NTSTATUS load_sampwd_entries(struct samr_info *info, uint16 acb_mask)
        DEBUG(10,("load_sampwd_entries\n"));
 
        /* if the snapshoot is already loaded, return */
-       if (info->disp_info.user_dbloaded==True) {
+       if ((info->disp_info.user_dbloaded==True) 
+           && (info->acb_mask == acb_mask) 
+           && (info->all_machines == all_machines)) {
                DEBUG(10,("load_sampwd_entries: already in memory\n"));
                return NT_STATUS_OK;
        }
 
+       free_samr_users(info);
+
        if (!pdb_setsampwent(False)) {
                DEBUG(0, ("load_sampwd_entries: Unable to open passdb.\n"));
                return NT_STATUS_ACCESS_DENIED;
@@ -222,10 +237,19 @@ static NTSTATUS load_sampwd_entries(struct samr_info *info, uint16 acb_mask)
        for (; (NT_STATUS_IS_OK(nt_status = pdb_init_sam_talloc(mem_ctx, &pwd))) 
                     && pdb_getsampwent(pwd) == True; pwd=NULL) {
                
-               if (acb_mask != 0 && !(pdb_get_acct_ctrl(pwd) & acb_mask)) {
-                       pdb_free_sam(&pwd);
-                       DEBUG(5,(" acb_mask %x reject\n", acb_mask));
-                       continue;
+               if (all_machines) {
+                       if (!((pdb_get_acct_ctrl(pwd) & ACB_WSTRUST) 
+                             || (pdb_get_acct_ctrl(pwd) & ACB_SVRTRUST))) {
+                               DEBUG(5,("load_sampwd_entries: '%s' is not a machine account - ACB: %x - skipping\n", pdb_get_username(pwd), acb_mask));
+                               pdb_free_sam(&pwd);
+                               continue;
+                       }
+               } else {
+                       if (acb_mask != 0 && !(pdb_get_acct_ctrl(pwd) & acb_mask)) {
+                               pdb_free_sam(&pwd);
+                               DEBUG(5,(" acb_mask %x reject\n", acb_mask));
+                               continue;
+                       }
                }
 
                /* Realloc some memory for the array of ptr to the SAM_ACCOUNT structs */
@@ -253,6 +277,8 @@ static NTSTATUS load_sampwd_entries(struct samr_info *info, uint16 acb_mask)
 
        /* the snapshoot is in memory, we're ready to enumerate fast */
 
+       info->acb_mask = acb_mask;
+       info->all_machines = all_machines;
        info->disp_info.user_dbloaded=True;
 
        DEBUG(12,("load_sampwd_entries: done\n"));
@@ -406,46 +432,6 @@ NTSTATUS _samr_get_usrdom_pwinfo(pipes_struct *p, SAMR_Q_GET_USRDOM_PWINFO *q_u,
        return r_u->status;
 }
 
-
-/*******************************************************************
- samr_make_sam_obj_sd
- ********************************************************************/
-
-static NTSTATUS samr_make_sam_obj_sd(TALLOC_CTX *ctx, SEC_DESC **psd, size_t *sd_size)
-{
-       extern DOM_SID global_sid_World;
-       DOM_SID adm_sid;
-       DOM_SID act_sid;
-
-       SEC_ACE ace[3];
-       SEC_ACCESS mask;
-
-       SEC_ACL *psa = NULL;
-
-       sid_copy(&adm_sid, &global_sid_Builtin);
-       sid_append_rid(&adm_sid, BUILTIN_ALIAS_RID_ADMINS);
-
-       sid_copy(&act_sid, &global_sid_Builtin);
-       sid_append_rid(&act_sid, BUILTIN_ALIAS_RID_ACCOUNT_OPS);
-
-       /*basic access for every one*/
-       init_sec_access(&mask, SAMR_EXECUTE | SAMR_READ);
-       init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
-
-       /*full access for builtin aliases Administrators and Account Operators*/
-       init_sec_access(&mask, SAMR_ALL_ACCESS);
-       init_sec_ace(&ace[1], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
-       init_sec_ace(&ace[2], &act_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
-
-       if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 3, ace)) == NULL)
-               return NT_STATUS_NO_MEMORY;
-
-       if ((*psd = make_sec_desc(ctx, SEC_DESC_REVISION, NULL, NULL, NULL, psa, sd_size)) == NULL)
-               return NT_STATUS_NO_MEMORY;
-
-       return NT_STATUS_OK;
-}
-
 /*******************************************************************
  samr_make_dom_obj_sd
  ********************************************************************/
@@ -787,7 +773,7 @@ NTSTATUS _samr_enum_dom_users(pipes_struct *p, SAMR_Q_ENUM_DOM_USERS *q_u,
        DEBUG(5,("_samr_enum_dom_users: %d\n", __LINE__));
 
        become_root();
-       r_u->status=load_sampwd_entries(info, q_u->acb_mask);
+       r_u->status=load_sampwd_entries(info, q_u->acb_mask, False);
        unbecome_root();
        
        if (!NT_STATUS_IS_OK(r_u->status))
@@ -1058,8 +1044,6 @@ static NTSTATUS get_group_domain_entries(TALLOC_CTX *ctx, DOMAIN_GRP **d_grp, DO
 
 /*******************************************************************
  samr_reply_enum_dom_groups
- Only reply with one group - domain admins. This must be fixed for
- a real PDC. JRA.
  ********************************************************************/
 
 NTSTATUS _samr_enum_dom_groups(pipes_struct *p, SAMR_Q_ENUM_DOM_GROUPS *q_u, SAMR_R_ENUM_DOM_GROUPS *r_u)
@@ -1143,7 +1127,6 @@ NTSTATUS _samr_query_dispinfo(pipes_struct *p, SAMR_Q_QUERY_DISPINFO *q_u,
 {
        struct samr_info *info = NULL;
        uint32 struct_size=0x20; /* W2K always reply that, client doesn't care */
-       uint16 acb_mask;
        
        uint32 max_entries=q_u->max_entries;
        uint32 enum_context=q_u->start_idx;
@@ -1194,20 +1177,14 @@ NTSTATUS _samr_query_dispinfo(pipes_struct *p, SAMR_Q_QUERY_DISPINFO *q_u,
         * JFM, 12/20/2001
         */
 
-       /* Get what we need from the password database */
-
-       if (q_u->switch_level==2)
-               acb_mask = ACB_WSTRUST;
-       else
-               acb_mask = ACB_NORMAL;
-
        /* Get what we need from the password database */
        switch (q_u->switch_level) {
                case 0x1:
                case 0x2:
                case 0x4:
                        become_root();          
-                       r_u->status=load_sampwd_entries(info, acb_mask);
+                       /* Level 2 is for all machines, otherwise only 'normal' users */
+                       r_u->status=load_sampwd_entries(info, ACB_NORMAL, q_u->switch_level==2);
                        unbecome_root();
                        if (!NT_STATUS_IS_OK(r_u->status)) {
                                DEBUG(5, ("_samr_query_dispinfo: load_sampwd_entries failed\n"));
@@ -2126,7 +2103,7 @@ NTSTATUS _samr_query_dom_info(pipes_struct *p, SAMR_Q_QUERY_DOMAIN_INFO *q_u, SA
                        break;
                case 0x02:
                        become_root();          
-                       r_u->status=load_sampwd_entries(info, ACB_NORMAL);
+                       r_u->status=load_sampwd_entries(info, ACB_NORMAL, False);
                        unbecome_root();
                        if (!NT_STATUS_IS_OK(r_u->status)) {
                                DEBUG(5, ("_samr_query_dispinfo: load_sampwd_entries failed\n"));
@@ -3880,6 +3857,7 @@ NTSTATUS _samr_create_dom_group(pipes_struct *p, SAMR_Q_CREATE_DOM_GROUP *q_u, S
        struct samr_info *info;
        PRIVILEGE_SET priv_set;
        uint32 acc_granted;
+       gid_t gid;
 
        init_privilege(&priv_set);
 
@@ -3903,10 +3881,11 @@ NTSTATUS _samr_create_dom_group(pipes_struct *p, SAMR_Q_CREATE_DOM_GROUP *q_u, S
                return NT_STATUS_GROUP_EXISTS;
 
        /* we can create the UNIX group */
-       smb_create_group(name);
+       if (smb_create_group(name, &gid) != 0)
+               return NT_STATUS_ACCESS_DENIED;
 
        /* check if the group has been successfully created */
-       if ((grp=getgrnam(name)) == NULL)
+       if ((grp=getgrgid(gid)) == NULL)
                return NT_STATUS_ACCESS_DENIED;
 
        r_u->rid=pdb_gid_to_group_rid(grp->gr_gid);
@@ -3943,6 +3922,7 @@ NTSTATUS _samr_create_dom_alias(pipes_struct *p, SAMR_Q_CREATE_DOM_ALIAS *q_u, S
        struct samr_info *info;
        PRIVILEGE_SET priv_set;
        uint32 acc_granted;
+       gid_t gid;
 
        init_privilege(&priv_set);
 
@@ -3966,10 +3946,11 @@ NTSTATUS _samr_create_dom_alias(pipes_struct *p, SAMR_Q_CREATE_DOM_ALIAS *q_u, S
                return NT_STATUS_GROUP_EXISTS;
 
        /* we can create the UNIX group */
-       smb_create_group(name);
+       if (smb_create_group(name, &gid) != 0)
+               return NT_STATUS_ACCESS_DENIED;
 
        /* check if the group has been successfully created */
-       if ((grp=getgrnam(name)) == NULL)
+       if ((grp=getgrgid(gid)) == NULL)
                return NT_STATUS_ACCESS_DENIED;
 
        r_u->rid=pdb_gid_to_group_rid(grp->gr_gid);
@@ -4095,9 +4076,9 @@ NTSTATUS _samr_set_groupinfo(pipes_struct *p, SAMR_Q_SET_GROUPINFO *q_u, SAMR_R_
 }
 
 /*********************************************************************
- _samr_set_groupinfo
+ _samr_set_aliasinfo
  
- update a domain group's comment.
+ update an alias's comment.
 *********************************************************************/
 
 NTSTATUS _samr_set_aliasinfo(pipes_struct *p, SAMR_Q_SET_ALIASINFO *q_u, SAMR_R_SET_ALIASINFO *r_u)
@@ -4290,10 +4271,10 @@ NTSTATUS _samr_unknown_2e(pipes_struct *p, SAMR_Q_UNKNOWN_2E *q_u, SAMR_R_UNKNOW
                        break;
                case 0x02:
                        become_root();          
-                       r_u->status=load_sampwd_entries(info, ACB_NORMAL);
+                       r_u->status=load_sampwd_entries(info, ACB_NORMAL, False);
                        unbecome_root();
                        if (!NT_STATUS_IS_OK(r_u->status)) {
-                               DEBUG(5, ("_samr_query_dispinfo: load_sampwd_entries failed\n"));
+                               DEBUG(5, ("_samr_unknown_2e: load_sampwd_entries failed\n"));
                                return r_u->status;
                        }
                        num_users=info->disp_info.num_user_account;
@@ -4301,7 +4282,7 @@ NTSTATUS _samr_unknown_2e(pipes_struct *p, SAMR_Q_UNKNOWN_2E *q_u, SAMR_R_UNKNOW
                        
                        r_u->status=load_group_domain_entries(info, get_global_sam_sid());
                        if (NT_STATUS_IS_ERR(r_u->status)) {
-                               DEBUG(5, ("_samr_query_dispinfo: load_group_domain_entries failed\n"));
+                               DEBUG(5, ("_samr_unknown_2e: load_group_domain_entries failed\n"));
                                return r_u->status;
                        }
                        num_groups=info->disp_info.num_group_account;
index 7aceaa548f29000bb4b1d5e9d55887ecb6b4cb2c..2190215107af553f5e11072aa88b3a8260af3732 100644 (file)
@@ -4,7 +4,7 @@
  *  Copyright (C) Andrew Tridgell              1992-2000,
  *  Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
  *  Copyright (C) Jean François Micouleau      1998-2000,
- *  Copyright (C) Jeremy Allison                   2001,
+ *  Copyright (C) Jeremy Allison               2001-2002,
  *  Copyright (C) Gerald Carter                       2000-2002,
  *  Copyright (C) Tim Potter                   2001-2002.
  *
@@ -87,6 +87,10 @@ typedef struct _Printer{
                fstring machine;
                fstring user;
        } client;
+       
+       /* devmode sent in the OpenPrinter() call */
+       NT_DEVICEMODE   *nt_devmode;
+       
 } Printer_entry;
 
 static Printer_entry *printers_list;
@@ -196,6 +200,11 @@ static void srv_spoolss_replycloseprinter(POLICY_HND *handle)
                cli_ulogoff(&notify_cli);
                cli_shutdown(&notify_cli);
                message_deregister(MSG_PRINTER_NOTIFY2);
+
+               /* Tell the connections db we're no longer interested in
+                * printer notify messages. */
+
+               register_message_flags( False, FLAG_MSG_PRINTING );
        }
 
        smb_connections--;
@@ -219,6 +228,8 @@ static void free_printer_entry(void *ptr)
        free_spool_notify_option(&Printer->notify.option);
        Printer->notify.option=NULL;
        Printer->notify.client_connected=False;
+       
+       free_nt_devicemode( &Printer->nt_devmode );
 
        /* Remove from the internal list. */
        DLIST_REMOVE(printers_list, Printer);
@@ -566,7 +577,14 @@ static BOOL is_monitoring_event(Printer_entry *p, uint16 notify_type,
 {
        SPOOL_NOTIFY_OPTION *option = p->notify.option;
        uint32 i, j;
-       
+
+       /* 
+        * Flags should always be zero when the change notify
+        * is registered by the cliebnt's spooler.  A user Win32 app
+        * might use the flags though instead of the NOTIFY_OPTION_INFO 
+        * --jerry
+        */
+        
        if (p->notify.flags)
                return is_monitoring_event_flags(
                        p->notify.flags, notify_type, notify_field);
@@ -716,26 +734,177 @@ static struct notify2_message_table job_notify_table[] = {
        /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
 };
 
+
+/***********************************************************************
+ Allocate talloc context for container object
+ **********************************************************************/
+static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
+{
+       if ( !ctr )
+               return;
+
+       ctr->ctx = talloc_init();
+               
+       return;
+}
+
+/***********************************************************************
+ release all allocated memory and zero out structure
+ **********************************************************************/
+static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
+{
+       if ( !ctr )
+               return;
+
+       if ( ctr->ctx )
+               talloc_destroy(ctr->ctx);
+               
+       ZERO_STRUCTP(ctr);
+               
+       return;
+}
+
+/***********************************************************************
+ **********************************************************************/
+static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
+{
+       if ( !ctr )
+               return NULL;
+               
+       return ctr->ctx;
+}
+
+/***********************************************************************
+ **********************************************************************/
+static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
+{
+       if ( !ctr || !ctr->msg_groups )
+               return NULL;
+       
+       if ( idx >= ctr->num_groups )
+               return NULL;
+               
+       return &ctr->msg_groups[idx];
+
+}
+
+/***********************************************************************
+ How many groups of change messages do we have ?
+ **********************************************************************/
+static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
+{
+       if ( !ctr )
+               return 0;
+               
+       return ctr->num_groups;
+}
+
+/***********************************************************************
+ Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
+ **********************************************************************/
+static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
+{
+       SPOOLSS_NOTIFY_MSG_GROUP        *groups = NULL;
+       SPOOLSS_NOTIFY_MSG_GROUP        *msg_grp = NULL;
+       SPOOLSS_NOTIFY_MSG              *msg_list = NULL;
+       int                             i, new_slot;
+       
+       if ( !ctr || !msg )
+               return 0;
+       
+       /* loop over all groups looking for a matching printer name */
+       
+       for ( i=0; i<ctr->num_groups; i++ ) {
+               if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
+                       break;
+       }
+       
+       /* add a new group? */
+       
+       if ( i == ctr->num_groups )
+       {
+               ctr->num_groups++;
+
+               if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, sizeof(SPOOLSS_NOTIFY_MSG_GROUP)*ctr->num_groups)) ) {
+                       DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
+                       return 0;
+               }
+               ctr->msg_groups = groups;
+
+               /* clear the new entry and set the printer name */
+               
+               ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
+               fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
+       }
+       
+       /* add the change messages; 'i' is the correct index now regardless */
+       
+       msg_grp = &ctr->msg_groups[i];
+       
+       msg_grp->num_msgs++;
+       
+       if ( !(msg_list =  talloc_realloc( ctr->ctx, msg_grp->msgs, sizeof(SPOOLSS_NOTIFY_MSG)*msg_grp->num_msgs )) ) {
+               DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
+               return 0;
+       }
+       msg_grp->msgs = msg_list;
+       
+       new_slot = msg_grp->num_msgs-1;
+       memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
+       
+       /* need to allocate own copy of data */
+       
+       if ( msg->len != 0 ) 
+               msg_grp->msgs[new_slot].notify.data = talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
+       
+       return ctr->num_groups;
+}
+
 /***********************************************************************
  Send a change notication message on all handles which have a call 
  back registered
  **********************************************************************/
 
-static void process_notify2_message(struct spoolss_notify_msg *msg, 
-                                   TALLOC_CTX *mem_ctx)
+static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
 {
-       Printer_entry *p;
-
-       DEBUG(8,("process_notify2_message: Enter...[%s]\n", msg->printer));
+       Printer_entry            *p;
+       TALLOC_CTX               *mem_ctx = notify_ctr_getctx( ctr );
+       SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
+       SPOOLSS_NOTIFY_MSG       *messages;
+       
+       
+       if ( !msg_group ) {
+               DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
+               return;
+       }
+       
+       messages = msg_group->msgs;
        
-       for (p = printers_list; p; p = p->next) {
+       if ( !messages ) {
+               DEBUG(5,("send_notify2_changes() called with no messages!\n"));
+               return;
+       }
+       
+       DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
+       
+       /* loop over all printers */
+       
+       for (p = printers_list; p; p = p->next) 
+       {
                SPOOL_NOTIFY_INFO_DATA *data;
-               uint32 data_len = 1;
-               uint32 id;
+               uint32  data_len = 0;
+               uint32  id;
+               int     i;
 
                /* Is there notification on this handle? */
 
-               if (!p->notify.client_connected)
+               if ( !p->notify.client_connected )
                        continue;
 
                DEBUG(10,("Client connected! [%s]\n", p->dev.handlename));
@@ -744,25 +913,31 @@ static void process_notify2_message(struct spoolss_notify_msg *msg,
                    notifications. */
 
                if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER )  &&
-                   ( !strequal(msg->printer, p->dev.handlename) ) )
+                   ( !strequal(msg_group->printername, p->dev.handlename) ) )
                        continue;
 
                DEBUG(10,("Our printer\n"));
                
+               /* allocate the max entries possible */
+               
+               data = talloc( mem_ctx, msg_group->num_msgs*sizeof(SPOOL_NOTIFY_INFO_DATA) );
+               ZERO_STRUCTP(data);
+               
+               /* build the array of change notifications */
+               
+               for ( i=0; i<msg_group->num_msgs; i++ )
+               {
+                       SPOOLSS_NOTIFY_MSG      *msg = &messages[i];
+                       
                /* Are we monitoring this event? */
 
                if (!is_monitoring_event(p, msg->type, msg->field))
                        continue;
 
+                       
                DEBUG(10,("process_notify2_message: Sending message type [%x] field [%x] for printer [%s]\n",
                        msg->type, msg->field, p->dev.handlename));
 
-               /* OK - send the event to the client */
-
-               data = talloc(mem_ctx, sizeof(SPOOL_NOTIFY_INFO_DATA));
-
-               ZERO_STRUCTP(data);
-
                /* 
                 * if the is a printer notification handle and not a job notification 
                 * type, then set the id to 0.  Other wise just use what was specified
@@ -784,8 +959,8 @@ static void process_notify2_message(struct spoolss_notify_msg *msg,
 
                /* Convert unix jobid to smb jobid */
 
-               if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
-
+                       if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) 
+                       {
                        id = sysjob_to_jobid(msg->id);
 
                        if (id == -1) {
@@ -794,22 +969,20 @@ static void process_notify2_message(struct spoolss_notify_msg *msg,
                        }
                }
 
-               construct_info_data(data, msg->type, msg->field, id);
+                       construct_info_data( &data[data_len], msg->type, msg->field, id );
 
                switch(msg->type) {
                case PRINTER_NOTIFY_TYPE:
                                if ( !printer_notify_table[msg->field].fn )
                                goto done;
-                                       
-                               printer_notify_table[msg->field].fn(msg, data, mem_ctx);
+                                       printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
                                
                        break;
                        
                case JOB_NOTIFY_TYPE:
                                if ( !job_notify_table[msg->field].fn )
                                goto done;
-
-                               job_notify_table[msg->field].fn(msg, data, mem_ctx);
+                                       job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
 
                                break;
 
@@ -818,59 +991,139 @@ static void process_notify2_message(struct spoolss_notify_msg *msg,
                                goto done;
                        }
 
+                       data_len++;
+               }
+
                cli_spoolss_rrpcn( &notify_cli, mem_ctx, &p->notify.client_hnd, 
                                data_len, data, p->notify.change, 0 );
        }
+       
 done:
-       DEBUG(8,("process_notify2_message: Exit...\n"));
+       DEBUG(8,("send_notify2_changes: Exit...\n"));
        return;
 }
 
-/* Receive a notify2 message */
+/***********************************************************************
+ **********************************************************************/
 
-static void receive_notify2_message(int msg_type, pid_t src, void *buf, 
-                                   size_t len)
+static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, void *buf, size_t len )
 {
-       struct spoolss_notify_msg msg;
+
        int offset = 0;
-       TALLOC_CTX *mem_ctx = talloc_init();
 
        /* Unpack message */
 
-       ZERO_STRUCT(msg);
-
        offset += tdb_unpack((char *)buf + offset, len - offset, "f",
-                            msg.printer);
+                            msg->printer);
        
        offset += tdb_unpack((char *)buf + offset, len - offset, "ddddd",
-                            &msg.type, &msg.field, &msg.id, &msg.len, &msg.flags);
+                            &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
 
-       if (msg.len == 0)
+       if (msg->len == 0)
                tdb_unpack((char *)buf + offset, len - offset, "dd",
-                          &msg.notify.value[0], &msg.notify.value[1]);
+                          &msg->notify.value[0], &msg->notify.value[1]);
        else
                tdb_unpack((char *)buf + offset, len - offset, "B", 
-                          &msg.len, &msg.notify.data);
+                          &msg->len, &msg->notify.data);
 
-       DEBUG(3, ("got NOTIFY2 message, type %d, field 0x%02x, flags 0x%04x\n",
-                 msg.type, msg.field, msg.flags));
+       DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message, type %d, field 0x%02x, flags 0x%04x\n",
+                 msg->type, msg->field, msg->flags));
 
-       if (msg.len == 0)
-               DEBUG(3, ("value1 = %d, value2 = %d\n", msg.notify.value[0],
-                         msg.notify.value[1]));
+       if (msg->len == 0)
+               DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
+                         msg->notify.value[1]));
        else
-               dump_data(3, msg.notify.data, msg.len);
+               dump_data(3, msg->notify.data, msg->len);
+
+       return True;
+}
+
+/********************************************************************
+ Receive a notify2 message list
+ ********************************************************************/
+
+static void receive_notify2_message_list(int msg_type, pid_t src, void *msg, size_t len)
+{
+       size_t                  msg_count, i;
+       char                    *buf = (char *)msg;
+       char                    *msg_ptr;
+       size_t                  msg_len;
+       SPOOLSS_NOTIFY_MSG      notify;
+       SPOOLSS_NOTIFY_MSG_CTR  messages;
+       int                     num_groups;
+
+       if (len < 4) {
+               DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
+               return;
+       }
+       
+       msg_count = IVAL(buf, 0);
+       msg_ptr = buf + 4;
 
-       /* Process message */
+       DEBUG(5, ("receive_notify2_message_list: got %d messages in list\n", msg_count));
 
-       process_notify2_message(&msg, mem_ctx);
+       if (msg_count == 0) {
+               DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
+               return;
+       }
 
-       /* Free message */
+       /* initialize the container */
+       
+       ZERO_STRUCT( messages );
+       notify_msg_ctr_init( &messages );
+       
+       /* 
+        * build message groups for each printer identified
+        * in a change_notify msg.  Remember that a PCN message
+        * includes the handle returned for the srv_spoolss_replyopenprinter()
+        * call.  Therefore messages are grouped according to printer handle.
+        */
+        
+       for ( i=0; i<msg_count; i++ ) 
+       {
+               if (msg_ptr + 4 - buf > len) {
+                       DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
+                       return;
+               }
 
-       if (msg.len > 0)
-               free(msg.notify.data);
+               msg_len = IVAL(msg_ptr,0);
+               msg_ptr += 4;
 
-       talloc_destroy(mem_ctx);
+               if (msg_ptr + msg_len - buf > len) {
+                       DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
+                       return;
+               }
+               
+               /* unpack messages */
+               
+               ZERO_STRUCT( notify );
+               notify2_unpack_msg( &notify, msg_ptr, msg_len );
+               msg_ptr += msg_len;
+               
+               /* add to correct list in container */
+               
+               notify_msg_ctr_addmsg( &messages, &notify );
+               
+               /* free memory that might have been allocated by notify2_unpack_msg() */
+               
+               if ( notify.len != 0 )
+                       SAFE_FREE( notify.notify.data );
+       }
+       
+       /* process each group of messages */
+       
+       num_groups = notify_msg_ctr_numgroups( &messages );
+       for ( i=0; i<num_groups; i++ )
+               send_notify2_changes( &messages, i );
+       
+       
+       /* cleanup */
+               
+       DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
+               
+       notify_msg_ctr_destroy( &messages );
+       
+       return;
 }
 
 /********************************************************************
@@ -1143,14 +1396,65 @@ WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R
 /********************************************************************
  * spoolss_open_printer
  *
- * called from the spoolss dispatcher
+ * If the openprinterex rpc call contains a devmode,
+ * it's a per-user one. This per-user devmode is derivated
+ * from the global devmode. Openprinterex() contains a per-user 
+ * devmode for when you do EMF printing and spooling.
+ * In the EMF case, the NT workstation is only doing half the job
+ * of rendering the page. The other half is done by running the printer
+ * driver on the server.
+ * The EMF file doesn't contain the page description (paper size, orientation, ...).
+ * The EMF file only contains what is to be printed on the page.
+ * So in order for the server to know how to print, the NT client sends
+ * a devicemode attached to the openprinterex call.
+ * But this devicemode is short lived, it's only valid for the current print job.
+ *
+ * If Samba would have supported EMF spooling, this devicemode would
+ * have been attached to the handle, to sent it to the driver to correctly
+ * rasterize the EMF file.
+ *
+ * As Samba only supports RAW spooling, we only receive a ready-to-print file,
+ * we just act as a pass-thru between windows and the printer.
+ *
+ * In order to know that Samba supports only RAW spooling, NT has to call
+ * getprinter() at level 2 (attribute field) or NT has to call startdoc()
+ * and until NT sends a RAW job, we refuse it.
+ *
+ * But to call getprinter() or startdoc(), you first need a valid handle,
+ * and to get an handle you have to call openprintex(). Hence why you have
+ * a devicemode in the openprinterex() call.
+ *
+ *
+ * Differences between NT4 and NT 2000.
+ * NT4:
+ * ---
+ * On NT4, you only have a global devicemode. This global devicemode can be changed
+ * by the administrator (or by a user with enough privs). Everytime a user
+ * wants to print, the devicemode is resetted to the default. In Word, everytime
+ * you print, the printer's characteristics are always reset to the global devicemode.
+ *
+ * NT 2000:
+ * -------
+ * In W2K, there is the notion of per-user devicemode. The first time you use
+ * a printer, a per-user devicemode is build from the global devicemode.
+ * If you change your per-user devicemode, it is saved in the registry, under the
+ * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
+ * printer preferences available.
+ *
+ * To change the per-user devicemode: it's the "Printing Preferences ..." button
+ * on the General Tab of the printer properties windows.
+ *
+ * To change the global devicemode: it's the "Printing Defaults..." button
+ * on the Advanced Tab of the printer properties window.
+ *
+ * JFM.
  ********************************************************************/
 
 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
 {
-       UNISTR2 *printername = NULL;
-       PRINTER_DEFAULT *printer_default = &q_u->printer_default;
-       POLICY_HND *handle = &r_u->handle;
+       UNISTR2                 *printername = NULL;
+       PRINTER_DEFAULT         *printer_default = &q_u->printer_default;
+       POLICY_HND              *handle = &r_u->handle;
 
        fstring name;
        int snum;
@@ -1180,39 +1484,36 @@ Can't find printer handle we created for printer %s\n", name ));
                return WERR_INVALID_PRINTER_NAME;
        }
 
-       /*
-          First case: the user is opening the print server:
-
-          Disallow MS AddPrinterWizard if parameter disables it. A Win2k
-          client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
-
-          Then both Win2k and WinNT clients try an OpenPrinterEx with
-          SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
-          or if the user is listed in the smb.conf printer admin parameter.
-
-          Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
-          client view printer folder, but does not show the MSAPW.
-
-          Note: this test needs code to check access rights here too. Jeremy
-          could you look at this?
-          
-          
-          Second case: the user is opening a printer:
-          NT doesn't let us connect to a printer if the connecting user
-          doesn't have print permission.
-
-       */
-
        get_current_user(&user, p);
 
-       if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
+       /*
+        * First case: the user is opening the print server:
+        *
+        * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
+        * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
+        *
+        * Then both Win2k and WinNT clients try an OpenPrinterEx with
+        * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
+        * or if the user is listed in the smb.conf printer admin parameter.
+        *
+        * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
+        * client view printer folder, but does not show the MSAPW.
+        *
+        * Note: this test needs code to check access rights here too. Jeremy
+        * could you look at this?
+        * 
+        * Second case: the user is opening a printer:
+        * NT doesn't let us connect to a printer if the connecting user
+        * doesn't have print permission.
+        */
 
+       if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) 
+       {
                /* Printserver handles use global struct... */
 
                snum = -1;
 
-               /* Map standard access rights to object specific access
-                  rights */
+               /* Map standard access rights to object specific access rights */
                
                se_map_standard(&printer_default->access_required, 
                                &printserver_std_mapping);
@@ -1231,23 +1532,32 @@ Can't find printer handle we created for printer %s\n", name ));
 
                /* Allow admin access */
 
-               if (printer_default->access_required & 
-                   SERVER_ACCESS_ADMINISTER) {
-
+               if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER ) 
+               {
                        if (!lp_ms_add_printer_wizard()) {
                                close_printer_handle(p, handle);
                                return WERR_ACCESS_DENIED;
                        }
 
-                       if (user.uid == 0 || 
-                           user_in_list(uidtoname(user.uid),
-                                        lp_printer_admin(snum)))
-                               return WERR_OK;
+                       /* if the user is not root and not a printer admin, then fail */
                        
-                       close_printer_handle(p, handle);
-                       return WERR_ACCESS_DENIED;
+                       if ( user.uid != 0
+                            && !user_in_list(uidtoname(user.uid), lp_printer_admin(snum)) )
+                       {
+                               close_printer_handle(p, handle);
+                               return WERR_ACCESS_DENIED;
+                       }
+                       
+                       printer_default->access_required = SERVER_ACCESS_ADMINISTER;
+               }
+               else
+               {
+                       printer_default->access_required = SERVER_ACCESS_ENUMERATE;
                }
 
+               DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER) 
+                       ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
+                       
                /* We fall through to return WERR_OK */
                
        }
@@ -1296,84 +1606,24 @@ Can't find printer handle we created for printer %s\n", name ));
                else
                        printer_default->access_required = PRINTER_ACCESS_USE;
 
-               DEBUG(4,("Setting printer access=%x\n", printer_default->access_required));
-               Printer->access_granted = printer_default->access_required;
-
-               /*
-                * If we have a default device pointer in the
-                * printer_default struct, then we need to get
-                * the printer info from the tdb and if there is
-                * no default devicemode there then we do a *SET*
-                * here ! This is insanity.... JRA.
-                */
-
-               /*
-                * If the openprinterex rpc call contains a devmode,
-                * it's a per-user one. This per-user devmode is derivated
-                * from the global devmode. Openprinterex() contains a per-user 
-                * devmode for when you do EMF printing and spooling.
-                * In the EMF case, the NT workstation is only doing half the job
-                * of rendering the page. The other half is done by running the printer
-                * driver on the server.
-                * The EMF file doesn't contain the page description (paper size, orientation, ...).
-                * The EMF file only contains what is to be printed on the page.
-                * So in order for the server to know how to print, the NT client sends
-                * a devicemode attached to the openprinterex call.
-                * But this devicemode is short lived, it's only valid for the current print job.
-                *
-                * If Samba would have supported EMF spooling, this devicemode would
-                * have been attached to the handle, to sent it to the driver to correctly
-                * rasterize the EMF file.
-                *
-                * As Samba only supports RAW spooling, we only receive a ready-to-print file,
-                * we just act as a pass-thru between windows and the printer.
-                *
-                * In order to know that Samba supports only RAW spooling, NT has to call
-                * getprinter() at level 2 (attribute field) or NT has to call startdoc()
-                * and until NT sends a RAW job, we refuse it.
-                *
-                * But to call getprinter() or startdoc(), you first need a valid handle,
-                * and to get an handle you have to call openprintex(). Hence why you have
-                * a devicemode in the openprinterex() call.
-                *
-                *
-                * Differences between NT4 and NT 2000.
-                * NT4:
-                * ---
-                * On NT4, you only have a global devicemode. This global devicemode can be changed
-                * by the administrator (or by a user with enough privs). Everytime a user
-                * wants to print, the devicemode is resetted to the default. In Word, everytime
-                * you print, the printer's characteristics are always reset to the global devicemode.
-                *
-                * NT 2000:
-                * -------
-                * In W2K, there is the notion of per-user devicemode. The first time you use
-                * a printer, a per-user devicemode is build from the global devicemode.
-                * If you change your per-user devicemode, it is saved in the registry, under the
-                * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
-                * printer preferences available.
-                *
-                * To change the per-user devicemode: it's the "Printing Preferences ..." button
-                * on the General Tab of the printer properties windows.
-                *
-                * To change the global devicemode: it's the "Printing Defaults..." button
-                * on the Advanced Tab of the printer properties window.
-                *
-                * JFM.
-                */
+               DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER) 
+                       ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
 
-
-
-#if 0
-               if (printer_default->devmode_cont.devmode != NULL) {
-                       result = printer_write_default_dev( snum, printer_default);
-                       if (result != 0) {
-                               close_printer_handle(p, handle);
-                               return result;
-                       }
-               }
-#endif
        }
+       
+       Printer->access_granted = printer_default->access_required;
+       
+       /* 
+        * If the client sent a devmode in the OpenPrinter() call, then
+        * save it here in case we get a job submission on this handle
+        */
+       
+        if ( (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
+               && q_u->printer_default.devmode_cont.devmode_ptr )
+        { 
+               convert_devicemode( Printer->dev.handlename, q_u->printer_default.devmode_cont.devmode,
+                       &Printer->nt_devmode );
+        }
 
        return WERR_OK;
 }
@@ -1599,8 +1849,11 @@ WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER
        fstring                         driver;
        fstring                         arch;
        NT_PRINTER_DRIVER_INFO_LEVEL    info;
+       NT_PRINTER_DRIVER_INFO_LEVEL    info_win2k;
        int                             version;
        struct current_user             user;
+       WERROR                          status;
+       WERROR                          status_win2k = WERR_ACCESS_DENIED;
        
        get_current_user(&user, p);
         
@@ -1608,25 +1861,58 @@ WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER
        unistr2_to_ascii(arch,   &q_u->arch,   sizeof(arch)-1   );
        
        /* check that we have a valid driver name first */
-       if ((version=get_version_id(arch)) == -1) {
-               /* this is what NT returns */
+       
+       if ((version=get_version_id(arch)) == -1) 
                return WERR_INVALID_ENVIRONMENT;
+                               
+       ZERO_STRUCT(info);
+       ZERO_STRUCT(info_win2k);
+       
+       if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) 
+       {
+               /* try for Win2k driver if "Windows NT x86" */
+               
+               if ( version == 2 ) {
+                       version = 3;
+                       if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
+                               status = WERR_UNKNOWN_PRINTER_DRIVER;
+                               goto done;
+                       }
+               }
        }
        
-       /* if they said "Windows NT x86", then try for version 2 & 3 */
+       if (printer_driver_in_use(info.info_3)) {
+               status = WERR_PRINTER_DRIVER_IN_USE;
+               goto done;
+       }
        
        if ( version == 2 )
-               version = DRIVER_ANY_VERSION;
+       {               
+               if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
+               {
+                       /* if we get to here, we now have 2 driver info structures to remove */
+                       /* remove the Win2k driver first*/
                
-       ZERO_STRUCT(info);
+                       status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False );
+                       free_a_printer_driver( info_win2k, 3 );
+               
+                       /* this should not have failed---if it did, report to client */
+                       if ( !W_ERROR_IS_OK(status_win2k) )
+                               goto done;
+               }
+       }
        
-       if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
-               return WERR_UNKNOWN_PRINTER_DRIVER;
+       status = delete_printer_driver(info.info_3, &user, version, False);
+       
+       /* if at least one of the deletes succeeded return OK */
        
-       if (printer_driver_in_use(info.info_3))
-               return WERR_PRINTER_DRIVER_IN_USE;
+       if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
+               status = WERR_OK;
+       
+done:
+       free_a_printer_driver( info, 3 );
 
-       return delete_printer_driver(info.info_3, &user, DRIVER_ANY_VERSION, False);
+       return status;
 }
 
 /********************************************************************
@@ -1638,10 +1924,13 @@ WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIV
        fstring                         driver;
        fstring                         arch;
        NT_PRINTER_DRIVER_INFO_LEVEL    info;
+       NT_PRINTER_DRIVER_INFO_LEVEL    info_win2k;
        int                             version;
        uint32                          flags = q_u->delete_flags;
        BOOL                            delete_files;
        struct current_user             user;
+       WERROR                          status;
+       WERROR                          status_win2k = WERR_ACCESS_DENIED;
        
        get_current_user(&user, p);
        
@@ -1656,17 +1945,36 @@ WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIV
        
        if ( flags & DPD_DELETE_SPECIFIC_VERSION )
                version = q_u->version;
-       else if ( version == 2 )
-               /* if they said "Windows NT x86", then try for version 2 & 3 */
-               version = DRIVER_ANY_VERSION;
                
        ZERO_STRUCT(info);
+       ZERO_STRUCT(info_win2k);
+               
+       status = get_a_printer_driver(&info, 3, driver, arch, version);
        
-       if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) 
-               return WERR_UNKNOWN_PRINTER_DRIVER;
+       if ( !W_ERROR_IS_OK(status) ) 
+       {
+               /* 
+                * if the client asked for a specific version, 
+                * or this is something other than Windows NT x86,
+                * then we've failed 
+                */
+               
+               if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
+                       goto done;
+                       
+               /* try for Win2k driver if "Windows NT x86" */
+               
+               version = 3;
+               if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
+                       status = WERR_UNKNOWN_PRINTER_DRIVER;
+                       goto done;
+               }
+       }
                
-       if ( printer_driver_in_use(info.info_3) )
-               return WERR_PRINTER_DRIVER_IN_USE;
+       if ( printer_driver_in_use(info.info_3) ) {
+               status = WERR_PRINTER_DRIVER_IN_USE;
+               goto done;
+       }
        
        /* 
         * we have a couple of cases to consider. 
@@ -1682,24 +1990,119 @@ WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIV
        
        delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
        
-       if ( delete_files ) 
-       {
-               /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
+       /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
+               
+       if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
+               /* no idea of the correct error here */
+               status = WERR_ACCESS_DENIED;    
+               goto done;
+       }
+
+                       
+       /* also check for W32X86/3 if necessary; maybe we already have? */
+               
+       if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION)  ) {
+               if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3))) 
+               {
+                       
+                       if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
+                               /* no idea of the correct error here */
+                               free_a_printer_driver( info_win2k, 3 );
+                               status = WERR_ACCESS_DENIED;    
+                               goto done;
+                       }
+               
+                       /* if we get to here, we now have 2 driver info structures to remove */
+                       /* remove the Win2k driver first*/
                
-               if ( printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) )
-                       /* no idea of the correct error here */
-                       return WERR_ACCESS_DENIED;      
+                       status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, delete_files);
+                       free_a_printer_driver( info_win2k, 3 );
+                               
+                       /* this should not have failed---if it did, report to client */
+                               
+                       if ( !W_ERROR_IS_OK(status_win2k) )
+                               goto done;
+               }
        }
 
-       return delete_printer_driver(info.info_3, &user, version, delete_files);
+       status = delete_printer_driver(info.info_3, &user, version, delete_files);
+
+       if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
+               status = WERR_OK;
+done:
+       free_a_printer_driver( info, 3 );
+       
+       return status;
+}
+
+
+/****************************************************************************
+ Internal routine for retreiving printerdata
+ ***************************************************************************/
+
+static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer, 
+                                  char *key, char *value, uint32 *type, uint8 **data, 
+                                 uint32 *needed, uint32 in_size  )
+{
+       REGISTRY_VALUE          *val;
+       int                     size, data_len;
+       
+       if ( !(val = get_printer_data( printer->info_2, key, value)) )
+               return WERR_BADFILE;
+       
+       *type = regval_type( val );
+
+       DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
+
+       size = regval_size( val );
+       
+       /* copy the min(in_size, len) */
+       
+       if ( in_size ) {
+               data_len = (size > in_size) ? in_size : size*sizeof(uint8);
+               if ( (*data  = (uint8 *)talloc_memdup(ctx, regval_data_p(val), data_len)) == NULL )
+                       return WERR_NOMEM;
+       }
+       else
+               *data = NULL;
+
+       *needed = size;
+       
+       DEBUG(5,("get_printer_dataex: copy done\n"));
+
+       return WERR_OK;
+}
+
+/****************************************************************************
+ Internal routine for removing printerdata
+ ***************************************************************************/
+
+static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, char *key, char *value )
+{
+       delete_printer_data( printer->info_2, key, value );
+       
+       return mod_a_printer(*printer, 2);
 }
 
+/****************************************************************************
+ Internal routine for storing printerdata
+ ***************************************************************************/
+
+static WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, char *key, char *value, 
+                                  uint32 type, uint8 *data, int real_len  )
+{
+       delete_printer_data( printer->info_2, key, value );
+       
+       add_printer_data( printer->info_2, key, value, type, data, real_len );
+       
+       return mod_a_printer(*printer, 2);
+}
 
 /********************************************************************
  GetPrinterData on a printer server Handle.
 ********************************************************************/
 
-static BOOL getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
+static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
 {              
        int i;
        
@@ -1708,50 +2111,50 @@ static BOOL getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32
        if (!strcmp(value, "W3SvcInstalled")) {
                *type = 0x4;
                if((*data = (uint8 *)talloc_zero(ctx, 4*sizeof(uint8) )) == NULL)
-                       return False;
-               *needed = 0x4;                  
-               return True;
+                       return WERR_NOMEM;
+               *needed = 0x4;
+               return WERR_OK;
        }
 
        if (!strcmp(value, "BeepEnabled")) {
                *type = 0x4;
                if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
-                       return False;
+                       return WERR_NOMEM;
                SIVAL(*data, 0, 0x00);
                *needed = 0x4;                  
-               return True;
+               return WERR_OK;
        }
 
        if (!strcmp(value, "EventLog")) {
                *type = 0x4;
                if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
-                       return False;
+                       return WERR_NOMEM;
                /* formally was 0x1b */
                SIVAL(*data, 0, 0x0);
                *needed = 0x4;                  
-               return True;
+               return WERR_OK;
        }
 
        if (!strcmp(value, "NetPopup")) {
                *type = 0x4;
                if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
-                       return False;
+                       return WERR_NOMEM;
                SIVAL(*data, 0, 0x00);
                *needed = 0x4;
-               return True;
+               return WERR_OK;
        }
 
        if (!strcmp(value, "MajorVersion")) {
                *type = 0x4;
                if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
-                       return False;
+                       return WERR_NOMEM;
 #ifndef EMULATE_WIN2K_HACK /* JERRY */
                SIVAL(*data, 0, 2);
 #else
                SIVAL(*data, 0, 3);
 #endif
                *needed = 0x4;
-               return True;
+               return WERR_OK;
        }
 
        if (!strcmp(value, "DefaultSpoolDirectory")) {
@@ -1761,7 +2164,7 @@ static BOOL getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32
                *type = 0x1;                    
                *needed = 2*(strlen(string)+1);         
                if((*data  = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
-                       return False;
+                       return WERR_NOMEM;
                memset(*data, 0, (*needed > in_size) ? *needed:in_size);
                
                /* it's done by hand ready to go on the wire */
@@ -1769,7 +2172,7 @@ static BOOL getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32
                        (*data)[2*i]=string[i];
                        (*data)[2*i+1]='\0';
                }                       
-               return True;
+               return WERR_OK;
        }
 
        if (!strcmp(value, "Architecture")) {                   
@@ -1777,97 +2180,36 @@ static BOOL getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32
                *type = 0x1;                    
                *needed = 2*(strlen(string)+1); 
                if((*data  = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
-                       return False;
+                       return WERR_NOMEM;
                memset(*data, 0, (*needed > in_size) ? *needed:in_size);
                for (i=0; i<strlen(string); i++) {
                        (*data)[2*i]=string[i];
                        (*data)[2*i+1]='\0';
                }                       
-               return True;
+               return WERR_OK;
        }
        
-       return False;
+       return WERR_INVALID_PARAM;
 }
 
-/********************************************************************
- GetPrinterData on a printer Handle.
-********************************************************************/
-
-static BOOL getprinterdata_printer(pipes_struct *p, TALLOC_CTX *ctx, POLICY_HND *handle,
-                               fstring value, uint32 *type,
-                               uint8 **data, uint32 *needed, uint32 in_size )
-{
-       NT_PRINTER_INFO_LEVEL *printer = NULL;
-       int             snum=0; 
-       Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
-       REGISTRY_VALUE  *val;
-       int             size = 0;
-       
-       DEBUG(5,("getprinterdata_printer\n"));
-
-       if ( !Printer ) {
-               DEBUG(2,("getprinterdata_printer: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
-               return False;
-       }
-
-       if ( !get_printer_snum(p, handle, &snum) )
-               return False;
-
-       if ( !W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))) )
-               return False;
-
-       if ( !(val = get_printer_data( printer->info_2, SPOOL_PRINTERDATA_KEY, value)) )
-       {
-               free_a_printer(&printer, 2);
-               return False;
-       }
-       
-       *type = regval_type( val );
-
-
-       DEBUG(5,("getprinterdata_printer:allocating %d\n", in_size));
-
-       if (in_size) 
-       {
-               if ( (*data  = (uint8 *)talloc(ctx, in_size * sizeof(uint8))) == NULL )
-                       return False;
-
-               memset( *data, 0, in_size *sizeof(uint8) );
-               
-               /* copy the min(in_size, len) */
-               
-               size = regval_size( val );
-               memcpy( *data, regval_data_p(val), (size > in_size) ? in_size : size*sizeof(uint8) );
-       }
-       else
-               *data = NULL;
-
-       *needed = size;
-       
-       DEBUG(5,("getprinterdata_printer:copy done\n"));
-                       
-       
-       free_a_printer(&printer, 2);
-       return True;
-}      
-
 /********************************************************************
  * spoolss_getprinterdata
  ********************************************************************/
 
 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
 {
-       POLICY_HND *handle = &q_u->handle;
-       UNISTR2 *valuename = &q_u->valuename;
-       uint32 in_size = q_u->size;
-       uint32 *type = &r_u->type;
-       uint32 *out_size = &r_u->size;
-       uint8 **data = &r_u->data;
-       uint32 *needed = &r_u->needed;
-
-       fstring value;
-       BOOL found=False;
-       Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
+       POLICY_HND      *handle = &q_u->handle;
+       UNISTR2         *valuename = &q_u->valuename;
+       uint32          in_size = q_u->size;
+       uint32          *type = &r_u->type;
+       uint32          *out_size = &r_u->size;
+       uint8           **data = &r_u->data;
+       uint32          *needed = &r_u->needed;
+       WERROR          status;
+       fstring         value;
+       Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
+       NT_PRINTER_INFO_LEVEL   *printer = NULL;
+       int             snum = 0;
        
        /*
         * Reminder: when it's a string, the length is in BYTES
@@ -1885,45 +2227,58 @@ WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPO
        
        DEBUG(4,("_spoolss_getprinterdata\n"));
        
-       if (!Printer) {
-               if((*data=(uint8 *)talloc_zero(p->mem_ctx, 4*sizeof(uint8))) == NULL)
-                       return WERR_NOMEM;
+       if ( !Printer ) {
                DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
-               return WERR_BADFID;
+               status = WERR_BADFID;
+               goto done;
        }
        
        unistr2_to_ascii(value, valuename, sizeof(value)-1);
        
-       if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
-               found = getprinterdata_printer_server(p->mem_ctx, value, type, data, needed, *out_size);
+       if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
+               status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
        else
-               found = getprinterdata_printer(p, p->mem_ctx, handle, value, type, data, needed, *out_size);
+       {
+               if ( !get_printer_snum(p,handle, &snum) ) {
+                       status = WERR_BADFID;
+                       goto done;
+               }
 
-       if ( !found ) 
+               status = get_a_printer(&printer, 2, lp_servicename(snum));
+               if ( !W_ERROR_IS_OK(status) )
+                       goto done;
+                       
+               status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
+       }
+
+       if (*needed > *out_size)
+               status = WERR_MORE_DATA;
+       
+done:
+       if ( !W_ERROR_IS_OK(status) ) 
        {
-               DEBUG(5, ("value not found, allocating %d\n", *out_size));
+               DEBUG(5, ("error: allocating %d\n", *out_size));
                
                /* reply this param doesn't exist */
                
-               if (*out_size) {
-                       if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL)
+               if ( *out_size ) {
+                       if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL) {
+                               if ( printer ) 
+                                       free_a_printer( &printer, 2 );
                                return WERR_NOMEM;
-               } else {
+               } 
+               } 
+               else {
                        *data = NULL;
                }
-
-               /* error depends on handle type */
-
-               if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
-                       return WERR_INVALID_PARAM;
-               else 
-                       return WERR_BADFILE;
        }
        
-       if (*needed > *out_size)
-               return WERR_MORE_DATA;
-       else 
-               return WERR_OK;
+       /* cleanup & exit */
+
+       if ( printer )
+               free_a_printer( &printer, 2 );
+       
+       return status;
 }
 
 /*********************************************************
@@ -1961,6 +2316,7 @@ static BOOL spoolss_connect_to_client(struct cli_state *the_cli, char *remote_ma
        if (!attempt_netbios_session_request(the_cli, global_myname, remote_machine, &the_cli->dest_ip)) {
                DEBUG(0,("connect_to_client: machine %s rejected the NetBIOS session request.\n", 
                        remote_machine));
+               cli_shutdown(the_cli);
                return False;
        }
 
@@ -2036,7 +2392,10 @@ static BOOL srv_spoolss_replyopenprinter(char *printer, uint32 localprinter, uin
                if(!spoolss_connect_to_client(&notify_cli, unix_printer))
                        return False;
                        
-               message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message);
+               message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
+               /* Tell the connections db we're now interested in printer
+                * notify messages. */
+               register_message_flags( True, FLAG_MSG_PRINTING );
        }
 
        smb_connections++;
@@ -2436,8 +2795,8 @@ static void spoolss_notify_security_desc(int snum,
                                         NT_PRINTER_INFO_LEVEL *printer,
                                         TALLOC_CTX *mem_ctx)
 {
-       data->notify_data.data.length=0;
-       data->notify_data.data.string = NULL;
+       data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
+       data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
 }
 
 /*******************************************************************
@@ -3443,47 +3802,20 @@ static void free_dev_mode(DEVICEMODE *dev)
        SAFE_FREE(dev); 
 }
 
+
 /****************************************************************************
- Create a DEVMODE struct. Returns malloced memory.
+ Convert an NT_DEVICEMODE to a DEVICEMODE structure.  Both pointers 
+ should be valid upon entry
 ****************************************************************************/
 
-DEVICEMODE *construct_dev_mode(int snum)
+static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
 {
-       char adevice[32];
-       char aform[32];
-       NT_PRINTER_INFO_LEVEL *printer = NULL;
-       NT_DEVICEMODE *ntdevmode = NULL;
-       DEVICEMODE *devmode = NULL;
-
-       DEBUG(7,("construct_dev_mode\n"));
-       
-       DEBUGADD(8,("getting printer characteristics\n"));
-
-       if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
-               DEBUG(2,("construct_dev_mode: malloc fail.\n"));
-               return NULL;
-       }
-
-       ZERO_STRUCTP(devmode);  
-
-       if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
-               goto fail;
-
-       if (printer->info_2->devmode)
-               ntdevmode = dup_nt_devicemode(printer->info_2->devmode);
-
-       if (ntdevmode == NULL) {
-               DEBUG(5, ("BONG! There was no device mode!\n"));
-               goto fail;
-       }
-
-       DEBUGADD(8,("loading DEVICEMODE\n"));
-
-       slprintf(adevice, sizeof(adevice)-1, printer->info_2->printername);
-       init_unistr(&devmode->devicename, adevice);
+       if ( !devmode || !ntdevmode )
+               return False;
+               
+       init_unistr(&devmode->devicename, ntdevmode->devicename);
 
-       slprintf(aform, sizeof(aform)-1, ntdevmode->formname);
-       init_unistr(&devmode->formname, aform);
+       init_unistr(&devmode->formname, ntdevmode->formname);
 
        devmode->specversion      = ntdevmode->specversion;
        devmode->driverversion    = ntdevmode->driverversion;
@@ -3511,23 +3843,51 @@ DEVICEMODE *construct_dev_mode(int snum)
 
        if (ntdevmode->private != NULL) {
                if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
-                       goto fail;
+                       return False;
        }
+       
+       return True;
+}
 
-       free_nt_devicemode(&ntdevmode);
-       free_a_printer(&printer,2);
+/****************************************************************************
+ Create a DEVMODE struct. Returns malloced memory.
+****************************************************************************/
 
-       return devmode;
+DEVICEMODE *construct_dev_mode(int snum)
+{
+       NT_PRINTER_INFO_LEVEL   *printer = NULL;
+       DEVICEMODE              *devmode = NULL;
+       
+       DEBUG(7,("construct_dev_mode\n"));
+       
+       DEBUGADD(8,("getting printer characteristics\n"));
 
-  fail:
+       if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum)))) 
+               return NULL;
 
-       if (ntdevmode)
-               free_nt_devicemode(&ntdevmode);
-       if (printer)
-               free_a_printer(&printer,2);
-       free_dev_mode(devmode);
+       if ( !printer->info_2->devmode ) {
+               DEBUG(5, ("BONG! There was no device mode!\n"));
+               goto done;
+       }
+
+       if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
+               DEBUG(2,("construct_dev_mode: malloc fail.\n"));
+               goto done;
+       }
+
+       ZERO_STRUCTP(devmode);  
+       
+       DEBUGADD(8,("loading DEVICEMODE\n"));
+
+       if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
+               free_dev_mode( devmode );
+               devmode = NULL;
+       }
 
-       return NULL;
+done:
+       free_a_printer(&printer,2);
+
+       return devmode;
 }
 
 /********************************************************************
@@ -4384,7 +4744,7 @@ static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fst
  * convert an array of ascii string to a UNICODE string
  ********************************************************************/
 
-static void init_unistr_array(uint16 **uni_array, fstring *char_array, char *servername)
+static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, char *servername)
 {
        int i=0;
        int j=0;
@@ -4397,26 +4757,34 @@ static void init_unistr_array(uint16 **uni_array, fstring *char_array, char *ser
 
        while (True) 
        {
-               if (char_array == NULL)
+               if ( !char_array )
                        v = "";
-               else {
+               else 
+               {
                        v = char_array[i];
-                       if (!v) v = ""; /* hack to handle null lists */
+                       if (!v) 
+                               v = ""; /* hack to handle null lists */
                }
                
-               if ( !strlen(v) ) 
-                       break;
+               /* hack to allow this to be used in places other than when generating 
+                  the list of dependent files */
+                  
+               if ( servername )
+                       slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
+               else
+                       pstrcpy( line, v );
                        
-               slprintf(line, sizeof(line)-1, "\\\\%s%s", servername, v);
-               
                DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
                
-               if((tuary=Realloc(*uni_array, (j+strlen(line)+2)*sizeof(uint16))) == NULL) {
+               if ( (tuary=Realloc(*uni_array, (j+strlen(line)+2)*sizeof(uint16))) == NULL ) {
                        DEBUG(2,("init_unistr_array: Realloc error\n" ));
-                       return;
+                       return 0;
                } else
                        *uni_array = tuary;
                        
+               if ( !strlen(v) ) 
+                       break;
+               
                j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
                i++;
        }
@@ -4426,6 +4794,10 @@ static void init_unistr_array(uint16 **uni_array, fstring *char_array, char *ser
        }
        
        DEBUGADD(6,("last one:done\n"));
+
+       /* return size of array in uint16's */
+               
+       return j+1;
 }
 
 /********************************************************************
@@ -4444,29 +4816,29 @@ static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_IN
        init_unistr( &info->name, driver.info_3->name );        
        init_unistr( &info->architecture, driver.info_3->environment );
 
-    if (strlen(driver.info_3->driverpath)) {
-        slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);             
-        init_unistr( &info->driverpath, temp );
-    } else
-        init_unistr( &info->driverpath, "" );
+       if (strlen(driver.info_3->driverpath)) {
+               slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);              
+               init_unistr( &info->driverpath, temp );
+       } else
+               init_unistr( &info->driverpath, "" );
     
-    if (strlen(driver.info_3->datafile)) {
-        slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
-        init_unistr( &info->datafile, temp );
-    } else
-        init_unistr( &info->datafile, "" );
+       if (strlen(driver.info_3->datafile)) {
+               slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
+               init_unistr( &info->datafile, temp );
+       } else
+               init_unistr( &info->datafile, "" );
 
-    if (strlen(driver.info_3->configfile)) {
-        slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
-        init_unistr( &info->configfile, temp );        
-    } else
-        init_unistr( &info->configfile, "" );
+       if (strlen(driver.info_3->configfile)) {
+               slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
+               init_unistr( &info->configfile, temp ); 
+       } else
+               init_unistr( &info->configfile, "" );
 
-    if (strlen(driver.info_3->helpfile)) {
-        slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
-        init_unistr( &info->helpfile, temp );
-    } else
-        init_unistr( &info->helpfile, "" );
+       if (strlen(driver.info_3->helpfile)) {
+               slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
+               init_unistr( &info->helpfile, temp );
+       } else
+               init_unistr( &info->helpfile, "" );
 
        init_unistr( &info->monitorname, driver.info_3->monitorname );
        init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
@@ -4933,10 +5305,6 @@ WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, S
         * in EMF format.
         *
         * So I add checks like in NT Server ...
-        *
-        * lkclXXXX jean-francois, i love this kind of thing.  oh, well,
-        * there's a bug in NT client-side code, so we'll fix it in the
-        * server-side code. *nnnnnggggh!*
         */
        
        if (info_1->p_datatype != 0) {
@@ -4954,7 +5322,7 @@ WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, S
 
        unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
        
-       Printer->jobid = print_job_start(&user, snum, jobname);
+       Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
 
        /* An error occured in print_job_start() so return an appropriate
           NT error code. */
@@ -5004,6 +5372,13 @@ WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R
                return WERR_BADFID;
 
        (*buffer_written) = print_job_write(snum, Printer->jobid, (char *)buffer, buffer_size);
+       if (*buffer_written == -1) {
+               r_u->buffer_written = 0;
+               if (errno == ENOSPC)
+                       return WERR_NO_SPOOL_SPACE;
+               else
+                       return WERR_ACCESS_DENIED;
+       }
 
        r_u->buffer_written = q_u->buffer_size2;
 
@@ -5046,11 +5421,13 @@ static WERROR control_printer(POLICY_HND *handle, uint32 command,
                        errcode = WERR_OK;
                }
                break;
+#if 0  /* JERRY - Never called */
        case PRINTER_CONTROL_PURGE:
                if (print_queue_purge(&user, snum, &errcode)) {
                        errcode = WERR_OK;
                }
                break;
+#endif
        default:
                return WERR_UNKNOWN_LEVEL;
        }
@@ -5060,13 +5437,31 @@ static WERROR control_printer(POLICY_HND *handle, uint32 command,
 
 /********************************************************************
  * api_spoolss_abortprinter
+ * From MSDN: "Deletes printer's spool file if printer is configured
+ * for spooling"
  ********************************************************************/
 
 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
 {
-       POLICY_HND *handle = &q_u->handle;
-
-       return control_printer(handle, PRINTER_CONTROL_PURGE, p);
+       POLICY_HND      *handle = &q_u->handle;
+       Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
+       int             snum;
+       struct          current_user user;
+       WERROR          errcode = WERR_OK;
+       
+       if (!Printer) {
+               DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
+               return WERR_BADFID;
+       }
+       
+       if (!get_printer_snum(p, handle, &snum))
+               return WERR_BADFID;
+       
+       get_current_user( &user, p );   
+       
+       print_job_delete( &user, snum, Printer->jobid, &errcode );      
+       
+       return errcode;
 }
 
 /********************************************************************
@@ -5315,22 +5710,6 @@ static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
                goto done;
        }
 
-#if 0  /* JERRY */
-       
-       /*
-        * Another one of those historical misunderstandings...
-        * This is reminisent of a similar call we had in _spoolss_setprinterdata()
-        * I'm leaving it here as a reminder.  --jerry
-        */
-
-       if (nt_printer_info_level_equal(printer, old_printer)) {
-               DEBUG(3, ("update_printer: printer info has not changed\n"));
-               result = WERR_OK;
-               goto done;
-       }
-
-#endif
-
        /* Check calling user has permission to update printer description */
 
        if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
@@ -5349,49 +5728,22 @@ static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
        }
        
        /*
-        * Set the DRIVER_INIT info in the tdb; trigger on magic value for the
-        * DEVMODE.displayfrequency, which is not used for printer drivers. This
-        * requires Win32 client code (see other notes elsewhere in the code).
+        * When a *new* driver is bound to a printer, the drivername is used to
+        * lookup previously saved driver initialization info, which is then
+        * bound to the printer, simulating what happens in the Windows arch.
         */
-       if (printer->info_2->devmode &&
-               printer->info_2->devmode->displayfrequency == MAGIC_DISPLAY_FREQUENCY) 
+       if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
        {
-               DEBUG(10,("update_printer: Save printer driver init data\n"));
-               printer->info_2->devmode->displayfrequency = 0;
-               if (update_driver_init(*printer, 2)!=0) {
-                       DEBUG(10,("update_printer: error updating printer driver init DEVMODE\n"));
-                       result = WERR_ACCESS_DENIED;
-                       goto done;
-               }
-               
-               /* we need to reset all driver init data for all printers 
-                  bound to this driver */
-               
-               srv_spoolss_reset_printerdata( printer->info_2->drivername );
-               
-       } 
-       else 
-       {
-               /*
-                * When a *new* driver is bound to a printer, the drivername is used to
-                * lookup previously saved driver initialization info, which is then
-                * bound to the printer, simulating what happens in the Windows arch.
-                */
-               if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
+               if (!set_driver_init(printer, 2)) 
                {
-                       if (!set_driver_init(printer, 2)) 
-                       {
-                               DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
-                                       printer->info_2->drivername));
-                       }
-                       
-                       DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
+                       DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
                                printer->info_2->drivername));
-                               
-                       notify_printer_driver(snum, printer->info_2->drivername);
                }
+               
+               DEBUG(10,("update_printer: changing driver [%s]!  Sending event!\n",
+                       printer->info_2->drivername));
+                       
+               notify_printer_driver(snum, printer->info_2->drivername);
        }
 
        /* Update printer info */
@@ -6594,8 +6946,11 @@ static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_
         */
 
        if (!devmode)
+       {
                set_driver_init(printer, 2);
-       else {
+       }
+       else 
+       {
                /* A valid devmode was included, convert and link it
                */
                DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
@@ -6605,8 +6960,6 @@ static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_
                        return  WERR_NOMEM;
        }
 
-       set_driver_init(printer, 2);
-       
        /* write the ASCII on disk */
        err = mod_a_printer(*printer, 2);
        if (!W_ERROR_IS_OK(err)) {
@@ -6905,7 +7258,7 @@ WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, S
        uint32 idx               = q_u->index;
        uint32 in_value_len      = q_u->valuesize;
        uint32 in_data_len       = q_u->datasize;
-       uint32 *out_max_value_len= &r_u->valuesize;
+       uint32 *out_max_value_len = &r_u->valuesize;
        uint16 **out_value       = &r_u->value;
        uint32 *out_value_len    = &r_u->realvaluesize;
        uint32 *out_type         = &r_u->type;
@@ -7112,7 +7465,8 @@ WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SP
         * when connecting to a printer  --jerry
         */
 
-       if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
+       if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) 
+       {
                DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
                status = WERR_ACCESS_DENIED;
                goto done;
@@ -7122,15 +7476,27 @@ WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SP
        if (!W_ERROR_IS_OK(status))
                return status;
 
-       /* save the registry data */
-       
        unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
-       delete_printer_data( printer->info_2, SPOOL_PRINTERDATA_KEY, valuename );
-       add_printer_data( printer->info_2, SPOOL_PRINTERDATA_KEY, valuename, type, data, real_len );
-
-       /* write the **entire** printer out to disk.... :-( */  
        
-       status = mod_a_printer(*printer, 2);
+       /*
+        * When client side code sets a magic printer data key, detect it and save
+        * the current printer data and the magic key's data (its the DEVMODE) for
+        * future printer/driver initializations.
+        */
+       if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY)) 
+       {
+               /* Set devmode and printer initialization info */
+               status = save_driver_init( printer, 2, data, real_len );
+       
+               srv_spoolss_reset_printerdata( printer->info_2->drivername );
+       }
+       else 
+       {
+       status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename, 
+                                       type, data, real_len );
+               if ( W_ERROR_IS_OK(status) )
+                       status = mod_a_printer(*printer, 2);
+       }
 
 done:
        free_a_printer(&printer, 2);
@@ -7204,9 +7570,7 @@ WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_
 
        unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
 
-       status = delete_printer_data( printer->info_2, SPOOL_PRINTERDATA_KEY, valuename );
-       if ( NT_STATUS_IS_OK(status) )
-               status = mod_a_printer(*printer, 2);
+       status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
 
        free_a_printer(&printer, 2);
 
@@ -7235,40 +7599,52 @@ WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM
                DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
                return WERR_BADFID;
        }
+       
+       
+       /* forms can be added on printer of on the print server handle */
+       
+       if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
+       {
+               if (!get_printer_snum(p,handle, &snum))
+                       return WERR_BADFID;
+        
+               status = get_a_printer(&printer, 2, lp_servicename(snum));
+               if (!W_ERROR_IS_OK(status))
+                       goto done;
+       }
 
-       if (!get_printer_snum(p,handle, &snum))
-                return WERR_BADFID;
-
-       if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
+       if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
                DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
                status = WERR_ACCESS_DENIED;
                goto done;
        }
-               
+       
        /* can't add if builtin */
+       
        if (get_a_builtin_ntform(&form->name,&tmpForm)) {
-               return WERR_ALREADY_EXISTS;
+               status = WERR_ALREADY_EXISTS;
+               goto done;
        }
 
-       count=get_ntforms(&list);
-       if(!add_a_form(&list, form, &count))
-               return WERR_NOMEM;
+       count = get_ntforms(&list);
+       
+       if(!add_a_form(&list, form, &count)) {
+               status =  WERR_NOMEM;
+               goto done;
+       }
+       
        write_ntforms(&list, count);
        
        /*
-        * ChangeID must always be set
+        * ChangeID must always be set if this is a printer
         */
         
-       status = get_a_printer(&printer, 2, lp_servicename(snum));
-        if (!W_ERROR_IS_OK(status))
-               goto done;
-       
-       status = mod_a_printer(*printer, 2);
-        if (!W_ERROR_IS_OK(status))
-               goto done;
+       if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
+               status = mod_a_printer(*printer, 2);
        
 done:
-       free_a_printer(&printer, 2);
+       if ( printer )
+               free_a_printer(&printer, 2);
        SAFE_FREE(list);
 
        return status;
@@ -7283,7 +7659,6 @@ WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DE
        UNISTR2 *form_name = &q_u->name;
        nt_forms_struct tmpForm;
        int count=0;
-       WERROR ret = WERR_OK;
        nt_forms_struct *list=NULL;
        Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
        int snum;
@@ -7297,40 +7672,49 @@ WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DE
                return WERR_BADFID;
        }
 
-       if (!get_printer_snum(p, handle, &snum))
-               return WERR_BADFID;
+       /* forms can be deleted on printer of on the print server handle */
+       
+       if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
+       {
+               if (!get_printer_snum(p,handle, &snum))
+                       return WERR_BADFID;
+        
+               status = get_a_printer(&printer, 2, lp_servicename(snum));
+               if (!W_ERROR_IS_OK(status))
+                       goto done;
+       }
 
-       if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
-               DEBUG(2,("_spoolss_deleteform: denied by handle permissions\n"));
-               return WERR_ACCESS_DENIED;
+       if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
+               DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
+               status = WERR_ACCESS_DENIED;
+               goto done;
        }
 
        /* can't delete if builtin */
+       
        if (get_a_builtin_ntform(form_name,&tmpForm)) {
-               return WERR_INVALID_PARAM;
+               status = WERR_INVALID_PARAM;
+               goto done;
        }
 
        count = get_ntforms(&list);
-       if(!delete_a_form(&list, form_name, &count, &ret))
-               return WERR_INVALID_PARAM;
+       
+       if ( !delete_a_form(&list, form_name, &count, &status ))
+               goto done;
 
        /*
-        * ChangeID must always be set
+        * ChangeID must always be set if this is a printer
         */
         
-       status = get_a_printer(&printer, 2, lp_servicename(snum));
-        if (!W_ERROR_IS_OK(status))
-               goto done;
-       
-       status = mod_a_printer(*printer, 2);
-        if (!W_ERROR_IS_OK(status))
-               goto done;
+       if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
+               status = mod_a_printer(*printer, 2);
        
 done:
-       free_a_printer(&printer, 2);
+       if ( printer )
+               free_a_printer(&printer, 2);
        SAFE_FREE(list);
 
-       return ret;
+       return status;
 }
 
 /****************************************************************************
@@ -7356,40 +7740,48 @@ WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *
                return WERR_BADFID;
        }
 
-       if (!get_printer_snum(p, handle, &snum))
-               return WERR_BADFID;
+       /* forms can be modified on printer of on the print server handle */
+       
+       if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
+       {
+               if (!get_printer_snum(p,handle, &snum))
+                       return WERR_BADFID;
+        
+               status = get_a_printer(&printer, 2, lp_servicename(snum));
+               if (!W_ERROR_IS_OK(status))
+                       goto done;
+       }
 
-       if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
+       if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
                DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
-               return WERR_ACCESS_DENIED;
+               status = WERR_ACCESS_DENIED;
+               goto done;
        }
 
        /* can't set if builtin */
        if (get_a_builtin_ntform(&form->name,&tmpForm)) {
-               return WERR_INVALID_PARAM;
+               status = WERR_INVALID_PARAM;
+               goto done;
        }
 
-       count=get_ntforms(&list);
+       count = get_ntforms(&list);
        update_a_form(&list, form, count);
        write_ntforms(&list, count);
 
        /*
-        * ChangeID must always be set
+        * ChangeID must always be set if this is a printer
         */
         
-       status = get_a_printer(&printer, 2, lp_servicename(snum));
-        if (!W_ERROR_IS_OK(status))
-               goto done;
+       if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
+               status = mod_a_printer(*printer, 2);
        
-       status = mod_a_printer(*printer, 2);
-        if (!W_ERROR_IS_OK(status))
-               goto done;
        
 done:
-       free_a_printer(&printer, 2);
+       if ( printer )
+               free_a_printer(&printer, 2);
        SAFE_FREE(list);
 
-       return WERR_OK;
+       return status;
 }
 
 /****************************************************************************
@@ -7638,7 +8030,7 @@ static WERROR getjob_level_1(print_queue_struct *queue, int count, int snum, uin
                return WERR_NOMEM;
        }
                
-       for (i=0; i<count && found==False; i++) {
+       for (i=0; i<count && found==False; i++) { 
                if (queue[i].job==(int)jobid)
                        found=True;
        }
@@ -7652,8 +8044,6 @@ static WERROR getjob_level_1(print_queue_struct *queue, int count, int snum, uin
        
        fill_job_info_1(info_1, &(queue[i-1]), i, snum);
        
-       SAFE_FREE(queue);
-       
        *needed += spoolss_size_job_info_1(info_1);
 
        if (!alloc_buffer_size(buffer, *needed)) {
@@ -7676,12 +8066,13 @@ static WERROR getjob_level_1(print_queue_struct *queue, int count, int snum, uin
 
 static WERROR getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
 {
-       int i=0;
-       BOOL found=False;
-       JOB_INFO_2 *info_2;
+       int             i = 0;
+       BOOL            found = False;
+       JOB_INFO_2      *info_2;
        NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
-       WERROR ret;
-       DEVICEMODE *devmode = NULL;
+       WERROR          ret;
+       DEVICEMODE      *devmode = NULL;
+       NT_DEVICEMODE   *nt_devmode = NULL;
 
        info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
 
@@ -7692,12 +8083,14 @@ static WERROR getjob_level_2(print_queue_struct *queue, int count, int snum, uin
                goto done;
        }
 
-       for (i=0; i<count && found==False; i++) {
-               if (queue[i].job==(int)jobid)
-                       found=True;
+       for ( i=0; i<count && found==False; i++ ) 
+       {
+               if (queue[i].job == (int)jobid)
+                       found = True;
        }
        
-       if (found==False) {
+       if ( !found ) 
+       {
                /* NT treats not found as bad param... yet another bad
                   choice */
                ret = WERR_INVALID_PARAM;
@@ -7707,7 +8100,22 @@ static WERROR getjob_level_2(print_queue_struct *queue, int count, int snum, uin
        ret = get_a_printer(&ntprinter, 2, lp_servicename(snum));
        if (!W_ERROR_IS_OK(ret))
                goto done;
-       if (construct_dev_mode(snum) == NULL) {
+       
+       /* 
+        * if the print job does not have a DEVMODE associated with it, 
+        * just use the one for the printer 
+        */
+        
+       if ( !(nt_devmode=print_job_devmode( snum, jobid )) )
+               devmode = construct_dev_mode(snum);
+       else {
+               if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) != NULL) {
+                       ZERO_STRUCTP( devmode );
+                       convert_nt_devicemode( devmode, nt_devmode );
+               }
+       }
+       
+       if ( !devmode ) {
                ret = WERR_NOMEM;
                goto done;
        }
@@ -7733,7 +8141,6 @@ static WERROR getjob_level_2(print_queue_struct *queue, int count, int snum, uin
  done:
        /* Cleanup allocated memory */
 
-       SAFE_FREE(queue);
        free_job_info_2(info_2);        /* Also frees devmode */
        SAFE_FREE(info_2);
        free_a_printer(&ntprinter, 2);
@@ -7752,10 +8159,11 @@ WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_
        NEW_BUFFER *buffer = NULL;
        uint32 offered = q_u->offered;
        uint32 *needed = &r_u->needed;
+       WERROR          wstatus = WERR_OK;
 
        int snum;
        int count;
-       print_queue_struct *queue=NULL;
+       print_queue_struct      *queue = NULL;
        print_status_struct prt_status;
 
        /* that's an [in out] buffer */
@@ -7764,7 +8172,7 @@ WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_
 
        DEBUG(5,("spoolss_getjob\n"));
        
-       *needed=0;
+       *needed = 0;
        
        if (!get_printer_snum(p, handle, &snum))
                return WERR_BADFID;
@@ -7774,19 +8182,29 @@ WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_
        DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
                     count, prt_status.status, prt_status.message));
                
-       switch (level) {
+       switch ( level ) {
        case 1:
-               return getjob_level_1(queue, count, snum, jobid, buffer, offered, needed);
+                       wstatus = getjob_level_1(queue, count, snum, jobid, 
+                               buffer, offered, needed);
+                       break;
        case 2:
-               return getjob_level_2(queue, count, snum, jobid, buffer, offered, needed);
+                       wstatus = getjob_level_2(queue, count, snum, jobid, 
+                               buffer, offered, needed);
+                       break;
        default:
-               SAFE_FREE(queue);
-               return WERR_UNKNOWN_LEVEL;
+                       wstatus = WERR_UNKNOWN_LEVEL;
+                       break;
        }
+       
+       SAFE_FREE(queue);
+       return wstatus;
 }
 
 /********************************************************************
- * spoolss_getprinterdataex
+ spoolss_getprinterdataex
+ From MSDN documentation of GetPrinterDataEx: pass request
+ to GetPrinterData if key is "PrinterDriverData".
  ********************************************************************/
 
 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
@@ -7797,112 +8215,181 @@ WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u,
        uint32          *out_size = &r_u->size;
        uint8           **data = &r_u->data;
        uint32          *needed = &r_u->needed;
-
-       fstring         key, value;
+       fstring         keyname, valuename;
+       
        Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
-       BOOL            found = False;
+       
+       NT_PRINTER_INFO_LEVEL   *printer = NULL;
+       int                     snum = 0;
+       WERROR                  status = WERR_OK;
 
        DEBUG(4,("_spoolss_getprinterdataex\n"));
 
-        unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
-        unistr2_to_ascii(value, &q_u->valuename, sizeof(value) - 1);
+        unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
+        unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
+       
+       DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n", 
+               keyname, valuename));
 
        /* in case of problem, return some default values */
-       *needed=0;
-       *type=0;
-       *out_size=0;
+       
+       *needed   = 0;
+       *type     = 0;
+       *out_size = in_size;
 
-               
        if (!Printer) {
-               if((*data=(uint8 *)talloc_zero(p->mem_ctx, 4*sizeof(uint8))) == NULL)
-                       return WERR_NOMEM;
-               DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
-               return WERR_BADFID;
+               DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
+               status = WERR_BADFID;
+               goto done;
        }
 
-               
        /* Is the handle to a printer or to the server? */
 
-       if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
-       {
+       if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
                DEBUG(10,("_spoolss_getprinterdatex: Not implemented for server handles yet\n"));
-               return WERR_INVALID_PARAM;
+               status = WERR_INVALID_PARAM;
+               goto done;
        }
-       else
-       {
-               /* 
-                * From MSDN documentation of GetPrinterDataEx: pass request
-                * to GetPrinterData if key is "PrinterDriverData". This is 
-                * the only key we really support. Other keys to implement:
-                * (a) DsDriver
-                * (b) DsSpooler
-                * (c) PnPData
-                * (d) DsUser
-                */
-          
-               if (strcmp(key, SPOOL_PRINTERDATA_KEY) != 0)
-                       return WERR_BADFILE;
+       
+       if ( !get_printer_snum(p,handle, &snum) )
+               return WERR_BADFID;
 
-               DEBUG(10, ("_spoolss_getprinterdataex: pass me to getprinterdata\n"));
-               found = getprinterdata_printer(p, p->mem_ctx, handle, value, 
-                       type, data, needed, in_size);
-               
+       status = get_a_printer(&printer, 2, lp_servicename(snum));
+       if ( !W_ERROR_IS_OK(status) )
+               goto done;
+
+       /* check to see if the keyname is valid */
+       if ( !strlen(keyname) ) {
+               status = WERR_INVALID_PARAM;
+               goto done;
        }
-        
-       if (!found) {
-               DEBUG(5, ("value not found, allocating %d\n", *out_size));
+       
+       if ( lookup_printerkey( &printer->info_2->data, keyname ) == -1 ) {
+               DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
+               free_a_printer( &printer, 2 );
+               status = WERR_BADFILE;
+               goto done;
+       }
+       
+       /* When given a new keyname, we should just create it */
+
+       status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
+       
+       if (*needed > *out_size)
+               status = WERR_MORE_DATA;
+
+done:
+       if ( !W_ERROR_IS_OK(status) ) 
+       {
+               DEBUG(5, ("error: allocating %d\n", *out_size));
                
                /* reply this param doesn't exist */
-               if (*out_size) {
-                       if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL)
-                               return WERR_NOMEM;
-               } else {
+               
+               if ( *out_size ) 
+               {
+                       if( (*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
+                               status = WERR_NOMEM;
+                               goto done;
+                       }
+               } 
+               else {
                        *data = NULL;
-               }
-
-               return WERR_INVALID_PARAM;
+       }
        }
        
-       if (*needed > *out_size)
-               return WERR_MORE_DATA;
-       else
-               return WERR_OK;
+       if ( printer )
+       free_a_printer( &printer, 2 );
+       
+       return status;
 }
 
 /********************************************************************
- * spoolss_setprinterdata
+ * spoolss_setprinterdataex
  ********************************************************************/
 
 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
 {
-       SPOOL_Q_SETPRINTERDATA q_u_local;
-       SPOOL_R_SETPRINTERDATA r_u_local;
-        fstring key;
+       POLICY_HND              *handle = &q_u->handle; 
+       uint32                  type = q_u->type;
+       uint8                   *data = q_u->data;
+       uint32                  real_len = q_u->real_len;
 
+       NT_PRINTER_INFO_LEVEL   *printer = NULL;
+       int                     snum = 0;
+       WERROR                  status = WERR_OK;
+       Printer_entry           *Printer = find_printer_index_by_hnd(p, handle);
+       fstring                 valuename;
+       fstring                 keyname;
+       char                    *oid_string;
+       
        DEBUG(4,("_spoolss_setprinterdataex\n"));
 
         /* From MSDN documentation of SetPrinterDataEx: pass request to
            SetPrinterData if key is "PrinterDriverData" */
 
-        unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
+       if (!Printer) {
+               DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
+               return WERR_BADFID;
+       }
 
-        if (strcmp(key, SPOOL_PRINTERDATA_KEY) != 0)
-               return WERR_INVALID_PARAM;
-               
-       ZERO_STRUCT(q_u_local); 
-       ZERO_STRUCT(r_u_local); 
-       
-       /* make a copy to call _spoolss_setprinterdata() */
-
-       memcpy(&q_u_local.handle, &q_u->handle, sizeof(POLICY_HND));
-       copy_unistr2(&q_u_local.value, &q_u->value);
-       q_u_local.type = q_u->type;
-       q_u_local.max_len = q_u->max_len;
-       q_u_local.data = q_u->data;
-       q_u_local.real_len = q_u->real_len;
-       q_u_local.numeric_data = q_u->numeric_data;
+       if ( !get_printer_snum(p,handle, &snum) )
+               return WERR_BADFID;
+
+       /* 
+        * Access check : NT returns "access denied" if you make a 
+        * SetPrinterData call without the necessary privildge.
+        * we were originally returning OK if nothing changed
+        * which made Win2k issue **a lot** of SetPrinterData
+        * when connecting to a printer  --jerry
+        */
+
+       if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) 
+       {
+               DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
+               return WERR_ACCESS_DENIED;
+       }
+
+       status = get_a_printer(&printer, 2, lp_servicename(snum));
+       if (!W_ERROR_IS_OK(status))
+               return status;
+
+        unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
+        unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
+       
+       /* check for OID in valuename */
+       
+       if ( (oid_string = strchr( valuename, ',' )) != NULL )
+       {
+               *oid_string = '\0';
+               oid_string++;
+       }
+
+       /* save the registry data */
+       
+       status = set_printer_dataex( printer, keyname, valuename, type, data, real_len ); 
+       
+       /* save the OID if one was specified and the previous set call succeeded */
+       
+       if ( W_ERROR_IS_OK(status) && oid_string )
+       {
+
+               fstrcat( keyname, "\\" );
+               fstrcat( keyname, SPOOL_OID_KEY );
                
-       return _spoolss_setprinterdata(p, &q_u_local, &r_u_local);
+               /* 
+                * I'm not checking the status here on purpose.  Don't know 
+                * if this is right, but I'm returning the status from the 
+                * previous set_printer_dataex() call.  I have no idea if 
+                * this is right.    --jerry
+                */
+                
+               set_printer_dataex( printer, keyname, valuename, 
+                                   REG_SZ, (void*)oid_string, strlen(oid_string)+1 );          
+       }
+       
+       free_a_printer(&printer, 2);
+
+       return status;
 }
 
 
@@ -7912,26 +8399,44 @@ WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u,
 
 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
 {
-       SPOOL_Q_DELETEPRINTERDATA q_u_local;
-       SPOOL_R_DELETEPRINTERDATA r_u_local;
-       fstring key;
-       
-        /* From MSDN documentation of SetPrinterDataEx: pass request to
-           SetPrinterData if key is "PrinterDriverData" */
-
-        unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
+       POLICY_HND      *handle = &q_u->handle;
+       UNISTR2         *value = &q_u->valuename;
+       UNISTR2         *key = &q_u->keyname;
 
-        if (strcmp(key, SPOOL_PRINTERDATA_KEY) != 0)
-               return WERR_INVALID_PARAM;
+       NT_PRINTER_INFO_LEVEL   *printer = NULL;
+       int             snum=0;
+       WERROR          status = WERR_OK;
+       Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
+       pstring         valuename, keyname;
        
-       memcpy(&q_u_local.handle, &q_u->handle, sizeof(POLICY_HND));
-       copy_unistr2(&q_u_local.valuename, &q_u->valuename);
+       DEBUG(5,("spoolss_deleteprinterdataex\n"));
        
-       return _spoolss_deleteprinterdata( p, &q_u_local, &r_u_local );
-}
+       if (!Printer) {
+               DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
+               return WERR_BADFID;
+       }
+
+       if (!get_printer_snum(p, handle, &snum))
+               return WERR_BADFID;
+
+       if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
+               DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
+               return WERR_ACCESS_DENIED;
+       }
+
+       status = get_a_printer(&printer, 2, lp_servicename(snum));
+       if (!W_ERROR_IS_OK(status))
+               return status;
+
+       unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
+       unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
 
+       status = delete_printer_dataex( printer, keyname, valuename );
 
+       free_a_printer(&printer, 2);
 
+       return status;
+}
 
 /********************************************************************
  * spoolss_enumprinterkey
@@ -7940,73 +8445,69 @@ WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX
 
 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
 {
-       fstring key;
-       uint16  *enumkeys = NULL;
-       char*   ptr = NULL;
-       int     i;
-       int     printerkey_len = strlen(SPOOL_PRINTERDATA_KEY)+1;       
-
+       fstring         key;
+       fstring         *keynames = NULL;
+       uint16          *enumkeys = NULL;
+       int             num_keys;
+       int             printerkey_len;
+       POLICY_HND      *handle = &q_u->handle;
+       Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
+       NT_PRINTER_DATA *data;
+       NT_PRINTER_INFO_LEVEL   *printer = NULL;
+       int             snum = 0;
+       WERROR          status = WERR_BADFILE;
+       
+       
        DEBUG(4,("_spoolss_enumprinterkey\n"));
 
-       unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
+       if (!Printer) {
+               DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
+               return WERR_BADFID;
+       }
 
-       /* 
-        * we only support enumating all keys (key == "")
-        * Of course, the only key we support is the "PrinterDriverData" 
-        * key
-        */
+       if ( !get_printer_snum(p,handle, &snum) )
+               return WERR_BADFID;
 
-       if ( !strlen( key ) )
-       {
-               r_u->needed = printerkey_len*2;
+       status = get_a_printer(&printer, 2, lp_servicename(snum));
+       if (!W_ERROR_IS_OK(status))
+               return status;
                
-               if ( q_u->size < r_u->needed )
-                       return WERR_MORE_DATA;
+       /* get the list of subkey names */
        
-               if ( !(enumkeys = talloc( p->mem_ctx, printerkey_len*2 )) ) {
-                       DEBUG(0,("_spoolss_enumprinterkey: talloc() failed for [%d] bytes!\n",
-                               printerkey_len));
-                       return WERR_NOMEM;
-               }
-               
-               ptr = SPOOL_PRINTERDATA_KEY;
-               for ( i=0; i<(printerkey_len-1); i++ )
-               {
-                       enumkeys[i] = (uint16)(*ptr);
-                       ptr++;
-               }
+       unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
+       data = &printer->info_2->data;
 
-               /* tag of '\0's */
-               
-               enumkeys[i] = 0x0;
-       
-               if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys))
-                       return WERR_BADFILE;
-                       
-               return WERR_OK;
+       num_keys = get_printer_subkeys( data, key, &keynames );
+
+       if ( num_keys == -1 ) {
+               status = WERR_BADFILE;
+               goto done;
        }
-       
-       /* The "PrinterDriverData" key should have no subkeys */
-       if ( strcmp(key, SPOOL_PRINTERDATA_KEY) == 0 )
-       {
-               uint16  dummy_key = 0;
-               
-               r_u->needed = 2;
-               
-               if (q_u->size < r_u->needed)
-                       return WERR_MORE_DATA;
-                       
-               if ( !make_spoolss_buffer5(p->mem_ctx, &r_u->keys, 1, &dummy_key ) )
-                       return WERR_BADFILE;
-                       
-               return WERR_OK;
+
+       printerkey_len = init_unistr_array( &enumkeys,  keynames, NULL );
+
+       r_u->needed = printerkey_len*2;
+
+       if ( q_u->size < r_u->needed ) {
+               status = WERR_MORE_DATA;
+               goto done;
        }
-       
 
-       /* The return value for an unknown key is documented in MSDN
-          EnumPrinterKey description */
-          
-        return WERR_BADFILE;
+       if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
+               status = WERR_NOMEM;
+               goto done;
+       }
+                       
+       status = WERR_OK;
+
+       if ( q_u->size < r_u->needed ) 
+               status = WERR_MORE_DATA;
+
+done:
+       free_a_printer( &printer, 2 );
+       SAFE_FREE( keynames );
+       
+        return status;
 }
 
 /********************************************************************
@@ -8015,25 +8516,49 @@ WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPO
 
 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
 {
-       Printer_entry   *Printer = find_printer_index_by_hnd(p, &q_u->handle);
-       fstring key;
+       POLICY_HND              *handle = &q_u->handle;
+       Printer_entry           *Printer = find_printer_index_by_hnd(p, &q_u->handle);
+       fstring                 key;
+       NT_PRINTER_INFO_LEVEL   *printer = NULL;
+       int                     snum=0;
+       WERROR                  status;
+       
+       DEBUG(5,("spoolss_deleteprinterkey\n"));
        
        if (!Printer) {
-               DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(&q_u->handle)));
+               DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
                return WERR_BADFID;
        }
+
+       /* if keyname == NULL, return error */
+       
+       if ( !q_u->keyname.buffer )
+               return WERR_INVALID_PARAM;
+               
+       if (!get_printer_snum(p, handle, &snum))
+               return WERR_BADFID;
+
+       if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
+               DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
+               return WERR_ACCESS_DENIED;
+       }
+
+       status = get_a_printer(&printer, 2, lp_servicename(snum));
+       if (!W_ERROR_IS_OK(status))
+               return status;
+       
+       /* delete the key and all subneys */
        
         unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
+       status = delete_all_printer_data( printer->info_2, key );       
 
-        if (strcmp(key, SPOOL_PRINTERDATA_KEY) != 0)
-               return WERR_INVALID_PARAM;
-               
-       /* 
-        * this is what 2k returns when you try to delete the "PrinterDriverData"
-        * key
-        */
-        
-       return WERR_ACCESS_DENIED;      
+       if ( W_ERROR_IS_OK(status) )
+               status = mod_a_printer(*printer, 2);
+       
+       free_a_printer( &printer, 2 );
+       
+       return status;
 }
 
 
@@ -8068,7 +8593,6 @@ WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_
                return WERR_BADFID;
        }
 
-               
        /* first get the printer off of disk */
        
        if (!get_printer_snum(p,handle, &snum))
index 5c1038949b522a4c78641d59ef8b095d2d0a07c6..69945b50b8485b6823c7d63975349f094be3ffa6 100644 (file)
@@ -338,10 +338,10 @@ BOOL share_access_check(connection_struct *conn, int snum, user_struct *vuser, u
        if (!psd)
                goto out;
 
-       if (vuser)
-               token = vuser->nt_user_token;
-       else
+       if (conn->nt_user_token)
                token = conn->nt_user_token;
+       else 
+               token = vuser->nt_user_token;
 
        ret = se_access_check(psd, token, desired_access, &granted, &status);
 
index 194e4981224d92ac97ccde78c69d59222f917613..ed6816065883542c5c61e41520eb84f85fc9a008 100644 (file)
@@ -86,15 +86,8 @@ static NTSTATUS cmd_lsa_query_info_policy(struct cli_state *cli,
                printf("forest name is %s\n", forest_name);
 
        if (info_class == 12) {
-               int i;
-               uint32 *data1 = (uint32 *) dom_guid.info;
-               uint16 *data2 = (uint16 *) &dom_guid.info[4];
-               uint16 *data3 = (uint16 *) &dom_guid.info[6];
-               printf("domain GUID is %08x-%04x-%04x", *data1,*data2,*data3);
-               printf("-%02x%02x-", dom_guid.info[8], dom_guid.info[9]);
-               for (i=10;i<GUID_SIZE;i++)
-                       printf("%02x", dom_guid.info[i]);
-               printf("\n");
+               printf("domain GUID is ");
+               print_guid(&dom_guid);
        }
  done:
        return result;
index c3bc9e5e130524b7bfa3974b43903897c884cf09..98ba92e5a3f528d5170f19f7693d5b9dfbe2ce08 100644 (file)
@@ -125,11 +125,10 @@ static void display_sam_sync(uint32 num_deltas, SAM_DELTA_HDR *hdr_deltas,
                                           group->rids[j], group->attribs[j]);
                         break;
                 }
-                case SAM_DELTA_SAM_STAMP: {
-                        SAM_DELTA_STAMP *stamp = &deltas[i].stamp;
+                case SAM_DELTA_MODIFIED_COUNT: {
+                        SAM_DELTA_MOD_COUNT *mc = &deltas[i].mod_count;
 
-                        printf("sam sequence update: 0x%04x\n",
-                                  stamp->seqnum);
+                        printf("sam sequence update: 0x%04x\n", mc->seqnum);
                         break;
                 }                                  
                 default:
@@ -152,6 +151,7 @@ static NTSTATUS cmd_netlogon_sam_sync(struct cli_state *cli,
         SAM_DELTA_HDR *hdr_deltas;
         SAM_DELTA_CTR *deltas;
        DOM_CRED ret_creds;
+       uint32 neg_flags = 0x000001ff;
 
         if (argc > 2) {
                 fprintf(stderr, "Usage: %s [database_id]\n", argv[0]);
@@ -174,8 +174,7 @@ static NTSTATUS cmd_netlogon_sam_sync(struct cli_state *cli,
                goto done;
        }        
 
-        result = cli_nt_setup_creds(cli, (lp_server_role() == ROLE_DOMAIN_MEMBER) ?
-                                       SEC_CHAN_WKSTA : SEC_CHAN_BDC, trust_passwd);
+        result = cli_nt_setup_creds(cli, get_sec_chan(), trust_passwd, &neg_flags, 2);
 
         if (!NT_STATUS_IS_OK(result)) {
                 fprintf(stderr, "Error initialising session creds\n");
@@ -188,7 +187,7 @@ static NTSTATUS cmd_netlogon_sam_sync(struct cli_state *cli,
         /* Synchronise sam database */
 
        result = cli_netlogon_sam_sync(cli, mem_ctx, &ret_creds, database_id,
-                                      &num_deltas, &hdr_deltas, &deltas);
+                                      0, &num_deltas, &hdr_deltas, &deltas);
 
        if (!NT_STATUS_IS_OK(result))
                goto done;
@@ -213,6 +212,7 @@ static NTSTATUS cmd_netlogon_sam_deltas(struct cli_state *cli,
         SAM_DELTA_HDR *hdr_deltas;
         SAM_DELTA_CTR *deltas;
         UINT64_S seqnum;
+       uint32 neg_flags = 0x000001ff;
 
         if (argc != 3) {
                 fprintf(stderr, "Usage: %s database_id seqnum\n", argv[0]);
@@ -238,8 +238,7 @@ static NTSTATUS cmd_netlogon_sam_deltas(struct cli_state *cli,
                goto done;
        }        
 
-        result = cli_nt_setup_creds(cli, (lp_server_role() == ROLE_DOMAIN_MEMBER) ?
-                                       SEC_CHAN_WKSTA : SEC_CHAN_BDC, trust_passwd);
+        result = cli_nt_setup_creds(cli, get_sec_chan(), trust_passwd, &neg_flags, 2);
 
         if (!NT_STATUS_IS_OK(result)) {
                 fprintf(stderr, "Error initialising session creds\n");
@@ -273,12 +272,15 @@ static NTSTATUS cmd_netlogon_sam_logon(struct cli_state *cli,
         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
         int logon_type = NET_LOGON_TYPE;
         char *username, *password;
+       uint32 neg_flags = 0x000001ff;
+       int auth_level = 2;
 
         /* Check arguments */
 
-        if (argc < 3 || argc > 4) {
+        if (argc < 3 || argc > 6) {
                 fprintf(stderr, "Usage: samlogon <username> <password> "
-                        "[logon_type]\n");
+                        "[logon_type] [neg flags] [auth level (2 or 3)]\n"
+                       "neg flags being 0x000001ff or 0x6007ffff\n");
                 return NT_STATUS_OK;
         }
 
@@ -288,6 +290,12 @@ static NTSTATUS cmd_netlogon_sam_logon(struct cli_state *cli,
         if (argc == 4)
                 sscanf(argv[3], "%i", &logon_type);
 
+       if (argc == 5)
+                sscanf(argv[4], "%i", &neg_flags);
+
+       if (argc == 6)
+                sscanf(argv[5], "%i", &auth_level);
+
         /* Authenticate ourselves with the domain controller */
 
         if (!secrets_init()) {
@@ -295,14 +303,12 @@ static NTSTATUS cmd_netlogon_sam_logon(struct cli_state *cli,
                 return result;
         }
 
-       if (!secrets_fetch_trust_account_password(lp_workgroup(), trust_passwd,
-                                                  NULL)) {
+       if (!secrets_fetch_trust_account_password(lp_workgroup(), trust_passwd, NULL)) {
                fprintf(stderr, "could not fetch trust account password\n");
                goto done;
        }        
 
-        result = cli_nt_setup_creds(cli, (lp_server_role() == ROLE_DOMAIN_MEMBER) ?
-                                       SEC_CHAN_WKSTA : SEC_CHAN_BDC, trust_passwd);
+        result = cli_nt_setup_creds(cli, get_sec_chan(), trust_passwd, &neg_flags, auth_level);
 
         if (!NT_STATUS_IS_OK(result)) {
                 fprintf(stderr, "Error initialising session creds\n");
@@ -311,8 +317,7 @@ static NTSTATUS cmd_netlogon_sam_logon(struct cli_state *cli,
 
         /* Perform the sam logon */
 
-        result = cli_netlogon_sam_logon(cli, mem_ctx, username, password,
-                                        logon_type);
+        result = cli_netlogon_sam_logon(cli, mem_ctx, username, password, logon_type);
 
        if (!NT_STATUS_IS_OK(result))
                goto done;
index 22e2db41f313e156e57355eeeeecddb6c2bca9b1..15648e4d1b5026310ad0f88d1ecf81d2e5616328 100644 (file)
@@ -313,15 +313,22 @@ static NTSTATUS cmd_spoolss_enum_printers(struct cli_state *cli,
        uint32                  info_level = 1;
        PRINTER_INFO_CTR        ctr;
        uint32                  i = 0, num_printers, needed;
+       fstring name;
 
-       if (argc > 2
+       if (argc > 3
        {
-               printf("Usage: %s [level]\n", argv[0]);
+               printf("Usage: %s [level] [name]\n", argv[0]);
                return NT_STATUS_OK;
        }
 
-       if (argc == 2) {
+       if (argc == 2)
                info_level = atoi(argv[1]);
+
+       if (argc == 3)
+               fstrcpy(name, argv[2]);
+       else {
+               slprintf(name, sizeof(name)-1, "\\\\%s", cli->desthost);
+               strupper(name);
        }
 
        /* Enumerate printers  -- Should we enumerate types other 
@@ -330,12 +337,12 @@ static NTSTATUS cmd_spoolss_enum_printers(struct cli_state *cli,
        ZERO_STRUCT(ctr);
 
        result = cli_spoolss_enum_printers(
-               cli, mem_ctx, 0, &needed, PRINTER_ENUM_LOCAL, 
+               cli, mem_ctx, 0, &needed, name, PRINTER_ENUM_LOCAL, 
                info_level, &num_printers, &ctr);
 
        if (W_ERROR_V(result) == ERRinsufficientbuffer)
                result = cli_spoolss_enum_printers(
-                       cli, mem_ctx, needed, NULL, PRINTER_ENUM_LOCAL, 
+                       cli, mem_ctx, needed, NULL, name, PRINTER_ENUM_LOCAL, 
                        info_level, &num_printers, &ctr);
 
        if (W_ERROR_IS_OK(result)) {
@@ -1613,7 +1620,8 @@ static NTSTATUS cmd_spoolss_setprinterdata(struct cli_state *cli,
        POLICY_HND pol;
        BOOL opened_hnd = False;
        PRINTER_INFO_CTR ctr;
-       PRINTER_INFO_0 *info = NULL;
+       PRINTER_INFO_0 info;
+       REGISTRY_VALUE value;
 
        /* parse the command arguements */
        if (argc != 4) {
@@ -1635,6 +1643,8 @@ static NTSTATUS cmd_spoolss_setprinterdata(struct cli_state *cli,
 
        opened_hnd = True;
 
+       ctr.printers_0 = &info;
+
         result = cli_spoolss_getprinter(cli, mem_ctx, 0, &needed,
                                         &pol, 0, &ctr);
 
@@ -1645,13 +1655,16 @@ static NTSTATUS cmd_spoolss_setprinterdata(struct cli_state *cli,
                 goto done;
                
        printf("%s\n", timestring(True));
-       printf("\tchange_id (before set)\t:[0x%x]\n", info->change_id);
+       printf("\tchange_id (before set)\t:[0x%x]\n", info.change_id);
 
        /* Set the printer data */
        
-       result = cli_spoolss_setprinterdata(
-               cli, mem_ctx, &pol, argv[2], REG_SZ, argv[3], 
-               strlen(argv[3]) + 1);
+       fstrcpy(value.valuename, argv[2]);
+       value.type = REG_SZ;
+       value.size = strlen(argv[3]) + 1;
+       value.data_p = talloc_memdup(mem_ctx, argv[3], value.size);
+
+       result = cli_spoolss_setprinterdata(cli, mem_ctx, &pol, &value);
                
        if (!W_ERROR_IS_OK(result)) {
                printf ("Unable to set [%s=%s]!\n", argv[2], argv[3]);
@@ -1668,7 +1681,7 @@ static NTSTATUS cmd_spoolss_setprinterdata(struct cli_state *cli,
                 goto done;
                
        printf("%s\n", timestring(True));
-       printf("\tchange_id (after set)\t:[0x%x]\n", info->change_id);
+       printf("\tchange_id (after set)\t:[0x%x]\n", info.change_id);
 
 done:
        /* cleanup */
@@ -1778,10 +1791,10 @@ static NTSTATUS cmd_spoolss_enum_jobs(struct cli_state *cli,
        for (i = 0; i < num_jobs; i++) {
                switch(level) {
                case 1:
-                       display_job_info_1(ctr.job.job_info_1[i]);
+                       display_job_info_1(&ctr.job.job_info_1[i]);
                        break;
                case 2:
-                       display_job_info_2(ctr.job.job_info_2[i]);
+                       display_job_info_2(&ctr.job.job_info_2[i]);
                        break;
                default:
                        d_printf("unknown info level %d\n", level);
index 2d86fb1d3d0668ba90999cf8c76db0d65e6906d4..880fdc599a8b2e4ca9c4e488ea76e271d4d8635c 100644 (file)
@@ -573,24 +573,6 @@ static NTSTATUS process_cmd(struct cli_state *cli, char *cmd)
 }
 
 
-/* Print usage information */
-static void usage(void)
-{
-       printf("Usage: rpcclient [options] server\n");
-
-       printf("\t-A or --authfile authfile          File containing user credentials\n");
-       printf("\t-c or --command \"command string\"   Execute semicolon separated cmds\n");
-       printf("\t-d or --debug debuglevel           Set the debuglevel\n");
-       printf("\t-l or --logfile logfile            Logfile to use instead of stdout\n");
-       printf("\t-h or --help                       Print this help message.\n");
-       printf("\t-N or --nopass                     Don't ask for a password\n");
-       printf("\t-s or --conf configfile            Specify an alternative config file\n");
-       printf("\t-U or --user username              Set the network username\n");
-       printf("\t-W or --workgroup domain           Set the domain name for user account\n");
-       printf("\t-I or --dest-ip ip                 Specify destination IP address\n");
-       printf("\n");
-}
-
 /* Main function */
 
  int main(int argc, char *argv[])
@@ -599,7 +581,6 @@ static void usage(void)
        static int              got_pass = 0;
        BOOL                    interactive = True;
        int                     opt;
-       int                     olddebug;
        static char             *cmdstr = "";
        const char *server;
        struct cli_state        *cli;
@@ -616,41 +597,36 @@ static void usage(void)
        struct cmd_set          **cmd_set;
        struct in_addr          server_ip;
        NTSTATUS                nt_status;
-       extern BOOL             AllowDebugChange;
 
        /* make sure the vars that get altered (4th field) are in
           a fixed location or certain compilers complain */
        poptContext pc;
        struct poptOption long_options[] = {
-               {"authfile",    'A', POPT_ARG_STRING,   &opt_authfile, 'A'},
-               {"conf",        's', POPT_ARG_STRING,   &opt_configfile, 's'},
-               {"nopass",      'N', POPT_ARG_NONE,     &got_pass},
-               {"user",        'U', POPT_ARG_STRING,   &opt_username, 'U'},
-               {"workgroup",   'W', POPT_ARG_STRING,   &opt_domain, 'W'},
-               {"command",     'c', POPT_ARG_STRING,   &cmdstr},
-               {"logfile",     'l', POPT_ARG_STRING,   &opt_logfile, 'l'},
-               {"help",        'h', POPT_ARG_NONE,     0, 'h'},
-               {"dest-ip",     'I', POPT_ARG_STRING,   &opt_ipaddr, 'I'},
+               POPT_AUTOHELP
+               {"authfile",    'A', POPT_ARG_STRING,   &opt_authfile, 'A', "File containing user credentials"},
+               {"conf",        's', POPT_ARG_STRING,   &opt_configfile, 's', "Specify an alternative config file"},
+               {"nopass",      'N', POPT_ARG_NONE,     &got_pass, 'N', "Don't ask for a password"},
+               {"user",        'U', POPT_ARG_STRING,   &opt_username, 'U', "Set the network username"},
+               {"workgroup",   'W', POPT_ARG_STRING,   &opt_domain, 'W', "Set the domain name for user account"},
+               {"command",     'c', POPT_ARG_STRING,   &cmdstr, 'c', "Execute semicolon separated cmds"},
+               {"logfile",     'l', POPT_ARG_STRING,   &opt_logfile, 'l', "Logfile to use instead of stdout"},
+               {"dest-ip",     'I', POPT_ARG_STRING,   &opt_ipaddr, 'I', "Specify destination IP address"},
                { NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_debug },
                { NULL }
        };
 
-
        setlinebuf(stdout);
 
-       DEBUGLEVEL = 1;
-       AllowDebugChange = False;
-
        /* Parse options */
 
+       pc = poptGetContext("rpcclient", argc, (const char **) argv,
+                           long_options, 0);
+
        if (argc == 1) {
-               usage();
+               poptPrintHelp(pc, stderr, 0);
                return 0;
        }
        
-       pc = poptGetContext("rpcclient", argc, (const char **) argv,
-                           long_options, 0);
-       
        while((opt = poptGetNextOpt(pc)) != -1) {
                switch (opt) {
                case 'A':
@@ -686,7 +662,7 @@ static void usage(void)
                        break;
                }
                case 'I':
-                       if (!inet_aton(opt_ipaddr, &server_ip)) {
+                       if ( (server_ip.s_addr=inet_addr(opt_ipaddr)) == INADDR_NONE ) {
                                fprintf(stderr, "%s not a valid IP address\n",
                                        opt_ipaddr);
                                return 1;
@@ -694,11 +670,6 @@ static void usage(void)
                case 'W':
                        pstrcpy(domain, opt_domain);
                        break;
-                       
-               case 'h':
-               default:
-                       usage();
-                       exit(1);
                }
        }
 
@@ -708,7 +679,7 @@ static void usage(void)
        server = poptGetArg(pc);
        
        if (!server || poptGetArg(pc)) {
-               usage();
+               poptPrintHelp(pc, stderr, 0);
                return 1;
        }
 
@@ -721,12 +692,9 @@ static void usage(void)
                reopen_logs();
        
        /* Load smb.conf file */
-       /* FIXME!  How to get this DEBUGLEVEL to last over lp_load()? */
-       olddebug = DEBUGLEVEL;
-       if (!lp_load(dyn_CONFIGFILE,True,False,False)) {
+
+       if (!lp_load(dyn_CONFIGFILE,True,False,False))
                fprintf(stderr, "Can't load %s\n", dyn_CONFIGFILE);
-       }
-       DEBUGLEVEL = olddebug;
 
        load_interfaces();
 
index 3694eb47dfa9c95a766dd67e3b922f20a35f0642..7124f9416ad4ff1fdf08b080f3d39b419411fd9d 100644 (file)
@@ -217,8 +217,8 @@ static void decode_sam_deltas(uint32 num_deltas, SAM_DELTA_HDR *hdr_deltas, SAM_
                                decode_sam_als_mem_info(a);
                                break;
                        }
-                       case SAM_DELTA_DOM_INFO: {
-                               SAM_DELTA_DOM *a;
+                       case SAM_DELTA_POLICY_INFO: {
+                               SAM_DELTA_POLICY *a;
                                a = &deltas[i].dom_info;
                                decode_sam_dom_info(a);
                                break;
@@ -324,15 +324,15 @@ static void sam_account_from_delta(SAM_ACCOUNT *account,
 
 static void apply_account_info(SAM_ACCOUNT_INFO *sam_acct_delta)
 {
-       SAM_ACCOUNT sam_acct;
+       SAM_ACCOUNT *sam_acct;
        BOOL result;
 
-       ZERO_STRUCT(sam_acct);
-
-       pdb_init_sam(&sam_acct);
+       if (!NT_STATUS_IS_OK(pdb_init_sam(&sam_acct))) {
+               return;
+       }
 
-       sam_account_from_delta(&sam_acct, sam_acct_delta);
-       result = pdb_add_sam_account(&sam_acct);
+       sam_account_from_delta(sam_acct, sam_acct_delta);
+       result = pdb_add_sam_account(sam_acct);
 }
 
 /* Apply an array of deltas to the SAM database */
@@ -362,6 +362,7 @@ static NTSTATUS sam_sync(struct cli_state *cli, unsigned char trust_passwd[16],
         uint32 num_deltas_0, num_deltas_2;
         NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
        struct pdb_context *in;
+       uint32 neg_flags = 0x000001ff;
 
        DOM_CRED ret_creds;
 
@@ -384,7 +385,7 @@ static NTSTATUS sam_sync(struct cli_state *cli, unsigned char trust_passwd[16],
 
         /* Request a challenge */
 
-        if (!NT_STATUS_IS_OK(cli_nt_setup_creds(cli, SEC_CHAN_BDC, trust_passwd))) {
+        if (!NT_STATUS_IS_OK(cli_nt_setup_creds(cli, SEC_CHAN_BDC, trust_passwd, &neg_flags, 2))) {
                 DEBUG(0, ("Error initialising session creds\n"));
                 goto done;
         }
@@ -394,13 +395,16 @@ static NTSTATUS sam_sync(struct cli_state *cli, unsigned char trust_passwd[16],
 
         /* Do sam synchronisation on the SAM database*/
 
-       result = cli_netlogon_sam_sync(cli, mem_ctx, &ret_creds, 0, 
+       result = cli_netlogon_sam_sync(cli, mem_ctx, &ret_creds, 0, 0,
                                       &num_deltas_0, &hdr_deltas_0, 
                                       &deltas_0);
         
         if (!NT_STATUS_IS_OK(result))
                goto done;
 
+       
+        /* Update sam */
+
        apply_deltas(num_deltas_0, hdr_deltas_0, deltas_0);
 
 
@@ -412,7 +416,7 @@ static NTSTATUS sam_sync(struct cli_state *cli, unsigned char trust_passwd[16],
 #if 1
         /* Do sam synchronisation on the LSA database */
 
-       result = cli_netlogon_sam_sync(cli, mem_ctx, &ret_creds, 2, &num_deltas_2, &hdr_deltas_2, &deltas_2);
+       result = cli_netlogon_sam_sync(cli, mem_ctx, &ret_creds, 2, 0, &num_deltas_2, &hdr_deltas_2, &deltas_2);
         
         if (!NT_STATUS_IS_OK(result))
                goto done;
@@ -466,8 +470,6 @@ static NTSTATUS sam_sync(struct cli_state *cli, unsigned char trust_passwd[16],
                 goto done;
         }
 
-        /* Update sam tdb */
-
  done:
        cli_nt_session_close(cli);
        talloc_destroy(mem_ctx);
@@ -543,7 +545,7 @@ static void user_callback(poptContext con,
                          const struct poptOption *opt,
                          const char *arg, const void *data)
 {
-       char *p, *ch;
+       const char *p, *ch;
 
        if (!arg)
                return;
index 6623c6df646cc561bf20359deee44ef7bbf77c95..9d411711cb95532b8df59e27263e4287843c9cca 100644 (file)
@@ -531,13 +531,33 @@ file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum ));
 }
 
 /****************************************************************************
- Return True if the blocking lock queue has entries.
+ Return the number of seconds to the next blocking locks timeout, or default_timeout
 *****************************************************************************/
-
-BOOL blocking_locks_pending(void)
+unsigned blocking_locks_timeout(unsigned default_timeout)
 {
-  blocking_lock_record *blr = (blocking_lock_record *)ubi_slFirst( &blocking_lock_queue );
-  return (blr == NULL ? False : True);
+       unsigned timeout = default_timeout;
+       time_t t;
+       blocking_lock_record *blr = (blocking_lock_record *)ubi_slFirst(&blocking_lock_queue);
+
+       /* note that we avoid the time() syscall if there are no blocking locks */
+       if (!blr) {
+               return timeout;
+       }
+
+       t = time(NULL);
+
+       while (blr) {
+               if (timeout > (blr->expire_time - t)) {
+                       timeout = blr->expire_time - t;
+               }
+               blr = (blocking_lock_record *)ubi_slNext(blr);
+       }
+
+       if (timeout < 1) {
+               timeout = 1;
+       }
+
+       return timeout;
 }
 
 /****************************************************************************
@@ -576,7 +596,7 @@ void process_blocking_lock_queue(time_t t)
     DEBUG(5,("process_blocking_lock_queue: examining pending lock fnum = %d for file %s\n",
           fsp->fnum, fsp->fsp_name ));
 
-    if((blr->expire_time != -1) && (blr->expire_time > t)) {
+    if((blr->expire_time != -1) && (blr->expire_time <= t)) {
       /*
        * Lock expired - throw away all previously
        * obtained locks and return lock error.
@@ -584,7 +604,7 @@ void process_blocking_lock_queue(time_t t)
       DEBUG(5,("process_blocking_lock_queue: pending lock fnum = %d for file %s timed out.\n",
           fsp->fnum, fsp->fsp_name ));
 
-      blocking_lock_reply_error(blr,NT_STATUS_ACCESS_DENIED);
+      blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT);
       free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev));
       blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue));
       continue;
index d70e50f89957624c47c1ebd81a8fa185464f152b..22407348e821777d6a8d9440af25140ddc7ea219 100644 (file)
@@ -131,7 +131,7 @@ void conn_close_all(void)
        connection_struct *conn, *next;
        for (conn=Connections;conn;conn=next) {
                next=conn->next;
-               close_cnum(conn, (uint16)-1);
+               close_cnum(conn, conn->vuid);
        }
 }
 
@@ -157,6 +157,27 @@ BOOL conn_idle_all(time_t t, int deadtime)
        return allidle;
 }
 
+/****************************************************************************
+clear a vuid out of the validity cache, and as the 'owner' of a connection.
+****************************************************************************/
+void conn_clear_vuid_cache(uint16 vuid)
+{
+       connection_struct *conn;
+       int i;
+
+       for (conn=Connections;conn;conn=conn->next) {
+               if (conn->vuid == vuid) {
+                       conn->vuid = UID_FIELD_INVALID;
+               }
+
+               for (i=0;i<conn->vuid_cache.entries && i< VUID_CACHE_SIZE;i++) {
+                       if (conn->vuid_cache.list[i] == vuid) {
+                               conn->vuid_cache.list[i] = UID_FIELD_INVALID;
+                       }
+               }
+       }
+}
+
 /****************************************************************************
  Free a conn structure.
 ****************************************************************************/
@@ -191,7 +212,6 @@ void conn_free(connection_struct *conn)
                conn->ngroups = 0;
        }
 
-       delete_nt_token(&conn->nt_user_token);
        free_namearray(conn->veto_list);
        free_namearray(conn->hide_list);
        free_namearray(conn->veto_oplock_list);
index 5609c2963d80ce6976f0e378bef9b8cb38f77862..ad394a01ca0fd99362dc42fbd714092a22027fd3 100644 (file)
@@ -28,14 +28,24 @@ static TDB_CONTEXT *tdb;
 
 TDB_CONTEXT *conn_tdb_ctx(void)
 {
-       if (!tdb) {
+       if (!tdb)
                tdb = tdb_open_log(lock_path("connections.tdb"), 0, TDB_CLEAR_IF_FIRST|TDB_DEFAULT, 
                               O_RDWR | O_CREAT, 0644);
-       }
 
        return tdb;
 }
 
+static void make_conn_key(connection_struct *conn,char *name, TDB_DATA *pkbuf, struct connections_key *pkey)
+{
+       ZERO_STRUCTP(pkey);
+       pkey->pid = sys_getpid();
+       pkey->cnum = conn?conn->cnum:-1;
+       fstrcpy(pkey->name, name);
+
+       pkbuf->dptr = (char *)pkey;
+       pkbuf->dsize = sizeof(*pkey);
+}
+
 /****************************************************************************
  Delete a connection record.
 ****************************************************************************/
@@ -45,17 +55,12 @@ BOOL yield_connection(connection_struct *conn,char *name)
        struct connections_key key;
        TDB_DATA kbuf;
 
-       if (!tdb) return False;
+       if (!tdb)
+               return False;
 
        DEBUG(3,("Yielding connection to %s\n",name));
 
-       ZERO_STRUCT(key);
-       key.pid = sys_getpid();
-       key.cnum = conn?conn->cnum:-1;
-       fstrcpy(key.name, name);
-
-       kbuf.dptr = (char *)&key;
-       kbuf.dsize = sizeof(key);
+       make_conn_key(conn, name, &kbuf, &key);
 
        if (tdb_delete(tdb, kbuf) != 0) {
                int dbg_lvl = (!conn && (tdb_error(tdb) == TDB_ERR_NOEXIST)) ? 3 : 0;
@@ -88,7 +93,7 @@ static int count_fn( TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *u
 
        memcpy(&crec, dbuf.dptr, sizeof(crec));
  
-    if (crec.cnum == -1)
+       if (crec.cnum == -1)
                return 0;
 
        /* If the pid was not found delete the entry from connections.tdb */
@@ -111,16 +116,16 @@ static int count_fn( TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *u
  Claim an entry in the connections database.
 ****************************************************************************/
 
-BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOOL Clear)
+BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOOL Clear, uint32 msg_flags)
 {
        struct connections_key key;
        struct connections_data crec;
        TDB_DATA kbuf, dbuf;
 
-       if (!tdb) {
+       if (!tdb)
                tdb = tdb_open_log(lock_path("connections.tdb"), 0, TDB_CLEAR_IF_FIRST|TDB_DEFAULT, 
                               O_RDWR | O_CREAT, 0644);
-       }
+
        if (!tdb)
                return False;
 
@@ -156,13 +161,7 @@ BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOO
 
        DEBUG(5,("claiming %s %d\n",name,max_connections));
 
-       ZERO_STRUCT(key);
-       key.pid = sys_getpid();
-       key.cnum = conn?conn->cnum:-1;
-       fstrcpy(key.name, name);
-
-       kbuf.dptr = (char *)&key;
-       kbuf.dsize = sizeof(key);
+       make_conn_key(conn, name, &kbuf, &key);
 
        /* fill in the crec */
        ZERO_STRUCT(crec);
@@ -176,6 +175,7 @@ BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOO
                        lp_servicename(SNUM(conn)),sizeof(crec.name)-1);
        }
        crec.start = time(NULL);
+       crec.bcast_msg_flags = msg_flags;
        
        StrnCpy(crec.machine,get_remote_machine_name(),sizeof(crec.machine)-1);
        StrnCpy(crec.addr,conn?conn->client_address:client_addr(),sizeof(crec.addr)-1);
@@ -191,3 +191,45 @@ BOOL claim_connection(connection_struct *conn,char *name,int max_connections,BOO
 
        return True;
 }
+
+BOOL register_message_flags(BOOL doreg, uint32 msg_flags)
+{
+       struct connections_key key;
+       struct connections_data *pcrec;
+       TDB_DATA kbuf, dbuf;
+
+       if (!tdb)
+               return False;
+
+       DEBUG(10,("register_message_flags: %s flags 0x%x\n",
+               doreg ? "adding" : "removing",
+               (unsigned int)msg_flags ));
+
+       make_conn_key(NULL, "", &kbuf, &key);
+
+        dbuf = tdb_fetch(tdb, kbuf);
+        if (!dbuf.dptr) {
+               DEBUG(0,("register_message_flags: tdb_fetch failed\n"));
+               return False;
+       }
+
+       pcrec = (struct connections_data *)dbuf.dptr;
+       pcrec->bcast_msg_flags = msg_flags;
+       if (doreg)
+               pcrec->bcast_msg_flags |= msg_flags;
+       else
+               pcrec->bcast_msg_flags &= ~msg_flags;
+
+       if (tdb_store(tdb, kbuf, dbuf, TDB_REPLACE) != 0) {
+               DEBUG(0,("register_message_flags: tdb_store failed with error %s.\n",
+                       tdb_errorstr(tdb) ));
+               SAFE_FREE(dbuf.dptr);
+               return False;
+       }
+
+       DEBUG(10,("register_message_flags: new flags 0x%x\n",
+               (unsigned int)pcrec->bcast_msg_flags ));
+
+       SAFE_FREE(dbuf.dptr);
+       return True;
+}
index 1a18476b75b179f425970133979688363d66e3fe..396ecd98c495e8f856edf090e96d54fa19b66a80 100644 (file)
@@ -553,9 +553,24 @@ void *dptr_fetch_lanman2(int dptr_num)
 
 BOOL dir_check_ftype(connection_struct *conn,int mode,SMB_STRUCT_STAT *st,int dirtype)
 {
-  if (((mode & ~dirtype) & (aHIDDEN | aSYSTEM | aDIR)) != 0)
-    return False;
-  return True;
+       int mask;
+
+       /* Check the "may have" search bits. */
+       if (((mode & ~dirtype) & (aHIDDEN | aSYSTEM | aDIR)) != 0)
+               return False;
+
+       /* Check the "must have" bits, which are the may have bits shifted eight */
+       /* If must have bit is set, the file/dir can not be returned in search unless the matching
+               file attribute is set */
+       mask = ((dirtype >> 8) & (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM)); /* & 0x37 */
+       if(mask) {
+               if((mask & (mode & (aDIR|aARCH|aRONLY|aHIDDEN|aSYSTEM))) == mask)   /* check if matching attribute present */
+                       return True;
+               else
+                       return False;
+       }
+
+       return True;
 }
 
 static BOOL mangle_mask_match(connection_struct *conn, char *filename, char *mask)
@@ -663,18 +678,15 @@ typedef struct
   char *current;
 } Dir;
 
-
-
 /*******************************************************************
-check to see if a user can read a file. This is only approximate,
-it is used as part of the "hide unreadable" option. Don't
-use it for anything security sensitive
+ Check to see if a user can read a file. This is only approximate,
+ it is used as part of the "hide unreadable" option. Don't
+ use it for anything security sensitive.
 ********************************************************************/
 
-static BOOL user_can_read_file(connection_struct *conn, char *name)
+static BOOL user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst)
 {
        extern struct current_user current_user;
-       SMB_STRUCT_STAT ste;
        SEC_DESC *psd = NULL;
        size_t sd_size;
        files_struct *fsp;
@@ -683,8 +695,6 @@ static BOOL user_can_read_file(connection_struct *conn, char *name)
        NTSTATUS status;
        uint32 access_granted;
 
-       ZERO_STRUCT(ste);
-
        /*
         * If user is a member of the Admin group
         * we never hide files from them.
@@ -694,16 +704,16 @@ static BOOL user_can_read_file(connection_struct *conn, char *name)
                return True;
 
        /* If we can't stat it does not show it */
-       if (vfs_stat(conn, name, &ste) != 0)
+       if (!VALID_STAT(*pst) && (vfs_stat(conn, name, pst) != 0))
                return False;
 
        /* Pseudo-open the file (note - no fd's created). */
 
-       if(S_ISDIR(ste.st_mode))        
-                fsp = open_directory(conn, name, &ste, 0, SET_DENY_MODE(DENY_NONE), (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
+       if(S_ISDIR(pst->st_mode))       
+                fsp = open_directory(conn, name, pst, 0, SET_DENY_MODE(DENY_NONE), (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
                        unix_mode(conn,aRONLY|aDIR, name), &smb_action);
        else
-               fsp = open_file_shared1(conn, name, &ste, FILE_READ_ATTRIBUTES, SET_DENY_MODE(DENY_NONE),
+               fsp = open_file_shared1(conn, name, pst, FILE_READ_ATTRIBUTES, SET_DENY_MODE(DENY_NONE),
                        (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
 
        if (!fsp)
@@ -722,16 +732,15 @@ static BOOL user_can_read_file(connection_struct *conn, char *name)
 }
 
 /*******************************************************************
-check to see if a user can write a file (and only files, we do not
-check dirs on this one). This is only approximate,
-it is used as part of the "hide unwriteable" option. Don't
-use it for anything security sensitive
+ Check to see if a user can write a file (and only files, we do not
+ check dirs on this one). This is only approximate,
+ it is used as part of the "hide unwriteable" option. Don't
+ use it for anything security sensitive.
 ********************************************************************/
 
-static BOOL user_can_write_file(connection_struct *conn, char *name)
+static BOOL user_can_write_file(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst)
 {
        extern struct current_user current_user;
-       SMB_STRUCT_STAT ste;
        SEC_DESC *psd = NULL;
        size_t sd_size;
        files_struct *fsp;
@@ -740,8 +749,6 @@ static BOOL user_can_write_file(connection_struct *conn, char *name)
        NTSTATUS status;
        uint32 access_granted;
 
-       ZERO_STRUCT(ste);
-
        /*
         * If user is a member of the Admin group
         * we never hide files from them.
@@ -751,15 +758,15 @@ static BOOL user_can_write_file(connection_struct *conn, char *name)
                return True;
 
        /* If we can't stat it does not show it */
-       if (vfs_stat(conn, name, &ste) != 0)
+       if (!VALID_STAT(*pst) && (vfs_stat(conn, name, pst) != 0))
                return False;
 
        /* Pseudo-open the file (note - no fd's created). */
 
-       if(S_ISDIR(ste.st_mode))        
+       if(S_ISDIR(pst->st_mode))       
                return True;
        else
-               fsp = open_file_shared1(conn, name, &ste, FILE_WRITE_ATTRIBUTES, SET_DENY_MODE(DENY_NONE),
+               fsp = open_file_shared1(conn, name, pst, FILE_WRITE_ATTRIBUTES, SET_DENY_MODE(DENY_NONE),
                        (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
 
        if (!fsp)
@@ -777,6 +784,30 @@ static BOOL user_can_write_file(connection_struct *conn, char *name)
                                  &access_granted, &status);
 }
 
+/*******************************************************************
+  Is a file a "special" type ?
+********************************************************************/
+
+static BOOL file_is_special(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst)
+{
+       /*
+        * If user is a member of the Admin group
+        * we never hide files from them.
+        */
+
+       if (conn->admin_user)
+               return True;
+
+       /* If we can't stat it does not show it */
+       if (!VALID_STAT(*pst) && (vfs_stat(conn, name, pst) != 0))
+               return True;
+
+       if (S_ISREG(pst->st_mode) || S_ISDIR(pst->st_mode) || S_ISLNK(pst->st_mode))
+               return False;
+
+       return True;
+}
+
 /*******************************************************************
  Open a directory.
 ********************************************************************/
@@ -802,6 +833,8 @@ void *OpenDir(connection_struct *conn, char *name, BOOL use_veto)
        while (True) {
                int l;
                BOOL normal_entry = True;
+               SMB_STRUCT_STAT st;
+               char *entry = NULL;
 
                if (used == 0) {
                        n = ".";
@@ -818,6 +851,7 @@ void *OpenDir(connection_struct *conn, char *name, BOOL use_veto)
                        normal_entry = True;
                }
 
+               ZERO_STRUCT(st);
                l = strlen(n)+1;
 
                /* If it's a vetoed file, pretend it doesn't even exist */
@@ -826,30 +860,45 @@ void *OpenDir(connection_struct *conn, char *name, BOOL use_veto)
 
                /* Honour _hide unreadable_ option */
                if (normal_entry && conn && lp_hideunreadable(SNUM(conn))) {
-                       char *entry;
                        int ret=0;
       
-                       if (asprintf(&entry, "%s/%s/%s", conn->origpath, name, n) > 0) {
-                               ret = user_can_read_file(conn, entry);
-                               SAFE_FREE(entry);
+                       if (entry || asprintf(&entry, "%s/%s/%s", conn->origpath, name, n) > 0) {
+                               ret = user_can_read_file(conn, entry, &st);
                        }
-                       if (!ret)
+                       if (!ret) {
+                               SAFE_FREE(entry);
                                continue;
+                       }
                }
 
                /* Honour _hide unwriteable_ option */
                if (normal_entry && conn && lp_hideunwriteable_files(SNUM(conn))) {
-                       char *entry;
                        int ret=0;
       
-                       if (asprintf(&entry, "%s/%s/%s", conn->origpath, name, n) > 0) {
-                               ret = user_can_write_file(conn, entry);
+                       if (entry || asprintf(&entry, "%s/%s/%s", conn->origpath, name, n) > 0) {
+                               ret = user_can_write_file(conn, entry, &st);
+                       }
+                       if (!ret) {
                                SAFE_FREE(entry);
+                               continue;
+                       }
+               }
+
+               /* Honour _hide_special_ option */
+               if (normal_entry && conn && lp_hide_special_files(SNUM(conn))) {
+                       int ret=0;
+      
+                       if (entry || asprintf(&entry, "%s/%s/%s", conn->origpath, name, n) > 0) {
+                               ret = file_is_special(conn, entry, &st);
                        }
-                       if (!ret)
+                       if (ret) {
+                               SAFE_FREE(entry);
                                continue;
+                       }
                }
 
+               SAFE_FREE(entry);
+
                if (used + l > dirp->mallocsize) {
                        int s = MAX(used+l,used+2000);
                        char *r;
index ce98af4ace5fcc65b8ee552640e34e0082692ce6..d343db26f6b6d57cb7acd65fe642ef37e2918ac9 100644 (file)
@@ -168,7 +168,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen
 
        pstrcpy(orig_path, name);
 
-       if(stat_cache_lookup(conn, name, dirpath, &start, &st)) {
+       if(!case_sensitive && stat_cache_lookup(conn, name, dirpath, &start, &st)) {
                *pst = st;
                return True;
        }
index 1d4697474cef3ab4d1d0fa0c0e06ebdd1e9affcb..0446a953ff5a4111b5c82de2522756e85ccd7084 100644 (file)
@@ -730,7 +730,7 @@ static void name_map(char *OutName, BOOL need83, BOOL cache83)
        DEBUG(5,("name_map( %s, need83 = %s, cache83 = %s)\n", OutName,
                 need83 ? "True" : "False", cache83 ? "True" : "False"));
        
-       if (push_ucs2_allocate((void **)&OutName_ucs2, OutName) < 0) {
+       if (push_ucs2_allocate(&OutName_ucs2, OutName) < 0) {
                DEBUG(0, ("push_ucs2_allocate failed!\n"));
                return;
        }
index 6b53cc72aa454626308088aff91e9cec2d3bf5a6..a0a3d51139d61aaaaf2d3fbd4145ad31e64163c5 100644 (file)
@@ -200,7 +200,7 @@ static BOOL is_mangled_component(const char *name)
 {
        int len, i;
 
-       M_DEBUG(0,("is_mangled_component %s ?\n", name));
+       M_DEBUG(10,("is_mangled_component %s ?\n", name));
 
        /* check the length */
        len = strlen(name);
@@ -234,7 +234,7 @@ static BOOL is_mangled_component(const char *name)
                }
        }
 
-       M_DEBUG(0,("is_mangled %s -> yes\n", name));
+       M_DEBUG(10,("is_mangled %s -> yes\n", name));
 
        return True;
 }
@@ -257,7 +257,7 @@ static BOOL is_mangled(const char *name)
        const char *p;
        const char *s;
 
-       M_DEBUG(0,("is_mangled %s ?\n", name));
+       M_DEBUG(10,("is_mangled %s ?\n", name));
 
        for (s=name; (p=strchr(s, '/')); s=p+1) {
                char *component = strndup(s, PTR_DIFF(p, s));
@@ -367,7 +367,7 @@ static BOOL check_cache(char *name)
 
        /* make sure that this is a mangled name from this cache */
        if (!is_mangled(name)) {
-               M_DEBUG(0,("check_cache: %s -> not mangled\n", name));
+               M_DEBUG(10,("check_cache: %s -> not mangled\n", name));
                return False;
        }
 
@@ -382,7 +382,7 @@ static BOOL check_cache(char *name)
        /* now look in the prefix cache for that hash */
        prefix = cache_lookup(hash);
        if (!prefix) {
-               M_DEBUG(0,("check_cache: %s -> %08X -> not found\n", name, hash));
+               M_DEBUG(10,("check_cache: %s -> %08X -> not found\n", name, hash));
                return False;
        }
 
@@ -395,10 +395,10 @@ static BOOL check_cache(char *name)
        }
 
        if (extension[0]) {
-               M_DEBUG(0,("check_cache: %s -> %s.%s\n", name, prefix, extension));
+               M_DEBUG(10,("check_cache: %s -> %s.%s\n", name, prefix, extension));
                slprintf(name, sizeof(fstring), "%s.%s", prefix, extension);
        } else {
-               M_DEBUG(0,("check_cache: %s -> %s\n", name, prefix));
+               M_DEBUG(10,("check_cache: %s -> %s\n", name, prefix));
                fstrcpy(name, prefix);
        }
 
@@ -573,7 +573,7 @@ static void name_map(char *name, BOOL need83, BOOL cache83)
                cache_insert(name, prefix_len, hash);
        }
 
-       M_DEBUG(0,("name_map: %s -> %08X -> %s (cache=%d)\n", 
+       M_DEBUG(10,("name_map: %s -> %08X -> %s (cache=%d)\n", 
                   name, hash, new_name, cache83));
 
        /* and overwrite the old name */
index 2be04fd686058f553412aa6cc13efa0d2e190b2e..16427b00d705ee101a89babde07090764c2df415 100644 (file)
@@ -170,9 +170,9 @@ static int negprot_spnego(char *p)
        DATA_BLOB blob;
        extern pstring global_myname;
        uint8 guid[16];
-       const char *OIDs_krb5[] = {OID_NTLMSSP,
-                                  OID_KERBEROS5,
+       const char *OIDs_krb5[] = {OID_KERBEROS5,
                                   OID_KERBEROS5_OLD,
+                                  OID_NTLMSSP,
                                   NULL};
        const char *OIDs_plain[] = {OID_NTLMSSP, NULL};
        char *principal;
@@ -199,9 +199,7 @@ static int negprot_spnego(char *p)
        if (lp_security() != SEC_ADS) {
                blob = spnego_gen_negTokenInit(guid, OIDs_plain, "NONE");
        } else {
-               /* win2000 uses host$@REALM, which we will probably use eventually,
-                  but for now this works */
-               asprintf(&principal, "HOST/%s@%s", guid, lp_realm());
+               asprintf(&principal, "%s$@%s", guid, lp_realm());
                blob = spnego_gen_negTokenInit(guid, OIDs_krb5, principal);
                free(principal);
        }
@@ -239,7 +237,11 @@ static int reply_nt1(char *inbuf, char *outbuf)
                capabilities |= CAP_EXTENDED_SECURITY;
        }
        
-       capabilities |= CAP_NT_SMBS|CAP_RPC_REMOTE_APIS|CAP_UNIX;
+       capabilities |= CAP_NT_SMBS|CAP_RPC_REMOTE_APIS;
+
+       if (lp_unix_extensions()) {
+               capabilities |= CAP_UNIX;
+       }
        
        if (lp_large_readwrite() && (SMB_OFF_T_BITS == 64))
                capabilities |= CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_W2K_SMBS;
index cf69dfddb049fa6044c56634d47a19ddaeb278dc..1f3bbd488e577446f429f72a03be7db992ba1d93 100644 (file)
@@ -371,7 +371,7 @@ static int map_share_mode( char *fname, uint32 create_options,
 
        if (smb_open_mode == -1) {
 
-               if(*desired_access & (DELETE_ACCESS|WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS|
+               if(*desired_access & (DELETE_ACCESS|WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS|SYNCHRONIZE_ACCESS|
                                        FILE_EXECUTE|FILE_READ_ATTRIBUTES|
                                        FILE_READ_EA|FILE_WRITE_EA|SYSTEM_SECURITY_ACCESS|
                                        FILE_WRITE_ATTRIBUTES|READ_CONTROL_ACCESS)) {
@@ -548,6 +548,7 @@ int reply_ntcreate_and_X(connection_struct *conn,
        uint32 create_disposition = IVAL(inbuf,smb_ntcreate_CreateDisposition);
        uint32 create_options = IVAL(inbuf,smb_ntcreate_CreateOptions);
        uint16 root_dir_fid = (uint16)IVAL(inbuf,smb_ntcreate_RootDirectoryFid);
+       SMB_OFF_T allocation_size = 0;
        int smb_ofun;
        int smb_open_mode;
        int smb_attr = (file_attributes & SAMBA_ATTRIBUTES_MASK);
@@ -563,8 +564,16 @@ int reply_ntcreate_and_X(connection_struct *conn,
        files_struct *fsp=NULL;
        char *p = NULL;
        time_t c_time;
+       BOOL extended_oplock_granted = False;
+
        START_PROFILE(SMBntcreateX);
 
+       DEBUG(10,("reply_ntcreateX: flags = 0x%x, desired_access = 0x%x \
+file_attributes = 0x%x, share_access = 0x%x, create_disposition = 0x%x \
+create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attributes,
+                       share_access, create_disposition,
+                       create_options, root_dir_fid ));
+
        /* If it's an IPC, use the pipe handler. */
 
        if (IS_IPC(conn)) {
@@ -573,10 +582,14 @@ int reply_ntcreate_and_X(connection_struct *conn,
                        return do_ntcreate_pipe_open(conn,inbuf,outbuf,length,bufsize);
                } else {
                        END_PROFILE(SMBntcreateX);
-                       return(ERROR_DOS(ERRDOS,ERRbadaccess));
+                       return(ERROR_DOS(ERRDOS,ERRnoaccess));
                }
        }
                        
+       if (create_options & FILE_OPEN_BY_FILE_ID) {
+               END_PROFILE(SMBntcreateX);
+               return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
+       }
 
        /* 
         * We need to construct the open_and_X ofun value from the
@@ -585,7 +598,7 @@ int reply_ntcreate_and_X(connection_struct *conn,
        
        if((smb_ofun = map_create_disposition( create_disposition )) == -1) {
                END_PROFILE(SMBntcreateX);
-               return(ERROR_DOS(ERRDOS,ERRbadaccess));
+               return(ERROR_DOS(ERRDOS,ERRnoaccess));
        }
 
        /*
@@ -660,7 +673,7 @@ int reply_ntcreate_and_X(connection_struct *conn,
                                           share_access, 
                                           file_attributes)) == -1) {
                END_PROFILE(SMBntcreateX);
-               return ERROR_DOS(ERRDOS,ERRbadaccess);
+               return ERROR_DOS(ERRDOS,ERRnoaccess);
        }
 
        oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
@@ -689,6 +702,12 @@ int reply_ntcreate_and_X(connection_struct *conn,
        if(create_options & FILE_DIRECTORY_FILE) {
                oplock_request = 0;
                
+               /* Can't open a temp directory. IFS kit test. */
+               if (file_attributes & FILE_ATTRIBUTE_TEMPORARY) {
+                       END_PROFILE(SMBntcreateX);
+                       return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+               }
+
                fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, unixmode, &smb_action);
                        
                restore_case_semantics(file_attributes);
@@ -787,6 +806,22 @@ int reply_ntcreate_and_X(connection_struct *conn,
                return ERROR_DOS(ERRDOS,ERRnoaccess);
        } 
        
+       /* Save the requested allocation size. */
+       allocation_size = IVAL(inbuf,smb_ntcreate_AllocationSize);
+#ifdef LARGE_SMB_OFF_T
+       allocation_size |= (((SMB_OFF_T)IVAL(inbuf,smb_ntcreate_AllocationSize + 4)) << 32);
+#endif
+       if (allocation_size && (allocation_size > file_len)) {
+               fsp->initial_allocation_size = SMB_ROUNDUP(allocation_size,SMB_ROUNDUP_ALLOCATION_SIZE);
+               if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
+                       close_file(fsp,False);
+                       END_PROFILE(SMBntcreateX);
+                       return ERROR_NT(NT_STATUS_DISK_FULL);
+               }
+       } else {
+               fsp->initial_allocation_size = SMB_ROUNDUP(file_len,SMB_ROUNDUP_ALLOCATION_SIZE);
+       }
+
        /* 
         * If the caller set the extended oplock request bit
         * and we granted one (by whatever means) - set the
@@ -794,10 +829,10 @@ int reply_ntcreate_and_X(connection_struct *conn,
         */
        
        if (oplock_request && lp_fake_oplocks(SNUM(conn)))
-               smb_action |= EXTENDED_OPLOCK_GRANTED;
+               extended_oplock_granted = True;
        
        if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
-               smb_action |= EXTENDED_OPLOCK_GRANTED;
+               extended_oplock_granted = True;
 
 #if 0
        /* W2K sends back 42 words here ! If we do the same it breaks offline sync. Go figure... ? JRA. */
@@ -813,7 +848,7 @@ int reply_ntcreate_and_X(connection_struct *conn,
         * exclusive & batch here.
         */
 
-       if (smb_action & EXTENDED_OPLOCK_GRANTED) {
+       if (extended_oplock_granted) {
                if (flags & REQUEST_BATCH_OPLOCK) {
                        SCVAL(p,0, BATCH_OPLOCK_RETURN);
                } else {
@@ -828,7 +863,10 @@ int reply_ntcreate_and_X(connection_struct *conn,
        p++;
        SSVAL(p,0,fsp->fnum);
        p += 2;
-       SIVAL(p,0,smb_action);
+       if ((create_disposition == FILE_SUPERSEDE) && (smb_action == FILE_WAS_OVERWRITTEN))
+               SIVAL(p,0,FILE_WAS_SUPERSEDED);
+       else
+               SIVAL(p,0,smb_action);
        p += 4;
        
        /* Create time. */  
@@ -851,7 +889,7 @@ int reply_ntcreate_and_X(connection_struct *conn,
        p += 8;
        SIVAL(p,0,fmode); /* File Attributes. */
        p += 4;
-       SOFF_T(p, 0, get_allocation_size(&sbuf));
+       SOFF_T(p, 0, get_allocation_size(fsp,&sbuf));
        p += 8;
        SOFF_T(p,0,file_len);
        p += 12;
@@ -886,7 +924,7 @@ static int do_nt_transact_create_pipe( connection_struct *conn,
 
        if(total_parameter_count < 54) {
                DEBUG(0,("do_nt_transact_create_pipe - insufficient parameters (%u)\n", (unsigned int)total_parameter_count));
-               return ERROR_DOS(ERRDOS,ERRbadaccess);
+               return ERROR_DOS(ERRDOS,ERRnoaccess);
        }
 
        srvstr_pull(inbuf, fname, params+53, sizeof(fname), total_parameter_count-53, STR_TERMINATE);
@@ -1018,6 +1056,7 @@ static int call_nt_transact_create(connection_struct *conn,
        BOOL bad_path = False;
        files_struct *fsp = NULL;
        char *p = NULL;
+       BOOL extended_oplock_granted = False;
        uint32 flags;
        uint32 desired_access;
        uint32 file_attributes;
@@ -1026,6 +1065,7 @@ static int call_nt_transact_create(connection_struct *conn,
        uint32 create_options;
        uint32 sd_len;
        uint16 root_dir_fid;
+       SMB_OFF_T allocation_size = 0;
        int smb_ofun;
        int smb_open_mode;
        int smb_attr;
@@ -1043,7 +1083,7 @@ static int call_nt_transact_create(connection_struct *conn,
                        return do_nt_transact_create_pipe(conn, inbuf, outbuf, length, 
                                        bufsize, ppsetup, ppparams, ppdata);
                else
-                       return ERROR_DOS(ERRDOS,ERRbadaccess);
+                       return ERROR_DOS(ERRDOS,ERRnoaccess);
        }
 
        /*
@@ -1052,7 +1092,7 @@ static int call_nt_transact_create(connection_struct *conn,
 
        if(total_parameter_count < 54) {
                DEBUG(0,("call_nt_transact_create - insufficient parameters (%u)\n", (unsigned int)total_parameter_count));
-               return ERROR_DOS(ERRDOS,ERRbadaccess);
+               return ERROR_DOS(ERRDOS,ERRnoaccess);
        }
 
        flags = IVAL(params,0);
@@ -1065,6 +1105,11 @@ static int call_nt_transact_create(connection_struct *conn,
        root_dir_fid = (uint16)IVAL(params,4);
        smb_attr = (file_attributes & SAMBA_ATTRIBUTES_MASK);
 
+       if (create_options & FILE_OPEN_BY_FILE_ID) {
+               END_PROFILE(SMBntcreateX);
+               return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
+       }
+
        /* 
         * We need to construct the open_and_X ofun value from the
         * NT values, as that's what our code is structured to accept.
@@ -1138,7 +1183,7 @@ static int call_nt_transact_create(connection_struct *conn,
 
        if((smb_open_mode = map_share_mode( fname, create_options, &desired_access,
                                                share_access, file_attributes)) == -1)
-               return ERROR_DOS(ERRDOS,ERRbadaccess);
+               return ERROR_DOS(ERRDOS,ERRnoaccess);
 
        oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
        oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
@@ -1161,6 +1206,12 @@ static int call_nt_transact_create(connection_struct *conn,
 
        if(create_options & FILE_DIRECTORY_FILE) {
 
+               /* Can't open a temp directory. IFS kit test. */
+               if (file_attributes & FILE_ATTRIBUTE_TEMPORARY) {
+                       END_PROFILE(SMBntcreateX);
+                       return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+               }
+
                oplock_request = 0;
 
                /*
@@ -1234,10 +1285,10 @@ static int call_nt_transact_create(connection_struct *conn,
                 */
     
                if (oplock_request && lp_fake_oplocks(SNUM(conn)))
-                       smb_action |= EXTENDED_OPLOCK_GRANTED;
+                       extended_oplock_granted = True;
   
                if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
-                       smb_action |= EXTENDED_OPLOCK_GRANTED;
+                       extended_oplock_granted = True;
        }
 
        /*
@@ -1252,6 +1303,22 @@ static int call_nt_transact_create(connection_struct *conn,
        
        restore_case_semantics(file_attributes);
 
+       /* Save the requested allocation size. */
+       allocation_size = IVAL(params,12);
+#ifdef LARGE_SMB_OFF_T
+       allocation_size |= (((SMB_OFF_T)IVAL(params,16)) << 32);
+#endif
+       if (allocation_size && (allocation_size > file_len)) {
+               fsp->initial_allocation_size = SMB_ROUNDUP(allocation_size,SMB_ROUNDUP_ALLOCATION_SIZE);
+               if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
+                       close_file(fsp,False);
+                       END_PROFILE(SMBntcreateX);
+                       return ERROR_NT(NT_STATUS_DISK_FULL);
+               }
+       } else {
+               fsp->initial_allocation_size = SMB_ROUNDUP(file_len,SMB_ROUNDUP_ALLOCATION_SIZE);
+       }
+
        /* Realloc the size of parameters and data we will return */
        params = Realloc(*ppparams, 69);
        if(params == NULL)
@@ -1262,7 +1329,7 @@ static int call_nt_transact_create(connection_struct *conn,
        memset((char *)params,'\0',69);
 
        p = params;
-       if (smb_action & EXTENDED_OPLOCK_GRANTED)       
+       if (extended_oplock_granted)
                SCVAL(p,0, BATCH_OPLOCK_RETURN);
        else if (LEVEL_II_OPLOCK_TYPE(fsp->oplock_type))
                SCVAL(p,0, LEVEL_II_OPLOCK_RETURN);
@@ -1272,7 +1339,10 @@ static int call_nt_transact_create(connection_struct *conn,
        p += 2;
        SSVAL(p,0,fsp->fnum);
        p += 2;
-       SIVAL(p,0,smb_action);
+       if ((create_disposition == FILE_SUPERSEDE) && (smb_action == FILE_WAS_OVERWRITTEN))
+               SIVAL(p,0,FILE_WAS_SUPERSEDED);
+       else
+               SIVAL(p,0,smb_action);
        p += 8;
 
        /* Create time. */
@@ -1295,7 +1365,7 @@ static int call_nt_transact_create(connection_struct *conn,
        p += 8;
        SIVAL(p,0,fmode); /* File Attributes. */
        p += 4;
-       SOFF_T(p, 0, get_allocation_size(&sbuf));
+       SOFF_T(p, 0, get_allocation_size(fsp,&sbuf));
        p += 8;
        SOFF_T(p,0,file_len);
 
@@ -1582,7 +1652,7 @@ static int call_nt_transact_set_security_desc(connection_struct *conn,
                (unsigned int)security_info_sent ));
 
        if (total_data_count == 0)
-               return ERROR_DOS(ERRDOS, ERRbadaccess);
+               return ERROR_DOS(ERRDOS, ERRnoaccess);
 
        if (!NT_STATUS_IS_OK(nt_status = set_sd( fsp, data, total_data_count, security_info_sent)))
                return ERROR_NT(nt_status);
index 8c6e8ed805c3641f85e649d3b800ea0cb304cf7a..a95793a0505a9cb221d3a9c38f36ffc533ca8307 100644 (file)
@@ -139,18 +139,31 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn,
         * as we always opened files read-write in that release. JRA.
         */
 
-       if ((accmode == O_RDONLY) && ((flags & O_TRUNC) == O_TRUNC))
+       if ((accmode == O_RDONLY) && ((flags & O_TRUNC) == O_TRUNC)) {
+               DEBUG(10,("open_file: truncate requested on read-only open for file %s\n",fname ));
                local_flags = (flags & ~O_ACCMODE)|O_RDWR;
+       }
 
-       /*
-        * We can't actually truncate here as the file may be locked.
-        * open_file_shared will take care of the truncate later. JRA.
-        */
+       if ((desired_access & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE)) ||
+                       (local_flags & O_CREAT) || ((local_flags & O_TRUNC) == O_TRUNC) ) {
 
-       local_flags &= ~O_TRUNC;
+               /*
+                * We can't actually truncate here as the file may be locked.
+                * open_file_shared will take care of the truncate later. JRA.
+                */
 
-       if ((desired_access & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE)) ||
-                       (local_flags & O_CREAT)) {
+               local_flags &= ~O_TRUNC;
+
+#if defined(O_NONBLOCK) && defined(S_ISFIFO)
+               /*
+                * We would block on opening a FIFO with no one else on the
+                * other end. Do what we used to do and add O_NONBLOCK to the
+                * open flags. JRA.
+                */
+
+               if (VALID_STAT(*psbuf) && S_ISFIFO(psbuf->st_mode))
+                       local_flags |= O_NONBLOCK;
+#endif
 
                /* actually do the open */
                fsp->fd = fd_open(conn, fname, local_flags, mode);
@@ -679,6 +692,31 @@ static void kernel_flock(files_struct *fsp, int deny_mode)
 }
 
 
+static BOOL open_match_attributes(connection_struct *conn, char *path, mode_t existing_mode, mode_t new_mode)
+{
+       uint32 old_dos_mode, new_dos_mode;
+       SMB_STRUCT_STAT sbuf;
+
+       ZERO_STRUCT(sbuf);
+
+       sbuf.st_mode = existing_mode;
+       old_dos_mode = dos_mode(conn, path, &sbuf);
+
+       sbuf.st_mode = new_mode;
+       new_dos_mode = dos_mode(conn, path, &sbuf);
+
+       /* If we're mapping SYSTEM and HIDDEN ensure they match. */
+       if (lp_map_system(SNUM(conn))) {
+               if ((old_dos_mode & FILE_ATTRIBUTE_SYSTEM) != (new_dos_mode & FILE_ATTRIBUTE_SYSTEM))
+                       return False;
+       }
+       if (lp_map_hidden(SNUM(conn))) {
+               if ((old_dos_mode & FILE_ATTRIBUTE_HIDDEN) != (new_dos_mode & FILE_ATTRIBUTE_HIDDEN))
+                       return False;
+       }
+       return True;
+}
+
 /****************************************************************************
  Open a file with a share mode. On output from this open we are guarenteeing
  that 
@@ -773,6 +811,17 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_
        if (CAN_WRITE(conn) && (GET_FILE_OPEN_DISPOSITION(ofun) == FILE_EXISTS_TRUNCATE))
                flags2 |= O_TRUNC;
 
+       /* We only care about matching attributes on file exists and truncate. */
+       if (file_existed && (GET_FILE_OPEN_DISPOSITION(ofun) == FILE_EXISTS_TRUNCATE)) {
+               if (!open_match_attributes(conn, fname, psbuf->st_mode, mode)) {
+                       DEBUG(5,("open_file_shared: attributes missmatch for file %s (0%o, 0%o)\n",
+                                               fname, psbuf->st_mode, mode ));
+                       file_free(fsp);
+                       errno = EACCES;
+                       return NULL;
+               }
+       }
+
        if (GET_FILE_OPEN_DISPOSITION(ofun) == FILE_EXISTS_FAIL)
                flags2 |= O_EXCL;
 
index cfac7cf695f1e8ae6d56071277ee5eab3a7aba34..f2956237dd202bd100e71975378427f491fa09ee 100644 (file)
@@ -69,6 +69,10 @@ void invalidate_vuid(uint16 vuid)
 
        DLIST_REMOVE(validated_users, vuser);
 
+       /* clear the vuid from the 'cache' on each connection, and
+          from the vuid 'owner' of connections */
+       conn_clear_vuid_cache(vuid);
+
        SAFE_FREE(vuser->groups);
        delete_nt_token(&vuser->nt_user_token);
        SAFE_FREE(vuser);
@@ -89,95 +93,6 @@ void invalidate_all_vuids(void)
        }
 }
 
-/****************************************************************************
- Create the SID list for this user.
-****************************************************************************/
-
-NT_USER_TOKEN *create_nt_token(uid_t uid, gid_t gid, int ngroups, gid_t *groups, BOOL is_guest, NT_USER_TOKEN *sup_tok)
-{
-       extern DOM_SID global_sid_World;
-       extern DOM_SID global_sid_Network;
-       extern DOM_SID global_sid_Builtin_Guests;
-       extern DOM_SID global_sid_Authenticated_Users;
-       NT_USER_TOKEN *token;
-       DOM_SID *psids;
-       int i, psid_ndx = 0;
-       size_t num_sids = 0;
-       fstring sid_str;
-
-       if ((token = (NT_USER_TOKEN *)malloc( sizeof(NT_USER_TOKEN) ) ) == NULL)
-               return NULL;
-
-       ZERO_STRUCTP(token);
-
-       /* We always have uid/gid plus World and Network and Authenticated Users or Guest SIDs. */
-       num_sids = 5 + ngroups;
-
-       if (sup_tok && sup_tok->num_sids)
-               num_sids += sup_tok->num_sids;
-
-       if ((token->user_sids = (DOM_SID *)malloc( num_sids*sizeof(DOM_SID))) == NULL) {
-               SAFE_FREE(token);
-               return NULL;
-       }
-
-       psids = token->user_sids;
-
-       /*
-        * Note - user SID *MUST* be first in token !
-        * se_access_check depends on this.
-        */
-
-       uid_to_sid( &psids[PRIMARY_USER_SID_INDEX], uid);
-       psid_ndx++;
-
-       /*
-        * Primary group SID is second in token. Convention.
-        */
-
-       gid_to_sid( &psids[PRIMARY_GROUP_SID_INDEX], gid);
-       psid_ndx++;
-
-       /* Now add the group SIDs. */
-
-       for (i = 0; i < ngroups; i++) {
-               if (groups[i] != gid) {
-                       gid_to_sid( &psids[psid_ndx++], groups[i]);
-               }
-       }
-
-       if (sup_tok) {
-               /* Now add the additional SIDs from the supplimentary token. */
-               for (i = 0; i < sup_tok->num_sids; i++)
-                       sid_copy( &psids[psid_ndx++], &sup_tok->user_sids[i] );
-       }
-
-       /*
-        * Finally add the "standard" SIDs.
-        * The only difference between guest and "anonymous" (which we
-        * don't really support) is the addition of Authenticated_Users.
-        */
-
-       sid_copy( &psids[psid_ndx++], &global_sid_World);
-       sid_copy( &psids[psid_ndx++], &global_sid_Network);
-
-       if (is_guest)
-               sid_copy( &psids[psid_ndx++], &global_sid_Builtin_Guests);
-       else
-               sid_copy( &psids[psid_ndx++], &global_sid_Authenticated_Users);
-
-       token->num_sids = psid_ndx;
-
-       /* Dump list of sids in token */
-
-       for (i = 0; i < token->num_sids; i++) {
-               DEBUG(5, ("user token sid %s\n", 
-                         sid_to_string(sid_str, &token->user_sids[i])));
-       }
-
-       return token;
-}
-
 /****************************************************************************
 register a uid/name pair as being valid and that a valid password
 has been given. vuid is biased by an offset. This allows us to
@@ -187,8 +102,6 @@ tell random client vuid's (normally zero) from valid vuids.
 int register_vuid(auth_serversupplied_info *server_info, const char *smb_name)
 {
        user_struct *vuser = NULL;
-       uid_t uid;
-       gid_t gid;
 
        /* Ensure no vuid gets registered in share level security. */
        if(lp_security() == SEC_SHARE)
@@ -205,15 +118,6 @@ int register_vuid(auth_serversupplied_info *server_info, const char *smb_name)
 
        ZERO_STRUCTP(vuser);
 
-       if (!IS_SAM_UNIX_USER(server_info->sam_account)) {
-               DEBUG(0,("Attempted session setup with invalid user.  No uid/gid in SAM_ACCOUNT (flags:%x)\n", pdb_get_init_flag(server_info->sam_account)));
-               free(vuser);
-               return UID_FIELD_INVALID;
-       }
-
-       uid = pdb_get_uid(server_info->sam_account);
-       gid = pdb_get_gid(server_info->sam_account);
-
        /* Allocate a free vuid. Yes this is a linear search... :-) */
        while( get_valid_user_struct(next_vuid) != NULL ) {
                next_vuid++;
@@ -225,18 +129,38 @@ int register_vuid(auth_serversupplied_info *server_info, const char *smb_name)
        DEBUG(10,("register_vuid: allocated vuid = %u\n", (unsigned int)next_vuid ));
 
        vuser->vuid = next_vuid;
-       vuser->uid = uid;
-       vuser->gid = gid;
+
+       /* the next functions should be done by a SID mapping system (SMS) as
+        * the new real sam db won't have reference to unix uids or gids
+        */
+       if (!IS_SAM_UNIX_USER(server_info->sam_account)) {
+               DEBUG(0,("Attempted session setup with invalid user.  No uid/gid in SAM_ACCOUNT (flags:%x)\n", pdb_get_init_flag(server_info->sam_account)));
+               free(vuser);
+               return UID_FIELD_INVALID;
+       }
+       
+       vuser->uid = pdb_get_uid(server_info->sam_account);
+       vuser->gid = pdb_get_gid(server_info->sam_account);
+       
+       vuser->n_groups = server_info->n_groups;
+       if (vuser->n_groups) {
+               if (!(vuser->groups = memdup(server_info->groups, sizeof(gid_t) * vuser->n_groups))) {
+                       DEBUG(0,("register_vuid: failed to memdup vuser->groups\n"));
+                       free(vuser);
+                       return UID_FIELD_INVALID;
+               }
+       }
+
        vuser->guest = server_info->guest;
-       fstrcpy(vuser->user.unix_name, pdb_get_username(server_info->sam_account));
-       fstrcpy(vuser->user.smb_name, smb_name);
+       fstrcpy(vuser->user.unix_name, pdb_get_username(server_info->sam_account)); 
+       fstrcpy(vuser->user.smb_name, smb_name); 
        fstrcpy(vuser->user.domain, pdb_get_domain(server_info->sam_account));
        fstrcpy(vuser->user.full_name, pdb_get_fullname(server_info->sam_account));
 
        {
                /* Keep the homedir handy */
                const char *homedir = pdb_get_homedir(server_info->sam_account);
-               const char *unix_homedir = pdb_get_unix_homedir(server_info->sam_account);
+               const char *unix_homedir = pdb_get_unix_homedir(server_info->sam_account); /* should be optained by SMS */
                const char *logon_script = pdb_get_logon_script(server_info->sam_account);
                if (homedir) {
                        vuser->homedir = smb_xstrdup(homedir);
@@ -260,19 +184,13 @@ int register_vuid(auth_serversupplied_info *server_info, const char *smb_name)
 
        DEBUG(3, ("User name: %s\tReal name: %s\n",vuser->user.unix_name,vuser->user.full_name));       
 
-       vuser->n_groups = 0;
-       vuser->groups  = NULL;
-
-       /* Find all the groups this uid is in and store them. 
-               Used by change_to_user() */
-       initialise_groups(vuser->user.unix_name, vuser->uid, vuser->gid);
-       get_current_groups(vuser->gid, &vuser->n_groups, &vuser->groups);
-
-       if (server_info->ptok)
-               add_supplementary_nt_login_groups(&vuser->n_groups, &vuser->groups, &server_info->ptok);
-
-       /* Create an NT_USER_TOKEN struct for this user. */
-       vuser->nt_user_token = create_nt_token(vuser->uid, vuser->gid, vuser->n_groups, vuser->groups, vuser->guest, server_info->ptok);
+       if (server_info->ptok) {
+               vuser->nt_user_token = dup_nt_token(server_info->ptok);
+       } else {
+               DEBUG(1, ("server_info does not contain a user_token - cannot continue\n"));
+               free(vuser);
+               return UID_FIELD_INVALID;
+       }
 
        DEBUG(3,("UNIX uid %d is UNIX user %s, and will be vuid %u\n",(int)vuser->uid,vuser->user.unix_name, vuser->vuid));
 
@@ -306,9 +224,11 @@ add a name to the session users list
 void add_session_user(const char *user)
 {
   fstring suser;
-  StrnCpy(suser,user,sizeof(suser)-1);
+  struct passwd *passwd;
+
+  if (!(passwd = Get_Pwnam(user))) return;
 
-  if (!Get_Pwnam_Modify(suser)) return;
+  StrnCpy(suser,passwd->pw_name,sizeof(suser)-1);
 
   if (suser && *suser && !in_list(suser,session_users,False))
     {
@@ -451,7 +371,7 @@ static char *validate_group(char *group, DATA_BLOB password,int snum)
  Note this is *NOT* used when logging on using sessionsetup_and_X.
 ****************************************************************************/
 
-BOOL authorise_login(int snum,char *user, DATA_BLOB password, 
+BOOL authorise_login(int snum, fstring user, DATA_BLOB password, 
                     BOOL *guest)
 {
        BOOL ok = False;
index 043e33e83675ca9267345bbffecbb078365b611e..e6ae1c7d7997dab5ca72a78ba8d64600c9fdb4b5 100644 (file)
@@ -1881,6 +1881,8 @@ static int nt_ace_comp( SEC_ACE *a1, SEC_ACE *a2)
 
 size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc)
 {
+       extern DOM_SID global_sid_Builtin_Administrators;
+       extern DOM_SID global_sid_Builtin_Users;
        connection_struct *conn = fsp->conn;
        SMB_STRUCT_STAT sbuf;
        SEC_ACE *nt_ace_list = NULL;
@@ -1895,6 +1897,7 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc)
        SMB_ACL_T dir_acl = NULL;
        canon_ace *file_ace = NULL;
        canon_ace *dir_ace = NULL;
+       size_t num_profile_acls = 0;
  
        *ppdesc = NULL;
 
@@ -1939,7 +1942,14 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc)
         * Get the owner, group and world SIDs.
         */
 
-       create_file_sids(&sbuf, &owner_sid, &group_sid);
+       if (lp_profile_acls(SNUM(fsp->conn))) {
+               /* For WXP SP1 the owner must be administrators. */
+               sid_copy(&owner_sid, &global_sid_Builtin_Administrators);
+               sid_copy(&group_sid, &global_sid_Builtin_Users);
+               num_profile_acls = 2;
+       } else {
+               create_file_sids(&sbuf, &owner_sid, &group_sid);
+       }
 
        /* Create the canon_ace lists. */
        file_ace = canonicalise_acl( fsp, posix_acl, &sbuf,  &owner_sid, &group_sid);
@@ -1963,7 +1973,7 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc)
        }
 
        /* Allocate the ace list. */
-       if ((nt_ace_list = (SEC_ACE *)malloc((num_acls + num_dir_acls)* sizeof(SEC_ACE))) == NULL) {
+       if ((nt_ace_list = (SEC_ACE *)malloc((num_acls + num_profile_acls + num_dir_acls)* sizeof(SEC_ACE))) == NULL) {
                DEBUG(0,("get_nt_acl: Unable to malloc space for nt_ace_list.\n"));
                goto done;
        }
@@ -1986,6 +1996,13 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc)
                        init_sec_ace(&nt_ace_list[num_aces++], &ace->trustee, nt_acl_type, acc, 0);
                }
 
+               /* The User must have access to a profile share - even if we can't map the SID. */
+               if (lp_profile_acls(SNUM(fsp->conn))) {
+                       SEC_ACCESS acc;
+                       init_sec_access(&acc,FILE_GENERIC_ALL);
+                       init_sec_ace(&nt_ace_list[num_aces++], &global_sid_Builtin_Users, SEC_ACE_TYPE_ACCESS_ALLOWED, acc, 0);
+               }
+
                ace = dir_ace;
 
                for (i = 0; i < num_dir_acls; i++, ace = ace->next) {
@@ -1994,6 +2011,15 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc)
                                        SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_INHERIT_ONLY);
                }
 
+               /* The User must have access to a profile share - even if we can't map the SID. */
+               if (lp_profile_acls(SNUM(fsp->conn))) {
+                       SEC_ACCESS acc;
+                       init_sec_access(&acc,FILE_GENERIC_ALL);
+                       init_sec_ace(&nt_ace_list[num_aces++], &global_sid_Builtin_Users, SEC_ACE_TYPE_ACCESS_ALLOWED, acc,
+                                       SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT|
+                                       SEC_ACE_FLAG_INHERIT_ONLY);
+               }
+
                /*
                 * Sort to force deny entries to the front.
                 */
index 55234ec896e422b7b14899401bea15fddce9facc..0f7cfd0e9cb0e78ba0a19d2f7b228f8c9e1ec09e 100644 (file)
@@ -42,8 +42,8 @@ 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;
-SIG_ATOMIC_T got_sig_term;
+SIG_ATOMIC_T reload_after_sighup = 0;
+SIG_ATOMIC_T got_sig_term = 0;
 extern BOOL global_machine_password_needs_changing;
 extern fstring global_myworkgroup;
 extern pstring global_myname;
@@ -609,8 +609,9 @@ const static struct smb_message_struct
 };
 
 /*******************************************************************
-dump a prs to a file
- ********************************************************************/
+ Dump a packet to a file.
+********************************************************************/
+
 static void smb_dump(const char *name, int type, char *data, ssize_t len)
 {
        int fd, i;
@@ -635,178 +636,171 @@ static void smb_dump(const char *name, int type, char *data, ssize_t len)
 
 
 /****************************************************************************
-do a switch on the message type, and return the response size
+ Do a switch on the message type, and return the response size
 ****************************************************************************/
+
 static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize)
 {
-  static pid_t pid= (pid_t)-1;
-  int outsize = 0;
-  extern uint16 global_smbpid;
-
-  type &= 0xff;
+       static pid_t pid= (pid_t)-1;
+       int outsize = 0;
+       extern uint16 global_smbpid;
 
-  if (pid == (pid_t)-1)
-    pid = sys_getpid();
+       type &= 0xff;
 
-  errno = 0;
-  last_message = type;
-
-  /* make sure this is an SMB packet */
-  if (strncmp(smb_base(inbuf),"\377SMB",4) != 0)
-  {
-    DEBUG(2,("Non-SMB packet of length %d\n",smb_len(inbuf)));
-    return(-1);
-  }
+       if (pid == (pid_t)-1)
+               pid = sys_getpid();
 
-  /* yuck! this is an interim measure before we get rid of our
-     current inbuf/outbuf system */
-  global_smbpid = SVAL(inbuf,smb_pid);
+       errno = 0;
+       last_message = type;
 
-  if (smb_messages[type].fn == NULL)
-  {
-    DEBUG(0,("Unknown message type %d!\n",type));
-    smb_dump("Unknown", 1, inbuf, size);
-    outsize = reply_unknown(inbuf,outbuf);
-  }
-  else
-  {
-    int flags = smb_messages[type].flags;
-    static uint16 last_session_tag = UID_FIELD_INVALID;
-    /* In share mode security we must ignore the vuid. */
-    uint16 session_tag = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : SVAL(inbuf,smb_uid);
-    connection_struct *conn = conn_find(SVAL(inbuf,smb_tid));
+       /* Make sure this is an SMB packet. smb_size contains NetBIOS header so subtract 4 from it. */
+       if ((strncmp(smb_base(inbuf),"\377SMB",4) != 0) || (size < (smb_size - 4))) {
+               DEBUG(2,("Non-SMB packet of length %d. Terminating server\n",smb_len(inbuf)));
+               exit_server("Non-SMB packet");
+               return(-1);
+       }
 
-    DEBUG(3,("switch message %s (pid %d)\n",smb_fn_name(type),(int)pid));
+       /* yuck! this is an interim measure before we get rid of our
+               current inbuf/outbuf system */
+       global_smbpid = SVAL(inbuf,smb_pid);
+
+       if (smb_messages[type].fn == NULL) {
+               DEBUG(0,("Unknown message type %d!\n",type));
+               smb_dump("Unknown", 1, inbuf, size);
+               outsize = reply_unknown(inbuf,outbuf);
+       } else {
+               int flags = smb_messages[type].flags;
+               static uint16 last_session_tag = UID_FIELD_INVALID;
+               /* In share mode security we must ignore the vuid. */
+               uint16 session_tag = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : SVAL(inbuf,smb_uid);
+               connection_struct *conn = conn_find(SVAL(inbuf,smb_tid));
+
+               DEBUG(3,("switch message %s (pid %d)\n",smb_fn_name(type),(int)pid));
+
+               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;
+                       }
+               }
 
-    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);
 
-    /* Ensure this value is replaced in the incoming packet. */
-    SSVAL(inbuf,smb_uid,session_tag);
+               /*
+                * Ensure the correct username is in current_user_info.
+                * This is a really ugly bugfix for problems with
+                * multiple session_setup_and_X's being done and
+                * allowing %U and %G substitutions to work correctly.
+                * There is a reason this code is done here, don't
+                * move it unless you know what you're doing... :-).
+                * JRA.
+                */
 
-    /*
-     * Ensure the correct username is in current_user_info.
-     * This is a really ugly bugfix for problems with
-     * multiple session_setup_and_X's being done and
-     * allowing %U and %G substitutions to work correctly.
-     * There is a reason this code is done here, don't
-     * move it unless you know what you're doing... :-).
-     * JRA.
-     */
+               if (session_tag != last_session_tag) {
+                       user_struct *vuser = NULL;
 
-    if (session_tag != last_session_tag) {
-      user_struct *vuser = NULL;
+                       last_session_tag = session_tag;
+                       if(session_tag != UID_FIELD_INVALID)
+                               vuser = get_valid_user_struct(session_tag);           
+                       if(vuser != NULL)
+                               current_user_info = vuser->user;
+               }
 
-      last_session_tag = session_tag;
-      if(session_tag != UID_FIELD_INVALID)
-        vuser = get_valid_user_struct(session_tag);           
-      if(vuser != NULL)
-        current_user_info = vuser->user;
-    }
+               /* does this protocol need to be run as root? */
+               if (!(flags & AS_USER))
+                       change_to_root_user();
 
-    /* does this protocol need to be run as root? */
-    if (!(flags & AS_USER))
-      change_to_root_user();
+               /* does this protocol need a valid tree connection? */
+               if ((flags & AS_USER) && !conn)
+                       return ERROR_DOS(ERRSRV, ERRinvnid);
 
-    /* does this protocol need a valid tree connection? */
-    if ((flags & AS_USER) && !conn) {
-           return ERROR_DOS(ERRSRV, ERRinvnid);
-    }
 
+               /* does this protocol need to be run as the connected user? */
+               if ((flags & AS_USER) && !change_to_user(conn,session_tag)) {
+                       if (flags & AS_GUEST) 
+                               flags &= ~AS_USER;
+                       else
+                               return(ERROR_DOS(ERRSRV,ERRaccess));
+               }
 
-    /* does this protocol need to be run as the connected user? */
-    if ((flags & AS_USER) && !change_to_user(conn,session_tag)) {
-      if (flags & AS_GUEST) 
-        flags &= ~AS_USER;
-      else
-        return(ERROR_DOS(ERRSRV,ERRaccess));
-    }
-
-    /* this code is to work around a bug is MS client 3 without
-       introducing a security hole - it needs to be able to do
-       print queue checks as guest if it isn't logged in properly */
-    if (flags & AS_USER)
-      flags &= ~AS_GUEST;
+               /* this code is to work around a bug is MS client 3 without
+                       introducing a security hole - it needs to be able to do
+                       print queue checks as guest if it isn't logged in properly */
+               if (flags & AS_USER)
+                       flags &= ~AS_GUEST;
 
-    /* does it need write permission? */
-    if ((flags & NEED_WRITE) && !CAN_WRITE(conn))
-      return(ERROR_DOS(ERRSRV,ERRaccess));
+               /* does it need write permission? */
+               if ((flags & NEED_WRITE) && !CAN_WRITE(conn))
+                       return(ERROR_DOS(ERRSRV,ERRaccess));
 
-    /* ipc services are limited */
-    if (IS_IPC(conn) && (flags & AS_USER) && !(flags & CAN_IPC)) {
-      return(ERROR_DOS(ERRSRV,ERRaccess));         
-    }
+               /* ipc services are limited */
+               if (IS_IPC(conn) && (flags & AS_USER) && !(flags & CAN_IPC))
+                       return(ERROR_DOS(ERRSRV,ERRaccess));        
 
-    /* load service specific parameters */
-    if (conn && !set_current_service(conn,(flags & AS_USER)?True:False)) {
-      return(ERROR_DOS(ERRSRV,ERRaccess));
-    }
+               /* load service specific parameters */
+               if (conn && !set_current_service(conn,(flags & AS_USER)?True:False))
+                       return(ERROR_DOS(ERRSRV,ERRaccess));
 
-    /* does this protocol need to be run as guest? */
-    if ((flags & AS_GUEST) && 
-                (!change_to_guest() || 
-               !check_access(smbd_server_fd(), lp_hostsallow(-1), lp_hostsdeny(-1)))) {
-      return(ERROR_DOS(ERRSRV,ERRaccess));
-    }
+               /* does this protocol need to be run as guest? */
+               if ((flags & AS_GUEST) && (!change_to_guest() || 
+                               !check_access(smbd_server_fd(), lp_hostsallow(-1), lp_hostsdeny(-1))))
+                       return(ERROR_DOS(ERRSRV,ERRaccess));
 
-    last_inbuf = inbuf;
+               last_inbuf = inbuf;
 
-    outsize = smb_messages[type].fn(conn, inbuf,outbuf,size,bufsize);
-  }
+               outsize = smb_messages[type].fn(conn, inbuf,outbuf,size,bufsize);
+       }
 
-  smb_dump(smb_fn_name(type), 0, outbuf, outsize);
+       smb_dump(smb_fn_name(type), 0, outbuf, outsize);
 
-  return(outsize);
+       return(outsize);
 }
 
 
 /****************************************************************************
-  construct a reply to the incoming packet
+ Construct a reply to the incoming packet.
 ****************************************************************************/
+
 static int construct_reply(char *inbuf,char *outbuf,int size,int bufsize)
 {
-  int type = CVAL(inbuf,smb_com);
-  int outsize = 0;
-  int msg_type = CVAL(inbuf,0);
+       int type = CVAL(inbuf,smb_com);
+       int outsize = 0;
+       int msg_type = CVAL(inbuf,0);
 
-  GetTimeOfDay(&smb_last_time);
+       GetTimeOfDay(&smb_last_time);
 
-  chain_size = 0;
-  file_chain_reset();
-  reset_chain_p();
+       chain_size = 0;
+       file_chain_reset();
+       reset_chain_p();
 
-  if (msg_type != 0)
-    return(reply_special(inbuf,outbuf));  
+       if (msg_type != 0)
+               return(reply_special(inbuf,outbuf));  
 
-  construct_reply_common(inbuf, outbuf);
+       construct_reply_common(inbuf, outbuf);
 
-  outsize = switch_message(type,inbuf,outbuf,size,bufsize);
+       outsize = switch_message(type,inbuf,outbuf,size,bufsize);
 
-  outsize += chain_size;
+       outsize += chain_size;
 
-  if(outsize > 4)
-    smb_setlen(outbuf,outsize - 4);
-  return(outsize);
+       if(outsize > 4)
+               smb_setlen(outbuf,outsize - 4);
+       return(outsize);
 }
 
 /****************************************************************************
 Keep track of the number of running smbd's. This functionality is used to
 'hard' limit Samba overhead on resource constrained systems. 
+ Keep track of the number of running smbd's. This functionality is used to
+ 'hard' limit Samba overhead on resource constrained systems. 
 ****************************************************************************/
+
 static BOOL smbd_process_limit(void)
 {
        int32  total_smbds;
@@ -1032,16 +1026,15 @@ static int setup_select_timeout(void)
        int select_timeout;
        int t;
 
-       /*
-        * Increase the select timeout back to SMBD_SELECT_TIMEOUT if we
-        * have removed any blocking locks. JRA.
-        */
-
-       select_timeout = blocking_locks_pending() ? SMBD_SELECT_TIMEOUT_WITH_PENDING_LOCKS*1000 :
-               SMBD_SELECT_TIMEOUT*1000;
+       select_timeout = blocking_locks_timeout(SMBD_SELECT_TIMEOUT);
+       select_timeout *= 1000;
 
        t = change_notify_timeout();
-       if (t != -1) select_timeout = MIN(select_timeout, t*1000);
+       if (t != -1)
+               select_timeout = MIN(select_timeout, t*1000);
+
+       if (print_notify_messages_pending())
+               select_timeout = MIN(select_timeout, 1000);
 
        return select_timeout;
 }
@@ -1161,9 +1154,16 @@ static BOOL timeout_processing(int deadtime, int *select_timeout, time_t *last_t
      * First, open the machine password file with an exclusive lock.
      */
 
+    if (secrets_lock_trust_account_password(global_myworkgroup, True) == False) {
+      DEBUG(0,("process: unable to lock the machine account password for \
+machine %s in domain %s.\n", global_myname, global_myworkgroup ));
+      return True;
+    }
+
     if(!secrets_fetch_trust_account_password(global_myworkgroup, trust_passwd_hash, &lct)) {
       DEBUG(0,("process: unable to read the machine account password for \
 machine %s in domain %s.\n", global_myname, global_myworkgroup ));
+      secrets_lock_trust_account_password(global_myworkgroup, False);
       return True;
     }
 
@@ -1173,6 +1173,7 @@ machine %s in domain %s.\n", global_myname, global_myworkgroup ));
 
     if(t < lct + lp_machine_password_timeout()) {
       global_machine_password_needs_changing = False;
+      secrets_lock_trust_account_password(global_myworkgroup, False);
       return True;
     }
 
@@ -1180,6 +1181,7 @@ machine %s in domain %s.\n", global_myname, global_myworkgroup ));
 
     change_trust_account_password( global_myworkgroup, remote_machine_list);
     global_machine_password_needs_changing = False;
+    secrets_lock_trust_account_password(global_myworkgroup, False);
   }
 
   /*
@@ -1201,6 +1203,10 @@ machine %s in domain %s.\n", global_myname, global_myworkgroup ));
   force_check_log_size();
   check_log_size();
 
+  /* Send any queued printer notify message to interested smbd's. */
+
+  print_notify_send_messages();
+
   /*
    * Modify the select timeout depending upon
    * what we have remaining in our queues.
index c6a082d7d892a7616aed49159f2bed10eda337b6..a881e135c08c1cecb4ae19f73a66e982984bed72 100644 (file)
@@ -23,7 +23,6 @@
    makes to handle specific protocols
 */
 
-
 #include "includes.h"
 
 /* look in server.c for some explanation of these variables */
@@ -40,9 +39,8 @@ unsigned int smb_echo_count = 0;
 
 extern BOOL global_encrypted_passwords_negotiated;
 
-
 /****************************************************************************
-  reply to an special message 
+ Reply to an special message.
 ****************************************************************************/
 
 int reply_special(char *inbuf,char *outbuf)
@@ -113,7 +111,7 @@ int reply_special(char *inbuf,char *outbuf)
                reload_services(True);
                reopen_logs();
 
-               claim_connection(NULL,"",MAXSTATUS,True);
+               claim_connection(NULL,"",0,True,FLAG_MSG_GENERAL|FLAG_MSG_SMBD);
 
                already_got_session = True;
                break;
@@ -141,7 +139,6 @@ int reply_special(char *inbuf,char *outbuf)
        return(outsize);
 }
 
-
 /****************************************************************************
  Reply to a tcon.
 ****************************************************************************/
@@ -307,10 +304,10 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
        return chain_reply(inbuf,outbuf,length,bufsize);
 }
 
-
 /****************************************************************************
-  reply to an unknown type
+ Reply to an unknown type.
 ****************************************************************************/
+
 int reply_unknown(char *inbuf,char *outbuf)
 {
        int type;
@@ -322,10 +319,10 @@ int reply_unknown(char *inbuf,char *outbuf)
        return(ERROR_DOS(ERRSRV,ERRunknownsmb));
 }
 
-
 /****************************************************************************
-  reply to an ioctl
+ Reply to an ioctl.
 ****************************************************************************/
+
 int reply_ioctl(connection_struct *conn,
                char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
@@ -339,8 +336,7 @@ int reply_ioctl(connection_struct *conn,
 
        DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
 
-       switch (ioctl_code)
-       {
+       switch (ioctl_code) {
            case IOCTL_QUERY_JOB_INFO:
                replysize = 32;
                break;
@@ -355,16 +351,15 @@ int reply_ioctl(connection_struct *conn,
        SSVAL(outbuf,smb_vwv6,52);        /* Offset to data */
        p = smb_buf(outbuf) + 1;          /* Allow for alignment */
 
-       switch (ioctl_code)
-       {
-           case IOCTL_QUERY_JOB_INFO:              
-          {
-               uint16 rap_jobid = pjobid_to_rap(SNUM(fsp->conn), fsp->print_jobid);
-               SSVAL(p,0,rap_jobid);             /* Job number */
-               srvstr_push(outbuf, p+2, global_myname, 15, STR_TERMINATE|STR_ASCII);
-               srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
-               break;
-          }
+       switch (ioctl_code) {
+               case IOCTL_QUERY_JOB_INFO:                  
+               {
+                       uint16 rap_jobid = pjobid_to_rap(SNUM(fsp->conn), fsp->print_jobid);
+                       SSVAL(p,0,rap_jobid);             /* Job number */
+                       srvstr_push(outbuf, p+2, global_myname, 15, STR_TERMINATE|STR_ASCII);
+                       srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
+                       break;
+               }
        }
 
        END_PROFILE(SMBioctl);
@@ -372,56 +367,56 @@ int reply_ioctl(connection_struct *conn,
 }
 
 /****************************************************************************
-  reply to a chkpth
+ Reply to a chkpth.
 ****************************************************************************/
+
 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
-  int outsize = 0;
-  int mode;
-  pstring name;
-  BOOL ok = False;
-  BOOL bad_path = False;
-  SMB_STRUCT_STAT sbuf;
-  START_PROFILE(SMBchkpth);
+       int outsize = 0;
+       int mode;
+       pstring name;
+       BOOL ok = False;
+       BOOL bad_path = False;
+       SMB_STRUCT_STAT sbuf;
+       START_PROFILE(SMBchkpth);
 
-  srvstr_pull_buf(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), STR_TERMINATE);
+       srvstr_pull_buf(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), STR_TERMINATE);
 
-  RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
+       RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
 
-  unix_convert(name,conn,0,&bad_path,&sbuf);
+       unix_convert(name,conn,0,&bad_path,&sbuf);
 
-  mode = SVAL(inbuf,smb_vwv0);
+       mode = SVAL(inbuf,smb_vwv0);
 
-  if (check_name(name,conn)) {
-    if (VALID_STAT(sbuf) || vfs_stat(conn,name,&sbuf) == 0)
-      ok = S_ISDIR(sbuf.st_mode);
-  }
+       if (check_name(name,conn)) {
+               if (VALID_STAT(sbuf) || vfs_stat(conn,name,&sbuf) == 0)
+                       ok = S_ISDIR(sbuf.st_mode);
+       }
 
-  if (!ok) {
-    /* We special case this - as when a Windows machine
-       is parsing a path is steps through the components
-       one at a time - if a component fails it expects
-       ERRbadpath, not ERRbadfile.
-     */
-    if(errno == ENOENT) {
-           return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
-    }
+       if (!ok) {
+               /* We special case this - as when a Windows machine
+                       is parsing a path is steps through the components
+                       one at a time - if a component fails it expects
+                       ERRbadpath, not ERRbadfile.
+               */
+               if(errno == ENOENT)
+                       return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
 
-    return(UNIXERROR(ERRDOS,ERRbadpath));
-  }
+               return(UNIXERROR(ERRDOS,ERRbadpath));
+       }
 
-  outsize = set_message(outbuf,0,0,True);
+       outsize = set_message(outbuf,0,0,True);
 
-  DEBUG(3,("chkpth %s mode=%d\n", name, mode));
+       DEBUG(3,("chkpth %s mode=%d\n", name, mode));
 
-  END_PROFILE(SMBchkpth);
-  return(outsize);
+       END_PROFILE(SMBchkpth);
+       return(outsize);
 }
 
-
 /****************************************************************************
-  reply to a getatr
+ Reply to a getatr.
 ****************************************************************************/
+
 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
   pstring fname;
@@ -494,10 +489,10 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
   return(outsize);
 }
 
-
 /****************************************************************************
-  reply to a setatr
+ Reply to a setatr.
 ****************************************************************************/
+
 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
   pstring fname;
@@ -543,10 +538,10 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
   return(outsize);
 }
 
-
 /****************************************************************************
-  reply to a dskattr
+ Reply to a dskattr.
 ****************************************************************************/
+
 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
        int outsize = 0;
@@ -591,11 +586,11 @@ int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_siz
        return(outsize);
 }
 
-
 /****************************************************************************
-  reply to a search
 Can be called from SMBsearch, SMBffirst or SMBfunique.
+ Reply to a search.
+ Can be called from SMBsearch, SMBffirst or SMBfunique.
 ****************************************************************************/
+
 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
   pstring mask;
@@ -673,12 +668,16 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
     if (strlen(directory) == 0)
       pstrcpy(directory,"./");
     memset((char *)status,'\0',21);
-    SCVAL(status,0,dirtype);
+    SCVAL(status,0,(dirtype & 0x1F));
   }
   else
   {
+    int status_dirtype;
     memcpy(status,p,21);
-    dirtype = CVAL(status,0) & 0x1F;
+    status_dirtype = CVAL(status,0) & 0x1F;
+    if (status_dirtype != (dirtype & 0x1F))
+      dirtype = status_dirtype;
+
     conn->dirptr = dptr_fetch(status+12,&dptr_num);      
     if (!conn->dirptr)
       goto SearchEmpty;
@@ -796,10 +795,10 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
   return(outsize);
 }
 
-
 /****************************************************************************
-  reply to a fclose (stop directory search)
+ Reply to a fclose (stop directory search).
 ****************************************************************************/
+
 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
   int outsize = 0;
@@ -838,9 +837,8 @@ int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
   return(outsize);
 }
 
-
 /****************************************************************************
-  reply to an open
+ Reply to an open.
 ****************************************************************************/
 
 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
@@ -910,10 +908,10 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
   return(outsize);
 }
 
-
 /****************************************************************************
-  reply to an open and X
+ Reply to an open and X.
 ****************************************************************************/
+
 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
 {
   pstring fname;
@@ -1019,10 +1017,10 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
   return chain_reply(inbuf,outbuf,length,bufsize);
 }
 
-
 /****************************************************************************
-  reply to a SMBulogoffX
+ Reply to a SMBulogoffX.
 ****************************************************************************/
+
 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
 {
   uint16 vuid = SVAL(inbuf,smb_uid);
@@ -1049,10 +1047,10 @@ int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,
   return chain_reply(inbuf,outbuf,length,bufsize);
 }
 
-
 /****************************************************************************
-  reply to a mknew or a create
+ Reply to a mknew or a create.
 ****************************************************************************/
+
 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
   pstring fname;
@@ -1122,10 +1120,10 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
   return(outsize);
 }
 
-
 /****************************************************************************
-  reply to a create temporary file
+ Reply to a create temporary file.
 ****************************************************************************/
+
 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
   pstring fname;
@@ -1433,6 +1431,59 @@ void fail_readraw(void)
        exit_server(errstr);
 }
 
+/****************************************************************************
+ Use sendfile in readbraw.
+****************************************************************************/
+
+void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
+               ssize_t mincount, char *outbuf)
+{
+       ssize_t ret=0;
+
+#if defined(WITH_SENDFILE)
+       /*
+        * We can only use sendfile on a non-chained packet and on a file
+        * that is exclusively oplocked. reply_readbraw has already checked the length.
+        */
+
+       if ((nread > 0) && (lp_write_cache_size(SNUM(conn)) == 0) &&
+                       EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && lp_use_sendfile(SNUM(conn)) ) {
+               DATA_BLOB header;
+
+               _smb_setlen(outbuf,nread);
+               header.data = outbuf;
+               header.length = 4;
+               header.free = NULL;
+
+               if ( conn->vfs_ops.sendfile( smbd_server_fd(), fsp, fsp->fd, &header, startpos, nread) == -1) {
+                       /*
+                        * Special hack for broken Linux with no 64 bit clean sendfile. If we
+                        * return ENOSYS then pretend we just got a normal read.
+                        */
+                       if (errno == ENOSYS)
+                               goto normal_read;
+
+                       DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
+                               fsp->fsp_name, strerror(errno) ));
+                       exit_server("send_file_readbraw sendfile failed");
+               }
+
+       }
+
+  normal_read:
+#endif
+
+       if (nread > 0) {
+               ret = read_file(fsp,outbuf+4,startpos,nread);
+               if (ret < mincount)
+                       ret = 0;
+       }
+
+       _smb_setlen(outbuf,ret);
+       if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
+               fail_readraw();
+}
+
 /****************************************************************************
  Reply to a readbraw (core+ protocol).
 ****************************************************************************/
@@ -1443,7 +1494,6 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s
        size_t nread = 0;
        SMB_OFF_T startpos;
        char *header = outbuf;
-       ssize_t ret=0;
        files_struct *fsp;
        START_PROFILE(SMBreadbraw);
 
@@ -1547,15 +1597,7 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s
        DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos,
                                (int)maxcount, (int)mincount, (int)nread ) );
   
-       if (nread > 0) {
-               ret = read_file(fsp,header+4,startpos,nread);
-               if (ret < mincount)
-                       ret = 0;
-       }
-
-       _smb_setlen(header,ret);
-       if (write_data(smbd_server_fd(),header,4+ret) != 4+ret)
-               fail_readraw();
+       send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf);
 
        DEBUG(5,("readbraw finished\n"));
        END_PROFILE(SMBreadbraw);
@@ -1563,8 +1605,9 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s
 }
 
 /****************************************************************************
-  reply to a lockread (core+ protocol)
+ Reply to a lockread (core+ protocol).
 ****************************************************************************/
+
 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
 {
        ssize_t nread = -1;
@@ -1599,15 +1642,16 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length
                         (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK);
 
        if (NT_STATUS_V(status)) {
-               if (lp_blocking_locks(SNUM(conn))) {
+               if (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, -1, 0))
+                       if(push_blocking_lock_request(inbuf, length, -1, 0)) {
                                END_PROFILE(SMBlockread);
-                       return -1;
+                               return -1;
+                       }
                }
                END_PROFILE(SMBlockread);
                return ERROR_NT(status);
@@ -1632,132 +1676,209 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length
        return(outsize);
 }
 
-
 /****************************************************************************
-  reply to a read
+ Reply to a read.
 ****************************************************************************/
 
 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
 {
-  size_t numtoread;
-  ssize_t nread = 0;
-  char *data;
-  SMB_OFF_T startpos;
-  int outsize = 0;
-  files_struct *fsp = file_fsp(inbuf,smb_vwv0);
-  START_PROFILE(SMBread);
-
-  CHECK_FSP(fsp,conn);
-  CHECK_READ(fsp);
+       size_t numtoread;
+       ssize_t nread = 0;
+       char *data;
+       SMB_OFF_T startpos;
+       int outsize = 0;
+       files_struct *fsp = file_fsp(inbuf,smb_vwv0);
+       START_PROFILE(SMBread);
 
-  numtoread = SVAL(inbuf,smb_vwv1);
-  startpos = IVAL(inbuf,smb_vwv2);
+       CHECK_FSP(fsp,conn);
+       CHECK_READ(fsp);
 
+       numtoread = SVAL(inbuf,smb_vwv1);
+       startpos = IVAL(inbuf,smb_vwv2);
 
-  outsize = set_message(outbuf,5,3,True);
-  numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
-  data = smb_buf(outbuf) + 3;
+       outsize = set_message(outbuf,5,3,True);
+       numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
+       data = smb_buf(outbuf) + 3;
   
-  if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
-    END_PROFILE(SMBread);
-    return ERROR_DOS(ERRDOS,ERRlock);
-  }
+       if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
+               END_PROFILE(SMBread);
+               return ERROR_DOS(ERRDOS,ERRlock);
+       }
 
-  if (numtoread > 0)
-    nread = read_file(fsp,data,startpos,numtoread);
+       if (numtoread > 0)
+               nread = read_file(fsp,data,startpos,numtoread);
 
-  if (nread < 0) {
-    END_PROFILE(SMBread);
-    return(UNIXERROR(ERRDOS,ERRnoaccess));
-  }
+       if (nread < 0) {
+               END_PROFILE(SMBread);
+               return(UNIXERROR(ERRDOS,ERRnoaccess));
+       }
   
-  outsize += nread;
-  SSVAL(outbuf,smb_vwv0,nread);
-  SSVAL(outbuf,smb_vwv5,nread+3);
-  SCVAL(smb_buf(outbuf),0,1);
-  SSVAL(smb_buf(outbuf),1,nread);
+       outsize += nread;
+       SSVAL(outbuf,smb_vwv0,nread);
+       SSVAL(outbuf,smb_vwv5,nread+3);
+       SCVAL(smb_buf(outbuf),0,1);
+       SSVAL(smb_buf(outbuf),1,nread);
   
-  DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
-            fsp->fnum, (int)numtoread, (int)nread ) );
+       DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
+               fsp->fnum, (int)numtoread, (int)nread ) );
 
-  END_PROFILE(SMBread);
-  return(outsize);
+       END_PROFILE(SMBread);
+       return(outsize);
 }
 
+/****************************************************************************
+ Reply to a read and X - possibly using sendfile.
+****************************************************************************/
+
+int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length, 
+               files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
+{
+       ssize_t nread = -1;
+       char *data = smb_buf(outbuf);
+
+#if defined(WITH_SENDFILE)
+       /*
+        * We can only use sendfile on a non-chained packet and on a file
+        * that is exclusively oplocked.
+        */
+
+       if ((CVAL(inbuf,smb_vwv0) == 0xFF) && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) &&
+                       lp_use_sendfile(SNUM(conn)) && (lp_write_cache_size(SNUM(conn)) == 0) ) {
+               SMB_STRUCT_STAT sbuf;
+               DATA_BLOB header;
+
+               if(vfs_fstat(fsp,fsp->fd, &sbuf) == -1)
+                       return(UNIXERROR(ERRDOS,ERRnoaccess));
+
+               if (startpos > sbuf.st_size)
+                       goto normal_read;
+
+               if (smb_maxcnt > (sbuf.st_size - startpos))
+                       smb_maxcnt = (sbuf.st_size - startpos);
+
+               if (smb_maxcnt == 0)
+                       goto normal_read;
+
+               /* 
+                * Set up the packet header before send. We
+                * assume here the sendfile will work (get the
+                * correct amount of data).
+                */
+
+               SSVAL(outbuf,smb_vwv5,smb_maxcnt);
+               SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
+               SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
+               SCVAL(outbuf,smb_vwv0,0xFF);
+               set_message(outbuf,12,smb_maxcnt,False);
+               header.data = outbuf;
+               header.length = data - outbuf;
+               header.free = NULL;
+
+               if ( conn->vfs_ops.sendfile( smbd_server_fd(), fsp, fsp->fd, &header, startpos, smb_maxcnt) == -1) {
+                       /*
+                        * Special hack for broken Linux with no 64 bit clean sendfile. If we
+                        * return ENOSYS then pretend we just got a normal read.
+                        */
+                       if (errno == ENOSYS)
+                               goto normal_read;
+
+                       DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
+                               fsp->fsp_name, strerror(errno) ));
+                       exit_server("send_file_readX sendfile failed");
+               }
+
+               DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
+                       fsp->fnum, (int)smb_maxcnt, (int)nread ) );
+               return -1;
+       }
+
+  normal_read:
+
+#endif
+
+       nread = read_file(fsp,data,startpos,smb_maxcnt);
+  
+       if (nread < 0) {
+               END_PROFILE(SMBreadX);
+               return(UNIXERROR(ERRDOS,ERRnoaccess));
+       }
+
+       SSVAL(outbuf,smb_vwv5,nread);
+       SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
+       SSVAL(smb_buf(outbuf),-2,nread);
+  
+       DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
+               fsp->fnum, (int)smb_maxcnt, (int)nread ) );
+
+       return nread;
+}
 
 /****************************************************************************
-  reply to a read and X
+ Reply to a read and X.
 ****************************************************************************/
+
 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
 {
-  files_struct *fsp = file_fsp(inbuf,smb_vwv2);
-  SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
-  size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
-  size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
-  ssize_t nread = -1;
-  char *data;
-  START_PROFILE(SMBreadX);
+       files_struct *fsp = file_fsp(inbuf,smb_vwv2);
+       SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
+       ssize_t nread = -1;
+       size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
+#if 0
+       size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
+#endif
 
-  /* If it's an IPC, pass off the pipe handler. */
-  if (IS_IPC(conn)) {
-    END_PROFILE(SMBreadX);
-    return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
-  }
+       START_PROFILE(SMBreadX);
 
-  CHECK_FSP(fsp,conn);
-  CHECK_READ(fsp);
+       /* If it's an IPC, pass off the pipe handler. */
+       if (IS_IPC(conn)) {
+               END_PROFILE(SMBreadX);
+               return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
+       }
+
+       CHECK_FSP(fsp,conn);
+       CHECK_READ(fsp);
 
-  set_message(outbuf,12,0,True);
-  data = smb_buf(outbuf);
+       set_message(outbuf,12,0,True);
 
-  if(CVAL(inbuf,smb_wct) == 12) {
+       if(CVAL(inbuf,smb_wct) == 12) {
 #ifdef LARGE_SMB_OFF_T
-    /*
-     * This is a large offset (64 bit) read.
-     */
-    startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
+               /*
+                * This is a large offset (64 bit) read.
+                */
+               startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
 
 #else /* !LARGE_SMB_OFF_T */
 
-    /*
-     * Ensure we haven't been sent a >32 bit offset.
-     */
+               /*
+                * Ensure we haven't been sent a >32 bit offset.
+                */
 
-    if(IVAL(inbuf,smb_vwv10) != 0) {
-      DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
+               if(IVAL(inbuf,smb_vwv10) != 0) {
+                       DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
-      END_PROFILE(SMBreadX);
-      return ERROR_DOS(ERRDOS,ERRbadaccess);
-    }
+                       END_PROFILE(SMBreadX);
+                       return ERROR_DOS(ERRDOS,ERRbadaccess);
+               }
 
 #endif /* LARGE_SMB_OFF_T */
 
-  }
+       }
 
-  if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
-    END_PROFILE(SMBreadX);
-    return ERROR_DOS(ERRDOS,ERRlock);
-  }
-  nread = read_file(fsp,data,startpos,smb_maxcnt);
+       if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
+               END_PROFILE(SMBreadX);
+               return ERROR_DOS(ERRDOS,ERRlock);
+       }
 
-  if (nread < 0) {
-    END_PROFILE(SMBreadX);
-    return(UNIXERROR(ERRDOS,ERRnoaccess));
-  }
-  
-  SSVAL(outbuf,smb_vwv5,nread);
-  SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
-  SSVAL(smb_buf(outbuf),-2,nread);
-  
-  DEBUG( 3, ( "readX fnum=%d min=%d max=%d nread=%d\n",
-             fsp->fnum, (int)smb_mincnt, (int)smb_maxcnt, (int)nread ) );
+       nread = send_file_readX(conn, inbuf, outbuf, length, fsp, startpos, smb_maxcnt);
+       if (nread != -1)
+               nread = chain_reply(inbuf,outbuf,length,bufsize);
 
-  END_PROFILE(SMBreadX);
-  return chain_reply(inbuf,outbuf,length,bufsize);
+       END_PROFILE(SMBreadX);
+       return nread;
 }
 
 /****************************************************************************
-  reply to a writebraw (core+ or LANMAN1.0 protocol)
+ Reply to a writebraw (core+ or LANMAN1.0 protocol).
 ****************************************************************************/
 
 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
@@ -1888,7 +2009,7 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size,
 }
 
 /****************************************************************************
-  reply to a writeunlock (core+)
+ Reply to a writeunlock (core+).
 ****************************************************************************/
 
 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf, 
@@ -1950,7 +2071,6 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
        return outsize;
 }
 
-
 /****************************************************************************
  Reply to a write.
 ****************************************************************************/
@@ -2029,10 +2149,10 @@ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int d
        return(outsize);
 }
 
-
 /****************************************************************************
-  reply to a write and X
+ Reply to a write and X.
 ****************************************************************************/
+
 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
 {
   files_struct *fsp = file_fsp(inbuf,smb_vwv2);
@@ -2129,9 +2249,8 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng
   return chain_reply(inbuf,outbuf,length,bufsize);
 }
 
-
 /****************************************************************************
-  reply to a lseek
+ Reply to a lseek.
 ****************************************************************************/
 
 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
@@ -2212,7 +2331,7 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int
 }
 
 /****************************************************************************
-  reply to a flush
+ Reply to a flush.
 ****************************************************************************/
 
 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
@@ -2234,10 +2353,10 @@ int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int
        return(outsize);
 }
 
-
 /****************************************************************************
-  reply to a exit
+ Reply to a exit.
 ****************************************************************************/
+
 int reply_exit(connection_struct *conn, 
               char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
@@ -2251,10 +2370,10 @@ int reply_exit(connection_struct *conn,
        return(outsize);
 }
 
-
 /****************************************************************************
  Reply to a close - has to deal with closing a directory opened by NT SMB's.
 ****************************************************************************/
+
 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
                 int dum_buffsize)
 {
@@ -2336,9 +2455,8 @@ int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
        return(outsize);
 }
 
-
 /****************************************************************************
-  reply to a writeclose (Core+ protocol)
+ Reply to a writeclose (Core+ protocol).
 ****************************************************************************/
 
 int reply_writeclose(connection_struct *conn,
@@ -2395,10 +2513,10 @@ int reply_writeclose(connection_struct *conn,
        return(outsize);
 }
 
-
 /****************************************************************************
-  reply to a lock
+ Reply to a lock.
 ****************************************************************************/
+
 int reply_lock(connection_struct *conn,
               char *inbuf,char *outbuf, int length, int dum_buffsize)
 {
@@ -2420,7 +2538,7 @@ int reply_lock(connection_struct *conn,
 
        status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK);
        if (NT_STATUS_V(status)) {
-               if (lp_blocking_locks(SNUM(conn))) {
+               if (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
@@ -2439,10 +2557,10 @@ int reply_lock(connection_struct *conn,
        return(outsize);
 }
 
-
 /****************************************************************************
-  reply to a unlock
+ Reply to a unlock.
 ****************************************************************************/
+
 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size, 
                 int dum_buffsize)
 {
@@ -2470,10 +2588,10 @@ int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
        return(outsize);
 }
 
-
 /****************************************************************************
-  reply to a tdis
+ Reply to a tdis.
 ****************************************************************************/
+
 int reply_tdis(connection_struct *conn, 
               char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
@@ -2497,11 +2615,10 @@ int reply_tdis(connection_struct *conn,
        return outsize;
 }
 
-
-
 /****************************************************************************
-  reply to a echo
+ Reply to a echo.
 ****************************************************************************/
+
 int reply_echo(connection_struct *conn,
               char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
@@ -2539,10 +2656,10 @@ int reply_echo(connection_struct *conn,
        return -1;
 }
 
-
 /****************************************************************************
-  reply to a printopen
+ Reply to a printopen.
 ****************************************************************************/
+
 int reply_printopen(connection_struct *conn, 
                    char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
@@ -2573,9 +2690,8 @@ int reply_printopen(connection_struct *conn,
        return(outsize);
 }
 
-
 /****************************************************************************
-  reply to a printclose
+ Reply to a printclose.
 ****************************************************************************/
 int reply_printclose(connection_struct *conn,
                     char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
@@ -2607,10 +2723,10 @@ int reply_printclose(connection_struct *conn,
        return(outsize);
 }
 
-
 /****************************************************************************
-  reply to a printqueue
+ Reply to a printqueue.
 ****************************************************************************/
+
 int reply_printqueue(connection_struct *conn,
                     char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
@@ -2678,10 +2794,10 @@ int reply_printqueue(connection_struct *conn,
        return(outsize);
 }
 
-
 /****************************************************************************
-  reply to a printwrite
+ Reply to a printwrite.
 ****************************************************************************/
+
 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
   int numtowrite;
@@ -2712,11 +2828,11 @@ int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_
   return(outsize);
 }
 
-
 /****************************************************************************
  The guts of the mkdir command, split out so it may be called by the NT SMB
  code. 
 ****************************************************************************/
+
 NTSTATUS mkdir_internal(connection_struct *conn, pstring directory)
 {
        BOOL bad_path = False;
@@ -2939,10 +3055,10 @@ int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
   return(outsize);
 }
 
-
 /*******************************************************************
-resolve wildcards in a filename rename
+ Resolve wildcards in a filename rename.
 ********************************************************************/
+
 static BOOL resolve_wildcards(char *name1,char *name2)
 {
   fstring root1,root2;
@@ -3378,8 +3494,9 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
 }
 
 /****************************************************************************
-  reply to a file copy.
-  ****************************************************************************/
+ Reply to a file copy.
+****************************************************************************/
+
 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
   int outsize = 0;
@@ -3542,8 +3659,9 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
 }
 
 /****************************************************************************
-  reply to a setdir
+ Reply to a setdir.
 ****************************************************************************/
+
 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
 {
   int snum;
@@ -3637,6 +3755,7 @@ SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format
 /****************************************************************************
  Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
 ****************************************************************************/
+
 static uint32 map_lock_offset(uint32 high, uint32 low)
 {
        unsigned int i;
@@ -3716,7 +3835,7 @@ SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_forma
 }
 
 /****************************************************************************
-  reply to a lockingX request
+ Reply to a lockingX request.
 ****************************************************************************/
 
 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
@@ -3827,7 +3946,7 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
 
        /* Setup the timeout in seconds. */
 
-       lock_timeout = ((lock_timeout == -1) ? -1 : lock_timeout/1000);
+       lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+999)/1000);
        
        /* Now do any requested locks */
        data += ((large_file_format ? 20 : 10)*num_ulocks);
@@ -3855,7 +3974,7 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
                status = do_lock_spin(fsp,conn,lock_pid, count,offset, 
                                 ((locktype & 1) ? READ_LOCK : WRITE_LOCK));
                if (NT_STATUS_V(status)) {
-                       if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn))) {
+                       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
index bdcdce6e14509225d4625774d1c46a83d053b18c..411ece52495c5f80b615147ad7fba289c0a1829b 100644 (file)
@@ -287,17 +287,8 @@ void set_sec_ctx(uid_t uid, gid_t gid, int ngroups, gid_t *groups, NT_USER_TOKEN
        DEBUG(3, ("setting sec ctx (%u, %u) - sec_ctx_stack_ndx = %d\n", 
                (unsigned int)uid, (unsigned int)gid, sec_ctx_stack_ndx));
 
-       if (ngroups) {
-               int i;
-
-               DEBUG(3, ("%d user groups: \n", ngroups));
-               for (i = 0; i < ngroups; i++) {
-                       DEBUGADD(3, ("%u ", (unsigned int)groups[i]));
-               }
-
-               DEBUG(3, ("\n"));
-       }
-       
+       debug_nt_user_token(DBGC_CLASS, 5, token);
+       debug_unix_user_token(DBGC_CLASS, 5, uid, gid, ngroups, groups);
 
        gain_root();
 
index b2b905cec3542fd8f59f83b62433309b149bffcb..39d5e3bcd3f75922aab515e50b06574a31d69405 100644 (file)
@@ -33,6 +33,8 @@ int last_message = -1;
 #define LAST_MESSAGE() smb_fn_name(last_message)
 
 extern pstring user_socket_options;
+extern SIG_ATOMIC_T got_sig_term;
+extern SIG_ATOMIC_T reload_after_sighup;
 
 #ifdef WITH_DFS
 extern int dcelogin_atmost_once;
@@ -61,8 +63,6 @@ static void smbd_set_server_fd(int fd)
  Terminate signal.
 ****************************************************************************/
 
-SIG_ATOMIC_T got_sig_term = 0;
-
 static void sig_term(void)
 {
        got_sig_term = 1;
@@ -73,8 +73,6 @@ static void sig_term(void)
  Catch a sighup.
 ****************************************************************************/
 
-SIG_ATOMIC_T reload_after_sighup = 0;
-
 static void sig_hup(int sig)
 {
        reload_after_sighup = 1;
@@ -542,6 +540,8 @@ void exit_server(char *reason)
 
        invalidate_all_vuids();
 
+       print_notify_send_messages();   
+
        /* delete our entry in the connections database. */
        yield_connection(NULL,"");
 
@@ -860,7 +860,7 @@ static void usage(char *pname)
        register_dmalloc_msgs();
 
        /* Setup the main smbd so that we can get messages. */
-       claim_connection(NULL,"",0,True);
+       claim_connection(NULL,"",0,True,FLAG_MSG_GENERAL|FLAG_MSG_SMBD);
 
        /* 
           DO NOT ENABLE THIS TILL YOU COPE WITH KILLING THESE TASKS AND INETD
index 6f83a2d3b75ce22d5302ddd2c33d795057921280..a8a590da804404f597d65b5eefd042b6d35b8e1e 100644 (file)
@@ -305,6 +305,7 @@ static void set_admin_user(connection_struct *conn)
 #endif
            ) {
                conn->admin_user = True;
+               conn->force_user = True;  /* Admin users are effectivly 'forced' */
                DEBUG(0,("%s logged in as admin user (root privileges)\n",conn->user));
        } else {
                conn->admin_user = False;
@@ -329,7 +330,6 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
 {
        struct passwd *pass = NULL;
        BOOL guest = False;
-       BOOL force = False;
        connection_struct *conn;
        struct stat st;
        fstring user;
@@ -349,7 +349,6 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
        if (lp_guest_only(snum)) {
                const char *guestname = lp_guestaccount();
                guest = True;
-               force = True;
                pass = getpwnam_alloc(guestname);
                if (!pass) {
                        DEBUG(0,("authorise_login: Invalid guest account %s??\n",guestname));
@@ -397,7 +396,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
                        return NULL;
                }
                pass = Get_Pwnam(user);
-               conn->force_user = force;
+               conn->force_user = True;
                conn->uid = pass->pw_uid;
                conn->gid = pass->pw_gid;
                string_set(&conn->user, pass->pw_name);
@@ -434,7 +433,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
 
        /*
         * If force user is true, then store the
-        * given userid and also the primary groupid
+        * given userid and also the groups
         * of the user we're forcing.
         */
        
@@ -492,6 +491,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
                gid = nametogid(gname);
                
                if (gid != (gid_t)-1) {
+
                        /*
                         * If the user has been forced and the forced group starts
                         * with a '+', then we only set the group to be the forced
@@ -507,6 +507,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
                                conn->gid = gid;
                                DEBUG(3,("Forced group %s\n",gname));
                        }
+                       conn->force_group = True;
                } else {
                        DEBUG(1,("Couldn't find group %s\n",gname));
                        conn_free(conn);
@@ -524,23 +525,27 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
                DEBUG(3,("Connect path is '%s' for service [%s]\n",s, lp_servicename(snum)));
        }
 
-       /* groups stuff added by ih */
-       conn->ngroups = 0;
-       conn->groups = NULL;
-       
-       /* Find all the groups this uid is in and
-          store them. Used by change_to_user() */
-       initialise_groups(conn->user, conn->uid, conn->gid); 
-       get_current_groups(conn->gid, &conn->ngroups,&conn->groups);
+       if (conn->force_user || conn->force_group) {
+
+               /* groups stuff added by ih */
+               conn->ngroups = 0;
+               conn->groups = NULL;
+               
+               /* Find all the groups this uid is in and
+                  store them. Used by change_to_user() */
+               initialise_groups(conn->user, conn->uid, conn->gid); 
+               get_current_groups(conn->gid, &conn->ngroups,&conn->groups);
                
-       conn->nt_user_token = create_nt_token(conn->uid, conn->gid, 
-                                             conn->ngroups, conn->groups,
-                                             guest, NULL);
+               conn->nt_user_token = create_nt_token(conn->uid, conn->gid, 
+                                                     conn->ngroups, conn->groups,
+                                                     guest);
+       }
 
        /*
         * New code to check if there's a share security descripter
         * added from NT server manager. This is done after the
         * smb.conf checks are done as we need a uid and token. JRA.
+        *
         */
 
        {
@@ -573,7 +578,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
        if (!claim_connection(conn,
                              lp_servicename(SNUM(conn)),
                              lp_max_connections(SNUM(conn)),
-                             False)) {
+                             False,0)) {
                DEBUG(1,("too many connections - rejected\n"));
                conn_free(conn);
                *status = NT_STATUS_INSUFFICIENT_RESOURCES;
@@ -803,7 +808,7 @@ connection_struct *make_connection(const char *service_in, DATA_BLOB password,
        } else if ((lp_security() != SEC_SHARE) && (vuser->homes_snum != -1)
                   && strequal(service_in, lp_servicename(vuser->homes_snum))) {
                DATA_BLOB no_pw = data_blob(NULL, 0);
-               DEBUG(5, ("making a connection to 'homes' service [%s] created at session setup time\n", service));
+               DEBUG(5, ("making a connection to 'homes' service [%s] created at session setup time\n", service_in));
                return make_connection_snum(vuser->homes_snum,
                                            vuser, no_pw, 
                                            dev, status);
index 77f93812dd545f36260136de0fa28423303f610a..b9af7200089aba2c103afc15e505b769be9bb696 100644 (file)
@@ -160,12 +160,12 @@ static int reply_spnego_kerberos(connection_struct *conn,
        ads_destroy(&ads);
 
        /* the password is good - let them in */
-       pw = smb_getpwnam(user,False);
+       pw = Get_Pwnam(user);
        if (!pw && !strstr(user, lp_winbind_separator())) {
                char *user2;
                /* try it with a winbind domain prefix */
                asprintf(&user2, "%s%s%s", lp_workgroup(), lp_winbind_separator(), user);
-               pw = smb_getpwnam(user2,False);
+               pw = Get_Pwnam(user2);
                if (pw) {
                        free(user);
                        user = user2;
@@ -177,9 +177,9 @@ static int reply_spnego_kerberos(connection_struct *conn,
                return ERROR_NT(NT_STATUS_NO_SUCH_USER);
        }
 
-       if (!make_server_info_pw(&server_info,pw)) {
+       if (!NT_STATUS_IS_OK(ret = make_server_info_pw(&server_info,pw))) {
                DEBUG(1,("make_server_info_from_pw failed!\n"));
-               return ERROR_NT(NT_STATUS_NO_MEMORY);
+               return ERROR_NT(ret);
        }
        
        sess_vuid = register_vuid(server_info, user);
@@ -294,8 +294,6 @@ static int reply_spnego_negotiate(connection_struct *conn,
                return ERROR_NT(NT_STATUS_LOGON_FAILURE);
        }
 
-       DEBUG(3,("Got neg_flags=0x%08x\n", neg_flags));
-
        debug_ntlmssp_flags(neg_flags);
 
        if (ntlmssp_auth_context) {
@@ -324,12 +322,12 @@ static int reply_spnego_negotiate(connection_struct *conn,
                          "U",
                          lp_workgroup());
 
-               fstrcpy(dnsdomname, lp_realm());
+               fstrcpy(dnsdomname, (SEC_ADS == lp_security())?lp_realm():"");
                strlower(dnsdomname);
 
                fstrcpy(dnsname, global_myname);
                fstrcat(dnsname, ".");
-               fstrcat(dnsname, lp_realm());
+               fstrcat(dnsname, dnsdomname);
                strlower(dnsname);
 
                msrpc_gen(&struct_blob, "aaaaa",
@@ -441,14 +439,14 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
                auth_flags |= AUTH_FLAG_NTLM_RESP;
        } else if (nthash.length > 24) {
                auth_flags |= AUTH_FLAG_NTLMv2_RESP;
-       }
+       };
+
+       nt_status = make_user_info_map(&user_info, user, workgroup, machine, 
+                                      lmhash, nthash, plaintext_password, 
+                                      auth_flags, True);
 
-       if (!make_user_info_map(&user_info, 
-                               user, workgroup, 
-                               machine, 
-                               lmhash, nthash,
-                               plaintext_password, 
-                               auth_flags, True)) {
+       /* it looks a bit weird, but this function returns int type... */
+       if (!NT_STATUS_IS_OK(nt_status)) {
                return ERROR_NT(NT_STATUS_NO_MEMORY);
        }
 
@@ -623,7 +621,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
        NTSTATUS nt_status;
 
        BOOL doencrypt = global_encrypted_passwords_negotiated;
-
+       
        START_PROFILE(SMBsesssetupX);
 
        ZERO_STRUCT(lm_resp);
@@ -736,7 +734,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
        
        /* don't allow for weird usernames or domains */
        alpha_strcpy(user, user, ". _-$", sizeof(user));
-       alpha_strcpy(domain, domain, ". _-", sizeof(domain));
+       alpha_strcpy(domain, domain, ". _-@", sizeof(domain));
        if (strstr(user, "..") || strstr(domain,"..")) {
                return ERROR_NT(NT_STATUS_LOGON_FAILURE);
        }
@@ -778,11 +776,9 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
                nt_status = check_guest_password(&server_info);
 
        } else if (doencrypt) {
-               if (!make_user_info_for_reply_enc(&user_info, 
-                                                 user, domain, 
-                                                 lm_resp, nt_resp)) {
-                       nt_status = NT_STATUS_NO_MEMORY;
-               } else {
+               nt_status = make_user_info_for_reply_enc(&user_info, user, domain,
+                                                        lm_resp, nt_resp);
+               if (NT_STATUS_IS_OK(nt_status)) {
                        nt_status = negprot_global_auth_context->check_ntlm_password(negprot_global_auth_context, 
                                                                                     user_info, 
                                                                                     &server_info);
index a66c029286338e83ced354241ca853fd2ecf51a8..de65cda2d09b21d958a0a4359fef8efde3c0a294 100644 (file)
@@ -30,19 +30,26 @@ extern int global_oplock_break;
 extern uint32 global_client_caps;
 extern pstring global_myname;
 
+#define get_file_size(sbuf) (sbuf.st_size)
+
 /* given a stat buffer return the allocated size on disk, taking into
    account sparse files */
-SMB_OFF_T get_allocation_size(SMB_STRUCT_STAT *sbuf)
+SMB_OFF_T get_allocation_size(files_struct *fsp, SMB_STRUCT_STAT *sbuf)
 {
        SMB_OFF_T ret;
+#if defined(HAVE_STAT_ST_BLKSIZE) && defined(HAVE_STAT_ST_BLOCKS)
        ret = sbuf->st_blksize * (SMB_OFF_T)sbuf->st_blocks;
-       ret = SMB_ROUNDUP_ALLOCATION(ret);
+#elif defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
+       ret = (SMB_OFF_T)STAT_ST_BLOCKSIZE * (SMB_OFF_T)sbuf->st_blocks;
+#else
+       ret = get_file_size(*sbuf);
+#endif
+       if (!ret && fsp && fsp->initial_allocation_size)
+               ret = fsp->initial_allocation_size;
+       ret = SMB_ROUNDUP(ret,SMB_ROUNDUP_ALLOCATION_SIZE);
        return ret;
 }
 
-#define get_file_size(sbuf) (sbuf.st_size)
-
-
 /****************************************************************************
   Send the required number of replies back.
   We assume all fields other than the data fields are
@@ -579,7 +586,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
                        }
 
                        file_size = get_file_size(sbuf);
-                       allocation_size = get_allocation_size(&sbuf);
+                       allocation_size = get_allocation_size(NULL,&sbuf);
                        mdate = sbuf.st_mtime;
                        adate = sbuf.st_atime;
                        cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
@@ -660,6 +667,11 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
                        SIVAL(p,0,nt_extmode); p += 4;
                        q = p; p += 4;
                        SIVAL(p,0,0); p += 4;
+                       /* Clear the short name buffer. This is
+                        * IMPORTANT as not doing so will trigger
+                        * a Win2k client bug. JRA.
+                        */
+                       memset(p,'\0',26);
                        if (!was_8_3) {
                                pstring mangled_name;
                                pstrcpy(mangled_name, fname);
@@ -751,12 +763,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
                        SOFF_T(p,0,get_file_size(sbuf));             /* File size 64 Bit */
                        p+= 8;
 
-#if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
-                       SOFF_T(p,0,sbuf.st_blocks*STAT_ST_BLOCKSIZE); /* Number of bytes used on disk - 64 Bit */
-#else
-                       /* Can't get the value - fake it using size. */
-                       SOFF_T(p,0,get_file_size(sbuf));             /* Number of bytes used on disk - 64 Bit */
-#endif
+                       SOFF_T(p,0,get_allocation_size(NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
                        p+= 8;
 
                        put_long_date(p,sbuf.st_ctime);       /* Creation Time 64 Bit */
@@ -899,7 +906,11 @@ close_if_end = %d requires_resume_key = %d level = %d, max_data_bytes = %d\n",
 
        p = strrchr_m(directory,'/');
        if(p == NULL) {
-               pstrcpy(mask,directory);
+               /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
+               if((directory[0] == '.') && (directory[1] == '\0'))
+                       pstrcpy(mask,"*");
+               else
+                       pstrcpy(mask,directory);
                pstrcpy(directory,"./");
        } else {
                pstrcpy(mask,p+1);
@@ -1554,12 +1565,16 @@ static int call_trans2qfilepathinfo(connection_struct *conn,
        BOOL delete_pending = False;
        int len;
        time_t c_time;
+       files_struct *fsp = NULL;
 
        if (!params)
                return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
 
        if (tran_call == TRANSACT2_QFILEINFO) {
-               files_struct *fsp = file_fsp(params,0);
+               if (total_params < 4)
+                       return(ERROR_DOS(ERRDOS,ERRinvalidparam));
+
+               fsp = file_fsp(params,0);
                info_level = SVAL(params,2);
 
                DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
@@ -1657,7 +1672,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn,
        mode = dos_mode(conn,fname,&sbuf);
        fullpathname = fname;
        file_size = get_file_size(sbuf);
-       allocation_size = get_allocation_size(&sbuf);
+       allocation_size = get_allocation_size(fsp,&sbuf);
        if (mode & aDIR)
                file_size = 0;
 
@@ -1842,7 +1857,12 @@ static int call_trans2qfilepathinfo(connection_struct *conn,
                        break;
 
                case SMB_FILE_INTERNAL_INFORMATION:
-                       /* This should be an index number - looks like dev/ino to me :-) */
+                       /* This should be an index number - looks like
+                          dev/ino to me :-) 
+
+                          I think this causes us to fail the IFSKIT
+                          BasicFileInformationTest. -tpot */
+
                        SIVAL(pdata,0,sbuf.st_dev);
                        SIVAL(pdata,4,sbuf.st_ino);
                        data_size = 8;
@@ -1972,12 +1992,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn,
                        SOFF_T(pdata,0,get_file_size(sbuf));             /* File size 64 Bit */
                        pdata += 8;
 
-#if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
-                       SOFF_T(pdata,0,sbuf.st_blocks*STAT_ST_BLOCKSIZE); /* Number of bytes used on disk - 64 Bit */
-#else
-                       /* Can't get the value - fake it using size. */
-                       SOFF_T(pdata,0,get_file_size(sbuf));             /* Number of bytes used on disk - 64 Bit */
-#endif
+                       SOFF_T(pdata,0,get_allocation_size(fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
                        pdata += 8;
 
                        put_long_date(pdata,sbuf.st_ctime);       /* Creation Time 64 Bit */
@@ -2334,7 +2349,6 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
 
        switch (info_level) {
                case SMB_INFO_STANDARD:
-               case SMB_INFO_QUERY_EA_SIZE:
                {
                        if (total_data < l1_cbFile+4)
                                return(ERROR_DOS(ERRDOS,ERRinvalidparam));
@@ -2351,6 +2365,9 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
                        break;
                }
 
+               case SMB_INFO_SET_EA:
+                       return(ERROR_DOS(ERRDOS,ERReasnotsupported));
+
                /* XXXX um, i don't think this is right.
                        it's also not in the cifs6.txt spec.
                */
@@ -2412,11 +2429,12 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
                case SMB_SET_FILE_ALLOCATION_INFO:
                {
                        int ret = -1;
-                       SMB_OFF_T allocation_size = IVAL(pdata,0);
+                       SMB_OFF_T allocation_size;
 
                        if (total_data < 8)
                                return(ERROR_DOS(ERRDOS,ERRinvalidparam));
 
+                       allocation_size = IVAL(pdata,0);
 #ifdef LARGE_SMB_OFF_T
                        allocation_size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
 #else /* LARGE_SMB_OFF_T */
@@ -2426,6 +2444,9 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
                        DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
                                        fname, (double)allocation_size ));
 
+                       if (allocation_size)
+                               allocation_size = SMB_ROUNDUP(allocation_size,SMB_ROUNDUP_ALLOCATION_SIZE);
+
                        if(allocation_size != get_file_size(sbuf)) {
                                SMB_STRUCT_STAT new_sbuf;
  
index c0bacf8f9105cd753dbe274120d473a6c51cf35f..2bda26aa510807babafd0a87d1920fc1a1ca1d48 100644 (file)
@@ -59,18 +59,26 @@ BOOL change_to_guest(void)
 static BOOL check_user_ok(connection_struct *conn, user_struct *vuser,int snum)
 {
        int i;
-       for (i=0;i<conn->uid_cache.entries;i++)
-               if (conn->uid_cache.list[i] == vuser->uid)
+       for (i=0;i<conn->vuid_cache.entries && i< VUID_CACHE_SIZE;i++)
+               if (conn->vuid_cache.list[i] == vuser->vuid)
                        return(True);
 
+       if ((conn->force_user || conn->force_group) 
+           && (conn->vuid != vuser->vuid)) {
+               return False;
+       }
+       
        if (!user_ok(vuser->user.unix_name,snum))
                return(False);
 
-       i = conn->uid_cache.entries % UID_CACHE_SIZE;
-       conn->uid_cache.list[i] = vuser->uid;
+       if (!share_access_check(conn, snum, vuser, conn->read_only ? FILE_READ_DATA : FILE_WRITE_DATA)) {
+               return False;
+       }
+
+       i = conn->vuid_cache.entries % VUID_CACHE_SIZE;
+       conn->vuid_cache.list[i] = vuser->vuid;
 
-       if (conn->uid_cache.entries < UID_CACHE_SIZE)
-               conn->uid_cache.entries++;
+       conn->vuid_cache.entries++;
 
        return(True);
 }
@@ -115,27 +123,21 @@ BOOL change_to_user(connection_struct *conn, uint16 vuid)
 
        snum = SNUM(conn);
 
-       if((vuser != NULL) && !check_user_ok(conn, vuser, snum))
-               return False;
-
-       if (conn->force_user || 
-               conn->admin_user ||
-           (lp_security() == SEC_SHARE)) {
+       if (conn->force_user) /* security = share sets this too */ {
                uid = conn->uid;
                gid = conn->gid;
                current_user.groups = conn->groups;
                current_user.ngroups = conn->ngroups;
                token = conn->nt_user_token;
-       } else {
-               if (!vuser) {
-                       DEBUG(2,("change_to_user: Invalid vuid used %d\n",vuid));
-                       return(False);
-               }
+       } else if ((vuser) && check_user_ok(conn, vuser, snum)) {
                uid = vuser->uid;
                gid = vuser->gid;
                current_user.ngroups = vuser->n_groups;
                current_user.groups  = vuser->groups;
                token = vuser->nt_user_token;
+       } else {
+               DEBUG(2,("change_to_user: Invalid vuid used %d or vuid not permitted access to share.\n",vuid));
+               return False;
        }
 
        /*
@@ -175,7 +177,11 @@ BOOL change_to_user(connection_struct *conn, uint16 vuid)
                if (vuser && vuser->guest)
                        is_guest = True;
 
-               token = create_nt_token(uid, gid, current_user.ngroups, current_user.groups, is_guest, NULL);
+               token = create_nt_token(uid, gid, current_user.ngroups, current_user.groups, is_guest);
+               if (!token) {
+                       DEBUG(1, ("change_to_user: create_nt_token failed!\n"));
+                       return False;
+               }
                must_free_token = True;
        }
        
index 394086dc075502adf57e9c9a4f72946589501d6c..bae304096cefcf88be82e1b8500eb8c161665e20 100644 (file)
 
 #include "includes.h"
 
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_VFS
+
+
 /* Check for NULL pointer parameters in vfswrap_* functions */
 
 /* We don't want to have NULL function pointers lying around.  Someone
@@ -188,6 +192,17 @@ SMB_OFF_T vfswrap_lseek(files_struct *fsp, int filedes, SMB_OFF_T offset, int wh
        return result;
 }
 
+ssize_t vfswrap_sendfile(int tofd, struct files_struct *fsp, int fromfd, const DATA_BLOB *hdr,
+                       SMB_OFF_T offset, size_t n)
+{
+       ssize_t result;
+
+       START_PROFILE_BYTES(syscall_sendfile, n);
+       result = sys_sendfile(tofd, fromfd, hdr, offset, n);
+       END_PROFILE(syscall_sendfile);
+       return result;
+}
+
 int vfswrap_rename(connection_struct *conn, const char *old, const char *new)
 {
     int result;
index a2291eba08f9f20ea68370442482dfbc6ca39037..a0a7b920b8bb47813167b40f63a63e2a95a2c463 100644 (file)
 
 #include "includes.h"
 
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_VFS
+
+
 /* Some structures to help us initialise the vfs operations table */
 
 struct vfs_syminfo {
@@ -64,6 +68,7 @@ static struct vfs_ops default_vfs_ops = {
        vfswrap_read,
        vfswrap_write,
        vfswrap_lseek,
+       vfswrap_sendfile,
        vfswrap_rename,
        vfswrap_fsync,
        vfswrap_stat,
@@ -138,7 +143,7 @@ static void vfs_init_default(connection_struct *conn)
   initialise custom vfs hooks
 ****************************************************************************/
 
-static BOOL vfs_init_custom(connection_struct *conn, const char *vfs_object)
+BOOL vfs_init_custom(connection_struct *conn, const char *vfs_object)
 {
        int vfs_version = -1;
        vfs_op_tuple *ops, *(*init_fptr)(int *, const struct vfs_ops *, struct smb_vfs_handle_struct *);
@@ -259,6 +264,7 @@ BOOL smbd_vfs_init(connection_struct *conn)
 /*******************************************************************
  Create vfs_ops reflecting current vfs_opaque_ops
 *******************************************************************/
+
 struct vfs_ops *smb_vfs_get_opaque_ops(void)
 {
   int i;
@@ -297,6 +303,7 @@ BOOL vfs_directory_exist(connection_struct *conn, const char *dname, SMB_STRUCT_
 /*******************************************************************
  vfs getwd wrapper 
 ********************************************************************/
+
 static char *vfs_getwd(connection_struct *conn, char *path)
 {
        return conn->vfs_ops.getwd(conn,path);
index 74472854cf21c90a781c32e604ea8053f69c4ba0..2370ce3bdd93286d8c86e3f7c410a3e0ad1e37a4 100644 (file)
@@ -30,6 +30,7 @@
 #include <errno.h>
 #include <sys/stat.h>
 #include <time.h>
+#include <signal.h>
 #include "tdb.h"
 #include "spinlock.h"
 
index ed75a55e3e9739370c46f091d13481b2443c2989..5bb75ffe07792cd6eb547f0fa78805859588de64 100644 (file)
@@ -34,6 +34,7 @@
 #include <errno.h>
 #include <sys/mman.h>
 #include <sys/stat.h>
+#include <signal.h>
 #include "tdb.h"
 #include "spinlock.h"
 #else
@@ -160,6 +161,18 @@ struct list_struct {
        */
 };
 
+/***************************************************************
+ Allow a caller to set a "alarm" flag that tdb can check to abort
+ a blocking lock on SIGALRM.
+***************************************************************/
+
+static sig_atomic_t *palarm_fired;
+
+void tdb_set_lock_alarm(sig_atomic_t *palarm)
+{
+       palarm_fired = palarm;
+}
+
 /* a byte range locking function - return 0 on success
    this functions locks/unlocks 1 byte at the specified offset.
 
@@ -186,6 +199,8 @@ static int tdb_brlock(TDB_CONTEXT *tdb, tdb_off offset,
 
        do {
                ret = fcntl(tdb->fd,lck_type,&fl);
+               if (ret == -1 && errno == EINTR && palarm_fired && *palarm_fired)
+                       break;
        } while (ret == -1 && errno == EINTR);
 
        if (ret == -1) {
@@ -517,17 +532,20 @@ int tdb_printfreelist(TDB_CONTEXT *tdb)
 
        /* read in the freelist top */
        if (ofs_read(tdb, offset, &rec_ptr) == -1) {
+               tdb_unlock(tdb, -1, F_WRLCK);
                return 0;
        }
 
        printf("freelist top=[0x%08x]\n", rec_ptr );
        while (rec_ptr) {
                if (tdb_read(tdb, rec_ptr, (char *)&rec, sizeof(rec), DOCONV()) == -1) {
+                       tdb_unlock(tdb, -1, F_WRLCK);
                        return -1;
                }
 
                if (rec.magic != TDB_FREE_MAGIC) {
                        printf("bad magic 0x%08x in free list\n", rec.magic);
+                       tdb_unlock(tdb, -1, F_WRLCK);
                        return -1;
                }
 
index 8cc908703f8209f4da251f8f8086c4c920b388d5..42b88aeb161e36f3002782f19031e70e4596d28a 100644 (file)
@@ -126,6 +126,7 @@ int tdb_lockall(TDB_CONTEXT *tdb);
 void tdb_unlockall(TDB_CONTEXT *tdb);
 
 /* Low level locking functions: use with care */
+void tdb_set_lock_alarm(sig_atomic_t *palarm);
 int tdb_chainlock(TDB_CONTEXT *tdb, TDB_DATA key);
 int tdb_chainunlock(TDB_CONTEXT *tdb, TDB_DATA key);
 
index f59f98a90f52306bfe1149bef43a8742ac463413..36ba7db918824e31784f834bfec0e55e0bd0d4af 100644 (file)
@@ -53,6 +53,7 @@
 #include <sys/stat.h>
 #include <sys/time.h>
 #include <ctype.h>
+#include <signal.h>
 #include "tdb.h"
 
 static int failed;
index 66642132093c85a10782578f65a20df8377cbc2d..9c1dc2761b67d9bb6af9879d798e4d6df89eb662 100644 (file)
@@ -30,6 +30,7 @@
 #include <sys/stat.h>
 #include <sys/time.h>
 #include <ctype.h>
+#include <signal.h>
 #include "tdb.h"
 
 static void print_data(TDB_DATA d)
index 0741073ce116ffbb49c620e5edb8f6b794e764c6..89295a3291f6a15d3c34be61f067fbc801dcb153 100644 (file)
@@ -8,6 +8,7 @@
 #include <sys/mman.h>
 #include <sys/stat.h>
 #include <sys/time.h>
+#include <signal.h>
 #include "tdb.h"
 #include <gdbm.h>
 
index ba0fb48957d78cd25cda5f38c1bc89c2e0250a78..f529c6e6eebe51107a8c2965e6024619a86d58ef 100644 (file)
@@ -33,6 +33,7 @@
 #include <sys/stat.h>
 #include <sys/time.h>
 #include <ctype.h>
+#include <signal.h>
 #include "tdb.h"
 
 /* a tdb tool for manipulating a tdb database */
index 101f4071cbb5149f33766c69a7d80a69598514ab..fb62b13657fe5d380fbef035355fa905d95338b4 100644 (file)
@@ -785,6 +785,7 @@ static BOOL run_locktest1(int dummy)
        char *fname = "\\lockt1.lck";
        int fnum1, fnum2, fnum3;
        time_t t1, t2;
+       unsigned lock_timeout;
 
        if (!torture_open_connection(&cli1) || !torture_open_connection(&cli2)) {
                return False;
@@ -827,9 +828,10 @@ static BOOL run_locktest1(int dummy)
        }
 
 
-       printf("Testing lock timeouts\n");
+       lock_timeout = (1 + (random() % 20));
+       printf("Testing lock timeout with timeout=%u\n", lock_timeout);
        t1 = time(NULL);
-       if (cli_lock(&cli2, fnum3, 0, 4, 10*1000, WRITE_LOCK)) {
+       if (cli_lock(&cli2, fnum3, 0, 4, lock_timeout * 1000, WRITE_LOCK)) {
                printf("lock3 succeeded! This is a locking bug\n");
                return False;
        } else {
@@ -841,6 +843,8 @@ static BOOL run_locktest1(int dummy)
        if (t2 - t1 < 5) {
                printf("error: This server appears not to support timed lock requests\n");
        }
+       printf("server slept for %u seconds for a %u second timeout\n",
+              (unsigned int)(t2-t1), lock_timeout);
 
        if (!cli_close(&cli1, fnum2)) {
                printf("close1 failed (%s)\n", cli_errstr(&cli1));
@@ -3413,6 +3417,52 @@ static BOOL run_opentest(int dummy)
 
        cli_unlink(&cli1, fname);
 
+       /* Test 8 - attributes test test... */
+       fnum1 = cli_nt_create_full(&cli1, fname,FILE_WRITE_DATA, FILE_ATTRIBUTE_HIDDEN,
+                                  FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0);
+
+       if (fnum1 == -1) {
+               printf("test 8 open 1 of %s failed (%s)\n", fname, cli_errstr(&cli1));
+               return False;
+       }
+
+       if (!cli_close(&cli1, fnum1)) {
+               printf("test 8 close 1 of %s failed (%s)\n", fname, cli_errstr(&cli1));
+               return False;
+       }
+
+       /* FILE_SUPERSEDE && FILE_OVERWRITE_IF have the same effect here. */
+       fnum1 = cli_nt_create_full(&cli1, fname,FILE_READ_DATA, FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_NORMAL,
+                                  FILE_SHARE_NONE, FILE_OVERWRITE_IF, 0);
+
+       if (fnum1 == -1) {
+               printf("test 8 open 2 of %s failed (%s)\n", fname, cli_errstr(&cli1));
+               return False;
+       }
+
+       if (!cli_close(&cli1, fnum1)) {
+               printf("test 8 close 2 of %s failed (%s)\n", fname, cli_errstr(&cli1));
+               return False;
+       }
+
+       /* This open should fail with ACCESS_DENIED for FILE_SUPERSEDE, FILE_OVERWRITE and FILE_OVERWRITE_IF. */
+       fnum1 = cli_nt_create_full(&cli1, fname,FILE_READ_DATA, FILE_ATTRIBUTE_NORMAL,
+                                  FILE_SHARE_NONE, FILE_OVERWRITE, 0);
+
+       if (fnum1 != -1) {
+               printf("test 8 open 3 of %s succeeded - should have failed with (NT_STATUS_ACCESS_DENIED)\n", fname);
+               correct = False;
+               cli_close(&cli1, fnum1);
+       } else {
+               if (check_error(__LINE__, &cli1, ERRDOS, ERRnoaccess, NT_STATUS_ACCESS_DENIED)) {
+                       printf("correct error code NT_STATUS_ACCESS_DENIED/ERRDOS:ERRnoaccess returned\n");
+               }
+       }
+
+       printf("Attribute open test #8 %s.\n", correct ? "passed" : "failed");
+
+       cli_unlink(&cli1, fname);
+
        if (!torture_close_connection(&cli1)) {
                correct = False;
        }
@@ -3483,6 +3533,105 @@ static BOOL run_dirtest(int dummy)
        return correct;
 }
 
+static void del_fn(file_info *finfo, const char *mask, void *state)
+{
+       struct cli_state *pcli = (struct cli_state *)state;
+       fstring fname;
+       slprintf(fname, sizeof(fname), "\\LISTDIR\\%s", finfo->name);
+
+       if (strcmp(finfo->name, ".") == 0 || strcmp(finfo->name, "..") == 0)
+               return;
+
+       if (finfo->mode & aDIR) {
+               if (!cli_rmdir(pcli, fname))
+                       printf("del_fn: failed to rmdir %s\n,", fname );
+       } else {
+               if (!cli_unlink(pcli, fname))
+                       printf("del_fn: failed to unlink %s\n,", fname );
+       }
+}
+
+static BOOL run_dirtest1(int dummy)
+{
+       int i;
+       static struct cli_state cli;
+       int fnum, num_seen;
+       BOOL correct = True;
+
+       printf("starting directory test\n");
+
+       if (!torture_open_connection(&cli)) {
+               return False;
+       }
+
+       cli_sockopt(&cli, sockops);
+
+       cli_list(&cli, "\\LISTDIR\\*", 0, del_fn, &cli);
+       cli_list(&cli, "\\LISTDIR\\*", aDIR, del_fn, &cli);
+       cli_rmdir(&cli, "\\LISTDIR");
+       cli_mkdir(&cli, "\\LISTDIR");
+
+       /* Create 1000 files and 1000 directories. */
+       for (i=0;i<1000;i++) {
+               fstring fname;
+               slprintf(fname, sizeof(fname), "\\LISTDIR\\f%d", i);
+               fnum = cli_nt_create_full(&cli, fname, GENERIC_ALL_ACCESS, FILE_ATTRIBUTE_ARCHIVE,
+                                  FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_OVERWRITE_IF, 0);
+               if (fnum == -1) {
+                       fprintf(stderr,"Failed to open %s\n", fname);
+                       return False;
+               }
+               cli_close(&cli, fnum);
+       }
+       for (i=0;i<1000;i++) {
+               fstring fname;
+               slprintf(fname, sizeof(fname), "\\LISTDIR\\d%d", i);
+               if (!cli_mkdir(&cli, fname)) {
+                       fprintf(stderr,"Failed to open %s\n", fname);
+                       return False;
+               }
+       }
+
+       /* Now ensure that doing an old list sees both files and directories. */
+       num_seen = cli_list_old(&cli, "\\LISTDIR\\*", aDIR, list_fn, NULL);
+       printf("num_seen = %d\n", num_seen );
+       /* We should see 100 files + 1000 directories + . and .. */
+       if (num_seen != 2002)
+               correct = False;
+
+       /* Ensure if we have the "must have" bits we only see the
+        * relevent entries.
+        */
+       num_seen = cli_list_old(&cli, "\\LISTDIR\\*", (aDIR<<8)|aDIR, list_fn, NULL);
+       printf("num_seen = %d\n", num_seen );
+       if (num_seen != 1002)
+               correct = False;
+
+       num_seen = cli_list_old(&cli, "\\LISTDIR\\*", (aARCH<<8)|aDIR, list_fn, NULL);
+       printf("num_seen = %d\n", num_seen );
+       if (num_seen != 1000)
+               correct = False;
+
+       /* Delete everything. */
+       cli_list(&cli, "\\LISTDIR\\*", 0, del_fn, &cli);
+       cli_list(&cli, "\\LISTDIR\\*", aDIR, del_fn, &cli);
+       cli_rmdir(&cli, "\\LISTDIR");
+
+#if 0
+       printf("Matched %d\n", cli_list(&cli, "a*.*", 0, list_fn, NULL));
+       printf("Matched %d\n", cli_list(&cli, "b*.*", 0, list_fn, NULL));
+       printf("Matched %d\n", cli_list(&cli, "xyzabc", 0, list_fn, NULL));
+#endif
+
+       if (!torture_close_connection(&cli)) {
+               correct = False;
+       }
+
+       printf("finished dirtest1\n");
+
+       return correct;
+}
+
 static BOOL run_error_map_extract(int dummy) {
        
        static struct cli_state c_dos;
@@ -3711,6 +3860,7 @@ static struct {
        {"OPLOCK2",  run_oplock2, 0},
        {"OPLOCK3",  run_oplock3, 0},
        {"DIR",  run_dirtest, 0},
+       {"DIR1",  run_dirtest1, 0},
        {"DENY1",  torture_denytest1, 0},
        {"DENY2",  torture_denytest2, 0},
        {"TCON",  run_tcon_test, 0},
@@ -3863,6 +4013,7 @@ static void usage(void)
        argc--;
        argv++;
 
+       srandom(time(NULL));
 
        fstrcpy(workgroup, lp_workgroup());
 
index fc7094bcf770a873f4d09c8839f38178dd45c874..800aeded0a607bb4ee8693fa7af964105d215e34 100644 (file)
@@ -329,6 +329,74 @@ static int net_file(int argc, const char **argv)
        return net_rap_file(argc, argv);
 }
 
+/*
+ Retrieve our local SID or the SID for the specified name
+ */
+static int net_getlocalsid(int argc, const char **argv)
+{
+        DOM_SID sid;
+       const char *name;
+       fstring sid_str;
+
+       if (argc >= 1) {
+               name = argv[0];
+        }
+       else {
+               name = global_myname;
+       }
+
+       if (!secrets_fetch_domain_sid(name, &sid)) {
+               DEBUG(0, ("Can't fetch domain SID for name: %s\n", name));      
+               return 1;
+       }
+       sid_to_string(sid_str, &sid);
+       d_printf("SID for domain %s is: %s\n", name, sid_str);
+       return 0;
+}
+
+static int net_setlocalsid(int argc, const char **argv)
+{
+       DOM_SID sid;
+
+       if ( (argc != 1)
+            || (strncmp(argv[0], "S-1-5-21-", strlen("S-1-5-21-")) != 0)
+            || (!string_to_sid(&sid, argv[0]))
+            || (sid.num_auths != 4)) {
+               d_printf("usage: net setlocalsid S-1-5-21-x-y-z\n");
+               return 1;
+       }
+
+       if (!secrets_store_domain_sid(global_myname, &sid)) {
+               DEBUG(0,("Can't store domain SID as a pdc/bdc.\n"));
+               return 1;
+       }
+
+       return 0;
+}
+
+static int net_getdomainsid(int argc, const char **argv)
+{
+       DOM_SID domain_sid;
+       fstring sid_str;
+
+       if (!secrets_fetch_domain_sid(global_myname, &domain_sid)) {
+               d_printf("Could not fetch local SID\n");
+               return 1;
+       }
+       sid_to_string(sid_str, &domain_sid);
+       d_printf("SID for domain %s is: %s\n", global_myname, sid_str);
+
+       if (!secrets_fetch_domain_sid(lp_workgroup(), &domain_sid)) {
+               d_printf("Could not fetch domain SID\n");
+               return 1;
+       }
+
+       sid_to_string(sid_str, &domain_sid);
+       d_printf("SID for domain %s is: %s\n", lp_workgroup(), sid_str);
+
+       return 0;
+}
+
 /* main function table */
 static struct functable net_func[] = {
        {"RPC", net_rpc},
@@ -352,6 +420,10 @@ static struct functable net_func[] = {
        {"TIME", net_time},
        {"LOOKUP", net_lookup},
        {"JOIN", net_join},
+       {"CACHE", net_cache},
+       {"GETLOCALSID", net_getlocalsid},
+       {"SETLOCALSID", net_setlocalsid},
+       {"GETDOMAINSID", net_getdomainsid},
 
        {"HELP", net_help},
        {NULL, NULL}
@@ -391,7 +463,7 @@ static struct functable net_func[] = {
                {"force",       'f', POPT_ARG_NONE,   &opt_force},
                {"timeout",     't', POPT_ARG_INT,    &opt_timeout},
                {"machine-pass",'P', POPT_ARG_NONE,   &opt_machine_pass},
-               { NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_debug },
+               {"debuglevel",  'D', POPT_ARG_STRING, &debuglevel},
                { 0, 0, 0, 0}
        };
 
@@ -469,7 +541,7 @@ static struct functable net_func[] = {
        if (!*global_myname) {
                char *p2;
 
-               fstrcpy(global_myname, myhostname());
+               pstrcpy(global_myname, myhostname());
                p2 = strchr_m(global_myname, '.');
                if (p2) 
                         *p2 = 0;
index ad405fe68c32fb46063fcabe0ca7c51db498a399..af290ce83c6bc239a60310d8ac8709a3664d28a5 100644 (file)
@@ -56,6 +56,31 @@ int net_ads_usage(int argc, const char **argv)
 }
 
 
+/*
+  this implements the CLDAP based netlogon lookup requests
+  for finding the domain controller of a ADS domain
+*/
+static int net_ads_lookup(int argc, const char **argv)
+{
+       ADS_STRUCT *ads;
+
+       ads = ads_init(NULL, NULL, opt_host);
+       if (ads) {
+               ads->auth.flags |= ADS_AUTH_NO_BIND;
+       }
+
+       ads_connect(ads);
+
+       if (!ads || !ads->config.realm) {
+               d_printf("Didn't find the cldap server!\n");
+               return -1;
+       }
+
+       return ads_cldap_netlogon(ads);
+}
+
+
+
 static int net_ads_info(int argc, const char **argv)
 {
        ADS_STRUCT *ads;
@@ -63,7 +88,7 @@ static int net_ads_info(int argc, const char **argv)
        ads = ads_init(NULL, NULL, opt_host);
 
        if (ads) {
-               ads->auth.no_bind = 1;
+               ads->auth.flags |= ADS_AUTH_NO_BIND;
        }
 
        ads_connect(ads);
@@ -78,6 +103,7 @@ static int net_ads_info(int argc, const char **argv)
        d_printf("Realm: %s\n", ads->config.realm);
        d_printf("Bind Path: %s\n", ads->config.bind_path);
        d_printf("LDAP port: %d\n", ads->ldap_port);
+       d_printf("Server time: %s\n", http_timestring(ads->config.current_time));
 
        return 0;
 }
@@ -174,7 +200,7 @@ static int net_ads_workgroup(int argc, const char **argv)
 
 
 
-static void usergrp_display(char *field, void **values, void *data_area)
+static BOOL usergrp_display(char *field, void **values, void *data_area)
 {
        char **disp_fields = (char **) data_area;
 
@@ -188,15 +214,16 @@ static void usergrp_display(char *field, void **values, void *data_area)
                }
                SAFE_FREE(disp_fields[0]);
                SAFE_FREE(disp_fields[1]);
-               return;
+               return True;
        }
        if (!values) /* must be new field, indicate string field */
-               return;
+               return True;
        if (StrCaseCmp(field, "sAMAccountName") == 0) {
                disp_fields[0] = strdup((char *) values[0]);
        }
        if (StrCaseCmp(field, "description") == 0)
                disp_fields[1] = strdup((char *) values[0]);
+       return True;
 }
 
 static int net_ads_user_usage(int argc, const char **argv)
@@ -245,7 +272,7 @@ static int ads_user_add(int argc, const char **argv)
 
        /* try setting the password */
        asprintf(&upn, "%s@%s", argv[0], ads->config.realm);
-       status = krb5_set_password(ads->auth.kdc_server, upn, argv[1]);
+       status = krb5_set_password(ads->auth.kdc_server, upn, argv[1], ads->auth.time_offset);
        safe_free(upn);
        if (ADS_ERR_OK(status)) {
                d_printf("User %s added\n", argv[0]);
@@ -610,7 +637,7 @@ int net_ads_join(int argc, const char **argv)
        rc = ads_search_dn(ads, &res, dn, NULL);
        ads_msgfree(ads, res);
 
-       if (rc.error_type == ADS_ERROR_LDAP && rc.rc == LDAP_NO_SUCH_OBJECT) {
+       if (rc.error_type == ADS_ERROR_LDAP && rc.err.rc == LDAP_NO_SUCH_OBJECT) {
                d_printf("ads_join_realm: organizational unit %s does not exist (dn:%s)\n", 
                         org_unit, dn);
                return -1;
@@ -628,15 +655,15 @@ int net_ads_join(int argc, const char **argv)
                return -1;
        }
 
-       rc = ads_set_machine_password(ads, global_myname, password);
+       rc = ads_domain_sid(ads, &dom_sid);
        if (!ADS_ERR_OK(rc)) {
-               d_printf("ads_set_machine_password: %s\n", ads_errstr(rc));
+               d_printf("ads_domain_sid: %s\n", ads_errstr(rc));
                return -1;
        }
 
-       rc = ads_domain_sid(ads, &dom_sid);
+       rc = ads_set_machine_password(ads, global_myname, password);
        if (!ADS_ERR_OK(rc)) {
-               d_printf("ads_domain_sid: %s\n", ads_errstr(rc));
+               d_printf("ads_set_machine_password: %s\n", ads_errstr(rc));
                return -1;
        }
 
@@ -856,7 +883,7 @@ static int net_ads_password(int argc, const char **argv)
     new_password = getpass(prompt);
 
     ret = kerberos_set_password(ads->auth.kdc_server, auth_principal, 
-                               auth_password, argv[0], new_password);
+                               auth_password, argv[0], new_password, ads->auth.time_offset);
     if (!ADS_ERR_OK(ret)) {
        d_printf("Password change failed :-( ...\n");
        ads_destroy(&ads);
@@ -1009,6 +1036,7 @@ int net_ads(int argc, const char **argv)
                {"PRINTER", net_ads_printer},
                {"SEARCH", net_ads_search},
                {"WORKGROUP", net_ads_workgroup},
+               {"LOOKUP", net_ads_lookup},
                {"HELP", net_ads_help},
                {NULL, NULL}
        };
index ab3eac4b434775bf8cc79d80df0f5862cf48f854..262670cb2a3b2d4b7df45a27b3c3054943886039 100644 (file)
@@ -58,7 +58,7 @@ static int help_usage(int argc, const char **argv)
 "\n"\
 "Valid functions are:\n"\
 "  RPC RAP ADS FILE SHARE SESSION SERVER DOMAIN PRINTQ USER GROUP VALIDATE\n"\
-"  GROUPMEMBER ADMIN SERVICE PASSWORD TIME LOOKUP\n");
+"  GROUPMEMBER ADMIN SERVICE PASSWORD TIME LOOKUP GETLOCALSID SETLOCALSID\n");
        return -1;
 }
 
@@ -135,6 +135,9 @@ static int net_usage(int argc, const char **argv)
                 "  net user\t\tto manage users\n"\
                 "  net group\t\tto manage groups\n"\
                 "  net join\t\tto join a domain\n"\
+                "  net cache\t\tto operate on cache tdb file\n"\
+                "  net getlocalsid [NAME]\tto get the SID for local name\n"\
+                "  net setlocalsid SID\tto set the local domain SID\n"\
                 "\n"\
                 "  net ads <command>\tto run ADS commands\n"\
                 "  net rap <command>\tto run RAP (pre-RPC) commands\n"\
index 55e8a497ccae1978b5642ac68bc2744d2d96dbc5..8b8278b053e616b162cd95fd667f3ced8b3ac9ae 100644 (file)
@@ -178,7 +178,7 @@ static int run_rpc_command(struct cli_state *cli_arg, const char *pipe_name, int
 /** 
  * Force a change of the trust acccount password.
  *
- * All paramaters are provided by the run_rpc_command funcion, except for
+ * All parameters are provided by the run_rpc_command function, except for
  * argc, argv which are passes through. 
  *
  * @param domain_sid The domain sid aquired from the remote server
@@ -224,7 +224,7 @@ static int rpc_changetrustpw(int argc, const char **argv)
  *
  * The password should be created with 'server manager' or eqiv first.
  *
- * All paramaters are provided by the run_rpc_command funcion, except for
+ * All parameters are provided by the run_rpc_command function, except for
  * argc, argv which are passes through. 
  *
  * @param domain_sid The domain sid aquired from the remote server
@@ -243,6 +243,7 @@ static NTSTATUS rpc_join_oldstyle_internals(const DOM_SID *domain_sid, struct cl
        extern pstring global_myname;
        fstring trust_passwd;
        unsigned char orig_trust_passwd_hash[16];
+       NTSTATUS result;
 
        fstrcpy(trust_passwd, global_myname);
        strlower(trust_passwd);
@@ -256,7 +257,12 @@ static NTSTATUS rpc_join_oldstyle_internals(const DOM_SID *domain_sid, struct cl
 
        E_md4hash(trust_passwd, orig_trust_passwd_hash);
 
-       return trust_pw_change_and_store_it(cli, mem_ctx, orig_trust_passwd_hash);
+       result = trust_pw_change_and_store_it(cli, mem_ctx, orig_trust_passwd_hash);
+
+       if (NT_STATUS_IS_OK(result))
+               printf("Joined domain %s.\n",lp_workgroup());
+
+       return result;
 }
 
 /** 
@@ -319,7 +325,7 @@ int net_rpc_join(int argc, const char **argv)
 /** 
  * display info about a rpc domain
  *
- * All paramaters are provided by the run_rpc_command function, except for
+ * All parameters are provided by the run_rpc_command function, except for
  * argc, argv which are passes through. 
  *
  * @param domain_sid The domain sid acquired from the remote server
@@ -339,6 +345,9 @@ rpc_info_internals(const DOM_SID *domain_sid, struct cli_state *cli,
        POLICY_HND connect_pol, domain_pol;
        NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
        SAM_UNK_CTR ctr;
+       fstring sid_str;
+
+       sid_to_string(sid_str, domain_sid);
 
        /* Get sam policy handle */     
        result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
@@ -361,6 +370,7 @@ rpc_info_internals(const DOM_SID *domain_sid, struct cli_state *cli,
        if (NT_STATUS_IS_OK(result)) {
                TALLOC_CTX *ctx = talloc_init();
                d_printf("Domain Name: %s\n", unistr2_tdup(ctx, &ctr.info.inf2.uni_domain));
+               d_printf("Domain SID: %s\n", sid_str);
                d_printf("Sequence number: %u\n", ctr.info.inf2.seq_num);
                d_printf("Num users: %u\n", ctr.info.inf2.num_domain_usrs);
                d_printf("Num domain groups: %u\n", ctr.info.inf2.num_domain_grps);
@@ -387,6 +397,53 @@ int net_rpc_info(int argc, const char **argv)
 }
 
 
+/** 
+ * Fetch domain SID into the local secrets.tdb
+ *
+ * All parameters are provided by the run_rpc_command function, except for
+ * argc, argv which are passes through. 
+ *
+ * @param domain_sid The domain sid acquired from the remote server
+ * @param cli A cli_state connected to the server.
+ * @param mem_ctx Talloc context, destoyed on completion of the function.
+ * @param argc  Standard main() style argc
+ * @param argv  Standard main() style argv.  Initial components are already
+ *              stripped
+ *
+ * @return Normal NTSTATUS return.
+ **/
+
+static NTSTATUS 
+rpc_getsid_internals(const DOM_SID *domain_sid, struct cli_state *cli,
+                  TALLOC_CTX *mem_ctx, int argc, const char **argv)
+{
+       fstring sid_str;
+
+       sid_to_string(sid_str, domain_sid);
+       d_printf("Storing SID %s for Domain %s in secrets.tdb\n",
+                sid_str, lp_workgroup());
+
+       if (!secrets_store_domain_sid(global_myname, domain_sid)) {
+               DEBUG(0,("Can't store domain SID\n"));
+               return NT_STATUS_UNSUCCESSFUL;
+       }
+
+       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, PIPE_SAMR, NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC, 
+                              rpc_getsid_internals,
+                              argc, argv);
+}
 
 
 /****************************************************************************/
@@ -406,7 +463,7 @@ static int rpc_user_usage(int argc, const char **argv)
 /** 
  * Add a new user to a remote RPC server
  *
- * All paramaters are provided by the run_rpc_command funcion, except for
+ * All parameters are provided by the run_rpc_command function, except for
  * argc, argv which are passes through. 
  *
  * @param domain_sid The domain sid acquired from the remote server
@@ -494,7 +551,7 @@ static int rpc_user_add(int argc, const char **argv)
 /** 
  * Delete a user from a remote RPC server
  *
- * All paramaters are provided by the run_rpc_command funcion, except for
+ * All parameters are provided by the run_rpc_command function, except for
  * argc, argv which are passes through. 
  *
  * @param domain_sid The domain sid acquired from the remote server
@@ -595,7 +652,7 @@ static int rpc_user_delete(int argc, const char **argv)
 /** 
  * List user's groups on a remote RPC server
  *
- * All paramaters are provided by the run_rpc_command funcion, except for
+ * All parameters are provided by the run_rpc_command function, except for
  * argc, argv which are passes through. 
  *
  * @param domain_sid The domain sid acquired from the remote server
@@ -697,7 +754,7 @@ static int rpc_user_info(int argc, const char **argv)
 /** 
  * List users on a remote RPC server
  *
- * All paramaters are provided by the run_rpc_command function, except for
+ * All parameters are provided by the run_rpc_command function, except for
  * argc, argv which are passes through. 
  *
  * @param domain_sid The domain sid acquired from the remote server
@@ -811,7 +868,7 @@ static int rpc_group_usage(int argc, const char **argv)
 /** 
  * List groups on a remote RPC server
  *
- * All paramaters are provided by the run_rpc_command funcion, except for
+ * All parameters are provided by the run_rpc_command function, except for
  * argc, argv which are passes through. 
  *
  * @param domain_sid The domain sid acquired from the remote server
@@ -954,7 +1011,7 @@ static int rpc_share_usage(int argc, const char **argv)
 /** 
  * Add a share on a remote RPC server
  *
- * All paramaters are provided by the run_rpc_command function, except for
+ * All parameters are provided by the run_rpc_command function, except for
  * argc, argv which are passes through. 
  *
  * @param domain_sid The domain sid acquired from the remote server
@@ -1002,7 +1059,7 @@ static int rpc_share_add(int argc, const char **argv)
 /** 
  * Delete a share on a remote RPC server
  *
- * All paramaters are provided by the run_rpc_command function, except for
+ * All parameters are provided by the run_rpc_command function, except for
  * argc, argv which are passes through. 
  *
  * @param domain_sid The domain sid acquired from the remote server
@@ -1070,7 +1127,7 @@ static void display_share_info_1(SRV_SHARE_INFO_1 *info1)
 /** 
  * List shares on a remote RPC server
  *
- * All paramaters are provided by the run_rpc_command function, except for
+ * All parameters are provided by the run_rpc_command function, except for
  * argc, argv which are passes through. 
  *
  * @param domain_sid The domain sid acquired from the remote server
@@ -1147,7 +1204,7 @@ static int rpc_file_usage(int argc, const char **argv)
 /** 
  * Close a file on a remote RPC server
  *
- * All paramaters are provided by the run_rpc_command function, except for
+ * All parameters are provided by the run_rpc_command function, except for
  * argc, argv which are passes through. 
  *
  * @param domain_sid The domain sid acquired from the remote server
@@ -1210,7 +1267,7 @@ static void display_file_info_3(FILE_INFO_3 *info3, FILE_INFO_3_STR *str3)
 /** 
  * List open files on a remote RPC server
  *
- * All paramaters are provided by the run_rpc_command funcion, except for
+ * All parameters are provided by the run_rpc_command function, except for
  * argc, argv which are passes through. 
  *
  * @param domain_sid The domain sid acquired from the remote server
@@ -1314,7 +1371,7 @@ int net_rpc_file(int argc, const char **argv)
 /** 
  * ABORT the shutdown of a remote RPC Server
  *
- * All paramaters are provided by the run_rpc_command function, except for
+ * All parameters are provided by the run_rpc_command function, except for
  * argc, argv which are passed through. 
  *
  * @param domain_sid The domain sid aquired from the remote server
@@ -1362,7 +1419,7 @@ static int rpc_shutdown_abort(int argc, const char **argv)
 /** 
  * Shut down a remote RPC Server
  *
- * All paramaters are provided by the run_rpc_command funcion, except for
+ * All parameters are provided by the run_rpc_command function, except for
  * argc, argv which are passes through. 
  *
  * @param domain_sid The domain sid aquired from the remote server
@@ -1914,6 +1971,12 @@ static int rpc_trustdom_list(int argc, const char **argv)
                        
                        d_printf("%s%s%s\n", trusted_dom_names[i], padding, ascii_sid);
                };
+               
+               /*
+                * in case of no trusted domains say something rather
+                * than just display blank line
+                */
+               if (!num_domains) d_printf("none\n");
 
        } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
 
@@ -2018,6 +2081,8 @@ static int rpc_trustdom_list(int argc, const char **argv)
                        };
                };
                
+               if (!num_domains) d_printf("none\n");
+               
        } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
 
        /* close opened samr and domain policy handles */
@@ -2083,7 +2148,7 @@ BOOL net_rpc_check(unsigned flags)
 
        /* flags (i.e. server type) may depend on command */
        if (!net_find_server(flags, &server_ip, &server_name))
-               goto done;
+               return False;
 
        ZERO_STRUCT(cli);
        if (cli_initialise(&cli) == False)
@@ -2120,12 +2185,13 @@ int net_rpc_usage(int argc, const char **argv)
 {
        d_printf("  net rpc info \t\t\tshow basic info about a domain \n");
        d_printf("  net rpc join \t\t\tto join a domain \n");
-       d_printf("  net rpc testjoin \t\t\ttests that a join is valid\n");
+       d_printf("  net rpc testjoin \t\ttests that a join is valid\n");
        d_printf("  net rpc user \t\t\tto add, delete and list users\n");
        d_printf("  net rpc group \t\tto list groups\n");
        d_printf("  net rpc share \t\tto add, delete, and list shares\n");
        d_printf("  net rpc file \t\t\tto list open files\n");
        d_printf("  net rpc changetrustpw \tto change the trust account password\n");
+       d_printf("  net rpc getsid \t\tfetch the domain sid into the local secrets.tdb\n");
        d_printf("  net rpc trustdom \t\tto create trusting domain's account\n"
                 "\t\t\t\t\tor establish trust\n");
        d_printf("  net rpc abortshutdown \tto abort the shutdown of a remote server\n");
@@ -2192,6 +2258,9 @@ int net_rpc(int argc, const char **argv)
                {"trustdom", rpc_trustdom},
                {"abortshutdown", rpc_shutdown_abort},
                {"shutdown", rpc_shutdown},
+               {"samdump", rpc_samdump},
+               {"vampire", rpc_vampire},
+               {"getsid", net_rpc_getsid},
                {"help", net_rpc_help},
                {NULL, NULL}
        };
index c8be93c39cc5131ee605489118f267ae5131a83e..b08095f1ccb67dcbb4a65dd3d4a13569a70a0732 100644 (file)
@@ -49,6 +49,7 @@ int net_rpc_join_ok(const char *domain)
        int retval = 1;
        uint32 channel;
        NTSTATUS result;
+       uint32 neg_flags = 0x000001ff;
 
        /* Connect to remote machine */
        if (!(cli = net_make_ipc_connection(NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC))) {
@@ -75,7 +76,7 @@ int net_rpc_join_ok(const char *domain)
 
        CHECK_RPC_ERR(cli_nt_setup_creds(cli, 
                                         channel,
-                                        stored_md4_trust_password),
+                                        stored_md4_trust_password, &neg_flags, 2),
                          "error in domain join verification");
        
        retval = 0;             /* Success! */
index 51dbbb98c06feab2c21995b77ec4a2b5a79e94c0..7c61e6d8be453e3d81c77ace79b9caabcef9785a 100644 (file)
@@ -508,6 +508,17 @@ int main (int argc, char **argv)
                exit(1);
        }
 
+       if (!*global_myname) {
+               char *p2;
+
+               pstrcpy(global_myname, myhostname());
+               p2 = strchr_m(global_myname, '.');
+               if (p2) 
+                        *p2 = 0;
+       }
+       
+       strupper(global_myname);
+
        setparms =      (config_file ? BIT_CONFIGFILE : 0) +
                        (new_debuglevel ? BIT_DEBUGLEVEL : 0) +
                        (backend ? BIT_BACKEND : 0) +
@@ -544,7 +555,7 @@ int main (int argc, char **argv)
        /* the lowest bit options are always accepted */
        checkparms = setparms & ~MASK_ALWAYS_GOOD;
 
-       /* accoun tpolicy operations */
+       /* accounpolicy operations */
        if ((checkparms & BIT_ACCPOLICY) && !(checkparms & ~(BIT_ACCPOLICY + BIT_ACCPOLVAL))) {
                uint32 value;
                int field = account_policy_name_to_fieldnum(account_policy);
index 2d78b21dcc8a8be234250d1756f825a91d7429e3..5401755376df7e4569d00b59e2d00369f8226739 100644 (file)
@@ -42,6 +42,7 @@ static struct {
        {"dmalloc-mark", MSG_REQ_DMALLOC_MARK },
        {"dmalloc-log-changed", MSG_REQ_DMALLOC_LOG_CHANGED },
        {"shutdown", MSG_SHUTDOWN },
+       {"change_id", MSG_PRINTER_DRVUPGRADE},
        {NULL, -1}
 };
 
@@ -553,6 +554,10 @@ static BOOL do_command(char *dest, char *msg_name, int iparams, char **params)
                if (!send_message(dest, MSG_SHUTDOWN, NULL, 0, False))
                        return False;
                break;
+       case MSG_PRINTER_DRVUPGRADE:
+               if (!send_message(dest, MSG_PRINTER_DRVUPGRADE, params[0], 0, False))
+                       return False;
+               break;
        }
 
        return (True);
index 98993676c98637fe3a90535c8fbbe116d9f05d44..75a4319cb965797c7fea04b0d87444442bdf44a2 100644 (file)
@@ -217,23 +217,23 @@ static int process_options(int argc, char **argv, int local_flags)
 *************************************************************/
 static char *stdin_new_passwd(void)
 {
-       static fstring new_passwd;
+       static fstring new_pw;
        size_t len;
 
-       ZERO_ARRAY(new_passwd);
+       ZERO_ARRAY(new_pw);
 
        /*
         * if no error is reported from fgets() and string at least contains
         * the newline that ends the password, then replace the newline with
         * a null terminator.
         */
-       if ( fgets(new_passwd, sizeof(new_passwd), stdin) != NULL) {
-               if ((len = strlen(new_passwd)) > 0) {
-                       if(new_passwd[len-1] == '\n')
-                               new_passwd[len - 1] = 0; 
+       if ( fgets(new_pw, sizeof(new_pw), stdin) != NULL) {
+               if ((len = strlen(new_pw)) > 0) {
+                       if(new_pw[len-1] == '\n')
+                               new_pw[len - 1] = 0; 
                }
        }
-       return(new_passwd);
+       return(new_pw);
 }
 
 
@@ -259,20 +259,20 @@ static char *get_pass( char *prompt, BOOL stdin_get)
 static char *prompt_for_new_password(BOOL stdin_get)
 {
        char *p;
-       fstring new_passwd;
+       fstring new_pw;
 
-       ZERO_ARRAY(new_passwd);
+       ZERO_ARRAY(new_pw);
  
        p = get_pass("New SMB password:", stdin_get);
 
-       fstrcpy(new_passwd, p);
+       fstrcpy(new_pw, p);
        SAFE_FREE(p);
 
        p = get_pass("Retype new SMB password:", stdin_get);
 
-       if (strcmp(p, new_passwd)) {
+       if (strcmp(p, new_pw)) {
                fprintf(stderr, "Mismatch - password unchanged.\n");
-               ZERO_ARRAY(new_passwd);
+               ZERO_ARRAY(new_pw);
                SAFE_FREE(p);
                return NULL;
        }
@@ -285,27 +285,27 @@ static char *prompt_for_new_password(BOOL stdin_get)
  Change a password either locally or remotely.
 *************************************************************/
 
-static BOOL password_change(const char *remote_machine, char *user_name, 
-                           char *old_passwd, char *new_passwd, int local_flags)
+static BOOL password_change(const char *remote_mach, char *username, 
+                           char *old_passwd, char *new_pw, int local_flags)
 {
        BOOL ret;
        pstring err_str;
        pstring msg_str;
 
-       if (remote_machine != NULL) {
+       if (remote_mach != NULL) {
                if (local_flags & (LOCAL_ADD_USER|LOCAL_DELETE_USER|LOCAL_DISABLE_USER|LOCAL_ENABLE_USER|
                                                        LOCAL_TRUST_ACCOUNT|LOCAL_SET_NO_PASSWORD)) {
                        /* these things can't be done remotely yet */
                        return False;
                }
-               ret = remote_password_change(remote_machine, user_name, 
-                                            old_passwd, new_passwd, err_str, sizeof(err_str));
+               ret = remote_password_change(remote_mach, username, 
+                                            old_passwd, new_pw, err_str, sizeof(err_str));
                if(*err_str)
                        fprintf(stderr, err_str);
                return ret;
        }
        
-       ret = local_password_change(user_name, local_flags, new_passwd
+       ret = local_password_change(username, local_flags, new_pw
                                     err_str, sizeof(err_str), msg_str, sizeof(msg_str));
 
        if(*msg_str)
index 0b0c591cb16a13a531210bb16d4371a58dc480fa..d87497f2fa333576065d1c65d3dea1cbc43c7eff 100644 (file)
@@ -146,6 +146,7 @@ static void print_brl(SMB_DEV_T dev, SMB_INO_T ino, int pid,
   ******************************************************************/
 static int profile_dump(void)
 {
+#ifdef WITH_PROFILE
        if (!profile_setup(True)) {
                fprintf(stderr,"Failed to initialise profile memory\n");
                return -1;
@@ -482,6 +483,9 @@ static int profile_dump(void)
        d_printf("run_elections_time:             %u\n", profile_p->run_elections_time);
        d_printf("election_count:                 %u\n", profile_p->election_count);
        d_printf("election_time:                  %u\n", profile_p->election_time);
+#else /* WITH_PROFILE */
+       fprintf(stderr, "Profile data unavailable\n");
+#endif /* WITH_PROFILE */
 
        return 0;
 }
@@ -549,7 +553,9 @@ static int traverse_sessionid(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, vo
                {"conf",        's', POPT_ARG_STRING,   0, 's'},
                {"user",        'u', POPT_ARG_STRING,   0, 'u'},
                {"brief",       'b', POPT_ARG_NONE,     &brief},
+#ifdef WITH_PROFILE
                {"profile",     'P', POPT_ARG_NONE,     &profile_only},
+#endif /* WITH_PROFILE */
                {"byterange",   'B', POPT_ARG_NONE,     &show_brl},
                { NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_debug },
                { 0, 0, 0, 0}
index 3086019467de3277cd4f8b5010d76a34bf7d2300..d48cecba47b4ebc2467bf6821b05f321f947584d 100644 (file)
@@ -48,7 +48,7 @@ static int do_global_checks(void)
        SMB_STRUCT_STAT st;
 
        if (lp_security() >= SEC_DOMAIN && !lp_encrypted_passwords()) {
-               printf("ERROR: in 'security=domain' mode the 'encrypt passwords' parameter must also be set to 'true'.\n");
+               printf("ERROR: in 'security=domain' mode the 'encrypt passwords' parameter must always be set to 'true'.\n");
                ret = 1;
        }
 
@@ -171,7 +171,7 @@ via the %%o substitution. With encrypted passwords this is not possible.\n", lp_
        return ret;
 }   
 
-int main(int argc, char *argv[])
+int main(int argc, const char *argv[])
 {
        extern char *optarg;
        extern int optind;
@@ -185,17 +185,19 @@ int main(int argc, char *argv[])
        static char *new_local_machine = NULL;
        const char *cname;
        const char *caddr;
+       static int show_defaults;
 
        struct poptOption long_options[] = {
                POPT_AUTOHELP
                {"suppress-prompt", 's', POPT_ARG_VAL, &silent_mode, 1, "Suppress prompt for enter"},
+               {"verbose", 'v', POPT_ARG_NONE, &show_defaults, 1, "Show default options too"},
                {"server", 'L',POPT_ARG_STRING, &new_local_machine, 0, "Set %%L macro to servername\n"},
                {"encoding", 't', POPT_ARG_STRING, &term_code, 0, "Print parameters with encoding"},
                {0,0,0,0}
        };
 
-       pc = poptGetContext(NULL, argc, (const char **) argv, long_options, 
-                                               POPT_CONTEXT_KEEP_FIRST);
+       pc = poptGetContext(NULL, argc, argv, long_options, 
+                           POPT_CONTEXT_KEEP_FIRST);
 
        while((opt = poptGetNextOpt(pc)) != -1);
 
@@ -276,7 +278,7 @@ int main(int argc, char *argv[])
                        fflush(stdout);
                        getc(stdin);
                }
-               lp_dump(stdout,True, lp_numservices());
+               lp_dump(stdout, show_defaults, lp_numservices());
        }
 
        if(cname && caddr){
index 80d3232d2bffedb6912b8f05047b507d790bb708..af6fa82ffe565c52b02cf1b2ee664e94cbbc1767 100644 (file)
@@ -1,7 +1,9 @@
 /* 
    Unix SMB/CIFS implementation.
    Samba Web Administration Tool
-   Copyright (C) Andrew Tridgell 1997-1998
+   Version 3.0.0
+   Copyright (C) Andrew Tridgell 1997-2002
+   Copyright (C) John H Terpstra 2002
    
    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
@@ -297,7 +299,7 @@ static void show_parameter(int snum, struct parm_struct *parm)
 /****************************************************************************
   display a set of parameters for a service 
 ****************************************************************************/
-static void show_parameters(int snum, int allparameters, int advanced, int printers)
+static void show_parameters(int snum, int allparameters, unsigned int parm_filter, int printers)
 {
        int i = 0;
        struct parm_struct *parm;
@@ -316,7 +318,7 @@ static void show_parameters(int snum, int allparameters, int advanced, int print
                        if (printers & !(parm->flags & FLAG_PRINT)) continue;
                        if (!printers & !(parm->flags & FLAG_SHARE)) continue;
                }
-               if (!advanced) {
+               if (parm_filter == FLAG_BASIC) {
                        if (!(parm->flags & FLAG_BASIC)) {
                                void *ptr = parm->ptr;
 
@@ -363,6 +365,12 @@ static void show_parameters(int snum, int allparameters, int advanced, int print
                        }
                        if (printers && !(parm->flags & FLAG_PRINT)) continue;
                }
+               if (parm_filter == FLAG_WIZARD) {
+                       if (!((parm->flags & FLAG_WIZARD))) continue;
+               }
+               if (parm_filter == FLAG_ADVANCED) {
+                       if (!((parm->flags & FLAG_ADVANCED))) continue;
+               }
                if (heading && heading != last_heading) {
                        d_printf("<tr><td></td></tr><tr><td><b><u>%s</u></b></td></tr>\n", _(heading));
                        last_heading = heading;
@@ -393,7 +401,7 @@ static void write_config(FILE *f, BOOL show_defaults)
 }
 
 /****************************************************************************
-  save and reoad the smb.conf config file 
+  save and reload the smb.conf config file 
 ****************************************************************************/
 static int save_reload(int snum)
 {
@@ -497,6 +505,7 @@ static void show_main_buttons(void)
                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");
        }
        if (have_read_access) {
                image_link(_("Status"), "status", "images/status.gif");
@@ -507,6 +516,18 @@ static void show_main_buttons(void)
        d_printf("<HR>\n");
 }
 
+/****************************************************************************
+ * Handle Display/Edit Mode CGI
+ ****************************************************************************/
+static void ViewModeBoxes(int mode)
+{
+       d_printf("<p>%s\n", _("Configuration View:&nbsp"));
+       d_printf("<input type=radio name=\"ViewMode\" value=0 %s>Basic\n", (mode == 0) ? "checked" : "");
+       d_printf("<input type=radio name=\"ViewMode\" value=1 %s>Advanced\n", (mode == 1) ? "checked" : "");
+       d_printf("<input type=radio name=\"ViewMode\" value=2 %s>Developer\n", (mode == 2) ? "checked" : "");
+       d_printf("</p><br>\n");
+}
+
 /****************************************************************************
   display a welcome page  
 ****************************************************************************/
@@ -541,25 +562,240 @@ static void viewconfig_page(void)
        d_printf("</form>\n");
 }
 
+/****************************************************************************
+  second screen of the wizard ... Fetch Configuration Parameters
+****************************************************************************/
+static void wizard_params_page(void)
+{
+       unsigned int parm_filter = FLAG_WIZARD;
+
+       /* Here we first set and commit all the parameters that were selected
+          in the previous screen. */
+
+       d_printf("<H2>Wizard Parameter Edit Page</H2>\n");
+
+       if (cgi_variable("Commit")) {
+               commit_parameters(GLOBALS_SNUM);
+               save_reload(0);
+       }
+
+       d_printf("<form name=\"swatform\" method=post action=wizard_params>\n");
+
+       if (have_write_access) {
+               d_printf("<input type=submit name=\"Commit\" value=\"Commit Changes\">\n");
+       }
+
+       d_printf("<input type=reset name=\"Reset Values\" value=\"Reset\">\n");
+       d_printf("<p>\n");
+       
+       d_printf("<table>\n");
+       show_parameters(GLOBALS_SNUM, 1, parm_filter, 0);
+       d_printf("</table>\n");
+       d_printf("</form>\n");
+}
+
+/****************************************************************************
+  Utility to just rewrite the smb.conf file - effectively just cleans it up
+****************************************************************************/
+static void rewritecfg_file(void)
+{
+       commit_parameters(GLOBALS_SNUM);
+       save_reload(0);
+       d_printf("<H2>Note: smb.conf %s</H2>\n", _("file has been read and rewritten"));
+}
+
+/****************************************************************************
+  wizard to create/modify the smb.conf file
+****************************************************************************/
+static void wizard_page(void)
+{
+       /* Set some variables to collect data from smb.conf */
+       int role = 0;
+       int winstype = 0;
+       int have_home = -1;
+       int HomeExpo = 0;
+       int SerType = 0;
+
+       if (cgi_variable("Rewrite")) {
+               (void) rewritecfg_file();
+               return;
+       }
+
+       if (cgi_variable("GetWizardParams")){
+               (void) wizard_params_page();
+               return;
+       }
+
+       if (cgi_variable("Commit")){
+               SerType = atoi(cgi_variable("ServerType"));
+               winstype = atoi(cgi_variable("WINSType"));
+               have_home = lp_servicenumber(HOMES_NAME);
+               HomeExpo = atoi(cgi_variable("HomeExpo"));
+
+               /* Plain text passwords are too badly broken - use encrypted passwords only */
+               lp_do_parameter( GLOBALS_SNUM, "encrypt passwords", "Yes");
+               
+               switch ( SerType ){
+                       case 0:
+                               /* Stand-alone Server */
+                               lp_do_parameter( GLOBALS_SNUM, "security", "USER" );
+                               lp_do_parameter( GLOBALS_SNUM, "domain logons", "No" );
+                               break;
+                       case 1:
+                               /* Domain Member */
+                               lp_do_parameter( GLOBALS_SNUM, "security", "DOMAIN" );
+                               lp_do_parameter( GLOBALS_SNUM, "domain logons", "No" );
+                               break;
+                       case 2:
+                               /* Domain Controller */
+                               lp_do_parameter( GLOBALS_SNUM, "security", "USER" );
+                               lp_do_parameter( GLOBALS_SNUM, "domain logons", "Yes" );
+                               break;
+               }
+               switch ( winstype ) {
+                       case 0:
+                               lp_do_parameter( GLOBALS_SNUM, "wins support", "No" );
+                               lp_do_parameter( GLOBALS_SNUM, "wins server", "" );
+                               break;
+                       case 1:
+                               lp_do_parameter( GLOBALS_SNUM, "wins support", "Yes" );
+                               lp_do_parameter( GLOBALS_SNUM, "wins server", "" );
+                               break;
+                       case 2:
+                               lp_do_parameter( GLOBALS_SNUM, "wins support", "No" );
+                               lp_do_parameter( GLOBALS_SNUM, "wins server", cgi_variable("WINSAddr"));
+                               break;
+               }
+
+               /* Have to create Homes share? */
+               if ((HomeExpo == 1) && (have_home == -1)) {
+                       pstring unix_share;
+                       
+                       pstrcpy(unix_share,HOMES_NAME);
+                       load_config(False);
+                       lp_copy_service(GLOBALS_SNUM, unix_share);
+                       iNumNonAutoPrintServices = lp_numservices();
+                       have_home = lp_servicenumber(HOMES_NAME);
+                       lp_do_parameter( have_home, "read only", "No");
+                       lp_do_parameter( have_home, "valid users", "%S");
+                       lp_do_parameter( have_home, "browseable", "No");
+                       commit_parameters(have_home);
+               }
+
+               /* Need to Delete Homes share? */
+               if ((HomeExpo == 0) && (have_home != -1)) {
+                       lp_remove_service(have_home);
+                       have_home = -1;
+               }
+
+               commit_parameters(GLOBALS_SNUM);
+               save_reload(0);
+       }
+       else
+       {
+               /* Now determine smb.conf WINS settings */
+               if (lp_wins_support())
+                       winstype = 1;
+/*             if (strlen(lp_wins_server_list()) != 0 )
+ *             winstype = 2;
+ */            
+
+               /* Do we have a homes share? */
+               have_home = lp_servicenumber(HOMES_NAME);
+       }
+       if ((winstype == 2) && lp_wins_support())
+               winstype = 3;
+
+       role = lp_server_role();
+       
+       /* Here we go ... */
+       d_printf("<H2>Samba Configuration Wizard</H2>\n");
+       d_printf("<form method=post action=wizard>\n");
+
+       if (have_write_access) {
+               d_printf(_("The \"Rewrite smb.conf file\" button will clear the smb.conf file of all default values and of comments.\n"));
+               d_printf(_("The same will happen if you press the commit button."));
+               d_printf("<br><br>");
+               d_printf("<center>");
+               d_printf("<input type=submit name=\"Rewrite\" value=%s> &nbsp;&nbsp;",_("Rewrite smb.conf file"));
+               d_printf("<input type=submit name=\"Commit\" value=%s> &nbsp;&nbsp;",_("Commit"));
+               d_printf("<input type=submit name=\"GetWizardParams\" value=%s>", _("Edit Parameter Values"));
+               d_printf("</center>");
+       }
+
+       d_printf("<hr>");
+       d_printf("<center><table border=0>");
+       d_printf("<tr><td><b>%s</b></td>\n", "Server Type:&nbsp;");
+       d_printf("<td><input type=radio name=\"ServerType\" value=0 %s> Stand Alone&nbsp;</td>", (role == ROLE_STANDALONE) ? "checked" : "");
+       d_printf("<td><input type=radio name=\"ServerType\" value=1 %s> Domain Member&nbsp;</td>", (role == ROLE_DOMAIN_MEMBER) ? "checked" : ""); 
+       d_printf("<td><input type=radio name=\"ServerType\" value=2 %s> Domain Controller&nbsp;</td>", (role == ROLE_DOMAIN_PDC) ? "checked" : "");
+       d_printf("</tr>");
+       if (role == ROLE_DOMAIN_BDC) {
+               d_printf("<tr><td></td><td colspan=3><font color=\"#ff0000\">Unusual Type in smb.conf - Please Select New Mode</font></td></tr>");
+       }
+       d_printf("<tr><td><b>%s</b></td>\n", "Configure WINS As:&nbsp;");
+       d_printf("<td><input type=radio name=\"WINSType\" value=0 %s> Not Used&nbsp;</td>", (winstype == 0) ? "checked" : "");
+       d_printf("<td><input type=radio name=\"WINSType\" value=1 %s> Server for client use&nbsp;</td>", (winstype == 1) ? "checked" : "");
+       d_printf("<td><input type=radio name=\"WINSType\" value=2 %s> Client of another WINS server&nbsp;</td>", (winstype == 2) ? "checked" : "");
+       d_printf("<tr><td></td><td></td><td></td><td>Remote WINS Server&nbsp;<input type=text size=\"16\" name=\"WINSAddr\" value=\"%s\"></td></tr>",lp_wins_server_list());
+       if (winstype == 3) {
+               d_printf("<tr><td></td><td colspan=3><font color=\"#ff0000\">Error: WINS Server Mode and WINS Support both set in smb.conf</font></td></tr>");
+               d_printf("<tr><td></td><td colspan=3><font color=\"#ff0000\">Please Select desired WINS mode above.</font></td></tr>");
+       }
+       d_printf("</tr>");
+       d_printf("<tr><td><b>%s</b></td>\n","Expose Home Directories:&nbsp;");
+       d_printf("<td><input type=radio name=\"HomeExpo\" value=1 %s> Yes</td>", (have_home == -1) ? "" : "checked ");
+       d_printf("<td><input type=radio name=\"HomeExpo\" value=0 %s> No</td>", (have_home == -1 ) ? "checked" : "");
+       d_printf("<td></td></tr>");
+       
+       /* Enable this when we are ready ....
+        * d_printf("<tr><td><b>%s</b></td>\n","Is Print Server:&nbsp;");
+        * d_printf("<td><input type=radio name=\"PtrSvr\" value=1 %s> Yes</td>");
+        * d_printf("<td><input type=radio name=\"PtrSvr\" value=0 %s> No</td>");
+        * d_printf("<td></td></tr>");
+        */
+       
+       d_printf("</table></center>");
+       d_printf("<hr>");
+
+       d_printf(_("The above configuration options will set multiple parameters and will generally assist with rapid Samba deployment.\n"));
+       d_printf("</form>\n");
+}
+
+
 /****************************************************************************
   display a globals editing page  
 ****************************************************************************/
 static void globals_page(void)
 {
-       int advanced = 0;
+       unsigned int parm_filter = FLAG_BASIC;
+       int mode = 0;
 
        d_printf("<H2>%s</H2>\n", _("Global Variables"));
 
-       if (cgi_variable("Advanced") && !cgi_variable("Basic"))
-               advanced = 1;
-
        if (cgi_variable("Commit")) {
                commit_parameters(GLOBALS_SNUM);
                save_reload(0);
        }
 
-       d_printf("<FORM name=\"swatform\" method=post>\n");
-
+       if ( cgi_variable("ViewMode") )
+               mode = atoi(cgi_variable("ViewMode"));
+
+       d_printf("<form name=\"swatform\" method=post action=globals>\n");
+
+       ViewModeBoxes( mode );
+       switch ( mode ) {
+               case 0:
+                       parm_filter = FLAG_BASIC;
+                       break;
+               case 1:
+                       parm_filter = FLAG_ADVANCED;
+                       break;
+               case 2:
+                       parm_filter = FLAG_DEVELOPER;
+                       break;
+       }
+       d_printf("<br>\n");
        if (have_write_access) {
                d_printf("<input type=submit name=\"Commit\" value=\"%s\">\n",
                        _("Commit Changes"));
@@ -567,22 +803,12 @@ static void globals_page(void)
 
        d_printf("<input type=reset name=\"Reset Values\" value=\"%s\">\n", 
                 _("Reset Values"));
-       if (advanced == 0) {
-               d_printf("<input type=submit name=\"Advanced\" value=\"%s\">\n", _("Advanced View"));
-       } else {
-               d_printf("<input type=submit name=\"Basic\" value=\"%s\">\n", _("Basic View"));
-       }
+
        d_printf("<p>\n");
-       
        d_printf("<table>\n");
-       show_parameters(GLOBALS_SNUM, 1, advanced, 0);
+       show_parameters(GLOBALS_SNUM, 1, parm_filter, 0);
        d_printf("</table>\n");
-
-       if (advanced) {
-               d_printf("<input type=hidden name=\"Advanced\" value=1>\n");
-       }
-
-       d_printf("</FORM>\n");
+       d_printf("</form>\n");
 }
 
 /****************************************************************************
@@ -595,16 +821,14 @@ static void shares_page(void)
        char *s;
        int snum = -1;
        int i;
-       int advanced = 0;
+       int mode = 0;
+       unsigned int parm_filter = FLAG_BASIC;
 
        if (share)
                snum = lp_servicenumber(share);
 
        d_printf("<H2>%s</H2>\n", _("Share Parameters"));
 
-       if (cgi_variable("Advanced") && !cgi_variable("Basic"))
-               advanced = 1;
-
        if (cgi_variable("Commit") && snum >= 0) {
                commit_parameters(snum);
                save_reload(0);
@@ -628,7 +852,21 @@ static void shares_page(void)
        d_printf("<FORM name=\"swatform\" method=post>\n");
 
        d_printf("<table>\n");
-       d_printf("<tr>\n");
+       if ( cgi_variable("ViewMode") )
+               mode = atoi(cgi_variable("ViewMode"));
+       ViewModeBoxes( mode );
+       switch ( mode ) {
+               case 0:
+                       parm_filter = FLAG_BASIC;
+                       break;
+               case 1:
+                       parm_filter = FLAG_ADVANCED;
+                       break;
+               case 2:
+                       parm_filter = FLAG_DEVELOPER;
+                       break;
+       }
+       d_printf("<br><tr>\n");
        d_printf("<td><input type=submit name=selectshare value=\"%s\"></td>\n", _("Choose Share"));
        d_printf("<td><select name=share>\n");
        if (snum < 0)
@@ -662,24 +900,15 @@ static void shares_page(void)
                }
 
                d_printf("<input type=reset name=\"Reset Values\" value=\"%s\">\n", _("Reset Values"));
-               if (advanced == 0) {
-                       d_printf("<input type=submit name=\"Advanced\" value=\"%s\">\n", _("Advanced View"));
-               } else {
-                       d_printf("<input type=submit name=\"Basic\" value=\"%s\">\n", _("Basic View"));
-               }
                d_printf("<p>\n");
        }
 
        if (snum >= 0) {
                d_printf("<table>\n");
-               show_parameters(snum, 1, advanced, 0);
+               show_parameters(snum, 1, parm_filter, 0);
                d_printf("</table>\n");
        }
 
-       if (advanced) {
-               d_printf("<input type=hidden name=\"Advanced\" value=1>\n");
-       }
-
        d_printf("</FORM>\n");
 }
 
@@ -922,7 +1151,8 @@ static void printers_page(void)
        char *s;
        int snum=-1;
        int i;
-       int advanced = 0;
+       int mode = 0;
+       unsigned int parm_filter = FLAG_BASIC;
 
        if (share)
                snum = lp_servicenumber(share);
@@ -935,9 +1165,6 @@ static void printers_page(void)
         d_printf("<A HREF=\"/swat/help/smb.conf.5.html#printcapname\" target=\"docs\">%s</A>\n", _("Printcap Name"));
         d_printf(_("Attempting to delete these printers from SWAT will have no effect.\n"));
 
-       if (cgi_variable("Advanced") && !cgi_variable("Basic"))
-               advanced = 1;
-
        if (cgi_variable("Commit") && snum >= 0) {
                commit_parameters(snum);
                if (snum >= iNumNonAutoPrintServices)
@@ -965,6 +1192,20 @@ static void printers_page(void)
 
        d_printf("<FORM name=\"swatform\" method=post>\n");
 
+       if ( cgi_variable("ViewMode") )
+               mode = atoi(cgi_variable("ViewMode"));
+       ViewModeBoxes( mode );
+       switch ( mode ) {
+               case 0:
+                       parm_filter = FLAG_BASIC;
+                       break;
+               case 1:
+                       parm_filter = FLAG_ADVANCED;
+                       break;
+               case 2:
+                       parm_filter = FLAG_DEVELOPER;
+                       break;
+       }
        d_printf("<table>\n");
        d_printf("<tr><td><input type=submit name=selectshare value=\"%s\"></td>\n", _("Choose Printer"));
        d_printf("<td><select name=share>\n");
@@ -1003,24 +1244,14 @@ static void printers_page(void)
                        d_printf("<input type=submit name=\"Commit\" value=\"%s\">\n", _("Commit Changes"));
                }
                d_printf("<input type=reset name=\"Reset Values\" value=\"%s\">\n", _("Reset Values"));
-               if (advanced == 0) {
-                       d_printf("<input type=submit name=\"Advanced\" value=\"%s\">\n", _("Advanced View"));
-               } else {
-                       d_printf("<input type=submit name=\"Basic\" value=\"%s\">\n", _("Basic View"));
-               }
                d_printf("<p>\n");
        }
 
        if (snum >= 0) {
                d_printf("<table>\n");
-               show_parameters(snum, 1, advanced, 1);
+               show_parameters(snum, 1, parm_filter, 1);
                d_printf("</table>\n");
        }
-
-       if (advanced) {
-               d_printf("<input type=hidden name=\"Advanced\" value=1>\n");
-       }
-
        d_printf("</FORM>\n");
 }
 
@@ -1109,6 +1340,12 @@ static void printers_page(void)
                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 {
                welcome_page();
        }