From 13af44768b39b622f12870e316293a55d97b06ce Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 7 Jun 2003 01:28:47 +0000 Subject: mark the HEAD branch as deprecated. Nothing that a determined programmer can't work around, but hopefully enough that people will notice that they should be using the 3.0 branch at the moment (This used to be commit d6de8e8a94c8fb7d7837ed2b43092a275cc9d6c5) --- source3/Makefile.in | 7 ++++++- source3/autogen.sh | 6 ++++++ 2 files changed, 12 insertions(+), 1 deletion(-) (limited to 'source3') diff --git a/source3/Makefile.in b/source3/Makefile.in index 5fa3018c69..77af73f5b8 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -626,7 +626,12 @@ NTLM_AUTH_OBJ = utils/ntlm_auth.o $(LIBNTLMSSP_OBJ) $(LIBSAMBA_OBJ) $(POPT_LIB_O ###################################################################### # now the rules... ###################################################################### -all : SHOWFLAGS proto_exists $(SBIN_PROGS) $(BIN_PROGS) $(SHLIBS) \ +all: + @echo The Samba HEAD branch is deprecated pending the release of Samba 3.0 + @echo Please use the SAMBA_3_0 branch + @exit 1 + +all_real : SHOWFLAGS proto_exists $(SBIN_PROGS) $(BIN_PROGS) $(SHLIBS) \ $(MODULES) @EXTRA_ALL_TARGETS@ pam_smbpass : SHOWFLAGS bin/pam_smbpass.@SHLIBEXT@ diff --git a/source3/autogen.sh b/source3/autogen.sh index 2d91173f4a..056c0e6133 100755 --- a/source3/autogen.sh +++ b/source3/autogen.sh @@ -1,5 +1,11 @@ #!/bin/sh +echo The Samba HEAD branch is deprecated pending the release of Samba 3.0 +echo Please use the SAMBA_3_0 branch +echo to update to SAMBA_3_0 use this command: +echo " cvs -z3 update -r SAMBA_3_0 -dP" +exit 1 + # Run this script to build samba from CVS. ## insert all possible names (only works with -- cgit From 95fe82670032a3a43571b46d7bbf2c26bc8cdcd9 Mon Sep 17 00:00:00 2001 From: Herb Lewis Date: Fri, 11 Jul 2003 14:23:45 +0000 Subject: get rid of CFLAGS from LDSHFLAGS and WINBIND_NSS_LDSHFLAGS and instead define it in SHLD for those systems that use CC for SHLD (This used to be commit 142c54ca924bd854e7d840c2a67692c9f61ee396) --- source3/Makefile.in | 4 ++-- source3/configure.in | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'source3') diff --git a/source3/Makefile.in b/source3/Makefile.in index 77af73f5b8..c81fdd4a83 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -18,8 +18,8 @@ CFLAGS=@CFLAGS@ CPPFLAGS=@CPPFLAGS@ EXEEXT=@EXEEXT@ LDFLAGS=@LDFLAGS@ -LDSHFLAGS=@LDSHFLAGS@ @LDFLAGS@ @CFLAGS@ -WINBIND_NSS_LDSHFLAGS=@WINBIND_NSS_LDSHFLAGS@ @LDFLAGS@ @CFLAGS@ +LDSHFLAGS=@LDSHFLAGS@ @LDFLAGS@ +WINBIND_NSS_LDSHFLAGS=@WINBIND_NSS_LDSHFLAGS@ @LDFLAGS@ AWK=@AWK@ DYNEXP=@DYNEXP@ PYTHON=@PYTHON@ diff --git a/source3/configure.in b/source3/configure.in index 93cbb0a871..533757aab8 100644 --- a/source3/configure.in +++ b/source3/configure.in @@ -910,7 +910,7 @@ BLDSHARED="false" HOST_OS="$host_os" LDSHFLAGS="-shared" SONAMEFLAG="#" -SHLD="\${CC}" +SHLD="\${CC} \${CFLAGS}" PICFLAG="" PICSUFFIX="po" POBAD_CC="#" -- cgit From 4a090ba06a54f5da179ac02bb307cc03d08831bf Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Wed, 16 Jul 2003 05:34:56 +0000 Subject: trying to get HEAD building again. If you want the code prior to this merge, checkout HEAD_PRE_3_0_0_BETA_3_MERGE (This used to be commit adb98e7b7cd0f025b52c570e4034eebf4047b1ad) --- source3/Makefile.in | 334 ++--- source3/aclocal.m4 | 115 +- source3/auth/auth.c | 59 +- source3/auth/auth_builtin.c | 9 +- source3/auth/auth_domain.c | 296 ++-- source3/auth/auth_rhosts.c | 19 +- source3/auth/auth_sam.c | 181 ++- source3/auth/auth_server.c | 19 +- source3/auth/auth_unix.c | 2 +- source3/auth/auth_util.c | 402 ++++-- source3/auth/auth_winbind.c | 20 +- source3/auth/pampass.c | 4 +- source3/auth/pass_check.c | 5 +- source3/autogen.sh | 6 - source3/change-log | 2 +- source3/client/client.c | 19 +- source3/client/clitar.c | 12 +- source3/client/mount.cifs.c | 5 +- source3/client/smbmount.c | 4 +- source3/client/tree.c | 6 +- source3/config.sub | 236 ++-- source3/configure.in | 922 +++++++++---- source3/groupdb/mapping.c | 736 +++------- source3/include/.cvsignore | 1 - source3/include/ads.h | 1 + source3/include/auth.h | 2 + source3/include/client.h | 17 +- source3/include/idmap.h | 19 +- source3/include/includes.h | 33 +- source3/include/mapping.h | 28 - source3/include/ntioctl.h | 44 +- source3/include/ntlmssp.h | 9 +- source3/include/passdb.h | 27 +- source3/include/privileges.h | 25 +- source3/include/rpc_dce.h | 26 +- source3/include/rpc_lsa.h | 20 +- source3/include/rpc_samr.h | 10 - source3/include/rpc_secdes.h | 19 +- source3/include/rpc_srvsvc.h | 8 +- source3/include/safe_string.h | 23 +- source3/include/smb.h | 35 +- source3/include/smb_macros.h | 60 +- source3/include/smbprofile.h | 8 + source3/include/trans2.h | 1 + source3/include/version.h | 2 +- source3/include/vfs.h | 420 ++++-- source3/lib/charcnv.c | 45 +- source3/lib/gencache.c | 29 +- source3/lib/module.c | 23 - source3/lib/popt_common.c | 4 +- source3/lib/substitute.c | 20 +- source3/lib/system.c | 125 ++ source3/lib/system_smbd.c | 24 +- source3/lib/time.c | 3 +- source3/lib/username.c | 76 +- source3/lib/util.c | 49 +- source3/lib/util_sid.c | 6 +- source3/lib/util_sock.c | 24 +- source3/lib/util_str.c | 107 +- source3/lib/util_unistr.c | 31 +- source3/lib/util_uuid.c | 6 +- source3/lib/wins_srv.c | 20 +- source3/libads/ads_ldap.c | 16 +- source3/libads/ads_struct.c | 3 +- source3/libads/ads_utils.c | 46 - source3/libads/kerberos_verify.c | 99 +- source3/libads/krb5_setpw.c | 37 +- source3/libads/ldap.c | 213 ++- source3/libads/ldap_printer.c | 23 +- source3/libads/ldap_user.c | 8 +- source3/libads/sasl.c | 5 +- source3/libsmb/cliconnect.c | 113 +- source3/libsmb/clientgen.c | 45 +- source3/libsmb/clifile.c | 4 +- source3/libsmb/clikrb5.c | 30 +- source3/libsmb/climessage.c | 38 +- source3/libsmb/clirap.c | 4 +- source3/libsmb/clirap2.c | 4 +- source3/libsmb/clispnego.c | 2 +- source3/libsmb/namecache.c | 111 +- source3/libsmb/namequery.c | 756 +++++------ source3/libsmb/namequery_dc.c | 128 +- source3/libsmb/nmblib.c | 4 +- source3/libsmb/ntlmssp.c | 120 +- source3/libsmb/ntlmssp_parse.c | 75 +- source3/libsmb/ntlmssp_sign.c | 206 ++- source3/libsmb/pwd_cache.c | 14 +- source3/libsmb/smb_signing.c | 270 ++-- source3/libsmb/smbencrypt.c | 157 ++- source3/libsmb/trustdom_cache.c | 129 +- source3/libsmb/trusts_util.c | 95 +- source3/locking/posix.c | 11 +- source3/modules/vfs_audit.c | 232 ++-- source3/modules/vfs_extd_audit.c | 241 ++-- source3/modules/vfs_fake_perms.c | 240 +--- source3/modules/vfs_netatalk.c | 78 +- source3/modules/vfs_recycle.c | 516 +++---- source3/msdfs/msdfs.c | 18 +- source3/nmbd/nmbd.c | 98 +- source3/nmbd/nmbd_become_lmb.c | 3 +- source3/nmbd/nmbd_browserdb.c | 139 +- source3/nmbd/nmbd_browsesync.c | 8 +- source3/nmbd/nmbd_elections.c | 2 +- source3/nmbd/nmbd_incomingdgrams.c | 16 +- source3/nmbd/nmbd_incomingrequests.c | 2 +- source3/nmbd/nmbd_namelistdb.c | 4 +- source3/nmbd/nmbd_processlogon.c | 67 +- source3/nmbd/nmbd_sendannounce.c | 10 +- source3/nmbd/nmbd_serverlistdb.c | 6 +- source3/nmbd/nmbd_winsserver.c | 416 +++--- source3/nmbd/nmbd_workgroupdb.c | 2 +- source3/nsswitch/wb_client.c | 323 ++++- source3/nsswitch/wb_common.c | 26 +- source3/nsswitch/wbinfo.c | 264 +++- source3/nsswitch/winbindd.c | 75 +- source3/nsswitch/winbindd.h | 8 +- source3/nsswitch/winbindd_ads.c | 143 +- source3/nsswitch/winbindd_cache.c | 513 +++++-- source3/nsswitch/winbindd_cm.c | 676 +++------ source3/nsswitch/winbindd_group.c | 263 +++- source3/nsswitch/winbindd_misc.c | 2 +- source3/nsswitch/winbindd_nss.h | 70 +- source3/nsswitch/winbindd_pam.c | 272 ++-- source3/nsswitch/winbindd_rpc.c | 315 ++++- source3/nsswitch/winbindd_sid.c | 30 +- source3/nsswitch/winbindd_user.c | 67 +- source3/nsswitch/winbindd_util.c | 235 +++- source3/nsswitch/winbindd_wins.c | 24 +- source3/nsswitch/wins.c | 13 +- source3/pam_smbpass/pam_smb_passwd.c | 2 +- source3/pam_smbpass/support.c | 2 +- source3/param/loadparm.c | 337 ++--- source3/passdb/machine_sid.c | 5 +- source3/passdb/passdb.c | 746 +++++++++- source3/passdb/pdb_get_set.c | 31 + source3/passdb/pdb_guest.c | 16 + source3/passdb/pdb_interface.c | 70 +- source3/passdb/pdb_ldap.c | 2479 ++++++++-------------------------- source3/passdb/pdb_smbpasswd.c | 153 +-- source3/passdb/pdb_tdb.c | 509 +------ source3/passdb/pdb_xml.c | 2 +- source3/passdb/privileges.c | 4 +- source3/passdb/secrets.c | 33 +- source3/printing/lpq_parse.c | 62 +- source3/printing/notify.c | 2 +- source3/printing/nt_printing.c | 171 +-- source3/printing/pcap.c | 6 +- source3/printing/printfsp.c | 2 +- source3/printing/printing.c | 6 +- source3/printing/printing_db.c | 4 +- source3/python/py_winbind.c | 4 +- source3/registry/reg_db.c | 2 +- source3/rpc_client/cli_lsarpc.c | 56 +- source3/rpc_client/cli_netlogon.c | 20 +- source3/rpc_client/cli_pipe.c | 1043 +++++++------- source3/rpc_client/cli_samr.c | 107 ++ source3/rpc_client/cli_spoolss.c | 32 +- source3/rpc_parse/parse_misc.c | 142 +- source3/rpc_parse/parse_net.c | 35 +- source3/rpc_parse/parse_prs.c | 278 ++-- source3/rpc_parse/parse_rpc.c | 26 +- source3/rpc_parse/parse_samr.c | 64 +- source3/rpc_parse/parse_sec.c | 179 ++- source3/rpc_parse/parse_spoolss.c | 9 +- source3/rpc_parse/parse_srv.c | 3 +- source3/rpc_server/srv_dfs_nt.c | 2 +- source3/rpc_server/srv_lsa.c | 185 +-- source3/rpc_server/srv_lsa_nt.c | 222 +-- source3/rpc_server/srv_netlog_nt.c | 26 +- source3/rpc_server/srv_pipe.c | 42 +- source3/rpc_server/srv_samr_nt.c | 212 +-- source3/rpc_server/srv_spoolss_nt.c | 85 +- source3/rpc_server/srv_srvsvc_nt.c | 33 +- source3/rpc_server/srv_util.c | 27 +- source3/rpc_server/srv_wkssvc_nt.c | 4 +- source3/rpcclient/cmd_lsarpc.c | 45 - source3/rpcclient/cmd_netlogon.c | 9 +- source3/rpcclient/cmd_samr.c | 24 +- source3/rpcclient/cmd_spoolss.c | 127 +- source3/rpcclient/cmd_wkssvc.c | 2 +- source3/rpcclient/rpcclient.c | 182 ++- source3/sam/idmap.c | 308 +++-- source3/sam/idmap_ldap.c | 1363 ++++++++++--------- source3/sam/idmap_tdb.c | 398 ++++-- source3/sam/idmap_util.c | 333 ++--- source3/script/.cvsignore | 1 - source3/script/build_env.sh | 26 +- source3/script/installswat.sh | 2 +- source3/script/mkproto.awk | 6 +- source3/smbd/.cvsignore | 1 + source3/smbd/change_trust_pw.c | 2 +- source3/smbd/close.c | 2 +- source3/smbd/conn.c | 39 +- source3/smbd/connection.c | 9 +- source3/smbd/dfree.c | 12 +- source3/smbd/dir.c | 20 +- source3/smbd/dosmode.c | 14 +- source3/smbd/fileio.c | 14 +- source3/smbd/filename.c | 8 +- source3/smbd/files.c | 4 + source3/smbd/lanman.c | 10 +- source3/smbd/mangle_hash.c | 17 +- source3/smbd/negprot.c | 16 +- source3/smbd/notify_hash.c | 4 +- source3/smbd/nttrans.c | 707 ++++++++-- source3/smbd/open.c | 38 +- source3/smbd/oplock.c | 2 +- source3/smbd/password.c | 22 +- source3/smbd/posix_acls.c | 989 ++++++++++---- source3/smbd/quotas.c | 114 ++ source3/smbd/reply.c | 86 +- source3/smbd/server.c | 28 +- source3/smbd/service.c | 31 +- source3/smbd/session.c | 17 +- source3/smbd/sesssetup.c | 28 +- source3/smbd/statcache.c | 404 +++--- source3/smbd/trans2.c | 353 +++-- source3/smbd/uid.c | 372 +++++ source3/smbd/utmp.c | 77 +- source3/smbd/vfs-wrap.c | 273 ++-- source3/smbd/vfs.c | 583 +++----- source3/smbwrapper/shared.c | 4 +- source3/smbwrapper/smbw_dir.c | 5 +- source3/tdb/tdb.c | 3 +- source3/tdb/tdbbackup.c | 174 +-- source3/tdb/tdbutil.c | 7 +- source3/torture/cmd_vfs.c | 201 ++- source3/torture/mangle_test.c | 4 +- source3/torture/masktest.c | 4 +- source3/torture/nsstest.c | 49 +- source3/torture/rpctorture.c | 8 +- source3/torture/smbiconv.c | 8 +- source3/torture/torture.c | 5 +- source3/torture/vfstest.c | 20 +- source3/torture/vfstest.h | 2 +- source3/utils/editreg.c | 30 +- source3/utils/net.c | 56 +- source3/utils/net_ads.c | 140 +- source3/utils/net_ads_cldap.c | 242 ++-- source3/utils/net_cache.c | 2 +- source3/utils/net_groupmap.c | 91 +- source3/utils/net_help.c | 20 - source3/utils/net_lookup.c | 8 +- source3/utils/net_rpc.c | 222 ++- source3/utils/net_rpc_join.c | 47 +- source3/utils/net_rpc_samsync.c | 165 ++- source3/utils/ntlm_auth.c | 587 +++++++- source3/utils/pdbedit.c | 36 +- source3/utils/profiles.c | 4 + source3/utils/smbcacls.c | 13 +- source3/utils/smbcontrol.c | 60 +- source3/utils/smbpasswd.c | 21 +- source3/utils/testparm.c | 4 + source3/web/swat.c | 46 +- 254 files changed, 16872 insertions(+), 13044 deletions(-) (limited to 'source3') diff --git a/source3/Makefile.in b/source3/Makefile.in index c81fdd4a83..73ff436c6f 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -31,8 +31,10 @@ PRINTLIBS=@PRINTLIBS@ AUTHLIBS=@AUTHLIBS@ ACLLIBS=@ACLLIBS@ PASSDBLIBS=@PASSDBLIBS@ +IDMAP_LIBS=@IDMAP_LIBS@ ADSLIBS=@ADSLIBS@ KRB5LIBS=@KRB5_LIBS@ +LDAPLIBS=@LDAP_LIBS@ LINK=$(CC) $(FLAGS) $(LDFLAGS) @@ -41,8 +43,8 @@ INSTALLCLIENTCMD_SH=@INSTALLCLIENTCMD_SH@ INSTALLCLIENTCMD_A=@INSTALLCLIENTCMD_A@ VPATH=@srcdir@ -srcdir=@srcdir@ -builddir=@builddir@ +srcdir=@abs_srcdir@ +builddir=@abs_builddir@ SHELL=/bin/sh # XXX: Perhaps this should be @SHELL@ instead -- apparently autoconf @@ -60,6 +62,7 @@ LIBDIR = @libdir@ VFSLIBDIR = $(LIBDIR)/vfs PDBLIBDIR = $(LIBDIR)/pdb RPCLIBDIR = $(LIBDIR)/rpc +IDMAPLIBDIR = $(LIBDIR)/idmap CHARSETLIBDIR = $(LIBDIR)/charset AUTHLIBDIR = $(LIBDIR)/auth CONFIGDIR = @configdir@ @@ -104,7 +107,6 @@ FLAGS3 = FLAGS4 = FLAGS5 = $(FLAGS1) $(FLAGS2) $(FLAGS3) $(FLAGS4) FLAGS = $(ISA) $(FLAGS5) -FLAGS32 = $(ISA32) $(FLAGS5) PASSWD_FLAGS = -DSMB_PASSWD_FILE=\"$(SMB_PASSWD_FILE)\" -DPRIVATE_DIR=\"$(PRIVATE_DIR)\" PATH_FLAGS1 = -DCONFIGFILE=\"$(CONFIGFILE)\" -DSBINDIR=\"$(SBINDIR)\" @@ -118,8 +120,7 @@ PATH_FLAGS = $(PATH_FLAGS6) $(PASSWD_FLAGS) # Note that all executable programs now provide for an optional executable suffix. -SBIN_PROGS = bin/smbd@EXEEXT@ bin/nmbd@EXEEXT@ bin/swat@EXEEXT@ \ - bin/wrepld@EXEEXT@ @EXTRA_SBIN_PROGS@ +SBIN_PROGS = bin/smbd@EXEEXT@ bin/nmbd@EXEEXT@ bin/swat@EXEEXT@ @EXTRA_SBIN_PROGS@ BIN_PROGS1 = bin/smbclient@EXEEXT@ bin/net@EXEEXT@ bin/smbspool@EXEEXT@ \ bin/testparm@EXEEXT@ bin/testprns@EXEEXT@ bin/smbstatus@EXEEXT@ @@ -127,7 +128,11 @@ BIN_PROGS2 = bin/smbcontrol@EXEEXT@ bin/smbtree@EXEEXT@ bin/tdbbackup@EXEEXT@ \ bin/nmblookup@EXEEXT@ bin/pdbedit@EXEEXT@ BIN_PROGS3 = bin/smbpasswd@EXEEXT@ bin/rpcclient@EXEEXT@ bin/smbcacls@EXEEXT@ \ bin/profiles@EXEEXT@ bin/ntlm_auth@EXEEXT@ \ - bin/editreg@EXEEXT@ bin/smbcquotas@EXEEXT@ + bin/smbcquotas@EXEEXT@ + +# editreg removed from standard build until it is portable. It needs a major rewrite to +# achieve this (tridge) +# bin/editreg@EXEEXT@ TORTURE_PROGS = bin/smbtorture@EXEEXT@ bin/msgtest@EXEEXT@ \ bin/masktest@EXEEXT@ bin/locktest@EXEEXT@ \ @@ -141,21 +146,22 @@ SHLIBS = @SHLIB_PROGS@ @LIBSMBCLIENT@ SCRIPTS = $(srcdir)/script/smbtar $(builddir)/script/findsmb -QUOTAOBJS=@QUOTAOBJS@ - VFS_MODULES = @VFS_MODULES@ PDB_MODULES = @PDB_MODULES@ RPC_MODULES = @RPC_MODULES@ +IDMAP_MODULES = @IDMAP_MODULES@ CHARSET_MODULES = @CHARSET_MODULES@ AUTH_MODULES = @AUTH_MODULES@ -MODULES = $(VFS_MODULES) $(PDB_MODULES) $(RPC_MODULES) $(CHARSET_MODULES) $(AUTH_MODULES) +MODULES = $(VFS_MODULES) $(PDB_MODULES) $(RPC_MODULES) $(IDMAP_MODULES) $(CHARSET_MODULES) $(AUTH_MODULES) ###################################################################### # object file lists ###################################################################### TDBBASE_OBJ = tdb/tdb.o tdb/spinlock.o -TDB_OBJ = $(TDBBASE_OBJ) tdb/tdbutil.o +TDB_OBJ = $(TDBBASE_OBJ) tdb/tdbutil.o tdb/tdbback.o + +SMBLDAP_OBJ = @SMBLDAP@ LIB_OBJ = lib/charcnv.o lib/debug.o lib/fault.o \ lib/getsmbpass.o lib/interface.o lib/md4.o \ @@ -175,10 +181,9 @@ LIB_OBJ = lib/charcnv.o lib/debug.o lib/fault.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/gencache.o $(TDB_OBJ) \ - lib/module.o lib/genparser.o lib/genparser_samba.o \ - lib/ldap_escape.o @CHARSET_STATIC@ + lib/module.o lib/ldap_escape.o @CHARSET_STATIC@ -LIB_SMBD_OBJ = lib/system_smbd.o lib/util_smbd.o +LIB_SMBD_OBJ = lib/system_smbd.o lib/util_smbd.o READLINE_OBJ = lib/readline.o @@ -202,11 +207,9 @@ LIBADS_SERVER_OBJ = libads/util.o libads/kerberos_verify.o SECRETS_OBJ = passdb/secrets.o LIBNMB_OBJ = libsmb/unexpected.o libsmb/namecache.o libsmb/nmblib.o \ - libsmb/namequery.o + libsmb/namequery.o libsmb/conncache.o -LIBNTLMSSP_OBJ = libsmb/ntlmssp.o libsmb/ntlmssp_parse.o libsmb/ntlmssp_sign.o - -LIBSAMBA_OBJ = libsmb/nterr.o libsmb/smbdes.o libsmb/smbencrypt.o +LIBSAMBA_OBJ = libsmb/nterr.o libsmb/smbdes.o libsmb/smbencrypt.o libsmb/ntlmssp.o libsmb/ntlmssp_parse.o libsmb/ntlmssp_sign.o LIBSMB_OBJ = libsmb/clientgen.o libsmb/cliconnect.o libsmb/clifile.o \ libsmb/clikrb5.o libsmb/clispnego.o libsmb/asn1.o \ @@ -218,17 +221,14 @@ LIBSMB_OBJ = libsmb/clientgen.o libsmb/cliconnect.o libsmb/clifile.o \ libsmb/smberr.o libsmb/credentials.o libsmb/pwd_cache.o \ libsmb/clioplock.o libsmb/errormap.o libsmb/clirap2.o \ libsmb/passchange.o libsmb/doserr.o \ - libsmb/trustdom_cache.o \ - $(RPC_PARSE_OBJ1) $(LIBNTLMSSP_OBJ) $(LIBSAMBA_OBJ) $(LIBNMB_OBJ) + $(RPC_PARSE_OBJ1) $(LIBSAMBA_OBJ) $(LIBNMB_OBJ) LIBMSRPC_OBJ = rpc_client/cli_lsarpc.o rpc_client/cli_samr.o \ rpc_client/cli_netlogon.o rpc_client/cli_srvsvc.o \ rpc_client/cli_wkssvc.o rpc_client/cli_dfs.o \ rpc_client/cli_reg.o rpc_client/cli_pipe.o \ rpc_client/cli_spoolss.o rpc_client/cli_spoolss_notify.o \ - rpc_client/cli_ds.o rpc_client/cli_echo.o libsmb/namequery_dc.o - -LIBMSRPC_SERVER_OBJ = libsmb/trusts_util.o + rpc_client/cli_ds.o rpc_client/cli_echo.o REGOBJS_OBJ = registry/reg_objects.o REGISTRY_OBJ = registry/reg_frontend.o registry/reg_cachehook.o registry/reg_printing.o \ @@ -279,26 +279,17 @@ 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/util_sam_sid.o passdb/pdb_compat.o \ - passdb/privileges.o @LDAP_OBJ@ @PDB_STATIC@ + passdb/privileges.o @PDB_STATIC@ XML_OBJ = passdb/pdb_xml.o MYSQL_OBJ = passdb/pdb_mysql.o -DEVEL_HELP_OBJ = modules/developer.o - -SAM_STATIC_MODULES = sam/sam_plugin.o sam/sam_skel.o sam/sam_ads.o - -IDMAP_OBJ = sam/idmap.o sam/idmap_util.o sam/idmap_tdb.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_STATIC_MODULES) - -SAMTEST_OBJ = torture/samtest.o torture/cmd_sam.o $(PARAM_OBJ) $(SAM_OBJ) $(LIB_OBJ) $(LIBSMB_OBJ) $(UBIQX_OBJ) $(READLINE_OBJ) lib/util_seaccess.o $(LIBADS_OBJ) $(KRBCLIENT_OBJ) $(PASSDB_OBJ) $(SECRETS_OBJ) $(GROUPDB_OBJ) +DEVEL_HELP_OBJ = modules/weird.o GROUPDB_OBJ = groupdb/mapping.o PROFILE_OBJ = profile/profile.o PROFILES_OBJ = utils/profiles.o -EDITREG_OBJ = utils/editreg.o lib/snprintf.o +EDITREG_OBJ = utils/editreg.o OPLOCK_OBJ = smbd/oplock.o smbd/oplock_irix.o smbd/oplock_linux.o @@ -306,13 +297,15 @@ NOTIFY_OBJ = smbd/notify.o smbd/notify_hash.o smbd/notify_kernel.o VFS_AUDIT_OBJ = modules/vfs_audit.o VFS_EXTD_AUDIT_OBJ = modules/vfs_extd_audit.o +VFS_FAKE_PERMS_OBJ = modules/vfs_fake_perms.o VFS_RECYCLE_OBJ = modules/vfs_recycle.o VFS_NETATALK_OBJ = modules/vfs_netatalk.o -VFS_FAKE_PERMS_OBJ = modules/vfs_fake_perms.o PLAINTEXT_AUTH_OBJ = auth/pampass.o auth/pass_check.o -UNIGRP_OBJ = libsmb/netlogon_unigrp.o +SLCACHE_OBJ = libsmb/samlogon_cache.o + +DCUTIL_OBJ = libsmb/namequery_dc.o libsmb/trustdom_cache.o libsmb/trusts_util.o AUTH_BUILTIN_OBJ = auth/auth_builtin.o AUTH_DOMAIN_OBJ = auth/auth_domain.o @@ -323,13 +316,15 @@ AUTH_UNIX_OBJ = auth/auth_unix.o AUTH_WINBIND_OBJ = auth/auth_winbind.o AUTH_OBJ = auth/auth.o @AUTH_STATIC@ auth/auth_util.o auth/auth_compat.o \ - auth/auth_ntlmssp.o \ - $(PLAINTEXT_AUTH_OBJ) $(UNIGRP_OBJ) + auth/auth_ntlmssp.o \ + $(PLAINTEXT_AUTH_OBJ) $(SLCACHE_OBJ) $(DCUTIL_OBJ) MANGLE_OBJ = smbd/mangle.o smbd/mangle_hash.o smbd/mangle_map.o smbd/mangle_hash2.o SMBD_OBJ_MAIN = smbd/server.o +BUILDOPT_OBJ = smbd/build_options.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 \ @@ -342,20 +337,19 @@ SMBD_OBJ_SRV = smbd/files.o smbd/chgpasswd.o smbd/connection.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/build_options.o \ - smbd/change_trust_pw.o \ + lib/sysquotas.o smbd/change_trust_pw.o smbd/fake_file.o \ + smbd/quotas.o smbd/ntquotas.o \ $(MANGLE_OBJ) @VFS_STATIC@ SMBD_OBJ_BASE = $(PARAM_OBJ) $(SMBD_OBJ_SRV) $(MSDFS_OBJ) $(LIBSMB_OBJ) \ - $(RPC_SERVER_OBJ) $(RPC_PARSE_OBJ) $(SECRETS_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) \ + $(LIB_OBJ) $(PRINTBACKEND_OBJ) $(OPLOCK_OBJ) \ $(NOTIFY_OBJ) $(GROUPDB_OBJ) $(AUTH_OBJ) \ - $(LIBMSRPC_OBJ) $(LIBMSRPC_SERVER_OBJ) \ + $(LIBMSRPC_OBJ) \ $(LIBADS_OBJ) $(KRBCLIENT_OBJ) $(LIBADS_SERVER_OBJ) \ $(LIB_SMBD_OBJ) $(REGISTRY_OBJ) $(POPT_LIB_OBJ) \ - $(IDMAP_OBJ) - + $(UBIQX_OBJ) $(BUILDOPT_OBJ) $(SMBLDAP_OBJ) PRINTING_OBJ = printing/pcap.o printing/print_svid.o \ printing/print_cups.o printing/print_generic.o \ @@ -395,7 +389,7 @@ SWAT_OBJ1 = web/cgi.o web/diagnose.o web/startstop.o web/statuspage.o \ SWAT_OBJ = $(SWAT_OBJ1) $(PARAM_OBJ) $(PRINTING_OBJ) $(LIBSMB_OBJ) \ $(LOCKING_OBJ) $(PASSDB_OBJ) $(SECRETS_OBJ) $(KRBCLIENT_OBJ) \ $(UBIQX_OBJ) $(LIB_OBJ) $(GROUPDB_OBJ) $(PLAINTEXT_AUTH_OBJ) \ - $(POPT_LIB_OBJ) $(IDMAP_OBJ) + $(POPT_LIB_OBJ) $(SMBLDAP_OBJ) SMBSH_OBJ = smbwrapper/smbsh.o smbwrapper/shared.o \ $(PARAM_OBJ) $(UBIQX_OBJ) $(LIB_OBJ) @@ -420,14 +414,11 @@ TESTPRNS_OBJ = utils/testprns.o $(PARAM_OBJ) $(PRINTING_OBJ) $(UBIQX_OBJ) \ SMBPASSWD_OBJ = utils/smbpasswd.o $(PARAM_OBJ) $(SECRETS_OBJ) \ $(LIBSMB_OBJ) $(PASSDB_OBJ) $(GROUPDB_OBJ)\ $(UBIQX_OBJ) $(LIB_OBJ) $(KRBCLIENT_OBJ) \ - $(IDMAP_OBJ) + $(SMBLDAP_OBJ) PDBEDIT_OBJ = utils/pdbedit.o $(PARAM_OBJ) $(PASSDB_OBJ) $(LIBSAMBA_OBJ) \ $(UBIQX_OBJ) $(LIB_OBJ) $(GROUPDB_OBJ) $(SECRETS_OBJ) \ - $(POPT_LIB_OBJ) $(IDMAP_OBJ) - -SMBGROUPEDIT_OBJ = utils/smbgroupedit.o $(GROUPDB_OBJ) $(PARAM_OBJ) \ - $(LIBSAMBA_OBJ) $(PASSDB_OBJ) $(SECRETS_OBJ) $(UBIQX_OBJ) $(LIB_OBJ) $(IDMAP_OBJ) + $(POPT_LIB_OBJ) $(SMBLDAP_OBJ) RPCCLIENT_OBJ1 = rpcclient/rpcclient.o rpcclient/cmd_lsarpc.o \ rpcclient/cmd_samr.o rpcclient/cmd_spoolss.o \ @@ -441,7 +432,7 @@ RPCCLIENT_OBJ = $(RPCCLIENT_OBJ1) \ $(RPC_PARSE_OBJ) $(PASSDB_OBJ) $(LIBMSRPC_OBJ) \ $(READLINE_OBJ) $(GROUPDB_OBJ) $(KRBCLIENT_OBJ) \ $(LIBADS_OBJ) $(SECRETS_OBJ) $(POPT_LIB_OBJ) \ - $(IDMAP_OBJ) + $(SMBLDAP_OBJ) $(DCUTIL_OBJ) PAM_WINBIND_OBJ = nsswitch/pam_winbind.po nsswitch/wb_common.po lib/snprintf.po @@ -469,7 +460,7 @@ LIBBIGBALLOFMUD_MAJOR = 0 LIBBIGBALLOFMUD_OBJ = $(PARAM_OBJ) $(LIB_OBJ) $(UBIQX_OBJ) $(SECRETS_OBJ) \ $(LIBSMB_OBJ) $(LIBMSRPC_OBJ) $(RPC_PARSE_OBJ) $(PASSDB_OBJ) \ - $(GROUPDB_OBJ) $(KRBCLIENT_OBJ) + $(GROUPDB_OBJ) $(KRBCLIENT_OBJ) $(SMBLDAP_OBJ) LIBBIGBALLOFMUD_PICOBJS = $(LIBBIGBALLOFMUD_OBJ:.o=.po) @@ -482,14 +473,14 @@ CLIENT_OBJ = $(CLIENT_OBJ1) $(PARAM_OBJ) $(LIBSMB_OBJ) $(UBIQX_OBJ) \ 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 utils/net_groupmap.o + utils/net_cache.o utils/net_groupmap.o utils/net_idmap.o NET_OBJ = $(NET_OBJ1) $(PARAM_OBJ) $(SECRETS_OBJ) $(LIBSMB_OBJ) \ $(RPC_PARSE_OBJ) $(PASSDB_OBJ) $(GROUPDB_OBJ) \ $(KRBCLIENT_OBJ) $(UBIQX_OBJ) $(LIB_OBJ) \ - $(LIBMSRPC_OBJ) $(LIBMSRPC_SERVER_OBJ) \ + $(LIBMSRPC_OBJ) $(IDMAP_OBJ) \ $(LIBADS_OBJ) $(LIBADS_SERVER_OBJ) $(POPT_LIB_OBJ) \ - $(IDMAP_OBJ) + $(SMBLDAP_OBJ) $(DCUTIL_OBJ) CUPS_OBJ = client/smbspool.o $(PARAM_OBJ) $(LIBSMB_OBJ) $(UBIQX_OBJ) \ $(LIB_OBJ) $(KRBCLIENT_OBJ) @@ -532,7 +523,7 @@ LOCKTEST2_OBJ = torture/locktest2.o $(PARAM_OBJ) $(LOCKING_OBJ) $(LIBSMB_OBJ) \ SMBCACLS_OBJ = utils/smbcacls.o $(PARAM_OBJ) $(LOCKING_OBJ) $(LIBSMB_OBJ) \ $(KRBCLIENT_OBJ) $(UBIQX_OBJ) $(LIB_OBJ) $(RPC_PARSE_OBJ) \ $(PASSDB_GET_SET_OBJ) $(LIBMSRPC_OBJ) $(SECRETS_OBJ) \ - $(POPT_LIB_OBJ) + $(POPT_LIB_OBJ) $(DCUTIL_OBJ) $(LIBADS_OBJ) SMBCQUOTAS_OBJ = utils/smbcquotas.o $(LOCKING_OBJ) $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) \ $(PARAM_OBJ) \ @@ -559,34 +550,35 @@ SMBFILTER_OBJ = utils/smbfilter.o $(PARAM_OBJ) $(LIBSMB_OBJ) \ 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) \ + $(LIBMSRPC_OBJ) $(RPC_CLIENT_OBJ) \ $(RPC_PIPE_OBJ) $(RPC_PARSE_OBJ) $(KRBCLIENT_OBJ) \ $(AUTH_OBJ) $(PARAM_OBJ) $(LOCKING_OBJ) $(SECRETS_OBJ) \ $(PRINTING_OBJ) $(PRINTBACKEND_OBJ) $(OPLOCK_OBJ) $(NOTIFY_OBJ) \ - $(QUOTAOBJS) $(PASSDB_OBJ) $(GROUPDB_OBJ) $(MSDFS_OBJ) \ + $(PASSDB_OBJ) $(GROUPDB_OBJ) $(MSDFS_OBJ) \ $(READLINE_OBJ) $(PROFILE_OBJ) $(LIBADS_OBJ) $(LIBADS_SERVER_OBJ) \ $(LIB_SMBD_OBJ) $(SAM_OBJ) $(REGISTRY_OBJ) $(POPT_LIB_OBJ) \ $(RPC_LSA_OBJ) $(RPC_NETLOG_OBJ) $(RPC_SAMR_OBJ) $(RPC_REG_OBJ) \ $(RPC_SVC_OBJ) $(RPC_WKS_OBJ) $(RPC_DFS_OBJ) $(RPC_SPOOLSS_OBJ) \ - $(IDMAP_OBJ) $(RPC_ECHO_OBJ) + $(RPC_ECHO_OBJ) $(SMBLDAP_OBJ) $(IDMAP_OBJ) -NSS_OBJ_0 = nsswitch/wins.o $(PARAM_OBJ) $(UBIQX_OBJ) $(LIBSMB_OBJ) \ - $(LIB_OBJ) $(NSSWINS_OBJ) +WINBIND_WINS_NSS_OBJ = nsswitch/wins.o $(PARAM_OBJ) $(UBIQX_OBJ) \ + $(LIBSMB_OBJ) $(LIB_OBJ) $(NSSWINS_OBJ) -NSS_OBJ = $(NSS_OBJ_0:.o=.po) +WINBIND_WINS_NSS_PICOBJS = $(WINBIND_WINS_NSS_OBJ:.o=.po) PICOBJS = $(SMBWRAPPER_OBJ:.o=.po) -PICOBJS32 = $(SMBWRAPPER_OBJ:.o=.po32) LIBSMBCLIENT_PICOBJS = $(LIBSMBCLIENT_OBJ:.o=.po) PAM_SMBPASS_OBJ_0 = pam_smbpass/pam_smb_auth.o pam_smbpass/pam_smb_passwd.o \ pam_smbpass/pam_smb_acct.o pam_smbpass/support.o \ libsmb/smbencrypt.o libsmb/smbdes.o libsmb/nterr.o \ $(PARAM_OBJ) $(LIB_OBJ) $(PASSDB_OBJ) $(GROUPDB_OBJ) \ - $(SECRETS_OBJ) $(UBIQX_OBJ) $(IDMAP_OBJ) + $(SECRETS_OBJ) $(UBIQX_OBJ) PAM_SMBPASS_PICOOBJ = $(PAM_SMBPASS_OBJ_0:.o=.po) +IDMAP_OBJ = sam/idmap.o sam/idmap_util.o @IDMAP_STATIC@ + WINBINDD_OBJ1 = \ nsswitch/winbindd.o \ nsswitch/winbindd_user.o \ @@ -601,16 +593,18 @@ WINBINDD_OBJ1 = \ nsswitch/winbindd_rpc.o \ nsswitch/winbindd_ads.o \ nsswitch/winbindd_dual.o \ - nsswitch/winbindd_passdb.o + nsswitch/winbindd_acct.o WINBINDD_OBJ = \ $(WINBINDD_OBJ1) $(PASSDB_OBJ) $(GROUPDB_OBJ) \ $(PARAM_OBJ) $(UBIQX_OBJ) $(LIB_OBJ) \ $(LIBSMB_OBJ) $(LIBMSRPC_OBJ) $(RPC_PARSE_OBJ) \ - $(PROFILE_OBJ) $(UNIGRP_OBJ) $(IDMAP_OBJ) \ - $(SECRETS_OBJ) $(LIBADS_OBJ) $(KRBCLIENT_OBJ) $(POPT_LIB_OBJ) + $(PROFILE_OBJ) $(SLCACHE_OBJ) $(SMBLDAP_OBJ) \ + $(SECRETS_OBJ) $(LIBADS_OBJ) $(KRBCLIENT_OBJ) $(POPT_LIB_OBJ) \ + $(DCUTIL_OBJ) $(IDMAP_OBJ) -WBINFO_OBJ = nsswitch/wbinfo.o libsmb/smbencrypt.o libsmb/smbdes.o $(POPT_LIB_OBJ) +WBINFO_OBJ = nsswitch/wbinfo.o $(LIBSAMBA_OBJ) $(PARAM_OBJ) $(LIB_OBJ) \ + $(UBIQX_OBJ) $(SECRETS_OBJ) $(POPT_LIB_OBJ) WINBIND_NSS_OBJ = nsswitch/wb_common.o @WINBIND_NSS_EXTRA_OBJS@ @@ -619,19 +613,14 @@ WINBIND_NSS_PICOBJS = $(WINBIND_NSS_OBJ:.o=.po) POPT_OBJS=popt/findme.o popt/popt.o popt/poptconfig.o \ popt/popthelp.o popt/poptparse.o -TDBBACKUP_OBJ = tdb/tdbbackup.o $(TDBBASE_OBJ) +TDBBACKUP_OBJ = tdb/tdbbackup.o tdb/tdbback.o $(TDBBASE_OBJ) -NTLM_AUTH_OBJ = utils/ntlm_auth.o $(LIBNTLMSSP_OBJ) $(LIBSAMBA_OBJ) $(POPT_LIB_OBJ) +NTLM_AUTH_OBJ = utils/ntlm_auth.o $(LIBSAMBA_OBJ) $(POPT_LIB_OBJ) ###################################################################### # now the rules... ###################################################################### -all: - @echo The Samba HEAD branch is deprecated pending the release of Samba 3.0 - @echo Please use the SAMBA_3_0 branch - @exit 1 - -all_real : SHOWFLAGS proto_exists $(SBIN_PROGS) $(BIN_PROGS) $(SHLIBS) \ +all : SHOWFLAGS proto_exists $(SBIN_PROGS) $(BIN_PROGS) $(SHLIBS) \ $(MODULES) @EXTRA_ALL_TARGETS@ pam_smbpass : SHOWFLAGS bin/pam_smbpass.@SHLIBEXT@ @@ -662,20 +651,20 @@ smbfilter : SHOWFLAGS bin/smbfilter@EXEEXT@ talloctort : SHOWFLAGS bin/talloctort@EXEEXT@ -nsswitch : SHOWFLAGS bin/winbindd@EXEEXT@ bin/wbinfo@EXEEXT@ nsswitch/@WINBIND_NSS@ nsswitch/pam_winbind.@SHLIBEXT@ +nsswitch : SHOWFLAGS bin/winbindd@EXEEXT@ bin/wbinfo@EXEEXT@ @WINBIND_NSS@ \ + @WINBIND_WINS_NSS@ nsswitch/pam_winbind.@SHLIBEXT@ -wins : SHOWFLAGS nsswitch/libnss_wins.@SHLIBEXT@ +wins : SHOWFLAGS @WINBIND_WINS_NSS@ modules: SHOWFLAGS proto_exists $(MODULES) -everything: all libsmbclient debug2html smbfilter talloctort torture +everything: all libsmbclient debug2html smbfilter talloctort modules torture .SUFFIXES: -.SUFFIXES: .c .o .po .po32 .lo +.SUFFIXES: .c .o .po .lo SHOWFLAGS: @echo "Using FLAGS = $(FLAGS)" - @echo " FLAGS32 = $(FLAGS32)" @echo " LIBS = $(LIBS)" @echo " LDSHFLAGS = $(LDSHFLAGS)" @echo " LDFLAGS = $(LDFLAGS)" @@ -715,6 +704,14 @@ dynconfig.po: dynconfig.c Makefile @BROKEN_CC@ -mv `echo $@ | sed -e 's%^.*/%%g' -e 's%\.po$$%.o%'` $@ @POBAD_CC@ @mv $*.po.o $@ +smbd/build_options.o: smbd/build_options.c Makefile include/config.h include/build_env.h include/proto.h + @echo Compiling $*.c + @$(CC) $(FLAGS) $(PATH_FLAGS) -c $< -o $@ + +smbd/build_options.c: include/config.h.in script/mkbuildoptions.awk + @echo Generating $@ + @dir=smbd $(MAKEDIR) && $(AWK) -f $(srcdir)/script/mkbuildoptions.awk > $(builddir)/smbd/build_options.c < $(srcdir)/include/config.h.in + .c.po: @if (: >> $@ || : > $@) >/dev/null 2>&1; then rm -f $@; else \ dir=`echo $@ | sed 's,/[^/]*$$,,;s,^$$,.,'` $(MAKEDIR); fi @@ -723,16 +720,6 @@ dynconfig.po: dynconfig.c Makefile @BROKEN_CC@ -mv `echo $@ | sed -e 's%^.*/%%g' -e 's%\.po$$%.o%'` $@ @POBAD_CC@ @mv $*.po.o $@ -# this is for IRIX -.c.po32: - @if (: >> $@ || : > $@) >/dev/null 2>&1; then rm -f $@; else \ - dir=`echo $@ | sed 's,/[^/]*$$,,;s,^$$,.,'` $(MAKEDIR); fi - @echo Compiling $*.c with @PICFLAG@ and -32 - @$(CC) -32 -I. -I$(srcdir) $(FLAGS32) $(PATH_FLAGS) @PICFLAG@ -c $< \ - -o $*.po32.o -@BROKEN_CC@ -mv `echo $@ | sed -e 's%^.*/%%g' -e 's%\.po32$$%.o%'` $@.o - @mv $*.po32.o $@ - bin/.dummy: @if (: >> $@ || : > $@) >/dev/null 2>&1; then :; else \ dir=bin $(MAKEDIR); fi @@ -745,7 +732,7 @@ bin/smbd@EXEEXT@: $(SMBD_OBJ) @BUILD_POPT@ bin/.dummy bin/nmbd@EXEEXT@: $(NMBD_OBJ) @BUILD_POPT@ bin/.dummy @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(NMBD_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) @POPTLIBS@ $(KRB5LIBS) + @$(CC) $(FLAGS) -o $@ $(NMBD_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) @POPTLIBS@ $(ADSLIBS) bin/wrepld@EXEEXT@: $(WREPL_OBJ) @BUILD_POPT@ bin/.dummy @echo Linking $@ @@ -754,7 +741,7 @@ bin/wrepld@EXEEXT@: $(WREPL_OBJ) @BUILD_POPT@ bin/.dummy bin/swat@EXEEXT@: $(SWAT_OBJ) @BUILD_POPT@ bin/.dummy @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(SWAT_OBJ) $(LDFLAGS) $(DYNEXP) $(PRINTLIBS) \ - $(AUTHLIBS) $(LIBS) $(PASSDBLIBS) @POPTLIBS@ $(KRB5LIBS) + $(AUTHLIBS) $(LIBS) $(PASSDBLIBS) @POPTLIBS@ $(KRB5LIBS) bin/rpcclient@EXEEXT@: $(RPCCLIENT_OBJ) @BUILD_POPT@ bin/.dummy @echo Linking $@ @@ -762,11 +749,11 @@ bin/rpcclient@EXEEXT@: $(RPCCLIENT_OBJ) @BUILD_POPT@ bin/.dummy bin/smbclient@EXEEXT@: $(CLIENT_OBJ) @BUILD_POPT@ bin/.dummy @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(CLIENT_OBJ) $(LDFLAGS) $(DYNEXP) $(TERMLDFLAGS) $(TERMLIBS) $(LIBS) @POPTLIBS@ $(KRB5LIBS) + @$(CC) $(FLAGS) -o $@ $(CLIENT_OBJ) $(LDFLAGS) $(DYNEXP) $(TERMLDFLAGS) $(TERMLIBS) $(LIBS) @POPTLIBS@ $(ADSLIBS) bin/net@EXEEXT@: $(NET_OBJ) @BUILD_POPT@ bin/.dummy @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(NET_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) @POPTLIBS@ $(ADSLIBS) + @$(CC) $(FLAGS) -o $@ $(NET_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) @POPTLIBS@ $(ADSLIBS) $(PASSDBLIBS) bin/profiles@EXEEXT@: $(PROFILES_OBJ) @BUILD_POPT@ bin/.dummy @echo Linking $@ @@ -778,11 +765,11 @@ bin/editreg@EXEEXT@: $(EDITREG_OBJ) @BUILD_POPT@ bin/.dummy bin/smbspool@EXEEXT@: $(CUPS_OBJ) bin/.dummy @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(CUPS_OBJ) $(LDFLAGS) $(LIBS) $(KRB5LIBS) + @$(CC) $(FLAGS) -o $@ $(CUPS_OBJ) $(LDFLAGS) $(LIBS) $(KRB5LIBS) $(LDAPLIBS) bin/smbmount@EXEEXT@: $(MOUNT_OBJ) bin/.dummy @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(MOUNT_OBJ) $(LDFLAGS) $(LIBS) $(KRB5LIBS) + @$(CC) $(FLAGS) -o $@ $(MOUNT_OBJ) $(LDFLAGS) $(LIBS) $(KRB5LIBS) $(LDAPLIBS) bin/smbmnt@EXEEXT@: $(MNT_OBJ) bin/.dummy @echo Linking $@ @@ -810,7 +797,7 @@ bin/smbcontrol@EXEEXT@: $(SMBCONTROL_OBJ) @BUILD_POPT@ bin/.dummy bin/smbtree@EXEEXT@: $(SMBTREE_OBJ) @BUILD_POPT@ bin/.dummy @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(SMBTREE_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) @POPTLIBS@ $(KRB5LIBS) + @$(CC) $(FLAGS) -o $@ $(SMBTREE_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAPLIBS) bin/smbpasswd@EXEEXT@: $(SMBPASSWD_OBJ) bin/.dummy @echo Linking $@ @@ -818,23 +805,19 @@ bin/smbpasswd@EXEEXT@: $(SMBPASSWD_OBJ) bin/.dummy bin/pdbedit@EXEEXT@: $(PDBEDIT_OBJ) @BUILD_POPT@ bin/.dummy @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(PASSDBLIBS) $(PDBEDIT_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) @POPTLIBS@ + @$(CC) $(FLAGS) -o $@ $(PDBEDIT_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) @POPTLIBS@ $(PASSDBLIBS) bin/samtest@EXEEXT@: $(SAMTEST_OBJ) @BUILD_POPT@ bin/.dummy @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(SAMTEST_OBJ) $(LDFLAGS) $(TERMLDFLAGS) $(TERMLIBS) $(DYNEXP) $(LIBS) @POPTLIBS@ $(PASSDBLIBS) $(ADSLIBS) - -bin/smbgroupedit@EXEEXT@: $(SMBGROUPEDIT_OBJ) bin/.dummy - @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(SMBGROUPEDIT_OBJ) $(PASSDBLIBS) $(LDFLAGS) $(DYNEXP) $(LIBS) + @$(CC) $(FLAGS) -o $@ $(SAMTEST_OBJ) $(LDFLAGS) $(TERMLDFLAGS) $(TERMLIBS) $(DYNEXP) $(LIBS) @POPTLIBS@ $(PASSDBLIBS) $(KRB5LIBS) $(LDAPLIBS) bin/nmblookup@EXEEXT@: $(NMBLOOKUP_OBJ) @BUILD_POPT@ bin/.dummy @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(NMBLOOKUP_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) @POPTLIBS@ + @$(CC) $(FLAGS) -o $@ $(NMBLOOKUP_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) @POPTLIBS@ $(LDAPLIBS) bin/smbtorture@EXEEXT@: $(SMBTORTURE_OBJ) bin/.dummy @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(SMBTORTURE_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) + @$(CC) $(FLAGS) -o $@ $(SMBTORTURE_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAPLIBS) bin/talloctort@EXEEXT@: $(TALLOCTORT_OBJ) bin/.dummy @echo Linking $@ @@ -842,31 +825,31 @@ bin/talloctort@EXEEXT@: $(TALLOCTORT_OBJ) bin/.dummy bin/masktest@EXEEXT@: $(MASKTEST_OBJ) bin/.dummy @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(MASKTEST_OBJ) $(LDFLAGS) $(LIBS) $(KRB5LIBS) + @$(CC) $(FLAGS) -o $@ $(MASKTEST_OBJ) $(LDFLAGS) $(LIBS) $(KRB5LIBS) $(LDAPLIBS) bin/msgtest@EXEEXT@: $(MSGTEST_OBJ) bin/.dummy @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(MSGTEST_OBJ) $(LDFLAGS) $(LIBS) $(KRB5LIBS) + @$(CC) $(FLAGS) -o $@ $(MSGTEST_OBJ) $(LDFLAGS) $(LIBS) $(KRB5LIBS) $(LDAPLIBS) bin/smbcacls@EXEEXT@: $(SMBCACLS_OBJ) @BUILD_POPT@ bin/.dummy @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(SMBCACLS_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) @POPTLIBS@ $(KRB5LIBS) + @$(CC) $(FLAGS) -o $@ $(SMBCACLS_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAPLIBS) bin/smbcquotas@EXEEXT@: $(SMBCQUOTAS_OBJ) @BUILD_POPT@ bin/.dummy @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(SMBCQUOTAS_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) @POPTLIBS@ $(KRB5LIBS) + @$(CC) $(FLAGS) -o $@ $(SMBCQUOTAS_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAPLIBS) bin/locktest@EXEEXT@: $(LOCKTEST_OBJ) bin/.dummy @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(LOCKTEST_OBJ) $(LDFLAGS) $(LIBS) $(KRB5LIBS) + @$(CC) $(FLAGS) -o $@ $(LOCKTEST_OBJ) $(LDFLAGS) $(LIBS) $(KRB5LIBS) $(LDAPLIBS) bin/nsstest@EXEEXT@: $(NSSTEST_OBJ) bin/.dummy @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(NSSTEST_OBJ) $(LDFLAGS) $(LIBS) $(KRB5LIBS) + @$(CC) $(FLAGS) -o $@ $(NSSTEST_OBJ) $(LDFLAGS) $(LIBS) $(KRB5LIBS) $(LDAPLIBS) bin/vfstest@EXEEXT@: $(VFSTEST_OBJ) @BUILD_POPT@ bin/.dummy @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(VFSTEST_OBJ) $(LDFLAGS) $(TERMLDFLAGS) $(TERMLIBS) $(DYNEXP) $(PRINTLIBS) $(AUTHLIBS) $(ACLLIBS) $(LIBS) @POPTLIBS@ $(ADSLIBS) + @$(CC) $(FLAGS) -o $@ $(VFSTEST_OBJ) $(LDFLAGS) $(TERMLDFLAGS) $(TERMLIBS) $(DYNEXP) $(PRINTLIBS) $(AUTHLIBS) $(ACLLIBS) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAPLIBS) bin/smbiconv@EXEEXT@: $(SMBICONV_OBJ) @BUILD_POPT@ bin/.dummy @echo Linking $@ @@ -874,11 +857,11 @@ bin/smbiconv@EXEEXT@: $(SMBICONV_OBJ) @BUILD_POPT@ bin/.dummy bin/locktest2@EXEEXT@: $(LOCKTEST2_OBJ) bin/.dummy @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(LOCKTEST2_OBJ) $(LDFLAGS) $(LIBS) $(KRB5LIBS) + @$(CC) $(FLAGS) -o $@ $(LOCKTEST2_OBJ) $(LDFLAGS) $(LIBS) $(KRB5LIBS) $(LDAPLIBS) bin/rpctorture@EXEEXT@: $(RPCTORTURE_OBJ) bin/.dummy @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(RPCTORTURE_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) $(KRB5LIBS) + @$(CC) $(FLAGS) -o $@ $(RPCTORTURE_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) $(KRB5LIBS) $(LDAPLIBS) bin/debug2html@EXEEXT@: $(DEBUG2HTML_OBJ) bin/.dummy @echo Linking $@ @@ -886,7 +869,7 @@ bin/debug2html@EXEEXT@: $(DEBUG2HTML_OBJ) bin/.dummy bin/smbfilter@EXEEXT@: $(SMBFILTER_OBJ) bin/.dummy @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(SMBFILTER_OBJ) $(LDFLAGS) $(LIBS) $(KRB5LIBS) + @$(CC) $(FLAGS) -o $@ $(SMBFILTER_OBJ) $(LDFLAGS) $(LIBS) $(KRB5LIBS) $(LDAPLIBS) bin/smbw_sample@EXEEXT@: $(SMBW_OBJ) utils/smbw_sample.o bin/.dummy @echo Linking $@ @@ -901,11 +884,6 @@ bin/smbwrapper.@SHLIBEXT@: $(PICOBJS) bin/.dummy @$(SHLD) $(LDSHFLAGS) -o $@ $(PICOBJS) $(LIBS) \ @SONAMEFLAG@`basename $@` $(KRB5LIBS) -bin/smbwrapper.32.@SHLIBEXT@: $(PICOBJS32) - @echo Linking shared library $@ - @$(SHLD) -32 $(LDSHFLAGS) -o $@ $(PICOBJS32) $(LIBS) \ - @SONAMEFLAG@`basename $@` $(KRB5LIBS) - bin/libsmbclient.@SHLIBEXT@: $(LIBSMBCLIENT_PICOBJS) @echo Linking libsmbclient shared library $@ @$(SHLD) $(LDSHFLAGS) -o $@ $(LIBSMBCLIENT_PICOBJS) $(LDFLAGS) $(LIBS) \ @@ -919,12 +897,12 @@ bin/libsmbclient.a: $(LIBSMBCLIENT_PICOBJS) bin/libbigballofmud.@SHLIBEXT@: $(LIBBIGBALLOFMUD_PICOBJS) @echo Linking bigballofmud shared library $@ @$(SHLD) $(LDSHFLAGS) -o $@ $(LIBBIGBALLOFMUD_PICOBJS) $(LIBS) \ - @SONAMEFLAG@`basename $@`.$(LIBBIGBALLOFMUD_MAJOR) $(PASSDBLIBS) $(ADSLIBS) + @SONAMEFLAG@`basename $@`.$(LIBBIGBALLOFMUD_MAJOR) $(PASSDBLIBS) $(IDMAP_LIBS) $(ADSLIBS) ln -snf libbigballofmud.so bin/libbigballofmud.so.0 # It would be nice to build a static bigballofmud too, but when I try -# I get linker errors about dl_open and similar things. I'm not sure -# if it can be fixed or if they just can't be called from a static +# I get linker errors about dl_open and similar things. I'm not sure if +# it can be fixed or if they just can't be called from a static # library. libsmbclient: $(LIBSMBCLIENT) @@ -974,22 +952,22 @@ bin/librpc_echo.@SHLIBEXT@: $(RPC_ECHO_OBJ) @$(SHLD) $(LDSHFLAGS) -o $@ $(RPC_ECHO_OBJ) -lc \ @SONAMEFLAG@`basename $@` -nsswitch/libnss_wins.@SHLIBEXT@: $(NSS_OBJ) - @echo "Linking $@" - @$(SHLD) $(LDSHFLAGS) -o $@ $(NSS_OBJ) -lc \ - @SONAMEFLAG@`basename $@` - bin/winbindd@EXEEXT@: $(WINBINDD_OBJ) @BUILD_POPT@ bin/.dummy - @echo Linking $@ - @$(LINK) -o $@ $(WINBINDD_OBJ) $(DYNEXP) $(LIBS) @POPTLIBS@ $(ADSLIBS) @LDAP_LIBS@ + @echo "Linking $@" + @$(LINK) -o $@ $(WINBINDD_OBJ) $(DYNEXP) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAPLIBS) -nsswitch/@WINBIND_NSS@: $(WINBIND_NSS_PICOBJS) +@WINBIND_NSS@: $(WINBIND_NSS_PICOBJS) @echo "Linking $@" @$(SHLD) $(WINBIND_NSS_LDSHFLAGS) -o $@ $(WINBIND_NSS_PICOBJS) \ @WINBIND_NSS_EXTRA_LIBS@ @SONAMEFLAG@`basename $@` +@WINBIND_WINS_NSS@: $(WINBIND_WINS_NSS_PICOBJS) + @echo "Linking $@" + @$(SHLD) $(LDSHFLAGS) -o $@ $(WINBIND_WINS_NSS_PICOBJS) -lc \ + @SONAMEFLAG@`basename $@` + nsswitch/pam_winbind.@SHLIBEXT@: $(PAM_WINBIND_OBJ) bin/.dummy - @echo Linking $@ + @echo "Linking $@" @$(SHLD) $(LDSHFLAGS) -o $@ $(PAM_WINBIND_OBJ) \ @SONAMEFLAG@`basename $@` -lpam @@ -1028,7 +1006,7 @@ bin/mysql.@SHLIBEXT@: $(MYSQL_OBJ:.o=.po) bin/ldapsam.@SHLIBEXT@: passdb/pdb_ldap.po @echo "Building plugin $@" - @$(SHLD) $(LDSHFLAGS) @LDAP_LIBS@ -o $@ passdb/pdb_ldap.po \ + @$(SHLD) $(LDSHFLAGS) $(LDAPLIBS) -o $@ passdb/pdb_ldap.po \ @SONAMEFLAG@`basename $@` bin/tdbsam.@SHLIBEXT@: passdb/pdb_tdb.po @@ -1041,11 +1019,6 @@ bin/smbpasswd.@SHLIBEXT@: passdb/pdb_smbpasswd.po @$(SHLD) $(LDSHFLAGS) -o $@ passdb/pdb_smbpasswd.po \ @SONAMEFLAG@`basename $@` -bin/nisplussam.@SHLIBEXT@: passdb/pdb_nisplus.po - @echo "Building plugin $@" - @$(SHLD) $(LDSHFLAGS) -o $@ passdb/pdb_nisplus.po \ - @SONAMEFLAG@`basename $@` - bin/weird.@SHLIBEXT@: $(DEVEL_HELP_OBJ:.o=.po) @echo "Building plugin $@" @$(SHLD) $(LDSHFLAGS) -o $@ $(DEVEL_HELP_OBJ:.o=.po) \ @@ -1081,11 +1054,9 @@ bin/fake_perms.@SHLIBEXT@: $(VFS_FAKE_PERMS_OBJ:.o=.po) @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_FAKE_PERMS_OBJ:.o=.po) \ @SONAMEFLAG@`basename $@` -bin/wbinfo@EXEEXT@: $(WBINFO_OBJ) $(PARAM_OBJ) $(LIB_OBJ) \ - $(UBIQX_OBJ) $(SECRETS_OBJ) @BUILD_POPT@ bin/.dummy +bin/wbinfo@EXEEXT@: $(WBINFO_OBJ) @BUILD_POPT@ bin/.dummy @echo Linking $@ - @$(LINK) -o $@ $(WBINFO_OBJ) $(PARAM_OBJ) $(LIB_OBJ) \ - $(UBIQX_OBJ) $(SECRETS_OBJ) $(LIBS) @POPTLIBS@ + @$(LINK) -o $@ $(WBINFO_OBJ) $(LIBS) @POPTLIBS@ bin/ntlm_auth@EXEEXT@: $(NTLM_AUTH_OBJ) $(PARAM_OBJ) $(LIB_OBJ) \ $(UBIQX_OBJ) @BUILD_POPT@ bin/.dummy @@ -1112,14 +1083,14 @@ bin/t_stringoverflow@EXEEXT@: bin/libbigballofmud.@SHLIBEXT@ torture/t_stringove bin/t_doschar@EXEEXT@: bin/libbigballofmud.@SHLIBEXT@ torture/t_doschar.o $(CC) $(FLAGS) -o $@ $(LIBS) torture/t_doschar.o -L ./bin -lbigballofmud - bin/t_push_ucs2@EXEEXT@: bin/libbigballofmud.@SHLIBEXT@ torture/t_push_ucs2.o $(CC) $(FLAGS) -o $@ $(LIBS) torture/t_push_ucs2.o -L ./bin -lbigballofmud bin/t_snprintf@EXEEXT@: lib/snprintf.c $(CC) $(FLAGS) -o $@ -DTEST_SNPRINTF lib/snprintf.c -lm +install: installbin installman installscripts installdat installswat installmodules -install: installbin installman installscripts installdat installswat installmodules installclientlib +install-everything: install installmodules # DESTDIR is used here to prevent packagers wasting their time # duplicating the Makefile. Remove it and you will have the privelege @@ -1130,7 +1101,7 @@ install: installbin installman installscripts installdat installswat installmodu # is not used installdirs: - @$(SHELL) $(srcdir)/script/installdirs.sh $(DESTDIR)$(BASEDIR) $(DESTDIR)$(BINDIR) $(DESTDIR)$(SBINDIR) $(DESTDIR)$(LIBDIR) $(DESTDIR)$(VARDIR) $(DESTDIR)$(PRIVATEDIR) $(DESTDIR)$(VFSLIBDIR) $(DESTDIR)$(PDBLIBDIR) $(DESTDIR)$(PIDDIR) $(DESTDIR)$(LOCKDIR) + @$(SHELL) $(srcdir)/script/installdirs.sh $(DESTDIR)$(BASEDIR) $(DESTDIR)$(BINDIR) $(DESTDIR)$(SBINDIR) $(DESTDIR)$(LIBDIR) $(DESTDIR)$(VARDIR) $(DESTDIR)$(PRIVATEDIR) $(DESTDIR)$(PIDDIR) $(DESTDIR)$(LOCKDIR) $(DESTDIR)$(MANDIR) installservers: all installdirs @$(SHELL) $(srcdir)/script/installbin.sh $(INSTALLPERMS) $(DESTDIR)$(BASEDIR) $(DESTDIR)$(SBINDIR) $(DESTDIR)$(LIBDIR) $(DESTDIR)$(VARDIR) $(SBIN_PROGS) @@ -1144,6 +1115,7 @@ installmodules: modules installdirs @$(SHELL) $(srcdir)/script/installmodules.sh $(INSTALLPERMS) $(DESTDIR)$(BASEDIR) $(DESTDIR)$(VFSLIBDIR) $(VFS_MODULES) @$(SHELL) $(srcdir)/script/installmodules.sh $(INSTALLPERMS) $(DESTDIR)$(BASEDIR) $(DESTDIR)$(PDBLIBDIR) $(PDB_MODULES) @$(SHELL) $(srcdir)/script/installmodules.sh $(INSTALLPERMS) $(DESTDIR)$(BASEDIR) $(DESTDIR)$(RPCLIBDIR) $(RPC_MODULES) + @$(SHELL) $(srcdir)/script/installmodules.sh $(INSTALLPERMS) $(DESTDIR)$(BASEDIR) $(DESTDIR)$(IDMAPLIBDIR) $(IDMAP_MODULES) @$(SHELL) $(srcdir)/script/installmodules.sh $(INSTALLPERMS) $(DESTDIR)$(BASEDIR) $(DESTDIR)$(CHARSETLIBDIR) $(CHARSET_MODULES) @$(SHELL) $(srcdir)/script/installmodules.sh $(INSTALLPERMS) $(DESTDIR)$(BASEDIR) $(DESTDIR)$(AUTHLIBDIR) $(AUTH_MODULES) @@ -1177,7 +1149,7 @@ python_ext: $(PYTHON_PICOBJS) fi PYTHON_OBJS="$(PYTHON_PICOBJS)" \ PYTHON_CFLAGS="$(CFLAGS) $(CPPFLAGS) $(FLAGS)" \ - LIBS="$(LIBS) $(PASSDBLIBS) $(KRB5LIBS)" \ + LIBS="$(LIBS) $(PASSDBLIBS) $(IDMAP_LIBS) $(KRB5LIBS)" \ $(PYTHON) python/setup.py build python_install: $(PYTHON_PICOBJS) @@ -1236,14 +1208,14 @@ uninstallscripts: TOPFILES=dynconfig.o dynconfig.po clean: delheaders python_clean - -rm -f core */*~ *~ */*.o */*.po */*.po32 */*.@SHLIBEXT@ \ + -rm -f core */*~ *~ */*.o */*.po */*.@SHLIBEXT@ \ $(TOPFILES) $(BIN_PROGS) $(SBIN_PROGS) $(MODULES) $(TORTURE_PROGS) \ $(LIBSMBCLIENT) $(EVERYTHING_PROGS) .headers.stamp # This is quite ugly actually.. But we need to make # sure the changes to include/config.h are used. modules_clean: - @-rm -f @MODULES_CLEAN@ auth/auth.o passdb/pdb_interface.o rpc_server/srv_pipe_hnd.o lib/iconv.o smbd/vfs.o + @-rm -f auth/auth.o passdb/pdb_interface.o smbd/server.o lib/iconv.o smbd/vfs.o sam/idmap.o # Making this target will just make sure that the prototype files # exist, not necessarily that they are up to date. Since they're @@ -1251,81 +1223,67 @@ modules_clean: # afterwards. proto_exists: include/proto.h include/wrepld_proto.h include/build_env.h \ nsswitch/winbindd_proto.h web/swat_proto.h \ - client/client_proto.h utils/net_proto.h -# include/tdbsam2_parse_info.h + client/client_proto.h utils/net_proto.h smbd/build_options.c delheaders: @echo Removing prototype headers - @/bin/rm -f $(srcdir)/include/proto.h $(srcdir)/include/build_env.h - @/bin/rm -f $(srcdir)/include/wrepld_proto.h $(srcdir)/nsswitch/winbindd_proto.h - @/bin/rm -f $(srcdir)/web/swat_proto.h - @/bin/rm -f $(srcdir)/client/client_proto.h $(srcdir)/utils/net_proto.h - @/bin/rm -f $(srcdir)/include/tdbsam2_parse_info.h - - @/bin/rm -f include/proto.h include/build_env.h include/wrepld_proto.h \ - nsswitch/winbindd_proto.h web/swat_proto.h \ - client/client_proto.h utils/net_proto.h -# include/tdbsam2_parse_info.h - -include/proto.h: + @rm -f include/proto.h include/build_env.h include/wrepld_proto.h \ + nsswitch/winbindd_proto.h web/swat_proto.h \ + client/client_proto.h utils/net_proto.h \ + smbd/build_options.c + +MKPROTO_SH = $(srcdir)/script/mkproto.sh + +include/proto.h: smbd/build_options.c @echo Building include/proto.h - @cd $(srcdir) && $(SHELL) script/mkproto.sh $(AWK) \ + @cd $(srcdir) && $(SHELL) $(MKPROTO_SH) $(AWK) \ -h _PROTO_H_ $(builddir)/include/proto.h \ $(PROTO_OBJ) -include/build_env.h: +include/build_env.h: script/build_env.sh @echo Building include/build_env.h - @cd $(srcdir) && $(SHELL) script/build_env.sh $(srcdir) $(builddir) $(CC) > $(builddir)/include/build_env.h + @$(SHELL) $(srcdir)/script/build_env.sh $(srcdir) $(builddir) $(CC) \ + > $(builddir)/include/build_env.h include/wrepld_proto.h: @echo Building include/wrepld_proto.h - @cd $(srcdir) && $(SHELL) script/mkproto.sh $(AWK) \ + @cd $(srcdir) && $(SHELL) $(MKPROTO_SH) $(AWK) \ -h _WREPLD_PROTO_H_ $(builddir)/include/wrepld_proto.h \ $(WREPL_OBJ1) nsswitch/winbindd_proto.h: - @cd $(srcdir) && $(SHELL) script/mkproto.sh $(AWK) \ - -h _WINBINDD_PROTO_H_ nsswitch/winbindd_proto.h \ + @cd $(srcdir) && $(SHELL) $(MKPROTO_SH) $(AWK) \ + -h _WINBINDD_PROTO_H_ $(builddir)/nsswitch/winbindd_proto.h \ $(WINBINDD_OBJ1) web/swat_proto.h: - @cd $(srcdir) && $(SHELL) script/mkproto.sh $(AWK) \ - -h _SWAT_PROTO_H_ web/swat_proto.h \ + @cd $(srcdir) && $(SHELL) $(MKPROTO_SH) $(AWK) \ + -h _SWAT_PROTO_H_ $(builddir)/web/swat_proto.h \ $(SWAT_OBJ1) client/client_proto.h: - @cd $(srcdir) && $(SHELL) script/mkproto.sh $(AWK) \ - -h _CLIENT_PROTO_H_ client/client_proto.h \ + @cd $(srcdir) && $(SHELL) $(MKPROTO_SH) $(AWK) \ + -h _CLIENT_PROTO_H_ $(builddir)/client/client_proto.h \ $(CLIENT_OBJ1) utils/net_proto.h: - @cd $(srcdir) && $(SHELL) script/mkproto.sh $(AWK) \ - -h _CLIENT_PROTO_H_ utils/net_proto.h \ + @cd $(srcdir) && $(SHELL) $(MKPROTO_SH) $(AWK) \ + -h _CLIENT_PROTO_H_ $(builddir)/utils/net_proto.h \ $(NET_OBJ1) -# not used yet an perl dependent -#include/tdbsam2_parse_info.h: -# @if test -n "$(PERL)"; then \ -# cd $(srcdir) && @PERL@ -w script/genstruct.pl \ -# -o include/tdbsam2_parse_info.h $(CC) -E -O2 -g \ -# include/tdbsam2.h; \ -# else \ -# echo Unable to build $@, continuing; \ -# fi - # "make headers" or "make proto" calls a subshell because we need to # make sure these commands are executed in sequence even for a # parallel make. headers: $(MAKE) delheaders; \ + $(MAKE) smbd/build_options.c; \ $(MAKE) include/proto.h; \ $(MAKE) include/build_env.h; \ $(MAKE) include/wrepld_proto.h; \ $(MAKE) nsswitch/winbindd_proto.h; \ $(MAKE) web/swat_proto.h; \ $(MAKE) client/client_proto.h; \ - $(MAKE) utils/net_proto.h; -# $(MAKE) include/tdbsam2_parse_info.h + $(MAKE) utils/net_proto.h proto: headers diff --git a/source3/aclocal.m4 b/source3/aclocal.m4 index f470e2e8b0..21358e2a71 100644 --- a/source3/aclocal.m4 +++ b/source3/aclocal.m4 @@ -64,7 +64,6 @@ AC_DEFUN(SMB_MODULE, else AC_MSG_RESULT([not]) fi - MODULES_CLEAN="$MODULES_CLEAN $2 $3" ]) AC_DEFUN(SMB_SUBSYSTEM, @@ -533,59 +532,83 @@ AC_DEFUN(jm_ICONV, jm_cv_func_iconv="no" jm_cv_lib_iconv=no jm_cv_giconv=no + jm_save_LIBS="$LIBS" + LIBS="$LIBS -lbiconv" AC_TRY_LINK([#include -#include ], - [iconv_t cd = iconv_open("",""); - iconv(cd,NULL,NULL,NULL,NULL); - iconv_close(cd);], +#include ], + [iconv_t cd = iconv_open("",""); + iconv(cd,NULL,NULL,NULL,NULL); + iconv_close(cd);], jm_cv_func_iconv=yes - jm_cv_giconv=yes) + jm_cv_biconv=yes + jm_cv_include="biconv.h" + jm_cv_lib_iconv="yes") + LIBS="$jm_save_LIBS" - if test "$jm_cv_func_iconv" != yes; then + if test "$jm_cv_func_iconv" != yes; then AC_TRY_LINK([#include -#include ], +#include ], [iconv_t cd = iconv_open("",""); iconv(cd,NULL,NULL,NULL,NULL); iconv_close(cd);], - jm_cv_func_iconv=yes) + jm_cv_func_iconv=yes + jm_cv_include="giconv.h" + jm_cv_giconv="yes") - if test "$jm_cv_lib_iconv" != yes; then + if test "$jm_cv_func_iconv" != yes; then + AC_TRY_LINK([#include +#include ], + [iconv_t cd = iconv_open("",""); + iconv(cd,NULL,NULL,NULL,NULL); + iconv_close(cd);], + jm_cv_include="iconv.h" + jm_cv_func_iconv=yes) + + if test "$jm_cv_lib_iconv" != yes; then + jm_save_LIBS="$LIBS" + LIBS="$LIBS -lgiconv" + AC_TRY_LINK([#include +#include ], + [iconv_t cd = iconv_open("",""); + iconv(cd,NULL,NULL,NULL,NULL); + iconv_close(cd);], + jm_cv_lib_iconv=yes + jm_cv_func_iconv=yes + jm_cv_include="giconv.h" + jm_cv_giconv=yes) + LIBS="$jm_save_LIBS" + + if test "$jm_cv_func_iconv" != yes; then jm_save_LIBS="$LIBS" - LIBS="$LIBS -lgiconv" + LIBS="$LIBS -liconv" AC_TRY_LINK([#include -#include ], +#include ], [iconv_t cd = iconv_open("",""); iconv(cd,NULL,NULL,NULL,NULL); iconv_close(cd);], jm_cv_lib_iconv=yes - jm_cv_func_iconv=yes - jm_cv_giconv=yes) + jm_cv_include="iconv.h" + jm_cv_func_iconv=yes) LIBS="$jm_save_LIBS" - - if test "$jm_cv_func_iconv" != yes; then - jm_save_LIBS="$LIBS" - LIBS="$LIBS -liconv" - AC_TRY_LINK([#include -#include ], - [iconv_t cd = iconv_open("",""); - iconv(cd,NULL,NULL,NULL,NULL); - iconv_close(cd);], - jm_cv_lib_iconv=yes - jm_cv_func_iconv=yes) - LIBS="$jm_save_LIBS" fi fi fi - + fi if test "$jm_cv_func_iconv" = yes; then if test "$jm_cv_giconv" = yes; then AC_DEFINE(HAVE_GICONV, 1, [What header to include for iconv() function: giconv.h]) AC_MSG_RESULT(yes) ICONV_FOUND=yes else - AC_DEFINE(HAVE_ICONV, 1, [What header to include for iconv() function: iconv.h]) - AC_MSG_RESULT(yes) - ICONV_FOUND=yes + if test "$jm_cv_biconv" = yes; then + AC_DEFINE(HAVE_BICONV, 1, [What header to include for iconv() function: biconv.h]) + AC_MSG_RESULT(yes) + ICONV_FOUND=yes + else + AC_DEFINE(HAVE_ICONV, 1, [What header to include for iconv() function: iconv.h]) + AC_MSG_RESULT(yes) + ICONV_FOUND=yes + fi fi else AC_MSG_RESULT(no) @@ -594,7 +617,11 @@ AC_DEFUN(jm_ICONV, if test "$jm_cv_giconv" = yes; then LIBS="$LIBS -lgiconv" else - LIBS="$LIBS -liconv" + if test "$jm_cv_biconv" = yes; then + LIBS="$LIBS -lbiconv" + else + LIBS="$LIBS -liconv" + fi fi fi ]) @@ -678,3 +705,29 @@ dnl AC_DISABLE_STATIC - set the default static flag to --disable-static AC_DEFUN([AC_DISABLE_STATIC], [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl AC_ENABLE_STATIC(no)]) + +dnl AC_TRY_RUN_STRICT(PROGRAM,CFLAGS,CPPFLAGS,LDFLAGS, +dnl [ACTION-IF-TRUE],[ACTION-IF-FALSE], +dnl [ACTION-IF-CROSS-COMPILING = RUNTIME-ERROR]) +AC_DEFUN( [AC_TRY_RUN_STRICT], +[ + old_CFLAGS="$CFLAGS"; + CFLAGS="$2"; + export CFLAGS; + old_CPPFLAGS="$CPPFLAGS"; + CPPFLAGS="$3"; + export CPPFLAGS; + old_LDFLAGS="$LDFLAGS"; + LDFLAGS="$4"; + export LDFLAGS; + AC_TRY_RUN([$1],[$5],[$6],[$7]); + CFLAGS="$old_CFLAGS"; + old_CFLAGS=""; + export CFLAGS; + CPPFLAGS="$old_CPPFLAGS"; + old_CPPFLAGS=""; + export CPPFLAGS; + LDFLAGS="$old_LDFLAGS"; + old_LDFLAGS=""; + export LDFLAGS; +]) diff --git a/source3/auth/auth.c b/source3/auth/auth.c index 0c4fe76830..a2486acbd1 100644 --- a/source3/auth/auth.c +++ b/source3/auth/auth.c @@ -63,7 +63,7 @@ static struct auth_init_function_entry *auth_find_backend_entry(const char *name struct auth_init_function_entry *entry = backends; while(entry) { - if (strequal(entry->name, name)) return entry; + if (strcmp(entry->name, name)==0) return entry; entry = entry->next; } @@ -203,9 +203,9 @@ static NTSTATUS check_ntlm_password(const struct auth_context *auth_context, const struct auth_usersupplied_info *user_info, struct auth_serversupplied_info **server_info) { - - NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; - const char *pdb_username; + /* if all the modules say 'not for me' this is reasonable */ + NTSTATUS nt_status = NT_STATUS_NO_SUCH_USER; + const char *unix_username; auth_methods *auth_method; TALLOC_CTX *mem_ctx; @@ -244,12 +244,24 @@ static NTSTATUS check_ntlm_password(const struct auth_context *auth_context, return NT_STATUS_LOGON_FAILURE; for (auth_method = auth_context->auth_method_list;auth_method; auth_method = auth_method->next) { + NTSTATUS result; + mem_ctx = talloc_init("%s authentication for user %s\\%s", auth_method->name, user_info->domain.str, user_info->smb_name.str); - nt_status = auth_method->auth(auth_context, auth_method->private_data, mem_ctx, user_info, server_info); + result = auth_method->auth(auth_context, auth_method->private_data, mem_ctx, user_info, server_info); + + /* check if the module did anything */ + if ( NT_STATUS_V(result) == NT_STATUS_V(NT_STATUS_NOT_IMPLEMENTED) ) { + DEBUG(10,("check_ntlm_password: %s had nothing to say\n", auth_method->name)); + talloc_destroy(mem_ctx); + continue; + } + + nt_status = result; + if (NT_STATUS_IS_OK(nt_status)) { - DEBUG(3, ("check_ntlm_password: %s authentication for user [%s] suceeded\n", + DEBUG(3, ("check_ntlm_password: %s authentication for user [%s] succeeded\n", auth_method->name, user_info->smb_name.str)); } else { DEBUG(5, ("check_ntlm_password: %s authentication for user [%s] FAILED with error %s\n", @@ -258,40 +270,36 @@ static NTSTATUS check_ntlm_password(const struct auth_context *auth_context, talloc_destroy(mem_ctx); - if (NT_STATUS_IS_OK(nt_status)) - break; + if ( NT_STATUS_IS_OK(nt_status)) + { + break; + } } - /* This is one of the few places the *relies* (rather than just sets defaults - on the value of lp_security(). This needs to change. A new paramater - perhaps? */ - if (lp_security() >= SEC_SERVER) - smb_user_control(user_info, *server_info, nt_status); - if (NT_STATUS_IS_OK(nt_status)) { - pdb_username = pdb_get_username((*server_info)->sam_account); + unix_username = (*server_info)->unix_name; if (!(*server_info)->guest) { /* We might not be root if we are an RPC call */ become_root(); - nt_status = smb_pam_accountcheck(pdb_username); + nt_status = smb_pam_accountcheck(unix_username); unbecome_root(); if (NT_STATUS_IS_OK(nt_status)) { - DEBUG(5, ("check_ntlm_password: PAM Account for user [%s] suceeded\n", - pdb_username)); + DEBUG(5, ("check_ntlm_password: PAM Account for user [%s] succeeded\n", + unix_username)); } else { DEBUG(3, ("check_ntlm_password: PAM Account for user [%s] FAILED with error %s\n", - pdb_username, nt_errstr(nt_status))); + unix_username, nt_errstr(nt_status))); } } if (NT_STATUS_IS_OK(nt_status)) { DEBUG((*server_info)->guest ? 5 : 2, - ("check_ntlm_password: %sauthentication for user [%s] -> [%s] -> [%s] suceeded\n", + ("check_ntlm_password: %sauthentication for user [%s] -> [%s] -> [%s] succeeded\n", (*server_info)->guest ? "guest " : "", user_info->smb_name.str, user_info->internal_username.str, - pdb_username)); + unix_username)); } } @@ -451,8 +459,13 @@ NTSTATUS make_auth_context_subsystem(struct auth_context **auth_context) break; case SEC_USER: if (lp_encrypted_passwords()) { - DEBUG(5,("Making default auth method list for security=user, encrypt passwords = yes\n")); - auth_method_list = str_list_make("guest sam", NULL); + if ((lp_server_role() == ROLE_DOMAIN_PDC) || (lp_server_role() == ROLE_DOMAIN_BDC)) { + DEBUG(5,("Making default auth method list for DC, security=user, encrypt passwords = yes\n")); + auth_method_list = str_list_make("guest sam winbind:trustdomain", NULL); + } else { + DEBUG(5,("Making default auth method list for standalone security=user, encrypt passwords = yes\n")); + auth_method_list = str_list_make("guest sam", NULL); + } } else { DEBUG(5,("Making default auth method list for security=user, encrypt passwords = no\n")); auth_method_list = str_list_make("guest unix", NULL); diff --git a/source3/auth/auth_builtin.c b/source3/auth/auth_builtin.c index 5a9b5534ab..f7cdfe3fd2 100644 --- a/source3/auth/auth_builtin.c +++ b/source3/auth/auth_builtin.c @@ -38,7 +38,8 @@ static NTSTATUS check_guest_security(const struct auth_context *auth_context, const auth_usersupplied_info *user_info, auth_serversupplied_info **server_info) { - NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; + /* mark this as 'not for me' */ + NTSTATUS nt_status = NT_STATUS_NOT_IMPLEMENTED; if (!(user_info->internal_username.str && *user_info->internal_username.str)) { @@ -86,11 +87,11 @@ static NTSTATUS check_name_to_ntstatus_security(const struct auth_context *auth_ fstrcpy(user, user_info->smb_name.str); if (strncasecmp("NT_STATUS", user, strlen("NT_STATUS")) == 0) { - strupper(user); + strupper_m(user); return nt_status_string_to_code(user); } - strlower(user); + strlower_m(user); error_num = strtoul(user, NULL, 16); DEBUG(5,("check_name_to_ntstatus_security: Error for user %s was %lx\n", user, error_num)); @@ -133,7 +134,7 @@ static NTSTATUS check_fixed_challenge_security(const struct auth_context *auth_c const auth_usersupplied_info *user_info, auth_serversupplied_info **server_info) { - return NT_STATUS_UNSUCCESSFUL; + return NT_STATUS_NOT_IMPLEMENTED; } /**************************************************************************** diff --git a/source3/auth/auth_domain.c b/source3/auth/auth_domain.c index bc03fecf74..56bd6b9aca 100644 --- a/source3/auth/auth_domain.c +++ b/source3/auth/auth_domain.c @@ -29,86 +29,6 @@ extern BOOL global_machine_password_needs_changing; extern userdom_struct current_user_info; -/* - resolve the name of a DC in ways appropriate for an ADS domain mode - an ADS domain may not have Netbios enabled at all, so this is - quite different from the RPC case - Note that we ignore the 'server' parameter here. That has the effect of using - the 'ADS server' smb.conf parameter, which is what we really want anyway - */ -static NTSTATUS ads_resolve_dc(fstring remote_machine, - struct in_addr *dest_ip) -{ - ADS_STRUCT *ads; - ads = ads_init_simple(); - if (!ads) { - return NT_STATUS_NO_LOGON_SERVERS; - } - - DEBUG(4,("ads_resolve_dc: realm=%s\n", ads->config.realm)); - - ads->auth.flags |= ADS_AUTH_NO_BIND; - -#ifdef HAVE_ADS - /* a full ads_connect() is actually overkill, as we don't srictly need - to do the SASL auth in order to get the info we need, but libads - doesn't offer a better way right now */ - ads_connect(ads); -#endif - - fstrcpy(remote_machine, ads->config.ldap_server_name); - strupper(remote_machine); - *dest_ip = ads->ldap_ip; - ads_destroy(&ads); - - if (!*remote_machine || is_zero_ip(*dest_ip)) { - return NT_STATUS_NO_LOGON_SERVERS; - } - - DEBUG(4,("ads_resolve_dc: using server='%s' IP=%s\n", - remote_machine, inet_ntoa(*dest_ip))); - - return NT_STATUS_OK; -} - -/* - resolve the name of a DC in ways appropriate for RPC domain mode - this relies on the server supporting netbios and port 137 not being - firewalled - */ -static NTSTATUS rpc_resolve_dc(const char *server, - fstring remote_machine, - struct in_addr *dest_ip) -{ - if (is_ipaddress(server)) { - struct in_addr to_ip = *interpret_addr2(server); - - /* we need to know the machines netbios name - this is a lousy - way to find it, but until we have a RPC call that does this - it will have to do */ - if (!name_status_find("*", 0x20, 0x20, to_ip, remote_machine)) { - DEBUG(2, ("rpc_resolve_dc: Can't resolve name for IP %s\n", server)); - return NT_STATUS_NO_LOGON_SERVERS; - } - - *dest_ip = to_ip; - return NT_STATUS_OK; - } - - fstrcpy(remote_machine, server); - strupper(remote_machine); - if (!resolve_name(remote_machine, dest_ip, 0x20)) { - DEBUG(1,("rpc_resolve_dc: Can't resolve address for %s\n", - remote_machine)); - return NT_STATUS_NO_LOGON_SERVERS; - } - - DEBUG(4,("rpc_resolve_dc: using server='%s' IP=%s\n", - remote_machine, inet_ntoa(*dest_ip))); - - return NT_STATUS_OK; -} - /** * Connect to a remote server for domain security authenticaion. * @@ -121,36 +41,14 @@ static NTSTATUS rpc_resolve_dc(const char *server, **/ static NTSTATUS connect_to_domain_password_server(struct cli_state **cli, - const char *server, + const char *dc_name, struct in_addr dc_ip, const char *setup_creds_as, uint16 sec_chan, const unsigned char *trust_passwd, BOOL *retry) { - struct in_addr dest_ip; - fstring remote_machine; NTSTATUS result; - uint32 neg_flags = 0x000001ff; - - *retry = False; - - if (lp_security() == SEC_ADS) - result = ads_resolve_dc(remote_machine, &dest_ip); - else - result = rpc_resolve_dc(server, remote_machine, &dest_ip); - - if (!NT_STATUS_IS_OK(result)) { - DEBUG(2,("connect_to_domain_password_server: unable to resolve DC: %s\n", - nt_errstr(result))); - return result; - } - if (ismyip(dest_ip)) { - DEBUG(1,("connect_to_domain_password_server: Password server loop - not using password server %s\n", - remote_machine)); - return NT_STATUS_NO_LOGON_SERVERS; - } - /* TODO: Send a SAMLOGON request to determine whether this is a valid logonserver. We can avoid a 30-second timeout if the DC is down if the SAMLOGON request fails as it is only over UDP. */ @@ -165,14 +63,13 @@ static NTSTATUS connect_to_domain_password_server(struct cli_state **cli, * ACCESS_DENIED errors if 2 auths are done from the same machine. JRA. */ - *retry = True; - - if (!grab_server_mutex(server)) + if (!grab_server_mutex(dc_name)) return NT_STATUS_NO_LOGON_SERVERS; /* Attempt connection */ - result = cli_full_connection(cli, global_myname(), remote_machine, - &dest_ip, 0, "IPC$", "IPC", "", "", "",0, retry); + *retry = True; + result = cli_full_connection(cli, global_myname(), dc_name, &dc_ip, 0, + "IPC$", "IPC", "", "", "", 0, retry); if (!NT_STATUS_IS_OK(result)) { /* map to something more useful */ @@ -199,7 +96,7 @@ static NTSTATUS connect_to_domain_password_server(struct cli_state **cli, if(cli_nt_session_open(*cli, PI_NETLOGON) == False) { DEBUG(0,("connect_to_domain_password_server: unable to open the domain client session to \ -machine %s. Error was : %s.\n", remote_machine, cli_errstr(*cli))); +machine %s. Error was : %s.\n", dc_name, cli_errstr(*cli))); cli_nt_session_close(*cli); cli_ulogoff(*cli); cli_shutdown(*cli); @@ -214,11 +111,11 @@ 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, &neg_flags, 2); + result = cli_nt_establish_netlogon(*cli, sec_chan, trust_passwd); if (!NT_STATUS_IS_OK(result)) { DEBUG(0,("connect_to_domain_password_server: unable to setup the NETLOGON credentials to machine \ -%s. Error was : %s.\n", remote_machine, nt_errstr(result))); +%s. Error was : %s.\n", dc_name, nt_errstr(result))); cli_nt_session_close(*cli); cli_ulogoff(*cli); cli_shutdown(*cli); @@ -231,61 +128,6 @@ machine %s. Error was : %s.\n", remote_machine, cli_errstr(*cli))); return NT_STATUS_OK; } -/*********************************************************************** - Utility function to attempt a connection to an IP address of a DC. -************************************************************************/ - -static NTSTATUS attempt_connect_to_dc(struct cli_state **cli, - const char *domain, - struct in_addr *ip, - const char *setup_creds_as, - uint16 sec_chan, - const unsigned char *trust_passwd) -{ - NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; - BOOL retry = True; - fstring dc_name; - int i; - - /* - * Ignore addresses we have already tried. - */ - - if (is_zero_ip(*ip)) - return NT_STATUS_NO_LOGON_SERVERS; - - if (!lookup_dc_name(global_myname(), domain, ip, dc_name)) - return NT_STATUS_NO_LOGON_SERVERS; - - for (i = 0; (!NT_STATUS_IS_OK(ret)) && retry && (i < 3); i++) - ret = connect_to_domain_password_server(cli, dc_name, setup_creds_as, - sec_chan, trust_passwd, &retry); - return ret; -} - -/*********************************************************************** - 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_dc(struct cli_state **cli, - const char *domain, - const char *setup_creds_as, - uint16 sec_chan, - unsigned char *trust_passwd, - time_t last_change_time) -{ - struct in_addr dc_ip; - fstring srv_name; - - if (!rpc_find_dc(domain, srv_name, &dc_ip)) { - DEBUG(0,("find_connect_dc: Failed to find an DCs for %s\n", lp_workgroup())); - return NT_STATUS_NO_LOGON_SERVERS; - } - - return attempt_connect_to_dc( cli, domain, &dc_ip, setup_creds_as, - sec_chan, trust_passwd ); -} - /*********************************************************************** Do the same as security=server, but using NT Domain calls and a session key from the machine password. If the server parameter is specified @@ -297,15 +139,17 @@ static NTSTATUS domain_client_validate(TALLOC_CTX *mem_ctx, const char *domain, uchar chal[8], auth_serversupplied_info **server_info, - const char *server, const char *setup_creds_as, + const char *dc_name, struct in_addr dc_ip, + const char *setup_creds_as, uint16 sec_chan, unsigned char trust_passwd[16], time_t last_change_time) { - fstring remote_machine; NET_USER_INFO_3 info3; struct cli_state *cli = NULL; NTSTATUS nt_status = NT_STATUS_NO_LOGON_SERVERS; + int i; + BOOL retry = True; /* * At this point, smb_apasswd points to the lanman response to @@ -315,20 +159,14 @@ static NTSTATUS domain_client_validate(TALLOC_CTX *mem_ctx, * see if they were valid. */ - while (!NT_STATUS_IS_OK(nt_status) && - next_token(&server,remote_machine,LIST_SEP,sizeof(remote_machine))) { - if(lp_security() != SEC_ADS && strequal(remote_machine, "*")) { - nt_status = find_connect_dc(&cli, domain, setup_creds_as, sec_chan, trust_passwd, last_change_time); - } else { - int i; - BOOL retry = True; - for (i = 0; !NT_STATUS_IS_OK(nt_status) && retry && (i < 3); i++) - nt_status = connect_to_domain_password_server(&cli, remote_machine, setup_creds_as, - sec_chan, trust_passwd, &retry); - } + /* rety loop for robustness */ + + for (i = 0; !NT_STATUS_IS_OK(nt_status) && retry && (i < 3); i++) { + nt_status = connect_to_domain_password_server(&cli, dc_name, dc_ip, setup_creds_as, + sec_chan, trust_passwd, &retry); } - if (!NT_STATUS_IS_OK(nt_status)) { + if ( !NT_STATUS_IS_OK(nt_status) ) { DEBUG(0,("domain_client_validate: Domain password server not available.\n")); return nt_status; } @@ -341,11 +179,15 @@ static NTSTATUS domain_client_validate(TALLOC_CTX *mem_ctx, */ nt_status = cli_netlogon_sam_network_logon(cli, mem_ctx, - user_info->smb_name.str, user_info->domain.str, - user_info->wksta_name.str, chal, - user_info->lm_resp, user_info->nt_resp, - &info3); + NULL, user_info->smb_name.str, user_info->domain.str, + user_info->wksta_name.str, chal, user_info->lm_resp, + user_info->nt_resp, &info3); + /* let go as soon as possible so we avoid any potential deadlocks + with winbind lookup up users or groups */ + + release_server_mutex(); + if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(0,("domain_client_validate: unable to validate password " "for user %s in domain %s to Domain controller %s. " @@ -360,7 +202,7 @@ static NTSTATUS domain_client_validate(TALLOC_CTX *mem_ctx, } else { nt_status = make_server_info_info3(mem_ctx, user_info->internal_username.str, user_info->smb_name.str, domain, server_info, &info3); - uni_group_cache_store_netlogon(mem_ctx, &info3); + netsamlogon_cache_store( mem_ctx, &info3 ); } #if 0 @@ -373,7 +215,7 @@ static NTSTATUS domain_client_validate(TALLOC_CTX *mem_ctx, if (NT_STATUS_IS_OK(status)) { if(cli_nt_logoff(&cli, &ctr) == False) { DEBUG(0,("domain_client_validate: unable to log off user %s in domain \ -%s to Domain controller %s. Error was %s.\n", user, domain, remote_machine, cli_errstr(&cli))); +%s to Domain controller %s. Error was %s.\n", user, domain, dc_name, cli_errstr(&cli))); nt_status = NT_STATUS_LOGON_FAILURE; } } @@ -386,7 +228,6 @@ static NTSTATUS domain_client_validate(TALLOC_CTX *mem_ctx, cli_nt_session_close(cli); cli_ulogoff(cli); cli_shutdown(cli); - release_server_mutex(); return nt_status; } @@ -401,11 +242,18 @@ static NTSTATUS check_ntdomain_security(const struct auth_context *auth_context, auth_serversupplied_info **server_info) { NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; - char *password_server; unsigned char trust_passwd[16]; time_t last_change_time; const char *domain = lp_workgroup(); uint32 sec_channel_type = 0; + fstring dc_name; + struct in_addr dc_ip; + + if ( lp_server_role() != ROLE_DOMAIN_MEMBER ) { + DEBUG(0,("check_ntdomain_security: Configuration error! Cannot use " + "ntdomain auth method when not a member of a domain.\n")); + return NT_STATUS_NOT_IMPLEMENTED; + } if (!user_info || !server_info || !auth_context) { DEBUG(1,("check_ntdomain_security: Critical variables not present. Failing.\n")); @@ -418,9 +266,9 @@ static NTSTATUS check_ntdomain_security(const struct auth_context *auth_context, * password file. */ - if(is_myname(user_info->domain.str)) { + if(strequal(get_global_sam_name(), user_info->domain.str)) { DEBUG(3,("check_ntdomain_security: Requested domain was for this machine.\n")); - return NT_STATUS_LOGON_FAILURE; + return NT_STATUS_NOT_IMPLEMENTED; } /* @@ -443,22 +291,23 @@ static NTSTATUS check_ntdomain_security(const struct auth_context *auth_context, } } - /* - * Treat each name in the 'password server =' line as a potential - * PDC/BDC. Contact each in turn and try and authenticate. - */ - - password_server = lp_passwordserver(); + /* we need our DC to send the net_sam_logon() request to */ + if ( !get_dc_name(domain, dc_name, &dc_ip) ) { + DEBUG(5,("check_trustdomain_security: unable to locate a DC for domain %s\n", + user_info->domain.str)); + return NT_STATUS_NO_LOGON_SERVERS; + } + nt_status = domain_client_validate(mem_ctx, user_info, domain, - (uchar *)auth_context->challenge.data, - server_info, - password_server, global_myname(), sec_channel_type,trust_passwd, last_change_time); + (uchar *)auth_context->challenge.data, server_info, dc_name, dc_ip, + global_myname(), sec_channel_type,trust_passwd, last_change_time); + return nt_status; } /* module initialisation */ -NTSTATUS auth_init_ntdomain(struct auth_context *auth_context, const char* param, auth_methods **auth_method) +static NTSTATUS auth_init_ntdomain(struct auth_context *auth_context, const char* param, auth_methods **auth_method) { if (!make_auth_methods(auth_context, auth_method)) { return NT_STATUS_NO_MEMORY; @@ -485,6 +334,8 @@ static NTSTATUS check_trustdomain_security(const struct auth_context *auth_conte char *trust_password; time_t last_change_time; DOM_SID sid; + fstring dc_name; + struct in_addr dc_ip; if (!user_info || !server_info || !auth_context) { DEBUG(1,("check_trustdomain_security: Critical variables not present. Failing.\n")); @@ -492,25 +343,22 @@ static NTSTATUS check_trustdomain_security(const struct auth_context *auth_conte } /* - * Check that the requested domain is not our own machine name. - * If it is, we should never check the PDC here, we use our own local - * password file. + * Check that the requested domain is not our own machine name or domain name. */ - if(is_myname(user_info->domain.str)) { - DEBUG(3,("check_trustdomain_security: Requested domain was for this machine.\n")); - return NT_STATUS_LOGON_FAILURE; + if( strequal(get_global_sam_name(), user_info->domain.str)) { + DEBUG(3,("check_trustdomain_security: Requested domain [%s] was for this machine.\n", + user_info->domain.str)); + return NT_STATUS_NOT_IMPLEMENTED; } - /* - * Check that the requested domain is not our own domain, - * If it is, we should use our own local password file. - */ - - if(strequal(lp_workgroup(), (user_info->domain.str))) { - DEBUG(3,("check_trustdomain_security: Requested domain was for this domain.\n")); - return NT_STATUS_LOGON_FAILURE; - } + /* No point is bothering if this is not a trusted domain. + This return makes "map to guest = bad user" work again. + The logic is that if we know nothing about the domain, that + user is known to us and does not exist */ + + if ( !is_trusted_domain( user_info->domain.str ) ) + return NT_STATUS_NOT_IMPLEMENTED; /* * Get the trusted account password for the trusted domain @@ -537,16 +385,24 @@ static NTSTATUS check_trustdomain_security(const struct auth_context *auth_conte } #endif - nt_status = domain_client_validate(mem_ctx, user_info, user_info->domain.str, - (uchar *)auth_context->challenge.data, - server_info, "*" /* Do a lookup */, - lp_workgroup(), SEC_CHAN_DOMAIN, trust_md4_password, last_change_time); + /* use get_dc_name() for consistency even through we know that it will be + a netbios name */ + + if ( !get_dc_name(user_info->domain.str, dc_name, &dc_ip) ) { + DEBUG(5,("check_trustdomain_security: unable to locate a DC for domain %s\n", + user_info->domain.str)); + return NT_STATUS_NO_LOGON_SERVERS; + } + nt_status = domain_client_validate(mem_ctx, user_info, user_info->domain.str, + (uchar *)auth_context->challenge.data, server_info, dc_name, dc_ip, + lp_workgroup(), SEC_CHAN_DOMAIN, trust_md4_password, last_change_time); + return nt_status; } /* module initialisation */ -NTSTATUS auth_init_trustdomain(struct auth_context *auth_context, const char* param, auth_methods **auth_method) +static NTSTATUS auth_init_trustdomain(struct auth_context *auth_context, const char* param, auth_methods **auth_method) { if (!make_auth_methods(auth_context, auth_method)) { return NT_STATUS_NO_MEMORY; diff --git a/source3/auth/auth_rhosts.c b/source3/auth/auth_rhosts.c index 3411083116..fab2d551f2 100644 --- a/source3/auth/auth_rhosts.c +++ b/source3/auth/auth_rhosts.c @@ -139,7 +139,7 @@ static BOOL check_hosts_equiv(SAM_ACCOUNT *account) char *fname = NULL; fname = lp_hosts_equiv(); - if (NT_STATUS_IS_ERR(sid_to_uid(pdb_get_user_sid(account), &uid))) + if (!NT_STATUS_IS_OK(sid_to_uid(pdb_get_user_sid(account), &uid))) return False; /* note: don't allow hosts.equiv on root */ @@ -162,11 +162,13 @@ static NTSTATUS check_hostsequiv_security(const struct auth_context *auth_contex const auth_usersupplied_info *user_info, auth_serversupplied_info **server_info) { - NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; + NTSTATUS nt_status; SAM_ACCOUNT *account = NULL; if (!NT_STATUS_IS_OK(nt_status = auth_get_sam_account(user_info->internal_username.str, &account))) { + if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER)) + nt_status = NT_STATUS_NOT_IMPLEMENTED; return nt_status; } @@ -174,14 +176,14 @@ static NTSTATUS check_hostsequiv_security(const struct auth_context *auth_contex nt_status = make_server_info_sam(server_info, account); } else { pdb_free_sam(&account); - nt_status = NT_STATUS_LOGON_FAILURE; + nt_status = NT_STATUS_NOT_IMPLEMENTED; } return nt_status; } /* module initialisation */ -NTSTATUS auth_init_hostsequiv(struct auth_context *auth_context, const char* param, auth_methods **auth_method) +static NTSTATUS auth_init_hostsequiv(struct auth_context *auth_context, const char* param, auth_methods **auth_method) { if (!make_auth_methods(auth_context, auth_method)) { return NT_STATUS_NO_MEMORY; @@ -203,7 +205,7 @@ static NTSTATUS check_rhosts_security(const struct auth_context *auth_context, const auth_usersupplied_info *user_info, auth_serversupplied_info **server_info) { - NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; + NTSTATUS nt_status; SAM_ACCOUNT *account = NULL; pstring rhostsfile; const char *home; @@ -211,6 +213,8 @@ static NTSTATUS check_rhosts_security(const struct auth_context *auth_context, if (!NT_STATUS_IS_OK(nt_status = auth_get_sam_account(user_info->internal_username.str, &account))) { + if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER)) + nt_status = NT_STATUS_NOT_IMPLEMENTED; return nt_status; } @@ -223,19 +227,18 @@ static NTSTATUS check_rhosts_security(const struct auth_context *auth_context, nt_status = make_server_info_sam(server_info, account); } else { pdb_free_sam(&account); - nt_status = NT_STATUS_LOGON_FAILURE; } unbecome_root(); } else { pdb_free_sam(&account); - nt_status = NT_STATUS_LOGON_FAILURE; + nt_status = NT_STATUS_NOT_IMPLEMENTED; } return nt_status; } /* module initialisation */ -NTSTATUS auth_init_rhosts(struct auth_context *auth_context, const char *param, auth_methods **auth_method) +static NTSTATUS auth_init_rhosts(struct auth_context *auth_context, const char *param, auth_methods **auth_method) { if (!make_auth_methods(auth_context, auth_method)) { return NT_STATUS_NO_MEMORY; diff --git a/source3/auth/auth_sam.c b/source3/auth/auth_sam.c index a7e49a270f..012696f46a 100644 --- a/source3/auth/auth_sam.c +++ b/source3/auth/auth_sam.c @@ -4,6 +4,7 @@ Copyright (C) Andrew Tridgell 1992-2000 Copyright (C) Luke Kenneth Casson Leighton 1996-2000 Copyright (C) Andrew Bartlett 2001 + Copyright (C) Gerald Carter 2003 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -28,9 +29,9 @@ /**************************************************************************** core of smb password checking routine. ****************************************************************************/ -static BOOL smb_pwd_check_ntlmv1(DATA_BLOB nt_response, +static BOOL smb_pwd_check_ntlmv1(const DATA_BLOB *nt_response, const uchar *part_passwd, - DATA_BLOB sec_blob, + const DATA_BLOB *sec_blob, uint8 user_sess_key[16]) { /* Finish the encryption of part_passwd. */ @@ -42,17 +43,17 @@ static BOOL smb_pwd_check_ntlmv1(DATA_BLOB nt_response, return False; } - if (sec_blob.length != 8) { - DEBUG(0, ("smb_pwd_check_ntlmv1: incorrect challenge size (%d)\n", sec_blob.length)); + if (sec_blob->length != 8) { + DEBUG(0, ("smb_pwd_check_ntlmv1: incorrect challenge size (%d)\n", sec_blob->length)); return False; } - if (nt_response.length != 24) { - DEBUG(0, ("smb_pwd_check_ntlmv1: incorrect password length (%d)\n", nt_response.length)); + if (nt_response->length != 24) { + DEBUG(0, ("smb_pwd_check_ntlmv1: incorrect password length (%d)\n", nt_response->length)); return False; } - SMBOWFencrypt(part_passwd, sec_blob.data, p24); + SMBOWFencrypt(part_passwd, sec_blob->data, p24); if (user_sess_key != NULL) { SMBsesskeygen_ntv1(part_passwd, NULL, user_sess_key); @@ -61,16 +62,16 @@ static BOOL smb_pwd_check_ntlmv1(DATA_BLOB nt_response, #if DEBUG_PASSWORD - DEBUG(100,("Part password (P16) was |")); + DEBUG(100,("Part password (P16) was |\n")); dump_data(100, part_passwd, 16); - DEBUG(100,("Password from client was |")); - dump_data(100, nt_response.data, nt_response.length); - DEBUG(100,("Given challenge was |")); - dump_data(100, sec_blob.data, sec_blob.length); - DEBUG(100,("Value from encryption was |")); + DEBUGADD(100,("Password from client was |\n")); + dump_data(100, nt_response->data, nt_response->length); + DEBUGADD(100,("Given challenge was |\n")); + dump_data(100, sec_blob->data, sec_blob->length); + DEBUGADD(100,("Value from encryption was |\n")); dump_data(100, p24, 24); #endif - return (memcmp(p24, nt_response.data, 24) == 0); + return (memcmp(p24, nt_response->data, 24) == 0); } @@ -79,9 +80,9 @@ core of smb password checking routine. (NTLMv2, LMv2) Note: The same code works with both NTLMv2 and LMv2. ****************************************************************************/ -static BOOL smb_pwd_check_ntlmv2(const DATA_BLOB ntv2_response, +static BOOL smb_pwd_check_ntlmv2(const DATA_BLOB *ntv2_response, const uchar *part_passwd, - const DATA_BLOB sec_blob, + const DATA_BLOB *sec_blob, const char *user, const char *domain, uint8 user_sess_key[16]) { @@ -98,42 +99,43 @@ static BOOL smb_pwd_check_ntlmv2(const DATA_BLOB ntv2_response, return False; } - if (ntv2_response.length < 16) { + if (ntv2_response->length < 24) { /* We MUST have more than 16 bytes, or the stuff below will go - crazy... */ + crazy. No known implementation sends less than the 24 bytes + for LMv2, let alone NTLMv2. */ DEBUG(0, ("smb_pwd_check_ntlmv2: incorrect password length (%d)\n", - ntv2_response.length)); + ntv2_response->length)); return False; } - client_key_data = data_blob(ntv2_response.data+16, ntv2_response.length-16); + client_key_data = data_blob(ntv2_response->data+16, ntv2_response->length-16); /* todo: should we be checking this for anything? We can't for LMv2, but for NTLMv2 it is meant to contain the current time etc. */ - memcpy(client_response, ntv2_response.data, sizeof(client_response)); + memcpy(client_response, ntv2_response->data, sizeof(client_response)); if (!ntv2_owf_gen(part_passwd, user, domain, kr)) { return False; } - SMBOWFencrypt_ntv2(kr, sec_blob, client_key_data, value_from_encryption); + SMBOWFencrypt_ntv2(kr, sec_blob, &client_key_data, value_from_encryption); if (user_sess_key != NULL) { SMBsesskeygen_ntv2(kr, value_from_encryption, user_sess_key); } #if DEBUG_PASSWORD - DEBUG(100,("Part password (P16) was |")); + DEBUG(100,("Part password (P16) was |\n")); dump_data(100, part_passwd, 16); - DEBUG(100,("Password from client was |")); - dump_data(100, ntv2_response.data, ntv2_response.length); - DEBUG(100,("Variable data from client was |")); + DEBUGADD(100,("Password from client was |\n")); + dump_data(100, ntv2_response->data, ntv2_response->length); + DEBUGADD(100,("Variable data from client was |\n")); dump_data(100, client_key_data.data, client_key_data.length); - DEBUG(100,("Given challenge was |")); - dump_data(100, sec_blob.data, sec_blob.length); - DEBUG(100,("Value from encryption was |")); + DEBUGADD(100,("Given challenge was |\n")); + dump_data(100, sec_blob->data, sec_blob->length); + DEBUGADD(100,("Value from encryption was |\n")); dump_data(100, value_from_encryption, 16); #endif data_blob_clear_free(&client_key_data); @@ -185,8 +187,8 @@ static NTSTATUS sam_password_ok(const struct auth_context *auth_context, use it (ie. does it exist in the smbpasswd file). */ DEBUG(4,("sam_password_ok: Checking NTLMv2 password with domain [%s]\n", user_info->client_domain.str)); - if (smb_pwd_check_ntlmv2( user_info->nt_resp, - nt_pw, auth_context->challenge, + if (smb_pwd_check_ntlmv2( &user_info->nt_resp, + nt_pw, &auth_context->challenge, user_info->smb_name.str, user_info->client_domain.str, user_sess_key)) @@ -195,11 +197,12 @@ static NTSTATUS sam_password_ok(const struct auth_context *auth_context, } DEBUG(4,("sam_password_ok: Checking NTLMv2 password without a domain\n")); - if (smb_pwd_check_ntlmv2( user_info->nt_resp, - nt_pw, auth_context->challenge, + if (smb_pwd_check_ntlmv2( &user_info->nt_resp, + nt_pw, &auth_context->challenge, user_info->smb_name.str, "", user_sess_key)) + { return NT_STATUS_OK; } else { @@ -213,8 +216,8 @@ static NTSTATUS sam_password_ok(const struct auth_context *auth_context, use it (ie. does it exist in the smbpasswd file). */ DEBUG(4,("sam_password_ok: Checking NT MD4 password\n")); - if (smb_pwd_check_ntlmv1(user_info->nt_resp, - nt_pw, auth_context->challenge, + if (smb_pwd_check_ntlmv1(&user_info->nt_resp, + nt_pw, &auth_context->challenge, user_sess_key)) { return NT_STATUS_OK; @@ -224,7 +227,7 @@ static NTSTATUS sam_password_ok(const struct auth_context *auth_context, } } else { DEBUG(2,("sam_password_ok: NTLMv1 passwords NOT PERMITTED for user %s\n",pdb_get_username(sampass))); - /* no return, because we might pick up LMv2 in the LM field */ + /* no return, becouse we might pick up LMv2 in the LM field */ } } @@ -242,8 +245,8 @@ static NTSTATUS sam_password_ok(const struct auth_context *auth_context, lm_pw = pdb_get_lanman_passwd(sampass); DEBUG(4,("sam_password_ok: Checking LM password\n")); - if (smb_pwd_check_ntlmv1(user_info->lm_resp, - lm_pw, auth_context->challenge, + if (smb_pwd_check_ntlmv1(&user_info->lm_resp, + lm_pw, &auth_context->challenge, user_sess_key)) { return NT_STATUS_OK; @@ -261,8 +264,8 @@ static NTSTATUS sam_password_ok(const struct auth_context *auth_context, - related to Win9X, legacy NAS pass-though authentication */ DEBUG(4,("sam_password_ok: Checking LMv2 password with domain %s\n", user_info->client_domain.str)); - if (smb_pwd_check_ntlmv2( user_info->lm_resp, - nt_pw, auth_context->challenge, + if (smb_pwd_check_ntlmv2( &user_info->lm_resp, + nt_pw, &auth_context->challenge, user_info->smb_name.str, user_info->client_domain.str, user_sess_key)) @@ -271,8 +274,8 @@ static NTSTATUS sam_password_ok(const struct auth_context *auth_context, } DEBUG(4,("sam_password_ok: Checking LMv2 password without a domain\n")); - if (smb_pwd_check_ntlmv2( user_info->lm_resp, - nt_pw, auth_context->challenge, + if (smb_pwd_check_ntlmv2( &user_info->lm_resp, + nt_pw, &auth_context->challenge, user_info->smb_name.str, "", user_sess_key)) @@ -286,8 +289,8 @@ static NTSTATUS sam_password_ok(const struct auth_context *auth_context, DEBUG(4,("sam_password_ok: Checking NT MD4 password in LM field\n")); if (lp_ntlm_auth()) { - if (smb_pwd_check_ntlmv1(user_info->lm_resp, - nt_pw, auth_context->challenge, + if (smb_pwd_check_ntlmv1(&user_info->lm_resp, + nt_pw, &auth_context->challenge, user_sess_key)) { return NT_STATUS_OK; @@ -330,7 +333,7 @@ static NTSTATUS sam_account_ok(TALLOC_CTX *mem_ctx, kickoff_time = pdb_get_kickoff_time(sampass); if (kickoff_time != 0 && time(NULL) > kickoff_time) { - DEBUG(1,("Account for user '%s' has expried.\n", pdb_get_username(sampass))); + DEBUG(1,("Account for user '%s' has expired.\n", pdb_get_username(sampass))); DEBUG(3,("Account expired at '%ld' unix time.\n", (long)kickoff_time)); return NT_STATUS_ACCOUNT_EXPIRED; } @@ -438,14 +441,14 @@ static NTSTATUS check_sam_security(const struct auth_context *auth_context, return NT_STATUS_NO_SUCH_USER; } - nt_status = sam_account_ok(mem_ctx, sampass, user_info); + nt_status = sam_password_ok(auth_context, mem_ctx, sampass, user_info, user_sess_key); if (!NT_STATUS_IS_OK(nt_status)) { pdb_free_sam(&sampass); return nt_status; } - nt_status = sam_password_ok(auth_context, mem_ctx, sampass, user_info, user_sess_key); + nt_status = sam_account_ok(mem_ctx, sampass, user_info); if (!NT_STATUS_IS_OK(nt_status)) { pdb_free_sam(&sampass); @@ -468,14 +471,14 @@ static NTSTATUS check_sam_security(const struct auth_context *auth_context, } /* module initialisation */ -NTSTATUS auth_init_sam(struct auth_context *auth_context, const char *param, auth_methods **auth_method) +static NTSTATUS auth_init_sam_ignoredomain(struct auth_context *auth_context, const char *param, auth_methods **auth_method) { if (!make_auth_methods(auth_context, auth_method)) { return NT_STATUS_NO_MEMORY; } (*auth_method)->auth = check_sam_security; - (*auth_method)->name = "sam"; + (*auth_method)->name = "sam_ignoredomain"; return NT_STATUS_OK; } @@ -490,83 +493,55 @@ static NTSTATUS check_samstrict_security(const struct auth_context *auth_context const auth_usersupplied_info *user_info, auth_serversupplied_info **server_info) { + BOOL is_local_name, is_my_domain; if (!user_info || !auth_context) { return NT_STATUS_LOGON_FAILURE; } - /* If we are a domain member, we must not - attempt to check the password locally, - unless it is one of our aliases. */ + is_local_name = is_myname(user_info->domain.str); + is_my_domain = strequal(user_info->domain.str, lp_workgroup()); + + /* check whether or not we service this domain/workgroup name */ - if (!is_myname(user_info->domain.str)) { - DEBUG(7,("The requested user domain is not the local server name. [%s]\\[%s]\n", - user_info->domain.str,user_info->internal_username.str)); - return NT_STATUS_NO_SUCH_USER; + switch ( lp_server_role() ) { + case ROLE_STANDALONE: + case ROLE_DOMAIN_MEMBER: + if ( !is_local_name ) { + DEBUG(6,("check_samstrict_security: %s is not one of my local names (%s)\n", + user_info->domain.str, (lp_server_role() == ROLE_DOMAIN_MEMBER + ? "ROLE_DOMAIN_MEMBER" : "ROLE_STANDALONE") )); + return NT_STATUS_NOT_IMPLEMENTED; + } + case ROLE_DOMAIN_PDC: + case ROLE_DOMAIN_BDC: + if ( !is_local_name && !is_my_domain ) { + DEBUG(6,("check_samstrict_security: %s is not one of my local names or domain name (DC)\n", + user_info->domain.str)); + return NT_STATUS_NOT_IMPLEMENTED; + } + default: /* name is ok */ + break; } return check_sam_security(auth_context, my_private_data, mem_ctx, user_info, server_info); } /* module initialisation */ -NTSTATUS auth_init_samstrict(struct auth_context *auth_context, const char *param, auth_methods **auth_method) +static NTSTATUS auth_init_sam(struct auth_context *auth_context, const char *param, auth_methods **auth_method) { if (!make_auth_methods(auth_context, auth_method)) { return NT_STATUS_NO_MEMORY; } (*auth_method)->auth = check_samstrict_security; - (*auth_method)->name = "samstrict"; - return NT_STATUS_OK; -} - -/**************************************************************************** -Check SAM security (above) but with a few extra checks if we're a DC. -****************************************************************************/ - -static NTSTATUS check_samstrict_dc_security(const struct auth_context *auth_context, - void *my_private_data, - TALLOC_CTX *mem_ctx, - const auth_usersupplied_info *user_info, - auth_serversupplied_info **server_info) -{ - - if (!user_info || !auth_context) { - return NT_STATUS_LOGON_FAILURE; - } - - /* If we are a domain member, we must not - attempt to check the password locally, - unless it is one of our aliases, empty - or our domain if we are a logon server.*/ - - - if ((!is_myworkgroup(user_info->domain.str))&& - (!is_myname(user_info->domain.str))) { - DEBUG(7,("The requested user domain is not the local server name or our domain. [%s]\\[%s]\n", - user_info->domain.str,user_info->internal_username.str)); - return NT_STATUS_NO_SUCH_USER; - } - - return check_sam_security(auth_context, my_private_data, mem_ctx, user_info, server_info); -} - -/* module initialisation */ -NTSTATUS auth_init_samstrict_dc(struct auth_context *auth_context, const char *param, auth_methods **auth_method) -{ - if (!make_auth_methods(auth_context, auth_method)) { - return NT_STATUS_NO_MEMORY; - } - - (*auth_method)->auth = check_samstrict_dc_security; - (*auth_method)->name = "samstrict_dc"; + (*auth_method)->name = "sam"; return NT_STATUS_OK; } NTSTATUS auth_sam_init(void) { - smb_register_auth(AUTH_INTERFACE_VERSION, "samstrict_dc", auth_init_samstrict_dc); - smb_register_auth(AUTH_INTERFACE_VERSION, "samstrict", auth_init_samstrict); smb_register_auth(AUTH_INTERFACE_VERSION, "sam", auth_init_sam); + smb_register_auth(AUTH_INTERFACE_VERSION, "sam_ignoredomain", auth_init_sam_ignoredomain); return NT_STATUS_OK; } diff --git a/source3/auth/auth_server.c b/source3/auth/auth_server.c index 73af290af2..30e0e13a56 100644 --- a/source3/auth/auth_server.c +++ b/source3/auth/auth_server.c @@ -50,7 +50,7 @@ static struct cli_state *server_cryptkey(TALLOC_CTX *mem_ctx) while(next_token( &p, desthost, LIST_SEP, sizeof(desthost))) { standard_sub_basic(current_user_info.smb_name, desthost, sizeof(desthost)); - strupper(desthost); + strupper_m(desthost); if(!resolve_name( desthost, &dest_ip, 0x20)) { DEBUG(1,("server_cryptkey: Can't resolve address for %s\n",desthost)); @@ -222,7 +222,7 @@ static NTSTATUS check_smbserver_security(const struct auth_context *auth_context static fstring baduser; static BOOL tested_password_server = False; static BOOL bad_password_server = False; - NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; + NTSTATUS nt_status = NT_STATUS_NOT_IMPLEMENTED; BOOL locally_made_cli = False; /* @@ -233,7 +233,7 @@ static NTSTATUS check_smbserver_security(const struct auth_context *auth_context if(is_myname(user_info->domain.str)) { DEBUG(3,("check_smbserver_security: Requested domain was for this machine.\n")); - return NT_STATUS_LOGON_FAILURE; + return nt_status; } cli = my_private_data; @@ -372,12 +372,19 @@ use this machine as the password server.\n")); cli_ulogoff(cli); - if NT_STATUS_IS_OK(nt_status) { + if (NT_STATUS_IS_OK(nt_status)) { struct passwd *pass = Get_Pwnam(user_info->internal_username.str); if (pass) { nt_status = make_server_info_pw(server_info, pass); } else { - nt_status = NT_STATUS_NO_SUCH_USER; + auth_add_user_script(user_info->domain.str, user_info->internal_username.str); + pass = Get_Pwnam(user_info->internal_username.str); + + if (pass) { + nt_status = make_server_info_pw(server_info, pass); + } else { + nt_status = NT_STATUS_NO_SUCH_USER; + } } } @@ -388,7 +395,7 @@ use this machine as the password server.\n")); return(nt_status); } -NTSTATUS auth_init_smbserver(struct auth_context *auth_context, const char* param, auth_methods **auth_method) +static NTSTATUS auth_init_smbserver(struct auth_context *auth_context, const char* param, auth_methods **auth_method) { if (!make_auth_methods(auth_context, auth_method)) { return NT_STATUS_NO_MEMORY; diff --git a/source3/auth/auth_unix.c b/source3/auth/auth_unix.c index 392178f77c..b9de6f7acb 100644 --- a/source3/auth/auth_unix.c +++ b/source3/auth/auth_unix.c @@ -119,7 +119,7 @@ static NTSTATUS check_unix_security(const struct auth_context *auth_context, } /* module initialisation */ -NTSTATUS auth_init_unix(struct auth_context *auth_context, const char* param, auth_methods **auth_method) +static NTSTATUS auth_init_unix(struct auth_context *auth_context, const char* param, auth_methods **auth_method) { if (!make_auth_methods(auth_context, auth_method)) { return NT_STATUS_NO_MEMORY; diff --git a/source3/auth/auth_util.c b/source3/auth/auth_util.c index e8f2af41f3..8e1b420b47 100644 --- a/source3/auth/auth_util.c +++ b/source3/auth/auth_util.c @@ -1,4 +1,4 @@ -/* +/* Unix SMB/CIFS implementation. Authentication utility functions Copyright (C) Andrew Tridgell 1992-1998 @@ -36,7 +36,7 @@ extern DOM_SID global_sid_Authenticated_Users; Create a UNIX user on demand. ****************************************************************************/ -static int smb_create_user(const char *unix_user, const char *homedir) +static int smb_create_user(const char *domain, const char *unix_username, const char *homedir) { pstring add_script; int ret; @@ -44,7 +44,9 @@ static int smb_create_user(const char *unix_user, const char *homedir) pstrcpy(add_script, lp_adduser_script()); if (! *add_script) return -1; - all_string_sub(add_script, "%u", unix_user, sizeof(pstring)); + all_string_sub(add_script, "%u", unix_username, sizeof(pstring)); + if (domain) + all_string_sub(add_script, "%D", domain, sizeof(pstring)); if (homedir) all_string_sub(add_script, "%H", homedir, sizeof(pstring)); ret = smbrun(add_script,NULL); @@ -54,25 +56,30 @@ static int smb_create_user(const char *unix_user, const char *homedir) /**************************************************************************** Add and Delete UNIX users on demand, based on NTSTATUS codes. + We don't care about RID's here so ignore. ****************************************************************************/ -void smb_user_control(const auth_usersupplied_info *user_info, auth_serversupplied_info *server_info, NTSTATUS nt_status) +void auth_add_user_script(const char *domain, const char *username) { - struct passwd *pwd=NULL; - - if (NT_STATUS_IS_OK(nt_status)) { - - if (!(server_info->sam_fill_level & SAM_FILL_UNIX)) { - - /* - * User validated ok against Domain controller. - * If the admin wants us to try and create a UNIX - * user on the fly, do so. - */ - - if(lp_adduser_script() && !(pwd = Get_Pwnam(user_info->internal_username.str))) { - smb_create_user(user_info->internal_username.str, NULL); - } + uint32 rid; + /* + * User validated ok against Domain controller. + * If the admin wants us to try and create a UNIX + * user on the fly, do so. + */ + + if ( lp_adduser_script() ) + smb_create_user(domain, username, NULL); + else { + DEBUG(10,("auth_add_user_script: no 'add user script'. Asking winbindd\n")); + + /* should never get here is we a re a domain member running winbindd + However, a host set for 'security = server' might run winbindd for + account allocation */ + + if ( !winbind_create_user(username, NULL) ) { + DEBUG(5,("auth_add_user_script: winbindd_create_user() failed\n")); + rid = 0; } } } @@ -208,41 +215,26 @@ NTSTATUS make_user_info_map(auth_usersupplied_info **user_info, DEBUG(5, ("make_user_info_map: Mapping user [%s]\\[%s] from workstation [%s]\n", client_domain, smb_name, wksta_name)); - if (lp_allow_trusted_domains() && *client_domain) { - - /* the client could have given us a workstation name - or other crap for the workgroup - we really need a - way of telling if this domain name is one of our - trusted domain names - - Also don't allow "" as a domain, fixes a Win9X bug + /* don't allow "" as a domain, fixes a Win9X bug where it doens't supply a domain for logon script - 'net use' commands. - - Finally, we do this by looking up a cache of trusted domains! - */ + 'net use' commands.*/ + if ( *client_domain ) domain = client_domain; + else + domain = lp_workgroup(); - if (is_trusted_domain(domain)) { - return make_user_info(user_info, smb_name, internal_username, - client_domain, domain, wksta_name, - lm_pwd, nt_pwd, plaintext, ntlmssp_flags, - encrypted); - } + /* do what win2k does. Always map unknown domains to our own + and let the "passdb backend" handle unknown users. */ - } else { - domain = lp_workgroup(); - } + if ( !is_trusted_domain(domain) ) + domain = get_default_sam_name(); - return make_user_info(user_info, - smb_name, internal_username, - client_domain, domain, - wksta_name, - lm_pwd, nt_pwd, - plaintext, - ntlmssp_flags, encrypted); + /* we know that it is a trusted domain (and we are allowing them) or it is our domain */ + return make_user_info(user_info, smb_name, internal_username, + client_domain, domain, wksta_name, lm_pwd, nt_pwd, + plaintext, ntlmssp_flags, encrypted); } /**************************************************************************** @@ -611,10 +603,10 @@ NT_USER_TOKEN *create_nt_token(uid_t uid, gid_t gid, int ngroups, gid_t *groups, NT_USER_TOKEN *token; int i; - if (NT_STATUS_IS_ERR(uid_to_sid(&user_sid, uid))) { + if (!NT_STATUS_IS_OK(uid_to_sid(&user_sid, uid))) { return NULL; } - if (NT_STATUS_IS_ERR(gid_to_sid(&group_sid, gid))) { + if (!NT_STATUS_IS_OK(gid_to_sid(&group_sid, gid))) { return NULL; } @@ -625,7 +617,7 @@ NT_USER_TOKEN *create_nt_token(uid_t uid, gid_t gid, int ngroups, gid_t *groups, } for (i = 0; i < ngroups; i++) { - if (NT_STATUS_IS_ERR(gid_to_sid(&(group_sids)[i], (groups)[i]))) { + if (!NT_STATUS_IS_OK(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; @@ -654,29 +646,22 @@ NT_USER_TOKEN *create_nt_token(uid_t uid, gid_t gid, int ngroups, gid_t *groups, * of groups. ******************************************************************************/ -static NTSTATUS get_user_groups_from_local_sam(SAM_ACCOUNT *sampass, +static NTSTATUS get_user_groups_from_local_sam(const char *username, uid_t uid, gid_t gid, int *n_groups, DOM_SID **groups, gid_t **unix_groups) { - uid_t uid; - gid_t gid; int n_unix_groups; int i; *n_groups = 0; *groups = NULL; - if (NT_STATUS_IS_ERR(sid_to_uid(pdb_get_user_sid(sampass), &uid)) || NT_STATUS_IS_ERR(sid_to_gid(pdb_get_group_sid(sampass), &gid))) { - DEBUG(0, ("get_user_groups_from_local_sam: error fetching uid or gid for user!\n")); - return NT_STATUS_UNSUCCESSFUL; - } - n_unix_groups = groups_max(); if ((*unix_groups = malloc( sizeof(gid_t) * n_unix_groups ) ) == NULL) { DEBUG(0, ("get_user_groups_from_local_sam: Out of memory allocating unix group list\n")); return NT_STATUS_NO_MEMORY; } - if (sys_getgrouplist(pdb_get_username(sampass), gid, *unix_groups, &n_unix_groups) == -1) { + if (sys_getgrouplist(username, gid, *unix_groups, &n_unix_groups) == -1) { gid_t *groups_tmp; groups_tmp = Realloc(*unix_groups, sizeof(gid_t) * n_unix_groups); if (!groups_tmp) { @@ -685,7 +670,7 @@ static NTSTATUS get_user_groups_from_local_sam(SAM_ACCOUNT *sampass, } *unix_groups = groups_tmp; - if (sys_getgrouplist(pdb_get_username(sampass), gid, *unix_groups, &n_unix_groups) == -1) { + if (sys_getgrouplist(username, 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); return NT_STATUS_NO_SUCH_USER; /* what should this return value be? */ @@ -706,7 +691,7 @@ static NTSTATUS get_user_groups_from_local_sam(SAM_ACCOUNT *sampass, *n_groups = n_unix_groups; for (i = 0; i < *n_groups; i++) { - if (NT_STATUS_IS_ERR(gid_to_sid(&(*groups)[i], (*unix_groups)[i]))) { + if (!NT_STATUS_IS_OK(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); @@ -721,10 +706,8 @@ static NTSTATUS get_user_groups_from_local_sam(SAM_ACCOUNT *sampass, Make a user_info struct ***************************************************************************/ -static NTSTATUS make_server_info(auth_serversupplied_info **server_info, SAM_ACCOUNT *sampass) +static NTSTATUS make_server_info(auth_serversupplied_info **server_info) { - NTSTATUS ret; - *server_info = malloc(sizeof(**server_info)); if (!*server_info) { DEBUG(0,("make_server_info: malloc failed!\n")); @@ -732,24 +715,25 @@ static NTSTATUS make_server_info(auth_serversupplied_info **server_info, SAM_ACC } ZERO_STRUCTP(*server_info); - (*server_info)->sam_fill_level = SAM_FILL_ALL; - (*server_info)->sam_account = sampass; - if (NT_STATUS_IS_ERR(ret = sid_to_uid(pdb_get_user_sid(sampass), &((*server_info)->uid)))) - return ret; - if (NT_STATUS_IS_ERR(ret = sid_to_gid(pdb_get_group_sid(sampass), &((*server_info)->gid)))) - return ret; + /* Initialise the uid and gid values to something non-zero + which may save us from giving away root access if there + is a bug in allocating these fields. */ + + (*server_info)->uid = -1; + (*server_info)->gid = -1; return NT_STATUS_OK; } /*************************************************************************** - Make (and fill) a user_info struct from a SAM_ACCOUNT +Fill a server_info struct from a SAM_ACCOUNT with their groups ***************************************************************************/ -NTSTATUS make_server_info_sam(auth_serversupplied_info **server_info, - SAM_ACCOUNT *sampass) +static NTSTATUS add_user_groups(auth_serversupplied_info **server_info, + SAM_ACCOUNT *sampass, + uid_t uid, gid_t gid) { - NTSTATUS nt_status = NT_STATUS_OK; + NTSTATUS nt_status; const DOM_SID *user_sid = pdb_get_user_sid(sampass); const DOM_SID *group_sid = pdb_get_group_sid(sampass); int n_groupSIDs = 0; @@ -759,14 +743,11 @@ NTSTATUS make_server_info_sam(auth_serversupplied_info **server_info, 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(sampass, - &n_groupSIDs, &groupSIDs, &unix_groups))) - { + nt_status = get_user_groups_from_local_sam(pdb_get_username(sampass), + uid, gid, + &n_groupSIDs, &groupSIDs, + &unix_groups); + if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(4,("get_user_groups_from_local_sam failed\n")); free_server_info(server_info); return nt_status; @@ -789,11 +770,49 @@ NTSTATUS make_server_info_sam(auth_serversupplied_info **server_info, (*server_info)->n_groups = n_groupSIDs; (*server_info)->groups = unix_groups; - (*server_info)->ptok = token; + + return nt_status; +} + +/*************************************************************************** + Make (and fill) a user_info struct from a SAM_ACCOUNT +***************************************************************************/ + +NTSTATUS make_server_info_sam(auth_serversupplied_info **server_info, + SAM_ACCOUNT *sampass) +{ + NTSTATUS nt_status; + struct passwd *pwd; + + if (!NT_STATUS_IS_OK(nt_status = make_server_info(server_info))) + return nt_status; + + (*server_info)->sam_account = sampass; + + if ( !(pwd = getpwnam_alloc(pdb_get_username(sampass))) ) { + DEBUG(1, ("User %s in passdb, but getpwnam() fails!\n", + pdb_get_username(sampass))); + free_server_info(server_info); + return NT_STATUS_NO_SUCH_USER; + } + (*server_info)->unix_name = smb_xstrdup(pwd->pw_name); + (*server_info)->gid = pwd->pw_gid; + (*server_info)->uid = pwd->pw_uid; - DEBUG(5,("make_server_info_sam: made server info for user %s\n", - pdb_get_username((*server_info)->sam_account))); + passwd_free(&pwd); + + if (!NT_STATUS_IS_OK(nt_status = add_user_groups(server_info, sampass, + (*server_info)->uid, + (*server_info)->gid))) { + free_server_info(server_info); + return nt_status; + } + + (*server_info)->sam_fill_level = SAM_FILL_ALL; + DEBUG(5,("make_server_info_sam: made server info for user %s -> %s\n", + pdb_get_username(sampass), + (*server_info)->unix_name)); return nt_status; } @@ -810,7 +829,22 @@ NTSTATUS make_server_info_pw(auth_serversupplied_info **server_info, const struc if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam_pw(&sampass, pwd))) { return nt_status; } - return make_server_info_sam(server_info, sampass); + if (!NT_STATUS_IS_OK(nt_status = make_server_info(server_info))) { + return nt_status; + } + + (*server_info)->sam_account = sampass; + + if (!NT_STATUS_IS_OK(nt_status = add_user_groups(server_info, sampass, pwd->pw_uid, pwd->pw_gid))) { + return nt_status; + } + + (*server_info)->unix_name = smb_xstrdup(pwd->pw_name); + + (*server_info)->sam_fill_level = SAM_FILL_ALL; + (*server_info)->uid = pwd->pw_uid; + (*server_info)->gid = pwd->pw_gid; + return nt_status; } /*************************************************************************** @@ -846,6 +880,43 @@ NTSTATUS make_server_info_guest(auth_serversupplied_info **server_info) return nt_status; } +/*************************************************************************** + Purely internal function for make_server_info_info3 + Fill the sam account from getpwnam +***************************************************************************/ +static NTSTATUS fill_sam_account(TALLOC_CTX *mem_ctx, + const char *domain, + const char *username, + char **found_username, + uid_t *uid, gid_t *gid, + SAM_ACCOUNT **sam_account) +{ + fstring dom_user; + struct passwd *passwd; + + fstr_sprintf(dom_user, "%s%s%s", + domain, lp_winbind_separator(), username); + + passwd = Get_Pwnam(dom_user); + + /* if the lookup for DOMAIN\username failed, try again + with just 'username'. This is need for accessing the server + as a trust user that actually maps to a local account */ + + if ( !passwd ) + passwd = Get_Pwnam(username); + + if (passwd == NULL) + return NT_STATUS_NO_SUCH_USER; + + *uid = passwd->pw_uid; + *gid = passwd->pw_gid; + + *found_username = talloc_strdup(mem_ctx, passwd->pw_name); + + return pdb_init_sam_pw(sam_account, passwd); +} + /*************************************************************************** Make a server_info struct from the info3 returned by a domain logon ***************************************************************************/ @@ -858,7 +929,7 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx, NET_USER_INFO_3 *info3) { NTSTATUS nt_status = NT_STATUS_OK; - + char *found_username; const char *nt_domain; const char *nt_username; @@ -866,10 +937,8 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx, DOM_SID user_sid; DOM_SID group_sid; - struct passwd *passwd; - - unid_t u_id, g_id; - int u_type, g_type; + uid_t uid; + gid_t gid; int n_lgroupSIDs; DOM_SID *lgroupSIDs = NULL; @@ -905,40 +974,20 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx, /* If the server didn't give us one, just use the one we sent them */ domain = domain; } - - u_type = ID_USERID; - g_type = ID_GROUPID; - if (NT_STATUS_IS_OK(idmap_get_id_from_sid(&u_id, &u_type, &user_sid)) - && NT_STATUS_IS_OK(idmap_get_id_from_sid(&g_id, &g_type, &group_sid)) - && ((passwd = getpwuid_alloc(u_id.uid)))) { - nt_status = pdb_init_sam_pw(&sam_account, passwd); - passwd_free(&passwd); - } else { - char *dom_user; - dom_user = talloc_asprintf(mem_ctx, "%s%s%s", - nt_domain, - lp_winbind_separator(), - internal_username); - - if (!dom_user) { - DEBUG(0, ("talloc_asprintf failed!\n")); - return NT_STATUS_NO_MEMORY; - } else { - - if (!(passwd = Get_Pwnam(dom_user)) - /* Only lookup local for the local - domain, we don't want this for - trusted domains */ - && strequal(nt_domain, lp_workgroup())) { - passwd = Get_Pwnam(internal_username); - } - - if (!passwd) { - return NT_STATUS_NO_SUCH_USER; - } else { - nt_status = pdb_init_sam_pw(&sam_account, passwd); - } - } + + /* try to fill the SAM account.. If getpwnam() fails, then try the + add user script (2.2.x behavior) */ + + nt_status = fill_sam_account(mem_ctx, nt_domain, internal_username, + &found_username, &uid, &gid, &sam_account); + + if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER)) { + DEBUG(3,("User %s does not exist, trying to add it\n", + internal_username)); + auth_add_user_script(nt_domain, internal_username); + nt_status = fill_sam_account(mem_ctx, nt_domain, + internal_username, &found_username, + &uid, &gid, &sam_account); } if (!NT_STATUS_IS_OK(nt_status)) { @@ -946,17 +995,12 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx, return nt_status; } - if (!pdb_set_user_sid(sam_account, &user_sid, PDB_CHANGED)) { + if (!pdb_set_nt_username(sam_account, nt_username, PDB_CHANGED)) { pdb_free_sam(&sam_account); - return NT_STATUS_UNSUCCESSFUL; + return NT_STATUS_NO_MEMORY; } - if (!pdb_set_group_sid(sam_account, &group_sid, PDB_CHANGED)) { - pdb_free_sam(&sam_account); - return NT_STATUS_UNSUCCESSFUL; - } - - if (!pdb_set_nt_username(sam_account, nt_username, PDB_CHANGED)) { + if (!pdb_set_username(sam_account, nt_username, PDB_CHANGED)) { pdb_free_sam(&sam_account); return NT_STATUS_NO_MEMORY; } @@ -966,7 +1010,18 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx, return NT_STATUS_NO_MEMORY; } - if (!pdb_set_fullname(sam_account, unistr2_static(&(info3->uni_full_name)), PDB_CHANGED)) { + if (!pdb_set_user_sid(sam_account, &user_sid, PDB_CHANGED)) { + pdb_free_sam(&sam_account); + return NT_STATUS_UNSUCCESSFUL; + } + + if (!pdb_set_group_sid(sam_account, &group_sid, PDB_CHANGED)) { + pdb_free_sam(&sam_account); + return NT_STATUS_UNSUCCESSFUL; + } + + if (!pdb_set_fullname(sam_account, unistr2_static(&(info3->uni_full_name)), + PDB_CHANGED)) { pdb_free_sam(&sam_account); return NT_STATUS_NO_MEMORY; } @@ -991,20 +1046,31 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx, return NT_STATUS_NO_MEMORY; } - if (!NT_STATUS_IS_OK(nt_status = make_server_info(server_info, sam_account))) { + if (!NT_STATUS_IS_OK(nt_status = make_server_info(server_info))) { DEBUG(4, ("make_server_info failed!\n")); pdb_free_sam(&sam_account); return nt_status; } + /* save this here to _net_sam_logon() doesn't fail (it assumes a + valid SAM_ACCOUNT) */ + + (*server_info)->sam_account = sam_account; + + (*server_info)->unix_name = smb_xstrdup(found_username); + + /* Fill in the unix info we found on the way */ + + (*server_info)->sam_fill_level = SAM_FILL_ALL; + (*server_info)->uid = uid; + (*server_info)->gid = gid; + /* Store the user group information in the server_info returned to the caller. */ - if (!NT_STATUS_IS_OK(nt_status - = get_user_groups_from_local_sam(sam_account, - &n_lgroupSIDs, - &lgroupSIDs, - &unix_groups))) + nt_status = get_user_groups_from_local_sam((*server_info)->unix_name, + uid, gid, &n_lgroupSIDs, &lgroupSIDs, &unix_groups); + if ( !NT_STATUS_IS_OK(nt_status) ) { DEBUG(4,("get_user_groups_from_local_sam failed\n")); return nt_status; @@ -1018,8 +1084,9 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx, (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")); + DEBUG(0, ("malloc() failed for DOM_SID list!\n")); SAFE_FREE(lgroupSIDs); + free_server_info(server_info); return NT_STATUS_NO_MEMORY; } @@ -1032,9 +1099,10 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx, 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", + DEBUG(3,("could not append additional group rid 0x%x\n", info3->gids[i].g_rid)); SAFE_FREE(lgroupSIDs); + free_server_info(server_info); return nt_status; } } @@ -1060,6 +1128,7 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx, all_group_SIDs, False, &token))) { DEBUG(4,("create_nt_user_token failed\n")); SAFE_FREE(all_group_SIDs); + free_server_info(server_info); return nt_status; } @@ -1111,6 +1180,7 @@ void free_server_info(auth_serversupplied_info **server_info) /* call pam_end here, unless we know we are keeping it */ delete_nt_token( &(*server_info)->ptok ); SAFE_FREE((*server_info)->groups); + SAFE_FREE((*server_info)->unix_name); ZERO_STRUCT(**server_info); } SAFE_FREE(*server_info); @@ -1208,4 +1278,52 @@ NTSTATUS nt_status_squash(NTSTATUS nt_status) } +/** + * Verify whether or not given domain is trusted. + * + * @param domain_name name of the domain to be verified + * @return true if domain is one of the trusted once or + * false if otherwise + **/ + +BOOL is_trusted_domain(const char* dom_name) +{ + DOM_SID trustdom_sid; + char *pass = NULL; + time_t lct; + BOOL ret; + + /* no trusted domains for a standalone server */ + + if ( lp_server_role() == ROLE_STANDALONE ) + return False; + + /* if we are a DC, then check for a direct trust relationships */ + + if (lp_server_role() == ROLE_DOMAIN_BDC || lp_server_role() == ROLE_DOMAIN_PDC) { + become_root(); + ret = secrets_fetch_trusted_domain_password(dom_name, &pass, &trustdom_sid, &lct); + unbecome_root(); + SAFE_FREE(pass); + if (ret) + return True; + } + else { + /* if winbindd is not up and we are a domain member) then we need to update the + trustdom_cache ourselves */ + + if ( !winbind_ping() ) + update_trustdom_cache(); + } + + /* now the trustdom cache should be available a DC could still + * have a transitive trust so fall back to the cache of trusted + * domains (like a domain member would use */ + + if ( trustdom_cache_fetch(dom_name, &trustdom_sid) ) { + return True; + } + + return False; +} diff --git a/source3/auth/auth_winbind.c b/source3/auth/auth_winbind.c index b8276b0866..aa8f345a5b 100644 --- a/source3/auth/auth_winbind.c +++ b/source3/auth/auth_winbind.c @@ -29,7 +29,7 @@ static NTSTATUS get_info3_from_ndr(TALLOC_CTX *mem_ctx, struct winbindd_response *response, NET_USER_INFO_3 *info3) { uint8 *info3_ndr; - size_t len = response->length - sizeof(response); + size_t len = response->length - sizeof(struct winbindd_response); prs_struct ps; if (len > 0) { info3_ndr = response->extra_data; @@ -72,15 +72,20 @@ static NTSTATUS check_winbind_security(const struct auth_context *auth_context, if (!auth_context) { DEBUG(3,("Password for user %s cannot be checked because we have no auth_info to get the challenge from.\n", user_info->internal_username.str)); - return NT_STATUS_UNSUCCESSFUL; + return NT_STATUS_INVALID_PARAMETER; } + if (strequal(user_info->domain.str, get_global_sam_name())) { + DEBUG(3,("check_winbind_security: Not using winbind, requested domain was for this SAM.\n")); + return NT_STATUS_NOT_IMPLEMENTED; + } + /* Send off request */ ZERO_STRUCT(request); ZERO_STRUCT(response); - request.data.auth_crap.flags = WINBIND_PAM_INFO3_NDR; + request.flags = WBFLAG_PAM_INFO3_NDR; push_utf8_fstring(request.data.auth_crap.user, user_info->smb_name.str); @@ -100,8 +105,11 @@ static NTSTATUS check_winbind_security(const struct auth_context *auth_context, request.data.auth_crap.lm_resp_len); memcpy(request.data.auth_crap.nt_resp, user_info->nt_resp.data, request.data.auth_crap.nt_resp_len); - + + /* we are contacting the privileged pipe */ + become_root(); result = winbindd_request(WINBINDD_PAM_AUTH_CRAP, &request, &response); + unbecome_root(); if ( result == NSS_STATUS_UNAVAIL ) { struct auth_methods *auth_method = my_private_data; @@ -129,14 +137,14 @@ static NTSTATUS check_winbind_security(const struct auth_context *auth_context, } } } else if (NT_STATUS_IS_OK(nt_status)) { - nt_status = NT_STATUS_UNSUCCESSFUL; + nt_status = NT_STATUS_NO_LOGON_SERVERS; } return nt_status; } /* module initialisation */ -NTSTATUS auth_init_winbind(struct auth_context *auth_context, const char *param, auth_methods **auth_method) +static NTSTATUS auth_init_winbind(struct auth_context *auth_context, const char *param, auth_methods **auth_method) { if (!make_auth_methods(auth_context, auth_method)) { return NT_STATUS_NO_MEMORY; diff --git a/source3/auth/pampass.c b/source3/auth/pampass.c index 045ceb7c72..d666e439b0 100644 --- a/source3/auth/pampass.c +++ b/source3/auth/pampass.c @@ -229,7 +229,7 @@ static struct chat_struct *make_pw_chat(char *p) special_char_sub(prompt); fstrcpy(t->prompt, prompt); - strlower(t->prompt); + strlower_m(t->prompt); trim_string(t->prompt, " ", " "); if (!next_token(&p, reply, NULL, sizeof(fstring))) @@ -240,7 +240,7 @@ static struct chat_struct *make_pw_chat(char *p) special_char_sub(reply); fstrcpy(t->reply, reply); - strlower(t->reply); + strlower_m(t->reply); trim_string(t->reply, " ", " "); } diff --git a/source3/auth/pass_check.c b/source3/auth/pass_check.c index 88b82e3474..1ac8c1815a 100644 --- a/source3/auth/pass_check.c +++ b/source3/auth/pass_check.c @@ -757,7 +757,7 @@ NTSTATUS pass_check(const struct passwd *pass, const char *user, const char *pas /* try all lowercase if it's currently all uppercase */ if (strhasupper(pass2)) { - strlower(pass2); + strlower_m(pass2); if NT_STATUS_IS_OK(nt_status = password_check(pass2)) { if (fn) fn(user, pass2); @@ -771,8 +771,7 @@ NTSTATUS pass_check(const struct passwd *pass, const char *user, const char *pas } /* last chance - all combinations of up to level chars upper! */ - strlower(pass2); - + strlower_m(pass2); if (NT_STATUS_IS_OK(nt_status = string_combinations(pass2, password_check, level))) { if (fn) diff --git a/source3/autogen.sh b/source3/autogen.sh index 056c0e6133..2d91173f4a 100755 --- a/source3/autogen.sh +++ b/source3/autogen.sh @@ -1,11 +1,5 @@ #!/bin/sh -echo The Samba HEAD branch is deprecated pending the release of Samba 3.0 -echo Please use the SAMBA_3_0 branch -echo to update to SAMBA_3_0 use this command: -echo " cvs -z3 update -r SAMBA_3_0 -dP" -exit 1 - # Run this script to build samba from CVS. ## insert all possible names (only works with diff --git a/source3/change-log b/source3/change-log index 71f5012484..1f7798b541 100644 --- a/source3/change-log +++ b/source3/change-log @@ -2,7 +2,7 @@ SUPERCEDED Change Log for Samba ^^^^^^^^^^ Unless otherwise attributed, all changes were made by -Andrew.Tridgell@anu.edu.au. +Andrew.Tridgell@anu.edu.au. All bugs to samba-bugs@samba.org. NOTE: THIS LOG IS IN CHRONOLOGICAL ORDER diff --git a/source3/client/client.c b/source3/client/client.c index 918b435b2d..d9c3a7aa1b 100644 --- a/source3/client/client.c +++ b/source3/client/client.c @@ -659,7 +659,7 @@ static int do_get(char *rname, char *lname, BOOL reget) GetTimeOfDay(&tp_start); if (lowercase) { - strlower(lname); + strlower_m(lname); } fnum = cli_open(cli, rname, O_RDONLY, DENY_NONE); @@ -834,7 +834,7 @@ static void do_mget(file_info *finfo) unix_format(finfo->name); if (lowercase) - strlower(finfo->name); + strlower_m(finfo->name); if (!directory_exist(finfo->name,NULL) && mkdir(finfo->name,0777) != 0) { @@ -2108,7 +2108,7 @@ static struct /* Yes, this must be here, see crh's comment above. */ {"!",NULL,"run a shell command on the local system",{COMPL_NONE,COMPL_NONE}}, - {"",NULL,NULL,{COMPL_NONE,COMPL_NONE}} + {NULL,NULL,NULL,{COMPL_NONE,COMPL_NONE}} }; @@ -2328,11 +2328,9 @@ static char **completion_fn(const char *text, int start, int end) if (sp == NULL) return NULL; - for (i = 0; commands[i].description; i++) { + for (i = 0; commands[i].name; i++) if ((strncmp(commands[i].name, text, sp - buf) == 0) && (commands[i].name[sp - buf] == 0)) break; - } - if (commands[i].name == NULL) return NULL; @@ -2565,6 +2563,9 @@ static struct cli_state *do_connect(const char *server, const char *share) if (password[0] || !username[0] || use_kerberos || !cli_session_setup(c, "", "", 0, "", 0, lp_workgroup())) { d_printf("session setup failed: %s\n", cli_errstr(c)); + if (NT_STATUS_V(cli_nt_error(c)) == + NT_STATUS_V(NT_STATUS_MORE_PROCESSING_REQUIRED)) + d_printf("did you forget to run kinit?\n"); cli_shutdown(c); return NULL; } @@ -2749,7 +2750,7 @@ static void remember_query_host(const char *arg, { "tar", 'T', POPT_ARG_STRING, NULL, 'T', "Command line tar", "IXFqgbNan" }, { "directory", 'D', POPT_ARG_STRING, NULL, 'D', "Start from directory", "DIR" }, { "command", 'c', POPT_ARG_STRING, &cmdstr, 'c', "Execute semicolon separated commands" }, - { "send-buffer", 'b', POPT_ARG_INT, NULL, 'b', "Changes the transmit/send buffer", "BYTES" }, + { "send-buffer", 'b', POPT_ARG_INT, &io_bufsize, 'b', "Changes the transmit/send buffer", "BYTES" }, { "port", 'p', POPT_ARG_INT, &port, 'p', "Port to connect to", "PORT" }, POPT_COMMON_SAMBA POPT_COMMON_CONNECTION @@ -2823,9 +2824,6 @@ static void remember_query_host(const char *arg, case 'D': fstrcpy(base_directory,poptGetOptArg(pc)); break; - case 'b': - io_bufsize = MAX(1, atoi(poptGetOptArg(pc))); - break; } } @@ -2864,6 +2862,7 @@ static void remember_query_host(const char *arg, pstrcpy(username, cmdline_auth_info.username); pstrcpy(password, cmdline_auth_info.password); + use_kerberos = cmdline_auth_info.use_kerberos; got_pass = cmdline_auth_info.got_pass; diff --git a/source3/client/clitar.c b/source3/client/clitar.c index dfda997ca2..765bc2a659 100644 --- a/source3/client/clitar.c +++ b/source3/client/clitar.c @@ -197,7 +197,7 @@ static void writetarheader(int f, const char *aname, SMB_BIG_UINT size, time_t m fixtarname(hb.dbuf.name, aname, (l >= NAMSIZ) ? NAMSIZ : l + 1); if (lowercase) - strlower(hb.dbuf.name); + strlower_m(hb.dbuf.name); /* write out a "standard" tar format header */ @@ -206,6 +206,16 @@ static void writetarheader(int f, const char *aname, SMB_BIG_UINT size, time_t m oct_it((SMB_BIG_UINT)0, 8, hb.dbuf.uid); oct_it((SMB_BIG_UINT)0, 8, hb.dbuf.gid); oct_it((SMB_BIG_UINT) size, 13, hb.dbuf.size); + if (size > (SMB_BIG_UINT)077777777777LL) { + + /* This is a non-POSIX compatible extention to store files + greater than 8GB. */ + + memset(hb.dbuf.size, 0, 4); + hb.dbuf.size[0]=128; + for (i = 8, jp=(char*)&size; i; i--) + hb.dbuf.size[i+3] = *(jp++); + } oct_it((SMB_BIG_UINT) mtime, 13, hb.dbuf.mtime); memcpy(hb.dbuf.chksum, " ", sizeof(hb.dbuf.chksum)); memset(hb.dbuf.linkname, 0, NAMSIZ); diff --git a/source3/client/mount.cifs.c b/source3/client/mount.cifs.c index 8ba1eff02e..9592dbdf96 100755 --- a/source3/client/mount.cifs.c +++ b/source3/client/mount.cifs.c @@ -222,6 +222,7 @@ char * parse_server(char * unc_name) printf(" %s does not begin with \\\\ or //\n",unc_name); return 0; } else { + unc_name[0] = '\\'; unc_name[0] = '/'; unc_name[1] = '/'; unc_name += 2; @@ -376,7 +377,7 @@ int main(int argc, char ** argv) test_opts = xstrdup(optarg); break;*/ case 'r': /* mount readonly */ - flags |= MS_RDONLY;; + flags |= MS_RDONLY; break; case 'U': uuid = optarg; @@ -388,7 +389,7 @@ int main(int argc, char ** argv) printf ("mount: %s\n", version); exit (0);*/ case 'w': - flags &= ~MS_RDONLY;; + flags &= ~MS_RDONLY; break; /* case 0: break; diff --git a/source3/client/smbmount.c b/source3/client/smbmount.c index 1ee7dbc8cb..343d4f2675 100644 --- a/source3/client/smbmount.c +++ b/source3/client/smbmount.c @@ -891,7 +891,7 @@ static void parse_mount_smb(int argc, char **argv) got_pass = True; memset(strchr_m(getenv("USER"),'%')+1,'X',strlen(password)); } - strupper(username); + strupper_m(username); } if (getenv("PASSWD")) { @@ -933,7 +933,7 @@ static void parse_mount_smb(int argc, char **argv) if (!*my_netbios_name) { pstrcpy(my_netbios_name, myhostname()); } - strupper(my_netbios_name); + strupper_m(my_netbios_name); init_mount(); return 0; diff --git a/source3/client/tree.c b/source3/client/tree.c index 94fd93c210..3b90d15f65 100644 --- a/source3/client/tree.c +++ b/source3/client/tree.c @@ -36,7 +36,7 @@ struct tree_data { }; -void error_message(gchar *message) { +static void tree_error_message(gchar *message) { GtkWidget *dialog, *label, *okay_button; @@ -344,7 +344,7 @@ static void cb_itemsignal( GtkWidget *item, slprintf(errmsg, sizeof(errmsg), "cb_itemsignal: Could not open dir %s, %s\n", get_path(item), strerror(errno)); - error_message(errmsg); + tree_error_message(errmsg); /* gtk_main_quit();*/ @@ -363,7 +363,7 @@ static void cb_itemsignal( GtkWidget *item, slprintf(errmsg, sizeof(errmsg), "cb_itemsignal: Could not read dir smbc://, %s\n", strerror(errno)); - error_message(errmsg); + tree_error_message(errmsg); /* gtk_main_quit();*/ diff --git a/source3/config.sub b/source3/config.sub index 04baf3d80d..2476310dff 100755 --- a/source3/config.sub +++ b/source3/config.sub @@ -1,9 +1,9 @@ #! /bin/sh # Configuration validation subroutine script. -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -# 2000, 2001, 2002, 2003 Free Software Foundation, Inc. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 +# Free Software Foundation, Inc. -timestamp='2003-01-03' +timestamp='2001-12-03' # This file is (in principle) common to ALL GNU software. # The presence of a machine in this file suggests that SOME GNU software @@ -118,7 +118,7 @@ esac # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in - nto-qnx* | linux-gnu* | freebsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*) + nto-qnx* | linux-gnu* | storm-chaos* | os2-emx* | windows32-*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; @@ -227,39 +227,26 @@ case $basic_machine in 1750a | 580 \ | a29k \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ - | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \ - | clipper \ - | d10v | d30v | dlx | dsp16xx \ - | fr30 | frv \ + | c4x | clipper \ + | d10v | d30v | dsp16xx \ + | fr30 \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | i370 | i860 | i960 | ia64 \ - | ip2k \ | m32r | m68000 | m68k | m88k | mcore \ - | mips | mipsbe | mipseb | mipsel | mipsle \ - | mips16 \ - | mips64 | mips64el \ - | mips64vr | mips64vrel \ - | mips64orion | mips64orionel \ - | mips64vr4100 | mips64vr4100el \ - | mips64vr4300 | mips64vr4300el \ - | mips64vr5000 | mips64vr5000el \ - | mipsisa32 | mipsisa32el \ - | mipsisa32r2 | mipsisa32r2el \ - | mipsisa64 | mipsisa64el \ - | mipsisa64sb1 | mipsisa64sb1el \ - | mipsisa64sr71k | mipsisa64sr71kel \ - | mipstx39 | mipstx39el \ + | mips16 | mips64 | mips64el | mips64orion | mips64orionel \ + | mips64vr4100 | mips64vr4100el | mips64vr4300 \ + | mips64vr4300el | mips64vr5000 | mips64vr5000el \ + | mipsbe | mipseb | mipsel | mipsle | mipstx39 | mipstx39el \ + | mipsisa32 \ | mn10200 | mn10300 \ - | msp430 \ | ns16k | ns32k \ - | openrisc | or32 \ + | openrisc \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ | pyramid \ - | sh | sh[1234] | sh3e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \ - | sh64 | sh64le \ - | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \ + | sh | sh[34] | sh[34]eb | shbe | shle \ + | sparc | sparc64 | sparclet | sparclite | sparcv9 | sparcv9b \ | strongarm \ | tahoe | thumb | tic80 | tron \ | v850 | v850e \ @@ -291,52 +278,38 @@ case $basic_machine in 580-* \ | a29k-* \ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ - | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ - | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ - | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | alphapca5[67]-* | arc-* \ + | arm-* | armbe-* | armle-* | armv*-* \ | avr-* \ | bs2000-* \ - | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* \ - | clipper-* | cydra-* \ - | d10v-* | d30v-* | dlx-* \ + | c[123]* | c30-* | [cjt]90-* | c54x-* \ + | clipper-* | cray2-* | cydra-* \ + | d10v-* | d30v-* \ | elxsi-* \ - | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \ + | f30[01]-* | f700-* | fr30-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | i*86-* | i860-* | i960-* | ia64-* \ - | ip2k-* \ | m32r-* \ - | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m68000-* | m680[01234]0-* | m68360-* | m683?2-* | m68k-* \ | m88110-* | m88k-* | mcore-* \ - | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ - | mips16-* \ - | mips64-* | mips64el-* \ - | mips64vr-* | mips64vrel-* \ - | mips64orion-* | mips64orionel-* \ - | mips64vr4100-* | mips64vr4100el-* \ - | mips64vr4300-* | mips64vr4300el-* \ - | mips64vr5000-* | mips64vr5000el-* \ - | mipsisa32-* | mipsisa32el-* \ - | mipsisa32r2-* | mipsisa32r2el-* \ - | mipsisa64-* | mipsisa64el-* \ - | mipsisa64sb1-* | mipsisa64sb1el-* \ - | mipsisa64sr71k-* | mipsisa64sr71kel-* \ - | mipstx39-* | mipstx39el-* \ - | msp430-* \ - | none-* | np1-* | nv1-* | ns16k-* | ns32k-* \ + | mips-* | mips16-* | mips64-* | mips64el-* | mips64orion-* \ + | mips64orionel-* | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* | mipsbe-* | mipseb-* \ + | mipsle-* | mipsel-* | mipstx39-* | mipstx39el-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ | pyramid-* \ | romp-* | rs6000-* \ - | sh-* | sh[1234]-* | sh3e-* | sh[34]eb-* | shbe-* \ - | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ - | sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \ - | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \ - | tahoe-* | thumb-* | tic30-* | tic4x-* | tic54x-* | tic80-* | tron-* \ + | sh-* | sh[34]-* | sh[34]eb-* | shbe-* | shle-* \ + | sparc-* | sparc64-* | sparc86x-* | sparclite-* \ + | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* \ + | t3e-* | tahoe-* | thumb-* | tic30-* | tic54x-* | tic80-* | tron-* \ | v850-* | v850e-* | vax-* \ | we32k-* \ - | x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \ + | x86-* | x86_64-* | xmp-* | xps100-* | xscale-* | xstormy16-* \ | xtensa-* \ | ymp-* \ | z8k-*) @@ -402,10 +375,6 @@ case $basic_machine in basic_machine=ns32k-sequent os=-dynix ;; - c90) - basic_machine=c90-cray - os=-unicos - ;; convex-c1) basic_machine=c1-convex os=-bsd @@ -426,8 +395,16 @@ case $basic_machine in basic_machine=c38-convex os=-bsd ;; - cray | j90) - basic_machine=j90-cray + cray | ymp) + basic_machine=ymp-cray + os=-unicos + ;; + cray2) + basic_machine=cray2-cray + os=-unicos + ;; + [cjt]90) + basic_machine=${basic_machine}-cray os=-unicos ;; crds | unos) @@ -442,14 +419,6 @@ case $basic_machine in decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) basic_machine=mips-dec ;; - decsystem10* | dec10*) - basic_machine=pdp10-dec - os=-tops10 - ;; - decsystem20* | dec20*) - basic_machine=pdp10-dec - os=-tops20 - ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) basic_machine=m68k-motorola @@ -630,6 +599,14 @@ case $basic_machine in basic_machine=m68k-atari os=-mint ;; + mipsel*-linux*) + basic_machine=mipsel-unknown + os=-linux-gnu + ;; + mips*-linux*) + basic_machine=mips-unknown + os=-linux-gnu + ;; mips3*-*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` ;; @@ -644,10 +621,6 @@ case $basic_machine in basic_machine=m68k-rom68k os=-coff ;; - morphos) - basic_machine=powerpc-unknown - os=-morphos - ;; msdos) basic_machine=i386-pc os=-msdos @@ -720,10 +693,6 @@ case $basic_machine in np1) basic_machine=np1-gould ;; - nv1) - basic_machine=nv1-cray - os=-unicosmp - ;; nsr-tandem) basic_machine=nsr-tandem ;; @@ -731,10 +700,6 @@ case $basic_machine in basic_machine=hppa1.1-oki os=-proelf ;; - or32 | or32-*) - basic_machine=or32-unknown - os=-coff - ;; OSE68000 | ose68000) basic_machine=m68000-ericsson os=-ose @@ -757,13 +722,13 @@ case $basic_machine in pbb) basic_machine=m68k-tti ;; - pc532 | pc532-*) + pc532 | pc532-*) basic_machine=ns32k-pc532 ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc ;; - pentiumpro | p6 | 6x86 | athlon | athlon_*) + pentiumpro | p6 | 6x86 | athlon) basic_machine=i686-pc ;; pentiumii | pentium2) @@ -784,22 +749,22 @@ case $basic_machine in power) basic_machine=power-ibm ;; ppc) basic_machine=powerpc-unknown - ;; + ;; ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppcle | powerpclittle | ppc-le | powerpc-little) basic_machine=powerpcle-unknown - ;; + ;; ppcle-* | powerpclittle-*) basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64) basic_machine=powerpc64-unknown - ;; + ;; ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64le | powerpc64little | ppc64-le | powerpc64-little) basic_machine=powerpc64le-unknown - ;; + ;; ppc64le-* | powerpc64little-*) basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` ;; @@ -830,12 +795,6 @@ case $basic_machine in basic_machine=a29k-amd os=-udi ;; - sb1) - basic_machine=mipsisa64sb1-unknown - ;; - sb1el) - basic_machine=mipsisa64sb1el-unknown - ;; sequent) basic_machine=i386-sequent ;; @@ -910,17 +869,9 @@ case $basic_machine in os=-dynix ;; t3e) - basic_machine=alphaev5-cray + basic_machine=t3e-cray os=-unicos ;; - t90) - basic_machine=t90-cray - os=-unicos - ;; - tic4x | c4x*) - basic_machine=tic4x-unknown - os=-coff - ;; tic54x | c54x*) basic_machine=tic54x-unknown os=-coff @@ -931,10 +882,6 @@ case $basic_machine in tx39el) basic_machine=mipstx39el-unknown ;; - toad1) - basic_machine=pdp10-xkl - os=-tops20 - ;; tower | tower-32) basic_machine=m68k-ncr ;; @@ -959,8 +906,8 @@ case $basic_machine in os=-vms ;; vpp*|vx|vx-*) - basic_machine=f301-fujitsu - ;; + basic_machine=f301-fujitsu + ;; vxworks960) basic_machine=i960-wrs os=-vxworks @@ -981,13 +928,17 @@ case $basic_machine in basic_machine=hppa1.1-winbond os=-proelf ;; - xps | xps100) - basic_machine=xps100-honeywell + windows32) + basic_machine=i386-pc + os=-windows32-msvcrt ;; - ymp) - basic_machine=ymp-cray + xmp) + basic_machine=xmp-cray os=-unicos ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; z8k-*-coff) basic_machine=z8k-unknown os=-sim @@ -1008,6 +959,13 @@ case $basic_machine in op60c) basic_machine=hppa1.1-oki ;; + mips) + if [ x$os = x-linux-gnu ]; then + basic_machine=mips-unknown + else + basic_machine=mips-mips + fi + ;; romp) basic_machine=romp-ibm ;; @@ -1027,16 +985,13 @@ case $basic_machine in we32k) basic_machine=we32k-att ;; - sh3 | sh4 | sh3eb | sh4eb | sh[1234]le | sh3ele) + sh3 | sh4 | sh3eb | sh4eb) basic_machine=sh-unknown ;; - sh64) - basic_machine=sh64-unknown - ;; sparc | sparcv9 | sparcv9b) basic_machine=sparc-sun ;; - cydra) + cydra) basic_machine=cydra-cydrome ;; orion) @@ -1051,6 +1006,10 @@ case $basic_machine in pmac | pmac-mpw) basic_machine=powerpc-apple ;; + c4x*) + basic_machine=c4x-none + os=-coff + ;; *-unknown) # Make sure to match an already-canonicalized machine name. ;; @@ -1113,12 +1072,10 @@ case $os in | -chorusos* | -chorusrdb* \ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \ - | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ - | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ - | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ - | -powermax* | -dnix* | -microbsd*) + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) @@ -1130,10 +1087,8 @@ case $os in ;; esac ;; - -nto-qnx*) - ;; -nto*) - os=`echo $os | sed -e 's|nto|nto-qnx|'` + os=-nto-qnx ;; -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ | -windows* | -osx | -abug | -netware* | -os9* | -beos* \ @@ -1181,11 +1136,8 @@ case $os in -ctix* | -uts*) os=-sysv ;; - -nova*) - os=-rtmk-nova - ;; -ns2 ) - os=-nextstep2 + os=-nextstep2 ;; -nsk*) os=-nsk @@ -1224,8 +1176,8 @@ case $os in -xenix) os=-xenix ;; - -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) - os=-mint + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint ;; -none) ;; @@ -1258,11 +1210,10 @@ case $basic_machine in arm*-semi) os=-aout ;; - # This must come before the *-dec entry. pdp10-*) os=-tops20 ;; - pdp11-*) + pdp11-*) os=-none ;; *-dec | vax-*) @@ -1289,9 +1240,6 @@ case $basic_machine in mips*-*) os=-elf ;; - or32-*) - os=-coff - ;; *-tti) # must be before sparc entry or we get the wrong os. os=-sysv3 ;; @@ -1355,19 +1303,19 @@ case $basic_machine in *-next) os=-nextstep3 ;; - *-gould) + *-gould) os=-sysv ;; - *-highlevel) + *-highlevel) os=-bsd ;; *-encore) os=-bsd ;; - *-sgi) + *-sgi) os=-irix ;; - *-siemens) + *-siemens) os=-sysv4 ;; *-masscomp) @@ -1439,7 +1387,7 @@ case $basic_machine in -ptx*) vendor=sequent ;; - -vxsim* | -vxworks* | -windiss*) + -vxsim* | -vxworks*) vendor=wrs ;; -aux*) diff --git a/source3/configure.in b/source3/configure.in index 533757aab8..fd7ee9fc30 100644 --- a/source3/configure.in +++ b/source3/configure.in @@ -154,6 +154,7 @@ AC_SUBST(AUTHLIBS) AC_SUBST(ACLLIBS) AC_SUBST(ADSLIBS) AC_SUBST(PASSDBLIBS) +AC_SUBST(IDMAP_LIBS) AC_SUBST(KRB5_LIBS) AC_SUBST(LDAP_LIBS) AC_SUBST(LDAP_OBJ) @@ -171,12 +172,14 @@ AC_ARG_ENABLE(debug, AC_ARG_ENABLE(developer, [ --enable-developer Turn on developer warnings and debugging (default=no)], [if eval "test x$enable_developer = xyes"; then - CFLAGS="${CFLAGS} -g -Wall -Wshadow -Wstrict-prototypes -Wpointer-arith -Wcast-qual -Wcast-align -Wwrite-strings -DDEBUG_PASSWORD -DDEVELOPER" + developer=yes + CFLAGS="${CFLAGS} -gstabs -Wall -Wshadow -Wstrict-prototypes -Wpointer-arith -Wcast-qual -Wcast-align -Wwrite-strings -DDEBUG_PASSWORD -DDEVELOPER" fi]) AC_ARG_ENABLE(krb5developer, [ --enable-krb5developer Turn on developer warnings and debugging, except -Wstrict-prototypes (default=no)], [if eval "test x$enable_krb5developer = xyes"; then - CFLAGS="${CFLAGS} -g -Wall -Wshadow -Wpointer-arith -Wcast-qual -Wcast-align -Wwrite-strings -DDEBUG_PASSWORD -DDEVELOPER" + developer=yes + CFLAGS="${CFLAGS} -gstabs -Wall -Wshadow -Wpointer-arith -Wcast-qual -Wcast-align -Wwrite-strings -DDEBUG_PASSWORD -DDEVELOPER" fi]) AC_ARG_ENABLE(dmalloc, [ --enable-dmalloc Enable heap debugging [default=no]]) @@ -221,6 +224,30 @@ else fi AC_SUBST(BROKEN_CC) +dnl Check if the C compiler understands -Werror +AC_CACHE_CHECK([that the C compiler understands -Werror],samba_cv_HAVE_Werror, [ + AC_TRY_RUN_STRICT([ + int main(void) + { + return 0; + }],[-Werror],[$CPPFLAGS],[$LDFLAGS], + samba_cv_HAVE_Werror=yes,samba_cv_HAVE_Werror=no,samba_cv_HAVE_Werror=cross)]) +if test x"$samba_cv_HAVE_Werror" = x"yes"; then + Werror_FLAGS="-Werror" +else +dnl Check if the C compiler understands -w2 +AC_CACHE_CHECK([that the C compiler understands -w2],samba_cv_HAVE_w2, [ + AC_TRY_RUN_STRICT([ + int main(void) + { + return 0; + }],[-w2],[$CPPFLAGS],[$LDFLAGS], + samba_cv_HAVE_w2=yes,samba_cv_HAVE_w2=no,samba_cv_HAVE_w2=cross)]) +if test x"$samba_cv_HAVE_w2" = x"yes"; then + Werror_FLAGS="-w2" +fi +fi + dnl Check if the C compiler understands volatile (it should, being ANSI). AC_CACHE_CHECK([that the C compiler understands volatile],samba_cv_volatile, [ AC_TRY_COMPILE([#include ],[volatile int i = 0], @@ -229,6 +256,21 @@ if test x"$samba_cv_volatile" = x"yes"; then AC_DEFINE(HAVE_VOLATILE, 1, [Whether the C compiler understands volatile]) fi +UNAME_S=`uname -s` +AC_MSG_CHECKING(uname -s) +AC_MSG_RESULT(${UNAME_S}) + +UNAME_R=`uname -r` +AC_MSG_CHECKING(uname -r) +AC_MSG_RESULT(${UNAME_R}) + +UNAME_M=`uname -m` +AC_MSG_CHECKING(uname -m) +AC_MSG_RESULT(${UNAME_M}) + +UNAME_P=`uname -p` +AC_MSG_CHECKING(uname -p) +AC_MSG_RESULT(${UNAME_P}) AC_CANONICAL_SYSTEM @@ -244,12 +286,12 @@ DYNEXP= dnl Add modules that have to be built by default here dnl These have to be built static: -default_static_modules="pdb_smbpasswd pdb_tdbsam rpc_lsa rpc_samr rpc_reg rpc_wks rpc_net rpc_dfs rpc_srv rpc_spoolss auth_rhosts auth_sam auth_unix auth_winbind auth_server auth_domain auth_builtin idmap_winbind" +default_static_modules="pdb_smbpasswd pdb_tdbsam rpc_lsa rpc_samr rpc_reg rpc_wks rpc_net rpc_dfs rpc_srv rpc_spoolss auth_rhosts auth_sam auth_unix auth_winbind auth_server auth_domain auth_builtin" dnl These are preferably build shared, and static if dlopen() is not available -default_shared_modules="vfs_recycle vfs_audit vfs_extd_audit vfs_fake_perms vfs_netatalk" +default_shared_modules="vfs_recycle vfs_audit vfs_extd_audit vfs_netatalk vfs_fake_perms" -if test "x$enable_developer" = xyes; then +if test "x$developer" = xyes; then default_static_modules="$default_static_modules rpc_echo" default_shared_modules="$default_shared_modules charset_weird" fi @@ -487,6 +529,7 @@ AC_CHECK_HEADERS(sys/mount.h sys/vfs.h sys/fs/s5param.h sys/filsys.h termios.h t 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 dlfcn.h) AC_CHECK_HEADERS(sys/syslog.h syslog.h execinfo.h) +AC_CHECK_HEADERS(langinfo.h locale.h) # In valgrind 1.0.x, it's just valgrind.h. In 1.9.x+ there's a # subdirectory of headers. @@ -509,18 +552,11 @@ AC_CHECK_HEADERS(shadow.h netinet/ip.h netinet/tcp.h netinet/in_systm.h netinet/ AC_CHECK_HEADERS(nss.h nss_common.h ns_api.h sys/security.h security/pam_appl.h security/pam_modules.h) AC_CHECK_HEADERS(stropts.h poll.h) AC_CHECK_HEADERS(sys/capability.h syscall.h sys/syscall.h) -AC_CHECK_HEADERS(sys/acl.h sys/cdefs.h glob.h) +AC_CHECK_HEADERS(sys/acl.h attr/xattr.h sys/cdefs.h glob.h) # For experimental utmp support (lastlog on some BSD-like systems) AC_CHECK_HEADERS(utmp.h utmpx.h lastlog.h) -# For quotas on Veritas VxFS filesystems -AC_CHECK_HEADERS(sys/fs/vx_quota.h) - -# For quotas on Linux XFS filesystems -AC_CHECK_HEADERS(linux/xqm.h) -AC_CHECK_HEADERS(xfs/xqm.h) - AC_CHECK_SIZEOF(int,cross) AC_CHECK_SIZEOF(long,cross) AC_CHECK_SIZEOF(short,cross) @@ -808,6 +844,7 @@ AC_CHECK_FUNCS(lstat64 fopen64 atexit grantpt dup2 lseek64 ftruncate64 readdir64 AC_CHECK_FUNCS(fseek64 fseeko64 ftell64 ftello64 setluid getpwanam setlinebuf) AC_CHECK_FUNCS(srandom random srand rand setenv usleep strcasecmp fcvt fcvtl symlink readlink) AC_CHECK_FUNCS(syslog vsyslog getgrouplist timegm) +AC_CHECK_FUNCS(setlocale nl_langinfo) # setbuffer, shmget, shm_open are needed for smbtorture AC_CHECK_FUNCS(setbuffer shmget shm_open backtrace_symbols) @@ -903,6 +940,13 @@ AC_LIBTESTFUNC(sec, bigcrypt) AC_LIBTESTFUNC(security, getprpwnam) AC_LIBTESTFUNC(sec, getprpwnam) +############################################ +# Check if we have libattr +AC_SEARCH_LIBS(getxattr, [attr]) +AC_CHECK_FUNCS(getxattr lgetxattr fgetxattr listxattr llistxattr) +AC_CHECK_FUNCS(flistxattr removexattr lremovexattr fremovexattr) +AC_CHECK_FUNCS(setxattr lsetxattr fsetxattr) + # Assume non-shared by default and override below BLDSHARED="false" @@ -982,7 +1026,6 @@ if test "$enable_shared" = "yes"; then *irix6*) AC_DEFINE(IRIX6,1,[Whether the host os is irix6]) ;; esac - ATTEMPT_WRAP32_BUILD=yes BLDSHARED="true" LDSHFLAGS="-set_version sgi1.0 -shared" SONAMEFLAG="-soname " @@ -1325,6 +1368,9 @@ if test x"$samba_cv_HAVE_UTIMBUF" = x"yes"; then AC_DEFINE(HAVE_UTIMBUF,1,[Whether struct utimbuf is available]) fi +############## +# Check utmp details, but only if our OS offers utmp.h +if test x"$ac_cv_header_utmp_h" = x"yes"; then dnl utmp and utmpx come in many flavours dnl We need to check for many of them dnl But we don't need to do each and every one, because our code uses @@ -1442,6 +1488,9 @@ if test x"$samba_cv_HAVE_UX_UT_SYSLEN" = x"yes"; then AC_DEFINE(HAVE_UX_UT_SYSLEN,1,[Whether the utmpx struct has a property ut_syslen]) fi +fi +# end utmp details + ICONV_LOCATION=standard LOOK_DIRS="/usr /usr/local /sw" @@ -1470,7 +1519,7 @@ dnl Try to find iconv(3) jm_ICONV($i) CPPFLAGS=$save_CPPFLAGS - if test -n "$ICONV_FOUND" ; then + if test "$ICONV_FOUND" = yes; then LDFLAGS=$save_LDFLAGS LIB_ADD_DIR(LDFLAGS, "$i/lib") CFLAGS_ADD_DIR(CPPFLAGS, "$i/include") @@ -1487,9 +1536,11 @@ done ############ # check for iconv in libc +ic_save_LIBS="$LIBS" +LIBS="$LIBS -L$ICONV_LOCATION/lib" AC_CACHE_CHECK([for working iconv],samba_cv_HAVE_NATIVE_ICONV,[ AC_TRY_RUN([ -#include +#include <$jm_cv_include> main() { iconv_t cd = iconv_open("ASCII", "UCS-2LE"); if (cd == 0 || cd == (iconv_t)-1) return -1; @@ -1500,6 +1551,7 @@ samba_cv_HAVE_NATIVE_ICONV=yes,samba_cv_HAVE_NATIVE_ICONV=no,samba_cv_HAVE_NATIV if test x"$samba_cv_HAVE_NATIVE_ICONV" = x"yes"; then AC_DEFINE(HAVE_NATIVE_ICONV,1,[Whether to use native iconv]) fi +LIBS="$ic_save_LIBS" if test x"$ICONV_FOUND" = x"no" -o x"$samba_cv_HAVE_NATIVE_ICONV" != x"yes" ; then AC_MSG_WARN([Sufficient support for iconv function was not found. @@ -1987,27 +2039,19 @@ AC_ARG_WITH(smbwrapper, WRAPPROG="bin/smbsh\$(EXEEXT)" WRAP="bin/smbwrapper.$SHLIBEXT" - if test x$ATTEMPT_WRAP32_BUILD = x; then - WRAP32="" - else - WRAP32=bin/smbwrapper.32.$SHLIBEXT - fi - # Conditions under which smbwrapper should not be built. if test x$PICFLAG = x; then echo No support for PIC code - disabling smbwrapper and smbsh WRAPPROG="" WRAP="" - WRAP32="" elif test x$ac_cv_func_syscall = xno; then AC_MSG_RESULT([No syscall() -- disabling smbwrapper and smbsh]) WRAPPROG="" WRAP="" - WRAP32="" fi - EXTRA_ALL_TARGETS="$EXTRA_ALL_TARGETS $WRAPPROG $WRAP $WRAP32" - SMBWRAPPER="$WRAPPROG $WRAP $WRAP32" + EXTRA_ALL_TARGETS="$EXTRA_ALL_TARGETS $WRAPPROG $WRAP" + SMBWRAPPER="$WRAPPROG $WRAP" ;; *) AC_MSG_RESULT(no) @@ -2054,31 +2098,29 @@ AC_ARG_WITH(dfs, ################################################# # active directory support -with_ads_support=yes +with_ads_support=auto 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 + yes|no) + with_ads_support="$withval" ;; esac ]) -if test x"$with_ads_support" = x"yes"; then - AC_DEFINE(WITH_ADS,1,[Whether to include Active Directory support]) -fi - AC_MSG_RESULT($with_ads_support) FOUND_KRB5=no KRB5_LIBS="" -if test x"$with_ads_support" = x"yes"; then -ac_save_CFLAGS="$CFLAGS" -ac_save_LIBS="$LIBS" -CFLAGS="" -LIBS="" +if test x"$with_ads_support" != x"no"; then + + # Do no harm to the values of CFLAGS and LIBS while testing for + # Kerberos support. + + ac_save_CFLAGS="$CFLAGS" + ac_save_LIBS="$LIBS" ################################################# # check for krb5-config from recent MIT and Heimdal kerberos 5 @@ -2095,157 +2137,239 @@ LIBS="" fi if test x$FOUND_KRB5 = x"no"; 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) + ################################################# + # 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) - ;; - *) - 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) - ) + ) fi -if test x$FOUND_KRB5 = x"no"; then -################################################# -# see if this box has the SuSE location for the heimdal kerberos implementation -AC_MSG_CHECKING(for /usr/include/heimdal) -if test -d /usr/include/heimdal; then - if test -f /usr/lib/heimdal/lib/libkrb5.a; then - LIBS="$LIBS -lkrb5" - CFLAGS="$CFLAGS -I/usr/include/heimdal" - CPPFLAGS="$CPPFLAGS -I/usr/include/heimdal" - LDFLAGS="$LDFLAGS -L/usr/lib/heimdal/lib" - AC_MSG_RESULT(yes) + if test x$FOUND_KRB5 = x"no"; then + ################################################# + # see if this box has the SuSE location for the heimdal krb implementation + AC_MSG_CHECKING(for /usr/include/heimdal) + if test -d /usr/include/heimdal; then + if test -f /usr/lib/heimdal/lib/libkrb5.a; then + LIBS="$LIBS -lkrb5" + CFLAGS="$CFLAGS -I/usr/include/heimdal" + CPPFLAGS="$CPPFLAGS -I/usr/include/heimdal" + LDFLAGS="$LDFLAGS -L/usr/lib/heimdal/lib" + AC_MSG_RESULT(yes) + else + LIBS="$LIBS -lkrb5" + CFLAGS="$CFLAGS -I/usr/include/heimdal" + CPPFLAGS="$CPPFLAGS -I/usr/include/heimdal" + AC_MSG_RESULT(yes) + fi else - LIBS="$LIBS -lkrb5" - CFLAGS="$CFLAGS -I/usr/include/heimdal" - CPPFLAGS="$CPPFLAGS -I/usr/include/heimdal" - AC_MSG_RESULT(yes) - + AC_MSG_RESULT(no) fi -else - AC_MSG_RESULT(no) -fi -fi - + fi -if test x$FOUND_KRB5 = x"no"; then -################################################# -# see if this box has the RedHat location for kerberos -AC_MSG_CHECKING(for /usr/kerberos) -if test -d /usr/kerberos -a -f /usr/kerberos/lib/libkrb5.a; then - LIBS="$LIBS -lkrb5" - LDFLAGS="$LDFLAGS -L/usr/kerberos/lib" - CFLAGS="$CFLAGS -I/usr/kerberos/include" - CPPFLAGS="$CPPFLAGS -I/usr/kerberos/include" - AC_MSG_RESULT(yes) -else - AC_MSG_RESULT(no) -fi -fi + if test x$FOUND_KRB5 = x"no"; then + ################################################# + # see if this box has the RedHat location for kerberos + AC_MSG_CHECKING(for /usr/kerberos) + if test -d /usr/kerberos -a -f /usr/kerberos/lib/libkrb5.a; then + LIBS="$LIBS -lkrb5" + LDFLAGS="$LDFLAGS -L/usr/kerberos/lib" + CFLAGS="$CFLAGS -I/usr/kerberos/include" + CPPFLAGS="$CPPFLAGS -I/usr/kerberos/include" + AC_MSG_RESULT(yes) + else + AC_MSG_RESULT(no) + fi + 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 AC_CHECK_HEADERS(krb5.h) + if test x"$ac_cv_header_krb5_h" = x"no"; then + + # Give a warning if AD support was not explicitly requested, + # i.e with_ads_support = auto, otherwise die with an error. + + if test x"$with_ads_support" = x"yes"; then + AC_MSG_ERROR([Active Directory cannot be supported without krb5.h]) + else + AC_MSG_WARN([Active Directory cannot be supported without krb5.h]) + fi + + # Turn off AD support and restore CFLAGS and LIBS variables + + with_ads_support="no" + + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + + else + + # Get rid of case where $with_ads_support=auto + + with_ads_support="yes" + + fi +fi + +# Now we have determined whether we really want ADS support + +if test x"$with_ads_support" = x"yes"; then + + AC_DEFINE(WITH_ADS,1,[Whether to include Active Directory support]) + # now check for gssapi headers. This is also done here to allow for # different kerberos include paths AC_CHECK_HEADERS(gssapi.h gssapi/gssapi_generic.h gssapi/gssapi.h com_err.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"]) + AC_CHECK_LIB(com_err, _et_list) + AC_CHECK_LIB(k5crypto, krb5_encrypt_data) + # Heimdal checks. - AC_CHECK_LIB(crypto, des_set_key, [LIBS="$LIBS -lcrypto"]) - AC_CHECK_LIB(asn1, copy_Authenticator, [LIBS="$LIBS -lasn1"]) - AC_CHECK_LIB(roken, roken_getaddrinfo_hostspec, [LIBS="$LIBS -lroken"]) + AC_CHECK_LIB(crypto, des_set_key) + AC_CHECK_LIB(asn1, copy_Authenticator) + AC_CHECK_LIB(roken, roken_getaddrinfo_hostspec) + # Heimdal checks. On static Heimdal gssapi must be linked before krb5. AC_CHECK_LIB(gssapi, gss_display_status, [LIBS="$LIBS -lgssapi -lkrb5"; - AC_DEFINE(HAVE_GSSAPI,1,[Whether GSSAPI is available])]) - - AC_CHECK_LIB(krb5, krb5_set_real_time, [AC_DEFINE(HAVE_KRB5_SET_REAL_TIME,1,[Whether krb5_set_real_time is available])]) - AC_CHECK_LIB(krb5, krb5_set_default_in_tkt_etypes, [AC_DEFINE(HAVE_KRB5_SET_DEFAULT_IN_TKT_ETYPES,1,[Whether krb5_set_default_in_tkt_etypes, is available])]) - AC_CHECK_LIB(krb5, krb5_set_default_tgs_ktypes, [AC_DEFINE(HAVE_KRB5_SET_DEFAULT_TGS_KTYPES,1,[Whether krb5_set_default_tgs_ktypes is available])]) - - AC_CHECK_LIB(krb5, krb5_principal2salt, [AC_DEFINE(HAVE_KRB5_PRINCIPAL2SALT,1,[Whether krb5_principal2salt is available])]) - AC_CHECK_LIB(krb5, krb5_use_enctype, [AC_DEFINE(HAVE_KRB5_USE_ENCTYPE,1,[Whether krb5_use_enctype is available])]) - AC_CHECK_LIB(krb5, krb5_string_to_key, [AC_DEFINE(HAVE_KRB5_STRING_TO_KEY,1,[Whether krb5_string_to_key is available])]) - AC_CHECK_LIB(krb5, krb5_get_pw_salt, [AC_DEFINE(HAVE_KRB5_GET_PW_SALT,1,[Whether krb5_get_pw_salt is available])]) - AC_CHECK_LIB(krb5, krb5_string_to_key_salt, [AC_DEFINE(HAVE_KRB5_STRING_TO_KEY_SALT,1,[Whether krb5_string_to_key_salt is available])]) - AC_CHECK_LIB(krb5, krb5_auth_con_setkey, [AC_DEFINE(HAVE_KRB5_AUTH_CON_SETKEY,1,[Whether krb5_auth_con_setkey is available])]) - AC_CHECK_LIB(krb5, krb5_auth_con_setuseruserkey, [AC_DEFINE(HAVE_KRB5_AUTH_CON_SETUSERUSERKEY,1,[Whether krb5_auth_con_setuseruserkey is available])]) - AC_CHECK_LIB(krb5, krb5_locate_kdc, [AC_DEFINE(HAVE_KRB5_LOCATE_KDC,1,[Whether krb5_locate_kdc is available])]) - AC_CHECK_LIB(krb5, krb5_get_permitted_enctypes, [AC_DEFINE(HAVE_KRB5_GET_PERMITTED_ENCTYPES,1,[Whether krb5_get_permitted_enctypes is available])]) - AC_CHECK_LIB(krb5, krb5_get_default_in_tkt_etypes, [AC_DEFINE(HAVE_KRB5_GET_DEFAULT_IN_TKT_ETYPES,1,[Whether krb5_get_default_in_tkt_etypes is available])]) - AC_CHECK_LIB(krb5, krb5_free_ktypes, [AC_DEFINE(HAVE_KRB5_FREE_KTYPES,1,[Whether krb5_free_ktypes is available])]) - -AC_CACHE_CHECK([for addrtype in krb5_address],samba_cv_HAVE_ADDRTYPE_IN_KRB5_ADDRESS,[ -AC_TRY_COMPILE([#include ], -[krb5_address kaddr; kaddr.addrtype = ADDRTYPE_INET;], -samba_cv_HAVE_ADDRTYPE_IN_KRB5_ADDRESS=yes,samba_cv_HAVE_ADDRTYPE_IN_KRB5_ADDRESS=no)]) -if test x"$samba_cv_HAVE_ADDRTYPE_IN_KRB5_ADDRESS" = x"yes"; then - AC_DEFINE(HAVE_ADDRTYPE_IN_KRB5_ADDRESS,1,[Whether the krb5_address struct has a addrtype property]) -fi - -AC_CACHE_CHECK([for addr_type in krb5_address],samba_cv_HAVE_ADDR_TYPE_IN_KRB5_ADDRESS,[ -AC_TRY_COMPILE([#include ], -[krb5_address kaddr; kaddr.addr_type = KRB5_ADDRESS_INET;], -samba_cv_HAVE_ADDR_TYPE_IN_KRB5_ADDRESS=yes,samba_cv_HAVE_ADDR_TYPE_IN_KRB5_ADDRESS=no)]) -if test x"$samba_cv_HAVE_ADDR_TYPE_IN_KRB5_ADDRESS" = x"yes"; then - AC_DEFINE(HAVE_ADDR_TYPE_IN_KRB5_ADDRESS,1,[Whether the krb5_address struct has a addr_type property]) -fi - -AC_CACHE_CHECK([for enc_part2 in krb5_ticket],samba_cv_HAVE_KRB5_TKT_ENC_PART2,[ -AC_TRY_COMPILE([#include ], -[krb5_ticket tkt; tkt.enc_part2->authorization_data[0]->contents = NULL;], -samba_cv_HAVE_KRB5_TKT_ENC_PART2=yes,samba_cv_HAVE_KRB5_TKT_ENC_PART2=no)]) -if test x"$samba_cv_HAVE_KRB5_TKT_ENC_PART2" = x"yes"; then - AC_DEFINE(HAVE_KRB5_TKT_ENC_PART2,1,[Whether the krb5_ticket struct has a enc_part2 property]) -fi - -AC_CACHE_CHECK([for keyvalue in krb5_keyblock],samba_cv_HAVE_KRB5_KEYBLOCK_KEYVALUE,[ -AC_TRY_COMPILE([#include ], -[krb5_keyblock key; key.keyvalue.data = NULL;], -samba_cv_HAVE_KRB5_KEYBLOCK_KEYVALUE=yes,samba_cv_HAVE_KRB5_KEYBLOCK_KEYVALUE=no)]) -if test x"$samba_cv_HAVE_KRB5_KEYBLOCK_KEYVALUE" = x"yes"; then - AC_DEFINE(HAVE_KRB5_KEYBLOCK_KEYVALUE,1,[Whether the krb5_keyblock struct has a keyvalue property]) -fi - -AC_CACHE_CHECK([for ENCTYPE_ARCFOUR_HMAC_MD5],samba_cv_HAVE_ENCTYPE_ARCFOUR_HMAC_MD5,[ -AC_TRY_COMPILE([#include ], -[krb5_enctype enctype; enctype = ENCTYPE_ARCFOUR_HMAC_MD5;], -samba_cv_HAVE_ENCTYPE_ARCFOUR_HMAC_MD5=yes,samba_cv_HAVE_ENCTYPE_ARCFOUR_HMAC_MD5=no)]) -if test x"$samba_cv_HAVE_ENCTYPE_ARCFOUR_HMAC_MD5" = x"yes"; then - AC_DEFINE(HAVE_ENCTYPE_ARCFOUR_HMAC_MD5,1,[Whether the ENCTYPE_ARCFOUR_HMAC_MD5 key type is available]) -fi + AC_DEFINE(HAVE_GSSAPI,1,[Whether GSSAPI is available])]) + + AC_CHECK_LIB(krb5, krb5_set_real_time, + [AC_DEFINE(HAVE_KRB5_SET_REAL_TIME,1, + [Whether krb5_set_real_time is available])]) + AC_CHECK_LIB(krb5, krb5_set_default_in_tkt_etypes, + [AC_DEFINE(HAVE_KRB5_SET_DEFAULT_IN_TKT_ETYPES,1, + [Whether krb5_set_default_in_tkt_etypes, is available])]) + AC_CHECK_LIB(krb5, krb5_set_default_tgs_ktypes, + [AC_DEFINE(HAVE_KRB5_SET_DEFAULT_TGS_KTYPES,1, + [Whether krb5_set_default_tgs_ktypes is available])]) + + AC_CHECK_LIB(krb5, krb5_principal2salt, + [AC_DEFINE(HAVE_KRB5_PRINCIPAL2SALT,1, + [Whether krb5_principal2salt is available])]) + AC_CHECK_LIB(krb5, krb5_use_enctype, + [AC_DEFINE(HAVE_KRB5_USE_ENCTYPE,1, + [Whether krb5_use_enctype is available])]) + AC_CHECK_LIB(krb5, krb5_string_to_key, + [AC_DEFINE(HAVE_KRB5_STRING_TO_KEY,1, + [Whether krb5_string_to_key is available])]) + AC_CHECK_LIB(krb5, krb5_get_pw_salt, + [AC_DEFINE(HAVE_KRB5_GET_PW_SALT,1, + [Whether krb5_get_pw_salt is available])]) + AC_CHECK_LIB(krb5, krb5_string_to_key_salt, + [AC_DEFINE(HAVE_KRB5_STRING_TO_KEY_SALT,1, + [Whether krb5_string_to_key_salt is available])]) + AC_CHECK_LIB(krb5, krb5_auth_con_setkey, + [AC_DEFINE(HAVE_KRB5_AUTH_CON_SETKEY,1, + [Whether krb5_auth_con_setkey is available])]) + AC_CHECK_LIB(krb5, krb5_auth_con_setuseruserkey, + [AC_DEFINE(HAVE_KRB5_AUTH_CON_SETUSERUSERKEY,1, + [Whether krb5_auth_con_setuseruserkey is available])]) + AC_CHECK_LIB(krb5, krb5_locate_kdc, + [AC_DEFINE(HAVE_KRB5_LOCATE_KDC,1, + [Whether krb5_locate_kdc is available])]) + AC_CHECK_LIB(krb5, krb5_get_permitted_enctypes, + [AC_DEFINE(HAVE_KRB5_GET_PERMITTED_ENCTYPES,1, + [Whether krb5_get_permitted_enctypes is available])]) + AC_CHECK_LIB(krb5, krb5_get_default_in_tkt_etypes, + [AC_DEFINE(HAVE_KRB5_GET_DEFAULT_IN_TKT_ETYPES,1, + [Whether krb5_get_default_in_tkt_etypes is available])]) + AC_CHECK_LIB(krb5, krb5_free_ktypes, + [AC_DEFINE(HAVE_KRB5_FREE_KTYPES,1, + [Whether krb5_free_ktypes is available])]) + + AC_CACHE_CHECK([for addrtype in krb5_address], + samba_cv_HAVE_ADDRTYPE_IN_KRB5_ADDRESS,[ + AC_TRY_COMPILE([#include ], + [krb5_address kaddr; kaddr.addrtype = ADDRTYPE_INET;], + samba_cv_HAVE_ADDRTYPE_IN_KRB5_ADDRESS=yes, + samba_cv_HAVE_ADDRTYPE_IN_KRB5_ADDRESS=no)]) + + if test x"$samba_cv_HAVE_ADDRTYPE_IN_KRB5_ADDRESS" = x"yes"; then + AC_DEFINE(HAVE_ADDRTYPE_IN_KRB5_ADDRESS,1, + [Whether the krb5_address struct has a addrtype property]) + fi + + AC_CACHE_CHECK([for addr_type in krb5_address], + samba_cv_HAVE_ADDR_TYPE_IN_KRB5_ADDRESS,[ + AC_TRY_COMPILE([#include ], + [krb5_address kaddr; kaddr.addr_type = KRB5_ADDRESS_INET;], + samba_cv_HAVE_ADDR_TYPE_IN_KRB5_ADDRESS=yes, + samba_cv_HAVE_ADDR_TYPE_IN_KRB5_ADDRESS=no)]) + + if test x"$samba_cv_HAVE_ADDR_TYPE_IN_KRB5_ADDRESS" = x"yes"; then + AC_DEFINE(HAVE_ADDR_TYPE_IN_KRB5_ADDRESS,1, + [Whether the krb5_address struct has a addr_type property]) + fi + + AC_CACHE_CHECK([for enc_part2 in krb5_ticket], + samba_cv_HAVE_KRB5_TKT_ENC_PART2, + [AC_TRY_COMPILE([#include ], + [krb5_ticket tkt; tkt.enc_part2->authorization_data[0]->contents = NULL;], + samba_cv_HAVE_KRB5_TKT_ENC_PART2=yes,samba_cv_HAVE_KRB5_TKT_ENC_PART2=no)]) + + if test x"$samba_cv_HAVE_KRB5_TKT_ENC_PART2" = x"yes"; then + AC_DEFINE(HAVE_KRB5_TKT_ENC_PART2,1, + [Whether the krb5_ticket struct has a enc_part2 property]) + fi + + AC_CACHE_CHECK([for keyvalue in krb5_keyblock], + samba_cv_HAVE_KRB5_KEYBLOCK_KEYVALUE,[ + AC_TRY_COMPILE([#include ], + [krb5_keyblock key; key.keyvalue.data = NULL;], + samba_cv_HAVE_KRB5_KEYBLOCK_KEYVALUE=yes, + samba_cv_HAVE_KRB5_KEYBLOCK_KEYVALUE=no)]) + + if test x"$samba_cv_HAVE_KRB5_KEYBLOCK_KEYVALUE" = x"yes"; then + AC_DEFINE(HAVE_KRB5_KEYBLOCK_KEYVALUE,1, + [Whether the krb5_keyblock struct has a keyvalue property]) + fi + + AC_CACHE_CHECK([for ENCTYPE_ARCFOUR_HMAC_MD5], + samba_cv_HAVE_ENCTYPE_ARCFOUR_HMAC_MD5,[ + AC_TRY_COMPILE([#include ], + [krb5_enctype enctype; enctype = ENCTYPE_ARCFOUR_HMAC_MD5;], + samba_cv_HAVE_ENCTYPE_ARCFOUR_HMAC_MD5=yes, + samba_cv_HAVE_ENCTYPE_ARCFOUR_HMAC_MD5=no)]) + + if test x"$samba_cv_HAVE_ENCTYPE_ARCFOUR_HMAC_MD5" = x"yes"; then + AC_DEFINE(HAVE_ENCTYPE_ARCFOUR_HMAC_MD5,1, + [Whether the ENCTYPE_ARCFOUR_HMAC_MD5 key type is available]) + fi ######################################################## # now see if we can find the krb5 libs in standard paths # or as specified above AC_CHECK_LIB(krb5, krb5_mk_req_extended, [KRB5_LIBS="$LIBS -lkrb5"; - KRB5_CFLAGS="$CFLAGS"; - AC_DEFINE(HAVE_KRB5,1,[Whether KRB5 is available])]) + KRB5_CFLAGS="$CFLAGS"; + AC_DEFINE(HAVE_KRB5,1,[Whether KRB5 is available])]) ######################################################## # now see if we can find the gssapi libs in standard paths - AC_CHECK_LIB(gssapi_krb5, gss_display_status, [KRB5_LIBS="$KRB5_LIBS -lgssapi_krb5"; - AC_DEFINE(HAVE_GSSAPI,1,[Whether GSSAPI is available])]) + AC_CHECK_LIB(gssapi_krb5, gss_display_status, + [KRB5_LIBS="$KRB5_LIBS -lgssapi_krb5"; + AC_DEFINE(HAVE_GSSAPI,1,[Whether GSSAPI is available])]) -LIBS="$ac_save_LIBS"; CFLAGS="$ac_save_CFLAGS" + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" fi ######################################################## @@ -2265,22 +2389,28 @@ AC_ARG_WITH(ldap, AC_MSG_RESULT($with_ldap_support) +SMBLDAP="" if test x"$with_ldap_support" = x"yes"; then -ac_save_LIBS="$LIBS" -LIBS="" + ac_save_LIBS="$LIBS" + LIBS="" ################################################################## # 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"]) + AC_CHECK_LIB(lber, ber_scanf) ######################################################## # 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"; - LDAP_OBJ=lib/ldap.o; - AC_DEFINE(HAVE_LDAP,1,[Whether ldap is available])]) - AC_CHECK_HEADERS([ldap.h lber.h], [default_static_modules="$default_static_modules pdb_ldap"]) + AC_CHECK_LIB(ldap, ldap_init, [ + LIBS="$LIBS -lldap"; + AC_CHECK_LIB(ldap, ldap_domain2hostlist, [ + AC_DEFINE(HAVE_LDAP,1,[Whether ldap is available]) + AC_CHECK_HEADERS([ldap.h lber.h], + [default_static_modules="$default_static_modules pdb_ldap idmap_ldap"; + SMBLDAP="lib/smbldap.o"]) + ]) + ]) ######################################################## # If we have LDAP, does it's rebind procedure take 2 or 3 arguments? @@ -2291,10 +2421,12 @@ LIBS="" #include #include ], [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, [Number of arguments to ldap_set_rebind_proc]) + AC_CHECK_FUNCS(ldap_initialize) fi -LDAP_LIBS="$LIBS"; -LIBS="$ac_save_LIBS"; + AC_SUBST(SMBLDAP) + LDAP_LIBS="$LIBS"; + LIBS="$ac_save_LIBS"; else # Can't have ADS support without LDAP if test x"$with_ads_support" = x"yes"; then @@ -2313,10 +2445,10 @@ AC_MSG_CHECKING(whether to build experimental passdb libraries) AC_ARG_WITH(expsam, [ --with-expsam= Include experimental passdb libraries (default=no)] [ Valid choices include (comma separated list): ] -[ xml, mysql, & nisplussam ], +[ xml & mysql], [ expsam_pdb_modules=`echo "$withval" | sed 's/,/ /g'` if test "z$expsam_pdb_modules" = "zyes"; then - expsam_pdb_modules="xml mysql nisplussam" + expsam_pdb_modules="xml mysql" fi AC_MSG_RESULT($expsam_pdb_modules) for i in $expsam_pdb_modules @@ -2332,9 +2464,7 @@ AC_ARG_WITH(expsam, AM_PATH_MYSQL([0.11.0],[default_shared_modules="$default_shared_modules pdb_mysql"],[]) CFLAGS="$CFLAGS $MYSQL_CFLAGS" ;; - nisplussam) - ## pdb_nisplussam - MODULE_pdb_nisplussam=SHARED + no) ;; *) echo "Unknown module name \"$i\"! Exiting..." @@ -2485,27 +2615,6 @@ AC_ARG_WITH(ldapsam, AC_MSG_RESULT(no) ) -################################################# -# check for IDMAP - -AC_DEFINE(WITH_IDMAP,1, [Include IDMAP support]) - -AC_MSG_CHECKING(whether to use IDMAP only for [ug]id mapping) -AC_ARG_WITH(idmap, -[ --with-idmap Include experimental IDMAP support (default=yes)], -[ case "$withval" in - yes) - AC_MSG_RESULT(yes) - AC_DEFINE(WITH_IDMAP,1,[Whether to include experimental IDMAP support]) - ;; - no) - AC_MSG_RESULT(no) - AC_DEFINE(WITH_IDMAP,0,[Whether to include experimental IDMAP support]) - ;; - esac ], - AC_MSG_RESULT(yes) -) - ######################################################################################## ## ## END OF TESTS FOR SAM BACKENDS. @@ -2566,63 +2675,318 @@ AC_ARG_WITH(profiling-data, ################################################# # check for experimental disk-quotas support -QUOTAOBJS=smbd/noquotas.o -AC_MSG_CHECKING(whether to support disk-quotas) +samba_cv_WITH_QUOTAS=auto +samba_cv_TRY_QUOTAS=no +samba_cv_RUN_QUOTA_TESTS=auto +samba_cv_WITH_SYS_QUOTAS=auto +samba_cv_TRY_SYS_QUOTAS=no + +AC_MSG_CHECKING(whether to try disk-quotas support) AC_ARG_WITH(quotas, -[ --with-quotas Include experimental disk-quota support (default=no)], +[ --with-quotas Include disk-quota support (default=no)], [ case "$withval" in yes) AC_MSG_RESULT(yes) - case "$host_os" in - *linux*) - # Check for kernel 2.4.x quota braindamage... - AC_CACHE_CHECK([for linux 2.4.x quota braindamage..],samba_cv_linux_2_4_quota_braindamage, [ - AC_TRY_COMPILE([#include -#include -#include -#include -#include -#include ],[struct mem_dqblk D;], - samba_cv_linux_2_4_quota_braindamage=yes,samba_cv_linux_2_4_quota_braindamage=no)]) -if test x"$samba_cv_linux_2_4_quota_braindamage" = x"yes"; then - AC_DEFINE(LINUX_QUOTAS_2,1,[linux 2.4.x quota braindamage]) -else - AC_DEFINE(LINUX_QUOTAS_1,1,[linux quotas]) -fi - ;; - *) - ;; - esac - QUOTAOBJS=smbd/quotas.o - AC_DEFINE(WITH_QUOTAS,1,[Whether to include experimental quota support]) + samba_cv_WITH_QUOTAS=yes + samba_cv_TRY_QUOTAS=yes + samba_cv_RUN_QUOTA_TESTS=yes + #set sys quotas to auto in this case + samba_cv_TRY_SYS_QUOTAS=auto + ;; + auto) + AC_MSG_RESULT(auto) + samba_cv_WITH_QUOTAS=auto + samba_cv_TRY_QUOTAS=auto + samba_cv_RUN_QUOTA_TESTS=auto + #set sys quotas to auto in this case + samba_cv_TRY_SYS_QUOTAS=auto + ;; + no) + AC_MSG_RESULT(no) + samba_cv_WITH_QUOTAS=no + samba_cv_TRY_QUOTAS=no + samba_cv_RUN_QUOTA_TESTS=no ;; *) + AC_MSG_RESULT(${samba_cv_TRY_QUOTAS}) + ;; + esac ], + AC_MSG_RESULT(${samba_cv_TRY_QUOTAS}) +) + +AC_MSG_CHECKING(whether to try the new lib/sysquotas.c interface) +AC_ARG_WITH(sys-quotas, +[ --with-sys-quotas Include lib/sysquotas.c support (default=auto)], +[ case "$withval" in + yes) + AC_MSG_RESULT(yes) + samba_cv_WITH_SYS_QUOTAS=yes + samba_cv_TRY_SYS_QUOTAS=yes + samba_cv_RUN_QUOTA_TESTS=yes + ;; + auto) + AC_MSG_RESULT(auto) + samba_cv_WITH_SYS_QUOTAS=auto + samba_cv_TRY_SYS_QUOTAS=auto + samba_cv_RUN_QUOTA_TESTS=auto + ;; + no) AC_MSG_RESULT(no) + samba_cv_WITH_SYS_QUOTAS=no + samba_cv_TRY_SYS_QUOTAS=no + ;; + *) + AC_MSG_RESULT(${samba_cv_TRY_SYS_QUOTAS}) ;; esac ], - AC_MSG_RESULT(no) + AC_MSG_RESULT(${samba_cv_TRY_SYS_QUOTAS}) ) -AC_SUBST(QUOTAOBJS) + +if test x"$samba_cv_TRY_SYS_QUOTAS" = x"auto"; then +AC_MSG_CHECKING(whether to try the lib/sysquotas.c interface on ${host_os}) + case "$host_os" in + *linux*) + AC_MSG_RESULT(yes) + samba_cv_TRY_SYS_QUOTAS=yes + samba_cv_RUN_QUOTA_TESTS=yes + ;; + *) + AC_MSG_RESULT(no) + samba_cv_TRY_SYS_QUOTAS=no + ;; + esac +fi + +############################################# +# only check for quota stuff if --with-quotas +if test x"$samba_cv_RUN_QUOTA_TESTS" != x"no"; then + +# For quotas on Veritas VxFS filesystems +AC_CHECK_HEADERS(sys/fs/vx_quota.h) + +# For sys/quota.h and linux/quota.h +AC_CHECK_HEADERS(sys/quota.h) +AC_CHECK_HEADERS(asm/types.h linux/quota.h) + +# For quotas on Linux XFS filesystems +AC_CHECK_HEADERS(linux/xqm.h linux/xfs_fs.h) +AC_CHECK_HEADERS(xfs/libxfs.h xfs/xqm.h xfs/xfs_fs.h) +# For linux > 2.5.56 +AC_CHECK_HEADERS(linux/dqblk_xfs.h) + +# if we have struct if_dqblk in we should use it +AC_CACHE_CHECK([for struct if_dqblk in ],samba_cv_HAVE_STRUCT_IF_DQBLK, [ +AC_TRY_COMPILE([ +#include "confdefs.h" +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_ASM_TYPES_H +#include +#endif +#include +],[struct if_dqblk D;], +samba_cv_HAVE_STRUCT_IF_DQBLK=yes,samba_cv_HAVE_STRUCT_IF_DQBLK=no)]) +if test "$samba_cv_HAVE_STRUCT_IF_DQBLK"x = "yes"x; then + AC_DEFINE(HAVE_STRUCT_IF_DQBLK,1,[struct if_dqblk]) +fi + +# if we have struct mem_dqblk in we should use it +AC_CACHE_CHECK([for struct mem_dqblk in ],samba_cv_HAVE_STRUCT_MEM_DQBLK, [ +AC_TRY_COMPILE([ +#include "confdefs.h" +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_ASM_TYPES_H +#include +#endif +#include +],[struct mem_dqblk D;], +samba_cv_HAVE_STRUCT_MEM_DQBLK=yes,samba_cv_HAVE_STRUCT_MEM_DQBLK=no)]) +if test "$samba_cv_HAVE_STRUCT_MEM_DQBLK"x = "yes"x; then + AC_DEFINE(HAVE_STRUCT_MEM_DQBLK,1,[struct mem_dqblk]) +fi + +# if we have struct dqblk .dqb_fsoftlimit instead of .dqb_isoftlimit on IRIX +AC_CACHE_CHECK([if struct dqblk has .dqb_fsoftlimit],samba_cv_HAVE_DQB_FSOFTLIMIT, [ +AC_TRY_COMPILE([ +#include "confdefs.h" +#ifdef HAVE_SYS_QUOTA_H +#include +#endif +],[ +struct dqblk D; +D.dqb_fsoftlimit = 0;], +samba_cv_HAVE_DQB_FSOFTLIMIT=yes,samba_cv_HAVE_DQB_FSOFTLIMIT=no)]) +if test "$samba_cv_HAVE_DQB_FSOFTLIMIT"x = "yes"x; then + AC_DEFINE(HAVE_DQB_FSOFTLIMIT,1,[struct dqblk .dqb_fsoftlimit]) +fi + +################## +# look for a working quota system +samba_cv_SYSQUOTA_FOUND=no; + +if test x"$samba_cv_SYSQUOTA_FOUND" != x"yes"; then +AC_CACHE_CHECK([for long quotactl(int cmd, char *special, qid_t id, caddr_t addr)],samba_cv_HAVE_QUOTACTL_4A,[ +AC_TRY_RUN_STRICT([ +#define HAVE_QUOTACTL_4A 1 +#define AUTOCONF_TEST 1 +#include "confdefs.h" +#include "${srcdir-.}/lib/sysquotas.c"],[$Werror_FLAGS],[$CPPFLAGS],[$LDFLAGS], + samba_cv_HAVE_QUOTACTL_4A=yes,samba_cv_HAVE_QUOTACTL_4A=no,samba_cv_HAVE_QUOTACTL_4A=cross)]) +if test x"$samba_cv_HAVE_QUOTACTL_4A" = x"yes"; then + samba_cv_SYSQUOTA_FOUND=yes;AC_DEFINE(HAVE_QUOTACTL_4A,1,[Whether long quotactl(int cmd, char *special, qid_t id, caddr_t addr) is available]) +fi +fi + +if test x"$samba_cv_SYSQUOTA_FOUND" != x"yes"; then +AC_CACHE_CHECK([for int quotactl(const char *path, int cmd, int id, char *addr)],samba_cv_HAVE_QUOTACTL_4B,[ +AC_TRY_RUN_STRICT([ +#define HAVE_QUOTACTL_4B 1 +#define AUTOCONF_TEST 1 +#include "confdefs.h" +#include "${srcdir-.}/lib/sysquotas.c"],[$Werror_FLAGS],[$CPPFLAGS],[$LDFLAGS], + samba_cv_HAVE_QUOTACTL_4B=yes,samba_cv_HAVE_QUOTACTL_4B=no,samba_cv_HAVE_QUOTACTL_4B=cross)]) +if test x"$samba_cv_HAVE_QUOTACTL_4B" = x"yes"; then + echo "int quotactl(const char *path, int cmd, int id, char *addr) is not reworked for the new sys_quota api" +# samba_cv_SYSQUOTA_FOUND=yes;AC_DEFINE(HAVE_QUOTACTL_4B,1,[Whether int quotactl(const char *path, int cmd, int id, char *addr) is available]) +fi +fi + +if test x"$samba_cv_SYSQUOTA_FOUND" != x"yes"; then +AC_CACHE_CHECK([for CRAY int quotactl (char *spec, int request, char *arg)],samba_cv_HAVE_QUOTACTL_3,[ +AC_TRY_RUN_STRICT([ +#define HAVE_QUOTACTL_3 1 +#define AUTOCONF_TEST 1 +#include "confdefs.h" +#include "${srcdir-.}/lib/sysquotas.c"],[$Werror_FLAGS],[$CPPFLAGS],[$LDFLAGS], + samba_cv_HAVE_QUOTACTL_3=yes,samba_cv_HAVE_QUOTACTL_3=no,samba_cv_HAVE_QUOTACTL_3=cross)]) +if test x"$samba_cv_HAVE_QUOTACTL_3" = x"yes"; then + echo "CRAY int quotactl (char *spec, int request, char *arg) is NOT reworked for the sys_quota api" +# samba_cv_SYSQUOTA_FOUND=yes;AC_DEFINE(HAVE_QUOTACTL_3,1,[Whether CRAY int quotactl (char *spec, int request, char *arg); is available]) +fi +fi + +################################################# +# check for mntent.h and struct mntent +AC_CHECK_HEADERS(mntent.h) +################################################# +# check for setmntent,getmntent,endmntent +AC_CHECK_FUNCS(setmntent getmntent endmntent) + +################################################# +# check for devnm.h and struct mntent +AC_CHECK_HEADERS(devnm.h) +################################################# +# check for devnm +AC_CHECK_FUNCS(devnm) + +if test x"$samba_cv_WITH_SYS_QUOTAS" = x"yes"; then + if test x"$samba_cv_SYSQUOTA_FOUND" != x"yes"; then + # if --with-sys-quotas=yes then build it + # you have can use the get/set quota command smb.conf + # options then + samba_cv_SYSQUOTA_FOUND=auto + fi + if test x"$samba_cv_TRY_SYS_QUOTAS" != x"yes"; then + # if --with-sys-quotas=yes then build it + # you have can use the get/set quota command smb.conf + # options then + samba_cv_TRY_SYS_QUOTAS=auto + fi +fi + +if test x"$samba_cv_SYSQUOTA_FOUND" != x"no"; then +AC_CACHE_CHECK([whether the sys_quota interface works],samba_cv_SYSQUOTA_WORKS,[ +SAVE_CPPFLAGS="$CPPFLAGS" +CPPFLAGS="$CPPFLAGS -I${srcdir-.}/ -I. -I${srcdir-.}/include -I${srcdir-.}/ubiqx -I${srcdir-.}/popt -I${srcdir-.}/smbwrapper -I${srcdir-.}/nsswitch" +AC_TRY_COMPILE([ +#include "confdefs.h" +#define NO_PROTO_H 1 +#define NO_CONFIG_H 1 +#define HAVE_SYS_QUOTAS 1 +#include "${srcdir-.}/lib/sysquotas.c" +],[],samba_cv_SYSQUOTA_WORKS=yes,samba_cv_SYSQUOTA_WORKS=no) +CPPFLAGS="$SAVE_CPPFLAGS" +]) +if test x"$samba_cv_SYSQUOTA_WORKS" = x"yes"; then +AC_MSG_CHECKING(whether to use the new lib/sysquotas.c interface) + if test x"$samba_cv_TRY_SYS_QUOTAS" != x"no"; then + AC_DEFINE(WITH_QUOTAS,1,[Whether to use disk quota support]) + AC_DEFINE(HAVE_SYS_QUOTAS,1,[Whether the new lib/sysquotas.c interface can be used]) + samba_cv_WE_USE_SYS_QUOTAS=yes + AC_MSG_RESULT(yes) + else + AC_MSG_RESULT(no) + fi +fi +fi + +AC_CACHE_CHECK([whether the old quota support works],samba_cv_QUOTA_WORKS,[ +SAVE_CPPFLAGS="$CPPFLAGS" +CPPFLAGS="$CPPFLAGS -I${srcdir-.}/ -I. -I${srcdir-.}/include -I${srcdir-.}/ubiqx -I${srcdir-.}/popt -I${srcdir-.}/smbwrapper -I${srcdir-.}/nsswitch" +AC_TRY_COMPILE([ +#include "confdefs.h" +#define NO_PROTO_H 1 +#define NO_CONFIG_H 1 +#include "${srcdir-.}/smbd/quotas.c" +],[],samba_cv_QUOTA_WORKS=yes,samba_cv_QUOTA_WORKS=no) +CPPFLAGS="$SAVE_CPPFLAGS" +]) +if test x"$samba_cv_QUOTA_WORKS" = x"yes"; then +AC_MSG_CHECKING(whether to use the old quota support) + if test x"$samba_cv_WE_USE_SYS_QUOTAS" != x"yes"; then + if test x"$samba_cv_TRY_QUOTAS" != x"no"; then + AC_DEFINE(WITH_QUOTAS,1,[Whether to use disk quota support]) + AC_MSG_RESULT(yes) + else + AC_MSG_RESULT(no) + fi + else + AC_MSG_RESULT(no) + fi +fi + +#################### +# End of quota check samba_cv_RUN_QUOTA_TESTS +fi ################################################# # check for experimental utmp accounting AC_MSG_CHECKING(whether to support utmp accounting) +WITH_UTMP=yes AC_ARG_WITH(utmp, -[ --with-utmp Include experimental utmp accounting (default=no)], +[ --with-utmp Include utmp accounting (default, if supported by OS)], [ case "$withval" in - yes) - AC_MSG_RESULT(yes) - AC_DEFINE(WITH_UTMP,1,[Whether to include experimental utmp accounting]) - ;; + no) + WITH_UTMP=no + ;; *) - AC_MSG_RESULT(no) - ;; + WITH_UTMP=yes + ;; esac ], - AC_MSG_RESULT(no) ) +# utmp requires utmp.h +# Note similar check earlier, when checking utmp details. + +if test x"$WITH_UTMP" = x"yes" -a x"$ac_cv_header_utmp_h" = x"no"; then + utmp_no_reason=", no utmp.h on $host_os" + WITH_UTMP=no +fi + +# Display test results + +if test x"$WITH_UTMP" = x"yes"; then + AC_MSG_RESULT(yes) + AC_DEFINE(WITH_UTMP,1,[Whether to include experimental utmp accounting]) +else + AC_MSG_RESULT(no$utmp_no_reason) +fi + ################################################# # choose native language(s) of man pages AC_MSG_CHECKING(chosen man pages' language(s)) @@ -2966,7 +3330,34 @@ AC_ARG_WITH(acl-support, AC_DEFINE(HAVE_POSIX_ACLS,1,[Whether FreeBSD POSIX ACLs are available]) AC_DEFINE(HAVE_ACL_GET_PERM_NP,1,[Whether acl_get_perm_np() is available]) ;; - *) + *linux*) + AC_CHECK_LIB(attr,getxattr,[ACLLIBS="$ACLLIBS -lattr"]) + AC_CHECK_LIB(acl,acl_get_file,[ACLLIBS="$ACLLIBS -lacl"]) + AC_CACHE_CHECK([for ACL support],samba_cv_HAVE_POSIX_ACLS,[ + acl_LIBS=$LIBS + LIBS="$LIBS -lacl" + AC_TRY_LINK([#include +#include ], +[ acl_t acl; int entry_id; acl_entry_t *entry_p; return acl_get_entry( acl, entry_id, entry_p);], +samba_cv_HAVE_POSIX_ACLS=yes,samba_cv_HAVE_POSIX_ACLS=no) + LIBS=$acl_LIBS]) + if test x"$samba_cv_HAVE_POSIX_ACLS" = x"yes"; then + AC_MSG_RESULT(Using posix ACLs) + AC_DEFINE(HAVE_POSIX_ACLS,1,[Whether POSIX ACLs are available]) + AC_CACHE_CHECK([for acl_get_perm_np],samba_cv_HAVE_ACL_GET_PERM_NP,[ + acl_LIBS=$LIBS + LIBS="$LIBS -lacl" + AC_TRY_LINK([#include +#include ], +[ acl_permset_t permset_d; acl_perm_t perm; return acl_get_perm_np( permset_d, perm);], +samba_cv_HAVE_ACL_GET_PERM_NP=yes,samba_cv_HAVE_ACL_GET_PERM_NP=no) + LIBS=$acl_LIBS]) + if test x"$samba_cv_HAVE_ACL_GET_PERM_NP" = x"yes"; then + AC_DEFINE(HAVE_ACL_GET_PERM_NP,1,[Whether acl_get_perm_np() is available]) + fi + fi + ;; + *) AC_CHECK_LIB(acl,acl_get_file,[ACLLIBS="$ACLLIBS -lacl"]) AC_CACHE_CHECK([for ACL support],samba_cv_HAVE_POSIX_ACLS,[ acl_LIBS=$LIBS @@ -3245,7 +3636,8 @@ HAVE_WINBIND=yes # Define the winbind shared library name and any specific linker flags # it needs to be built with. -WINBIND_NSS=libnss_winbind.$SHLIBEXT +WINBIND_NSS="nsswitch/libnss_winbind.$SHLIBEXT" +WINBIND_WINS_NSS="nsswitch/libnss_wins.$SHLIBEXT" WINBIND_NSS_LDSHFLAGS=$LDSHFLAGS case "$host_os" in @@ -3253,8 +3645,10 @@ case "$host_os" in WINBIND_NSS_EXTRA_OBJS="nsswitch/winbind_nss_linux.o" ;; *irix*) + # IRIX has differently named shared libraries WINBIND_NSS_EXTRA_OBJS="nsswitch/winbind_nss_irix.o" - WINBIND_NSS="libns_winbind.$SHLIBEXT" + WINBIND_NSS="nsswitch/libns_winbind.$SHLIBEXT" + WINBIND_WINS_NSS="nsswitch/libns_wins.$SHLIBEXT" ;; *solaris*) # Solaris winbind client is implemented as a wrapper around @@ -3267,9 +3661,12 @@ case "$host_os" in WINBIND_NSS_EXTRA_OBJS="nsswitch/winbind_nss_solaris.o" ;; *aix*) + # AIX has even differently named shared libraries. No + # WINS support has been implemented yet. WINBIND_NSS_EXTRA_OBJS="nsswitch/winbind_nss_aix.o" WINBIND_NSS_LDSHFLAGS="-Wl,-bexpall,-bM:SRE,-ewb_aix_init" - WINBIND_NSS="WINBIND" + WINBIND_NSS="nsswitch/WINBIND" + WINBIND_WINS_NSS="" ;; *) HAVE_WINBIND=no @@ -3278,6 +3675,7 @@ case "$host_os" in esac AC_SUBST(WINBIND_NSS) +AC_SUBST(WINBIND_WINS_NSS) AC_SUBST(WINBIND_NSS_LDSHFLAGS) AC_SUBST(WINBIND_NSS_EXTRA_OBJS) AC_SUBST(WINBIND_NSS_EXTRA_LIBS) @@ -3316,7 +3714,7 @@ if test x"$HAVE_WINBIND" = x"yes"; then EXTRA_BIN_PROGS="$EXTRA_BIN_PROGS bin/wbinfo\$(EXEEXT)" EXTRA_SBIN_PROGS="$EXTRA_SBIN_PROGS bin/winbindd\$(EXEEXT)" if test x"$BLDSHARED" = x"true"; then - SHLIB_PROGS="$SHLIB_PROGS nsswitch/$WINBIND_NSS" + SHLIB_PROGS="$SHLIB_PROGS $WINBIND_NSS $WINBIND_WINS_NSS" if test x"$with_pam" = x"yes"; then SHLIB_PROGS="$SHLIB_PROGS nsswitch/pam_winbind.$SHLIBEXT" @@ -3327,31 +3725,15 @@ else fi # Solaris has some extra fields in struct passwd that need to be -# initialised otherwise nscd crashes. Unfortunately autoconf < 2.50 -# doesn't have the AC_CHECK_MEMBER macro which would be handy for checking -# this. - -#AC_CHECK_MEMBER(struct passwd.pw_comment, -# AC_DEFINE(HAVE_PASSWD_PW_COMMENT, 1, [Defined if struct passwd has pw_comment field]), -# [#include ]) - -AC_CACHE_CHECK([whether struct passwd has pw_comment],samba_cv_passwd_pw_comment, [ - AC_TRY_COMPILE([#include ],[struct passwd p; p.pw_comment;], - samba_cv_passwd_pw_comment=yes,samba_cv_passwd_pw_comment=no)]) -if test x"$samba_cv_passwd_pw_comment" = x"yes"; then - AC_DEFINE(HAVE_PASSWD_PW_COMMENT,1,[Whether struct passwd has pw_comment]) -fi - -#AC_CHECK_MEMBER(struct passwd.pw_age, -# AC_DEFINE(HAVE_PASSWD_PW_AGE, 1, [Defined if struct passwd has pw_age field]), -# [#include ]) +# initialised otherwise nscd crashes. + +AC_CHECK_MEMBER(struct passwd.pw_comment, + AC_DEFINE(HAVE_PASSWD_PW_COMMENT, 1, [Defined if struct passwd has pw_comment field]),, + [#include ]) -AC_CACHE_CHECK([whether struct passwd has pw_age],samba_cv_passwd_pw_age, [ - AC_TRY_COMPILE([#include ],[struct passwd p; p.pw_age;], - samba_cv_passwd_pw_age=yes,samba_cv_passwd_pw_age=no)]) -if test x"$samba_cv_passwd_pw_age" = x"yes"; then - AC_DEFINE(HAVE_PASSWD_PW_AGE,1,[Whether struct passwd has pw_age]) -fi +AC_CHECK_MEMBER(struct passwd.pw_age, + AC_DEFINE(HAVE_PASSWD_PW_AGE, 1, [Defined if struct passwd has pw_age field]),, + [#include ]) ################################################# # Check to see if we should use the included popt @@ -3435,6 +3817,7 @@ dnl Always built these modules static MODULE_pdb_guest=STATIC MODULE_rpc_spoolss=STATIC MODULE_rpc_srv=STATIC +MODULE_idmap_tdb=STATIC AC_ARG_WITH(static-modules, [ --with-static-modules=MODULES Comma-seperated list of names of modules to statically link in], @@ -3461,7 +3844,6 @@ SMB_MODULE(pdb_xml, passdb/pdb_xml.o, "bin/xml.$SHLIBEXT", PDB, [ PASSDBLIBS="$PASSDBLIBS $XML_LIBS" ] ) SMB_MODULE(pdb_mysql, passdb/pdb_mysql.o, "bin/mysql.$SHLIBEXT", PDB, [ PASSDBLIBS="$PASSDBLIBS $MYSQL_LIBS" ] ) -SMB_MODULE(pdb_nisplussam, passdb/pdb_nisplus.o, "bin/nisplussam.$SHLIBEXT", PDB) ## end of contributed pdb_modules ########################################################################### @@ -3484,7 +3866,11 @@ SMB_MODULE(rpc_samr, \$(RPC_SAMR_OBJ), "bin/librpc_samr.$SHLIBEXT", RPC) SMB_MODULE(rpc_echo, \$(RPC_ECHO_OBJ), "bin/librpc_echo.$SHLIBEXT", RPC) SMB_SUBSYSTEM(RPC) -SMB_MODULE(charset_weird, modules/developer.o, "bin/weird.$SHLIBEXT", CHARSET) +SMB_MODULE(idmap_ldap, sam/idmap_ldap.o, "bin/idmap_ldap.$SHLIBEXT", IDMAP) +SMB_MODULE(idmap_tdb, sam/idmap_tdb.o, "bin/idmap_tdb.$SHLIBEXT", IDMAP) +SMB_SUBSYSTEM(IDMAP) + +SMB_MODULE(charset_weird, modules/weird.o, "bin/weird.$SHLIBEXT", CHARSET) SMB_SUBSYSTEM(CHARSET) SMB_MODULE(auth_rhosts, \$(AUTH_RHOSTS_OBJ), "bin/rhosts.$SHLIBEXT", AUTH) @@ -3499,14 +3885,12 @@ SMB_SUBSYSTEM(AUTH) SMB_MODULE(vfs_recycle, \$(VFS_RECYCLE_OBJ), "bin/recycle.$SHLIBEXT", VFS) SMB_MODULE(vfs_audit, \$(VFS_AUDIT_OBJ), "bin/audit.$SHLIBEXT", VFS) SMB_MODULE(vfs_extd_audit, \$(VFS_EXTD_AUDIT_OBJ), "bin/extd_audit.$SHLIBEXT", VFS) -SMB_MODULE(vfs_fake_perms, \$(VFS_FAKE_PERMS_OBJ), "bin/fake_perms.$SHLIBEXT", VFS) SMB_MODULE(vfs_netatalk, \$(VFS_NETATALK_OBJ), "bin/netatalk.$SHLIBEXT", VFS) +SMB_MODULE(vfs_fake_perms, \$(VFS_FAKE_PERMS_OBJ), "bin/fake_perms.$SHLIBEXT", VFS) SMB_SUBSYSTEM(VFS) AC_DEFINE_UNQUOTED(STRING_STATIC_MODULES, "$string_static_modules", [String list of builtin modules]) -AC_SUBST(MODULES_CLEAN) - ################################################# # do extra things if we are running insure @@ -3514,6 +3898,18 @@ if test "${ac_cv_prog_CC}" = "insure"; then CPPFLAGS="$CPPFLAGS -D__INSURE__" fi +################################################# +# Display summary of libraries detected + +AC_MSG_RESULT([Using libraries:]) +AC_MSG_RESULT([ LIBS = $LIBS]) +if test x"$with_ads_support" = x"yes"; then + AC_MSG_RESULT([ KRB5_LIBS = $KRB5_LIBS]) +fi +if test x"$with_ldap_support" = x"yes"; then + AC_MSG_RESULT([ LDAP_LIBS = $LDAP_LIBS]) +fi + ################################################# # final configure stuff diff --git a/source3/groupdb/mapping.c b/source3/groupdb/mapping.c index 2b7a852688..3d2af5d0ba 100644 --- a/source3/groupdb/mapping.c +++ b/source3/groupdb/mapping.c @@ -37,69 +37,7 @@ PRIVS privs[] = { {SE_PRIV_PRINT_OPERATOR, "SaPrintOp", "Add or remove printers - Samba" }, {SE_PRIV_ALL, "SaAllPrivs", "all privileges" } }; -/* -PRIVS privs[] = { - { 2, "SeCreateTokenPrivilege" }, - { 3, "SeAssignPrimaryTokenPrivilege" }, - { 4, "SeLockMemoryPrivilege" }, - { 5, "SeIncreaseQuotaPrivilege" }, - { 6, "SeMachineAccountPrivilege" }, - { 7, "SeTcbPrivilege" }, - { 8, "SeSecurityPrivilege" }, - { 9, "SeTakeOwnershipPrivilege" }, - { 10, "SeLoadDriverPrivilege" }, - { 11, "SeSystemProfilePrivilege" }, - { 12, "SeSystemtimePrivilege" }, - { 13, "SeProfileSingleProcessPrivilege" }, - { 14, "SeIncreaseBasePriorityPrivilege" }, - { 15, "SeCreatePagefilePrivilege" }, - { 16, "SeCreatePermanentPrivilege" }, - { 17, "SeBackupPrivilege" }, - { 18, "SeRestorePrivilege" }, - { 19, "SeShutdownPrivilege" }, - { 20, "SeDebugPrivilege" }, - { 21, "SeAuditPrivilege" }, - { 22, "SeSystemEnvironmentPrivilege" }, - { 23, "SeChangeNotifyPrivilege" }, - { 24, "SeRemoteShutdownPrivilege" }, - { 25, "SeUndockPrivilege" }, - { 26, "SeSyncAgentPrivilege" }, - { 27, "SeEnableDelegationPrivilege" }, -}; -*/ - /* - * Those are not really privileges like the other ones. - * They are handled in a special case and called - * system privileges. - * - * SeNetworkLogonRight - * SeUnsolicitedInputPrivilege - * SeBatchLogonRight - * SeServiceLogonRight - * SeInteractiveLogonRight - * SeDenyInteractiveLogonRight - * SeDenyNetworkLogonRight - * SeDenyBatchLogonRight - * SeDenyBatchLogonRight - */ - -#if 0 -/**************************************************************************** -check if the user has the required privilege. -****************************************************************************/ -static BOOL se_priv_access_check(NT_USER_TOKEN *token, uint32 privilege) -{ - /* no token, no privilege */ - if (token==NULL) - return False; - - if ((token->privilege & privilege)==privilege) - return True; - - return False; -} -#endif /**************************************************************************** dump the mapping group mapping to a text file @@ -151,53 +89,35 @@ static BOOL default_group_mapping(void) fstring str_admins; fstring str_users; fstring str_guests; - LUID_ATTR set; - - PRIVILEGE_SET privilege_none; - PRIVILEGE_SET privilege_all; - PRIVILEGE_SET privilege_print_op; - - init_privilege(&privilege_none); - init_privilege(&privilege_all); - init_privilege(&privilege_print_op); - - set.attr=0; - set.luid.high=0; - set.luid.low=SE_PRIV_PRINT_OPERATOR; - add_privilege(&privilege_print_op, set); - - add_all_privilege(&privilege_all); /* Add the Wellknown groups */ - add_initial_entry(-1, "S-1-5-32-544", SID_NAME_WKN_GRP, "Administrators", "", privilege_all, PR_ACCESS_FROM_NETWORK|PR_LOG_ON_LOCALLY); - add_initial_entry(-1, "S-1-5-32-545", SID_NAME_WKN_GRP, "Users", "", privilege_none, PR_ACCESS_FROM_NETWORK|PR_LOG_ON_LOCALLY); - add_initial_entry(-1, "S-1-5-32-546", SID_NAME_WKN_GRP, "Guests", "", privilege_none, PR_ACCESS_FROM_NETWORK); - add_initial_entry(-1, "S-1-5-32-547", SID_NAME_WKN_GRP, "Power Users", "", privilege_none, PR_ACCESS_FROM_NETWORK|PR_LOG_ON_LOCALLY); - - add_initial_entry(-1, "S-1-5-32-548", SID_NAME_WKN_GRP, "Account Operators", "", privilege_none, PR_ACCESS_FROM_NETWORK|PR_LOG_ON_LOCALLY); - add_initial_entry(-1, "S-1-5-32-549", SID_NAME_WKN_GRP, "System Operators", "", privilege_none, PR_ACCESS_FROM_NETWORK|PR_LOG_ON_LOCALLY); - add_initial_entry(-1, "S-1-5-32-550", SID_NAME_WKN_GRP, "Print Operators", "", privilege_print_op, PR_ACCESS_FROM_NETWORK|PR_LOG_ON_LOCALLY); - add_initial_entry(-1, "S-1-5-32-551", SID_NAME_WKN_GRP, "Backup Operators", "", privilege_none, PR_ACCESS_FROM_NETWORK|PR_LOG_ON_LOCALLY); - - add_initial_entry(-1, "S-1-5-32-552", SID_NAME_WKN_GRP, "Replicators", "", privilege_none, PR_ACCESS_FROM_NETWORK); + add_initial_entry(-1, "S-1-5-32-544", SID_NAME_WKN_GRP, "Administrators", ""); + add_initial_entry(-1, "S-1-5-32-545", SID_NAME_WKN_GRP, "Users", ""); + add_initial_entry(-1, "S-1-5-32-546", SID_NAME_WKN_GRP, "Guests", ""); + add_initial_entry(-1, "S-1-5-32-547", SID_NAME_WKN_GRP, "Power Users", ""); + add_initial_entry(-1, "S-1-5-32-548", SID_NAME_WKN_GRP, "Account Operators", ""); + add_initial_entry(-1, "S-1-5-32-549", SID_NAME_WKN_GRP, "System Operators", ""); + add_initial_entry(-1, "S-1-5-32-550", SID_NAME_WKN_GRP, "Print Operators", ""); + add_initial_entry(-1, "S-1-5-32-551", SID_NAME_WKN_GRP, "Backup Operators", ""); + add_initial_entry(-1, "S-1-5-32-552", SID_NAME_WKN_GRP, "Replicators", ""); /* Add the defaults domain groups */ sid_copy(&sid_admins, get_global_sam_sid()); sid_append_rid(&sid_admins, DOMAIN_GROUP_RID_ADMINS); sid_to_string(str_admins, &sid_admins); - add_initial_entry(-1, str_admins, SID_NAME_DOM_GRP, "Domain Admins", "", privilege_all, PR_ACCESS_FROM_NETWORK|PR_LOG_ON_LOCALLY); + add_initial_entry(-1, str_admins, SID_NAME_DOM_GRP, "Domain Admins", ""); sid_copy(&sid_users, get_global_sam_sid()); sid_append_rid(&sid_users, DOMAIN_GROUP_RID_USERS); sid_to_string(str_users, &sid_users); - add_initial_entry(-1, str_users, SID_NAME_DOM_GRP, "Domain Users", "", privilege_none, PR_ACCESS_FROM_NETWORK|PR_LOG_ON_LOCALLY); + add_initial_entry(-1, str_users, SID_NAME_DOM_GRP, "Domain Users", ""); sid_copy(&sid_guests, get_global_sam_sid()); sid_append_rid(&sid_guests, DOMAIN_GROUP_RID_GUESTS); sid_to_string(str_guests, &sid_guests); - add_initial_entry(-1, str_guests, SID_NAME_DOM_GRP, "Domain Guests", "", privilege_none, PR_ACCESS_FROM_NETWORK); + add_initial_entry(-1, str_guests, SID_NAME_DOM_GRP, "Domain Guests", ""); return True; } @@ -255,8 +175,6 @@ static BOOL add_mapping_entry(GROUP_MAP *map, int flag) pstring key, buf; fstring string_sid=""; int len; - int i; - PRIVILEGE_SET *set; if(!init_group_mapping()) { DEBUG(0,("failed to initialize group mapping")); @@ -265,16 +183,8 @@ static BOOL add_mapping_entry(GROUP_MAP *map, int flag) sid_to_string(string_sid, &map->sid); - len = tdb_pack(buf, sizeof(buf), "ddffd", - map->gid, map->sid_name_use, map->nt_name, map->comment, map->systemaccount); - - /* write the privilege list in the TDB database */ - - set=&map->priv_set; - len += tdb_pack(buf+len, sizeof(buf)-len, "d", set->count); - for (i=0; icount; i++) - len += tdb_pack(buf+len, sizeof(buf)-len, "ddd", - set->set[i].luid.low, set->set[i].luid.high, set->set[i].attr); + len = tdb_pack(buf, sizeof(buf), "ddff", + map->gid, map->sid_name_use, map->nt_name, map->comment); if (len > sizeof(buf)) return False; @@ -293,8 +203,7 @@ static BOOL add_mapping_entry(GROUP_MAP *map, int flag) /**************************************************************************** initialise first time the mapping list ****************************************************************************/ -BOOL add_initial_entry(gid_t gid, const char *sid, enum SID_NAME_USE sid_name_use, - const char *nt_name, const char *comment, PRIVILEGE_SET priv_set, uint32 systemaccount) +BOOL add_initial_entry(gid_t gid, const char *sid, enum SID_NAME_USE sid_name_use, const char *nt_name, const char *comment) { GROUP_MAP map; @@ -312,207 +221,20 @@ BOOL add_initial_entry(gid_t gid, const char *sid, enum SID_NAME_USE sid_name_us map.sid_name_use=sid_name_use; fstrcpy(map.nt_name, nt_name); fstrcpy(map.comment, comment); - map.systemaccount=systemaccount; - - map.priv_set.count=priv_set.count; - map.priv_set.set=priv_set.set; - - pdb_add_group_mapping_entry(&map); - - return True; -} - -/**************************************************************************** -initialise a privilege list -****************************************************************************/ -void init_privilege(PRIVILEGE_SET *priv_set) -{ - priv_set->count=0; - priv_set->control=0; - priv_set->set=NULL; -} - -/**************************************************************************** -free a privilege list -****************************************************************************/ -BOOL free_privilege(PRIVILEGE_SET *priv_set) -{ - if (priv_set->count==0) { - DEBUG(100,("free_privilege: count=0, nothing to clear ?\n")); - return False; - } - - if (priv_set->set==NULL) { - DEBUG(0,("free_privilege: list ptr is NULL, very strange !\n")); - return False; - } - - safe_free(priv_set->set); - priv_set->count=0; - priv_set->control=0; - priv_set->set=NULL; - - return True; -} - -/**************************************************************************** -add a privilege to a privilege array -****************************************************************************/ -BOOL add_privilege(PRIVILEGE_SET *priv_set, LUID_ATTR set) -{ - LUID_ATTR *new_set; - - /* check if the privilege is not already in the list */ - if (check_priv_in_privilege(priv_set, set)) - return False; - - /* we can allocate memory to add the new privilege */ - - new_set=(LUID_ATTR *)Realloc(priv_set->set, (priv_set->count+1)*(sizeof(LUID_ATTR))); - if (new_set==NULL) { - DEBUG(0,("add_privilege: could not Realloc memory to add a new privilege\n")); - return False; - } - - new_set[priv_set->count].luid.high=set.luid.high; - new_set[priv_set->count].luid.low=set.luid.low; - new_set[priv_set->count].attr=set.attr; - - priv_set->count++; - priv_set->set=new_set; - - return True; -} - -/**************************************************************************** -add all the privileges to a privilege array -****************************************************************************/ -BOOL add_all_privilege(PRIVILEGE_SET *priv_set) -{ - LUID_ATTR set; - - set.attr=0; - set.luid.high=0; - - set.luid.low=SE_PRIV_ADD_USERS; - add_privilege(priv_set, set); - - set.luid.low=SE_PRIV_ADD_MACHINES; - add_privilege(priv_set, set); - - set.luid.low=SE_PRIV_PRINT_OPERATOR; - add_privilege(priv_set, set); - - return True; -} - -/**************************************************************************** -check if the privilege list is empty -****************************************************************************/ -BOOL check_empty_privilege(PRIVILEGE_SET *priv_set) -{ - return (priv_set->count == 0); -} - -/**************************************************************************** -check if the privilege is in the privilege list -****************************************************************************/ -BOOL check_priv_in_privilege(PRIVILEGE_SET *priv_set, LUID_ATTR set) -{ - int i; - - /* if the list is empty, obviously we can't have it */ - if (check_empty_privilege(priv_set)) - return False; - - for (i=0; icount; i++) { - LUID_ATTR *cur_set; - - cur_set=&priv_set->set[i]; - /* check only the low and high part. Checking the attr field has no meaning */ - if( (cur_set->luid.low==set.luid.low) && (cur_set->luid.high==set.luid.high) ) - return True; - } - - return False; -} - -/**************************************************************************** -remove a privilege from a privilege array -****************************************************************************/ -BOOL remove_privilege(PRIVILEGE_SET *priv_set, LUID_ATTR set) -{ - LUID_ATTR *new_set; - LUID_ATTR *old_set; - int i,j; - - /* check if the privilege is in the list */ - if (!check_priv_in_privilege(priv_set, set)) - return False; - - /* special case if it's the only privilege in the list */ - if (priv_set->count==1) { - free_privilege(priv_set); - init_privilege(priv_set); - - return True; - } - - /* - * the privilege is there, create a new list, - * and copy the other privileges - */ - - old_set=priv_set->set; - - new_set=(LUID_ATTR *)malloc((priv_set->count-1)*(sizeof(LUID_ATTR))); - if (new_set==NULL) { - DEBUG(0,("remove_privilege: could not malloc memory for new privilege list\n")); - return False; - } - - for (i=0, j=0; icount; i++) { - if ((old_set[i].luid.low==set.luid.low) && - (old_set[i].luid.high==set.luid.high)) { - continue; - } - - new_set[j].luid.low=old_set[i].luid.low; - new_set[j].luid.high=old_set[i].luid.high; - new_set[j].attr=old_set[i].attr; - j++; - } - - if (j!=priv_set->count-1) { - DEBUG(0,("remove_privilege: mismatch ! difference is not -1\n")); - DEBUGADD(0,("old count:%d, new count:%d\n", priv_set->count, j)); - safe_free(new_set); - return False; - } - - /* ok everything is fine */ - - priv_set->count--; - priv_set->set=new_set; - - safe_free(old_set); - - return True; + return pdb_add_group_mapping_entry(&map); } /**************************************************************************** Return the sid and the type of the unix group. ****************************************************************************/ -static BOOL get_group_map_from_sid(DOM_SID sid, GROUP_MAP *map, BOOL with_priv) +static BOOL get_group_map_from_sid(DOM_SID sid, GROUP_MAP *map) { TDB_DATA kbuf, dbuf; pstring key; fstring string_sid; int ret; - int i; - PRIVILEGE_SET *set; if(!init_group_mapping()) { DEBUG(0,("failed to initialize group mapping")); @@ -531,34 +253,10 @@ static BOOL get_group_map_from_sid(DOM_SID sid, GROUP_MAP *map, BOOL with_priv) if (!dbuf.dptr) return False; - ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "ddffd", - &map->gid, &map->sid_name_use, &map->nt_name, &map->comment, &map->systemaccount); - - set=&map->priv_set; - init_privilege(set); - ret += tdb_unpack(dbuf.dptr+ret, dbuf.dsize-ret, "d", &set->count); - - DEBUG(10,("get_group_map_from_sid: %d privileges\n", map->priv_set.count)); - - set->set = NULL; - if (set->count) { - set->set=(LUID_ATTR *)smb_xmalloc(set->count*sizeof(LUID_ATTR)); - } - - for (i=0; icount; i++) - ret += tdb_unpack(dbuf.dptr+ret, dbuf.dsize-ret, "ddd", - &(set->set[i].luid.low), &(set->set[i].luid.high), &(set->set[i].attr)); + ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "ddff", + &map->gid, &map->sid_name_use, &map->nt_name, &map->comment); SAFE_FREE(dbuf.dptr); - if (ret != dbuf.dsize) { - DEBUG(0,("get_group_map_from_sid: group mapping TDB corrupted ?\n")); - free_privilege(set); - return False; - } - - /* we don't want the privileges */ - if (with_priv==MAPPING_WITHOUT_PRIV) - free_privilege(set); sid_copy(&map->sid, &sid); @@ -569,13 +267,11 @@ static BOOL get_group_map_from_sid(DOM_SID sid, GROUP_MAP *map, BOOL with_priv) Return the sid and the type of the unix group. ****************************************************************************/ -static BOOL get_group_map_from_gid(gid_t gid, GROUP_MAP *map, BOOL with_priv) +static BOOL get_group_map_from_gid(gid_t gid, GROUP_MAP *map) { TDB_DATA kbuf, dbuf, newkey; fstring string_sid; int ret; - int i; - PRIVILEGE_SET *set; if(!init_group_mapping()) { DEBUG(0,("failed to initialize group mapping")); @@ -598,33 +294,15 @@ static BOOL get_group_map_from_gid(gid_t gid, GROUP_MAP *map, BOOL with_priv) string_to_sid(&map->sid, string_sid); - ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "ddffd", - &map->gid, &map->sid_name_use, &map->nt_name, &map->comment, &map->systemaccount); - - set=&map->priv_set; - ret += tdb_unpack(dbuf.dptr+ret, dbuf.dsize-ret, "d", &set->count); - set->set = NULL; - if (set->count) { - set->set=(LUID_ATTR *)smb_xmalloc(set->count*sizeof(LUID_ATTR)); - } - - for (i=0; icount; i++) - ret += tdb_unpack(dbuf.dptr+ret, dbuf.dsize-ret, "ddd", - &(set->set[i].luid.low), &(set->set[i].luid.high), &(set->set[i].attr)); + ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "ddff", + &map->gid, &map->sid_name_use, &map->nt_name, &map->comment); SAFE_FREE(dbuf.dptr); - if (ret != dbuf.dsize){ - free_privilege(set); - continue; - } if (gid==map->gid) { - if (!with_priv) - free_privilege(&map->priv_set); + SAFE_FREE(kbuf.dptr); return True; } - - free_privilege(set); } return False; @@ -634,13 +312,11 @@ static BOOL get_group_map_from_gid(gid_t gid, GROUP_MAP *map, BOOL with_priv) Return the sid and the type of the unix group. ****************************************************************************/ -static BOOL get_group_map_from_ntname(char *name, GROUP_MAP *map, BOOL with_priv) +static BOOL get_group_map_from_ntname(const char *name, GROUP_MAP *map) { TDB_DATA kbuf, dbuf, newkey; fstring string_sid; int ret; - int i; - PRIVILEGE_SET *set; if(!init_group_mapping()) { DEBUG(0,("get_group_map_from_ntname:failed to initialize group mapping")); @@ -663,35 +339,15 @@ static BOOL get_group_map_from_ntname(char *name, GROUP_MAP *map, BOOL with_priv string_to_sid(&map->sid, string_sid); - ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "ddffd", - &map->gid, &map->sid_name_use, &map->nt_name, &map->comment, &map->systemaccount); - - set=&map->priv_set; - ret += tdb_unpack(dbuf.dptr+ret, dbuf.dsize-ret, "d", &set->count); - - set->set=(LUID_ATTR *)malloc(set->count*sizeof(LUID_ATTR)); - if (set->set==NULL) { - DEBUG(0,("get_group_map_from_ntname: could not allocate memory for privileges\n")); - return False; - } - - for (i=0; icount; i++) - ret += tdb_unpack(dbuf.dptr+ret, dbuf.dsize-ret, "ddd", - &(set->set[i].luid.low), &(set->set[i].luid.high), &(set->set[i].attr)); + ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "ddff", + &map->gid, &map->sid_name_use, &map->nt_name, &map->comment); SAFE_FREE(dbuf.dptr); - if (ret != dbuf.dsize) { - free_privilege(set); - continue; - } if (StrCaseCmp(name, map->nt_name)==0) { - if (!with_priv) - free_privilege(&map->priv_set); + SAFE_FREE(kbuf.dptr); return True; } - - free_privilege(set); } return False; @@ -737,7 +393,7 @@ static BOOL group_map_remove(DOM_SID sid) ****************************************************************************/ static BOOL enum_group_mapping(enum SID_NAME_USE sid_name_use, GROUP_MAP **rmap, - int *num_entries, BOOL unix_only, BOOL with_priv) + int *num_entries, BOOL unix_only) { TDB_DATA kbuf, dbuf, newkey; fstring string_sid; @@ -746,8 +402,6 @@ static BOOL enum_group_mapping(enum SID_NAME_USE sid_name_use, GROUP_MAP **rmap, GROUP_MAP *mapt; int ret; int entries=0; - int i; - PRIVILEGE_SET *set; if(!init_group_mapping()) { DEBUG(0,("failed to initialize group mapping")); @@ -770,43 +424,19 @@ static BOOL enum_group_mapping(enum SID_NAME_USE sid_name_use, GROUP_MAP **rmap, fstrcpy(string_sid, kbuf.dptr+strlen(GROUP_PREFIX)); - ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "ddffd", - &map.gid, &map.sid_name_use, &map.nt_name, &map.comment, &map.systemaccount); - - set=&map.priv_set; - init_privilege(set); - - ret += tdb_unpack(dbuf.dptr+ret, dbuf.dsize-ret, "d", &set->count); - - if (set->count!=0) { - set->set=(LUID_ATTR *)malloc(set->count*sizeof(LUID_ATTR)); - if (set->set==NULL) { - DEBUG(0,("enum_group_mapping: could not allocate memory for privileges\n")); - return False; - } - } - - for (i=0; icount; i++) - ret += tdb_unpack(dbuf.dptr+ret, dbuf.dsize-ret, "ddd", - &(set->set[i].luid.low), &(set->set[i].luid.high), &(set->set[i].attr)); + ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "ddff", + &map.gid, &map.sid_name_use, &map.nt_name, &map.comment); SAFE_FREE(dbuf.dptr); - if (ret != dbuf.dsize) { - DEBUG(11,("enum_group_mapping: error in memory size\n")); - free_privilege(set); - continue; - } /* list only the type or everything if UNKNOWN */ if (sid_name_use!=SID_NAME_UNKNOWN && sid_name_use!=map.sid_name_use) { DEBUG(11,("enum_group_mapping: group %s is not of the requested type\n", map.nt_name)); - free_privilege(set); continue; } if (unix_only==ENUM_ONLY_MAPPED && map.gid==-1) { DEBUG(11,("enum_group_mapping: group %s is non mapped\n", map.nt_name)); - free_privilege(set); continue; } @@ -819,7 +449,6 @@ static BOOL enum_group_mapping(enum SID_NAME_USE sid_name_use, GROUP_MAP **rmap, if (!mapt) { DEBUG(0,("enum_group_mapping: Unable to enlarge group map!\n")); SAFE_FREE(*rmap); - free_privilege(set); return False; } else @@ -830,12 +459,6 @@ static BOOL enum_group_mapping(enum SID_NAME_USE sid_name_use, GROUP_MAP **rmap, mapt[entries].sid_name_use = map.sid_name_use; fstrcpy(mapt[entries].nt_name, map.nt_name); fstrcpy(mapt[entries].comment, map.comment); - mapt[entries].systemaccount=map.systemaccount; - mapt[entries].priv_set.count=set->count; - mapt[entries].priv_set.control=set->control; - mapt[entries].priv_set.set=set->set; - if (!with_priv) - free_privilege(&(mapt[entries].priv_set)); entries++; @@ -846,64 +469,6 @@ static BOOL enum_group_mapping(enum SID_NAME_USE sid_name_use, GROUP_MAP **rmap, return True; } - -/**************************************************************************** -convert a privilege string to a privilege array -****************************************************************************/ -void convert_priv_from_text(PRIVILEGE_SET *se_priv, char *privilege) -{ - pstring tok; - const char *p = privilege; - int i; - LUID_ATTR set; - - /* By default no privilege */ - init_privilege(se_priv); - - if (privilege==NULL) - return; - - while(next_token(&p, tok, " ", sizeof(tok)) ) { - for (i=0; i<=PRIV_ALL_INDEX; i++) { - if (StrCaseCmp(privs[i].priv, tok)==0) { - set.attr=0; - set.luid.high=0; - set.luid.low=privs[i].se_priv; - add_privilege(se_priv, set); - } - } - } -} - -/**************************************************************************** -convert a privilege array to a privilege string -****************************************************************************/ -void convert_priv_to_text(PRIVILEGE_SET *se_priv, char *privilege) -{ - int i,j; - - if (privilege==NULL) - return; - - ZERO_STRUCTP(privilege); - - if (check_empty_privilege(se_priv)) { - fstrcat(privilege, "No privilege"); - return; - } - - for(i=0; icount; i++) { - j=1; - while (privs[j].se_priv!=se_priv->set[i].luid.low && j<=PRIV_ALL_INDEX) { - j++; - } - - fstrcat(privilege, privs[j].priv); - fstrcat(privilege, " "); - } -} - - /* * * High level functions @@ -916,7 +481,7 @@ void convert_priv_to_text(PRIVILEGE_SET *se_priv, char *privilege) /* get a domain group from it's SID */ -BOOL get_domain_group_from_sid(DOM_SID sid, GROUP_MAP *map, BOOL with_priv) +BOOL get_domain_group_from_sid(DOM_SID sid, GROUP_MAP *map) { struct group *grp; @@ -928,23 +493,19 @@ BOOL get_domain_group_from_sid(DOM_SID sid, GROUP_MAP *map, BOOL with_priv) DEBUG(10, ("get_domain_group_from_sid\n")); /* if the group is NOT in the database, it CAN NOT be a domain group */ - if(!pdb_getgrsid(map, sid, with_priv)) + if(!pdb_getgrsid(map, sid)) return False; DEBUG(10, ("get_domain_group_from_sid: SID found in the TDB\n")); /* if it's not a domain group, continue */ if (map->sid_name_use!=SID_NAME_DOM_GRP) { - if (with_priv) - free_privilege(&map->priv_set); return False; } DEBUG(10, ("get_domain_group_from_sid: SID is a domain group\n")); if (map->gid==-1) { - if (with_priv) - free_privilege(&map->priv_set); return False; } @@ -952,8 +513,6 @@ BOOL get_domain_group_from_sid(DOM_SID sid, GROUP_MAP *map, BOOL with_priv) if ( (grp=getgrgid(map->gid)) == NULL) { DEBUG(10, ("get_domain_group_from_sid: gid DOESN'T exist in UNIX security\n")); - if (with_priv) - free_privilege(&map->priv_set); return False; } @@ -965,7 +524,7 @@ BOOL get_domain_group_from_sid(DOM_SID sid, GROUP_MAP *map, BOOL with_priv) /* get a local (alias) group from it's SID */ -BOOL get_local_group_from_sid(DOM_SID sid, GROUP_MAP *map, BOOL with_priv) +BOOL get_local_group_from_sid(DOM_SID sid, GROUP_MAP *map) { struct group *grp; @@ -975,22 +534,16 @@ BOOL get_local_group_from_sid(DOM_SID sid, GROUP_MAP *map, BOOL with_priv) } /* The group is in the mapping table */ - if(pdb_getgrsid(map, sid, with_priv)) { + if(pdb_getgrsid(map, sid)) { if (map->sid_name_use!=SID_NAME_ALIAS) { - if (with_priv) - free_privilege(&map->priv_set); return False; } if (map->gid==-1) { - if (with_priv) - free_privilege(&map->priv_set); return False; } if ( (grp=getgrgid(map->gid)) == NULL) { - if (with_priv) - free_privilege(&map->priv_set); return False; } } else { @@ -1005,13 +558,10 @@ BOOL get_local_group_from_sid(DOM_SID sid, GROUP_MAP *map, BOOL with_priv) return False; map->sid_name_use=SID_NAME_ALIAS; - map->systemaccount=PR_ACCESS_FROM_NETWORK; fstrcpy(map->nt_name, grp->gr_name); fstrcpy(map->comment, "Local Unix Group"); - init_privilege(&map->priv_set); - sid_copy(&map->sid, &sid); } @@ -1020,7 +570,7 @@ BOOL get_local_group_from_sid(DOM_SID sid, GROUP_MAP *map, BOOL with_priv) /* get a builtin group from it's SID */ -BOOL get_builtin_group_from_sid(DOM_SID sid, GROUP_MAP *map, BOOL with_priv) +BOOL get_builtin_group_from_sid(DOM_SID sid, GROUP_MAP *map) { struct group *grp; @@ -1029,24 +579,18 @@ BOOL get_builtin_group_from_sid(DOM_SID sid, GROUP_MAP *map, BOOL with_priv) return(False); } - if(!pdb_getgrsid(map, sid, with_priv)) + if(!pdb_getgrsid(map, sid)) return False; if (map->sid_name_use!=SID_NAME_WKN_GRP) { - if (with_priv) - free_privilege(&map->priv_set); return False; } if (map->gid==-1) { - if (with_priv) - free_privilege(&map->priv_set); return False; } if ( (grp=getgrgid(map->gid)) == NULL) { - if (with_priv) - free_privilege(&map->priv_set); return False; } @@ -1058,7 +602,7 @@ BOOL get_builtin_group_from_sid(DOM_SID sid, GROUP_MAP *map, BOOL with_priv) /**************************************************************************** Returns a GROUP_MAP struct based on the gid. ****************************************************************************/ -BOOL get_group_from_gid(gid_t gid, GROUP_MAP *map, BOOL with_priv) +BOOL get_group_from_gid(gid_t gid, GROUP_MAP *map) { struct group *grp; @@ -1073,11 +617,9 @@ BOOL get_group_from_gid(gid_t gid, GROUP_MAP *map, BOOL with_priv) /* * make a group map from scratch if doesn't exist. */ - if (!pdb_getgrgid(map, gid, with_priv)) { + if (!pdb_getgrgid(map, gid)) { map->gid=gid; map->sid_name_use=SID_NAME_ALIAS; - map->systemaccount=PR_ACCESS_FROM_NETWORK; - init_privilege(&map->priv_set); /* interim solution until we have a last RID allocated */ @@ -1139,8 +681,8 @@ BOOL get_uid_list_of_group(gid_t gid, uid_t **uid, int *num_uids) if( (pwd=getpwnam_alloc(gr)) !=NULL) { (*uid)[*num_uids]=pwd->pw_uid; (*num_uids)++; + passwd_free(&pwd); } - passwd_free(&pwd); gr = grp->gr_mem[++i]; } DEBUG(10, ("got [%d] members\n", *num_uids)); @@ -1172,40 +714,49 @@ BOOL get_uid_list_of_group(gid_t gid, uid_t **uid, int *num_uids) 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, (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; + int ret = -1; + int fd = 0; + + *new_gid = 0; - *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; + /* defer to scripts */ + + if ( *lp_addgroup_script() ) { + pstrcpy(add_script, lp_addgroup_script()); + pstring_sub(add_script, "%g", unix_group); + 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); } } - return ret; + /* Try winbindd */ + + if ( winbind_create_group( unix_group, NULL ) ) { + DEBUG(3,("smb_create_group: winbindd created the group (%s)\n", + unix_group)); + ret = 0; + } + + if (*new_gid == 0) { + struct group *grp = getgrnam(unix_group); + + if (grp != NULL) + *new_gid = grp->gr_gid; + } + + return ret; } /**************************************************************************** @@ -1217,12 +768,23 @@ int smb_delete_group(char *unix_group) pstring del_script; int ret; - pstrcpy(del_script, lp_delgroup_script()); - if (! *del_script) return -1; - pstring_sub(del_script, "%g", unix_group); - ret = smbrun(del_script,NULL); - DEBUG(3,("smb_delete_group: Running the command `%s' gave %d\n",del_script,ret)); - return ret; + /* defer to scripts */ + + if ( *lp_delgroup_script() ) { + pstrcpy(del_script, lp_delgroup_script()); + pstring_sub(del_script, "%g", unix_group); + ret = smbrun(del_script,NULL); + DEBUG(3,("smb_delete_group: Running the command `%s' gave %d\n",del_script,ret)); + return ret; + } + + if ( winbind_delete_group( unix_group ) ) { + DEBUG(3,("smb_delete_group: winbindd deleted the group (%s)\n", + unix_group)); + return 0; + } + + return -1; } /**************************************************************************** @@ -1233,14 +795,27 @@ 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; + /* defer to scripts */ + + if ( *lp_setprimarygroup_script() ) { + pstrcpy(add_script, lp_setprimarygroup_script()); + 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; + } + + /* Try winbindd */ + + if ( winbind_set_user_primary_group( unix_user, unix_group ) ) { + DEBUG(3,("smb_delete_group: winbindd set the group (%s) as the primary group for user (%s)\n", + unix_group, unix_user)); + return 0; + } + + return -1; } /**************************************************************************** @@ -1252,13 +827,26 @@ int smb_add_user_group(char *unix_group, char *unix_user) pstring add_script; int ret; - pstrcpy(add_script, lp_addusertogroup_script()); - if (! *add_script) return -1; - pstring_sub(add_script, "%g", unix_group); - pstring_sub(add_script, "%u", unix_user); - ret = smbrun(add_script,NULL); - DEBUG(3,("smb_add_user_group: Running the command `%s' gave %d\n",add_script,ret)); - return ret; + /* defer to scripts */ + + if ( *lp_addusertogroup_script() ) { + pstrcpy(add_script, lp_addusertogroup_script()); + pstring_sub(add_script, "%g", unix_group); + pstring_sub(add_script, "%u", unix_user); + ret = smbrun(add_script,NULL); + DEBUG(3,("smb_add_user_group: Running the command `%s' gave %d\n",add_script,ret)); + return ret; + } + + /* Try winbindd */ + + if ( winbind_add_user_to_group( unix_user, unix_group ) ) { + DEBUG(3,("smb_delete_group: winbindd added user (%s) to the group (%s)\n", + unix_user, unix_group)); + return -1; + } + + return -1; } /**************************************************************************** @@ -1270,34 +858,47 @@ int smb_delete_user_group(const char *unix_group, const char *unix_user) pstring del_script; int ret; - pstrcpy(del_script, lp_deluserfromgroup_script()); - if (! *del_script) return -1; - pstring_sub(del_script, "%g", unix_group); - pstring_sub(del_script, "%u", unix_user); - ret = smbrun(del_script,NULL); - DEBUG(3,("smb_delete_user_group: Running the command `%s' gave %d\n",del_script,ret)); - return ret; + /* defer to scripts */ + + if ( *lp_deluserfromgroup_script() ) { + pstrcpy(del_script, lp_deluserfromgroup_script()); + pstring_sub(del_script, "%g", unix_group); + pstring_sub(del_script, "%u", unix_user); + ret = smbrun(del_script,NULL); + DEBUG(3,("smb_delete_user_group: Running the command `%s' gave %d\n",del_script,ret)); + return ret; + } + + /* Try winbindd */ + + if ( winbind_remove_user_from_group( unix_user, unix_group ) ) { + DEBUG(3,("smb_delete_group: winbindd removed user (%s) from the group (%s)\n", + unix_user, unix_group)); + return 0; + } + + return -1; } NTSTATUS pdb_default_getgrsid(struct pdb_methods *methods, GROUP_MAP *map, - DOM_SID sid, BOOL with_priv) + DOM_SID sid) { - return get_group_map_from_sid(sid, map, with_priv) ? + return get_group_map_from_sid(sid, map) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL; } NTSTATUS pdb_default_getgrgid(struct pdb_methods *methods, GROUP_MAP *map, - gid_t gid, BOOL with_priv) + gid_t gid) { - return get_group_map_from_gid(gid, map, with_priv) ? + return get_group_map_from_gid(gid, map) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL; } NTSTATUS pdb_default_getgrnam(struct pdb_methods *methods, GROUP_MAP *map, - char *name, BOOL with_priv) + const char *name) { - return get_group_map_from_ntname(name, map, with_priv) ? + return get_group_map_from_ntname(name, map) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL; } @@ -1325,10 +926,9 @@ NTSTATUS pdb_default_delete_group_mapping_entry(struct pdb_methods *methods, NTSTATUS pdb_default_enum_group_mapping(struct pdb_methods *methods, enum SID_NAME_USE sid_name_use, GROUP_MAP **rmap, int *num_entries, - BOOL unix_only, BOOL with_priv) + BOOL unix_only) { - return enum_group_mapping(sid_name_use, rmap, num_entries, unix_only, - with_priv) ? + return enum_group_mapping(sid_name_use, rmap, num_entries, unix_only) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL; } @@ -1337,19 +937,19 @@ NTSTATUS pdb_default_enum_group_mapping(struct pdb_methods *methods, *********************************************************************/ NTSTATUS pdb_nop_getgrsid(struct pdb_methods *methods, GROUP_MAP *map, - DOM_SID sid, BOOL with_priv) + DOM_SID sid) { return NT_STATUS_UNSUCCESSFUL; } NTSTATUS pdb_nop_getgrgid(struct pdb_methods *methods, GROUP_MAP *map, - gid_t gid, BOOL with_priv) + gid_t gid) { return NT_STATUS_UNSUCCESSFUL; } NTSTATUS pdb_nop_getgrnam(struct pdb_methods *methods, GROUP_MAP *map, - char *name, BOOL with_priv) + const char *name) { return NT_STATUS_UNSUCCESSFUL; } @@ -1375,7 +975,7 @@ NTSTATUS pdb_nop_delete_group_mapping_entry(struct pdb_methods *methods, NTSTATUS pdb_nop_enum_group_mapping(struct pdb_methods *methods, enum SID_NAME_USE sid_name_use, GROUP_MAP **rmap, int *num_entries, - BOOL unix_only, BOOL with_priv) + BOOL unix_only) { return NT_STATUS_UNSUCCESSFUL; } diff --git a/source3/include/.cvsignore b/source3/include/.cvsignore index 4bff170b3b..bff248727f 100644 --- a/source3/include/.cvsignore +++ b/source3/include/.cvsignore @@ -3,5 +3,4 @@ config.h stamp-h proto.h wrepld_proto.h -tdbsam2_parse_info.h config.h.in diff --git a/source3/include/ads.h b/source3/include/ads.h index 7f7568d8b0..0961c9581c 100644 --- a/source3/include/ads.h +++ b/source3/include/ads.h @@ -205,6 +205,7 @@ typedef void **ADS_MODLIST; #define ADS_AUTH_NO_BIND 0x02 #define ADS_AUTH_ANON_BIND 0x04 #define ADS_AUTH_SIMPLE_BIND 0x08 +#define ADS_AUTH_ALLOW_NTLMSSP 0x10 /* Kerberos environment variable names */ #define KRB5_ENV_CCNAME "KRB5CCNAME" diff --git a/source3/include/auth.h b/source3/include/auth.h index eb80e3c5b4..6b42418be8 100644 --- a/source3/include/auth.h +++ b/source3/include/auth.h @@ -96,6 +96,8 @@ typedef struct auth_serversupplied_info SAM_ACCOUNT *sam_account; void *pam_handle; + + char *unix_name; } auth_serversupplied_info; diff --git a/source3/include/client.h b/source3/include/client.h index d75effd7d0..fad2c099b9 100644 --- a/source3/include/client.h +++ b/source3/include/client.h @@ -66,7 +66,7 @@ typedef struct smb_sign_info { BOOL negotiated_smb_signing; BOOL allow_smb_signing; BOOL doing_signing; - BOOL mandetory_signing; + BOOL mandatory_signing; } smb_sign_info; struct cli_state { @@ -131,25 +131,30 @@ struct cli_state { * Only used in NT domain calls. */ + int pipe_idx; /* Index (into list of known pipes) + of the pipe we're talking to, + if any */ + uint16 nt_pipe_fnum; /* Pipe handle. */ + /* Secure pipe parameters */ + int pipe_auth_flags; + uint16 saved_netlogon_pipe_fnum; /* The "first" pipe to get the session key for the schannel. */ struct netsec_auth_struct auth_info; + NTLMSSP_CLIENT_STATE *ntlmssp_pipe_state; + unsigned char sess_key[16]; /* Current session key. */ - unsigned char ntlmssp_hash[258]; /* ntlmssp data. */ - uint32 ntlmssp_cli_flgs; /* ntlmssp client flags */ - uint32 ntlmssp_srv_flgs; /* ntlmssp server flags */ - uint32 ntlmssp_seq_num; /* ntlmssp sequence number */ DOM_CRED clnt_cred; /* Client credential. */ fstring mach_acct; /* MYNAME$. */ fstring srv_name_slash; /* \\remote server. */ fstring clnt_name_slash; /* \\local client. */ uint16 max_xmit_frag; uint16 max_recv_frag; - uint32 ntlmssp_flags; + BOOL use_kerberos; BOOL use_spnego; diff --git a/source3/include/idmap.h b/source3/include/idmap.h index 1e56519453..ae7e4e5101 100644 --- a/source3/include/idmap.h +++ b/source3/include/idmap.h @@ -1,3 +1,5 @@ +#ifndef _IDMAP_H_ +#define _IDMAP_H_ /* Unix SMB/CIFS implementation. @@ -22,6 +24,9 @@ Boston, MA 02111-1307, USA. */ +#define SMB_IDMAP_INTERFACE_VERSION 2 + + #define ID_EMPTY 0x00 #define ID_USERID 0x01 #define ID_GROUPID 0x02 @@ -29,20 +34,16 @@ #define ID_TYPEMASK 0x0f -#define ID_NOMAP 0x10 -#define ID_CACHE 0x20 - -typedef union unid_t { - uid_t uid; - gid_t gid; -} unid_t; +#define ID_QUERY_ONLY 0x10 /* Filled out by IDMAP backends */ struct idmap_methods { /* Called when backend is first loaded */ - NTSTATUS (*init)(void); + NTSTATUS (*init)( char *params ); + NTSTATUS (*allocate_rid)(uint32 *rid, int rid_type); + NTSTATUS (*allocate_id)(unid_t *id, int id_type); NTSTATUS (*get_sid_from_id)(DOM_SID *sid, unid_t id, int id_type); NTSTATUS (*get_id_from_sid)(unid_t *id, int *id_type, const DOM_SID *sid); NTSTATUS (*set_mapping)(const DOM_SID *sid, unid_t id, int id_type); @@ -53,4 +54,4 @@ struct idmap_methods { /* Called to dump backend status */ void (*status)(void); }; - +#endif /* _IDMAP_H_ */ diff --git a/source3/include/includes.h b/source3/include/includes.h index 534bbfbf26..edaeda3abe 100644 --- a/source3/include/includes.h +++ b/source3/include/includes.h @@ -437,6 +437,18 @@ #include #endif +#if HAVE_ATTR_XATTR_H +#include +#endif + +#if HAVE_LOCALE_H +#include +#endif + +#if HAVE_LANGINFO_H +#include +#endif + /* Special macros that are no-ops except when run under Valgrind on * x86. They've moved a little bit from valgrind 1.0.4 to 1.9.4 */ #if HAVE_VALGRIND_MEMCHECK_H @@ -769,9 +781,6 @@ extern int errno; #include "version.h" #include "smb.h" -/* -#include "smbw.h" -*/ #include "nameserv.h" @@ -808,14 +817,12 @@ extern int errno; #include "auth.h" -#include "sam.h" - -#include "gums.h" - #include "idmap.h" #include "client.h" + #include "smbw.h" + #include "session.h" #include "asn_1.h" @@ -828,8 +835,6 @@ extern int errno; #include "nsswitch/winbind_client.h" -#include "genparser.h" - /* * Type for wide character dirent structure. * Only d_name is defined by POSIX. @@ -876,6 +881,10 @@ struct printjob; struct smb_ldap_privates; +/* forward declarations from smbldap.c */ + +#include "smbldap.h" + /***** automatically generated prototypes *****/ #ifndef NO_PROTO_H #include "proto.h" @@ -1034,10 +1043,6 @@ int setresgid(gid_t rgid, gid_t egid, gid_t sgid); int vasprintf(char **ptr, const char *format, va_list ap); #endif -#if !defined(HAVE_BZERO) && defined(HAVE_MEMSET) -#define bzero(a,b) memset((a),'\0',(b)) -#endif - #ifdef REPLACE_GETPASS #define getpass(prompt) getsmbpass((prompt)) #endif @@ -1283,7 +1288,7 @@ krb5_const_principal get_principal_from_tkt(krb5_ticket *tkt); krb5_error_code krb5_locate_kdc(krb5_context ctx, const krb5_data *realm, struct sockaddr **addr_pp, int *naddrs, int get_masters); krb5_error_code get_kerberos_allowed_etypes(krb5_context context, krb5_enctype **enctypes); void free_kerberos_etypes(krb5_context context, krb5_enctype *enctypes); -BOOL krb5_get_smb_session_key(krb5_context context, krb5_auth_context auth_context, uint8 session_key[16]); +BOOL get_krb5_smb_session_key(krb5_context context, krb5_auth_context auth_context, uint8 session_key[16]); #endif /* HAVE_KRB5 */ /* TRUE and FALSE are part of the C99 standard and gcc, but diff --git a/source3/include/mapping.h b/source3/include/mapping.h index d4f2d28e6a..fdaa2b0453 100644 --- a/source3/include/mapping.h +++ b/source3/include/mapping.h @@ -19,29 +19,9 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#define PRIV_ALL_INDEX 5 - -#define SE_PRIV_NONE 0x0000 -#define SE_PRIV_ADD_MACHINES 0x0006 -#define SE_PRIV_SEC_PRIV 0x0008 -#define SE_PRIV_TAKE_OWNER 0x0009 -#define SE_PRIV_ADD_USERS 0xff01 -#define SE_PRIV_PRINT_OPERATOR 0xff03 -#define SE_PRIV_ALL 0xffff - #define ENUM_ONLY_MAPPED True #define ENUM_ALL_MAPPED False -#define MAPPING_WITH_PRIV True -#define MAPPING_WITHOUT_PRIV False - -#define PR_NONE 0x0000 -#define PR_LOG_ON_LOCALLY 0x0001 -#define PR_ACCESS_FROM_NETWORK 0x0002 -#define PR_LOG_ON_BATCH_JOB 0x0004 -#define PR_LOG_ON_SERVICE 0x0010 - - typedef struct _GROUP_MAP { struct pdb_methods *methods; gid_t gid; @@ -49,13 +29,5 @@ typedef struct _GROUP_MAP { enum SID_NAME_USE sid_name_use; fstring nt_name; fstring comment; - uint32 systemaccount; - PRIVILEGE_SET priv_set; } GROUP_MAP; -typedef struct _PRIVS { - uint32 se_priv; - const char *priv; - const char *description; -} PRIVS; - diff --git a/source3/include/ntioctl.h b/source3/include/ntioctl.h index 4749842ddc..17791fde18 100644 --- a/source3/include/ntioctl.h +++ b/source3/include/ntioctl.h @@ -23,4 +23,46 @@ we only need the sparse flag */ -#define NTIOCTL_SET_SPARSE 0x900c4 + +/* IOCTL information */ +/* List of ioctl function codes that look to be of interest to remote clients like this. */ +/* Need to do some experimentation to make sure they all work remotely. */ +/* Some of the following such as the encryption/compression ones would be */ +/* invoked from tools via a specialized hook into the VFS rather than via the */ +/* standard vfs entry points */ +#define FSCTL_REQUEST_OPLOCK_LEVEL_1 0x00090000 +#define FSCTL_REQUEST_OPLOCK_LEVEL_2 0x00090004 +#define FSCTL_REQUEST_BATCH_OPLOCK 0x00090008 +#define FSCTL_LOCK_VOLUME 0x00090018 +#define FSCTL_UNLOCK_VOLUME 0x0009001C +#define FSCTL_GET_COMPRESSION 0x0009003C +#define FSCTL_SET_COMPRESSION 0x0009C040 +#define FSCTL_REQUEST_FILTER_OPLOCK 0x0009008C +#define FSCTL_FIND_FILES_BY_SID 0x0009008F +#define FSCTL_FILESYS_GET_STATISTICS 0x00090090 +#define FSCTL_SET_REPARSE_POINT 0x000900A4 +#define FSCTL_GET_REPARSE_POINT 0x000900A8 +#define FSCTL_DELETE_REPARSE_POINT 0x000900AC +#define FSCTL_0x000900C0 0x000900C0 +#define FSCTL_SET_SPARSE 0x000900C4 +#define FSCTL_SET_ZERO_DATA 0x000900C8 +#define FSCTL_SET_ENCRYPTION 0x000900D7 +#define FSCTL_ENCRYPTION_FSCTL_IO 0x000900DB +#define FSCTL_WRITE_RAW_ENCRYPTED 0x000900DF +#define FSCTL_READ_RAW_ENCRYPTED 0x000900E3 +#define FSCTL_SIS_COPYFILE 0x00090100 +#define FSCTL_SIS_LINK_FILES 0x0009C104 + +#if 0 +#define FSCTL_SECURITY_ID_CHECK +#define FSCTL_DISMOUNT_VOLUME +#define FSCTL_GET_NTFS_FILE_RECORD +#define FSCTL_ALLOW_EXTENDED_DASD_IO +#define FSCTL_RECALL_FILE +#define FSCTL_QUERY_ALLOCATED_RANGES + +#endif + +#define IO_REPARSE_TAG_MOUNT_POINT 0xA0000003 +#define IO_REPARSE_TAG_HSM 0xC0000004 +#define IO_REPARSE_TAG_SIS 0x80000007 diff --git a/source3/include/ntlmssp.h b/source3/include/ntlmssp.h index cfbbb00381..562e4853cc 100644 --- a/source3/include/ntlmssp.h +++ b/source3/include/ntlmssp.h @@ -64,8 +64,8 @@ enum NTLM_MESSAGE_TYPE #define NTLMSSP_NAME_TYPE_SERVER 0x01 #define NTLMSSP_NAME_TYPE_DOMAIN 0x02 -#define NTLMSSP_NAME_TYPE_DOMAIN_DNS 0x03 -#define NTLMSSP_NAME_TYPE_SERVER_DNS 0x04 +#define NTLMSSP_NAME_TYPE_SERVER_DNS 0x03 +#define NTLMSSP_NAME_TYPE_DOMAIN_DNS 0x04 typedef struct ntlmssp_state { @@ -129,5 +129,10 @@ typedef struct ntlmssp_client_state /* ntlmv1 */ unsigned char ntlmssp_hash[258]; + /* it turns out that we don't always get the + response in at the time we want to process it. + Store it here, until we need it */ + DATA_BLOB stored_response; + } NTLMSSP_CLIENT_STATE; diff --git a/source3/include/passdb.h b/source3/include/passdb.h index e14e250d34..e3077eee70 100644 --- a/source3/include/passdb.h +++ b/source3/include/passdb.h @@ -61,6 +61,7 @@ enum pdb_elements { PDB_UNKNOWN6, PDB_LMPASSWD, PDB_NTPASSWD, + PDB_BACKEND_PRIVATE_DATA, /* this must be the last element */ PDB_COUNT @@ -137,6 +138,10 @@ typedef struct sam_passwd uint32 unknown_5; /* 0x0002 0000 */ uint32 unknown_6; /* 0x0000 04ec */ + /* a tag for who added the private methods */ + const struct pdb_methods *backend_private_methods; + void *backend_private_data; + void (*backend_private_data_free_fn)(void **); } private; /* Lets see if the remaining code can get the hint that you @@ -203,14 +208,11 @@ typedef struct pdb_context NTSTATUS (*pdb_delete_sam_account)(struct pdb_context *, SAM_ACCOUNT *username); - NTSTATUS (*pdb_getgrsid)(struct pdb_context *context, GROUP_MAP *map, - DOM_SID sid, BOOL with_priv); + NTSTATUS (*pdb_getgrsid)(struct pdb_context *context, GROUP_MAP *map, DOM_SID sid); - NTSTATUS (*pdb_getgrgid)(struct pdb_context *context, GROUP_MAP *map, - gid_t gid, BOOL with_priv); + NTSTATUS (*pdb_getgrgid)(struct pdb_context *context, GROUP_MAP *map, gid_t gid); - NTSTATUS (*pdb_getgrnam)(struct pdb_context *context, GROUP_MAP *map, - char *name, BOOL with_priv); + NTSTATUS (*pdb_getgrnam)(struct pdb_context *context, GROUP_MAP *map, const char *name); NTSTATUS (*pdb_add_group_mapping_entry)(struct pdb_context *context, GROUP_MAP *map); @@ -224,7 +226,7 @@ typedef struct pdb_context NTSTATUS (*pdb_enum_group_mapping)(struct pdb_context *context, enum SID_NAME_USE sid_name_use, GROUP_MAP **rmap, int *num_entries, - BOOL unix_only, BOOL with_priv); + BOOL unix_only); void (*free_fn)(struct pdb_context **); @@ -257,14 +259,11 @@ typedef struct pdb_methods NTSTATUS (*delete_sam_account)(struct pdb_methods *, SAM_ACCOUNT *username); - NTSTATUS (*getgrsid)(struct pdb_methods *methods, GROUP_MAP *map, - DOM_SID sid, BOOL with_priv); + NTSTATUS (*getgrsid)(struct pdb_methods *methods, GROUP_MAP *map, DOM_SID sid); - NTSTATUS (*getgrgid)(struct pdb_methods *methods, GROUP_MAP *map, - gid_t gid, BOOL with_priv); + NTSTATUS (*getgrgid)(struct pdb_methods *methods, GROUP_MAP *map, gid_t gid); - NTSTATUS (*getgrnam)(struct pdb_methods *methods, GROUP_MAP *map, - char *name, BOOL with_priv); + NTSTATUS (*getgrnam)(struct pdb_methods *methods, GROUP_MAP *map, const char *name); NTSTATUS (*add_group_mapping_entry)(struct pdb_methods *methods, GROUP_MAP *map); @@ -278,7 +277,7 @@ typedef struct pdb_methods NTSTATUS (*enum_group_mapping)(struct pdb_methods *methods, enum SID_NAME_USE sid_name_use, GROUP_MAP **rmap, int *num_entries, - BOOL unix_only, BOOL with_priv); + BOOL unix_only); void *private_data; /* Private data of some kind */ diff --git a/source3/include/privileges.h b/source3/include/privileges.h index 404c5d246b..67d8a2cbcc 100644 --- a/source3/include/privileges.h +++ b/source3/include/privileges.h @@ -23,6 +23,22 @@ #ifndef PRIVILEGES_H #define PRIVILEGES_H +#define PRIV_ALL_INDEX 5 + +#define SE_PRIV_NONE 0x0000 +#define SE_PRIV_ADD_MACHINES 0x0006 +#define SE_PRIV_SEC_PRIV 0x0008 +#define SE_PRIV_TAKE_OWNER 0x0009 +#define SE_PRIV_ADD_USERS 0xff01 +#define SE_PRIV_PRINT_OPERATOR 0xff03 +#define SE_PRIV_ALL 0xffff + +#define PR_NONE 0x0000 +#define PR_LOG_ON_LOCALLY 0x0001 +#define PR_ACCESS_FROM_NETWORK 0x0002 +#define PR_LOG_ON_BATCH_JOB 0x0004 +#define PR_LOG_ON_SERVICE 0x0010 + typedef struct LUID { uint32 low; @@ -42,4 +58,11 @@ typedef struct privilege_set LUID_ATTR *set; } PRIVILEGE_SET; -#endif /* _RPC_LSA_H */ +typedef struct _PRIVS { + uint32 se_priv; + const char *priv; + const char *description; +} PRIVS; + + +#endif /* PRIVILEGES_H */ diff --git a/source3/include/rpc_dce.h b/source3/include/rpc_dce.h index b99639d68d..dc82f45368 100644 --- a/source3/include/rpc_dce.h +++ b/source3/include/rpc_dce.h @@ -51,17 +51,32 @@ enum RPC_PKT_TYPE /* NTLMSSP signature version */ #define NTLMSSP_SIGN_VERSION 0x01 -/* NTLMSSP auth type and level. */ +/* NTLMSSP auth type */ #define NTLMSSP_AUTH_TYPE 0xa -#define NTLMSSP_AUTH_LEVEL 0x6 + +/* DCE-RPC standard identifiers to indicate + signing or sealing of an RPC pipe */ +#define RPC_PIPE_AUTH_SIGN_LEVEL 0x5 +#define RPC_PIPE_AUTH_SEAL_LEVEL 0x6 /* Netlogon schannel auth type and level */ #define NETSEC_AUTH_TYPE 0x44 -#define NETSEC_AUTH_LEVEL 0x6 #define NETSEC_SIGNATURE { 0x77, 0x00, 0x7a, 0x00, 0xff, 0xff, 0x00, 0x00 } #define RPC_AUTH_NETSEC_CHK_LEN 0x20 #define NETLOGON_NEG_SCHANNEL 0x40000000 +enum netsec_direction +{ + SENDER_IS_INITIATOR, + SENDER_IS_ACCEPTOR +}; + +/* Internal Flags to indicate what type of authentication on the pipe */ +#define AUTH_PIPE_SIGN 0x0001 +#define AUTH_PIPE_SEAL 0x0002 +#define AUTH_PIPE_NTLMSSP 0x0004 +#define AUTH_PIPE_NETSEC 0x0008 + /* Maximum PDU fragment size. */ #define MAX_PDU_FRAG_LEN 0x1630 /* #define MAX_PDU_FRAG_LEN 0x10b8 this is what w2k sets */ @@ -222,8 +237,8 @@ typedef struct rpc_auth_netsec_neg_info typedef struct rpc_auth_netsec_chk_info { uint8 sig [8]; /* 77 00 7a 00 ff ff 00 00 */ - uint8 data1[8]; - uint8 data3[8]; /* verifier, seq num */ + uint8 packet_digest[8]; /* checksum over the packet, MD5'ed with session key */ + uint8 seq_num[8]; /* verifier, seq num */ uint8 data8[8]; /* random 8-byte nonce */ } RPC_AUTH_NETSEC_CHK; @@ -350,5 +365,4 @@ typedef struct rpc_auth_ntlmssp_chk_info #define RPC_AUTH_NTLMSSP_CHK_LEN 16 - #endif /* _DCE_RPC_H */ diff --git a/source3/include/rpc_lsa.h b/source3/include/rpc_lsa.h index d4136a9fde..135fd76d6c 100644 --- a/source3/include/rpc_lsa.h +++ b/source3/include/rpc_lsa.h @@ -237,7 +237,7 @@ typedef struct r_lsa_query_sec_obj_info typedef struct lsa_query_info { POLICY_HND pol; /* policy handle */ - uint16 info_class; /* info class */ + uint16 info_class; /* info class */ } LSA_Q_QUERY_INFO; @@ -537,6 +537,7 @@ typedef struct POLICY_HND pol; /* policy handle */ DOM_SID2 sid; UNISTR2_ARRAY rights; + uint32 count; } LSA_Q_ADD_ACCT_RIGHTS; /* LSA_R_ADD_ACCT_RIGHTS - LSA add account rights */ @@ -553,6 +554,7 @@ typedef struct DOM_SID2 sid; uint32 removeall; UNISTR2_ARRAY rights; + uint32 count; } LSA_Q_REMOVE_ACCT_RIGHTS; /* LSA_R_REMOVE_ACCT_RIGHTS - LSA remove account rights */ @@ -561,22 +563,6 @@ typedef struct NTSTATUS status; } LSA_R_REMOVE_ACCT_RIGHTS; -/* LSA_Q_ENUM_ACCT_WITH_RIGHT - LSA enum accounts with right */ -typedef struct -{ - POLICY_HND pol; - STRHDR right_hdr; - UNISTR2 right; -} LSA_Q_ENUM_ACCT_WITH_RIGHT; - -/* LSA_R_ENUM_ACCT_WITH_RIGHT - LSA enum accounts with right */ -typedef struct -{ - uint32 count; - SID_ARRAY sids; - NTSTATUS status; -} LSA_R_ENUM_ACCT_WITH_RIGHT; - /* LSA_Q_PRIV_GET_DISPNAME - LSA get privilege display name */ typedef struct lsa_q_priv_get_dispname diff --git a/source3/include/rpc_samr.h b/source3/include/rpc_samr.h index e1fa9c06bc..7d28a0f3a7 100644 --- a/source3/include/rpc_samr.h +++ b/source3/include/rpc_samr.h @@ -147,16 +147,6 @@ SamrTestPrivateFunctionsUser #define SAMR_SET_USERINFO 0x3A #define SAMR_CONNECT4 0x3E - -typedef struct _DISP_USER_INFO { - SAM_ACCOUNT *sam; -} DISP_USER_INFO; - -typedef struct _DISP_GROUP_INFO { - DOMAIN_GRP *grp; -} DISP_GROUP_INFO; - - typedef struct logon_hours_info { uint32 len; /* normally 21 bytes */ diff --git a/source3/include/rpc_secdes.h b/source3/include/rpc_secdes.h index 1bb25e8651..fb7060cde3 100644 --- a/source3/include/rpc_secdes.h +++ b/source3/include/rpc_secdes.h @@ -78,7 +78,8 @@ #define SEC_DESC_DACL_DEFAULTED 0x0008 #define SEC_DESC_SACL_PRESENT 0x0010 #define SEC_DESC_SACL_DEFAULTED 0x0020 -#define SEC_DESC_SELF_RELATIVE 0x8000 +#define SEC_DESC_DACL_TRUSTED 0x0040 +#define SEC_DESC_SERVER_SECURITY 0x0080 /* * New Windows 2000 bits. */ @@ -89,14 +90,28 @@ #define SE_DESC_DACL_PROTECTED 0x1000 #define SE_DESC_SACL_PROTECTED 0x2000 +/* Don't know what this means. */ +#define SEC_DESC_RM_CONTROL_VALID 0x4000 + +#define SEC_DESC_SELF_RELATIVE 0x8000 + /* security information */ #define OWNER_SECURITY_INFORMATION 0x00000001 #define GROUP_SECURITY_INFORMATION 0x00000002 #define DACL_SECURITY_INFORMATION 0x00000004 #define SACL_SECURITY_INFORMATION 0x00000008 +/* Extra W2K flags. */ +#define UNPROTECTED_SACL_SECURITY_INFORMATION 0x10000000 +#define UNPROTECTED_DACL_SECURITY_INFORMATION 0x20000000 +#define PROTECTED_SACL_SECURITY_INFORMATION 0x40000000 +#define PROTECTED_DACL_SECURITY_INFORMATION 0x80000000 #define ALL_SECURITY_INFORMATION (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|\ - DACL_SECURITY_INFORMATION|SACL_SECURITY_INFORMATION) + DACL_SECURITY_INFORMATION|SACL_SECURITY_INFORMATION|\ + UNPROTECTED_SACL_SECURITY_INFORMATION|\ + UNPROTECTED_DACL_SECURITY_INFORMATION|\ + PROTECTED_SACL_SECURITY_INFORMATION|\ + PROTECTED_DACL_SECURITY_INFORMATION) /* Globally Unique ID */ #define GUID_SIZE 16 diff --git a/source3/include/rpc_srvsvc.h b/source3/include/rpc_srvsvc.h index 94d23bb4bc..5ebb77a8c2 100644 --- a/source3/include/rpc_srvsvc.h +++ b/source3/include/rpc_srvsvc.h @@ -463,9 +463,15 @@ typedef struct ptr_info_1004_info SH_INFO_1004_STR info_1004_str; } SRV_SHARE_INFO_1004; +#define SHARE_1005_IN_DFS 0x00000001 +#define SHARE_1005_DFS_ROOT 0x00000002 +/* use the CSC policy mask and shift to match up with the smb.conf parm */ +#define SHARE_1005_CSC_POLICY_MASK 0x00000030 +#define SHARE_1005_CSC_POLICY_SHIFT 4 + typedef struct share_info_1005_info { - uint32 dfs_root_flag; + uint32 share_info_flags; } SRV_SHARE_INFO_1005; typedef struct share_info_1006_info diff --git a/source3/include/safe_string.h b/source3/include/safe_string.h index a6b352b02e..6656f4f6bb 100644 --- a/source3/include/safe_string.h +++ b/source3/include/safe_string.h @@ -113,24 +113,24 @@ size_t __unsafe_string_function_usage_here_char__(void); #endif /* HAVE_COMPILER_WILL_OPTIMIZE_OUT_FNS */ -/* the addition of the DEVELOPER checks in safe_strcpy means we must - * update a lot of code. To make this a little easier here are some - * functions that provide the lengths with less pain */ -#define pstrcpy_base(dest, src, pstring_base) \ - safe_strcpy(dest, src, sizeof(pstring)-PTR_DIFF(dest,pstring_base)-1) - #define safe_strcpy_base(dest, src, base, size) \ safe_strcpy(dest, src, size-PTR_DIFF(dest,base)-1) -/* String copy functions - macro hell below adds 'type checking' - (limited, but the best we can do in C) and may tag with function - name/number to record the last 'clobber region' on that string */ +/* String copy functions - macro hell below adds 'type checking' (limited, + but the best we can do in C) and may tag with function name/number to + record the last 'clobber region' on that string */ #define pstrcpy(d,s) safe_strcpy((d), (s),sizeof(pstring)-1) #define pstrcat(d,s) safe_strcat((d), (s),sizeof(pstring)-1) #define fstrcpy(d,s) safe_strcpy((d),(s),sizeof(fstring)-1) #define fstrcat(d,s) safe_strcat((d),(s),sizeof(fstring)-1) +/* the addition of the DEVELOPER checks in safe_strcpy means we must + * update a lot of code. To make this a little easier here are some + * functions that provide the lengths with less pain */ +#define pstrcpy_base(dest, src, pstring_base) \ + safe_strcpy(dest, src, sizeof(pstring)-PTR_DIFF(dest,pstring_base)-1) + /* Inside the _fn variants of these is a call to clobber_region(), - * which might destroy the stack on a buggy function. We help the @@ -209,9 +209,4 @@ size_t __unsafe_string_function_usage_here_char__(void); #endif -/* replace some string functions with multi-byte - versions */ -#define strlower(s) strlower_m(s) -#define strupper(s) strupper_m(s) - #endif diff --git a/source3/include/smb.h b/source3/include/smb.h index 0889abf038..d2714e78bc 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -45,6 +45,7 @@ #define False (0) #define True (1) #define Auto (2) +#define Required (3) #ifndef _BOOL typedef int BOOL; @@ -66,6 +67,7 @@ typedef int BOOL; #define STR_ASCII 4 #define STR_UNICODE 8 #define STR_NOALIGN 16 +#define STR_TERMINATE_ASCII 128 /* how long to wait for secondary SMB packets (milli-seconds) */ #define SMB_SECONDARY_WAIT (60*1000) @@ -155,6 +157,11 @@ typedef int BOOL; #include "doserr.h" +typedef union unid_t { + uid_t uid; + gid_t gid; +} unid_t; + /* * SMB UCS2 (16-bit unicode) internal type. */ @@ -404,9 +411,11 @@ typedef struct files_struct BOOL is_stat; BOOL directory_delete_on_close; char *fsp_name; + FAKE_FILE_HANDLE *fake_file_handle; } files_struct; #include "ntquotas.h" +#include "sysquotas.h" /* used to hold an arbitrary blob of data */ typedef struct data_blob { @@ -442,18 +451,10 @@ typedef struct #include "smb_acls.h" #include "vfs.h" -typedef struct smb_vfs_handle_struct -{ - void *data; - /* Handle on dlopen() call */ - void *handle; - struct smb_vfs_handle_struct *next, *prev; - -} smb_vfs_handle_struct; - typedef struct connection_struct { struct connection_struct *next, *prev; + TALLOC_CTX *mem_ctx; unsigned cnum; /* an index passed over the wire */ int service; BOOL force_user; @@ -468,8 +469,9 @@ typedef struct connection_struct char *connectpath; char *origpath; - struct vfs_ops vfs_ops; /* Filesystem operations */ - struct smb_vfs_handle_struct *vfs_private; + struct vfs_ops vfs; /* Filesystem operations */ + struct vfs_ops vfs_opaque; /* OPAQUE Filesystem operations */ + struct vfs_handle_struct *vfs_handles; /* for the new plugins */ char *user; /* name of user who *opened* this connection */ uid_t uid; /* uid of user who *opened* this connection */ @@ -1617,4 +1619,15 @@ typedef struct { #include "popt_common.h" +#define PORT_NONE 0 +#ifndef LDAP_PORT +#define LDAP_PORT 389 +#endif + +/* used by the IP comparison function */ +struct ip_service { + struct in_addr ip; + unsigned port; +}; + #endif /* _SMB_H */ diff --git a/source3/include/smb_macros.h b/source3/include/smb_macros.h index 8e2cb1c818..21ccdf295c 100644 --- a/source3/include/smb_macros.h +++ b/source3/include/smb_macros.h @@ -77,12 +77,15 @@ #define OPEN_CONN(conn) ((conn) && (conn)->open) #define IS_IPC(conn) ((conn) && (conn)->ipc) #define IS_PRINT(conn) ((conn) && (conn)->printer) -#define FNUM_OK(fsp,c) (OPEN_FSP(fsp) && (c)==(fsp)->conn) +#define FNUM_OK(fsp,c) (OPEN_FSP(fsp) && (c)==(fsp)->conn && current_user.vuid==(fsp)->vuid) -#define CHECK_FSP(fsp,conn) if (!FNUM_OK(fsp,conn)) \ +#define CHECK_FSP(fsp,conn) do {\ + extern struct current_user current_user;\ + if (!FNUM_OK(fsp,conn)) \ return(ERROR_DOS(ERRDOS,ERRbadfid)); \ else if((fsp)->fd == -1) \ - return(ERROR_DOS(ERRDOS,ERRbadaccess)) + return(ERROR_DOS(ERRDOS,ERRbadaccess));\ + } while(0) #define CHECK_READ(fsp) if (!(fsp)->can_read) \ return(ERROR_DOS(ERRDOS,ERRbadaccess)) @@ -199,6 +202,7 @@ true if two IP addresses are equal ****************************************************************************/ #define ip_equal(ip1,ip2) ((ip1).s_addr == (ip2).s_addr) +#define ip_service_equal(ip1,ip2) ( ((ip1).ip.s_addr == (ip2).ip.s_addr) && ((ip1).port == (ip2).port) ) /***************************************************************** splits out the last subkey of a key @@ -244,52 +248,10 @@ copy an IP address from one buffer to another #define dos_format(fname) string_replace(fname,'/','\\') -/******************************************************************* - vfs stat wrapper that calls internal2unix. -********************************************************************/ - -#define vfs_stat(conn, fname, st) ((conn)->vfs_ops.stat((conn), fname,(st))) - -/******************************************************************* - vfs lstat wrapper that calls internal2unix. -********************************************************************/ - -#define vfs_lstat(conn, fname, st) ((conn)->vfs_ops.lstat((conn), fname,(st))) - -/******************************************************************* - vfs fstat wrapper -********************************************************************/ - -#define vfs_fstat(fsp, fd, st) ((fsp)->conn->vfs_ops.fstat((fsp),(fd),(st))) - -/******************************************************************* - vfs rmdir wrapper that calls internal2unix. -********************************************************************/ - -#define vfs_rmdir(conn,fname) ((conn)->vfs_ops.rmdir((conn),fname)) - -/******************************************************************* - vfs Unlink wrapper that calls internal2unix. -********************************************************************/ - -#define vfs_unlink(conn, fname) ((conn)->vfs_ops.unlink((conn),fname)) - -/******************************************************************* - vfs chmod wrapper that calls internal2unix. -********************************************************************/ - -#define vfs_chmod(conn,fname,mode) ((conn)->vfs_ops.chmod((conn),fname,(mode))) - -/******************************************************************* - vfs chown wrapper that calls internal2unix. -********************************************************************/ - -#define vfs_chown(conn,fname,uid,gid) ((conn)->vfs_ops.chown((conn),fname,(uid),(gid))) - -/******************************************************************* - A wrapper for vfs_chdir(). -********************************************************************/ +/***************************************************************************** + Check to see if we are a DO for this domain +*****************************************************************************/ -#define vfs_chdir(conn,fname) ((conn)->vfs_ops.chdir((conn),fname)) +#define IS_DC (lp_server_role()==ROLE_DOMAIN_PDC || lp_server_role()==ROLE_DOMAIN_BDC) #endif /* _SMB_MACROS_H */ diff --git a/source3/include/smbprofile.h b/source3/include/smbprofile.h index e501de8c0e..a64c2ce69e 100644 --- a/source3/include/smbprofile.h +++ b/source3/include/smbprofile.h @@ -108,6 +108,10 @@ struct profile_stats { unsigned syscall_mknod_time; unsigned syscall_realpath_count; unsigned syscall_realpath_time; + unsigned syscall_get_quota_count; + unsigned syscall_get_quota_time; + unsigned syscall_set_quota_count; + unsigned syscall_set_quota_time; /* stat cache counters */ unsigned statcache_lookups; unsigned statcache_misses; @@ -326,6 +330,10 @@ struct profile_stats { unsigned NT_transact_rename_time; unsigned NT_transact_query_security_desc_count; unsigned NT_transact_query_security_desc_time; + unsigned NT_transact_get_user_quota_count; + unsigned NT_transact_get_user_quota_time; + unsigned NT_transact_set_user_quota_count; + unsigned NT_transact_set_user_quota_time; /* These are ACL manipulation calls */ unsigned get_nt_acl_count; unsigned get_nt_acl_time; diff --git a/source3/include/trans2.h b/source3/include/trans2.h index 2ccf83478b..eb5b1bc79f 100644 --- a/source3/include/trans2.h +++ b/source3/include/trans2.h @@ -224,6 +224,7 @@ Byte offset Type name description #define SMB_QUERY_FILE_ALL_INFO 0x107 #define SMB_QUERY_FILE_ALT_NAME_INFO 0x108 #define SMB_QUERY_FILE_STREAM_INFO 0x109 +#define SMB_QUERY_COMPRESSION_INFO 0x10b #define SMB_FIND_FILE_DIRECTORY_INFO 0x101 #define SMB_FIND_FILE_FULL_DIRECTORY_INFO 0x102 diff --git a/source3/include/version.h b/source3/include/version.h index c0a1c702f2..5e2d47e1de 100644 --- a/source3/include/version.h +++ b/source3/include/version.h @@ -1 +1 @@ -#define VERSION "post3.0-HEAD" +#define VERSION "3.0.0beta3" diff --git a/source3/include/vfs.h b/source3/include/vfs.h index 756e417814..924d706321 100644 --- a/source3/include/vfs.h +++ b/source3/include/vfs.h @@ -1,8 +1,10 @@ /* Unix SMB/CIFS implementation. VFS structures and parameters + Copyright (C) Jeremy Allison 1999-2003 Copyright (C) Tim Potter 1999 Copyright (C) Alexander Bokovoy 2002 + Copyright (C) Stefan (metze) Metzmacher 2003 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -45,150 +47,41 @@ /* 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 +/* Changed to version 6 for the new module system, fixed cascading and quota functions. --metze */ +/* Changed to version 7 to include the get_nt_acl info parameter. JRA. */ +/* Changed to version 8 includes EA calls. JRA. */ +#define SMB_VFS_INTERFACE_VERSION 8 -/* Version of supported cascaded interface backward compatibility. - (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 5 + +/* to bug old modules witch are trying to compile with the old functions */ +#define vfs_init __ERROR_please_port_this_module_to_SMB_VFS_INTERFACE_VERSION_8_donot_use_vfs_init_anymore(void) { __ERROR_please_port_this_module_to_SMB_VFS_INTERFACE_VERSION_8_donot_use_vfs_init_anymore }; +#define lp_parm_string __ERROR_please_port_lp_parm_string_to_lp_parm_const_string_or_lp_parm_talloc_string { \ + __ERROR_please_port_lp_parm_string_to_lp_parm_const_string_or_lp_parm_talloc_string }; +#define lp_vfs_options __ERROR_please_donot_use_lp_vfs_options_anymore_use_lp_parm_xxxx_functions_instead { \ + __ERROR_please_donot_use_lp_vfs_options_anymore_use_lp_parm_xxxx_functions_instead }; /* - Each VFS module must provide following global functions: - vfs_init -- initialization function - vfs_done -- finalization function - - vfs_init must return proper initialized vfs_op_tuple[] array - which describes all operations this module claims to intercept. This function - is called whenever module is loaded into smbd process using sys_dlopen(). - - vfs_init must store somewhere vfs_handle reference if module wants to store per-instance - private information for further usage. vfs_handle->data should be used to - store such information. Do not try to change other fields in this structure - or results likely to be unpredictable. - - vfs_done must perform finalization of the module. In particular, - this function must free vfs_ops structure returned to module from smb_vfs_get_opaque_ops() - function if it is used (see below). This function is called whenever module - is unloaded from smbd process using sys_dlclose(). - - Prototypes: - vfs_op_tuple *vfs_init(const struct vfs_ops *def_vfs_ops, - struct smb_vfs_handle_struct *vfs_handle); - void vfs_done(connection_struct *conn); - All intercepted VFS operations must be declared as static functions inside module source - in order to keep smbd namespace unpolluted. See source of skel, audit, and recycle bin + in order to keep smbd namespace unpolluted. See source of audit, extd_audit, fake_perms and recycle example VFS modules for more details. - */ /* VFS operations structure */ +struct vfs_handle_struct; struct connection_struct; struct files_struct; struct security_descriptor_info; -struct vfs_ops { - - /* Disk operations */ - - int (*connect)(struct connection_struct *conn, const char *service, const char *user); - void (*disconnect)(struct connection_struct *conn); - SMB_BIG_UINT (*disk_free)(struct connection_struct *conn, const char *path, BOOL small_query, SMB_BIG_UINT *bsize, - SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize); - - /* Directory operations */ - - DIR *(*opendir)(struct connection_struct *conn, const char *fname); - struct dirent *(*readdir)(struct connection_struct *conn, DIR *dirp); - int (*mkdir)(struct connection_struct *conn, const char *path, mode_t mode); - int (*rmdir)(struct connection_struct *conn, const char *path); - int (*closedir)(struct connection_struct *conn, DIR *dir); - - /* File operations */ - - int (*open)(struct connection_struct *conn, const char *fname, int flags, mode_t mode); - int (*close)(struct files_struct *fsp, int fd); - 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); - int (*fstat)(struct files_struct *fsp, int fd, SMB_STRUCT_STAT *sbuf); - int (*lstat)(struct connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbuf); - int (*unlink)(struct connection_struct *conn, const char *path); - int (*chmod)(struct connection_struct *conn, const char *path, mode_t mode); - int (*fchmod)(struct files_struct *fsp, int fd, mode_t mode); - int (*chown)(struct connection_struct *conn, const char *path, uid_t uid, gid_t gid); - int (*fchown)(struct files_struct *fsp, int fd, uid_t uid, gid_t gid); - int (*chdir)(struct connection_struct *conn, const char *path); - char *(*getwd)(struct connection_struct *conn, char *buf); - int (*utime)(struct connection_struct *conn, const char *path, struct utimbuf *times); - int (*ftruncate)(struct files_struct *fsp, int fd, SMB_OFF_T offset); - BOOL (*lock)(struct files_struct *fsp, int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type); - int (*symlink)(struct connection_struct *conn, const char *oldpath, const char *newpath); - int (*readlink)(struct connection_struct *conn, const char *path, char *buf, size_t bufsiz); - int (*link)(struct connection_struct *conn, const char *oldpath, const char *newpath); - int (*mknod)(struct connection_struct *conn, const char *path, mode_t mode, SMB_DEV_T dev); - char *(*realpath)(struct connection_struct *conn, const char *path, char *resolved_path); - - /* NT ACL operations. */ - - size_t (*fget_nt_acl)(struct files_struct *fsp, int fd, struct security_descriptor_info **ppdesc); - size_t (*get_nt_acl)(struct files_struct *fsp, const char *name, struct security_descriptor_info **ppdesc); - BOOL (*fset_nt_acl)(struct files_struct *fsp, int fd, uint32 security_info_sent, struct security_descriptor_info *psd); - BOOL (*set_nt_acl)(struct files_struct *fsp, const char *name, uint32 security_info_sent, struct security_descriptor_info *psd); - - /* POSIX ACL operations. */ - - int (*chmod_acl)(struct connection_struct *conn, const char *name, mode_t mode); - int (*fchmod_acl)(struct files_struct *fsp, int fd, mode_t mode); - - int (*sys_acl_get_entry)(struct connection_struct *conn, SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p); - int (*sys_acl_get_tag_type)(struct connection_struct *conn, SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p); - int (*sys_acl_get_permset)(struct connection_struct *conn, SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p); - void * (*sys_acl_get_qualifier)(struct connection_struct *conn, SMB_ACL_ENTRY_T entry_d); - SMB_ACL_T (*sys_acl_get_file)(struct connection_struct *conn, const char *path_p, SMB_ACL_TYPE_T type); - SMB_ACL_T (*sys_acl_get_fd)(struct files_struct *fsp, int fd); - int (*sys_acl_clear_perms)(struct connection_struct *conn, SMB_ACL_PERMSET_T permset); - int (*sys_acl_add_perm)(struct connection_struct *conn, SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm); - char * (*sys_acl_to_text)(struct connection_struct *conn, SMB_ACL_T theacl, ssize_t *plen); - SMB_ACL_T (*sys_acl_init)(struct connection_struct *conn, int count); - int (*sys_acl_create_entry)(struct connection_struct *conn, SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry); - int (*sys_acl_set_tag_type)(struct connection_struct *conn, SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype); - int (*sys_acl_set_qualifier)(struct connection_struct *conn, SMB_ACL_ENTRY_T entry, void *qual); - int (*sys_acl_set_permset)(struct connection_struct *conn, SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset); - int (*sys_acl_valid)(struct connection_struct *conn, SMB_ACL_T theacl ); - int (*sys_acl_set_file)(struct connection_struct *conn, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl); - int (*sys_acl_set_fd)(struct files_struct *fsp, int fd, SMB_ACL_T theacl); - int (*sys_acl_delete_def_file)(struct connection_struct *conn, const char *path); - int (*sys_acl_get_perm)(struct connection_struct *conn, SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm); - int (*sys_acl_free_text)(struct connection_struct *conn, char *text); - int (*sys_acl_free_acl)(struct connection_struct *conn, SMB_ACL_T posix_acl); - int (*sys_acl_free_qualifier)(struct connection_struct *conn, void *qualifier, SMB_ACL_TAG_T tagtype); -}; - -struct vfs_options { - struct vfs_options *prev, *next; - char *name; - char *value; -}; - /* - Available VFS operations. These values must be in sync with vfs_ops struct. + Available VFS operations. These values must be in sync with vfs_ops struct + (struct vfs_fn_pointers and struct vfs_handle_pointers inside of struct vfs_ops). In particular, if new operations are added to vfs_ops, appropriate constants should be added to vfs_op_type so that order of them kept same as in vfs_ops. */ typedef enum _vfs_op_type { - SMB_VFS_OP_NOOP = -1, /* Disk operations */ @@ -196,6 +89,8 @@ typedef enum _vfs_op_type { SMB_VFS_OP_CONNECT = 0, SMB_VFS_OP_DISCONNECT, SMB_VFS_OP_DISK_FREE, + SMB_VFS_OP_GET_QUOTA, + SMB_VFS_OP_SET_QUOTA, /* Directory operations */ @@ -269,11 +164,224 @@ typedef enum _vfs_op_type { SMB_VFS_OP_SYS_ACL_FREE_ACL, SMB_VFS_OP_SYS_ACL_FREE_QUALIFIER, + /* EA operations. */ + SMB_VFS_OP_GETXATTR, + SMB_VFS_OP_LGETXATTR, + SMB_VFS_OP_FGETXATTR, + SMB_VFS_OP_LISTXATTR, + SMB_VFS_OP_LLISTXATTR, + SMB_VFS_OP_FLISTXATTR, + SMB_VFS_OP_REMOVEXATTR, + SMB_VFS_OP_LREMOVEXATTR, + SMB_VFS_OP_FREMOVEXATTR, + SMB_VFS_OP_SETXATTR, + SMB_VFS_OP_LSETXATTR, + SMB_VFS_OP_FSETXATTR, + /* This should always be last enum value */ SMB_VFS_OP_LAST } vfs_op_type; +/* + Please keep vfs_op_type, struct vfs_fn_pointers and struct vfs_handles_pointers in sync. +*/ +struct vfs_ops { + struct vfs_fn_pointers { + /* Disk operations */ + + int (*connect)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *service, const char *user); + void (*disconnect)(struct vfs_handle_struct *handle, struct connection_struct *conn); + SMB_BIG_UINT (*disk_free)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path, BOOL small_query, SMB_BIG_UINT *bsize, + SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize); + int (*get_quota)(struct vfs_handle_struct *handle, struct connection_struct *conn, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt); + int (*set_quota)(struct vfs_handle_struct *handle, struct connection_struct *conn, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt); + + /* Directory operations */ + + DIR *(*opendir)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *fname); + struct dirent *(*readdir)(struct vfs_handle_struct *handle, struct connection_struct *conn, DIR *dirp); + int (*mkdir)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path, mode_t mode); + int (*rmdir)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path); + int (*closedir)(struct vfs_handle_struct *handle, struct connection_struct *conn, DIR *dir); + + /* File operations */ + + int (*open)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *fname, int flags, mode_t mode); + int (*close)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd); + ssize_t (*read)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, void *data, size_t n); + ssize_t (*write)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, const void *data, size_t n); + SMB_OFF_T (*lseek)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, SMB_OFF_T offset, int whence); + ssize_t (*sendfile)(struct vfs_handle_struct *handle, int tofd, files_struct *fsp, int fromfd, const DATA_BLOB *header, SMB_OFF_T offset, size_t count); + int (*rename)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *old, const char *new); + int (*fsync)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd); + int (*stat)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *fname, SMB_STRUCT_STAT *sbuf); + int (*fstat)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, SMB_STRUCT_STAT *sbuf); + int (*lstat)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbuf); + int (*unlink)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path); + int (*chmod)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path, mode_t mode); + int (*fchmod)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, mode_t mode); + int (*chown)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path, uid_t uid, gid_t gid); + int (*fchown)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, uid_t uid, gid_t gid); + int (*chdir)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path); + char *(*getwd)(struct vfs_handle_struct *handle, struct connection_struct *conn, char *buf); + int (*utime)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path, struct utimbuf *times); + int (*ftruncate)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, SMB_OFF_T offset); + BOOL (*lock)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type); + int (*symlink)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *oldpath, const char *newpath); + int (*readlink)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path, char *buf, size_t bufsiz); + int (*link)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *oldpath, const char *newpath); + int (*mknod)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path, mode_t mode, SMB_DEV_T dev); + char *(*realpath)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path, char *resolved_path); + + /* NT ACL operations. */ + + size_t (*fget_nt_acl)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, uint32 security_info, struct security_descriptor_info **ppdesc); + size_t (*get_nt_acl)(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, uint32 security_info, struct security_descriptor_info **ppdesc); + BOOL (*fset_nt_acl)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, uint32 security_info_sent, struct security_descriptor_info *psd); + BOOL (*set_nt_acl)(struct vfs_handle_struct *handle, struct files_struct *fsp, const char *name, uint32 security_info_sent, struct security_descriptor_info *psd); + + /* POSIX ACL operations. */ + + int (*chmod_acl)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *name, mode_t mode); + int (*fchmod_acl)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, mode_t mode); + + int (*sys_acl_get_entry)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p); + int (*sys_acl_get_tag_type)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p); + int (*sys_acl_get_permset)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p); + void * (*sys_acl_get_qualifier)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_ACL_ENTRY_T entry_d); + SMB_ACL_T (*sys_acl_get_file)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path_p, SMB_ACL_TYPE_T type); + SMB_ACL_T (*sys_acl_get_fd)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd); + int (*sys_acl_clear_perms)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_ACL_PERMSET_T permset); + int (*sys_acl_add_perm)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm); + char * (*sys_acl_to_text)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_ACL_T theacl, ssize_t *plen); + SMB_ACL_T (*sys_acl_init)(struct vfs_handle_struct *handle, struct connection_struct *conn, int count); + int (*sys_acl_create_entry)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry); + int (*sys_acl_set_tag_type)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype); + int (*sys_acl_set_qualifier)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_ACL_ENTRY_T entry, void *qual); + int (*sys_acl_set_permset)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset); + int (*sys_acl_valid)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_ACL_T theacl ); + int (*sys_acl_set_file)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl); + int (*sys_acl_set_fd)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, SMB_ACL_T theacl); + int (*sys_acl_delete_def_file)(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path); + int (*sys_acl_get_perm)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm); + int (*sys_acl_free_text)(struct vfs_handle_struct *handle, struct connection_struct *conn, char *text); + int (*sys_acl_free_acl)(struct vfs_handle_struct *handle, struct connection_struct *conn, SMB_ACL_T posix_acl); + int (*sys_acl_free_qualifier)(struct vfs_handle_struct *handle, struct connection_struct *conn, void *qualifier, SMB_ACL_TAG_T tagtype); + + /* EA operations. */ + ssize_t (*getxattr)(struct vfs_handle_struct *handle,struct connection_struct *conn,const char *path, const char *name, void *value, size_t size); + ssize_t (*lgetxattr)(struct vfs_handle_struct *handle,struct connection_struct *conn,const char *path, const char *name, void *value, size_t size); + ssize_t (*fgetxattr)(struct vfs_handle_struct *handle, struct files_struct *fsp,int fd, const char *name, void *value, size_t size); + ssize_t (*listxattr)(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, char *list, size_t size); + ssize_t (*llistxattr)(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, char *list, size_t size); + ssize_t (*flistxattr)(struct vfs_handle_struct *handle, struct files_struct *fsp,int fd, char *list, size_t size); + int (*removexattr)(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name); + int (*lremovexattr)(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name); + int (*fremovexattr)(struct vfs_handle_struct *handle, struct files_struct *fsp,int filedes, const char *name); + int (*setxattr)(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name, const void *value, size_t size, int flags); + int (*lsetxattr)(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name, const void *value, size_t size, int flags); + int (*fsetxattr)(struct vfs_handle_struct *handle, struct files_struct *fsp,int filedes, const char *name, const void *value, size_t size, int flags); + + } ops; + + struct vfs_handles_pointers { + /* Disk operations */ + + struct vfs_handle_struct *connect; + struct vfs_handle_struct *disconnect; + struct vfs_handle_struct *disk_free; + struct vfs_handle_struct *get_quota; + struct vfs_handle_struct *set_quota; + + /* Directory operations */ + + struct vfs_handle_struct *opendir; + struct vfs_handle_struct *readdir; + struct vfs_handle_struct *mkdir; + struct vfs_handle_struct *rmdir; + struct vfs_handle_struct *closedir; + + /* File operations */ + + struct vfs_handle_struct *open; + struct vfs_handle_struct *close; + struct vfs_handle_struct *read; + struct vfs_handle_struct *write; + struct vfs_handle_struct *lseek; + struct vfs_handle_struct *sendfile; + struct vfs_handle_struct *rename; + struct vfs_handle_struct *fsync; + struct vfs_handle_struct *stat; + struct vfs_handle_struct *fstat; + struct vfs_handle_struct *lstat; + struct vfs_handle_struct *unlink; + struct vfs_handle_struct *chmod; + struct vfs_handle_struct *fchmod; + struct vfs_handle_struct *chown; + struct vfs_handle_struct *fchown; + struct vfs_handle_struct *chdir; + struct vfs_handle_struct *getwd; + struct vfs_handle_struct *utime; + struct vfs_handle_struct *ftruncate; + struct vfs_handle_struct *lock; + struct vfs_handle_struct *symlink; + struct vfs_handle_struct *readlink; + struct vfs_handle_struct *link; + struct vfs_handle_struct *mknod; + struct vfs_handle_struct *realpath; + + /* NT ACL operations. */ + + struct vfs_handle_struct *fget_nt_acl; + struct vfs_handle_struct *get_nt_acl; + struct vfs_handle_struct *fset_nt_acl; + struct vfs_handle_struct *set_nt_acl; + + /* POSIX ACL operations. */ + + struct vfs_handle_struct *chmod_acl; + struct vfs_handle_struct *fchmod_acl; + + struct vfs_handle_struct *sys_acl_get_entry; + struct vfs_handle_struct *sys_acl_get_tag_type; + struct vfs_handle_struct *sys_acl_get_permset; + struct vfs_handle_struct *sys_acl_get_qualifier; + struct vfs_handle_struct *sys_acl_get_file; + struct vfs_handle_struct *sys_acl_get_fd; + struct vfs_handle_struct *sys_acl_clear_perms; + struct vfs_handle_struct *sys_acl_add_perm; + struct vfs_handle_struct *sys_acl_to_text; + struct vfs_handle_struct *sys_acl_init; + struct vfs_handle_struct *sys_acl_create_entry; + struct vfs_handle_struct *sys_acl_set_tag_type; + struct vfs_handle_struct *sys_acl_set_qualifier; + struct vfs_handle_struct *sys_acl_set_permset; + struct vfs_handle_struct *sys_acl_valid; + struct vfs_handle_struct *sys_acl_set_file; + struct vfs_handle_struct *sys_acl_set_fd; + struct vfs_handle_struct *sys_acl_delete_def_file; + struct vfs_handle_struct *sys_acl_get_perm; + struct vfs_handle_struct *sys_acl_free_text; + struct vfs_handle_struct *sys_acl_free_acl; + struct vfs_handle_struct *sys_acl_free_qualifier; + + /* EA operations. */ + struct vfs_handle_struct *getxattr; + struct vfs_handle_struct *lgetxattr; + struct vfs_handle_struct *fgetxattr; + struct vfs_handle_struct *listxattr; + struct vfs_handle_struct *llistxattr; + struct vfs_handle_struct *flistxattr; + struct vfs_handle_struct *removexattr; + struct vfs_handle_struct *lremovexattr; + struct vfs_handle_struct *fremovexattr; + struct vfs_handle_struct *setxattr; + struct vfs_handle_struct *lsetxattr; + struct vfs_handle_struct *fsetxattr; + } handles; +}; + /* Possible VFS operation layers (per-operation) @@ -300,7 +408,7 @@ typedef enum _vfs_op_layer { SMB_VFS_LAYER_OPAQUE = 0, /* - Final level, does not call anything beyond itself */ SMB_VFS_LAYER_TRANSPARENT, /* - Normal operation, calls underlying layer after */ /* possibly changing passed data */ - SMB_VFS_LAYER_LOGGER, /* - Logs data, calls underlying layer, logging does not */ + SMB_VFS_LAYER_LOGGER, /* - Logs data, calls underlying layer, logging may not */ /* use Samba VFS */ SMB_VFS_LAYER_SPLITTER, /* - Splits operation, calls underlying layer _and_ own facility, */ /* then combines result */ @@ -309,10 +417,10 @@ typedef enum _vfs_op_layer { } vfs_op_layer; /* - VFS operation description. Each VFS module initialization function returns to VFS subsystem - an array of vfs_op_tuple which describes all operations this module is willing to intercept. - VFS subsystem initializes then vfs_ops using this information and passes it - to next VFS module as underlying vfs_ops and to connection after all VFS modules are initialized. + VFS operation description. Each VFS module registers an array of vfs_op_tuple to VFS subsystem, + which describes all operations this module is willing to intercept. + VFS subsystem initializes then the conn->vfs_ops and conn->vfs_opaque_ops structs + using this information. */ typedef struct _vfs_op_tuple { @@ -321,18 +429,46 @@ typedef struct _vfs_op_tuple { vfs_op_layer layer; } vfs_op_tuple; -/* - Return vfs_ops filled with current opaque VFS operations. This function is designed to - be called from VFS module initialization function for those modules which needs 'direct' VFS - access (loggers or initiators of file operations other than connection asks for). - - Returned vfs_ops must be cleaned up in VFS module's finalizer function (vfs_done_) - using safe_free(). - - Prototype: - struct vfs_ops *smb_vfs_get_opaque_ops(); - - This prototype will be available via include/proto.h -*/ + +typedef struct vfs_handle_struct { + struct vfs_handle_struct *next, *prev; + const char *param; + struct vfs_ops vfs_next; + struct connection_struct *conn; + void *data; + void (*free_data)(void **data); +} vfs_handle_struct; + + +#define SMB_VFS_HANDLE_GET_DATA(handle, datap, type, ret) { \ + if (!(handle)||((datap=(type *)(handle)->data)==NULL)) { \ + DEBUG(0,("%s() failed to get vfs_handle->data!\n",FUNCTION_MACRO)); \ + ret; \ + } \ +} + +#define SMB_VFS_HANDLE_SET_DATA(handle, datap, free_fn, type, ret) { \ + if (!(handle)) { \ + DEBUG(0,("%s() failed to set handle->data!\n",FUNCTION_MACRO)); \ + ret; \ + } else { \ + if ((handle)->free_data) { \ + (handle)->free_data(&(handle)->data); \ + } \ + (handle)->data = (void *)datap; \ + (handle)->free_data = free_fn; \ + } \ +} + +#define SMB_VFS_HANDLE_FREE_DATA(handle) { \ + if ((handle) && (handle)->free_data) { \ + (handle)->free_data(&(handle)->data); \ + } \ +} + +#define SMB_VFS_OP(x) ((void *) x) + + +#include "vfs_macros.h" #endif /* _VFS_H */ diff --git a/source3/lib/charcnv.c b/source3/lib/charcnv.c index eb427cc0fc..4e9c2c1592 100644 --- a/source3/lib/charcnv.c +++ b/source3/lib/charcnv.c @@ -55,6 +55,30 @@ static const char *charset_name(charset_t ch) else if (ch == CH_DISPLAY) ret = lp_display_charset(); else if (ch == CH_UTF8) ret = "UTF8"; +#if defined(HAVE_NL_LANGINFO) && defined(CODESET) + if (ret && strcasecmp(ret, "LOCALE") == 0) { + const char *ln = NULL; + +#ifdef HAVE_SETLOCALE + setlocale(LC_ALL, ""); +#endif + ln = nl_langinfo(CODESET); + if (ln) { + /* Check whether the charset name is supported + by iconv */ + smb_iconv_t handle = smb_iconv_open(ln,"UCS-2LE"); + if (handle == (smb_iconv_t) -1) { + DEBUG(5,("Locale charset '%s' unsupported, using ASCII instead\n", ln)); + ln = NULL; + } else { + DEBUG(5,("Substituting charset '%s' for LOCALE\n", ln)); + smb_iconv_close(handle); + } + } + ret = ln; + } +#endif + if (!ret || !*ret) ret = "ASCII"; return ret; } @@ -363,11 +387,11 @@ size_t push_ascii(void *dest, const char *src, size_t dest_len, int flags) if (flags & STR_UPPER) { pstrcpy(tmpbuf, src); - strupper(tmpbuf); + strupper_m(tmpbuf); src = tmpbuf; } - if (flags & STR_TERMINATE) + if (flags & (STR_TERMINATE | STR_TERMINATE_ASCII)) src_len++; return convert_string(CH_UNIX, CH_DOS, src, src_len, dest, dest_len); @@ -464,7 +488,7 @@ size_t push_ucs2(const void *base_ptr, void *dest, const char *src, size_t dest_ if (flags & STR_UPPER) { pstrcpy(tmpbuf, src); - strupper(tmpbuf); + strupper_m(tmpbuf); src = tmpbuf; } @@ -542,7 +566,7 @@ static size_t push_utf8(void *dest, const char *src, size_t dest_len, int flags) if (flags & STR_UPPER) { pstrcpy(tmpbuf, src); - strupper(tmpbuf); + strupper_m(tmpbuf); src = tmpbuf; } @@ -723,8 +747,21 @@ size_t pull_utf8_allocate(void **dest, const char *src) size_t push_string_fn(const char *function, unsigned int line, const void *base_ptr, void *dest, const char *src, size_t dest_len, int flags) { +#ifdef DEVELOPER + /* We really need to zero fill here, not clobber + * region, as we want to ensure that valgrind thinks + * all of the outgoing buffer has been written to + * so a send() or write() won't trap an error. + * JRA. + */ +#if 0 if (dest_len != (size_t)-1) clobber_region(function, line, dest, dest_len); +#else + if (dest_len != (size_t)-1) + memset(dest, '\0', dest_len); +#endif +#endif if (!(flags & STR_ASCII) && \ ((flags & STR_UNICODE || \ diff --git a/source3/lib/gencache.c b/source3/lib/gencache.c index 40b4d1390d..f3740e3e12 100644 --- a/source3/lib/gencache.c +++ b/source3/lib/gencache.c @@ -319,9 +319,8 @@ void gencache_iterate(void (*fn)(const char* key, const char *value, time_t time while (node) { /* ensure null termination of the key string */ - node->node_key.dptr[node->node_key.dsize] = '\0'; - keystr = node->node_key.dptr; - + keystr = strndup(node->node_key.dptr, node->node_key.dsize); + /* * We don't use gencache_get function, because we need to iterate through * all of the entries. Validity verification is up to fn routine. @@ -329,6 +328,8 @@ void gencache_iterate(void (*fn)(const char* key, const char *value, time_t time databuf = tdb_fetch(cache, node->node_key); if (!databuf.dptr || databuf.dsize <= TIMEOUT_LEN) { SAFE_FREE(databuf.dptr); + SAFE_FREE(keystr); + node = node->next; continue; } entry = strndup(databuf.dptr, databuf.dsize); @@ -342,8 +343,30 @@ void gencache_iterate(void (*fn)(const char* key, const char *value, time_t time SAFE_FREE(valstr); SAFE_FREE(entry); + SAFE_FREE(keystr); node = node->next; } tdb_search_list_free(first_node); } + +/******************************************************************** + lock a key +********************************************************************/ + +int gencache_lock_entry( const char *key ) +{ + return tdb_lock_bystring(cache, key, 0); +} + +/******************************************************************** + unlock a key +********************************************************************/ + +void gencache_unlock_entry( const char *key ) +{ + tdb_unlock_bystring(cache, key); + return; +} + + diff --git a/source3/lib/module.c b/source3/lib/module.c index 4437d085f9..ac4fe57a2c 100644 --- a/source3/lib/module.c +++ b/source3/lib/module.c @@ -130,29 +130,6 @@ void init_modules(void) } -/************************************************************************* - * This functions /path/to/foobar.so -> foobar - ************************************************************************/ -void module_path_get_name(const char *path, pstring name) -{ - char *s; - - /* First, make the path relative */ - s = strrchr(path, '/'); - if(s) pstrcpy(name, s+1); - else pstrcpy(name, path); - - if (dyn_SHLIBEXT && *dyn_SHLIBEXT && strlen(dyn_SHLIBEXT) < strlen(name)) { - int n = strlen(name) - strlen(dyn_SHLIBEXT); - - /* Remove extension if necessary */ - if (name[n-1] == '.' && !strcmp(name+n, dyn_SHLIBEXT)) { - name[n-1] = '\0'; - } - } -} - - /*************************************************************************** * This Function registers a idle event * diff --git a/source3/lib/popt_common.c b/source3/lib/popt_common.c index 6920ef4d5f..b8e77b2d9e 100644 --- a/source3/lib/popt_common.c +++ b/source3/lib/popt_common.c @@ -335,8 +335,8 @@ static void popt_common_credentials_callback(poptContext con, struct poptOption popt_common_credentials[] = { { NULL, 0, POPT_ARG_CALLBACK|POPT_CBFLAG_PRE, popt_common_credentials_callback }, { "user", 'U', POPT_ARG_STRING, NULL, 'U', "Set the network username", "USERNAME" }, - { "no-pass", 'N', POPT_ARG_NONE, &cmdline_auth_info.got_pass, True, "Don't ask for a password" }, - { "kerberos", 'k', POPT_ARG_NONE, &cmdline_auth_info.use_kerberos, True, "Use kerberos (active directory) authentication" }, + { "no-pass", 'N', POPT_ARG_NONE, &cmdline_auth_info.got_pass, 0, "Don't ask for a password" }, + { "kerberos", 'k', POPT_ARG_NONE, &cmdline_auth_info.use_kerberos, 'k', "Use kerberos (active directory) authentication" }, { "authentication-file", 'A', POPT_ARG_STRING, NULL, 'A', "Get the credentials from a file", "FILE" }, POPT_TABLEEND }; diff --git a/source3/lib/substitute.c b/source3/lib/substitute.c index 7ba8648156..ac2cf687c4 100644 --- a/source3/lib/substitute.c +++ b/source3/lib/substitute.c @@ -58,7 +58,7 @@ void set_local_machine_name(const char* local_name, BOOL perm) fstrcpy(tmp_local_machine,local_name); trim_string(tmp_local_machine," "," "); - strlower(tmp_local_machine); + strlower_m(tmp_local_machine); alpha_strcpy(local_machine,tmp_local_machine,SAFE_NETBIOS_CHARS,sizeof(local_machine)-1); } @@ -80,7 +80,7 @@ void set_remote_machine_name(const char* remote_name, BOOL perm) fstrcpy(tmp_remote_machine,remote_name); trim_string(tmp_remote_machine," "," "); - strlower(tmp_remote_machine); + strlower_m(tmp_remote_machine); alpha_strcpy(remote_machine,tmp_remote_machine,SAFE_NETBIOS_CHARS,sizeof(remote_machine)-1); } @@ -111,7 +111,7 @@ void sub_set_smb_name(const char *name) fstrcpy(tmp,name); trim_string(tmp," "," "); - strlower(tmp); + strlower_m(tmp); alpha_strcpy(smb_user_name,tmp,SAFE_NETBIOS_CHARS,sizeof(smb_user_name)-1); } @@ -331,7 +331,7 @@ void standard_sub_basic(const char *smb_name, char *str,size_t len) switch (*(p+1)) { case 'U' : fstrcpy(tmp_str, smb_name); - strlower(tmp_str); + strlower_m(tmp_str); string_sub(p,"%U",tmp_str,l); break; case 'G' : @@ -344,7 +344,7 @@ void standard_sub_basic(const char *smb_name, char *str,size_t len) break; case 'D' : fstrcpy(tmp_str, current_user_info.domain); - strupper(tmp_str); + strupper_m(tmp_str); string_sub(p,"%D", tmp_str,l); break; case 'I' : @@ -357,7 +357,7 @@ void standard_sub_basic(const char *smb_name, char *str,size_t len) pstring temp_name; pstrcpy(temp_name, global_myname()); - strlower(temp_name); + strlower_m(temp_name); string_sub(p,"%L", temp_name,l); } break; @@ -650,7 +650,7 @@ char *talloc_sub_advanced(TALLOC_CTX *mem_ctx, const char *connectpath, gid_t gid, const char *smb_name, - char *str) + const char *str) { char *a, *t; a = alloc_sub_advanced(snum, user, connectpath, gid, smb_name, str); @@ -662,7 +662,7 @@ char *talloc_sub_advanced(TALLOC_CTX *mem_ctx, char *alloc_sub_advanced(int snum, const char *user, const char *connectpath, gid_t gid, - const char *smb_name, char *str) + const char *smb_name, const char *str) { char *a_string, *ret_string; char *b, *p, *s, *t, *h; @@ -736,14 +736,14 @@ void standard_sub_conn(connection_struct *conn, char *str, size_t len) conn->gid, smb_user_name, str, len); } -char *talloc_sub_conn(TALLOC_CTX *mem_ctx, connection_struct *conn, char *str) +char *talloc_sub_conn(TALLOC_CTX *mem_ctx, connection_struct *conn, const char *str) { return talloc_sub_advanced(mem_ctx, SNUM(conn), conn->user, conn->connectpath, conn->gid, smb_user_name, str); } -char *alloc_sub_conn(connection_struct *conn, char *str) +char *alloc_sub_conn(connection_struct *conn, const char *str) { return alloc_sub_advanced(SNUM(conn), conn->user, conn->connectpath, conn->gid, smb_user_name, str); diff --git a/source3/lib/system.c b/source3/lib/system.c index 6ff97b88da..a7024c852d 100644 --- a/source3/lib/system.c +++ b/source3/lib/system.c @@ -1253,3 +1253,128 @@ int sys_dup2(int oldfd, int newfd) #endif SAFE_FREE(msgbuf); } + +/************************************************************************** + Wrappers for extented attribute calls. Based on the Linux package with + support for IRIX also. Expand as other systems have them. +****************************************************************************/ + +ssize_t sys_getxattr (const char *path, const char *name, void *value, size_t size) +{ +#if defined(HAVE_GETXATTR) + return getxattr(path, name, value, size); +#else + errno = ENOSYS; + return -1; +#endif +} + +ssize_t sys_lgetxattr (const char *path, const char *name, void *value, size_t size) +{ +#if defined(HAVE_LGETXATTR) + return lgetxattr(path, name, value, size); +#else + errno = ENOSYS; + return -1; +#endif +} + +ssize_t sys_fgetxattr (int filedes, const char *name, void *value, size_t size) +{ +#if defined(HAVE_FGETXATTR) + return fgetxattr(filedes, name, value, size); +#else + errno = ENOSYS; + return -1; +#endif +} + +ssize_t sys_listxattr (const char *path, char *list, size_t size) +{ +#if defined(HAVE_LISTXATTR) + return listxattr(path, list, size); +#else + errno = ENOSYS; + return -1; +#endif +} + +ssize_t sys_llistxattr (const char *path, char *list, size_t size) +{ +#if defined(HAVE_GETXATTR) + return llistxattr(path, list, size); +#else + errno = ENOSYS; + return -1; +#endif +} + +ssize_t sys_flistxattr (int filedes, char *list, size_t size) +{ +#if defined(HAVE_FLISTXATTR) + return flistxattr(filedes, list, size); +#else + errno = ENOSYS; + return -1; +#endif +} + +int sys_removexattr (const char *path, const char *name) +{ +#if defined(HAVE_REMOVEXATTR) + return removexattr(path, name); +#else + errno = ENOSYS; + return -1; +#endif +} + +int sys_lremovexattr (const char *path, const char *name) +{ +#if defined(HAVE_LREMOVEXATTR) + return lremovexattr(path, name); +#else + errno = ENOSYS; + return -1; +#endif +} + +int sys_fremovexattr (int filedes, const char *name) +{ +#if defined(HAVE_FREMOVEXATTR) + return fremovexattr(filedes, name); +#else + errno = ENOSYS; + return -1; +#endif +} + +int sys_setxattr (const char *path, const char *name, const void *value, size_t size, int flags) +{ +#if defined(HAVE_SETXATTR) + return setxattr(path, name, value, size, flags); +#else + errno = ENOSYS; + return -1; +#endif +} + +int sys_lsetxattr (const char *path, const char *name, const void *value, size_t size, int flags) +{ +#if defined(HAVE_LSETXATTR) + return lsetxattr(path, name, value, size, flags); +#else + errno = ENOSYS; + return -1; +#endif +} + +int sys_fsetxattr (int filedes, const char *name, const void *value, size_t size, int flags) +{ +#if defined(HAVE_FSETXATTR) + return fsetxattr(filedes, name, value, size, flags); +#else + errno = ENOSYS; + return -1; +#endif +} diff --git a/source3/lib/system_smbd.c b/source3/lib/system_smbd.c index 3ae0a6395e..bcbc8c61e6 100644 --- a/source3/lib/system_smbd.c +++ b/source3/lib/system_smbd.c @@ -107,13 +107,31 @@ static int getgrouplist_internals(const char *user, gid_t gid, gid_t *groups, in int sys_getgrouplist(const char *user, gid_t gid, gid_t *groups, int *grpcnt) { + char *p; + int retval; + + DEBUG(10,("sys_getgrouplist: user [%s]\n", user)); + + /* see if we should disable winbindd lookups for local users */ + if ( (p = strchr(user, *lp_winbind_separator())) == NULL ) { + if ( !winbind_off() ) + DEBUG(0,("sys_getgroup_list: Insufficient environment space for %s\n", + WINBINDD_DONT_ENV)); + else + DEBUG(10,("sys_getgrouplist(): disabled winbindd for group lookup [user == %s]\n", + user)); + } + #ifdef HAVE_GETGROUPLIST - return getgrouplist(user, gid, groups, grpcnt); + retval = getgrouplist(user, gid, groups, grpcnt); #else - int retval; become_root(); retval = getgrouplist_internals(user, gid, groups, grpcnt); unbecome_root(); - return retval; #endif + + /* allow winbindd lookups */ + winbind_on(); + + return retval; } diff --git a/source3/lib/time.c b/source3/lib/time.c index f76a1bdc0d..5309711a05 100644 --- a/source3/lib/time.c +++ b/source3/lib/time.c @@ -308,7 +308,8 @@ time_t nt_time_to_unix(NTTIME *nt) time_t l_time_min = TIME_T_MIN; time_t l_time_max = TIME_T_MAX; - if (nt->high == 0) return(0); + if (nt->high == 0 || (nt->high == 0xffffffff && nt->low == 0xffffffff)) + return(0); d = ((double)nt->high)*4.0*(double)(1<<30); d += (nt->low&0xFFF00000); diff --git a/source3/lib/username.c b/source3/lib/username.c index d8f4ff80ed..98b8f33aae 100644 --- a/source3/lib/username.c +++ b/source3/lib/username.c @@ -219,7 +219,7 @@ static struct passwd *Get_Pwnam_internals(const char *user, char *user2) /* Try in all lower case first as this is the most common case on UNIX systems */ - strlower(user2); + strlower_m(user2); DEBUG(5,("Trying _Get_Pwnam(), username as lowercase is %s\n",user2)); ret = getpwnam_alloc(user2); if(ret) @@ -234,7 +234,7 @@ static struct passwd *Get_Pwnam_internals(const char *user, char *user2) } /* Try as uppercase, if username wasn't originally uppercase */ - strupper(user2); + strupper_m(user2); if(strcmp(user, user2) != 0) { DEBUG(5,("Trying _Get_Pwnam(), username as uppercase is %s\n", user2)); ret = getpwnam_alloc(user2); @@ -243,7 +243,7 @@ static struct passwd *Get_Pwnam_internals(const char *user, char *user2) } /* Try all combinations up to usernamelevel */ - strlower(user2); + strlower_m(user2); DEBUG(5,("Checking combinations of %d uppercase letters in %s\n", lp_usernamelevel(), user2)); ret = uname_string_combinations(user2, getpwnam_alloc, lp_usernamelevel()); @@ -325,11 +325,12 @@ static BOOL user_in_netgroup_list(const char *user, const char *ngname) static BOOL user_in_winbind_group_list(const char *user, const char *gname, BOOL *winbind_answered) { - int num_groups; int i; - gid_t *groups = NULL; gid_t gid, gid_low, gid_high; BOOL ret = False; + static gid_t *groups = NULL; + static int num_groups = 0; + static fstring last_user = ""; *winbind_answered = False; @@ -349,27 +350,44 @@ static BOOL user_in_winbind_group_list(const char *user, const char *gname, BOOL goto err; } - /* - * Get the gid's that this user belongs to. - */ - - if ((num_groups = winbind_getgroups(user, 0, NULL)) == -1) - return False; + /* try to user the last user we looked up */ + /* otherwise fall back to lookups */ + + if ( !strequal( last_user, user ) || !groups ) + { + /* clear any cached information */ + + SAFE_FREE(groups); + fstrcpy( last_user, "" ); + + /* + * Get the gid's that this user belongs to. + */ - if (num_groups == 0) { - *winbind_answered = True; - return False; - } + if ((num_groups = winbind_getgroups(user, &groups)) == -1) + return False; + + if ( num_groups == -1 ) + return False; - if ((groups = (gid_t *)malloc(sizeof(gid_t) * num_groups )) == NULL) { - DEBUG(0,("user_in_winbind_group_list: malloc fail.\n")); - goto err; - } + if ( num_groups == 0 ) { + *winbind_answered = True; + return False; + } + + /* save the last username */ + + fstrcpy( last_user, user ); + + } + else + DEBUG(10,("user_in_winbind_group_list: using cached user groups for [%s]\n", user)); - if ((num_groups = winbind_getgroups(user, num_groups, groups)) == -1) { - DEBUG(0,("user_in_winbind_group_list: second winbind_getgroups call \ -failed with error %s\n", strerror(errno) )); - goto err; + if ( DEBUGLEVEL >= 10 ) { + DEBUG(10,("user_in_winbind_group_list: using groups -- ")); + for ( i=0; i 0) + { + dump_data(11, data, len); + } +#endif +} + char *tab_depth(int depth) { static pstring spaces; @@ -2323,8 +2347,8 @@ BOOL mask_match(const char *string, char *pattern, BOOL is_case_sensitive) fstrcpy(p2, pattern); fstrcpy(s2, string); - strlower(p2); - strlower(s2); + strlower_m(p2); + strlower_m(s2); return ms_fnmatch(p2, s2, Protocol) == 0; } @@ -2332,9 +2356,9 @@ BOOL mask_match(const char *string, char *pattern, BOOL is_case_sensitive) Recursive routine that is called by unix_wild_match. *********************************************************/ -static BOOL unix_do_match(char *regexp, char *str) +static BOOL unix_do_match(const char *regexp, const char *str) { - char *p; + const char *p; for( p = regexp; *p && *str; ) { @@ -2440,8 +2464,8 @@ BOOL unix_wild_match(const char *pattern, const char *string) pstrcpy(p2, pattern); pstrcpy(s2, string); - strlower(p2); - strlower(s2); + strlower_m(p2); + strlower_m(s2); /* Remove any *? and ** from the pattern as they are meaningless */ for(p = p2; *p; p++) @@ -2454,6 +2478,7 @@ BOOL unix_wild_match(const char *pattern, const char *string) return unix_do_match(p2, s2) == 0; } + #ifdef __INSURE__ /******************************************************************* diff --git a/source3/lib/util_sid.c b/source3/lib/util_sid.c index 9dc0c8ca18..00f14d7d26 100644 --- a/source3/lib/util_sid.c +++ b/source3/lib/util_sid.c @@ -391,6 +391,9 @@ BOOL sid_peek_check_rid(const DOM_SID *exp_dom_sid, const DOM_SID *sid, uint32 * if (!exp_dom_sid || !sid || !rid) return False; + if (sid->num_auths != (exp_dom_sid->num_auths+1)) { + return False; + } if (sid_compare_domain(exp_dom_sid, sid)!=0){ *rid=(-1); @@ -642,8 +645,9 @@ DOM_SID *sid_dup_talloc(TALLOC_CTX *ctx, DOM_SID *src) if(!src) return NULL; - if((dst = talloc_zero(ctx, sizeof(DOM_SID))) != NULL) + if((dst = talloc_zero(ctx, sizeof(DOM_SID))) != NULL) { sid_copy( dst, src); + } return dst; } diff --git a/source3/lib/util_sock.c b/source3/lib/util_sock.c index c974050b43..1bd4c3a96b 100644 --- a/source3/lib/util_sock.c +++ b/source3/lib/util_sock.c @@ -654,8 +654,8 @@ int open_socket_out(int type, struct in_addr *addr, int port ,int timeout) { struct sockaddr_in sock_out; int res,ret; - int connect_loop = 250; /* 250 milliseconds */ - int loops = (timeout) / connect_loop; + int connect_loop = 10; + int increment = 10; /* create a socket to write to */ res = socket(PF_INET, type, 0); @@ -681,8 +681,13 @@ connect_again: /* Some systems return EAGAIN when they mean EINPROGRESS */ if (ret < 0 && (errno == EINPROGRESS || errno == EALREADY || - errno == EAGAIN) && loops--) { + errno == EAGAIN) && (connect_loop < timeout) ) { msleep(connect_loop); + connect_loop += increment; + if (increment < 250) { + /* After 8 rounds we end up at a max of 255 msec */ + increment *= 1.5; + } goto connect_again; } @@ -764,6 +769,19 @@ char *client_addr(void) return get_socket_addr(client_fd); } +struct in_addr *client_inaddr(struct sockaddr *sa) +{ + struct sockaddr_in *sockin = (struct sockaddr_in *) (sa); + int length = sizeof(*sa); + + if (getpeername(client_fd, sa, &length) < 0) { + DEBUG(0,("getpeername failed. Error was %s\n", strerror(errno) )); + return NULL; + } + + return &sockin->sin_addr; +} + /******************************************************************* matchname - determine if host name matches IP address. Used to confirm a hostname lookup to prevent spoof attacks diff --git a/source3/lib/util_str.c b/source3/lib/util_str.c index e561d15f61..96fbc3f124 100644 --- a/source3/lib/util_str.c +++ b/source3/lib/util_str.c @@ -38,6 +38,7 @@ BOOL next_token(const char **ptr,char *buff, const char *sep, size_t bufsize) { const char *s; + char *pbuf; BOOL quoted; size_t len=1; @@ -59,17 +60,18 @@ BOOL next_token(const char **ptr,char *buff, const char *sep, size_t bufsize) return(False); /* copy over the token */ + pbuf = buff; for (quoted = False; len < bufsize && *s && (quoted || !strchr_m(sep,*s)); s++) { if (*s == '\"') { quoted = !quoted; } else { len++; - *buff++ = *s; + *pbuf++ = *s; } } *ptr = (*s) ? s+1 : s; - *buff = 0; + *pbuf = 0; return(True); } @@ -312,7 +314,7 @@ char *strupper_static(const char *s) static pstring str; pstrcpy(str, s); - strupper(str); + strupper_m(str); return str; } @@ -325,9 +327,9 @@ void strnorm(char *s) { extern int case_default; if (case_default == CASE_UPPER) - strupper(s); + strupper_m(s); else - strlower(s); + strlower_m(s); } /** @@ -1109,6 +1111,26 @@ char *strrchr_m(const char *s, char c) return (char *)(s+strlen(s2)); } +/*********************************************************************** + Return the equivalent of doing strrchr 'n' times - always going + backwards. +***********************************************************************/ + +char *strnrchr_m(const char *s, char c, unsigned int n) +{ + wpstring ws; + pstring s2; + smb_ucs2_t *p; + + push_ucs2(NULL, ws, s, sizeof(ws), STR_TERMINATE); + p = strnrchr_w(ws, UCS2_CHAR(c), n); + if (!p) + return NULL; + *p = 0; + pull_ucs2_pstring(s2, ws); + return (char *)(s+strlen(s2)); +} + /** Convert a string to lower case. **/ @@ -1469,6 +1491,7 @@ BOOL str_list_substitute(char **list, const char *pattern, const char *insert) #define IPSTR_LIST_SEP "," +#define IPSTR_LIST_CHAR ',' /** * Add ip string representation to ipstr list. Used also @@ -1483,19 +1506,20 @@ BOOL str_list_substitute(char **list, const char *pattern, const char *insert) * reallocated to new length **/ -char* ipstr_list_add(char** ipstr_list, const struct in_addr *ip) +char* ipstr_list_add(char** ipstr_list, const struct ip_service *service) { char* new_ipstr = NULL; /* arguments checking */ - if (!ipstr_list || !ip) return NULL; + if (!ipstr_list || !service) return NULL; /* attempt to convert ip to a string and append colon separator to it */ if (*ipstr_list) { - asprintf(&new_ipstr, "%s%s%s", *ipstr_list, IPSTR_LIST_SEP,inet_ntoa(*ip)); + asprintf(&new_ipstr, "%s%s%s:%d", *ipstr_list, IPSTR_LIST_SEP, + inet_ntoa(service->ip), service->port); SAFE_FREE(*ipstr_list); } else { - asprintf(&new_ipstr, "%s", inet_ntoa(*ip)); + asprintf(&new_ipstr, "%s:%d", inet_ntoa(service->ip), service->port); } *ipstr_list = new_ipstr; return *ipstr_list; @@ -1512,7 +1536,7 @@ char* ipstr_list_add(char** ipstr_list, const struct in_addr *ip) * @return pointer to allocated ip string **/ -char* ipstr_list_make(char** ipstr_list, const struct in_addr* ip_list, int ip_count) +char* ipstr_list_make(char** ipstr_list, const struct ip_service* ip_list, int ip_count) { int i; @@ -1531,7 +1555,8 @@ char* ipstr_list_make(char** ipstr_list, const struct in_addr* ip_list, int ip_c /** * Parse given ip string list into array of ip addresses - * (as in_addr structures) + * (as ip_service structures) + * e.g. 192.168.1.100:389,192.168.1.78, ... * * @param ipstr ip string list to be parsed * @param ip_list pointer to array of ip addresses which is @@ -1539,28 +1564,40 @@ char* ipstr_list_make(char** ipstr_list, const struct in_addr* ip_list, int ip_c * @return number of succesfully parsed addresses **/ -int ipstr_list_parse(const char* ipstr_list, struct in_addr** ip_list) +int ipstr_list_parse(const char* ipstr_list, struct ip_service **ip_list) { fstring token_str; - int count; + size_t count; + int i; - if (!ipstr_list || !ip_list) return 0; + if (!ipstr_list || !ip_list) + return 0; + + count = count_chars(ipstr_list, IPSTR_LIST_CHAR) + 1; + if ( (*ip_list = (struct ip_service*)malloc(count * sizeof(struct ip_service))) == NULL ) { + DEBUG(0,("ipstr_list_parse: malloc failed for %d entries\n", count)); + return 0; + } - for (*ip_list = NULL, count = 0; - next_token(&ipstr_list, token_str, IPSTR_LIST_SEP, FSTRING_LEN); - count++) { - + for ( i=0; + next_token(&ipstr_list, token_str, IPSTR_LIST_SEP, FSTRING_LEN) && inode, ptr+10, 6); } -void uuid_generate_random(GUID *out) +void smb_uuid_generate_random(GUID *out) { GUID tmp; struct uuid uu; @@ -71,7 +71,7 @@ void uuid_generate_random(GUID *out) uuid_pack(&uu, out); } -char *guid_to_string(const GUID in) +char *smb_uuid_to_string(const GUID in) { struct uuid uu; char *out; @@ -87,7 +87,7 @@ char *guid_to_string(const GUID in) return out; } -const char *uuid_string_static(const GUID in) +const char *smb_uuid_string_static(const GUID in) { struct uuid uu; static char out[37]; diff --git a/source3/lib/wins_srv.c b/source3/lib/wins_srv.c index 3372f74dcb..4a54762fde 100644 --- a/source3/lib/wins_srv.c +++ b/source3/lib/wins_srv.c @@ -70,14 +70,24 @@ static char *wins_srv_keystr(struct in_addr wins_ip, struct in_addr src_ip) { - char *keystr; + char *keystr = NULL, *wins_ip_addr = NULL, *src_ip_addr = NULL; - if (asprintf(&keystr, WINS_SRV_FMT, inet_ntoa(wins_ip), - inet_ntoa(src_ip)) == -1) { - DEBUG(0, ("wins_srv_is_dead: malloc error\n")); - return NULL; + wins_ip_addr = strdup(inet_ntoa(wins_ip)); + src_ip_addr = strdup(inet_ntoa(src_ip)); + + if ( !wins_ip_addr || !src_ip_addr ) { + DEBUG(0,("wins_srv_keystr: malloc error\n")); + goto done; } + if (asprintf(&keystr, WINS_SRV_FMT, wins_ip_addr, src_ip_addr) == -1) { + DEBUG(0, (": ns_srv_keystr: malloc error for key string\n")); + } + +done: + SAFE_FREE(wins_ip_addr); + SAFE_FREE(src_ip_addr); + return keystr; } diff --git a/source3/libads/ads_ldap.c b/source3/libads/ads_ldap.c index 97f12de0f7..dcceaaeb83 100644 --- a/source3/libads/ads_ldap.c +++ b/source3/libads/ads_ldap.c @@ -34,7 +34,7 @@ NTSTATUS ads_name_to_sid(ADS_STRUCT *ads, int count; ADS_STATUS rc; void *res = NULL; - char *exp; + char *ldap_exp; uint32 t; NTSTATUS status = NT_STATUS_UNSUCCESSFUL; char *escaped_name = escape_ldap_string_alloc(name); @@ -45,15 +45,15 @@ NTSTATUS ads_name_to_sid(ADS_STRUCT *ads, goto done; } - if (asprintf(&exp, "(|(sAMAccountName=%s)(userPrincipalName=%s@%s))", + if (asprintf(&ldap_exp, "(|(sAMAccountName=%s)(userPrincipalName=%s@%s))", escaped_name, escaped_name, escaped_realm) == -1) { DEBUG(1,("ads_name_to_sid: asprintf failed!\n")); status = NT_STATUS_NO_MEMORY; goto done; } - rc = ads_search_retry(ads, &res, exp, attrs); - free(exp); + rc = ads_search_retry(ads, &res, ldap_exp, attrs); + free(ldap_exp); if (!ADS_ERR_OK(rc)) { DEBUG(1,("name_to_sid ads_search: %s\n", ads_errstr(rc))); goto done; @@ -102,7 +102,7 @@ NTSTATUS ads_sid_to_name(ADS_STRUCT *ads, "sAMAccountType", NULL}; ADS_STATUS rc; void *msg = NULL; - char *exp = NULL; + char *ldap_exp = NULL; char *sidstr = NULL; uint32 atype; NTSTATUS status = NT_STATUS_UNSUCCESSFUL; @@ -113,13 +113,13 @@ NTSTATUS ads_sid_to_name(ADS_STRUCT *ads, goto done; } - if (asprintf(&exp, "(objectSid=%s)", sidstr) == -1) { + if (asprintf(&ldap_exp, "(objectSid=%s)", sidstr) == -1) { DEBUG(1,("ads_sid_to_name: asprintf failed!\n")); status = NT_STATUS_NO_MEMORY; goto done; } - rc = ads_search_retry(ads, &msg, exp, attrs); + rc = ads_search_retry(ads, &msg, ldap_exp, attrs); if (!ADS_ERR_OK(rc)) { status = ads_ntstatus(rc); DEBUG(1,("ads_sid_to_name ads_search: %s\n", ads_errstr(rc))); @@ -146,7 +146,7 @@ NTSTATUS ads_sid_to_name(ADS_STRUCT *ads, done: if (msg) ads_msgfree(ads, msg); - SAFE_FREE(exp); + SAFE_FREE(ldap_exp); SAFE_FREE(sidstr); return status; diff --git a/source3/libads/ads_struct.c b/source3/libads/ads_struct.c index 652bfe31be..dd31439d83 100644 --- a/source3/libads/ads_struct.c +++ b/source3/libads/ads_struct.c @@ -94,8 +94,7 @@ ADS_STRUCT *ads_init(const char *realm, ads->server.workgroup = workgroup ? strdup(workgroup) : NULL; ads->server.ldap_server = ldap_server? strdup(ldap_server) : NULL; - /* we need to know if this is a foreign realm to know if we can - use lp_ads_server() */ + /* we need to know if this is a foreign realm */ if (realm && *realm && strcasecmp(lp_realm(), realm) != 0) { ads->server.foreign = 1; } diff --git a/source3/libads/ads_utils.c b/source3/libads/ads_utils.c index c56e7385a4..1aad0bed54 100644 --- a/source3/libads/ads_utils.c +++ b/source3/libads/ads_utils.c @@ -88,52 +88,6 @@ uint32 ads_uf2atype(uint32 uf) return atype; } -/* -translated the GROUP_CTRL Flags to GroupType (groupType) -*/ -uint32 ads_gcb2gtype(uint16 gcb) -{ - uint32 gtype = 0x00000000; - - if (gcb & GCB_ALIAS_GROUP) gtype |= GTYPE_SECURITY_BUILTIN_LOCAL_GROUP; - else if(gcb & GCB_LOCAL_GROUP) gtype |= GTYPE_SECURITY_DOMAIN_LOCAL_GROUP; - if (gcb & GCB_GLOBAL_GROUP) gtype |= GTYPE_SECURITY_GLOBAL_GROUP; - - return gtype; -} - -/* -translated the GroupType (groupType) to GROUP_CTRL Flags -*/ -uint16 ads_gtype2gcb(uint32 gtype) -{ - uint16 gcb = 0x0000; - - switch(gtype) { - case GTYPE_SECURITY_BUILTIN_LOCAL_GROUP: - gcb = GCB_ALIAS_GROUP; - break; - case GTYPE_SECURITY_DOMAIN_LOCAL_GROUP: - gcb = GCB_LOCAL_GROUP; - break; - case GTYPE_SECURITY_GLOBAL_GROUP: - gcb = GCB_GLOBAL_GROUP; - break; - - case GTYPE_DISTRIBUTION_GLOBAL_GROUP: - gcb = GCB_GLOBAL_GROUP; - break; - case GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP: - gcb = GCB_LOCAL_GROUP; - break; - case GTYPE_DISTRIBUTION_UNIVERSAL_GROUP: - gcb = GCB_GLOBAL_GROUP; - break; - } - - return gcb; -} - /* get the accountType from the groupType */ diff --git a/source3/libads/kerberos_verify.c b/source3/libads/kerberos_verify.c index 35d429ca2a..25b7f9d948 100644 --- a/source3/libads/kerberos_verify.c +++ b/source3/libads/kerberos_verify.c @@ -33,21 +33,32 @@ NTSTATUS ads_verify_ticket(ADS_STRUCT *ads, const DATA_BLOB *ticket, DATA_BLOB *ap_rep, uint8 session_key[16]) { - krb5_context context; + NTSTATUS sret = NT_STATUS_LOGON_FAILURE; + krb5_context context = NULL; krb5_auth_context auth_context = NULL; krb5_keytab keytab = NULL; krb5_data packet; krb5_ticket *tkt = NULL; + krb5_rcache rcache = NULL; int ret, i; - krb5_keyblock * key; + krb5_keyblock *key = NULL; krb5_principal host_princ; - char *host_princ_s; + char *host_princ_s = NULL; fstring myname; - char *password_s; + char *password_s = NULL; krb5_data password; krb5_enctype *enctypes = NULL; +#if 0 + krb5_address local_addr; + krb5_address remote_addr; +#endif BOOL auth_ok = False; + ZERO_STRUCT(packet); + ZERO_STRUCT(password); + ZERO_STRUCTP(auth_data); + ZERO_STRUCTP(ap_rep); + if (!secrets_init()) { DEBUG(1,("secrets_init failed\n")); return NT_STATUS_LOGON_FAILURE; @@ -71,35 +82,63 @@ NTSTATUS ads_verify_ticket(ADS_STRUCT *ads, const DATA_BLOB *ticket, ret = krb5_set_default_realm(context, ads->auth.realm); if (ret) { DEBUG(1,("krb5_set_default_realm failed (%s)\n", error_message(ret))); - return NT_STATUS_LOGON_FAILURE; + sret = NT_STATUS_LOGON_FAILURE; + goto out; } - /* this whole process is far more complex than I would + /* This whole process is far more complex than I would like. We have to go through all this to allow us to store the secret internally, instead of using /etc/krb5.keytab */ + ret = krb5_auth_con_init(context, &auth_context); if (ret) { DEBUG(1,("krb5_auth_con_init failed (%s)\n", error_message(ret))); - return NT_STATUS_LOGON_FAILURE; + sret = NT_STATUS_LOGON_FAILURE; + goto out; } fstrcpy(myname, global_myname()); - strlower(myname); + strlower_m(myname); asprintf(&host_princ_s, "HOST/%s@%s", myname, lp_realm()); ret = krb5_parse_name(context, host_princ_s, &host_princ); if (ret) { DEBUG(1,("krb5_parse_name(%s) failed (%s)\n", host_princ_s, error_message(ret))); - return NT_STATUS_LOGON_FAILURE; + sret = NT_STATUS_LOGON_FAILURE; + goto out; } + /* + * JRA. We must set the rcache and the allowed addresses in the auth_context + * here. This will prevent replay attacks and ensure the client has got a key from + * the correct IP address. + */ + + ret = krb5_get_server_rcache(context, krb5_princ_component(context, host_princ, 0), &rcache); + if (ret) { + DEBUG(1,("krb5_get_server_rcache failed (%s)\n", error_message(ret))); + sret = NT_STATUS_LOGON_FAILURE; + goto out; + } + + ret = krb5_auth_con_setrcache(context, auth_context, rcache); + if (ret) { + DEBUG(1,("krb5_auth_con_setrcache failed (%s)\n", error_message(ret))); + sret = NT_STATUS_LOGON_FAILURE; + goto out; + } + + /* Now we need to add the addresses.... JRA. */ + if (!(key = (krb5_keyblock *)malloc(sizeof(*key)))) { - return NT_STATUS_NO_MEMORY; + sret = NT_STATUS_NO_MEMORY; + goto out; } if ((ret = get_kerberos_allowed_etypes(context, &enctypes))) { DEBUG(1,("krb5_get_permitted_enctypes failed (%s)\n", error_message(ret))); - return NT_STATUS_LOGON_FAILURE; + sret = NT_STATUS_LOGON_FAILURE; + goto out; } /* we need to setup a auth context with each possible encoding type in turn */ @@ -124,23 +163,26 @@ NTSTATUS ads_verify_ticket(ADS_STRUCT *ads, const DATA_BLOB *ticket, if (!auth_ok) { DEBUG(3,("krb5_rd_req with auth failed (%s)\n", error_message(ret))); - return NT_STATUS_LOGON_FAILURE; + sret = NT_STATUS_LOGON_FAILURE; + goto out; } ret = krb5_mk_rep(context, auth_context, &packet); if (ret) { DEBUG(3,("Failed to generate mutual authentication reply (%s)\n", error_message(ret))); - krb5_auth_con_free(context, auth_context); - return NT_STATUS_LOGON_FAILURE; + sret = NT_STATUS_LOGON_FAILURE; + goto out; } *ap_rep = data_blob(packet.data, packet.length); free(packet.data); - krb5_get_smb_session_key(context, auth_context, session_key); - DEBUG(0,("SMB session key (from ticket) follows:\n")); - dump_data(0, session_key, 16); + get_krb5_smb_session_key(context, auth_context, session_key); +#ifdef DEBUG_PASSWORD + DEBUG(10,("SMB session key (from ticket) follows:\n")); + dump_data(10, session_key, 16); +#endif #if 0 file_save("/tmp/ticket.dat", ticket->data, ticket->length); @@ -165,15 +207,30 @@ NTSTATUS ads_verify_ticket(ADS_STRUCT *ads, const DATA_BLOB *ticket, principal))) { DEBUG(3,("krb5_unparse_name failed (%s)\n", error_message(ret))); + sret = NT_STATUS_LOGON_FAILURE; + goto out; + } + + sret = NT_STATUS_OK; + + out: + + if (!NT_STATUS_IS_OK(sret)) data_blob_free(auth_data); + + if (!NT_STATUS_IS_OK(sret)) data_blob_free(ap_rep); + + SAFE_FREE(host_princ_s); + SAFE_FREE(password_s); + + if (auth_context) krb5_auth_con_free(context, auth_context); - return NT_STATUS_LOGON_FAILURE; - } - krb5_auth_con_free(context, auth_context); + if (context) + krb5_free_context(context); - return NT_STATUS_OK; + return sret; } #endif /* HAVE_KRB5 */ diff --git a/source3/libads/krb5_setpw.c b/source3/libads/krb5_setpw.c index 214871b3fb..80ef6cdf01 100644 --- a/source3/libads/krb5_setpw.c +++ b/source3/libads/krb5_setpw.c @@ -195,9 +195,9 @@ static const struct kpasswd_errors { {0, NULL} }; -static krb5_error_code krb5_setpw_result_code_string(krb5_context context, - int result_code, - const char **code_string) +static krb5_error_code setpw_result_code_string(krb5_context context, + int result_code, + const char **code_string) { unsigned int idx = 0; @@ -311,7 +311,7 @@ static krb5_error_code parse_setpw_reply(krb5_context context, return 0; else { const char *errstr; - krb5_setpw_result_code_string(context, res_code, &errstr); + setpw_result_code_string(context, res_code, &errstr); DEBUG(1, ("Error changing password: %s\n", errstr)); switch(res_code) { @@ -457,8 +457,8 @@ static ADS_STATUS do_krb5_kpasswd_request(krb5_context context, return ADS_SUCCESS; } -ADS_STATUS krb5_set_password(const char *kdc_host, const char *princ, const char *newpw, - int time_offset) +ADS_STATUS ads_krb5_set_password(const char *kdc_host, const char *princ, + const char *newpw, int time_offset) { ADS_STATUS aret; @@ -570,11 +570,11 @@ kerb_prompter(krb5_context ctx, void *data, return 0; } -static ADS_STATUS krb5_chg_password(const char *kdc_host, - const char *principal, - const char *oldpw, - const char *newpw, - int time_offset) +static ADS_STATUS ads_krb5_chg_password(const char *kdc_host, + const char *principal, + const char *oldpw, + const char *newpw, + int time_offset) { ADS_STATUS aret; krb5_error_code ret; @@ -648,11 +648,11 @@ ADS_STATUS kerberos_set_password(const char *kpasswd_server, } if (!strcmp(auth_principal, target_principal)) - return krb5_chg_password(kpasswd_server, target_principal, - auth_password, new_password, time_offset); + return ads_krb5_chg_password(kpasswd_server, target_principal, + auth_password, new_password, time_offset); else - return krb5_set_password(kpasswd_server, target_principal, - new_password, time_offset); + return ads_krb5_set_password(kpasswd_server, target_principal, + new_password, time_offset); } @@ -671,15 +671,16 @@ ADS_STATUS ads_set_machine_password(ADS_STRUCT *ads, char *host = strdup(hostname); char *principal; - strlower(host); + strlower_m(host); /* we need to use the '$' form of the name here, as otherwise the server might end up setting the password for a user instead */ - asprintf(&principal, "%s$@%s", host, ads->auth.realm); + asprintf(&principal, "%s$@%s", host, ads->config.realm); - status = krb5_set_password(ads->auth.kdc_server, principal, password, ads->auth.time_offset); + status = ads_krb5_set_password(ads->auth.kdc_server, principal, + password, ads->auth.time_offset); free(host); free(principal); diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c index 3ce80975da..92f7f7645a 100644 --- a/source3/libads/ldap.c +++ b/source3/libads/ldap.c @@ -41,6 +41,9 @@ /* try a connection to a given ldap server, returning True and setting the servers IP in the ads struct if successful + + TODO : add a negative connection cache in here leveraged off of the one + found in the rpc code. --jerry */ static BOOL ads_try_connect(ADS_STRUCT *ads, const char *server, unsigned port) { @@ -90,133 +93,81 @@ static BOOL ads_try_connect_uri(ADS_STRUCT *ads) return False; } -/* used by the IP comparison function */ -struct ldap_ip { - struct in_addr ip; - unsigned port; -}; - -/* compare 2 ldap IPs by nearness to our interfaces - used in qsort */ -static int ldap_ip_compare(struct ldap_ip *ip1, struct ldap_ip *ip2) -{ - return ip_compare(&ip1->ip, &ip2->ip); -} +/********************************************************************** + Try to find an AD dc using our internal name resolution routines + Try the realm first and then then workgroup name if netbios is not + disabled +**********************************************************************/ -/* try connecting to a ldap server via DNS */ -static BOOL ads_try_dns(ADS_STRUCT *ads) +static BOOL ads_find_dc(ADS_STRUCT *ads) { const char *c_realm; - const char *ptr; - char *realm; - char *list = NULL; - pstring tok; - struct ldap_ip *ip_list; int count, i=0; + struct ip_service *ip_list; + pstring realm; + BOOL got_realm = False; + /* realm */ c_realm = ads->server.realm; if (!c_realm || !*c_realm) { c_realm = lp_realm(); } - if (!c_realm || !*c_realm) { - c_realm = ads->server.workgroup; - } - if (!c_realm || !*c_realm) { - c_realm = lp_workgroup(); - } - if (!c_realm) { - return False; - } - realm = smb_xstrdup(c_realm); + if ( c_realm ) + got_realm = True; - DEBUG(6,("ads_try_dns: looking for realm '%s'\n", realm)); - if (ldap_domain2hostlist(realm, &list) != LDAP_SUCCESS) { - SAFE_FREE(realm); - return False; + +again: + /* we need to try once with the realm name and fallback to the + netbios domain name if we fail (if netbios has not been disabled */ + + if ( !got_realm && !lp_disable_netbios() ) { + c_realm = ads->server.workgroup; + if (!c_realm || !*c_realm) + c_realm = lp_workgroup(); + if (!c_realm) + return False; } + + pstrcpy( realm, c_realm ); - DEBUG(6,("ads_try_dns: ldap realm '%s' host list '%s'\n", realm, list)); - SAFE_FREE(realm); + DEBUG(6,("ads_find_dc: looking for %s '%s'\n", + (got_realm ? "realm" : "domain"), realm)); - count = count_chars(list, ' ') + 1; - ip_list = malloc(count * sizeof(struct ldap_ip)); - if (!ip_list) { - return False; - } - - ptr = list; - while (next_token(&ptr, tok, " ", sizeof(tok))) { - unsigned port = LDAP_PORT; - char *p = strchr(tok, ':'); - if (p) { - *p = 0; - port = atoi(p+1); - } - ip_list[i].ip = *interpret_addr2(tok); - ip_list[i].port = port; - if (!is_zero_ip(ip_list[i].ip)) { - i++; + if ( !get_sorted_dc_list(realm, &ip_list, &count, got_realm) ) { + /* fall back to netbios if we can */ + if ( got_realm && !lp_disable_netbios() ) { + got_realm = False; + goto again; } + + return False; } - free(list); - - count = i; - - /* we sort the list of addresses by closeness to our interfaces. This - tries to prevent us using a DC on the other side of the country */ - if (count > 1) { - qsort(ip_list, count, sizeof(struct ldap_ip), - QSORT_CAST ldap_ip_compare); - } - - for (i=0;iserver.workgroup; - BOOL list_ordered; - - if (!workgroup) { - workgroup = lp_workgroup(); - } - - DEBUG(6,("ads_try_netbios: looking for workgroup '%s'\n", workgroup)); - - /* try the PDC first */ - if (get_pdc_ip(workgroup, &pdc_ip)) { - DEBUG(6,("ads_try_netbios: trying server '%s'\n", - inet_ntoa(pdc_ip))); - if (ads_try_connect(ads, inet_ntoa(pdc_ip), LDAP_PORT)) - return True; - } - - /* now any DC, including backups */ - if (get_dc_list(workgroup, &ip_list, &count, &list_ordered)) { - for (i=0;iserver.foreign && - ads_try_connect(ads, lp_ads_server(), LDAP_PORT)) { - goto got_connection; - } - - /* try via DNS */ - if (ads_try_dns(ads)) { - goto got_connection; - } - - /* try via netbios lookups */ - if (!lp_disable_netbios() && ads_try_netbios(ads)) { + if (ads_find_dc(ads)) { goto got_connection; } @@ -278,7 +216,7 @@ got_connection: /* by default use the machine account */ fstring myname; fstrcpy(myname, global_myname()); - strlower(myname); + strlower_m(myname); asprintf(&ads->auth.user_name, "HOST/%s", myname); } @@ -400,7 +338,7 @@ static char **ads_pull_strvals(TALLOC_CTX *ctx, const char **in_vals) * again when the entire search is complete * @param ads connection to ads server * @param bind_path Base dn for the search - * @param scope Scope of search (LDAP_BASE | LDAP_ONE | LDAP_SUBTREE) + * @param scope Scope of search (LDAP_SCOPE_BASE | LDAP_SCOPE_ONE | LDAP_SCOPE_SUBTREE) * @param expr Search expression - specified in local charset * @param attrs Attributes to retrieve - specified in utf8 or ascii * @param res ** which will contain results - free res* with ads_msgfree() @@ -540,7 +478,7 @@ done: * all entries in a large search. * @param ads connection to ads server * @param bind_path Base dn for the search - * @param scope Scope of search (LDAP_BASE | LDAP_ONE | LDAP_SUBTREE) + * @param scope Scope of search (LDAP_SCOPE_BASE | LDAP_SCOPE_ONE | LDAP_SCOPE_SUBTREE) * @param expr Search expression * @param attrs Attributes to retrieve * @param res ** which will contain results - free res* with ads_msgfree() @@ -587,7 +525,7 @@ ADS_STATUS ads_do_search_all(ADS_STRUCT *ads, const char *bind_path, * runs the function as each page is returned, using ads_process_results() * @param ads connection to ads server * @param bind_path Base dn for the search - * @param scope Scope of search (LDAP_BASE | LDAP_ONE | LDAP_SUBTREE) + * @param scope Scope of search (LDAP_SCOPE_BASE | LDAP_SCOPE_ONE | LDAP_SCOPE_SUBTREE) * @param expr Search expression - specified in local charset * @param attrs Attributes to retrieve - specified in UTF-8 or ascii * @param fn Function which takes attr name, values list, and data_area @@ -629,7 +567,7 @@ ADS_STATUS ads_do_search_all_fn(ADS_STRUCT *ads, const char *bind_path, * Do a search with a timeout. * @param ads connection to ads server * @param bind_path Base dn for the search - * @param scope Scope of search (LDAP_BASE | LDAP_ONE | LDAP_SUBTREE) + * @param scope Scope of search (LDAP_SCOPE_BASE | LDAP_SCOPE_ONE | LDAP_SCOPE_SUBTREE) * @param expr Search expression * @param attrs Attributes to retrieve * @param res ** which will contain results - free res* with ads_msgfree() @@ -749,14 +687,15 @@ void ads_memfree(ADS_STRUCT *ads, void *mem) /** * Get a dn from search results * @param ads connection to ads server - * @param res Search results + * @param msg Search result * @return dn string **/ -char *ads_get_dn(ADS_STRUCT *ads, void *res) +char *ads_get_dn(ADS_STRUCT *ads, void *msg) { char *utf8_dn, *unix_dn; - utf8_dn = ldap_get_dn(ads->ld, res); + utf8_dn = ldap_get_dn(ads->ld, msg); + pull_utf8_allocate((void **) &unix_dn, utf8_dn); ldap_memfree(utf8_dn); return unix_dn; @@ -998,7 +937,7 @@ ADS_STATUS ads_del_dn(ADS_STRUCT *ads, char *del_dn) return ADS_ERROR_NT(NT_STATUS_NO_MEMORY); } - ret = ldap_delete(ads->ld, utf8_dn); + ret = ldap_delete_s(ads->ld, utf8_dn); return ADS_ERROR(ret); } @@ -1058,13 +997,13 @@ static ADS_STATUS ads_add_machine_acct(ADS_STRUCT *ads, const char *hostname, psp = talloc_asprintf(ctx, "HOST/%s.%s", hostname, ads->config.realm); - strlower(&psp[5]); + strlower_m(&psp[5]); servicePrincipalName[1] = psp; servicePrincipalName[2] = talloc_asprintf(ctx, "CIFS/%s", hostname); psp2 = talloc_asprintf(ctx, "CIFS/%s.%s", hostname, ads->config.realm); - strlower(&psp2[5]); + strlower_m(&psp2[5]); servicePrincipalName[3] = psp2; free(ou_str); @@ -1078,6 +1017,7 @@ static ADS_STATUS ads_add_machine_acct(ADS_STRUCT *ads, const char *hostname, #ifndef ENCTYPE_ARCFOUR_HMAC acct_control |= UF_USE_DES_KEY_ONLY; #endif + if (!(controlstr = talloc_asprintf(ctx, "%u", acct_control))) goto done; @@ -1142,7 +1082,7 @@ static void dump_guid(const char *field, struct berval **values) GUID guid; for (i=0; values[i]; i++) { memcpy(guid.info, values[i]->bv_val, sizeof(guid.info)); - printf("%s: %s\n", field, uuid_string_static(guid)); + printf("%s: %s\n", field, smb_uuid_string_static(guid)); } } @@ -1345,7 +1285,7 @@ ADS_STATUS ads_join_realm(ADS_STRUCT *ads, const char *hostname, /* hostname must be lowercase */ host = strdup(hostname); - strlower(host); + strlower_m(host); status = ads_find_machine_acct(ads, (void **)&res, host); if (ADS_ERR_OK(status) && ads_count_replies(ads, res) == 1) { @@ -1384,13 +1324,13 @@ ADS_STATUS ads_join_realm(ADS_STRUCT *ads, const char *hostname, ADS_STATUS ads_leave_realm(ADS_STRUCT *ads, const char *hostname) { ADS_STATUS status; - void *res; + void *res, *msg; char *hostnameDN, *host; int rc; /* hostname must be lowercase */ host = strdup(hostname); - strlower(host); + strlower_m(host); status = ads_find_machine_acct(ads, &res, host); if (!ADS_ERR_OK(status)) { @@ -1398,7 +1338,12 @@ ADS_STATUS ads_leave_realm(ADS_STRUCT *ads, const char *hostname) return status; } - hostnameDN = ads_get_dn(ads, (LDAPMessage *)res); + msg = ads_first_entry(ads, res); + if (!msg) { + return ADS_ERROR_SYSTEM(ENOENT); + } + + hostnameDN = ads_get_dn(ads, (LDAPMessage *)msg); rc = ldap_delete_s(ads->ld, hostnameDN); ads_memfree(ads, hostnameDN); if (rc != LDAP_SUCCESS) { diff --git a/source3/libads/ldap_printer.c b/source3/libads/ldap_printer.c index f5cd4f2885..b650a5eb38 100644 --- a/source3/libads/ldap_printer.c +++ b/source3/libads/ldap_printer.c @@ -31,7 +31,7 @@ ADS_STATUS ads_find_printer_on_server(ADS_STRUCT *ads, void **res, const char *printer, const char *servername) { ADS_STATUS status; - char *srv_dn, **srv_cn, *exp; + char *srv_dn, **srv_cn, *s; const char *attrs[] = {"*", "nTSecurityDescriptor", NULL}; status = ads_find_machine_acct(ads, res, servername); @@ -44,15 +44,29 @@ ADS_STATUS ads_find_printer_on_server(ADS_STRUCT *ads, void **res, srv_cn = ldap_explode_dn(srv_dn, 1); ads_msgfree(ads, *res); - asprintf(&exp, "(cn=%s-%s)", srv_cn[0], printer); - status = ads_search(ads, res, exp, attrs); + asprintf(&s, "(cn=%s-%s)", srv_cn[0], printer); + status = ads_search(ads, res, s, attrs); ldap_memfree(srv_dn); ldap_value_free(srv_cn); - free(exp); + free(s); return status; } +ADS_STATUS ads_find_printers(ADS_STRUCT *ads, void **res) +{ + char *ldap_expr; + const char *attrs[] = { "objectClass", "printerName", "location", "driverName", + "serverName", "description", NULL }; + + /* For the moment only display all printers */ + + ldap_expr = "(&(!(showInAdvancedViewOnly=TRUE))(uncName=*)" + "(objectCategory=printQueue))"; + + return ads_search(ads, res, ldap_expr, attrs); +} + /* modify a printer entry in the directory */ @@ -338,4 +352,3 @@ BOOL get_local_printer_publishing_data(TALLOC_CTX *mem_ctx, } #endif - diff --git a/source3/libads/ldap_user.c b/source3/libads/ldap_user.c index 7efe5338f3..e70249dd78 100644 --- a/source3/libads/ldap_user.c +++ b/source3/libads/ldap_user.c @@ -28,16 +28,16 @@ ADS_STATUS ads_find_user_acct(ADS_STRUCT *ads, void **res, const char *user) { ADS_STATUS status; - char *exp; + char *ldap_exp; const char *attrs[] = {"*", NULL}; char *escaped_user = escape_ldap_string_alloc(user); if (!escaped_user) { return ADS_ERROR(LDAP_NO_MEMORY); } - asprintf(&exp, "(samAccountName=%s)", escaped_user); - status = ads_search(ads, res, exp, attrs); - SAFE_FREE(exp); + asprintf(&ldap_exp, "(samAccountName=%s)", escaped_user); + status = ads_search(ads, res, ldap_exp, attrs); + SAFE_FREE(ldap_exp); SAFE_FREE(escaped_user); return status; } diff --git a/source3/libads/sasl.c b/source3/libads/sasl.c index 29d4533a54..598208b17f 100644 --- a/source3/libads/sasl.c +++ b/source3/libads/sasl.c @@ -198,8 +198,11 @@ static ADS_STATUS ads_sasl_spnego_bind(ADS_STRUCT *ads) if (ads_kinit_password(ads) == 0) { status = ads_sasl_spnego_krb5_bind(ads, principal); } - if (ADS_ERR_OK(status)) + /* only fallback to NTLMSSP if allowed */ + if (ADS_ERR_OK(status) || + !(ads->auth.flags & ADS_AUTH_ALLOW_NTLMSSP)) { return status; + } } #endif diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c index 32397173da..fa9af19bf5 100644 --- a/source3/libsmb/cliconnect.c +++ b/source3/libsmb/cliconnect.c @@ -270,28 +270,41 @@ static BOOL cli_session_setup_nt1(struct cli_state *cli, const char *user, if (passlen != 24) { if (lp_client_ntlmv2_auth()) { DATA_BLOB server_chal; - + DATA_BLOB names_blob; server_chal = data_blob(cli->secblob.data, MIN(cli->secblob.length, 8)); - if (!SMBNTLMv2encrypt(user, workgroup, pass, server_chal, + /* note that the 'workgroup' here is a best guess - we don't know + the server's domain at this point. The 'server name' is also + dodgy... + */ + names_blob = NTLMv2_generate_names_blob(cli->called.name, workgroup); + + if (!SMBNTLMv2encrypt(user, workgroup, pass, &server_chal, + &names_blob, &lm_response, &nt_response, &session_key)) { + data_blob_free(&names_blob); data_blob_free(&server_chal); return False; } + data_blob_free(&names_blob); data_blob_free(&server_chal); } else { uchar nt_hash[16]; E_md4hash(pass, nt_hash); + nt_response = data_blob(NULL, 24); + SMBNTencrypt(pass,cli->secblob.data,nt_response.data); + /* non encrypted password supplied. Ignore ntpass. */ if (lp_client_lanman_auth()) { lm_response = data_blob(NULL, 24); - SMBencrypt(pass,cli->secblob.data,lm_response.data); + SMBencrypt(pass,cli->secblob.data, lm_response.data); + } else { + /* LM disabled, place NT# in LM feild instead */ + lm_response = data_blob(nt_response.data, nt_response.length); } - nt_response = data_blob(NULL, 24); - SMBNTencrypt(pass,cli->secblob.data,nt_response.data); session_key = data_blob(NULL, 16); SMBsesskeygen_ntv1(nt_hash, NULL, session_key.data); } @@ -440,6 +453,8 @@ static DATA_BLOB cli_session_setup_blob_receive(struct cli_state *cli) return blob2; } +#ifdef HAVE_KRB5 + /**************************************************************************** Send a extended security session setup blob, returning a reply blob. ****************************************************************************/ @@ -454,7 +469,6 @@ static DATA_BLOB cli_session_setup_blob(struct cli_state *cli, DATA_BLOB blob) return cli_session_setup_blob_receive(cli); } -#ifdef HAVE_KRB5 /**************************************************************************** Use in-memory credentials cache ****************************************************************************/ @@ -490,7 +504,8 @@ static BOOL cli_session_setup_kerberos(struct cli_state *cli, const char *princi return !cli_is_error(cli); } -#endif +#endif /* HAVE_KRB5 */ + /**************************************************************************** Do a spnego/NTLMSSP encrypted session setup. @@ -525,11 +540,18 @@ static BOOL cli_session_setup_ntlmssp(struct cli_state *cli, const char *user, ntlmssp_state->use_ntlmv2 = lp_client_ntlmv2_auth(); + if (cli->sign_info.negotiated_smb_signing + || cli->sign_info.mandatory_signing) { + ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN; + ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN; + } + do { nt_status = ntlmssp_client_update(ntlmssp_state, blob_in, &blob_out); data_blob_free(&blob_in); if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { + DATA_BLOB null = data_blob(NULL, 0); if (turn == 1) { /* and wrap it in a SPNEGO wrapper */ msg1 = gen_negTokenInit(OID_NTLMSSP, blob_out); @@ -538,14 +560,16 @@ static BOOL cli_session_setup_ntlmssp(struct cli_state *cli, const char *user, msg1 = spnego_gen_auth(blob_out); } + cli_simple_set_signing(cli, + ntlmssp_state->session_key.data, + null); + /* now send that blob on its way */ if (!cli_session_setup_blob_send(cli, msg1)) { return False; } data_blob_free(&msg1); - cli_ntlmssp_set_signing(cli, ntlmssp_state); - blob = cli_session_setup_blob_receive(cli); nt_status = cli_nt_error(cli); @@ -566,7 +590,6 @@ static BOOL cli_session_setup_ntlmssp(struct cli_state *cli, const char *user, } data_blob_free(&tmp_blob); } else { - /* the server might give us back two challenges */ if (!spnego_parse_auth_response(blob, nt_status, &blob_in)) { DEBUG(3,("Failed to parse auth response\n")); @@ -704,8 +727,22 @@ BOOL cli_session_setup(struct cli_state *cli, /* if its an older server then we have to use the older request format */ - if (cli->protocol < PROTOCOL_NT1) + if (cli->protocol < PROTOCOL_NT1) { + if (!lp_client_lanman_auth() && passlen != 24 && (*pass)) { + DEBUG(1, ("Server requested LM password but 'client lanman auth'" + " is disabled\n")); + return False; + } + + if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) == 0 && + !lp_client_plaintext_auth() && (*pass)) { + DEBUG(1, ("Server requested plaintext password but 'client use plaintext auth'" + " is disabled\n")); + return False; + } + 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 */ @@ -717,17 +754,21 @@ BOOL cli_session_setup(struct cli_state *cli, 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) { + if (!lp_client_plaintext_auth() && (*pass)) { + DEBUG(1, ("Server requested plaintext password but 'client use plaintext auth'" + " is disabled\n")); + return False; + } 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) @@ -780,6 +821,12 @@ BOOL cli_send_tconX(struct cli_state *cli, } if ((cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) && *pass && passlen != 24) { + if (!lp_client_lanman_auth()) { + DEBUG(1, ("Server requested LANMAN password but 'client use lanman auth'" + " is disabled\n")); + return False; + } + /* * Non-encrypted passwords - convert to DOS codepage before encryption. */ @@ -787,10 +834,17 @@ BOOL cli_send_tconX(struct cli_state *cli, SMBencrypt(pass,cli->secblob.data,(uchar *)pword); } else { if((cli->sec_mode & (NEGOTIATE_SECURITY_USER_LEVEL|NEGOTIATE_SECURITY_CHALLENGE_RESPONSE)) == 0) { + if (!lp_client_plaintext_auth() && (*pass)) { + DEBUG(1, ("Server requested plaintext password but 'client use plaintext auth'" + " is disabled\n")); + return False; + } + /* * Non-encrypted passwords - convert to DOS codepage before using. */ passlen = clistr_push(cli, pword, pass, sizeof(pword), STR_TERMINATE); + } else { memcpy(pword, pass, passlen); } @@ -823,9 +877,6 @@ BOOL cli_send_tconX(struct cli_state *cli, clistr_pull(cli, cli->dev, smb_buf(cli->inbuf), sizeof(fstring), -1, STR_TERMINATE|STR_ASCII); - if (strcasecmp(share,"IPC$")==0) - fstrcpy(cli->dev, "IPC"); - if (cli->protocol >= PROTOCOL_NT1 && smb_buflen(cli->inbuf) == 3) { /* almost certainly win95 - enable bug fixes */ @@ -962,12 +1013,24 @@ BOOL cli_negprot(struct cli_state *cli) smb_buflen(cli->inbuf)-8, STR_UNICODE|STR_NOALIGN); } - if ((cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED)) + if ((cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED)) { + /* Fail if signing is mandatory and we don't want to support it. */ + if (!lp_client_signing()) { + DEBUG(1,("cli_negprot: SMB signing is mandatory and we have disabled it.\n")); + return False; + } cli->sign_info.negotiated_smb_signing = True; + } if ((cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) && cli->sign_info.allow_smb_signing) cli->sign_info.negotiated_smb_signing = True; + /* Fail if signing is mandatory and the server doesn't support it. */ + if (cli->sign_info.mandatory_signing && !(cli->sign_info.negotiated_smb_signing)) { + DEBUG(1,("cli_negprot: SMB signing is mandatory and the server doesn't support it.\n")); + return False; + } + } else if (cli->protocol >= PROTOCOL_LANMAN1) { cli->use_spnego = False; cli->sec_mode = SVAL(cli->inbuf,smb_vwv1); @@ -1369,6 +1432,12 @@ NTSTATUS cli_raw_tcon(struct cli_state *cli, { char *p; + if (!lp_client_plaintext_auth() && (*pass)) { + DEBUG(1, ("Server requested plaintext password but 'client use plaintext auth'" + " is disabled\n")); + return NT_STATUS_ACCESS_DENIED; + } + memset(cli->outbuf,'\0',smb_size); memset(cli->inbuf,'\0',smb_size); @@ -1433,7 +1502,7 @@ struct cli_state *get_ipc_connect(char *server, struct in_addr *server_ip, struct cli_state *get_ipc_connect_master_ip_bcast(pstring workgroup, struct user_auth_info *user_info) { - struct in_addr *ip_list; + struct ip_service *ip_list; struct cli_state *cli; int i, count; struct in_addr server_ip; @@ -1447,7 +1516,7 @@ struct cli_state *get_ipc_connect_master_ip_bcast(pstring workgroup, struct user for (i = 0; i < count; i++) { static fstring name; - if (!name_status_find("*", 0, 0x1d, ip_list[i], name)) + if (!name_status_find("*", 0, 0x1d, ip_list[i].ip, name)) continue; if (!find_master_ip(name, &server_ip)) @@ -1456,7 +1525,7 @@ struct cli_state *get_ipc_connect_master_ip_bcast(pstring workgroup, struct user pstrcpy(workgroup, name); DEBUG(4, ("found master browser %s, %s\n", - name, inet_ntoa(ip_list[i]))); + name, inet_ntoa(ip_list[i].ip))); cli = get_ipc_connect(inet_ntoa(server_ip), &server_ip, user_info); diff --git a/source3/libsmb/clientgen.c b/source3/libsmb/clientgen.c index 8d4e8a266c..58c5ad8cd3 100644 --- a/source3/libsmb/clientgen.c +++ b/source3/libsmb/clientgen.c @@ -203,12 +203,9 @@ void cli_init_creds(struct cli_state *cli, const struct ntuser_creds *usr) fstrcpy(cli->domain , usr->domain); fstrcpy(cli->user_name, usr->user_name); memcpy(&cli->pwd, &usr->pwd, sizeof(usr->pwd)); - cli->ntlmssp_flags = usr->ntlmssp_flags; - cli->ntlmssp_cli_flgs = usr != NULL ? usr->ntlmssp_flags : 0; - DEBUG(10,("cli_init_creds: user %s domain %s flgs: %x\nntlmssp_cli_flgs:%x\n", - cli->user_name, cli->domain, - cli->ntlmssp_flags,cli->ntlmssp_cli_flgs)); + DEBUG(10,("cli_init_creds: user %s domain %s\n", + cli->user_name, cli->domain)); } /**************************************************************************** @@ -264,6 +261,9 @@ struct cli_state *cli_initialise(struct cli_state *cli) if (lp_client_signing()) cli->sign_info.allow_smb_signing = True; + + if (lp_client_signing() == Required) + cli->sign_info.mandatory_signing = True; if (!cli->outbuf || !cli->inbuf) goto error; @@ -287,6 +287,8 @@ struct cli_state *cli_initialise(struct cli_state *cli) cli->initialised = 1; cli->allocated = alloced_cli; + cli->pipe_idx = -1; + return cli; /* Clean up after malloc() error */ @@ -302,18 +304,51 @@ struct cli_state *cli_initialise(struct cli_state *cli) return NULL; } +/**************************************************************************** +close the session +****************************************************************************/ + +void cli_nt_session_close(struct cli_state *cli) +{ + if (cli->ntlmssp_pipe_state) { + ntlmssp_client_end(&cli->ntlmssp_pipe_state); + } + + cli_close(cli, cli->nt_pipe_fnum); + cli->nt_pipe_fnum = 0; + cli->pipe_idx = -1; +} + +/**************************************************************************** +close the NETLOGON session holding the session key for NETSEC +****************************************************************************/ + +void cli_nt_netlogon_netsec_session_close(struct cli_state *cli) +{ + if (cli->saved_netlogon_pipe_fnum != 0) { + cli_close(cli, cli->saved_netlogon_pipe_fnum); + cli->saved_netlogon_pipe_fnum = 0; + } +} + /**************************************************************************** Close a client connection and free the memory without destroying cli itself. ****************************************************************************/ void cli_close_connection(struct cli_state *cli) { + cli_nt_session_close(cli); + cli_nt_netlogon_netsec_session_close(cli); + SAFE_FREE(cli->outbuf); SAFE_FREE(cli->inbuf); cli_free_signing_context(cli); data_blob_free(&cli->secblob); + if (cli->ntlmssp_pipe_state) + ntlmssp_client_end(&cli->ntlmssp_pipe_state); + if (cli->mem_ctx) { talloc_destroy(cli->mem_ctx); cli->mem_ctx = NULL; diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c index b771e135f4..f021076a46 100644 --- a/source3/libsmb/clifile.c +++ b/source3/libsmb/clifile.c @@ -600,8 +600,8 @@ NTSTATUS cli_locktype(struct cli_state *cli, int fnum, /**************************************************************************** Lock a file. + note that timeout is in units of 2 milliseconds ****************************************************************************/ - BOOL cli_lock(struct cli_state *cli, int fnum, uint32 offset, uint32 len, int timeout, enum brl_type lock_type) { @@ -636,7 +636,7 @@ BOOL cli_lock(struct cli_state *cli, int fnum, cli_send_smb(cli); if (timeout != 0) { - cli->timeout = (timeout == -1) ? 0x7FFFFFFF : (timeout + 10*1000); + cli->timeout = (timeout == -1) ? 0x7FFFFFFF : (timeout*2 + 5*1000); } if (!cli_receive_smb(cli)) { diff --git a/source3/libsmb/clikrb5.c b/source3/libsmb/clikrb5.c index 5edc56daa9..fd5dd91325 100644 --- a/source3/libsmb/clikrb5.c +++ b/source3/libsmb/clikrb5.c @@ -235,12 +235,12 @@ krb5_error_code get_kerberos_allowed_etypes(krb5_context context, /* we can't use krb5_mk_req because w2k wants the service to be in a particular format */ -static krb5_error_code krb5_mk_req2(krb5_context context, - krb5_auth_context *auth_context, - const krb5_flags ap_req_options, - const char *principal, - krb5_ccache ccache, - krb5_data *outbuf) +static krb5_error_code ads_krb5_mk_req(krb5_context context, + krb5_auth_context *auth_context, + const krb5_flags ap_req_options, + const char *principal, + krb5_ccache ccache, + krb5_data *outbuf) { krb5_error_code retval; krb5_principal server; @@ -255,7 +255,7 @@ static krb5_error_code krb5_mk_req2(krb5_context context, } /* obtain ticket & session key */ - memset((char *)&creds, 0, sizeof(creds)); + ZERO_STRUCT(creds); if ((retval = krb5_copy_principal(context, server, &creds.server))) { DEBUG(1,("krb5_copy_principal failed (%s)\n", error_message(retval))); @@ -305,7 +305,7 @@ cleanup_princ: /* get a kerberos5 ticket for the given service */ -DATA_BLOB krb5_get_ticket(const char *principal, time_t time_offset) +DATA_BLOB cli_krb5_get_ticket(const char *principal, time_t time_offset) { krb5_error_code retval; krb5_data packet; @@ -344,11 +344,11 @@ DATA_BLOB krb5_get_ticket(const char *principal, time_t time_offset) goto failed; } - if ((retval = krb5_mk_req2(context, - &auth_context, - 0, - principal, - ccdef, &packet))) { + if ((retval = ads_krb5_mk_req(context, + &auth_context, + 0, + principal, + ccdef, &packet))) { goto failed; } @@ -365,7 +365,7 @@ failed: return data_blob(NULL, 0); } - BOOL krb5_get_smb_session_key(krb5_context context, krb5_auth_context auth_context, uint8 session_key[16]) + BOOL get_krb5_smb_session_key(krb5_context context, krb5_auth_context auth_context, uint8 session_key[16]) { #ifdef ENCTYPE_ARCFOUR_HMAC krb5_keyblock *skey; @@ -390,7 +390,7 @@ failed: } #else /* HAVE_KRB5 */ /* this saves a few linking headaches */ -DATA_BLOB krb5_get_ticket(const char *principal, time_t time_offset) +DATA_BLOB cli_krb5_get_ticket(const char *principal, time_t time_offset) { DEBUG(0,("NO KERBEROS SUPPORT\n")); return data_blob(NULL, 0); diff --git a/source3/libsmb/climessage.c b/source3/libsmb/climessage.c index 2b1be75089..8ce8416487 100644 --- a/source3/libsmb/climessage.c +++ b/source3/libsmb/climessage.c @@ -26,12 +26,11 @@ /**************************************************************************** start a message sequence ****************************************************************************/ -BOOL cli_message_start(struct cli_state *cli, char *host, char *username, - int *grp) +int cli_message_start_build(struct cli_state *cli, char *host, char *username) { char *p; - /* send a SMBsendstrt command */ + /* construct a SMBsendstrt command */ memset(cli->outbuf,'\0',smb_size); set_message(cli->outbuf,0,0,True); SCVAL(cli->outbuf,smb_com,SMBsendstrt); @@ -45,6 +44,14 @@ BOOL cli_message_start(struct cli_state *cli, char *host, char *username, p += clistr_push(cli, p, host, -1, STR_ASCII|STR_TERMINATE); cli_setup_bcc(cli, p); + + return(PTR_DIFF(p, cli->outbuf)); +} + +BOOL cli_message_start(struct cli_state *cli, char *host, char *username, + int *grp) +{ + cli_message_start_build(cli, host, username); cli_send_smb(cli); @@ -63,7 +70,7 @@ BOOL cli_message_start(struct cli_state *cli, char *host, char *username, /**************************************************************************** send a message ****************************************************************************/ -BOOL cli_message_text(struct cli_state *cli, char *msg, int len, int grp) +int cli_message_text_build(struct cli_state *cli, char *msg, int len, int grp) { char *msgdos; int lendos; @@ -93,6 +100,14 @@ BOOL cli_message_text(struct cli_state *cli, char *msg, int len, int grp) } cli_setup_bcc(cli, p); + + return(PTR_DIFF(p, cli->outbuf)); +} + +BOOL cli_message_text(struct cli_state *cli, char *msg, int len, int grp) +{ + cli_message_text_build(cli, msg, len, grp); + cli_send_smb(cli); if (!cli_receive_smb(cli)) { @@ -107,8 +122,10 @@ BOOL cli_message_text(struct cli_state *cli, char *msg, int len, int grp) /**************************************************************************** end a message ****************************************************************************/ -BOOL cli_message_end(struct cli_state *cli, int grp) +int cli_message_end_build(struct cli_state *cli, int grp) { + char *p; + memset(cli->outbuf,'\0',smb_size); set_message(cli->outbuf,1,0,True); SCVAL(cli->outbuf,smb_com,SMBsendend); @@ -117,7 +134,16 @@ BOOL cli_message_end(struct cli_state *cli, int grp) SSVAL(cli->outbuf,smb_vwv0,grp); cli_setup_packet(cli); - + + p = smb_buf(cli->outbuf); + + return(PTR_DIFF(p, cli->outbuf)); +} + +BOOL cli_message_end(struct cli_state *cli, int grp) +{ + cli_message_end_build(cli, grp); + cli_send_smb(cli); if (!cli_receive_smb(cli)) { diff --git a/source3/libsmb/clirap.c b/source3/libsmb/clirap.c index 9d4411797d..a307ac6ccf 100644 --- a/source3/libsmb/clirap.c +++ b/source3/libsmb/clirap.c @@ -92,13 +92,13 @@ BOOL cli_NetWkstaUserLogon(struct cli_state *cli,char *user, char *workstation) SSVAL(p,0,1); p += 2; pstrcpy_base(p,user,param); - strupper(p); + strupper_m(p); p += 21; p++; p += 15; p++; pstrcpy_base(p, workstation, param); - strupper(p); + strupper_m(p); p += 16; SSVAL(p, 0, CLI_BUFFER_SIZE); p += 2; diff --git a/source3/libsmb/clirap2.c b/source3/libsmb/clirap2.c index 948e88061a..669b33860d 100644 --- a/source3/libsmb/clirap2.c +++ b/source3/libsmb/clirap2.c @@ -1396,11 +1396,11 @@ BOOL cli_NetWkstaUserLogoff(struct cli_state *cli,char *user, char *workstation) PUTDWORD(p, 0); /* Null pointer */ PUTDWORD(p, 0); /* Null pointer */ fstrcpy(upperbuf, user); - strupper(upperbuf); + strupper_m(upperbuf); PUTSTRINGF(p, upperbuf, RAP_USERNAME_LEN); p++; /* strange format, but ok */ fstrcpy(upperbuf, workstation); - strupper(upperbuf); + strupper_m(upperbuf); PUTSTRINGF(p, upperbuf, RAP_MACHNAME_LEN); PUTWORD(p, CLI_BUFFER_SIZE); PUTWORD(p, CLI_BUFFER_SIZE); diff --git a/source3/libsmb/clispnego.c b/source3/libsmb/clispnego.c index 53f7eb6e7d..bb48f57915 100644 --- a/source3/libsmb/clispnego.c +++ b/source3/libsmb/clispnego.c @@ -329,7 +329,7 @@ DATA_BLOB spnego_gen_negTokenTarg(const char *principal, int time_offset) const char *krb_mechs[] = {OID_KERBEROS5_OLD, OID_NTLMSSP, NULL}; /* get a kerberos ticket for the service */ - tkt = krb5_get_ticket(principal, time_offset); + tkt = cli_krb5_get_ticket(principal, time_offset); /* wrap that up in a nice GSS-API wrapping */ tkt_wrapped = spnego_gen_krb5_wrap(tkt, TOK_ID_KRB_AP_REQ); diff --git a/source3/libsmb/namecache.c b/source3/libsmb/namecache.c index d3541b7719..e3e7ac4e3c 100644 --- a/source3/libsmb/namecache.c +++ b/source3/libsmb/namecache.c @@ -113,7 +113,7 @@ static char* namecache_key(const char *name, int name_type) **/ BOOL namecache_store(const char *name, int name_type, - int num_names, struct in_addr *ip_list) + int num_names, struct ip_service *ip_list) { time_t expiry; char *key, *value_string; @@ -126,27 +126,19 @@ BOOL namecache_store(const char *name, int name_type, */ if (!gencache_init()) return False; - DEBUG(5, ("namecache_store: storing %d address%s for %s#%02x: ", - num_names, num_names == 1 ? "": "es", name, name_type)); - - for (i = 0; i < num_names; i++) - DEBUGADD(5, ("%s%s", inet_ntoa(ip_list[i]), - i == (num_names - 1) ? "" : ", ")); - - DEBUGADD(5, ("\n")); + if ( DEBUGLEVEL >= 5 ) { + DEBUG(5, ("namecache_store: storing %d address%s for %s#%02x: ", + num_names, num_names == 1 ? "": "es", name, name_type)); + for (i = 0; i < num_names; i++) + DEBUGADD(5, ("%s:%d%s", inet_ntoa(ip_list[i].ip), + ip_list[i].port, (i == (num_names - 1) ? "" : ","))); + + DEBUGADD(5, ("\n")); + } + key = namecache_key(name, name_type); - - /* - * Cache pdc location or dc lists for only a little while - * otherwise if we lock on to a bad DC we can potentially be - * out of action for the entire cache timeout time! - */ - - if (name_type == 0x1b || name_type == 0x1c) - expiry = time(NULL) + 10; - else - expiry = time(NULL) + lp_name_cache_timeout(); + expiry = time(NULL) + lp_name_cache_timeout(); /* * Generate string representation of ip addresses list @@ -180,7 +172,7 @@ BOOL namecache_store(const char *name, int name_type, * false if name isn't found in the cache or has expired **/ -BOOL namecache_fetch(const char *name, int name_type, struct in_addr **ip_list, +BOOL namecache_fetch(const char *name, int name_type, struct ip_service **ip_list, int *num_names) { char *key, *value; @@ -201,7 +193,9 @@ BOOL namecache_fetch(const char *name, int name_type, struct in_addr **ip_list, if (!gencache_get(key, &value, &timeout)) { DEBUG(5, ("no entry for %s#%02X found.\n", name, name_type)); + gencache_del(key); SAFE_FREE(key); + SAFE_FREE(value); return False; } else { DEBUG(5, ("name %s#%02X found.\n", name, name_type)); @@ -213,7 +207,8 @@ BOOL namecache_fetch(const char *name, int name_type, struct in_addr **ip_list, *num_names = ipstr_list_parse(value, ip_list); SAFE_FREE(key); - SAFE_FREE(value); + SAFE_FREE(value); + return *num_names > 0; /* true only if some ip has been fetched */ } @@ -252,3 +247,75 @@ void namecache_flush(void) DEBUG(5, ("Namecache flushed\n")); } +/* Construct a name status record key. */ + +static char *namecache_status_record_key(const char *name, int name_type1, + int name_type2, struct in_addr keyip) +{ + char *keystr; + + asprintf(&keystr, "NBT/%s#%02X.%02X.%s", + strupper_static(name), name_type1, name_type2, inet_ntoa(keyip)); + return keystr; +} + +/* Store a name status record. */ + +BOOL namecache_status_store(const char *keyname, int keyname_type, + int name_type, struct in_addr keyip, + const char *srvname) +{ + char *key; + time_t expiry; + BOOL ret; + + if (!gencache_init()) + return False; + + key = namecache_status_record_key(keyname, keyname_type, name_type, keyip); + if (!key) + return False; + + expiry = time(NULL) + lp_name_cache_timeout(); + ret = gencache_set(key, srvname, expiry); + + if (ret) + DEBUG(5, ("namecache_status_store: entry %s -> %s\n", key, srvname )); + else + DEBUG(5, ("namecache_status_store: entry %s store failed.\n", key )); + + SAFE_FREE(key); + return ret; +} + +/* Fetch a name status record. */ + +BOOL namecache_status_fetch(const char *keyname, int keyname_type, + int name_type, struct in_addr keyip, char *srvname_out) +{ + char *key = NULL; + char *value = NULL; + time_t timeout; + + if (!gencache_init()) + return False; + + key = namecache_status_record_key(keyname, keyname_type, name_type, keyip); + if (!key) + return False; + + if (!gencache_get(key, &value, &timeout)) { + DEBUG(5, ("namecache_status_fetch: no entry for %s found.\n", key)); + gencache_del(key); + SAFE_FREE(key); + SAFE_FREE(value); + return False; + } else { + DEBUG(5, ("namecache_status_fetch: key %s -> %s\n", key, value )); + } + + strlcpy(srvname_out, value, 16); + SAFE_FREE(key); + SAFE_FREE(value); + return True; +} diff --git a/source3/libsmb/namequery.c b/source3/libsmb/namequery.c index 18ce5e4bd9..9875f77c72 100644 --- a/source3/libsmb/namequery.c +++ b/source3/libsmb/namequery.c @@ -25,8 +25,9 @@ BOOL global_in_nmbd = False; /**************************************************************************** -generate a random trn_id + Generate a random trn_id. ****************************************************************************/ + static int generate_trn_id(void) { static int trn_id; @@ -40,10 +41,10 @@ static int generate_trn_id(void) return trn_id % (unsigned)0x7FFF; } - /**************************************************************************** - parse a node status response into an array of structures + Parse a node status response into an array of structures. ****************************************************************************/ + static struct node_status *parse_node_status(char *p, int *num_names) { struct node_status *ret; @@ -51,7 +52,8 @@ static struct node_status *parse_node_status(char *p, int *num_names) *num_names = CVAL(p,0); - if (*num_names == 0) return NULL; + if (*num_names == 0) + return NULL; ret = (struct node_status *)malloc(sizeof(struct node_status)* (*num_names)); if (!ret) return NULL; @@ -71,9 +73,10 @@ static struct node_status *parse_node_status(char *p, int *num_names) /**************************************************************************** -do a NBT node status query on an open socket and return an array of -structures holding the returned names or NULL if the query failed + Do a NBT node status query on an open socket and return an array of + structures holding the returned names or NULL if the query failed. **************************************************************************/ + struct node_status *node_status_query(int fd,struct nmb_name *name, struct in_addr to_ip, int *num_names) { @@ -155,11 +158,9 @@ struct node_status *node_status_query(int fd,struct nmb_name *name, return NULL; } - /**************************************************************************** -find the first type XX name in a node status reply - used for finding -a servers name given its IP -return the matched name in *name + Find the first type XX name in a node status reply - used for finding + a servers name given its IP. Return the matched name in *name. **************************************************************************/ BOOL name_status_find(const char *q_name, int q_type, int type, struct in_addr to_ip, char *name) @@ -178,6 +179,11 @@ BOOL name_status_find(const char *q_name, int q_type, int type, struct in_addr t DEBUG(10, ("name_status_find: looking up %s#%02x at %s\n", q_name, q_type, inet_ntoa(to_ip))); + /* Check the cache first. */ + + if (namecache_status_fetch(q_name, q_type, type, to_ip, name)) + return True; + sock = open_socket_in(SOCK_DGRAM, 0, 3, interpret_addr(lp_socket_address()), True); if (sock == -1) goto done; @@ -197,6 +203,14 @@ BOOL name_status_find(const char *q_name, int q_type, int type, struct in_addr t goto done; pull_ascii(name, status[i].name, 16, 15, STR_TERMINATE); + + /* Store the result in the cache. */ + /* but don't store an entry for 0x1c names here. Here we have + a single host and DOMAIN<0x1c> names should be a list of hosts */ + + if ( q_type != 0x1c ) + namecache_status_store(q_name, q_type, type, to_ip, name); + result = True; done: @@ -205,17 +219,17 @@ BOOL name_status_find(const char *q_name, int q_type, int type, struct in_addr t DEBUG(10, ("name_status_find: name %sfound", result ? "" : "not ")); if (result) - DEBUGADD(10, (", ip address is %s", inet_ntoa(to_ip))); + DEBUGADD(10, (", name %s ip address is %s", name, inet_ntoa(to_ip))); DEBUG(10, ("\n")); return result; } - /* comparison function used by sort_ip_list */ + int ip_compare(struct in_addr *ip1, struct in_addr *ip2) { int max_bits1=0, max_bits2=0; @@ -243,11 +257,32 @@ int ip_compare(struct in_addr *ip1, struct in_addr *ip2) return max_bits2 - max_bits1; } +/******************************************************************* + compare 2 ldap IPs by nearness to our interfaces - used in qsort +*******************************************************************/ + +static int ip_service_compare(struct ip_service *ip1, struct ip_service *ip2) +{ + int result; + + if ( (result = ip_compare(&ip1->ip, &ip2->ip)) != 0 ) + return result; + + if ( ip1->port > ip2->port ) + return 1; + + if ( ip1->port < ip2->port ) + return -1; + + return 0; +} + /* sort an IP list so that names that are close to one of our interfaces are at the top. This prevents the problem where a WINS server returns an IP that is not reachable from our subnet as the first match */ + static void sort_ip_list(struct in_addr *iplist, int count) { if (count <= 1) { @@ -257,6 +292,50 @@ static void sort_ip_list(struct in_addr *iplist, int count) qsort(iplist, count, sizeof(struct in_addr), QSORT_CAST ip_compare); } +void sort_ip_list2(struct ip_service *iplist, int count) +{ + if (count <= 1) { + return; + } + + qsort(iplist, count, sizeof(struct ip_service), QSORT_CAST ip_service_compare); +} + +/********************************************************************** + Remove any duplicate address/port pairs in the list + *********************************************************************/ + +static int remove_duplicate_addrs2( struct ip_service *iplist, int count ) +{ + int i, j; + + DEBUG(10,("remove_duplicate_addrs2: looking for duplicate address/port pairs\n")); + + /* one loop to remove duplicates */ + for ( i=0; i if we are using ADS */ + if ( lp_security() != SEC_ADS ) + return False; + + DEBUG(5,("resolve_hosts: Attempting to resolve DC's for %s using DNS\n", + name)); + + if (ldap_domain2hostlist(name, &list) != LDAP_SUCCESS) + return False; + + count = count_chars(list, ' ') + 1; + if ( (*return_iplist = malloc(count * sizeof(struct ip_service))) == NULL ) { + DEBUG(0,("resolve_hosts: malloc failed for %d entries\n", count )); + return False; + } + + ptr = list; + while (next_token(&ptr, tok, " ", sizeof(tok))) { + unsigned port = LDAP_PORT; + char *p = strchr(tok, ':'); + if (p) { + *p = 0; + port = atoi(p+1); + } + (*return_iplist)[i].ip = *interpret_addr2(tok); + (*return_iplist)[i].port = port; + + /* make sure it is a valid IP. I considered checking the negative + connection cache, but this is the wrong place for it. Maybe only + as a hac. After think about it, if all of the IP addresses retuend + from DNS are dead, what hope does a netbios name lookup have? + The standard reason for falling back to netbios lookups is that + our DNS server doesn't know anything about the DC's -- jerry */ + + if ( is_zero_ip((*return_iplist)[i].ip) ) + continue; + + i++; + } + SAFE_FREE(list); + + *return_count = i; + + return True; + } +#endif /* HAVE_ADS */ *return_iplist = NULL; *return_count = 0; @@ -764,27 +946,33 @@ static BOOL resolve_hosts(const char *name, if (((hp = sys_gethostbyname(name)) != NULL) && (hp->h_addr != NULL)) { struct in_addr return_ip; putip((char *)&return_ip,(char *)hp->h_addr); - *return_iplist = (struct in_addr *)malloc(sizeof(struct in_addr)); + *return_iplist = (struct ip_service *)malloc(sizeof(struct ip_service)); if(*return_iplist == NULL) { DEBUG(3,("resolve_hosts: malloc fail !\n")); return False; } - **return_iplist = return_ip; + (*return_iplist)->ip = return_ip; + (*return_iplist)->port = PORT_NONE; *return_count = 1; return True; } return False; } -/******************************************************** +/******************************************************************* Internal interface to resolve a name into an IP address. Use this function if the string is either an IP address, DNS or host name or NetBIOS name. This uses the name switch in the smb.conf to determine the order of name resolution. -*********************************************************/ + + Added support for ip addr/port to support ADS ldap servers. + the only place we currently care about the port is in the + resolve_hosts() when looking up DC's via SRV RR entries in DNS +**********************************************************************/ static BOOL internal_resolve_name(const char *name, int name_type, - struct in_addr **return_iplist, int *return_count) + struct ip_service **return_iplist, + int *return_count, const char *resolve_order) { pstring name_resolve_list; fstring tok; @@ -793,7 +981,6 @@ static BOOL internal_resolve_name(const char *name, int name_type, BOOL allzeros = (strcmp(name,"0.0.0.0") == 0); BOOL is_address = is_ipaddress(name); BOOL result = False; - struct in_addr *nodupes_iplist; int i; *return_iplist = NULL; @@ -802,42 +989,56 @@ static BOOL internal_resolve_name(const char *name, int name_type, DEBUG(10, ("internal_resolve_name: looking up %s#%x\n", name, name_type)); if (allzeros || allones || is_address) { - *return_iplist = (struct in_addr *)malloc(sizeof(struct in_addr)); - if(*return_iplist == NULL) { - DEBUG(3,("internal_resolve_name: malloc fail !\n")); + + if ( (*return_iplist = (struct ip_service *)malloc(sizeof(struct ip_service))) == NULL ) { + DEBUG(0,("internal_resolve_name: malloc fail !\n")); return False; } + if(is_address) { + /* ignore the port here */ + (*return_iplist)->port = PORT_NONE; + /* if it's in the form of an IP address then get the lib to interpret it */ - if (((*return_iplist)->s_addr = inet_addr(name)) == 0xFFFFFFFF ){ + if (((*return_iplist)->ip.s_addr = inet_addr(name)) == 0xFFFFFFFF ){ DEBUG(1,("internal_resolve_name: inet_addr failed on %s\n", name)); return False; } } else { - (*return_iplist)->s_addr = allones ? 0xFFFFFFFF : 0; + (*return_iplist)->ip.s_addr = allones ? 0xFFFFFFFF : 0; *return_count = 1; } return True; } - /* Check netbios name cache */ + /* Check name cache */ if (namecache_fetch(name, name_type, return_iplist, return_count)) { - - /* This could be a negative response */ - - return (*return_count > 0); + /* This could be a negative response */ + return (*return_count > 0); } - pstrcpy(name_resolve_list, lp_name_resolve_order()); - ptr = name_resolve_list; - if (!ptr || !*ptr) + /* set the name resolution order */ + + if ( !resolve_order ) + pstrcpy(name_resolve_list, lp_name_resolve_order()); + else + pstrcpy(name_resolve_list, resolve_order); + + if ( !name_resolve_list[0] ) ptr = "host"; + else + ptr = name_resolve_list; + /* iterate through the name resolution backends */ + while (next_token(&ptr, tok, LIST_SEP, sizeof(tok))) { if((strequal(tok, "host") || strequal(tok, "hosts"))) { - if (name_type == 0x20) { - if (resolve_hosts(name, return_iplist, return_count)) { + /* deal with 0x20 & 0x1c names here. The latter will result + in a SRV record lookup for _ldap._tcp. if we are using + 'security = ads' */ + if ( name_type==0x20 || name_type == 0x1c ) { + if (resolve_hosts(name, name_type, return_iplist, return_count)) { result = True; goto done; } @@ -878,58 +1079,31 @@ static BOOL internal_resolve_name(const char *name, int name_type, controllers including the PDC in iplist[1..n]. Iterating over the iplist when the PDC is down will cause two sets of timeouts. */ - if (*return_count && (nodupes_iplist = (struct in_addr *) - malloc(sizeof(struct in_addr) * (*return_count)))) { - int nodupes_count = 0; - - /* Iterate over return_iplist looking for duplicates */ - - for (i = 0; i < *return_count; i++) { - BOOL is_dupe = False; - int j; - - for (j = i + 1; j < *return_count; j++) { - if (ip_equal((*return_iplist)[i], - (*return_iplist)[j])) { - is_dupe = True; - break; - } - } - - if (!is_dupe) { - - /* This one not a duplicate */ - - nodupes_iplist[nodupes_count] = (*return_iplist)[i]; - nodupes_count++; - } - } - - /* Switcheroo with original list */ - - free(*return_iplist); - - *return_iplist = nodupes_iplist; - *return_count = nodupes_count; + if ( *return_count ) { + *return_count = remove_duplicate_addrs2( *return_iplist, *return_count ); } /* Save in name cache */ - for (i = 0; i < *return_count && DEBUGLEVEL == 100; i++) - DEBUG(100, ("Storing name %s of type %d (ip: %s)\n", name, - name_type, inet_ntoa((*return_iplist)[i]))); - + if ( DEBUGLEVEL >= 100 ) { + for (i = 0; i < *return_count && DEBUGLEVEL == 100; i++) + DEBUG(100, ("Storing name %s of type %d (%s:%d)\n", name, + name_type, inet_ntoa((*return_iplist)[i].ip), (*return_iplist)[i].port)); + } + namecache_store(name, name_type, *return_count, *return_iplist); /* Display some debugging info */ - DEBUG(10, ("internal_resolve_name: returning %d addresses: ", - *return_count)); - - for (i = 0; i < *return_count; i++) - DEBUGADD(10, ("%s ", inet_ntoa((*return_iplist)[i]))); + if ( DEBUGLEVEL >= 10 ) { + DEBUG(10, ("internal_resolve_name: returning %d addresses: ", + *return_count)); - DEBUG(10, ("\n")); + for (i = 0; i < *return_count; i++) + DEBUGADD(10, ("%s:%d ", inet_ntoa((*return_iplist)[i].ip), (*return_iplist)[i].port)); + DEBUG(10, ("\n")); + } + return result; } @@ -942,7 +1116,7 @@ static BOOL internal_resolve_name(const char *name, int name_type, BOOL resolve_name(const char *name, struct in_addr *return_ip, int name_type) { - struct in_addr *ip_list = NULL; + struct ip_service *ip_list = NULL; int count = 0; if (is_ipaddress(name)) { @@ -950,20 +1124,23 @@ BOOL resolve_name(const char *name, struct in_addr *return_ip, int name_type) return True; } - if (internal_resolve_name(name, name_type, &ip_list, &count)) { + if (internal_resolve_name(name, name_type, &ip_list, &count, lp_name_resolve_order())) { int i; + /* only return valid addresses for TCP connections */ for (i=0; iheader.msg_type = 0x10; - dgram->header.flags.node_type = M_NODE; - dgram->header.flags.first = True; - dgram->header.flags.more = False; - dgram->header.dgm_id = dgm_id; - dgram->header.source_ip = *iface_ip(*pdc_ip); - dgram->header.source_port = ntohs(sock_name.sin_port); - dgram->header.dgm_length = 0; /* Let build_dgram() handle this. */ - dgram->header.packet_offset = 0; - - make_nmb_name(&dgram->source_name,srcname,0); - make_nmb_name(&dgram->dest_name,domain,0x1C); - - ptr = &dgram->data[0]; - - /* Setup the smb part. */ - ptr -= 4; /* XXX Ugliness because of handling of tcp SMB length. */ - memcpy(tmp,ptr,4); - set_message(ptr,17,17 + len,True); - memcpy(ptr,tmp,4); - - CVAL(ptr,smb_com) = SMBtrans; - SSVAL(ptr,smb_vwv1,len); - SSVAL(ptr,smb_vwv11,len); - SSVAL(ptr,smb_vwv12,70 + strlen(mailslot)); - SSVAL(ptr,smb_vwv13,3); - SSVAL(ptr,smb_vwv14,1); - SSVAL(ptr,smb_vwv15,1); - SSVAL(ptr,smb_vwv16,2); - p2 = smb_buf(ptr); - pstrcpy(p2,mailslot); - p2 = skip_string(p2,1); - - memcpy(p2,buffer,len); - p2 += len; - - dgram->datasize = PTR_DIFF(p2,ptr+4); /* +4 for tcp length. */ - - p.ip = *pdc_ip; - p.port = DGRAM_PORT; - p.fd = sock; - p.timestamp = time(NULL); - p.packet_type = DGRAM_PACKET; - - GetTimeOfDay(&tval); - - if (!send_packet(&p)) { - DEBUG(0,("lookup_pdc_name: send_packet failed.\n")); - close(sock); - return False; - } - - retries--; - - while (1) { - struct timeval tval2; - struct packet_struct *p_ret; - - GetTimeOfDay(&tval2); - if (TvalDiff(&tval,&tval2) > retry_time) { - if (!retries) - break; - if (!send_packet(&p)) { - DEBUG(0,("lookup_pdc_name: send_packet failed.\n")); - close(sock); - return False; - } - GetTimeOfDay(&tval); - retries--; - } - - if ((p_ret = receive_dgram_packet(sock,90,mailslot_name))) { - struct dgram_packet *dgram2 = &p_ret->packet.dgram; - char *buf; - char *buf2; - - buf = &dgram2->data[0]; - buf -= 4; - - if (CVAL(buf,smb_com) != SMBtrans) { - DEBUG(0,("lookup_pdc_name: datagram type %u != SMBtrans(%u)\n", (unsigned int) - CVAL(buf,smb_com), (unsigned int)SMBtrans )); - free_packet(p_ret); - continue; - } - - len = SVAL(buf,smb_vwv11); - buf2 = smb_base(buf) + SVAL(buf,smb_vwv12); - - if (len <= 0) { - DEBUG(0,("lookup_pdc_name: datagram len < 0 (%d)\n", len )); - free_packet(p_ret); - continue; - } - - DEBUG(4,("lookup_pdc_name: datagram reply from %s to %s IP %s for %s of type %d len=%d\n", - nmb_namestr(&dgram2->source_name),nmb_namestr(&dgram2->dest_name), - inet_ntoa(p_ret->ip), smb_buf(buf),SVAL(buf2,0),len)); - - if(SVAL(buf2,0) != QUERYFORPDC_R) { - DEBUG(0,("lookup_pdc_name: datagram type (%u) != QUERYFORPDC_R(%u)\n", - (unsigned int)SVAL(buf,0), (unsigned int)QUERYFORPDC_R )); - free_packet(p_ret); - continue; - } - - buf2 += 2; - /* Note this is safe as it is a bounded strcpy. */ - fstrcpy(ret_name, buf2); - ret_name[sizeof(fstring)-1] = '\0'; - close(sock); - free_packet(p_ret); - return True; - } - } - - close(sock); - return False; -#endif /* defined(I_HATE_WINDOWS_REPLY_CODE) */ -} - /******************************************************** Get the IP address list of the primary domain controller for a domain. @@ -1215,68 +1181,81 @@ NT GETDC call, UNICODE, NT domain SID and uncle tom cobbley and all... BOOL get_pdc_ip(const char *domain, struct in_addr *ip) { - struct in_addr *ip_list; + struct ip_service *ip_list; int count; - int i = 0; /* Look up #1B name */ - if (!internal_resolve_name(domain, 0x1b, &ip_list, &count)) + if (!internal_resolve_name(domain, 0x1b, &ip_list, &count, lp_name_resolve_order())) return False; /* if we get more than 1 IP back we have to assume it is a multi-homed PDC and not a mess up */ - + if ( count > 1 ) { - DEBUG(6,("get_pdc_ip: PDC has %d IP addresses!\n", count)); - - /* look for a local net */ - for ( i=0; i= 4 ) { + DEBUG(4,("get_dc_list: returning %d ip addresses in an %sordered list\n", local_count, + *ordered ? "":"un")); + DEBUG(4,("get_dc_list: ")); + for ( i=0; iauth.flags |= ADS_AUTH_NO_BIND; + + DEBUG(4,("ads_dc_name: domain=%s\n", domain)); + +#ifdef HAVE_ADS + /* a full ads_connect() is actually overkill, as we don't srictly need + to do the SASL auth in order to get the info we need, but libads + doesn't offer a better way right now */ + ads_connect(ads); +#endif + + if (!ads->config.realm) + return False; + + fstrcpy(srv_name, ads->config.ldap_server_name); + strupper_m(srv_name); + *dc_ip = ads->ldap_ip; + ads_destroy(&ads); + + DEBUG(4,("ads_dc_name: using server='%s' IP=%s\n", + srv_name, inet_ntoa(*dc_ip))); + + return True; +} + +/**************************************************************************** + Utility function to return the name of a DC. The name is guaranteed to be + valid since we have already done a name_status_find on it + ***************************************************************************/ + +static BOOL rpc_dc_name(const char *domain, fstring srv_name, struct in_addr *ip_out) { - struct in_addr *ip_list = NULL, dc_ip, exclude_ip; + struct ip_service *ip_list = NULL; + struct in_addr dc_ip, exclude_ip; int count, i; - BOOL list_ordered; BOOL use_pdc_only; + NTSTATUS result; zero_ip(&exclude_ip); @@ -41,11 +86,17 @@ BOOL rpc_find_dc(const char *domain, fstring srv_name, struct in_addr *ip_out) /* Lookup domain controller name */ - if ( use_pdc_only && get_pdc_ip(domain, &dc_ip) ) { - DEBUG(10,("rpc_find_dc: Atempting to lookup PDC to avoid sam sync delays\n")); + if ( use_pdc_only && get_pdc_ip(domain, &dc_ip) ) + { + DEBUG(10,("rpc_dc_name: Atempting to lookup PDC to avoid sam sync delays\n")); - if (name_status_find(domain, 0x1c, 0x20, dc_ip, srv_name)) { - goto done; + /* check the connection cache and perform the node status + lookup only if the IP is not found to be bad */ + + if (name_status_find(domain, 0x1b, 0x20, dc_ip, srv_name) ) { + result = check_negative_conn_cache( domain, srv_name ); + if ( NT_STATUS_IS_OK(result) ) + goto done; } /* Didn't get name, remember not to talk to this DC. */ exclude_ip = dc_ip; @@ -53,7 +104,7 @@ BOOL rpc_find_dc(const char *domain, fstring srv_name, struct in_addr *ip_out) /* get a list of all domain controllers */ - if (!get_dc_list( domain, &ip_list, &count, &list_ordered) ) { + if ( !get_sorted_dc_list(domain, &ip_list, &count, False) ) { DEBUG(3, ("Could not look up dc's for domain %s\n", domain)); return False; } @@ -62,37 +113,37 @@ BOOL rpc_find_dc(const char *domain, fstring srv_name, struct in_addr *ip_out) if ( use_pdc_only ) { for (i = 0; i < count; i++) { - if (ip_equal( exclude_ip, ip_list[i])) - zero_ip(&ip_list[i]); + if (ip_equal( exclude_ip, ip_list[i].ip)) + zero_ip(&ip_list[i].ip); } } - /* Pick a nice close server, but only if the list was not ordered */ - if (!list_ordered && (count > 1) ) { - qsort(ip_list, count, sizeof(struct in_addr), QSORT_CAST ip_compare); - } - for (i = 0; i < count; i++) { - if (is_zero_ip(ip_list[i])) + if (is_zero_ip(ip_list[i].ip)) continue; - if (name_status_find(domain, 0x1c, 0x20, ip_list[i], srv_name)) { - dc_ip = ip_list[i]; - goto done; + if (name_status_find(domain, 0x1c, 0x20, ip_list[i].ip, srv_name)) { + result = check_negative_conn_cache( domain, srv_name ); + if ( NT_STATUS_IS_OK(result) ) { + dc_ip = ip_list[i].ip; + goto done; + } } } - + SAFE_FREE(ip_list); - return False; -done: + /* No-one to talk to )-: */ + return False; /* Boo-hoo */ + + done: /* We have the netbios name and IP address of a domain controller. Ideally we should sent a SAMLOGON request to determine whether the DC is alive and kicking. If we can catch a dead DC before performing a cli_connect() we can avoid a 30-second timeout. */ - DEBUG(3, ("rpc_find_dc: Returning DC %s (%s) for domain %s\n", srv_name, + DEBUG(3, ("rpc_dc_name: Returning DC %s (%s) for domain %s\n", srv_name, inet_ntoa(dc_ip), domain)); *ip_out = dc_ip; @@ -102,3 +153,28 @@ done: return True; } +/********************************************************************** + wrapper around ads and rpc methods of finds DC's +**********************************************************************/ + +BOOL get_dc_name(const char *domain, fstring srv_name, struct in_addr *ip_out) +{ + struct in_addr dc_ip; + BOOL ret; + + zero_ip(&dc_ip); + + ret = False; + if (lp_security() == SEC_ADS) + ret = ads_dc_name(domain, &dc_ip, srv_name); + + if (!ret) { + /* fall back on rpc methods if the ADS methods fail */ + ret = rpc_dc_name(domain, srv_name, &dc_ip); + } + + *ip_out = dc_ip; + + return ret; +} + diff --git a/source3/libsmb/nmblib.c b/source3/libsmb/nmblib.c index 30ce5b6b10..157a2bb43c 100644 --- a/source3/libsmb/nmblib.c +++ b/source3/libsmb/nmblib.c @@ -295,7 +295,7 @@ static int put_nmb_name(char *buf,int offset,struct nmb_name *name) if (name->scope[0]) { /* XXXX this scope handling needs testing */ ret += strlen(name->scope) + 1; - pstrcpy(&buf[offset+1],name->scope); + safe_strcpy(&buf[offset+1],name->scope,sizeof(name->scope)); p = &buf[offset+1]; while ((p = strchr_m(p,'.'))) { @@ -823,7 +823,7 @@ void make_nmb_name( struct nmb_name *n, const char *name, int type) push_ascii(n->name, name, 16, STR_TERMINATE|STR_UPPER); n->name_type = (unsigned int)type & 0xFF; StrnCpy( n->scope, global_scope(), 63 ); - strupper( n->scope ); + strupper_m( n->scope ); } /******************************************************************* diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index d54655d17f..66dc6e08eb 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -175,11 +175,11 @@ static NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state, /* This should be a 'netbios domain -> DNS domain' mapping */ dnsdomname[0] = '\0'; get_mydomname(dnsdomname); - strlower(dnsdomname); + strlower_m(dnsdomname); dnsname[0] = '\0'; get_myfullname(dnsname); - strlower(dnsname); + strlower_m(dnsname); if (chal_flags & NTLMSSP_CHAL_TARGET_INFO) { @@ -190,7 +190,6 @@ static NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state, target_name_dns = dnsname; } - /* the numbers here are the string type flags */ msrpc_gen(&struct_blob, "aaaaa", ntlmssp_state->unicode, NTLMSSP_NAME_TYPE_DOMAIN, target_name, ntlmssp_state->unicode, NTLMSSP_NAME_TYPE_SERVER, ntlmssp_state->get_global_myname(), @@ -410,6 +409,10 @@ static NTSTATUS ntlmssp_client_initial(struct ntlmssp_client_state *ntlmssp_stat ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_UNICODE; } + if (ntlmssp_state->use_ntlmv2) { + ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_NTLM2; + } + /* generate the ntlmssp negotiate packet */ msrpc_gen(next_request, "CddAA", "NTLMSSP", @@ -436,7 +439,7 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st uint32 chal_flags, ntlmssp_command, unkn1, unkn2; DATA_BLOB server_domain_blob; DATA_BLOB challenge_blob; - DATA_BLOB struct_blob; + DATA_BLOB struct_blob = data_blob(NULL, 0); char *server_domain; const char *chal_parse_string; const char *auth_gen_string; @@ -444,28 +447,48 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st DATA_BLOB nt_response = data_blob(NULL, 0); DATA_BLOB session_key = data_blob(NULL, 0); uint8 datagram_sess_key[16]; + size_t datagram_sess_key_len; +#if 0 /* until we know what flag to tigger it on */ generate_random_buffer(datagram_sess_key, sizeof(datagram_sess_key), False); + datagram_sess_key_len = sizeof(datagram_sess_key); +#else + ZERO_STRUCT(datagram_sess_key); + datagram_sess_key_len = 0; +#endif if (!msrpc_parse(&reply, "CdBd", "NTLMSSP", &ntlmssp_command, &server_domain_blob, &chal_flags)) { - DEBUG(0, ("Failed to parse the NTLMSSP Challenge\n")); + DEBUG(1, ("Failed to parse the NTLMSSP Challenge: (#1)\n")); + dump_data(2, reply.data, reply.length); + return NT_STATUS_INVALID_PARAMETER; } data_blob_free(&server_domain_blob); + DEBUG(3, ("Got challenge flags:\n")); + debug_ntlmssp_flags(chal_flags); + if (chal_flags & NTLMSSP_NEGOTIATE_UNICODE) { - chal_parse_string = "CdUdbddB"; + if (chal_flags & NTLMSSP_CHAL_TARGET_INFO) { + chal_parse_string = "CdUdbddB"; + } else { + chal_parse_string = "CdUdbdd"; + } auth_gen_string = "CdBBUUUBd"; ntlmssp_state->unicode = True; ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_UNICODE; ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_OEM; } else if (chal_flags & NTLMSSP_NEGOTIATE_OEM) { - chal_parse_string = "CdAdbddB"; + if (chal_flags & NTLMSSP_CHAL_TARGET_INFO) { + chal_parse_string = "CdAdbddB"; + } else { + chal_parse_string = "CdAdbdd"; + } auth_gen_string = "CdBBAAABd"; ntlmssp_state->unicode = False; ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_UNICODE; @@ -474,6 +497,25 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st return NT_STATUS_INVALID_PARAMETER; } + if (chal_flags & NTLMSSP_NEGOTIATE_LM_KEY && lp_client_lanman_auth()) { + /* server forcing us to use LM */ + ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_LM_KEY; + ntlmssp_state->use_ntlmv2 = False; + } else { + ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY; + } + + if (!(chal_flags & NTLMSSP_NEGOTIATE_NTLM2)) { + ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_NTLM2; + } + + if (!(chal_flags & NTLMSSP_NEGOTIATE_128)) { + ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_128; + } + + DEBUG(3, ("NTLMSSP: Set final flags:\n")); + debug_ntlmssp_flags(ntlmssp_state->neg_flags); + if (!msrpc_parse(&reply, chal_parse_string, "NTLMSSP", &ntlmssp_command, @@ -482,34 +524,43 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st &challenge_blob, 8, &unkn1, &unkn2, &struct_blob)) { - DEBUG(0, ("Failed to parse the NTLMSSP Challenge\n")); + DEBUG(1, ("Failed to parse the NTLMSSP Challenge: (#2)\n")); + dump_data(2, reply.data, reply.length); return NT_STATUS_INVALID_PARAMETER; } SAFE_FREE(server_domain); - data_blob_free(&struct_blob); - if (challenge_blob.length != 8) { + data_blob_free(&struct_blob); return NT_STATUS_INVALID_PARAMETER; } if (ntlmssp_state->use_ntlmv2) { + if (!struct_blob.length) { + /* be lazy, match win2k - we can't do NTLMv2 without it */ + return NT_STATUS_INVALID_PARAMETER; + } + /* TODO: if the remote server is standalone, then we should replace 'domain' with the server name as supplied above */ if (!SMBNTLMv2encrypt(ntlmssp_state->user, ntlmssp_state->domain, - ntlmssp_state->password, challenge_blob, + ntlmssp_state->password, &challenge_blob, + &struct_blob, &lm_response, &nt_response, &session_key)) { data_blob_free(&challenge_blob); + data_blob_free(&struct_blob); return NT_STATUS_NO_MEMORY; } } else { + uchar lm_hash[16]; uchar nt_hash[16]; + E_deshash(ntlmssp_state->password, lm_hash); E_md4hash(ntlmssp_state->password, nt_hash); - /* non encrypted password supplied. Ignore ntpass. */ + /* lanman auth is insecure, it may be disabled */ if (lp_client_lanman_auth()) { lm_response = data_blob(NULL, 24); SMBencrypt(ntlmssp_state->password,challenge_blob.data, @@ -519,9 +570,17 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st nt_response = data_blob(NULL, 24); SMBNTencrypt(ntlmssp_state->password,challenge_blob.data, nt_response.data); + session_key = data_blob(NULL, 16); - SMBsesskeygen_ntv1(nt_hash, NULL, session_key.data); + if ((ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_LM_KEY) + && lp_client_lanman_auth()) { + SMBsesskeygen_lmv1(lm_hash, lm_response.data, + session_key.data); + } else { + SMBsesskeygen_ntv1(nt_hash, NULL, session_key.data); + } } + data_blob_free(&struct_blob); /* this generates the actual auth packet */ if (!msrpc_gen(next_request, auth_gen_string, @@ -532,7 +591,7 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st ntlmssp_state->domain, ntlmssp_state->user, ntlmssp_state->get_global_myname(), - datagram_sess_key, 16, + datagram_sess_key, datagram_sess_key_len, ntlmssp_state->neg_flags)) { data_blob_free(&lm_response); @@ -574,6 +633,8 @@ NTSTATUS ntlmssp_client_start(NTLMSSP_CLIENT_STATE **ntlmssp_state) (*ntlmssp_state)->unicode = True; + (*ntlmssp_state)->use_ntlmv2 = lp_client_ntlmv2_auth(); + (*ntlmssp_state)->neg_flags = NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_NTLM | @@ -595,6 +656,7 @@ NTSTATUS ntlmssp_client_end(NTLMSSP_CLIENT_STATE **ntlmssp_state) data_blob_free(&(*ntlmssp_state)->lm_resp); data_blob_free(&(*ntlmssp_state)->nt_resp); data_blob_free(&(*ntlmssp_state)->session_key); + data_blob_free(&(*ntlmssp_state)->stored_response); talloc_destroy(mem_ctx); } @@ -605,12 +667,18 @@ NTSTATUS ntlmssp_client_end(NTLMSSP_CLIENT_STATE **ntlmssp_state) NTSTATUS ntlmssp_client_update(NTLMSSP_CLIENT_STATE *ntlmssp_state, DATA_BLOB reply, DATA_BLOB *next_request) { + NTSTATUS nt_status = NT_STATUS_INVALID_PARAMETER; uint32 ntlmssp_command; *next_request = data_blob(NULL, 0); if (!reply.length) { - return ntlmssp_client_initial(ntlmssp_state, reply, next_request); - } + /* If there is a cached reply, use it - otherwise this is the first packet */ + if (!ntlmssp_state->stored_response.length) { + return ntlmssp_client_initial(ntlmssp_state, reply, next_request); + } + + reply = ntlmssp_state->stored_response; + } if (!msrpc_parse(&reply, "Cd", "NTLMSSP", @@ -619,9 +687,12 @@ NTSTATUS ntlmssp_client_update(NTLMSSP_CLIENT_STATE *ntlmssp_state, } if (ntlmssp_command == NTLMSSP_CHALLENGE) { - return ntlmssp_client_challenge(ntlmssp_state, reply, next_request); + nt_status = ntlmssp_client_challenge(ntlmssp_state, reply, next_request); + } + if (ntlmssp_state->stored_response.length) { + data_blob_free(&ntlmssp_state->stored_response); } - return NT_STATUS_INVALID_PARAMETER; + return nt_status; } NTSTATUS ntlmssp_set_username(NTLMSSP_CLIENT_STATE *ntlmssp_state, const char *user) @@ -650,3 +721,16 @@ NTSTATUS ntlmssp_set_domain(NTLMSSP_CLIENT_STATE *ntlmssp_state, const char *dom } return NT_STATUS_OK; } + +/** + * Store a DATA_BLOB containing an NTLMSSP response, for use later. + * This 'keeps' the data blob - the caller must *not* free it. + */ + +NTSTATUS ntlmssp_client_store_response(NTLMSSP_CLIENT_STATE *ntlmssp_state, + DATA_BLOB response) +{ + data_blob_free(&ntlmssp_state->stored_response); + ntlmssp_state->stored_response = response; + return NT_STATUS_OK; +} diff --git a/source3/libsmb/ntlmssp_parse.c b/source3/libsmb/ntlmssp_parse.c index ac779a3906..f53afcdcd0 100644 --- a/source3/libsmb/ntlmssp_parse.c +++ b/source3/libsmb/ntlmssp_parse.c @@ -220,23 +220,27 @@ BOOL msrpc_parse(const DATA_BLOB *blob, len2 = SVAL(blob->data, head_ofs); head_ofs += 2; ptr = IVAL(blob->data, head_ofs); head_ofs += 4; - /* make sure its in the right format - be strict */ - if (len1 != len2 || ptr + len1 > blob->length) { - return False; - } - if (len1 & 1) { - /* if odd length and unicode */ - return False; - } - ps = va_arg(ap, char **); - if (0 < len1) { - pull_string(NULL, p, blob->data + ptr, sizeof(p), - len1, - STR_UNICODE|STR_NOALIGN); - (*ps) = smb_xstrdup(p); + if (len1 == 0 && len2 == 0) { + *ps = smb_xstrdup(""); } else { - (*ps) = smb_xstrdup(""); + /* make sure its in the right format - be strict */ + if (len1 != len2 || ptr + len1 > blob->length) { + return False; + } + if (len1 & 1) { + /* if odd length and unicode */ + return False; + } + + if (0 < len1) { + pull_string(NULL, p, blob->data + ptr, sizeof(p), + len1, + STR_UNICODE|STR_NOALIGN); + (*ps) = smb_xstrdup(p); + } else { + (*ps) = smb_xstrdup(""); + } } break; case 'A': @@ -245,19 +249,23 @@ BOOL msrpc_parse(const DATA_BLOB *blob, len2 = SVAL(blob->data, head_ofs); head_ofs += 2; ptr = IVAL(blob->data, head_ofs); head_ofs += 4; - /* make sure its in the right format - be strict */ - if (len1 != len2 || ptr + len1 > blob->length) { - return False; - } - ps = va_arg(ap, char **); - if (0 < len1) { - pull_string(NULL, p, blob->data + ptr, sizeof(p), - len1, - STR_ASCII|STR_NOALIGN); - (*ps) = smb_xstrdup(p); + /* make sure its in the right format - be strict */ + if (len1 == 0 && len2 == 0) { + *ps = smb_xstrdup(""); } else { - (*ps) = smb_xstrdup(""); + if (len1 != len2 || ptr + len1 > blob->length) { + return False; + } + + if (0 < len1) { + pull_string(NULL, p, blob->data + ptr, sizeof(p), + len1, + STR_ASCII|STR_NOALIGN); + (*ps) = smb_xstrdup(p); + } else { + (*ps) = smb_xstrdup(""); + } } break; case 'B': @@ -265,12 +273,17 @@ BOOL msrpc_parse(const DATA_BLOB *blob, len1 = SVAL(blob->data, head_ofs); head_ofs += 2; len2 = SVAL(blob->data, head_ofs); head_ofs += 2; ptr = IVAL(blob->data, head_ofs); head_ofs += 4; - /* make sure its in the right format - be strict */ - if (len1 != len2 || ptr + len1 > blob->length) { - return False; - } + b = (DATA_BLOB *)va_arg(ap, void *); - *b = data_blob(blob->data + ptr, len1); + if (len1 == 0 && len2 == 0) { + *b = data_blob(NULL, 0); + } else { + /* make sure its in the right format - be strict */ + if (len1 != len2 || ptr + len1 > blob->length) { + return False; + } + *b = data_blob(blob->data + ptr, len1); + } break; case 'b': b = (DATA_BLOB *)va_arg(ap, void *); diff --git a/source3/libsmb/ntlmssp_sign.c b/source3/libsmb/ntlmssp_sign.c index 86faf1f5e6..748c008963 100644 --- a/source3/libsmb/ntlmssp_sign.c +++ b/source3/libsmb/ntlmssp_sign.c @@ -79,13 +79,18 @@ static void calc_hash(unsigned char *hash, const char *k2, int k2l) } static void calc_ntlmv2_hash(unsigned char hash[16], char digest[16], - const char encrypted_response[16], + DATA_BLOB session_key, const char *constant) { struct MD5Context ctx3; + /* NOTE: This code is currently complate fantasy - it's + got more in common with reality than the previous code + (the LM session key is not the right thing to use) but + it still needs work */ + MD5Init(&ctx3); - MD5Update(&ctx3, encrypted_response, 5); + MD5Update(&ctx3, session_key.data, session_key.length); MD5Update(&ctx3, constant, strlen(constant)); MD5Final(digest, &ctx3); @@ -113,25 +118,28 @@ static NTSTATUS ntlmssp_make_packet_signiture(NTLMSSP_CLIENT_STATE *ntlmssp_stat hmac_md5_update(data, length, &ctx); hmac_md5_final(digest, &ctx); - if (!msrpc_gen(sig, "Bd", digest, sizeof(digest), ntlmssp_state->ntlmssp_seq_num)) { + if (!msrpc_gen(sig, "dBd", NTLMSSP_SIGN_VERSION, digest, 8 /* only copy first 8 bytes */ + , ntlmssp_state->ntlmssp_seq_num)) { return NT_STATUS_NO_MEMORY; } switch (direction) { case NTLMSSP_SEND: - NTLMSSPcalc_ap(ntlmssp_state->cli_sign_hash, sig->data, sig->length); + NTLMSSPcalc_ap(ntlmssp_state->cli_sign_hash, sig->data+4, sig->length-4); break; case NTLMSSP_RECEIVE: - NTLMSSPcalc_ap(ntlmssp_state->srv_sign_hash, sig->data, sig->length); + NTLMSSPcalc_ap(ntlmssp_state->srv_sign_hash, sig->data+4, sig->length-4); break; } } else { uint32 crc; crc = crc32_calc_buffer(data, length); - if (!msrpc_gen(sig, "ddd", 0, crc, ntlmssp_state->ntlmssp_seq_num)) { + if (!msrpc_gen(sig, "dddd", NTLMSSP_SIGN_VERSION, 0, crc, ntlmssp_state->ntlmssp_seq_num)) { return NT_STATUS_NO_MEMORY; } - NTLMSSPcalc_ap(ntlmssp_state->ntlmssp_hash, sig->data, sig->length); + dump_data_pw("ntlmssp hash:\n", ntlmssp_state->ntlmssp_hash, + sizeof(ntlmssp_state->ntlmssp_hash)); + NTLMSSPcalc_ap(ntlmssp_state->ntlmssp_hash, sig->data+4, sig->length-4); } return NT_STATUS_OK; } @@ -140,8 +148,11 @@ NTSTATUS ntlmssp_client_sign_packet(NTLMSSP_CLIENT_STATE *ntlmssp_state, const uchar *data, size_t length, DATA_BLOB *sig) { + NTSTATUS nt_status = ntlmssp_make_packet_signiture(ntlmssp_state, data, length, NTLMSSP_SEND, sig); + + /* increment counter on send */ ntlmssp_state->ntlmssp_seq_num++; - return ntlmssp_make_packet_signiture(ntlmssp_state, data, length, NTLMSSP_SEND, sig); + return nt_status; } /** @@ -151,8 +162,8 @@ NTSTATUS ntlmssp_client_sign_packet(NTLMSSP_CLIENT_STATE *ntlmssp_state, */ NTSTATUS ntlmssp_client_check_packet(NTLMSSP_CLIENT_STATE *ntlmssp_state, - const uchar *data, size_t length, - const DATA_BLOB *sig) + const uchar *data, size_t length, + const DATA_BLOB *sig) { DATA_BLOB local_sig; NTSTATUS nt_status; @@ -170,9 +181,7 @@ NTSTATUS ntlmssp_client_check_packet(NTLMSSP_CLIENT_STATE *ntlmssp_state, return nt_status; } - if (memcmp(sig->data, local_sig.data, MIN(sig->length, local_sig.length)) == 0) { - return NT_STATUS_OK; - } else { + if (memcmp(sig->data+sig->length - 8, local_sig.data+local_sig.length - 8, 8) != 0) { DEBUG(5, ("BAD SIG: wanted signature of\n")); dump_data(5, local_sig.data, local_sig.length); @@ -182,6 +191,97 @@ NTSTATUS ntlmssp_client_check_packet(NTLMSSP_CLIENT_STATE *ntlmssp_state, DEBUG(0, ("NTLMSSP packet check failed due to invalid signiture!\n")); return NT_STATUS_ACCESS_DENIED; } + + /* increment counter on recieive */ + ntlmssp_state->ntlmssp_seq_num++; + + return NT_STATUS_OK; +} + + +/** + * Seal data with the NTLMSSP algorithm + * + */ + +NTSTATUS ntlmssp_client_seal_packet(NTLMSSP_CLIENT_STATE *ntlmssp_state, + uchar *data, size_t length, + DATA_BLOB *sig) +{ + DEBUG(10,("ntlmssp_client_seal_data: seal\n")); + dump_data_pw("ntlmssp clear data\n", data, length); + if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) { + HMACMD5Context ctx; + char seq_num[4]; + uchar digest[16]; + SIVAL(seq_num, 0, ntlmssp_state->ntlmssp_seq_num); + + hmac_md5_init_limK_to_64(ntlmssp_state->cli_sign_const, 16, &ctx); + hmac_md5_update(seq_num, 4, &ctx); + hmac_md5_update(data, length, &ctx); + hmac_md5_final(digest, &ctx); + + if (!msrpc_gen(sig, "dBd", NTLMSSP_SIGN_VERSION, digest, 8 /* only copy first 8 bytes */ + , ntlmssp_state->ntlmssp_seq_num)) { + return NT_STATUS_NO_MEMORY; + } + + dump_data_pw("ntlmssp client sealing hash:\n", + ntlmssp_state->cli_seal_hash, + sizeof(ntlmssp_state->cli_seal_hash)); + NTLMSSPcalc_ap(ntlmssp_state->cli_seal_hash, data, length); + dump_data_pw("ntlmssp client signing hash:\n", + ntlmssp_state->cli_sign_hash, + sizeof(ntlmssp_state->cli_sign_hash)); + NTLMSSPcalc_ap(ntlmssp_state->cli_sign_hash, sig->data+4, sig->length-4); + } else { + uint32 crc; + crc = crc32_calc_buffer(data, length); + if (!msrpc_gen(sig, "dddd", NTLMSSP_SIGN_VERSION, 0, crc, ntlmssp_state->ntlmssp_seq_num)) { + return NT_STATUS_NO_MEMORY; + } + + /* The order of these two operations matters - we must first seal the packet, + then seal the sequence number - this is becouse the ntlmssp_hash is not + constant, but is is rather updated with each iteration */ + + dump_data_pw("ntlmssp hash:\n", ntlmssp_state->ntlmssp_hash, + sizeof(ntlmssp_state->ntlmssp_hash)); + NTLMSSPcalc_ap(ntlmssp_state->ntlmssp_hash, data, length); + + dump_data_pw("ntlmssp hash:\n", ntlmssp_state->ntlmssp_hash, + sizeof(ntlmssp_state->ntlmssp_hash)); + NTLMSSPcalc_ap(ntlmssp_state->ntlmssp_hash, sig->data+4, sig->length-4); + } + dump_data_pw("ntlmssp sealed data\n", data, length); + + /* increment counter on send */ + ntlmssp_state->ntlmssp_seq_num++; + + return NT_STATUS_OK; +} + +/** + * Unseal data with the NTLMSSP algorithm + * + */ + +NTSTATUS ntlmssp_client_unseal_packet(NTLMSSP_CLIENT_STATE *ntlmssp_state, + uchar *data, size_t length, + DATA_BLOB *sig) +{ + DEBUG(10,("ntlmssp_client_unseal_data: seal\n")); + dump_data_pw("ntlmssp sealed data\n", data, length); + if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) { + NTLMSSPcalc_ap(ntlmssp_state->srv_seal_hash, data, length); + } else { + dump_data_pw("ntlmssp hash:\n", ntlmssp_state->ntlmssp_hash, + sizeof(ntlmssp_state->ntlmssp_hash)); + NTLMSSPcalc_ap(ntlmssp_state->ntlmssp_hash, data, length); + } + dump_data_pw("ntlmssp clear data\n", data, length); + + return ntlmssp_client_check_packet(ntlmssp_state, data, length, sig); } /** @@ -190,37 +290,69 @@ NTSTATUS ntlmssp_client_check_packet(NTLMSSP_CLIENT_STATE *ntlmssp_state, NTSTATUS ntlmssp_client_sign_init(NTLMSSP_CLIENT_STATE *ntlmssp_state) { unsigned char p24[24]; - unsigned char lm_hash[16]; + ZERO_STRUCT(p24); + + DEBUG(3, ("NTLMSSP Sign/Seal - Initialising with flags:\n")); + debug_ntlmssp_flags(ntlmssp_state->neg_flags); - if (!ntlmssp_state->lm_resp.data) { - /* can't sign or check signitures yet */ - return NT_STATUS_UNSUCCESSFUL; - } - - E_deshash(ntlmssp_state->password, lm_hash); - - NTLMSSPOWFencrypt(lm_hash, ntlmssp_state->lm_resp.data, p24); - if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) { - calc_ntlmv2_hash(ntlmssp_state->cli_sign_hash, ntlmssp_state->cli_sign_const, p24, CLI_SIGN); - calc_ntlmv2_hash(ntlmssp_state->cli_seal_hash, ntlmssp_state->cli_seal_const, p24, CLI_SEAL); - calc_ntlmv2_hash(ntlmssp_state->srv_sign_hash, ntlmssp_state->srv_sign_const, p24, SRV_SIGN); - calc_ntlmv2_hash(ntlmssp_state->srv_seal_hash, ntlmssp_state->srv_seal_const, p24, SRV_SEAL); - } - else - { - char k2[8]; - memcpy(k2, p24, 5); - k2[5] = 0xe5; - k2[6] = 0x38; - k2[7] = 0xb0; + + calc_ntlmv2_hash(ntlmssp_state->cli_sign_hash, + ntlmssp_state->cli_sign_const, + ntlmssp_state->session_key, CLI_SIGN); + dump_data_pw("NTLMSSP client sign hash:\n", + ntlmssp_state->cli_sign_hash, + sizeof(ntlmssp_state->cli_sign_hash)); + + calc_ntlmv2_hash(ntlmssp_state->cli_seal_hash, + ntlmssp_state->cli_seal_const, + ntlmssp_state->session_key, CLI_SEAL); + dump_data_pw("NTLMSSP client sesl hash:\n", + ntlmssp_state->cli_seal_hash, + sizeof(ntlmssp_state->cli_seal_hash)); + + calc_ntlmv2_hash(ntlmssp_state->srv_sign_hash, + ntlmssp_state->srv_sign_const, + ntlmssp_state->session_key, SRV_SIGN); + dump_data_pw("NTLMSSP server sign hash:\n", + ntlmssp_state->srv_sign_hash, + sizeof(ntlmssp_state->srv_sign_hash)); + + calc_ntlmv2_hash(ntlmssp_state->srv_seal_hash, + ntlmssp_state->srv_seal_const, + ntlmssp_state->session_key, SRV_SEAL); + dump_data_pw("NTLMSSP server seal hash:\n", + ntlmssp_state->cli_sign_hash, + sizeof(ntlmssp_state->cli_sign_hash)); + } + else if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_LM_KEY) { + if (!ntlmssp_state->session_key.data || ntlmssp_state->session_key.length < 8) { + /* can't sign or check signitures yet */ + DEBUG(5, ("NTLMSSP Sign/Seal - cannot use LM KEY yet\n")); + return NT_STATUS_UNSUCCESSFUL; + } + + DEBUG(5, ("NTLMSSP Sign/Seal - using LM KEY\n")); + + calc_hash(ntlmssp_state->ntlmssp_hash, ntlmssp_state->session_key.data, 8); + dump_data_pw("NTLMSSP hash:\n", ntlmssp_state->ntlmssp_hash, + sizeof(ntlmssp_state->ntlmssp_hash)); + } else { + if (!ntlmssp_state->session_key.data || ntlmssp_state->session_key.length < 16) { + /* can't sign or check signitures yet */ + DEBUG(5, ("NTLMSSP Sign/Seal - cannot use NT KEY yet\n")); + return NT_STATUS_UNSUCCESSFUL; + } - calc_hash(ntlmssp_state->ntlmssp_hash, k2, 8); + DEBUG(5, ("NTLMSSP Sign/Seal - using NT KEY\n")); + + calc_hash(ntlmssp_state->ntlmssp_hash, ntlmssp_state->session_key.data, 16); + dump_data_pw("NTLMSSP hash:\n", ntlmssp_state->ntlmssp_hash, + sizeof(ntlmssp_state->ntlmssp_hash)); } ntlmssp_state->ntlmssp_seq_num = 0; - ZERO_STRUCT(lm_hash); return NT_STATUS_OK; } diff --git a/source3/libsmb/pwd_cache.c b/source3/libsmb/pwd_cache.c index 7ddcf853c4..f45832d7d7 100644 --- a/source3/libsmb/pwd_cache.c +++ b/source3/libsmb/pwd_cache.c @@ -43,15 +43,10 @@ static void pwd_init(struct pwd_info *pwd) static void pwd_make_lm_nt_16(struct pwd_info *pwd, const char *clr) { - pstring dos_passwd; - pwd_init(pwd); - push_ascii_pstring(dos_passwd, clr); - - nt_lm_owf_gen(dos_passwd, pwd->smb_nt_pwd, pwd->smb_lm_pwd); + nt_lm_owf_gen(clr, pwd->smb_nt_pwd, pwd->smb_lm_pwd); pwd->null_pwd = False; - pwd->cleartext = False; pwd->crypted = False; } @@ -61,12 +56,9 @@ static void pwd_make_lm_nt_16(struct pwd_info *pwd, const char *clr) void pwd_set_cleartext(struct pwd_info *pwd, const char *clr) { - pwd_init(pwd); - push_ascii_fstring(pwd->password, clr); - pwd->cleartext = True; - pwd->null_pwd = False; - pwd->crypted = False; pwd_make_lm_nt_16(pwd, clr); + fstrcpy(pwd->password, clr); + pwd->cleartext = True; } /**************************************************************************** diff --git a/source3/libsmb/smb_signing.c b/source3/libsmb/smb_signing.c index 4e9b895a1b..d4f77bf07c 100644 --- a/source3/libsmb/smb_signing.c +++ b/source3/libsmb/smb_signing.c @@ -21,20 +21,58 @@ #include "includes.h" +/* Lookup a packet's MID (multiplex id) and figure out it's sequence number */ +struct outstanding_packet_lookup { + uint16 mid; + uint32 reply_seq_num; + struct outstanding_packet_lookup *prev, *next; +}; + struct smb_basic_signing_context { DATA_BLOB mac_key; uint32 send_seq_num; - uint32 reply_seq_num; + struct outstanding_packet_lookup *outstanding_packet_list; }; +static void store_sequence_for_reply(struct outstanding_packet_lookup **list, + uint16 mid, uint32 reply_seq_num) +{ + struct outstanding_packet_lookup *t; + struct outstanding_packet_lookup *tmp; + + t = smb_xmalloc(sizeof(*t)); + ZERO_STRUCTP(t); + + DLIST_ADD_END(*list, t, tmp); + t->mid = mid; + t->reply_seq_num = reply_seq_num; +} + +static BOOL get_sequence_for_reply(struct outstanding_packet_lookup **list, + uint16 mid, uint32 *reply_seq_num) +{ + struct outstanding_packet_lookup *t; + + for (t = *list; t; t = t->next) { + if (t->mid == mid) { + *reply_seq_num = t->reply_seq_num; + DLIST_REMOVE(*list, t); + return True; + } + } + DEBUG(0, ("Unexpected incoming packet, it's MID (%u) does not match" + " a MID in our outstanding list!\n", mid)); + return False; +} + /*********************************************************** SMB signing - Common code before we set a new signing implementation ************************************************************/ -static BOOL set_smb_signing_common(struct cli_state *cli) +static BOOL cli_set_smb_signing_common(struct cli_state *cli) { if (!cli->sign_info.negotiated_smb_signing - && !cli->sign_info.mandetory_signing) { + && !cli->sign_info.mandatory_signing) { return False; } @@ -56,9 +94,9 @@ static BOOL set_smb_signing_common(struct cli_state *cli) SMB signing - Common code for 'real' implementations ************************************************************/ -static BOOL set_smb_signing_real_common(struct cli_state *cli) +static BOOL cli_set_smb_signing_real_common(struct cli_state *cli) { - if (cli->sign_info.mandetory_signing) { + if (cli->sign_info.mandatory_signing) { DEBUG(5, ("Mandatory SMB signing enabled!\n")); cli->sign_info.doing_signing = True; } @@ -68,7 +106,7 @@ static BOOL set_smb_signing_real_common(struct cli_state *cli) return True; } -static void mark_packet_signed(struct cli_state *cli) +static void cli_mark_packet_signed(struct cli_state *cli) { uint16 flags2; flags2 = SVAL(cli->outbuf,smb_flg2); @@ -76,7 +114,7 @@ static void mark_packet_signed(struct cli_state *cli) SSVAL(cli->outbuf,smb_flg2, flags2); } -static BOOL signing_good(struct cli_state *cli, BOOL good) +static BOOL cli_signing_good(struct cli_state *cli, BOOL good) { DEBUG(10, ("got SMB signature of\n")); dump_data(10,&cli->inbuf[smb_ss_field] , 8); @@ -99,32 +137,67 @@ static BOOL signing_good(struct cli_state *cli, BOOL good) } /*********************************************************** - SMB signing - Simple implementation - calculate a MAC to send. + SMB signing - Simple implementation - calculate a MAC on the packet ************************************************************/ -static void cli_simple_sign_outgoing_message(struct cli_state *cli) +static void simple_packet_signature(struct smb_basic_signing_context *data, + const uchar *buf, uint32 seq_number, + unsigned char calc_md5_mac[16]) { - unsigned char calc_md5_mac[16]; + const size_t offset_end_of_sig = (smb_ss_field + 8); + unsigned char sequence_buf[8]; struct MD5Context md5_ctx; - struct smb_basic_signing_context *data = cli->sign_info.signing_context; /* * Firstly put the sequence number into the first 4 bytes. * and zero out the next 4 bytes. + * + * We do this here, to avoid modifying the packet. */ - SIVAL(cli->outbuf, smb_ss_field, - data->send_seq_num); - SIVAL(cli->outbuf, smb_ss_field + 4, 0); - /* mark the packet as signed - BEFORE we sign it...*/ - mark_packet_signed(cli); + SIVAL(sequence_buf, 0, seq_number); + SIVAL(sequence_buf, 4, 0); - /* Calculate the 16 byte MAC and place first 8 bytes into the field. */ + /* Calculate the 16 byte MAC - but don't alter the data in the + incoming packet. + + This makes for a bit for fussing about, but it's not too bad. + */ MD5Init(&md5_ctx); + + /* intialise with the key */ MD5Update(&md5_ctx, data->mac_key.data, data->mac_key.length); - MD5Update(&md5_ctx, cli->outbuf + 4, smb_len(cli->outbuf)); + + /* copy in the first bit of the SMB header */ + MD5Update(&md5_ctx, buf + 4, smb_ss_field - 4); + + /* copy in the sequence number, instead of the signature */ + MD5Update(&md5_ctx, sequence_buf, sizeof(sequence_buf)); + + /* copy in the rest of the packet in, skipping the signature */ + MD5Update(&md5_ctx, buf + offset_end_of_sig, + smb_len(buf) - (offset_end_of_sig - 4)); + + /* caclulate the MD5 sig */ MD5Final(calc_md5_mac, &md5_ctx); +} + + +/*********************************************************** + SMB signing - Simple implementation - send the MAC. +************************************************************/ + +static void cli_simple_sign_outgoing_message(struct cli_state *cli) +{ + unsigned char calc_md5_mac[16]; + struct smb_basic_signing_context *data = cli->sign_info.signing_context; + + /* mark the packet as signed - BEFORE we sign it...*/ + cli_mark_packet_signed(cli); + + simple_packet_signature(data, cli->outbuf, data->send_seq_num, + calc_md5_mac); DEBUG(10, ("sent SMB signature of\n")); dump_data(10, calc_md5_mac, 8); @@ -132,9 +205,12 @@ static void cli_simple_sign_outgoing_message(struct cli_state *cli) 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...*/ + Uncomment this to test if the remote server actually verifies signatures...*/ + data->send_seq_num++; - data->reply_seq_num = data->send_seq_num; + store_sequence_for_reply(&data->outstanding_packet_list, + cli->mid, + data->send_seq_num); data->send_seq_num++; } @@ -145,35 +221,21 @@ static void cli_simple_sign_outgoing_message(struct cli_state *cli) static BOOL cli_simple_check_incoming_message(struct cli_state *cli) { BOOL good; + uint32 reply_seq_number; unsigned char calc_md5_mac[16]; - unsigned char server_sent_mac[8]; - unsigned char sequence_buf[8]; - struct MD5Context md5_ctx; + unsigned char *server_sent_mac; + struct smb_basic_signing_context *data = cli->sign_info.signing_context; - const size_t offset_end_of_sig = (smb_ss_field + 8); - /* - * Firstly put the sequence number into the first 4 bytes. - * and zero out the next 4 bytes. - */ + if (!get_sequence_for_reply(&data->outstanding_packet_list, + SVAL(cli->inbuf, smb_mid), + &reply_seq_number)) { + return False; + } - SIVAL(sequence_buf, 0, data->reply_seq_num); - SIVAL(sequence_buf, 4, 0); - - /* get a copy of the server-sent mac */ - memcpy(server_sent_mac, &cli->inbuf[smb_ss_field], sizeof(server_sent_mac)); - - /* Calculate the 16 byte MAC and place first 8 bytes into the field. */ - MD5Init(&md5_ctx); - MD5Update(&md5_ctx, data->mac_key.data, - data->mac_key.length); - MD5Update(&md5_ctx, cli->inbuf + 4, smb_ss_field - 4); - MD5Update(&md5_ctx, sequence_buf, sizeof(sequence_buf)); - - MD5Update(&md5_ctx, cli->inbuf + offset_end_of_sig, - smb_len(cli->inbuf) - (offset_end_of_sig - 4)); - MD5Final(calc_md5_mac, &md5_ctx); + simple_packet_signature(data, cli->inbuf, reply_seq_number, calc_md5_mac); + server_sent_mac = &cli->inbuf[smb_ss_field]; good = (memcmp(server_sent_mac, calc_md5_mac, 8) == 0); if (!good) { @@ -183,7 +245,7 @@ static BOOL cli_simple_check_incoming_message(struct cli_state *cli) DEBUG(5, ("BAD SIG: got SMB signature of\n")); dump_data(5, server_sent_mac, 8); } - return signing_good(cli, good); + return cli_signing_good(cli, good); } /*********************************************************** @@ -193,6 +255,13 @@ static BOOL cli_simple_check_incoming_message(struct cli_state *cli) static void cli_simple_free_signing_context(struct cli_state *cli) { struct smb_basic_signing_context *data = cli->sign_info.signing_context; + struct outstanding_packet_lookup *list = data->outstanding_packet_list; + + while (list) { + struct outstanding_packet_lookup *old_head = list; + DLIST_REMOVE(list, list); + SAFE_FREE(old_head); + } data_blob_free(&data->mac_key); SAFE_FREE(cli->sign_info.signing_context); @@ -208,25 +277,32 @@ BOOL cli_simple_set_signing(struct cli_state *cli, const uchar user_session_key[ { struct smb_basic_signing_context *data; - if (!set_smb_signing_common(cli)) { + if (!user_session_key) + return False; + + if (!cli_set_smb_signing_common(cli)) { return False; } - if (!set_smb_signing_real_common(cli)) { + if (!cli_set_smb_signing_real_common(cli)) { return False; } data = smb_xmalloc(sizeof(*data)); + cli->sign_info.signing_context = data; - data->mac_key = data_blob(NULL, MIN(response.length + 16, 40)); + data->mac_key = data_blob(NULL, response.length + 16); memcpy(&data->mac_key.data[0], user_session_key, 16); - memcpy(&data->mac_key.data[16],response.data, MIN(response.length, 40 - 16)); + memcpy(&data->mac_key.data[16],response.data, response.length); /* Initialise the sequence number */ data->send_seq_num = 0; + /* Initialise the list of outstanding packets */ + data->outstanding_packet_list = NULL; + cli->sign_info.sign_outgoing_message = cli_simple_sign_outgoing_message; cli->sign_info.check_incoming_message = cli_simple_check_incoming_message; cli->sign_info.free_signing_context = cli_simple_free_signing_context; @@ -234,97 +310,6 @@ BOOL cli_simple_set_signing(struct cli_state *cli, const uchar user_session_key[ return True; } -/*********************************************************** - SMB signing - NTLMSSP implementation - calculate a MAC to send. -************************************************************/ - -static void cli_ntlmssp_sign_outgoing_message(struct cli_state *cli) -{ - NTSTATUS nt_status; - DATA_BLOB sig; - NTLMSSP_CLIENT_STATE *ntlmssp_state = cli->sign_info.signing_context; - - /* mark the packet as signed - BEFORE we sign it...*/ - mark_packet_signed(cli); - - nt_status = ntlmssp_client_sign_packet(ntlmssp_state, cli->outbuf + 4, - smb_len(cli->outbuf), &sig); - - if (!NT_STATUS_IS_OK(nt_status)) { - DEBUG(0, ("NTLMSSP signing failed with %s\n", nt_errstr(nt_status))); - return; - } - - DEBUG(10, ("sent SMB signature of\n")); - dump_data(10, sig.data, MIN(sig.length, 8)); - memcpy(&cli->outbuf[smb_ss_field], sig.data, MIN(sig.length, 8)); - - data_blob_free(&sig); -} - -/*********************************************************** - SMB signing - NTLMSSP implementation - check a MAC sent by server. -************************************************************/ - -static BOOL cli_ntlmssp_check_incoming_message(struct cli_state *cli) -{ - BOOL good; - NTSTATUS nt_status; - DATA_BLOB sig = data_blob(&cli->inbuf[smb_ss_field], 8); - - NTLMSSP_CLIENT_STATE *ntlmssp_state = cli->sign_info.signing_context; - - nt_status = ntlmssp_client_check_packet(ntlmssp_state, cli->outbuf + 4, - smb_len(cli->outbuf), &sig); - - data_blob_free(&sig); - - good = NT_STATUS_IS_OK(nt_status); - if (!NT_STATUS_IS_OK(nt_status)) { - DEBUG(5, ("NTLMSSP signing failed with %s\n", nt_errstr(nt_status))); - } - - return signing_good(cli, good); -} - -/*********************************************************** - SMB signing - NTLMSSP implementation - free signing context -************************************************************/ - -static void cli_ntlmssp_free_signing_context(struct cli_state *cli) -{ - ntlmssp_client_end((NTLMSSP_CLIENT_STATE **)&cli->sign_info.signing_context); -} - -/*********************************************************** - SMB signing - NTLMSSP implementation - setup the MAC key. -************************************************************/ - -BOOL cli_ntlmssp_set_signing(struct cli_state *cli, - NTLMSSP_CLIENT_STATE *ntlmssp_state) -{ - if (!set_smb_signing_common(cli)) { - return False; - } - - if (!NT_STATUS_IS_OK(ntlmssp_client_sign_init(ntlmssp_state))) { - return False; - } - - if (!set_smb_signing_real_common(cli)) { - return False; - } - - cli->sign_info.signing_context = ntlmssp_state; - ntlmssp_state->ref_count++; - - cli->sign_info.sign_outgoing_message = cli_ntlmssp_sign_outgoing_message; - cli->sign_info.check_incoming_message = cli_ntlmssp_check_incoming_message; - cli->sign_info.free_signing_context = cli_ntlmssp_free_signing_context; - - return True; -} - /*********************************************************** SMB signing - NULL implementation - calculate a MAC to send. ************************************************************/ @@ -380,7 +365,7 @@ BOOL cli_null_set_signing(struct cli_state *cli) static void cli_temp_sign_outgoing_message(struct cli_state *cli) { /* mark the packet as signed - BEFORE we sign it...*/ - mark_packet_signed(cli); + cli_mark_packet_signed(cli); /* I wonder what BSRSPYL stands for - but this is what MS actually sends! */ @@ -412,7 +397,7 @@ static void cli_temp_free_signing_context(struct cli_state *cli) BOOL cli_temp_set_signing(struct cli_state *cli) { - if (!set_smb_signing_common(cli)) { + if (!cli_set_smb_signing_common(cli)) { return False; } @@ -473,4 +458,3 @@ BOOL cli_check_sign_mac(struct cli_state *cli) return True; } - diff --git a/source3/libsmb/smbencrypt.c b/source3/libsmb/smbencrypt.c index 28160d9609..7a1a2d7d18 100644 --- a/source3/libsmb/smbencrypt.c +++ b/source3/libsmb/smbencrypt.c @@ -76,10 +76,9 @@ void E_deshash(const char *passwd, uchar p16[16]) { fstring dospwd; ZERO_STRUCT(dospwd); - ZERO_STRUCTP(p16); /* Password must be converted to DOS charset - null terminated, uppercase. */ - push_ascii(dospwd, (const char *)passwd, sizeof(dospwd), STR_UPPER|STR_TERMINATE); + push_ascii(dospwd, passwd, sizeof(dospwd), STR_UPPER|STR_TERMINATE); /* Only the fisrt 14 chars are considered, password need not be null terminated. */ E_P16(dospwd, p16); @@ -250,21 +249,21 @@ BOOL make_oem_passwd_hash(char data[516], const char *passwd, uchar old_pw_hash[ /* Does the md5 encryption from the NT hash for NTLMv2. */ void SMBOWFencrypt_ntv2(const uchar kr[16], - const DATA_BLOB srv_chal, - const DATA_BLOB cli_chal, + const DATA_BLOB *srv_chal, + const DATA_BLOB *cli_chal, uchar resp_buf[16]) { HMACMD5Context ctx; hmac_md5_init_limK_to_64(kr, 16, &ctx); - hmac_md5_update(srv_chal.data, srv_chal.length, &ctx); - hmac_md5_update(cli_chal.data, cli_chal.length, &ctx); + hmac_md5_update(srv_chal->data, srv_chal->length, &ctx); + hmac_md5_update(cli_chal->data, cli_chal->length, &ctx); hmac_md5_final(resp_buf, &ctx); #ifdef DEBUG_PASSWORD DEBUG(100, ("SMBOWFencrypt_ntv2: srv_chal, cli_chal, resp_buf\n")); - dump_data(100, srv_chal.data, srv_chal.length); - dump_data(100, cli_chal.data, cli_chal.length); + dump_data(100, srv_chal->data, srv_chal->length); + dump_data(100, cli_chal->data, cli_chal->length); dump_data(100, resp_buf, 16); #endif } @@ -272,6 +271,8 @@ void SMBOWFencrypt_ntv2(const uchar kr[16], void SMBsesskeygen_ntv2(const uchar kr[16], const uchar * nt_resp, uint8 sess_key[16]) { + /* a very nice, 128 bit, variable session key */ + HMACMD5Context ctx; hmac_md5_init_limK_to_64(kr, 16, &ctx); @@ -287,6 +288,9 @@ void SMBsesskeygen_ntv2(const uchar kr[16], void SMBsesskeygen_ntv1(const uchar kr[16], const uchar * nt_resp, uint8 sess_key[16]) { + /* yes, this session key does not change - yes, this + is a problem - but it is 128 bits */ + mdfour((unsigned char *)sess_key, kr, 16); #ifdef DEBUG_PASSWORD @@ -295,36 +299,125 @@ void SMBsesskeygen_ntv1(const uchar kr[16], #endif } -static DATA_BLOB NTLMv2_generate_response(uchar ntlm_v2_hash[16], - DATA_BLOB server_chal, size_t client_chal_length) +void SMBsesskeygen_lmv1(const uchar lm_hash[16], + const uchar lm_resp[24], /* only uses 8 */ + uint8 sess_key[16]) +{ + /* Calculate the LM session key (effective length 40 bits, + but changes with each session) */ + + uchar p24[24]; + uchar partial_lm_hash[16]; + + memcpy(partial_lm_hash, lm_hash, 8); + memset(partial_lm_hash + 8, 0xbd, 8); + + SMBOWFencrypt(lm_hash, lm_resp, p24); + + memcpy(sess_key, p24, 16); + sess_key[5] = 0xe5; + sess_key[6] = 0x38; + sess_key[7] = 0xb0; + +#ifdef DEBUG_PASSWORD + DEBUG(100, ("SMBsesskeygen_lmv1:\n")); + dump_data(100, sess_key, 16); +#endif +} + +DATA_BLOB NTLMv2_generate_names_blob(const char *hostname, + const char *domain) +{ + DATA_BLOB names_blob = data_blob(NULL, 0); + + msrpc_gen(&names_blob, "aaa", + True, NTLMSSP_NAME_TYPE_DOMAIN, domain, + True, NTLMSSP_NAME_TYPE_SERVER, hostname, + True, 0, ""); + return names_blob; +} + +static DATA_BLOB NTLMv2_generate_client_data(const DATA_BLOB *names_blob) +{ + uchar client_chal[8]; + DATA_BLOB response = data_blob(NULL, 0); + char long_date[8]; + + generate_random_buffer(client_chal, sizeof(client_chal), False); + + put_long_date(long_date, time(NULL)); + + /* See http://www.ubiqx.org/cifs/SMB.html#SMB.8.5 */ + + msrpc_gen(&response, "ddbbdb", + 0x00000101, /* Header */ + 0, /* 'Reserved' */ + long_date, 8, /* Timestamp */ + client_chal, 8, /* client challenge */ + 0, /* Unknown */ + names_blob->data, names_blob->length); /* End of name list */ + + return response; +} + +static DATA_BLOB NTLMv2_generate_response(const uchar ntlm_v2_hash[16], + const DATA_BLOB *server_chal, + const DATA_BLOB *names_blob) { uchar ntlmv2_response[16]; DATA_BLOB ntlmv2_client_data; DATA_BLOB final_response; /* NTLMv2 */ + /* generate some data to pass into the response function - including + the hostname and domain name of the server */ + ntlmv2_client_data = NTLMv2_generate_client_data(names_blob); - /* We also get to specify some random data */ - ntlmv2_client_data = data_blob(NULL, client_chal_length); - generate_random_buffer(ntlmv2_client_data.data, ntlmv2_client_data.length, False); - /* Given that data, and the challenge from the server, generate a response */ - SMBOWFencrypt_ntv2(ntlm_v2_hash, server_chal, ntlmv2_client_data, ntlmv2_response); + SMBOWFencrypt_ntv2(ntlm_v2_hash, server_chal, &ntlmv2_client_data, ntlmv2_response); - /* put it into nt_response, for the code below to put into the packet */ - final_response = data_blob(NULL, ntlmv2_client_data.length + sizeof(ntlmv2_response)); + final_response = data_blob(NULL, sizeof(ntlmv2_response) + ntlmv2_client_data.length); + memcpy(final_response.data, ntlmv2_response, sizeof(ntlmv2_response)); - /* after the first 16 bytes is the random data we generated above, so the server can verify us with it */ - memcpy(final_response.data + sizeof(ntlmv2_response), ntlmv2_client_data.data, ntlmv2_client_data.length); + + memcpy(final_response.data+sizeof(ntlmv2_response), + ntlmv2_client_data.data, ntlmv2_client_data.length); + data_blob_free(&ntlmv2_client_data); return final_response; } +static DATA_BLOB LMv2_generate_response(const uchar ntlm_v2_hash[16], + const DATA_BLOB *server_chal) +{ + uchar lmv2_response[16]; + DATA_BLOB lmv2_client_data = data_blob(NULL, 8); + DATA_BLOB final_response = data_blob(NULL, 24); + + /* LMv2 */ + /* client-supplied random data */ + generate_random_buffer(lmv2_client_data.data, lmv2_client_data.length, False); + + /* Given that data, and the challenge from the server, generate a response */ + SMBOWFencrypt_ntv2(ntlm_v2_hash, server_chal, &lmv2_client_data, lmv2_response); + memcpy(final_response.data, lmv2_response, sizeof(lmv2_response)); + + /* after the first 16 bytes is the random data we generated above, + so the server can verify us with it */ + memcpy(final_response.data+sizeof(lmv2_response), + lmv2_client_data.data, lmv2_client_data.length); + + data_blob_free(&lmv2_client_data); + + return final_response; +} + BOOL SMBNTLMv2encrypt(const char *user, const char *domain, const char *password, - const DATA_BLOB server_chal, + const DATA_BLOB *server_chal, + const DATA_BLOB *names_blob, DATA_BLOB *lm_response, DATA_BLOB *nt_response, - DATA_BLOB *session_key) + DATA_BLOB *nt_session_key) { uchar nt_hash[16]; uchar ntlm_v2_hash[16]; @@ -338,18 +431,24 @@ BOOL SMBNTLMv2encrypt(const char *user, const char *domain, const char *password return False; } - *nt_response = NTLMv2_generate_response(ntlm_v2_hash, server_chal, 64 /* pick a number, > 8 */); + if (nt_response) { + *nt_response = NTLMv2_generate_response(ntlm_v2_hash, server_chal, + names_blob); + if (nt_session_key) { + *nt_session_key = data_blob(NULL, 16); + + /* The NTLMv2 calculations also provide a session key, for signing etc later */ + /* use only the first 16 bytes of nt_response for session key */ + SMBsesskeygen_ntv2(ntlm_v2_hash, nt_response->data, nt_session_key->data); + } + } /* LMv2 */ - *lm_response = NTLMv2_generate_response(ntlm_v2_hash, server_chal, 8); - - *session_key = data_blob(NULL, 16); + if (lm_response) { + *lm_response = LMv2_generate_response(ntlm_v2_hash, server_chal); + } - /* The NTLMv2 calculations also provide a session key, for signing etc later */ - /* use only the first 16 bytes of nt_response for session key */ - SMBsesskeygen_ntv2(ntlm_v2_hash, nt_response->data, session_key->data); - return True; } diff --git a/source3/libsmb/trustdom_cache.c b/source3/libsmb/trustdom_cache.c index cddbb2daa6..8378125088 100644 --- a/source3/libsmb/trustdom_cache.c +++ b/source3/libsmb/trustdom_cache.c @@ -26,6 +26,7 @@ #define DBGC_CLASS DBGC_ALL /* there's no proper class yet */ #define TDOMKEY_FMT "TDOM/%s" +#define TDOMTSKEY "TDOMCACHE/TIMESTAMP" /** @@ -89,7 +90,7 @@ BOOL trustdom_cache_shutdown(void) static char* trustdom_cache_key(const char* name) { - char* keystr; + char* keystr = NULL; asprintf(&keystr, TDOMKEY_FMT, strupper_static(name)); return keystr; @@ -165,11 +166,14 @@ BOOL trustdom_cache_fetch(const char* name, DOM_SID* sid) /* prepare a key and get the value */ key = trustdom_cache_key(name); + if (!key) return False; if (!gencache_get(key, &value, &timeout)) { DEBUG(5, ("no entry for trusted domain %s found.\n", name)); + SAFE_FREE(key); return False; } else { + SAFE_FREE(key); DEBUG(5, ("trusted domain %s found (%s)\n", name, value)); } @@ -183,6 +187,71 @@ BOOL trustdom_cache_fetch(const char* name, DOM_SID* sid) } +/******************************************************************* + fetch the timestamp from the last update +*******************************************************************/ + +uint32 trustdom_cache_fetch_timestamp( void ) +{ + char *value; + time_t timeout; + uint32 timestamp; + + /* init the cache */ + if (!gencache_init()) + return False; + + if (!gencache_get(TDOMTSKEY, &value, &timeout)) { + DEBUG(5, ("no timestamp for trusted domain cache located.\n")); + return 0; + } + + timestamp = atoi(value); + + return timestamp; +} + +/******************************************************************* + store the timestamp from the last update +*******************************************************************/ + +BOOL trustdom_cache_store_timestamp( uint32 t, time_t timeout ) +{ + fstring value; + + /* init the cache */ + if (!gencache_init()) + return False; + + snprintf(value, sizeof(value), "%d", t ); + + if (!gencache_set(TDOMTSKEY, value, timeout)) { + DEBUG(5, ("failed to set timestamp for trustdom_cache\n")); + return False; + } + + return True; +} + + +/******************************************************************* + lock the timestamp entry in the trustdom_cache +*******************************************************************/ + +BOOL trustdom_cache_lock_timestamp( void ) +{ + return gencache_lock_entry( TDOMTSKEY ) != -1; +} + +/******************************************************************* + unlock the timestamp entry in the trustdom_cache +*******************************************************************/ + +void trustdom_cache_unlock_timestamp( void ) +{ + gencache_unlock_entry( TDOMTSKEY ); +} + /** * Delete single trustdom entry. Look at the * gencache_iterate definition. @@ -213,3 +282,61 @@ void trustdom_cache_flush(void) DEBUG(5, ("Trusted domains cache flushed\n")); } +/******************************************************************** + update the trustdom_cache if needed +********************************************************************/ +#define TRUSTDOM_UPDATE_INTERVAL 600 + +void update_trustdom_cache( void ) +{ + char **domain_names; + DOM_SID *dom_sids; + uint32 num_domains; + uint32 last_check; + int time_diff; + TALLOC_CTX *mem_ctx = NULL; + time_t now = time(NULL); + int i; + + /* get the timestamp. We have to initialise it if the last timestamp == 0 */ + + if ( (last_check = trustdom_cache_fetch_timestamp()) == 0 ) + trustdom_cache_store_timestamp(0, now+TRUSTDOM_UPDATE_INTERVAL); + + time_diff = now - last_check; + + if ( (time_diff > 0) && (time_diff < TRUSTDOM_UPDATE_INTERVAL) ) { + DEBUG(10,("update_trustdom_cache: not time to update trustdom_cache yet\n")); + return; + } + + /* lock the timestamp */ + if ( !trustdom_cache_lock_timestamp() ) + return; + + if ( !(mem_ctx = talloc_init("update_trustdom_cache")) ) { + DEBUG(0,("update_trustdom_cache: talloc_init() failed!\n")); + goto done; + } + + /* get the domains and store them */ + + if ( enumerate_domain_trusts(mem_ctx, lp_workgroup(), &domain_names, + &num_domains, &dom_sids) ) + { + for ( i=0; ivfs_ops.close(fsp,fsp->fd); + ret = SMB_VFS_CLOSE(fsp,fsp->fd); fsp->fd = -1; return ret; } @@ -259,7 +259,7 @@ int fd_close_posix(struct connection_struct *conn, files_struct *fsp) DEBUG(10,("fd_close_posix: doing close on %u fd's.\n", (unsigned int)count )); for(i = 0; i < count; i++) { - if (conn->vfs_ops.close(fsp,fd_array[i]) == -1) { + if (SMB_VFS_CLOSE(fsp,fd_array[i]) == -1) { saved_errno = errno; } } @@ -278,7 +278,7 @@ int fd_close_posix(struct connection_struct *conn, files_struct *fsp) * Finally close the fd associated with this fsp. */ - ret = conn->vfs_ops.close(fsp,fsp->fd); + ret = SMB_VFS_CLOSE(fsp,fsp->fd); if (saved_errno != 0) { errno = saved_errno; @@ -646,11 +646,10 @@ static BOOL posix_lock_in_range(SMB_OFF_T *offset_out, SMB_OFF_T *count_out, static BOOL posix_fcntl_lock(files_struct *fsp, int op, SMB_OFF_T offset, SMB_OFF_T count, int type) { int ret; - struct connection_struct *conn = fsp->conn; DEBUG(8,("posix_fcntl_lock %d %d %.0f %.0f %d\n",fsp->fd,op,(double)offset,(double)count,type)); - ret = conn->vfs_ops.lock(fsp,fsp->fd,op,offset,count,type); + ret = SMB_VFS_LOCK(fsp,fsp->fd,op,offset,count,type); if (!ret && ((errno == EFBIG) || (errno == ENOLCK) || (errno == EINVAL))) { @@ -674,7 +673,7 @@ static BOOL posix_fcntl_lock(files_struct *fsp, int op, SMB_OFF_T offset, SMB_OF DEBUG(0,("Count greater than 31 bits - retrying with 31 bit truncated length.\n")); errno = 0; count &= 0x7fffffff; - ret = conn->vfs_ops.lock(fsp,fsp->fd,op,offset,count,type); + ret = SMB_VFS_LOCK(fsp,fsp->fd,op,offset,count,type); } } diff --git a/source3/modules/vfs_audit.c b/source3/modules/vfs_audit.c index 4f9dc1b1e4..550d918b43 100644 --- a/source3/modules/vfs_audit.c +++ b/source3/modules/vfs_audit.c @@ -2,8 +2,9 @@ * Auditing VFS module for samba. Log selected file operations to syslog * facility. * - * Copyright (C) Tim Potter, 1999-2000 - * Copyright (C) Alexander Bokovoy, 2002 + * Copyright (C) Tim Potter 1999-2000 + * Copyright (C) Alexander Bokovoy 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 @@ -20,118 +21,111 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "config.h" -#include -#include -#ifdef HAVE_UTIME_H -#include -#endif -#ifdef HAVE_DIRENT_H -#include -#endif -#include -#ifdef HAVE_FCNTL_H -#include -#endif -#include -#include -#include -#include - -#ifndef SYSLOG_FACILITY -#define SYSLOG_FACILITY LOG_USER -#endif - -#ifndef SYSLOG_PRIORITY -#define SYSLOG_PRIORITY LOG_NOTICE -#endif + +#include "includes.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_VFS /* Function prototypes */ -static int audit_connect(struct connection_struct *conn, const char *svc, const char *user); -static void audit_disconnect(struct connection_struct *conn); -static DIR *audit_opendir(struct connection_struct *conn, const char *fname); -static int audit_mkdir(struct connection_struct *conn, const char *path, mode_t mode); -static int audit_rmdir(struct connection_struct *conn, const char *path); -static int audit_open(struct connection_struct *conn, const char *fname, int flags, mode_t mode); -static int audit_close(struct files_struct *fsp, int fd); -static int audit_rename(struct connection_struct *conn, const char *old, const char *new); -static int audit_unlink(struct connection_struct *conn, const char *path); -static int audit_chmod(struct connection_struct *conn, const char *path, mode_t mode); -static int audit_chmod_acl(struct connection_struct *conn, const char *name, mode_t mode); -static int audit_fchmod(struct files_struct *fsp, int fd, mode_t mode); -static int audit_fchmod_acl(struct files_struct *fsp, int fd, mode_t mode); +static int audit_connect(vfs_handle_struct *handle, connection_struct *conn, const char *svc, const char *user); +static void audit_disconnect(vfs_handle_struct *handle, connection_struct *conn); +static DIR *audit_opendir(vfs_handle_struct *handle, connection_struct *conn, const char *fname); +static int audit_mkdir(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode); +static int audit_rmdir(vfs_handle_struct *handle, connection_struct *conn, const char *path); +static int audit_open(vfs_handle_struct *handle, connection_struct *conn, const char *fname, int flags, mode_t mode); +static int audit_close(vfs_handle_struct *handle, files_struct *fsp, int fd); +static int audit_rename(vfs_handle_struct *handle, connection_struct *conn, const char *old, const char *new); +static int audit_unlink(vfs_handle_struct *handle, connection_struct *conn, const char *path); +static int audit_chmod(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode); +static int audit_chmod_acl(vfs_handle_struct *handle, connection_struct *conn, const char *name, mode_t mode); +static int audit_fchmod(vfs_handle_struct *handle, files_struct *fsp, int fd, mode_t mode); +static int audit_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, mode_t mode); /* VFS operations */ -static struct vfs_ops default_vfs_ops; /* For passthrough operation */ -static struct smb_vfs_handle_struct *audit_handle; - -static vfs_op_tuple audit_ops[] = { +static vfs_op_tuple audit_op_tuples[] = { /* Disk operations */ - {audit_connect, SMB_VFS_OP_CONNECT, SMB_VFS_LAYER_LOGGER}, - {audit_disconnect, SMB_VFS_OP_DISCONNECT, SMB_VFS_LAYER_LOGGER}, + {SMB_VFS_OP(audit_connect), SMB_VFS_OP_CONNECT, SMB_VFS_LAYER_LOGGER}, + {SMB_VFS_OP(audit_disconnect), SMB_VFS_OP_DISCONNECT, SMB_VFS_LAYER_LOGGER}, /* Directory operations */ - {audit_opendir, SMB_VFS_OP_OPENDIR, SMB_VFS_LAYER_LOGGER}, - {audit_mkdir, SMB_VFS_OP_MKDIR, SMB_VFS_LAYER_LOGGER}, - {audit_rmdir, SMB_VFS_OP_RMDIR, SMB_VFS_LAYER_LOGGER}, + {SMB_VFS_OP(audit_opendir), SMB_VFS_OP_OPENDIR, SMB_VFS_LAYER_LOGGER}, + {SMB_VFS_OP(audit_mkdir), SMB_VFS_OP_MKDIR, SMB_VFS_LAYER_LOGGER}, + {SMB_VFS_OP(audit_rmdir), SMB_VFS_OP_RMDIR, SMB_VFS_LAYER_LOGGER}, /* File operations */ - {audit_open, SMB_VFS_OP_OPEN, SMB_VFS_LAYER_LOGGER}, - {audit_close, SMB_VFS_OP_CLOSE, SMB_VFS_LAYER_LOGGER}, - {audit_rename, SMB_VFS_OP_RENAME, SMB_VFS_LAYER_LOGGER}, - {audit_unlink, SMB_VFS_OP_UNLINK, SMB_VFS_LAYER_LOGGER}, - {audit_chmod, SMB_VFS_OP_CHMOD, SMB_VFS_LAYER_LOGGER}, - {audit_fchmod, SMB_VFS_OP_FCHMOD, SMB_VFS_LAYER_LOGGER}, - {audit_chmod_acl, SMB_VFS_OP_CHMOD_ACL, SMB_VFS_LAYER_LOGGER}, - {audit_fchmod_acl, SMB_VFS_OP_FCHMOD_ACL, SMB_VFS_LAYER_LOGGER}, + {SMB_VFS_OP(audit_open), SMB_VFS_OP_OPEN, SMB_VFS_LAYER_LOGGER}, + {SMB_VFS_OP(audit_close), SMB_VFS_OP_CLOSE, SMB_VFS_LAYER_LOGGER}, + {SMB_VFS_OP(audit_rename), SMB_VFS_OP_RENAME, SMB_VFS_LAYER_LOGGER}, + {SMB_VFS_OP(audit_unlink), SMB_VFS_OP_UNLINK, SMB_VFS_LAYER_LOGGER}, + {SMB_VFS_OP(audit_chmod), SMB_VFS_OP_CHMOD, SMB_VFS_LAYER_LOGGER}, + {SMB_VFS_OP(audit_fchmod), SMB_VFS_OP_FCHMOD, SMB_VFS_LAYER_LOGGER}, + {SMB_VFS_OP(audit_chmod_acl), SMB_VFS_OP_CHMOD_ACL, SMB_VFS_LAYER_LOGGER}, + {SMB_VFS_OP(audit_fchmod_acl), SMB_VFS_OP_FCHMOD_ACL, SMB_VFS_LAYER_LOGGER}, /* Finish VFS operations definition */ - {NULL, SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP} + {SMB_VFS_OP(NULL), SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP} }; -/* VFS initialisation function. Return vfs_op_tuple array back to SAMBA. */ -static vfs_op_tuple *audit_init(const struct vfs_ops *def_vfs_ops, - struct smb_vfs_handle_struct *vfs_handle) +static int audit_syslog_facility(vfs_handle_struct *handle) { - memcpy(&default_vfs_ops, def_vfs_ops, sizeof(struct vfs_ops)); - - audit_handle = vfs_handle; + /* fix me: let this be configurable by: + * lp_param_enum(SNUM(handle->conn),(handle->param?handle->param:"audit"),"syslog facility", + * audit_enum_facility,LOG_USER); + */ + return LOG_USER; +} - openlog("smbd_audit", LOG_PID, SYSLOG_FACILITY); - syslog(SYSLOG_PRIORITY, "VFS_INIT: vfs_ops loaded\n"); - return audit_ops; + +static int audit_syslog_priority(vfs_handle_struct *handle) +{ + /* fix me: let this be configurable by: + * lp_param_enum(SNUM(handle->conn),(handle->param?handle->param:"audit"),"syslog priority", + * audit_enum_priority,LOG_NOTICE); + */ + return LOG_NOTICE; } /* Implementation of vfs_ops. Pass everything on to the default operation but log event first. */ -static int audit_connect(struct connection_struct *conn, const char *svc, const char *user) +static int audit_connect(vfs_handle_struct *handle, connection_struct *conn, const char *svc, const char *user) { - syslog(SYSLOG_PRIORITY, "connect to service %s by user %s\n", + int result; + + openlog("smbd_audit", LOG_PID, audit_syslog_facility(handle)); + + syslog(audit_syslog_priority(handle), "connect to service %s by user %s\n", svc, user); - return default_vfs_ops.connect(conn, svc, user); + result = SMB_VFS_NEXT_CONNECT(handle, conn, svc, user); + + return result; } -static void audit_disconnect(struct connection_struct *conn) +static void audit_disconnect(vfs_handle_struct *handle, connection_struct *conn) { - syslog(SYSLOG_PRIORITY, "disconnected\n"); - default_vfs_ops.disconnect(conn); + syslog(audit_syslog_priority(handle), "disconnected\n"); + SMB_VFS_NEXT_DISCONNECT(handle, conn); + + return; } -static DIR *audit_opendir(struct connection_struct *conn, const char *fname) +static DIR *audit_opendir(vfs_handle_struct *handle, connection_struct *conn, const char *fname) { - DIR *result = default_vfs_ops.opendir(conn, fname); + DIR *result; + + result = SMB_VFS_NEXT_OPENDIR(handle, conn, fname); - syslog(SYSLOG_PRIORITY, "opendir %s %s%s\n", + syslog(audit_syslog_priority(handle), "opendir %s %s%s\n", fname, (result == NULL) ? "failed: " : "", (result == NULL) ? strerror(errno) : ""); @@ -139,11 +133,13 @@ static DIR *audit_opendir(struct connection_struct *conn, const char *fname) return result; } -static int audit_mkdir(struct connection_struct *conn, const char *path, mode_t mode) +static int audit_mkdir(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode) { - int result = default_vfs_ops.mkdir(conn, path, mode); - - syslog(SYSLOG_PRIORITY, "mkdir %s %s%s\n", + int result; + + result = SMB_VFS_NEXT_MKDIR(handle, conn, path, mode); + + syslog(audit_syslog_priority(handle), "mkdir %s %s%s\n", path, (result < 0) ? "failed: " : "", (result < 0) ? strerror(errno) : ""); @@ -151,11 +147,13 @@ static int audit_mkdir(struct connection_struct *conn, const char *path, mode_t return result; } -static int audit_rmdir(struct connection_struct *conn, const char *path) +static int audit_rmdir(vfs_handle_struct *handle, connection_struct *conn, const char *path) { - int result = default_vfs_ops.rmdir(conn, path); + int result; + + result = SMB_VFS_NEXT_RMDIR(handle, conn, path); - syslog(SYSLOG_PRIORITY, "rmdir %s %s%s\n", + syslog(audit_syslog_priority(handle), "rmdir %s %s%s\n", path, (result < 0) ? "failed: " : "", (result < 0) ? strerror(errno) : ""); @@ -163,11 +161,13 @@ static int audit_rmdir(struct connection_struct *conn, const char *path) return result; } -static int audit_open(struct connection_struct *conn, const char *fname, int flags, mode_t mode) +static int audit_open(vfs_handle_struct *handle, connection_struct *conn, const char *fname, int flags, mode_t mode) { - int result = default_vfs_ops.open(conn, fname, flags, mode); + int result; + + result = SMB_VFS_NEXT_OPEN(handle, conn, fname, flags, mode); - syslog(SYSLOG_PRIORITY, "open %s (fd %d) %s%s%s\n", + syslog(audit_syslog_priority(handle), "open %s (fd %d) %s%s%s\n", fname, result, ((flags & O_WRONLY) || (flags & O_RDWR)) ? "for writing " : "", (result < 0) ? "failed: " : "", @@ -176,11 +176,13 @@ static int audit_open(struct connection_struct *conn, const char *fname, int fla return result; } -static int audit_close(struct files_struct *fsp, int fd) +static int audit_close(vfs_handle_struct *handle, files_struct *fsp, int fd) { - int result = default_vfs_ops.close(fsp, fd); + int result; + + result = SMB_VFS_NEXT_CLOSE(handle, fsp, fd); - syslog(SYSLOG_PRIORITY, "close fd %d %s%s\n", + syslog(audit_syslog_priority(handle), "close fd %d %s%s\n", fd, (result < 0) ? "failed: " : "", (result < 0) ? strerror(errno) : ""); @@ -188,11 +190,13 @@ static int audit_close(struct files_struct *fsp, int fd) return result; } -static int audit_rename(struct connection_struct *conn, const char *old, const char *new) +static int audit_rename(vfs_handle_struct *handle, connection_struct *conn, const char *old, const char *new) { - int result = default_vfs_ops.rename(conn, old, new); + int result; + + result = SMB_VFS_NEXT_RENAME(handle, conn, old, new); - syslog(SYSLOG_PRIORITY, "rename %s -> %s %s%s\n", + syslog(audit_syslog_priority(handle), "rename %s -> %s %s%s\n", old, new, (result < 0) ? "failed: " : "", (result < 0) ? strerror(errno) : ""); @@ -200,11 +204,13 @@ static int audit_rename(struct connection_struct *conn, const char *old, const c return result; } -static int audit_unlink(struct connection_struct *conn, const char *path) +static int audit_unlink(vfs_handle_struct *handle, connection_struct *conn, const char *path) { - int result = default_vfs_ops.unlink(conn, path); + int result; + + result = SMB_VFS_NEXT_UNLINK(handle, conn, path); - syslog(SYSLOG_PRIORITY, "unlink %s %s%s\n", + syslog(audit_syslog_priority(handle), "unlink %s %s%s\n", path, (result < 0) ? "failed: " : "", (result < 0) ? strerror(errno) : ""); @@ -212,11 +218,13 @@ static int audit_unlink(struct connection_struct *conn, const char *path) return result; } -static int audit_chmod(struct connection_struct *conn, const char *path, mode_t mode) +static int audit_chmod(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode) { - int result = default_vfs_ops.chmod(conn, path, mode); + int result; + + result = SMB_VFS_NEXT_CHMOD(handle, conn, path, mode); - syslog(SYSLOG_PRIORITY, "chmod %s mode 0x%x %s%s\n", + syslog(audit_syslog_priority(handle), "chmod %s mode 0x%x %s%s\n", path, mode, (result < 0) ? "failed: " : "", (result < 0) ? strerror(errno) : ""); @@ -224,16 +232,13 @@ static int audit_chmod(struct connection_struct *conn, const char *path, mode_t return result; } -static int audit_chmod_acl(struct connection_struct *conn, const char *path, mode_t mode) +static int audit_chmod_acl(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode) { int result; - if ( !default_vfs_ops.chmod_acl ) - return 0; + result = SMB_VFS_NEXT_CHMOD_ACL(handle, conn, path, mode); - result = default_vfs_ops.chmod_acl(conn, path, mode); - - syslog(SYSLOG_PRIORITY, "chmod_acl %s mode 0x%x %s%s\n", + syslog(audit_syslog_priority(handle), "chmod_acl %s mode 0x%x %s%s\n", path, mode, (result < 0) ? "failed: " : "", (result < 0) ? strerror(errno) : ""); @@ -241,11 +246,13 @@ static int audit_chmod_acl(struct connection_struct *conn, const char *path, mod return result; } -static int audit_fchmod(struct files_struct *fsp, int fd, mode_t mode) +static int audit_fchmod(vfs_handle_struct *handle, files_struct *fsp, int fd, mode_t mode) { - int result = default_vfs_ops.fchmod(fsp, fd, mode); + int result; - syslog(SYSLOG_PRIORITY, "fchmod %s mode 0x%x %s%s\n", + result = SMB_VFS_NEXT_FCHMOD(handle, fsp, fd, mode); + + syslog(audit_syslog_priority(handle), "fchmod %s mode 0x%x %s%s\n", fsp->fsp_name, mode, (result < 0) ? "failed: " : "", (result < 0) ? strerror(errno) : ""); @@ -253,16 +260,13 @@ static int audit_fchmod(struct files_struct *fsp, int fd, mode_t mode) return result; } -static int audit_fchmod_acl(struct files_struct *fsp, int fd, mode_t mode) +static int audit_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, mode_t mode) { int result; - if ( !default_vfs_ops.fchmod_acl ) - return 0; - - result = default_vfs_ops.fchmod_acl(fsp, fd, mode); + result = SMB_VFS_NEXT_FCHMOD_ACL(handle, fsp, fd, mode); - syslog(SYSLOG_PRIORITY, "fchmod_acl %s mode 0x%x %s%s\n", + syslog(audit_syslog_priority(handle), "fchmod_acl %s mode 0x%x %s%s\n", fsp->fsp_name, mode, (result < 0) ? "failed: " : "", (result < 0) ? strerror(errno) : ""); @@ -272,5 +276,5 @@ static int audit_fchmod_acl(struct files_struct *fsp, int fd, mode_t mode) NTSTATUS vfs_audit_init(void) { - return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "audit", audit_init); + return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "audit", audit_op_tuples); } diff --git a/source3/modules/vfs_extd_audit.c b/source3/modules/vfs_extd_audit.c index ef30ca7027..06cddc78e4 100644 --- a/source3/modules/vfs_extd_audit.c +++ b/source3/modules/vfs_extd_audit.c @@ -5,6 +5,7 @@ * Copyright (C) Tim Potter, 1999-2000 * Copyright (C) Alexander Bokovoy, 2002 * Copyright (C) John H Terpstra, 2003 + * Copyright (C) Stefan (metze) Metzmacher, 2003 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,127 +22,120 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "config.h" -#include -#include -#ifdef HAVE_UTIME_H -#include -#endif -#ifdef HAVE_DIRENT_H -#include -#endif -#include -#ifdef HAVE_FCNTL_H -#include -#endif -#include -#include -#include -#include - -#ifndef SYSLOG_FACILITY -#define SYSLOG_FACILITY LOG_USER -#endif - -#ifndef SYSLOG_PRIORITY -#define SYSLOG_PRIORITY LOG_NOTICE -#endif + +#include "includes.h" + +static int vfs_extd_audit_debug_level = DBGC_VFS; + +#undef DBGC_CLASS +#define DBGC_CLASS vfs_extd_audit_debug_level /* Function prototypes */ -static int audit_connect(struct connection_struct *conn, const char *svc, const char *user); -static void audit_disconnect(struct connection_struct *conn); -static DIR *audit_opendir(struct connection_struct *conn, const char *fname); -static int audit_mkdir(struct connection_struct *conn, const char *path, mode_t mode); -static int audit_rmdir(struct connection_struct *conn, const char *path); -static int audit_open(struct connection_struct *conn, const char *fname, int flags, mode_t mode); -static int audit_close(struct files_struct *fsp, int fd); -static int audit_rename(struct connection_struct *conn, const char *old, const char *new); -static int audit_unlink(struct connection_struct *conn, const char *path); -static int audit_chmod(struct connection_struct *conn, const char *path, mode_t mode); -static int audit_chmod_acl(struct connection_struct *conn, const char *name, mode_t mode); -static int audit_fchmod(struct files_struct *fsp, int fd, mode_t mode); -static int audit_fchmod_acl(struct files_struct *fsp, int fd, mode_t mode); +static int audit_connect(vfs_handle_struct *handle, connection_struct *conn, const char *svc, const char *user); +static void audit_disconnect(vfs_handle_struct *handle, connection_struct *conn); +static DIR *audit_opendir(vfs_handle_struct *handle, connection_struct *conn, const char *fname); +static int audit_mkdir(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode); +static int audit_rmdir(vfs_handle_struct *handle, connection_struct *conn, const char *path); +static int audit_open(vfs_handle_struct *handle, connection_struct *conn, const char *fname, int flags, mode_t mode); +static int audit_close(vfs_handle_struct *handle, files_struct *fsp, int fd); +static int audit_rename(vfs_handle_struct *handle, connection_struct *conn, const char *old, const char *new); +static int audit_unlink(vfs_handle_struct *handle, connection_struct *conn, const char *path); +static int audit_chmod(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode); +static int audit_chmod_acl(vfs_handle_struct *handle, connection_struct *conn, const char *name, mode_t mode); +static int audit_fchmod(vfs_handle_struct *handle, files_struct *fsp, int fd, mode_t mode); +static int audit_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, mode_t mode); /* VFS operations */ -static struct vfs_ops default_vfs_ops; /* For passthrough operation */ -static struct smb_vfs_handle_struct *audit_handle; - -static vfs_op_tuple audit_ops[] = { +static vfs_op_tuple audit_op_tuples[] = { /* Disk operations */ - {audit_connect, SMB_VFS_OP_CONNECT, SMB_VFS_LAYER_LOGGER}, - {audit_disconnect, SMB_VFS_OP_DISCONNECT, SMB_VFS_LAYER_LOGGER}, + {SMB_VFS_OP(audit_connect), SMB_VFS_OP_CONNECT, SMB_VFS_LAYER_LOGGER}, + {SMB_VFS_OP(audit_disconnect), SMB_VFS_OP_DISCONNECT, SMB_VFS_LAYER_LOGGER}, /* Directory operations */ - {audit_opendir, SMB_VFS_OP_OPENDIR, SMB_VFS_LAYER_LOGGER}, - {audit_mkdir, SMB_VFS_OP_MKDIR, SMB_VFS_LAYER_LOGGER}, - {audit_rmdir, SMB_VFS_OP_RMDIR, SMB_VFS_LAYER_LOGGER}, + {SMB_VFS_OP(audit_opendir), SMB_VFS_OP_OPENDIR, SMB_VFS_LAYER_LOGGER}, + {SMB_VFS_OP(audit_mkdir), SMB_VFS_OP_MKDIR, SMB_VFS_LAYER_LOGGER}, + {SMB_VFS_OP(audit_rmdir), SMB_VFS_OP_RMDIR, SMB_VFS_LAYER_LOGGER}, /* File operations */ - {audit_open, SMB_VFS_OP_OPEN, SMB_VFS_LAYER_LOGGER}, - {audit_close, SMB_VFS_OP_CLOSE, SMB_VFS_LAYER_LOGGER}, - {audit_rename, SMB_VFS_OP_RENAME, SMB_VFS_LAYER_LOGGER}, - {audit_unlink, SMB_VFS_OP_UNLINK, SMB_VFS_LAYER_LOGGER}, - {audit_chmod, SMB_VFS_OP_CHMOD, SMB_VFS_LAYER_LOGGER}, - {audit_fchmod, SMB_VFS_OP_FCHMOD, SMB_VFS_LAYER_LOGGER}, - {audit_chmod_acl, SMB_VFS_OP_CHMOD_ACL, SMB_VFS_LAYER_LOGGER}, - {audit_fchmod_acl, SMB_VFS_OP_FCHMOD_ACL, SMB_VFS_LAYER_LOGGER}, + {SMB_VFS_OP(audit_open), SMB_VFS_OP_OPEN, SMB_VFS_LAYER_LOGGER}, + {SMB_VFS_OP(audit_close), SMB_VFS_OP_CLOSE, SMB_VFS_LAYER_LOGGER}, + {SMB_VFS_OP(audit_rename), SMB_VFS_OP_RENAME, SMB_VFS_LAYER_LOGGER}, + {SMB_VFS_OP(audit_unlink), SMB_VFS_OP_UNLINK, SMB_VFS_LAYER_LOGGER}, + {SMB_VFS_OP(audit_chmod), SMB_VFS_OP_CHMOD, SMB_VFS_LAYER_LOGGER}, + {SMB_VFS_OP(audit_fchmod), SMB_VFS_OP_FCHMOD, SMB_VFS_LAYER_LOGGER}, + {SMB_VFS_OP(audit_chmod_acl), SMB_VFS_OP_CHMOD_ACL, SMB_VFS_LAYER_LOGGER}, + {SMB_VFS_OP(audit_fchmod_acl), SMB_VFS_OP_FCHMOD_ACL, SMB_VFS_LAYER_LOGGER}, /* Finish VFS operations definition */ - {NULL, SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP} + {SMB_VFS_OP(NULL), SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP} }; -/* VFS initialisation function. Return vfs_op_tuple array back to SAMBA. */ -static vfs_op_tuple *audit_init(const struct vfs_ops *def_vfs_ops, - struct smb_vfs_handle_struct *vfs_handle) +static int audit_syslog_facility(vfs_handle_struct *handle) { - memcpy(&default_vfs_ops, def_vfs_ops, sizeof(struct vfs_ops)); - - audit_handle = vfs_handle; + /* fix me: let this be configurable by: + * lp_param_enum(SNUM(handle->conn),(handle->param?handle->param:"extd_audit"),"syslog facility", + * audit_enum_facility,LOG_USER); + */ + return LOG_USER; +} - openlog("smbd_audit", LOG_PID, SYSLOG_FACILITY); - syslog(SYSLOG_PRIORITY, "VFS_INIT: vfs_ops loaded\n"); - return audit_ops; +static int audit_syslog_priority(vfs_handle_struct *handle) +{ + /* fix me: let this be configurable by: + * lp_param_enum(SNUM(handle->conn),(handle->param?handle->param:"extd_audit"),"syslog priority", + * audit_enum_priority,LOG_NOTICE); + */ + return LOG_NOTICE; } /* Implementation of vfs_ops. Pass everything on to the default operation but log event first. */ -static int audit_connect(struct connection_struct *conn, const char *svc, const char *user) +static int audit_connect(vfs_handle_struct *handle, connection_struct *conn, const char *svc, const char *user) { - syslog(SYSLOG_PRIORITY, "connect to service %s by user %s\n", + int result; + + openlog("smbd_audit", LOG_PID, audit_syslog_facility(handle)); + + syslog(audit_syslog_priority(handle), "connect to service %s by user %s\n", svc, user); DEBUG(10, ("Connected to service %s as user %s\n", svc, user)); - return default_vfs_ops.connect(conn, svc, user); + result = SMB_VFS_NEXT_CONNECT(handle, conn, svc, user); + + return result; } -static void audit_disconnect(struct connection_struct *conn) +static void audit_disconnect(vfs_handle_struct *handle, connection_struct *conn) { - syslog(SYSLOG_PRIORITY, "disconnected\n"); + syslog(audit_syslog_priority(handle), "disconnected\n"); DEBUG(10, ("Disconnected from VFS module extd_audit\n")); + SMB_VFS_NEXT_DISCONNECT(handle, conn); - default_vfs_ops.disconnect(conn); + return; } -static DIR *audit_opendir(struct connection_struct *conn, const char *fname) +static DIR *audit_opendir(vfs_handle_struct *handle, connection_struct *conn, const char *fname) { - DIR *result = default_vfs_ops.opendir(conn, fname); + DIR *result; + + result = SMB_VFS_NEXT_OPENDIR(handle, conn, fname); - syslog(SYSLOG_PRIORITY, "opendir %s %s%s\n", + syslog(audit_syslog_priority(handle), "opendir %s %s%s\n", fname, (result == NULL) ? "failed: " : "", (result == NULL) ? strerror(errno) : ""); - DEBUG(1, ("vfs_extd_audit: opendir %s %s %s", + DEBUG(1, ("vfs_extd_audit: opendir %s %s %s\n", fname, (result == NULL) ? "failed: " : "", (result == NULL) ? strerror(errno) : "")); @@ -149,11 +143,13 @@ static DIR *audit_opendir(struct connection_struct *conn, const char *fname) return result; } -static int audit_mkdir(struct connection_struct *conn, const char *path, mode_t mode) +static int audit_mkdir(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode) { - int result = default_vfs_ops.mkdir(conn, path, mode); - - syslog(SYSLOG_PRIORITY, "mkdir %s %s%s\n", + int result; + + result = SMB_VFS_NEXT_MKDIR(handle, conn, path, mode); + + syslog(audit_syslog_priority(handle), "mkdir %s %s%s\n", path, (result < 0) ? "failed: " : "", (result < 0) ? strerror(errno) : ""); @@ -165,11 +161,13 @@ static int audit_mkdir(struct connection_struct *conn, const char *path, mode_t return result; } -static int audit_rmdir(struct connection_struct *conn, const char *path) +static int audit_rmdir(vfs_handle_struct *handle, connection_struct *conn, const char *path) { - int result = default_vfs_ops.rmdir(conn, path); + int result; + + result = SMB_VFS_NEXT_RMDIR(handle, conn, path); - syslog(SYSLOG_PRIORITY, "rmdir %s %s%s\n", + syslog(audit_syslog_priority(handle), "rmdir %s %s%s\n", path, (result < 0) ? "failed: " : "", (result < 0) ? strerror(errno) : ""); @@ -181,11 +179,13 @@ static int audit_rmdir(struct connection_struct *conn, const char *path) return result; } -static int audit_open(struct connection_struct *conn, const char *fname, int flags, mode_t mode) +static int audit_open(vfs_handle_struct *handle, connection_struct *conn, const char *fname, int flags, mode_t mode) { - int result = default_vfs_ops.open(conn, fname, flags, mode); + int result; + + result = SMB_VFS_NEXT_OPEN(handle, conn, fname, flags, mode); - syslog(SYSLOG_PRIORITY, "open %s (fd %d) %s%s%s\n", + syslog(audit_syslog_priority(handle), "open %s (fd %d) %s%s%s\n", fname, result, ((flags & O_WRONLY) || (flags & O_RDWR)) ? "for writing " : "", (result < 0) ? "failed: " : "", @@ -198,11 +198,13 @@ static int audit_open(struct connection_struct *conn, const char *fname, int fla return result; } -static int audit_close(struct files_struct *fsp, int fd) +static int audit_close(vfs_handle_struct *handle, files_struct *fsp, int fd) { - int result = default_vfs_ops.close(fsp, fd); + int result; + + result = SMB_VFS_NEXT_CLOSE(handle, fsp, fd); - syslog(SYSLOG_PRIORITY, "close fd %d %s%s\n", + syslog(audit_syslog_priority(handle), "close fd %d %s%s\n", fd, (result < 0) ? "failed: " : "", (result < 0) ? strerror(errno) : ""); @@ -214,11 +216,13 @@ static int audit_close(struct files_struct *fsp, int fd) return result; } -static int audit_rename(struct connection_struct *conn, const char *old, const char *new) +static int audit_rename(vfs_handle_struct *handle, connection_struct *conn, const char *old, const char *new) { - int result = default_vfs_ops.rename(conn, old, new); + int result; + + result = SMB_VFS_NEXT_RENAME(handle, conn, old, new); - syslog(SYSLOG_PRIORITY, "rename %s -> %s %s%s\n", + syslog(audit_syslog_priority(handle), "rename %s -> %s %s%s\n", old, new, (result < 0) ? "failed: " : "", (result < 0) ? strerror(errno) : ""); @@ -230,11 +234,13 @@ static int audit_rename(struct connection_struct *conn, const char *old, const c return result; } -static int audit_unlink(struct connection_struct *conn, const char *path) +static int audit_unlink(vfs_handle_struct *handle, connection_struct *conn, const char *path) { - int result = default_vfs_ops.unlink(conn, path); + int result; + + result = SMB_VFS_NEXT_UNLINK(handle, conn, path); - syslog(SYSLOG_PRIORITY, "unlink %s %s%s\n", + syslog(audit_syslog_priority(handle), "unlink %s %s%s\n", path, (result < 0) ? "failed: " : "", (result < 0) ? strerror(errno) : ""); @@ -246,11 +252,13 @@ static int audit_unlink(struct connection_struct *conn, const char *path) return result; } -static int audit_chmod(struct connection_struct *conn, const char *path, mode_t mode) +static int audit_chmod(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode) { - int result = default_vfs_ops.chmod(conn, path, mode); + int result; - syslog(SYSLOG_PRIORITY, "chmod %s mode 0x%x %s%s\n", + result = SMB_VFS_NEXT_CHMOD(handle, conn, path, mode); + + syslog(audit_syslog_priority(handle), "chmod %s mode 0x%x %s%s\n", path, mode, (result < 0) ? "failed: " : "", (result < 0) ? strerror(errno) : ""); @@ -262,11 +270,13 @@ static int audit_chmod(struct connection_struct *conn, const char *path, mode_t return result; } -static int audit_chmod_acl(struct connection_struct *conn, const char *path, mode_t mode) +static int audit_chmod_acl(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode) { - int result = default_vfs_ops.chmod_acl(conn, path, mode); + int result; + + result = SMB_VFS_NEXT_CHMOD_ACL(handle, conn, path, mode); - syslog(SYSLOG_PRIORITY, "chmod_acl %s mode 0x%x %s%s\n", + syslog(audit_syslog_priority(handle), "chmod_acl %s mode 0x%x %s%s\n", path, mode, (result < 0) ? "failed: " : "", (result < 0) ? strerror(errno) : ""); @@ -278,11 +288,13 @@ static int audit_chmod_acl(struct connection_struct *conn, const char *path, mod return result; } -static int audit_fchmod(struct files_struct *fsp, int fd, mode_t mode) +static int audit_fchmod(vfs_handle_struct *handle, files_struct *fsp, int fd, mode_t mode) { - int result = default_vfs_ops.fchmod(fsp, fd, mode); + int result; + + result = SMB_VFS_NEXT_FCHMOD(handle, fsp, fd, mode); - syslog(SYSLOG_PRIORITY, "fchmod %s mode 0x%x %s%s\n", + syslog(audit_syslog_priority(handle), "fchmod %s mode 0x%x %s%s\n", fsp->fsp_name, mode, (result < 0) ? "failed: " : "", (result < 0) ? strerror(errno) : ""); @@ -294,11 +306,13 @@ static int audit_fchmod(struct files_struct *fsp, int fd, mode_t mode) return result; } -static int audit_fchmod_acl(struct files_struct *fsp, int fd, mode_t mode) +static int audit_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, mode_t mode) { - int result = default_vfs_ops.fchmod_acl(fsp, fd, mode); + int result; + + result = SMB_VFS_NEXT_FCHMOD_ACL(handle, fsp, fd, mode); - syslog(SYSLOG_PRIORITY, "fchmod_acl %s mode 0x%x %s%s\n", + syslog(audit_syslog_priority(handle), "fchmod_acl %s mode 0x%x %s%s\n", fsp->fsp_name, mode, (result < 0) ? "failed: " : "", (result < 0) ? strerror(errno) : ""); @@ -312,5 +326,18 @@ static int audit_fchmod_acl(struct files_struct *fsp, int fd, mode_t mode) NTSTATUS vfs_extd_audit_init(void) { - return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "extd_audit", audit_init); + NTSTATUS ret = smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "extd_audit", audit_op_tuples); + + if (!NT_STATUS_IS_OK(ret)) + return ret; + + vfs_extd_audit_debug_level = debug_add_class("extd_audit"); + if (vfs_extd_audit_debug_level == -1) { + vfs_extd_audit_debug_level = DBGC_VFS; + DEBUG(0, ("vfs_extd_audit: Couldn't register custom debugging class!\n")); + } else { + DEBUG(10, ("vfs_extd_audit: Debug class number of 'extd_audit': %d\n", vfs_extd_audit_debug_level)); + } + + return ret; } diff --git a/source3/modules/vfs_fake_perms.c b/source3/modules/vfs_fake_perms.c index 3a18fbb730..740218dcd4 100644 --- a/source3/modules/vfs_fake_perms.c +++ b/source3/modules/vfs_fake_perms.c @@ -22,31 +22,16 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "config.h" +#include "includes.h" -#include -#include -#ifdef HAVE_UTIME_H -#include -#endif -#ifdef HAVE_DIRENT_H -#include -#endif -#ifdef HAVE_FCNTL_H -#include -#endif -#include -#include +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_VFS -#include -#include - -static struct vfs_ops default_vfs_ops; /* For passthrough operation */ -static struct smb_vfs_handle_struct *fake_perms_handle; /* use fake_perms_handle->data for storing per-instance private data */ - -static int fake_perms_stat(struct connection_struct *conn, const char *fname, SMB_STRUCT_STAT *sbuf) +static int fake_perms_stat(vfs_handle_struct *handle, connection_struct *conn, const char *fname, SMB_STRUCT_STAT *sbuf) { - int ret = default_vfs_ops.stat(conn, fname, sbuf); + int ret = -1; + + ret = SMB_VFS_NEXT_STAT(handle, conn, fname, sbuf); if (ret == 0) { extern struct current_user current_user; @@ -58,12 +43,15 @@ static int fake_perms_stat(struct connection_struct *conn, const char *fname, SM sbuf->st_uid = current_user.uid; sbuf->st_gid = current_user.gid; } + return ret; } -static int fake_perms_fstat(struct files_struct *fsp, int fd, SMB_STRUCT_STAT *sbuf) +static int fake_perms_fstat(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_STRUCT_STAT *sbuf) { - int ret = default_vfs_ops.fstat(fsp, fd, sbuf); + int ret = -1; + + ret = SMB_VFS_NEXT_FSTAT(handle, fsp, fd, sbuf); if (ret == 0) { extern struct current_user current_user; @@ -78,210 +66,16 @@ static int fake_perms_fstat(struct files_struct *fsp, int fd, SMB_STRUCT_STAT *s return ret; } -#if 0 -static size_t fake_perms_fget_nt_acl(struct files_struct *fsp, int fd, struct security_descriptor_info **ppdesc) -{ - return default_vfs_ops.fget_nt_acl(fsp, fd, ppdesc); -} - -static size_t fake_perms_get_nt_acl(struct files_struct *fsp, const char *name, struct security_descriptor_info **ppdesc) -{ - return default_vfs_ops.get_nt_acl(fsp, name, ppdesc); -} - -static BOOL fake_perms_fset_nt_acl(struct files_struct *fsp, int fd, uint32 security_info_sent, struct security_descriptor_info *psd) -{ - return default_vfs_ops.fset_nt_acl(fsp, fd, security_info_sent, psd); -} - -static BOOL fake_perms_set_nt_acl(struct files_struct *fsp, const char *name, uint32 security_info_sent, struct security_descriptor_info *psd) -{ - return default_vfs_ops.set_nt_acl(fsp, name, security_info_sent, psd); -} - -static BOOL fake_perms_chmod_acl(struct connection_struct *conn, const char *name, mode_t mode) -{ - return default_vfs_ops.chmod_acl(conn, name, mode); -} - -static BOOL fake_perms_fchmod_acl(struct files_struct *fsp, int fd, mode_t mode) -{ - return default_vfs_ops.fchmod_acl(fsp, fd, mode); -} - -static int fake_perms_sys_acl_get_entry(struct connection_struct *conn, SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p) -{ - return default_vfs_ops.sys_acl_get_entry(conn, theacl, entry_id, entry_p); -} - -static int fake_perms_sys_acl_get_tag_type(struct connection_struct *conn, SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p) -{ - return default_vfs_ops.sys_acl_get_tag_type(conn, entry_d, tag_type_p); -} - -static int fake_perms_sys_acl_get_permset(struct connection_struct *conn, SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p) -{ - return default_vfs_ops.sys_acl_get_permset(conn, entry_d, permset_p); -} - -static void *fake_perms_sys_acl_get_qualifier(struct connection_struct *conn, SMB_ACL_ENTRY_T entry_d) -{ - return default_vfs_ops.sys_acl_get_qualifier(conn, entry_d); -} - -static SMB_ACL_T fake_perms_sys_acl_get_file(struct connection_struct *conn, const char *path_p, SMB_ACL_TYPE_T type) -{ - return default_vfs_ops.sys_acl_get_file(conn, path_p, type); -} - -static SMB_ACL_T fake_perms_sys_acl_get_fd(struct files_struct *fsp, int fd) -{ - return default_vfs_ops.sys_acl_get_fd(fsp, fd); -} - -static int fake_perms_sys_acl_clear_perms(struct connection_struct *conn, SMB_ACL_PERMSET_T permset) -{ - return default_vfs_ops.sys_acl_clear_perms(conn, permset); -} - -static int fake_perms_sys_acl_add_perm(struct connection_struct *conn, SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm) -{ - return default_vfs_ops.sys_acl_add_perm(conn, permset, perm); -} - -static char *fake_perms_sys_acl_to_text(struct connection_struct *conn, SMB_ACL_T theacl, ssize_t *plen) -{ - return default_vfs_ops.sys_acl_to_text(conn, theacl, plen); -} - -static SMB_ACL_T fake_perms_sys_acl_init(struct connection_struct *conn, int count) -{ - return default_vfs_ops.sys_acl_init(conn, count); -} - -static int fake_perms_sys_acl_create_entry(struct connection_struct *conn, SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry) -{ - return default_vfs_ops.sys_acl_create_entry(conn, pacl, pentry); -} - -static int fake_perms_sys_acl_set_tag_type(struct connection_struct *conn, SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype) -{ - return default_vfs_ops.sys_acl_set_tag_type(conn, entry, tagtype); -} - -static int fake_perms_sys_acl_set_qualifier(struct connection_struct *conn, SMB_ACL_ENTRY_T entry, void *qual) -{ - return default_vfs_ops.sys_acl_set_qualifier(conn, entry, qual); -} - -static int fake_perms_sys_acl_set_permset(struct connection_struct *conn, SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset) -{ - return default_vfs_ops.sys_acl_set_permset(conn, entry, permset); -} - -static int fake_perms_sys_acl_valid(struct connection_struct *conn, SMB_ACL_T theacl ) -{ - return default_vfs_ops.sys_acl_valid(conn, theacl ); -} - -static int fake_perms_sys_acl_set_file(struct connection_struct *conn, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl) -{ - return default_vfs_ops.sys_acl_set_file(conn, name, acltype, theacl); -} - -static int fake_perms_sys_acl_set_fd(struct files_struct *fsp, int fd, SMB_ACL_T theacl) -{ - return default_vfs_ops.sys_acl_set_fd(fsp, fd, theacl); -} - -static int fake_perms_sys_acl_delete_def_file(struct connection_struct *conn, const char *path) -{ - return default_vfs_ops.sys_acl_delete_def_file(conn, path); -} - -static int fake_perms_sys_acl_get_perm(struct connection_struct *conn, SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm) -{ - return default_vfs_ops.sys_acl_get_perm(conn, permset, perm); -} - -static int fake_perms_sys_acl_free_text(struct connection_struct *conn, char *text) -{ - return default_vfs_ops.sys_acl_free_text(conn, text); -} - -static int fake_perms_sys_acl_free_acl(struct connection_struct *conn, SMB_ACL_T posix_acl) -{ - return default_vfs_ops.sys_acl_free_acl(conn, posix_acl); -} - -static int fake_perms_sys_acl_free_qualifier(struct connection_struct *conn, void *qualifier, SMB_ACL_TAG_T tagtype) -{ - return default_vfs_ops.sys_acl_free_qualifier(conn, qualifier, tagtype); -} -#endif - /* VFS operations structure */ -static vfs_op_tuple fake_perms_ops[] = { - - /* NT File ACL operations */ -#if 0 - {fake_perms_fget_nt_acl, SMB_VFS_OP_FGET_NT_ACL, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_get_nt_acl, SMB_VFS_OP_GET_NT_ACL, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_fset_nt_acl, SMB_VFS_OP_FSET_NT_ACL, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_set_nt_acl, SMB_VFS_OP_SET_NT_ACL, SMB_VFS_LAYER_TRANSPARENT}, - - /* POSIX ACL operations */ +static vfs_op_tuple fake_perms_ops[] = { + {SMB_VFS_OP(fake_perms_stat), SMB_VFS_OP_STAT, SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(fake_perms_fstat), SMB_VFS_OP_FSTAT, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_chmod_acl, SMB_VFS_OP_CHMOD_ACL, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_fchmod_acl, SMB_VFS_OP_FCHMOD_ACL, SMB_VFS_LAYER_TRANSPARENT}, - - {fake_perms_sys_acl_get_entry, SMB_VFS_OP_SYS_ACL_GET_ENTRY, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_sys_acl_get_tag_type, SMB_VFS_OP_SYS_ACL_GET_TAG_TYPE, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_sys_acl_get_permset, SMB_VFS_OP_SYS_ACL_GET_PERMSET, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_sys_acl_get_qualifier, SMB_VFS_OP_SYS_ACL_GET_QUALIFIER, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_sys_acl_get_file, SMB_VFS_OP_SYS_ACL_GET_FILE, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_sys_acl_get_fd, SMB_VFS_OP_SYS_ACL_GET_FD, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_sys_acl_clear_perms, SMB_VFS_OP_SYS_ACL_CLEAR_PERMS, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_sys_acl_add_perm, SMB_VFS_OP_SYS_ACL_ADD_PERM, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_sys_acl_to_text, SMB_VFS_OP_SYS_ACL_TO_TEXT, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_sys_acl_init, SMB_VFS_OP_SYS_ACL_INIT, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_sys_acl_create_entry, SMB_VFS_OP_SYS_ACL_CREATE_ENTRY, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_sys_acl_set_tag_type, SMB_VFS_OP_SYS_ACL_SET_TAG_TYPE, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_sys_acl_set_qualifier, SMB_VFS_OP_SYS_ACL_SET_QUALIFIER, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_sys_acl_set_permset, SMB_VFS_OP_SYS_ACL_SET_PERMSET, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_sys_acl_valid, SMB_VFS_OP_SYS_ACL_VALID, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_sys_acl_set_file, SMB_VFS_OP_SYS_ACL_SET_FILE, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_sys_acl_set_fd, SMB_VFS_OP_SYS_ACL_SET_FD, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_sys_acl_delete_def_file, SMB_VFS_OP_SYS_ACL_DELETE_DEF_FILE, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_sys_acl_get_perm, SMB_VFS_OP_SYS_ACL_GET_PERM, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_sys_acl_free_text, SMB_VFS_OP_SYS_ACL_FREE_TEXT, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_sys_acl_free_acl, SMB_VFS_OP_SYS_ACL_FREE_ACL, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_sys_acl_free_qualifier, SMB_VFS_OP_SYS_ACL_FREE_QUALIFIER, SMB_VFS_LAYER_TRANSPARENT}, -#endif - - {fake_perms_stat, SMB_VFS_OP_STAT, SMB_VFS_LAYER_TRANSPARENT}, - {fake_perms_fstat, SMB_VFS_OP_FSTAT, SMB_VFS_LAYER_TRANSPARENT}, - {NULL, SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP} + {SMB_VFS_OP(NULL), SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP} }; -/* VFS initialisation - return initialized vfs_op_tuple array back to Samba */ - -static vfs_op_tuple *fake_perms_init(const struct vfs_ops *def_vfs_ops, - struct smb_vfs_handle_struct *vfs_handle) -{ - DEBUG(3, ("Initialising default vfs hooks\n")); - - memcpy(&default_vfs_ops, def_vfs_ops, sizeof(struct vfs_ops)); - - /* Remember vfs_handle for further allocation and referencing of private - information in vfs_handle->data - */ - fake_perms_handle = vfs_handle; - return fake_perms_ops; -} - NTSTATUS vfs_fake_perms_init(void) { - return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "fake_perms", fake_perms_init); + return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "fake_perms", fake_perms_ops); } diff --git a/source3/modules/vfs_netatalk.c b/source3/modules/vfs_netatalk.c index 718bc2a35c..ae6286e292 100644 --- a/source3/modules/vfs_netatalk.c +++ b/source3/modules/vfs_netatalk.c @@ -2,6 +2,7 @@ * AppleTalk VFS module for Samba-3.x * * Copyright (C) Alexei Kotovich, 2002 + * Copyright (C) Stefan (metze) Metzmacher, 2003 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -18,22 +19,10 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "config.h" -#include -#include -#ifdef HAVE_UTIME_H -#include -#endif -#ifdef HAVE_DIRENT_H -#include -#endif -#ifdef HAVE_FCNTL_H -#include -#endif -#include -#include -#include -#include +#include "includes.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_VFS #define APPLEDOUBLE ".AppleDouble" #define ADOUBLEMODE 0777 @@ -46,9 +35,6 @@ static int atalk_build_paths(TALLOC_CTX *ctx, const char *path, static int atalk_unlink_file(const char *path); -static struct vfs_ops default_vfs_ops; /* For passthrough operation */ -static struct smb_vfs_handle_struct *atalk_handle; - static int atalk_get_path_ptr(char *path) { int i = 0; @@ -187,11 +173,11 @@ static void atalk_rrmdir(TALLOC_CTX *ctx, char *path) /* Directory operations */ -DIR *atalk_opendir(struct connection_struct *conn, const char *fname) +DIR *atalk_opendir(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *fname) { DIR *ret = 0; - - ret = default_vfs_ops.opendir(conn, fname); + + ret = SMB_VFS_NEXT_OPENDIR(handle, conn, fname); /* * when we try to perform delete operation upon file which has fork @@ -208,7 +194,7 @@ DIR *atalk_opendir(struct connection_struct *conn, const char *fname) return ret; } -static int atalk_rmdir(struct connection_struct *conn, const char *path) +static int atalk_rmdir(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path) { BOOL add = False; TALLOC_CTX *ctx = 0; @@ -233,12 +219,12 @@ static int atalk_rmdir(struct connection_struct *conn, const char *path) exit_rmdir: talloc_destroy(ctx); - return default_vfs_ops.rmdir(conn, path); + return SMB_VFS_NEXT_RMDIR(handle, conn, path); } /* File operations */ -static int atalk_rename(struct connection_struct *conn, const char *old, const char *new) +static int atalk_rename(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *old, const char *new) { int ret = 0; char *adbl_path = 0; @@ -247,7 +233,7 @@ static int atalk_rename(struct connection_struct *conn, const char *old, const c SMB_STRUCT_STAT orig_info; TALLOC_CTX *ctx; - ret = default_vfs_ops.rename(conn, old, new); + ret = SMB_VFS_NEXT_RENAME(handle, conn, old, new); if (!conn || !old) return ret; @@ -270,7 +256,7 @@ exit_rename: return ret; } -static int atalk_unlink(struct connection_struct *conn, const char *path) +static int atalk_unlink(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path) { int ret = 0, i; char *adbl_path = 0; @@ -279,7 +265,7 @@ static int atalk_unlink(struct connection_struct *conn, const char *path) SMB_STRUCT_STAT orig_info; TALLOC_CTX *ctx; - ret = default_vfs_ops.unlink(conn, path); + ret = SMB_VFS_NEXT_UNLINK(handle, conn, path); if (!conn || !path) return ret; @@ -326,7 +312,7 @@ exit_unlink: return ret; } -static int atalk_chmod(struct connection_struct *conn, const char *path, mode_t mode) +static int atalk_chmod(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path, mode_t mode) { int ret = 0; char *adbl_path = 0; @@ -335,7 +321,7 @@ static int atalk_chmod(struct connection_struct *conn, const char *path, mode_t SMB_STRUCT_STAT orig_info; TALLOC_CTX *ctx; - ret = default_vfs_ops.chmod(conn, path, mode); + ret = SMB_VFS_NEXT_CHMOD(handle, conn, path, mode); if (!conn || !path) return ret; @@ -358,7 +344,7 @@ exit_chmod: return ret; } -static int atalk_chown(struct connection_struct *conn, const char *path, uid_t uid, gid_t gid) +static int atalk_chown(struct vfs_handle_struct *handle, struct connection_struct *conn, const char *path, uid_t uid, gid_t gid) { int ret = 0; char *adbl_path = 0; @@ -367,7 +353,7 @@ static int atalk_chown(struct connection_struct *conn, const char *path, uid_t u SMB_STRUCT_STAT orig_info; TALLOC_CTX *ctx; - ret = default_vfs_ops.chown(conn, path, uid, gid); + ret = SMB_VFS_NEXT_CHOWN(handle, conn, path, uid, gid); if (!conn || !path) return ret; @@ -394,34 +380,22 @@ static vfs_op_tuple atalk_ops[] = { /* Directory operations */ - {atalk_opendir, SMB_VFS_OP_OPENDIR, SMB_VFS_LAYER_TRANSPARENT}, - {atalk_rmdir, SMB_VFS_OP_RMDIR, SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(atalk_opendir), SMB_VFS_OP_OPENDIR, SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(atalk_rmdir), SMB_VFS_OP_RMDIR, SMB_VFS_LAYER_TRANSPARENT}, /* File operations */ - {atalk_rename, SMB_VFS_OP_RENAME, SMB_VFS_LAYER_TRANSPARENT}, - {atalk_unlink, SMB_VFS_OP_UNLINK, SMB_VFS_LAYER_TRANSPARENT}, - {atalk_chmod, SMB_VFS_OP_CHMOD, SMB_VFS_LAYER_TRANSPARENT}, - {atalk_chown, SMB_VFS_OP_CHOWN, SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(atalk_rename), SMB_VFS_OP_RENAME, SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(atalk_unlink), SMB_VFS_OP_UNLINK, SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(atalk_chmod), SMB_VFS_OP_CHMOD, SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(atalk_chown), SMB_VFS_OP_CHOWN, SMB_VFS_LAYER_TRANSPARENT}, /* Finish VFS operations definition */ - {NULL, SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP} + {SMB_VFS_OP(NULL), SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP} }; -/* VFS initialisation function. Return vfs_op_tuple array back to SAMBA. */ -static vfs_op_tuple *netatalk_init(const struct vfs_ops *def_vfs_ops, - struct smb_vfs_handle_struct *vfs_handle) -{ - memcpy(&default_vfs_ops, def_vfs_ops, sizeof(struct vfs_ops)); - - atalk_handle = vfs_handle; - - DEBUG(3, ("ATALK: vfs module loaded\n")); - return atalk_ops; -} - NTSTATUS vfs_netatalk_init(void) { - return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "netatalk", netatalk_init); + return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "netatalk", atalk_ops); } diff --git a/source3/modules/vfs_recycle.c b/source3/modules/vfs_recycle.c index 87dea944ac..e725daedba 100644 --- a/source3/modules/vfs_recycle.c +++ b/source3/modules/vfs_recycle.c @@ -6,6 +6,7 @@ * Copyright (C) 2002, Alexander Bokovoy - cascaded VFS adoption, * Copyright (C) 2002, Juergen Hasch - added some options. * Copyright (C) 2002, Simo Sorce + * Copyright (C) 2002, Stefan (metze) Metzmacher * * 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 @@ -30,231 +31,133 @@ static int vfs_recycle_debug_level = DBGC_VFS; #undef DBGC_CLASS #define DBGC_CLASS vfs_recycle_debug_level - -static const char *delimiter = "|"; /* delimiter for options */ - -/* One per connection */ - -typedef struct recycle_bin_struct -{ - TALLOC_CTX *mem_ctx; - char *repository; /* name of the recycle bin directory */ - BOOL keep_dir_tree; /* keep directory structure of deleted file in recycle bin */ - BOOL versions; /* create versions of deleted files with identical name */ - BOOL touch; /* touch access date of deleted file */ - char *exclude; /* which files to exclude */ - char *exclude_dir; /* which directories to exclude */ - char *noversions; /* which files to exclude from versioning */ - SMB_OFF_T maxsize; /* maximum file size to be saved */ -} recycle_bin_struct; - -typedef struct recycle_bin_connections { - int conn; - recycle_bin_struct *data; - struct recycle_bin_connections *next; -} recycle_bin_connections; - -typedef struct recycle_bin_private_data { - TALLOC_CTX *mem_ctx; - recycle_bin_connections *conns; -} recycle_bin_private_data; - -struct smb_vfs_handle_struct *recycle_bin_private_handle; - -/* VFS operations */ -static struct vfs_ops default_vfs_ops; /* For passthrough operation */ - -static int recycle_connect(struct connection_struct *conn, const char *service, const char *user); -static void recycle_disconnect(struct connection_struct *conn); -static int recycle_unlink(connection_struct *, const char *); - -#define VFS_OP(x) ((void *) x) + +static int recycle_connect(vfs_handle_struct *handle, connection_struct *conn, const char *service, const char *user); +static void recycle_disconnect(vfs_handle_struct *handle, connection_struct *conn); +static int recycle_unlink(vfs_handle_struct *handle, connection_struct *conn, const char *name); static vfs_op_tuple recycle_ops[] = { /* Disk operations */ - {VFS_OP(recycle_connect), SMB_VFS_OP_CONNECT, SMB_VFS_LAYER_TRANSPARENT}, - {VFS_OP(recycle_disconnect), SMB_VFS_OP_DISCONNECT, SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(recycle_connect), SMB_VFS_OP_CONNECT, SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(recycle_disconnect), SMB_VFS_OP_DISCONNECT, SMB_VFS_LAYER_TRANSPARENT}, /* File operations */ - {VFS_OP(recycle_unlink), SMB_VFS_OP_UNLINK, SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(recycle_unlink), SMB_VFS_OP_UNLINK, SMB_VFS_LAYER_TRANSPARENT}, - {NULL, SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP} + {SMB_VFS_OP(NULL), SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP} }; -/** - * VFS initialisation function. - * - * @retval initialised vfs_op_tuple array - **/ -static vfs_op_tuple *recycle_init(const struct vfs_ops *def_vfs_ops, - struct smb_vfs_handle_struct *vfs_handle) +static int recycle_connect(vfs_handle_struct *handle, connection_struct *conn, const char *service, const char *user) { - TALLOC_CTX *mem_ctx = NULL; + DEBUG(10,("recycle_connect() connect to service[%s] as user[%s].\n", + service,user)); - DEBUG(10, ("Initializing VFS module recycle\n")); - memcpy(&default_vfs_ops, def_vfs_ops, sizeof(struct vfs_ops)); - vfs_recycle_debug_level = debug_add_class("vfs_recycle_bin"); - if (vfs_recycle_debug_level == -1) { - vfs_recycle_debug_level = DBGC_VFS; - DEBUG(0, ("vfs_recycle: Couldn't register custom debugging class!\n")); - } else { - DEBUG(0, ("vfs_recycle: Debug class number of 'vfs_recycle': %d\n", vfs_recycle_debug_level)); - } - - recycle_bin_private_handle = vfs_handle; - if (!(mem_ctx = talloc_init("recycle bin data"))) { - DEBUG(0, ("Failed to allocate memory in VFS module recycle_bin\n")); - return NULL; - } + return SMB_VFS_NEXT_CONNECT(handle, conn, service, user); +} - recycle_bin_private_handle->data = talloc(mem_ctx, sizeof(recycle_bin_private_data)); - if (recycle_bin_private_handle->data == NULL) { - DEBUG(0, ("Failed to allocate memory in VFS module recycle_bin\n")); - return NULL; - } - ((recycle_bin_private_data *)(recycle_bin_private_handle->data))->mem_ctx = mem_ctx; - ((recycle_bin_private_data *)(recycle_bin_private_handle->data))->conns = NULL; +static void recycle_disconnect(vfs_handle_struct *handle, connection_struct *conn) +{ + DEBUG(10,("recycle_disconnect() connect to service[%s].\n", + lp_servicename(SNUM(conn)))); - return recycle_ops; + SMB_VFS_NEXT_DISCONNECT(handle, conn); } -static int recycle_connect(struct connection_struct *conn, const char *service, const char *user) +static const char *recycle_repository(vfs_handle_struct *handle) { - TALLOC_CTX *ctx = NULL; - recycle_bin_struct *recbin; - recycle_bin_connections *recconn; - recycle_bin_connections *recconnbase; - recycle_bin_private_data *recdata; - const char *tmp_str; + const char *tmp_str = NULL; + - DEBUG(10, ("Called for service %s (%d) as user %s\n", service, SNUM(conn), user)); + tmp_str = lp_parm_const_string(SNUM(handle->conn), "recycle", "repository",".recycle"); - if (recycle_bin_private_handle) - recdata = (recycle_bin_private_data *)(recycle_bin_private_handle->data); - else { - DEBUG(0, ("Recycle bin not initialized!\n")); - return -1; - } + DEBUG(10, ("recycle: repository = %s\n", tmp_str)); + + return tmp_str; +} - if (!(ctx = talloc_init("recycle bin connection"))) { - DEBUG(0, ("Failed to allocate memory in VFS module recycle_bin\n")); - return -1; - } +static BOOL recycle_keep_dir_tree(vfs_handle_struct *handle) +{ + BOOL ret; + + ret = lp_parm_bool(SNUM(handle->conn), "recycle", "keeptree", False); - recbin = talloc_zero(ctx, sizeof(recycle_bin_struct)); - if (recbin == NULL) { - DEBUG(0, ("Failed to allocate memory in VFS module recycle_bin\n")); - return -1; - } - recbin->mem_ctx = ctx; - - /* parse configuration options */ - if ((tmp_str = lp_parm_const_string(SNUM(conn), "vfs_recycle_bin", "repository", ".recycle")) != NULL) { - recbin->repository = talloc_sub_conn(recbin->mem_ctx, conn, tmp_str); - ALLOC_CHECK(recbin->repository, error); - trim_string(recbin->repository, "/", "/"); - DEBUG(5, ("recycle.bin: repository = %s\n", recbin->repository)); - } else { - DEBUG(0,("recycle.bin: no repository found (fail) !\n")); - goto error; - } + DEBUG(10, ("recycle_bin: keeptree = %s\n", ret?"True":"False")); - recbin->keep_dir_tree = lp_parm_bool(SNUM(conn), "vfs_recycle_bin", "keeptree", False); - DEBUG(5, ("recycle.bin: keeptree = %d\n", recbin->keep_dir_tree)); + return ret; +} + +static BOOL recycle_versions(vfs_handle_struct *handle) +{ + BOOL ret; + + ret = lp_parm_bool(SNUM(handle->conn), "recycle", "versions", False); + + DEBUG(10, ("recycle: versions = %s\n", ret?"True":"False")); - recbin->versions = lp_parm_bool(SNUM(conn), "vfs_recycle_bin", "versions", False); - DEBUG(5, ("recycle.bin: versions = %d\n", recbin->versions)); + return ret; +} + +static BOOL recycle_touch(vfs_handle_struct *handle) +{ + BOOL ret; + + ret = lp_parm_bool(SNUM(handle->conn), "recycle", "touch", False); + + DEBUG(10, ("recycle: touch = %s\n", ret?"True":"False")); - recbin->touch = lp_parm_bool(SNUM(conn), "vfs_recycle_bin", "touch", False); - DEBUG(5, ("recycle.bin: touch = %d\n", recbin->touch)); + return ret; +} - recbin->maxsize = lp_parm_ulong(SNUM(conn), "vfs_recycle_bin", "maxsize" , 0); - if (recbin->maxsize == 0) { - recbin->maxsize = -1; - DEBUG(5, ("recycle.bin: maxsize = -infinite-\n")); - } else { - DEBUG(5, ("recycle.bin: maxsize = %ld\n", (long int)recbin->maxsize)); - } +static const char **recycle_exclude(vfs_handle_struct *handle) +{ + const char **tmp_lp; + + tmp_lp = lp_parm_string_list(SNUM(handle->conn), "recycle", "exclude", NULL); - if ((tmp_str = lp_parm_const_string(SNUM(conn), "vfs_recycle_bin", "exclude", "")) != NULL) { - recbin->exclude = talloc_strdup(recbin->mem_ctx, tmp_str); - ALLOC_CHECK(recbin->exclude, error); - DEBUG(5, ("recycle.bin: exclude = %s\n", recbin->exclude)); - } - if ((tmp_str = lp_parm_const_string(SNUM(conn), "vfs_recycle_bin", "exclude_dir", "")) != NULL) { - recbin->exclude_dir = talloc_strdup(recbin->mem_ctx, tmp_str); - ALLOC_CHECK(recbin->exclude_dir, error); - DEBUG(5, ("recycle.bin: exclude_dir = %s\n", recbin->exclude_dir)); - } - if ((tmp_str = lp_parm_const_string(SNUM(conn), "vfs_recycle_bin", "noversions", "")) != NULL) { - recbin->noversions = talloc_strdup(recbin->mem_ctx, tmp_str); - ALLOC_CHECK(recbin->noversions, error); - DEBUG(5, ("recycle.bin: noversions = %s\n", recbin->noversions)); - } + DEBUG(10, ("recycle: exclude = %s ...\n", tmp_lp?*tmp_lp:"")); + + return tmp_lp; +} - recconn = talloc(recdata->mem_ctx, sizeof(recycle_bin_connections)); - if (recconn == NULL) { - DEBUG(0, ("Failed to allocate memory in VFS module recycle_bin\n")); - goto error; - } - recconn->conn = SNUM(conn); - recconn->data = recbin; - recconn->next = NULL; - if (recdata->conns) { - recconnbase = recdata->conns; - while (recconnbase->next != NULL) recconnbase = recconnbase->next; - recconnbase->next = recconn; - } else { - recdata->conns = recconn; - } - return default_vfs_ops.connect(conn, service, user); +static const char **recycle_exclude_dir(vfs_handle_struct *handle) +{ + const char **tmp_lp; + + tmp_lp = lp_parm_string_list(SNUM(handle->conn), "recycle", "exclude_dir", NULL); -error: - talloc_destroy(ctx); - return -1; + DEBUG(10, ("recycle: exclude_dir = %s ...\n", tmp_lp?*tmp_lp:"")); + + return tmp_lp; } -static void recycle_disconnect(struct connection_struct *conn) +static const char **recycle_noversions(vfs_handle_struct *handle) { - recycle_bin_private_data *recdata; - recycle_bin_connections *recconn; + const char **tmp_lp; + + tmp_lp = lp_parm_string_list(SNUM(handle->conn), "recycle", "noversions", NULL); - DEBUG(10, ("Disconnecting VFS module recycle bin\n")); + DEBUG(10, ("recycle: noversions = %s\n", tmp_lp?*tmp_lp:"")); + + return tmp_lp; +} - if (recycle_bin_private_handle) - recdata = (recycle_bin_private_data *)(recycle_bin_private_handle->data); - else { - DEBUG(0, ("Recycle bin not initialized!\n")); - return; - } +static int recycle_maxsize(vfs_handle_struct *handle) +{ + int maxsize; + + maxsize = lp_parm_int(SNUM(handle->conn), "recycle", "maxsize", -1); - if (recdata) { - if (recdata->conns) { - if (recdata->conns->conn == SNUM(conn)) { - talloc_destroy(recdata->conns->data->mem_ctx); - recdata->conns = recdata->conns->next; - } else { - recconn = recdata->conns; - while (recconn->next) { - if (recconn->next->conn == SNUM(conn)) { - talloc_destroy(recconn->next->data->mem_ctx); - recconn->next = recconn->next->next; - break; - } - recconn = recconn->next; - } - } - } - } - default_vfs_ops.disconnect(conn); + DEBUG(10, ("recycle: maxsize = %d\n", maxsize)); + + return maxsize; } -static BOOL recycle_directory_exist(connection_struct *conn, const char *dname) +static BOOL recycle_directory_exist(vfs_handle_struct *handle, const char *dname) { SMB_STRUCT_STAT st; - if (default_vfs_ops.stat(conn, dname, &st) == 0) { + if (SMB_VFS_NEXT_STAT(handle, handle->conn, dname, &st) == 0) { if (S_ISDIR(st.st_mode)) { return True; } @@ -263,11 +166,11 @@ static BOOL recycle_directory_exist(connection_struct *conn, const char *dname) return False; } -static BOOL recycle_file_exist(connection_struct *conn, const char *fname) +static BOOL recycle_file_exist(vfs_handle_struct *handle, const char *fname) { SMB_STRUCT_STAT st; - if (default_vfs_ops.stat(conn, fname, &st) == 0) { + if (SMB_VFS_NEXT_STAT(handle, handle->conn, fname, &st) == 0) { if (S_ISREG(st.st_mode)) { return True; } @@ -282,13 +185,15 @@ static BOOL recycle_file_exist(connection_struct *conn, const char *fname) * @param fname file name * @return size in bytes **/ -static SMB_OFF_T recycle_get_file_size(connection_struct *conn, const char *fname) +static SMB_OFF_T recycle_get_file_size(vfs_handle_struct *handle, const char *fname) { SMB_STRUCT_STAT st; - if (default_vfs_ops.stat(conn, fname, &st) != 0) { - DEBUG(0,("recycle.bin: stat for %s returned %s\n", fname, strerror(errno))); + + if (SMB_VFS_NEXT_STAT(handle, handle->conn, fname, &st) != 0) { + DEBUG(0,("recycle: stat for %s returned %s\n", fname, strerror(errno))); return (SMB_OFF_T)0; } + return(st.st_size); } @@ -298,7 +203,7 @@ static SMB_OFF_T recycle_get_file_size(connection_struct *conn, const char *fnam * @param dname Directory tree to be created * @return Returns True for success **/ -static BOOL recycle_create_dir(connection_struct *conn, const char *dname) +static BOOL recycle_create_dir(vfs_handle_struct *handle, const char *dname) { int len; mode_t mode; @@ -322,18 +227,18 @@ static BOOL recycle_create_dir(connection_struct *conn, const char *dname) /* Create directory tree if neccessary */ for(token = strtok(tok_str, "/"); token; token = strtok(NULL, "/")) { safe_strcat(new_dir, token, len); - if (recycle_directory_exist(conn, new_dir)) - DEBUG(10, ("recycle.bin: dir %s already exists\n", new_dir)); + if (recycle_directory_exist(handle, new_dir)) + DEBUG(10, ("recycle: dir %s already exists\n", new_dir)); else { - DEBUG(5, ("recycle.bin: creating new dir %s\n", new_dir)); - if (default_vfs_ops.mkdir(conn, new_dir, mode) != 0) { - DEBUG(1,("recycle.bin: mkdir failed for %s with error: %s\n", new_dir, strerror(errno))); + DEBUG(5, ("recycle: creating new dir %s\n", new_dir)); + if (SMB_VFS_NEXT_MKDIR(handle, handle->conn, new_dir, mode) != 0) { + DEBUG(1,("recycle: mkdir failed for %s with error: %s\n", new_dir, strerror(errno))); ret = False; goto done; } } safe_strcat(new_dir, "/", len); - } + } ret = True; done: @@ -348,30 +253,22 @@ done: * @param needle string to be matched exactly to haystack * @return True if found **/ -static BOOL checkparam(const char *haystack, const char *needle) +static BOOL checkparam(const char **haystack_list, const char *needle) { - char *token; - char *tok_str; - char *tmp_str; - BOOL ret = False; + int i; - if (haystack == NULL || strlen(haystack) == 0 || needle == NULL || strlen(needle) == 0) { + if (haystack_list == NULL || haystack_list[0] == NULL || + *haystack_list[0] == '\0' || needle == NULL || *needle == '\0') { return False; } - tmp_str = strdup(haystack); - ALLOC_CHECK(tmp_str, done); - token = tok_str = tmp_str; - - for(token = strtok(tok_str, delimiter); token; token = strtok(NULL, delimiter)) { - if(strcmp(token, needle) == 0) { - ret = True; - goto done; + for(i=0; haystack_list[i] ; i++) { + if(strequal(haystack_list[i], needle)) { + return True; } } -done: - SAFE_FREE(tmp_str); - return ret; + + return False; } /** @@ -380,110 +277,87 @@ done: * @param needle string to be matched exectly to haystack including pattern matching * @return True if found **/ -static BOOL matchparam(const char *haystack, const char *needle) +static BOOL matchparam(const char **haystack_list, const char *needle) { - char *token; - char *tok_str; - char *tmp_str; - BOOL ret = False; + int i; - if (haystack == NULL || strlen(haystack) == 0 || needle == NULL || strlen(needle) == 0) { + if (haystack_list == NULL || haystack_list[0] == NULL || + *haystack_list[0] == '\0' || needle == NULL || *needle == '\0') { return False; } - tmp_str = strdup(haystack); - ALLOC_CHECK(tmp_str, done); - token = tok_str = tmp_str; - - for(token = strtok(tok_str, delimiter); token; token = strtok(NULL, delimiter)) { - if (!unix_wild_match(token, needle)) { - ret = True; - goto done; + for(i=0; haystack_list[i] ; i++) { + if(!unix_wild_match(haystack_list[i], needle)) { + return True; } } -done: - SAFE_FREE(tmp_str); - return ret; + + return False; } /** * Touch access date **/ -static void recycle_touch(connection_struct *conn, const char *fname) +static void recycle_do_touch(vfs_handle_struct *handle, const char *fname) { SMB_STRUCT_STAT st; struct utimbuf tb; time_t currtime; - - if (default_vfs_ops.stat(conn, fname, &st) != 0) { - DEBUG(0,("recycle.bin: stat for %s returned %s\n", fname, strerror(errno))); + + if (SMB_VFS_NEXT_STAT(handle, handle->conn, fname, &st) != 0) { + DEBUG(0,("recycle: stat for %s returned %s\n", fname, strerror(errno))); return; } currtime = time(&currtime); tb.actime = currtime; tb.modtime = st.st_mtime; - if (default_vfs_ops.utime(conn, fname, &tb) == -1 ) - DEBUG(0, ("recycle.bin: touching %s failed, reason = %s\n", fname, strerror(errno))); + if (SMB_VFS_NEXT_UTIME(handle, handle->conn, fname, &tb) == -1 ) { + DEBUG(0, ("recycle: touching %s failed, reason = %s\n", fname, strerror(errno))); } +} /** * Check if file should be recycled **/ -static int recycle_unlink(connection_struct *conn, const char *file_name) +static int recycle_unlink(vfs_handle_struct *handle, connection_struct *conn, const char *file_name) { - recycle_bin_private_data *recdata; - recycle_bin_connections *recconn; - recycle_bin_struct *recbin; char *path_name = NULL; char *temp_name = NULL; char *final_name = NULL; const char *base; - int i; -/* SMB_BIG_UINT dfree, dsize, bsize; */ + char *repository = NULL; + int i = 1; + int maxsize; SMB_OFF_T file_size; /* space_avail; */ BOOL exist; int rc = -1; - recbin = NULL; - if (recycle_bin_private_handle) { - recdata = (recycle_bin_private_data *)(recycle_bin_private_handle->data); - if (recdata) { - if (recdata->conns) { - recconn = recdata->conns; - while (recconn && recconn->conn != SNUM(conn)) recconn = recconn->next; - if (recconn != NULL) { - recbin = recconn->data; - } - } - } - } - if (recbin == NULL) { - DEBUG(0, ("Recycle bin not initialized!\n")); - rc = default_vfs_ops.unlink(conn, file_name); - goto done; - } - - if(!recbin->repository || *(recbin->repository) == '\0') { - DEBUG(3, ("Recycle path not set, purging %s...\n", file_name)); - rc = default_vfs_ops.unlink(conn, file_name); + repository = alloc_sub_conn(conn, recycle_repository(handle)); + ALLOC_CHECK(repository, done); + /* shouldn't we allow absolute path names here? --metze */ + trim_string(repository, "/", "/"); + + if(!repository || *(repository) == '\0') { + DEBUG(3, ("recycle: repository path not set, purging %s...\n", file_name)); + rc = SMB_VFS_NEXT_UNLINK(handle, conn, file_name); goto done; } /* we don't recycle the recycle bin... */ - if (strncmp(file_name, recbin->repository, strlen(recbin->repository)) == 0) { - DEBUG(3, ("File is within recycling bin, unlinking ...\n")); - rc = default_vfs_ops.unlink(conn, file_name); + if (strncmp(file_name, repository, strlen(repository)) == 0) { + DEBUG(3, ("recycle: File is within recycling bin, unlinking ...\n")); + rc = SMB_VFS_NEXT_UNLINK(handle, conn, file_name); goto done; } - file_size = recycle_get_file_size(conn, file_name); + file_size = recycle_get_file_size(handle, file_name); /* it is wrong to purge filenames only because they are empty imho * --- simo * if(fsize == 0) { - DEBUG(3, ("File %s is empty, purging...\n", file_name)); - rc = default_vfs_ops.unlink(conn,file_name); + DEBUG(3, ("recycle: File %s is empty, purging...\n", file_name)); + rc = SMB_VFS_NEXT_UNLINK(handle,conn,file_name); goto done; } */ @@ -492,20 +366,21 @@ static int recycle_unlink(connection_struct *conn, const char *file_name) * not greater then maxsize, not the size of the single file, also it is better * to remove older files */ - if(recbin->maxsize > 0 && file_size > recbin->maxsize) { - DEBUG(3, ("File %s exceeds maximum recycle size, purging... \n", file_name)); - rc = default_vfs_ops.unlink(conn, file_name); + maxsize = recycle_maxsize(handle); + if(maxsize > 0 && file_size > maxsize) { + DEBUG(3, ("recycle: File %s exceeds maximum recycle size, purging... \n", file_name)); + rc = SMB_VFS_NEXT_UNLINK(handle, conn, file_name); goto done; } /* FIXME: this is wrong: moving files with rename does not change the disk space * allocation * - space_avail = default_vfs_ops.disk_free(conn, ".", True, &bsize, &dfree, &dsize) * 1024L; + space_avail = SMB_VFS_NEXT_DISK_FREE(handle, conn, ".", True, &bsize, &dfree, &dsize) * 1024L; DEBUG(5, ("space_avail = %Lu, file_size = %Lu\n", space_avail, file_size)); if(space_avail < file_size) { - DEBUG(3, ("Not enough diskspace, purging file %s\n", file_name)); - rc = default_vfs_ops.unlink(conn, file_name); + DEBUG(3, ("recycle: Not enough diskspace, purging file %s\n", file_name)); + rc = SMB_VFS_NEXT_UNLINK(handle, conn, file_name); goto done; } */ @@ -524,13 +399,13 @@ static int recycle_unlink(connection_struct *conn, const char *file_name) base++; } - DEBUG(10, ("recycle.bin: fname = %s\n", file_name)); /* original filename with path */ - DEBUG(10, ("recycle.bin: fpath = %s\n", path_name)); /* original path */ - DEBUG(10, ("recycle.bin: base = %s\n", base)); /* filename without path */ + DEBUG(10, ("recycle: fname = %s\n", file_name)); /* original filename with path */ + DEBUG(10, ("recycle: fpath = %s\n", path_name)); /* original path */ + DEBUG(10, ("recycle: base = %s\n", base)); /* filename without path */ - if (matchparam(recbin->exclude, base)) { - DEBUG(3, ("recycle.bin: file %s is excluded \n", base)); - rc = default_vfs_ops.unlink(conn, file_name); + if (matchparam(recycle_exclude(handle), base)) { + DEBUG(3, ("recycle: file %s is excluded \n", base)); + rc = SMB_VFS_NEXT_UNLINK(handle, conn, file_name); goto done; } @@ -538,72 +413,85 @@ static int recycle_unlink(connection_struct *conn, const char *file_name) * we shoud check for every level 1, 1/2, 1/2/3, 1/2/3/4 .... * ---simo */ - if (checkparam(recbin->exclude_dir, path_name)) { - DEBUG(3, ("recycle.bin: directory %s is excluded \n", path_name)); - rc = default_vfs_ops.unlink(conn, file_name); + if (checkparam(recycle_exclude_dir(handle), path_name)) { + DEBUG(3, ("recycle: directory %s is excluded \n", path_name)); + rc = SMB_VFS_NEXT_UNLINK(handle, conn, file_name); goto done; } - /* see if we need to recreate the original directory structure in the recycle bin */ - if (recbin->keep_dir_tree == True) { - asprintf(&temp_name, "%s/%s", recbin->repository, path_name); + if (recycle_keep_dir_tree(handle) == True) { + asprintf(&temp_name, "%s/%s", repository, path_name); } else { - temp_name = strdup(recbin->repository); + temp_name = strdup(repository); } ALLOC_CHECK(temp_name, done); - exist = recycle_directory_exist(conn, temp_name); + exist = recycle_directory_exist(handle, temp_name); if (exist) { - DEBUG(10, ("recycle.bin: Directory already exists\n")); + DEBUG(10, ("recycle: Directory already exists\n")); } else { - DEBUG(10, ("recycle.bin: Creating directory %s\n", temp_name)); - if (recycle_create_dir(conn, temp_name) == False) { - DEBUG(3, ("Could not create directory, purging %s...\n", file_name)); - rc = default_vfs_ops.unlink(conn, file_name); + DEBUG(10, ("recycle: Creating directory %s\n", temp_name)); + if (recycle_create_dir(handle, temp_name) == False) { + DEBUG(3, ("recycle: Could not create directory, purging %s...\n", file_name)); + rc = SMB_VFS_NEXT_UNLINK(handle, conn, file_name); goto done; } } asprintf(&final_name, "%s/%s", temp_name, base); ALLOC_CHECK(final_name, done); - DEBUG(10, ("recycle.bin: recycled file name: %s\n", temp_name)); /* new filename with path */ + DEBUG(10, ("recycle: recycled file name: %s\n", final_name)); /* new filename with path */ /* check if we should delete file from recycle bin */ - if (recycle_file_exist(conn, final_name)) { - if (recbin->versions == False || matchparam(recbin->noversions, base) == True) { - DEBUG(3, ("recycle.bin: Removing old file %s from recycle bin\n", final_name)); - if (default_vfs_ops.unlink(conn, final_name) != 0) { - DEBUG(1, ("recycle.bin: Error deleting old file: %s\n", strerror(errno))); + if (recycle_file_exist(handle, final_name)) { + if (recycle_versions(handle) == False || matchparam(recycle_noversions(handle), base) == True) { + DEBUG(3, ("recycle: Removing old file %s from recycle bin\n", final_name)); + if (SMB_VFS_NEXT_UNLINK(handle, conn, final_name) != 0) { + DEBUG(1, ("recycle: Error deleting old file: %s\n", strerror(errno))); } } } /* rename file we move to recycle bin */ i = 1; - while (recycle_file_exist(conn, final_name)) { - snprintf(final_name, PATH_MAX, "%s/Copy #%d of %s", temp_name, i++, base); + while (recycle_file_exist(handle, final_name)) { + snprintf(final_name, PATH_MAX -1, "%s/Copy #%d of %s", temp_name, i++, base); } - DEBUG(10, ("recycle.bin: Moving %s to %s\n", file_name, final_name)); - rc = default_vfs_ops.rename(conn, file_name, final_name); + DEBUG(10, ("recycle: Moving %s to %s\n", file_name, final_name)); + rc = SMB_VFS_NEXT_RENAME(handle, conn, file_name, final_name); if (rc != 0) { - DEBUG(3, ("recycle.bin: Move error %d (%s), purging file %s (%s)\n", errno, strerror(errno), file_name, final_name)); - rc = default_vfs_ops.unlink(conn, file_name); + DEBUG(3, ("recycle: Move error %d (%s), purging file %s (%s)\n", errno, strerror(errno), file_name, final_name)); + rc = SMB_VFS_NEXT_UNLINK(handle, conn, file_name); goto done; } /* touch access date of moved file */ - if (recbin->touch == True ) - recycle_touch(conn, final_name); + if (recycle_touch(handle) == True ) + recycle_do_touch(handle, final_name); done: SAFE_FREE(path_name); SAFE_FREE(temp_name); SAFE_FREE(final_name); + SAFE_FREE(repository); return rc; } NTSTATUS vfs_recycle_init(void) -{ - return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "recycle", recycle_init); +{ + NTSTATUS ret = smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "recycle", recycle_ops); + + if (!NT_STATUS_IS_OK(ret)) + return ret; + + vfs_recycle_debug_level = debug_add_class("recycle"); + if (vfs_recycle_debug_level == -1) { + vfs_recycle_debug_level = DBGC_VFS; + DEBUG(0, ("vfs_recycle: Couldn't register custom debugging class!\n")); + } else { + DEBUG(10, ("vfs_recycle: Debug class number of 'recycle': %d\n", vfs_recycle_debug_level)); + } + + return ret; } diff --git a/source3/msdfs/msdfs.c b/source3/msdfs/msdfs.c index 69a315d4e4..ce6e64d915 100644 --- a/source3/msdfs/msdfs.c +++ b/source3/msdfs/msdfs.c @@ -164,19 +164,19 @@ BOOL is_msdfs_link(connection_struct* conn, char* path, if (!path || !conn) return False; - strlower(path); + strlower_m(path); if (sbufp == NULL) sbufp = &st; - if (conn->vfs_ops.lstat(conn, path, sbufp) != 0) { + if (SMB_VFS_LSTAT(conn, path, sbufp) != 0) { DEBUG(5,("is_msdfs_link: %s does not exist.\n",path)); return False; } if (S_ISLNK(sbufp->st_mode)) { /* open the link and read it */ - referral_len = conn->vfs_ops.readlink(conn, path, referral, + referral_len = SMB_VFS_READLINK(conn, path, referral, sizeof(pstring)); if (referral_len == -1) { DEBUG(0,("is_msdfs_link: Error reading msdfs link %s: %s\n", path, strerror(errno))); @@ -740,7 +740,7 @@ static BOOL junction_to_local_path(struct junction_map* jn, char* path, safe_strcpy(path, lp_pathname(snum), max_pathlen-1); safe_strcat(path, "/", max_pathlen-1); - strlower(jn->volume_name); + strlower_m(jn->volume_name); safe_strcat(path, jn->volume_name, max_pathlen-1); pstrcpy(conn_path, lp_pathname(snum)); @@ -785,10 +785,10 @@ BOOL create_msdfs_link(struct junction_map* jn, BOOL exists) DEBUG(5,("create_msdfs_link: Creating new msdfs link: %s -> %s\n", path, msdfs_link)); if(exists) - if(conn->vfs_ops.unlink(conn,path)!=0) + if(SMB_VFS_UNLINK(conn,path)!=0) return False; - if(conn->vfs_ops.symlink(conn, msdfs_link, path) < 0) { + if(SMB_VFS_SYMLINK(conn, msdfs_link, path) < 0) { DEBUG(1,("create_msdfs_link: symlink failed %s -> %s\nError: %s\n", path, msdfs_link, strerror(errno))); return False; @@ -805,7 +805,7 @@ BOOL remove_msdfs_link(struct junction_map* jn) if(!junction_to_local_path(jn, path, sizeof(path), conn)) return False; - if(conn->vfs_ops.unlink(conn, path)!=0) + if(SMB_VFS_UNLINK(conn, path)!=0) return False; return True; @@ -862,7 +862,7 @@ static BOOL form_junctions(int snum, struct junction_map* jn, int* jn_count) cnt++; /* Now enumerate all dfs links */ - dirp = conn->vfs_ops.opendir(conn, connect_path); + dirp = SMB_VFS_OPENDIR(conn, connect_path); if(!dirp) return False; @@ -881,7 +881,7 @@ static BOOL form_junctions(int snum, struct junction_map* jn, int* jn_count) } } - conn->vfs_ops.closedir(conn,dirp); + SMB_VFS_CLOSEDIR(conn,dirp); *jn_count = cnt; return True; } diff --git a/source3/nmbd/nmbd.c b/source3/nmbd/nmbd.c index ad5ab4d734..2801e54551 100644 --- a/source3/nmbd/nmbd.c +++ b/source3/nmbd/nmbd.c @@ -298,6 +298,28 @@ static BOOL reload_nmbd_services(BOOL test) return(ret); } +/**************************************************************************** ** + * React on 'smbcontrol nmbd reload-config' in the same way as to SIGHUP + * We use buf here to return BOOL result to process() when reload_interfaces() + * detects that there are no subnets. + **************************************************************************** */ +static void msg_reload_nmbd_services(int msg_type, pid_t src, void *buf, size_t len) +{ + write_browse_list( 0, True ); + dump_all_namelists(); + reload_nmbd_services( True ); + reopen_logs(); + + if(buf) { + /* We were called from process() */ + /* If reload_interfaces() returned True */ + /* we need to shutdown if there are no subnets... */ + /* pass this info back to process() */ + *((BOOL*)buf) = reload_interfaces(0); + } +} + + /**************************************************************************** ** The main select loop. **************************************************************************** */ @@ -305,6 +327,7 @@ static BOOL reload_nmbd_services(BOOL test) static void process(void) { BOOL run_election; + BOOL no_subnets; while( True ) { time_t t = time(NULL); @@ -513,11 +536,8 @@ static void process(void) if(reload_after_sighup) { DEBUG( 0, ( "Got SIGHUP dumping debug info.\n" ) ); - write_browse_list( 0, True ); - dump_all_namelists(); - reload_nmbd_services( True ); - reopen_logs(); - if(reload_interfaces(0)) + msg_reload_nmbd_services(MSG_SMB_CONF_UPDATED, (pid_t) 0, (void*) &no_subnets, 0); + if(no_subnets) return; reload_after_sighup = 0; } @@ -573,8 +593,10 @@ static BOOL open_sockets(BOOL isdaemon, int port) **************************************************************************** */ int main(int argc, const char *argv[]) { - static BOOL opt_interactive = False; + pstring logfile; + static BOOL opt_interactive; poptContext pc; + int opt; struct poptOption long_options[] = { POPT_AUTOHELP {"daemon", 'D', POPT_ARG_VAL, &is_daemon, True, "Become a daemon(default)" }, @@ -586,46 +608,47 @@ static BOOL open_sockets(BOOL isdaemon, int port) POPT_COMMON_SAMBA { NULL } }; - pstring logfile; - - global_nmb_port = NMB_PORT; - global_in_nmbd = True; - - StartupTime = time(NULL); - - sys_srandom(time(NULL) ^ sys_getpid()); - slprintf(logfile, sizeof(logfile)-1, "%s/log.nmbd", dyn_LOGFILEBASE); - lp_set_logfile(logfile); + global_nmb_port = NMB_PORT; - fault_setup((void (*)(void *))fault_continue ); - - /* POSIX demands that signals are inherited. If the invoking process has - * these signals masked, we will have problems, as we won't receive them. */ - BlockSignals(False, SIGHUP); - BlockSignals(False, SIGUSR1); - BlockSignals(False, SIGTERM); - - CatchSignal( SIGHUP, SIGNAL_CAST sig_hup ); - CatchSignal( SIGTERM, SIGNAL_CAST sig_term ); + pc = poptGetContext("nmbd", argc, argv, long_options, 0); + while ((opt = poptGetNextOpt(pc)) != -1) ; + poptFreeContext(pc); + global_in_nmbd = True; + + StartupTime = time(NULL); + + sys_srandom(time(NULL) ^ sys_getpid()); + + slprintf(logfile, sizeof(logfile)-1, "%s/log.nmbd", dyn_LOGFILEBASE); + lp_set_logfile(logfile); + + fault_setup((void (*)(void *))fault_continue ); + + /* POSIX demands that signals are inherited. If the invoking process has + * these signals masked, we will have problems, as we won't receive them. */ + BlockSignals(False, SIGHUP); + BlockSignals(False, SIGUSR1); + BlockSignals(False, SIGTERM); + + CatchSignal( SIGHUP, SIGNAL_CAST sig_hup ); + CatchSignal( SIGTERM, SIGNAL_CAST sig_term ); + #if defined(SIGFPE) - /* we are never interested in SIGFPE */ - BlockSignals(True,SIGFPE); + /* we are never interested in SIGFPE */ + BlockSignals(True,SIGFPE); #endif - /* We no longer use USR2... */ + /* We no longer use USR2... */ #if defined(SIGUSR2) - BlockSignals(True, SIGUSR2); + BlockSignals(True, SIGUSR2); #endif - pc = poptGetContext("nmbd", argc, argv, long_options, 0); - - poptFreeContext(pc); - if ( opt_interactive ) { - Fork = False; - log_stdout = True; - } + if ( opt_interactive ) { + Fork = False; + log_stdout = True; + } if ( log_stdout && Fork ) { DEBUG(0,("ERROR: Can't log to stdout (-S) unless daemon is in foreground (-F) or interactive (-i)\n")); @@ -693,6 +716,7 @@ static BOOL open_sockets(BOOL isdaemon, int port) message_register(MSG_FORCE_ELECTION, nmbd_message_election); message_register(MSG_WINS_NEW_ENTRY, nmbd_wins_new_entry); message_register(MSG_SHUTDOWN, nmbd_terminate); + message_register(MSG_SMB_CONF_UPDATED, msg_reload_nmbd_services); DEBUG( 3, ( "Opening sockets %d\n", global_nmb_port ) ); diff --git a/source3/nmbd/nmbd_become_lmb.c b/source3/nmbd/nmbd_become_lmb.c index 6f8e7efb1a..d390bf72e9 100644 --- a/source3/nmbd/nmbd_become_lmb.c +++ b/source3/nmbd/nmbd_become_lmb.c @@ -600,6 +600,5 @@ local_master_browser_name for workgroup %s to workgroup name.\n", } #endif - StrnCpy(work->local_master_browser_name, newname, - sizeof(work->local_master_browser_name)-1); + fstrcpy(work->local_master_browser_name, newname); } diff --git a/source3/nmbd/nmbd_browserdb.c b/source3/nmbd/nmbd_browserdb.c index a4ef98e265..4a302ddfd4 100644 --- a/source3/nmbd/nmbd_browserdb.c +++ b/source3/nmbd/nmbd_browserdb.c @@ -37,7 +37,6 @@ ubi_dlNewList( lmb_browserlist ); - /* -------------------------------------------------------------------------- ** * Functions... */ @@ -52,9 +51,9 @@ ubi_dlNewList( lmb_browserlist ); * ************************************************************************** ** */ static void remove_lmb_browser_entry( struct browse_cache_record *browc ) - { - safe_free( ubi_dlRemThis( lmb_browserlist, browc ) ); - } /* remove_lmb_browser_entry */ +{ + safe_free( ubi_dlRemThis( lmb_browserlist, browc ) ); +} /* ************************************************************************** ** * Update a browser death time. @@ -65,10 +64,10 @@ static void remove_lmb_browser_entry( struct browse_cache_record *browc ) * ************************************************************************** ** */ void update_browser_death_time( struct browse_cache_record *browc ) - { - /* Allow the new lmb to miss an announce period before we remove it. */ - browc->death_time = time(NULL) + ( (CHECK_TIME_MST_ANNOUNCE + 2) * 60 ); - } /* update_browser_death_time */ +{ + /* Allow the new lmb to miss an announce period before we remove it. */ + browc->death_time = time(NULL) + ( (CHECK_TIME_MST_ANNOUNCE + 2) * 60 ); +} /* ************************************************************************** ** * Create a browser entry and add it to the local master browser list. @@ -84,48 +83,47 @@ void update_browser_death_time( struct browse_cache_record *browc ) struct browse_cache_record *create_browser_in_lmb_cache( char *work_name, char *browser_name, struct in_addr ip ) - { - struct browse_cache_record *browc; - time_t now = time( NULL ); +{ + struct browse_cache_record *browc; + time_t now = time( NULL ); - browc = (struct browse_cache_record *)malloc( sizeof( *browc ) ); + browc = (struct browse_cache_record *)malloc( sizeof( *browc ) ); - if( NULL == browc ) - { - DEBUG( 0, ("create_browser_in_lmb_cache: malloc fail !\n") ); - return( NULL ); - } + if( NULL == browc ) { + DEBUG( 0, ("create_browser_in_lmb_cache: malloc fail !\n") ); + return( NULL ); + } - memset( (char *)browc, '\0', sizeof( *browc ) ); + memset( (char *)browc, '\0', sizeof( *browc ) ); - /* For a new lmb entry we want to sync with it after one minute. This - will allow it time to send out a local announce and build its - browse list. - */ - browc->sync_time = now + 60; - - /* Allow the new lmb to miss an announce period before we remove it. */ - browc->death_time = now + ( (CHECK_TIME_MST_ANNOUNCE + 2) * 60 ); - - StrnCpy( browc->lmb_name, browser_name, sizeof(browc->lmb_name)-1 ); - StrnCpy( browc->work_group, work_name, sizeof(browc->work_group)-1 ); - strupper( browc->lmb_name ); - strupper( browc->work_group ); + /* For a new lmb entry we want to sync with it after one minute. This + will allow it time to send out a local announce and build its + browse list. + */ + + browc->sync_time = now + 60; + + /* Allow the new lmb to miss an announce period before we remove it. */ + browc->death_time = now + ( (CHECK_TIME_MST_ANNOUNCE + 2) * 60 ); + + pstrcpy( browc->lmb_name, browser_name); + pstrcpy( browc->work_group, work_name); + strupper_m( browc->lmb_name ); + strupper_m( browc->work_group ); - browc->ip = ip; + browc->ip = ip; - (void)ubi_dlAddTail( lmb_browserlist, browc ); - - if( DEBUGLVL( 3 ) ) - { - Debug1( "nmbd_browserdb:create_browser_in_lmb_cache()\n" ); - Debug1( " Added lmb cache entry for workgroup %s ", browc->work_group ); - Debug1( "name %s IP %s ", browc->lmb_name, inet_ntoa(ip) ); - Debug1( "ttl %d\n", (int)browc->death_time ); - } + (void)ubi_dlAddTail( lmb_browserlist, browc ); + + if( DEBUGLVL( 3 ) ) { + Debug1( "nmbd_browserdb:create_browser_in_lmb_cache()\n" ); + Debug1( " Added lmb cache entry for workgroup %s ", browc->work_group ); + Debug1( "name %s IP %s ", browc->lmb_name, inet_ntoa(ip) ); + Debug1( "ttl %d\n", (int)browc->death_time ); + } - return( browc ); - } /* create_browser_in_lmb_cache */ + return( browc ); +} /* ************************************************************************** ** * Find a browser entry in the local master browser list. @@ -137,17 +135,16 @@ struct browse_cache_record *create_browser_in_lmb_cache( char *work_name, * ************************************************************************** ** */ struct browse_cache_record *find_browser_in_lmb_cache( char *browser_name ) - { - struct browse_cache_record *browc; +{ + struct browse_cache_record *browc; - for( browc = (struct browse_cache_record *)ubi_dlFirst( lmb_browserlist ); - browc; - browc = (struct browse_cache_record *)ubi_dlNext( browc ) ) - if( strequal( browser_name, browc->lmb_name ) ) - break; + for( browc = (struct browse_cache_record *)ubi_dlFirst( lmb_browserlist ); + browc; browc = (struct browse_cache_record *)ubi_dlNext( browc ) ) + if( strequal( browser_name, browc->lmb_name ) ) + break; - return( browc ); - } /* find_browser_in_lmb_cache */ + return( browc ); +} /* ************************************************************************** ** * Expire timed out browsers in the browserlist. @@ -159,24 +156,20 @@ struct browse_cache_record *find_browser_in_lmb_cache( char *browser_name ) * ************************************************************************** ** */ void expire_lmb_browsers( time_t t ) - { - struct browse_cache_record *browc; - struct browse_cache_record *nextbrowc; - - for( browc = (struct browse_cache_record *)ubi_dlFirst( lmb_browserlist ); - browc; - browc = nextbrowc ) - { - nextbrowc = (struct browse_cache_record *)ubi_dlNext( browc ); - - if( browc->death_time < t ) - { - if( DEBUGLVL( 3 ) ) - { - Debug1( "nmbd_browserdb:expire_lmb_browsers()\n" ); - Debug1( " Removing timed out lmb entry %s\n", browc->lmb_name ); - } - remove_lmb_browser_entry( browc ); - } - } - } /* expire_lmb_browsers */ +{ + struct browse_cache_record *browc; + struct browse_cache_record *nextbrowc; + + for( browc = (struct browse_cache_record *)ubi_dlFirst( lmb_browserlist ); + browc; browc = nextbrowc ) { + nextbrowc = (struct browse_cache_record *)ubi_dlNext( browc ); + + if( browc->death_time < t ) { + if( DEBUGLVL( 3 ) ) { + Debug1( "nmbd_browserdb:expire_lmb_browsers()\n" ); + Debug1( " Removing timed out lmb entry %s\n", browc->lmb_name ); + } + remove_lmb_browser_entry( browc ); + } + } +} diff --git a/source3/nmbd/nmbd_browsesync.c b/source3/nmbd/nmbd_browsesync.c index adfefc9f27..26d4735744 100644 --- a/source3/nmbd/nmbd_browsesync.c +++ b/source3/nmbd/nmbd_browsesync.c @@ -106,6 +106,7 @@ As a local master browser, send an announce packet to the domain master browser. static void announce_local_master_browser_to_domain_master_browser( struct work_record *work) { pstring outbuf; + fstring myname; char *p; if(ismyip(work->dmb_addr)) @@ -125,8 +126,11 @@ static void announce_local_master_browser_to_domain_master_browser( struct work_ SCVAL(p,0,ANN_MasterAnnouncement); p++; - StrnCpy(p,global_myname(),15); - strupper(p); + fstrcpy(myname, global_myname()); + strupper_m(myname); + myname[15]='\0'; + push_pstring_base(p, myname, outbuf); + p = skip_string(p,1); if( DEBUGLVL( 4 ) ) diff --git a/source3/nmbd/nmbd_elections.c b/source3/nmbd/nmbd_elections.c index 339a27d207..b948eb9d04 100644 --- a/source3/nmbd/nmbd_elections.c +++ b/source3/nmbd/nmbd_elections.c @@ -48,7 +48,7 @@ static void send_election_dgram(struct subnet_record *subrec, const char *workgr SIVAL(p,5,timeup*1000); /* ms - Despite what the spec says. */ p += 13; pstrcpy_base(p, server_name, outbuf); - strupper(p); + strupper_m(p); p = skip_string(p,1); send_mailslot(False, BROWSE_MAILSLOT, outbuf, PTR_DIFF(p,outbuf), diff --git a/source3/nmbd/nmbd_incomingdgrams.c b/source3/nmbd/nmbd_incomingdgrams.c index cd6954fc62..80465ada0d 100644 --- a/source3/nmbd/nmbd_incomingdgrams.c +++ b/source3/nmbd/nmbd_incomingdgrams.c @@ -172,7 +172,7 @@ void process_host_announce(struct subnet_record *subrec, struct packet_struct *p /* Update the record. */ servrec->serv.type = servertype|SV_TYPE_LOCAL_LIST_ONLY; update_server_ttl( servrec, ttl); - StrnCpy(servrec->serv.comment,comment,sizeof(servrec->serv.comment)-1); + fstrcpy(servrec->serv.comment,comment); } } else @@ -343,7 +343,7 @@ a local master browser for workgroup %s and we think we are master. Forcing elec /* Update the record. */ servrec->serv.type = servertype|SV_TYPE_LOCAL_LIST_ONLY; update_server_ttl(servrec, ttl); - StrnCpy(servrec->serv.comment,comment,sizeof(servrec->serv.comment)-1); + fstrcpy(servrec->serv.comment,comment); } set_workgroup_local_master_browser_name( work, server_name ); @@ -520,7 +520,7 @@ originate from OS/2 Warp client. Ignoring packet.\n")); /* Update the record. */ servrec->serv.type = servertype|SV_TYPE_LOCAL_LIST_ONLY; update_server_ttl( servrec, ttl); - StrnCpy(servrec->serv.comment,comment,sizeof(servrec->serv.comment)-1); + fstrcpy(servrec->serv.comment,comment); } } else @@ -559,6 +559,7 @@ static void send_backup_list_response(struct subnet_record *subrec, #if 0 struct server_record *servrec; #endif + fstring myname; memset(outbuf,'\0',sizeof(outbuf)); @@ -578,8 +579,11 @@ static void send_backup_list_response(struct subnet_record *subrec, /* We always return at least one name - our own. */ count = 1; - StrnCpy(p,global_myname(),15); - strupper(p); + fstrcpy(myname, global_myname()); + strupper_m(myname); + myname[15]='\0'; + push_pstring_base(p, myname, outbuf); + p = skip_string(p,1); /* Look for backup browsers in this workgroup. */ @@ -610,7 +614,7 @@ static void send_backup_list_response(struct subnet_record *subrec, continue; StrnCpy(p, servrec->serv.name, 15); - strupper(p); + strupper_m(p); count++; DEBUG(5,("send_backup_list_response: Adding server %s number %d\n", diff --git a/source3/nmbd/nmbd_incomingrequests.c b/source3/nmbd/nmbd_incomingrequests.c index a8168566f1..a3faf5e104 100644 --- a/source3/nmbd/nmbd_incomingrequests.c +++ b/source3/nmbd/nmbd_incomingrequests.c @@ -364,7 +364,7 @@ subnet %s - name not found.\n", nmb_namestr(&nmb->question.question_name), /* Start with the name. */ memset(buf,'\0',18); slprintf(buf, 17, "%-15.15s",namerec->name.name); - strupper(buf); + strupper_m(buf); /* Put the name type and netbios flags in the buffer. */ buf[15] = name_type; diff --git a/source3/nmbd/nmbd_namelistdb.c b/source3/nmbd/nmbd_namelistdb.c index 932d926a91..3f6d2f3b64 100644 --- a/source3/nmbd/nmbd_namelistdb.c +++ b/source3/nmbd/nmbd_namelistdb.c @@ -49,8 +49,8 @@ static void upcase_name( struct nmb_name *target, struct nmb_name *source ) if( NULL != source ) (void)memcpy( target, source, sizeof( struct nmb_name ) ); - strupper( target->name ); - strupper( target->scope ); + strupper_m( target->name ); + strupper_m( target->scope ); /* fudge... We're using a byte-by-byte compare, so we must be sure that * unused space doesn't have garbage in it. diff --git a/source3/nmbd/nmbd_processlogon.c b/source3/nmbd/nmbd_processlogon.c index a702fc3015..42edcc871f 100644 --- a/source3/nmbd/nmbd_processlogon.c +++ b/source3/nmbd/nmbd_processlogon.c @@ -304,19 +304,19 @@ reporting %s domain %s 0x%x ntversion=%x lm_nt token=%x lm_20 token=%x\n", pstring hostname; char *component, *dc, *q1; uint8 size; + char *q_orig = q; + int str_offset; get_mydomname(domain); get_myname(hostname); if (SVAL(uniuser, 0) == 0) { - SSVAL(q, 0, SAMLOGON_AD_UNK_R); /* user unknown */ + SIVAL(q, 0, SAMLOGON_AD_UNK_R); /* user unknown */ } else { - SSVAL(q, 0, SAMLOGON_AD_R); + SIVAL(q, 0, SAMLOGON_AD_R); } - q += 2; + q += 4; - SSVAL(q, 0, 0); - q += 2; SIVAL(q, 0, ADS_PDC|ADS_GC|ADS_LDAP|ADS_DS| ADS_KDC|ADS_TIMESERV|ADS_CLOSEST|ADS_WRITABLE); q += 4; @@ -329,7 +329,8 @@ reporting %s domain %s 0x%x ntversion=%x lm_nt token=%x lm_20 token=%x\n", memcpy(q, &domain_guid, sizeof(domain_guid)); q += sizeof(domain_guid); - /* Push domain components */ + /* Forest */ + str_offset = q - q_orig; dc = domain; q1 = q; while ((component = strtok(dc, "."))) { @@ -338,44 +339,60 @@ reporting %s domain %s 0x%x ntversion=%x lm_nt token=%x lm_20 token=%x\n", SCVAL(q, 0, size); q += (size + 1); } + + /* Unk0 */ SCVAL(q, 0, 0); q++; - SSVAL(q, 0, 0x18c0); /* not sure what this is for, but */ - q += 2; /* it must follow the domain name. */ - /* Push dns host name */ + /* Domain */ + SCVAL(q, 0, 0xc0 | ((str_offset >> 8) & 0x3F)); + SCVAL(q, 1, str_offset & 0xFF); + q += 2; + + /* Hostname */ size = push_ascii(&q[1], hostname, -1, 0); SCVAL(q, 0, size); q += (size + 1); - SSVAL(q, 0, 0x18c0); /* not sure what this is for, but */ - q += 2; /* it must follow the domain name. */ + SCVAL(q, 0, 0xc0 | ((str_offset >> 8) & 0x3F)); + SCVAL(q, 1, str_offset & 0xFF); + q += 2; - /* Push NETBIOS of domain */ + /* NETBIOS of domain */ size = push_ascii(&q[1], lp_workgroup(), -1, STR_UPPER); SCVAL(q, 0, size); q += (size + 1); - SCVAL(q, 0, 0); q++; /* is this a null terminator or empty field */ - /* null terminator would not be needed because size is included */ - /* Push NETBIOS of hostname */ + /* Unk1 */ + SCVAL(q, 0, 0); q++; + + /* NETBIOS of hostname */ size = push_ascii(&q[1], my_name, -1, 0); SCVAL(q, 0, size); q += (size + 1); - SCVAL(q, 0, 0); q++; /* null terminator or empty field? */ - /* Push user account */ - size = push_ascii(&q[1], ascuser, -1, 0); - SCVAL(q, 0, size); - q += (size + 1); + /* Unk2 */ + SCVAL(q, 0, 0); q++; + + /* User name */ + if (SVAL(uniuser, 0) != 0) { + size = push_ascii(&q[1], ascuser, -1, 0); + SCVAL(q, 0, size); + q += (size + 1); + } - /* Push 'Default-First-Site-Name' */ + q_orig = q; + /* Site name */ size = push_ascii(&q[1], "Default-First-Site-Name", -1, 0); SCVAL(q, 0, size); q += (size + 1); - SSVAL(q, 0, 0xc000); /* unknown */ - SCVAL(q, 2, PTR_DIFF(q,q1)); - SCVAL(q, 3, 0x10); /* unknown */ - q += 4; + /* Site name (2) */ + str_offset = q - q_orig; + SCVAL(q, 0, 0xc0 | ((str_offset >> 8) & 0x3F)); + SCVAL(q, 1, str_offset & 0xFF); + q += 2; + + SCVAL(q, 0, PTR_DIFF(q,q1)); + SCVAL(q, 1, 0x10); /* unknown */ SIVAL(q, 0, 0x00000002); q += 4; /* unknown */ SIVAL(q, 0, (iface_ip(p->ip))->s_addr); q += 4; diff --git a/source3/nmbd/nmbd_sendannounce.c b/source3/nmbd/nmbd_sendannounce.c index 40d07aae16..353717ee62 100644 --- a/source3/nmbd/nmbd_sendannounce.c +++ b/source3/nmbd/nmbd_sendannounce.c @@ -142,7 +142,7 @@ static void send_lm_announcement(struct subnet_record *subrec, int announce_type p += 10; /*StrnCpy(p,server_name,15); - strupper(p); + strupper_m(p); p = skip_string(p,1); pstrcpy(p,server_comment); p = skip_string(p,1);*/ @@ -555,6 +555,7 @@ void browse_sync_remote(time_t t) struct work_record *work; pstring outbuf; char *p; + fstring myname; if (last_time && (t < (last_time + REMOTE_ANNOUNCE_INTERVAL))) return; @@ -589,8 +590,11 @@ for workgroup %s on subnet %s.\n", lp_workgroup(), FIRST_SUBNET->subnet_name )); SCVAL(p,0,ANN_MasterAnnouncement); p++; - StrnCpy(p,global_myname(),15); - strupper(p); + fstrcpy(myname, global_myname()); + strupper_m(myname); + myname[15]='\0'; + push_pstring_base(p, myname, outbuf); + p = skip_string(p,1); for (ptr=s; next_token(&ptr,s2,NULL,sizeof(s2)); ) diff --git a/source3/nmbd/nmbd_serverlistdb.c b/source3/nmbd/nmbd_serverlistdb.c index ee0c021d5d..2484a7f830 100644 --- a/source3/nmbd/nmbd_serverlistdb.c +++ b/source3/nmbd/nmbd_serverlistdb.c @@ -153,9 +153,9 @@ workgroup %s. This is a bug.\n", name, work->work_group)); servrec->subnet = work->subnet; - StrnCpy(servrec->serv.name,name,sizeof(servrec->serv.name)-1); - StrnCpy(servrec->serv.comment,comment,sizeof(servrec->serv.comment)-1); - strupper(servrec->serv.name); + fstrcpy(servrec->serv.name,name); + fstrcpy(servrec->serv.comment,comment); + strupper_m(servrec->serv.name); servrec->serv.type = servertype; update_server_ttl(servrec, ttl); diff --git a/source3/nmbd/nmbd_winsserver.c b/source3/nmbd/nmbd_winsserver.c index 47ce8119f3..eafff03b76 100644 --- a/source3/nmbd/nmbd_winsserver.c +++ b/source3/nmbd/nmbd_winsserver.c @@ -22,7 +22,7 @@ #include "includes.h" -#define WINS_LIST "wins.tdb" +#define WINS_LIST "wins.dat" #define WINS_VERSION 1 /**************************************************************************** @@ -221,123 +221,177 @@ Load or create the WINS database. BOOL initialise_wins(void) { - time_t time_now = time(NULL); - TDB_CONTEXT *tdb; - TDB_DATA kbuf, dbuf, newkey; - struct name_record *namerec = NULL; - struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0"); + time_t time_now = time(NULL); + XFILE *fp; + pstring line; - DEBUG(2,("initialise_wins: started\n")); + if(!lp_we_are_a_wins_server()) + return True; - if(!lp_we_are_a_wins_server()) - return True; + add_samba_names_to_subnet(wins_server_subnet); - add_samba_names_to_subnet(wins_server_subnet); + if((fp = x_fopen(lock_path(WINS_LIST),O_RDONLY,0)) == NULL) + { + DEBUG(2,("initialise_wins: Can't open wins database file %s. Error was %s\n", + WINS_LIST, strerror(errno) )); + return True; + } - tdb = tdb_open_log(lock_path(WINS_LIST), 0, TDB_DEFAULT, O_RDONLY, 0600); - if (!tdb) { - DEBUG(2,("initialise_wins: Can't open wins database file %s. Error was %s\n", WINS_LIST, strerror(errno) )); - return True; - } + while (!x_feof(fp)) + { + pstring name_str, ip_str, ttl_str, nb_flags_str; + unsigned int num_ips; + pstring name; + struct in_addr *ip_list; + int type = 0; + int nb_flags; + int ttl; + const char *ptr; + char *p; + BOOL got_token; + BOOL was_ip; + int i; + unsigned hash; + int version; + + /* Read a line from the wins.dat file. Strips whitespace + from the beginning and end of the line. + */ + if (!fgets_slash(line,sizeof(pstring),fp)) + continue; + + if (*line == '#') + continue; + + if (strncmp(line,"VERSION ", 8) == 0) { + if (sscanf(line,"VERSION %d %u", &version, &hash) != 2 || + version != WINS_VERSION) { + DEBUG(0,("Discarding invalid wins.dat file [%s]\n",line)); + x_fclose(fp); + return True; + } + continue; + } - if (tdb_fetch_int32(tdb, INFO_VERSION) != WINS_VERSION) { - DEBUG(0,("Discarding invalid wins.tdb file\n")); - tdb_close(tdb); - return True; - } + ptr = line; - for (kbuf = tdb_firstkey(tdb); - kbuf.dptr; - newkey = tdb_nextkey(tdb, kbuf), safe_free(kbuf.dptr), kbuf=newkey) { - - fstring name_type; - pstring name, ip_str; - char *p; - int type = 0; - int nb_flags; - int ttl; - unsigned int num_ips; - int high, low; - struct in_addr wins_ip; - struct in_addr *ip_list; - int wins_flags; - int len,i; - - if (strncmp(kbuf.dptr, ENTRY_PREFIX, strlen(ENTRY_PREFIX)) != 0) - continue; - - dbuf = tdb_fetch(tdb, kbuf); - if (!dbuf.dptr) - continue; + /* + * Now we handle multiple IP addresses per name we need + * to iterate over the line twice. The first time to + * determine how many IP addresses there are, the second + * time to actually parse them into the ip_list array. + */ - fstrcpy(name_type, kbuf.dptr+strlen(ENTRY_PREFIX)); + if (!next_token(&ptr,name_str,NULL,sizeof(name_str))) + { + DEBUG(0,("initialise_wins: Failed to parse name when parsing line %s\n", line )); + continue; + } - pstrcpy(name, name_type); + if (!next_token(&ptr,ttl_str,NULL,sizeof(ttl_str))) + { + DEBUG(0,("initialise_wins: Failed to parse time to live when parsing line %s\n", line )); + continue; + } - if((p = strchr(name,'#')) != NULL) { - *p = 0; - sscanf(p+1,"%x",&type); - } + /* + * Determine the number of IP addresses per line. + */ + num_ips = 0; + do + { + got_token = next_token(&ptr,ip_str,NULL,sizeof(ip_str)); + was_ip = False; - len = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddfddd", - &nb_flags, &high, &low, - ip_str, &ttl, &num_ips, &wins_flags); + if(got_token && strchr(ip_str, '.')) + { + num_ips++; + was_ip = True; + } + } while( got_token && was_ip); - wins_ip=*interpret_addr2(ip_str); + if(num_ips == 0) + { + DEBUG(0,("initialise_wins: Missing IP address when parsing line %s\n", line )); + continue; + } - /* Don't reload replica records */ - if (!ip_equal(wins_ip, our_fake_ip)) { - SAFE_FREE(dbuf.dptr); - continue; - } + if(!got_token) + { + DEBUG(0,("initialise_wins: Missing nb_flags when parsing line %s\n", line )); + continue; + } - /* Don't reload released or tombstoned records */ - if ((wins_flags&WINS_STATE_MASK) != WINS_ACTIVE) { - SAFE_FREE(dbuf.dptr); - continue; - } + /* Allocate the space for the ip_list. */ + if((ip_list = (struct in_addr *)malloc( num_ips * sizeof(struct in_addr))) == NULL) + { + DEBUG(0,("initialise_wins: Malloc fail !\n")); + return False; + } + + /* Reset and re-parse the line. */ + ptr = line; + next_token(&ptr,name_str,NULL,sizeof(name_str)); + next_token(&ptr,ttl_str,NULL,sizeof(ttl_str)); + for(i = 0; i < num_ips; i++) + { + next_token(&ptr, ip_str, NULL, sizeof(ip_str)); + ip_list[i] = *interpret_addr2(ip_str); + } + next_token(&ptr,nb_flags_str,NULL, sizeof(nb_flags_str)); - /* Allocate the space for the ip_list. */ - if((ip_list = (struct in_addr *)malloc( num_ips * sizeof(struct in_addr))) == NULL) { - SAFE_FREE(dbuf.dptr); - DEBUG(0,("initialise_wins: Malloc fail !\n")); - return False; - } + /* + * Deal with SELF or REGISTER name encoding. Default is REGISTER + * for compatibility with old nmbds. + */ - for (i = 0; i < num_ips; i++) { - len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f", ip_str); - ip_list[i] = *interpret_addr2(ip_str); - } + if(nb_flags_str[strlen(nb_flags_str)-1] == 'S') + { + DEBUG(5,("initialise_wins: Ignoring SELF name %s\n", line)); + SAFE_FREE(ip_list); + continue; + } + + if(nb_flags_str[strlen(nb_flags_str)-1] == 'R') + nb_flags_str[strlen(nb_flags_str)-1] = '\0'; + + /* Netbios name. # divides the name from the type (hex): netbios#xx */ + pstrcpy(name,name_str); + + if((p = strchr(name,'#')) != NULL) + { + *p = 0; + sscanf(p+1,"%x",&type); + } + + /* Decode the netbios flags (hex) and the time-to-live (in seconds). */ + sscanf(nb_flags_str,"%x",&nb_flags); + sscanf(ttl_str,"%d",&ttl); - /* add all entries that have 60 seconds or more to live */ - if ((ttl - 60) > time_now || ttl == PERMANENT_TTL) { - if(ttl != PERMANENT_TTL) - ttl -= time_now; + /* add all entries that have 60 seconds or more to live */ + if ((ttl - 60) > time_now || ttl == PERMANENT_TTL) + { + if(ttl != PERMANENT_TTL) + ttl -= time_now; - DEBUG( 4, ("initialise_wins: add name: %s#%02x ttl = %d first IP %s flags = %2x\n", - name, type, ttl, inet_ntoa(ip_list[0]), nb_flags)); - - namerec=add_name_to_subnet( wins_server_subnet, name, type, nb_flags, - ttl, REGISTER_NAME, num_ips, ip_list); - if (namerec!=NULL) { - update_wins_owner(namerec, wins_ip); - update_wins_flag(namerec, wins_flags); - /* we don't reload the ID, on startup we restart at 1 */ - get_global_id_and_update(&namerec->data.id, True); - } + DEBUG( 4, ("initialise_wins: add name: %s#%02x ttl = %d first IP %s flags = %2x\n", + name, type, ttl, inet_ntoa(ip_list[0]), nb_flags)); - } else { - DEBUG(4, ("initialise_wins: not adding name (ttl problem) %s#%02x ttl = %d first IP %s flags = %2x\n", - name, type, ttl, inet_ntoa(ip_list[0]), nb_flags)); - } + (void)add_name_to_subnet( wins_server_subnet, name, type, nb_flags, + ttl, REGISTER_NAME, num_ips, ip_list ); - SAFE_FREE(dbuf.dptr); - SAFE_FREE(ip_list); - } + } + else + { + DEBUG(4, ("initialise_wins: not adding name (ttl problem) %s#%02x ttl = %d first IP %s flags = %2x\n", + name, type, ttl, inet_ntoa(ip_list[0]), nb_flags)); + } + + SAFE_FREE(ip_list); + } - tdb_close(tdb); - DEBUG(2,("initialise_wins: done\n")); - return True; + x_fclose(fp); + return True; } /**************************************************************************** @@ -1765,113 +1819,87 @@ we are not the wins owner !\n", nmb_namestr(&namerec->name))); ******************************************************************/ void wins_write_database(BOOL background) { - struct name_record *namerec; - pstring fname, fnamenew; - TDB_CONTEXT *tdb; - TDB_DATA kbuf, dbuf; - pstring key, buf; - int len; - int num_record=0; - SMB_BIG_UINT id; - - if(!lp_we_are_a_wins_server()) - return; - - /* we will do the writing in a child process to ensure that the parent - doesn't block while this is done */ - if (background) { - CatchChild(); - if (sys_fork()) { - return; - } - } - - slprintf(fname,sizeof(fname)-1,"%s/%s", lp_lockdir(), WINS_LIST); - all_string_sub(fname,"//", "/", 0); - slprintf(fnamenew,sizeof(fnamenew)-1,"%s.%u", fname, (unsigned int)sys_getpid()); - - tdb = tdb_open_log(fnamenew, 0, TDB_DEFAULT, O_RDWR|O_CREAT|O_TRUNC, 0644); - if (!tdb) { - DEBUG(0,("wins_write_database: Can't open %s. Error was %s\n", fnamenew, strerror(errno))); - if (background) - _exit(0); - return; - } - - DEBUG(3,("wins_write_database: Dump of WINS name list.\n")); - - tdb_store_int32(tdb, INFO_VERSION, WINS_VERSION); - - for (namerec = (struct name_record *)ubi_trFirst( wins_server_subnet->namelist ); - namerec; - namerec = (struct name_record *)ubi_trNext( namerec ) ) { - - int i; - struct tm *tm; - - DEBUGADD(3,("%-19s ", nmb_namestr(&namerec->name) )); + struct name_record *namerec; + pstring fname, fnamenew; - if( namerec->data.death_time != PERMANENT_TTL ) { - char *ts, *nl; - - tm = LocalTime(&namerec->data.death_time); - ts = asctime(tm); - nl = strrchr_m( ts, '\n' ); - if( NULL != nl ) - *nl = '\0'; + XFILE *fp; + + if(!lp_we_are_a_wins_server()) + return; - DEBUGADD(3,("TTL = %s ", ts )); - } else - DEBUGADD(3,("TTL = PERMANENT ")); + /* we will do the writing in a child process to ensure that the parent + doesn't block while this is done */ + if (background) { + CatchChild(); + if (sys_fork()) { + return; + } + } - for (i = 0; i < namerec->data.num_ips; i++) - DEBUGADD(0,("%15s ", inet_ntoa(namerec->data.ip[i]) )); + slprintf(fname,sizeof(fname)-1,"%s/%s", lp_lockdir(), WINS_LIST); + all_string_sub(fname,"//", "/", 0); + slprintf(fnamenew,sizeof(fnamenew)-1,"%s.%u", fname, (unsigned int)sys_getpid()); - DEBUGADD(3,("0x%2x 0x%2x %15s\n", namerec->data.nb_flags, namerec->data.wins_flags, inet_ntoa(namerec->data.wins_ip))); + if((fp = x_fopen(fnamenew,O_WRONLY|O_CREAT,0644)) == NULL) + { + DEBUG(0,("wins_write_database: Can't open %s. Error was %s\n", fnamenew, strerror(errno))); + if (background) { + _exit(0); + } + return; + } - if( namerec->data.source == REGISTER_NAME ) { - - /* store the type in the key to make the name unique */ - slprintf(key, sizeof(key), "%s%s#%02x", ENTRY_PREFIX, namerec->name.name, namerec->name.name_type); - - len = tdb_pack(buf, sizeof(buf), "dddfddd", - (int)namerec->data.nb_flags, - (int)(namerec->data.id>>32), - (int)(namerec->data.id&0xffffffff), - inet_ntoa(namerec->data.wins_ip), - (int)namerec->data.death_time, - namerec->data.num_ips, - namerec->data.wins_flags); - - for (i = 0; i < namerec->data.num_ips; i++) - len += tdb_pack(buf+len, sizeof(buf)-len, "f", inet_ntoa(namerec->data.ip[i])); - - kbuf.dsize = strlen(key)+1; - kbuf.dptr = key; - dbuf.dsize = len; - dbuf.dptr = buf; - if (tdb_store(tdb, kbuf, dbuf, TDB_INSERT) != 0) return; + DEBUG(4,("wins_write_database: Dump of WINS name list.\n")); - num_record++; - } - } + x_fprintf(fp,"VERSION %d %u\n", WINS_VERSION, 0); + + for( namerec + = (struct name_record *)ubi_trFirst( wins_server_subnet->namelist ); + namerec; + namerec = (struct name_record *)ubi_trNext( namerec ) ) + { + int i; + struct tm *tm; - /* store the number of records */ - tdb_store_int32(tdb, INFO_COUNT, num_record); + DEBUGADD(4,("%-19s ", nmb_namestr(&namerec->name) )); - /* get and store the last used ID */ - get_global_id_and_update(&id, False); - tdb_store_int32(tdb, INFO_ID_HIGH, id>>32); - tdb_store_int32(tdb, INFO_ID_LOW, id&0xffffffff); + if( namerec->data.death_time != PERMANENT_TTL ) + { + char *ts, *nl; + + tm = LocalTime(&namerec->data.death_time); + ts = asctime(tm); + nl = strrchr( ts, '\n' ); + if( NULL != nl ) + *nl = '\0'; + DEBUGADD(4,("TTL = %s ", ts )); + } + else + DEBUGADD(4,("TTL = PERMANENT ")); - tdb_close(tdb); + for (i = 0; i < namerec->data.num_ips; i++) + DEBUGADD(4,("%15s ", inet_ntoa(namerec->data.ip[i]) )); + DEBUGADD(4,("%2x\n", namerec->data.nb_flags )); - chmod(fnamenew,0644); - unlink(fname); - rename(fnamenew,fname); + if( namerec->data.source == REGISTER_NAME ) + { + x_fprintf(fp, "\"%s#%02x\" %d ", + namerec->name.name,namerec->name.name_type, /* Ignore scope. */ + (int)namerec->data.death_time); - if (background) - _exit(0); + for (i = 0; i < namerec->data.num_ips; i++) + x_fprintf( fp, "%s ", inet_ntoa( namerec->data.ip[i] ) ); + x_fprintf( fp, "%2xR\n", namerec->data.nb_flags ); + } + } + + x_fclose(fp); + chmod(fnamenew,0644); + unlink(fname); + rename(fnamenew,fname); + if (background) { + _exit(0); + } } /**************************************************************************** diff --git a/source3/nmbd/nmbd_workgroupdb.c b/source3/nmbd/nmbd_workgroupdb.c index b8ea60dec0..2357fd637b 100644 --- a/source3/nmbd/nmbd_workgroupdb.c +++ b/source3/nmbd/nmbd_workgroupdb.c @@ -57,7 +57,7 @@ static struct work_record *create_workgroup(const char *name, int ttl) } memset((char *)work, '\0', sizeof(*work)); - StrnCpy(work->work_group,name,sizeof(work->work_group)-1); + fstrcpy(work->work_group,name); work->serverlist = NULL; work->RunningElection = False; diff --git a/source3/nsswitch/wb_client.c b/source3/nsswitch/wb_client.c index 996d15180d..7c5a8dd054 100644 --- a/source3/nsswitch/wb_client.c +++ b/source3/nsswitch/wb_client.c @@ -269,11 +269,8 @@ static int wb_getgroups(const char *user, gid_t **groups) time consuming. If size is zero, list is not modified and the total number of groups for the user is returned. */ -int winbind_getgroups(const char *user, int size, gid_t *list) +int winbind_getgroups(const char *user, gid_t **list) { - gid_t *groups = NULL; - int result, i; - /* * Don't do the lookup if the name has no separator _and_ we are not in * 'winbind use default domain' mode. @@ -284,24 +281,316 @@ int winbind_getgroups(const char *user, int size, gid_t *list) /* Fetch list of groups */ - result = wb_getgroups(user, &groups); + return wb_getgroups(user, list); +} + +/********************************************************************** + simple wrapper function to see if winbindd is alive +**********************************************************************/ + +BOOL winbind_ping( void ) +{ + NSS_STATUS result; + + result = winbindd_request(WINBINDD_PING, NULL, NULL); + + return result == NSS_STATUS_SUCCESS; +} + +/********************************************************************** + Ask winbindd to create a local user +**********************************************************************/ + +BOOL winbind_create_user( const char *name, uint32 *rid ) +{ + struct winbindd_request request; + struct winbindd_response response; + NSS_STATUS result; + + if ( !lp_winbind_enable_local_accounts() ) + return False; + + if ( !name ) + return False; + + DEBUG(10,("winbind_create_user: %s\n", name)); + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + /* see if the caller wants a new RID returned */ + + if ( rid ) + request.flags = WBFLAG_ALLOCATE_RID; + + fstrcpy( request.data.acct_mgt.username, name ); + fstrcpy( request.data.acct_mgt.groupname, "" ); + + result = winbindd_request( WINBINDD_CREATE_USER, &request, &response); + + if ( rid ) + *rid = response.data.rid; + + return result == NSS_STATUS_SUCCESS; +} + +/********************************************************************** + Ask winbindd to create a local group +**********************************************************************/ + +BOOL winbind_create_group( const char *name, uint32 *rid ) +{ + struct winbindd_request request; + struct winbindd_response response; + NSS_STATUS result; + + if ( !lp_winbind_enable_local_accounts() ) + return False; + + if ( !name ) + return False; + + DEBUG(10,("winbind_create_group: %s\n", name)); + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + /* see if the caller wants a new RID returned */ + + if ( rid ) + request.flags = WBFLAG_ALLOCATE_RID; + + fstrcpy( request.data.acct_mgt.groupname, name ); + + + result = winbindd_request( WINBINDD_CREATE_GROUP, &request, &response); + + if ( rid ) + *rid = response.data.rid; + + return result == NSS_STATUS_SUCCESS; +} + +/********************************************************************** + Ask winbindd to add a user to a local group +**********************************************************************/ + +BOOL winbind_add_user_to_group( const char *user, const char *group ) +{ + struct winbindd_request request; + struct winbindd_response response; + NSS_STATUS result; + + if ( !lp_winbind_enable_local_accounts() ) + return False; + + if ( !user || !group ) + return False; + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + DEBUG(10,("winbind_add_user_to_group: user(%s), group(%s) \n", + user, group)); + + fstrcpy( request.data.acct_mgt.username, user ); + fstrcpy( request.data.acct_mgt.groupname, group ); + + result = winbindd_request( WINBINDD_ADD_USER_TO_GROUP, &request, &response); + + return result == NSS_STATUS_SUCCESS; +} + +/********************************************************************** + Ask winbindd to remove a user to a local group +**********************************************************************/ + +BOOL winbind_remove_user_from_group( const char *user, const char *group ) +{ + struct winbindd_request request; + struct winbindd_response response; + NSS_STATUS result; + + if ( !lp_winbind_enable_local_accounts() ) + return False; + + if ( !user || !group ) + return False; + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + DEBUG(10,("winbind_remove_user_from_group: user(%s), group(%s) \n", + user, group)); + + ZERO_STRUCT(response); + + result = winbindd_request( WINBINDD_REMOVE_USER_FROM_GROUP, &request, &response); + + return result == NSS_STATUS_SUCCESS; +} + +/********************************************************************** + Ask winbindd to set the primary group for a user local user +**********************************************************************/ + +BOOL winbind_set_user_primary_group( const char *user, const char *group ) +{ + struct winbindd_request request; + struct winbindd_response response; + NSS_STATUS result; + + if ( !lp_winbind_enable_local_accounts() ) + return False; + + if ( !user || !group ) + return False; + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + DEBUG(10,("winbind_set_user_primary_group: user(%s), group(%s) \n", + user, group)); + + fstrcpy( request.data.acct_mgt.username, user ); + fstrcpy( request.data.acct_mgt.groupname, group ); + + result = winbindd_request( WINBINDD_SET_USER_PRIMARY_GROUP, &request, &response); + + return result == NSS_STATUS_SUCCESS; +} + + +/********************************************************************** + Ask winbindd to remove a user from its lists of accounts +**********************************************************************/ + +BOOL winbind_delete_user( const char *user ) +{ + struct winbindd_request request; + struct winbindd_response response; + NSS_STATUS result; + + if ( !lp_winbind_enable_local_accounts() ) + return False; + + if ( !user ) + return False; + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + DEBUG(10,("winbind_delete_user: user (%s)\n", user)); + + fstrcpy( request.data.acct_mgt.username, user ); + + result = winbindd_request( WINBINDD_DELETE_USER, &request, &response); + + return result == NSS_STATUS_SUCCESS; +} + +/********************************************************************** + Ask winbindd to remove a group from its lists of accounts +**********************************************************************/ + +BOOL winbind_delete_group( const char *group ) +{ + struct winbindd_request request; + struct winbindd_response response; + NSS_STATUS result; + + if ( !lp_winbind_enable_local_accounts() ) + return False; + + if ( !group ) + return False; + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + DEBUG(10,("winbind_delete_group: group (%s)\n", group)); + + fstrcpy( request.data.acct_mgt.groupname, group ); + + result = winbindd_request( WINBINDD_DELETE_GROUP, &request, &response); + + return result == NSS_STATUS_SUCCESS; +} + +/***********************************************************************/ +#if 0 /* not needed currently since winbindd_acct was added -- jerry */ + +/* Call winbindd to convert SID to uid. Do not allocate */ + +BOOL winbind_sid_to_uid_query(uid_t *puid, const DOM_SID *sid) +{ + struct winbindd_request request; + struct winbindd_response response; + int result; + fstring sid_str; + + if (!puid) + return False; + + /* Initialise request */ + + ZERO_STRUCT(request); + ZERO_STRUCT(response); - if (size == 0) - goto done; + sid_to_string(sid_str, sid); + fstrcpy(request.data.sid, sid_str); + + request.flags = WBFLAG_QUERY_ONLY; + + /* Make request */ - if (result > size) { - result = -1; - errno = EINVAL; /* This is what getgroups() does */ - goto done; + result = winbindd_request(WINBINDD_SID_TO_UID, &request, &response); + + /* Copy out result */ + + if (result == NSS_STATUS_SUCCESS) { + *puid = response.data.uid; } - /* Copy list of groups across */ + return (result == NSS_STATUS_SUCCESS); +} + +/* Call winbindd to convert SID to gid. Do not allocate */ - for (i = 0; i < result; i++) { - list[i] = groups[i]; +BOOL winbind_sid_to_gid_query(gid_t *pgid, const DOM_SID *sid) +{ + struct winbindd_request request; + struct winbindd_response response; + int result; + fstring sid_str; + + if (!pgid) + return False; + + /* Initialise request */ + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + sid_to_string(sid_str, sid); + fstrcpy(request.data.sid, sid_str); + + request.flags = WBFLAG_QUERY_ONLY; + + /* Make request */ + + result = winbindd_request(WINBINDD_SID_TO_GID, &request, &response); + + /* Copy out result */ + + if (result == NSS_STATUS_SUCCESS) { + *pgid = response.data.gid; } - done: - SAFE_FREE(groups); - return result; + return (result == NSS_STATUS_SUCCESS); } + +#endif /* JERRY */ + +/***********************************************************************/ + diff --git a/source3/nsswitch/wb_common.c b/source3/nsswitch/wb_common.c index ac1ccb217e..acaf0ed17c 100644 --- a/source3/nsswitch/wb_common.c +++ b/source3/nsswitch/wb_common.c @@ -395,11 +395,15 @@ int read_reply(struct winbindd_response *response) NSS_STATUS winbindd_send_request(int req_type, struct winbindd_request *request) { struct winbindd_request lrequest; - + char *env; + int value; + /* Check for our tricky environment variable */ - if (getenv(WINBINDD_DONT_ENV)) { - return NSS_STATUS_NOTFOUND; + if ( (env = getenv(WINBINDD_DONT_ENV)) != NULL ) { + value = atoi(env); + if ( value == 1 ) + return NSS_STATUS_NOTFOUND; } if (!request) { @@ -464,3 +468,19 @@ NSS_STATUS winbindd_request(int req_type, return(status); return winbindd_get_response(response); } + +/************************************************************************* + A couple of simple jfunctions to disable winbindd lookups and re- + enable them + ************************************************************************/ + +BOOL winbind_off( void ) +{ + return (setenv( WINBINDD_DONT_ENV, "1", 1 ) != -1); +} + +BOOL winbind_on( void ) +{ + return (setenv( WINBINDD_DONT_ENV, "0", 1 ) != -1); +} + diff --git a/source3/nsswitch/wbinfo.c b/source3/nsswitch/wbinfo.c index 61c54b3738..f533799370 100644 --- a/source3/nsswitch/wbinfo.c +++ b/source3/nsswitch/wbinfo.c @@ -103,7 +103,7 @@ static BOOL parse_wbinfo_domain_user(const char *domuser, fstring domain, fstrcpy(user, p+1); fstrcpy(domain, domuser); domain[PTR_DIFF(p, domuser)] = 0; - strupper(domain); + strupper_m(domain); return True; } @@ -511,6 +511,175 @@ static BOOL wbinfo_auth_crap(char *username) return result == NSS_STATUS_SUCCESS; } +/****************************************************************** + create a winbindd user +******************************************************************/ + +static BOOL wbinfo_create_user(char *username) +{ + struct winbindd_request request; + struct winbindd_response response; + NSS_STATUS result; + + /* Send off request */ + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + request.flags = WBFLAG_ALLOCATE_RID; + fstrcpy(request.data.acct_mgt.username, username); + + result = winbindd_request(WINBINDD_CREATE_USER, &request, &response); + + if ( result == NSS_STATUS_SUCCESS ) + d_printf("New RID is %d\n", response.data.rid); + + return result == NSS_STATUS_SUCCESS; +} + +/****************************************************************** + remove a winbindd user +******************************************************************/ + +static BOOL wbinfo_delete_user(char *username) +{ + struct winbindd_request request; + struct winbindd_response response; + NSS_STATUS result; + + /* Send off request */ + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + fstrcpy(request.data.acct_mgt.username, username); + + result = winbindd_request(WINBINDD_DELETE_USER, &request, &response); + + return result == NSS_STATUS_SUCCESS; +} + +/****************************************************************** + create a winbindd group +******************************************************************/ + +static BOOL wbinfo_create_group(char *groupname) +{ + struct winbindd_request request; + struct winbindd_response response; + NSS_STATUS result; + + /* Send off request */ + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + fstrcpy(request.data.acct_mgt.groupname, groupname); + + result = winbindd_request(WINBINDD_CREATE_GROUP, &request, &response); + + return result == NSS_STATUS_SUCCESS; +} + +/****************************************************************** + remove a winbindd group +******************************************************************/ + +static BOOL wbinfo_delete_group(char *groupname) +{ + struct winbindd_request request; + struct winbindd_response response; + NSS_STATUS result; + + /* Send off request */ + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + fstrcpy(request.data.acct_mgt.groupname, groupname); + + result = winbindd_request(WINBINDD_DELETE_GROUP, &request, &response); + + return result == NSS_STATUS_SUCCESS; +} + +/****************************************************************** + parse a string in the form user:group +******************************************************************/ + +static BOOL parse_user_group( const char *string, fstring user, fstring group ) +{ + char *p; + + if ( !string ) + return False; + + if ( !(p = strchr( string, ':' )) ) + return False; + + *p = '\0'; + p++; + + fstrcpy( user, string ); + fstrcpy( group, p ); + + return True; +} + +/****************************************************************** + add a user to a winbindd group +******************************************************************/ + +static BOOL wbinfo_add_user_to_group(char *string) +{ + struct winbindd_request request; + struct winbindd_response response; + NSS_STATUS result; + + /* Send off request */ + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + if ( !parse_user_group( string, request.data.acct_mgt.username, + request.data.acct_mgt.groupname)) + { + d_printf("Can't parse user:group from %s\n", string); + return False; + } + + result = winbindd_request(WINBINDD_ADD_USER_TO_GROUP, &request, &response); + + return result == NSS_STATUS_SUCCESS; +} + +/****************************************************************** + remove a user from a winbindd group +******************************************************************/ + +static BOOL wbinfo_remove_user_from_group(char *string) +{ + struct winbindd_request request; + struct winbindd_response response; + NSS_STATUS result; + + /* Send off request */ + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + if ( !parse_user_group( string, request.data.acct_mgt.username, + request.data.acct_mgt.groupname)) + { + d_printf("Can't parse user:group from %s\n", string); + return False; + } + + result = winbindd_request(WINBINDD_REMOVE_USER_FROM_GROUP, &request, &response); + + return result == NSS_STATUS_SUCCESS; +} + /* Print domain users */ static BOOL print_domain_users(void) @@ -705,12 +874,18 @@ int main(int argc, char **argv) { "gid-to-sid", 'G', POPT_ARG_INT, &int_arg, 'G', "Converts gid to sid", "GID" }, { "sid-to-uid", 'S', POPT_ARG_STRING, &string_arg, 'S', "Converts sid to uid", "SID" }, { "sid-to-gid", 'Y', POPT_ARG_STRING, &string_arg, 'Y', "Converts sid to gid", "SID" }, + { "create-user", 'c', POPT_ARG_STRING, &string_arg, 'c', "Create a local user account", "name" }, + { "delete-user", 'x', POPT_ARG_STRING, &string_arg, 'x', "Delete a local user account", "name" }, + { "create-group", 'C', POPT_ARG_STRING, &string_arg, 'C', "Create a local group", "name" }, + { "delete-group", 'X', POPT_ARG_STRING, &string_arg, 'X', "Delete a local group", "name" }, + { "add-to-group", 'o', POPT_ARG_STRING, &string_arg, 'o', "Add user to group", "user:group" }, + { "del-from-group", 'O', POPT_ARG_STRING, &string_arg, 'O', "Remove user from group", "user:group" }, { "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", "USER" }, { "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" }, + { "set-auth-user", 0, POPT_ARG_STRING, &string_arg, OPT_SET_AUTH_USER, "Store user and password used by winbindd (root only)", "user%password" }, { "get-auth-user", 0, POPT_ARG_NONE, NULL, OPT_GET_AUTH_USER, "Retrieve user and password used by winbindd (root only)", NULL }, { "ping", 'p', POPT_ARG_NONE, 0, 'p', "Ping winbindd to see if it is alive" }, POPT_COMMON_VERSION @@ -845,31 +1020,66 @@ int main(int argc, char **argv) } break; case 'a': { - BOOL got_error = False; - - if (!wbinfo_auth(string_arg)) { - d_printf("Could not authenticate user %s with " - "plaintext password\n", string_arg); - got_error = True; - } - - if (!wbinfo_auth_crap(string_arg)) { - d_printf("Could not authenticate user %s with " - "challenge/response\n", string_arg); - got_error = True; - } - - if (got_error) - goto done; - break; - } - case 'p': { - if (!wbinfo_ping()) { - d_printf("could not ping winbindd!\n"); - goto done; - } - break; - } + BOOL got_error = False; + + if (!wbinfo_auth(string_arg)) { + d_printf("Could not authenticate user %s with " + "plaintext password\n", string_arg); + got_error = True; + } + + if (!wbinfo_auth_crap(string_arg)) { + d_printf("Could not authenticate user %s with " + "challenge/response\n", string_arg); + got_error = True; + } + + if (got_error) + goto done; + break; + } + case 'c': + if ( !wbinfo_create_user(string_arg) ) { + d_printf("Could not create user account\n"); + goto done; + } + break; + case 'C': + if ( !wbinfo_create_group(string_arg) ) { + d_printf("Could not create group\n"); + goto done; + } + break; + case 'o': + if ( !wbinfo_add_user_to_group(string_arg) ) { + d_printf("Could not add user to group\n"); + goto done; + } + break; + case 'O': + if ( !wbinfo_remove_user_from_group(string_arg) ) { + d_printf("Could not remove user kfrom group\n"); + goto done; + } + break; + case 'x': + if ( !wbinfo_delete_user(string_arg) ) { + d_printf("Could not delete user account\n"); + goto done; + } + break; + case 'X': + if ( !wbinfo_delete_group(string_arg) ) { + d_printf("Could not delete group\n"); + goto done; + } + break; + case 'P': + if (!wbinfo_ping()) { + d_printf("could not ping winbindd!\n"); + goto done; + } + break; case OPT_SET_AUTH_USER: wbinfo_set_auth_user(string_arg); break; diff --git a/source3/nsswitch/winbindd.c b/source3/nsswitch/winbindd.c index c7e45e5429..0860d701d8 100644 --- a/source3/nsswitch/winbindd.c +++ b/source3/nsswitch/winbindd.c @@ -25,7 +25,21 @@ #include "winbindd.h" BOOL opt_nocache = False; -BOOL opt_dual_daemon = False; +BOOL opt_dual_daemon = True; + +/***************************************************************************** + stubb functions +****************************************************************************/ + +void become_root( void ) +{ + return; +} + +void unbecome_root( void ) +{ + return; +} /* Reload configuration */ @@ -52,6 +66,7 @@ static BOOL reload_services_file(BOOL test) return(ret); } + #if DUMP_CORE /**************************************************************************** ** @@ -135,8 +150,17 @@ static void print_winbindd_status(void) static void flush_caches(void) { +#if 0 /* Clear cached user and group enumation info */ - wcache_flush_cache(); + if (!opt_dual_daemon) /* Until we have coherent cache flush. */ + wcache_flush_cache(); +#endif + + /* We need to invalidate cached user list entries on a SIGHUP + otherwise cached access denied errors due to restrict anonymous + hang around until the sequence number changes. */ + + wcache_invalidate_cache(); } /* Handle the signal by unlinking socket and exiting */ @@ -178,6 +202,20 @@ static void sighup_handler(int signum) sys_select_signal(); } +/* React on 'smbcontrol winbindd reload-config' in the same way as on SIGHUP*/ +static void msg_reload_services(int msg_type, pid_t src, void *buf, size_t len) +{ + /* Flush various caches */ + flush_caches(); + reload_services_file(True); +} + +/* React on 'smbcontrol winbindd shutdown' in the same way as on SIGTERM*/ +static void msg_shutdown(int msg_type, pid_t src, void *buf, size_t len) +{ + terminate(); +} + struct dispatch_table { enum winbindd_cmd cmd; enum winbindd_result (*fn)(struct winbindd_cli_state *state); @@ -245,7 +283,16 @@ static struct dispatch_table dispatch_table[] = { { WINBINDD_WINS_BYNAME, winbindd_wins_byname, "WINS_BYNAME" }, { WINBINDD_WINS_BYIP, winbindd_wins_byip, "WINS_BYIP" }, - + + /* UNIX account management functions */ + { WINBINDD_CREATE_USER, winbindd_create_user, "CREATE_USER" }, + { WINBINDD_CREATE_GROUP, winbindd_create_group, "CREATE_GROUP" }, + { WINBINDD_ADD_USER_TO_GROUP, winbindd_add_user_to_group, "ADD_USER_TO_GROUP" }, + { WINBINDD_REMOVE_USER_FROM_GROUP, winbindd_remove_user_from_group,"REMOVE_USER_FROM_GROUP"}, + { WINBINDD_SET_USER_PRIMARY_GROUP, winbindd_set_user_primary_group,"SET_USER_PRIMARY_GROUP"}, + { WINBINDD_DELETE_USER, winbindd_delete_user, "DELETE_USER" }, + { WINBINDD_DELETE_GROUP, winbindd_delete_group, "DELETE_GROUP" }, + /* End of list */ { WINBINDD_NUM_CMDS, NULL, "NONE" } @@ -714,11 +761,8 @@ static void process_loop(void) if (do_sighup) { DEBUG(3, ("got SIGHUP\n")); - - /* Flush various caches */ - flush_caches(); - reload_services_file(True); + msg_reload_services(MSG_SMB_CONF_UPDATED, (pid_t) 0, NULL, 0); do_sighup = False; } @@ -744,7 +788,7 @@ int main(int argc, char **argv) { "stdout", 'S', POPT_ARG_VAL, &log_stdout, True, "Log to stdout" }, { "foreground", 'F', POPT_ARG_VAL, &Fork, False, "Daemon in foreground mode" }, { "interactive", 'i', POPT_ARG_NONE, NULL, 'i', "Interactive mode" }, - { "dual-daemon", 'B', POPT_ARG_VAL, &opt_dual_daemon, True, "Dual daemon mode" }, + { "single-daemon", 'Y', POPT_ARG_VAL, &opt_dual_daemon, False, "Single daemon mode" }, { "no-caching", 'n', POPT_ARG_VAL, &opt_nocache, False, "Disable caching" }, POPT_COMMON_SAMBA POPT_TABLEEND @@ -833,11 +877,11 @@ int main(int argc, char **argv) /* Winbind daemon initialisation */ - if (!idmap_init()) + if (!winbindd_upgrade_idmap()) return 1; - if (!idmap_init_wellknown_sids()) - exit(1); + if (!idmap_init(lp_idmap_backend())) + return 1; /* Unblock all signals we are interested in as they may have been blocked by the parent process. */ @@ -884,14 +928,21 @@ int main(int argc, char **argv) DEBUG(0, ("unable to initialise messaging system\n")); exit(1); } + + /* React on 'smbcontrol winbindd reload-config' in the same way + as to SIGHUP signal */ + message_register(MSG_SMB_CONF_UPDATED, msg_reload_services); + message_register(MSG_SHUTDOWN, msg_shutdown); + poptFreeContext(pc); + netsamlogon_cache_init(); /* Non-critical */ + /* Loop waiting for requests */ process_loop(); trustdom_cache_shutdown(); - uni_group_cache_shutdown(); return 0; } diff --git a/source3/nsswitch/winbindd.h b/source3/nsswitch/winbindd.h index 2d9a0b5949..2acb89b24b 100644 --- a/source3/nsswitch/winbindd.h +++ b/source3/nsswitch/winbindd.h @@ -98,9 +98,12 @@ struct winbindd_domain { BOOL native_mode; /* is this a win2k domain in native mode ? */ /* Lookup methods for this domain (LDAP or RPC) */ - struct winbindd_methods *methods; + /* the backend methods are used by the cache layer to find the right + backend */ + struct winbindd_methods *backend; + /* Private data for the backends (used for connection cache) */ void *private; @@ -109,6 +112,7 @@ struct winbindd_domain { time_t last_seq_check; uint32 sequence_number; + NTSTATUS last_status; /* Linked list info */ @@ -219,7 +223,7 @@ struct winbindd_idmap_methods { void (*status)(void); }; -#include "winbindd_proto.h" +#include "../nsswitch/winbindd_proto.h" #include "rpc_parse.h" #include "rpc_client.h" diff --git a/source3/nsswitch/winbindd_ads.c b/source3/nsswitch/winbindd_ads.c index beb40af79d..462dd21531 100644 --- a/source3/nsswitch/winbindd_ads.c +++ b/source3/nsswitch/winbindd_ads.c @@ -65,7 +65,7 @@ static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain) status = ads_connect(ads); if (!ADS_ERR_OK(status) || !ads->config.realm) { - extern struct winbindd_methods msrpc_methods; + extern struct winbindd_methods msrpc_methods, cache_methods; DEBUG(1,("ads_connect for domain %s failed: %s\n", domain->name, ads_errstr(status))); ads_destroy(&ads); @@ -75,7 +75,11 @@ static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain) if (status.error_type == ADS_ERROR_SYSTEM && status.err.rc == ECONNREFUSED) { DEBUG(1,("Trying MSRPC methods\n")); - domain->methods = &msrpc_methods; + if (domain->methods == &cache_methods) { + domain->backend = &msrpc_methods; + } else { + domain->methods = &msrpc_methods; + } } return NULL; } @@ -112,7 +116,11 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain, DEBUG(3,("ads: query_user_list\n")); ads = ads_cached_connection(domain); - if (!ads) goto done; + + if (!ads) { + domain->last_status = NT_STATUS_SERVER_DISABLED; + goto done; + } rc = ads_search_retry(ads, &res, "(objectCategory=user)", attrs); if (!ADS_ERR_OK(rc)) { @@ -209,7 +217,11 @@ static NTSTATUS enum_dom_groups(struct winbindd_domain *domain, DEBUG(3,("ads: enum_dom_groups\n")); ads = ads_cached_connection(domain); - if (!ads) goto done; + + if (!ads) { + domain->last_status = NT_STATUS_SERVER_DISABLED; + goto done; + } rc = ads_search_retry(ads, &res, "(objectCategory=group)", attrs); if (!ADS_ERR_OK(rc)) { @@ -232,7 +244,9 @@ static NTSTATUS enum_dom_groups(struct winbindd_domain *domain, i = 0; group_flags = ATYPE_GLOBAL_GROUP; - if ( domain->native_mode ) + + /* only grab domain local groups for our domain */ + if ( domain->native_mode && strequal(lp_realm(), domain->alt_name) ) group_flags |= ATYPE_LOCAL_GROUP; for (msg = ads_first_entry(ads, res); msg; msg = ads_next_entry(ads, msg)) { @@ -282,7 +296,7 @@ static NTSTATUS enum_local_groups(struct winbindd_domain *domain, { /* * This is a stub function only as we returned the domain - * ocal groups in enum_dom_groups() if the domain->native field + * local groups in enum_dom_groups() if the domain->native field * was true. This is a simple performance optimization when * using LDAP. * @@ -307,8 +321,11 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain, DEBUG(3,("ads: name_to_sid\n")); ads = ads_cached_connection(domain); - if (!ads) + + if (!ads) { + domain->last_status = NT_STATUS_SERVER_DISABLED; return NT_STATUS_UNSUCCESSFUL; + } return ads_name_to_sid(ads, name, sid, type); } @@ -322,9 +339,13 @@ static NTSTATUS sid_to_name(struct winbindd_domain *domain, { ADS_STRUCT *ads = NULL; DEBUG(3,("ads: sid_to_name\n")); + ads = ads_cached_connection(domain); - if (!ads) + + if (!ads) { + domain->last_status = NT_STATUS_SERVER_DISABLED; return NT_STATUS_UNSUCCESSFUL; + } return ads_sid_to_name(ads, mem_ctx, sid, name, type); } @@ -338,7 +359,7 @@ static BOOL dn_lookup(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, const char *dn, char **name, uint32 *name_type, DOM_SID *sid) { - char *exp; + char *ldap_exp; void *res = NULL; const char *attrs[] = {"userPrincipalName", "sAMAccountName", "objectSid", "sAMAccountType", NULL}; @@ -346,13 +367,15 @@ static BOOL dn_lookup(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, uint32 atype; char *escaped_dn = escape_ldap_string_alloc(dn); + DEBUG(3,("ads: dn_lookup\n")); + if (!escaped_dn) { return False; } - asprintf(&exp, "(distinguishedName=%s)", dn); - rc = ads_search_retry(ads, &res, exp, attrs); - SAFE_FREE(exp); + asprintf(&ldap_exp, "(distinguishedName=%s)", dn); + rc = ads_search_retry(ads, &res, ldap_exp, attrs); + SAFE_FREE(ldap_exp); SAFE_FREE(escaped_dn); if (!ADS_ERR_OK(rc)) { @@ -392,7 +415,7 @@ static NTSTATUS query_user(struct winbindd_domain *domain, ADS_STATUS rc; int count; void *msg = NULL; - char *exp; + char *ldap_exp; char *sidstr; uint32 group_rid; NTSTATUS status = NT_STATUS_UNSUCCESSFUL; @@ -402,12 +425,16 @@ static NTSTATUS query_user(struct winbindd_domain *domain, DEBUG(3,("ads: query_user\n")); ads = ads_cached_connection(domain); - if (!ads) goto done; + + if (!ads) { + domain->last_status = NT_STATUS_SERVER_DISABLED; + goto done; + } sidstr = sid_binstring(sid); - asprintf(&exp, "(objectSid=%s)", sidstr); - rc = ads_search_retry(ads, &msg, exp, attrs); - free(exp); + asprintf(&ldap_exp, "(objectSid=%s)", sidstr); + rc = ads_search_retry(ads, &msg, ldap_exp, attrs); + free(ldap_exp); free(sidstr); if (!ADS_ERR_OK(rc)) { DEBUG(1,("query_user(sid=%s) ads_search: %s\n", sid_to_string(sid_string, sid), ads_errstr(rc))); @@ -461,22 +488,28 @@ static NTSTATUS lookup_usergroups_alt(struct winbindd_domain *domain, int count; void *res = NULL; void *msg = NULL; - char *exp; + char *ldap_exp; ADS_STRUCT *ads; const char *group_attrs[] = {"objectSid", NULL}; + DEBUG(3,("ads: lookup_usergroups_alt\n")); + ads = ads_cached_connection(domain); - if (!ads) goto done; + + if (!ads) { + domain->last_status = NT_STATUS_SERVER_DISABLED; + goto done; + } /* buggy server, no tokenGroups. Instead lookup what groups this user is a member of by DN search on member*/ - if (asprintf(&exp, "(&(member=%s)(objectClass=group))", user_dn) == -1) { + if (asprintf(&ldap_exp, "(&(member=%s)(objectClass=group))", user_dn) == -1) { DEBUG(1,("lookup_usergroups(dn=%s) asprintf failed!\n", user_dn)); return NT_STATUS_NO_MEMORY; } - rc = ads_search_retry(ads, &res, exp, group_attrs); - free(exp); + rc = ads_search_retry(ads, &res, ldap_exp, group_attrs); + free(ldap_exp); if (!ADS_ERR_OK(rc)) { DEBUG(1,("lookup_usergroups ads_search member=%s: %s\n", user_dn, ads_errstr(rc))); @@ -540,7 +573,7 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, ADS_STATUS rc; int count; void *msg = NULL; - char *exp; + char *ldap_exp; char *user_dn; DOM_SID *sids; int i; @@ -554,22 +587,26 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, *num_groups = 0; ads = ads_cached_connection(domain); - if (!ads) goto done; + + if (!ads) { + domain->last_status = NT_STATUS_SERVER_DISABLED; + goto done; + } if (!(sidstr = sid_binstring(sid))) { DEBUG(1,("lookup_usergroups(sid=%s) sid_binstring returned NULL\n", sid_to_string(sid_string, sid))); status = NT_STATUS_NO_MEMORY; goto done; } - if (asprintf(&exp, "(objectSid=%s)", sidstr) == -1) { + if (asprintf(&ldap_exp, "(objectSid=%s)", sidstr) == -1) { free(sidstr); DEBUG(1,("lookup_usergroups(sid=%s) asprintf failed!\n", sid_to_string(sid_string, sid))); status = NT_STATUS_NO_MEMORY; goto done; } - rc = ads_search_retry(ads, &msg, exp, attrs); - free(exp); + rc = ads_search_retry(ads, &msg, ldap_exp, attrs); + free(ldap_exp); free(sidstr); if (!ADS_ERR_OK(rc)) { @@ -648,7 +685,7 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, int count; void *res=NULL; ADS_STRUCT *ads = NULL; - char *exp; + char *ldap_exp; NTSTATUS status = NT_STATUS_UNSUCCESSFUL; char *sidstr; const char *attrs[] = {"member", NULL}; @@ -656,17 +693,23 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, int i, num_members; fstring sid_string; + DEBUG(10,("ads: lookup_groupmem %s sid=%s\n", domain->name, sid_string_static(group_sid))); + *num_names = 0; ads = ads_cached_connection(domain); - if (!ads) goto done; + + if (!ads) { + domain->last_status = NT_STATUS_SERVER_DISABLED; + goto done; + } sidstr = sid_binstring(group_sid); /* search for all members of the group */ - asprintf(&exp, "(objectSid=%s)",sidstr); - rc = ads_search_retry(ads, &res, exp, attrs); - free(exp); + asprintf(&ldap_exp, "(objectSid=%s)",sidstr); + rc = ads_search_retry(ads, &res, ldap_exp, attrs); + free(ldap_exp); free(sidstr); if (!ADS_ERR_OK(rc)) { @@ -730,10 +773,16 @@ static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq) ADS_STRUCT *ads = NULL; ADS_STATUS rc; + DEBUG(3,("ads: fetch sequence_number for %s\n", domain->name)); + *seq = DOM_SEQUENCE_NONE; ads = ads_cached_connection(domain); - if (!ads) return NT_STATUS_UNSUCCESSFUL; + + if (!ads) { + domain->last_status = NT_STATUS_SERVER_DISABLED; + return NT_STATUS_UNSUCCESSFUL; + } rc = ads_USN(ads, seq); if (!ADS_ERR_OK(rc)) { @@ -755,11 +804,17 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain, ADS_STRUCT *ads; ADS_STATUS rc; + DEBUG(3,("ads: trusted_domains\n")); + *num_domains = 0; *names = NULL; ads = ads_cached_connection(domain); - if (!ads) return NT_STATUS_UNSUCCESSFUL; + + if (!ads) { + domain->last_status = NT_STATUS_SERVER_DISABLED; + return NT_STATUS_UNSUCCESSFUL; + } rc = ads_trusted_domains(ads, mem_ctx, num_domains, names, alt_names, dom_sids); @@ -772,8 +827,14 @@ static NTSTATUS domain_sid(struct winbindd_domain *domain, DOM_SID *sid) ADS_STRUCT *ads; ADS_STATUS rc; + DEBUG(3,("ads: domain_sid\n")); + ads = ads_cached_connection(domain); - if (!ads) return NT_STATUS_UNSUCCESSFUL; + + if (!ads) { + domain->last_status = NT_STATUS_SERVER_DISABLED; + return NT_STATUS_UNSUCCESSFUL; + } rc = ads_domain_sid(ads, sid); @@ -796,8 +857,14 @@ static NTSTATUS alternate_name(struct winbindd_domain *domain) TALLOC_CTX *ctx; char *workgroup; + DEBUG(3,("ads: alternate_name\n")); + ads = ads_cached_connection(domain); - if (!ads) return NT_STATUS_UNSUCCESSFUL; + + if (!ads) { + domain->last_status = NT_STATUS_SERVER_DISABLED; + return NT_STATUS_UNSUCCESSFUL; + } if (!(ctx = talloc_init("alternate_name"))) { return NT_STATUS_NO_MEMORY; @@ -808,8 +875,8 @@ static NTSTATUS alternate_name(struct winbindd_domain *domain) if (ADS_ERR_OK(rc)) { fstrcpy(domain->name, workgroup); fstrcpy(domain->alt_name, ads->config.realm); - strupper(domain->alt_name); - strupper(domain->name); + strupper_m(domain->alt_name); + strupper_m(domain->name); } talloc_destroy(ctx); diff --git a/source3/nsswitch/winbindd_cache.c b/source3/nsswitch/winbindd_cache.c index f3dc1263b9..2da2a9e641 100644 --- a/source3/nsswitch/winbindd_cache.c +++ b/source3/nsswitch/winbindd_cache.c @@ -4,6 +4,8 @@ Winbind cache backend functions Copyright (C) Andrew Tridgell 2001 + Copyright (C) Gerald Carter 2003 + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -26,7 +28,6 @@ #define DBGC_CLASS DBGC_WINBIND struct winbind_cache { - struct winbindd_methods *backend; TDB_CONTEXT *tdb; }; @@ -46,12 +47,14 @@ void wcache_flush_cache(void) { extern BOOL opt_nocache; - if (!wcache) return; + if (!wcache) + return; if (wcache->tdb) { tdb_close(wcache->tdb); wcache->tdb = NULL; } - if (opt_nocache) return; + if (opt_nocache) + return; wcache->tdb = tdb_open_log(lock_path("winbindd_cache.tdb"), 5000, TDB_CLEAR_IF_FIRST, O_RDWR|O_CREAT, 0600); @@ -59,6 +62,7 @@ void wcache_flush_cache(void) if (!wcache->tdb) { DEBUG(0,("Failed to open winbindd_cache.tdb!\n")); } + DEBUG(10,("wcache_flush_cache success\n")); } void winbindd_check_cache_size(time_t t) @@ -93,30 +97,39 @@ void winbindd_check_cache_size(time_t t) /* get the winbind_cache structure */ static struct winbind_cache *get_cache(struct winbindd_domain *domain) { - extern struct winbindd_methods msrpc_methods; struct winbind_cache *ret = wcache; - if (ret) return ret; - - ret = smb_xmalloc(sizeof(*ret)); - ZERO_STRUCTP(ret); - - if (!strcmp(domain->name, lp_workgroup()) && (lp_security() == SEC_USER)) { - extern struct winbindd_methods passdb_methods; - ret->backend = &passdb_methods; - - } else switch (lp_security()) { + if (!domain->backend) { + extern struct winbindd_methods msrpc_methods; + switch (lp_security()) { #ifdef HAVE_ADS - case SEC_ADS: { - extern struct winbindd_methods ads_methods; - ret->backend = &ads_methods; - break; - } + case SEC_ADS: { + extern struct winbindd_methods ads_methods; + /* always obey the lp_security parameter for our domain */ + if ( strequal(lp_realm(), domain->alt_name) ) { + domain->backend = &ads_methods; + break; + } + + if ( domain->native_mode ) { + domain->backend = &ads_methods; + break; + } + + /* fall through */ + } #endif - default: - ret->backend = &msrpc_methods; + default: + domain->backend = &msrpc_methods; + } } + if (ret) + return ret; + + ret = smb_xmalloc(sizeof(*ret)); + ZERO_STRUCTP(ret); + wcache = ret; wcache_flush_cache(); @@ -128,12 +141,12 @@ static struct winbind_cache *get_cache(struct winbindd_domain *domain) */ static void centry_free(struct cache_entry *centry) { - if (!centry) return; + if (!centry) + return; SAFE_FREE(centry->data); free(centry); } - /* pull a uint32 from a cache entry */ @@ -204,8 +217,10 @@ static DOM_SID *centry_sid(struct cache_entry *centry, TALLOC_CTX *mem_ctx) { DOM_SID *sid; char *sid_string; + sid = talloc(mem_ctx, sizeof(*sid)); - if (!sid) return NULL; + if (!sid) + return NULL; sid_string = centry_string(centry, mem_ctx); if (!string_to_sid(sid, sid_string)) { @@ -217,8 +232,17 @@ static DOM_SID *centry_sid(struct cache_entry *centry, TALLOC_CTX *mem_ctx) /* the server is considered down if it can't give us a sequence number */ static BOOL wcache_server_down(struct winbindd_domain *domain) { - if (!wcache->tdb) return False; - return (domain->sequence_number == DOM_SEQUENCE_NONE); + BOOL ret; + + if (!wcache->tdb) + return False; + + ret = (domain->sequence_number == DOM_SEQUENCE_NONE); + + if (ret) + DEBUG(10,("wcache_server_down: server for Domain %s down\n", + domain->name )); + return ret; } static NTSTATUS fetch_cache_seqnum( struct winbindd_domain *domain, time_t now ) @@ -227,14 +251,18 @@ static NTSTATUS fetch_cache_seqnum( struct winbindd_domain *domain, time_t now ) fstring key; uint32 time_diff; - if (!wcache->tdb) + if (!wcache->tdb) { + DEBUG(10,("fetch_cache_seqnum: tdb == NULL\n")); return NT_STATUS_UNSUCCESSFUL; + } snprintf( key, sizeof(key), "SEQNUM/%s", domain->name ); - data = tdb_fetch_by_string( wcache->tdb, key ); - if ( !data.dptr || data.dsize!=8 ) + data = tdb_fetch_bystring( wcache->tdb, key ); + if ( !data.dptr || data.dsize!=8 ) { + DEBUG(10,("fetch_cache_seqnum: invalid data size key [%s]\n", key )); return NT_STATUS_UNSUCCESSFUL; + } domain->sequence_number = IVAL(data.dptr, 0); domain->last_seq_check = IVAL(data.dptr, 4); @@ -242,8 +270,12 @@ static NTSTATUS fetch_cache_seqnum( struct winbindd_domain *domain, time_t now ) /* have we expired? */ time_diff = now - domain->last_seq_check; - if ( time_diff > lp_winbind_cache_time() ) + if ( time_diff > lp_winbind_cache_time() ) { + DEBUG(10,("fetch_cache_seqnum: timeout [%s][%u @ %u]\n", + domain->name, domain->sequence_number, + (uint32)domain->last_seq_check)); return NT_STATUS_UNSUCCESSFUL; + } DEBUG(10,("fetch_cache_seqnum: success [%s][%u @ %u]\n", domain->name, domain->sequence_number, @@ -258,8 +290,10 @@ static NTSTATUS store_cache_seqnum( struct winbindd_domain *domain ) fstring key_str; char buf[8]; - if (!wcache->tdb) + if (!wcache->tdb) { + DEBUG(10,("store_cache_seqnum: tdb == NULL\n")); return NT_STATUS_UNSUCCESSFUL; + } snprintf( key_str, sizeof(key_str), "SEQNUM/%s", domain->name ); key.dptr = key_str; @@ -270,8 +304,10 @@ static NTSTATUS store_cache_seqnum( struct winbindd_domain *domain ) data.dptr = buf; data.dsize = 8; - if ( tdb_store( wcache->tdb, key, data, TDB_REPLACE) == -1 ) + if ( tdb_store( wcache->tdb, key, data, TDB_REPLACE) == -1 ) { + DEBUG(10,("store_cache_seqnum: tdb_store fail key [%s]\n", key_str )); return NT_STATUS_UNSUCCESSFUL; + } DEBUG(10,("store_cache_seqnum: success [%s][%u @ %u]\n", domain->name, domain->sequence_number, @@ -280,8 +316,6 @@ static NTSTATUS store_cache_seqnum( struct winbindd_domain *domain ) return NT_STATUS_OK; } - - /* refresh the domain sequence number. If force is True then always refresh it, no matter how recently we fetched it @@ -303,7 +337,8 @@ static void refresh_sequence_number(struct winbindd_domain *domain, BOOL force) /* see if we have to refetch the domain sequence number */ if (!force && (time_diff < cache_time)) { - return; + DEBUG(10, ("refresh_sequence_number: %s time ok\n", domain->name)); + goto done; } /* try to get the sequence number from the tdb cache first */ @@ -313,20 +348,21 @@ static void refresh_sequence_number(struct winbindd_domain *domain, BOOL force) if ( NT_STATUS_IS_OK(status) ) goto done; - status = wcache->backend->sequence_number(domain, &domain->sequence_number); + status = domain->backend->sequence_number(domain, &domain->sequence_number); if (!NT_STATUS_IS_OK(status)) { domain->sequence_number = DOM_SEQUENCE_NONE; } + domain->last_status = status; domain->last_seq_check = time(NULL); /* save the new sequence number ni the cache */ store_cache_seqnum( domain ); done: - DEBUG(10, ("refresh_sequence_number: seq number is now %d\n", - domain->sequence_number)); + DEBUG(10, ("refresh_sequence_number: %s seq number is now %d\n", + domain->name, domain->sequence_number)); return; } @@ -334,12 +370,14 @@ done: /* decide if a cache entry has expired */ -static BOOL centry_expired(struct winbindd_domain *domain, struct cache_entry *centry) +static BOOL centry_expired(struct winbindd_domain *domain, const char *keystr, struct cache_entry *centry) { /* if the server is OK and our cache entry came from when it was down then the entry is invalid */ if (domain->sequence_number != DOM_SEQUENCE_NONE && centry->sequence_number == DOM_SEQUENCE_NONE) { + DEBUG(10,("centry_expired: Key %s for domain %s invalid sequence.\n", + keystr, domain->name )); return True; } @@ -347,9 +385,14 @@ static BOOL centry_expired(struct winbindd_domain *domain, struct cache_entry *c current sequence number then it is OK */ if (wcache_server_down(domain) || centry->sequence_number == domain->sequence_number) { + DEBUG(10,("centry_expired: Key %s for domain %s is good.\n", + keystr, domain->name )); return False; } + DEBUG(10,("centry_expired: Key %s for domain %s expired\n", + keystr, domain->name )); + /* it's expired */ return True; } @@ -380,9 +423,9 @@ static struct cache_entry *wcache_fetch(struct winbind_cache *cache, key.dptr = kstr; key.dsize = strlen(kstr); data = tdb_fetch(wcache->tdb, key); - free(kstr); if (!data.dptr) { /* a cache miss */ + free(kstr); return NULL; } @@ -393,25 +436,38 @@ static struct cache_entry *wcache_fetch(struct winbind_cache *cache, if (centry->len < 8) { /* huh? corrupt cache? */ + DEBUG(10,("wcache_fetch: Corrupt cache for key %s domain %s (len < 8) ?\n", + kstr, domain->name )); centry_free(centry); + free(kstr); return NULL; } centry->status = NT_STATUS(centry_uint32(centry)); centry->sequence_number = centry_uint32(centry); - if (centry_expired(domain, centry)) { + if (centry_expired(domain, kstr, centry)) { extern BOOL opt_dual_daemon; + DEBUG(10,("wcache_fetch: entry %s expired for domain %s\n", + kstr, domain->name )); + if (opt_dual_daemon) { extern BOOL background_process; background_process = True; + DEBUG(10,("wcache_fetch: background processing expired entry %s for domain %s\n", + kstr, domain->name )); } else { centry_free(centry); + free(kstr); return NULL; } } + DEBUG(10,("wcache_fetch: returning entry %s for domain %s\n", + kstr, domain->name )); + + free(kstr); return centry; } @@ -421,7 +477,8 @@ static struct cache_entry *wcache_fetch(struct winbind_cache *cache, static void centry_expand(struct cache_entry *centry, uint32 len) { uint8 *p; - if (centry->len - centry->ofs >= len) return; + if (centry->len - centry->ofs >= len) + return; centry->len *= 2; p = realloc(centry->data, centry->len); if (!p) { @@ -466,7 +523,8 @@ static void centry_put_string(struct cache_entry *centry, const char *s) len = strlen(s); /* can't handle more than 254 char strings. Truncating is probably best */ - if (len > 254) len = 254; + if (len > 254) + len = 254; centry_put_uint8(centry, len); centry_expand(centry, len); memcpy(centry->data + centry->ofs, s, len); @@ -486,7 +544,8 @@ struct cache_entry *centry_start(struct winbindd_domain *domain, NTSTATUS status { struct cache_entry *centry; - if (!wcache->tdb) return NULL; + if (!wcache->tdb) + return NULL; centry = smb_xmalloc(sizeof(*centry)); @@ -532,11 +591,13 @@ static void wcache_save_name_to_sid(struct winbindd_domain *domain, fstring sid_string; centry = centry_start(domain, status); - if (!centry) return; + if (!centry) + return; centry_put_sid(centry, sid); fstrcpy(uname, name); - strupper(uname); + strupper_m(uname); centry_end(centry, "NS/%s", sid_to_string(sid_string, sid)); + DEBUG(10,("wcache_save_name_to_sid: %s -> %s\n", uname, sid_string)); centry_free(centry); } @@ -547,12 +608,14 @@ static void wcache_save_sid_to_name(struct winbindd_domain *domain, NTSTATUS sta fstring sid_string; centry = centry_start(domain, status); - if (!centry) return; + if (!centry) + return; if (NT_STATUS_IS_OK(status)) { centry_put_uint32(centry, type); centry_put_string(centry, name); } centry_end(centry, "SN/%s", sid_to_string(sid_string, sid)); + DEBUG(10,("wcache_save_sid_to_name: %s -> %s\n", sid_string, name)); centry_free(centry); } @@ -563,12 +626,14 @@ static void wcache_save_user(struct winbindd_domain *domain, NTSTATUS status, WI fstring sid_string; centry = centry_start(domain, status); - if (!centry) return; + if (!centry) + return; centry_put_string(centry, info->acct_name); centry_put_string(centry, info->full_name); centry_put_sid(centry, info->user_sid); centry_put_sid(centry, info->group_sid); centry_end(centry, "U/%s", sid_to_string(sid_string, info->user_sid)); + DEBUG(10,("wcache_save_user: %s (acct_name %s)\n", sid_string, info->acct_name)); centry_free(centry); } @@ -582,19 +647,23 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain, struct winbind_cache *cache = get_cache(domain); struct cache_entry *centry = NULL; NTSTATUS status; - unsigned int i; + unsigned int i, retry; - if (!cache->tdb) goto do_query; + if (!cache->tdb) + goto do_query; centry = wcache_fetch(cache, domain, "UL/%s", domain->name); - if (!centry) goto do_query; + if (!centry) + goto do_query; *num_entries = centry_uint32(centry); - if (*num_entries == 0) goto do_cached; + if (*num_entries == 0) + goto do_cached; (*info) = talloc(mem_ctx, sizeof(**info) * (*num_entries)); - if (! (*info)) smb_panic("query_user_list out of memory"); + if (! (*info)) + smb_panic("query_user_list out of memory"); for (i=0; i<(*num_entries); i++) { (*info)[i].acct_name = centry_string(centry, mem_ctx); (*info)[i].full_name = centry_string(centry, mem_ctx); @@ -604,6 +673,10 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain, do_cached: status = centry->status; + + DEBUG(10,("query_user_list: [Cached] - cached list for domain %s status %s\n", + domain->name, get_friendly_nt_error_msg(status) )); + centry_free(centry); return status; @@ -611,23 +684,48 @@ do_query: *num_entries = 0; *info = NULL; - if (wcache_server_down(domain)) { - return NT_STATUS_SERVER_DISABLED; - } + /* Return status value returned by seq number check */ + + if (!NT_STATUS_IS_OK(domain->last_status)) + return domain->last_status; - status = cache->backend->query_user_list(domain, mem_ctx, num_entries, info); + /* Put the query_user_list() in a retry loop. There appears to be + * some bug either with Windows 2000 or Samba's handling of large + * rpc replies. This manifests itself as sudden disconnection + * at a random point in the enumeration of a large (60k) user list. + * The retry loop simply tries the operation again. )-: It's not + * pretty but an acceptable workaround until we work out what the + * real problem is. */ + + retry = 0; + do { + + DEBUG(10,("query_user_list: [Cached] - doing backend query for list for domain %s\n", + domain->name )); + + status = domain->backend->query_user_list(domain, mem_ctx, num_entries, info); + if (!NT_STATUS_IS_OK(status)) + DEBUG(3, ("query_user_list: returned 0x%08x, retrying\n", NT_STATUS_V(status))); + if (NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_UNSUCCESSFUL)) { + DEBUG(3, ("query_user_list: flushing connection cache\n")); + winbindd_cm_flush(); + } + + } while (NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_UNSUCCESSFUL) && + (retry++ < 5)); /* and save it */ refresh_sequence_number(domain, False); centry = centry_start(domain, status); - if (!centry) goto skip_save; + if (!centry) + goto skip_save; centry_put_uint32(centry, *num_entries); for (i=0; i<(*num_entries); i++) { centry_put_string(centry, (*info)[i].acct_name); centry_put_string(centry, (*info)[i].full_name); centry_put_sid(centry, (*info)[i].user_sid); centry_put_sid(centry, (*info)[i].group_sid); - if (cache->backend->consistent) { + if (domain->backend->consistent) { /* when the backend is consistent we can pre-prime some mappings */ wcache_save_name_to_sid(domain, NT_STATUS_OK, (*info)[i].acct_name, @@ -658,17 +756,21 @@ static NTSTATUS enum_dom_groups(struct winbindd_domain *domain, NTSTATUS status; unsigned int i; - if (!cache->tdb) goto do_query; + if (!cache->tdb) + goto do_query; centry = wcache_fetch(cache, domain, "GL/%s/domain", domain->name); - if (!centry) goto do_query; + if (!centry) + goto do_query; *num_entries = centry_uint32(centry); - if (*num_entries == 0) goto do_cached; + if (*num_entries == 0) + goto do_cached; (*info) = talloc(mem_ctx, sizeof(**info) * (*num_entries)); - if (! (*info)) smb_panic("enum_dom_groups out of memory"); + if (! (*info)) + smb_panic("enum_dom_groups out of memory"); for (i=0; i<(*num_entries); i++) { fstrcpy((*info)[i].acct_name, centry_string(centry, mem_ctx)); fstrcpy((*info)[i].acct_desc, centry_string(centry, mem_ctx)); @@ -677,6 +779,10 @@ static NTSTATUS enum_dom_groups(struct winbindd_domain *domain, do_cached: status = centry->status; + + DEBUG(10,("enum_dom_groups: [Cached] - cached list for domain %s status %s\n", + domain->name, get_friendly_nt_error_msg(status) )); + centry_free(centry); return status; @@ -684,16 +790,21 @@ do_query: *num_entries = 0; *info = NULL; - if (wcache_server_down(domain)) { - return NT_STATUS_SERVER_DISABLED; - } + /* Return status value returned by seq number check */ - status = cache->backend->enum_dom_groups(domain, mem_ctx, num_entries, info); + if (!NT_STATUS_IS_OK(domain->last_status)) + return domain->last_status; + + DEBUG(10,("enum_dom_groups: [Cached] - doing backend query for list for domain %s\n", + domain->name )); + + status = domain->backend->enum_dom_groups(domain, mem_ctx, num_entries, info); /* and save it */ refresh_sequence_number(domain, False); centry = centry_start(domain, status); - if (!centry) goto skip_save; + if (!centry) + goto skip_save; centry_put_uint32(centry, *num_entries); for (i=0; i<(*num_entries); i++) { centry_put_string(centry, (*info)[i].acct_name); @@ -718,17 +829,21 @@ static NTSTATUS enum_local_groups(struct winbindd_domain *domain, NTSTATUS status; unsigned int i; - if (!cache->tdb) goto do_query; + if (!cache->tdb) + goto do_query; centry = wcache_fetch(cache, domain, "GL/%s/local", domain->name); - if (!centry) goto do_query; + if (!centry) + goto do_query; *num_entries = centry_uint32(centry); - if (*num_entries == 0) goto do_cached; + if (*num_entries == 0) + goto do_cached; (*info) = talloc(mem_ctx, sizeof(**info) * (*num_entries)); - if (! (*info)) smb_panic("enum_dom_groups out of memory"); + if (! (*info)) + smb_panic("enum_dom_groups out of memory"); for (i=0; i<(*num_entries); i++) { fstrcpy((*info)[i].acct_name, centry_string(centry, mem_ctx)); fstrcpy((*info)[i].acct_desc, centry_string(centry, mem_ctx)); @@ -743,11 +858,14 @@ do_cached: indicate this. */ if (wcache_server_down(domain)) { - DEBUG(10, ("query_user_list: returning cached user list and server was down\n")); + DEBUG(10, ("enum_local_groups: returning cached user list and server was down\n")); status = NT_STATUS_MORE_PROCESSING_REQUIRED; } else status = centry->status; + DEBUG(10,("enum_local_groups: [Cached] - cached list for domain %s status %s\n", + domain->name, get_friendly_nt_error_msg(status) )); + centry_free(centry); return status; @@ -755,16 +873,21 @@ do_query: *num_entries = 0; *info = NULL; - if (wcache_server_down(domain)) { - return NT_STATUS_SERVER_DISABLED; - } + /* Return status value returned by seq number check */ + + if (!NT_STATUS_IS_OK(domain->last_status)) + return domain->last_status; - status = cache->backend->enum_local_groups(domain, mem_ctx, num_entries, info); + DEBUG(10,("enum_local_groups: [Cached] - doing backend query for list for domain %s\n", + domain->name )); + + status = domain->backend->enum_local_groups(domain, mem_ctx, num_entries, info); /* and save it */ refresh_sequence_number(domain, False); centry = centry_start(domain, status); - if (!centry) goto skip_save; + if (!centry) + goto skip_save; centry_put_uint32(centry, *num_entries); for (i=0; i<(*num_entries); i++) { centry_put_string(centry, (*info)[i].acct_name); @@ -791,12 +914,14 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain, fstring uname; DOM_SID *sid2; - if (!cache->tdb) goto do_query; + if (!cache->tdb) + goto do_query; fstrcpy(uname, name); - strupper(uname); + strupper_m(uname); centry = wcache_fetch(cache, domain, "NS/%s/%s", domain->name, uname); - if (!centry) goto do_query; + if (!centry) + goto do_query; *type = centry_uint32(centry); sid2 = centry_sid(centry, mem_ctx); if (!sid2) { @@ -806,16 +931,31 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain, } status = centry->status; + + DEBUG(10,("name_to_sid: [Cached] - cached name for domain %s status %s\n", + domain->name, get_friendly_nt_error_msg(status) )); + centry_free(centry); return status; do_query: ZERO_STRUCTP(sid); - if (wcache_server_down(domain)) { - return NT_STATUS_SERVER_DISABLED; - } - status = cache->backend->name_to_sid(domain, mem_ctx, name, sid, type); + /* If the seq number check indicated that there is a problem + * with this DC, then return that status... except for + * access_denied. This is special because the dc may be in + * "restrict anonymous = 1" mode, in which case it will deny + * most unauthenticated operations, but *will* allow the LSA + * name-to-sid that we try as a fallback. */ + + if (!(NT_STATUS_IS_OK(domain->last_status) + || NT_STATUS_EQUAL(domain->last_status, NT_STATUS_ACCESS_DENIED))) + return domain->last_status; + + DEBUG(10,("name_to_sid: [Cached] - doing backend query for name for domain %s\n", + domain->name )); + + status = domain->backend->name_to_sid(domain, mem_ctx, name, sid, type); /* and save it */ wcache_save_name_to_sid(domain, status, name, sid, *type); @@ -839,25 +979,42 @@ static NTSTATUS sid_to_name(struct winbindd_domain *domain, NTSTATUS status; fstring sid_string; - if (!cache->tdb) goto do_query; + if (!cache->tdb) + goto do_query; centry = wcache_fetch(cache, domain, "SN/%s", sid_to_string(sid_string, sid)); - if (!centry) goto do_query; + if (!centry) + goto do_query; if (NT_STATUS_IS_OK(centry->status)) { *type = centry_uint32(centry); *name = centry_string(centry, mem_ctx); } status = centry->status; + + DEBUG(10,("sid_to_name: [Cached] - cached name for domain %s status %s\n", + domain->name, get_friendly_nt_error_msg(status) )); + centry_free(centry); return status; do_query: *name = NULL; - if (wcache_server_down(domain)) { - return NT_STATUS_SERVER_DISABLED; - } - status = cache->backend->sid_to_name(domain, mem_ctx, sid, name, type); + /* If the seq number check indicated that there is a problem + * with this DC, then return that status... except for + * access_denied. This is special because the dc may be in + * "restrict anonymous = 1" mode, in which case it will deny + * most unauthenticated operations, but *will* allow the LSA + * sid-to-name that we try as a fallback. */ + + if (!(NT_STATUS_IS_OK(domain->last_status) + || NT_STATUS_EQUAL(domain->last_status, NT_STATUS_ACCESS_DENIED))) + return domain->last_status; + + DEBUG(10,("sid_to_name: [Cached] - doing backend query for name for domain %s\n", + domain->name )); + + status = domain->backend->sid_to_name(domain, mem_ctx, sid, name, type); /* and save it */ refresh_sequence_number(domain, False); @@ -877,29 +1034,51 @@ static NTSTATUS query_user(struct winbindd_domain *domain, struct winbind_cache *cache = get_cache(domain); struct cache_entry *centry = NULL; NTSTATUS status; - fstring sid_string; - if (!cache->tdb) goto do_query; + if (!cache->tdb) + goto do_query; - centry = wcache_fetch(cache, domain, "U/%s", sid_to_string(sid_string, user_sid)); - if (!centry) goto do_query; + centry = wcache_fetch(cache, domain, "U/%s", sid_string_static(user_sid)); + + /* If we have an access denied cache entry and a cached info3 in the + samlogon cache then do a query. This will force the rpc back end + to return the info3 data. */ + + if (NT_STATUS_V(domain->last_status) == NT_STATUS_V(NT_STATUS_ACCESS_DENIED) && + netsamlogon_cache_have(user_sid)) { + DEBUG(10, ("query_user: cached access denied and have cached info3\n")); + domain->last_status = NT_STATUS_OK; + centry_free(centry); + goto do_query; + } + + if (!centry) + goto do_query; info->acct_name = centry_string(centry, mem_ctx); info->full_name = centry_string(centry, mem_ctx); info->user_sid = centry_sid(centry, mem_ctx); info->group_sid = centry_sid(centry, mem_ctx); status = centry->status; + + DEBUG(10,("query_user: [Cached] - cached info for domain %s status %s\n", + domain->name, get_friendly_nt_error_msg(status) )); + centry_free(centry); return status; do_query: ZERO_STRUCTP(info); - if (wcache_server_down(domain)) { - return NT_STATUS_SERVER_DISABLED; - } + /* Return status value returned by seq number check */ + + if (!NT_STATUS_IS_OK(domain->last_status)) + return domain->last_status; - status = cache->backend->query_user(domain, mem_ctx, user_sid, info); + DEBUG(10,("sid_to_name: [Cached] - doing backend query for info for domain %s\n", + domain->name )); + + status = domain->backend->query_user(domain, mem_ctx, user_sid, info); /* and save it */ refresh_sequence_number(domain, False); @@ -921,23 +1100,44 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, unsigned int i; fstring sid_string; - if (!cache->tdb) goto do_query; + if (!cache->tdb) + goto do_query; centry = wcache_fetch(cache, domain, "UG/%s", sid_to_string(sid_string, user_sid)); - if (!centry) goto do_query; + + /* If we have an access denied cache entry and a cached info3 in the + samlogon cache then do a query. This will force the rpc back end + to return the info3 data. */ + + if (NT_STATUS_V(domain->last_status) == NT_STATUS_V(NT_STATUS_ACCESS_DENIED) && + netsamlogon_cache_have(user_sid)) { + DEBUG(10, ("query_user: cached access denied and have cached info3\n")); + domain->last_status = NT_STATUS_OK; + centry_free(centry); + goto do_query; + } + + if (!centry) + goto do_query; *num_groups = centry_uint32(centry); - if (*num_groups == 0) goto do_cached; + if (*num_groups == 0) + goto do_cached; (*user_gids) = talloc(mem_ctx, sizeof(**user_gids) * (*num_groups)); - if (! (*user_gids)) smb_panic("lookup_usergroups out of memory"); + if (! (*user_gids)) + smb_panic("lookup_usergroups out of memory"); for (i=0; i<(*num_groups); i++) { (*user_gids)[i] = centry_sid(centry, mem_ctx); } do_cached: status = centry->status; + + DEBUG(10,("lookup_usergroups: [Cached] - cached info for domain %s status %s\n", + domain->name, get_friendly_nt_error_msg(status) )); + centry_free(centry); return status; @@ -945,15 +1145,21 @@ do_query: (*num_groups) = 0; (*user_gids) = NULL; - if (wcache_server_down(domain)) { - return NT_STATUS_SERVER_DISABLED; - } - status = cache->backend->lookup_usergroups(domain, mem_ctx, user_sid, num_groups, user_gids); + /* Return status value returned by seq number check */ + + if (!NT_STATUS_IS_OK(domain->last_status)) + return domain->last_status; + + DEBUG(10,("lookup_usergroups: [Cached] - doing backend query for info for domain %s\n", + domain->name )); + + status = domain->backend->lookup_usergroups(domain, mem_ctx, user_sid, num_groups, user_gids); /* and save it */ refresh_sequence_number(domain, False); centry = centry_start(domain, status); - if (!centry) goto skip_save; + if (!centry) + goto skip_save; centry_put_uint32(centry, *num_groups); for (i=0; i<(*num_groups); i++) { centry_put_sid(centry, (*user_gids)[i]); @@ -978,14 +1184,17 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, unsigned int i; fstring sid_string; - if (!cache->tdb) goto do_query; + if (!cache->tdb) + goto do_query; centry = wcache_fetch(cache, domain, "GM/%s", sid_to_string(sid_string, group_sid)); - if (!centry) goto do_query; + if (!centry) + goto do_query; *num_names = centry_uint32(centry); - if (*num_names == 0) goto do_cached; + if (*num_names == 0) + goto do_cached; (*sid_mem) = talloc(mem_ctx, sizeof(**sid_mem) * (*num_names)); (*names) = talloc(mem_ctx, sizeof(**names) * (*num_names)); @@ -1003,6 +1212,10 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, do_cached: status = centry->status; + + DEBUG(10,("lookup_groupmem: [Cached] - cached info for domain %s status %s\n", + domain->name, get_friendly_nt_error_msg(status) )); + centry_free(centry); return status; @@ -1012,17 +1225,22 @@ do_query: (*names) = NULL; (*name_types) = NULL; + /* Return status value returned by seq number check */ - if (wcache_server_down(domain)) { - return NT_STATUS_SERVER_DISABLED; - } - status = cache->backend->lookup_groupmem(domain, mem_ctx, group_sid, num_names, - sid_mem, names, name_types); + if (!NT_STATUS_IS_OK(domain->last_status)) + return domain->last_status; + + DEBUG(10,("lookup_groupmem: [Cached] - doing backend query for info for domain %s\n", + domain->name )); + + status = domain->backend->lookup_groupmem(domain, mem_ctx, group_sid, num_names, + sid_mem, names, name_types); /* and save it */ refresh_sequence_number(domain, False); centry = centry_start(domain, status); - if (!centry) goto skip_save; + if (!centry) + goto skip_save; centry_put_uint32(centry, *num_names); for (i=0; i<(*num_names); i++) { centry_put_sid(centry, (*sid_mem)[i]); @@ -1054,29 +1272,78 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain, char ***alt_names, DOM_SID **dom_sids) { - struct winbind_cache *cache = get_cache(domain); + get_cache(domain); + + DEBUG(10,("trusted_domains: [Cached] - doing backend query for info for domain %s\n", + domain->name )); /* we don't cache this call */ - return cache->backend->trusted_domains(domain, mem_ctx, num_domains, + return domain->backend->trusted_domains(domain, mem_ctx, num_domains, names, alt_names, dom_sids); } /* find the domain sid */ static NTSTATUS domain_sid(struct winbindd_domain *domain, DOM_SID *sid) { - struct winbind_cache *cache = get_cache(domain); + get_cache(domain); + + DEBUG(10,("domain_sid: [Cached] - doing backend query for info for domain %s\n", + domain->name )); /* we don't cache this call */ - return cache->backend->domain_sid(domain, sid); + return domain->backend->domain_sid(domain, sid); } /* find the alternate names for the domain, if any */ static NTSTATUS alternate_name(struct winbindd_domain *domain) { - struct winbind_cache *cache = get_cache(domain); + get_cache(domain); + + DEBUG(10,("alternate_name: [Cached] - doing backend query for info for domain %s\n", + domain->name )); /* we don't cache this call */ - return cache->backend->alternate_name(domain); + return domain->backend->alternate_name(domain); +} + +/* Invalidate cached user and group lists coherently */ + +static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, + void *state) +{ + if (strncmp(kbuf.dptr, "UL/", 3) == 0 || + strncmp(kbuf.dptr, "GL/", 3) == 0) + tdb_delete(the_tdb, kbuf); + + return 0; +} + +/* Invalidate the getpwnam and getgroups entries for a winbindd domain */ + +void wcache_invalidate_samlogon(struct winbindd_domain *domain, + NET_USER_INFO_3 *info3) +{ + struct winbind_cache *cache; + + if (!domain) + return; + + cache = get_cache(domain); + netsamlogon_clear_cached_user(cache->tdb, info3); +} + +void wcache_invalidate_cache(void) +{ + struct winbindd_domain *domain; + + for (domain = domain_list(); domain; domain = domain->next) { + struct winbind_cache *cache = get_cache(domain); + + DEBUG(10, ("wcache_invalidate_cache: invalidating cache " + "entries for %s\n", domain->name)); + if (cache) + tdb_traverse(cache->tdb, traverse_fn, NULL); + } } /* the ADS backend methods are exposed via this structure */ diff --git a/source3/nsswitch/winbindd_cm.c b/source3/nsswitch/winbindd_cm.c index 02fd15e069..7f35167778 100644 --- a/source3/nsswitch/winbindd_cm.c +++ b/source3/nsswitch/winbindd_cm.c @@ -51,9 +51,6 @@ - I'm pretty annoyed by all the make_nmb_name() stuff. It should be moved down into another function. - - There needs to be a utility function in libsmb/namequery.c that does - cm_get_dc_name() - - Take care when destroying cli_structs as they can be shared between various sam handles. @@ -79,139 +76,6 @@ struct winbindd_cm_conn { static struct winbindd_cm_conn *cm_conns = NULL; -/* Get a domain controller name. Cache positive and negative lookups so we - don't go to the network too often when something is badly broken. */ - -#define GET_DC_NAME_CACHE_TIMEOUT 30 /* Seconds between dc lookups */ - -struct get_dc_name_cache { - fstring domain_name; - fstring srv_name; - time_t lookup_time; - struct get_dc_name_cache *prev, *next; -}; - -/* - find the DC for a domain using methods appropriate for a ADS domain -*/ -static BOOL cm_ads_find_dc(const char *domain, struct in_addr *dc_ip, fstring srv_name) -{ - ADS_STRUCT *ads; - const char *realm = domain; - - if (strcasecmp(realm, lp_workgroup()) == 0) - realm = lp_realm(); - - ads = ads_init(realm, domain, NULL); - if (!ads) - return False; - - /* we don't need to bind, just connect */ - ads->auth.flags |= ADS_AUTH_NO_BIND; - - DEBUG(4,("cm_ads_find_dc: domain=%s\n", domain)); - -#ifdef HAVE_ADS - /* a full ads_connect() is actually overkill, as we don't srictly need - to do the SASL auth in order to get the info we need, but libads - doesn't offer a better way right now */ - ads_connect(ads); -#endif - - if (!ads->config.realm) - return False; - - fstrcpy(srv_name, ads->config.ldap_server_name); - strupper(srv_name); - *dc_ip = ads->ldap_ip; - ads_destroy(&ads); - - DEBUG(4,("cm_ads_find_dc: using server='%s' IP=%s\n", - srv_name, inet_ntoa(*dc_ip))); - - return True; -} - - - -static BOOL cm_get_dc_name(const char *domain, fstring srv_name, struct in_addr *ip_out) -{ - static struct get_dc_name_cache *get_dc_name_cache; - struct get_dc_name_cache *dcc; - struct in_addr dc_ip; - BOOL ret; - - /* Check the cache for previous lookups */ - - for (dcc = get_dc_name_cache; dcc; dcc = dcc->next) { - - if (!strequal(domain, dcc->domain_name)) - continue; /* Not our domain */ - - if ((time(NULL) - dcc->lookup_time) > - GET_DC_NAME_CACHE_TIMEOUT) { - - /* Cache entry has expired, delete it */ - - DEBUG(10, ("get_dc_name_cache entry expired for %s\n", domain)); - - DLIST_REMOVE(get_dc_name_cache, dcc); - SAFE_FREE(dcc); - - break; - } - - /* Return a positive or negative lookup for this domain */ - - if (dcc->srv_name[0]) { - DEBUG(10, ("returning positive get_dc_name_cache entry for %s\n", domain)); - fstrcpy(srv_name, dcc->srv_name); - return True; - } else { - DEBUG(10, ("returning negative get_dc_name_cache entry for %s\n", domain)); - return False; - } - } - - /* Add cache entry for this lookup. */ - - DEBUG(10, ("Creating get_dc_name_cache entry for %s\n", domain)); - - if (!(dcc = (struct get_dc_name_cache *) - malloc(sizeof(struct get_dc_name_cache)))) - return False; - - ZERO_STRUCTP(dcc); - - fstrcpy(dcc->domain_name, domain); - dcc->lookup_time = time(NULL); - - DLIST_ADD(get_dc_name_cache, dcc); - - zero_ip(&dc_ip); - - ret = False; - if (lp_security() == SEC_ADS) - ret = cm_ads_find_dc(domain, &dc_ip, srv_name); - - if (!ret) { - /* fall back on rpc methods if the ADS methods fail */ - ret = rpc_find_dc(domain, srv_name, &dc_ip); - } - - if (!ret) - return False; - - /* We have a name so make the cache entry positive now */ - fstrcpy(dcc->srv_name, srv_name); - - DEBUG(3, ("cm_get_dc_name: Returning DC %s (%s) for domain %s\n", srv_name, - inet_ntoa(dc_ip), domain)); - - *ip_out = dc_ip; - - return True; -} /* Choose between anonymous or authenticated connections. We need to use an authenticated connection if DCs have the RestrictAnonymous registry @@ -246,65 +110,11 @@ static void cm_get_ipc_userpass(char **username, char **domain, char **password) } } -/* Open a new smb pipe connection to a DC on a given domain. Cache - negative creation attempts so we don't try and connect to broken - machines too often. */ - -#define FAILED_CONNECTION_CACHE_TIMEOUT 30 /* Seconds between attempts */ - -struct failed_connection_cache { - fstring domain_name; - fstring controller; - time_t lookup_time; - NTSTATUS nt_status; - struct failed_connection_cache *prev, *next; -}; - -static struct failed_connection_cache *failed_connection_cache; - -/* Add an entry to the failed conneciton cache */ - -static void add_failed_connection_entry(struct winbindd_cm_conn *new_conn, - NTSTATUS result) -{ - struct failed_connection_cache *fcc; - - SMB_ASSERT(!NT_STATUS_IS_OK(result)); - - /* Check we already aren't in the cache */ - - for (fcc = failed_connection_cache; fcc; fcc = fcc->next) { - if (strequal(fcc->domain_name, new_conn->domain)) { - DEBUG(10, ("domain %s already tried and failed\n", - fcc->domain_name)); - return; - } - } - - /* Create negative lookup cache entry for this domain and controller */ - - if (!(fcc = (struct failed_connection_cache *) - malloc(sizeof(struct failed_connection_cache)))) { - DEBUG(0, ("malloc failed in add_failed_connection_entry!\n")); - return; - } - - ZERO_STRUCTP(fcc); - - fstrcpy(fcc->domain_name, new_conn->domain); - fstrcpy(fcc->controller, new_conn->controller); - fcc->lookup_time = time(NULL); - fcc->nt_status = result; - - DLIST_ADD(failed_connection_cache, fcc); -} - /* Open a connction to the remote server, cache failures for 30 seconds */ static NTSTATUS cm_open_connection(const char *domain, const int pipe_index, struct winbindd_cm_conn *new_conn) { - struct failed_connection_cache *fcc; NTSTATUS result; char *ipc_username, *ipc_domain, *ipc_password; struct in_addr dc_ip; @@ -316,47 +126,15 @@ static NTSTATUS cm_open_connection(const char *domain, const int pipe_index, fstrcpy(new_conn->domain, domain); fstrcpy(new_conn->pipe_name, get_pipe_name_from_index(pipe_index)); - /* Look for a domain controller for this domain. Negative results - are cached so don't bother applying the caching for this - function just yet. */ + /* connection failure cache has been moved inside of get_dc_name + so we can deal with half dead DC's --jerry */ - if (!cm_get_dc_name(domain, new_conn->controller, &dc_ip)) { + if (!get_dc_name(domain, new_conn->controller, &dc_ip)) { result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND; - add_failed_connection_entry(new_conn, result); + add_failed_connection_entry(domain, "", result); return result; } - /* Return false if we have tried to look up this domain and netbios - name before and failed. */ - - for (fcc = failed_connection_cache; fcc; fcc = fcc->next) { - - if (!(strequal(domain, fcc->domain_name) && - strequal(new_conn->controller, fcc->controller))) - continue; /* Not our domain */ - - if ((time(NULL) - fcc->lookup_time) > - FAILED_CONNECTION_CACHE_TIMEOUT) { - - /* Cache entry has expired, delete it */ - - DEBUG(10, ("cm_open_connection cache entry expired for %s, %s\n", domain, new_conn->controller)); - - DLIST_REMOVE(failed_connection_cache, fcc); - free(fcc); - - break; - } - - /* The timeout hasn't expired yet so return false */ - - DEBUG(10, ("returning negative open_connection_cache entry for %s, %s\n", domain, new_conn->controller)); - - result = fcc->nt_status; - SMB_ASSERT(!NT_STATUS_IS_OK(result)); - return result; - } - /* Initialise SMB connection */ cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password); @@ -387,7 +165,7 @@ static NTSTATUS cm_open_connection(const char *domain, const int pipe_index, SAFE_FREE(ipc_password); if (!NT_STATUS_IS_OK(result)) { - add_failed_connection_entry(new_conn, result); + add_failed_connection_entry(domain, new_conn->controller, result); return result; } @@ -402,7 +180,7 @@ static NTSTATUS cm_open_connection(const char *domain, const int pipe_index, * specific UUID right now, i'm not going to bother. --jerry */ if ( !is_win2k_pipe(pipe_index) ) - add_failed_connection_entry(new_conn, result); + add_failed_connection_entry(domain, new_conn->controller, result); cli_shutdown(new_conn->cli); return result; } @@ -415,21 +193,19 @@ static NTSTATUS cm_open_connection(const char *domain, const int pipe_index, static BOOL connection_ok(struct winbindd_cm_conn *conn) { if (!conn) { - smb_panic("Invalid paramater passed to conneciton_ok(): conn was NULL!\n"); + smb_panic("Invalid parameter passed to connection_ok(): conn was NULL!\n"); return False; } if (!conn->cli) { - DEBUG(0, ("Connection to %s for domain %s (pipe %s) has NULL conn->cli!\n", + DEBUG(3, ("Connection to %s for domain %s (pipe %s) has NULL conn->cli!\n", conn->controller, conn->domain, conn->pipe_name)); - smb_panic("connection_ok: conn->cli was null!"); return False; } if (!conn->cli->initialised) { - DEBUG(0, ("Connection to %s for domain %s (pipe %s) was never initialised!\n", + DEBUG(3, ("Connection to %s for domain %s (pipe %s) was never initialised!\n", conn->controller, conn->domain, conn->pipe_name)); - smb_panic("connection_ok: conn->cli->initialised is False!"); return False; } @@ -442,52 +218,73 @@ static BOOL connection_ok(struct winbindd_cm_conn *conn) return True; } -/* Get a connection to the remote DC and open the pipe. If there is already a connection, use that */ +/* Search the cache for a connection. If there is a broken one, + shut it down properly and return NULL. */ -static NTSTATUS get_connection_from_cache(const char *domain, const char *pipe_name, - struct winbindd_cm_conn **conn_out) +static void find_cm_connection(const char *domain, const char *pipe_name, + struct winbindd_cm_conn **conn_out) { - struct winbindd_cm_conn *conn, conn_temp; - NTSTATUS result; - - *conn_out = NULL; + struct winbindd_cm_conn *conn; - for (conn = cm_conns; conn; conn = conn->next) { + for (conn = cm_conns; conn; ) { if (strequal(conn->domain, domain) && strequal(conn->pipe_name, pipe_name)) { if (!connection_ok(conn)) { + /* Dead connection - remove it. */ + struct winbindd_cm_conn *conn_temp = conn->next; if (conn->cli) cli_shutdown(conn->cli); - ZERO_STRUCT(conn_temp); - conn_temp.next = conn->next; DLIST_REMOVE(cm_conns, conn); SAFE_FREE(conn); - conn = &conn_temp; /* Just to keep the loop moving */ + conn = conn_temp; /* Keep the loop moving */ + continue; } else { break; } } + conn = conn->next; } - - if (!conn) { - if (!(conn = malloc(sizeof(*conn)))) - return NT_STATUS_NO_MEMORY; + + *conn_out = conn; +} + +/* Initialize a new connection up to the RPC BIND. */ + +static NTSTATUS new_cm_connection(const char *domain, const char *pipe_name, + struct winbindd_cm_conn **conn_out) +{ + struct winbindd_cm_conn *conn; + NTSTATUS result; + + if (!(conn = malloc(sizeof(*conn)))) + return NT_STATUS_NO_MEMORY; - ZERO_STRUCTP(conn); + ZERO_STRUCTP(conn); - if (!NT_STATUS_IS_OK(result = cm_open_connection(domain, get_pipe_index(pipe_name), conn))) { - DEBUG(3, ("Could not open a connection to %s for %s (%s)\n", - domain, pipe_name, nt_errstr(result))); - SAFE_FREE(conn); - return result; - } - DLIST_ADD(cm_conns, conn); + if (!NT_STATUS_IS_OK(result = cm_open_connection(domain, get_pipe_index(pipe_name), conn))) { + DEBUG(3, ("Could not open a connection to %s for %s (%s)\n", + domain, pipe_name, nt_errstr(result))); + SAFE_FREE(conn); + return result; } - + DLIST_ADD(cm_conns, conn); + *conn_out = conn; return NT_STATUS_OK; } +/* Get a connection to the remote DC and open the pipe. If there is already a connection, use that */ + +static NTSTATUS get_connection_from_cache(const char *domain, const char *pipe_name, + struct winbindd_cm_conn **conn_out) +{ + find_cm_connection(domain, pipe_name, conn_out); + + if (*conn_out != NULL) + return NT_STATUS_OK; + + return new_cm_connection(domain, pipe_name, conn_out); +} /********************************************************************************** **********************************************************************************/ @@ -522,8 +319,14 @@ BOOL cm_check_for_native_mode_win2k( const char *domain ) ret = True; done: + +#if 0 + /* + * I don't think we need to shutdown here ? JRA. + */ if ( conn.cli ) cli_shutdown( conn.cli ); +#endif return ret; } @@ -532,7 +335,7 @@ done: /* Return a LSA policy handle on a domain */ -CLI_POLICY_HND *cm_get_lsa_handle(const char *domain) +NTSTATUS cm_get_lsa_handle(const char *domain, CLI_POLICY_HND **return_hnd) { struct winbindd_cm_conn *conn; uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED; @@ -542,13 +345,16 @@ CLI_POLICY_HND *cm_get_lsa_handle(const char *domain) /* Look for existing connections */ if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_LSARPC, &conn))) - return NULL; + return result; /* This *shitty* code needs scrapping ! JRA */ + if (policy_handle_is_valid(&conn->pol)) { hnd.pol = conn->pol; hnd.cli = conn->cli; - return &hnd; + *return_hnd = &hnd; + + return NT_STATUS_OK; } result = cli_lsa_open_policy(conn->cli, conn->cli->mem_ctx, False, @@ -558,7 +364,7 @@ CLI_POLICY_HND *cm_get_lsa_handle(const char *domain) /* Hit the cache code again. This cleans out the old connection and gets a new one */ if (conn->cli->fd == -1) { /* Try again, if the remote host disapeared */ if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_LSARPC, &conn))) - return NULL; + return result; result = cli_lsa_open_policy(conn->cli, conn->cli->mem_ctx, False, des_access, &conn->pol); @@ -568,19 +374,21 @@ CLI_POLICY_HND *cm_get_lsa_handle(const char *domain) cli_shutdown(conn->cli); DLIST_REMOVE(cm_conns, conn); SAFE_FREE(conn); - return NULL; + return result; } } hnd.pol = conn->pol; hnd.cli = conn->cli; - return &hnd; + *return_hnd = &hnd; + + return NT_STATUS_OK; } /* Return a SAM policy handle on a domain */ -CLI_POLICY_HND *cm_get_sam_handle(char *domain) +NTSTATUS cm_get_sam_handle(char *domain, CLI_POLICY_HND **return_hnd) { struct winbindd_cm_conn *conn; uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED; @@ -590,279 +398,62 @@ CLI_POLICY_HND *cm_get_sam_handle(char *domain) /* Look for existing connections */ if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_SAMR, &conn))) - return NULL; + return result; /* This *shitty* code needs scrapping ! JRA */ + if (policy_handle_is_valid(&conn->pol)) { hnd.pol = conn->pol; hnd.cli = conn->cli; - return &hnd; + + *return_hnd = &hnd; + + return NT_STATUS_OK; } + result = cli_samr_connect(conn->cli, conn->cli->mem_ctx, des_access, &conn->pol); if (!NT_STATUS_IS_OK(result)) { /* Hit the cache code again. This cleans out the old connection and gets a new one */ if (conn->cli->fd == -1) { /* Try again, if the remote host disapeared */ + if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_SAMR, &conn))) - return NULL; + return result; result = cli_samr_connect(conn->cli, conn->cli->mem_ctx, des_access, &conn->pol); } if (!NT_STATUS_IS_OK(result)) { + cli_shutdown(conn->cli); DLIST_REMOVE(cm_conns, conn); SAFE_FREE(conn); - return NULL; + + return result; } } hnd.pol = conn->pol; hnd.cli = conn->cli; - return &hnd; -} - -#if 0 /* This code now *well* out of date */ + *return_hnd = &hnd; -/* Return a SAM domain policy handle on a domain */ - -CLI_POLICY_HND *cm_get_sam_dom_handle(char *domain, DOM_SID *domain_sid) -{ - struct winbindd_cm_conn *conn, *basic_conn = NULL; - static CLI_POLICY_HND hnd; - NTSTATUS result; - uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED; - - /* Look for existing connections */ - - for (conn = cm_conns; conn; conn = conn->next) { - if (strequal(conn->domain, domain) && - strequal(conn->pipe_name, PIPE_SAMR) && - conn->pipe_data.samr.pipe_type == SAM_PIPE_DOM) { - - if (!connection_ok(conn)) { - /* Shutdown cli? Free conn? Allow retry of DC? */ - DLIST_REMOVE(cm_conns, conn); - return NULL; - } - - goto ok; - } - } - - /* Create a basic handle to open a domain handle from */ - - if (!cm_get_sam_handle(domain)) - return False; - - for (conn = cm_conns; conn; conn = conn->next) { - if (strequal(conn->domain, domain) && - strequal(conn->pipe_name, PIPE_SAMR) && - conn->pipe_data.samr.pipe_type == SAM_PIPE_BASIC) - basic_conn = conn; - } - - if (!(conn = (struct winbindd_cm_conn *) - malloc(sizeof(struct winbindd_cm_conn)))) - return NULL; - - ZERO_STRUCTP(conn); - - fstrcpy(conn->domain, basic_conn->domain); - fstrcpy(conn->controller, basic_conn->controller); - fstrcpy(conn->pipe_name, basic_conn->pipe_name); - - conn->pipe_data.samr.pipe_type = SAM_PIPE_DOM; - conn->cli = basic_conn->cli; - - result = cli_samr_open_domain(conn->cli, conn->cli->mem_ctx, - &basic_conn->pol, des_access, - domain_sid, &conn->pol); - - if (!NT_STATUS_IS_OK(result)) - return NULL; - - /* Add to list */ - - DLIST_ADD(cm_conns, conn); - - ok: - hnd.pol = conn->pol; - hnd.cli = conn->cli; - - return &hnd; -} - -/* Return a SAM policy handle on a domain user */ - -CLI_POLICY_HND *cm_get_sam_user_handle(char *domain, DOM_SID *domain_sid, - uint32 user_rid) -{ - struct winbindd_cm_conn *conn, *basic_conn = NULL; - static CLI_POLICY_HND hnd; - NTSTATUS result; - uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED; - - /* Look for existing connections */ - - for (conn = cm_conns; conn; conn = conn->next) { - if (strequal(conn->domain, domain) && - strequal(conn->pipe_name, PIPE_SAMR) && - conn->pipe_data.samr.pipe_type == SAM_PIPE_USER && - conn->pipe_data.samr.rid == user_rid) { - - if (!connection_ok(conn)) { - /* Shutdown cli? Free conn? Allow retry of DC? */ - DLIST_REMOVE(cm_conns, conn); - return NULL; - } - - goto ok; - } - } - - /* Create a domain handle to open a user handle from */ - - if (!cm_get_sam_dom_handle(domain, domain_sid)) - return NULL; - - for (conn = cm_conns; conn; conn = conn->next) { - if (strequal(conn->domain, domain) && - strequal(conn->pipe_name, PIPE_SAMR) && - conn->pipe_data.samr.pipe_type == SAM_PIPE_DOM) - basic_conn = conn; - } - - if (!basic_conn) { - DEBUG(0, ("No domain sam handle was created!\n")); - return NULL; - } - - if (!(conn = (struct winbindd_cm_conn *) - malloc(sizeof(struct winbindd_cm_conn)))) - return NULL; - - ZERO_STRUCTP(conn); - - fstrcpy(conn->domain, basic_conn->domain); - fstrcpy(conn->controller, basic_conn->controller); - fstrcpy(conn->pipe_name, basic_conn->pipe_name); - - conn->pipe_data.samr.pipe_type = SAM_PIPE_USER; - conn->cli = basic_conn->cli; - conn->pipe_data.samr.rid = user_rid; - - result = cli_samr_open_user(conn->cli, conn->cli->mem_ctx, - &basic_conn->pol, des_access, user_rid, - &conn->pol); - - if (!NT_STATUS_IS_OK(result)) - return NULL; - - /* Add to list */ - - DLIST_ADD(cm_conns, conn); - - ok: - hnd.pol = conn->pol; - hnd.cli = conn->cli; - - return &hnd; -} - -/* Return a SAM policy handle on a domain group */ - -CLI_POLICY_HND *cm_get_sam_group_handle(char *domain, DOM_SID *domain_sid, - uint32 group_rid) -{ - struct winbindd_cm_conn *conn, *basic_conn = NULL; - static CLI_POLICY_HND hnd; - NTSTATUS result; - uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED; - - /* Look for existing connections */ - - for (conn = cm_conns; conn; conn = conn->next) { - if (strequal(conn->domain, domain) && - strequal(conn->pipe_name, PIPE_SAMR) && - conn->pipe_data.samr.pipe_type == SAM_PIPE_GROUP && - conn->pipe_data.samr.rid == group_rid) { - - if (!connection_ok(conn)) { - /* Shutdown cli? Free conn? Allow retry of DC? */ - DLIST_REMOVE(cm_conns, conn); - return NULL; - } - - goto ok; - } - } - - /* Create a domain handle to open a user handle from */ - - if (!cm_get_sam_dom_handle(domain, domain_sid)) - return NULL; - - for (conn = cm_conns; conn; conn = conn->next) { - if (strequal(conn->domain, domain) && - strequal(conn->pipe_name, PIPE_SAMR) && - conn->pipe_data.samr.pipe_type == SAM_PIPE_DOM) - basic_conn = conn; - } - - if (!basic_conn) { - DEBUG(0, ("No domain sam handle was created!\n")); - return NULL; - } - - if (!(conn = (struct winbindd_cm_conn *) - malloc(sizeof(struct winbindd_cm_conn)))) - return NULL; - - ZERO_STRUCTP(conn); - - fstrcpy(conn->domain, basic_conn->domain); - fstrcpy(conn->controller, basic_conn->controller); - fstrcpy(conn->pipe_name, basic_conn->pipe_name); - - conn->pipe_data.samr.pipe_type = SAM_PIPE_GROUP; - conn->cli = basic_conn->cli; - conn->pipe_data.samr.rid = group_rid; - - result = cli_samr_open_group(conn->cli, conn->cli->mem_ctx, - &basic_conn->pol, des_access, group_rid, - &conn->pol); - - if (!NT_STATUS_IS_OK(result)) - return NULL; - - /* Add to list */ - - DLIST_ADD(cm_conns, conn); - - ok: - hnd.pol = conn->pol; - hnd.cli = conn->cli; - - return &hnd; + return NT_STATUS_OK; } -#endif - /* Get a handle on a netlogon pipe. This is a bit of a hack to re-use the netlogon pipe as no handle is returned. */ NTSTATUS cm_get_netlogon_cli(const char *domain, const unsigned char *trust_passwd, uint32 sec_channel_type, + BOOL fresh, struct cli_state **cli) { NTSTATUS result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND; struct winbindd_cm_conn *conn; - uint32 neg_flags = 0x000001ff; fstring lock_name; BOOL got_mutex; @@ -871,7 +462,30 @@ NTSTATUS cm_get_netlogon_cli(const char *domain, /* Open an initial conection - keep the mutex. */ - if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_NETLOGON, &conn))) + find_cm_connection(domain, PIPE_NETLOGON, &conn); + + if ( fresh && (conn != NULL) ) { + cli_shutdown(conn->cli); + conn->cli = NULL; + + conn = NULL; + + /* purge connection from cache */ + find_cm_connection(domain, PIPE_NETLOGON, &conn); + if (conn != NULL) { + DEBUG(0,("Could not purge connection\n")); + return NT_STATUS_UNSUCCESSFUL; + } + } + + if (conn != NULL) { + *cli = conn->cli; + return NT_STATUS_OK; + } + + result = new_cm_connection(domain, PIPE_NETLOGON, &conn); + + if (!NT_STATUS_IS_OK(result)) return result; snprintf(lock_name, sizeof(lock_name), "NETLOGON\\%s", conn->controller); @@ -879,39 +493,20 @@ NTSTATUS cm_get_netlogon_cli(const char *domain, if (!(got_mutex = secrets_named_mutex(lock_name, WINBIND_SERVER_MUTEX_WAIT_TIME))) { DEBUG(0,("cm_get_netlogon_cli: mutex grab failed for %s\n", conn->controller)); } + + if ( sec_channel_type == SEC_CHAN_DOMAIN ) + snprintf(conn->cli->mach_acct, sizeof(conn->cli->mach_acct) - 1, "%s$", lp_workgroup()); - result = cli_nt_setup_creds(conn->cli, sec_channel_type, trust_passwd, &neg_flags, 2); + result = cli_nt_establish_netlogon(conn->cli, sec_channel_type, trust_passwd); if (got_mutex) secrets_named_mutex_release(lock_name); - + if (!NT_STATUS_IS_OK(result)) { - DEBUG(0, ("error connecting to domain password server: %s\n", - nt_errstr(result))); - - /* Hit the cache code again. This cleans out the old connection and gets a new one */ - if (conn->cli->fd == -1) { - if (!NT_STATUS_IS_OK(result = get_connection_from_cache(domain, PIPE_NETLOGON, &conn))) - return result; - - snprintf(lock_name, sizeof(lock_name), "NETLOGON\\%s", conn->controller); - if (!(got_mutex = secrets_named_mutex(lock_name, WINBIND_SERVER_MUTEX_WAIT_TIME))) { - DEBUG(0,("cm_get_netlogon_cli: mutex grab failed for %s\n", conn->controller)); - } - - /* Try again */ - result = cli_nt_setup_creds( conn->cli, sec_channel_type,trust_passwd, &neg_flags, 2); - - if (got_mutex) - secrets_named_mutex_release(lock_name); - } - - if (!NT_STATUS_IS_OK(result)) { - cli_shutdown(conn->cli); - DLIST_REMOVE(cm_conns, conn); - SAFE_FREE(conn); - return result; - } + cli_shutdown(conn->cli); + DLIST_REMOVE(cm_conns, conn); + SAFE_FREE(conn); + return result; } *cli = conn->cli; @@ -952,3 +547,34 @@ void winbindd_cm_status(void) else DEBUG(0, ("\tNo active connections\n")); } + +/* Close all cached connections */ + +void winbindd_cm_flush(void) +{ + struct winbindd_cm_conn *conn, tmp; + + /* Flush connection cache */ + + for (conn = cm_conns; conn; conn = conn->next) { + + if (!connection_ok(conn)) + continue; + + DEBUG(10, ("Closing connection to %s on %s\n", + conn->pipe_name, conn->controller)); + + if (conn->cli) + cli_shutdown(conn->cli); + + tmp.next = conn->next; + + DLIST_REMOVE(cm_conns, conn); + SAFE_FREE(conn); + conn = &tmp; + } + + /* Flush failed connection cache */ + + flush_negative_conn_cache(); +} diff --git a/source3/nsswitch/winbindd_group.c b/source3/nsswitch/winbindd_group.c index 94b6326b90..d67d48d506 100644 --- a/source3/nsswitch/winbindd_group.c +++ b/source3/nsswitch/winbindd_group.c @@ -5,6 +5,7 @@ Copyright (C) Tim Potter 2000 Copyright (C) Jeremy Allison 2001. + Copyright (C) Gerald (Jerry) Carter 2003. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -26,6 +27,34 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_WINBIND +/********************************************************************* +*********************************************************************/ + +static int gr_mem_buffer( char **buffer, char **members, int num_members ) +{ + int i; + int len = 0; + int idx = 0; + + if ( num_members == 0 ) { + *buffer = NULL; + return 0; + } + + for ( i=0; iname)); + if ( !((group_name_type==SID_NAME_DOM_GRP) || + ((group_name_type==SID_NAME_ALIAS) && strequal(lp_workgroup(), domain->name))) ) + { + DEBUG(1, ("SID %s in domain %s isn't a domain group (%d)\n", + sid_to_string(sid_string, group_sid), domain->name, + group_name_type)); goto done; } @@ -189,6 +221,7 @@ done: enum winbindd_result winbindd_getgrnam(struct winbindd_cli_state *state) { DOM_SID group_sid; + WINBINDD_GR *grp; struct winbindd_domain *domain; enum SID_NAME_USE name_type; fstring name_domain, name_group; @@ -207,9 +240,39 @@ enum winbindd_result winbindd_getgrnam(struct winbindd_cli_state *state) memset(name_group, 0, sizeof(fstring)); tmp = state->request.data.groupname; - if (!parse_domain_user(tmp, name_domain, name_group)) + + parse_domain_user(tmp, name_domain, name_group); + + /* if no domain or our local domain, then do a local tdb search */ + + if ( !*name_domain || strequal(name_domain, get_global_sam_name()) ) { + char *buffer = NULL; + + if ( !(grp=wb_getgrnam(name_group)) ) { + DEBUG(5,("winbindd_getgrnam: lookup for %s\\%s failed\n", + name_domain, name_group)); + return WINBINDD_ERROR; + } + memcpy( &state->response.data.gr, grp, sizeof(WINBINDD_GR) ); + + gr_mem_len = gr_mem_buffer( &buffer, grp->gr_mem, grp->num_gr_mem ); + + state->response.data.gr.gr_mem_ofs = 0; + state->response.length += gr_mem_len; + state->response.extra_data = buffer; /* give the memory away */ + + return WINBINDD_OK; + } + + /* should we deal with users for our domain? */ + + if ( lp_winbind_trusted_domains_only() && strequal(name_domain, lp_workgroup())) { + DEBUG(7,("winbindd_getgrnam: My domain -- rejecting getgrnam() for %s\\%s.\n", + name_domain, name_group)); return WINBINDD_ERROR; + } + /* Get info for the domain */ if ((domain = find_domain_from_name(name_domain)) == NULL) { @@ -227,13 +290,15 @@ enum winbindd_result winbindd_getgrnam(struct winbindd_cli_state *state) return WINBINDD_ERROR; } - if ((name_type != SID_NAME_ALIAS) && (name_type != SID_NAME_DOM_GRP)) { + if ( !((name_type==SID_NAME_DOM_GRP) || + ((name_type==SID_NAME_ALIAS) && strequal(lp_workgroup(), domain->name))) ) + { DEBUG(1, ("name '%s' is not a local or domain group: %d\n", name_group, name_type)); return WINBINDD_ERROR; } - if (NT_STATUS_IS_ERR(sid_to_gid(&group_sid, &gid))) { + if (!NT_STATUS_IS_OK(idmap_sid_to_gid(&group_sid, &gid, 0))) { DEBUG(1, ("error converting unix gid to sid\n")); return WINBINDD_ERROR; } @@ -261,6 +326,7 @@ enum winbindd_result winbindd_getgrnam(struct winbindd_cli_state *state) enum winbindd_result winbindd_getgrgid(struct winbindd_cli_state *state) { struct winbindd_domain *domain; + WINBINDD_GR *grp; DOM_SID group_sid; enum SID_NAME_USE name_type; fstring dom_name; @@ -277,8 +343,23 @@ enum winbindd_result winbindd_getgrgid(struct winbindd_cli_state *state) (state->request.data.gid > server_state.gid_high)) return WINBINDD_ERROR; + /* alway try local tdb lookup first */ + if ( ( grp=wb_getgrgid(state->request.data.gid)) != NULL ) { + char *buffer = NULL; + + memcpy( &state->response.data.gr, grp, sizeof(WINBINDD_GR) ); + + gr_mem_len = gr_mem_buffer( &buffer, grp->gr_mem, grp->num_gr_mem ); + + state->response.data.gr.gr_mem_ofs = 0; + state->response.length += gr_mem_len; + state->response.extra_data = buffer; /* give away the memory */ + + return WINBINDD_OK; + } + /* Get rid from gid */ - if (NT_STATUS_IS_ERR(uid_to_sid(&group_sid, state->request.data.gid))) { + if (!NT_STATUS_IS_OK(idmap_gid_to_sid(&group_sid, state->request.data.gid))) { DEBUG(1, ("could not convert gid %d to rid\n", state->request.data.gid)); return WINBINDD_ERROR; @@ -291,13 +372,6 @@ enum winbindd_result winbindd_getgrgid(struct winbindd_cli_state *state) return WINBINDD_ERROR; } - if (!((name_type == SID_NAME_ALIAS) || - (name_type == SID_NAME_DOM_GRP))) { - DEBUG(1, ("name '%s' is not a local or domain group: %d\n", - group_name, name_type)); - return WINBINDD_ERROR; - } - /* Fill in group structure */ domain = find_domain_from_sid(&group_sid); @@ -307,6 +381,14 @@ enum winbindd_result winbindd_getgrgid(struct winbindd_cli_state *state) return WINBINDD_ERROR; } + if ( !((name_type==SID_NAME_DOM_GRP) || + ((name_type==SID_NAME_ALIAS) && strequal(lp_workgroup(), domain->name))) ) + { + DEBUG(1, ("name '%s' is not a local or domain group: %d\n", + group_name, name_type)); + return WINBINDD_ERROR; + } + if (!fill_grent(&state->response.data.gr, dom_name, group_name, state->request.data.gid) || !fill_grent_mem(domain, &group_sid, name_type, @@ -353,6 +435,16 @@ enum winbindd_result winbindd_setgrent(struct winbindd_cli_state *state) for (domain = domain_list(); domain != NULL; domain = domain->next) { struct getent_state *domain_state; + + /* don't add our domaina if we are a PDC or if we + are a member of a Samba domain */ + + if ( (IS_DC || lp_winbind_trusted_domains_only()) + && strequal(domain->name, lp_workgroup()) ) + { + continue; + } + /* Create a state record for this domain */ if ((domain_state = (struct getent_state *) @@ -450,10 +542,10 @@ static BOOL get_sam_group_entries(struct getent_state *ent) ent->num_sam_entries = num_entries; - /* get the domain local groups if we are a member of a native win2k domain */ + /* get the domain local groups if we are a member of a native win2k domain + and are not using LDAP to get the groups */ - if ( domain->native_mode - && domain->methods->enum_local_groups + if ( lp_security() != SEC_ADS && domain->native_mode && strequal(lp_workgroup(), domain->name) ) { DEBUG(4,("get_sam_group_entries: Native Mode 2k domain; enumerating local groups as well\n")); @@ -590,7 +682,7 @@ enum winbindd_result winbindd_getgrent(struct winbindd_cli_state *state) sid_copy(&group_sid, &domain->sid); sid_append_rid(&group_sid, name_list[ent->sam_entry_index].rid); - if (NT_STATUS_IS_ERR(sid_to_gid(&group_sid, &group_gid))) { + if (!NT_STATUS_IS_OK(idmap_sid_to_gid(&group_sid, &group_gid, 0))) { DEBUG(1, ("could not look up gid for group %s\n", name_list[ent->sam_entry_index].acct_name)); @@ -743,7 +835,7 @@ enum winbindd_result winbindd_list_groups(struct winbindd_cli_state *state) ZERO_STRUCT(groups); /* Get list of sam groups */ - ZERO_STRUCT(groups); + fstrcpy(groups.domain_name, domain->name); get_sam_group_entries(&groups); @@ -799,21 +891,26 @@ enum winbindd_result winbindd_list_groups(struct winbindd_cli_state *state) } /* Get user supplementary groups. This is much quicker than trying to - invert the groups database. */ + invert the groups database. We merge the groups from the gids and + other_sids info3 fields as trusted domain, universal group + memberships, and nested groups (win2k native mode only) are not + returned by the getgroups RPC call but are present in the info3. */ enum winbindd_result winbindd_getgroups(struct winbindd_cli_state *state) { fstring name_domain, name_user; - DOM_SID user_sid; + DOM_SID user_sid, group_sid; enum SID_NAME_USE name_type; - uint32 num_groups, num_gids; + uint32 num_groups = 0; + uint32 num_gids = 0; NTSTATUS status; - DOM_SID **user_gids; + DOM_SID **user_grpsids; struct winbindd_domain *domain; enum winbindd_result result = WINBINDD_ERROR; gid_t *gid_list; unsigned int i; TALLOC_CTX *mem_ctx; + NET_USER_INFO_3 *info3 = NULL; /* Ensure null termination */ state->request.data.username[sizeof(state->request.data.username)-1]='\0'; @@ -827,8 +924,12 @@ enum winbindd_result winbindd_getgroups(struct winbindd_cli_state *state) /* Parse domain and username */ - if (!parse_domain_user(state->request.data.username, name_domain, - name_user)) + parse_domain_user(state->request.data.username, + name_domain, name_user); + + /* bail if there is no domain */ + + if ( !*name_domain ) goto done; /* Get info for the domain */ @@ -853,33 +954,109 @@ enum winbindd_result winbindd_getgroups(struct winbindd_cli_state *state) goto done; } - status = domain->methods->lookup_usergroups(domain, mem_ctx, - &user_sid, &num_groups, - &user_gids); - if (!NT_STATUS_IS_OK(status)) goto done; + /* Treat the info3 cache as authoritative as the + lookup_usergroups() function may return cached data. */ - /* Copy data back to client */ + if ((info3 = netsamlogon_cache_get(mem_ctx, &user_sid))) { - num_gids = 0; - gid_list = malloc(sizeof(gid_t) * num_groups); + DEBUG(10, ("winbindd_getgroups: info3 has %d groups, %d other sids\n", + info3->num_groups2, info3->num_other_sids)); - if (state->response.extra_data) - goto done; + num_groups = info3->num_other_sids + info3->num_groups2; + gid_list = calloc(sizeof(gid_t), num_groups); - for (i = 0; i < num_groups; i++) { - gid_t gid; + /* Go through each other sid and convert it to a gid */ + + for (i = 0; i < info3->num_other_sids; i++) { + fstring name; + fstring dom_name; + enum SID_NAME_USE sid_type; + + /* Is this sid known to us? It can either be + a trusted domain sid or a foreign sid. */ + + if (!winbindd_lookup_name_by_sid( &info3->other_sids[i].sid, + dom_name, name, &sid_type)) + { + DEBUG(10, ("winbindd_getgroups: could not lookup name for %s\n", + sid_string_static(&info3->other_sids[i].sid))); + continue; + } + + /* Check it is a domain group or an alias (domain local group) + in a win2k native mode domain. */ + + if ( !((sid_type==SID_NAME_DOM_GRP) || + ((sid_type==SID_NAME_ALIAS) && strequal(lp_workgroup(), domain->name))) ) + { + DEBUG(10, ("winbindd_getgroups: sid type %d " + "for %s is not a domain group\n", + sid_type, + sid_string_static( + &info3->other_sids[i].sid))); + continue; + } + + /* Map to a gid */ + + if (!NT_STATUS_IS_OK(idmap_sid_to_gid(&info3->other_sids[i].sid, &gid_list[num_gids], 0)) ) + { + DEBUG(10, ("winbindd_getgroups: could not map sid %s to gid\n", + sid_string_static(&info3->other_sids[i].sid))); + continue; + } + + /* We've jumped through a lot of hoops to get here */ + + DEBUG(10, ("winbindd_getgroups: mapped other sid %s to " + "gid %d\n", sid_string_static( + &info3->other_sids[i].sid), + gid_list[num_gids])); + + num_gids++; + } + + for (i = 0; i < info3->num_groups2; i++) { - if (NT_STATUS_IS_ERR(sid_to_gid(user_gids[i], &gid))) { - fstring sid_string; + /* create the group SID */ + + sid_copy( &group_sid, &domain->sid ); + sid_append_rid( &group_sid, info3->gids[i].g_rid ); - DEBUG(1, ("unable to convert group sid %s to gid\n", - sid_to_string(sid_string, user_gids[i]))); - continue; + if (!NT_STATUS_IS_OK(idmap_sid_to_gid(&group_sid, &gid_list[num_gids], 0)) ) { + DEBUG(10, ("winbindd_getgroups: could not map sid %s to gid\n", + sid_string_static(&group_sid))); + } + + num_gids++; + } + + SAFE_FREE(info3); + + } else { + status = domain->methods->lookup_usergroups(domain, mem_ctx, + &user_sid, &num_groups, + &user_grpsids); + if (!NT_STATUS_IS_OK(status)) + goto done; + + gid_list = malloc(sizeof(gid_t) * num_groups); + + if (state->response.extra_data) + goto done; + + for (i = 0; i < num_groups; i++) { + if (!NT_STATUS_IS_OK(idmap_sid_to_gid(user_grpsids[i], &gid_list[num_gids], 0))) { + DEBUG(1, ("unable to convert group sid %s to gid\n", + sid_string_static(user_grpsids[i]))); + continue; + } + num_gids++; } - gid_list[num_gids] = gid; - num_gids++; } + /* Send data back to client */ + state->response.data.num_entries = num_gids; state->response.extra_data = gid_list; state->response.length += num_gids * sizeof(gid_t); diff --git a/source3/nsswitch/winbindd_misc.c b/source3/nsswitch/winbindd_misc.c index fb56d0e657..8d7cdc4731 100644 --- a/source3/nsswitch/winbindd_misc.c +++ b/source3/nsswitch/winbindd_misc.c @@ -50,7 +50,7 @@ enum winbindd_result winbindd_check_machine_acct(struct winbindd_cli_state *stat the trust account password. */ /* Don't shut this down - it belongs to the connection cache code */ - result = cm_get_netlogon_cli(lp_workgroup(), trust_passwd, sec_channel_type, &cli); + result = cm_get_netlogon_cli(lp_workgroup(), trust_passwd, sec_channel_type, True, &cli); if (!NT_STATUS_IS_OK(result)) { DEBUG(3, ("could not open handle to NETLOGON pipe\n")); diff --git a/source3/nsswitch/winbindd_nss.h b/source3/nsswitch/winbindd_nss.h index cc1b144063..c4407bbe31 100644 --- a/source3/nsswitch/winbindd_nss.h +++ b/source3/nsswitch/winbindd_nss.h @@ -36,7 +36,7 @@ /* Update this when you change the interface. */ -#define WINBIND_INTERFACE_VERSION 7 +#define WINBIND_INTERFACE_VERSION 8 /* Socket commands */ @@ -99,6 +99,16 @@ enum winbindd_cmd { WINBINDD_WINS_BYIP, WINBINDD_WINS_BYNAME, + /* account management commands */ + + WINBINDD_CREATE_USER, + WINBINDD_CREATE_GROUP, + WINBINDD_ADD_USER_TO_GROUP, + WINBINDD_REMOVE_USER_FROM_GROUP, + WINBINDD_SET_USER_PRIMARY_GROUP, + WINBINDD_DELETE_USER, + WINBINDD_DELETE_GROUP, + /* this is like GETGRENT but gives an empty group list */ WINBINDD_GETGRLST, @@ -111,11 +121,34 @@ enum winbindd_cmd { WINBINDD_NUM_CMDS }; -#define WINBIND_PAM_INFO3_NDR 0x0001 -#define WINBIND_PAM_INFO3_TEXT 0x0002 -#define WINBIND_PAM_NTKEY 0x0004 -#define WINBIND_PAM_LMKEY 0x0008 -#define WINBIND_PAM_CONTACT_TRUSTDOM 0x0010 +typedef struct winbindd_pw { + fstring pw_name; + fstring pw_passwd; + uid_t pw_uid; + gid_t pw_gid; + fstring pw_gecos; + fstring pw_dir; + fstring pw_shell; +} WINBINDD_PW; + + +typedef struct winbindd_gr { + fstring gr_name; + fstring gr_passwd; + gid_t gr_gid; + int num_gr_mem; + int gr_mem_ofs; /* offset to group membership */ + char **gr_mem; +} WINBINDD_GR; + + +#define WBFLAG_PAM_INFO3_NDR 0x0001 +#define WBFLAG_PAM_INFO3_TEXT 0x0002 +#define WBFLAG_PAM_NTKEY 0x0004 +#define WBFLAG_PAM_LMKEY 0x0008 +#define WBFLAG_PAM_CONTACT_TRUSTDOM 0x0010 +#define WBFLAG_QUERY_ONLY 0x0020 +#define WBFLAG_ALLOCATE_RID 0x0040 /* Winbind request structure */ @@ -123,6 +156,7 @@ struct winbindd_request { uint32 length; enum winbindd_cmd cmd; /* Winbindd command to execute */ pid_t pid; /* pid of calling process */ + uint32 flags; /* flags relavant to a given request */ union { fstring winsreq; /* WINS request */ @@ -146,7 +180,6 @@ struct winbindd_request { fstring nt_resp; uint16 nt_resp_len; fstring workstation; - uint32 flags; } auth_crap; struct { fstring user; @@ -159,6 +192,10 @@ struct winbindd_request { fstring name; } name; uint32 num_entries; /* getpwent, getgrent */ + struct { + fstring username; + fstring groupname; + } acct_mgt; } data; char null_term; }; @@ -188,25 +225,11 @@ struct winbindd_response { /* getpwnam, getpwuid */ - struct winbindd_pw { - fstring pw_name; - fstring pw_passwd; - uid_t pw_uid; - gid_t pw_gid; - fstring pw_gecos; - fstring pw_dir; - fstring pw_shell; - } pw; + struct winbindd_pw pw; /* getgrnam, getgrgid */ - struct winbindd_gr { - fstring gr_name; - fstring gr_passwd; - gid_t gr_gid; - int num_gr_mem; - int gr_mem_ofs; /* offset to group membership */ - } gr; + struct winbindd_gr gr; uint32 num_entries; /* getpwent, getgrent */ struct winbindd_sid { @@ -235,6 +258,7 @@ struct winbindd_response { char nt_session_key[16]; char first_8_lm_hash[8]; } auth; + uint32 rid; /* create user or group */ } data; /* Variable length return data */ diff --git a/source3/nsswitch/winbindd_pam.c b/source3/nsswitch/winbindd_pam.c index 2998372bd2..8df0f621c0 100644 --- a/source3/nsswitch/winbindd_pam.c +++ b/source3/nsswitch/winbindd_pam.c @@ -1,4 +1,4 @@ -/* +/* Unix SMB/CIFS implementation. Winbind daemon - pam auth funcions @@ -53,7 +53,58 @@ static NTSTATUS append_info3_as_ndr(TALLOC_CTX *mem_ctx, return NT_STATUS_OK; } -/* Return a password structure from a username. */ +/******************************************************************* + wrapper around retreiving the trsut account password +*******************************************************************/ + +static BOOL get_trust_pw(const char *domain, uint8 ret_pwd[16], + time_t *pass_last_set_time, uint32 *channel) +{ + DOM_SID sid; + char *pwd; + + /* if we are a DC and this is not our domain, then lookup an account + for the domain trust */ + + if ( IS_DC && !strequal(domain, lp_workgroup()) && lp_allow_trusted_domains() ) + { + if ( !secrets_fetch_trusted_domain_password(domain, &pwd, &sid, + pass_last_set_time) ) + { + DEBUG(0, ("get_trust_pw: could not fetch trust account " + "password for trusted domain %s\n", domain)); + return False; + } + + *channel = SEC_CHAN_DOMAIN; + E_md4hash(pwd, ret_pwd); + SAFE_FREE(pwd); + + return True; + } + else /* just get the account for our domain (covers + ROLE_DOMAIN_MEMBER as well */ + { + /* get the machine trust account for our domain */ + + if ( !secrets_fetch_trust_account_password (lp_workgroup(), ret_pwd, + pass_last_set_time, channel) ) + { + DEBUG(0, ("get_trust_pw: could not fetch trust account " + "password for my domain %s\n", domain)); + return False; + } + + return True; + } + + /* Failure */ + return False; +} + +/********************************************************************** + Authenticate a user with a clear test password +**********************************************************************/ enum winbindd_result winbindd_pam_auth(struct winbindd_cli_state *state) { @@ -68,6 +119,11 @@ enum winbindd_result winbindd_pam_auth(struct winbindd_cli_state *state) TALLOC_CTX *mem_ctx = NULL; DATA_BLOB lm_resp; DATA_BLOB nt_resp; + DOM_CRED ret_creds; + int attempts = 0; + unsigned char local_lm_response[24]; + unsigned char local_nt_response[24]; + const char *contact_domain; /* Ensure null termination */ state->request.data.auth.user[sizeof(state->request.data.auth.user)-1]='\0'; @@ -86,58 +142,85 @@ enum winbindd_result winbindd_pam_auth(struct winbindd_cli_state *state) /* Parse domain and username */ - if (!parse_domain_user(state->request.data.auth.user, name_domain, - name_user)) { + parse_domain_user(state->request.data.auth.user, name_domain, name_user); + if ( !name_domain ) { DEBUG(5,("no domain separator (%s) in username (%s) - failing auth\n", lp_winbind_separator(), state->request.data.auth.user)); result = NT_STATUS_INVALID_PARAMETER; goto done; } - { - unsigned char local_lm_response[24]; - unsigned char local_nt_response[24]; - - generate_random_buffer(chal, 8, False); - SMBencrypt(state->request.data.auth.pass, chal, local_lm_response); + /* do password magic */ + + generate_random_buffer(chal, 8, False); + SMBencrypt(state->request.data.auth.pass, chal, local_lm_response); - SMBNTencrypt(state->request.data.auth.pass, chal, local_nt_response); + SMBNTencrypt(state->request.data.auth.pass, chal, local_nt_response); - lm_resp = data_blob_talloc(mem_ctx, local_lm_response, sizeof(local_lm_response)); - nt_resp = data_blob_talloc(mem_ctx, local_nt_response, sizeof(local_nt_response)); - } + lm_resp = data_blob_talloc(mem_ctx, local_lm_response, sizeof(local_lm_response)); + nt_resp = data_blob_talloc(mem_ctx, local_nt_response, sizeof(local_nt_response)); - /* - * Get the machine account password for our primary domain - */ - - if (!secrets_fetch_trust_account_password( - lp_workgroup(), trust_passwd, &last_change_time, - &sec_channel_type)) { - DEBUG(0, ("winbindd_pam_auth: could not fetch trust account " - "password for domain %s\n", lp_workgroup())); + if ( !get_trust_pw(name_domain, trust_passwd, &last_change_time, &sec_channel_type) ) { result = NT_STATUS_CANT_ACCESS_DOMAIN_INFO; goto done; } - ZERO_STRUCT(info3); + /* what domain should we contact? */ + + if ( IS_DC ) + contact_domain = name_domain; + else + contact_domain = lp_workgroup(); + + /* check authentication loop */ + + do { + ZERO_STRUCT(info3); + ZERO_STRUCT(ret_creds); + + /* Don't shut this down - it belongs to the connection cache code */ + result = cm_get_netlogon_cli(contact_domain, trust_passwd, + sec_channel_type, False, &cli); + + if (!NT_STATUS_IS_OK(result)) { + DEBUG(3, ("could not open handle to NETLOGON pipe\n")); + goto done; + } + + result = cli_netlogon_sam_network_logon(cli, mem_ctx, + &ret_creds, + name_user, name_domain, + global_myname(), chal, + lm_resp, nt_resp, + &info3); + attempts += 1; + + /* if we get access denied, a possible cuase was that we had and open + connection to the DC, but someone changed our machine accoutn password + out from underneath us using 'net rpc changetrustpw' */ + + if ( NT_STATUS_V(result) == NT_STATUS_V(NT_STATUS_ACCESS_DENIED) ) { + DEBUG(3,("winbindd_pam_auth: sam_logon returned ACCESS_DENIED. Maybe the trust account " + "password was changed and we didn't know it. Killing connections to domain %s\n", + name_domain)); + winbindd_cm_flush(); + cli->fd = -1; + } + + /* We have to try a second time as cm_get_netlogon_cli + might not yet have noticed that the DC has killed + our connection. */ + + } while ( (attempts < 2) && (cli->fd == -1) ); + + + clnt_deal_with_creds(cli->sess_key, &(cli->clnt_cred), &ret_creds); + + if (NT_STATUS_IS_OK(result)) { + netsamlogon_cache_store( cli->mem_ctx, &info3 ); + wcache_invalidate_samlogon(find_domain_from_name(name_domain), &info3); + } - /* Don't shut this down - it belongs to the connection cache code */ - result = cm_get_netlogon_cli(lp_workgroup(), trust_passwd, - sec_channel_type, - &cli); - - if (!NT_STATUS_IS_OK(result)) { - DEBUG(3, ("could not open handle to NETLOGON pipe\n")); - goto done; - } - - result = cli_netlogon_sam_network_logon(cli, mem_ctx, - name_user, name_domain, - global_myname(), chal, - lm_resp, nt_resp, - &info3); - uni_group_cache_store_netlogon(mem_ctx, &info3); done: /* give us a more useful (more correct?) error code */ @@ -160,8 +243,10 @@ done: return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR; } - -/* Challenge Response Authentication Protocol */ + +/********************************************************************** + Challenge Response Authentication Protocol +**********************************************************************/ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state) { @@ -174,8 +259,10 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state) TALLOC_CTX *mem_ctx = NULL; char *user = NULL; const char *domain = NULL; - const char *contact_domain; const char *workstation; + const char *contact_domain; + DOM_CRED ret_creds; + int attempts = 0; DATA_BLOB lm_resp, nt_resp; @@ -220,11 +307,10 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state) DEBUG(3, ("[%5d]: pam auth crap domain: %s user: %s\n", state->pid, domain, user)); - - if (lp_allow_trusted_domains() && (state->request.data.auth_crap.flags & WINBIND_PAM_CONTACT_TRUSTDOM)) { - contact_domain = domain; - } else { - contact_domain = lp_workgroup(); + + if ( !get_trust_pw(domain, trust_passwd, &last_change_time, &sec_channel_type) ) { + result = NT_STATUS_CANT_ACCESS_DOMAIN_INFO; + goto done; } if (*state->request.data.auth_crap.workstation) { @@ -249,47 +335,68 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state) lm_resp = data_blob_talloc(mem_ctx, state->request.data.auth_crap.lm_resp, state->request.data.auth_crap.lm_resp_len); nt_resp = data_blob_talloc(mem_ctx, state->request.data.auth_crap.nt_resp, state->request.data.auth_crap.nt_resp_len); - /* - * Get the machine account password for the domain to contact. - * This is either our own domain for a workstation, or possibly - * any domain for a PDC with trusted domains. - */ - - if (!secrets_fetch_trust_account_password ( - contact_domain, trust_passwd, &last_change_time, - &sec_channel_type)) { - DEBUG(0, ("winbindd_pam_auth: could not fetch trust account " - "password for domain %s\n", contact_domain)); - result = NT_STATUS_CANT_ACCESS_DOMAIN_INFO; - goto done; - } + /* what domain should we contact? */ + + if ( IS_DC ) + contact_domain = domain; + else + contact_domain = lp_workgroup(); + + do { + ZERO_STRUCT(info3); + ZERO_STRUCT(ret_creds); + + /* Don't shut this down - it belongs to the connection cache code */ + result = cm_get_netlogon_cli(contact_domain, trust_passwd, sec_channel_type, False, &cli); - ZERO_STRUCT(info3); + if (!NT_STATUS_IS_OK(result)) { + DEBUG(3, ("could not open handle to NETLOGON pipe (error: %s)\n", + nt_errstr(result))); + goto done; + } - /* Don't shut this down - it belongs to the connection cache code */ - result = cm_get_netlogon_cli(contact_domain, trust_passwd, sec_channel_type, &cli); + result = cli_netlogon_sam_network_logon(cli, mem_ctx, + &ret_creds, + user, domain, + workstation, + state->request.data.auth_crap.chal, + lm_resp, nt_resp, + &info3); + + attempts += 1; + + /* if we get access denied, a possible cuase was that we had and open + connection to the DC, but someone changed our machine accoutn password + out from underneath us using 'net rpc changetrustpw' */ + + if ( NT_STATUS_V(result) == NT_STATUS_V(NT_STATUS_ACCESS_DENIED) ) { + DEBUG(3,("winbindd_pam_auth_crap: sam_logon returned ACCESS_DENIED. Maybe the trust account " + "password was changed and we didn't know it. Killing connections to domain %s\n", + domain)); + winbindd_cm_flush(); + cli->fd = -1; + } + + /* We have to try a second time as cm_get_netlogon_cli + might not yet have noticed that the DC has killed + our connection. */ - if (!NT_STATUS_IS_OK(result)) { - DEBUG(3, ("could not open handle to NETLOGON pipe (error: %s)\n", nt_errstr(result))); - goto done; - } + } while ( (attempts < 2) && (cli->fd == -1) ); - result = cli_netlogon_sam_network_logon(cli, mem_ctx, - user, domain, - workstation, state->request.data.auth_crap.chal, - lm_resp, nt_resp, - &info3); + clnt_deal_with_creds(cli->sess_key, &(cli->clnt_cred), &ret_creds); if (NT_STATUS_IS_OK(result)) { - uni_group_cache_store_netlogon(mem_ctx, &info3); - if (state->request.data.auth_crap.flags & WINBIND_PAM_INFO3_NDR) { + netsamlogon_cache_store( cli->mem_ctx, &info3 ); + wcache_invalidate_samlogon(find_domain_from_name(domain), &info3); + + if (state->request.flags & WBFLAG_PAM_INFO3_NDR) { result = append_info3_as_ndr(mem_ctx, state, &info3); } - - if (state->request.data.auth_crap.flags & WINBIND_PAM_NTKEY) { + + if (state->request.flags & WBFLAG_PAM_NTKEY) { memcpy(state->response.data.auth.nt_session_key, info3.user_sess_key, sizeof(state->response.data.auth.nt_session_key) /* 16 */); } - if (state->request.data.auth_crap.flags & WINBIND_PAM_LMKEY) { + if (state->request.flags & WBFLAG_PAM_LMKEY) { memcpy(state->response.data.auth.first_8_lm_hash, info3.padding, sizeof(state->response.data.auth.first_8_lm_hash) /* 8 */); } } @@ -337,8 +444,8 @@ enum winbindd_result winbindd_pam_chauthtok(struct winbindd_cli_state *state) if (state == NULL) return WINBINDD_ERROR; - if (!parse_domain_user(state->request.data.chauthtok.user, domain, - user)) { + parse_domain_user(state->request.data.chauthtok.user, domain, user); + if ( !*domain ) { result = NT_STATUS_INVALID_PARAMETER; goto done; } @@ -350,9 +457,8 @@ enum winbindd_result winbindd_pam_chauthtok(struct winbindd_cli_state *state) /* Get sam handle */ - if (!(hnd = cm_get_sam_handle(domain))) { + if ( NT_STATUS_IS_ERR(result = cm_get_sam_handle(domain, &hnd)) ) { DEBUG(1, ("could not get SAM handle on DC for %s\n", domain)); - result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND; goto done; } diff --git a/source3/nsswitch/winbindd_rpc.c b/source3/nsswitch/winbindd_rpc.c index 9ec35617f1..33339d7ca0 100644 --- a/source3/nsswitch/winbindd_rpc.c +++ b/source3/nsswitch/winbindd_rpc.c @@ -51,8 +51,8 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain, do { /* Get sam handle */ - if (!(hnd = cm_get_sam_handle(domain->name))) - goto done; + if ( !NT_STATUS_IS_OK(result = cm_get_sam_handle(domain->name, &hnd)) ) + return result; /* Get domain handle */ @@ -136,6 +136,7 @@ static NTSTATUS enum_dom_groups(struct winbindd_domain *domain, NTSTATUS status; uint32 start = 0; int retry; + NTSTATUS result; *num_entries = 0; *info = NULL; @@ -144,8 +145,8 @@ static NTSTATUS enum_dom_groups(struct winbindd_domain *domain, retry = 0; do { - if (!(hnd = cm_get_sam_handle(domain->name))) - return NT_STATUS_UNSUCCESSFUL; + if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain->name, &hnd))) + return result; status = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol, des_access, &domain->sid, &dom_pol); @@ -209,8 +210,8 @@ static NTSTATUS enum_local_groups(struct winbindd_domain *domain, retry = 0; do { - if ( !(hnd = cm_get_sam_handle(domain->name)) ) - return NT_STATUS_UNSUCCESSFUL; + if ( !NT_STATUS_IS_OK(result = cm_get_sam_handle(domain->name, &hnd)) ) + return result; result = cli_samr_open_domain( hnd->cli, mem_ctx, &hnd->pol, des_access, &domain->sid, &dom_pol); @@ -262,7 +263,7 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain, enum SID_NAME_USE *type) { CLI_POLICY_HND *hnd; - NTSTATUS status; + NTSTATUS result; DOM_SID *sids = NULL; uint32 *types = NULL; const char *full_name; @@ -277,24 +278,27 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain, return NT_STATUS_NO_MEMORY; } + DEBUG(3,("name_to_sid [rpc] %s for domain %s\n", name, domain->name )); + retry = 0; do { - if (!(hnd = cm_get_lsa_handle(domain->name))) { - return NT_STATUS_UNSUCCESSFUL; + if (!NT_STATUS_IS_OK(result = cm_get_lsa_handle(domain->name, &hnd))) { + return result; } - status = cli_lsa_lookup_names(hnd->cli, mem_ctx, &hnd->pol, 1, + result = cli_lsa_lookup_names(hnd->cli, mem_ctx, &hnd->pol, 1, &full_name, &sids, &types); - } while (!NT_STATUS_IS_OK(status) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1); + } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && + hnd && hnd->cli && hnd->cli->fd == -1); /* Return rid and type if lookup successful */ - if (NT_STATUS_IS_OK(status)) { + if (NT_STATUS_IS_OK(result)) { sid_copy(sid, &sids[0]); *type = types[0]; } - return status; + return result; } /* @@ -310,21 +314,23 @@ static NTSTATUS sid_to_name(struct winbindd_domain *domain, char **domains; char **names; uint32 *types; - NTSTATUS status; + NTSTATUS result; int retry; - DEBUG(3,("rpc: sid_to_name\n")); + DEBUG(3,("sid_to_name [rpc] %s for domain %s\n", sid_string_static(sid), + domain->name )); retry = 0; do { - if (!(hnd = cm_get_lsa_handle(domain->name))) - return NT_STATUS_UNSUCCESSFUL; + if (!NT_STATUS_IS_OK(result = cm_get_lsa_handle(domain->name, &hnd))) + return result; - status = cli_lsa_lookup_sids(hnd->cli, mem_ctx, &hnd->pol, + result = cli_lsa_lookup_sids(hnd->cli, mem_ctx, &hnd->pol, 1, sid, &domains, &names, &types); - } while (!NT_STATUS_IS_OK(status) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1); + } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && + hnd && hnd->cli && hnd->cli->fd == -1); - if (NT_STATUS_IS_OK(status)) { + if (NT_STATUS_IS_OK(result)) { *type = types[0]; *name = names[0]; DEBUG(5,("Mapped sid to [%s]\\[%s]\n", domains[0], *name)); @@ -335,7 +341,8 @@ static NTSTATUS sid_to_name(struct winbindd_domain *domain, return NT_STATUS_UNSUCCESSFUL; } } - return status; + + return result; } /* Lookup user information from a rid or username. */ @@ -352,24 +359,48 @@ static NTSTATUS query_user(struct winbindd_domain *domain, int retry; fstring sid_string; uint32 user_rid; + NET_USER_INFO_3 *user; DEBUG(3,("rpc: query_user rid=%s\n", sid_to_string(sid_string, user_sid))); if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid)) { goto done; } - + + /* try netsamlogon cache first */ + + if ( (user = netsamlogon_cache_get( mem_ctx, user_sid )) != NULL ) + { + + DEBUG(5,("query_user: Cache lookup succeeded for %s\n", + sid_string_static(user_sid))); + + user_info->user_sid = rid_to_talloced_sid( domain, mem_ctx, user_rid ); + user_info->group_sid = rid_to_talloced_sid( domain, mem_ctx, user->group_rid ); + + user_info->acct_name = unistr2_tdup(mem_ctx, &user->uni_user_name); + user_info->full_name = unistr2_tdup(mem_ctx, &user->uni_full_name); + + SAFE_FREE(user); + + return NT_STATUS_OK; + } + + /* no cache; hit the wire */ + retry = 0; do { - /* Get sam handle */ - if (!(hnd = cm_get_sam_handle(domain->name))) + /* Get sam handle; if we fail here there is no hope */ + + if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain->name, &hnd))) goto done; - + /* Get domain handle */ result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol, SEC_RIGHTS_MAXIMUM_ALLOWED, &domain->sid, &dom_pol); - } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1); + } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && + hnd && hnd->cli && hnd->cli->fd == -1); if (!NT_STATUS_IS_OK(result)) goto done; @@ -417,7 +448,7 @@ static NTSTATUS query_user(struct winbindd_domain *domain, static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, DOM_SID *user_sid, - uint32 *num_groups, DOM_SID ***user_gids) + uint32 *num_groups, DOM_SID ***user_grpsids) { CLI_POLICY_HND *hnd; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; @@ -429,30 +460,47 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, unsigned int retry; fstring sid_string; uint32 user_rid; + NET_USER_INFO_3 *user; DEBUG(3,("rpc: lookup_usergroups sid=%s\n", sid_to_string(sid_string, user_sid))); *num_groups = 0; + *user_grpsids = NULL; - /* First try cached universal groups from logon */ - *user_gids = uni_group_cache_fetch(&domain->sid, user_sid, mem_ctx, num_groups); - if((*num_groups > 0) && *user_gids) { + /* so lets see if we have a cached user_info_3 */ + + if ( (user = netsamlogon_cache_get( mem_ctx, user_sid )) != NULL ) + { + DEBUG(5,("query_user: Cache lookup succeeded for %s\n", + sid_string_static(user_sid))); + + *num_groups = user->num_groups; + + (*user_grpsids) = talloc(mem_ctx, sizeof(DOM_SID*) * (*num_groups)); + for (i=0;i<(*num_groups);i++) { + (*user_grpsids)[i] = rid_to_talloced_sid(domain, mem_ctx, user->gids[i].g_rid); + } + + SAFE_FREE(user); + return NT_STATUS_OK; - } else { - *user_gids = NULL; - *num_groups = 0; } + /* no cache; hit the wire */ + retry = 0; do { - /* Get sam handle */ - if (!(hnd = cm_get_sam_handle(domain->name))) + /* Get sam handle; if we fail here there is no hope */ + + if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain->name, &hnd))) goto done; /* Get domain handle */ + result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol, des_access, &domain->sid, &dom_pol); - } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1); + } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && + hnd && hnd->cli && hnd->cli->fd == -1); if (!NT_STATUS_IS_OK(result)) goto done; @@ -480,14 +528,14 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, if (!NT_STATUS_IS_OK(result) || (*num_groups) == 0) goto done; - (*user_gids) = talloc(mem_ctx, sizeof(uint32) * (*num_groups)); - if (!(*user_gids)) { + (*user_grpsids) = talloc(mem_ctx, sizeof(DOM_SID*) * (*num_groups)); + if (!(*user_grpsids)) { result = NT_STATUS_NO_MEMORY; goto done; } for (i=0;i<(*num_groups);i++) { - (*user_gids)[i] = rid_to_talloced_sid(domain, mem_ctx, user_groups[i].g_rid); + (*user_grpsids)[i] = rid_to_talloced_sid(domain, mem_ctx, user_groups[i].g_rid); } done: @@ -532,7 +580,7 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, retry = 0; do { /* Get sam handle */ - if (!(hnd = cm_get_sam_handle(domain->name))) + if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain->name, &hnd))) goto done; /* Get domain handle */ @@ -581,7 +629,7 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, (*sid_mem)[j] = rid_to_talloced_sid(domain, mem_ctx, (rid_mem)[j]); } - if (!*names || !*name_types) { + if (*num_names>0 && (!*names || !*name_types)) { result = NT_STATUS_NO_MEMORY; goto done; } @@ -601,9 +649,12 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, &tmp_num_names, &tmp_names, &tmp_types); - if (!NT_STATUS_IS_OK(result)) + /* see if we have a real error (and yes the STATUS_SOME_UNMAPPED is + the one returned from 2k) */ + + if (!NT_STATUS_IS_OK(result) && NT_STATUS_V(result) != NT_STATUS_V(STATUS_SOME_UNMAPPED)) goto done; - + /* Copy result into array. The talloc system will take care of freeing the temporary arrays later on. */ @@ -618,7 +669,9 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, *num_names = total_names; - done: + result = NT_STATUS_OK; + +done: if (got_group_pol) cli_samr_close(hnd->cli, mem_ctx, &group_pol); @@ -628,6 +681,137 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, return result; } +#ifdef HAVE_LDAP + +#include + +static SIG_ATOMIC_T gotalarm; + +/*************************************************************** + Signal function to tell us we timed out. +****************************************************************/ + +static void gotalarm_sig(void) +{ + gotalarm = 1; +} + +static LDAP *ldap_open_with_timeout(const char *server, int port, unsigned int to) +{ + LDAP *ldp = NULL; + + /* Setup timeout */ + gotalarm = 0; + CatchSignal(SIGALRM, SIGNAL_CAST gotalarm_sig); + alarm(to); + /* End setup timeout. */ + + ldp = ldap_open(server, port); + + /* Teardown timeout. */ + CatchSignal(SIGALRM, SIGNAL_CAST SIG_IGN); + alarm(0); + + return ldp; +} + +static int get_ldap_seq(const char *server, int port, uint32 *seq) +{ + int ret = -1; + struct timeval to; + char *attrs[] = {"highestCommittedUSN", NULL}; + LDAPMessage *res = NULL; + char **values = NULL; + LDAP *ldp = NULL; + + *seq = DOM_SEQUENCE_NONE; + + /* + * 10 second timeout on open. This is needed as the search timeout + * doesn't seem to apply to doing an open as well. JRA. + */ + + if ((ldp = ldap_open_with_timeout(server, port, 10)) == NULL) + return -1; + + /* Timeout if no response within 20 seconds. */ + to.tv_sec = 10; + to.tv_usec = 0; + + if (ldap_search_st(ldp, "", LDAP_SCOPE_BASE, "(objectclass=*)", &attrs[0], 0, &to, &res)) + goto done; + + if (ldap_count_entries(ldp, res) != 1) + goto done; + + values = ldap_get_values(ldp, res, "highestCommittedUSN"); + if (!values || !values[0]) + goto done; + + *seq = atoi(values[0]); + ret = 0; + + done: + + if (values) + ldap_value_free(values); + if (res) + ldap_msgfree(res); + if (ldp) + ldap_unbind(ldp); + return ret; +} + +/********************************************************************** + Get the sequence number for a Windows AD native mode domain using + LDAP queries +**********************************************************************/ + +int get_ldap_sequence_number( const char* domain, uint32 *seq) +{ + int ret = -1; + int i, port = LDAP_PORT; + struct ip_service *ip_list = NULL; + int count; + + if ( !get_sorted_dc_list(domain, &ip_list, &count, False) ) { + DEBUG(3, ("Could not look up dc's for domain %s\n", domain)); + return False; + } + + /* Finally return first DC that we can contact */ + + for (i = 0; i < count; i++) { + fstring ipstr; + + /* since the is an LDAP lookup, default to the LDAP_PORT is not set */ + port = (ip_list[i].port!= PORT_NONE) ? ip_list[i].port : LDAP_PORT; + + fstrcpy( ipstr, inet_ntoa(ip_list[i].ip) ); + + if (is_zero_ip(ip_list[i].ip)) + continue; + + if ( (ret = get_ldap_seq( ipstr, port, seq)) == 0 ) + goto done; + + /* add to failed connection cache */ + add_failed_connection_entry( domain, ipstr, NT_STATUS_UNSUCCESSFUL ); + } + +done: + if ( ret == 0 ) { + DEBUG(3, ("get_ldap_sequence_number: Retrieved sequence number for Domain (%s) from DC (%s:%d)\n", + domain, inet_ntoa(ip_list[i].ip), port)); + } + + SAFE_FREE(ip_list); + + return ret; +} + +#endif /* HAVE_LDAP */ + /* find the sequence number for a domain */ static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq) { @@ -636,7 +820,6 @@ static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq) SAM_UNK_CTR ctr; uint16 switch_value = 2; NTSTATUS result; - uint32 seqnum = DOM_SEQUENCE_NONE; POLICY_HND dom_pol; BOOL got_dom_pol = False; uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED; @@ -651,8 +834,24 @@ static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq) retry = 0; do { - /* Get sam handle */ - if (!(hnd = cm_get_sam_handle(domain->name))) +#ifdef HAVE_LDAP + if ( domain->native_mode ) + { + DEBUG(8,("using get_ldap_seq() to retrieve the sequence number\n")); + + if ( get_ldap_sequence_number( domain->name, seq ) == 0 ) { + result = NT_STATUS_OK; + DEBUG(10,("domain_sequence_number: LDAP for domain %s is %u\n", + domain->name, *seq)); + goto done; + } + + DEBUG(10,("domain_sequence_number: failed to get LDAP sequence number for domain %s\n", + domain->name )); + } +#endif /* HAVE_LDAP */ + /* Get sam handle */ + if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain->name, &hnd))) goto done; /* Get domain handle */ @@ -671,11 +870,11 @@ static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq) switch_value, &ctr); if (NT_STATUS_IS_OK(result)) { - seqnum = ctr.info.inf2.seq_num; - DEBUG(10,("domain_sequence_number: for domain %s is %u\n", domain->name, (unsigned)seqnum )); + *seq = ctr.info.inf2.seq_num; + DEBUG(10,("domain_sequence_number: for domain %s is %u\n", domain->name, (unsigned)*seq)); } else { DEBUG(10,("domain_sequence_number: failed to get sequence number (%u) for domain %s\n", - (unsigned)seqnum, domain->name )); + (unsigned)*seq, domain->name )); } done: @@ -685,8 +884,6 @@ static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq) talloc_destroy(mem_ctx); - *seq = seqnum; - return result; } @@ -710,7 +907,7 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain, retry = 0; do { - if (!(hnd = cm_get_lsa_handle(lp_workgroup()))) + if (!NT_STATUS_IS_OK(result = cm_get_lsa_handle(lp_workgroup(), &hnd))) goto done; result = cli_lsa_enum_trust_dom(hnd->cli, mem_ctx, @@ -725,7 +922,7 @@ done: /* find the domain sid for a domain */ static NTSTATUS domain_sid(struct winbindd_domain *domain, DOM_SID *sid) { - NTSTATUS status = NT_STATUS_UNSUCCESSFUL; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; TALLOC_CTX *mem_ctx; CLI_POLICY_HND *hnd; fstring level5_dom; @@ -738,17 +935,17 @@ static NTSTATUS domain_sid(struct winbindd_domain *domain, DOM_SID *sid) retry = 0; do { - /* Get sam handle */ - if (!(hnd = cm_get_lsa_handle(domain->name))) + /* Get lsa handle */ + if (!NT_STATUS_IS_OK(result = cm_get_lsa_handle(domain->name, &hnd))) goto done; - status = cli_lsa_query_info_policy(hnd->cli, mem_ctx, + result = cli_lsa_query_info_policy(hnd->cli, mem_ctx, &hnd->pol, 0x05, level5_dom, sid); - } while (!NT_STATUS_IS_OK(status) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1); + } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1); done: talloc_destroy(mem_ctx); - return status; + return result; } /* find alternate names list for the domain - none for rpc */ diff --git a/source3/nsswitch/winbindd_sid.c b/source3/nsswitch/winbindd_sid.c index f5dd904dc1..676beae3aa 100644 --- a/source3/nsswitch/winbindd_sid.c +++ b/source3/nsswitch/winbindd_sid.c @@ -122,6 +122,7 @@ enum winbindd_result winbindd_lookupname(struct winbindd_cli_state *state) enum winbindd_result winbindd_sid_to_uid(struct winbindd_cli_state *state) { DOM_SID sid; + uint32 flags = 0x0; /* Ensure null termination */ state->request.data.sid[sizeof(state->request.data.sid)-1]='\0'; @@ -131,15 +132,16 @@ enum winbindd_result winbindd_sid_to_uid(struct winbindd_cli_state *state) /* Split sid into domain sid and user rid */ if (!string_to_sid(&sid, state->request.data.sid)) { - DEBUG(1, ("Could not get convert sid %s from string\n", - state->request.data.sid)); + DEBUG(1, ("Could not get convert sid %s from string\n", state->request.data.sid)); return WINBINDD_ERROR; } - + + if ( state->request.flags & WBFLAG_QUERY_ONLY ) + flags = ID_QUERY_ONLY; + /* Find uid for this sid and return it */ - if (NT_STATUS_IS_ERR(sid_to_uid(&sid, &(state->response.data.uid)))) { - DEBUG(1, ("Could not get uid for sid %s\n", - state->request.data.sid)); + if ( !NT_STATUS_IS_OK(idmap_sid_to_uid(&sid, &(state->response.data.uid), flags)) ) { + DEBUG(1, ("Could not get uid for sid %s\n", state->request.data.sid)); return WINBINDD_ERROR; } @@ -152,6 +154,7 @@ enum winbindd_result winbindd_sid_to_uid(struct winbindd_cli_state *state) enum winbindd_result winbindd_sid_to_gid(struct winbindd_cli_state *state) { DOM_SID sid; + uint32 flags = 0x0; /* Ensure null termination */ state->request.data.sid[sizeof(state->request.data.sid)-1]='\0'; @@ -160,15 +163,16 @@ enum winbindd_result winbindd_sid_to_gid(struct winbindd_cli_state *state) state->request.data.sid)); if (!string_to_sid(&sid, state->request.data.sid)) { - DEBUG(1, ("Could not cvt string to sid %s\n", - state->request.data.sid)); + DEBUG(1, ("Could not cvt string to sid %s\n", state->request.data.sid)); return WINBINDD_ERROR; } + if ( state->request.flags & WBFLAG_QUERY_ONLY ) + flags = ID_QUERY_ONLY; + /* Find gid for this sid and return it */ - if (NT_STATUS_IS_ERR(sid_to_gid(&sid, &(state->response.data.gid)))) { - DEBUG(1, ("Could not get gid for sid %s\n", - state->request.data.sid)); + if ( !NT_STATUS_IS_OK(idmap_sid_to_gid(&sid, &(state->response.data.gid), flags)) ) { + DEBUG(1, ("Could not get gid for sid %s\n", state->request.data.sid)); return WINBINDD_ERROR; } @@ -192,7 +196,7 @@ enum winbindd_result winbindd_uid_to_sid(struct winbindd_cli_state *state) state->request.data.uid)); /* Lookup rid for this uid */ - if (NT_STATUS_IS_ERR(uid_to_sid(&sid, state->request.data.uid))) { + if (!NT_STATUS_IS_OK(idmap_uid_to_sid(&sid, state->request.data.uid))) { DEBUG(1, ("Could not convert uid %d to rid\n", state->request.data.uid)); return WINBINDD_ERROR; @@ -221,7 +225,7 @@ enum winbindd_result winbindd_gid_to_sid(struct winbindd_cli_state *state) state->request.data.gid)); /* Lookup sid for this uid */ - if (NT_STATUS_IS_ERR(gid_to_sid(&sid, state->request.data.gid))) { + if (!NT_STATUS_IS_OK(idmap_gid_to_sid(&sid, state->request.data.gid))) { DEBUG(1, ("Could not convert gid %d to sid\n", state->request.data.gid)); return WINBINDD_ERROR; diff --git a/source3/nsswitch/winbindd_user.c b/source3/nsswitch/winbindd_user.c index dc07bc42e7..c49c41687b 100644 --- a/source3/nsswitch/winbindd_user.c +++ b/source3/nsswitch/winbindd_user.c @@ -5,6 +5,7 @@ Copyright (C) Tim Potter 2000 Copyright (C) Jeremy Allison 2001. + Copyright (C) Gerald (Jerry) Carter 2003. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -26,13 +27,14 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_WINBIND +extern userdom_struct current_user_info; + /* Fill a pwent structure with information we have obtained */ static BOOL winbindd_fill_pwent(char *dom_name, char *user_name, DOM_SID *user_sid, DOM_SID *group_sid, char *full_name, struct winbindd_pw *pw) { - extern userdom_struct current_user_info; fstring output_username; pstring homedir; fstring sid_string; @@ -42,14 +44,14 @@ static BOOL winbindd_fill_pwent(char *dom_name, char *user_name, /* Resolve the uid number */ - if (NT_STATUS_IS_ERR(sid_to_uid(user_sid, &(pw->pw_uid)))) { + if (!NT_STATUS_IS_OK(idmap_sid_to_uid(user_sid, &(pw->pw_uid), 0))) { DEBUG(1, ("error getting user id for sid %s\n", sid_to_string(sid_string, user_sid))); return False; } /* Resolve the gid number */ - if (NT_STATUS_IS_ERR(sid_to_gid(group_sid, &(pw->pw_gid)))) { + if (!NT_STATUS_IS_OK(idmap_sid_to_gid(group_sid, &(pw->pw_gid), 0))) { DEBUG(1, ("error getting group id for sid %s\n", sid_to_string(sid_string, group_sid))); return False; } @@ -95,6 +97,7 @@ static BOOL winbindd_fill_pwent(char *dom_name, char *user_name, enum winbindd_result winbindd_getpwnam(struct winbindd_cli_state *state) { WINBIND_USERINFO user_info; + WINBINDD_PW *pw; DOM_SID user_sid; NTSTATUS status; fstring name_domain, name_user; @@ -110,9 +113,28 @@ enum winbindd_result winbindd_getpwnam(struct winbindd_cli_state *state) /* Parse domain and username */ - if (!parse_domain_user(state->request.data.username, name_domain, - name_user)) + parse_domain_user(state->request.data.username, + name_domain, name_user); + + /* if this is our local domain (or no domain), the do a local tdb search */ + + if ( !*name_domain || strequal(name_domain, get_global_sam_name()) ) { + if ( !(pw = wb_getpwnam(name_user)) ) { + DEBUG(5,("winbindd_getpwnam: lookup for %s\\%s failed\n", + name_domain, name_user)); + return WINBINDD_ERROR; + } + memcpy( &state->response.data.pw, pw, sizeof(WINBINDD_PW) ); + return WINBINDD_OK; + } + + /* should we deal with users for our domain? */ + + if ( lp_winbind_trusted_domains_only() && strequal(name_domain, lp_workgroup())) { + DEBUG(7,("winbindd_getpenam: My domain -- rejecting getpwnam() for %s\\%s.\n", + name_domain, name_user)); return WINBINDD_ERROR; + } if ((domain = find_domain_from_name(name_domain)) == NULL) { DEBUG(5, ("no such domain: %s\n", name_domain)); @@ -172,6 +194,7 @@ enum winbindd_result winbindd_getpwuid(struct winbindd_cli_state *state) { DOM_SID user_sid; struct winbindd_domain *domain; + WINBINDD_PW *pw; fstring dom_name; fstring user_name; enum SID_NAME_USE name_type; @@ -188,10 +211,17 @@ enum winbindd_result winbindd_getpwuid(struct winbindd_cli_state *state) DEBUG(3, ("[%5d]: getpwuid %d\n", state->pid, state->request.data.uid)); + + /* always try local tdb first */ + + if ( (pw = wb_getpwuid(state->request.data.uid)) != NULL ) { + memcpy( &state->response.data.pw, pw, sizeof(WINBINDD_PW) ); + return WINBINDD_OK; + } /* Get rid from uid */ - if (NT_STATUS_IS_ERR(uid_to_sid(&user_sid, state->request.data.uid))) { + if (!NT_STATUS_IS_OK(idmap_uid_to_sid(&user_sid, state->request.data.uid))) { DEBUG(1, ("could not convert uid %d to SID\n", state->request.data.uid)); return WINBINDD_ERROR; @@ -235,7 +265,7 @@ enum winbindd_result winbindd_getpwuid(struct winbindd_cli_state *state) /* Check group has a gid number */ - if (NT_STATUS_IS_ERR(sid_to_gid(user_info.group_sid, &gid))) { + if (!NT_STATUS_IS_OK(idmap_sid_to_gid(user_info.group_sid, &gid, 0))) { DEBUG(1, ("error getting group id for user %s\n", user_name)); talloc_destroy(mem_ctx); return WINBINDD_ERROR; @@ -278,12 +308,35 @@ enum winbindd_result winbindd_setpwent(struct winbindd_cli_state *state) free_getent_state(state->getpwent_state); state->getpwent_state = NULL; } + +#if 0 /* JERRY */ + /* add any local users we have */ + + if ( (domain_state = (struct getent_state *)malloc(sizeof(struct getent_state))) == NULL ) + return WINBINDD_ERROR; + + ZERO_STRUCTP(domain_state); + + /* Add to list of open domains */ + + DLIST_ADD(state->getpwent_state, domain_state); +#endif /* Create sam pipes for each domain we know about */ for(domain = domain_list(); domain != NULL; domain = domain->next) { struct getent_state *domain_state; + + /* don't add our domaina if we are a PDC or if we + are a member of a Samba domain */ + + if ( (IS_DC || lp_winbind_trusted_domains_only()) + && strequal(domain->name, lp_workgroup()) ) + { + continue; + } + /* Create a state record for this domain */ if ((domain_state = (struct getent_state *) diff --git a/source3/nsswitch/winbindd_util.c b/source3/nsswitch/winbindd_util.c index 84f5d19568..6177c46aef 100644 --- a/source3/nsswitch/winbindd_util.c +++ b/source3/nsswitch/winbindd_util.c @@ -118,6 +118,7 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const } domain->methods = methods; + domain->backend = NULL; domain->sequence_number = DOM_SEQUENCE_NONE; domain->last_seq_check = 0; if (sid) { @@ -296,14 +297,10 @@ BOOL winbindd_lookup_sid_by_name(struct winbindd_domain *domain, * @brief Lookup a name in a domain from a sid. * * @param sid Security ID you want to look up. - * * @param name On success, set to the name corresponding to @p sid. - * * @param dom_name On success, set to the 'domain name' corresponding to @p sid. - * * @param type On success, contains the type of name: alias, group or * user. - * * @retval True if the name exists, in which case @p name and @p type * are set, otherwise False. **/ @@ -379,12 +376,14 @@ BOOL winbindd_param_init(void) /* Parse winbind uid and winbind_gid parameters */ if (!lp_idmap_uid(&server_state.uid_low, &server_state.uid_high)) { - DEBUG(0, ("winbind uid range missing or invalid\n")); + DEBUG(0, ("winbindd: idmap uid range missing or invalid\n")); + DEBUG(0, ("winbindd: cannot continue, exiting.\n")); return False; } if (!lp_idmap_gid(&server_state.gid_low, &server_state.gid_high)) { - DEBUG(0, ("winbind gid range missing or invalid\n")); + DEBUG(0, ("winbindd: idmap gid range missing or invalid\n")); + DEBUG(0, ("winbindd: cannot continue, exiting.\n")); return False; } @@ -412,18 +411,22 @@ BOOL parse_domain_user(const char *domuser, fstring domain, fstring user) { char *p = strchr(domuser,*lp_winbind_separator()); - if (!(p || lp_winbind_use_default_domain())) - return False; - - if(!p && lp_winbind_use_default_domain()) { + if ( !p ) { fstrcpy(user, domuser); - fstrcpy(domain, lp_workgroup()); - } else { + + if ( lp_winbind_use_default_domain() ) + fstrcpy(domain, lp_workgroup()); + else + fstrcpy( domain, "" ); + } + else { fstrcpy(user, p+1); fstrcpy(domain, domuser); domain[PTR_DIFF(p, domuser)] = 0; } - strupper(domain); + + strupper_m(domain); + return True; } @@ -573,3 +576,209 @@ DOM_SID *rid_to_talloced_sid(struct winbindd_domain *domain, return sid; } +/***************************************************************************** + For idmap conversion: convert one record to new format + Ancient versions (eg 2.2.3a) of winbindd_idmap.tdb mapped DOMAINNAME/rid + instead of the SID. +*****************************************************************************/ +static int convert_fn(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA data, void *state) +{ + struct winbindd_domain *domain; + char *p; + DOM_SID sid; + uint32 rid; + fstring keystr; + fstring dom_name; + TDB_DATA key2; + BOOL *failed = (BOOL *)state; + + DEBUG(10,("Converting %s\n", key.dptr)); + + p = strchr(key.dptr, '/'); + if (!p) + return 0; + + *p = 0; + fstrcpy(dom_name, key.dptr); + *p++ = '/'; + + domain = find_domain_from_name(dom_name); + if (domain == NULL) { + /* We must delete the old record. */ + DEBUG(0,("Unable to find domain %s\n", dom_name )); + DEBUG(0,("deleting record %s\n", key.dptr )); + + if (tdb_delete(tdb, key) != 0) { + DEBUG(0, ("Unable to delete record %s\n", key.dptr)); + *failed = True; + return -1; + } + + return 0; + } + + rid = atoi(p); + + sid_copy(&sid, &domain->sid); + sid_append_rid(&sid, rid); + + sid_to_string(keystr, &sid); + key2.dptr = keystr; + key2.dsize = strlen(keystr) + 1; + + if (tdb_store(tdb, key2, data, TDB_INSERT) != 0) { + DEBUG(0,("Unable to add record %s\n", key2.dptr )); + *failed = True; + return -1; + } + + if (tdb_store(tdb, data, key2, TDB_REPLACE) != 0) { + DEBUG(0,("Unable to update record %s\n", data.dptr )); + *failed = True; + return -1; + } + + if (tdb_delete(tdb, key) != 0) { + DEBUG(0,("Unable to delete record %s\n", key.dptr )); + *failed = True; + return -1; + } + + return 0; +} + +/* These definitions are from sam/idmap_tdb.c. Replicated here just + out of laziness.... :-( */ + +/* High water mark keys */ +#define HWM_GROUP "GROUP HWM" +#define HWM_USER "USER HWM" + +/* idmap version determines auto-conversion */ +#define IDMAP_VERSION 2 + + +/***************************************************************************** + Convert the idmap database from an older version. +*****************************************************************************/ + +static BOOL idmap_convert(const char *idmap_name) +{ + int32 vers; + BOOL bigendianheader; + BOOL failed = False; + TDB_CONTEXT *idmap_tdb; + + if (!(idmap_tdb = tdb_open_log(idmap_name, 0, + TDB_DEFAULT, O_RDWR, + 0600))) { + DEBUG(0, ("idmap_convert: Unable to open idmap database\n")); + return False; + } + + bigendianheader = (idmap_tdb->flags & TDB_BIGENDIAN) ? True : False; + + vers = tdb_fetch_int32(idmap_tdb, "IDMAP_VERSION"); + + if (((vers == -1) && bigendianheader) || (IREV(vers) == IDMAP_VERSION)) { + /* Arrggghh ! Bytereversed or old big-endian - make order independent ! */ + /* + * high and low records were created on a + * big endian machine and will need byte-reversing. + */ + + int32 wm; + + wm = tdb_fetch_int32(idmap_tdb, HWM_USER); + + if (wm != -1) { + wm = IREV(wm); + } else { + wm = server_state.uid_low; + } + + if (tdb_store_int32(idmap_tdb, HWM_USER, wm) == -1) { + DEBUG(0, ("idmap_convert: Unable to byteswap user hwm in idmap database\n")); + tdb_close(idmap_tdb); + return False; + } + + wm = tdb_fetch_int32(idmap_tdb, HWM_GROUP); + if (wm != -1) { + wm = IREV(wm); + } else { + wm = server_state.gid_low; + } + + if (tdb_store_int32(idmap_tdb, HWM_GROUP, wm) == -1) { + DEBUG(0, ("idmap_convert: Unable to byteswap group hwm in idmap database\n")); + tdb_close(idmap_tdb); + return False; + } + } + + /* the old format stored as DOMAIN/rid - now we store the SID direct */ + tdb_traverse(idmap_tdb, convert_fn, &failed); + + if (failed) { + DEBUG(0, ("Problem during conversion\n")); + tdb_close(idmap_tdb); + return False; + } + + if (tdb_store_int32(idmap_tdb, "IDMAP_VERSION", IDMAP_VERSION) == -1) { + DEBUG(0, ("idmap_convert: Unable to dtore idmap version in databse\n")); + tdb_close(idmap_tdb); + return False; + } + + tdb_close(idmap_tdb); + return True; +} + +/***************************************************************************** + Convert the idmap database from an older version if necessary +*****************************************************************************/ + +BOOL winbindd_upgrade_idmap(void) +{ + pstring idmap_name; + pstring backup_name; + SMB_STRUCT_STAT stbuf; + TDB_CONTEXT *idmap_tdb; + + pstrcpy(idmap_name, lock_path("winbindd_idmap.tdb")); + + if (!file_exist(idmap_name, &stbuf)) { + /* nothing to convert return */ + return True; + } + + if (!(idmap_tdb = tdb_open_log(idmap_name, 0, + TDB_DEFAULT, O_RDWR, + 0600))) { + DEBUG(0, ("idmap_convert: Unable to open idmap database\n")); + return False; + } + + if (tdb_fetch_int32(idmap_tdb, "IDMAP_VERSION") == IDMAP_VERSION) { + /* nothing to convert return */ + tdb_close(idmap_tdb); + return True; + } + + /* backup_tdb expects the tdb not to be open */ + tdb_close(idmap_tdb); + + DEBUG(0, ("Upgrading winbindd_idmap.tdb from an old version\n")); + + pstrcpy(backup_name, idmap_name); + pstrcat(backup_name, ".bak"); + + if (backup_tdb(idmap_name, backup_name) != 0) { + DEBUG(0, ("Could not backup idmap database\n")); + return False; + } + + return idmap_convert(idmap_name); +} diff --git a/source3/nsswitch/winbindd_wins.c b/source3/nsswitch/winbindd_wins.c index a1d38ed69a..66903e250d 100644 --- a/source3/nsswitch/winbindd_wins.c +++ b/source3/nsswitch/winbindd_wins.c @@ -86,14 +86,26 @@ static struct node_status *lookup_byaddr_backend(char *addr, int *count) static struct in_addr *lookup_byname_backend(const char *name, int *count) { int fd; - struct in_addr *ret = NULL; - int j, flags = 0; + struct ip_service *ret = NULL; + struct in_addr *return_ip; + int j, i, flags = 0; *count = 0; /* always try with wins first */ if (resolve_wins(name,0x20,&ret,count)) { - return ret; + if ( count == 0 ) + return NULL; + if ( (return_ip = (struct in_addr *)malloc((*count)*sizeof(struct in_addr))) == NULL ) { + free( ret ); + return NULL; + } + + /* copy the IP addresses */ + for ( i=0; i<(*count); i++ ) + return_ip[i] = ret[i].ip; + + return return_ip; } fd = wins_lookup_open_socket_in(); @@ -106,12 +118,12 @@ static struct in_addr *lookup_byname_backend(const char *name, int *count) j >= 0; j--) { struct in_addr *bcast = iface_n_bcast(j); - ret = name_query(fd,name,0x20,True,True,*bcast,count, &flags, NULL); - if (ret) break; + return_ip = name_query(fd,name,0x20,True,True,*bcast,count, &flags, NULL); + if (return_ip) break; } close(fd); - return ret; + return return_ip; } /* Get hostname from IP */ diff --git a/source3/nsswitch/wins.c b/source3/nsswitch/wins.c index 9bb2d6755c..62493ef0a9 100644 --- a/source3/nsswitch/wins.c +++ b/source3/nsswitch/wins.c @@ -112,8 +112,8 @@ static struct node_status *lookup_byaddr_backend(char *addr, int *count) static struct in_addr *lookup_byname_backend(const char *name, int *count) { int fd = -1; - struct in_addr *ret = NULL; - struct in_addr p; + struct ip_service *address = NULL; + struct in_addr *ret; int j, flags = 0; if (!initialised) { @@ -123,7 +123,13 @@ static struct in_addr *lookup_byname_backend(const char *name, int *count) *count = 0; /* always try with wins first */ - if (resolve_wins(name,0x20,&ret,count)) { + if (resolve_wins(name,0x20,&address,count)) { + if ( (ret = (struct in_addr *)malloc(sizeof(struct in_addr))) == NULL ) { + free( address ); + return NULL; + } + *ret = address[0].ip; + free( address ); return ret; } @@ -139,7 +145,6 @@ static struct in_addr *lookup_byname_backend(const char *name, int *count) if (ret) break; } -out: close(fd); return ret; } diff --git a/source3/pam_smbpass/pam_smb_passwd.c b/source3/pam_smbpass/pam_smb_passwd.c index 78b89c60b7..bef587a916 100644 --- a/source3/pam_smbpass/pam_smb_passwd.c +++ b/source3/pam_smbpass/pam_smb_passwd.c @@ -298,7 +298,7 @@ int pam_sm_chauthtok(pam_handle_t *pamh, int flags, uid_t uid; /* password updated */ - if (NT_STATUS_IS_ERR(sid_to_uid(pdb_get_user_sid(sampass), &uid))) { + if (!NT_STATUS_IS_OK(sid_to_uid(pdb_get_user_sid(sampass), &uid))) { _log_err( LOG_NOTICE, "Unable to get uid for user %s", pdb_get_username(sampass)); _log_err( LOG_NOTICE, "password for (%s) changed by (%s/%d)", diff --git a/source3/pam_smbpass/support.c b/source3/pam_smbpass/support.c index 62cc866fae..8a0432c855 100644 --- a/source3/pam_smbpass/support.c +++ b/source3/pam_smbpass/support.c @@ -399,7 +399,7 @@ int _smb_verify_password( pam_handle_t * pamh, SAM_ACCOUNT *sampass, service ? service : "**unknown**", name); new->count = 1; } - if (NT_STATUS_IS_ERR(sid_to_uid(pdb_get_user_sid(sampass), &(new->id)))) { + if (!NT_STATUS_IS_OK(sid_to_uid(pdb_get_user_sid(sampass), &(new->id)))) { _log_err(LOG_NOTICE, "failed auth request by %s for service %s as %s", uidtoname(getuid()), diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index 3925a569ca..dd429fa688 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -109,6 +109,8 @@ typedef struct char *szRootdir; char *szDefaultService; char *szDfree; + char *szGetQuota; + char *szSetQuota; char *szMsgCommand; char *szHostsEquiv; char *szServerString; @@ -124,7 +126,6 @@ typedef struct char *szPasswordServer; char *szSocketOptions; char *szRealm; - char *szADSserver; char *szUsernameMap; char *szLogonScript; char *szLogonPath; @@ -156,23 +157,23 @@ typedef struct char *szAbortShutdownScript; char *szWINSHook; char *szWINSPartners; -#ifdef WITH_UTMP char *szUtmpDir; char *szWtmpDir; BOOL bUtmp; -#endif char *szSourceEnv; char *szIdmapUID; char *szIdmapGID; - BOOL *bIdmapOnly; - char *szNonUnixAccountRange; + BOOL bEnableRidAlgorithm; int AlgorithmicRidBase; + char *szTemplatePrimaryGroup; char *szTemplateHomedir; char *szTemplateShell; char *szWinbindSeparator; + BOOL bWinbindEnableLocalAccounts; BOOL bWinbindEnumUsers; BOOL bWinbindEnumGroups; BOOL bWinbindUseDefaultDomain; + BOOL bWinbindTrustedDomainsOnly; char *szWinbindBackend; char *szIdmapBackend; char *szAddShareCommand; @@ -212,7 +213,6 @@ typedef struct int announce_as; /* This is initialised in init_globals */ int machine_password_timeout; int change_notify_timeout; - int stat_cache_size; int map_to_guest; int min_passwd_length; int oplock_break_wait_time; @@ -221,6 +221,8 @@ typedef struct int iLockSpinTime; char *szLdapMachineSuffix; char *szLdapUserSuffix; + char *szLdapIdmapSuffix; + char *szLdapGroupSuffix; #ifdef WITH_LDAP_SAMCONFIG int ldap_port; char *szLdapServer; @@ -274,6 +276,7 @@ typedef struct BOOL bUseSpnego; BOOL bClientLanManAuth; BOOL bClientNTLMv2Auth; + BOOL bClientPlaintextAuth; BOOL bClientUseSpnego; BOOL bDebugHiresTimestamp; BOOL bDebugPid; @@ -288,7 +291,7 @@ typedef struct BOOL bKernelChangeNotify; int restrict_anonymous; int name_cache_timeout; - BOOL client_signing; + int client_signing; param_opt_struct *param_opt; } global; @@ -339,9 +342,7 @@ typedef struct char **printer_admin; char *volume; char *fstype; - char *szVfsObjectFile; - char *szVfsOptions; - char *szVfsPath; + char **szVfsObjects; char *szMSDfsProxy; int iMinPrintSpace; int iMaxPrintJobs; @@ -412,6 +413,7 @@ typedef struct BOOL bNTAclSupport; BOOL bUseSendfile; BOOL bProfileAcls; + BOOL bMap_acl_inherit; param_opt_struct *param_opt; char dummy[3]; /* for alignment */ @@ -460,9 +462,7 @@ static service sDefault = { NULL, /* printer admin */ NULL, /* volume */ NULL, /* fstype */ - NULL, /* vfs object */ - NULL, /* vfs options */ - NULL, /* vfs path */ + NULL, /* vfs objects */ NULL, /* szMSDfsProxy */ 0, /* iMinPrintSpace */ 1000, /* iMaxPrintJobs */ @@ -533,6 +533,7 @@ static service sDefault = { True, /* bNTAclSupport */ False, /* bUseSendfile */ False, /* bProfileAcls */ + False, /* bMap_acl_inherit */ NULL, /* Parametric options */ @@ -562,14 +563,14 @@ static BOOL handle_workgroup( const char *pszParmValue, char **ptr ); static BOOL handle_netbios_aliases( const char *pszParmValue, char **ptr ); static BOOL handle_netbios_scope( const char *pszParmValue, char **ptr ); -static BOOL handle_ldap_machine_suffix ( const char *pszParmValue, char **ptr ); -static BOOL handle_ldap_user_suffix ( const char *pszParmValue, char **ptr ); static BOOL handle_ldap_suffix ( const char *pszParmValue, char **ptr ); +static BOOL handle_ldap_sub_suffix ( const char *pszParmValue, char **ptr ); static BOOL handle_acl_compatibility(const char *pszParmValue, char **ptr); static void set_server_role(void); static void set_default_server_announce_type(void); +static void set_allowed_client_auth(void); static const struct enum_list enum_protocol[] = { {PROTOCOL_NT1, "NT1"}, @@ -627,18 +628,16 @@ static const struct enum_list enum_ldap_ssl[] = { }; static const 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_ON, "Yes"}, + {LDAP_PASSWD_SYNC_ON, "yes"}, + {LDAP_PASSWD_SYNC_ON, "on"}, + {LDAP_PASSWD_SYNC_ON, "On"}, {LDAP_PASSWD_SYNC_ONLY, "Only"}, {LDAP_PASSWD_SYNC_ONLY, "only"}, -#endif /* LDAP_EXOP_X_MODIFY_PASSWD */ {-1, NULL} }; @@ -688,6 +687,25 @@ static const struct enum_list enum_csc_policy[] = { {-1, NULL} }; +/* SMB signing types. */ +static const struct enum_list enum_smb_signing_vals[] = { + {False, "No"}, + {False, "False"}, + {False, "0"}, + {False, "Off"}, + {True, "Yes"}, + {True, "True"}, + {True, "1"}, + {True, "On"}, + {Required, "Required"}, + {Required, "Mandatory"}, + {Required, "Force"}, + {Required, "Forced"}, + {Required, "Enforced"}, + {-1, NULL} +}; + + /* Do you want session setups at user level security with a invalid password to be rejected or allowed in as guest? WinNT rejects them @@ -737,7 +755,6 @@ static struct parm_struct parm_table[] = { {"directory", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, FLAG_HIDE}, {"workgroup", P_USTRING, P_GLOBAL, &Globals.szWorkgroup, handle_workgroup, 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_USTRING, P_GLOBAL, &Globals.szNetbiosName, handle_netbios_name, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER}, {"netbios aliases", P_LIST, P_GLOBAL, &Globals.szNetbiosAliases, handle_netbios_aliases, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER}, {"netbios scope", P_USTRING, P_GLOBAL, &Globals.szNetbiosScope, handle_netbios_scope, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, @@ -751,8 +768,8 @@ static struct parm_struct parm_table[] = { {"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}, - {"client schannel", P_ENUM, P_GLOBAL, &Globals.clientSchannel, NULL, enum_bool_auto, FLAG_BASIC}, - {"server schannel", P_ENUM, P_GLOBAL, &Globals.serverSchannel, NULL, enum_bool_auto, FLAG_BASIC}, + {"client schannel", P_ENUM, P_GLOBAL, &Globals.clientSchannel, NULL, enum_bool_auto, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER}, + {"server schannel", P_ENUM, P_GLOBAL, &Globals.serverSchannel, NULL, enum_bool_auto, 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}, @@ -763,7 +780,7 @@ static struct parm_struct parm_table[] = { {"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}, + {"passdb backend", P_LIST, P_GLOBAL, &Globals.szPassdbBackend, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER}, {"algorithmic rid base", P_INTEGER, P_GLOBAL, &Globals.AlgorithmicRidBase, 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}, @@ -783,6 +800,7 @@ static struct parm_struct parm_table[] = { {"ntlm auth", P_BOOL, P_GLOBAL, &Globals.bNTLMAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, {"client NTLMv2 auth", P_BOOL, P_GLOBAL, &Globals.bClientNTLMv2Auth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, {"client lanman auth", P_BOOL, P_GLOBAL, &Globals.bClientLanManAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, + {"client plaintext auth", P_BOOL, P_GLOBAL, &Globals.bClientPlaintextAuth, 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, FLAG_HIDE}, @@ -804,12 +822,12 @@ static struct parm_struct parm_table[] = { {"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 | FLAG_SHARE}, + {"create mode", P_OCTAL, P_LOCAL, &sDefault.iCreate_mask, NULL, NULL, FLAG_GLOBAL}, {"force create mode", P_OCTAL, P_LOCAL, &sDefault.iCreate_force_mode, NULL, NULL, FLAG_GLOBAL | FLAG_SHARE}, {"security mask", P_OCTAL, P_LOCAL, &sDefault.iSecurity_mask, NULL, NULL, FLAG_GLOBAL | FLAG_SHARE}, {"force security mode", P_OCTAL, P_LOCAL, &sDefault.iSecurity_force_mode, NULL, NULL, FLAG_GLOBAL | FLAG_SHARE}, {"directory mask", P_OCTAL, P_LOCAL, &sDefault.iDir_mask, NULL, NULL, FLAG_GLOBAL | FLAG_SHARE}, - {"directory mode", P_OCTAL, P_LOCAL, &sDefault.iDir_mask, NULL, NULL, FLAG_GLOBAL | FLAG_SHARE}, + {"directory mode", P_OCTAL, P_LOCAL, &sDefault.iDir_mask, NULL, NULL, FLAG_GLOBAL}, {"force directory mode", P_OCTAL, P_LOCAL, &sDefault.iDir_force_mode, NULL, NULL, FLAG_GLOBAL | FLAG_SHARE}, {"directory security mask", P_OCTAL, P_LOCAL, &sDefault.iDir_Security_mask, NULL, NULL, FLAG_GLOBAL | FLAG_SHARE}, {"force directory security mode", P_OCTAL, P_LOCAL, &sDefault.iDir_Security_force_mode, NULL, NULL, FLAG_GLOBAL | FLAG_SHARE}, @@ -856,14 +874,15 @@ static struct parm_struct parm_table[] = { {"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}, - {"acl compatibility", P_STRING, P_GLOBAL, &Globals.szAclCompat, handle_acl_compatibility, NULL, FLAG_SHARE | FLAG_GLOBAL | FLAG_ADVANCED}, - {"nt acl support", P_BOOL, P_LOCAL, &sDefault.bNTAclSupport, NULL, NULL, FLAG_GLOBAL | FLAG_SHARE | FLAG_ADVANCED | FLAG_WIZARD}, + {"acl compatibility", P_STRING, P_GLOBAL, &Globals.szAclCompat, handle_acl_compatibility, NULL, FLAG_SHARE | FLAG_GLOBAL | FLAG_ADVANCED | FLAG_DEVELOPER}, + {"nt acl support", P_BOOL, P_LOCAL, &sDefault.bNTAclSupport, NULL, NULL, FLAG_GLOBAL | FLAG_SHARE | FLAG_ADVANCED | FLAG_DEVELOPER}, {"nt pipe support", P_BOOL, P_GLOBAL, &Globals.bNTPipeSupport, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, {"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}, + {"profile acls", P_BOOL, P_LOCAL, &sDefault.bProfileAcls, NULL, NULL, FLAG_GLOBAL | FLAG_SHARE | FLAG_ADVANCED}, {"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}, + {"map acl inherit", P_BOOL, P_LOCAL, &sDefault.bMap_acl_inherit, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL}, {"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}, @@ -874,7 +893,7 @@ static struct parm_struct parm_table[] = { {"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}, - {"client signing", P_BOOL, P_GLOBAL, &Globals.client_signing, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, + {"client signing", P_ENUM, P_GLOBAL, &Globals.client_signing, NULL, enum_smb_signing_vals, FLAG_ADVANCED | FLAG_DEVELOPER}, {"client use spnego", P_BOOL, P_GLOBAL, &Globals.bClientUseSpnego, NULL, NULL, FLAG_DEVELOPER}, {"Tuning Options", P_SEP, P_SEPARATOR}, @@ -896,7 +915,6 @@ static struct parm_struct parm_table[] = { {"read size", P_INTEGER, P_GLOBAL, &Globals.ReadSize, NULL, NULL, FLAG_DEVELOPER}, {"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}, @@ -1003,6 +1021,7 @@ static struct parm_struct parm_table[] = { {"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, FLAG_ADVANCED | FLAG_DEVELOPER}, {"wins proxy", P_BOOL, P_GLOBAL, &Globals.bWINSproxy, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, @@ -1027,7 +1046,7 @@ static struct parm_struct parm_table[] = { {"oplock contention limit", P_INTEGER, P_LOCAL, &sDefault.iOplockContentionLimit, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL}, {"posix locking", P_BOOL, P_LOCAL, &sDefault.bPosixLocking, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL}, {"strict locking", P_BOOL, P_LOCAL, &sDefault.bStrictLocking, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL}, - {"share modes", P_BOOL, P_LOCAL, &sDefault.bShareModes, NULL, NULL, FLAG_SHARE|FLAG_GLOBAL}, + {"share modes", P_BOOL, P_LOCAL, &sDefault.bShareModes, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL}, {"Ldap Options", P_SEP, P_SEPARATOR}, @@ -1036,8 +1055,10 @@ static struct parm_struct parm_table[] = { {"ldap port", P_INTEGER, P_GLOBAL, &Globals.ldap_port, NULL, NULL, 0}, #endif {"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 machine suffix", P_STRING, P_GLOBAL, &Globals.szLdapMachineSuffix, handle_ldap_sub_suffix, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, + {"ldap user suffix", P_STRING, P_GLOBAL, &Globals.szLdapUserSuffix, handle_ldap_sub_suffix, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, + {"ldap group suffix", P_STRING, P_GLOBAL, &Globals.szLdapGroupSuffix, handle_ldap_sub_suffix, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, + {"ldap idmap suffix", P_STRING, P_GLOBAL, &Globals.szLdapIdmapSuffix, handle_ldap_sub_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}, @@ -1066,6 +1087,8 @@ static struct parm_struct parm_table[] = { {"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}, + {"get quota command", P_STRING, P_GLOBAL, &Globals.szGetQuota, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, + {"set quota command", P_STRING, P_GLOBAL, &Globals.szSetQuota, 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}, @@ -1104,10 +1127,9 @@ static struct parm_struct parm_table[] = { {"hide local users", P_BOOL, P_GLOBAL, &Globals.bHideLocalUsers, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, {"VFS module options", P_SEP, P_SEPARATOR}, - - {"vfs object", P_LIST, P_LOCAL, &sDefault.szVfsObjectFile, NULL, NULL, FLAG_SHARE}, - {"vfs options", P_STRING, P_LOCAL, &sDefault.szVfsOptions, NULL, NULL, FLAG_SHARE}, - {"vfs path", P_STRING, P_LOCAL, &sDefault.szVfsPath, NULL, NULL, FLAG_SHARE}, + + {"vfs objects", P_LIST, P_LOCAL, &sDefault.szVfsObjects, NULL, NULL, FLAG_SHARE}, + {"vfs object", P_LIST, P_LOCAL, &sDefault.szVfsObjects, NULL, NULL, FLAG_SHARE | FLAG_HIDE}, {"msdfs root", P_BOOL, P_LOCAL, &sDefault.bMSDfsRoot, NULL, NULL, FLAG_SHARE}, @@ -1116,19 +1138,22 @@ static struct parm_struct parm_table[] = { {"Winbind options", P_SEP, P_SEPARATOR}, - {"idmap only", P_BOOL, P_GLOBAL, &Globals.bIdmapOnly, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, + {"enable rid algorithm", P_BOOL, P_GLOBAL, &Globals.bEnableRidAlgorithm, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER | FLAG_DEPRECATED}, {"idmap backend", P_STRING, P_GLOBAL, &Globals.szIdmapBackend, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, {"idmap uid", P_STRING, P_GLOBAL, &Globals.szIdmapUID, handle_idmap_uid, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, - {"winbind uid", P_STRING, P_GLOBAL, &Globals.szIdmapUID, handle_idmap_uid, NULL, FLAG_ADVANCED | FLAG_DEVELOPER | FLAG_HIDE}, + {"winbind uid", P_STRING, P_GLOBAL, &Globals.szIdmapUID, handle_idmap_uid, NULL, FLAG_ADVANCED | FLAG_DEVELOPER }, {"idmap gid", P_STRING, P_GLOBAL, &Globals.szIdmapGID, handle_idmap_gid, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, - {"winbind gid", P_STRING, P_GLOBAL, &Globals.szIdmapGID, handle_idmap_gid, NULL, FLAG_ADVANCED | FLAG_DEVELOPER | FLAG_HIDE}, + {"winbind gid", P_STRING, P_GLOBAL, &Globals.szIdmapGID, handle_idmap_gid, NULL, FLAG_ADVANCED | FLAG_DEVELOPER }, + {"template primary group", P_STRING, P_GLOBAL, &Globals.szTemplatePrimaryGroup, NULL, 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 enable local accounts", P_BOOL, P_GLOBAL, &Globals.bWinbindEnableLocalAccounts, 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}, + {"winbind trusted domains only", P_BOOL, P_GLOBAL, &Globals.bWinbindTrustedDomainsOnly, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, {NULL, P_BOOL, P_NONE, NULL, NULL, NULL, 0} }; @@ -1278,8 +1303,13 @@ static void init_globals(void) /* using UTF8 by default allows us to support all chars */ string_set(&Globals.unix_charset, "UTF8"); - /* using UTF8 by default allows us to support all chars */ +#if defined(HAVE_NL_LANGINFO) && defined(CODESET) + /* If the system supports nl_langinfo(), try to grab the value + from the user's locale */ + string_set(&Globals.display_charset, "LOCALE"); +#else string_set(&Globals.display_charset, "ASCII"); +#endif /* Use codepage 850 as a default for the dos character set */ string_set(&Globals.dos_charset, "CP850"); @@ -1341,8 +1371,8 @@ static void init_globals(void) Globals.paranoid_server_security = True; Globals.bEncryptPasswords = True; Globals.bUpdateEncrypt = False; - Globals.clientSchannel = False; - Globals.serverSchannel = False; + Globals.clientSchannel = Auto; + Globals.serverSchannel = Auto; Globals.bReadRaw = True; Globals.bWriteRaw = True; Globals.bReadPrediction = False; @@ -1366,7 +1396,6 @@ static void init_globals(void) Globals.ReadSize = 16 * 1024; Globals.lm_announce = 2; /* = Auto: send only if LM clients found */ Globals.lm_interval = 60; - Globals.stat_cache_size = 50; /* Number of stat translations we'll keep */ Globals.announce_as = ANNOUNCE_AS_NT_SERVER; #if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT)) Globals.bNISHomeMap = False; @@ -1387,6 +1416,7 @@ static void init_globals(void) Globals.bStatCache = True; /* use stat cache by default */ Globals.restrict_anonymous = 0; Globals.bClientLanManAuth = True; /* Do use the LanMan hash if it is available */ + Globals.bClientPlaintextAuth = True; /* Do use a plaintext password if is requested by the server */ Globals.bLanmanAuth = True; /* Do use the LanMan hash if it is available */ Globals.bNTLMAuth = True; /* Do use NTLMv1 if it is available (otherwise NTLMv2) */ @@ -1410,15 +1440,17 @@ static void init_globals(void) #ifdef WITH_LDAP_SAMCONFIG string_set(&Globals.szLdapServer, "localhost"); Globals.ldap_port = 636; - Globals.szPassdbBackend = str_list_make("ldapsam guest", NULL); + Globals.szPassdbBackend = str_list_make("ldapsam_compat", NULL); #else - Globals.szPassdbBackend = str_list_make("smbpasswd guest", NULL); + Globals.szPassdbBackend = str_list_make("smbpasswd", NULL); #endif /* WITH_LDAP_SAMCONFIG */ string_set(&Globals.szLdapSuffix, ""); string_set(&Globals.szLdapFilter, "(uid=%u)"); string_set(&Globals.szLdapMachineSuffix, ""); string_set(&Globals.szLdapUserSuffix, ""); + string_set(&Globals.szLdapGroupSuffix, ""); + string_set(&Globals.szLdapIdmapSuffix, ""); string_set(&Globals.szLdapAdminDn, ""); Globals.ldap_ssl = LDAP_SSL_ON; @@ -1456,15 +1488,18 @@ static void init_globals(void) string_set(&Globals.szTemplateShell, "/bin/false"); string_set(&Globals.szTemplateHomedir, "/home/%D/%U"); + string_set(&Globals.szTemplatePrimaryGroup, "nobody"); string_set(&Globals.szWinbindSeparator, "\\"); string_set(&Globals.szAclCompat, ""); - Globals.winbind_cache_time = 600; /* 5 minutes */ + Globals.winbind_cache_time = 300; /* 5 minutes */ + Globals.bWinbindEnableLocalAccounts = True; Globals.bWinbindEnumUsers = True; Globals.bWinbindEnumGroups = True; Globals.bWinbindUseDefaultDomain = False; + Globals.bWinbindTrustedDomainsOnly = False; - Globals.bIdmapOnly = False; + Globals.bEnableRidAlgorithm = True; Globals.name_cache_timeout = 660; /* In seconds */ @@ -1496,8 +1531,7 @@ void lp_talloc_free(void) static char *lp_string(const char *s) { - size_t len = s ? strlen(s) : 0; - char *ret; + char *ret, *tmpstr; /* The follow debug is useful for tracking down memory problems especially if you have an inner loop that is calling a lp_*() @@ -1511,25 +1545,16 @@ static char *lp_string(const char *s) if (!lp_talloc) lp_talloc = talloc_init("lp_talloc"); - ret = (char *)talloc(lp_talloc, len + 100); /* leave room for substitution */ - - if (!ret) - return NULL; - - /* Note: StrnCpy touches len+1 bytes, but we allocate 100 - * extra bytes so we're OK. */ - - if (!s) - *ret = 0; - else - StrnCpy(ret, s, len); - - if (trim_string(ret, "\"", "\"")) { - if (strchr(ret,'"') != NULL) - StrnCpy(ret, s, len); + tmpstr = alloc_sub_basic(current_user_info.smb_name, s); + if (trim_string(tmpstr, "\"", "\"")) { + if (strchr(tmpstr,'"') != NULL) { + SAFE_FREE(tmpstr); + tmpstr = alloc_sub_basic(current_user_info.smb_name,s); + } } - - standard_sub_basic(current_user_info.smb_name,ret,len+100); + ret = talloc_strdup(lp_talloc, tmpstr); + SAFE_FREE(tmpstr); + return (ret); } @@ -1582,16 +1607,16 @@ FN_GLOBAL_STRING(lp_lockdir, &Globals.szLockDir) FN_GLOBAL_STRING(lp_piddir, &Globals.szPidDir) FN_GLOBAL_STRING(lp_mangling_method, &Globals.szManglingMethod) FN_GLOBAL_INTEGER(lp_mangle_prefix, &Globals.mangle_prefix) -#ifdef WITH_UTMP FN_GLOBAL_STRING(lp_utmpdir, &Globals.szUtmpDir) FN_GLOBAL_STRING(lp_wtmpdir, &Globals.szWtmpDir) FN_GLOBAL_BOOL(lp_utmp, &Globals.bUtmp) -#endif FN_GLOBAL_STRING(lp_rootdir, &Globals.szRootdir) FN_GLOBAL_STRING(lp_source_environment, &Globals.szSourceEnv) FN_GLOBAL_STRING(lp_defaultservice, &Globals.szDefaultService) FN_GLOBAL_STRING(lp_msg_command, &Globals.szMsgCommand) FN_GLOBAL_STRING(lp_dfree_command, &Globals.szDfree) +FN_GLOBAL_STRING(lp_get_quota_command, &Globals.szGetQuota) +FN_GLOBAL_STRING(lp_set_quota_command, &Globals.szSetQuota) FN_GLOBAL_STRING(lp_hosts_equiv, &Globals.szHostsEquiv) FN_GLOBAL_STRING(lp_auto_services, &Globals.szAutoServices) FN_GLOBAL_STRING(lp_passwd_program, &Globals.szPasswdProgram) @@ -1599,7 +1624,6 @@ FN_GLOBAL_STRING(lp_passwd_chat, &Globals.szPasswdChat) FN_GLOBAL_STRING(lp_passwordserver, &Globals.szPasswordServer) FN_GLOBAL_STRING(lp_name_resolve_order, &Globals.szNameResolveOrder) FN_GLOBAL_STRING(lp_realm, &Globals.szRealm) -FN_GLOBAL_STRING(lp_ads_server, &Globals.szADSserver) FN_GLOBAL_STRING(lp_username_map, &Globals.szUsernameMap) FN_GLOBAL_CONST_STRING(lp_logon_script, &Globals.szLogonScript) FN_GLOBAL_CONST_STRING(lp_logon_path, &Globals.szLogonPath) @@ -1633,16 +1657,19 @@ FN_GLOBAL_STRING(lp_abort_shutdown_script, &Globals.szAbortShutdownScript) FN_GLOBAL_STRING(lp_wins_hook, &Globals.szWINSHook) FN_GLOBAL_STRING(lp_wins_partners, &Globals.szWINSPartners) +FN_GLOBAL_STRING(lp_template_primary_group, &Globals.szTemplatePrimaryGroup) FN_GLOBAL_STRING(lp_template_homedir, &Globals.szTemplateHomedir) FN_GLOBAL_STRING(lp_template_shell, &Globals.szTemplateShell) FN_GLOBAL_CONST_STRING(lp_winbind_separator, &Globals.szWinbindSeparator) FN_GLOBAL_STRING(lp_acl_compatibility, &Globals.szAclCompat) +FN_GLOBAL_BOOL(lp_winbind_enable_local_accounts, &Globals.bWinbindEnableLocalAccounts) FN_GLOBAL_BOOL(lp_winbind_enum_users, &Globals.bWinbindEnumUsers) FN_GLOBAL_BOOL(lp_winbind_enum_groups, &Globals.bWinbindEnumGroups) FN_GLOBAL_BOOL(lp_winbind_use_default_domain, &Globals.bWinbindUseDefaultDomain) +FN_GLOBAL_BOOL(lp_winbind_trusted_domains_only, &Globals.bWinbindTrustedDomainsOnly) FN_GLOBAL_STRING(lp_idmap_backend, &Globals.szIdmapBackend) -FN_GLOBAL_BOOL(lp_idmap_only, &Globals.bIdmapOnly) +FN_GLOBAL_BOOL(lp_enable_rid_algorithm, &Globals.bEnableRidAlgorithm) #ifdef WITH_LDAP_SAMCONFIG FN_GLOBAL_STRING(lp_ldap_server, &Globals.szLdapServer) @@ -1651,6 +1678,8 @@ FN_GLOBAL_INTEGER(lp_ldap_port, &Globals.ldap_port) FN_GLOBAL_STRING(lp_ldap_suffix, &Globals.szLdapSuffix) FN_GLOBAL_STRING(lp_ldap_machine_suffix, &Globals.szLdapMachineSuffix) FN_GLOBAL_STRING(lp_ldap_user_suffix, &Globals.szLdapUserSuffix) +FN_GLOBAL_STRING(lp_ldap_idmap_suffix, &Globals.szLdapIdmapSuffix) +FN_GLOBAL_STRING(lp_ldap_group_suffix, &Globals.szLdapGroupSuffix) 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) @@ -1702,6 +1731,7 @@ FN_GLOBAL_BOOL(lp_allow_trusted_domains, &Globals.bAllowTrustedDomains) FN_GLOBAL_INTEGER(lp_restrict_anonymous, &Globals.restrict_anonymous) FN_GLOBAL_BOOL(lp_lanman_auth, &Globals.bLanmanAuth) FN_GLOBAL_BOOL(lp_ntlm_auth, &Globals.bNTLMAuth) +FN_GLOBAL_BOOL(lp_client_plaintext_auth, &Globals.bClientPlaintextAuth) FN_GLOBAL_BOOL(lp_client_lanman_auth, &Globals.bClientLanManAuth) FN_GLOBAL_BOOL(lp_client_ntlmv2_auth, &Globals.bClientNTLMv2Auth) FN_GLOBAL_BOOL(lp_host_msdfs, &Globals.bHostMSDfs) @@ -1740,7 +1770,6 @@ FN_GLOBAL_INTEGER(lp_lm_announce, &Globals.lm_announce) FN_GLOBAL_INTEGER(lp_lm_interval, &Globals.lm_interval) FN_GLOBAL_INTEGER(lp_machine_password_timeout, &Globals.machine_password_timeout) FN_GLOBAL_INTEGER(lp_change_notify_timeout, &Globals.change_notify_timeout) -FN_GLOBAL_INTEGER(lp_stat_cache_size, &Globals.stat_cache_size) FN_GLOBAL_INTEGER(lp_map_to_guest, &Globals.map_to_guest) FN_GLOBAL_INTEGER(lp_min_passwd_length, &Globals.min_passwd_length) FN_GLOBAL_INTEGER(lp_oplock_break_wait_time, &Globals.oplock_break_wait_time) @@ -1777,9 +1806,7 @@ FN_LOCAL_LIST(lp_readlist, readlist) FN_LOCAL_LIST(lp_writelist, writelist) FN_LOCAL_LIST(lp_printer_admin, printer_admin) FN_LOCAL_STRING(lp_fstype, fstype) -FN_LOCAL_LIST(lp_vfsobj, szVfsObjectFile) -FN_LOCAL_STRING(lp_vfs_options, szVfsOptions) -FN_LOCAL_STRING(lp_vfs_path, szVfsPath) +FN_LOCAL_LIST(lp_vfs_objects, szVfsObjects) FN_LOCAL_STRING(lp_msdfs_proxy, szMSDfsProxy) static FN_LOCAL_STRING(lp_volume, volume) FN_LOCAL_STRING(lp_mangled_map, szMangledMap) @@ -1835,6 +1862,7 @@ FN_LOCAL_BOOL(lp_default_devmode, bDefaultDevmode) FN_LOCAL_BOOL(lp_nt_acl_support, bNTAclSupport) FN_LOCAL_BOOL(lp_use_sendfile, bUseSendfile) FN_LOCAL_BOOL(lp_profile_acls, bProfileAcls) +FN_LOCAL_BOOL(lp_map_acl_inherit, bMap_acl_inherit) 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) @@ -2259,6 +2287,7 @@ BOOL lp_add_home(const char *pszHomename, int iDefaultService, } else { pstrcpy(newHomedir, lp_pathname(iDefaultService)); string_sub(newHomedir,"%H", pszHomedir, sizeof(newHomedir)); + string_sub(newHomedir,"%S", pszHomename, sizeof(newHomedir)); } string_set(&ServicePtrs[i]->szPath, newHomedir); @@ -2475,7 +2504,7 @@ static void copy_service(service * pserviceDest, service * pserviceSource, BOOL case P_USTRING: string_set(dest_ptr, *(char **)src_ptr); - strupper(*(char **)dest_ptr); + strupper_m(*(char **)dest_ptr); break; case P_LIST: str_list_copy((char ***)dest_ptr, *(const char ***)src_ptr); @@ -2942,91 +2971,61 @@ static BOOL handle_debug_list( const char *pszParmValueIn, char **ptr ) } /*************************************************************************** - Handle the ldap machine suffix option. + Handle setting ldap suffix and determines whether ldap machine suffix needs + to be set as well. + + Set all of the sub suffix strings to be the 'ldap suffix' by default ***************************************************************************/ -static BOOL handle_ldap_machine_suffix( const char *pszParmValue, char **ptr) +static BOOL handle_ldap_suffix( const char *pszParmValue, char **ptr ) { - pstring suffix; - - pstrcpy(suffix, pszParmValue); - - if (! *Globals.szLdapSuffix ) { - string_set( ptr, suffix ); - return True; - } - - if (! strstr(suffix, Globals.szLdapSuffix) ) { - if ( *pszParmValue ) - pstrcat(suffix, ","); - pstrcat(suffix, Globals.szLdapSuffix); - } - string_set( ptr, suffix ); - return True; + pstring suffix; + + pstrcpy(suffix, pszParmValue); + + /* set defaults for the the sub-suffixes */ + + if (! *Globals.szLdapMachineSuffix ) + string_set(&Globals.szLdapMachineSuffix, suffix); + if (! *Globals.szLdapUserSuffix ) + string_set(&Globals.szLdapUserSuffix, suffix); + if (! *Globals.szLdapGroupSuffix ) + string_set(&Globals.szLdapGroupSuffix, suffix); + if (! *Globals.szLdapIdmapSuffix ) + string_set(&Globals.szLdapIdmapSuffix, suffix); + + string_set(ptr, suffix); + return True; } /*************************************************************************** - Handle the ldap user suffix option. + Handle the ldap sub suffix option. + Always append the 'ldap suffix' if it is set ***************************************************************************/ -static BOOL handle_ldap_user_suffix( const char *pszParmValue, char **ptr) +static BOOL handle_ldap_sub_suffix( const char *pszParmValue, char **ptr) { - pstring suffix; + pstring suffix; - pstrcpy(suffix, pszParmValue); + pstrcpy(suffix, pszParmValue); - if (! *Globals.szLdapSuffix ) { - string_set( ptr, suffix ); - return True; - } - - if (! strstr(suffix, Globals.szLdapSuffix) ) { - if ( *pszParmValue ) - pstrcat(suffix, ","); - pstrcat(suffix, Globals.szLdapSuffix); - } - string_set( ptr, suffix ); - return True; + if (! *Globals.szLdapSuffix ) { + string_set( ptr, suffix ); + return True; + } + else { + if ( *pszParmValue ) + pstrcat(suffix, ","); + pstrcat(suffix, Globals.szLdapSuffix); + } + + string_set( ptr, suffix ); + return True; } /*************************************************************************** - Handle setting ldap suffix and determines whether ldap machine suffix needs - to be set as well. ***************************************************************************/ -static BOOL handle_ldap_suffix( const char *pszParmValue, char **ptr) -{ - pstring suffix; - pstring user_suffix; - pstring machine_suffix; - - pstrcpy(suffix, pszParmValue); - - if (! *Globals.szLdapMachineSuffix ) - string_set(&Globals.szLdapMachineSuffix, suffix); - if (! *Globals.szLdapUserSuffix ) - string_set(&Globals.szLdapUserSuffix, suffix); - - if (! strstr(Globals.szLdapMachineSuffix, suffix)) { - pstrcpy(machine_suffix, Globals.szLdapMachineSuffix); - if ( *Globals.szLdapMachineSuffix ) - pstrcat(machine_suffix, ","); - pstrcat(machine_suffix, suffix); - string_set(&Globals.szLdapMachineSuffix, machine_suffix); - } - - if (! strstr(Globals.szLdapUserSuffix, suffix)) { - pstrcpy(user_suffix, Globals.szLdapUserSuffix); - if ( *Globals.szLdapUserSuffix ) - pstrcat(user_suffix, ","); - pstrcat(user_suffix, suffix); - string_set(&Globals.szLdapUserSuffix, user_suffix); - } - - string_set(ptr, suffix); - return True; -} - static BOOL handle_acl_compatibility(const char *pszParmValue, char **ptr) { if (strequal(pszParmValue, "auto")) @@ -3040,6 +3039,7 @@ static BOOL handle_acl_compatibility(const char *pszParmValue, char **ptr) return True; } + /*************************************************************************** Initialise a copymap. ***************************************************************************/ @@ -3201,7 +3201,7 @@ BOOL lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue case P_USTRING: string_set(parm_ptr, pszParmValue); - strupper(*(char **)parm_ptr); + strupper_m(*(char **)parm_ptr); break; case P_GSTRING: @@ -3210,7 +3210,7 @@ BOOL lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue case P_UGSTRING: pstrcpy((char *)parm_ptr, pszParmValue); - strupper((char *)parm_ptr); + strupper_m((char *)parm_ptr); break; case P_ENUM: @@ -3858,6 +3858,19 @@ static void set_server_role(void) } } +/*********************************************************** + If we should send plaintext/LANMAN passwords in the clinet +************************************************************/ +static void set_allowed_client_auth(void) +{ + if (Globals.bClientNTLMv2Auth) { + Globals.bClientLanManAuth = False; + } + if (!Globals.bClientLanManAuth) { + Globals.bClientPlaintextAuth = False; + } +} + /*************************************************************************** Load the services array from the services file. Return True on success, False on failure. @@ -3925,6 +3938,7 @@ BOOL lp_load(const char *pszFname, BOOL global_only, BOOL save_defaults, set_server_role(); set_default_server_announce_type(); + set_allowed_client_auth(); bLoaded = True; @@ -4242,7 +4256,7 @@ void lp_set_logfile(const char *name) } /******************************************************************* - Return the NetBIOS called name. + Return the NetBIOS called name, or my IP - but never global_myname(). ********************************************************************/ const char *get_called_name(void) @@ -4250,22 +4264,11 @@ const char *get_called_name(void) extern fstring local_machine; static fstring called_name; - if (! *local_machine) - return global_myname(); - - /* - * Windows NT/2k uses "*SMBSERVER" and XP uses "*SMBSERV" - * arrggg!!! but we've already rewritten the client's - * netbios name at this point... - */ - - if (*local_machine) { - if (!StrCaseCmp(local_machine, "_SMBSERVER") || !StrCaseCmp(local_machine, "_SMBSERV")) { - fstrcpy(called_name, get_my_primary_ip()); - DEBUG(8,("get_called_name: assuming that client used IP address [%s] as called name.\n", - called_name)); - return called_name; - } + if (!*local_machine) { + fstrcpy(called_name, get_my_primary_ip()); + DEBUG(8,("get_called_name: assuming that client used IP address [%s] as called name.\n", + called_name)); + return called_name; } return local_machine; diff --git a/source3/passdb/machine_sid.c b/source3/passdb/machine_sid.c index a578ecc711..4e7476781c 100644 --- a/source3/passdb/machine_sid.c +++ b/source3/passdb/machine_sid.c @@ -191,8 +191,9 @@ DOM_SID *get_global_sam_sid(void) /* memory for global_sam_sid is allocated in pdb_generate_sam_sid() as needed */ - if (!pdb_generate_sam_sid()) - global_sam_sid=NULL; + if (!pdb_generate_sam_sid()) { + smb_panic("Could not generate a machine SID\n"); + } return global_sam_sid; } diff --git a/source3/passdb/passdb.c b/source3/passdb/passdb.c index f34513b225..9a99e07d82 100644 --- a/source3/passdb/passdb.c +++ b/source3/passdb/passdb.c @@ -27,6 +27,30 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_PASSDB +/****************************************************************** + get the default domain/netbios name to be used when + testing authentication. For example, if you connect + to a Windows member server using a bogus domain name, the + Windows box will map the BOGUS\user to DOMAIN\user. A + standalone box will map to WKS\user. +******************************************************************/ + +const char *get_default_sam_name(void) +{ + /* standalone servers can only use the local netbios name */ + if ( lp_server_role() == ROLE_STANDALONE ) + return global_myname(); + + /* Windows domain members default to the DOMAIN + name when not specified */ + return lp_workgroup(); +} + +/****************************************************************** + get the default domain/netbios name to be used when dealing + with our passdb list of accounts +******************************************************************/ + const char *get_global_sam_name(void) { if ((lp_server_role() == ROLE_DOMAIN_PDC) || (lp_server_role() == ROLE_DOMAIN_BDC)) { @@ -190,7 +214,7 @@ NTSTATUS pdb_fill_sam_pw(SAM_ACCOUNT *sam_account, const struct passwd *pwd) */ ret = pdb_set_sam_sids(sam_account, pwd); - if (NT_STATUS_IS_ERR(ret)) return ret; + if (!NT_STATUS_IS_OK(ret)) return ret; /* check if this is a user account or a machine account */ if (pwd->pw_name[strlen(pwd->pw_name)-1] != '$') @@ -266,41 +290,37 @@ NTSTATUS pdb_init_sam_pw(SAM_ACCOUNT **new_sam_acct, const struct passwd *pwd) /************************************************************* Initialises a SAM_ACCOUNT ready to add a new account, based - on the unix user if possible. + on the UNIX user. Pass in a RID if you have one ************************************************************/ -NTSTATUS pdb_init_sam_new(SAM_ACCOUNT **new_sam_acct, const char *username) +NTSTATUS pdb_init_sam_new(SAM_ACCOUNT **new_sam_acct, const char *username, + uint32 rid) { - NTSTATUS nt_status = NT_STATUS_NO_MEMORY; - - struct passwd *pwd; + NTSTATUS nt_status = NT_STATUS_NO_MEMORY; + struct passwd *pwd; + BOOL ret; pwd = Get_Pwnam(username); - if (pwd) { - if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam_pw(new_sam_acct, pwd))) { - *new_sam_acct = NULL; - return nt_status; - } - } else { - DOM_SID g_sid; - if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam(new_sam_acct))) { - *new_sam_acct = NULL; - return nt_status; - } - if (!pdb_set_username(*new_sam_acct, username, PDB_SET)) { - pdb_free_sam(new_sam_acct); - return nt_status; - } - - pdb_set_domain (*new_sam_acct, get_global_sam_name(), PDB_DEFAULT); - - /* set Domain Users by default ! */ - sid_copy(&g_sid, get_global_sam_sid()); - sid_append_rid(&g_sid, DOMAIN_GROUP_RID_USERS); - pdb_set_group_sid(*new_sam_acct, &g_sid, PDB_SET); + if (!pwd) + return NT_STATUS_NO_SUCH_USER; + + if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam_pw(new_sam_acct, pwd))) { + *new_sam_acct = NULL; + return nt_status; } - return NT_STATUS_OK; + + /* see if we need to generate a new rid using the 2.2 algorithm */ + if ( rid == 0 && lp_enable_rid_algorithm() ) { + DEBUG(10,("pdb_init_sam_new: no RID specified. Generating one via old algorithm\n")); + rid = fallback_pdb_uid_to_user_rid(pwd->pw_uid); + } + + /* set the new SID */ + + ret = pdb_set_user_sid_from_rid( *new_sam_acct, rid, PDB_SET ); + + return (ret ? NT_STATUS_OK : NT_STATUS_NO_SUCH_USER); } @@ -323,6 +343,10 @@ static void pdb_free_sam_contents(SAM_ACCOUNT *user) 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)); + + if (user->private.backend_private_data && user->private.backend_private_data_free_fn) { + user->private.backend_private_data_free_fn(&user->private.backend_private_data); + } } @@ -413,7 +437,7 @@ NTSTATUS pdb_set_sam_sids(SAM_ACCOUNT *account_data, const struct passwd *pwd) } /* call the mapping code here */ - if(pdb_getgrgid(&map, pwd->pw_gid, MAPPING_WITHOUT_PRIV)) { + if(pdb_getgrgid(&map, pwd->pw_gid)) { if (!pdb_set_group_sid(account_data, &map.sid, PDB_SET)){ DEBUG(0,("Can't set Group SID!\n")); return NT_STATUS_INVALID_PARAMETER; @@ -557,7 +581,7 @@ BOOL pdb_gethexpwd(const char *p, unsigned char *pwd) return (True); } -static int algorithmic_rid_base(void) +int algorithmic_rid_base(void) { static int rid_offset = 0; @@ -706,7 +730,10 @@ BOOL local_lookup_sid(DOM_SID *sid, char *name, enum SID_NAME_USE *psid_name_use } /* see if the passdb can help us with the name of the user */ + + become_root(); if (pdb_getsampwsid(sam_account, sid)) { + unbecome_root(); fstrcpy(name, pdb_get_username(sam_account)); *psid_name_use = SID_NAME_USER; @@ -714,10 +741,10 @@ BOOL local_lookup_sid(DOM_SID *sid, char *name, enum SID_NAME_USE *psid_name_use return True; } - + unbecome_root(); pdb_free_sam(&sam_account); - if (pdb_getgrsid(&map, *sid, MAPPING_WITHOUT_PRIV)) { + if (pdb_getgrsid(&map, *sid)) { if (map.gid!=(gid_t)-1) { DEBUG(5,("local_lookup_sid: mapped group %s to gid %u\n", map.nt_name, (unsigned int)map.gid)); } else { @@ -812,13 +839,16 @@ BOOL local_lookup_name(const char *c_user, DOM_SID *psid, enum SID_NAME_USE *psi return False; } + become_root(); if (pdb_getsampwnam(sam_account, user)) { + unbecome_root(); sid_copy(psid, pdb_get_user_sid(sam_account)); *psid_name_use = SID_NAME_USER; pdb_free_sam(&sam_account); return True; } + unbecome_root(); pdb_free_sam(&sam_account); @@ -827,7 +857,7 @@ BOOL local_lookup_name(const char *c_user, DOM_SID *psid, enum SID_NAME_USE *psi */ /* check if it's a mapped group */ - if (pdb_getgrnam(&map, user, MAPPING_WITHOUT_PRIV)) { + if (pdb_getgrnam(&map, user)) { /* yes it's a mapped group */ sid_copy(&local_sid, &map.sid); *psid_name_use = map.sid_name_use; @@ -849,7 +879,7 @@ BOOL local_lookup_name(const char *c_user, DOM_SID *psid, enum SID_NAME_USE *psi * JFM, 30/11/2001 */ - if (pdb_getgrgid(&map, grp->gr_gid, MAPPING_WITHOUT_PRIV)){ + if (pdb_getgrgid(&map, grp->gr_gid)){ return False; } @@ -864,10 +894,6 @@ BOOL local_lookup_name(const char *c_user, DOM_SID *psid, enum SID_NAME_USE *psi /************************************************************* Change a password entry in the local smbpasswd file. - -It is currently being called by SWAT and by smbpasswd. - - --jerry *************************************************************/ BOOL local_password_change(const char *user_name, int local_flags, @@ -883,12 +909,15 @@ BOOL local_password_change(const char *user_name, int local_flags, /* Get the smb passwd entry for this user */ pdb_init_sam(&sam_pass); + + become_root(); if(!pdb_getsampwnam(sam_pass, user_name)) { + unbecome_root(); pdb_free_sam(&sam_pass); if ((local_flags & LOCAL_ADD_USER) || (local_flags & LOCAL_DELETE_USER)) { - /* Might not exist in /etc/passwd */ - if (!NT_STATUS_IS_OK(pdb_init_sam_new(&sam_pass, user_name))) { + /* Might not exist in /etc/passwd. Use rid algorithm here */ + if (!NT_STATUS_IS_OK(pdb_init_sam_new(&sam_pass, user_name, 0))) { slprintf(err_str, err_str_len-1, "Failed initialise SAM_ACCOUNT for user %s.\n", user_name); return False; } @@ -897,6 +926,7 @@ BOOL local_password_change(const char *user_name, int local_flags, return False; } } else { + unbecome_root(); /* the entry already existed */ local_flags &= ~LOCAL_ADD_USER; } @@ -1012,3 +1042,637 @@ BOOL local_password_change(const char *user_name, int local_flags, pdb_free_sam(&sam_pass); return True; } + +/**************************************************************************** + Convert a uid to SID - locally. +****************************************************************************/ + +DOM_SID *local_uid_to_sid(DOM_SID *psid, uid_t uid) +{ + SAM_ACCOUNT *sampw = NULL; + struct passwd *unix_pw; + BOOL ret; + + unix_pw = sys_getpwuid( uid ); + + if ( !unix_pw ) { + DEBUG(4,("local_uid_to_sid: host has know idea of uid %d\n", uid)); + return NULL; + } + + if ( !NT_STATUS_IS_OK(pdb_init_sam(&sampw)) ) { + DEBUG(0,("local_uid_to_sid: failed to allocate SAM_ACCOUNT object\n")); + return NULL; + } + + become_root(); + ret = pdb_getsampwnam( sampw, unix_pw->pw_name ); + unbecome_root(); + + if ( ret ) + sid_copy( psid, pdb_get_user_sid(sampw) ); + else { + DEBUG(4,("local_uid_to_sid: User %s [uid == %d] has no samba account\n", + unix_pw->pw_name, uid)); + + if ( !lp_enable_rid_algorithm() ) + return NULL; + + DEBUG(8,("local_uid_to_sid: falling back to RID algorithm\n")); + + sid_copy( psid, get_global_sam_sid() ); + sid_append_rid( psid, fallback_pdb_uid_to_user_rid(uid) ); + } + + + DEBUG(10,("local_uid_to_sid: uid (%d) -> SID %s (%s).\n", + (unsigned int)uid, sid_string_static(psid), unix_pw->pw_name)); + + return psid; +} + +/**************************************************************************** + Convert a SID to uid - locally. +****************************************************************************/ + +BOOL local_sid_to_uid(uid_t *puid, const DOM_SID *psid, enum SID_NAME_USE *name_type) +{ + SAM_ACCOUNT *sampw = NULL; + struct passwd *unix_pw; + const char *user_name; + + *name_type = SID_NAME_UNKNOWN; + + /* + * We can only convert to a uid if this is our local + * Domain SID (ie. we are the controling authority). + */ + if (!sid_check_is_in_our_domain(psid) ) { + DEBUG(5,("local_sid_to_uid: this SID (%s) is not from our domain\n", sid_string_static(psid))); + return False; + } + + /* lookup the user account */ + + if ( !NT_STATUS_IS_OK(pdb_init_sam(&sampw)) ) { + DEBUG(0,("local_sid_to_uid: Failed to allocate memory for SAM_ACCOUNT object\n")); + return False; + } + + become_root(); + if ( !pdb_getsampwsid(sampw, psid) ) { + unbecome_root(); + DEBUG(8,("local_sid_to_uid: Could not find SID %s in passdb\n", + sid_string_static(psid))); + return False; + } + unbecome_root(); + + user_name = pdb_get_username(sampw); + + unix_pw = sys_getpwnam( user_name ); + + if ( !unix_pw ) { + DEBUG(0,("local_sid_to_uid: %s found in passdb but getpwnam() return NULL!\n", + user_name)); + pdb_free_sam( &sampw ); + return False; + } + + *puid = unix_pw->pw_uid; + + DEBUG(10,("local_sid_to_uid: SID %s -> uid (%u) (%s).\n", sid_string_static(psid), + (unsigned int)*puid, user_name )); + + *name_type = SID_NAME_USER; + + return True; +} + +/**************************************************************************** + Convert a gid to SID - locally. +****************************************************************************/ + +DOM_SID *local_gid_to_sid(DOM_SID *psid, gid_t gid) +{ + GROUP_MAP group; + + /* we don't need to disable winbindd since the gid is stored in + the GROUP_MAP object */ + + if ( !pdb_getgrgid( &group, gid ) ) { + + /* fallback to rid mapping if enabled */ + + if ( lp_enable_rid_algorithm() ) { + sid_copy(psid, get_global_sam_sid()); + sid_append_rid(psid, pdb_gid_to_group_rid(gid)); + + DEBUG(10,("local_gid_to_sid: Fall back to algorithmic mapping: %u -> %s\n", + (unsigned int)gid, sid_string_static(psid))); + + return psid; + } + else + return NULL; + } + + sid_copy( psid, &group.sid ); + + DEBUG(10,("local_gid_to_sid: gid (%d) -> SID %s.\n", + (unsigned int)gid, sid_string_static(psid))); + + return psid; +} + +/**************************************************************************** + Convert a SID to gid - locally. +****************************************************************************/ + +BOOL local_sid_to_gid(gid_t *pgid, const DOM_SID *psid, enum SID_NAME_USE *name_type) +{ + uint32 rid; + GROUP_MAP group; + + *name_type = SID_NAME_UNKNOWN; + + /* This call can enumerate group mappings for foreign sids as well. + So don't check for a match against our domain SID */ + + /* we don't need to disable winbindd since the gid is stored in + the GROUP_MAP object */ + + if ( !pdb_getgrsid(&group, *psid) ) { + + /* fallback to rid mapping if enabled */ + + if ( lp_enable_rid_algorithm() ) { + + if (!sid_check_is_in_our_domain(psid) ) { + DEBUG(5,("local_sid_to_gid: RID algorithm only supported for our domain (%s is not)\n", sid_string_static(psid))); + return False; + } + + if (!sid_peek_rid(psid, &rid)) { + DEBUG(10,("local_sid_to_uid: invalid SID!\n")); + return False; + } + + DEBUG(10,("local_sid_to_gid: Fall back to algorithmic mapping\n")); + + if (fallback_pdb_rid_is_user(rid)) { + DEBUG(3, ("local_sid_to_gid: SID %s is *NOT* a group\n", sid_string_static(psid))); + return False; + } else { + *pgid = pdb_group_rid_to_gid(rid); + DEBUG(10,("local_sid_to_gid: mapping: %s -> %u\n", sid_string_static(psid), (unsigned int)(*pgid))); + return True; + } + } + + return False; + } + + *pgid = group.gid; + + DEBUG(10,("local_sid_to_gid: SID %s -> gid (%u)\n", sid_string_static(psid), + (unsigned int)*pgid)); + + return True; +} + +/********************************************************************** + Marshall/unmarshall SAM_ACCOUNT structs. + *********************************************************************/ + +#define TDB_FORMAT_STRING "ddddddBBBBBBBBBBBBddBBwdwdBdd" + +/********************************************************************** + Intialize a SAM_ACCOUNT struct from a BYTE buffer of size len + *********************************************************************/ + +BOOL init_sam_from_buffer(SAM_ACCOUNT *sampass, uint8 *buf, uint32 buflen) +{ + + /* times are stored as 32bit integer + take care on system with 64bit wide time_t + --SSS */ + uint32 logon_time, + logoff_time, + kickoff_time, + pass_last_set_time, + pass_can_change_time, + pass_must_change_time; + char *username; + char *domain; + char *nt_username; + char *dir_drive; + char *unknown_str; + char *munged_dial; + char *fullname; + char *homedir; + char *logon_script; + char *profile_path; + char *acct_desc; + char *workstations; + uint32 username_len, domain_len, nt_username_len, + dir_drive_len, unknown_str_len, munged_dial_len, + fullname_len, homedir_len, logon_script_len, + profile_path_len, acct_desc_len, workstations_len; + + uint32 user_rid, group_rid, unknown_3, hours_len, unknown_5, unknown_6; + uint16 acct_ctrl, logon_divs; + uint8 *hours; + static uint8 *lm_pw_ptr, *nt_pw_ptr; + uint32 len = 0; + uint32 lm_pw_len, nt_pw_len, hourslen; + BOOL ret = True; + uid_t uid = -1; + gid_t gid = -1; + + if(sampass == NULL || buf == NULL) { + DEBUG(0, ("init_sam_from_buffer: NULL parameters found!\n")); + return False; + } + + /* unpack the buffer into variables */ + len = tdb_unpack (buf, buflen, TDB_FORMAT_STRING, + &logon_time, + &logoff_time, + &kickoff_time, + &pass_last_set_time, + &pass_can_change_time, + &pass_must_change_time, + &username_len, &username, + &domain_len, &domain, + &nt_username_len, &nt_username, + &fullname_len, &fullname, + &homedir_len, &homedir, + &dir_drive_len, &dir_drive, + &logon_script_len, &logon_script, + &profile_path_len, &profile_path, + &acct_desc_len, &acct_desc, + &workstations_len, &workstations, + &unknown_str_len, &unknown_str, + &munged_dial_len, &munged_dial, + &user_rid, + &group_rid, + &lm_pw_len, &lm_pw_ptr, + &nt_pw_len, &nt_pw_ptr, + &acct_ctrl, + &unknown_3, + &logon_divs, + &hours_len, + &hourslen, &hours, + &unknown_5, + &unknown_6); + + if (len == -1) { + ret = False; + goto done; + } + + pdb_set_logon_time(sampass, logon_time, PDB_SET); + pdb_set_logoff_time(sampass, logoff_time, PDB_SET); + pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET); + pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET); + pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET); + pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET); + + pdb_set_username(sampass, username, PDB_SET); + pdb_set_domain(sampass, domain, PDB_SET); + pdb_set_nt_username(sampass, nt_username, PDB_SET); + pdb_set_fullname(sampass, fullname, PDB_SET); + + if (homedir) { + pdb_set_homedir(sampass, homedir, PDB_SET); + } + else { + pdb_set_homedir(sampass, + talloc_sub_specified(sampass->mem_ctx, + lp_logon_home(), + username, domain, + uid, gid), + PDB_DEFAULT); + } + + if (dir_drive) + pdb_set_dir_drive(sampass, dir_drive, PDB_SET); + else { + pdb_set_dir_drive(sampass, + talloc_sub_specified(sampass->mem_ctx, + lp_logon_drive(), + username, domain, + uid, gid), + PDB_DEFAULT); + } + + if (logon_script) + pdb_set_logon_script(sampass, logon_script, PDB_SET); + else { + pdb_set_logon_script(sampass, + talloc_sub_specified(sampass->mem_ctx, + lp_logon_script(), + username, domain, + uid, gid), + PDB_DEFAULT); + } + + if (profile_path) { + pdb_set_profile_path(sampass, profile_path, PDB_SET); + } else { + pdb_set_profile_path(sampass, + talloc_sub_specified(sampass->mem_ctx, + lp_logon_path(), + username, domain, + uid, gid), + PDB_DEFAULT); + } + + pdb_set_acct_desc(sampass, acct_desc, PDB_SET); + pdb_set_workstations(sampass, workstations, PDB_SET); + pdb_set_munged_dial(sampass, munged_dial, PDB_SET); + + if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) { + if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) { + ret = False; + goto done; + } + } + + if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) { + if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) { + ret = False; + goto done; + } + } + + pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET); + pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET); + pdb_set_unknown_3(sampass, unknown_3, PDB_SET); + pdb_set_hours_len(sampass, hours_len, PDB_SET); + pdb_set_unknown_5(sampass, unknown_5, PDB_SET); + pdb_set_unknown_6(sampass, unknown_6, PDB_SET); + pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET); + pdb_set_logon_divs(sampass, logon_divs, PDB_SET); + pdb_set_hours(sampass, hours, PDB_SET); + +done: + + SAFE_FREE(username); + SAFE_FREE(domain); + SAFE_FREE(nt_username); + SAFE_FREE(fullname); + SAFE_FREE(homedir); + SAFE_FREE(dir_drive); + SAFE_FREE(logon_script); + SAFE_FREE(profile_path); + SAFE_FREE(acct_desc); + SAFE_FREE(workstations); + SAFE_FREE(munged_dial); + SAFE_FREE(unknown_str); + SAFE_FREE(hours); + + return ret; +} + +/********************************************************************** + Intialize a BYTE buffer from a SAM_ACCOUNT struct + *********************************************************************/ + +uint32 init_buffer_from_sam (uint8 **buf, const SAM_ACCOUNT *sampass, BOOL size_only) +{ + size_t len, buflen; + + /* times are stored as 32bit integer + take care on system with 64bit wide time_t + --SSS */ + uint32 logon_time, + logoff_time, + kickoff_time, + pass_last_set_time, + pass_can_change_time, + pass_must_change_time; + + uint32 user_rid, group_rid; + + const char *username; + const char *domain; + const char *nt_username; + const char *dir_drive; + const char *unknown_str; + const char *munged_dial; + const char *fullname; + const char *homedir; + const char *logon_script; + const char *profile_path; + const char *acct_desc; + const char *workstations; + uint32 username_len, domain_len, nt_username_len, + dir_drive_len, unknown_str_len, munged_dial_len, + fullname_len, homedir_len, logon_script_len, + profile_path_len, acct_desc_len, workstations_len; + + const uint8 *lm_pw; + const uint8 *nt_pw; + uint32 lm_pw_len = 16; + uint32 nt_pw_len = 16; + + /* do we have a valid SAM_ACCOUNT pointer? */ + if (sampass == NULL) { + DEBUG(0, ("init_buffer_from_sam: SAM_ACCOUNT is NULL!\n")); + return -1; + } + + *buf = NULL; + buflen = 0; + + logon_time = (uint32)pdb_get_logon_time(sampass); + logoff_time = (uint32)pdb_get_logoff_time(sampass); + kickoff_time = (uint32)pdb_get_kickoff_time(sampass); + pass_can_change_time = (uint32)pdb_get_pass_can_change_time(sampass); + pass_must_change_time = (uint32)pdb_get_pass_must_change_time(sampass); + pass_last_set_time = (uint32)pdb_get_pass_last_set_time(sampass); + + user_rid = pdb_get_user_rid(sampass); + group_rid = pdb_get_group_rid(sampass); + + username = pdb_get_username(sampass); + if (username) + username_len = strlen(username) +1; + else + username_len = 0; + + domain = pdb_get_domain(sampass); + if (domain) + domain_len = strlen(domain) +1; + else + domain_len = 0; + + nt_username = pdb_get_nt_username(sampass); + if (nt_username) + nt_username_len = strlen(nt_username) +1; + else + nt_username_len = 0; + + fullname = pdb_get_fullname(sampass); + if (fullname) + fullname_len = strlen(fullname) +1; + else + fullname_len = 0; + + /* + * Only updates fields which have been set (not defaults from smb.conf) + */ + + if (!IS_SAM_DEFAULT(sampass, PDB_DRIVE)) + dir_drive = pdb_get_dir_drive(sampass); + else + dir_drive = NULL; + if (dir_drive) + dir_drive_len = strlen(dir_drive) +1; + else + dir_drive_len = 0; + + if (!IS_SAM_DEFAULT(sampass, PDB_SMBHOME)) + homedir = pdb_get_homedir(sampass); + else + homedir = NULL; + if (homedir) + homedir_len = strlen(homedir) +1; + else + homedir_len = 0; + + if (!IS_SAM_DEFAULT(sampass, PDB_LOGONSCRIPT)) + logon_script = pdb_get_logon_script(sampass); + else + logon_script = NULL; + if (logon_script) + logon_script_len = strlen(logon_script) +1; + else + logon_script_len = 0; + + if (!IS_SAM_DEFAULT(sampass, PDB_PROFILE)) + profile_path = pdb_get_profile_path(sampass); + else + profile_path = NULL; + if (profile_path) + profile_path_len = strlen(profile_path) +1; + else + profile_path_len = 0; + + lm_pw = pdb_get_lanman_passwd(sampass); + if (!lm_pw) + lm_pw_len = 0; + + nt_pw = pdb_get_nt_passwd(sampass); + if (!nt_pw) + nt_pw_len = 0; + + acct_desc = pdb_get_acct_desc(sampass); + if (acct_desc) + acct_desc_len = strlen(acct_desc) +1; + else + acct_desc_len = 0; + + workstations = pdb_get_workstations(sampass); + if (workstations) + workstations_len = strlen(workstations) +1; + else + workstations_len = 0; + + unknown_str = NULL; + unknown_str_len = 0; + + munged_dial = pdb_get_munged_dial(sampass); + if (munged_dial) + munged_dial_len = strlen(munged_dial) +1; + else + munged_dial_len = 0; + + /* one time to get the size needed */ + len = tdb_pack(NULL, 0, TDB_FORMAT_STRING, + logon_time, + logoff_time, + kickoff_time, + pass_last_set_time, + pass_can_change_time, + pass_must_change_time, + username_len, username, + domain_len, domain, + nt_username_len, nt_username, + fullname_len, fullname, + homedir_len, homedir, + dir_drive_len, dir_drive, + logon_script_len, logon_script, + profile_path_len, profile_path, + acct_desc_len, acct_desc, + workstations_len, workstations, + unknown_str_len, unknown_str, + munged_dial_len, munged_dial, + user_rid, + group_rid, + lm_pw_len, lm_pw, + nt_pw_len, nt_pw, + pdb_get_acct_ctrl(sampass), + pdb_get_unknown_3(sampass), + pdb_get_logon_divs(sampass), + pdb_get_hours_len(sampass), + MAX_HOURS_LEN, pdb_get_hours(sampass), + pdb_get_unknown_5(sampass), + pdb_get_unknown_6(sampass)); + + + if (size_only) + return buflen; + + /* malloc the space needed */ + if ( (*buf=(uint8*)malloc(len)) == NULL) { + DEBUG(0,("init_buffer_from_sam: Unable to malloc() memory for buffer!\n")); + return (-1); + } + + /* now for the real call to tdb_pack() */ + buflen = tdb_pack(*buf, len, TDB_FORMAT_STRING, + logon_time, + logoff_time, + kickoff_time, + pass_last_set_time, + pass_can_change_time, + pass_must_change_time, + username_len, username, + domain_len, domain, + nt_username_len, nt_username, + fullname_len, fullname, + homedir_len, homedir, + dir_drive_len, dir_drive, + logon_script_len, logon_script, + profile_path_len, profile_path, + acct_desc_len, acct_desc, + workstations_len, workstations, + unknown_str_len, unknown_str, + munged_dial_len, munged_dial, + user_rid, + group_rid, + lm_pw_len, lm_pw, + nt_pw_len, nt_pw, + pdb_get_acct_ctrl(sampass), + pdb_get_unknown_3(sampass), + pdb_get_logon_divs(sampass), + pdb_get_hours_len(sampass), + MAX_HOURS_LEN, pdb_get_hours(sampass), + pdb_get_unknown_5(sampass), + pdb_get_unknown_6(sampass)); + + + /* check to make sure we got it correct */ + if (buflen != len) { + DEBUG(0, ("init_buffer_from_sam: somthing odd is going on here: bufflen (%d) != len (%d) in tdb_pack operations!\n", + buflen, len)); + /* error */ + SAFE_FREE (*buf); + return (-1); + } + + return (buflen); +} diff --git a/source3/passdb/pdb_get_set.c b/source3/passdb/pdb_get_set.c index c95719451a..ba07a4e01c 100644 --- a/source3/passdb/pdb_get_set.c +++ b/source3/passdb/pdb_get_set.c @@ -330,6 +330,14 @@ uint32 pdb_get_unknown_6 (const SAM_ACCOUNT *sampass) return (-1); } +void *pdb_get_backend_private_data (const SAM_ACCOUNT *sampass, const struct pdb_methods *my_methods) +{ + if (sampass && my_methods == sampass->private.backend_private_methods) + return sampass->private.backend_private_data; + else + return NULL; +} + /********************************************************************* Collection of set...() functions for SAM_ACCOUNT. ********************************************************************/ @@ -1011,6 +1019,29 @@ BOOL pdb_set_hours (SAM_ACCOUNT *sampass, const uint8 *hours, enum pdb_value_sta return pdb_set_init_flags(sampass, PDB_HOURS, flag); } +BOOL pdb_set_backend_private_data (SAM_ACCOUNT *sampass, void *private_data, + void (*free_fn)(void **), + const struct pdb_methods *my_methods, + enum pdb_value_state flag) +{ + if (!sampass) + return False; + + /* does this backend 'own' this SAM_ACCOUNT? */ + if (my_methods != sampass->private.backend_private_methods) + return False; + + if (sampass->private.backend_private_data && sampass->private.backend_private_data_free_fn) { + sampass->private.backend_private_data_free_fn(&sampass->private.backend_private_data); + } + + sampass->private.backend_private_data = private_data; + sampass->private.backend_private_data_free_fn = free_fn; + sampass->private.backend_private_methods = my_methods; + + return pdb_set_init_flags(sampass, PDB_BACKEND_PRIVATE_DATA, flag); +} + /* Helpful interfaces to the above */ diff --git a/source3/passdb/pdb_guest.c b/source3/passdb/pdb_guest.c index 359e2285a3..fa29657edc 100644 --- a/source3/passdb/pdb_guest.c +++ b/source3/passdb/pdb_guest.c @@ -98,6 +98,21 @@ static NTSTATUS guestsam_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUNT } +/*************************************************************************** + Updates a SAM_ACCOUNT + + This isn't a particulary practical option for pdb_guest. We certainly don't + want to twidde the filesystem, so what should we do? + + Current plan is to transparently add the account. It should appear + as if the pdb_guest version was modified, but its actually stored somehwere. + ****************************************************************************/ + +static NTSTATUS guestsam_update_sam_account (struct pdb_methods *methods, SAM_ACCOUNT *newpwd) +{ + return methods->parent->pdb_add_sam_account(methods->parent, newpwd); +} + NTSTATUS pdb_init_guestsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location) { NTSTATUS nt_status; @@ -115,6 +130,7 @@ NTSTATUS pdb_init_guestsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, c (*pdb_method)->getsampwnam = guestsam_getsampwnam; (*pdb_method)->getsampwsid = guestsam_getsampwsid; + (*pdb_method)->update_sam_account = guestsam_update_sam_account; /* we should do no group mapping here */ (*pdb_method)->getgrsid = pdb_nop_getgrsid; diff --git a/source3/passdb/pdb_interface.c b/source3/passdb/pdb_interface.c index 7b44df193f..5ebc14030f 100644 --- a/source3/passdb/pdb_interface.c +++ b/source3/passdb/pdb_interface.c @@ -74,7 +74,7 @@ static struct pdb_init_function_entry *pdb_find_backend_entry(const char *name) struct pdb_init_function_entry *entry = backends; while(entry) { - if (strcasecmp(entry->name, name) == 0) return entry; + if (strcmp(entry->name, name)==0) return entry; entry = entry->next; } @@ -258,7 +258,7 @@ static NTSTATUS context_delete_sam_account(struct pdb_context *context, SAM_ACCO } static NTSTATUS context_getgrsid(struct pdb_context *context, - GROUP_MAP *map, DOM_SID sid, BOOL with_priv) + GROUP_MAP *map, DOM_SID sid) { NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; @@ -269,7 +269,7 @@ static NTSTATUS context_getgrsid(struct pdb_context *context, } curmethods = context->pdb_methods; while (curmethods){ - ret = curmethods->getgrsid(curmethods, map, sid, with_priv); + ret = curmethods->getgrsid(curmethods, map, sid); if (NT_STATUS_IS_OK(ret)) { map->methods = curmethods; return ret; @@ -281,7 +281,7 @@ static NTSTATUS context_getgrsid(struct pdb_context *context, } static NTSTATUS context_getgrgid(struct pdb_context *context, - GROUP_MAP *map, gid_t gid, BOOL with_priv) + GROUP_MAP *map, gid_t gid) { NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; @@ -292,7 +292,7 @@ static NTSTATUS context_getgrgid(struct pdb_context *context, } curmethods = context->pdb_methods; while (curmethods){ - ret = curmethods->getgrgid(curmethods, map, gid, with_priv); + ret = curmethods->getgrgid(curmethods, map, gid); if (NT_STATUS_IS_OK(ret)) { map->methods = curmethods; return ret; @@ -304,7 +304,7 @@ static NTSTATUS context_getgrgid(struct pdb_context *context, } static NTSTATUS context_getgrnam(struct pdb_context *context, - GROUP_MAP *map, char *name, BOOL with_priv) + GROUP_MAP *map, const char *name) { NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; @@ -315,7 +315,7 @@ static NTSTATUS context_getgrnam(struct pdb_context *context, } curmethods = context->pdb_methods; while (curmethods){ - ret = curmethods->getgrnam(curmethods, map, name, with_priv); + ret = curmethods->getgrnam(curmethods, map, name); if (NT_STATUS_IS_OK(ret)) { map->methods = curmethods; return ret; @@ -371,7 +371,7 @@ static NTSTATUS context_delete_group_mapping_entry(struct pdb_context *context, static NTSTATUS context_enum_group_mapping(struct pdb_context *context, enum SID_NAME_USE sid_name_use, GROUP_MAP **rmap, int *num_entries, - BOOL unix_only, BOOL with_priv) + BOOL unix_only) { NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; @@ -382,8 +382,7 @@ static NTSTATUS context_enum_group_mapping(struct pdb_context *context, return context->pdb_methods->enum_group_mapping(context->pdb_methods, sid_name_use, rmap, - num_entries, unix_only, - with_priv); + num_entries, unix_only); } /****************************************************************** @@ -517,12 +516,21 @@ NTSTATUS make_pdb_context_list(struct pdb_context **context, const char **select int i = 0; struct pdb_methods *curmethods, *tmpmethods; NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; + BOOL have_guest = False; if (!NT_STATUS_IS_OK(nt_status = make_pdb_context(context))) { return nt_status; } + if (!selected) { + DEBUG(0, ("ERROR: empty passdb backend list!\n")); + return nt_status; + } + while (selected[i]){ + if (strcmp(selected[i], "guest") == 0) { + have_guest = True; + } /* Try to initialise pdb */ DEBUG(5,("Trying to load: %s\n", selected[i])); if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods_name(&curmethods, *context, selected[i]))) { @@ -535,6 +543,27 @@ NTSTATUS make_pdb_context_list(struct pdb_context **context, const char **select i++; } + if (have_guest) + return NT_STATUS_OK; + + if ( (lp_guestaccount() == NULL) || + (*lp_guestaccount() == '\0') ) { + /* We explicitly don't want guest access. No idea what + else that breaks, but be it that way. */ + return NT_STATUS_OK; + } + + if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods_name(&curmethods, + *context, + "guest"))) { + DEBUG(1, ("Loading guest module failed!\n")); + free_pdb_context(context); + return nt_status; + } + + curmethods->parent = *context; + DLIST_ADD_END((*context)->pdb_methods, curmethods, tmpmethods); + return NT_STATUS_OK; } @@ -562,13 +591,13 @@ static struct pdb_context *pdb_get_static_context(BOOL reload) if ((pdb_context) && (reload)) { pdb_context->free_fn(&pdb_context); - if (NT_STATUS_IS_ERR(make_pdb_context_list(&pdb_context, lp_passdb_backend()))) { + if (!NT_STATUS_IS_OK(make_pdb_context_list(&pdb_context, lp_passdb_backend()))) { return NULL; } } if (!pdb_context) { - if (NT_STATUS_IS_ERR(make_pdb_context_list(&pdb_context, lp_passdb_backend()))) { + if (!NT_STATUS_IS_OK(make_pdb_context_list(&pdb_context, lp_passdb_backend()))) { return NULL; } } @@ -668,7 +697,7 @@ BOOL pdb_delete_sam_account(SAM_ACCOUNT *sam_acct) return NT_STATUS_IS_OK(pdb_context->pdb_delete_sam_account(pdb_context, sam_acct)); } -BOOL pdb_getgrsid(GROUP_MAP *map, DOM_SID sid, BOOL with_priv) +BOOL pdb_getgrsid(GROUP_MAP *map, DOM_SID sid) { struct pdb_context *pdb_context = pdb_get_static_context(False); @@ -677,10 +706,10 @@ BOOL pdb_getgrsid(GROUP_MAP *map, DOM_SID sid, BOOL with_priv) } return NT_STATUS_IS_OK(pdb_context-> - pdb_getgrsid(pdb_context, map, sid, with_priv)); + pdb_getgrsid(pdb_context, map, sid)); } -BOOL pdb_getgrgid(GROUP_MAP *map, gid_t gid, BOOL with_priv) +BOOL pdb_getgrgid(GROUP_MAP *map, gid_t gid) { struct pdb_context *pdb_context = pdb_get_static_context(False); @@ -689,10 +718,10 @@ BOOL pdb_getgrgid(GROUP_MAP *map, gid_t gid, BOOL with_priv) } return NT_STATUS_IS_OK(pdb_context-> - pdb_getgrgid(pdb_context, map, gid, with_priv)); + pdb_getgrgid(pdb_context, map, gid)); } -BOOL pdb_getgrnam(GROUP_MAP *map, char *name, BOOL with_priv) +BOOL pdb_getgrnam(GROUP_MAP *map, char *name) { struct pdb_context *pdb_context = pdb_get_static_context(False); @@ -701,7 +730,7 @@ BOOL pdb_getgrnam(GROUP_MAP *map, char *name, BOOL with_priv) } return NT_STATUS_IS_OK(pdb_context-> - pdb_getgrnam(pdb_context, map, name, with_priv)); + pdb_getgrnam(pdb_context, map, name)); } BOOL pdb_add_group_mapping_entry(GROUP_MAP *map) @@ -741,7 +770,7 @@ BOOL pdb_delete_group_mapping_entry(DOM_SID sid) } BOOL pdb_enum_group_mapping(enum SID_NAME_USE sid_name_use, GROUP_MAP **rmap, - int *num_entries, BOOL unix_only, BOOL with_priv) + int *num_entries, BOOL unix_only) { struct pdb_context *pdb_context = pdb_get_static_context(False); @@ -751,8 +780,7 @@ BOOL pdb_enum_group_mapping(enum SID_NAME_USE sid_name_use, GROUP_MAP **rmap, return NT_STATUS_IS_OK(pdb_context-> pdb_enum_group_mapping(pdb_context, sid_name_use, - rmap, num_entries, unix_only, - with_priv)); + rmap, num_entries, unix_only)); } /*************************************************************** diff --git a/source3/passdb/pdb_ldap.c b/source3/passdb/pdb_ldap.c index fb63e81d28..a4ee4dbd4b 100644 --- a/source3/passdb/pdb_ldap.c +++ b/source3/passdb/pdb_ldap.c @@ -4,7 +4,7 @@ Copyright (C) Jean François Micouleau 1998 Copyright (C) Gerald Carter 2001-2003 Copyright (C) Shahms King 2001 - Copyright (C) Andrew Bartlett 2002 + Copyright (C) Andrew Bartlett 2002-2003 Copyright (C) Stefan (metze) Metzmacher 2002 This program is free software; you can redistribute it and/or modify @@ -51,218 +51,61 @@ #include #include -#ifndef LDAP_OPT_SUCCESS -#define LDAP_OPT_SUCCESS 0 +/* + * Work around versions of the LDAP client libs that don't have the OIDs + * defined, or have them defined under the old name. + * This functionality is really a factor of the server, not the client + * + */ + +#if defined(LDAP_EXOP_X_MODIFY_PASSWD) && !defined(LDAP_EXOP_MODIFY_PASSWD) +#define LDAP_EXOP_MODIFY_PASSWD LDAP_EXOP_X_MODIFY_PASSWD +#elif !defined(LDAP_EXOP_MODIFY_PASSWD) +#define "1.3.6.1.4.1.4203.1.11.1" #endif +#if defined(LDAP_EXOP_X_MODIFY_PASSWD_ID) && !defined(LDAP_EXOP_MODIFY_PASSWD_ID) +#define LDAP_TAG_EXOP_MODIFY_PASSWD_ID LDAP_EXOP_X_MODIFY_PASSWD_ID +#elif !defined(LDAP_EXOP_MODIFY_PASSWD_ID) +#define LDAP_TAG_EXOP_MODIFY_PASSWD_ID ((ber_tag_t) 0x80U) +#endif + +#if defined(LDAP_EXOP_X_MODIFY_PASSWD_NEW) && !defined(LDAP_EXOP_MODIFY_PASSWD_NEW) +#define LDAP_TAG_EXOP_MODIFY_PASSWD_NEW LDAP_EXOP_X_MODIFY_PASSWD_NEW +#elif !defined(LDAP_EXOP_MODIFY_PASSWD_NEW) +#define LDAP_TAG_EXOP_MODIFY_PASSWD_NEW ((ber_tag_t) 0x82U) +#endif + + #ifndef SAM_ACCOUNT #define SAM_ACCOUNT struct sam_passwd #endif +#include "smbldap.h" + struct ldapsam_privates { + struct smbldap_state *smbldap_state; + /* Former statics */ - LDAP *ldap_struct; LDAPMessage *result; LDAPMessage *entry; int index; - time_t last_ping; - /* retrive-once info */ - const char *uri; const char *domain_name; DOM_SID domain_sid; /* configuration items */ int schema_ver; - - BOOL permit_non_unix_accounts; - - uint32 low_allocated_user_rid; - uint32 high_allocated_user_rid; - - uint32 low_allocated_group_rid; - uint32 high_allocated_group_rid; - - char *bind_dn; - char *bind_secret; - - unsigned int num_failures; -}; - -#define LDAPSAM_DONT_PING_TIME 10 /* ping only all 10 seconds */ - -static struct ldapsam_privates *static_ldap_state; - -/* specify schema versions between 2.2. and 3.0 */ - -#define SCHEMAVER_SAMBAACCOUNT 1 -#define SCHEMAVER_SAMBASAMACCOUNT 2 - -/* objectclass names */ - -#define LDAP_OBJ_SAMBASAMACCOUNT "sambaSamAccount" -#define LDAP_OBJ_SAMBAACCOUNT "sambaAccount" -#define LDAP_OBJ_GROUPMAP "sambaGroupMapping" -#define LDAP_OBJ_DOMINFO "sambaDomain" - -#define LDAP_OBJ_ACCOUNT "account" -#define LDAP_OBJ_POSIXACCOUNT "posixAccount" -#define LDAP_OBJ_POSIXGROUP "posixGroup" - -/* some generic attributes that get reused a lot */ - -#define LDAP_ATTRIBUTE_SID "sambaSID" - -/* attribute map table indexes */ - -#define LDAP_ATTR_LIST_END 0 -#define LDAP_ATTR_UID 1 -#define LDAP_ATTR_UIDNUMBER 2 -#define LDAP_ATTR_GIDNUMBER 3 -#define LDAP_ATTR_UNIX_HOME 4 -#define LDAP_ATTR_PWD_LAST_SET 5 -#define LDAP_ATTR_PWD_CAN_CHANGE 6 -#define LDAP_ATTR_PWD_MUST_CHANGE 7 -#define LDAP_ATTR_LOGON_TIME 8 -#define LDAP_ATTR_LOGOFF_TIME 9 -#define LDAP_ATTR_KICKOFF_TIME 10 -#define LDAP_ATTR_CN 11 -#define LDAP_ATTR_DISPLAY_NAME 12 -#define LDAP_ATTR_HOME_PATH 13 -#define LDAP_ATTR_LOGON_SCRIPT 14 -#define LDAP_ATTR_PROFILE_PATH 15 -#define LDAP_ATTR_DESC 16 -#define LDAP_ATTR_USER_WKS 17 -#define LDAP_ATTR_USER_SID 18 -#define LDAP_ATTR_USER_RID 18 -#define LDAP_ATTR_PRIMARY_GROUP_SID 19 -#define LDAP_ATTR_PRIMARY_GROUP_RID 20 -#define LDAP_ATTR_LMPW 21 -#define LDAP_ATTR_NTPW 22 -#define LDAP_ATTR_DOMAIN 23 -#define LDAP_ATTR_OBJCLASS 24 -#define LDAP_ATTR_ACB_INFO 25 -#define LDAP_ATTR_NEXT_USERRID 26 -#define LDAP_ATTR_NEXT_GROUPRID 27 -#define LDAP_ATTR_DOM_SID 28 -#define LDAP_ATTR_HOME_DRIVE 29 -#define LDAP_ATTR_GROUP_SID 30 -#define LDAP_ATTR_GROUP_TYPE 31 - - -typedef struct _attrib_map_entry { - int attrib; - const char *name; -} ATTRIB_MAP_ENTRY; - - -/* attributes used by Samba 2.2 */ - -static ATTRIB_MAP_ENTRY attrib_map_v22[] = { - { LDAP_ATTR_UID, "uid" }, - { LDAP_ATTR_UIDNUMBER, "uidNumber" }, - { LDAP_ATTR_GIDNUMBER, "gidNumber" }, - { LDAP_ATTR_UNIX_HOME, "homeDirectory" }, - { LDAP_ATTR_PWD_LAST_SET, "pwdLastSet" }, - { LDAP_ATTR_PWD_CAN_CHANGE, "pwdCanChange" }, - { LDAP_ATTR_PWD_MUST_CHANGE, "pwdMustChange" }, - { LDAP_ATTR_LOGON_TIME, "logonTime" }, - { LDAP_ATTR_LOGOFF_TIME, "logoffTime" }, - { LDAP_ATTR_KICKOFF_TIME, "kickoffTime" }, - { LDAP_ATTR_CN, "cn" }, - { LDAP_ATTR_DISPLAY_NAME, "displayName" }, - { LDAP_ATTR_HOME_PATH, "smbHome" }, - { LDAP_ATTR_HOME_DRIVE, "homeDrives" }, - { LDAP_ATTR_LOGON_SCRIPT, "scriptPath" }, - { LDAP_ATTR_PROFILE_PATH, "profilePath" }, - { LDAP_ATTR_DESC, "description" }, - { LDAP_ATTR_USER_WKS, "userWorkstations"}, - { LDAP_ATTR_USER_RID, "rid" }, - { LDAP_ATTR_PRIMARY_GROUP_RID, "primaryGroupID"}, - { LDAP_ATTR_LMPW, "lmPassword" }, - { LDAP_ATTR_NTPW, "ntPassword" }, - { LDAP_ATTR_DOMAIN, "domain" }, - { LDAP_ATTR_OBJCLASS, "objectClass" }, - { LDAP_ATTR_ACB_INFO, "acctFlags" }, - { LDAP_ATTR_LIST_END, NULL } -}; - -/* attributes used by Samba 3.0's sambaSamAccount */ - -static ATTRIB_MAP_ENTRY attrib_map_v30[] = { - { LDAP_ATTR_UID, "uid" }, - { LDAP_ATTR_UIDNUMBER, "uidNumber" }, - { LDAP_ATTR_GIDNUMBER, "gidNumber" }, - { LDAP_ATTR_UNIX_HOME, "homeDirectory" }, - { LDAP_ATTR_PWD_LAST_SET, "sambaPwdLastSet" }, - { LDAP_ATTR_PWD_CAN_CHANGE, "sambaPwdCanChange" }, - { LDAP_ATTR_PWD_MUST_CHANGE, "sambaPwdMustChange" }, - { LDAP_ATTR_LOGON_TIME, "sambaLogonTime" }, - { LDAP_ATTR_LOGOFF_TIME, "sambaLogoffTime" }, - { LDAP_ATTR_KICKOFF_TIME, "sambaKickoffTime" }, - { LDAP_ATTR_CN, "cn" }, - { LDAP_ATTR_DISPLAY_NAME, "displayName" }, - { LDAP_ATTR_HOME_DRIVE, "sambaHomeDrive" }, - { LDAP_ATTR_HOME_PATH, "sambaHomePath" }, - { LDAP_ATTR_LOGON_SCRIPT, "sambaLogonScript" }, - { LDAP_ATTR_PROFILE_PATH, "sambaProfilePath" }, - { LDAP_ATTR_DESC, "description" }, - { LDAP_ATTR_USER_WKS, "sambaUserWorkstations" }, - { LDAP_ATTR_USER_SID, "sambaSID" }, - { LDAP_ATTR_PRIMARY_GROUP_SID, "sambaPrimaryGroupSID" }, - { LDAP_ATTR_LMPW, "sambaLMPassword" }, - { LDAP_ATTR_NTPW, "sambaNTPassword" }, - { LDAP_ATTR_DOMAIN, "sambaDomainName" }, - { LDAP_ATTR_OBJCLASS, "objectClass" }, - { LDAP_ATTR_ACB_INFO, "sambaAcctFlags" }, - { LDAP_ATTR_LIST_END, NULL } -}; - -/* attributes used for alalocating RIDs */ - -static ATTRIB_MAP_ENTRY dominfo_attr_list[] = { - { LDAP_ATTR_DOMAIN, "sambaDomainName" }, - { LDAP_ATTR_NEXT_USERRID, "sambaNextUserRid" }, - { LDAP_ATTR_NEXT_GROUPRID, "sambaNextGroupRid" }, - { LDAP_ATTR_DOM_SID, "sambaSID" }, - { LDAP_ATTR_LIST_END, NULL }, -}; - -/* Samba 3.0 group mapping attributes */ - -static ATTRIB_MAP_ENTRY groupmap_attr_list[] = { - { LDAP_ATTR_GIDNUMBER, "gidNumber" }, - { LDAP_ATTR_GROUP_SID, "sambaSID" }, - { LDAP_ATTR_GROUP_TYPE, "sambaGroupType" }, - { LDAP_ATTR_DESC, "description" }, - { LDAP_ATTR_DISPLAY_NAME, "displayName" }, - { LDAP_ATTR_CN, "cn" }, - { LDAP_ATTR_LIST_END, NULL } -}; - -static ATTRIB_MAP_ENTRY groupmap_attr_list_to_delete[] = { - { LDAP_ATTR_GROUP_SID, "sambaSID" }, - { LDAP_ATTR_GROUP_TYPE, "sambaGroupType" }, - { LDAP_ATTR_DESC, "description" }, - { LDAP_ATTR_DISPLAY_NAME, "displayName" }, - { LDAP_ATTR_LIST_END, NULL } }; /********************************************************************** - perform a simple table lookup and return the attribute name + Free a LDAPMessage (one is stored on the SAM_ACCOUNT) **********************************************************************/ -static const char* get_attr_key2string( ATTRIB_MAP_ENTRY table[], int key ) +static void private_data_free_fn(void **result) { - int i = 0; - - while ( table[i].attrib != LDAP_ATTR_LIST_END ) { - if ( table[i].attrib == key ) - return table[i].name; - i++; - } - - return NULL; + ldap_memfree(*result); + *result = NULL; } /********************************************************************** @@ -286,52 +129,6 @@ static const char* get_userattr_key2string( int schema_ver, int key ) return NULL; } -/********************************************************************** - Return the list of attribute names from a mapping table - **********************************************************************/ - -static char** get_attr_list( ATTRIB_MAP_ENTRY table[] ) -{ - char **names; - int i = 0; - - while ( table[i].attrib != LDAP_ATTR_LIST_END ) - i++; - i++; - - names = (char**)malloc( sizeof(char*)*i ); - if ( !names ) { - DEBUG(0,("get_attr_list: out of memory\n")); - return NULL; - } - - i = 0; - while ( table[i].attrib != LDAP_ATTR_LIST_END ) { - names[i] = strdup( table[i].name ); - i++; - } - names[i] = NULL; - - return names; -} - -/********************************************************************* - Cleanup - ********************************************************************/ - -static void free_attr_list( char **list ) -{ - int i = 0; - - if ( !list ) - return; - - while ( list[i] ) - SAFE_FREE( list[i] ); - - SAFE_FREE( list ); -} - /********************************************************************** return the list of attribute names given a user schema version **********************************************************************/ @@ -352,1478 +149,187 @@ static char** get_userattr_list( int schema_ver ) return NULL; } - /******************************************************************* - find the ldap password -******************************************************************/ -static BOOL fetch_ldapsam_pw(char **dn, char** pw) -{ - char *key = NULL; - size_t size; - - *dn = smb_xstrdup(lp_ldap_admin_dn()); - - if (asprintf(&key, "%s/%s", SECRETS_LDAP_BIND_PW, *dn) < 0) { - SAFE_FREE(*dn); - DEBUG(0, ("fetch_ldapsam_pw: asprintf failed!\n")); - } - - *pw=secrets_fetch(key, &size); - SAFE_FREE(key); - - if (!size) { - /* Upgrade 2.2 style entry */ - char *p; - char* old_style_key = strdup(*dn); - char *data; - fstring old_style_pw; - - if (!old_style_key) { - DEBUG(0, ("fetch_ldapsam_pw: strdup failed!\n")); - return False; - } - - for (p=old_style_key; *p; p++) - if (*p == ',') *p = '/'; - - data=secrets_fetch(old_style_key, &size); - if (!size && size < sizeof(old_style_pw)) { - DEBUG(0,("fetch_ldap_pw: neither ldap secret retrieved!\n")); - SAFE_FREE(old_style_key); - SAFE_FREE(*dn); - return False; - } - - strncpy(old_style_pw, data, size); - old_style_pw[size] = 0; - - SAFE_FREE(data); - - if (!secrets_store_ldap_pw(*dn, old_style_pw)) { - DEBUG(0,("fetch_ldap_pw: ldap secret could not be upgraded!\n")); - SAFE_FREE(old_style_key); - SAFE_FREE(*dn); - return False; - } - if (!secrets_delete(old_style_key)) { - DEBUG(0,("fetch_ldap_pw: old ldap secret could not be deleted!\n")); - } - - SAFE_FREE(old_style_key); + generate the LDAP search filter for the objectclass based on the + version of the schema we are using + ******************************************************************/ - *pw = smb_xstrdup(old_style_pw); - } - - return True; -} - -/******************************************************************* - open a connection to the ldap server. -******************************************************************/ -static int ldapsam_open_connection (struct ldapsam_privates *ldap_state, LDAP ** ldap_struct) +static const char* get_objclass_filter( int schema_ver ) { - int rc = LDAP_SUCCESS; - int version; - BOOL ldap_v3 = False; - -#ifdef HAVE_LDAP_INITIALIZE - DEBUG(10, ("ldapsam_open_connection: %s\n", ldap_state->uri)); - - if ((rc = ldap_initialize(ldap_struct, ldap_state->uri)) != LDAP_SUCCESS) { - DEBUG(0, ("ldap_initialize: %s\n", ldap_err2string(rc))); - return rc; - } + static fstring objclass_filter; -#else - - /* Parse the string manually */ - - { - int port = 0; - fstring protocol; - fstring host; - const char *p = ldap_state->uri; - SMB_ASSERT(sizeof(protocol)>10 && sizeof(host)>254); - - /* skip leading "URL:" (if any) */ - if ( strncasecmp( p, "URL:", 4 ) == 0 ) { - p += 4; - } - - sscanf(p, "%10[^:]://%254s[^:]:%d", protocol, host, &port); - - if (port == 0) { - if (strequal(protocol, "ldap")) { - port = LDAP_PORT; - } else if (strequal(protocol, "ldaps")) { - port = LDAPS_PORT; - } else { - DEBUG(0, ("unrecognised protocol (%s)!\n", protocol)); - } - } - - if ((*ldap_struct = ldap_init(host, port)) == NULL) { - DEBUG(0, ("ldap_init failed !\n")); - return LDAP_OPERATIONS_ERROR; - } - - if (strequal(protocol, "ldaps")) { -#ifdef LDAP_OPT_X_TLS - int tls = LDAP_OPT_X_TLS_HARD; - if (ldap_set_option (*ldap_struct, LDAP_OPT_X_TLS, &tls) != LDAP_SUCCESS) - { - DEBUG(0, ("Failed to setup a TLS session\n")); - } - - DEBUG(3,("LDAPS option set...!\n")); -#else - DEBUG(0,("ldapsam_open_connection: Secure connection not supported by LDAP client libraries!\n")); - return LDAP_OPERATIONS_ERROR; -#endif - } - } -#endif - - if (ldap_get_option(*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version) == LDAP_OPT_SUCCESS) + switch( schema_ver ) { - if (version != LDAP_VERSION3) - { - version = LDAP_VERSION3; - if (ldap_set_option (*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version) == LDAP_OPT_SUCCESS) { - ldap_v3 = True; - } - } else { - ldap_v3 = True; - } - } - - if (lp_ldap_ssl() == LDAP_SSL_START_TLS) { -#ifdef LDAP_OPT_X_TLS - if (ldap_v3) { - if ((rc = ldap_start_tls_s (*ldap_struct, NULL, NULL)) != LDAP_SUCCESS) - { - DEBUG(0,("Failed to issue the StartTLS instruction: %s\n", - ldap_err2string(rc))); - return rc; - } - DEBUG (3, ("StartTLS issued: using a TLS connection\n")); - } else { - - DEBUG(0, ("Need LDAPv3 for Start TLS\n")); - return LDAP_OPERATIONS_ERROR; - } -#else - DEBUG(0,("ldapsam_open_connection: StartTLS not supported by LDAP client libraries!\n")); - return LDAP_OPERATIONS_ERROR; -#endif + case SCHEMAVER_SAMBAACCOUNT: + snprintf( objclass_filter, sizeof(objclass_filter)-1, "(objectclass=%s)", LDAP_OBJ_SAMBAACCOUNT ); + break; + case SCHEMAVER_SAMBASAMACCOUNT: + snprintf( objclass_filter, sizeof(objclass_filter)-1, "(objectclass=%s)", LDAP_OBJ_SAMBASAMACCOUNT ); + break; + default: + DEBUG(0,("pdb_ldapsam: get_objclass_filter(): Invalid schema version specified!\n")); + break; } - - DEBUG(2, ("ldapsam_open_connection: connection opened\n")); - return rc; + + return objclass_filter; } - /******************************************************************* - a rebind function for authenticated referrals - This version takes a void* that we can shove useful stuff in :-) + run the search by name. ******************************************************************/ -#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) +static int ldapsam_search_suffix_by_name (struct ldapsam_privates *ldap_state, + const char *user, + LDAPMessage ** result, char **attr) { - struct ldapsam_privates *ldap_state = arg; - - /** @TODO Should we be doing something to check what servers we rebind to? - Could we get a referral to a machine that we don't want to give our - username and password to? */ - - if (freeit) { - SAFE_FREE(*whop); - memset(*credp, '\0', strlen(*credp)); - SAFE_FREE(*credp); - } else { - DEBUG(5,("rebind_proc_with_state: Rebinding as \"%s\"\n", - ldap_state->bind_dn)); + pstring filter; + char *escape_user = escape_ldap_string_alloc(user); - *whop = strdup(ldap_state->bind_dn); - if (!*whop) { - return LDAP_NO_MEMORY; - } - *credp = strdup(ldap_state->bind_secret); - if (!*credp) { - SAFE_FREE(*whop); - return LDAP_NO_MEMORY; - } - *methodp = LDAP_AUTH_SIMPLE; + if (!escape_user) { + return LDAP_NO_MEMORY; } - 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, - ber_int_t msgid, void *arg) -{ - struct ldapsam_privates *ldap_state = arg; - int rc; - DEBUG(5,("rebindproc_connect_with_state: Rebinding as \"%s\"\n", - ldap_state->bind_dn)); - - /** @TODO Should we be doing something to check what servers we rebind to? - Could we get a referral to a machine that we don't want to give our - username and password to? */ + /* + * in the filter expression, replace %u with the real name + * so in ldap filter, %u MUST exist :-) + */ + snprintf(filter, sizeof(filter)-1, "(&%s%s)", lp_ldap_filter(), + get_objclass_filter(ldap_state->schema_ver)); - rc = ldap_simple_bind_s(ldap_struct, ldap_state->bind_dn, ldap_state->bind_secret); + /* + * have to use this here because $ is filtered out + * in pstring_sub + */ - 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 ) -{ - return rebindproc_with_state(ldap_struct, whop, credp, - method, freeit, static_ldap_state); - -} -# endif /*LDAP_SET_REBIND_PROC_ARGS == 2*/ -#endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/ + all_string_sub(filter, "%u", escape_user, sizeof(pstring)); + SAFE_FREE(escape_user); -/******************************************************************* - 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); + return smbldap_search_suffix(ldap_state->smbldap_state, filter, attr, result); } -# 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. + run the search by rid. ******************************************************************/ -static int ldapsam_connect_system(struct ldapsam_privates *ldap_state, LDAP * ldap_struct) -{ - int rc; - char *ldap_dn; - char *ldap_secret; - - /* The rebind proc needs this *HACK*. We are not multithreaded, so - this will work, but it's not nice. */ - static_ldap_state = ldap_state; - - /* get the password */ - if (!fetch_ldapsam_pw(&ldap_dn, &ldap_secret)) - { - DEBUG(0, ("ldap_connect_system: Failed to retrieve password from secrets.tdb\n")); - return LDAP_INVALID_CREDENTIALS; - } - - ldap_state->bind_dn = ldap_dn; - ldap_state->bind_secret = ldap_secret; - - /* removed the sasl_bind_s "EXTERNAL" stuff, as my testsuite - (OpenLDAP) doesnt' seem to support it */ - - DEBUG(10,("ldap_connect_system: Binding to ldap server %s as \"%s\"\n", - ldap_state->uri, ldap_dn)); - -#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000) -# if LDAP_SET_REBIND_PROC_ARGS == 2 - ldap_set_rebind_proc(ldap_struct, &rebindproc_connect); -# endif -# if LDAP_SET_REBIND_PROC_ARGS == 3 - ldap_set_rebind_proc(ldap_struct, &rebindproc_connect_with_state, (void *)ldap_state); -# endif -#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 /*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) { - char *ld_error = NULL; - ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, - &ld_error); - DEBUG(ldap_state->num_failures ? 2 : 0, - ("failed to bind to server with dn= %s Error: %s\n\t%s\n", - ldap_dn ? ld_error : "(unknown)", ldap_err2string(rc), - ld_error)); - SAFE_FREE(ld_error); - ldap_state->num_failures++; - return rc; - } - - ldap_state->num_failures = 0; - - DEBUG(3, ("ldap_connect_system: succesful connection to the LDAP server\n")); - return rc; -} - -/********************************************************************** -Connect to LDAP server -*********************************************************************/ -static int ldapsam_open(struct ldapsam_privates *ldap_state) +static int ldapsam_search_suffix_by_rid (struct ldapsam_privates *ldap_state, + uint32 rid, LDAPMessage ** result, + char **attr) { + pstring filter; int rc; - SMB_ASSERT(ldap_state); - -#ifndef NO_LDAP_SECURITY - if (geteuid() != 0) { - DEBUG(0, ("ldapsam_open: cannot access LDAP when not root..\n")); - return LDAP_INSUFFICIENT_ACCESS; - } -#endif - if ((ldap_state->ldap_struct != NULL) && ((ldap_state->last_ping + LDAPSAM_DONT_PING_TIME) < time(NULL))) { - struct sockaddr_un addr; - socklen_t len = sizeof(addr); - int sd; - if (ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_DESC, &sd) == 0 && - getpeername(sd, (struct sockaddr *) &addr, &len) < 0) { - /* the other end has died. reopen. */ - ldap_unbind_ext(ldap_state->ldap_struct, NULL, NULL); - ldap_state->ldap_struct = NULL; - ldap_state->last_ping = (time_t)0; - } else { - ldap_state->last_ping = time(NULL); - } - } - - if (ldap_state->ldap_struct != NULL) { - DEBUG(5,("ldapsam_open: already connected to the LDAP server\n")); - return LDAP_SUCCESS; - } - - if ((rc = ldapsam_open_connection(ldap_state, &ldap_state->ldap_struct))) { - return rc; - } - - if ((rc = ldapsam_connect_system(ldap_state, ldap_state->ldap_struct))) { - ldap_unbind_ext(ldap_state->ldap_struct, NULL, NULL); - ldap_state->ldap_struct = NULL; - return rc; - } - - - ldap_state->last_ping = time(NULL); - DEBUG(4,("The LDAP server is succesful connected\n")); - - return LDAP_SUCCESS; -} - -/********************************************************************** -Disconnect from LDAP server -*********************************************************************/ -static NTSTATUS ldapsam_close(struct ldapsam_privates *ldap_state) -{ - if (!ldap_state) - return NT_STATUS_INVALID_PARAMETER; - - if (ldap_state->ldap_struct != NULL) { - ldap_unbind_ext(ldap_state->ldap_struct, NULL, NULL); - ldap_state->ldap_struct = NULL; - } + snprintf(filter, sizeof(filter)-1, "(&(rid=%i)%s)", rid, + get_objclass_filter(ldap_state->schema_ver)); - DEBUG(5,("The connection to the LDAP server was closed\n")); - /* maybe free the results here --metze */ + rc = smbldap_search_suffix(ldap_state->smbldap_state, filter, attr, result); - return NT_STATUS_OK; + return rc; } -static int ldapsam_retry_open(struct ldapsam_privates *ldap_state, int *attempts) +/******************************************************************* + run the search by SID. +******************************************************************/ +static int ldapsam_search_suffix_by_sid (struct ldapsam_privates *ldap_state, + const DOM_SID *sid, LDAPMessage ** result, + char **attr) { + pstring filter; int rc; + fstring sid_string; - SMB_ASSERT(ldap_state && attempts); - - if (*attempts != 0) { - unsigned int sleep_time; - uint8 rand_byte; - - /* Sleep for a random timeout */ - rand_byte = (char)(sys_random()); - - sleep_time = (((*attempts)*(*attempts))/2)*rand_byte*2; - /* we retry after (0.5, 1, 2, 3, 4.5, 6) seconds - on average. - */ - DEBUG(3, ("Sleeping for %u milliseconds before reconnecting\n", - sleep_time)); - msleep(sleep_time); - } - (*attempts)++; - - if ((rc = ldapsam_open(ldap_state))) { - DEBUG(1,("Connection to LDAP Server failed for the %d try!\n",*attempts)); - return rc; - } - - return LDAP_SUCCESS; -} - - -/********************************************************************* - ********************************************************************/ - -static int ldapsam_search(struct ldapsam_privates *ldap_state, - const char *base, int scope, const char *filter, - char *attrs[], int attrsonly, - LDAPMessage **res) -{ - int rc = LDAP_SERVER_DOWN; - int attempts = 0; - char *utf8_filter; - - SMB_ASSERT(ldap_state); - - if (push_utf8_allocate(&utf8_filter, filter) == (size_t)-1) { - return LDAP_NO_MEMORY; - } - - while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) { - - if ((rc = ldapsam_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS) - continue; + snprintf(filter, sizeof(filter)-1, "(&(%s=%s)%s)", + get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID), + sid_to_string(sid_string, sid), + get_objclass_filter(ldap_state->schema_ver)); - rc = ldap_search_s(ldap_state->ldap_struct, base, scope, - utf8_filter, attrs, attrsonly, res); - } + rc = smbldap_search_suffix(ldap_state->smbldap_state, filter, attr, result); - if (rc == LDAP_SERVER_DOWN) { - DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO)); - ldapsam_close(ldap_state); - } - - SAFE_FREE(utf8_filter); return rc; } -static int ldapsam_modify(struct ldapsam_privates *ldap_state, const char *dn, LDAPMod *attrs[]) +/******************************************************************* + Delete complete object or objectclass and attrs from + object found in search_result depending on lp_ldap_delete_dn +******************************************************************/ +static NTSTATUS ldapsam_delete_entry(struct ldapsam_privates *ldap_state, + LDAPMessage *result, + const char *objectclass, + char **attrs) { - int rc = LDAP_SERVER_DOWN; - int attempts = 0; - char *utf8_dn; + int rc; + LDAPMessage *entry; + LDAPMod **mods = NULL; + char *name, *dn; + BerElement *ptr = NULL; - SMB_ASSERT(ldap_state); - - if (push_utf8_allocate(&utf8_dn, dn) == (size_t)-1) { - return LDAP_NO_MEMORY; - } - - while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) { - - if ((rc = ldapsam_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS) - continue; - - rc = ldap_modify_s(ldap_state->ldap_struct, utf8_dn, attrs); - } - - if (rc == LDAP_SERVER_DOWN) { - DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO)); - ldapsam_close(ldap_state); - } - - SAFE_FREE(utf8_dn); - return rc; -} - -static int ldapsam_add(struct ldapsam_privates *ldap_state, const char *dn, LDAPMod *attrs[]) -{ - int rc = LDAP_SERVER_DOWN; - int attempts = 0; - char *utf8_dn; - - SMB_ASSERT(ldap_state); - - if (push_utf8_allocate(&utf8_dn, dn) == (size_t)-1) { - return LDAP_NO_MEMORY; - } - - while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) { - - if ((rc = ldapsam_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS) - continue; - - rc = ldap_add_s(ldap_state->ldap_struct, utf8_dn, attrs); - } - - if (rc == LDAP_SERVER_DOWN) { - DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO)); - ldapsam_close(ldap_state); - } - - SAFE_FREE(utf8_dn); - return rc; -} - -static int ldapsam_delete(struct ldapsam_privates *ldap_state, char *dn) -{ - int rc = LDAP_SERVER_DOWN; - int attempts = 0; - char *utf8_dn; - - SMB_ASSERT(ldap_state); - - if (push_utf8_allocate(&utf8_dn, dn) == (size_t)-1) { - return LDAP_NO_MEMORY; - } - - while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) { - - if ((rc = ldapsam_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS) - continue; - - rc = ldap_delete_s(ldap_state->ldap_struct, utf8_dn); - } - - if (rc == LDAP_SERVER_DOWN) { - DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO)); - ldapsam_close(ldap_state); - } - - SAFE_FREE(utf8_dn); - return rc; -} - -#ifdef LDAP_EXOP_X_MODIFY_PASSWD -static int ldapsam_extended_operation(struct ldapsam_privates *ldap_state, LDAP_CONST char *reqoid, struct berval *reqdata, LDAPControl **serverctrls, LDAPControl **clientctrls, char **retoidp, struct berval **retdatap) -{ - int rc = LDAP_SERVER_DOWN; - int attempts = 0; - - if (!ldap_state) - return (-1); - - while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) { - - if ((rc = ldapsam_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS) - continue; - - rc = ldap_extended_operation_s(ldap_state->ldap_struct, reqoid, reqdata, serverctrls, clientctrls, retoidp, retdatap); - } - - if (rc == LDAP_SERVER_DOWN) { - DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO)); - ldapsam_close(ldap_state); - } - - return rc; -} -#endif - -/******************************************************************* - run the search by name. -******************************************************************/ -static int ldapsam_search_suffix (struct ldapsam_privates *ldap_state, const char *filter, - char **search_attr, LDAPMessage ** result) -{ - int scope = LDAP_SCOPE_SUBTREE; - int rc; - - DEBUG(2, ("ldapsam_search_suffix: searching for:[%s]\n", filter)); - - rc = ldapsam_search(ldap_state, lp_ldap_suffix(), scope, filter, search_attr, 0, result); - - if (rc != LDAP_SUCCESS) { - char *ld_error = NULL; - ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, - &ld_error); - DEBUG(0,("ldapsam_search_suffix: Problem during the LDAP search: %s (%s)\n", - ld_error?ld_error:"(unknown)", ldap_err2string (rc))); - DEBUG(3,("ldapsam_search_suffix: Query was: %s, %s\n", lp_ldap_suffix(), - filter)); - SAFE_FREE(ld_error); - } - - return rc; -} - -/******************************************************************* - generate the LDAP search filter for the objectclass based on the - version of the schema we are using - ******************************************************************/ - -static const char* get_objclass_filter( int schema_ver ) -{ - static fstring objclass_filter; - - switch( schema_ver ) - { - case SCHEMAVER_SAMBAACCOUNT: - snprintf( objclass_filter, sizeof(objclass_filter)-1, "(objectclass=%s)", LDAP_OBJ_SAMBAACCOUNT ); - break; - case SCHEMAVER_SAMBASAMACCOUNT: - snprintf( objclass_filter, sizeof(objclass_filter)-1, "(objectclass=%s)", LDAP_OBJ_SAMBASAMACCOUNT ); - break; - default: - DEBUG(0,("ldapsam_search_suffix_by_name(): Invalid schema version specified!\n")); - break; - } - - return objclass_filter; -} - -/******************************************************************* - run the search by name. -******************************************************************/ -static int ldapsam_search_suffix_by_name (struct ldapsam_privates *ldap_state, const char *user, - LDAPMessage ** result, char **attr) -{ - pstring filter; - char *escape_user = escape_ldap_string_alloc(user); - - if (!escape_user) { - return LDAP_NO_MEMORY; - } - - /* - * in the filter expression, replace %u with the real name - * so in ldap filter, %u MUST exist :-) - */ - snprintf(filter, sizeof(filter)-1, "(&%s%s)", lp_ldap_filter(), - get_objclass_filter(ldap_state->schema_ver)); - - /* - * have to use this here because $ is filtered out - * in pstring_sub - */ - - - all_string_sub(filter, "%u", escape_user, sizeof(pstring)); - SAFE_FREE(escape_user); - - return ldapsam_search_suffix(ldap_state, filter, attr, result); -} - -/******************************************************************* - run the search by rid. -******************************************************************/ -static int ldapsam_search_suffix_by_rid (struct ldapsam_privates *ldap_state, - uint32 rid, LDAPMessage ** result, - char **attr) -{ - pstring filter; - int rc; - - /* check if the user rid exists, if not, try searching on the uid */ - - snprintf(filter, sizeof(filter)-1, "(&(rid=%i)%s)", rid, - get_objclass_filter(ldap_state->schema_ver)); - - rc = ldapsam_search_suffix(ldap_state, filter, attr, result); - - return rc; -} - -/******************************************************************* - run the search by SID. -******************************************************************/ -static int ldapsam_search_suffix_by_sid (struct ldapsam_privates *ldap_state, - const DOM_SID *sid, LDAPMessage ** result, - char **attr) -{ - pstring filter; - int rc; - fstring sid_string; - - /* check if the user rid exsists, if not, try searching on the uid */ - - snprintf(filter, sizeof(filter)-1, "(&(%s=%s)%s)", - get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID), - sid_to_string(sid_string, sid), - get_objclass_filter(ldap_state->schema_ver)); - - rc = ldapsam_search_suffix(ldap_state, filter, attr, result); - - return rc; -} - -/******************************************************************* -search an attribute and return the first value found. -******************************************************************/ -static BOOL get_single_attribute (LDAP * ldap_struct, LDAPMessage * entry, - const char *attribute, pstring value) -{ - char **values; - - if ( !attribute ) - return False; - - value[0] = '\0'; - - if ((values = ldap_get_values (ldap_struct, entry, attribute)) == NULL) { - DEBUG (10, ("get_single_attribute: [%s] = []\n", attribute)); - - return False; - } - - if (convert_string(CH_UTF8, CH_UNIX,values[0], -1, value, sizeof(pstring)) == (size_t)-1) - { - DEBUG(1, ("get_single_attribute: string conversion of [%s] = [%s] failed!\n", - attribute, values[0])); - ldap_value_free(values); - return False; - } - - ldap_value_free(values); -#ifdef DEBUG_PASSWORDS - DEBUG (100, ("get_single_attribute: [%s] = [%s]\n", attribute, value)); -#endif - return True; -} - -/************************************************************************ -Routine to manage the LDAPMod structure array -manage memory used by the array, by each struct, and values - -************************************************************************/ -static void make_a_mod (LDAPMod *** modlist, int modop, const char *attribute, const char *value) -{ - LDAPMod **mods; - int i; - int j; - - mods = *modlist; - - /* sanity checks on the mod values */ - - if (attribute == NULL || *attribute == '\0') - return; -#if 0 /* commented out after discussion with abartlet. Do not reenable. - left here so other so re-add similar code --jerry */ - if (value == NULL || *value == '\0') - return; -#endif - - if (mods == NULL) - { - mods = (LDAPMod **) malloc(sizeof(LDAPMod *)); - if (mods == NULL) - { - DEBUG(0, ("make_a_mod: out of memory!\n")); - return; - } - mods[0] = NULL; - } - - for (i = 0; mods[i] != NULL; ++i) { - if (mods[i]->mod_op == modop && !strcasecmp(mods[i]->mod_type, attribute)) - break; - } - - if (mods[i] == NULL) - { - mods = (LDAPMod **) Realloc (mods, (i + 2) * sizeof (LDAPMod *)); - if (mods == NULL) - { - DEBUG(0, ("make_a_mod: out of memory!\n")); - return; - } - mods[i] = (LDAPMod *) malloc(sizeof(LDAPMod)); - if (mods[i] == NULL) - { - DEBUG(0, ("make_a_mod: out of memory!\n")); - return; - } - mods[i]->mod_op = modop; - mods[i]->mod_values = NULL; - mods[i]->mod_type = strdup(attribute); - mods[i + 1] = NULL; - } - - if (value != NULL) - { - char *utf8_value = NULL; - - j = 0; - if (mods[i]->mod_values != NULL) { - for (; mods[i]->mod_values[j] != NULL; j++); - } - mods[i]->mod_values = (char **)Realloc(mods[i]->mod_values, - (j + 2) * sizeof (char *)); - - if (mods[i]->mod_values == NULL) { - DEBUG (0, ("make_a_mod: Memory allocation failure!\n")); - return; - } - - if (push_utf8_allocate(&utf8_value, value) == (size_t)-1) { - DEBUG (0, ("make_a_mod: String conversion failure!\n")); - return; - } - - mods[i]->mod_values[j] = utf8_value; - - mods[i]->mod_values[j + 1] = NULL; - } - *modlist = mods; -} - -/********************************************************************** - Set attribute to newval in LDAP, regardless of what value the - attribute had in LDAP before. -*********************************************************************/ -static void make_ldap_mod(LDAP *ldap_struct, LDAPMessage *existing, - LDAPMod ***mods, - const char *attribute, const char *newval) -{ - char **values = NULL; - - if (existing != NULL) { - values = ldap_get_values(ldap_struct, existing, attribute); - } - - /* all of our string attributes are case insensitive */ - - if ((values != NULL) && (values[0] != NULL) && - StrCaseCmp(values[0], newval) == 0) - { - - /* Believe it or not, but LDAP will deny a delete and - an add at the same time if the values are the - same... */ - - ldap_value_free(values); - return; - } - - /* Regardless of the real operation (add or modify) - we add the new value here. We rely on deleting - the old value, should it exist. */ - - if ((newval != NULL) && (strlen(newval) > 0)) { - make_a_mod(mods, LDAP_MOD_ADD, attribute, newval); - } - - if (values == NULL) { - /* There has been no value before, so don't delete it. - Here's a possible race: We might end up with - duplicate attributes */ - return; - } - - /* By deleting exactly the value we found in the entry this - should be race-free in the sense that the LDAP-Server will - deny the complete operation if somebody changed the - attribute behind our back. */ - - make_a_mod(mods, LDAP_MOD_DELETE, attribute, values[0]); - ldap_value_free(values); -} - -/******************************************************************* - Delete complete object or objectclass and attrs from - object found in search_result depending on lp_ldap_delete_dn -******************************************************************/ -static NTSTATUS ldapsam_delete_entry(struct ldapsam_privates *ldap_state, - LDAPMessage *result, - const char *objectclass, - char **attrs) -{ - int rc; - LDAPMessage *entry; - LDAPMod **mods = NULL; - char *name, *dn; - BerElement *ptr = NULL; - - rc = ldap_count_entries(ldap_state->ldap_struct, result); + rc = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result); if (rc != 1) { DEBUG(0, ("Entry must exist exactly once!\n")); return NT_STATUS_UNSUCCESSFUL; } - entry = ldap_first_entry(ldap_state->ldap_struct, result); - dn = ldap_get_dn(ldap_state->ldap_struct, entry); - - if (lp_ldap_delete_dn()) { - NTSTATUS ret = NT_STATUS_OK; - rc = ldapsam_delete(ldap_state, dn); - - if (rc != LDAP_SUCCESS) { - DEBUG(0, ("Could not delete object %s\n", dn)); - ret = NT_STATUS_UNSUCCESSFUL; - } - ldap_memfree(dn); - return ret; - } - - /* Ok, delete only the SAM attributes */ - - for (name = ldap_first_attribute(ldap_state->ldap_struct, entry, &ptr); - name != NULL; - name = ldap_next_attribute(ldap_state->ldap_struct, entry, ptr)) - { - char **attrib; - - /* We are only allowed to delete the attributes that - really exist. */ - - for (attrib = attrs; *attrib != NULL; attrib++) - { - if (StrCaseCmp(*attrib, name) == 0) { - DEBUG(10, ("deleting attribute %s\n", name)); - make_a_mod(&mods, LDAP_MOD_DELETE, name, NULL); - } - } - - ldap_memfree(name); - } - - if (ptr != NULL) { - ber_free(ptr, 0); - } - - make_a_mod(&mods, LDAP_MOD_DELETE, "objectClass", objectclass); - - rc = ldapsam_modify(ldap_state, dn, mods); - ldap_mods_free(mods, 1); - - if (rc != LDAP_SUCCESS) { - char *ld_error = NULL; - ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, - &ld_error); - - DEBUG(0, ("could not delete attributes for %s, error: %s (%s)\n", - dn, ldap_err2string(rc), ld_error?ld_error:"unknown")); - SAFE_FREE(ld_error); - ldap_memfree(dn); - return NT_STATUS_UNSUCCESSFUL; - } - - ldap_memfree(dn); - return NT_STATUS_OK; -} - -/********************************************************************** -Search for the domain info entry -*********************************************************************/ -static int ldapsam_search_domain_info(struct ldapsam_privates *ldap_state, - LDAPMessage ** result) -{ - pstring filter; - int rc; - char **attr_list; - - snprintf(filter, sizeof(filter)-1, "(&(objectClass=%s)(%s=%s))", - LDAP_OBJ_DOMINFO, - get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN), - ldap_state->domain_name); - - DEBUG(2, ("Searching for:[%s]\n", filter)); - - - attr_list = get_attr_list( dominfo_attr_list ); - rc = ldapsam_search_suffix(ldap_state, filter, attr_list , result); - free_attr_list( attr_list ); - - if (rc != LDAP_SUCCESS) { - DEBUG(2,("Problem during LDAPsearch: %s\n", ldap_err2string (rc))); - DEBUG(2,("Query was: %s, %s\n", lp_ldap_suffix(), filter)); - } - - return rc; -} - -/********************************************************************** - If this entry is is the 'allocated' range, extract the RID and return - it, so we can find the 'next' rid to allocate. - - Do this, no matter what type of object holds the RID - be it a user, - group or somthing else. -*********************************************************************/ -static uint32 entry_to_rid(struct ldapsam_privates *ldap_state, LDAPMessage *entry, int rid_type) -{ - pstring sid_string; - DOM_SID dom_sid; - uint32 rid; - - if (!get_single_attribute(ldap_state->ldap_struct, entry, - LDAP_ATTRIBUTE_SID, sid_string)) - { - return 0; - } - - if (!string_to_sid(&dom_sid, sid_string)) { - return 0; - } - - if (!sid_peek_check_rid(&dom_sid, get_global_sam_sid(), &rid)) { - /* not our domain, so we don't care */ - return 0; - } - - switch (rid_type) { - case USER_RID_TYPE: - if (rid >= ldap_state->low_allocated_user_rid && - rid <= ldap_state->high_allocated_user_rid) { - return rid; - } - break; - case GROUP_RID_TYPE: - if (rid >= ldap_state->low_allocated_group_rid && - rid <= ldap_state->high_allocated_group_rid) { - return rid; - } - break; - } - return 0; -} - - -/********************************************************************** -Connect to LDAP server and find the next available 'allocated' RID. - -The search is done 'per type' as we allocate seperate pools for the -EVEN and ODD (user and group) RIDs. - -This is only done once, so that we can fill out the sambaDomain. -*********************************************************************/ -static uint32 search_next_allocated_rid(struct ldapsam_privates *ldap_state, int rid_type) -{ - int rc; - LDAPMessage *result; - LDAPMessage *entry; - uint32 top_rid = 0; - uint32 next_rid; - uint32 count; - uint32 rid; - char *sid_attr[] = {LDAP_ATTRIBUTE_SID, NULL}; - fstring filter; - - snprintf( filter, sizeof(filter)-1, "(%s=*)", LDAP_ATTRIBUTE_SID ); - - DEBUG(2, ("search_top_allocated_rid: searching for:[%s]\n", filter)); - - rc = ldapsam_search_suffix(ldap_state, filter, sid_attr, &result); - - 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(), filter)); - - result = NULL; - return 0; - } - - count = ldap_count_entries(ldap_state->ldap_struct, result); - DEBUG(2, ("search_top_allocated_rid: %d entries in the base!\n", count)); - - if (count == 0) { - DEBUG(3, ("LDAP search returned no records, assuming no allocated RIDs present!: %s\n", ldap_err2string(rc))); - DEBUGADD(3, ("Query was: %s, %s\n", lp_ldap_suffix(), filter)); - } else { - entry = ldap_first_entry(ldap_state->ldap_struct,result); - - top_rid = entry_to_rid(ldap_state, entry, rid_type); - - while ((entry = ldap_next_entry(ldap_state->ldap_struct, entry))) { - - rid = entry_to_rid(ldap_state, entry, rid_type); - if (((rid & ~RID_TYPE_MASK) == rid_type) && (rid > top_rid)) { - top_rid = rid; - } - } - } - - switch (rid_type) { - case USER_RID_TYPE: - if (top_rid < ldap_state->low_allocated_user_rid) { - return ldap_state->low_allocated_user_rid; - } - break; - case GROUP_RID_TYPE: - if (top_rid < ldap_state->low_allocated_group_rid) - return ldap_state->low_allocated_group_rid; - break; - } - - next_rid = (top_rid & ~RID_TYPE_MASK) + rid_type + RID_MULTIPLIER; - - switch (rid_type) { - case USER_RID_TYPE: - if (next_rid > ldap_state->high_allocated_user_rid) { - return 0; - } - break; - case GROUP_RID_TYPE: - if (next_rid > ldap_state->high_allocated_group_rid) { - return 0; - } - break; - } - return next_rid; -} - -/********************************************************************** - Add the sambaDomain to LDAP, so we don't have to search for this stuff - again. This is a once-add operation for now. - - TODO: Add other attributes, and allow modification. -*********************************************************************/ -static NTSTATUS add_new_domain_info(struct ldapsam_privates *ldap_state) -{ - pstring tmp; - pstring filter; - LDAPMod **mods = NULL; - int rc; - int ldap_op; - LDAPMessage *result = NULL; - char *dn = NULL; - int num_result; - char **attr_list; - - uint32 next_allocated_user_rid; - uint32 next_allocated_group_rid; - - next_allocated_user_rid = search_next_allocated_rid(ldap_state, USER_RID_TYPE); - if (!next_allocated_user_rid) { - return NT_STATUS_UNSUCCESSFUL; - } - - next_allocated_group_rid = search_next_allocated_rid(ldap_state, GROUP_RID_TYPE); - if (!next_allocated_group_rid) { - return NT_STATUS_UNSUCCESSFUL; - } - - slprintf (filter, sizeof (filter) - 1, "(&(%s=%s)(objectclass=%s))", - get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN), - ldap_state->domain_name, LDAP_OBJ_DOMINFO); - - attr_list = get_attr_list( dominfo_attr_list ); - rc = ldapsam_search_suffix(ldap_state, filter, attr_list, &result); - free_attr_list( attr_list ); - - if (rc != LDAP_SUCCESS) { - return NT_STATUS_UNSUCCESSFUL; - } - - num_result = ldap_count_entries(ldap_state->ldap_struct, result); - - if (num_result > 1) { - DEBUG (0, ("More than domain with that name exists: bailing out!\n")); - ldap_msgfree(result); - return NT_STATUS_UNSUCCESSFUL; - } - - /* Check if we need to add an entry */ - DEBUG(3,("Adding new domain\n")); - ldap_op = LDAP_MOD_ADD; - asprintf (&dn, "%s=%s,%s", get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN), - ldap_state->domain_name, lp_ldap_suffix()); - - /* Free original search */ - ldap_msgfree(result); - - if (!dn) - return NT_STATUS_NO_MEMORY; - - /* make the changes - the entry *must* not already have samba attributes */ - make_a_mod(&mods, LDAP_MOD_ADD, get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN), - ldap_state->domain_name); - - sid_to_string(tmp, &ldap_state->domain_sid); - make_a_mod(&mods, LDAP_MOD_ADD, get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOM_SID), tmp); - - snprintf(tmp, sizeof(tmp)-1, "%i", next_allocated_user_rid); - make_a_mod(&mods, LDAP_MOD_ADD, get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_USERRID), tmp); - - snprintf(tmp, sizeof(tmp)-1, "%i", next_allocated_group_rid); - make_a_mod(&mods, LDAP_MOD_ADD, get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_GROUPRID), tmp); - - make_a_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_DOMINFO); - - switch(ldap_op) - { - case LDAP_MOD_ADD: - rc = ldapsam_add(ldap_state, dn, mods); - break; - case LDAP_MOD_REPLACE: - rc = ldapsam_modify(ldap_state, dn, mods); - break; - default: - DEBUG(0,("Wrong LDAP operation type: %d!\n", ldap_op)); - return NT_STATUS_INVALID_PARAMETER; - } - - if (rc!=LDAP_SUCCESS) { - char *ld_error = NULL; - ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, - &ld_error); - DEBUG(1, - ("failed to %s domain dn= %s with: %s\n\t%s\n", - ldap_op == LDAP_MOD_ADD ? "add" : "modify", - dn, ldap_err2string(rc), - ld_error?ld_error:"unknown")); - SAFE_FREE(ld_error); - - ldap_mods_free(mods,1); - return NT_STATUS_UNSUCCESSFUL; - } - - DEBUG(2,("added: domain = %s in the LDAP database\n", ldap_state->domain_name)); - ldap_mods_free(mods, 1); - return NT_STATUS_OK; -} - -/********************************************************************** - Even if the sambaAccount attribute in LDAP tells us that this RID is - safe to use, always check before use. -*********************************************************************/ -static BOOL sid_in_use(struct ldapsam_privates *ldap_state, - const DOM_SID *sid, int *error) -{ - fstring filter; - fstring sid_string; - LDAPMessage *result = NULL; - int count; - int rc; - char *sid_attr[] = {LDAP_ATTRIBUTE_SID, NULL}; - - slprintf(filter, sizeof(filter)-1, "(%s=%s)", LDAP_ATTRIBUTE_SID, sid_to_string(sid_string, sid)); - - rc = ldapsam_search_suffix(ldap_state, filter, sid_attr, &result); - - if (rc != LDAP_SUCCESS) { - char *ld_error = NULL; - ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error); - DEBUG(2, ("Failed to check if sid %s is alredy in use: %s\n", - sid_string, ld_error)); - SAFE_FREE(ld_error); - - *error = rc; - return True; - } - - if ((count = ldap_count_entries(ldap_state->ldap_struct, result)) > 0) { - DEBUG(3, ("Sid %s already in use - trying next RID\n", - sid_string)); - ldap_msgfree(result); - return True; - } - - ldap_msgfree(result); - - /* good, sid is not in use */ - return False; -} - -/********************************************************************** - Set the new nextRid attribute, and return one we can use. - - This also checks that this RID is actually free - in case the admin - manually stole it :-). -*********************************************************************/ -static NTSTATUS ldapsam_next_rid(struct ldapsam_privates *ldap_state, uint32 *rid, int rid_type) -{ - NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; - int rc; - LDAPMessage *result = NULL; - LDAPMessage *entry = NULL; - char *dn; - LDAPMod **mods = NULL; - int count; - fstring old_rid_string; - fstring next_rid_string; - uint32 next_rid; - int attempts = 0; - - if ( ldap_state->schema_ver != SCHEMAVER_SAMBASAMACCOUNT ) { - DEBUG(0, ("Allocated RIDs require the %s objectclass used by 'ldapsam'\n", - LDAP_OBJ_SAMBASAMACCOUNT)); - return NT_STATUS_UNSUCCESSFUL; - } - - while (attempts < 10) - { - char *ld_error; - if (ldapsam_search_domain_info(ldap_state, &result)) { - return ret; - } - - if (ldap_count_entries(ldap_state->ldap_struct, result) < 1) { - DEBUG(3, ("Got no domain info entries for domain %s\n", - ldap_state->domain_name)); - ldap_msgfree(result); - if (NT_STATUS_IS_OK(ret = add_new_domain_info(ldap_state))) { - continue; - } else { - DEBUG(0, ("Adding domain info failed with %s\n", nt_errstr(ret))); - return ret; - } - } - - if ((count = ldap_count_entries(ldap_state->ldap_struct, result)) > 1) { - DEBUG(0, ("Got too many (%d) domain info entries for domain %s\n", - count, ldap_state->domain_name)); - ldap_msgfree(result); - return ret; - } - - entry = ldap_first_entry(ldap_state->ldap_struct, result); - if (!entry) { - ldap_msgfree(result); - return ret; - } - - if ((dn = ldap_get_dn(ldap_state->ldap_struct, entry)) == NULL) { - DEBUG(0, ("Could not get domain info DN\n")); - ldap_msgfree(result); - return ret; - } - - /* yes, we keep 2 seperate counters, to avoid stomping on the two - different sets of algorithmic RIDs */ - - switch (rid_type) { - case USER_RID_TYPE: - if (!get_single_attribute(ldap_state->ldap_struct, entry, - get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_USERRID), - old_rid_string)) - { - ldap_memfree(dn); - ldap_msgfree(result); - return ret; - } - break; - case GROUP_RID_TYPE: - if (!get_single_attribute(ldap_state->ldap_struct, entry, - get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_GROUPRID), - old_rid_string)) - { - ldap_memfree(dn); - ldap_msgfree(result); - return ret; - } - break; - } - - /* This is the core of the whole routine. If we had - scheme-style closures, there would be a *lot* less code - duplication... */ - *rid = (uint32)atol(old_rid_string); - next_rid = *rid+RID_MULTIPLIER; - - slprintf(next_rid_string, sizeof(next_rid_string)-1, "%d", next_rid); - - switch (rid_type) { - case USER_RID_TYPE: - if (next_rid > ldap_state->high_allocated_user_rid) { - return NT_STATUS_UNSUCCESSFUL; - } - - /* Try to make the modification atomically by enforcing the - old value in the delete mod. */ - make_ldap_mod(ldap_state->ldap_struct, entry, &mods, - get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_USERRID), - next_rid_string); - break; - - case GROUP_RID_TYPE: - if (next_rid > ldap_state->high_allocated_group_rid) { - return NT_STATUS_UNSUCCESSFUL; - } - - /* Try to make the modification atomically by enforcing the - old value in the delete mod. */ - make_ldap_mod(ldap_state->ldap_struct, entry, &mods, - get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_GROUPRID), - next_rid_string); - break; - } - - if ((rc = ldap_modify_s(ldap_state->ldap_struct, dn, mods)) == LDAP_SUCCESS) { - DOM_SID dom_sid; - DOM_SID sid; - pstring domain_sid_string; - int error = 0; - - if (!get_single_attribute(ldap_state->ldap_struct, result, - get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOM_SID), - domain_sid_string)) - { - ldap_mods_free(mods, 1); - ldap_memfree(dn); - ldap_msgfree(result); - return ret; - } + entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result); + dn = ldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry); - if (!string_to_sid(&dom_sid, domain_sid_string)) { - ldap_mods_free(mods, 1); - ldap_memfree(dn); - ldap_msgfree(result); - return ret; - } + if (lp_ldap_delete_dn()) { + NTSTATUS ret = NT_STATUS_OK; + rc = smbldap_delete(ldap_state->smbldap_state, dn); - ldap_mods_free(mods, 1); - mods = NULL; - ldap_memfree(dn); - ldap_msgfree(result); + if (rc != LDAP_SUCCESS) { + DEBUG(0, ("Could not delete object %s\n", dn)); + ret = NT_STATUS_UNSUCCESSFUL; + } + ldap_memfree(dn); + return ret; + } + + /* Ok, delete only the SAM attributes */ + + for (name = ldap_first_attribute(ldap_state->smbldap_state->ldap_struct, entry, &ptr); + name != NULL; + name = ldap_next_attribute(ldap_state->smbldap_state->ldap_struct, entry, ptr)) + { + char **attrib; - sid_copy(&sid, &dom_sid); - sid_append_rid(&sid, *rid); + /* We are only allowed to delete the attributes that + really exist. */ - /* check RID is not in use */ - if (sid_in_use(ldap_state, &sid, &error)) { - if (error) { - return ret; - } - continue; + for (attrib = attrs; *attrib != NULL; attrib++) + { + if (StrCaseCmp(*attrib, name) == 0) { + DEBUG(10, ("deleting attribute %s\n", name)); + smbldap_set_mod(&mods, LDAP_MOD_DELETE, name, NULL); } - - return NT_STATUS_OK; } - ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error); - DEBUG(2, ("Failed to modify rid: %s\n", ld_error)); - SAFE_FREE(ld_error); + ldap_memfree(name); + } + + if (ptr != NULL) { + ber_free(ptr, 0); + } + + smbldap_set_mod(&mods, LDAP_MOD_DELETE, "objectClass", objectclass); - ldap_mods_free(mods, 1); - mods = NULL; + rc = smbldap_modify(ldap_state->smbldap_state, dn, mods); + ldap_mods_free(mods, True); + if (rc != LDAP_SUCCESS) { + char *ld_error = NULL; + ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, + &ld_error); + + DEBUG(0, ("could not delete attributes for %s, error: %s (%s)\n", + dn, ldap_err2string(rc), ld_error?ld_error:"unknown")); + SAFE_FREE(ld_error); ldap_memfree(dn); - dn = NULL; - - ldap_msgfree(result); - result = NULL; - - { - /* Sleep for a random timeout */ - unsigned sleeptime = (sys_random()*sys_getpid()*attempts); - attempts += 1; - - sleeptime %= 100; - msleep(sleeptime); - } + return NT_STATUS_UNSUCCESSFUL; } - DEBUG(0, ("Failed to set new RID\n")); - return ret; + ldap_memfree(dn); + return NT_STATUS_OK; } + /* New Interface is being implemented here */ @@ -1840,7 +346,7 @@ static BOOL get_unix_attributes (struct ldapsam_privates *ldap_state, char **ldap_values; char **values; - if ((ldap_values = ldap_get_values (ldap_state->ldap_struct, entry, "objectClass")) == NULL) { + if ((ldap_values = ldap_get_values (ldap_state->smbldap_state->ldap_struct, entry, "objectClass")) == NULL) { DEBUG (1, ("get_unix_attributes: no objectClass! \n")); return False; } @@ -1858,13 +364,13 @@ static BOOL get_unix_attributes (struct ldapsam_privates *ldap_state, } ldap_value_free(ldap_values); - if ( !get_single_attribute(ldap_state->ldap_struct, entry, + if ( !smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_UNIX_HOME), homedir) ) { return False; } - if ( !get_single_attribute(ldap_state->ldap_struct, entry, + if ( !smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_GIDNUMBER), temp) ) { return False; @@ -1937,12 +443,12 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, return False; } - if (ldap_state->ldap_struct == NULL) { - DEBUG(0, ("init_sam_from_ldap: ldap_state->ldap_struct is NULL!\n")); + if (ldap_state->smbldap_state->ldap_struct == NULL) { + DEBUG(0, ("init_sam_from_ldap: ldap_state->smbldap_state->ldap_struct is NULL!\n")); return False; } - if (!get_single_attribute(ldap_state->ldap_struct, entry, "uid", username)) { + if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, "uid", username)) { DEBUG(1, ("No uid attribute found for this user!\n")); return False; } @@ -1962,13 +468,13 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, if ( ldap_state->schema_ver == SCHEMAVER_SAMBASAMACCOUNT ) { - if (get_single_attribute(ldap_state->ldap_struct, entry, + if (smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID), temp)) { pdb_set_user_sid_from_string(sampass, temp, PDB_SET); } - if (get_single_attribute(ldap_state->ldap_struct, entry, + if (smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PRIMARY_GROUP_SID), temp)) { pdb_set_group_sid_from_string(sampass, temp, PDB_SET); @@ -1982,14 +488,14 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, } else { - if (get_single_attribute(ldap_state->ldap_struct, entry, + if (smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_RID), temp)) { user_rid = (uint32)atol(temp); pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET); } - if (!get_single_attribute(ldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PRIMARY_GROUP_RID), temp)) { pdb_set_group_sid_from_rid(sampass, DOMAIN_GROUP_RID_USERS, PDB_DEFAULT); @@ -2027,7 +533,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, { GROUP_MAP map; /* call the mapping code here */ - if(pdb_getgrgid(&map, gid, MAPPING_WITHOUT_PRIV)) { + if(pdb_getgrgid(&map, gid)) { pdb_set_group_sid(sampass, &map.sid, PDB_SET); } else { @@ -2036,7 +542,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, } } - if (!get_single_attribute(ldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_LAST_SET), temp)) { /* leave as default */ @@ -2045,7 +551,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET); } - if (!get_single_attribute(ldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGON_TIME), temp)) { /* leave as default */ @@ -2054,7 +560,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, pdb_set_logon_time(sampass, logon_time, PDB_SET); } - if (!get_single_attribute(ldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGOFF_TIME), temp)) { /* leave as default */ @@ -2063,7 +569,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, pdb_set_logoff_time(sampass, logoff_time, PDB_SET); } - if (!get_single_attribute(ldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_KICKOFF_TIME), temp)) { /* leave as default */ @@ -2072,7 +578,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET); } - if (!get_single_attribute(ldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_CAN_CHANGE), temp)) { /* leave as default */ @@ -2081,7 +587,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET); } - if (!get_single_attribute(ldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_MUST_CHANGE), temp)) { /* leave as default */ @@ -2096,10 +602,10 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, * that fits your needs; using cn then displayName rather than 'userFullName' */ - if (!get_single_attribute(ldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_DISPLAY_NAME), fullname)) { - if (!get_single_attribute(ldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_CN), fullname)) { /* leave as default */ @@ -2110,7 +616,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, pdb_set_fullname(sampass, fullname, PDB_SET); } - if (!get_single_attribute(ldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_HOME_DRIVE), dir_drive)) { pdb_set_dir_drive(sampass, talloc_sub_specified(sampass->mem_ctx, @@ -2122,7 +628,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, pdb_set_dir_drive(sampass, dir_drive, PDB_SET); } - if (!get_single_attribute(ldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_HOME_PATH), homedir)) { pdb_set_homedir(sampass, talloc_sub_specified(sampass->mem_ctx, @@ -2134,7 +640,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, pdb_set_homedir(sampass, homedir, PDB_SET); } - if (!get_single_attribute(ldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGON_SCRIPT), logon_script)) { pdb_set_logon_script(sampass, talloc_sub_specified(sampass->mem_ctx, @@ -2146,7 +652,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, pdb_set_logon_script(sampass, logon_script, PDB_SET); } - if (!get_single_attribute(ldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PROFILE_PATH), profile_path)) { pdb_set_profile_path(sampass, talloc_sub_specified(sampass->mem_ctx, @@ -2158,7 +664,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, pdb_set_profile_path(sampass, profile_path, PDB_SET); } - if (!get_single_attribute(ldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_DESC), acct_desc)) { /* leave as default */ @@ -2166,7 +672,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, pdb_set_acct_desc(sampass, acct_desc, PDB_SET); } - if (!get_single_attribute(ldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_WKS), workstations)) { /* leave as default */; @@ -2180,7 +686,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, hours_len = 21; memset(hours, 0xff, hours_len); - if (!get_single_attribute (ldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute (ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LMPW), temp)) { /* leave as default */ @@ -2192,7 +698,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, ZERO_STRUCT(smblmpwd); } - if (!get_single_attribute (ldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute (ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_NTPW), temp)) { /* leave as default */ @@ -2204,7 +710,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, ZERO_STRUCT(smbntpwd); } - if (!get_single_attribute (ldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute (ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_ACB_INFO), temp)) { acct_ctrl |= ACB_NORMAL; @@ -2256,39 +762,11 @@ static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state, * do this on a per-mod basis */ if (need_update(sampass, PDB_USERNAME)) - make_ldap_mod(ldap_state->ldap_struct, existing, mods, + smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods, "uid", pdb_get_username(sampass)); DEBUG(2, ("Setting entry for user: %s\n", pdb_get_username(sampass))); - if (pdb_get_init_flags(sampass, PDB_USERSID) == PDB_DEFAULT) { - if (ldap_state->permit_non_unix_accounts) { - if (!NT_STATUS_IS_OK(ldapsam_next_rid(ldap_state, &rid, USER_RID_TYPE))) { - DEBUG(0, ("NO user RID specified on account %s, and " - "finding next available NUA RID failed, " - "cannot store!\n", - pdb_get_username(sampass))); - ldap_mods_free(*mods, 1); - return False; - } - } else { - DEBUG(0, ("NO user RID specified on account %s, " - "cannot store!\n", pdb_get_username(sampass))); - ldap_mods_free(*mods, 1); - return False; - } - - /* now that we have figured out the RID, always store it, as - the schema requires it (either as a SID or a RID) */ - - if (!pdb_set_user_sid_from_rid(sampass, rid, PDB_CHANGED)) { - DEBUG(0, ("Could not store RID back onto SAM_ACCOUNT for user %s!\n", - pdb_get_username(sampass))); - ldap_mods_free(*mods, 1); - return False; - } - } - /* only update the RID if we actually need to */ if (need_update(sampass, PDB_USERSID)) { @@ -2299,20 +777,20 @@ static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state, switch ( ldap_state->schema_ver ) { case SCHEMAVER_SAMBAACCOUNT: - if (!sid_peek_check_rid(get_global_sam_sid(), user_sid, &rid)) { + if (!sid_peek_check_rid(&ldap_state->domain_sid, user_sid, &rid)) { DEBUG(1, ("User's SID (%s) is not for this domain (%s), cannot add to LDAP!\n", sid_to_string(sid_string, user_sid), - sid_to_string(dom_sid_string, get_global_sam_sid()))); + sid_to_string(dom_sid_string, &ldap_state->domain_sid))); return False; } slprintf(temp, sizeof(temp) - 1, "%i", rid); - make_ldap_mod(ldap_state->ldap_struct, existing, mods, + smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_RID), temp); break; case SCHEMAVER_SAMBASAMACCOUNT: - make_ldap_mod(ldap_state->ldap_struct, existing, mods, + smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID), sid_to_string(sid_string, user_sid)); break; @@ -2335,21 +813,21 @@ static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state, switch ( ldap_state->schema_ver ) { case SCHEMAVER_SAMBAACCOUNT: - if (!sid_peek_check_rid(get_global_sam_sid(), group_sid, &rid)) { + if (!sid_peek_check_rid(&ldap_state->domain_sid, group_sid, &rid)) { DEBUG(1, ("User's Primary Group SID (%s) is not for this domain (%s), cannot add to LDAP!\n", sid_to_string(sid_string, group_sid), - sid_to_string(dom_sid_string, get_global_sam_sid()))); + sid_to_string(dom_sid_string, &ldap_state->domain_sid))); return False; } slprintf(temp, sizeof(temp) - 1, "%i", rid); - make_ldap_mod(ldap_state->ldap_struct, existing, mods, + smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PRIMARY_GROUP_RID), temp); break; case SCHEMAVER_SAMBASAMACCOUNT: - make_ldap_mod(ldap_state->ldap_struct, existing, mods, + smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PRIMARY_GROUP_SID), sid_to_string(sid_string, group_sid)); break; @@ -2370,63 +848,63 @@ static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state, */ if (need_update(sampass, PDB_FULLNAME)) - make_ldap_mod(ldap_state->ldap_struct, existing, mods, + smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_DISPLAY_NAME), pdb_get_fullname(sampass)); if (need_update(sampass, PDB_ACCTDESC)) - make_ldap_mod(ldap_state->ldap_struct, existing, mods, + smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_DESC), pdb_get_acct_desc(sampass)); if (need_update(sampass, PDB_WORKSTATIONS)) - make_ldap_mod(ldap_state->ldap_struct, existing, mods, + smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_WKS), pdb_get_workstations(sampass)); if (need_update(sampass, PDB_SMBHOME)) - make_ldap_mod(ldap_state->ldap_struct, existing, mods, + smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_HOME_PATH), pdb_get_homedir(sampass)); if (need_update(sampass, PDB_DRIVE)) - make_ldap_mod(ldap_state->ldap_struct, existing, mods, + smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_HOME_DRIVE), pdb_get_dir_drive(sampass)); if (need_update(sampass, PDB_LOGONSCRIPT)) - make_ldap_mod(ldap_state->ldap_struct, existing, mods, + smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGON_SCRIPT), pdb_get_logon_script(sampass)); if (need_update(sampass, PDB_PROFILE)) - make_ldap_mod(ldap_state->ldap_struct, existing, mods, + smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PROFILE_PATH), pdb_get_profile_path(sampass)); slprintf(temp, sizeof(temp) - 1, "%li", pdb_get_logon_time(sampass)); if (need_update(sampass, PDB_LOGONTIME)) - make_ldap_mod(ldap_state->ldap_struct, existing, mods, + smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGON_TIME), temp); slprintf(temp, sizeof(temp) - 1, "%li", pdb_get_logoff_time(sampass)); if (need_update(sampass, PDB_LOGOFFTIME)) - make_ldap_mod(ldap_state->ldap_struct, existing, mods, + smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGOFF_TIME), temp); slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_kickoff_time(sampass)); if (need_update(sampass, PDB_KICKOFFTIME)) - make_ldap_mod(ldap_state->ldap_struct, existing, mods, + smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_KICKOFF_TIME), temp); slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_can_change_time(sampass)); if (need_update(sampass, PDB_CANCHANGETIME)) - make_ldap_mod(ldap_state->ldap_struct, existing, mods, + smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_CAN_CHANGE), temp); slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_must_change_time(sampass)); if (need_update(sampass, PDB_MUSTCHANGETIME)) - make_ldap_mod(ldap_state->ldap_struct, existing, mods, + smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_MUST_CHANGE), temp); if ((pdb_get_acct_ctrl(sampass)&(ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST)) @@ -2437,7 +915,7 @@ static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state, pdb_get_acct_ctrl(sampass)); if (need_update(sampass, PDB_LMPASSWD)) - make_ldap_mod(ldap_state->ldap_struct, existing, mods, + smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LMPW), temp); @@ -2445,13 +923,13 @@ static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state, pdb_get_acct_ctrl(sampass)); if (need_update(sampass, PDB_NTPASSWD)) - make_ldap_mod(ldap_state->ldap_struct, existing, mods, + smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_NTPW), temp); slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_last_set_time(sampass)); if (need_update(sampass, PDB_PASSLASTSET)) - make_ldap_mod(ldap_state->ldap_struct, existing, mods, + smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_LAST_SET), temp); } @@ -2459,7 +937,7 @@ static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state, /* FIXME: Hours stuff goes in LDAP */ if (need_update(sampass, PDB_ACCTCTRL)) - make_ldap_mod(ldap_state->ldap_struct, existing, mods, + smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_ACB_INFO), pdb_encode_acct_ctrl (pdb_get_acct_ctrl(sampass), NEW_PW_FORMAT_SPACE_PADDED_LEN)); @@ -2483,7 +961,8 @@ static NTSTATUS ldapsam_setsampwent(struct pdb_methods *my_methods, BOOL update) all_string_sub(filter, "%u", "*", sizeof(pstring)); attr_list = get_userattr_list(ldap_state->schema_ver); - rc = ldapsam_search_suffix(ldap_state, filter, attr_list, &ldap_state->result); + rc = smbldap_search_suffix(ldap_state->smbldap_state, filter, + attr_list, &ldap_state->result); free_attr_list( attr_list ); if (rc != LDAP_SUCCESS) { @@ -2495,10 +974,10 @@ static NTSTATUS ldapsam_setsampwent(struct pdb_methods *my_methods, BOOL update) } DEBUG(2, ("ldapsam_setsampwent: %d entries in the base!\n", - ldap_count_entries(ldap_state->ldap_struct, + ldap_count_entries(ldap_state->smbldap_state->ldap_struct, ldap_state->result))); - ldap_state->entry = ldap_first_entry(ldap_state->ldap_struct, + ldap_state->entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, ldap_state->result); ldap_state->index = 0; @@ -2526,10 +1005,6 @@ static NTSTATUS ldapsam_getsampwent(struct pdb_methods *my_methods, SAM_ACCOUNT struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data; BOOL bret = False; - /* The rebind proc needs this *HACK*. We are not multithreaded, so - this will work, but it's not nice. */ - static_ldap_state = ldap_state; - while (!bret) { if (!ldap_state->entry) return ret; @@ -2537,7 +1012,7 @@ static NTSTATUS ldapsam_getsampwent(struct pdb_methods *my_methods, SAM_ACCOUNT ldap_state->index++; bret = init_sam_from_ldap(ldap_state, user, ldap_state->entry); - ldap_state->entry = ldap_next_entry(ldap_state->ldap_struct, + ldap_state->entry = ldap_next_entry(ldap_state->smbldap_state->ldap_struct, ldap_state->entry); } @@ -2564,28 +1039,32 @@ static NTSTATUS ldapsam_getsampwnam(struct pdb_methods *my_methods, SAM_ACCOUNT if ( rc != LDAP_SUCCESS ) return NT_STATUS_NO_SUCH_USER; - count = ldap_count_entries(ldap_state->ldap_struct, result); + count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result); if (count < 1) { DEBUG(4, ("Unable to locate user [%s] count=%d\n", sname, count)); + ldap_msgfree(result); return NT_STATUS_NO_SUCH_USER; } else if (count > 1) { DEBUG(1, ("Duplicate entries for this user [%s] Failing. count=%d\n", sname, count)); + ldap_msgfree(result); return NT_STATUS_NO_SUCH_USER; } - entry = ldap_first_entry(ldap_state->ldap_struct, result); + entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result); if (entry) { if (!init_sam_from_ldap(ldap_state, user, entry)) { DEBUG(1,("ldapsam_getsampwnam: init_sam_from_ldap failed for user '%s'!\n", sname)); ldap_msgfree(result); return NT_STATUS_NO_SUCH_USER; } - ldap_msgfree(result); + pdb_set_backend_private_data(user, result, + private_data_free_fn, + my_methods, PDB_CHANGED); ret = NT_STATUS_OK; } else { ldap_msgfree(result); @@ -2593,55 +1072,65 @@ static NTSTATUS ldapsam_getsampwnam(struct pdb_methods *my_methods, SAM_ACCOUNT return ret; } -/********************************************************************** -Get SAM_ACCOUNT entry from LDAP by SID -*********************************************************************/ -static NTSTATUS ldapsam_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUNT * user, const DOM_SID *sid) +static int ldapsam_get_ldap_user_by_sid(struct ldapsam_privates *ldap_state, + const DOM_SID *sid, LDAPMessage **result) { - NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; - struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data; - LDAPMessage *result; - LDAPMessage *entry; - fstring sid_string; - int count; - int rc; + int rc = -1; char ** attr_list; - + uint32 rid; + switch ( ldap_state->schema_ver ) { case SCHEMAVER_SAMBASAMACCOUNT: attr_list = get_userattr_list(ldap_state->schema_ver); - rc = ldapsam_search_suffix_by_sid(ldap_state, sid, &result, attr_list); + rc = ldapsam_search_suffix_by_sid(ldap_state, sid, result, attr_list); free_attr_list( attr_list ); if ( rc != LDAP_SUCCESS ) - return NT_STATUS_NO_SUCH_USER; + return rc; break; case SCHEMAVER_SAMBAACCOUNT: - { - uint32 rid; - if (!sid_peek_check_rid(get_global_sam_sid(), sid, &rid)) { - return NT_STATUS_NO_SUCH_USER; + if (!sid_peek_check_rid(&ldap_state->domain_sid, sid, &rid)) { + return rc; } attr_list = get_userattr_list(ldap_state->schema_ver); - rc = ldapsam_search_suffix_by_rid(ldap_state, rid, &result, attr_list ); + rc = ldapsam_search_suffix_by_rid(ldap_state, rid, result, attr_list ); free_attr_list( attr_list ); if ( rc != LDAP_SUCCESS ) - return NT_STATUS_NO_SUCH_USER; - } - break; + return rc; + break; } - - count = ldap_count_entries(ldap_state->ldap_struct, result); + return rc; +} + +/********************************************************************** +Get SAM_ACCOUNT entry from LDAP by SID +*********************************************************************/ +static NTSTATUS ldapsam_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUNT * user, const DOM_SID *sid) +{ + struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data; + LDAPMessage *result; + LDAPMessage *entry; + int count; + int rc; + fstring sid_string; + + rc = ldapsam_get_ldap_user_by_sid(ldap_state, + sid, &result); + if (rc != LDAP_SUCCESS) + return NT_STATUS_NO_SUCH_USER; + + count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result); if (count < 1) { DEBUG(4, ("Unable to locate SID [%s] count=%d\n", sid_to_string(sid_string, sid), count)); + ldap_msgfree(result); return NT_STATUS_NO_SUCH_USER; } else if (count > 1) @@ -2649,23 +1138,27 @@ static NTSTATUS ldapsam_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUNT DEBUG(1, ("More than one user with SID [%s]. Failing. count=%d\n", sid_to_string(sid_string, sid), count)); + ldap_msgfree(result); return NT_STATUS_NO_SUCH_USER; } - entry = ldap_first_entry(ldap_state->ldap_struct, result); - if (entry) + entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result); + if (!entry) { - if (!init_sam_from_ldap(ldap_state, user, entry)) { - DEBUG(1,("ldapsam_getsampwrid: init_sam_from_ldap failed!\n")); - ldap_msgfree(result); - return NT_STATUS_NO_SUCH_USER; - } ldap_msgfree(result); - ret = NT_STATUS_OK; - } else { + return NT_STATUS_NO_SUCH_USER; + } + + if (!init_sam_from_ldap(ldap_state, user, entry)) { + DEBUG(1,("ldapsam_getsampwrid: init_sam_from_ldap failed!\n")); ldap_msgfree(result); + return NT_STATUS_NO_SUCH_USER; } - return ret; + + pdb_set_backend_private_data(user, result, + private_data_free_fn, + my_methods, PDB_CHANGED); + return NT_STATUS_OK; } /******************************************************************** @@ -2693,20 +1186,25 @@ static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods, switch(ldap_op) { case LDAP_MOD_ADD: - make_a_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_ACCOUNT); - rc = ldapsam_add(ldap_state, dn, mods); + smbldap_set_mod(&mods, LDAP_MOD_ADD, + "objectclass", + LDAP_OBJ_ACCOUNT); + rc = smbldap_add(ldap_state->smbldap_state, + dn, mods); break; case LDAP_MOD_REPLACE: - rc = ldapsam_modify(ldap_state, dn ,mods); + rc = smbldap_modify(ldap_state->smbldap_state, + dn ,mods); break; default: - DEBUG(0,("Wrong LDAP operation type: %d!\n", ldap_op)); + DEBUG(0,("Wrong LDAP operation type: %d!\n", + ldap_op)); return NT_STATUS_INVALID_PARAMETER; } if (rc!=LDAP_SUCCESS) { char *ld_error = NULL; - ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, + ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error); DEBUG(1, ("failed to %s user dn= %s with: %s\n\t%s\n", @@ -2718,7 +1216,6 @@ static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods, } } -#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) && need_update(newpwd, PDB_PLAINTEXT_PW) && @@ -2745,8 +1242,8 @@ static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods, } ber_printf (ber, "{"); - ber_printf (ber, "ts", LDAP_TAG_EXOP_X_MODIFY_PASSWD_ID, utf8_dn); - ber_printf (ber, "ts", LDAP_TAG_EXOP_X_MODIFY_PASSWD_NEW, utf8_password); + ber_printf (ber, "ts", LDAP_TAG_EXOP_MODIFY_PASSWD_ID, utf8_dn); + ber_printf (ber, "ts", LDAP_TAG_EXOP_MODIFY_PASSWD_NEW, utf8_password); ber_printf (ber, "N}"); if ((rc = ber_flatten (ber, &bv))<0) { @@ -2761,8 +1258,10 @@ static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods, SAFE_FREE(utf8_password); ber_free(ber, 1); - if ((rc = ldapsam_extended_operation(ldap_state, LDAP_EXOP_X_MODIFY_PASSWD, - bv, NULL, NULL, &retoid, &retdata))!=LDAP_SUCCESS) { + if ((rc = smbldap_extended_operation(ldap_state->smbldap_state, + LDAP_EXOP_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 { @@ -2775,9 +1274,6 @@ static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods, } ber_bvfree(bv); } -#else - DEBUG(10,("LDAP PASSWORD SYNC is not supported!\n")); -#endif /* LDAP_EXOP_X_MODIFY_PASSWD */ return NT_STATUS_OK; } @@ -2857,43 +1353,46 @@ static NTSTATUS ldapsam_update_sam_account(struct pdb_methods *my_methods, SAM_A LDAPMod **mods; char **attr_list; - attr_list = get_userattr_list(ldap_state->schema_ver); - rc = ldapsam_search_suffix_by_name(ldap_state, pdb_get_username(newpwd), &result, attr_list ); - free_attr_list( attr_list ); - if (rc != LDAP_SUCCESS) - return NT_STATUS_UNSUCCESSFUL; + result = pdb_get_backend_private_data(newpwd, my_methods); + if (!result) { + attr_list = get_userattr_list(ldap_state->schema_ver); + rc = ldapsam_search_suffix_by_name(ldap_state, pdb_get_username(newpwd), &result, attr_list ); + free_attr_list( attr_list ); + if (rc != LDAP_SUCCESS) { + return NT_STATUS_UNSUCCESSFUL; + } + pdb_set_backend_private_data(newpwd, result, private_data_free_fn, my_methods, PDB_CHANGED); + } - if (ldap_count_entries(ldap_state->ldap_struct, result) == 0) { + if (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result) == 0) { DEBUG(0, ("No user to modify!\n")); - ldap_msgfree(result); return NT_STATUS_UNSUCCESSFUL; } - entry = ldap_first_entry(ldap_state->ldap_struct, result); - dn = ldap_get_dn(ldap_state->ldap_struct, entry); + entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result); + dn = ldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry); + + DEBUG(4, ("user %s to be modified has dn: %s\n", pdb_get_username(newpwd), dn)); if (!init_ldap_from_sam(ldap_state, entry, &mods, newpwd, element_is_changed)) { DEBUG(0, ("ldapsam_update_sam_account: init_ldap_from_sam failed!\n")); - ldap_msgfree(result); return NT_STATUS_UNSUCCESSFUL; } - ldap_msgfree(result); - if (mods == NULL) { DEBUG(4,("mods is empty: nothing to update for user: %s\n", pdb_get_username(newpwd))); - ldap_mods_free(mods, 1); + ldap_mods_free(mods, True); return NT_STATUS_OK; } ret = ldapsam_modify_entry(my_methods,newpwd,dn,mods,LDAP_MOD_REPLACE, element_is_changed); - ldap_mods_free(mods,1); + ldap_mods_free(mods,True); if (!NT_STATUS_IS_OK(ret)) { char *ld_error = NULL; - ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, + ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error); DEBUG(0,("failed to modify user with uid = %s, error: %s (%s)\n", pdb_get_username(newpwd), ld_error?ld_error:"(unknwon)", ldap_err2string(rc))); @@ -2935,7 +1434,9 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCO char **attr_list; char *escape_user; const char *username = pdb_get_username(newpwd); + const DOM_SID *sid = pdb_get_user_sid(newpwd); pstring filter; + fstring sid_string; if (!username || !*username) { DEBUG(0, ("Cannot add user without a username!\n")); @@ -2943,8 +1444,8 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCO } /* free this list after the second search or in case we exit on failure */ - attr_list = get_userattr_list(ldap_state->schema_ver); + rc = ldapsam_search_suffix_by_name (ldap_state, username, &result, attr_list); if (rc != LDAP_SUCCESS) { @@ -2952,7 +1453,7 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCO return NT_STATUS_UNSUCCESSFUL; } - if (ldap_count_entries(ldap_state->ldap_struct, result) != 0) { + if (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result) != 0) { DEBUG(0,("User '%s' already in the base, with samba attributes\n", username)); ldap_msgfree(result); @@ -2960,25 +1461,42 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCO return NT_STATUS_UNSUCCESSFUL; } ldap_msgfree(result); + result = NULL; + + if (element_is_set_or_changed(newpwd, PDB_USERSID)) { + rc = ldapsam_get_ldap_user_by_sid(ldap_state, + sid, &result); + if (rc == LDAP_SUCCESS) { + if (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result) != 0) { + DEBUG(0,("SID '%s' already in the base, with samba attributes\n", + sid_to_string(sid_string, sid))); + free_attr_list( attr_list ); + return NT_STATUS_UNSUCCESSFUL; + } + ldap_msgfree(result); + } + } - /* does the entry already exist but without a samba rttibutes? - we don't really care what attributes are returned here */ + /* does the entry already exist but without a samba attributes? + we need to return the samba attributes here */ escape_user = escape_ldap_string_alloc( username ); pstrcpy( filter, lp_ldap_filter() ); all_string_sub( filter, "%u", escape_user, sizeof(filter) ); SAFE_FREE( escape_user ); - rc = ldapsam_search_suffix(ldap_state, filter, attr_list, &result); - free_attr_list( attr_list ); - - if ( rc != LDAP_SUCCESS ) + rc = smbldap_search_suffix(ldap_state->smbldap_state, + filter, attr_list, &result); + if ( rc != LDAP_SUCCESS ) { + free_attr_list( attr_list ); return NT_STATUS_UNSUCCESSFUL; + } - num_result = ldap_count_entries(ldap_state->ldap_struct, result); + num_result = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result); if (num_result > 1) { DEBUG (0, ("More than one user with that uid exists: bailing out!\n")); + free_attr_list( attr_list ); ldap_msgfree(result); return NT_STATUS_UNSUCCESSFUL; } @@ -2989,19 +1507,62 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCO DEBUG(3,("User exists without samba attributes: adding them\n")); ldap_op = LDAP_MOD_REPLACE; - entry = ldap_first_entry (ldap_state->ldap_struct, result); - tmp = ldap_get_dn (ldap_state->ldap_struct, entry); + entry = ldap_first_entry (ldap_state->smbldap_state->ldap_struct, result); + tmp = ldap_get_dn (ldap_state->smbldap_state->ldap_struct, entry); slprintf (dn, sizeof (dn) - 1, "%s", tmp); ldap_memfree (tmp); - } else { + + } else if (ldap_state->schema_ver == SCHEMAVER_SAMBASAMACCOUNT) { + + /* There might be a SID for this account already - say an idmap entry */ + + snprintf(filter, sizeof(filter)-1, "(&(%s=%s)(|(objectClass=%s)(objectClass=%s)))", + get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID), + sid_to_string(sid_string, sid), + LDAP_OBJ_IDMAP_ENTRY, + LDAP_OBJ_SID_ENTRY); + + rc = smbldap_search_suffix(ldap_state->smbldap_state, + filter, attr_list, &result); + + if ( rc != LDAP_SUCCESS ) { + free_attr_list( attr_list ); + return NT_STATUS_UNSUCCESSFUL; + } + + num_result = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result); + + if (num_result > 1) { + DEBUG (0, ("More than one user with that uid exists: bailing out!\n")); + free_attr_list( attr_list ); + ldap_msgfree(result); + return NT_STATUS_UNSUCCESSFUL; + } + + /* Check if we need to update an existing entry */ + if (num_result == 1) { + char *tmp; + + DEBUG(3,("User exists without samba attributes: adding them\n")); + ldap_op = LDAP_MOD_REPLACE; + entry = ldap_first_entry (ldap_state->smbldap_state->ldap_struct, result); + tmp = ldap_get_dn (ldap_state->smbldap_state->ldap_struct, entry); + slprintf (dn, sizeof (dn) - 1, "%s", tmp); + ldap_memfree (tmp); + } + } + + free_attr_list( attr_list ); + + if (num_result == 0) { /* Check if we need to add an entry */ DEBUG(3,("Adding new user\n")); ldap_op = LDAP_MOD_ADD; if (username[strlen(username)-1] == '$') { - slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_machine_suffix ()); - } else { - slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_user_suffix ()); - } + slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_machine_suffix ()); + } else { + slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_user_suffix ()); + } } if (!init_ldap_from_sam(ldap_state, entry, &mods, newpwd, @@ -3020,10 +1581,10 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCO switch ( ldap_state->schema_ver ) { case SCHEMAVER_SAMBAACCOUNT: - make_a_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_SAMBAACCOUNT); + smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_SAMBAACCOUNT); break; case SCHEMAVER_SAMBASAMACCOUNT: - make_a_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_SAMBASAMACCOUNT); + smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_SAMBASAMACCOUNT); break; default: DEBUG(0,("ldapsam_add_sam_account: invalid schema version specified\n")); @@ -3031,43 +1592,19 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCO } ret = ldapsam_modify_entry(my_methods,newpwd,dn,mods,ldap_op, element_is_set_or_changed); - if (NT_STATUS_IS_ERR(ret)) { + if (!NT_STATUS_IS_OK(ret)) { DEBUG(0,("failed to modify/add user with uid = %s (dn = %s)\n", pdb_get_username(newpwd),dn)); - ldap_mods_free(mods,1); + ldap_mods_free(mods, True); return ret; } DEBUG(2,("added: uid == %s in the LDAP database\n", pdb_get_username(newpwd))); - ldap_mods_free(mods, 1); + ldap_mods_free(mods, True); return NT_STATUS_OK; } -/********************************************************************** - Housekeeping - *********************************************************************/ - -static void free_private_data(void **vp) -{ - struct ldapsam_privates **ldap_state = (struct ldapsam_privates **)vp; - - ldapsam_close(*ldap_state); - - if ((*ldap_state)->bind_secret) { - memset((*ldap_state)->bind_secret, '\0', strlen((*ldap_state)->bind_secret)); - } - - ldapsam_close(*ldap_state); - - SAFE_FREE((*ldap_state)->bind_dn); - SAFE_FREE((*ldap_state)->bind_secret); - - *ldap_state = NULL; - - /* No need to free any further, as it is talloc()ed */ -} - /********************************************************************** *********************************************************************/ @@ -3083,19 +1620,20 @@ static int ldapsam_search_one_group (struct ldapsam_privates *ldap_state, attr_list = get_attr_list(groupmap_attr_list); - rc = ldapsam_search(ldap_state, lp_ldap_suffix (), scope, + rc = smbldap_search(ldap_state->smbldap_state, + lp_ldap_group_suffix (), scope, filter, attr_list, 0, result); free_attr_list( attr_list ); if (rc != LDAP_SUCCESS) { char *ld_error = NULL; - ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, + ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error); DEBUG(0, ("ldapsam_search_one_group: " "Problem during the LDAP search: LDAP error: %s (%s)", ld_error?ld_error:"(unknown)", ldap_err2string(rc))); DEBUG(3, ("ldapsam_search_one_group: Query was: %s, %s\n", - lp_ldap_suffix(), filter)); + lp_ldap_group_suffix(), filter)); SAFE_FREE(ld_error); } @@ -3111,13 +1649,13 @@ static BOOL init_group_from_ldap(struct ldapsam_privates *ldap_state, pstring temp; if (ldap_state == NULL || map == NULL || entry == NULL || - ldap_state->ldap_struct == NULL) + ldap_state->smbldap_state->ldap_struct == NULL) { DEBUG(0, ("init_group_from_ldap: NULL parameters found!\n")); return False; } - if (!get_single_attribute(ldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GIDNUMBER), temp)) { DEBUG(0, ("Mandatory attribute %s not found\n", @@ -3128,7 +1666,7 @@ static BOOL init_group_from_ldap(struct ldapsam_privates *ldap_state, map->gid = (gid_t)atol(temp); - if (!get_single_attribute(ldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_attr_key2string( groupmap_attr_list, LDAP_ATTR_GROUP_SID), temp)) { DEBUG(0, ("Mandatory attribute %s not found\n", @@ -3137,7 +1675,7 @@ static BOOL init_group_from_ldap(struct ldapsam_privates *ldap_state, } string_to_sid(&map->sid, temp); - if (!get_single_attribute(ldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_attr_key2string( groupmap_attr_list, LDAP_ATTR_GROUP_TYPE), temp)) { DEBUG(0, ("Mandatory attribute %s not found\n", @@ -3152,11 +1690,11 @@ static BOOL init_group_from_ldap(struct ldapsam_privates *ldap_state, return False; } - if (!get_single_attribute(ldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_attr_key2string( groupmap_attr_list, LDAP_ATTR_DISPLAY_NAME), temp)) { temp[0] = '\0'; - if (!get_single_attribute(ldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_attr_key2string( groupmap_attr_list, LDAP_ATTR_CN), temp)) { DEBUG(0, ("Attributes cn not found either " @@ -3166,16 +1704,13 @@ static BOOL init_group_from_ldap(struct ldapsam_privates *ldap_state, } fstrcpy(map->nt_name, temp); - if (!get_single_attribute(ldap_state->ldap_struct, entry, + if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_attr_key2string( groupmap_attr_list, LDAP_ATTR_DESC), temp)) { temp[0] = '\0'; } fstrcpy(map->comment, temp); - map->systemaccount = 0; - init_privilege(&map->priv_set); - return True; } @@ -3197,15 +1732,15 @@ static BOOL init_ldap_from_group(LDAP *ldap_struct, *mods = NULL; sid_to_string(tmp, &map->sid); - make_ldap_mod(ldap_struct, existing, mods, + smbldap_make_mod(ldap_struct, existing, mods, get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GROUP_SID), tmp); snprintf(tmp, sizeof(tmp)-1, "%i", map->sid_name_use); - make_ldap_mod(ldap_struct, existing, mods, + smbldap_make_mod(ldap_struct, existing, mods, get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GROUP_TYPE), tmp); - make_ldap_mod(ldap_struct, existing, mods, + smbldap_make_mod(ldap_struct, existing, mods, get_attr_key2string( groupmap_attr_list, LDAP_ATTR_DISPLAY_NAME), map->nt_name); - make_ldap_mod(ldap_struct, existing, mods, + smbldap_make_mod(ldap_struct, existing, mods, get_attr_key2string( groupmap_attr_list, LDAP_ATTR_DESC), map->comment); return True; @@ -3229,20 +1764,22 @@ static NTSTATUS ldapsam_getgroup(struct pdb_methods *methods, return NT_STATUS_NO_SUCH_GROUP; } - count = ldap_count_entries(ldap_state->ldap_struct, result); + count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result); if (count < 1) { - DEBUG(4, ("Did not find group for filter %s\n", filter)); + DEBUG(4, ("Did not find group\n")); + ldap_msgfree(result); return NT_STATUS_NO_SUCH_GROUP; } if (count > 1) { DEBUG(1, ("Duplicate entries for filter %s: count=%d\n", filter, count)); + ldap_msgfree(result); return NT_STATUS_NO_SUCH_GROUP; } - entry = ldap_first_entry(ldap_state->ldap_struct, result); + entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result); if (!entry) { ldap_msgfree(result); @@ -3264,7 +1801,7 @@ static NTSTATUS ldapsam_getgroup(struct pdb_methods *methods, *********************************************************************/ static NTSTATUS ldapsam_getgrsid(struct pdb_methods *methods, GROUP_MAP *map, - DOM_SID sid, BOOL with_priv) + DOM_SID sid) { pstring filter; @@ -3280,7 +1817,7 @@ static NTSTATUS ldapsam_getgrsid(struct pdb_methods *methods, GROUP_MAP *map, *********************************************************************/ static NTSTATUS ldapsam_getgrgid(struct pdb_methods *methods, GROUP_MAP *map, - gid_t gid, BOOL with_priv) + gid_t gid) { pstring filter; @@ -3296,16 +1833,21 @@ static NTSTATUS ldapsam_getgrgid(struct pdb_methods *methods, GROUP_MAP *map, *********************************************************************/ static NTSTATUS ldapsam_getgrnam(struct pdb_methods *methods, GROUP_MAP *map, - char *name, BOOL with_priv) + const char *name) { pstring filter; + char *escape_name = escape_ldap_string_alloc(name); - /* TODO: Escaping of name? */ + if (!escape_name) { + return NT_STATUS_NO_MEMORY; + } snprintf(filter, sizeof(filter)-1, "(&(objectClass=%s)(|(%s=%s)(%s=%s)))", LDAP_OBJ_GROUPMAP, - get_attr_key2string(groupmap_attr_list, LDAP_ATTR_DISPLAY_NAME), name, - get_attr_key2string(groupmap_attr_list, LDAP_ATTR_CN), name); + get_attr_key2string(groupmap_attr_list, LDAP_ATTR_DISPLAY_NAME), escape_name, + get_attr_key2string(groupmap_attr_list, LDAP_ATTR_CN), escape_name); + + SAFE_FREE(escape_name); return ldapsam_getgroup(methods, filter, map); } @@ -3337,6 +1879,7 @@ static NTSTATUS ldapsam_add_group_mapping_entry(struct pdb_methods *methods, (struct ldapsam_privates *)methods->private_data; LDAPMessage *result = NULL; LDAPMod **mods = NULL; + int count; char *tmp; pstring dn; @@ -3347,7 +1890,7 @@ static NTSTATUS ldapsam_add_group_mapping_entry(struct pdb_methods *methods, int rc; if (NT_STATUS_IS_OK(ldapsam_getgrgid(methods, &dummy, - map->gid, False))) { + map->gid))) { DEBUG(0, ("Group %i already exists in LDAP\n", map->gid)); return NT_STATUS_UNSUCCESSFUL; } @@ -3357,22 +1900,27 @@ static NTSTATUS ldapsam_add_group_mapping_entry(struct pdb_methods *methods, return NT_STATUS_UNSUCCESSFUL; } - if (ldap_count_entries(ldap_state->ldap_struct, result) != 1) { + count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result); + + if ( count == 0 ) + return NT_STATUS_UNSUCCESSFUL; + + if (count > 1) { DEBUG(2, ("Group %i must exist exactly once in LDAP\n", map->gid)); ldap_msgfree(result); return NT_STATUS_UNSUCCESSFUL; } - entry = ldap_first_entry(ldap_state->ldap_struct, result); - tmp = ldap_get_dn(ldap_state->ldap_struct, entry); + entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result); + tmp = ldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry); pstrcpy(dn, tmp); ldap_memfree(tmp); - if (!init_ldap_from_group(ldap_state->ldap_struct, + if (!init_ldap_from_group(ldap_state->smbldap_state->ldap_struct, result, &mods, map)) { DEBUG(0, ("init_ldap_from_group failed!\n")); - ldap_mods_free(mods, 1); + ldap_mods_free(mods, True); ldap_msgfree(result); return NT_STATUS_UNSUCCESSFUL; } @@ -3384,15 +1932,14 @@ static NTSTATUS ldapsam_add_group_mapping_entry(struct pdb_methods *methods, return NT_STATUS_UNSUCCESSFUL; } - make_a_mod(&mods, LDAP_MOD_ADD, "objectClass", - "sambaGroupMapping"); + smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_GROUPMAP ); - rc = ldapsam_modify(ldap_state, dn, mods); - ldap_mods_free(mods, 1); + rc = smbldap_modify(ldap_state->smbldap_state, dn, mods); + ldap_mods_free(mods, True); if (rc != LDAP_SUCCESS) { char *ld_error = NULL; - ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, + ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error); DEBUG(0, ("failed to add group %i error: %s (%s)\n", map->gid, ld_error ? ld_error : "(unknown)", ldap_err2string(rc))); @@ -3424,16 +1971,16 @@ static NTSTATUS ldapsam_update_group_mapping_entry(struct pdb_methods *methods, return NT_STATUS_UNSUCCESSFUL; } - if (ldap_count_entries(ldap_state->ldap_struct, result) == 0) { + if (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result) == 0) { DEBUG(0, ("No group to modify!\n")); ldap_msgfree(result); return NT_STATUS_UNSUCCESSFUL; } - entry = ldap_first_entry(ldap_state->ldap_struct, result); - dn = ldap_get_dn(ldap_state->ldap_struct, entry); + entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result); + dn = ldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry); - if (!init_ldap_from_group(ldap_state->ldap_struct, + if (!init_ldap_from_group(ldap_state->smbldap_state->ldap_struct, result, &mods, map)) { DEBUG(0, ("init_ldap_from_group failed\n")); ldap_msgfree(result); @@ -3447,13 +1994,13 @@ static NTSTATUS ldapsam_update_group_mapping_entry(struct pdb_methods *methods, return NT_STATUS_UNSUCCESSFUL; } - rc = ldapsam_modify(ldap_state, dn, mods); + rc = smbldap_modify(ldap_state->smbldap_state, dn, mods); - ldap_mods_free(mods, 1); + ldap_mods_free(mods, True); if (rc != LDAP_SUCCESS) { char *ld_error = NULL; - ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, + ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error); DEBUG(0, ("failed to modify group %i error: %s (%s)\n", map->gid, ld_error ? ld_error : "(unknown)", ldap_err2string(rc))); @@ -3509,24 +2056,24 @@ static NTSTATUS ldapsam_setsamgrent(struct pdb_methods *my_methods, BOOL update) snprintf( filter, sizeof(filter)-1, "(objectclass=%s)", LDAP_OBJ_GROUPMAP); attr_list = get_attr_list( groupmap_attr_list ); - rc = ldapsam_search(ldap_state, lp_ldap_suffix(), + rc = smbldap_search(ldap_state->smbldap_state, lp_ldap_group_suffix(), LDAP_SCOPE_SUBTREE, filter, attr_list, 0, &ldap_state->result); free_attr_list( attr_list ); 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)); + DEBUG(3, ("Query was: %s, %s\n", lp_ldap_group_suffix(), filter)); ldap_msgfree(ldap_state->result); ldap_state->result = NULL; return NT_STATUS_UNSUCCESSFUL; } DEBUG(2, ("ldapsam_setsampwent: %d entries in the base!\n", - ldap_count_entries(ldap_state->ldap_struct, + ldap_count_entries(ldap_state->smbldap_state->ldap_struct, ldap_state->result))); - ldap_state->entry = ldap_first_entry(ldap_state->ldap_struct, ldap_state->result); + ldap_state->entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, ldap_state->result); ldap_state->index = 0; return NT_STATUS_OK; @@ -3550,10 +2097,6 @@ static NTSTATUS ldapsam_getsamgrent(struct pdb_methods *my_methods, struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data; BOOL bret = False; - /* The rebind proc needs this *HACK*. We are not multithreaded, so - this will work, but it's not nice. */ - static_ldap_state = ldap_state; - while (!bret) { if (!ldap_state->entry) return ret; @@ -3561,7 +2104,7 @@ static NTSTATUS ldapsam_getsamgrent(struct pdb_methods *my_methods, ldap_state->index++; bret = init_group_from_ldap(ldap_state, map, ldap_state->entry); - ldap_state->entry = ldap_next_entry(ldap_state->ldap_struct, + ldap_state->entry = ldap_next_entry(ldap_state->smbldap_state->ldap_struct, ldap_state->entry); } @@ -3574,7 +2117,7 @@ static NTSTATUS ldapsam_getsamgrent(struct pdb_methods *my_methods, static NTSTATUS ldapsam_enum_group_mapping(struct pdb_methods *methods, enum SID_NAME_USE sid_name_use, GROUP_MAP **rmap, int *num_entries, - BOOL unix_only, BOOL with_priv) + BOOL unix_only) { GROUP_MAP map; GROUP_MAP *mapt; @@ -3622,6 +2165,22 @@ static NTSTATUS ldapsam_enum_group_mapping(struct pdb_methods *methods, } /********************************************************************** + Housekeeping + *********************************************************************/ + +static void free_private_data(void **vp) +{ + struct ldapsam_privates **ldap_state = (struct ldapsam_privates **)vp; + + smbldap_free_struct(&(*ldap_state)->smbldap_state); + + *ldap_state = NULL; + + /* No need to free any further, as it is talloc()ed */ +} + +/********************************************************************** + Intitalise the parts of the pdb_context that are common to all pdb_ldap modes *********************************************************************/ static NTSTATUS pdb_init_ldapsam_common(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, @@ -3655,26 +2214,21 @@ static NTSTATUS pdb_init_ldapsam_common(PDB_CONTEXT *pdb_context, PDB_METHODS ** /* TODO: Setup private data and free */ - ldap_state = talloc_zero(pdb_context->mem_ctx, sizeof(struct ldapsam_privates)); - + ldap_state = talloc_zero(pdb_context->mem_ctx, sizeof(*ldap_state)); if (!ldap_state) { DEBUG(0, ("talloc() failed for ldapsam private_data!\n")); return NT_STATUS_NO_MEMORY; } - if (location) { - ldap_state->uri = talloc_strdup(pdb_context->mem_ctx, location); - } else { - ldap_state->uri = "ldap://localhost"; - } + if (!NT_STATUS_IS_OK(nt_status = + smbldap_init(pdb_context->mem_ctx, location, + &ldap_state->smbldap_state))); ldap_state->domain_name = talloc_strdup(pdb_context->mem_ctx, get_global_sam_name()); if (!ldap_state->domain_name) { return NT_STATUS_NO_MEMORY; } - sid_copy(&ldap_state->domain_sid, get_global_sam_sid()); - (*pdb_method)->private_data = ldap_state; (*pdb_method)->free_private_data = free_private_data; @@ -3683,6 +2237,7 @@ static NTSTATUS pdb_init_ldapsam_common(PDB_CONTEXT *pdb_context, PDB_METHODS ** } /********************************************************************** + Initialise the 'compat' mode for pdb_ldap *********************************************************************/ static NTSTATUS pdb_init_ldapsam_compat(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location) @@ -3690,21 +2245,8 @@ static NTSTATUS pdb_init_ldapsam_compat(PDB_CONTEXT *pdb_context, PDB_METHODS ** NTSTATUS nt_status; struct ldapsam_privates *ldap_state; - if (!NT_STATUS_IS_OK(nt_status = pdb_init_ldapsam_common(pdb_context, pdb_method, location))) { - return nt_status; - } - - (*pdb_method)->name = "ldapsam_compat"; - - ldap_state = (*pdb_method)->private_data; - ldap_state->schema_ver = SCHEMAVER_SAMBAACCOUNT; - - if (location) { - ldap_state->uri = talloc_strdup(pdb_context->mem_ctx, location); - } else { -#ifndef WITH_LDAP_SAMCONFIG - ldap_state->uri = "ldap://localhost"; -#else +#ifdef WITH_LDAP_SAMCONFIG + if (!location) { int ldap_port = lp_ldap_port(); /* remap default port if not using SSL (ie clear or TLS) */ @@ -3712,25 +2254,42 @@ static NTSTATUS pdb_init_ldapsam_compat(PDB_CONTEXT *pdb_context, PDB_METHODS ** ldap_port = 389; } - ldap_state->uri = talloc_asprintf(pdb_context->mem_ctx, "%s://%s:%d", lp_ldap_ssl() == LDAP_SSL_ON ? "ldaps" : "ldap", lp_ldap_server(), ldap_port); - if (!ldap_state->uri) { + location = talloc_asprintf(pdb_context->mem_ctx, "%s://%s:%d", lp_ldap_ssl() == LDAP_SSL_ON ? "ldaps" : "ldap", lp_ldap_server(), ldap_port); + if (!location) { return NT_STATUS_NO_MEMORY; } + } #endif + + if (!NT_STATUS_IS_OK(nt_status = pdb_init_ldapsam_common(pdb_context, pdb_method, location))) { + return nt_status; } + (*pdb_method)->name = "ldapsam_compat"; + + ldap_state = (*pdb_method)->private_data; + ldap_state->schema_ver = SCHEMAVER_SAMBAACCOUNT; + + sid_copy(&ldap_state->domain_sid, get_global_sam_sid()); + return NT_STATUS_OK; } /********************************************************************** + Initialise the normal mode for pdb_ldap *********************************************************************/ static NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location) { NTSTATUS nt_status; struct ldapsam_privates *ldap_state; - uint32 low_idmap_uid, high_idmap_uid; - uint32 low_idmap_gid, high_idmap_gid; + uint32 alg_rid_base; + pstring alg_rid_base_string; + LDAPMessage *result = NULL; + LDAPMessage *entry = NULL; + DOM_SID ldap_domain_sid; + DOM_SID secrets_domain_sid; + pstring domain_sid_string; if (!NT_STATUS_IS_OK(nt_status = pdb_init_ldapsam_common(pdb_context, pdb_method, location))) { return nt_status; @@ -3739,23 +2298,57 @@ static NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_met (*pdb_method)->name = "ldapsam"; ldap_state = (*pdb_method)->private_data; - ldap_state->schema_ver = SCHEMAVER_SAMBASAMACCOUNT; - ldap_state->permit_non_unix_accounts = False; + ldap_state->schema_ver = SCHEMAVER_SAMBASAMACCOUNT; + + /* Try to setup the Domain Name, Domain SID, algorithmic rid base */ + + nt_status = smbldap_search_domain_info(ldap_state->smbldap_state, &result, + ldap_state->domain_name, True); + + if ( !NT_STATUS_IS_OK(nt_status) ) { + DEBUG(2, ("WARNING: Could not get domain info, nor add one to the domain\n")); + DEBUGADD(2, ("Continuing on regardless, will be unable to allocate new users/groups, " + "and will risk BDCs having inconsistant SIDs\n")); + sid_copy(&ldap_state->domain_sid, get_global_sam_sid()); + return NT_STATUS_OK; + } - /* check for non-unix account ranges */ + /* Given that the above might fail, everything below this must be optional */ + + entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result); + if (!entry) { + DEBUG(0, ("Could not get domain info entry\n")); + ldap_msgfree(result); + return NT_STATUS_UNSUCCESSFUL; + } - if (lp_idmap_uid(&low_idmap_uid, &high_idmap_uid) - && lp_idmap_gid(&low_idmap_gid, &high_idmap_gid)) + if (smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, + get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID), + domain_sid_string)) { - DEBUG(2, ("Enabling non-unix account ranges\n")); - - ldap_state->permit_non_unix_accounts = True; + BOOL found_sid; + string_to_sid(&ldap_domain_sid, domain_sid_string); + found_sid = secrets_fetch_domain_sid(ldap_state->domain_name, &secrets_domain_sid); + if (!found_sid || !sid_equal(&secrets_domain_sid, &ldap_domain_sid)) { + /* reset secrets.tdb sid */ + secrets_store_domain_sid(ldap_state->domain_name, &ldap_domain_sid); + } + sid_copy(&ldap_state->domain_sid, &ldap_domain_sid); + } - ldap_state->low_allocated_user_rid = fallback_pdb_uid_to_user_rid(low_idmap_uid); - ldap_state->high_allocated_user_rid = fallback_pdb_uid_to_user_rid(high_idmap_uid); - ldap_state->low_allocated_group_rid = pdb_gid_to_group_rid(low_idmap_gid); - ldap_state->high_allocated_group_rid = pdb_gid_to_group_rid(high_idmap_gid); + if (smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, + get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_ALGORITHMIC_RID_BASE), + alg_rid_base_string)) + { + alg_rid_base = (uint32)atol(alg_rid_base_string); + if (alg_rid_base != algorithmic_rid_base()) { + DEBUG(0, ("The value of 'algorithmic RID base' has changed since the LDAP\n" + "database was initialised. Aborting. \n")); + ldap_msgfree(result); + return NT_STATUS_UNSUCCESSFUL; + } } + ldap_msgfree(result); return NT_STATUS_OK; } diff --git a/source3/passdb/pdb_smbpasswd.c b/source3/passdb/pdb_smbpasswd.c index c392846d93..055e8e71ba 100644 --- a/source3/passdb/pdb_smbpasswd.c +++ b/source3/passdb/pdb_smbpasswd.c @@ -1,10 +1,10 @@ /* * Unix SMB/CIFS implementation. * SMB parameters and setup - * Copyright (C) Andrew Tridgell 1992-1998 - * Modified by Jeremy Allison 1995. - * Modified by Gerald (Jerry) Carter 2000-2001 - * Modified by Andrew Bartlett 2002. + * Copyright (C) Andrew Tridgell 1992-1998 + * Modified by Jeremy Allison 1995. + * Modified by Gerald (Jerry) Carter 2000-2001,2003 + * Modified by Andrew Bartlett 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 @@ -34,14 +34,13 @@ struct smb_passwd { - BOOL smb_userid_set; /* this is actually the unix uid_t */ - uint32 smb_userid; /* this is actually the unix uid_t */ + uint32 smb_userid; /* this is actually the unix uid_t */ const char *smb_name; /* username string */ - const unsigned char *smb_passwd; /* Null if no password */ + const unsigned char *smb_passwd; /* Null if no password */ const unsigned char *smb_nt_passwd; /* Null if no password */ - uint16 acct_ctrl; /* account info (ACB_xxxx bit-mask) */ + uint16 acct_ctrl; /* account info (ACB_xxxx bit-mask) */ time_t pass_last_set_time; /* password last set time */ }; @@ -61,12 +60,6 @@ struct smbpasswd_privates /* retrive-once info */ const char *smbpasswd_file; - - BOOL permit_non_unix_accounts; - - uid_t low_nua_userid; - uid_t high_nua_userid; - }; enum pwf_access_type { PWF_READ, PWF_UPDATE, PWF_CREATE }; @@ -591,28 +584,6 @@ static BOOL add_smbfilepwd_entry(struct smbpasswd_privates *smbpasswd_state, str /* Ok - entry doesn't exist. We can add it */ - /* Account not in /etc/passwd hack!!! */ - if (!newpwd->smb_userid_set) { - if (!smbpasswd_state->permit_non_unix_accounts) { - DEBUG(0, ("add_smbfilepwd_entry: cannot add account %s without unix identity\n", newpwd->smb_name)); - endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth)); - return False; - } - - if (max_found_uid < smbpasswd_state->low_nua_userid) { - newpwd->smb_userid = smbpasswd_state->low_nua_userid; - newpwd->smb_userid_set = True; - } else if (max_found_uid >= smbpasswd_state->high_nua_userid) { - DEBUG(0, ("add_smbfilepwd_entry: cannot add machine %s, no uids are free! \n", newpwd->smb_name)); - endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth)); - return False; - } else { - newpwd->smb_userid = max_found_uid + 1; - newpwd->smb_userid_set = True; - } - } - - /* Create a new smb passwd entry and set it to the given password. */ /* * The add user write needs to be atomic - so get the fd from @@ -1133,24 +1104,32 @@ Error was %s\n", pwd->smb_name, pfile2, strerror(errno))); ********************************************************************/ static BOOL build_smb_pass (struct smb_passwd *smb_pw, const SAM_ACCOUNT *sampass) { - uid_t uid; uint32 rid; if (sampass == NULL) return False; - - rid = pdb_get_user_rid(sampass); - - /* If the user specified a RID, make sure its able to be both stored and retreived */ - if (rid && rid != DOMAIN_USER_RID_GUEST && uid != fallback_pdb_user_rid_to_uid(rid)) { - DEBUG(0,("build_sam_pass: Failing attempt to store user with non-uid based user RID. \n")); - return False; - } - ZERO_STRUCTP(smb_pw); - smb_pw->smb_userid_set = True; - smb_pw->smb_userid=uid; + if (!IS_SAM_DEFAULT(sampass, PDB_USERSID)) { + rid = pdb_get_user_rid(sampass); + + /* If the user specified a RID, make sure its able to be both stored and retreived */ + if (rid == DOMAIN_USER_RID_GUEST) { + struct passwd *passwd = getpwnam_alloc(lp_guestaccount()); + if (!passwd) { + DEBUG(0, ("Could not find gest account via getpwnam()! (%s)\n", lp_guestaccount())); + return False; + } + smb_pw->smb_userid=passwd->pw_uid; + passwd_free(&passwd); + + } else if (fallback_pdb_rid_is_user(rid)) { + smb_pw->smb_userid=fallback_pdb_user_rid_to_uid(rid); + } else { + DEBUG(0,("build_sam_pass: Failing attempt to store user with non-uid based user RID. \n")); + return False; + } + } smb_pw->smb_name=(const char*)pdb_get_username(sampass); @@ -1160,25 +1139,6 @@ static BOOL build_smb_pass (struct smb_passwd *smb_pw, const SAM_ACCOUNT *sampas smb_pw->acct_ctrl=pdb_get_acct_ctrl(sampass); smb_pw->pass_last_set_time=pdb_get_pass_last_set_time(sampass); -#if 0 - /* - * ifdef'out by JFM on 11/29/2001. - * this assertion is no longer valid - * and I don't understand the goal - * and doing the same thing with the group mapping code - * is hairy ! - * - * We just have the RID, in which SID is it valid ? - * our domain SID ? well known SID ? local SID ? - */ - - if (gid != pdb_group_rid_to_gid(pdb_get_group_rid(sampass))) { - DEBUG(0,("build_sam_pass: Failing attempt to store user with non-gid based primary group RID. \n")); - DEBUG(0,("build_sam_pass: %d %d %d. \n", *gid, pdb_group_rid_to_gid(pdb_get_group_rid(sampass)), pdb_get_group_rid(sampass))); - return False; - } -#endif - return True; } @@ -1194,49 +1154,28 @@ static BOOL build_sam_account(struct smbpasswd_privates *smbpasswd_state, DEBUG(5,("build_sam_account: SAM_ACCOUNT is NULL\n")); return False; } - - pwfile = getpwnam_alloc(pw_buf->smb_name); - if (pwfile == NULL) { - if ((smbpasswd_state->permit_non_unix_accounts) - && (pw_buf->smb_userid >= smbpasswd_state->low_nua_userid) - && (pw_buf->smb_userid <= smbpasswd_state->high_nua_userid)) { - pdb_set_user_sid_from_rid(sam_pass, fallback_pdb_uid_to_user_rid (pw_buf->smb_userid), PDB_SET); + /* verify the user account exists */ - /* lkclXXXX this is OBSERVED behaviour by NT PDCs, enforced here. - - This was down the bottom for machines, but it looks pretty good as - a general default for non-unix users. --abartlet 2002-01-08 - */ - pdb_set_group_sid_from_rid (sam_pass, DOMAIN_GROUP_RID_USERS, PDB_SET); - pdb_set_username (sam_pass, pw_buf->smb_name, PDB_SET); - pdb_set_domain (sam_pass, get_global_sam_name(), PDB_DEFAULT); - - } else { - DEBUG(0,("build_sam_account: smbpasswd database is corrupt! username %s with uid %u is not in unix passwd database!\n", pw_buf->smb_name, pw_buf->smb_userid)); + if ( !(pwfile = getpwnam_alloc(pw_buf->smb_name)) ) { + DEBUG(0,("build_sam_account: smbpasswd database is corrupt! username %s with uid " + "%u is not in unix passwd database!\n", pw_buf->smb_name, pw_buf->smb_userid)); return False; - } - } else { - if (!NT_STATUS_IS_OK(pdb_fill_sam_pw(sam_pass, pwfile))) { - return False; - } - - passwd_free(&pwfile); } + if (!NT_STATUS_IS_OK(pdb_fill_sam_pw(sam_pass, pwfile))) + return False; + + passwd_free(&pwfile); + + /* set remaining fields */ + pdb_set_nt_passwd (sam_pass, pw_buf->smb_nt_passwd, PDB_SET); pdb_set_lanman_passwd (sam_pass, pw_buf->smb_passwd, PDB_SET); pdb_set_acct_ctrl (sam_pass, pw_buf->acct_ctrl, PDB_SET); pdb_set_pass_last_set_time (sam_pass, pw_buf->pass_last_set_time, PDB_SET); pdb_set_pass_can_change_time (sam_pass, pw_buf->pass_last_set_time, PDB_SET); -#if 0 /* JERRY */ - /* the smbpasswd format doesn't have a must change time field, so - we can't get this right. The best we can do is to set this to - some time in the future. 21 days seems as reasonable as any other value :) - */ - pdb_set_pass_must_change_time (sam_pass, pw_buf->pass_last_set_time + MAX_PASSWORD_AGE, PDB_DEFAULT); -#endif return True; } @@ -1342,7 +1281,7 @@ static NTSTATUS smbpasswd_getsampwnam(struct pdb_methods *my_methods, fp = startsmbfilepwent(smbpasswd_state->smbpasswd_file, PWF_READ, &(smbpasswd_state->pw_file_lock_depth)); if (fp == NULL) { - DEBUG(0, ("unable to open passdb database.\n")); + DEBUG(0, ("Unable to open passdb database.\n")); return nt_status; } @@ -1402,7 +1341,7 @@ static NTSTATUS smbpasswd_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUN fp = startsmbfilepwent(smbpasswd_state->smbpasswd_file, PWF_READ, &(smbpasswd_state->pw_file_lock_depth)); if (fp == NULL) { - DEBUG(0, ("unable to open passdb database.\n")); + DEBUG(0, ("Unable to open passdb database.\n")); return nt_status; } @@ -1502,7 +1441,7 @@ static void free_private_data(void **vp) /* No need to free any further, as it is talloc()ed */ } -NTSTATUS pdb_init_smbpasswd(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location) +static NTSTATUS pdb_init_smbpasswd(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location) { NTSTATUS nt_status; struct smbpasswd_privates *privates; @@ -1548,16 +1487,10 @@ NTSTATUS pdb_init_smbpasswd(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, (*pdb_method)->free_private_data = free_private_data; - if (lp_idmap_uid(&privates->low_nua_userid, &privates->high_nua_userid)) { - DEBUG(0, ("idmap uid range defined, non unix accounts enabled\n")); - privates->permit_non_unix_accounts = True; - } - return NT_STATUS_OK; } -int pdb_smbpasswd_init(void) +NTSTATUS pdb_smbpasswd_init(void) { - smb_register_passdb(PASSDB_INTERFACE_VERSION, "smbpasswd", pdb_init_smbpasswd); - return True; + return smb_register_passdb(PASSDB_INTERFACE_VERSION, "smbpasswd", pdb_init_smbpasswd); } diff --git a/source3/passdb/pdb_tdb.c b/source3/passdb/pdb_tdb.c index 7f8c2a26f7..1078a5bd26 100644 --- a/source3/passdb/pdb_tdb.c +++ b/source3/passdb/pdb_tdb.c @@ -1,11 +1,11 @@ /* * Unix SMB/CIFS implementation. * SMB parameters and setup - * Copyright (C) Andrew Tridgell 1992-1998 - * Copyright (C) Simo Sorce 2000-2002 - * Copyright (C) Gerald Carter 2000 - * Copyright (C) Jeremy Allison 2001 - * Copyright (C) Andrew Bartlett 2002 + * Copyright (C) Andrew Tridgell 1992-1998 + * Copyright (C) Simo Sorce 2000-2002 + * Copyright (C) Gerald Carter 2000 + * Copyright (C) Jeremy Allison 2001 + * Copyright (C) Andrew Bartlett 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 @@ -39,7 +39,6 @@ static int tdbsam_debug_level = DBGC_ALL; #define PDB_VERSION "20010830" #define PASSDB_FILE_NAME "passdb.tdb" -#define TDB_FORMAT_STRING "ddddddBBBBBBBBBBBBddBBwdwdBdd" #define USERPREFIX "USER_" #define RIDPREFIX "RID_" @@ -49,410 +48,8 @@ struct tdbsam_privates { /* retrive-once info */ const char *tdbsam_location; - - BOOL permit_non_unix_accounts; - - BOOL algorithmic_rids; - - uint32 low_nua_rid; - uint32 high_nua_rid; }; -/********************************************************************** - Intialize a SAM_ACCOUNT struct from a BYTE buffer of size len - *********************************************************************/ - -static BOOL init_sam_from_buffer (struct tdbsam_privates *tdb_state, - SAM_ACCOUNT *sampass, uint8 *buf, uint32 buflen) -{ - - /* times are stored as 32bit integer - take care on system with 64bit wide time_t - --SSS */ - uint32 logon_time, - logoff_time, - kickoff_time, - pass_last_set_time, - pass_can_change_time, - pass_must_change_time; - char *username; - char *domain; - char *nt_username; - char *dir_drive; - char *unknown_str; - char *munged_dial; - char *fullname; - char *homedir; - char *logon_script; - char *profile_path; - char *acct_desc; - char *workstations; - uint32 username_len, domain_len, nt_username_len, - dir_drive_len, unknown_str_len, munged_dial_len, - fullname_len, homedir_len, logon_script_len, - profile_path_len, acct_desc_len, workstations_len; - - uint32 user_rid, group_rid, unknown_3, hours_len, unknown_5, unknown_6; - uint16 acct_ctrl, logon_divs; - uint8 *hours; - static uint8 *lm_pw_ptr, *nt_pw_ptr; - uint32 len = 0; - uint32 lm_pw_len, nt_pw_len, hourslen; - BOOL ret = True; - uid_t uid = -1; - gid_t gid = -1; - - if(sampass == NULL || buf == NULL) { - DEBUG(0, ("init_sam_from_buffer: NULL parameters found!\n")); - return False; - } - - /* unpack the buffer into variables */ - len = tdb_unpack (buf, buflen, TDB_FORMAT_STRING, - &logon_time, - &logoff_time, - &kickoff_time, - &pass_last_set_time, - &pass_can_change_time, - &pass_must_change_time, - &username_len, &username, - &domain_len, &domain, - &nt_username_len, &nt_username, - &fullname_len, &fullname, - &homedir_len, &homedir, - &dir_drive_len, &dir_drive, - &logon_script_len, &logon_script, - &profile_path_len, &profile_path, - &acct_desc_len, &acct_desc, - &workstations_len, &workstations, - &unknown_str_len, &unknown_str, - &munged_dial_len, &munged_dial, - &user_rid, - &group_rid, - &lm_pw_len, &lm_pw_ptr, - &nt_pw_len, &nt_pw_ptr, - &acct_ctrl, - &unknown_3, - &logon_divs, - &hours_len, - &hourslen, &hours, - &unknown_5, - &unknown_6); - - if (len == -1) { - ret = False; - goto done; - } - - pdb_set_logon_time(sampass, logon_time, PDB_SET); - pdb_set_logoff_time(sampass, logoff_time, PDB_SET); - pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET); - pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET); - pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET); - pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET); - - pdb_set_username (sampass, username, PDB_SET); - pdb_set_domain (sampass, domain, PDB_SET); - pdb_set_nt_username (sampass, nt_username, PDB_SET); - pdb_set_fullname (sampass, fullname, PDB_SET); - - if (homedir) { - pdb_set_homedir(sampass, homedir, PDB_SET); - } - else { - pdb_set_homedir(sampass, - talloc_sub_specified(sampass->mem_ctx, - lp_logon_home(), - username, domain, - uid, gid), - PDB_DEFAULT); - } - - if (dir_drive) - pdb_set_dir_drive(sampass, dir_drive, PDB_SET); - else { - pdb_set_dir_drive(sampass, - talloc_sub_specified(sampass->mem_ctx, - lp_logon_drive(), - username, domain, - uid, gid), - PDB_DEFAULT); - } - - if (logon_script) - pdb_set_logon_script(sampass, logon_script, PDB_SET); - else { - pdb_set_logon_script(sampass, - talloc_sub_specified(sampass->mem_ctx, - lp_logon_script(), - username, domain, - uid, gid), - PDB_DEFAULT); - } - - if (profile_path) { - pdb_set_profile_path(sampass, profile_path, PDB_SET); - } else { - pdb_set_profile_path(sampass, - talloc_sub_specified(sampass->mem_ctx, - lp_logon_path(), - username, domain, - uid, gid), - PDB_DEFAULT); - } - - pdb_set_acct_desc (sampass, acct_desc, PDB_SET); - pdb_set_workstations (sampass, workstations, PDB_SET); - pdb_set_munged_dial (sampass, munged_dial, PDB_SET); - - if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) { - if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) { - ret = False; - goto done; - } - } - - if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) { - if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) { - ret = False; - goto done; - } - } - - pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET); - pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET); - pdb_set_unknown_3(sampass, unknown_3, PDB_SET); - pdb_set_hours_len(sampass, hours_len, PDB_SET); - pdb_set_unknown_5(sampass, unknown_5, PDB_SET); - pdb_set_unknown_6(sampass, unknown_6, PDB_SET); - pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET); - pdb_set_logon_divs(sampass, logon_divs, PDB_SET); - pdb_set_hours(sampass, hours, PDB_SET); - -done: - - SAFE_FREE(username); - SAFE_FREE(domain); - SAFE_FREE(nt_username); - SAFE_FREE(fullname); - SAFE_FREE(homedir); - SAFE_FREE(dir_drive); - SAFE_FREE(logon_script); - SAFE_FREE(profile_path); - SAFE_FREE(acct_desc); - SAFE_FREE(workstations); - SAFE_FREE(munged_dial); - - return ret; -} - -/********************************************************************** - Intialize a BYTE buffer from a SAM_ACCOUNT struct - *********************************************************************/ -static uint32 init_buffer_from_sam (struct tdbsam_privates *tdb_state, - uint8 **buf, const SAM_ACCOUNT *sampass) -{ - size_t len, buflen; - - /* times are stored as 32bit integer - take care on system with 64bit wide time_t - --SSS */ - uint32 logon_time, - logoff_time, - kickoff_time, - pass_last_set_time, - pass_can_change_time, - pass_must_change_time; - - uint32 user_rid, group_rid; - - const char *username; - const char *domain; - const char *nt_username; - const char *dir_drive; - const char *unknown_str; - const char *munged_dial; - const char *fullname; - const char *homedir; - const char *logon_script; - const char *profile_path; - const char *acct_desc; - const char *workstations; - uint32 username_len, domain_len, nt_username_len, - dir_drive_len, unknown_str_len, munged_dial_len, - fullname_len, homedir_len, logon_script_len, - profile_path_len, acct_desc_len, workstations_len; - - const uint8 *lm_pw; - const uint8 *nt_pw; - uint32 lm_pw_len = 16; - uint32 nt_pw_len = 16; - - /* do we have a valid SAM_ACCOUNT pointer? */ - if (sampass == NULL) { - DEBUG(0, ("init_buffer_from_sam: SAM_ACCOUNT is NULL!\n")); - return -1; - } - - *buf = NULL; - buflen = 0; - - logon_time = (uint32)pdb_get_logon_time(sampass); - logoff_time = (uint32)pdb_get_logoff_time(sampass); - kickoff_time = (uint32)pdb_get_kickoff_time(sampass); - pass_can_change_time = (uint32)pdb_get_pass_can_change_time(sampass); - pass_must_change_time = (uint32)pdb_get_pass_must_change_time(sampass); - pass_last_set_time = (uint32)pdb_get_pass_last_set_time(sampass); - - user_rid = pdb_get_user_rid(sampass); - group_rid = pdb_get_group_rid(sampass); - - username = pdb_get_username(sampass); - if (username) username_len = strlen(username) +1; - else username_len = 0; - - domain = pdb_get_domain(sampass); - if (domain) domain_len = strlen(domain) +1; - else domain_len = 0; - - nt_username = pdb_get_nt_username(sampass); - if (nt_username) nt_username_len = strlen(nt_username) +1; - else nt_username_len = 0; - - fullname = pdb_get_fullname(sampass); - if (fullname) fullname_len = strlen(fullname) +1; - else fullname_len = 0; - - /* - * Only updates fields which have been set (not defaults from smb.conf) - */ - - if (!IS_SAM_DEFAULT(sampass, PDB_DRIVE)) - dir_drive = pdb_get_dir_drive(sampass); - else dir_drive = NULL; - if (dir_drive) dir_drive_len = strlen(dir_drive) +1; - else dir_drive_len = 0; - - if (!IS_SAM_DEFAULT(sampass, PDB_SMBHOME)) homedir = pdb_get_homedir(sampass); - else homedir = NULL; - if (homedir) homedir_len = strlen(homedir) +1; - else homedir_len = 0; - - if (!IS_SAM_DEFAULT(sampass, PDB_LOGONSCRIPT)) logon_script = pdb_get_logon_script(sampass); - else logon_script = NULL; - if (logon_script) logon_script_len = strlen(logon_script) +1; - else logon_script_len = 0; - - if (!IS_SAM_DEFAULT(sampass, PDB_PROFILE)) profile_path = pdb_get_profile_path(sampass); - else profile_path = NULL; - if (profile_path) profile_path_len = strlen(profile_path) +1; - else profile_path_len = 0; - - lm_pw = pdb_get_lanman_passwd(sampass); - if (!lm_pw) lm_pw_len = 0; - - nt_pw = pdb_get_nt_passwd(sampass); - if (!nt_pw) nt_pw_len = 0; - - acct_desc = pdb_get_acct_desc(sampass); - if (acct_desc) acct_desc_len = strlen(acct_desc) +1; - else acct_desc_len = 0; - - workstations = pdb_get_workstations(sampass); - if (workstations) workstations_len = strlen(workstations) +1; - else workstations_len = 0; - - unknown_str = NULL; - unknown_str_len = 0; - - munged_dial = pdb_get_munged_dial(sampass); - if (munged_dial) munged_dial_len = strlen(munged_dial) +1; - else munged_dial_len = 0; - - /* one time to get the size needed */ - len = tdb_pack(NULL, 0, TDB_FORMAT_STRING, - logon_time, - logoff_time, - kickoff_time, - pass_last_set_time, - pass_can_change_time, - pass_must_change_time, - username_len, username, - domain_len, domain, - nt_username_len, nt_username, - fullname_len, fullname, - homedir_len, homedir, - dir_drive_len, dir_drive, - logon_script_len, logon_script, - profile_path_len, profile_path, - acct_desc_len, acct_desc, - workstations_len, workstations, - unknown_str_len, unknown_str, - munged_dial_len, munged_dial, - user_rid, - group_rid, - lm_pw_len, lm_pw, - nt_pw_len, nt_pw, - pdb_get_acct_ctrl(sampass), - pdb_get_unknown_3(sampass), - pdb_get_logon_divs(sampass), - pdb_get_hours_len(sampass), - MAX_HOURS_LEN, pdb_get_hours(sampass), - pdb_get_unknown_5(sampass), - pdb_get_unknown_6(sampass)); - - - /* malloc the space needed */ - if ( (*buf=(uint8*)malloc(len)) == NULL) { - DEBUG(0,("init_buffer_from_sam: Unable to malloc() memory for buffer!\n")); - return (-1); - } - - /* now for the real call to tdb_pack() */ - buflen = tdb_pack(*buf, len, TDB_FORMAT_STRING, - logon_time, - logoff_time, - kickoff_time, - pass_last_set_time, - pass_can_change_time, - pass_must_change_time, - username_len, username, - domain_len, domain, - nt_username_len, nt_username, - fullname_len, fullname, - homedir_len, homedir, - dir_drive_len, dir_drive, - logon_script_len, logon_script, - profile_path_len, profile_path, - acct_desc_len, acct_desc, - workstations_len, workstations, - unknown_str_len, unknown_str, - munged_dial_len, munged_dial, - user_rid, - group_rid, - lm_pw_len, lm_pw, - nt_pw_len, nt_pw, - pdb_get_acct_ctrl(sampass), - pdb_get_unknown_3(sampass), - pdb_get_logon_divs(sampass), - pdb_get_hours_len(sampass), - MAX_HOURS_LEN, pdb_get_hours(sampass), - pdb_get_unknown_5(sampass), - pdb_get_unknown_6(sampass)); - - - /* check to make sure we got it correct */ - if (buflen != len) { - DEBUG(0, ("init_buffer_from_sam: somthing odd is going on here: bufflen (%d) != len (%d) in tdb_pack operations!\n", - buflen, len)); - /* error */ - SAFE_FREE (*buf); - return (-1); - } - - return (buflen); -} - /*************************************************************** Open the TDB passwd database for SAM account enumeration. ****************************************************************/ @@ -488,6 +85,7 @@ static void close_tdb(struct tdbsam_privates *tdb_state) static void tdbsam_endsampwent(struct pdb_methods *my_methods) { struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)my_methods->private_data; + SAFE_FREE(tdb_state->key.dptr); close_tdb(tdb_state); DEBUG(7, ("endtdbpwent: closed sam database.\n")); @@ -501,7 +99,7 @@ static NTSTATUS tdbsam_getsampwent(struct pdb_methods *my_methods, SAM_ACCOUNT * { NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)my_methods->private_data; - TDB_DATA data; + TDB_DATA data, old_key; const char *prefix = USERPREFIX; int prefixlen = strlen (prefix); @@ -512,10 +110,16 @@ static NTSTATUS tdbsam_getsampwent(struct pdb_methods *my_methods, SAM_ACCOUNT * } /* skip all non-USER entries (eg. RIDs) */ - while ((tdb_state->key.dsize != 0) && (strncmp(tdb_state->key.dptr, prefix, prefixlen))) + while ((tdb_state->key.dsize != 0) && (strncmp(tdb_state->key.dptr, prefix, prefixlen))) { + + old_key = tdb_state->key; + /* increment to next in line */ tdb_state->key = tdb_nextkey(tdb_state->passwd_tdb, tdb_state->key); + SAFE_FREE(old_key.dptr); + } + /* do we have an valid iteration pointer? */ if(tdb_state->passwd_tdb == NULL) { DEBUG(0,("pdb_get_sampwent: Bad TDB Context pointer.\n")); @@ -529,16 +133,20 @@ static NTSTATUS tdbsam_getsampwent(struct pdb_methods *my_methods, SAM_ACCOUNT * } /* unpack the buffer */ - if (!init_sam_from_buffer(tdb_state, user, data.dptr, data.dsize)) { + if (!init_sam_from_buffer(user, data.dptr, data.dsize)) { DEBUG(0,("pdb_getsampwent: Bad SAM_ACCOUNT entry returned from TDB!\n")); SAFE_FREE(data.dptr); return nt_status; } SAFE_FREE(data.dptr); + old_key = tdb_state->key; + /* increment to next in line */ tdb_state->key = tdb_nextkey(tdb_state->passwd_tdb, tdb_state->key); + SAFE_FREE(old_key.dptr); + return NT_STATUS_OK; } @@ -563,7 +171,7 @@ static NTSTATUS tdbsam_getsampwnam (struct pdb_methods *my_methods, SAM_ACCOUNT /* Data is stored in all lower-case */ fstrcpy(name, sname); - strlower(name); + strlower_m(name); /* set search key */ slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name); @@ -587,7 +195,7 @@ static NTSTATUS tdbsam_getsampwnam (struct pdb_methods *my_methods, SAM_ACCOUNT } /* unpack the buffer */ - if (!init_sam_from_buffer(tdb_state, user, data.dptr, data.dsize)) { + if (!init_sam_from_buffer(user, data.dptr, data.dsize)) { DEBUG(0,("pdb_getsampwent: Bad SAM_ACCOUNT entry returned from TDB!\n")); SAFE_FREE(data.dptr); tdb_close(pwd_tdb); @@ -670,7 +278,7 @@ static NTSTATUS tdbsam_delete_sam_account(struct pdb_methods *my_methods, SAM_AC fstring name; fstrcpy(name, pdb_get_username(sam_pass)); - strlower(name); + strlower_m(name); /* open the TDB */ if (!(pwd_tdb = tdb_open_log(tdb_state->tdbsam_location, 0, TDB_DEFAULT, O_RDWR, 0600))) { @@ -727,63 +335,39 @@ static BOOL tdb_update_sam(struct pdb_methods *my_methods, SAM_ACCOUNT* newpwd, fstring name; BOOL ret = True; uint32 user_rid; - BOOL tdb_ret; /* invalidate the existing TDB iterator if it is open */ + if (tdb_state->passwd_tdb) { tdb_close(tdb_state->passwd_tdb); tdb_state->passwd_tdb = NULL; } /* open the account TDB passwd*/ + pwd_tdb = tdb_open_log(tdb_state->tdbsam_location, 0, TDB_DEFAULT, O_RDWR | O_CREAT, 0600); - if (!pwd_tdb) - { - DEBUG(0, ("tdb_update_sam: Unable to open TDB passwd (%s)!\n", tdb_state->tdbsam_location)); + + if (!pwd_tdb) { + DEBUG(0, ("tdb_update_sam: Unable to open TDB passwd (%s)!\n", + tdb_state->tdbsam_location)); return False; } if (!pdb_get_group_rid(newpwd)) { - DEBUG (0,("tdb_update_sam: Failing to store a SAM_ACCOUNT for [%s] without a primary group RID\n",pdb_get_username(newpwd))); + DEBUG (0,("tdb_update_sam: Failing to store a SAM_ACCOUNT for [%s] without a primary group RID\n", + pdb_get_username(newpwd))); ret = False; goto done; } - /* if flag == TDB_INSERT then make up a new RID else throw an error. */ - if (!(user_rid = pdb_get_user_rid(newpwd))) { - if ((flag & TDB_INSERT) && tdb_state->permit_non_unix_accounts) { - uint32 lowrid, highrid; - if (!idmap_get_free_rid_range(&lowrid, &highrid)) { - /* should never happen */ - DEBUG(0, ("tdbsam: something messed up, no high/low rids but nua enabled ?!\n")); - ret = False; - goto done; - } - user_rid = lowrid; - tdb_ret = tdb_change_uint32_atomic(pwd_tdb, "RID_COUNTER", &user_rid, RID_MULTIPLIER); - if (!tdb_ret) { - ret = False; - goto done; - } - if (user_rid > highrid) { - DEBUG(0, ("tdbsam: no NUA rids available, cannot add user %s!\n", pdb_get_username(newpwd))); - ret = False; - goto done; - } - if (!pdb_set_user_sid_from_rid(newpwd, user_rid, PDB_CHANGED)) { - DEBUG(0, ("tdbsam: not able to set new allocated user RID into sam account!\n")); - ret = False; - goto done; - } - } else { - DEBUG (0,("tdb_update_sam: Failing to store a SAM_ACCOUNT for [%s] without a RID\n",pdb_get_username(newpwd))); - ret = False; - goto done; - } + if ( !(user_rid = pdb_get_user_rid(newpwd)) ) { + DEBUG(0,("tdb_update_sam: SAM_ACCOUNT (%s) with no RID!\n", pdb_get_username(newpwd))); + ret = False; + goto done; } /* copy the SAM_ACCOUNT struct into a BYTE buffer for storage */ - if ((data.dsize=init_buffer_from_sam (tdb_state, &buf, newpwd)) == -1) { + if ((data.dsize=init_buffer_from_sam (&buf, newpwd, False)) == -1) { DEBUG(0,("tdb_update_sam: ERROR - Unable to copy SAM_ACCOUNT info BYTE buffer!\n")); ret = False; goto done; @@ -791,7 +375,7 @@ static BOOL tdb_update_sam(struct pdb_methods *my_methods, SAM_ACCOUNT* newpwd, data.dptr = buf; fstrcpy(name, pdb_get_username(newpwd)); - strlower(name); + strlower_m(name); DEBUG(5, ("Storing %saccount %s with RID %d\n", flag == TDB_INSERT ? "(new) " : "", name, user_rid)); @@ -912,11 +496,10 @@ static void free_private_data(void **vp) } -NTSTATUS pdb_init_tdbsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location) +static NTSTATUS pdb_init_tdbsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location) { NTSTATUS nt_status; struct tdbsam_privates *tdb_state; - uid_t low_nua_uid, high_nua_uid; if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) { return nt_status; @@ -954,25 +537,11 @@ NTSTATUS pdb_init_tdbsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, con (*pdb_method)->free_private_data = free_private_data; - if (lp_idmap_uid(&low_nua_uid, &high_nua_uid)) { - DEBUG(0, ("idmap uid range defined, non unix accounts enabled\n")); - - tdb_state->permit_non_unix_accounts = True; - - tdb_state->low_nua_rid=fallback_pdb_uid_to_user_rid(low_nua_uid); - - tdb_state->high_nua_rid=fallback_pdb_uid_to_user_rid(high_nua_uid); - - } else { - tdb_state->algorithmic_rids = True; - } - return NT_STATUS_OK; } -int pdb_tdbsam_init(void) +NTSTATUS pdb_tdbsam_init(void) { - smb_register_passdb(PASSDB_INTERFACE_VERSION, "tdbsam", pdb_init_tdbsam); - return True; + return smb_register_passdb(PASSDB_INTERFACE_VERSION, "tdbsam", pdb_init_tdbsam); } diff --git a/source3/passdb/pdb_xml.c b/source3/passdb/pdb_xml.c index 7a5c0e2b53..154d8c927f 100644 --- a/source3/passdb/pdb_xml.c +++ b/source3/passdb/pdb_xml.c @@ -28,7 +28,7 @@ */ -#define XML_URL "http://www.samba.org/ns" +#define XML_URL "http://samba.org/~jelmer/sambapdb.dtd" #include "includes.h" diff --git a/source3/passdb/privileges.c b/source3/passdb/privileges.c index 688053674b..624817e32e 100644 --- a/source3/passdb/privileges.c +++ b/source3/passdb/privileges.c @@ -107,7 +107,7 @@ NTSTATUS privilege_enum_account_with_right(const char *right, return NT_STATUS_INTERNAL_ERROR; } - data = tdb_fetch_by_string(tdb, right); + data = tdb_fetch_bystring(tdb, right); if (!data.dptr) { *count = 0; *sids = NULL; @@ -168,7 +168,7 @@ static NTSTATUS privilege_set_accounts_with_right(const char *right, data.dsize = PTR_DIFF(p, data.dptr); - if (tdb_store_by_string(tdb, right, data, TDB_REPLACE) != 0) { + if (tdb_store_bystring(tdb, right, data, TDB_REPLACE) != 0) { free(data.dptr); return NT_STATUS_INTERNAL_ERROR; } diff --git a/source3/passdb/secrets.c b/source3/passdb/secrets.c index 5df0edc29a..bad8e96865 100644 --- a/source3/passdb/secrets.c +++ b/source3/passdb/secrets.c @@ -100,7 +100,7 @@ BOOL secrets_store_domain_sid(const char *domain, const DOM_SID *sid) fstring key; slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_DOMAIN_SID, domain); - strupper(key); + strupper_m(key); return secrets_store(key, sid, sizeof(DOM_SID)); } @@ -111,7 +111,7 @@ BOOL secrets_fetch_domain_sid(const char *domain, DOM_SID *sid) size_t size; slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_DOMAIN_SID, domain); - strupper(key); + strupper_m(key); dyn_sid = (DOM_SID *)secrets_fetch(key, &size); if (dyn_sid == NULL) @@ -133,7 +133,7 @@ BOOL secrets_store_domain_guid(const char *domain, GUID *guid) fstring key; slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_DOMAIN_GUID, domain); - strupper(key); + strupper_m(key); return secrets_store(key, guid, sizeof(GUID)); } @@ -145,13 +145,13 @@ BOOL secrets_fetch_domain_guid(const char *domain, GUID *guid) GUID new_guid; slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_DOMAIN_GUID, domain); - strupper(key); + strupper_m(key); dyn_guid = (GUID *)secrets_fetch(key, &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); + smb_uuid_generate_random(&new_guid); if (!secrets_store_domain_guid(domain, &new_guid)) return False; dyn_guid = (GUID *)secrets_fetch(key, &size); @@ -183,7 +183,7 @@ const char *trust_keystr(const char *domain) slprintf(keystr,sizeof(keystr)-1,"%s/%s", SECRETS_MACHINE_ACCT_PASS, domain); - strupper(keystr); + strupper_m(keystr); return keystr; } @@ -200,7 +200,7 @@ char *trustdom_keystr(const char *domain) static char* keystr; asprintf(&keystr, "%s/%s", SECRETS_DOMTRUST_ACCT_PASS, domain); - strupper(keystr); + strupper_m(keystr); return keystr; } @@ -252,8 +252,7 @@ BOOL secrets_fetch_trust_account_password(const char *domain, uint8 ret_pwd[16], plaintext = secrets_fetch_machine_password(domain, pass_last_set_time, channel); if (plaintext) { - /* we have an ADS password - use that */ - DEBUG(4,("Using ADS machine password\n")); + DEBUG(4,("Using cleartext machine password\n")); E_md4hash(plaintext, ret_pwd); SAFE_FREE(plaintext); return True; @@ -400,7 +399,7 @@ BOOL secrets_store_machine_password(const char *pass, const char *domain, uint32 asprintf(&key, "%s/%s", SECRETS_MACHINE_PASSWORD, domain); if (!key) return False; - strupper(key); + strupper_m(key); ret = secrets_store(key, pass, strlen(pass)+1); SAFE_FREE(key); @@ -411,7 +410,7 @@ BOOL secrets_store_machine_password(const char *pass, const char *domain, uint32 asprintf(&key, "%s/%s", SECRETS_MACHINE_LAST_CHANGE_TIME, domain); if (!key) return False; - strupper(key); + strupper_m(key); SIVAL(&last_change_time, 0, time(NULL)); ret = secrets_store(key, &last_change_time, sizeof(last_change_time)); @@ -420,7 +419,7 @@ BOOL secrets_store_machine_password(const char *pass, const char *domain, uint32 asprintf(&key, "%s/%s", SECRETS_MACHINE_SEC_CHANNEL_TYPE, domain); if (!key) return False; - strupper(key); + strupper_m(key); SIVAL(&sec_channel_type, 0, sec_channel); ret = secrets_store(key, &sec_channel_type, sizeof(sec_channel_type)); @@ -441,7 +440,7 @@ char *secrets_fetch_machine_password(const char *domain, char *key = NULL; char *ret; asprintf(&key, "%s/%s", SECRETS_MACHINE_PASSWORD, domain); - strupper(key); + strupper_m(key); ret = (char *)secrets_fetch(key, NULL); SAFE_FREE(key); @@ -449,10 +448,11 @@ char *secrets_fetch_machine_password(const char *domain, size_t size; uint32 *last_set_time; asprintf(&key, "%s/%s", SECRETS_MACHINE_LAST_CHANGE_TIME, domain); - strupper(key); + strupper_m(key); last_set_time = secrets_fetch(key, &size); if (last_set_time) { *pass_last_set_time = IVAL(last_set_time,0); + SAFE_FREE(last_set_time); } else { *pass_last_set_time = 0; } @@ -463,10 +463,11 @@ char *secrets_fetch_machine_password(const char *domain, size_t size; uint32 *channel_type; asprintf(&key, "%s/%s", SECRETS_MACHINE_SEC_CHANNEL_TYPE, domain); - strupper(key); + strupper_m(key); channel_type = secrets_fetch(key, &size); if (channel_type) { *channel = IVAL(channel_type,0); + SAFE_FREE(channel_type); } else { *channel = get_default_sec_channel(); } @@ -614,7 +615,7 @@ NTSTATUS secrets_get_trusted_domains(TALLOC_CTX* ctx, int* enum_ctx, unsigned in DEBUG(0, ("strndup failed!\n")); return NT_STATUS_NO_MEMORY; } - + packed_pass = secrets_fetch(secrets_key, &size); packed_size = tdb_trusted_dom_pass_unpack(packed_pass, size, pass); /* packed representation isn't needed anymore */ diff --git a/source3/printing/lpq_parse.c b/source3/printing/lpq_parse.c index c845170749..0acca67b70 100644 --- a/source3/printing/lpq_parse.c +++ b/source3/printing/lpq_parse.c @@ -145,8 +145,8 @@ static BOOL parse_lpq_bsd(char *line,print_queue_struct *buf,BOOL first) buf->size = atoi(tok[TOTALTOK]); buf->status = strequal(tok[RANKTOK],"active")?LPQ_PRINTING:LPQ_QUEUED; buf->time = time(NULL); - StrnCpy(buf->fs_user,tok[USERTOK],sizeof(buf->fs_user)-1); - StrnCpy(buf->fs_file,tok[FILETOK],sizeof(buf->fs_file)-1); + fstrcpy(buf->fs_user,tok[USERTOK]); + fstrcpy(buf->fs_file,tok[FILETOK]); if ((FILETOK + 1) != TOTALTOK) { int i; @@ -266,7 +266,7 @@ static BOOL parse_lpq_lprng(char *line,print_queue_struct *buf,BOOL first) buf->time = LPRng_time(tokarr[LPRNG_TIMETOK]); - StrnCpy(buf->fs_user,tokarr[LPRNG_USERTOK],sizeof(buf->fs_user)-1); + fstrcpy(buf->fs_user,tokarr[LPRNG_USERTOK]); /* The '@hostname' prevents windows from displaying the printing icon * for the current user on the taskbar. Plop in a null. @@ -276,7 +276,7 @@ static BOOL parse_lpq_lprng(char *line,print_queue_struct *buf,BOOL first) *ptr = '\0'; } - StrnCpy(buf->fs_file,tokarr[LPRNG_FILETOK],sizeof(buf->fs_file)-1); + fstrcpy(buf->fs_file,tokarr[LPRNG_FILETOK]); if ((LPRNG_FILETOK + 1) != LPRNG_TOTALTOK) { int i; @@ -353,8 +353,8 @@ static BOOL parse_lpq_aix(char *line,print_queue_struct *buf,BOOL first) buf->status = strequal(tok[0],"HELD")?LPQ_PAUSED:LPQ_QUEUED; buf->priority = 0; buf->time = time(NULL); - StrnCpy(buf->fs_user,tok[3],sizeof(buf->fs_user)-1); - StrnCpy(buf->fs_file,tok[2],sizeof(buf->fs_file)-1); + fstrcpy(buf->fs_user,tok[3]); + fstrcpy(buf->fs_file,tok[2]); } else { @@ -387,8 +387,8 @@ static BOOL parse_lpq_aix(char *line,print_queue_struct *buf,BOOL first) buf->status = strequal(tok[2],"RUNNING")?LPQ_PRINTING:LPQ_QUEUED; buf->priority = 0; buf->time = time(NULL); - StrnCpy(buf->fs_user,tok[5],sizeof(buf->fs_user)-1); - StrnCpy(buf->fs_file,tok[4],sizeof(buf->fs_file)-1); + fstrcpy(buf->fs_user,tok[5]); + fstrcpy(buf->fs_file,tok[4]); } @@ -449,14 +449,14 @@ static BOOL parse_lpq_hpux(char *line, print_queue_struct *buf, BOOL first) fstrcpy(tok[0],"STDIN"); buf->size = atoi(tok[1]); - StrnCpy(buf->fs_file,tok[0],sizeof(buf->fs_file)-1); + fstrcpy(buf->fs_file,tok[0]); /* fill things from header line */ buf->time = jobtime; buf->job = jobid; buf->status = jobstat; buf->priority = jobprio; - StrnCpy(buf->fs_user,jobuser,sizeof(buf->fs_user)-1); + fstrcpy(buf->fs_user,jobuser); return(True); } @@ -482,7 +482,7 @@ static BOOL parse_lpq_hpux(char *line, print_queue_struct *buf, BOOL first) /* the 2nd, 5th & 7th column must be integer */ if (!isdigit((int)*tok[1]) || !isdigit((int)*tok[4]) || !isdigit((int)*tok[6])) return(False); jobid = atoi(tok[1]); - StrnCpy(jobuser,tok[2],sizeof(buf->fs_user)-1); + fstrcpy(jobuser,tok[2]); jobprio = atoi(tok[4]); /* process time */ @@ -573,8 +573,8 @@ static BOOL parse_lpq_sysv(char *line,print_queue_struct *buf,BOOL first) buf->status = LPQ_QUEUED; buf->priority = 0; buf->time = EntryTime(tok, 4, count, 7); - StrnCpy(buf->fs_user,tok[2],sizeof(buf->fs_user)-1); - StrnCpy(buf->fs_file,tok[2],sizeof(buf->fs_file)-1); + fstrcpy(buf->fs_user,tok[2]); + fstrcpy(buf->fs_file,tok[2]); return(True); } @@ -633,8 +633,8 @@ static BOOL parse_lpq_qnx(char *line,print_queue_struct *buf,BOOL first) buf->status = strequal(tok[3],"active")?LPQ_PRINTING:LPQ_QUEUED; buf->priority = 0; buf->time = time(NULL); - StrnCpy(buf->fs_user,tok[1],sizeof(buf->fs_user)-1); - StrnCpy(buf->fs_file,tok[6],sizeof(buf->fs_file)-1); + fstrcpy(buf->fs_user,tok[1]); + fstrcpy(buf->fs_file,tok[6]); return(True); } @@ -704,8 +704,8 @@ static BOOL parse_lpq_plp(char *line,print_queue_struct *buf,BOOL first) buf->status = strequal(tok[0],"active")?LPQ_PRINTING:LPQ_QUEUED; buf->priority = 0; buf->time = time(NULL); - StrnCpy(buf->fs_user,tok[1],sizeof(buf->fs_user)-1); - StrnCpy(buf->fs_file,tok[6],sizeof(buf->fs_file)-1); + fstrcpy(buf->fs_user,tok[1]); + fstrcpy(buf->fs_file,tok[6]); return(True); } @@ -779,8 +779,8 @@ static BOOL parse_lpq_nt(char *line,print_queue_struct *buf,BOOL first) buf->priority = 0; buf->size = atoi(parse_line.size); buf->time = time(NULL); - StrnCpy(buf->fs_user, parse_line.owner, sizeof(buf->fs_user)-1); - StrnCpy(buf->fs_file, parse_line.jobname, sizeof(buf->fs_file)-1); + fstrcpy(buf->fs_user, parse_line.owner); + fstrcpy(buf->fs_file, parse_line.jobname); if (strequal(parse_line.status, LPRNT_PRINTING)) buf->status = LPQ_PRINTING; else if (strequal(parse_line.status, LPRNT_PAUSED)) @@ -838,7 +838,7 @@ static BOOL parse_lpq_os2(char *line,print_queue_struct *buf,BOOL first) /* Get the job name */ parse_line.space2[0] = '\0'; trim_string(parse_line.jobname, NULL, " "); - StrnCpy(buf->fs_file, parse_line.jobname, sizeof(buf->fs_file)-1); + fstrcpy(buf->fs_file, parse_line.jobname); buf->priority = 0; buf->size = atoi(parse_line.size); @@ -856,7 +856,7 @@ static BOOL parse_lpq_os2(char *line,print_queue_struct *buf,BOOL first) !strequal(parse_line.status, LPROS2_WAITING)) return(False); - StrnCpy(buf->fs_user, parse_line.owner, sizeof(buf->fs_user)-1); + fstrcpy(buf->fs_user, parse_line.owner); if (strequal(parse_line.status, LPROS2_PRINTING)) buf->status = LPQ_PRINTING; else if (strequal(parse_line.status, LPROS2_PAUSED)) @@ -984,29 +984,29 @@ BOOL parse_lpq_entry(int snum,char *line, printer status line: handle them so that most severe condition is shown */ int i; - strlower(line); + strlower_m(line); switch (status->status) { case LPSTAT_OK: for (i=0; stat0_strings[i]; i++) if (strstr(line,stat0_strings[i])) { - StrnCpy(status->message,line,sizeof(status->message)-1); - status->status=LPSTAT_OK; - return ret; + fstrcpy(status->message,line); + status->status=LPSTAT_OK; + return ret; } case LPSTAT_STOPPED: for (i=0; stat1_strings[i]; i++) if (strstr(line,stat1_strings[i])) { - StrnCpy(status->message,line,sizeof(status->message)-1); - status->status=LPSTAT_STOPPED; - return ret; + fstrcpy(status->message,line); + status->status=LPSTAT_STOPPED; + return ret; } case LPSTAT_ERROR: for (i=0; stat2_strings[i]; i++) if (strstr(line,stat2_strings[i])) { - StrnCpy(status->message,line,sizeof(status->message)-1); - status->status=LPSTAT_ERROR; - return ret; + fstrcpy(status->message,line); + status->status=LPSTAT_ERROR; + return ret; } break; } diff --git a/source3/printing/notify.c b/source3/printing/notify.c index ee973da211..479d883134 100644 --- a/source3/printing/notify.c +++ b/source3/printing/notify.c @@ -480,7 +480,7 @@ void notify_printer_location(int snum, char *location) snum, strlen(location) + 1, location); } -void notify_printer_byname( char *printername, uint32 change, char *value ) +void notify_printer_byname( const char *printername, uint32 change, char *value ) { int snum = print_queue_snum(printername); int type = PRINTER_NOTIFY_TYPE; diff --git a/source3/printing/nt_printing.c b/source3/printing/nt_printing.c index 2b4b7dab6b..5e6e95ff7e 100644 --- a/source3/printing/nt_printing.c +++ b/source3/printing/nt_printing.c @@ -198,6 +198,22 @@ static const nt_forms_struct default_forms[] = { {"PRC Envelope #10 Rotated",0x1,0x6fd10,0x4f1a0,0x0,0x0,0x6fd10,0x4f1a0} }; +struct table_node { + const char *long_archi; + const char *short_archi; + int version; +}; + +static const struct table_node archi_table[]= { + + {"Windows 4.0", "WIN40", 0 }, + {"Windows NT x86", "W32X86", 2 }, + {"Windows NT R4000", "W32MIPS", 2 }, + {"Windows NT Alpha_AXP", "W32ALPHA", 2 }, + {"Windows NT PowerPC", "W32PPC", 2 }, + {NULL, "", -1 } +}; + static BOOL upgrade_to_version_3(void) { TDB_DATA kbuf, newkey, dbuf; @@ -638,12 +654,12 @@ void update_a_form(nt_forms_struct **list, const FORM *form, int count) int get_ntdrivers(fstring **list, const char *architecture, uint32 version) { int total=0; - fstring short_archi; + const char *short_archi; fstring *fl; pstring key; TDB_DATA kbuf, newkey; - get_short_archi(short_archi, architecture); + short_archi = get_short_archi(architecture); slprintf(key, sizeof(key)-1, "%s%s/%d/", DRIVERS_PREFIX, short_archi, version); for (kbuf = tdb_firstkey(tdb_drivers); @@ -667,52 +683,32 @@ int get_ntdrivers(fstring **list, const char *architecture, uint32 version) } /**************************************************************************** - Function to do the mapping between the long architecture name and - the short one. +function to do the mapping between the long architecture name and +the short one. ****************************************************************************/ -BOOL get_short_archi(char *short_archi, const char *long_archi) +const char *get_short_archi(const char *long_archi) { - struct table { - const char *long_archi; - const char *short_archi; - }; - - struct table archi_table[]= - { - {"Windows 4.0", "WIN40" }, - {"Windows NT x86", "W32X86" }, - {"Windows NT R4000", "W32MIPS" }, - {"Windows NT Alpha_AXP", "W32ALPHA" }, - {"Windows NT PowerPC", "W32PPC" }, - {NULL, "" } - }; - - int i=-1; + int i=-1; - DEBUG(107,("Getting architecture dependant directory\n")); + DEBUG(107,("Getting architecture dependant directory\n")); + do { + i++; + } while ( (archi_table[i].long_archi!=NULL ) && + StrCaseCmp(long_archi, archi_table[i].long_archi) ); - if (long_archi == NULL) { - DEBUGADD(107,("Bad long_archi param.!\n")); - return False; - } + if (archi_table[i].long_archi==NULL) { + DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi)); + return NULL; + } - do { - i++; - } while ( (archi_table[i].long_archi!=NULL ) && - StrCaseCmp(long_archi, archi_table[i].long_archi) ); + /* this might be client code - but shouldn't this be an fstrcpy etc? */ - if (archi_table[i].long_archi==NULL) { - DEBUGADD(107,("Unknown architecture [%s] !\n", long_archi)); - return False; - } - StrnCpy (short_archi, archi_table[i].short_archi, strlen(archi_table[i].short_archi)); + DEBUGADD(108,("index: [%d]\n", i)); + DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi)); + DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi)); - DEBUGADD(108,("index: [%d]\n", i)); - DEBUGADD(108,("long architecture: [%s]\n", long_archi)); - DEBUGADD(108,("short architecture: [%s]\n", short_archi)); - - return True; + return archi_table[i].short_archi; } /**************************************************************************** @@ -750,7 +746,7 @@ static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 } /* Skip OEM header (if any) and the DOS stub to start of Windows header */ - if (fsp->conn->vfs_ops.lseek(fsp, fsp->fd, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) { + if (SMB_VFS_LSEEK(fsp, fsp->fd, SVAL(buf,DOS_HEADER_LFANEW_OFFSET), SEEK_SET) == (SMB_OFF_T)-1) { DEBUG(3,("get_file_version: File [%s] too short, errno = %d\n", fname, errno)); /* Assume this isn't an error... the file just looks sort of like a PE/NE file */ @@ -810,7 +806,7 @@ static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 } /* Seek to the start of the .rsrc section info */ - if (fsp->conn->vfs_ops.lseek(fsp, fsp->fd, section_pos, SEEK_SET) == (SMB_OFF_T)-1) { + if (SMB_VFS_LSEEK(fsp, fsp->fd, section_pos, SEEK_SET) == (SMB_OFF_T)-1) { DEBUG(3,("get_file_version: PE file [%s] too short for section info, errno = %d\n", fname, errno)); goto error_exit; @@ -903,7 +899,7 @@ static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 * twice, as it is simpler to read the code. */ if (strcmp(&buf[i], VS_SIGNATURE) == 0) { /* Compute skip alignment to next long address */ - int skip = -(fsp->conn->vfs_ops.lseek(fsp, fsp->fd, 0, SEEK_CUR) - (byte_count - i) + + int skip = -(SMB_VFS_LSEEK(fsp, fsp->fd, 0, SEEK_CUR) - (byte_count - i) + sizeof(VS_SIGNATURE)) & 3; if (IVAL(buf,i+sizeof(VS_SIGNATURE)+skip) != 0xfeef04bd) continue; @@ -996,7 +992,7 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file, fstr DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n", old_file)); use_version = False; - if (fsp->conn->vfs_ops.fstat(fsp, fsp->fd, &st) == -1) goto error_exit; + if (SMB_VFS_FSTAT(fsp, fsp->fd, &st) == -1) goto error_exit; old_create_time = st.st_mtime; DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time)); } @@ -1025,7 +1021,7 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file, fstr DEBUG(6,("file_version_is_newer: Version info not found [%s], use mod time\n", new_file)); use_version = False; - if (fsp->conn->vfs_ops.fstat(fsp, fsp->fd, &st) == -1) goto error_exit; + if (SMB_VFS_FSTAT(fsp, fsp->fd, &st) == -1) goto error_exit; new_create_time = st.st_mtime; DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time)); } @@ -1066,7 +1062,7 @@ static int file_version_is_newer(connection_struct *conn, fstring new_file, fstr /**************************************************************************** Determine the correct cVersion associated with an architecture and driver ****************************************************************************/ -static uint32 get_correct_cversion(fstring architecture, fstring driverpath_in, +static uint32 get_correct_cversion(const char *architecture, fstring driverpath_in, struct current_user *user, WERROR *perr) { int cversion; @@ -1111,7 +1107,7 @@ static uint32 get_correct_cversion(fstring architecture, fstring driverpath_in, } /* We are temporarily becoming the connection user. */ - if (!become_user(conn, conn->vuid)) { + if (!become_user(conn, user->vuid)) { DEBUG(0,("get_correct_cversion: Can't become user!\n")); *perr = WERR_ACCESS_DENIED; return -1; @@ -1192,7 +1188,7 @@ static uint32 get_correct_cversion(fstring architecture, fstring driverpath_in, static WERROR clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver, struct current_user *user) { - fstring architecture; + const char *architecture; fstring new_name; char *p; int i; @@ -1232,7 +1228,7 @@ static WERROR clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *dri } } - get_short_archi(architecture, driver->environment); + architecture = get_short_archi(driver->environment); /* jfm:7/16/2000 the client always sends the cversion=0. * The server should check which version the driver is by reading @@ -1256,7 +1252,7 @@ static WERROR clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *dri ****************************************************************************/ static WERROR clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver, struct current_user *user) { - fstring architecture; + const char *architecture; fstring new_name; char *p; int i; @@ -1296,7 +1292,7 @@ static WERROR clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *dri } } - get_short_archi(architecture, driver->environment); + architecture = get_short_archi(driver->environment); /* jfm:7/16/2000 the client always sends the cversion=0. * The server should check which version the driver is by reading @@ -1382,7 +1378,7 @@ BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, { NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver; NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver; - fstring architecture; + const char *architecture; pstring new_dir; pstring old_name; pstring new_name; @@ -1409,7 +1405,7 @@ BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, return False; } - get_short_archi(architecture, driver->environment); + architecture = get_short_archi(driver->environment); /* * Connect to the print$ share under the same account as the user connected to the rpc pipe. @@ -1589,7 +1585,7 @@ BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver) { int len, buflen; - fstring architecture; + const char *architecture; pstring directory; fstring temp_name; pstring key; @@ -1597,7 +1593,7 @@ static uint32 add_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver) int i, ret; TDB_DATA kbuf, dbuf; - get_short_archi(architecture, driver->environment); + architecture = get_short_archi(driver->environment); /* The names are relative. We store them in the form: \print$\arch\version\driver.xxx * \\server is added in the rpc server layer. @@ -1751,14 +1747,14 @@ static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, { NT_PRINTER_DRIVER_INFO_LEVEL_3 driver; TDB_DATA kbuf, dbuf; - fstring architecture; + const char *architecture; int len = 0; int i; pstring key; ZERO_STRUCT(driver); - get_short_archi(architecture, arch); + architecture = get_short_archi(arch); DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, drivername)); @@ -2447,6 +2443,7 @@ uint32 get_printer_subkeys( NT_PRINTER_DATA *data, const char* key, fstring **su return num_subkeys; } +#ifdef HAVE_ADS static void map_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name, const char *sz) { @@ -2559,7 +2556,6 @@ static BOOL map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2 *info2) return True; } -#ifdef HAVE_ADS static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2 *info2, GUID guid) { int i; @@ -2605,12 +2601,19 @@ static WERROR publish_it(NT_PRINTER_INFO_LEVEL *printer) ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME, printer->info_2->sharename); - /* connect to the ADS server */ - ads = ads_init(NULL, NULL, lp_ads_server()); + /* initial ads structure */ + + ads = ads_init(NULL, NULL, NULL); if (!ads) { DEBUG(3, ("ads_init() failed\n")); return WERR_SERVER_UNAVAILABLE; } + setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1); + SAFE_FREE(ads->auth.password); + ads->auth.password = secrets_fetch_machine_password(lp_workgroup(), + NULL, NULL); + + /* ads_connect() will find the DC for us */ ads_rc = ads_connect(ads); if (!ADS_ERR_OK(ads_rc)) { DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc))); @@ -2663,11 +2666,17 @@ WERROR unpublish_it(NT_PRINTER_INFO_LEVEL *printer) return win_rc; } - ads = ads_init(NULL, NULL, lp_ads_server()); + ads = ads_init(NULL, NULL, NULL); if (!ads) { DEBUG(3, ("ads_init() failed\n")); return WERR_SERVER_UNAVAILABLE; } + setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1); + SAFE_FREE(ads->auth.password); + ads->auth.password = secrets_fetch_machine_password(lp_workgroup(), + NULL, NULL); + + /* ads_connect() will find the DC for us */ ads_rc = ads_connect(ads); if (!ADS_ERR_OK(ads_rc)) { DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc))); @@ -3813,7 +3822,7 @@ static NTSTATUS copy_printer_data( NT_PRINTER_DATA *dst, NT_PRINTER_DATA *src ) Caller must free. ****************************************************************************/ -static NT_PRINTER_INFO_LEVEL_2* dup_printer_2( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL_2 *printer ) +NT_PRINTER_INFO_LEVEL_2* dup_printer_2( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL_2 *printer ) { NT_PRINTER_INFO_LEVEL_2 *copy; @@ -3845,8 +3854,6 @@ static NT_PRINTER_INFO_LEVEL_2* dup_printer_2( TALLOC_CTX *ctx, NT_PRINTER_INFO_ Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory. ****************************************************************************/ -#define ENABLE_PRINT_HND_CACHE 1 - WERROR get_a_printer( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level, const char *sharename) { @@ -3871,7 +3878,6 @@ WERROR get_a_printer( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_print * is actually for a printer and that the printer_info pointer * is valid */ -#ifdef ENABLE_PRINT_HND_CACHE /* JERRY */ if ( print_hnd && (print_hnd->printer_type==PRINTER_HANDLE_IS_PRINTER) && print_hnd->printer_info ) @@ -3890,20 +3896,27 @@ WERROR get_a_printer( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_print break; } -#endif - /* no cache; look it up on disk */ + /* no cache for this handle; see if we can match one from another handle */ - result=get_a_printer_2(&printer->info_2, sharename); - if (W_ERROR_IS_OK(result)) { - dump_a_printer(*printer, level); + if ( print_hnd ) + result = find_printer_in_print_hnd_cache(print_hnd->ctx, &printer->info_2, sharename); + + /* fail to disk if we don't have it with any open handle */ -#if ENABLE_PRINT_HND_CACHE /* JERRY */ + if ( !print_hnd || !W_ERROR_IS_OK(result) ) + result = get_a_printer_2(&printer->info_2, sharename); + + /* we have a new printer now. Save it with this handle */ + + if ( W_ERROR_IS_OK(result) ) { + dump_a_printer(*printer, level); + /* save a copy in cache */ if ( print_hnd && (print_hnd->printer_type==PRINTER_HANDLE_IS_PRINTER)) { if ( !print_hnd->printer_info ) print_hnd->printer_info = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL)); - + if ( print_hnd->printer_info ) { print_hnd->printer_info->info_2 = dup_printer_2(print_hnd->ctx, printer->info_2); @@ -3911,16 +3924,14 @@ WERROR get_a_printer( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_print if ( !print_hnd->printer_info->info_2 ) DEBUG(0,("get_a_printer: unable to copy new printer info!\n")); } - } -#endif - *pp_printer = printer; + *pp_printer = printer; } - else + else SAFE_FREE(printer); - - + break; + default: result=WERR_UNKNOWN_LEVEL; break; @@ -4405,13 +4416,13 @@ WERROR delete_printer_driver( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct cur uint32 version, BOOL delete_files ) { pstring key; - fstring arch; + const char *arch; TDB_DATA kbuf, dbuf; NT_PRINTER_DRIVER_INFO_LEVEL ctr; /* delete the tdb data first */ - get_short_archi(arch, info_3->environment); + arch = get_short_archi(info_3->environment); slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, arch, version, info_3->name); diff --git a/source3/printing/pcap.c b/source3/printing/pcap.c index c399c3c6cc..1bdbf4a789 100644 --- a/source3/printing/pcap.c +++ b/source3/printing/pcap.c @@ -384,7 +384,7 @@ void pcap_printer_fn(void (*fn)(char *, char *)) if (strlen(p)>strlen(comment) && has_punctuation) { - StrnCpy(comment,p,sizeof(comment)-1); + pstrcpy(comment,p); continue; } @@ -398,8 +398,8 @@ void pcap_printer_fn(void (*fn)(char *, char *)) if (!strchr_m(comment,' ') && strlen(p) > strlen(comment)) { - StrnCpy(comment,p,sizeof(comment)-1); - continue; + pstrcpy(comment,p); + continue; } } diff --git a/source3/printing/printfsp.c b/source3/printing/printfsp.c index 45d937f29c..0b6d4fdbe1 100644 --- a/source3/printing/printfsp.c +++ b/source3/printing/printfsp.c @@ -80,7 +80,7 @@ files_struct *print_fsp_open(connection_struct *conn, char *fname) string_set(&fsp->fsp_name,print_job_fname(SNUM(conn),jobid)); fsp->wbmpx_ptr = NULL; fsp->wcp = NULL; - conn->vfs_ops.fstat(fsp,fsp->fd, &sbuf); + SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf); fsp->mode = sbuf.st_mode; fsp->inode = sbuf.st_ino; fsp->dev = sbuf.st_dev; diff --git a/source3/printing/printing.c b/source3/printing/printing.c index add690fb8b..1a7066f906 100644 --- a/source3/printing/printing.c +++ b/source3/printing/printing.c @@ -1180,7 +1180,7 @@ BOOL print_notify_register_pid(int snum) } /* Store back the record. */ - if (tdb_store_by_string(tdb, NOTIFY_PID_LIST_KEY, data, TDB_REPLACE) == -1) { + if (tdb_store_bystring(tdb, NOTIFY_PID_LIST_KEY, data, TDB_REPLACE) == -1) { DEBUG(0,("print_notify_register_pid: Failed to update pid \ list for printer %s\n", printername)); goto done; @@ -1270,7 +1270,7 @@ printer %s database\n", printername)); SAFE_FREE(data.dptr); /* Store back the record. */ - if (tdb_store_by_string(tdb, NOTIFY_PID_LIST_KEY, data, TDB_REPLACE) == -1) { + if (tdb_store_bystring(tdb, NOTIFY_PID_LIST_KEY, data, TDB_REPLACE) == -1) { DEBUG(0,("print_notify_register_pid: Failed to update pid \ list for printer %s\n", printername)); goto done; @@ -1465,7 +1465,7 @@ static BOOL print_job_delete1(int snum, uint32 jobid) else remove_from_jobs_changed(snum, jobid); - /* Delete the tdb entry if the delete suceeded or the job hasn't + /* Delete the tdb entry if the delete succeeded or the job hasn't been spooled. */ if (result == 0) { diff --git a/source3/printing/printing_db.c b/source3/printing/printing_db.c index 0aa8dfafa5..1c7ac71353 100644 --- a/source3/printing/printing_db.c +++ b/source3/printing/printing_db.c @@ -154,7 +154,7 @@ TDB_DATA get_printer_notify_pid_list(TDB_CONTEXT *tdb, const char *printer_name, ZERO_STRUCT(data); - data = tdb_fetch_by_string( tdb, NOTIFY_PID_LIST_KEY ); + data = tdb_fetch_bystring( tdb, NOTIFY_PID_LIST_KEY ); if (!data.dptr) { ZERO_STRUCT(data); @@ -163,7 +163,7 @@ TDB_DATA get_printer_notify_pid_list(TDB_CONTEXT *tdb, const char *printer_name, if (data.dsize % 8) { DEBUG(0,("get_printer_notify_pid_list: Size of record for printer %s not a multiple of 8 !\n", printer_name )); - tdb_delete_by_string(tdb, NOTIFY_PID_LIST_KEY ); + tdb_delete_bystring(tdb, NOTIFY_PID_LIST_KEY ); SAFE_FREE(data.dptr); ZERO_STRUCT(data); return data; diff --git a/source3/python/py_winbind.c b/source3/python/py_winbind.c index 0c40861c70..db66be2321 100644 --- a/source3/python/py_winbind.c +++ b/source3/python/py_winbind.c @@ -261,12 +261,12 @@ static PyObject *py_config_dict(void) /* Winbind uid/gid range */ - if (lp_idmap_uid(&ulow, &uhi)) { + if (lp_winbind_uid(&ulow, &uhi)) { PyDict_SetItemString(result, "uid_low", PyInt_FromLong(ulow)); PyDict_SetItemString(result, "uid_high", PyInt_FromLong(uhi)); } - if (lp_idmap_gid(&glow, &ghi)) { + if (lp_winbind_gid(&glow, &ghi)) { PyDict_SetItemString(result, "gid_low", PyInt_FromLong(glow)); PyDict_SetItemString(result, "gid_high", PyInt_FromLong(ghi)); } diff --git a/source3/registry/reg_db.c b/source3/registry/reg_db.c index b0917c8f60..cd5ec18f02 100644 --- a/source3/registry/reg_db.c +++ b/source3/registry/reg_db.c @@ -250,7 +250,7 @@ int regdb_fetch_reg_keys( char* key, REGSUBKEY_CTR *ctr ) pstring_sub( path, "\\", "/" ); strupper_m( path ); - dbuf = tdb_fetch_by_string( tdb_reg, path ); + dbuf = tdb_fetch_bystring( tdb_reg, path ); buf = dbuf.dptr; buflen = dbuf.dsize; diff --git a/source3/rpc_client/cli_lsarpc.c b/source3/rpc_client/cli_lsarpc.c index 9002ad3d1b..db873236e4 100644 --- a/source3/rpc_client/cli_lsarpc.c +++ b/source3/rpc_client/cli_lsarpc.c @@ -1164,7 +1164,7 @@ NTSTATUS cli_lsa_enum_account_rights(struct cli_state *cli, TALLOC_CTX *mem_ctx, LSA_Q_ENUM_ACCT_RIGHTS q; LSA_R_ENUM_ACCT_RIGHTS r; NTSTATUS result; - unsigned int i; + int i; ZERO_STRUCT(q); ZERO_STRUCT(r); @@ -1199,7 +1199,7 @@ NTSTATUS cli_lsa_enum_account_rights(struct cli_state *cli, TALLOC_CTX *mem_ctx, *privs_name = (char **)talloc(mem_ctx, (*count) * sizeof(char **)); for (i=0;i<*count;i++) { - (*privs_name)[i] = unistr2_tdup(mem_ctx, &r.rights.strings[i].string); + pull_ucs2_talloc(mem_ctx, &(*privs_name)[i], r.rights.strings[i].string.buffer); } done: @@ -1293,58 +1293,6 @@ done: } -/* list account SIDs that have the specified right */ - -NTSTATUS cli_lsa_enum_account_with_right(struct cli_state *cli, TALLOC_CTX *mem_ctx, - POLICY_HND *pol, const char *right, - uint32 *count, DOM_SID **sids) -{ - prs_struct qbuf, rbuf; - LSA_Q_ENUM_ACCT_WITH_RIGHT q; - LSA_R_ENUM_ACCT_WITH_RIGHT r; - NTSTATUS result; - - ZERO_STRUCT(q); - - /* Initialise parse structures */ - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - - /* Marshall data and send request */ - init_q_enum_acct_with_right(&q, pol, right); - - if (!lsa_io_q_enum_acct_with_right("", &q, &qbuf, 0) || - !rpc_api_pipe_req(cli, LSA_ENUMACCTWITHRIGHT, &qbuf, &rbuf)) { - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } - - /* Unmarshall response */ - - if (!lsa_io_r_enum_acct_with_right("", &r, &rbuf, 0)) { - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } - - *count = r.count; - - if (!NT_STATUS_IS_OK(result = r.status)) { - goto done; - } - - if (*count) { - int i; - (*sids) = (DOM_SID *)talloc(mem_ctx, sizeof(DOM_SID) * (*count)); - for (i=0; i<*count; i++) { - sid_copy(&(*sids)[i], &r.sids.sids[i].sid.sid); - } - } -done: - - return result; -} - - #if 0 /** An example of how to use the routines in this file. Fetch a DOMAIN diff --git a/source3/rpc_client/cli_netlogon.c b/source3/rpc_client/cli_netlogon.c index ce0dd95e94..831101ed81 100644 --- a/source3/rpc_client/cli_netlogon.c +++ b/source3/rpc_client/cli_netlogon.c @@ -280,7 +280,7 @@ NTSTATUS cli_nt_setup_creds(struct cli_state *cli, } if (!NT_STATUS_IS_OK(result)) - DEBUG(1,("cli_nt_setup_creds: auth%d challenge failed %s\n", level, nt_errstr(result))); + DEBUG(3,("cli_nt_setup_creds: auth%d challenge failed %s\n", level, nt_errstr(result))); return result; } @@ -472,6 +472,7 @@ NTSTATUS cli_netlogon_sam_deltas(struct cli_state *cli, TALLOC_CTX *mem_ctx, /* Logon domain user */ NTSTATUS cli_netlogon_sam_logon(struct cli_state *cli, TALLOC_CTX *mem_ctx, + DOM_CRED *ret_creds, const char *username, const char *password, int logon_type) { @@ -486,6 +487,7 @@ NTSTATUS cli_netlogon_sam_logon(struct cli_state *cli, TALLOC_CTX *mem_ctx, ZERO_STRUCT(q); ZERO_STRUCT(r); + ZERO_STRUCT(dummy_rtn_creds); /* Initialise parse structures */ @@ -498,8 +500,8 @@ NTSTATUS cli_netlogon_sam_logon(struct cli_state *cli, TALLOC_CTX *mem_ctx, q.validation_level = validation_level; - memset(&dummy_rtn_creds, '\0', sizeof(dummy_rtn_creds)); - dummy_rtn_creds.timestamp.time = time(NULL); + if (ret_creds == NULL) + ret_creds = &dummy_rtn_creds; ctr.switch_value = logon_type; @@ -542,7 +544,7 @@ NTSTATUS cli_netlogon_sam_logon(struct cli_state *cli, TALLOC_CTX *mem_ctx, } init_sam_info(&q.sam_id, cli->srv_name_slash, global_myname(), - &clnt_creds, &dummy_rtn_creds, logon_type, + &clnt_creds, ret_creds, logon_type, &ctr); /* Marshall data and send request */ @@ -563,6 +565,7 @@ NTSTATUS cli_netlogon_sam_logon(struct cli_state *cli, TALLOC_CTX *mem_ctx, /* Return results */ result = r.status; + memcpy(ret_creds, &r.srv_creds, sizeof(*ret_creds)); done: prs_mem_free(&qbuf); @@ -579,6 +582,7 @@ NTSTATUS cli_netlogon_sam_logon(struct cli_state *cli, TALLOC_CTX *mem_ctx, **/ NTSTATUS cli_netlogon_sam_network_logon(struct cli_state *cli, TALLOC_CTX *mem_ctx, + DOM_CRED *ret_creds, const char *username, const char *domain, const char *workstation, const uint8 chal[8], DATA_BLOB lm_response, DATA_BLOB nt_response, @@ -598,6 +602,7 @@ NTSTATUS cli_netlogon_sam_network_logon(struct cli_state *cli, TALLOC_CTX *mem_c ZERO_STRUCT(q); ZERO_STRUCT(r); + ZERO_STRUCT(dummy_rtn_creds); workstation_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", workstation); @@ -617,8 +622,8 @@ NTSTATUS cli_netlogon_sam_network_logon(struct cli_state *cli, TALLOC_CTX *mem_c q.validation_level = validation_level; - memset(&dummy_rtn_creds, '\0', sizeof(dummy_rtn_creds)); - dummy_rtn_creds.timestamp.time = time(NULL); + if (ret_creds == NULL) + ret_creds = &dummy_rtn_creds; ctr.switch_value = NET_LOGON_TYPE; @@ -629,7 +634,7 @@ NTSTATUS cli_netlogon_sam_network_logon(struct cli_state *cli, TALLOC_CTX *mem_c lm_response.data, lm_response.length, nt_response.data, nt_response.length); init_sam_info(&q.sam_id, cli->srv_name_slash, global_myname(), - &clnt_creds, &dummy_rtn_creds, NET_LOGON_TYPE, + &clnt_creds, ret_creds, NET_LOGON_TYPE, &ctr); /* Marshall data and send request */ @@ -659,6 +664,7 @@ NTSTATUS cli_netlogon_sam_network_logon(struct cli_state *cli, TALLOC_CTX *mem_c /* Return results */ result = r.status; + memcpy(ret_creds, &r.srv_creds, sizeof(*ret_creds)); done: prs_mem_free(&qbuf); diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index a5cb6d425e..d6307ddb46 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -28,6 +28,23 @@ extern struct pipe_id_info pipe_names[]; +static void get_auth_type_level(int pipe_auth_flags, int *auth_type, int *auth_level) +{ + *auth_type = 0; + *auth_level = 0; + if (pipe_auth_flags & AUTH_PIPE_SEAL) { + *auth_level = RPC_PIPE_AUTH_SEAL_LEVEL; + } else if (pipe_auth_flags & AUTH_PIPE_SIGN) { + *auth_level = RPC_PIPE_AUTH_SIGN_LEVEL; + } + + if (pipe_auth_flags & AUTH_PIPE_NETSEC) { + *auth_type = NETSEC_AUTH_TYPE; + } else if (pipe_auth_flags & AUTH_PIPE_NTLMSSP) { + *auth_type = NTLMSSP_AUTH_TYPE; + } +} + /******************************************************************** Rpc pipe call id. ********************************************************************/ @@ -132,32 +149,6 @@ static BOOL rpc_check_hdr(prs_struct *rdata, RPC_HDR *rhdr, return (rhdr->pkt_type != RPC_FAULT); } -static void NTLMSSPcalc_ap( struct cli_state *cli, unsigned char *data, uint32 len) -{ - unsigned char *hash = cli->ntlmssp_hash; - unsigned char index_i = hash[256]; - unsigned char index_j = hash[257]; - int ind; - - for( ind = 0; ind < len; ind++) { - unsigned char tc; - unsigned char t; - - index_i++; - index_j += hash[index_i]; - - tc = hash[index_i]; - hash[index_i] = hash[index_j]; - hash[index_j] = tc; - - t = hash[index_i] + hash[index_j]; - data[ind] = data[ind] ^ hash[t]; - } - - hash[256] = index_i; - hash[257] = index_j; -} - /**************************************************************************** Verify data on an rpc pipe. The VERIFY & SEAL code is only executed on packets that look like this : @@ -174,8 +165,11 @@ static void NTLMSSPcalc_ap( struct cli_state *cli, unsigned char *data, uint32 l Never on bind requests/responses. ****************************************************************************/ -static BOOL rpc_auth_pipe(struct cli_state *cli, prs_struct *rdata, int len, int auth_len) +static BOOL rpc_auth_pipe(struct cli_state *cli, prs_struct *rdata, + uint32 fragment_start, int len, int auth_len, uint8 pkt_type, + int *pauth_padding_len) { + /* * The following is that length of the data we must sign or seal. * This doesn't include the RPC headers or the auth_len or the RPC_HDR_AUTH_LEN @@ -187,155 +181,173 @@ static BOOL rpc_auth_pipe(struct cli_state *cli, prs_struct *rdata, int len, int /* * The start of the data to sign/seal is just after the RPC headers. */ - char *reply_data = prs_data_p(rdata) + RPC_HEADER_LEN + RPC_HDR_REQ_LEN; + char *reply_data = prs_data_p(rdata) + fragment_start + RPC_HEADER_LEN + RPC_HDR_REQ_LEN; - BOOL auth_verify = ((cli->ntlmssp_srv_flgs & NTLMSSP_NEGOTIATE_SIGN) != 0); - BOOL auth_seal = ((cli->ntlmssp_srv_flgs & NTLMSSP_NEGOTIATE_SEAL) != 0); - BOOL auth_schannel = (cli->saved_netlogon_pipe_fnum != 0); + RPC_HDR_AUTH rhdr_auth; - DEBUG(5,("rpc_auth_pipe: len: %d auth_len: %d verify %s seal %s schannel %s\n", - len, auth_len, BOOLSTR(auth_verify), BOOLSTR(auth_seal), BOOLSTR(auth_schannel))); + char *dp = prs_data_p(rdata) + fragment_start + len - + RPC_HDR_AUTH_LEN - auth_len; + prs_struct auth_verf; - /* - * Unseal any sealed data in the PDU, not including the - * 8 byte auth_header or the auth_data. - */ - - if (auth_seal) { - DEBUG(10,("rpc_auth_pipe: unseal\n")); - dump_data(100, reply_data, data_len); - NTLMSSPcalc_ap(cli, (uchar*)reply_data, data_len); - dump_data(100, reply_data, data_len); - } - - if (auth_verify || auth_seal) { - RPC_HDR_AUTH rhdr_auth; - prs_struct auth_req; - char data[RPC_HDR_AUTH_LEN]; - /* - * We set dp to be the end of the packet, minus the auth_len - * and the length of the header that preceeds the auth_data. - */ - char *dp = prs_data_p(rdata) + len - auth_len - RPC_HDR_AUTH_LEN; + *pauth_padding_len = 0; - if(dp - prs_data_p(rdata) > prs_data_size(rdata)) { - DEBUG(0,("rpc_auth_pipe: auth data > data size !\n")); - return False; + if (auth_len == 0) { + if (cli->pipe_auth_flags == 0) { + /* move along, nothing to see here */ + return True; } - memcpy(data, dp, sizeof(data)); - - prs_init(&auth_req , 0, cli->mem_ctx, UNMARSHALL); + DEBUG(2, ("No authenticaton header recienved on reply, but this pipe is authenticated\n")); + return False; + } - /* The endianness must be preserved... JRA. */ + DEBUG(5,("rpc_auth_pipe: pkt_type: %d len: %d auth_len: %d NTLMSSP %s schannel %s sign %s seal %s \n", + pkt_type, len, auth_len, + BOOLSTR(cli->pipe_auth_flags & AUTH_PIPE_NTLMSSP), + BOOLSTR(cli->pipe_auth_flags & AUTH_PIPE_NETSEC), + BOOLSTR(cli->pipe_auth_flags & AUTH_PIPE_SIGN), + BOOLSTR(cli->pipe_auth_flags & AUTH_PIPE_SEAL))); - prs_set_endian_data(&auth_req, rdata->bigendian_data); + if (dp - prs_data_p(rdata) > prs_data_size(rdata)) { + DEBUG(0,("rpc_auth_pipe: schannel auth data > data size !\n")); + return False; + } - prs_give_memory(&auth_req, data, RPC_HDR_AUTH_LEN, False); + DEBUG(10,("rpc_auth_pipe: packet:\n")); + dump_data(100, dp, auth_len); - /* - * Unmarshall the 8 byte auth_header that comes before the - * auth data. - */ + prs_init(&auth_verf, 0, cli->mem_ctx, UNMARSHALL); + + /* The endinness must be preserved. JRA. */ + prs_set_endian_data( &auth_verf, rdata->bigendian_data); + + /* Point this new parse struct at the auth section of the main + parse struct - rather than copying it. Avoids needing to + free it on every error + */ + prs_give_memory(&auth_verf, dp, RPC_HDR_AUTH_LEN + auth_len, False /* not dynamic */); + prs_set_offset(&auth_verf, 0); - if(!smb_io_rpc_hdr_auth("hdr_auth", &rhdr_auth, &auth_req, 0)) { - DEBUG(0,("rpc_auth_pipe: unmarshalling RPC_HDR_AUTH failed.\n")); + { + int auth_type; + int auth_level; + if (!smb_io_rpc_hdr_auth("auth_hdr", &rhdr_auth, &auth_verf, 0)) { + DEBUG(0, ("rpc_auth_pipe: Could not parse auth header\n")); return False; } - if (!rpc_hdr_auth_chk(&rhdr_auth)) { - DEBUG(0,("rpc_auth_pipe: rpc_hdr_auth_chk failed.\n")); + /* Let the caller know how much padding at the end of the data */ + *pauth_padding_len = rhdr_auth.padding; + + /* Check it's the type of reply we were expecting to decode */ + + get_auth_type_level(cli->pipe_auth_flags, &auth_type, &auth_level); + if (rhdr_auth.auth_type != auth_type) { + DEBUG(0, ("BAD auth type %d (should be %d)\n", + rhdr_auth.auth_type, auth_type)); return False; } - } - - /* - * Now unseal and check the auth verifier in the auth_data at - * then end of the packet. The 4 bytes skipped in the unseal - * seem to be a buffer pointer preceeding the sealed data. - */ - - if (auth_verify) { - RPC_AUTH_NTLMSSP_CHK chk; - uint32 crc32; - prs_struct auth_verf; - char data[RPC_AUTH_NTLMSSP_CHK_LEN]; - char *dp = prs_data_p(rdata) + len - auth_len; - - if(dp - prs_data_p(rdata) > prs_data_size(rdata)) { - DEBUG(0,("rpc_auth_pipe: auth data > data size !\n")); + + if (rhdr_auth.auth_level != auth_level) { + DEBUG(0, ("BAD auth level %d (should be %d)\n", + rhdr_auth.auth_level, auth_level)); return False; } + } - DEBUG(10,("rpc_auth_pipe: verify\n")); - dump_data(100, dp, auth_len); - NTLMSSPcalc_ap(cli, (uchar*)(dp+4), auth_len - 4); + if (pkt_type == RPC_BINDACK) { + if (cli->pipe_auth_flags & AUTH_PIPE_NTLMSSP) { + /* copy the next auth_len bytes into a buffer for + later use */ - memcpy(data, dp, RPC_AUTH_NTLMSSP_CHK_LEN); - dump_data(100, data, auth_len); + DATA_BLOB ntlmssp_verf = data_blob(NULL, auth_len); + + /* save the reply away, for use a little later */ + prs_copy_data_out(ntlmssp_verf.data, &auth_verf, auth_len); - prs_init(&auth_verf, 0, cli->mem_ctx, UNMARSHALL); - /* The endinness must be preserved. JRA. */ - prs_set_endian_data( &auth_verf, rdata->bigendian_data); + return (NT_STATUS_IS_OK(ntlmssp_client_store_response(cli->ntlmssp_pipe_state, + ntlmssp_verf))); + } + else if (cli->pipe_auth_flags & AUTH_PIPE_NETSEC) { + /* nothing to do here - we don't seem to be able to + validate the bindack based on VL's comments */ + return True; + } + } + + if (cli->pipe_auth_flags & AUTH_PIPE_NTLMSSP) { + NTSTATUS nt_status; + DATA_BLOB sig; + if ((cli->pipe_auth_flags & AUTH_PIPE_SIGN) || + (cli->pipe_auth_flags & AUTH_PIPE_SEAL)) { + if (auth_len != RPC_AUTH_NTLMSSP_CHK_LEN) { + DEBUG(0,("rpc_auth_pipe: wrong ntlmssp auth len %d\n", auth_len)); + return False; + } + sig = data_blob(NULL, auth_len); + prs_copy_data_out(sig.data, &auth_verf, auth_len); + } + + /* + * Unseal any sealed data in the PDU, not including the + * 8 byte auth_header or the auth_data. + */ - prs_give_memory(&auth_verf, data, RPC_AUTH_NTLMSSP_CHK_LEN, False); + /* + * Now unseal and check the auth verifier in the auth_data at + * the end of the packet. + */ - if(!smb_io_rpc_auth_ntlmssp_chk("auth_sign", &chk, &auth_verf, 0)) { - DEBUG(0,("rpc_auth_pipe: unmarshalling RPC_AUTH_NTLMSSP_CHK failed.\n")); - return False; + if (cli->pipe_auth_flags & AUTH_PIPE_SEAL) { + if (data_len < 0) { + DEBUG(1, ("Can't unseal - data_len < 0!!\n")); + return False; + } + nt_status = ntlmssp_client_unseal_packet(cli->ntlmssp_pipe_state, + reply_data, data_len, + &sig); + } + else if (cli->pipe_auth_flags & AUTH_PIPE_SIGN) { + nt_status = ntlmssp_client_check_packet(cli->ntlmssp_pipe_state, + reply_data, data_len, + &sig); } - crc32 = crc32_calc_buffer(reply_data, data_len); + data_blob_free(&sig); - if (!rpc_auth_ntlmssp_chk(&chk, crc32 , cli->ntlmssp_seq_num)) { - DEBUG(0,("rpc_auth_pipe: rpc_auth_ntlmssp_chk failed.\n")); + if (!NT_STATUS_IS_OK(nt_status)) { + DEBUG(0, ("rpc_auth_pipe: could not validate " + "incoming NTLMSSP packet!\n")); return False; } - cli->ntlmssp_seq_num++; } - if (auth_schannel) { + if (cli->pipe_auth_flags & AUTH_PIPE_NETSEC) { RPC_AUTH_NETSEC_CHK chk; - char data[RPC_AUTH_NETSEC_CHK_LEN]; - char *dp = prs_data_p(rdata) + len - auth_len; - prs_struct auth_verf; if (auth_len != RPC_AUTH_NETSEC_CHK_LEN) { DEBUG(0,("rpc_auth_pipe: wrong schannel auth len %d\n", auth_len)); return False; } - if (dp - prs_data_p(rdata) > prs_data_size(rdata)) { - DEBUG(0,("rpc_auth_pipe: schannel auth data > data size !\n")); - return False; - } - - DEBUG(10,("rpc_auth_pipe: schannel verify netsec\n")); - dump_data(100, dp, auth_len); - - memcpy(data, dp, sizeof(data)); - dump_data(100, data, sizeof(data)); - - prs_init(&auth_verf, 0, cli->mem_ctx, UNMARSHALL); - - /* The endinness must be preserved. JRA. */ - prs_set_endian_data( &auth_verf, rdata->bigendian_data); - - prs_give_memory(&auth_verf, data, RPC_AUTH_NETSEC_CHK_LEN, False); - - if (!smb_io_rpc_auth_netsec_chk("schannel_auth_sign", &chk, &auth_verf, 0)) { + if (!smb_io_rpc_auth_netsec_chk("schannel_auth_sign", + &chk, &auth_verf, 0)) { DEBUG(0, ("rpc_auth_pipe: schannel unmarshalling " "RPC_AUTH_NETSECK_CHK failed\n")); return False; } - cli->auth_info.seq_num++; - - if (!netsec_decode(&cli->auth_info, &chk, reply_data, data_len)) { + if (!netsec_decode(&cli->auth_info, + cli->pipe_auth_flags, + SENDER_IS_ACCEPTOR, + &chk, reply_data, data_len)) { DEBUG(0, ("rpc_auth_pipe: Could not decode schannel\n")); return False; } + + cli->auth_info.seq_num++; + } return True; } @@ -365,7 +377,8 @@ static BOOL rpc_auth_pipe(struct cli_state *cli, prs_struct *rdata, int len, int ****************************************************************************/ -static BOOL rpc_api_pipe(struct cli_state *cli, prs_struct *data, prs_struct *rdata) +static BOOL rpc_api_pipe(struct cli_state *cli, prs_struct *data, prs_struct *rdata, + uint8 expected_pkt_type) { uint32 len; char *rparam = NULL; @@ -379,7 +392,9 @@ static BOOL rpc_api_pipe(struct cli_state *cli, prs_struct *data, prs_struct *rd char *prdata = NULL; uint32 rdata_len = 0; uint32 current_offset = 0; + uint32 fragment_start = 0; uint32 max_data = cli->max_xmit_frag ? cli->max_xmit_frag : 1024; + int auth_padding_len = 0; /* Create setup parameters - must be in native byte order. */ @@ -437,6 +452,12 @@ static BOOL rpc_api_pipe(struct cli_state *cli, prs_struct *data, prs_struct *rd } } + if (rhdr.pkt_type == RPC_BINDNACK) { + DEBUG(3, ("Bind NACK received on pipe %x!\n", (int)cli->nt_pipe_fnum)); + prs_mem_free(rdata); + return False; + } + if (rhdr.pkt_type == RPC_RESPONSE) { RPC_HDR_RESP rhdr_resp; if(!smb_io_rpc_hdr_resp("rpc_hdr_resp", &rhdr_resp, rdata, 0)) { @@ -446,6 +467,12 @@ static BOOL rpc_api_pipe(struct cli_state *cli, prs_struct *data, prs_struct *rd } } + if (rhdr.pkt_type != expected_pkt_type) { + DEBUG(3, ("Connection to pipe %x got an unexpected RPC packet type - %d, not %d\n", (int)cli->nt_pipe_fnum, rhdr.pkt_type, expected_pkt_type)); + prs_mem_free(rdata); + return False; + } + DEBUG(5,("rpc_api_pipe: len left: %u smbtrans read: %u\n", (unsigned int)len, (unsigned int)rdata_len )); @@ -468,16 +495,20 @@ static BOOL rpc_api_pipe(struct cli_state *cli, prs_struct *data, prs_struct *rd * Now we have a complete PDU, check the auth struct if any was sent. */ + if(!rpc_auth_pipe(cli, rdata, fragment_start, rhdr.frag_len, + rhdr.auth_len, rhdr.pkt_type, &auth_padding_len)) { + prs_mem_free(rdata); + return False; + } + if (rhdr.auth_len != 0) { - if(!rpc_auth_pipe(cli, rdata, rhdr.frag_len, rhdr.auth_len)) - return False; /* * Drop the auth footers from the current offset. * We need this if there are more fragments. * The auth footers consist of the auth_data and the * preceeding 8 byte auth_header. */ - current_offset -= (rhdr.auth_len + RPC_HDR_AUTH_LEN); + current_offset -= (auth_padding_len + RPC_HDR_AUTH_LEN + rhdr.auth_len); } /* @@ -501,7 +532,7 @@ static BOOL rpc_api_pipe(struct cli_state *cli, prs_struct *data, prs_struct *rd prs_struct hps; uint8 eclass; uint32 ecode; - + /* * First read the header of the next PDU. */ @@ -554,23 +585,33 @@ static BOOL rpc_api_pipe(struct cli_state *cli, prs_struct *data, prs_struct *rd * Now read the rest of the PDU. */ - if (!rpc_read(cli, rdata, len, ¤t_offset)) + if (!rpc_read(cli, rdata, len, ¤t_offset)) { + prs_mem_free(rdata); return False; + } + + fragment_start = current_offset - len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN; /* * Verify any authentication footer. */ + + if(!rpc_auth_pipe(cli, rdata, fragment_start, rhdr.frag_len, + rhdr.auth_len, rhdr.pkt_type, &auth_padding_len)) { + prs_mem_free(rdata); + return False; + } + if (rhdr.auth_len != 0 ) { - if(!rpc_auth_pipe(cli, rdata, rhdr.frag_len, rhdr.auth_len)) - return False; + /* * Drop the auth footers from the current offset. * The auth footers consist of the auth_data and the * preceeding 8 byte auth_header. * We need this if there are more fragments. */ - current_offset -= (rhdr.auth_len + RPC_HDR_AUTH_LEN); + current_offset -= (auth_padding_len + RPC_HDR_AUTH_LEN + rhdr.auth_len); } } @@ -586,97 +627,94 @@ static BOOL rpc_api_pipe(struct cli_state *cli, prs_struct *data, prs_struct *rd ********************************************************************/ -static BOOL create_rpc_bind_req(prs_struct *rpc_out, BOOL do_auth, BOOL do_netsec, uint32 rpc_call_id, - RPC_IFACE *abstract, RPC_IFACE *transfer, - const char *my_name, const char *domain, uint32 neg_flags) +static NTSTATUS create_rpc_bind_req(struct cli_state *cli, prs_struct *rpc_out, + uint32 rpc_call_id, + RPC_IFACE *abstract, RPC_IFACE *transfer, + const char *my_name, const char *domain) { RPC_HDR hdr; RPC_HDR_RB hdr_rb; - char buffer[4096]; - prs_struct auth_info; + RPC_HDR_AUTH hdr_auth; int auth_len = 0; + int auth_type, auth_level; + size_t saved_hdr_offset; - prs_init(&auth_info, 0, prs_get_mem_context(rpc_out), MARSHALL); - - if (do_auth) { - RPC_HDR_AUTH hdr_auth; - RPC_AUTH_VERIFIER auth_verifier; - RPC_AUTH_NTLMSSP_NEG ntlmssp_neg; + prs_struct auth_info; + prs_init(&auth_info, RPC_HDR_AUTH_LEN, /* we will need at least this much */ + prs_get_mem_context(rpc_out), MARSHALL); + if (cli->pipe_auth_flags) { + get_auth_type_level(cli->pipe_auth_flags, &auth_type, &auth_level); + /* * Create the auth structs we will marshall. */ - - init_rpc_hdr_auth(&hdr_auth, NTLMSSP_AUTH_TYPE, NTLMSSP_AUTH_LEVEL, 0x00, 1); - init_rpc_auth_verifier(&auth_verifier, "NTLMSSP", NTLMSSP_NEGOTIATE); - init_rpc_auth_ntlmssp_neg(&ntlmssp_neg, neg_flags, my_name, domain); - - /* - * Use the 4k buffer to store the auth info. - */ - - prs_give_memory( &auth_info, buffer, sizeof(buffer), False); - + + init_rpc_hdr_auth(&hdr_auth, auth_type, auth_level, 0x00, 1); + /* * Now marshall the data into the temporary parse_struct. */ - + if(!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, &auth_info, 0)) { DEBUG(0,("create_rpc_bind_req: failed to marshall RPC_HDR_AUTH.\n")); - return False; + prs_mem_free(&auth_info); + return NT_STATUS_NO_MEMORY; } + saved_hdr_offset = prs_offset(&auth_info); + } + + if (cli->pipe_auth_flags & AUTH_PIPE_NTLMSSP) { - if(!smb_io_rpc_auth_verifier("auth_verifier", &auth_verifier, &auth_info, 0)) { - DEBUG(0,("create_rpc_bind_req: failed to marshall RPC_AUTH_VERIFIER.\n")); - return False; - } + NTSTATUS nt_status; + DATA_BLOB null_blob = data_blob(NULL, 0); + DATA_BLOB request; - if(!smb_io_rpc_auth_ntlmssp_neg("ntlmssp_neg", &ntlmssp_neg, &auth_info, 0)) { - DEBUG(0,("create_rpc_bind_req: failed to marshall RPC_AUTH_NTLMSSP_NEG.\n")); - return False; + DEBUG(5, ("Processing NTLMSSP Negotiate\n")); + nt_status = ntlmssp_client_update(cli->ntlmssp_pipe_state, + null_blob, + &request); + + if (!NT_STATUS_EQUAL(nt_status, + NT_STATUS_MORE_PROCESSING_REQUIRED)) { + prs_mem_free(&auth_info); + return nt_status; } /* Auth len in the rpc header doesn't include auth_header. */ - auth_len = prs_offset(&auth_info) - RPC_HDR_AUTH_LEN; - } + auth_len = request.length; + prs_copy_data_in(&auth_info, request.data, request.length); - if (do_netsec) { - RPC_HDR_AUTH hdr_auth; - RPC_AUTH_NETSEC_NEG netsec_neg; + DEBUG(5, ("NTLMSSP Negotiate:\n")); + dump_data(5, request.data, request.length); - /* - * Create the auth structs we will marshall. - */ + data_blob_free(&request); - init_rpc_hdr_auth(&hdr_auth, NETSEC_AUTH_TYPE, NETSEC_AUTH_LEVEL, - 0x00, 1); - init_rpc_auth_netsec_neg(&netsec_neg, domain, my_name); + } + else if (cli->pipe_auth_flags & AUTH_PIPE_NETSEC) { + RPC_AUTH_NETSEC_NEG netsec_neg; - /* - * Use the 4k buffer to store the auth info. - */ + /* Use lp_workgroup() if domain not specified */ - prs_give_memory( &auth_info, buffer, sizeof(buffer), False); + if (!domain || !domain[0]) + domain = lp_workgroup(); + + init_rpc_auth_netsec_neg(&netsec_neg, domain, my_name); /* * Now marshall the data into the temporary parse_struct. */ - if(!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, &auth_info, 0)) { - DEBUG(0,("Failed to marshall RPC_HDR_AUTH.\n")); - return False; - } - if(!smb_io_rpc_auth_netsec_neg("netsec_neg", &netsec_neg, &auth_info, 0)) { DEBUG(0,("Failed to marshall RPC_AUTH_NETSEC_NEG.\n")); - return False; + prs_mem_free(&auth_info); + return NT_STATUS_NO_MEMORY; } /* Auth len in the rpc header doesn't include auth_header. */ - auth_len = prs_offset(&auth_info) - RPC_HDR_AUTH_LEN; + auth_len = prs_offset(&auth_info) - saved_hdr_offset; } - /* create the request RPC_HDR */ init_rpc_hdr(&hdr, RPC_BIND, 0x3, rpc_call_id, RPC_HEADER_LEN + RPC_HDR_RB_LEN + prs_offset(&auth_info), @@ -684,7 +722,8 @@ static BOOL create_rpc_bind_req(prs_struct *rpc_out, BOOL do_auth, BOOL do_netse if(!smb_io_rpc_hdr("hdr" , &hdr, rpc_out, 0)) { DEBUG(0,("create_rpc_bind_req: failed to marshall RPC_HDR.\n")); - return False; + prs_mem_free(&auth_info); + return NT_STATUS_NO_MEMORY; } /* create the bind request RPC_HDR_RB */ @@ -694,21 +733,22 @@ static BOOL create_rpc_bind_req(prs_struct *rpc_out, BOOL do_auth, BOOL do_netse /* Marshall the bind request data */ if(!smb_io_rpc_hdr_rb("", &hdr_rb, rpc_out, 0)) { DEBUG(0,("create_rpc_bind_req: failed to marshall RPC_HDR_RB.\n")); - return False; + prs_mem_free(&auth_info); + return NT_STATUS_NO_MEMORY; } /* * Grow the outgoing buffer to store any auth info. */ - if(hdr.auth_len != 0) { + if(auth_len != 0) { if(!prs_append_prs_data( rpc_out, &auth_info)) { DEBUG(0,("create_rpc_bind_req: failed to grow parse struct to add auth.\n")); - return False; + prs_mem_free(&auth_info); + return NT_STATUS_NO_MEMORY; } } - - return True; + return NT_STATUS_OK; } /******************************************************************* @@ -718,90 +758,71 @@ static BOOL create_rpc_bind_req(prs_struct *rpc_out, BOOL do_auth, BOOL do_netse the authentication handshake. ********************************************************************/ -static BOOL create_rpc_bind_resp(struct pwd_info *pwd, - const char *domain, const char *user_name, const char *my_name, - uint32 ntlmssp_cli_flgs, - uint32 rpc_call_id, - prs_struct *rpc_out) +static NTSTATUS create_rpc_bind_resp(struct cli_state *cli, + uint32 rpc_call_id, + prs_struct *rpc_out) { - unsigned char lm_owf[24]; - unsigned char nt_owf[24]; + NTSTATUS nt_status; RPC_HDR hdr; RPC_HDR_AUTHA hdr_autha; - RPC_AUTH_VERIFIER auth_verifier; - RPC_AUTH_NTLMSSP_RESP ntlmssp_resp; - char buffer[4096]; - prs_struct auth_info; - - /* - * Marshall the variable length data into a temporary parse - * struct, pointing into a 4k local buffer. - */ - prs_init(&auth_info, 0, prs_get_mem_context(rpc_out), MARSHALL); - - /* - * Use the 4k buffer to store the auth info. - */ - - prs_give_memory( &auth_info, buffer, sizeof(buffer), False); - - /* - * Create the variable length auth_data. - */ - - init_rpc_auth_verifier(&auth_verifier, "NTLMSSP", NTLMSSP_AUTH); - - pwd_get_lm_nt_owf(pwd, lm_owf, nt_owf); - - init_rpc_auth_ntlmssp_resp(&ntlmssp_resp, - lm_owf, nt_owf, - domain, user_name, my_name, - ntlmssp_cli_flgs); - - /* - * Marshall the variable length auth_data into a temp parse_struct. - */ - - if(!smb_io_rpc_auth_verifier("auth_verifier", &auth_verifier, &auth_info, 0)) { - DEBUG(0,("create_rpc_bind_resp: failed to marshall RPC_AUTH_VERIFIER.\n")); - return False; - } - - if(!smb_io_rpc_auth_ntlmssp_resp("ntlmssp_resp", &ntlmssp_resp, &auth_info, 0)) { - DEBUG(0,("create_rpc_bind_resp: failed to marshall RPC_AUTH_NTLMSSP_RESP.\n")); - return False; + DATA_BLOB ntlmssp_null_response = data_blob(NULL, 0); + DATA_BLOB ntlmssp_reply; + int auth_type, auth_level; + + /* The response is picked up from the internal cache, + where it was placed by the rpc_auth_pipe() code */ + nt_status = ntlmssp_client_update(cli->ntlmssp_pipe_state, + ntlmssp_null_response, + &ntlmssp_reply); + + if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { + return nt_status; } /* Create the request RPC_HDR */ init_rpc_hdr(&hdr, RPC_BINDRESP, 0x0, rpc_call_id, - RPC_HEADER_LEN + RPC_HDR_AUTHA_LEN + prs_offset(&auth_info), - prs_offset(&auth_info) ); - + RPC_HEADER_LEN + RPC_HDR_AUTHA_LEN + ntlmssp_reply.length, + ntlmssp_reply.length ); + /* Marshall it. */ if(!smb_io_rpc_hdr("hdr", &hdr, rpc_out, 0)) { DEBUG(0,("create_rpc_bind_resp: failed to marshall RPC_HDR.\n")); - return False; + data_blob_free(&ntlmssp_reply); + return NT_STATUS_NO_MEMORY; } + get_auth_type_level(cli->pipe_auth_flags, &auth_type, &auth_level); + /* Create the request RPC_HDR_AUTHA */ init_rpc_hdr_autha(&hdr_autha, MAX_PDU_FRAG_LEN, MAX_PDU_FRAG_LEN, - NTLMSSP_AUTH_TYPE, NTLMSSP_AUTH_LEVEL, 0x00); + auth_type, auth_level, 0x00); if(!smb_io_rpc_hdr_autha("hdr_autha", &hdr_autha, rpc_out, 0)) { DEBUG(0,("create_rpc_bind_resp: failed to marshall RPC_HDR_AUTHA.\n")); - return False; + data_blob_free(&ntlmssp_reply); + return NT_STATUS_NO_MEMORY; } /* * Append the auth data to the outgoing buffer. */ - if(!prs_append_prs_data(rpc_out, &auth_info)) { + if(!prs_copy_data_in(rpc_out, ntlmssp_reply.data, ntlmssp_reply.length)) { DEBUG(0,("create_rpc_bind_req: failed to grow parse struct to add auth.\n")); - return False; + data_blob_free(&ntlmssp_reply); + return NT_STATUS_NO_MEMORY; } - return True; + if (cli->pipe_auth_flags & AUTH_PIPE_SIGN) { + nt_status = ntlmssp_client_sign_init(cli->ntlmssp_pipe_state); + + if (!NT_STATUS_IS_OK(nt_status)) { + return nt_status; + } + } + + data_blob_free(&ntlmssp_reply); + return NT_STATUS_OK; } @@ -852,34 +873,17 @@ static uint32 create_rpc_request(prs_struct *rpc_out, uint8 op_num, int data_len } /******************************************************************* - Puts an NTLMSSP auth header into an rpc request. - ********************************************************************/ - -static BOOL create_ntlmssp_auth_hdr(prs_struct *outgoing_packet, BOOL auth_verify) -{ - RPC_HDR_AUTH hdr_auth; - - init_rpc_hdr_auth(&hdr_auth, NTLMSSP_AUTH_TYPE, - NTLMSSP_AUTH_LEVEL, 0x08, - (auth_verify ? 1 : 0)); - if(!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, - outgoing_packet, 0)) { - DEBUG(0,("create_auth_hdr:Failed to marshal RPC_HDR_AUTH.\n")); - return False; - } - return True; -} - -/******************************************************************* - Puts a NETLOGON schannel auth header into an rpc request. + Puts an auth header into an rpc request. ********************************************************************/ -static BOOL create_netsec_auth_hdr(prs_struct *outgoing_packet, int padding) +static BOOL create_auth_hdr(prs_struct *outgoing_packet, + int auth_type, + int auth_level, int padding) { RPC_HDR_AUTH hdr_auth; - init_rpc_hdr_auth(&hdr_auth, NETSEC_AUTH_TYPE, - NETSEC_AUTH_LEVEL, padding, 1); + init_rpc_hdr_auth(&hdr_auth, auth_type, auth_level, + padding, 1); if(!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, outgoing_packet, 0)) { DEBUG(0,("create_auth_hdr:Failed to marshal RPC_HDR_AUTH.\n")); @@ -888,30 +892,6 @@ static BOOL create_netsec_auth_hdr(prs_struct *outgoing_packet, int padding) return True; } -/******************************************************************* - Puts auth data into an rpc request. - ********************************************************************/ - -static BOOL create_auth_data(struct cli_state *cli, uint32 crc32, - prs_struct *outgoing_packet) -{ - char *pdata_out = prs_data_p(outgoing_packet); - RPC_AUTH_NTLMSSP_CHK chk; - uint32 current_offset = prs_offset(outgoing_packet); - - init_rpc_auth_ntlmssp_chk(&chk, NTLMSSP_SIGN_VERSION, - crc32, cli->ntlmssp_seq_num++); - if(!smb_io_rpc_auth_ntlmssp_chk("auth_sign", &chk, - outgoing_packet, 0)) { - DEBUG(0,("create_auth_data: Failed to marshal RPC_AUTH_NTLMSSP_CHK.\n")); - return False; - } - NTLMSSPcalc_ap(cli, (unsigned char*) - &pdata_out[current_offset+4], - RPC_AUTH_NTLMSSP_CHK_LEN - 4); - return True; -} - /** * Send a request on an RPC pipe and get a response. * @@ -922,43 +902,60 @@ static BOOL create_auth_data(struct cli_state *cli, uint32 crc32, BOOL rpc_api_pipe_req(struct cli_state *cli, uint8 op_num, prs_struct *data, prs_struct *rdata) { - uint32 auth_len, max_data, data_left, data_sent; + uint32 auth_len, real_auth_len, auth_hdr_len, max_data, data_left, data_sent; + NTSTATUS nt_status; BOOL ret = False; - BOOL auth_verify, auth_seal, auth_schannel; uint32 callid = 0; fstring dump_name; - auth_verify = ((cli->ntlmssp_srv_flgs & NTLMSSP_NEGOTIATE_SIGN) != 0); - auth_seal = ((cli->ntlmssp_srv_flgs & NTLMSSP_NEGOTIATE_SEAL) != 0); - auth_schannel = (cli->saved_netlogon_pipe_fnum != 0); - auth_len = 0; + real_auth_len = 0; + auth_hdr_len = 0; - if (auth_verify) - auth_len = RPC_AUTH_NTLMSSP_CHK_LEN; - - if (auth_schannel) - auth_len = RPC_AUTH_NETSEC_CHK_LEN; + if (cli->pipe_auth_flags & AUTH_PIPE_SIGN) { + if (cli->pipe_auth_flags & AUTH_PIPE_NTLMSSP) { + auth_len = RPC_AUTH_NTLMSSP_CHK_LEN; + } + if (cli->pipe_auth_flags & AUTH_PIPE_NETSEC) { + auth_len = RPC_AUTH_NETSEC_CHK_LEN; + } + auth_hdr_len = RPC_HDR_AUTH_LEN; + } /* * calc how much actual data we can send in a PDU fragment */ max_data = cli->max_xmit_frag - RPC_HEADER_LEN - RPC_HDR_REQ_LEN - - (auth_verify ? RPC_HDR_AUTH_LEN : 0) - auth_len - 8; - + auth_hdr_len - auth_len - 8; + for (data_left = prs_offset(data), data_sent = 0; data_left > 0;) { prs_struct outgoing_packet; + prs_struct sec_blob; uint32 data_len, send_size; uint8 flags = 0; - uint32 crc32 = 0; uint32 auth_padding = 0; RPC_AUTH_NETSEC_CHK verf; + DATA_BLOB sign_blob; /* * how much will we send this time */ send_size = MIN(data_left, max_data); + if (!prs_init(&sec_blob, send_size, /* will need at least this much */ + cli->mem_ctx, MARSHALL)) { + DEBUG(0,("Could not malloc %u bytes", + send_size+auth_padding)); + return False; + } + + if(!prs_append_some_prs_data(&sec_blob, data, + data_sent, send_size)) { + DEBUG(0,("Failed to append data to netsec blob\n")); + prs_mem_free(&sec_blob); + return False; + } + /* * NT expects the data that is sealed to be 8-byte * aligned. The padding must be encrypted as well and @@ -967,12 +964,95 @@ BOOL rpc_api_pipe_req(struct cli_state *cli, uint8 op_num, * be stored in the auth header. */ - if (auth_schannel) - auth_padding = 8 - (send_size & 7); + if (cli->pipe_auth_flags) { + size_t data_and_padding_size; + int auth_type; + int auth_level; + prs_align_uint64(&sec_blob); - data_len = RPC_HEADER_LEN + RPC_HDR_REQ_LEN + send_size + - ((auth_verify|auth_schannel) ? RPC_HDR_AUTH_LEN : 0) + - auth_len + auth_padding; + get_auth_type_level(cli->pipe_auth_flags, &auth_type, &auth_level); + + data_and_padding_size = prs_offset(&sec_blob); + auth_padding = data_and_padding_size - send_size; + + /* insert the auth header */ + + if(!create_auth_hdr(&sec_blob, auth_type, auth_level, auth_padding)) { + prs_mem_free(&sec_blob); + return False; + } + + /* create an NTLMSSP signature */ + if (cli->pipe_auth_flags & AUTH_PIPE_NTLMSSP) { + /* + * Seal the outgoing data if requested. + */ + if (cli->pipe_auth_flags & AUTH_PIPE_SEAL) { + + nt_status = ntlmssp_client_seal_packet(cli->ntlmssp_pipe_state, + (unsigned char*)prs_data_p(&sec_blob), + data_and_padding_size, + &sign_blob); + if (!NT_STATUS_IS_OK(nt_status)) { + prs_mem_free(&sec_blob); + return False; + } + } + else if (cli->pipe_auth_flags & AUTH_PIPE_SIGN) { + + nt_status = ntlmssp_client_sign_packet(cli->ntlmssp_pipe_state, + (unsigned char*)prs_data_p(&sec_blob), + data_and_padding_size, &sign_blob); + if (!NT_STATUS_IS_OK(nt_status)) { + prs_mem_free(&sec_blob); + return False; + } + } + + + /* write auth footer onto the packet */ + real_auth_len = sign_blob.length; + + prs_copy_data_in(&sec_blob, sign_blob.data, sign_blob.length); + data_blob_free(&sign_blob); + + } + else if (cli->pipe_auth_flags & AUTH_PIPE_NETSEC) { + static const uchar netsec_sig[8] = NETSEC_SIGNATURE; + static const uchar nullbytes[8] = { 0,0,0,0,0,0,0,0 }; + size_t parse_offset_marker; + if ((cli->auth_info.seq_num & 1) != 0) { + DEBUG(0,("SCHANNEL ERROR: seq_num must be even in client (seq_num=%d)\n", + cli->auth_info.seq_num)); + } + + DEBUG(10,("SCHANNEL seq_num=%d\n", cli->auth_info.seq_num)); + + init_rpc_auth_netsec_chk(&verf, netsec_sig, nullbytes, + nullbytes, nullbytes); + + netsec_encode(&cli->auth_info, + cli->pipe_auth_flags, + SENDER_IS_INITIATOR, + &verf, + prs_data_p(&sec_blob), + data_and_padding_size); + + cli->auth_info.seq_num++; + + /* write auth footer onto the packet */ + + parse_offset_marker = prs_offset(&sec_blob); + if (!smb_io_rpc_auth_netsec_chk("", &verf, + &sec_blob, 0)) { + prs_mem_free(&sec_blob); + return False; + } + real_auth_len = prs_offset(&sec_blob) - parse_offset_marker; + } + } + + data_len = RPC_HEADER_LEN + RPC_HDR_REQ_LEN + prs_offset(&sec_blob); /* * Malloc parse struct to hold it (and enough for alignments). @@ -992,128 +1072,23 @@ BOOL rpc_api_pipe_req(struct cli_state *cli, uint8 op_num, * Write out the RPC header and the request header. */ if(!(callid = create_rpc_request(&outgoing_packet, op_num, - data_len, auth_len, flags, + data_len, real_auth_len, flags, callid, data_left))) { DEBUG(0,("rpc_api_pipe_req: Failed to create RPC request.\n")); prs_mem_free(&outgoing_packet); + prs_mem_free(&sec_blob); return False; } - /* - * Seal the outgoing data if requested. - */ - if (auth_seal) { - crc32 = crc32_calc_buffer(prs_data_p(data) + data_sent, - send_size); - NTLMSSPcalc_ap(cli, (unsigned char*)prs_data_p(data) + - data_sent, send_size); - } - - /* - * Now copy the data into the outgoing packet. - */ - - if (auth_schannel) { - static const uchar netsec_sig[8] = NETSEC_SIGNATURE; - static const uchar nullbytes[8] = { 0,0,0,0,0,0,0,0 }; - uchar sign[8]; - prs_struct netsec_blob; - - if ((cli->auth_info.seq_num & 1) != 0) { - DEBUG(0,("SCHANNEL ERROR: seq_num must be even in client (seq_num=%d)\n", - cli->auth_info.seq_num)); - } - - DEBUG(10,("SCHANNEL seq_num=%d\n", cli->auth_info.seq_num)); - - RSIVAL(sign, 0, cli->auth_info.seq_num); - SIVAL(sign, 4, 0x80); - - if (!prs_init(&netsec_blob, send_size+auth_padding, - cli->mem_ctx, MARSHALL)) { - DEBUG(0,("Could not malloc %u bytes", - send_size+auth_padding)); - prs_mem_free(&outgoing_packet); - return False; - } - - if(!prs_append_some_prs_data(&netsec_blob, data, - data_sent, send_size)) { - DEBUG(0,("Failed to append data to netsec blob\n")); - prs_mem_free(&outgoing_packet); - return False; - } - - netsec_blob.align = 8; - - if (!prs_align(&netsec_blob)) { - DEBUG(0,("Could not align netsec blob\n")); - prs_mem_free(&outgoing_packet); - return False; - } - - init_rpc_auth_netsec_chk(&verf, netsec_sig, nullbytes, - sign, nullbytes); - - netsec_encode(&cli->auth_info, &verf, - prs_data_p(&netsec_blob), - prs_data_size(&netsec_blob)); - - prs_append_prs_data(&outgoing_packet, &netsec_blob); - prs_mem_free(&netsec_blob); - - cli->auth_info.seq_num++; - - } else { - if(!prs_append_some_prs_data(&outgoing_packet, data, - data_sent, send_size)) { - DEBUG(0,("rpc_api_pipe_req: Failed to append " - "data to outgoing packet.\n")); - prs_mem_free(&outgoing_packet); - return False; - } - } - - /* - * Add a trailing auth_verifier if needed. - */ - if (auth_seal || auth_verify) { - if(!create_ntlmssp_auth_hdr(&outgoing_packet, auth_verify)) { - prs_mem_free(&outgoing_packet); - return False; - } - } - - /* - * Finally the auth data itself. - */ - if (auth_verify) { - if (!create_auth_data(cli, crc32, &outgoing_packet)) { - prs_mem_free(&outgoing_packet); - return False; - } - } - - if (auth_schannel) { - - if (!create_netsec_auth_hdr(&outgoing_packet, - auth_padding)) { - prs_mem_free(&outgoing_packet); - return False; - } - - if (!smb_io_rpc_auth_netsec_chk("", &verf, - &outgoing_packet, 0)) { - prs_mem_free(&outgoing_packet); - return False; - } - } + prs_append_prs_data(&outgoing_packet, &sec_blob); + prs_mem_free(&sec_blob); DEBUG(100,("data_len: %x data_calc_len: %x\n", data_len, prs_offset(&outgoing_packet))); if (flags & RPC_FLG_LAST) - ret = rpc_api_pipe(cli, &outgoing_packet, rdata); + ret = rpc_api_pipe(cli, &outgoing_packet, + rdata, RPC_RESPONSE); else { cli_write(cli, cli->nt_pipe_fnum, 0x0008, prs_data_p(&outgoing_packet), @@ -1297,84 +1272,23 @@ static BOOL check_bind_response(RPC_HDR_BA *hdr_ba, const int pipe_idx, RPC_IFAC static BOOL rpc_send_auth_reply(struct cli_state *cli, prs_struct *rdata, uint32 rpc_call_id) { - RPC_HDR_AUTH rhdr_auth; - RPC_AUTH_VERIFIER rhdr_verf; - RPC_AUTH_NTLMSSP_CHAL rhdr_chal; - char buffer[MAX_PDU_FRAG_LEN]; prs_struct rpc_out; ssize_t ret; - unsigned char p24[24]; - unsigned char lm_owf[24]; - unsigned char lm_hash[16]; - - if(!smb_io_rpc_hdr_auth("", &rhdr_auth, rdata, 0)) { - DEBUG(0,("rpc_send_auth_reply: Failed to unmarshall RPC_HDR_AUTH.\n")); - return False; - } - if(!smb_io_rpc_auth_verifier("", &rhdr_verf, rdata, 0)) { - DEBUG(0,("rpc_send_auth_reply: Failed to unmarshall RPC_AUTH_VERIFIER.\n")); - return False; - } - if(!smb_io_rpc_auth_ntlmssp_chal("", &rhdr_chal, rdata, 0)) { - DEBUG(0,("rpc_send_auth_reply: Failed to unmarshall RPC_AUTH_NTLMSSP_CHAL.\n")); - return False; - } - - cli->ntlmssp_cli_flgs = rhdr_chal.neg_flags; - - pwd_make_lm_nt_owf(&cli->pwd, rhdr_chal.challenge); + prs_init(&rpc_out, RPC_HEADER_LEN + RPC_HDR_AUTHA_LEN, /* need at least this much */ + cli->mem_ctx, MARSHALL); - prs_init(&rpc_out, 0, cli->mem_ctx, MARSHALL); - - prs_give_memory( &rpc_out, buffer, sizeof(buffer), False); - - create_rpc_bind_resp(&cli->pwd, cli->domain, - cli->user_name, global_myname(), - cli->ntlmssp_cli_flgs, rpc_call_id, + create_rpc_bind_resp(cli, rpc_call_id, &rpc_out); - - pwd_get_lm_nt_owf(&cli->pwd, lm_owf, NULL); - pwd_get_lm_nt_16(&cli->pwd, lm_hash, NULL); - - NTLMSSPOWFencrypt(lm_hash, lm_owf, p24); - - { - unsigned char j = 0; - int ind; - unsigned char k2[8]; - - memcpy(k2, p24, 5); - k2[5] = 0xe5; - k2[6] = 0x38; - k2[7] = 0xb0; - - for (ind = 0; ind < 256; ind++) - cli->ntlmssp_hash[ind] = (unsigned char)ind; - - for( ind = 0; ind < 256; ind++) { - unsigned char tc; - - j += (cli->ntlmssp_hash[ind] + k2[ind%8]); - - tc = cli->ntlmssp_hash[ind]; - cli->ntlmssp_hash[ind] = cli->ntlmssp_hash[j]; - cli->ntlmssp_hash[j] = tc; - } - - cli->ntlmssp_hash[256] = 0; - cli->ntlmssp_hash[257] = 0; - } - - memset((char *)lm_hash, '\0', sizeof(lm_hash)); if ((ret = cli_write(cli, cli->nt_pipe_fnum, 0x8, prs_data_p(&rpc_out), 0, (size_t)prs_offset(&rpc_out))) != (ssize_t)prs_offset(&rpc_out)) { DEBUG(0,("rpc_send_auth_reply: cli_write failed. Return was %d\n", (int)ret)); + prs_mem_free(&rpc_out); return False; } - cli->ntlmssp_srv_flgs = rhdr_chal.neg_flags; + prs_mem_free(&rpc_out); return True; } @@ -1382,14 +1296,12 @@ static BOOL rpc_send_auth_reply(struct cli_state *cli, prs_struct *rdata, uint32 Do an rpc bind. ****************************************************************************/ -static BOOL rpc_pipe_bind(struct cli_state *cli, int pipe_idx, const char *my_name, - BOOL do_netsec) +static BOOL rpc_pipe_bind(struct cli_state *cli, int pipe_idx, const char *my_name) { RPC_IFACE abstract; RPC_IFACE transfer; prs_struct rpc_out; prs_struct rdata; - BOOL do_auth = (cli->ntlmssp_cli_flgs != 0); uint32 rpc_call_id; char buffer[MAX_PDU_FRAG_LEN]; @@ -1411,16 +1323,54 @@ static BOOL rpc_pipe_bind(struct cli_state *cli, int pipe_idx, const char *my_na rpc_call_id = get_rpc_call_id(); + if (cli->pipe_auth_flags & AUTH_PIPE_NTLMSSP) { + NTSTATUS nt_status; + fstring password; + + DEBUG(5, ("NTLMSSP authenticated pipe selected\n")); + + nt_status = ntlmssp_client_start(&cli->ntlmssp_pipe_state); + + if (!NT_STATUS_IS_OK(nt_status)) + return False; + + nt_status = ntlmssp_set_username(cli->ntlmssp_pipe_state, + cli->user_name); + if (!NT_STATUS_IS_OK(nt_status)) + return False; + + nt_status = ntlmssp_set_domain(cli->ntlmssp_pipe_state, + cli->domain); + if (!NT_STATUS_IS_OK(nt_status)) + return False; + + pwd_get_cleartext(&cli->pwd, password); + nt_status = ntlmssp_set_password(cli->ntlmssp_pipe_state, + password); + if (!NT_STATUS_IS_OK(nt_status)) + return False; + + if (cli->pipe_auth_flags & AUTH_PIPE_SIGN) { + cli->ntlmssp_pipe_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN; + } + + if (cli->pipe_auth_flags & AUTH_PIPE_SEAL) { + cli->ntlmssp_pipe_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL; + } + } else if (cli->pipe_auth_flags & AUTH_PIPE_NETSEC) { + cli->auth_info.seq_num = 0; + } + /* Marshall the outgoing data. */ - create_rpc_bind_req(&rpc_out, do_auth, do_netsec, rpc_call_id, + create_rpc_bind_req(cli, &rpc_out, rpc_call_id, &abstract, &transfer, - global_myname(), cli->domain, cli->ntlmssp_cli_flgs); + global_myname(), cli->domain); /* Initialize the incoming data struct. */ prs_init(&rdata, 0, cli->mem_ctx, UNMARSHALL); /* send data on \PIPE\. receive a response */ - if (rpc_api_pipe(cli, &rpc_out, &rdata)) { + if (rpc_api_pipe(cli, &rpc_out, &rdata, RPC_BINDACK)) { RPC_HDR_BA hdr_ba; DEBUG(5, ("rpc_pipe_bind: rpc_api_pipe returned OK.\n")); @@ -1446,15 +1396,17 @@ static BOOL rpc_pipe_bind(struct cli_state *cli, int pipe_idx, const char *my_na * handshake. */ - if (do_auth && !rpc_send_auth_reply(cli, &rdata, rpc_call_id)) { + if ((cli->pipe_auth_flags & AUTH_PIPE_NTLMSSP) + && !rpc_send_auth_reply(cli, &rdata, rpc_call_id)) { DEBUG(0,("rpc_pipe_bind: rpc_send_auth_reply failed.\n")); prs_mem_free(&rdata); return False; } + prs_mem_free(&rdata); + return True; } - prs_mem_free(&rdata); - return True; + return False; } /**************************************************************************** @@ -1502,7 +1454,7 @@ BOOL cli_nt_session_open(struct cli_state *cli, const int pipe_idx) /******************* bind request on pipe *****************/ - if (!rpc_pipe_bind(cli, pipe_idx, global_myname(), False)) { + if (!rpc_pipe_bind(cli, pipe_idx, global_myname())) { DEBUG(2,("cli_nt_session_open: rpc bind to %s failed\n", get_pipe_name_from_index(pipe_idx))); cli_close(cli, cli->nt_pipe_fnum); @@ -1515,15 +1467,15 @@ BOOL cli_nt_session_open(struct cli_state *cli, const int pipe_idx) fstrcpy(cli->srv_name_slash, "\\\\"); fstrcat(cli->srv_name_slash, cli->desthost); - strupper(cli->srv_name_slash); + strupper_m(cli->srv_name_slash); fstrcpy(cli->clnt_name_slash, "\\\\"); fstrcat(cli->clnt_name_slash, global_myname()); - strupper(cli->clnt_name_slash); + strupper_m(cli->clnt_name_slash); fstrcpy(cli->mach_acct, global_myname()); fstrcat(cli->mach_acct, "$"); - strupper(cli->mach_acct); + strupper_m(cli->mach_acct); /* Remember which pipe we're talking to */ fstrcpy(cli->pipe_name, pipe_names[pipe_idx].client_pipe); @@ -1534,34 +1486,28 @@ BOOL cli_nt_session_open(struct cli_state *cli, const int pipe_idx) /**************************************************************************** Open a session to the NETLOGON pipe using schannel. + + (Assumes that the netlogon pipe is already open) ****************************************************************************/ -BOOL cli_nt_open_netlogon(struct cli_state *cli, const char *trust_password, - int sec_chan) +NTSTATUS cli_nt_establish_netlogon(struct cli_state *cli, int sec_chan, + const uchar trust_password[16]) { - NTSTATUS result; + NTSTATUS result; uint32 neg_flags = 0x000001ff; int fnum; + cli_nt_netlogon_netsec_session_close(cli); + if (lp_client_schannel() != False) neg_flags |= NETLOGON_NEG_SCHANNEL; - - if (!cli_nt_session_open(cli, PI_NETLOGON)) { - return False; - } - - if (!secrets_init()) { - DEBUG(3,("Failed to init secrets.tdb\n")); - return False; - } - result = cli_nt_setup_creds(cli, sec_chan, trust_password, &neg_flags, 2); if (!NT_STATUS_IS_OK(result)) { cli_nt_session_close(cli); - return False; + return result; } if ((lp_client_schannel() == True) && @@ -1569,35 +1515,40 @@ BOOL cli_nt_open_netlogon(struct cli_state *cli, const char *trust_password, DEBUG(3, ("Server did not offer schannel\n")); cli_nt_session_close(cli); - return False; + return NT_STATUS_UNSUCCESSFUL; } if ((lp_client_schannel() == False) || ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) { - return True; + return NT_STATUS_OK; + + /* keep the existing connection to NETLOGON open */ + } /* Server offered schannel, so try it. */ - cli->auth_info.seq_num = 0; memcpy(cli->auth_info.sess_key, cli->sess_key, sizeof(cli->auth_info.sess_key)); cli->saved_netlogon_pipe_fnum = cli->nt_pipe_fnum; + cli->pipe_auth_flags = AUTH_PIPE_NETSEC; + cli->pipe_auth_flags |= AUTH_PIPE_SIGN; + cli->pipe_auth_flags |= AUTH_PIPE_SEAL; + if (cli->capabilities & CAP_NT_SMBS) { /* The secure channel connection must be opened on the same session (TCP connection) as the one the challenge was requested from. */ - if ((fnum = cli_nt_create(cli, PIPE_NETLOGON_PLAIN, DESIRED_ACCESS_PIPE)) == -1) { DEBUG(0,("cli_nt_create failed to %s machine %s. " "Error was %s\n", PIPE_NETLOGON, cli->desthost, cli_errstr(cli))); - return False; + return NT_STATUS_UNSUCCESSFUL; } cli->nt_pipe_fnum = (uint16)fnum; @@ -1608,7 +1559,7 @@ BOOL cli_nt_open_netlogon(struct cli_state *cli, const char *trust_password, "Error was %s\n", PIPE_NETLOGON, cli->desthost, cli_errstr(cli))); - return False; + return NT_STATUS_UNSUCCESSFUL; } cli->nt_pipe_fnum = (uint16)fnum; @@ -1618,17 +1569,20 @@ BOOL cli_nt_open_netlogon(struct cli_state *cli, const char *trust_password, DEBUG(0,("Pipe hnd state failed. Error was %s\n", cli_errstr(cli))); cli_close(cli, cli->nt_pipe_fnum); - return False; + return NT_STATUS_UNSUCCESSFUL; } } - - if (!rpc_pipe_bind(cli, PI_NETLOGON, global_myname(), True)) { + + /* doing schannel, not per-user auth */ + cli->pipe_auth_flags = AUTH_PIPE_NETSEC | AUTH_PIPE_SIGN | AUTH_PIPE_SEAL; + + if (!rpc_pipe_bind(cli, PI_NETLOGON, global_myname())) { DEBUG(2,("rpc bind to %s failed\n", PIPE_NETLOGON)); cli_close(cli, cli->nt_pipe_fnum); - return False; + return NT_STATUS_UNSUCCESSFUL; } - return True; + return NT_STATUS_OK; } @@ -1638,16 +1592,3 @@ const char *cli_pipe_get_name(struct cli_state *cli) } -/**************************************************************************** -close the session -****************************************************************************/ - -void cli_nt_session_close(struct cli_state *cli) -{ - if (cli->saved_netlogon_pipe_fnum != 0) { - cli_close(cli, cli->saved_netlogon_pipe_fnum); - cli->saved_netlogon_pipe_fnum = 0; - } - cli_close(cli, cli->nt_pipe_fnum); - cli->nt_pipe_fnum = 0; -} diff --git a/source3/rpc_client/cli_samr.c b/source3/rpc_client/cli_samr.c index 767c6a12b2..635b7e7135 100644 --- a/source3/rpc_client/cli_samr.c +++ b/source3/rpc_client/cli_samr.c @@ -35,6 +35,8 @@ NTSTATUS cli_samr_connect(struct cli_state *cli, TALLOC_CTX *mem_ctx, SAMR_R_CONNECT r; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + DEBUG(10,("cli_samr_connect to %s\n", cli->desthost)); + ZERO_STRUCT(q); ZERO_STRUCT(r); @@ -82,6 +84,8 @@ NTSTATUS cli_samr_connect4(struct cli_state *cli, TALLOC_CTX *mem_ctx, SAMR_R_CONNECT4 r; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + DEBUG(10,("cli_samr_connect4 to %s\n", cli->desthost)); + ZERO_STRUCT(q); ZERO_STRUCT(r); @@ -129,6 +133,8 @@ NTSTATUS cli_samr_close(struct cli_state *cli, TALLOC_CTX *mem_ctx, SAMR_R_CLOSE_HND r; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + DEBUG(10,("cli_samr_close\n")); + ZERO_STRUCT(q); ZERO_STRUCT(r); @@ -177,6 +183,8 @@ NTSTATUS cli_samr_open_domain(struct cli_state *cli, TALLOC_CTX *mem_ctx, SAMR_R_OPEN_DOMAIN r; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + DEBUG(10,("cli_samr_open_domain with sid %s\n", sid_string_static(domain_sid) )); + ZERO_STRUCT(q); ZERO_STRUCT(r); @@ -225,6 +233,8 @@ NTSTATUS cli_samr_open_user(struct cli_state *cli, TALLOC_CTX *mem_ctx, SAMR_R_OPEN_USER r; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + DEBUG(10,("cli_samr_open_user with rid 0x%x\n", user_rid )); + ZERO_STRUCT(q); ZERO_STRUCT(r); @@ -273,6 +283,8 @@ NTSTATUS cli_samr_open_group(struct cli_state *cli, TALLOC_CTX *mem_ctx, SAMR_R_OPEN_GROUP r; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + DEBUG(10,("cli_samr_open_group with rid 0x%x\n", group_rid )); + ZERO_STRUCT(q); ZERO_STRUCT(r); @@ -321,6 +333,8 @@ NTSTATUS cli_samr_query_userinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx, SAMR_R_QUERY_USERINFO r; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + DEBUG(10,("cli_samr_query_userinfo\n")); + ZERO_STRUCT(q); ZERO_STRUCT(r); @@ -365,6 +379,8 @@ NTSTATUS cli_samr_query_groupinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx, SAMR_R_QUERY_GROUPINFO r; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + DEBUG(10,("cli_samr_query_groupinfo\n")); + ZERO_STRUCT(q); ZERO_STRUCT(r); @@ -410,6 +426,8 @@ NTSTATUS cli_samr_query_usergroups(struct cli_state *cli, TALLOC_CTX *mem_ctx, SAMR_R_QUERY_USERGROUPS r; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + DEBUG(10,("cli_samr_query_usergroups\n")); + ZERO_STRUCT(q); ZERO_STRUCT(r); @@ -457,6 +475,8 @@ NTSTATUS cli_samr_query_useraliases(struct cli_state *cli, TALLOC_CTX *mem_ctx, NTSTATUS result = NT_STATUS_UNSUCCESSFUL; unsigned int ptr=1; + DEBUG(10,("cli_samr_query_useraliases\n")); + ZERO_STRUCT(q); ZERO_STRUCT(r); @@ -503,6 +523,8 @@ NTSTATUS cli_samr_query_groupmem(struct cli_state *cli, TALLOC_CTX *mem_ctx, SAMR_R_QUERY_GROUPMEM r; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + DEBUG(10,("cli_samr_query_groupmem\n")); + ZERO_STRUCT(q); ZERO_STRUCT(r); @@ -568,6 +590,8 @@ NTSTATUS cli_samr_enum_dom_users(struct cli_state *cli, TALLOC_CTX *mem_ctx, NTSTATUS result = NT_STATUS_UNSUCCESSFUL; int i; + DEBUG(10,("cli_samr_enum_dom_users starting at index %u\n", (unsigned int)*start_idx)); + ZERO_STRUCT(q); ZERO_STRUCT(r); @@ -646,6 +670,8 @@ NTSTATUS cli_samr_enum_dom_groups(struct cli_state *cli, TALLOC_CTX *mem_ctx, NTSTATUS result = NT_STATUS_UNSUCCESSFUL; uint32 name_idx, i; + DEBUG(10,("cli_samr_enum_dom_groups starting at index %u\n", (unsigned int)*start_idx)); + ZERO_STRUCT(q); ZERO_STRUCT(r); @@ -724,6 +750,8 @@ NTSTATUS cli_samr_enum_als_groups(struct cli_state *cli, TALLOC_CTX *mem_ctx, NTSTATUS result = NT_STATUS_UNSUCCESSFUL; uint32 name_idx, i; + DEBUG(10,("cli_samr_enum_als_groups starting at index %u\n", (unsigned int)*start_idx)); + ZERO_STRUCT(q); ZERO_STRUCT(r); @@ -804,6 +832,8 @@ NTSTATUS cli_samr_query_aliasmem(struct cli_state *cli, TALLOC_CTX *mem_ctx, NTSTATUS result = NT_STATUS_UNSUCCESSFUL; uint32 i; + DEBUG(10,("cli_samr_query_aliasmem\n")); + ZERO_STRUCT(q); ZERO_STRUCT(r); @@ -862,6 +892,8 @@ NTSTATUS cli_samr_open_alias(struct cli_state *cli, TALLOC_CTX *mem_ctx, SAMR_R_OPEN_ALIAS r; NTSTATUS result; + DEBUG(10,("cli_samr_open_alias with rid 0x%x\n", alias_rid)); + ZERO_STRUCT(q); ZERO_STRUCT(r); @@ -903,6 +935,57 @@ NTSTATUS cli_samr_open_alias(struct cli_state *cli, TALLOC_CTX *mem_ctx, return result; } +/* Query alias info */ + +NTSTATUS cli_samr_query_alias_info(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *alias_pol, uint16 switch_value, + ALIAS_INFO_CTR *ctr) +{ + prs_struct qbuf, rbuf; + SAMR_Q_QUERY_ALIASINFO q; + SAMR_R_QUERY_ALIASINFO r; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + + DEBUG(10,("cli_samr_query_dom_info\n")); + + ZERO_STRUCT(q); + ZERO_STRUCT(r); + + /* Initialise parse structures */ + + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); + + /* Marshall data and send request */ + + init_samr_q_query_aliasinfo(&q, alias_pol, switch_value); + + if (!samr_io_q_query_aliasinfo("", &q, &qbuf, 0) || + !rpc_api_pipe_req(cli, SAMR_QUERY_ALIASINFO, &qbuf, &rbuf)) { + goto done; + } + + /* Unmarshall response */ + + if (!samr_io_r_query_aliasinfo("", &r, &rbuf, 0)) { + goto done; + } + + /* Return output parameters */ + + if (!NT_STATUS_IS_OK(result = r.status)) { + goto done; + } + + *ctr = r.ctr; + + done: + prs_mem_free(&qbuf); + prs_mem_free(&rbuf); + + return result; +} + /* Query domain info */ NTSTATUS cli_samr_query_dom_info(struct cli_state *cli, TALLOC_CTX *mem_ctx, @@ -914,6 +997,8 @@ NTSTATUS cli_samr_query_dom_info(struct cli_state *cli, TALLOC_CTX *mem_ctx, SAMR_R_QUERY_DOMAIN_INFO r; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + DEBUG(10,("cli_samr_query_dom_info\n")); + ZERO_STRUCT(q); ZERO_STRUCT(r); @@ -997,9 +1082,13 @@ NTSTATUS cli_samr_query_dispinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx, SAMR_R_QUERY_DISPINFO r; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + DEBUG(10,("cli_samr_query_dispinfo for start_idx = %u\n", *start_idx)); + ZERO_STRUCT(q); ZERO_STRUCT(r); + *num_entries = 0; + /* Initialise parse structures */ prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); @@ -1057,6 +1146,8 @@ NTSTATUS cli_samr_lookup_rids(struct cli_state *cli, TALLOC_CTX *mem_ctx, NTSTATUS result = NT_STATUS_UNSUCCESSFUL; uint32 i; + DEBUG(10,("cli_samr_lookup_rids\n")); + if (num_rids > 1000) { DEBUG(2, ("cli_samr_lookup_rids: warning: NT4 can crash if " "more than ~1000 rids are looked up at once.\n")); @@ -1131,6 +1222,8 @@ NTSTATUS cli_samr_lookup_names(struct cli_state *cli, TALLOC_CTX *mem_ctx, NTSTATUS result = NT_STATUS_UNSUCCESSFUL; uint32 i; + DEBUG(10,("cli_samr_lookup_names\n")); + ZERO_STRUCT(q); ZERO_STRUCT(r); @@ -1194,6 +1287,8 @@ NTSTATUS cli_samr_create_dom_user(struct cli_state *cli, TALLOC_CTX *mem_ctx, SAMR_R_CREATE_USER r; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + DEBUG(10,("cli_samr_create_dom_user %s\n", acct_name)); + ZERO_STRUCT(q); ZERO_STRUCT(r); @@ -1247,6 +1342,8 @@ NTSTATUS cli_samr_set_userinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx, SAMR_R_SET_USERINFO r; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + DEBUG(10,("cli_samr_set_userinfo\n")); + ZERO_STRUCT(q); ZERO_STRUCT(r); @@ -1297,6 +1394,8 @@ NTSTATUS cli_samr_set_userinfo2(struct cli_state *cli, TALLOC_CTX *mem_ctx, SAMR_R_SET_USERINFO2 r; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + DEBUG(10,("cli_samr_set_userinfo2\n")); + ZERO_STRUCT(q); ZERO_STRUCT(r); @@ -1343,6 +1442,8 @@ NTSTATUS cli_samr_delete_dom_user(struct cli_state *cli, TALLOC_CTX *mem_ctx, SAMR_R_DELETE_DOM_USER r; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + DEBUG(10,("cli_samr_delete_dom_user\n")); + ZERO_STRUCT(q); ZERO_STRUCT(r); @@ -1388,6 +1489,8 @@ NTSTATUS cli_samr_query_sec_obj(struct cli_state *cli, TALLOC_CTX *mem_ctx, SAMR_R_QUERY_SEC_OBJ r; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + DEBUG(10,("cli_samr_query_sec_obj\n")); + ZERO_STRUCT(q); ZERO_STRUCT(r); @@ -1433,6 +1536,8 @@ NTSTATUS cli_samr_get_dom_pwinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx, SAMR_R_GET_DOM_PWINFO r; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + DEBUG(10,("cli_samr_get_dom_pwinfo\n")); + ZERO_STRUCT(q); ZERO_STRUCT(r); @@ -1485,6 +1590,8 @@ NTSTATUS cli_samr_lookup_domain(struct cli_state *cli, TALLOC_CTX *mem_ctx, SAMR_R_LOOKUP_DOMAIN r; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + DEBUG(10,("cli_samr_lookup_domain\n")); + ZERO_STRUCT(q); ZERO_STRUCT(r); diff --git a/source3/rpc_client/cli_spoolss.c b/source3/rpc_client/cli_spoolss.c index bb6ce1b998..6392620497 100644 --- a/source3/rpc_client/cli_spoolss.c +++ b/source3/rpc_client/cli_spoolss.c @@ -511,8 +511,8 @@ WERROR cli_spoolss_enum_ports(struct cli_state *cli, TALLOC_CTX *mem_ctx, ZERO_STRUCT(q); ZERO_STRUCT(r); - slprintf (server, sizeof(fstring)-1, "\\\\%s", cli->desthost); - strupper (server); + slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->desthost); + strupper_m(server); /* Initialise input parameters */ @@ -732,8 +732,8 @@ WERROR cli_spoolss_getprinterdriver(struct cli_state *cli, ZERO_STRUCT(q); ZERO_STRUCT(r); - fstrcpy (server, cli->desthost); - strupper (server); + fstrcpy(server, cli->desthost); + strupper_m(server); /* Initialise input parameters */ @@ -813,8 +813,8 @@ WERROR cli_spoolss_enumprinterdrivers (struct cli_state *cli, ZERO_STRUCT(q); ZERO_STRUCT(r); - slprintf (server, sizeof(fstring)-1, "\\\\%s", cli->desthost); - strupper (server); + slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->desthost); + strupper_m(server); /* Initialise input parameters */ @@ -899,8 +899,8 @@ WERROR cli_spoolss_getprinterdriverdir (struct cli_state *cli, ZERO_STRUCT(q); ZERO_STRUCT(r); - slprintf (server, sizeof(fstring)-1, "\\\\%s", cli->desthost); - strupper (server); + slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->desthost); + strupper_m(server); /* Initialise input parameters */ @@ -967,8 +967,8 @@ WERROR cli_spoolss_addprinterdriver (struct cli_state *cli, ZERO_STRUCT(q); ZERO_STRUCT(r); - slprintf (server, sizeof(fstring)-1, "\\\\%s", cli->desthost); - strupper (server); + slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->desthost); + strupper_m(server); /* Initialise input parameters */ @@ -1021,10 +1021,10 @@ WERROR cli_spoolss_addprinterex (struct cli_state *cli, TALLOC_CTX *mem_ctx, ZERO_STRUCT(q); ZERO_STRUCT(r); - slprintf (client, sizeof(fstring)-1, "\\\\%s", cli->desthost); - strupper (client); - slprintf (server, sizeof(fstring)-1, "\\\\%s", cli->desthost); - strupper (server); + slprintf(client, sizeof(fstring)-1, "\\\\%s", cli->desthost); + strupper_m(client); + slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->desthost); + strupper_m(server); fstrcpy (user, cli->user_name); /* Initialise input parameters */ @@ -1084,8 +1084,8 @@ WERROR cli_spoolss_deleteprinterdriver (struct cli_state *cli, prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - slprintf (server, sizeof(fstring)-1, "\\\\%s", cli->desthost); - strupper (server); + slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->desthost); + strupper_m(server); /* Write the request */ diff --git a/source3/rpc_parse/parse_misc.c b/source3/rpc_parse/parse_misc.c index a39e3391bb..17a96fff80 100644 --- a/source3/rpc_parse/parse_misc.c +++ b/source3/rpc_parse/parse_misc.c @@ -1122,78 +1122,6 @@ BOOL smb_io_unistr2_array(const char *desc, UNISTR2_ARRAY *array, prs_struct *ps } -/* - initialise a SID_ARRAY from a list of sids -*/ -BOOL init_sid_array(SID_ARRAY *array, - uint32 count, DOM_SID *sids) -{ - unsigned int i; - - array->count = count; - array->ref_id = count?1:0; - if (array->count == 0) { - return True; - } - - array->sids = (SID_ARRAY_EL *)talloc_zero(get_talloc_ctx(), count * sizeof(SID_ARRAY_EL)); - if (!array->sids) { - return False; - } - - for (i=0;isids[i].ref_id = 1; - init_dom_sid2(&array->sids[i].sid, &sids[i]); - } - - return True; -} - - -/******************************************************************* - Reads or writes a SID_ARRAY structure. -********************************************************************/ -BOOL smb_io_sid_array(const char *desc, SID_ARRAY *array, prs_struct *ps, int depth) -{ - unsigned int i; - - prs_debug(ps, depth, desc, "smb_io_sid_array"); - depth++; - - if(!prs_uint32("ref_id", ps, depth, &array->ref_id)) - return False; - - if (! array->ref_id) { - return True; - } - - if(!prs_uint32("count", ps, depth, &array->count)) - return False; - - if (array->count == 0) { - return True; - } - - if (UNMARSHALLING(ps)) { - array->sids = talloc_zero(get_talloc_ctx(), array->count * sizeof(array->sids[0])); - } - if (! array->sids) { - return False; - } - - for (i=0;icount;i++) { - if(!prs_uint32("ref_id", ps, depth, &array->sids[i].ref_id)) - return False; - } - - for (i=0;icount;i++) { - if (!smb_io_dom_sid2("sid", &array->sids[i].sid, ps, depth)) - return False; - } - - return True; -} - /******************************************************************* Inits a DOM_RID2 structure. ********************************************************************/ @@ -1289,22 +1217,22 @@ void init_dom_rid4(DOM_RID4 *rid4, uint16 unknown, uint16 attr, uint32 rid) Inits a DOM_CLNT_SRV structure. ********************************************************************/ -static void init_clnt_srv(DOM_CLNT_SRV *dlog, const char *logon_srv, const char *comp_name) +static void init_clnt_srv(DOM_CLNT_SRV *logcln, const char *logon_srv, const char *comp_name) { DEBUG(5,("init_clnt_srv: %d\n", __LINE__)); if (logon_srv != NULL) { - dlog->undoc_buffer = 1; - init_unistr2(&dlog->uni_logon_srv, logon_srv, strlen(logon_srv)+1); + logcln->undoc_buffer = 1; + init_unistr2(&logcln->uni_logon_srv, logon_srv, strlen(logon_srv)+1); } else { - dlog->undoc_buffer = 0; + logcln->undoc_buffer = 0; } if (comp_name != NULL) { - dlog->undoc_buffer2 = 1; - init_unistr2(&dlog->uni_comp_name, comp_name, strlen(comp_name)+1); + logcln->undoc_buffer2 = 1; + init_unistr2(&logcln->uni_comp_name, comp_name, strlen(comp_name)+1); } else { - dlog->undoc_buffer2 = 0; + logcln->undoc_buffer2 = 0; } } @@ -1312,9 +1240,9 @@ static void init_clnt_srv(DOM_CLNT_SRV *dlog, const char *logon_srv, const char Inits or writes a DOM_CLNT_SRV structure. ********************************************************************/ -static BOOL smb_io_clnt_srv(const char *desc, DOM_CLNT_SRV *dlog, prs_struct *ps, int depth) +static BOOL smb_io_clnt_srv(const char *desc, DOM_CLNT_SRV *logcln, prs_struct *ps, int depth) { - if (dlog == NULL) + if (logcln == NULL) return False; prs_debug(ps, depth, desc, "smb_io_clnt_srv"); @@ -1323,22 +1251,22 @@ static BOOL smb_io_clnt_srv(const char *desc, DOM_CLNT_SRV *dlog, prs_struct *ps if(!prs_align(ps)) return False; - if(!prs_uint32("undoc_buffer ", ps, depth, &dlog->undoc_buffer)) + if(!prs_uint32("undoc_buffer ", ps, depth, &logcln->undoc_buffer)) return False; - if (dlog->undoc_buffer != 0) { - if(!smb_io_unistr2("unistr2", &dlog->uni_logon_srv, dlog->undoc_buffer, ps, depth)) + if (logcln->undoc_buffer != 0) { + if(!smb_io_unistr2("unistr2", &logcln->uni_logon_srv, logcln->undoc_buffer, ps, depth)) return False; } if(!prs_align(ps)) return False; - if(!prs_uint32("undoc_buffer2", ps, depth, &dlog->undoc_buffer2)) + if(!prs_uint32("undoc_buffer2", ps, depth, &logcln->undoc_buffer2)) return False; - if (dlog->undoc_buffer2 != 0) { - if(!smb_io_unistr2("unistr2", &dlog->uni_comp_name, dlog->undoc_buffer2, ps, depth)) + if (logcln->undoc_buffer2 != 0) { + if(!smb_io_unistr2("unistr2", &logcln->uni_comp_name, logcln->undoc_buffer2, ps, depth)) return False; } @@ -1349,28 +1277,28 @@ static BOOL smb_io_clnt_srv(const char *desc, DOM_CLNT_SRV *dlog, prs_struct *ps Inits a DOM_LOG_INFO structure. ********************************************************************/ -void init_log_info(DOM_LOG_INFO *dlog, const char *logon_srv, const char *acct_name, +void init_log_info(DOM_LOG_INFO *loginfo, const char *logon_srv, const char *acct_name, uint16 sec_chan, const char *comp_name) { DEBUG(5,("make_log_info %d\n", __LINE__)); - dlog->undoc_buffer = 1; + loginfo->undoc_buffer = 1; - init_unistr2(&dlog->uni_logon_srv, logon_srv, strlen(logon_srv)+1); - init_unistr2(&dlog->uni_acct_name, acct_name, strlen(acct_name)+1); + init_unistr2(&loginfo->uni_logon_srv, logon_srv, strlen(logon_srv)+1); + init_unistr2(&loginfo->uni_acct_name, acct_name, strlen(acct_name)+1); - dlog->sec_chan = sec_chan; + loginfo->sec_chan = sec_chan; - init_unistr2(&dlog->uni_comp_name, comp_name, strlen(comp_name)+1); + init_unistr2(&loginfo->uni_comp_name, comp_name, strlen(comp_name)+1); } /******************************************************************* Reads or writes a DOM_LOG_INFO structure. ********************************************************************/ -BOOL smb_io_log_info(const char *desc, DOM_LOG_INFO *dlog, prs_struct *ps, int depth) +BOOL smb_io_log_info(const char *desc, DOM_LOG_INFO *loginfo, prs_struct *ps, int depth) { - if (dlog == NULL) + if (loginfo == NULL) return False; prs_debug(ps, depth, desc, "smb_io_log_info"); @@ -1379,18 +1307,18 @@ BOOL smb_io_log_info(const char *desc, DOM_LOG_INFO *dlog, prs_struct *ps, int d if(!prs_align(ps)) return False; - if(!prs_uint32("undoc_buffer", ps, depth, &dlog->undoc_buffer)) + if(!prs_uint32("undoc_buffer", ps, depth, &loginfo->undoc_buffer)) return False; - if(!smb_io_unistr2("unistr2", &dlog->uni_logon_srv, True, ps, depth)) + if(!smb_io_unistr2("unistr2", &loginfo->uni_logon_srv, True, ps, depth)) return False; - if(!smb_io_unistr2("unistr2", &dlog->uni_acct_name, True, ps, depth)) + if(!smb_io_unistr2("unistr2", &loginfo->uni_acct_name, True, ps, depth)) return False; - if(!prs_uint16("sec_chan", ps, depth, &dlog->sec_chan)) + if(!prs_uint16("sec_chan", ps, depth, &loginfo->sec_chan)) return False; - if(!smb_io_unistr2("unistr2", &dlog->uni_comp_name, True, ps, depth)) + if(!smb_io_unistr2("unistr2", &loginfo->uni_comp_name, True, ps, depth)) return False; return True; @@ -1529,21 +1457,21 @@ BOOL smb_io_clnt_info(const char *desc, DOM_CLNT_INFO *clnt, prs_struct *ps, in Inits a DOM_LOGON_ID structure. ********************************************************************/ -void init_logon_id(DOM_LOGON_ID *dlog, uint32 log_id_low, uint32 log_id_high) +void init_logon_id(DOM_LOGON_ID *logonid, uint32 log_id_low, uint32 log_id_high) { DEBUG(5,("make_logon_id: %d\n", __LINE__)); - dlog->low = log_id_low; - dlog->high = log_id_high; + logonid->low = log_id_low; + logonid->high = log_id_high; } /******************************************************************* Reads or writes a DOM_LOGON_ID structure. ********************************************************************/ -BOOL smb_io_logon_id(const char *desc, DOM_LOGON_ID *dlog, prs_struct *ps, int depth) +BOOL smb_io_logon_id(const char *desc, DOM_LOGON_ID *logonid, prs_struct *ps, int depth) { - if (dlog == NULL) + if (logonid == NULL) return False; prs_debug(ps, depth, desc, "smb_io_logon_id"); @@ -1552,9 +1480,9 @@ BOOL smb_io_logon_id(const char *desc, DOM_LOGON_ID *dlog, prs_struct *ps, int d if(!prs_align(ps)) return False; - if(!prs_uint32("low ", ps, depth, &dlog->low )) + if(!prs_uint32("low ", ps, depth, &logonid->low )) return False; - if(!prs_uint32("high", ps, depth, &dlog->high)) + if(!prs_uint32("high", ps, depth, &logonid->high)) return False; return True; diff --git a/source3/rpc_parse/parse_net.c b/source3/rpc_parse/parse_net.c index 1a14915c9f..804da707de 100644 --- a/source3/rpc_parse/parse_net.c +++ b/source3/rpc_parse/parse_net.c @@ -446,7 +446,7 @@ void init_r_trust_dom(NET_R_TRUST_DOM_LIST *r_t, for (i = 0; i < num_doms; i++) { fstring domain_name; fstrcpy(domain_name, dom_name); - strupper(domain_name); + strupper_m(domain_name); init_unistr2(&r_t->uni_trust_dom_name[i], domain_name, strlen(domain_name)+1); /* the use of UNISTR2 here is non-standard. */ r_t->uni_trust_dom_name[i].undoc = 0x1; @@ -1294,7 +1294,7 @@ void init_net_user_info3(TALLOC_CTX *ctx, NET_USER_INFO_3 *usr, int len_logon_srv = strlen(logon_srv); int len_logon_dom = strlen(logon_dom); - len_user_name = strlen(user_name ); + len_user_name = strlen(user_name ); len_full_name = strlen(full_name ); len_home_dir = strlen(home_dir ); len_dir_drive = strlen(dir_drive ); @@ -1306,6 +1306,7 @@ void init_net_user_info3(TALLOC_CTX *ctx, NET_USER_INFO_3 *usr, usr->ptr_user_info = 1; /* yes, we're bothering to put USER_INFO data here */ + /* Create NTTIME structs */ unix_to_nt_time (&logon_time, unix_logon_time); @@ -1808,9 +1809,9 @@ static BOOL net_io_sam_domain_info(const char *desc, SAM_DOMAIN_INFO * info, if (!smb_io_unihdr("hdr_unknown", &info->hdr_unknown, ps, depth)) return False; - if (prs_offset(ps) + 40 > prs_data_size(ps)) + if (ps->data_offset + 40 > ps->buffer_size) return False; - prs_set_offset(ps, prs_offset(ps) + 40); + ps->data_offset += 40; if (!smb_io_unistr2("uni_dom_name", &info->uni_dom_name, info->hdr_dom_name.buffer, ps, depth)) @@ -1847,9 +1848,9 @@ static BOOL net_io_sam_group_info(const char *desc, SAM_GROUP_INFO * info, if (!smb_io_bufhdr2("hdr_sec_desc", &info->hdr_sec_desc, ps, depth)) return False; - if (prs_offset(ps) + 48 > prs_data_size(ps)) + if (ps->data_offset + 48 > ps->buffer_size) return False; - prs_set_offset(ps, prs_offset(ps) + 48); + ps->data_offset += 48; if (!smb_io_unistr2("uni_grp_name", &info->uni_grp_name, info->hdr_grp_name.buffer, ps, depth)) @@ -2128,13 +2129,13 @@ static BOOL net_io_sam_account_info(const char *desc, uint8 sess_key[16], uint32 len = 0x44; if (!prs_uint32("pwd_len", ps, depth, &len)) return False; - old_offset = prs_offset(ps); + old_offset = ps->data_offset; if (len > 0) { if (ps->io) { /* reading */ - if (!prs_hash1(ps, prs_offset(ps), sess_key)) + if (!prs_hash1(ps, ps->data_offset, sess_key, len)) return False; } if (!net_io_sam_passwd_info("pass", &info->pass, @@ -2144,13 +2145,13 @@ static BOOL net_io_sam_account_info(const char *desc, uint8 sess_key[16], if (!ps->io) { /* writing */ - if (!prs_hash1(ps, old_offset, sess_key)) + if (!prs_hash1(ps, old_offset, sess_key, len)) return False; } } - if (old_offset + len > prs_data_size(ps)) + if (old_offset + len > ps->buffer_size) return False; - prs_set_offset(ps, old_offset + len); + ps->data_offset = old_offset + len; } if (!smb_io_buffer4("buf_sec_desc", &info->buf_sec_desc, info->hdr_sec_desc.buffer, ps, depth)) @@ -2185,9 +2186,9 @@ static BOOL net_io_sam_group_mem_info(const char *desc, SAM_GROUP_MEM_INFO * inf if (!prs_uint32("num_members", ps, depth, &info->num_members)) return False; - if (prs_offset(ps) + 16 > prs_data_size(ps)) + if (ps->data_offset + 16 > ps->buffer_size) return False; - prs_set_offset(ps, prs_offset(ps) + 16); + ps->data_offset += 16; if (info->ptr_rids != 0) { @@ -2267,9 +2268,9 @@ static BOOL net_io_sam_alias_info(const char *desc, SAM_ALIAS_INFO * info, if (!smb_io_unihdr("hdr_als_desc", &info->hdr_als_desc, ps, depth)) return False; - if (prs_offset(ps) + 40 > prs_data_size(ps)) + if (ps->data_offset + 40 > ps->buffer_size) return False; - prs_set_offset(ps, prs_offset(ps) + 40); + ps->data_offset += 40; if (!smb_io_unistr2("uni_als_name", &info->uni_als_name, info->hdr_als_name.buffer, ps, depth)) @@ -2307,9 +2308,9 @@ static BOOL net_io_sam_alias_mem_info(const char *desc, SAM_ALIAS_MEM_INFO * inf if (info->ptr_members != 0) { - if (prs_offset(ps) + 16 > prs_data_size(ps)) + if (ps->data_offset + 16 > ps->buffer_size) return False; - prs_set_offset(ps, prs_offset(ps) + 16); + ps->data_offset += 16; if (!prs_uint32("num_sids", ps, depth, &info->num_sids)) return False; diff --git a/source3/rpc_parse/parse_prs.c b/source3/rpc_parse/parse_prs.c index e0a75d7382..efd4914c66 100644 --- a/source3/rpc_parse/parse_prs.c +++ b/source3/rpc_parse/parse_prs.c @@ -1316,7 +1316,7 @@ int tdb_prs_fetch(TDB_CONTEXT *tdb, char *keystr, prs_struct *ps, TALLOC_CTX *me /******************************************************************* hash a stream. ********************************************************************/ -BOOL prs_hash1(prs_struct *ps, uint32 offset, uint8 sess_key[16]) +BOOL prs_hash1(prs_struct *ps, uint32 offset, uint8 sess_key[16], int len) { char *q; @@ -1326,12 +1326,12 @@ BOOL prs_hash1(prs_struct *ps, uint32 offset, uint8 sess_key[16]) #ifdef DEBUG_PASSWORD DEBUG(100, ("prs_hash1\n")); dump_data(100, sess_key, 16); - dump_data(100, q, 68); + dump_data(100, q, len); #endif - SamOEMhash((uchar *) q, sess_key, 68); + SamOEMhash((uchar *) q, sess_key, len); #ifdef DEBUG_PASSWORD - dump_data(100, q, 68); + dump_data(100, q, len); #endif return True; @@ -1378,141 +1378,221 @@ static void netsechash(uchar * key, uchar * data, int data_len) } } -void dump_data_pw(const char *msg, const uchar * data, size_t len) + +/******************************************************************* + Create a digest over the entire packet (including the data), and + MD5 it with the session key. + ********************************************************************/ +static void netsec_digest(struct netsec_auth_struct *a, + int auth_flags, + RPC_AUTH_NETSEC_CHK * verf, + char *data, size_t data_len, + uchar digest_final[16]) { -#ifdef DEBUG_PASSWORD - DEBUG(11, ("%s", msg)); - if (data != NULL && len > 0) - { - dump_data(11, data, len); + uchar whole_packet_digest[16]; + static uchar zeros[4]; + struct MD5Context ctx3; + + /* verfiy the signature on the packet by MD5 over various bits */ + MD5Init(&ctx3); + /* use our sequence number, which ensures the packet is not + out of order */ + MD5Update(&ctx3, zeros, sizeof(zeros)); + MD5Update(&ctx3, verf->sig, sizeof(verf->sig)); + if (auth_flags & AUTH_PIPE_SEAL) { + MD5Update(&ctx3, verf->data8, sizeof(verf->data8)); } -#endif + MD5Update(&ctx3, data, data_len); + MD5Final(whole_packet_digest, &ctx3); + dump_data_pw("whole_packet_digest:\n", whole_packet_digest, sizeof(whole_packet_digest)); + + /* MD5 this result and the session key, to prove that + only a valid client could had produced this */ + hmac_md5(a->sess_key, whole_packet_digest, sizeof(whole_packet_digest), digest_final); } -void netsec_encode(struct netsec_auth_struct *a, - RPC_AUTH_NETSEC_CHK * verf, char *data, size_t data_len) +/******************************************************************* + Calculate the key with which to encode the data payload + ********************************************************************/ +static void netsec_get_sealing_key(struct netsec_auth_struct *a, + RPC_AUTH_NETSEC_CHK *verf, + uchar sealing_key[16]) { - uchar dataN[4]; - uchar digest1[16]; - struct MD5Context ctx3; + static uchar zeros[4]; + uchar digest2[16]; uchar sess_kf0[16]; int i; - SIVAL(dataN, 0, 0); - for (i = 0; i < sizeof(sess_kf0); i++) { sess_kf0[i] = a->sess_key[i] ^ 0xf0; } + + dump_data_pw("sess_kf0:\n", sess_kf0, sizeof(sess_kf0)); + + /* MD5 of sess_kf0 and the high bytes of the sequence number */ + hmac_md5(sess_kf0, zeros, 0x4, digest2); + dump_data_pw("digest2:\n", digest2, sizeof(digest2)); + + /* MD5 of the above result, plus 8 bytes of sequence number */ + hmac_md5(digest2, verf->seq_num, sizeof(verf->seq_num), sealing_key); + dump_data_pw("sealing_key:\n", sealing_key, 16); +} - DEBUG(10,("SCHANNEL: netsec_encode seq_num=%d data_len=%d\n", a->seq_num, data_len)); - dump_data_pw("a->sess_key:\n", a->sess_key, sizeof(a->sess_key)); - dump_data_pw("a->seq_num :\n", dataN, sizeof(dataN)); +/******************************************************************* + Encode or Decode the sequence number (which is symmetric) + ********************************************************************/ +static void netsec_deal_with_seq_num(struct netsec_auth_struct *a, + RPC_AUTH_NETSEC_CHK *verf) +{ + static uchar zeros[4]; + uchar sequence_key[16]; + uchar digest1[16]; - MD5Init(&ctx3); - MD5Update(&ctx3, dataN, 0x4); - MD5Update(&ctx3, verf->sig, 8); + hmac_md5(a->sess_key, zeros, sizeof(zeros), digest1); + dump_data_pw("(sequence key) digest1:\n", digest1, sizeof(digest1)); - MD5Update(&ctx3, verf->data8, 8); + hmac_md5(digest1, verf->packet_digest, 8, sequence_key); - dump_data_pw("verf->data8:\n", verf->data8, sizeof(verf->data8)); - dump_data_pw("sess_kf0:\n", sess_kf0, sizeof(sess_kf0)); + dump_data_pw("sequence_key:\n", sequence_key, sizeof(sequence_key)); - hmac_md5(sess_kf0, dataN, 0x4, digest1); - dump_data_pw("digest1 (ebp-8):\n", digest1, sizeof(digest1)); - hmac_md5(digest1, verf->data3, 8, digest1); - dump_data_pw("netsechashkey:\n", digest1, sizeof(digest1)); - netsechash(digest1, verf->data8, 8); + dump_data_pw("seq_num (before):\n", verf->seq_num, sizeof(verf->seq_num)); + netsechash(sequence_key, verf->seq_num, 8); + dump_data_pw("seq_num (after):\n", verf->seq_num, sizeof(verf->seq_num)); +} - dump_data_pw("verf->data8:\n", verf->data8, sizeof(verf->data8)); - dump_data_pw("data :\n", data, data_len); - MD5Update(&ctx3, data, data_len); +/******************************************************************* + Encode a blob of data using the netsec (schannel) alogrithm, also produceing + a checksum over the original data. We currently only support + signing and sealing togeather - the signing-only code is close, but not + quite compatible with what MS does. + ********************************************************************/ +void netsec_encode(struct netsec_auth_struct *a, int auth_flags, + enum netsec_direction direction, + RPC_AUTH_NETSEC_CHK * verf, char *data, size_t data_len) +{ + uchar digest_final[16]; - { - char digest_tmp[16]; - char digest2[16]; - MD5Final(digest_tmp, &ctx3); - hmac_md5(a->sess_key, digest_tmp, 16, digest2); - dump_data_pw("digest_tmp:\n", digest_tmp, sizeof(digest_tmp)); - dump_data_pw("digest:\n", digest2, sizeof(digest2)); - memcpy(verf->data1, digest2, sizeof(verf->data1)); + DEBUG(10,("SCHANNEL: netsec_encode seq_num=%d data_len=%d\n", a->seq_num, data_len)); + dump_data_pw("a->sess_key:\n", a->sess_key, sizeof(a->sess_key)); + + RSIVAL(verf->seq_num, 0, a->seq_num); + + switch (direction) { + case SENDER_IS_INITIATOR: + SIVAL(verf->seq_num, 4, 0x80); + break; + case SENDER_IS_ACCEPTOR: + SIVAL(verf->seq_num, 4, 0x0); + break; } - netsechash(digest1, data, data_len); - dump_data_pw("data:\n", data, data_len); + dump_data_pw("verf->seq_num:\n", verf->seq_num, sizeof(verf->seq_num)); - hmac_md5(a->sess_key, dataN, 0x4, digest1); - dump_data_pw("ctx:\n", digest1, sizeof(digest1)); + /* produce a digest of the packet to prove it's legit (before we seal it) */ + netsec_digest(a, auth_flags, verf, data, data_len, digest_final); + memcpy(verf->packet_digest, digest_final, sizeof(verf->packet_digest)); - hmac_md5(digest1, verf->data1, 8, digest1); + if (auth_flags & AUTH_PIPE_SEAL) { + uchar sealing_key[16]; - dump_data_pw("netsechashkey:\n", digest1, sizeof(digest1)); + /* get the key to encode the data with */ + netsec_get_sealing_key(a, verf, sealing_key); - dump_data_pw("verf->data3:\n", verf->data3, sizeof(verf->data3)); - netsechash(digest1, verf->data3, 8); - dump_data_pw("verf->data3:\n", verf->data3, sizeof(verf->data3)); + /* encode the verification data */ + dump_data_pw("verf->data8:\n", verf->data8, sizeof(verf->data8)); + netsechash(sealing_key, verf->data8, 8); + + dump_data_pw("verf->data8_enc:\n", verf->data8, sizeof(verf->data8)); + + /* encode the packet payload */ + dump_data_pw("data:\n", data, data_len); + netsechash(sealing_key, data, data_len); + dump_data_pw("data_enc:\n", data, data_len); + } + + /* encode the sequence number (key based on packet digest) */ + /* needs to be done after the sealing, as the original version + is used in the sealing stuff... */ + netsec_deal_with_seq_num(a, verf); return; } -BOOL netsec_decode(struct netsec_auth_struct *a, +/******************************************************************* + Decode a blob of data using the netsec (schannel) alogrithm, also verifiying + a checksum over the original data. We currently can verify signed messages, + as well as decode sealed messages + ********************************************************************/ + +BOOL netsec_decode(struct netsec_auth_struct *a, int auth_flags, + enum netsec_direction direction, RPC_AUTH_NETSEC_CHK * verf, char *data, size_t data_len) { - uchar dataN[4]; - uchar digest1[16]; - struct MD5Context ctx3; - uchar sess_kf0[16]; - int i; - - SIVAL(dataN, 0, 0); - - for (i = 0; i < sizeof(sess_kf0); i++) { - sess_kf0[i] = a->sess_key[i] ^ 0xf0; + uchar digest_final[16]; + + /* Create the expected sequence number for comparison */ + uchar seq_num[8]; + RSIVAL(seq_num, 0, a->seq_num); + + switch (direction) { + case SENDER_IS_INITIATOR: + SIVAL(seq_num, 4, 0x80); + break; + case SENDER_IS_ACCEPTOR: + SIVAL(seq_num, 4, 0x0); + break; } DEBUG(10,("SCHANNEL: netsec_decode seq_num=%d data_len=%d\n", a->seq_num, data_len)); dump_data_pw("a->sess_key:\n", a->sess_key, sizeof(a->sess_key)); - dump_data_pw("a->seq_num :\n", dataN, sizeof(dataN)); - hmac_md5(a->sess_key, dataN, 0x4, digest1); - dump_data_pw("ctx:\n", digest1, sizeof(digest1)); - - hmac_md5(digest1, verf->data1, 8, digest1); - - dump_data_pw("netsechashkey:\n", digest1, sizeof(digest1)); - dump_data_pw("verf->data3:\n", verf->data3, sizeof(verf->data3)); - netsechash(digest1, verf->data3, 8); - dump_data_pw("verf->data3_dec:\n", verf->data3, sizeof(verf->data3)); - - MD5Init(&ctx3); - MD5Update(&ctx3, dataN, 0x4); - MD5Update(&ctx3, verf->sig, 8); - - dump_data_pw("sess_kf0:\n", sess_kf0, sizeof(sess_kf0)); - hmac_md5(sess_kf0, dataN, 0x4, digest1); - dump_data_pw("digest1 (ebp-8):\n", digest1, sizeof(digest1)); - hmac_md5(digest1, verf->data3, 8, digest1); - dump_data_pw("netsechashkey:\n", digest1, sizeof(digest1)); + dump_data_pw("seq_num:\n", seq_num, sizeof(seq_num)); - dump_data_pw("verf->data8:\n", verf->data8, sizeof(verf->data8)); - netsechash(digest1, verf->data8, 8); - dump_data_pw("verf->data8_dec:\n", verf->data8, sizeof(verf->data8)); - MD5Update(&ctx3, verf->data8, 8); + /* extract the sequence number (key based on supplied packet digest) */ + /* needs to be done before the sealing, as the original version + is used in the sealing stuff... */ + netsec_deal_with_seq_num(a, verf); - dump_data_pw("data :\n", data, data_len); - netsechash(digest1, data, data_len); - dump_data_pw("datadec:\n", data, data_len); + if (memcmp(verf->seq_num, seq_num, sizeof(seq_num))) { + /* don't even bother with the below if the sequence number is out */ + /* The sequence number is MD5'ed with a key based on the whole-packet + digest, as supplied by the client. We check that it's a valid + checksum after the decode, below + */ + return False; + } - MD5Update(&ctx3, data, data_len); - { - uchar digest_tmp[16]; - MD5Final(digest_tmp, &ctx3); - hmac_md5(a->sess_key, digest_tmp, 16, digest1); - dump_data_pw("digest_tmp:\n", digest_tmp, sizeof(digest_tmp)); + if (auth_flags & AUTH_PIPE_SEAL) { + uchar sealing_key[16]; + + /* get the key to extract the data with */ + netsec_get_sealing_key(a, verf, sealing_key); + + /* extract the verification data */ + dump_data_pw("verf->data8:\n", verf->data8, + sizeof(verf->data8)); + netsechash(sealing_key, verf->data8, 8); + + dump_data_pw("verf->data8_dec:\n", verf->data8, + sizeof(verf->data8)); + + /* extract the packet payload */ + dump_data_pw("data :\n", data, data_len); + netsechash(sealing_key, data, data_len); + dump_data_pw("datadec:\n", data, data_len); } - dump_data_pw("digest:\n", digest1, sizeof(digest1)); - dump_data_pw("verf->data1:\n", verf->data1, sizeof(verf->data1)); + /* digest includes 'data' after unsealing */ + netsec_digest(a, auth_flags, verf, data, data_len, digest_final); - return memcmp(digest1, verf->data1, sizeof(verf->data1)) == 0; + dump_data_pw("Calculated digest:\n", digest_final, + sizeof(digest_final)); + dump_data_pw("verf->packet_digest:\n", verf->packet_digest, + sizeof(verf->packet_digest)); + + /* compare - if the client got the same result as us, then + it must know the session key */ + return (memcmp(digest_final, verf->packet_digest, + sizeof(verf->packet_digest)) == 0); } diff --git a/source3/rpc_parse/parse_rpc.c b/source3/rpc_parse/parse_rpc.c index be3a04e31c..34ba62caa9 100644 --- a/source3/rpc_parse/parse_rpc.c +++ b/source3/rpc_parse/parse_rpc.c @@ -602,15 +602,6 @@ BOOL smb_io_rpc_hdr_autha(const char *desc, RPC_HDR_AUTHA *rai, prs_struct *ps, return True; } -/******************************************************************* - Checks an RPC_HDR_AUTH structure. -********************************************************************/ - -BOOL rpc_hdr_auth_chk(RPC_HDR_AUTH *rai) -{ - return (rai->auth_type == NTLMSSP_AUTH_TYPE && rai->auth_level == NTLMSSP_AUTH_LEVEL); -} - /******************************************************************* Inits an RPC_HDR_AUTH structure. ********************************************************************/ @@ -1088,9 +1079,10 @@ BOOL rpc_auth_ntlmssp_chk(RPC_AUTH_NTLMSSP_CHK *chk, uint32 crc32, uint32 seq_nu chk->seq_num != seq_num) { DEBUG(5,("verify failed - crc %x ver %x seq %d\n", - crc32, NTLMSSP_SIGN_VERSION, seq_num)); + chk->crc32, chk->ver, chk->seq_num)); + DEBUG(5,("verify expect - crc %x ver %x seq %d\n", - chk->crc32, chk->ver, chk->seq_num)); + crc32, NTLMSSP_SIGN_VERSION, seq_num)); return False; } return True; @@ -1182,15 +1174,15 @@ creates an RPC_AUTH_NETSEC_CHK structure. ********************************************************************/ BOOL init_rpc_auth_netsec_chk(RPC_AUTH_NETSEC_CHK * chk, const uchar sig[8], - const uchar data1[8], - const uchar data3[8], const uchar data8[8]) + const uchar packet_digest[8], + const uchar seq_num[8], const uchar data8[8]) { if (chk == NULL) return False; memcpy(chk->sig, sig, sizeof(chk->sig)); - memcpy(chk->data1, data1, sizeof(chk->data1)); - memcpy(chk->data3, data3, sizeof(chk->data3)); + memcpy(chk->packet_digest, packet_digest, sizeof(chk->packet_digest)); + memcpy(chk->seq_num, seq_num, sizeof(chk->seq_num)); memcpy(chk->data8, data8, sizeof(chk->data8)); return True; @@ -1209,8 +1201,8 @@ BOOL smb_io_rpc_auth_netsec_chk(const char *desc, RPC_AUTH_NETSEC_CHK * chk, depth++; prs_uint8s(False, "sig ", ps, depth, chk->sig, sizeof(chk->sig)); - prs_uint8s(False, "data3", ps, depth, chk->data3, sizeof(chk->data3)); - prs_uint8s(False, "data1", ps, depth, chk->data1, sizeof(chk->data1)); + prs_uint8s(False, "seq_num", ps, depth, chk->seq_num, sizeof(chk->seq_num)); + prs_uint8s(False, "packet_digest", ps, depth, chk->packet_digest, sizeof(chk->packet_digest)); prs_uint8s(False, "data8", ps, depth, chk->data8, sizeof(chk->data8)); return True; diff --git a/source3/rpc_parse/parse_samr.c b/source3/rpc_parse/parse_samr.c index ac1e9da61b..45c81deb89 100644 --- a/source3/rpc_parse/parse_samr.c +++ b/source3/rpc_parse/parse_samr.c @@ -1500,7 +1500,7 @@ inits a SAM_DISPINFO_1 structure. ********************************************************************/ NTSTATUS init_sam_dispinfo_1(TALLOC_CTX *ctx, SAM_DISPINFO_1 *sam, uint32 num_entries, - uint32 start_idx, DISP_USER_INFO *disp_user_info, + uint32 start_idx, SAM_ACCOUNT *disp_user_info, DOM_SID *domain_sid) { uint32 len_sam_name, len_sam_full, len_sam_desc; @@ -1535,7 +1535,7 @@ NTSTATUS init_sam_dispinfo_1(TALLOC_CTX *ctx, SAM_DISPINFO_1 *sam, uint32 num_en DEBUG(11, ("init_sam_dispinfo_1: entry: %d\n",i)); - pwd=disp_user_info[i+start_idx].sam; + pwd=&disp_user_info[i+start_idx]; username = pdb_get_username(pwd); fullname = pdb_get_fullname(pwd); @@ -1635,7 +1635,7 @@ inits a SAM_DISPINFO_2 structure. ********************************************************************/ NTSTATUS init_sam_dispinfo_2(TALLOC_CTX *ctx, SAM_DISPINFO_2 *sam, uint32 num_entries, - uint32 start_idx, DISP_USER_INFO *disp_user_info, + uint32 start_idx, SAM_ACCOUNT *disp_user_info, DOM_SID *domain_sid ) { uint32 len_sam_name, len_sam_desc; @@ -1666,7 +1666,7 @@ NTSTATUS init_sam_dispinfo_2(TALLOC_CTX *ctx, SAM_DISPINFO_2 *sam, uint32 num_en fstring user_sid_string, domain_sid_string; DEBUG(11, ("init_sam_dispinfo_2: entry: %d\n",i)); - pwd=disp_user_info[i+start_idx].sam; + pwd=&disp_user_info[i+start_idx]; username = pdb_get_username(pwd); acct_desc = pdb_get_acct_desc(pwd); @@ -1754,7 +1754,7 @@ inits a SAM_DISPINFO_3 structure. ********************************************************************/ NTSTATUS init_sam_dispinfo_3(TALLOC_CTX *ctx, SAM_DISPINFO_3 *sam, uint32 num_entries, - uint32 start_idx, DISP_GROUP_INFO *disp_group_info) + uint32 start_idx, DOMAIN_GRP *disp_group_info) { uint32 len_sam_name, len_sam_desc; uint32 i; @@ -1776,7 +1776,7 @@ NTSTATUS init_sam_dispinfo_3(TALLOC_CTX *ctx, SAM_DISPINFO_3 *sam, uint32 num_en ZERO_STRUCTP(sam->str); for (i = 0; i < num_entries; i++) { - DOMAIN_GRP *grp = disp_group_info[i+start_idx].grp; + DOMAIN_GRP *grp = &disp_group_info[i+start_idx]; DEBUG(11, ("init_sam_dispinfo_3: entry: %d\n",i)); @@ -1848,7 +1848,7 @@ inits a SAM_DISPINFO_4 structure. ********************************************************************/ NTSTATUS init_sam_dispinfo_4(TALLOC_CTX *ctx, SAM_DISPINFO_4 *sam, uint32 num_entries, - uint32 start_idx, DISP_USER_INFO *disp_user_info) + uint32 start_idx, SAM_ACCOUNT *disp_user_info) { uint32 len_sam_name; uint32 i; @@ -1872,7 +1872,7 @@ NTSTATUS init_sam_dispinfo_4(TALLOC_CTX *ctx, SAM_DISPINFO_4 *sam, uint32 num_en for (i = 0; i < num_entries; i++) { DEBUG(11, ("init_sam_dispinfo_2: entry: %d\n",i)); - pwd=disp_user_info[i+start_idx].sam; + pwd=&disp_user_info[i+start_idx]; len_sam_name = strlen(pdb_get_username(pwd)); @@ -1939,7 +1939,7 @@ inits a SAM_DISPINFO_5 structure. ********************************************************************/ NTSTATUS init_sam_dispinfo_5(TALLOC_CTX *ctx, SAM_DISPINFO_5 *sam, uint32 num_entries, - uint32 start_idx, DISP_GROUP_INFO *disp_group_info) + uint32 start_idx, DOMAIN_GRP *disp_group_info) { uint32 len_sam_name; uint32 i; @@ -1961,7 +1961,7 @@ NTSTATUS init_sam_dispinfo_5(TALLOC_CTX *ctx, SAM_DISPINFO_5 *sam, uint32 num_en ZERO_STRUCTP(sam->str); for (i = 0; i < num_entries; i++) { - DOMAIN_GRP *grp = disp_group_info[i+start_idx].grp; + DOMAIN_GRP *grp = &disp_group_info[i+start_idx]; DEBUG(11, ("init_sam_dispinfo_5: entry: %d\n",i)); @@ -4598,7 +4598,6 @@ BOOL samr_io_r_query_aliasmem(const char *desc, SAMR_R_QUERY_ALIASMEM * r_u, prs_struct *ps, int depth) { uint32 i; - uint32 ptr_sid[MAX_LOOKUP_SIDS]; if (r_u == NULL) return False; @@ -4614,28 +4613,31 @@ BOOL samr_io_r_query_aliasmem(const char *desc, SAMR_R_QUERY_ALIASMEM * r_u, if(!prs_uint32("ptr", ps, depth, &r_u->ptr)) return False; - if (r_u->ptr != 0) { - SMB_ASSERT_ARRAY(ptr_sid, r_u->num_sids); - - if (r_u->num_sids != 0) { - if(!prs_uint32("num_sids1", ps, depth, &r_u->num_sids1)) - return False; - - for (i = 0; i < r_u->num_sids1; i++) { - ptr_sid[i] = 1; - if(!prs_uint32("ptr_sid", ps, depth, &ptr_sid[i])) - return False; - } + if (r_u->ptr != 0 && r_u->num_sids != 0) { + uint32 *ptr_sid = NULL; - if (UNMARSHALLING(ps)) { - r_u->sid = talloc(ps->mem_ctx, r_u->num_sids1 * sizeof(DOM_SID2)); - } + if(!prs_uint32("num_sids1", ps, depth, &r_u->num_sids1)) + return False; - for (i = 0; i < r_u->num_sids1; i++) { - if (ptr_sid[i] != 0) { - if(!smb_io_dom_sid2("sid", &r_u->sid[i], ps, depth)) - return False; - } + ptr_sid = talloc(ps->mem_ctx, sizeof(uint32) * r_u->num_sids1); + if (!ptr_sid) { + return False; + } + + for (i = 0; i < r_u->num_sids1; i++) { + ptr_sid[i] = 1; + if(!prs_uint32("ptr_sid", ps, depth, &ptr_sid[i])) + return False; + } + + if (UNMARSHALLING(ps)) { + r_u->sid = talloc(ps->mem_ctx, r_u->num_sids1 * sizeof(DOM_SID2)); + } + + for (i = 0; i < r_u->num_sids1; i++) { + if (ptr_sid[i] != 0) { + if(!smb_io_dom_sid2("sid", &r_u->sid[i], ps, depth)) + return False; } } } diff --git a/source3/rpc_parse/parse_sec.c b/source3/rpc_parse/parse_sec.c index 081173cf8d..3848bd7051 100644 --- a/source3/rpc_parse/parse_sec.c +++ b/source3/rpc_parse/parse_sec.c @@ -3,7 +3,7 @@ * Version 1.9. * RPC Pipe client / server routines * Copyright (C) Andrew Tridgell 1992-1998, - * Copyright (C) Jeremy R. Allison 1995-1998 + * Copyright (C) Jeremy R. Allison 1995-2003. * Copyright (C) Luke Kenneth Casson Leighton 1996-1998, * Copyright (C) Paul Ashton 1997-1998. * @@ -48,7 +48,7 @@ BOOL sec_io_access(const char *desc, SEC_ACCESS *t, prs_struct *ps, int depth) prs_debug(ps, depth, desc, "sec_io_access"); depth++; - if(!prs_uint32("mask", ps, depth, &(t->mask))) + if(!prs_uint32("mask", ps, depth, &t->mask)) return False; return True; @@ -579,8 +579,6 @@ SEC_DESC *make_sec_desc(TALLOC_CTX *ctx, uint16 revision, { SEC_DESC *dst; uint32 offset = 0; - uint32 offset_sid = SEC_DESC_HEADER_SIZE; - uint32 offset_acl = 0; *sd_size = 0; @@ -610,58 +608,33 @@ SEC_DESC *make_sec_desc(TALLOC_CTX *ctx, uint16 revision, if(dacl && ((dst->dacl = dup_sec_acl(ctx, dacl)) == NULL)) goto error_exit; - offset = 0; + offset = SEC_DESC_HEADER_SIZE; /* * Work out the linearization sizes. */ - if (dst->owner_sid != NULL) { - - if (offset == 0) - offset = SEC_DESC_HEADER_SIZE; - - offset += sid_size(dst->owner_sid); - } - - if (dst->grp_sid != NULL) { - - if (offset == 0) - offset = SEC_DESC_HEADER_SIZE; - - offset += sid_size(dst->grp_sid); - } if (dst->sacl != NULL) { - - offset_acl = SEC_DESC_HEADER_SIZE; - - dst->off_sacl = offset_acl; - offset_acl += dst->sacl->size; - offset += dst->sacl->size; - offset_sid += dst->sacl->size; + dst->off_sacl = offset; + offset += dst->sacl->size; } if (dst->dacl != NULL) { - - if (offset_acl == 0) - offset_acl = SEC_DESC_HEADER_SIZE; - - dst->off_dacl = offset_acl; - offset_acl += dst->dacl->size; - offset += dst->dacl->size; - offset_sid += dst->dacl->size; + dst->off_dacl = offset; + offset += dst->dacl->size; } - *sd_size = (size_t)((offset == 0) ? SEC_DESC_HEADER_SIZE : offset); + if (dst->owner_sid != NULL) { + dst->off_owner_sid = offset; + offset += sid_size(dst->owner_sid); + } - if (dst->owner_sid != NULL) - dst->off_owner_sid = offset_sid; - - /* sid_size() returns 0 if the sid is NULL so this is ok */ - - if (dst->grp_sid != NULL) - dst->off_grp_sid = offset_sid + sid_size(dst->owner_sid); + if (dst->grp_sid != NULL) { + dst->off_grp_sid = offset; + offset += sid_size(dst->grp_sid); + } + *sd_size = (size_t)offset; return dst; error_exit: @@ -928,7 +901,7 @@ BOOL sec_io_desc_buf(const char *desc, SEC_DESC_BUF **ppsdb, prs_struct *ps, int } /******************************************************************* - adds new SID with its permissions to SEC_DESC + Add a new SID with its permissions to SEC_DESC. ********************************************************************/ NTSTATUS sec_desc_add_sid(TALLOC_CTX *ctx, SEC_DESC **psd, DOM_SID *sid, uint32 mask, size_t *sd_size) @@ -940,7 +913,8 @@ NTSTATUS sec_desc_add_sid(TALLOC_CTX *ctx, SEC_DESC **psd, DOM_SID *sid, uint32 *sd_size = 0; - if (!ctx || !psd || !sid || !sd_size) return NT_STATUS_INVALID_PARAMETER; + if (!ctx || !psd || !sid || !sd_size) + return NT_STATUS_INVALID_PARAMETER; status = sec_ace_add_sid(ctx, &ace, psd[0]->dacl->ace, &psd[0]->dacl->num_aces, sid, mask); @@ -960,14 +934,15 @@ NTSTATUS sec_desc_add_sid(TALLOC_CTX *ctx, SEC_DESC **psd, DOM_SID *sid, uint32 } /******************************************************************* - modify SID's permissions at SEC_DESC + Modify a SID's permissions in a SEC_DESC. ********************************************************************/ NTSTATUS sec_desc_mod_sid(SEC_DESC *sd, DOM_SID *sid, uint32 mask) { NTSTATUS status; - if (!sd || !sid) return NT_STATUS_INVALID_PARAMETER; + if (!sd || !sid) + return NT_STATUS_INVALID_PARAMETER; status = sec_ace_mod_sid(sd->dacl->ace, sd->dacl->num_aces, sid, mask); @@ -978,7 +953,7 @@ NTSTATUS sec_desc_mod_sid(SEC_DESC *sd, DOM_SID *sid, uint32 mask) } /******************************************************************* - delete SID from SEC_DESC + Delete a SID from a SEC_DESC. ********************************************************************/ NTSTATUS sec_desc_del_sid(TALLOC_CTX *ctx, SEC_DESC **psd, DOM_SID *sid, size_t *sd_size) @@ -990,7 +965,8 @@ NTSTATUS sec_desc_del_sid(TALLOC_CTX *ctx, SEC_DESC **psd, DOM_SID *sid, size_t *sd_size = 0; - if (!ctx || !psd[0] || !sid || !sd_size) return NT_STATUS_INVALID_PARAMETER; + if (!ctx || !psd[0] || !sid || !sd_size) + return NT_STATUS_INVALID_PARAMETER; status = sec_ace_del_sid(ctx, &ace, psd[0]->dacl->ace, &psd[0]->dacl->num_aces, sid); @@ -1008,3 +984,108 @@ NTSTATUS sec_desc_del_sid(TALLOC_CTX *ctx, SEC_DESC **psd, DOM_SID *sid, size_t sd = 0; return NT_STATUS_OK; } + +/******************************************************************* + Comparison function to sort non-inherited first. +*******************************************************************/ + +static int nt_ace_inherit_comp( SEC_ACE *a1, SEC_ACE *a2) +{ + int a1_inh = a1->flags & SEC_ACE_FLAG_INHERITED_ACE; + int a2_inh = a2->flags & SEC_ACE_FLAG_INHERITED_ACE; + + if (a1_inh == a2_inh) + return 0; + + if (!a1_inh && a2_inh) + return -1; + return 1; +} + +/******************************************************************* + Comparison function to apply the order explained below in a group. +*******************************************************************/ + +static int nt_ace_canon_comp( SEC_ACE *a1, SEC_ACE *a2) +{ + if ((a1->type == SEC_ACE_TYPE_ACCESS_DENIED) && + (a2->type != SEC_ACE_TYPE_ACCESS_DENIED)) + return -1; + + if ((a2->type == SEC_ACE_TYPE_ACCESS_DENIED) && + (a1->type != SEC_ACE_TYPE_ACCESS_DENIED)) + return 1; + + /* Both access denied or access allowed. */ + + /* 1. ACEs that apply to the object itself */ + + if (!(a1->flags & SEC_ACE_FLAG_INHERIT_ONLY) && + (a2->flags & SEC_ACE_FLAG_INHERIT_ONLY)) + return -1; + else if (!(a2->flags & SEC_ACE_FLAG_INHERIT_ONLY) && + (a1->flags & SEC_ACE_FLAG_INHERIT_ONLY)) + return 1; + + /* 2. ACEs that apply to a subobject of the object, such as + * a property set or property. */ + + if (a1->flags & (SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT) && + !(a2->flags & (SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT))) + return -1; + else if (a2->flags & (SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT) && + !(a1->flags & (SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT))) + return 1; + + return 0; +} + +/******************************************************************* + Functions to convert a SEC_DESC ACE DACL list into canonical order. + JRA. + +--- from http://msdn.microsoft.com/library/default.asp?url=/library/en-us/security/security/order_of_aces_in_a_dacl.asp + +The following describes the preferred order: + + To ensure that noninherited ACEs have precedence over inherited ACEs, + place all noninherited ACEs in a group before any inherited ACEs. + This ordering ensures, for example, that a noninherited access-denied ACE + is enforced regardless of any inherited ACE that allows access. + + Within the groups of noninherited ACEs and inherited ACEs, order ACEs according to ACE type, as the following shows: + 1. Access-denied ACEs that apply to the object itself + 2. Access-denied ACEs that apply to a subobject of the object, such as a property set or property + 3. Access-allowed ACEs that apply to the object itself + 4. Access-allowed ACEs that apply to a subobject of the object" + +********************************************************************/ + +void dacl_sort_into_canonical_order(SEC_ACE *srclist, unsigned int num_aces) +{ + unsigned int i; + + if (!srclist || num_aces == 0) + return; + + /* Sort so that non-inherited ACE's come first. */ + qsort( srclist, num_aces, sizeof(srclist[0]), QSORT_CAST nt_ace_inherit_comp); + + /* Find the boundary between non-inherited ACEs. */ + for (i = 0; i < num_aces; i++ ) { + SEC_ACE *curr_ace = &srclist[i]; + + if (curr_ace->flags & SEC_ACE_FLAG_INHERITED_ACE) + break; + } + + /* i now points at entry number of the first inherited ACE. */ + + /* Sort the non-inherited ACEs. */ + if (i) + qsort( srclist, i, sizeof(srclist[0]), QSORT_CAST nt_ace_canon_comp); + + /* Now sort the inherited ACEs. */ + if (num_aces - i) + qsort( &srclist[i], num_aces - i, sizeof(srclist[0]), QSORT_CAST nt_ace_canon_comp); +} diff --git a/source3/rpc_parse/parse_spoolss.c b/source3/rpc_parse/parse_spoolss.c index a5d2087a3a..1a380c64d5 100644 --- a/source3/rpc_parse/parse_spoolss.c +++ b/source3/rpc_parse/parse_spoolss.c @@ -645,7 +645,7 @@ static BOOL spool_io_user_level(const char *desc, SPOOL_USER_CTR *q_u, prs_struc BOOL spoolss_io_devmode(const char *desc, prs_struct *ps, int depth, DEVICEMODE *devmode) { - uint32 available_space; /* size of the device mode left to parse */ + int available_space; /* size of the device mode left to parse */ /* only important on unmarshalling */ int i = 0; @@ -7296,15 +7296,14 @@ static BOOL spoolss_io_printer_enum_values_ctr(const char *desc, prs_struct *ps, if (!prs_unistr("valuename", ps, depth, &ctr->values[i].valuename)) return False; - if (UNMARSHALLING(ps)) { + if (UNMARSHALLING(ps) && ctr->values[i].data_len) { 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_uint8s(False, "data", ps, depth, ctr->values[i].data, ctr->values[i].data_len)) - return False; if ( !prs_align_uint16(ps) ) return False; diff --git a/source3/rpc_parse/parse_srv.c b/source3/rpc_parse/parse_srv.c index 27763aa224..bbb5193ddc 100644 --- a/source3/rpc_parse/parse_srv.c +++ b/source3/rpc_parse/parse_srv.c @@ -623,7 +623,8 @@ static BOOL srv_io_share_info1005(const char* desc, SRV_SHARE_INFO_1005* sh1005, if(!prs_align(ps)) return False; - if(!prs_uint32("dfs_root_flag", ps, depth, &sh1005->dfs_root_flag)) + if(!prs_uint32("share_info_flags", ps, depth, + &sh1005->share_info_flags)) return False; return True; diff --git a/source3/rpc_server/srv_dfs_nt.c b/source3/rpc_server/srv_dfs_nt.c index da92e5c06b..eba4eaec75 100644 --- a/source3/rpc_server/srv_dfs_nt.c +++ b/source3/rpc_server/srv_dfs_nt.c @@ -135,7 +135,7 @@ WERROR _dfs_remove(pipes_struct *p, DFS_Q_DFS_REMOVE *q_u, pstrcpy(altpath, servername); pstrcat(altpath, "\\"); pstrcat(altpath, sharename); - strlower(altpath); + strlower_m(altpath); } DEBUG(5,("init_reply_dfs_remove: Request to remove %s -> %s\\%s.\n", diff --git a/source3/rpc_server/srv_lsa.c b/source3/rpc_server/srv_lsa.c index 1c4ef6c8e6..679cfb73bb 100644 --- a/source3/rpc_server/srv_lsa.c +++ b/source3/rpc_server/srv_lsa.c @@ -642,176 +642,45 @@ static BOOL api_lsa_query_info2(pipes_struct *p) } - -/*************************************************************************** - api_lsa_enum_acctrights - ***************************************************************************/ -static BOOL api_lsa_enum_acct_rights(pipes_struct *p) -{ - LSA_Q_ENUM_ACCT_RIGHTS q_u; - LSA_R_ENUM_ACCT_RIGHTS r_u; - - prs_struct *data = &p->in_data.data; - prs_struct *rdata = &p->out_data.rdata; - - ZERO_STRUCT(q_u); - ZERO_STRUCT(r_u); - - if(!lsa_io_q_enum_acct_rights("", &q_u, data, 0)) { - DEBUG(0,("api_lsa_enum_acct_rights: failed to unmarshall LSA_Q_ENUM_ACCT_RIGHTS.\n")); - return False; - } - - r_u.status = _lsa_enum_acct_rights(p, &q_u, &r_u); - - /* store the response in the SMB stream */ - if(!lsa_io_r_enum_acct_rights("", &r_u, rdata, 0)) { - DEBUG(0,("api_lsa_enum_acct_rights: Failed to marshall LSA_R_ENUM_ACCT_RIGHTS.\n")); - return False; - } - - return True; -} - - -/*************************************************************************** - api_lsa_enum_acct_with_right - ***************************************************************************/ -static BOOL api_lsa_enum_acct_with_right(pipes_struct *p) -{ - LSA_Q_ENUM_ACCT_WITH_RIGHT q_u; - LSA_R_ENUM_ACCT_WITH_RIGHT r_u; - - prs_struct *data = &p->in_data.data; - prs_struct *rdata = &p->out_data.rdata; - - ZERO_STRUCT(q_u); - ZERO_STRUCT(r_u); - - if(!lsa_io_q_enum_acct_with_right("", &q_u, data, 0)) { - DEBUG(0,("api_lsa_enum_acct_with_right: failed to unmarshall LSA_Q_ENUM_ACCT_WITH_RIGHT.\n")); - return False; - } - - r_u.status = _lsa_enum_acct_with_right(p, &q_u, &r_u); - - /* store the response in the SMB stream */ - if(!lsa_io_r_enum_acct_with_right("", &r_u, rdata, 0)) { - DEBUG(0,("api_lsa_enum_acct_with_right: Failed to marshall LSA_R_ENUM_ACCT_WITH_RIGHT.\n")); - return False; - } - - return True; -} - - -/*************************************************************************** - api_lsa_add_acctrights - ***************************************************************************/ -static BOOL api_lsa_add_acct_rights(pipes_struct *p) -{ - LSA_Q_ADD_ACCT_RIGHTS q_u; - LSA_R_ADD_ACCT_RIGHTS r_u; - - prs_struct *data = &p->in_data.data; - prs_struct *rdata = &p->out_data.rdata; - - ZERO_STRUCT(q_u); - ZERO_STRUCT(r_u); - - if(!lsa_io_q_add_acct_rights("", &q_u, data, 0)) { - DEBUG(0,("api_lsa_add_acct_rights: failed to unmarshall LSA_Q_ADD_ACCT_RIGHTS.\n")); - return False; - } - - r_u.status = _lsa_add_acct_rights(p, &q_u, &r_u); - - /* store the response in the SMB stream */ - if(!lsa_io_r_add_acct_rights("", &r_u, rdata, 0)) { - DEBUG(0,("api_lsa_add_acct_rights: Failed to marshall LSA_R_ADD_ACCT_RIGHTS.\n")); - return False; - } - - return True; -} - - -/*************************************************************************** - api_lsa_remove_acctrights - ***************************************************************************/ -static BOOL api_lsa_remove_acct_rights(pipes_struct *p) -{ - LSA_Q_REMOVE_ACCT_RIGHTS q_u; - LSA_R_REMOVE_ACCT_RIGHTS r_u; - - prs_struct *data = &p->in_data.data; - prs_struct *rdata = &p->out_data.rdata; - - ZERO_STRUCT(q_u); - ZERO_STRUCT(r_u); - - if(!lsa_io_q_remove_acct_rights("", &q_u, data, 0)) { - DEBUG(0,("api_lsa_remove_acct_rights: failed to unmarshall LSA_Q_REMOVE_ACCT_RIGHTS.\n")); - return False; - } - - r_u.status = _lsa_remove_acct_rights(p, &q_u, &r_u); - - /* store the response in the SMB stream */ - if(!lsa_io_r_remove_acct_rights("", &r_u, rdata, 0)) { - DEBUG(0,("api_lsa_remove_acct_rights: Failed to marshall LSA_R_REMOVE_ACCT_RIGHTS.\n")); - return False; - } - - return True; -} - - /*************************************************************************** \PIPE\ntlsa commands ***************************************************************************/ - NTSTATUS rpc_lsa_init(void) { - static const struct api_struct api_lsa_cmds[] = - { - { "LSA_OPENPOLICY2" , LSA_OPENPOLICY2 , api_lsa_open_policy2 }, - { "LSA_OPENPOLICY" , LSA_OPENPOLICY , api_lsa_open_policy }, - { "LSA_QUERYINFOPOLICY" , LSA_QUERYINFOPOLICY , api_lsa_query_info }, - { "LSA_ENUMTRUSTDOM" , LSA_ENUMTRUSTDOM , api_lsa_enum_trust_dom }, - { "LSA_CLOSE" , LSA_CLOSE , api_lsa_close }, - { "LSA_OPENSECRET" , LSA_OPENSECRET , api_lsa_open_secret }, - { "LSA_LOOKUPSIDS" , LSA_LOOKUPSIDS , api_lsa_lookup_sids }, - { "LSA_LOOKUPNAMES" , LSA_LOOKUPNAMES , api_lsa_lookup_names }, - { "LSA_ENUM_PRIVS" , LSA_ENUM_PRIVS , api_lsa_enum_privs }, - { "LSA_PRIV_GET_DISPNAME",LSA_PRIV_GET_DISPNAME,api_lsa_priv_get_dispname}, - { "LSA_ENUM_ACCOUNTS" , LSA_ENUM_ACCOUNTS , api_lsa_enum_accounts }, - { "LSA_UNK_GET_CONNUSER", LSA_UNK_GET_CONNUSER, api_lsa_unk_get_connuser }, - { "LSA_OPENACCOUNT" , LSA_OPENACCOUNT , api_lsa_open_account }, - { "LSA_ENUMPRIVSACCOUNT", LSA_ENUMPRIVSACCOUNT, api_lsa_enum_privsaccount}, - { "LSA_GETSYSTEMACCOUNT", LSA_GETSYSTEMACCOUNT, api_lsa_getsystemaccount }, - { "LSA_SETSYSTEMACCOUNT", LSA_SETSYSTEMACCOUNT, api_lsa_setsystemaccount }, - { "LSA_ADDPRIVS" , LSA_ADDPRIVS , api_lsa_addprivs }, - { "LSA_REMOVEPRIVS" , LSA_REMOVEPRIVS , api_lsa_removeprivs }, - { "LSA_QUERYSECOBJ" , LSA_QUERYSECOBJ , api_lsa_query_secobj }, - { "LSA_ENUMACCTRIGHTS" , LSA_ENUMACCTRIGHTS , api_lsa_enum_acct_rights }, - { "LSA_ENUMACCTWITHRIGHT", LSA_ENUMACCTWITHRIGHT, api_lsa_enum_acct_with_right }, - { "LSA_ADDACCTRIGHTS" , LSA_ADDACCTRIGHTS , api_lsa_add_acct_rights }, - { "LSA_REMOVEACCTRIGHTS", LSA_REMOVEACCTRIGHTS, api_lsa_remove_acct_rights}, - /* be careful of the adding of new RPC's. See commentrs below about - * ADS DC capabilities */ - { "LSA_QUERYINFO2" , LSA_QUERYINFO2 , api_lsa_query_info2 }, - }; - +static const struct api_struct api_lsa_cmds[] = +{ + { "LSA_OPENPOLICY2" , LSA_OPENPOLICY2 , api_lsa_open_policy2 }, + { "LSA_OPENPOLICY" , LSA_OPENPOLICY , api_lsa_open_policy }, + { "LSA_QUERYINFOPOLICY" , LSA_QUERYINFOPOLICY , api_lsa_query_info }, + { "LSA_ENUMTRUSTDOM" , LSA_ENUMTRUSTDOM , api_lsa_enum_trust_dom }, + { "LSA_CLOSE" , LSA_CLOSE , api_lsa_close }, + { "LSA_OPENSECRET" , LSA_OPENSECRET , api_lsa_open_secret }, + { "LSA_LOOKUPSIDS" , LSA_LOOKUPSIDS , api_lsa_lookup_sids }, + { "LSA_LOOKUPNAMES" , LSA_LOOKUPNAMES , api_lsa_lookup_names }, + { "LSA_ENUM_PRIVS" , LSA_ENUM_PRIVS , api_lsa_enum_privs }, + { "LSA_PRIV_GET_DISPNAME",LSA_PRIV_GET_DISPNAME,api_lsa_priv_get_dispname}, + { "LSA_ENUM_ACCOUNTS" , LSA_ENUM_ACCOUNTS , api_lsa_enum_accounts }, + { "LSA_UNK_GET_CONNUSER", LSA_UNK_GET_CONNUSER, api_lsa_unk_get_connuser }, + { "LSA_OPENACCOUNT" , LSA_OPENACCOUNT , api_lsa_open_account }, + { "LSA_ENUMPRIVSACCOUNT", LSA_ENUMPRIVSACCOUNT, api_lsa_enum_privsaccount}, + { "LSA_GETSYSTEMACCOUNT", LSA_GETSYSTEMACCOUNT, api_lsa_getsystemaccount }, + { "LSA_SETSYSTEMACCOUNT", LSA_SETSYSTEMACCOUNT, api_lsa_setsystemaccount }, + { "LSA_ADDPRIVS" , LSA_ADDPRIVS , api_lsa_addprivs }, + { "LSA_REMOVEPRIVS" , LSA_REMOVEPRIVS , api_lsa_removeprivs }, + { "LSA_QUERYSECOBJ" , LSA_QUERYSECOBJ , api_lsa_query_secobj }, + /* be careful of the adding of new RPC's. See commentrs below about + ADS DC capabilities */ + { "LSA_QUERYINFO2" , LSA_QUERYINFO2 , api_lsa_query_info2 } +}; /* * NOTE: Certain calls can not be enabled if we aren't an ADS DC. Make sure * these calls are always last and that you decrement by the amount of calls * to disable. - */ + */ int funcs = sizeof(api_lsa_cmds) / sizeof(struct api_struct); if (!(SEC_ADS == lp_security() && ROLE_DOMAIN_PDC == lp_server_role())) { - funcs -= 1; + funcs -= 1; } return rpc_pipe_register_commands(SMB_RPC_INTERFACE_VERSION, "lsarpc", "lsass", api_lsa_cmds, diff --git a/source3/rpc_server/srv_lsa_nt.c b/source3/rpc_server/srv_lsa_nt.c index 3581be0181..ca3021a876 100644 --- a/source3/rpc_server/srv_lsa_nt.c +++ b/source3/rpc_server/srv_lsa_nt.c @@ -403,8 +403,16 @@ NTSTATUS _lsa_open_policy2(pipes_struct *p, LSA_Q_OPEN_POL2 *q_u, LSA_R_OPEN_POL /* get the generic lsa policy SD until we store it */ lsa_get_generic_sd(p->mem_ctx, &psd, &sd_size); - if(!se_access_check(psd, p->pipe_user.nt_user_token, des_access, &acc_granted, &status)) - return status; + if(!se_access_check(psd, p->pipe_user.nt_user_token, des_access, &acc_granted, &status)) { + if (geteuid() != 0) { + return status; + } + DEBUG(4,("ACCESS should be DENIED (granted: %#010x; required: %#010x)\n", + acc_granted, des_access)); + DEBUGADD(4,("but overwritten by euid == 0\n")); + acc_granted = des_access; + } + /* associate the domain SID with the (unique) handle. */ if ((info = (struct lsa_info *)malloc(sizeof(struct lsa_info))) == NULL) @@ -441,8 +449,15 @@ NTSTATUS _lsa_open_policy(pipes_struct *p, LSA_Q_OPEN_POL *q_u, LSA_R_OPEN_POL * /* get the generic lsa policy SD until we store it */ lsa_get_generic_sd(p->mem_ctx, &psd, &sd_size); - if(!se_access_check(psd, p->pipe_user.nt_user_token, des_access, &acc_granted, &status)) - return status; + if(!se_access_check(psd, p->pipe_user.nt_user_token, des_access, &acc_granted, &status)) { + if (geteuid() != 0) { + return status; + } + DEBUG(4,("ACCESS should be DENIED (granted: %#010x; required: %#010x)\n", + acc_granted, des_access)); + DEBUGADD(4,("but overwritten by euid == 0\n")); + acc_granted = des_access; + } /* associate the domain SID with the (unique) handle. */ if ((info = (struct lsa_info *)malloc(sizeof(struct lsa_info))) == NULL) @@ -547,7 +562,7 @@ NTSTATUS _lsa_query_info(pipes_struct *p, LSA_Q_QUERY_INFO *q_u, LSA_R_QUERY_INF switch (lp_server_role()) { case ROLE_DOMAIN_PDC: case ROLE_DOMAIN_BDC: - name = lp_workgroup(); + name = get_global_sam_name(); sid = get_global_sam_sid(); break; case ROLE_DOMAIN_MEMBER: @@ -573,23 +588,8 @@ NTSTATUS _lsa_query_info(pipes_struct *p, LSA_Q_QUERY_INFO *q_u, LSA_R_QUERY_INF return NT_STATUS_ACCESS_DENIED; /* Request PolicyAccountDomainInformation. */ - switch (lp_server_role()) { - case ROLE_DOMAIN_PDC: - case ROLE_DOMAIN_BDC: - name = lp_workgroup(); - sid = get_global_sam_sid(); - break; - case ROLE_DOMAIN_MEMBER: - name = global_myname(); - sid = get_global_sam_sid(); - break; - case ROLE_STANDALONE: - name = global_myname(); - sid = get_global_sam_sid(); - break; - default: - return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; - } + name = get_global_sam_name(); + sid = get_global_sam_sid(); init_dom_query(&r_u->dom.id5, name, sid); break; case 0x06: @@ -645,7 +645,7 @@ NTSTATUS _lsa_lookup_sids(pipes_struct *p, LSA_Q_LOOKUP_SIDS *q_u, LSA_R_LOOKUP_ num_entries = MAX_LOOKUP_SIDS; DEBUG(5,("_lsa_lookup_sids: truncating SID lookup list to %d\n", num_entries)); } - + ref = (DOM_R_REF *)talloc_zero(p->mem_ctx, sizeof(DOM_R_REF)); names = (LSA_TRANS_NAME_ENUM *)talloc_zero(p->mem_ctx, sizeof(LSA_TRANS_NAME_ENUM)); @@ -859,7 +859,7 @@ NTSTATUS _lsa_enum_accounts(pipes_struct *p, LSA_Q_ENUM_ACCOUNTS *q_u, LSA_R_ENU return NT_STATUS_ACCESS_DENIED; /* get the list of mapped groups (domain, local, builtin) */ - if(!pdb_enum_group_mapping(SID_NAME_UNKNOWN, &map, &num_entries, ENUM_ONLY_MAPPED, MAPPING_WITHOUT_PRIV)) + if(!pdb_enum_group_mapping(SID_NAME_UNKNOWN, &map, &num_entries, ENUM_ONLY_MAPPED)) return NT_STATUS_OK; if (q_u->enum_context >= num_entries) @@ -964,8 +964,6 @@ NTSTATUS _lsa_enum_privsaccount(pipes_struct *p, LSA_Q_ENUMPRIVSACCOUNT *q_u, LS { struct lsa_info *info=NULL; GROUP_MAP map; - int i=0; - LUID_ATTR *set=NULL; r_u->status = NT_STATUS_OK; @@ -974,9 +972,10 @@ NTSTATUS _lsa_enum_privsaccount(pipes_struct *p, LSA_Q_ENUMPRIVSACCOUNT *q_u, LS if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info)) return NT_STATUS_INVALID_HANDLE; - if (!pdb_getgrsid(&map, info->sid, MAPPING_WITH_PRIV)) + if (!pdb_getgrsid(&map, info->sid)) return NT_STATUS_NO_SUCH_GROUP; +#if 0 /* privileges currently not implemented! */ DEBUG(10,("_lsa_enum_privsaccount: %d privileges\n", map.priv_set.count)); if (map.priv_set.count!=0) { @@ -997,6 +996,9 @@ NTSTATUS _lsa_enum_privsaccount(pipes_struct *p, LSA_Q_ENUMPRIVSACCOUNT *q_u, LS init_lsa_r_enum_privsaccount(r_u, set, map.priv_set.count, 0); free_privilege(&map.priv_set); +#endif + + init_lsa_r_enum_privsaccount(r_u, set, 0, 0); return r_u->status; } @@ -1015,7 +1017,7 @@ NTSTATUS _lsa_getsystemaccount(pipes_struct *p, LSA_Q_GETSYSTEMACCOUNT *q_u, LSA if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info)) return NT_STATUS_INVALID_HANDLE; - if (!pdb_getgrsid(&map, info->sid, MAPPING_WITHOUT_PRIV)) + if (!pdb_getgrsid(&map, info->sid)) return NT_STATUS_NO_SUCH_GROUP; /* @@ -1027,7 +1029,7 @@ NTSTATUS _lsa_getsystemaccount(pipes_struct *p, LSA_Q_GETSYSTEMACCOUNT *q_u, LSA they can be ORed together */ - r_u->access=map.systemaccount; + r_u->access = PR_LOG_ON_LOCALLY | PR_ACCESS_FROM_NETWORK; return r_u->status; } @@ -1046,16 +1048,12 @@ NTSTATUS _lsa_setsystemaccount(pipes_struct *p, LSA_Q_SETSYSTEMACCOUNT *q_u, LSA if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info)) return NT_STATUS_INVALID_HANDLE; - if (!pdb_getgrsid(&map, info->sid, MAPPING_WITH_PRIV)) + if (!pdb_getgrsid(&map, info->sid)) return NT_STATUS_NO_SUCH_GROUP; - map.systemaccount=q_u->access; - if(!pdb_update_group_mapping_entry(&map)) return NT_STATUS_NO_SUCH_GROUP; - free_privilege(&map.priv_set); - return r_u->status; } @@ -1065,20 +1063,22 @@ NTSTATUS _lsa_setsystemaccount(pipes_struct *p, LSA_Q_SETSYSTEMACCOUNT *q_u, LSA NTSTATUS _lsa_addprivs(pipes_struct *p, LSA_Q_ADDPRIVS *q_u, LSA_R_ADDPRIVS *r_u) { +#if 0 struct lsa_info *info=NULL; GROUP_MAP map; int i=0; - LUID_ATTR *luid_attr=NULL; PRIVILEGE_SET *set=NULL; +#endif r_u->status = NT_STATUS_OK; +#if 0 /* privileges are not implemented */ /* find the connection policy handle. */ if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info)) return NT_STATUS_INVALID_HANDLE; - if (!pdb_getgrsid(&map, info->sid, MAPPING_WITH_PRIV)) + if (!pdb_getgrsid(&map, info->sid)) return NT_STATUS_NO_SUCH_GROUP; set=&q_u->set; @@ -1100,6 +1100,7 @@ NTSTATUS _lsa_addprivs(pipes_struct *p, LSA_Q_ADDPRIVS *q_u, LSA_R_ADDPRIVS *r_u free_privilege(&map.priv_set); +#endif return r_u->status; } @@ -1109,20 +1110,22 @@ NTSTATUS _lsa_addprivs(pipes_struct *p, LSA_Q_ADDPRIVS *q_u, LSA_R_ADDPRIVS *r_u NTSTATUS _lsa_removeprivs(pipes_struct *p, LSA_Q_REMOVEPRIVS *q_u, LSA_R_REMOVEPRIVS *r_u) { +#if 0 struct lsa_info *info=NULL; GROUP_MAP map; int i=0; - LUID_ATTR *luid_attr=NULL; PRIVILEGE_SET *set=NULL; +#endif r_u->status = NT_STATUS_OK; +#if 0 /* privileges are not implemented */ /* find the connection policy handle. */ if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info)) return NT_STATUS_INVALID_HANDLE; - if (!pdb_getgrsid(&map, info->sid, MAPPING_WITH_PRIV)) + if (!pdb_getgrsid(&map, info->sid)) return NT_STATUS_NO_SUCH_GROUP; if (q_u->allrights!=0) { @@ -1156,7 +1159,7 @@ NTSTATUS _lsa_removeprivs(pipes_struct *p, LSA_Q_REMOVEPRIVS *q_u, LSA_R_REMOVEP return NT_STATUS_NO_SUCH_GROUP; free_privilege(&map.priv_set); - +#endif return r_u->status; } @@ -1240,13 +1243,13 @@ NTSTATUS _lsa_query_info2(pipes_struct *p, LSA_Q_QUERY_INFO2 *q_u, LSA_R_QUERY_I switch (lp_server_role()) { case ROLE_DOMAIN_PDC: case ROLE_DOMAIN_BDC: - nb_name = lp_workgroup(); + nb_name = get_global_sam_name(); /* ugly temp hack for these next two */ /* This should be a 'netbios domain -> DNS domain' mapping */ dnsdomname[0] = '\0'; get_mydomname(dnsdomname); - strlower(dnsdomname); + strlower_m(dnsdomname); dns_name = dnsdomname; forest_name = dnsdomname; @@ -1273,140 +1276,3 @@ NTSTATUS _lsa_query_info2(pipes_struct *p, LSA_Q_QUERY_INFO2 *q_u, LSA_R_QUERY_I return r_u->status; } - - -/*************************************************************************** - For a given SID, enumerate all the privilege this account has. - ***************************************************************************/ -NTSTATUS _lsa_enum_acct_rights(pipes_struct *p, LSA_Q_ENUM_ACCT_RIGHTS *q_u, LSA_R_ENUM_ACCT_RIGHTS *r_u) -{ - struct lsa_info *info=NULL; - char **rights = NULL; - int num_rights = 0; - int i; - - r_u->status = NT_STATUS_OK; - - /* find the connection policy handle. */ - if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info)) - return NT_STATUS_INVALID_HANDLE; - - r_u->status = privilege_enum_account_rights(&q_u->sid.sid, &num_rights, &rights); - - init_r_enum_acct_rights(r_u, num_rights, (const char **)rights); - - for (i=0;istatus; -} - -/*************************************************************************** -return a list of SIDs for a particular privilege - ***************************************************************************/ -NTSTATUS _lsa_enum_acct_with_right(pipes_struct *p, - LSA_Q_ENUM_ACCT_WITH_RIGHT *q_u, - LSA_R_ENUM_ACCT_WITH_RIGHT *r_u) -{ - struct lsa_info *info=NULL; - char *right; - DOM_SID *sids = NULL; - uint32 count = 0; - - r_u->status = NT_STATUS_OK; - - /* find the connection policy handle. */ - if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info)) - return NT_STATUS_INVALID_HANDLE; - - right = unistr2_tdup(p->mem_ctx, &q_u->right); - - DEBUG(5,("lsa_enum_acct_with_right on right %s\n", right)); - - r_u->status = privilege_enum_account_with_right(right, &count, &sids); - - init_r_enum_acct_with_right(r_u, count, sids); - - safe_free(sids); - - return r_u->status; -} - -/*************************************************************************** - add privileges to a acct by SID - ***************************************************************************/ -NTSTATUS _lsa_add_acct_rights(pipes_struct *p, LSA_Q_ADD_ACCT_RIGHTS *q_u, LSA_R_ADD_ACCT_RIGHTS *r_u) -{ - struct lsa_info *info=NULL; - int i; - - r_u->status = NT_STATUS_OK; - - /* find the connection policy handle. */ - if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info)) - return NT_STATUS_INVALID_HANDLE; - - DEBUG(5,("_lsa_add_acct_rights to %s (%d rights)\n", - sid_string_static(&q_u->sid.sid), q_u->rights.count)); - - for (i=0;irights.count;i++) { - DEBUG(5,("\t%s\n", unistr2_static(&q_u->rights.strings[i].string))); - } - - - for (i=0;irights.count;i++) { - r_u->status = privilege_add_account_right(unistr2_static(&q_u->rights.strings[i].string), - &q_u->sid.sid); - if (!NT_STATUS_IS_OK(r_u->status)) { - DEBUG(2,("Failed to add right '%s'\n", - unistr2_static(&q_u->rights.strings[i].string))); - break; - } - } - - init_r_add_acct_rights(r_u); - - return r_u->status; -} - - -/*************************************************************************** - remove privileges from a acct by SID - ***************************************************************************/ -NTSTATUS _lsa_remove_acct_rights(pipes_struct *p, LSA_Q_REMOVE_ACCT_RIGHTS *q_u, LSA_R_REMOVE_ACCT_RIGHTS *r_u) -{ - struct lsa_info *info=NULL; - int i; - - r_u->status = NT_STATUS_OK; - - /* find the connection policy handle. */ - if (!find_policy_by_hnd(p, &q_u->pol, (void **)&info)) - return NT_STATUS_INVALID_HANDLE; - - - DEBUG(5,("_lsa_remove_acct_rights from %s all=%d (%d rights)\n", - sid_string_static(&q_u->sid.sid), - q_u->removeall, - q_u->rights.count)); - - for (i=0;irights.count;i++) { - DEBUG(5,("\t%s\n", unistr2_static(&q_u->rights.strings[i].string))); - } - - for (i=0;irights.count;i++) { - r_u->status = privilege_remove_account_right(unistr2_static(&q_u->rights.strings[i].string), - &q_u->sid.sid); - if (!NT_STATUS_IS_OK(r_u->status)) { - DEBUG(2,("Failed to remove right '%s'\n", - unistr2_static(&q_u->rights.strings[i].string))); - break; - } - } - - init_r_remove_acct_rights(r_u); - - return r_u->status; -} diff --git a/source3/rpc_server/srv_netlog_nt.c b/source3/rpc_server/srv_netlog_nt.c index aa573b8154..c4a87d2e26 100644 --- a/source3/rpc_server/srv_netlog_nt.c +++ b/source3/rpc_server/srv_netlog_nt.c @@ -524,6 +524,7 @@ NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON * auth_serversupplied_info *server_info = NULL; extern userdom_struct current_user_info; SAM_ACCOUNT *sampw; + struct auth_context *auth_context = NULL; usr_info = (NET_USER_INFO_3 *)talloc(p->mem_ctx, sizeof(NET_USER_INFO_3)); if (!usr_info) @@ -598,10 +599,11 @@ NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON * DEBUG(5,("Attempting validation level %d for unmapped username %s.\n", q_u->sam_id.ctr->switch_value, nt_username)); + status = NT_STATUS_OK; + switch (ctr->switch_value) { case NET_LOGON_TYPE: { - struct auth_context *auth_context = NULL; if (!NT_STATUS_IS_OK(status = make_auth_context_fixed(&auth_context, ctr->auth.id2.lm_chal))) { return status; } @@ -615,11 +617,7 @@ NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON * ctr->auth.id2.nt_chal_resp.buffer, ctr->auth.id2.nt_chal_resp.str_str_len)) { status = NT_STATUS_NO_MEMORY; - } else { - status = auth_context->check_ntlm_password(auth_context, user_info, &server_info); - } - (auth_context->free)(&auth_context); - + } break; } case INTERACTIVE_LOGON_TYPE: @@ -628,8 +626,8 @@ NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON * convert this to chellange/responce for the auth subsystem to chew on */ { - struct auth_context *auth_context = NULL; const uint8 *chal; + if (!NT_STATUS_IS_OK(status = make_auth_context_subsystem(&auth_context))) { return status; } @@ -643,12 +641,7 @@ NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON * ctr->auth.id1.nt_owf.data, p->dc.sess_key)) { status = NT_STATUS_NO_MEMORY; - } else { - status = auth_context->check_ntlm_password(auth_context, user_info, &server_info); } - - (auth_context->free)(&auth_context); - break; } default: @@ -656,6 +649,12 @@ NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON * return NT_STATUS_INVALID_INFO_CLASS; } /* end switch */ + if ( NT_STATUS_IS_OK(status) ) { + status = auth_context->check_ntlm_password(auth_context, + user_info, &server_info); + } + + (auth_context->free)(&auth_context); free_user_info(&user_info); DEBUG(5, ("_net_sam_logon: check_password returned status %s\n", @@ -731,8 +730,7 @@ NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON * init_net_user_info3(p->mem_ctx, usr_info, user_rid, - group_rid, - + group_rid, pdb_get_username(sampw), pdb_get_fullname(sampw), pdb_get_homedir(sampw), diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c index 6a9e591f64..9a63ebc7a3 100644 --- a/source3/rpc_server/srv_pipe.c +++ b/source3/rpc_server/srv_pipe.c @@ -227,7 +227,7 @@ BOOL create_next_pdu(pipes_struct *p) if (auth_seal || auth_verify) { RPC_HDR_AUTH auth_info; - init_rpc_hdr_auth(&auth_info, NTLMSSP_AUTH_TYPE, NTLMSSP_AUTH_LEVEL, + init_rpc_hdr_auth(&auth_info, NTLMSSP_AUTH_TYPE, RPC_PIPE_AUTH_SEAL_LEVEL, (auth_verify ? RPC_HDR_AUTH_LEN : 0), (auth_verify ? 1 : 0)); if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, &outgoing_pdu, 0)) { DEBUG(0,("create_next_pdu: failed to marshall RPC_HDR_AUTH.\n")); @@ -263,11 +263,9 @@ BOOL create_next_pdu(pipes_struct *p) prs_struct rverf; prs_struct rauth; - uchar sign[8]; - data = prs_data_p(&outgoing_pdu) + data_pos; - init_rpc_hdr_auth(&auth_info, NETSEC_AUTH_TYPE, NETSEC_AUTH_LEVEL, + init_rpc_hdr_auth(&auth_info, NETSEC_AUTH_TYPE, RPC_PIPE_AUTH_SEAL_LEVEL, RPC_HDR_AUTH_LEN, 1); if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, &outgoing_pdu, 0)) { @@ -284,12 +282,12 @@ BOOL create_next_pdu(pipes_struct *p) p->netsec_auth.seq_num)); } - RSIVAL(sign, 0, p->netsec_auth.seq_num); - SIVAL(sign, 4, 0); - - init_rpc_auth_netsec_chk(&verf, netsec_sig, nullbytes, sign, nullbytes); + init_rpc_auth_netsec_chk(&verf, netsec_sig, nullbytes, nullbytes, nullbytes); - netsec_encode(&p->netsec_auth, &verf, data, data_len); + netsec_encode(&p->netsec_auth, + AUTH_PIPE_NETSEC|AUTH_PIPE_SIGN|AUTH_PIPE_SEAL, + SENDER_IS_ACCEPTOR, + &verf, data, data_len); smb_io_rpc_auth_netsec_chk("", &verf, &outgoing_pdu, 0); @@ -458,13 +456,17 @@ failed authentication on named pipe %s.\n", domain, user_name, wks, p->name )); p->ntlmssp_hash[256] = 0; p->ntlmssp_hash[257] = 0; } + + dump_data_pw("NTLMSSP hash (v1)\n", p->ntlmssp_hash, + sizeof(p->ntlmssp_hash)); + /* NTLMSSPhash(p->ntlmssp_hash, p24); */ p->ntlmssp_seq_num = 0; } fstrcpy(p->user_name, user_name); - fstrcpy(p->pipe_user_name, pdb_get_username(server_info->sam_account)); + fstrcpy(p->pipe_user_name, server_info->unix_name); fstrcpy(p->domain, domain); fstrcpy(p->wks, wks); @@ -546,7 +548,7 @@ BOOL api_pipe_bind_auth_resp(pipes_struct *p, prs_struct *rpc_in_p) return False; } - if (autha_info.auth_type != NTLMSSP_AUTH_TYPE || autha_info.auth_level != NTLMSSP_AUTH_LEVEL) { + if (autha_info.auth_type != NTLMSSP_AUTH_TYPE || autha_info.auth_level != RPC_PIPE_AUTH_SEAL_LEVEL) { DEBUG(0,("api_pipe_bind_auth_resp: incorrect auth type (%d) or level (%d).\n", (int)autha_info.auth_type, (int)autha_info.auth_level )); return False; @@ -1070,7 +1072,7 @@ BOOL api_pipe_bind_req(pipes_struct *p, prs_struct *rpc_in_p) /*** Authentication info ***/ - init_rpc_hdr_auth(&auth_info, NTLMSSP_AUTH_TYPE, NTLMSSP_AUTH_LEVEL, RPC_HDR_AUTH_LEN, 1); + init_rpc_hdr_auth(&auth_info, NTLMSSP_AUTH_TYPE, RPC_PIPE_AUTH_SEAL_LEVEL, RPC_HDR_AUTH_LEN, 1); if(!smb_io_rpc_hdr_auth("", &auth_info, &out_auth, 0)) { DEBUG(0,("api_pipe_bind_req: marshalling of RPC_HDR_AUTH failed.\n")); goto err_exit; @@ -1105,7 +1107,7 @@ BOOL api_pipe_bind_req(pipes_struct *p, prs_struct *rpc_in_p) re-used from the auth2 the client did before. */ p->dc = last_dcinfo; - init_rpc_hdr_auth(&auth_info, NETSEC_AUTH_TYPE, NETSEC_AUTH_LEVEL, RPC_HDR_AUTH_LEN, 1); + init_rpc_hdr_auth(&auth_info, NETSEC_AUTH_TYPE, RPC_PIPE_AUTH_SEAL_LEVEL, RPC_HDR_AUTH_LEN, 1); if(!smb_io_rpc_hdr_auth("", &auth_info, &out_auth, 0)) { DEBUG(0,("api_pipe_bind_req: marshalling of RPC_HDR_AUTH failed.\n")); goto err_exit; @@ -1226,7 +1228,14 @@ BOOL api_pipe_auth_process(pipes_struct *p, prs_struct *rpc_in) * has already been consumed. */ char *data = prs_data_p(rpc_in) + RPC_HDR_REQ_LEN; + dump_data_pw("NTLMSSP hash (v1)\n", p->ntlmssp_hash, + sizeof(p->ntlmssp_hash)); + + dump_data_pw("Incoming RPC PDU (NTLMSSP sealed)\n", + data, data_len); NTLMSSPcalc_p(p, (uchar*)data, data_len); + dump_data_pw("Incoming RPC PDU (NTLMSSP unsealed)\n", + data, data_len); crc32 = crc32_calc_buffer(data, data_len); } @@ -1335,7 +1344,7 @@ BOOL api_pipe_netsec_process(pipes_struct *p, prs_struct *rpc_in) } if ((auth_info.auth_type != NETSEC_AUTH_TYPE) || - (auth_info.auth_level != NETSEC_AUTH_LEVEL)) { + (auth_info.auth_level != RPC_PIPE_AUTH_SEAL_LEVEL)) { DEBUG(0,("Invalid auth info %d or level %d on schannel\n", auth_info.auth_type, auth_info.auth_level)); return False; @@ -1346,7 +1355,10 @@ BOOL api_pipe_netsec_process(pipes_struct *p, prs_struct *rpc_in) return False; } - if (!netsec_decode(&p->netsec_auth, &netsec_chk, + if (!netsec_decode(&p->netsec_auth, + AUTH_PIPE_NETSEC|AUTH_PIPE_SIGN|AUTH_PIPE_SEAL, + SENDER_IS_INITIATOR, + &netsec_chk, prs_data_p(rpc_in)+old_offset, data_len)) { DEBUG(0,("failed to decode PDU\n")); return False; diff --git a/source3/rpc_server/srv_samr_nt.c b/source3/rpc_server/srv_samr_nt.c index fc29df3976..9324fd4765 100644 --- a/source3/rpc_server/srv_samr_nt.c +++ b/source3/rpc_server/srv_samr_nt.c @@ -44,10 +44,10 @@ extern rid_name builtin_alias_rids[]; typedef struct _disp_info { BOOL user_dbloaded; uint32 num_user_account; - DISP_USER_INFO *disp_user_info; + SAM_ACCOUNT *disp_user_info; BOOL group_dbloaded; uint32 num_group_account; - DISP_GROUP_INFO *disp_group_info; + DOMAIN_GRP *disp_group_info; } DISP_INFO; struct samr_info { @@ -151,28 +151,29 @@ 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_users(struct samr_info *info) { int i; if (info->disp_info.user_dbloaded){ for (i=0; idisp_info.num_user_account; i++) { + SAM_ACCOUNT *sam = &info->disp_info.disp_user_info[i]; /* Not really a free, actually a 'clear' */ - pdb_free_sam(&info->disp_info.disp_user_info[i].sam); + pdb_free_sam(&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 */ @@ -183,7 +184,6 @@ static void free_samr_db(struct samr_info *info) info->disp_info.num_group_account=0; } - static void free_samr_info(void *ptr) { struct samr_info *info=(struct samr_info *) ptr; @@ -212,7 +212,7 @@ static void samr_clear_sam_passwd(SAM_ACCOUNT *sam_pass) 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; + SAM_ACCOUNT *pwd_array = NULL; NTSTATUS nt_status = NT_STATUS_OK; TALLOC_CTX *mem_ctx = info->mem_ctx; @@ -255,8 +255,8 @@ static NTSTATUS load_sampwd_entries(struct samr_info *info, uint16 acb_mask, BOO if (info->disp_info.num_user_account % MAX_SAM_ENTRIES == 0) { DEBUG(10,("load_sampwd_entries: allocating more memory\n")); - pwd_array=(DISP_USER_INFO *)talloc_realloc(mem_ctx, info->disp_info.disp_user_info, - (info->disp_info.num_user_account+MAX_SAM_ENTRIES)*sizeof(DISP_USER_INFO)); + pwd_array=(SAM_ACCOUNT *)talloc_realloc(mem_ctx, info->disp_info.disp_user_info, + (info->disp_info.num_user_account+MAX_SAM_ENTRIES)*sizeof(SAM_ACCOUNT)); if (pwd_array==NULL) return NT_STATUS_NO_MEMORY; @@ -264,8 +264,8 @@ static NTSTATUS load_sampwd_entries(struct samr_info *info, uint16 acb_mask, BOO info->disp_info.disp_user_info=pwd_array; } - /* link the SAM_ACCOUNT to the array */ - info->disp_info.disp_user_info[info->disp_info.num_user_account].sam=pwd; + /* Copy the SAM_ACCOUNT into the array */ + info->disp_info.disp_user_info[info->disp_info.num_user_account]=*pwd; DEBUG(10,("load_sampwd_entries: entry: %d\n", info->disp_info.num_user_account)); @@ -288,7 +288,7 @@ static NTSTATUS load_sampwd_entries(struct samr_info *info, uint16 acb_mask, BOO static NTSTATUS load_group_domain_entries(struct samr_info *info, DOM_SID *sid) { GROUP_MAP *map=NULL; - DISP_GROUP_INFO *grp_array = NULL; + DOMAIN_GRP *grp_array = NULL; uint32 group_entries = 0; uint32 i; TALLOC_CTX *mem_ctx = info->mem_ctx; @@ -304,7 +304,7 @@ static NTSTATUS load_group_domain_entries(struct samr_info *info, DOM_SID *sid) become_root(); - if (!pdb_enum_group_mapping(SID_NAME_DOM_GRP, &map, (int *)&group_entries, ENUM_ONLY_MAPPED, MAPPING_WITHOUT_PRIV)) { + if (!pdb_enum_group_mapping(SID_NAME_DOM_GRP, &map, (int *)&group_entries, ENUM_ONLY_MAPPED)) { DEBUG(1, ("load_group_domain_entries: pdb_enum_group_mapping() failed!\n")); return NT_STATUS_NO_MEMORY; } @@ -313,8 +313,7 @@ static NTSTATUS load_group_domain_entries(struct samr_info *info, DOM_SID *sid) info->disp_info.num_group_account=group_entries; - grp_array=(DISP_GROUP_INFO *)talloc(mem_ctx, info->disp_info.num_group_account*sizeof(DISP_GROUP_INFO)); - + grp_array=(DOMAIN_GRP *)talloc(mem_ctx, info->disp_info.num_group_account*sizeof(DOMAIN_GRP)); if (group_entries!=0 && grp_array==NULL) { DEBUG(1, ("load_group_domain_entries: talloc() failed for grp_array!\n")); SAFE_FREE(map); @@ -324,13 +323,10 @@ static NTSTATUS load_group_domain_entries(struct samr_info *info, DOM_SID *sid) info->disp_info.disp_group_info=grp_array; for (i=0; iname, map[i].nt_name); - fstrcpy(grp_array[i].grp->comment, map[i].comment); - sid_split_rid(&map[i].sid, &grp_array[i].grp->rid); - grp_array[i].grp->attr=SID_NAME_DOM_GRP; + fstrcpy(grp_array[i].name, map[i].nt_name); + fstrcpy(grp_array[i].comment, map[i].comment); + sid_split_rid(&map[i].sid, &grp_array[i].rid); + grp_array[i].attr=SID_NAME_DOM_GRP; } SAFE_FREE(map); @@ -691,7 +687,7 @@ makes a SAM_ENTRY / UNISTR2* structure from a user list. ********************************************************************/ static NTSTATUS make_user_sam_entry_list(TALLOC_CTX *ctx, SAM_ENTRY **sam_pp, UNISTR2 **uni_name_pp, - uint32 num_entries, uint32 start_idx, DISP_USER_INFO *disp_user_info, + uint32 num_entries, uint32 start_idx, SAM_ACCOUNT *disp_user_info, DOM_SID *domain_sid) { uint32 i; @@ -721,7 +717,7 @@ static NTSTATUS make_user_sam_entry_list(TALLOC_CTX *ctx, SAM_ENTRY **sam_pp, UN } for (i = 0; i < num_entries; i++) { - pwd = disp_user_info[i+start_idx].sam; + pwd = &disp_user_info[i+start_idx]; temp_name = pdb_get_username(pwd); init_unistr2(&uni_temp_name, temp_name, strlen(temp_name)+1); user_sid = pdb_get_user_sid(pwd); @@ -900,7 +896,7 @@ static NTSTATUS get_group_alias_entries(TALLOC_CTX *ctx, DOMAIN_GRP **d_grp, DOM /* well-known aliases */ if (sid_equal(sid, &global_sid_Builtin) && !lp_hide_local_users()) { - pdb_enum_group_mapping(SID_NAME_WKN_GRP, &map, (int *)&num_entries, ENUM_ONLY_MAPPED, MAPPING_WITHOUT_PRIV); + pdb_enum_group_mapping(SID_NAME_WKN_GRP, &map, (int *)&num_entries, ENUM_ONLY_MAPPED); if (num_entries != 0) { *d_grp=(DOMAIN_GRP *)talloc_zero(ctx, num_entries*sizeof(DOMAIN_GRP)); @@ -937,7 +933,7 @@ static NTSTATUS get_group_alias_entries(TALLOC_CTX *ctx, DOMAIN_GRP **d_grp, DOM for (; (num_entries < max_entries) && (grp != NULL); grp = grp->next) { uint32 trid; - if(!pdb_getgrgid(&smap, grp->gr_gid, MAPPING_WITHOUT_PRIV)) + if(!pdb_getgrgid(&smap, grp->gr_gid)) continue; if (smap.sid_name_use!=SID_NAME_ALIAS) { @@ -1018,7 +1014,7 @@ static NTSTATUS get_group_domain_entries(TALLOC_CTX *ctx, DOMAIN_GRP **d_grp, DO *p_num_entries = 0; - pdb_enum_group_mapping(SID_NAME_DOM_GRP, &map, (int *)&group_entries, ENUM_ONLY_MAPPED, MAPPING_WITHOUT_PRIV); + pdb_enum_group_mapping(SID_NAME_DOM_GRP, &map, (int *)&group_entries, ENUM_ONLY_MAPPED); num_entries=group_entries-start_idx; @@ -1128,6 +1124,7 @@ NTSTATUS _samr_enum_dom_aliases(pipes_struct *p, SAMR_Q_ENUM_DOM_ALIASES *q_u, S /******************************************************************* samr_reply_query_dispinfo ********************************************************************/ + NTSTATUS _samr_query_dispinfo(pipes_struct *p, SAMR_Q_QUERY_DISPINFO *q_u, SAMR_R_QUERY_DISPINFO *r_u) { @@ -1346,7 +1343,7 @@ NTSTATUS _samr_query_aliasinfo(pipes_struct *p, SAMR_Q_QUERY_ALIASINFO *q_u, SAM !sid_check_is_in_builtin(&sid)) return NT_STATUS_OBJECT_TYPE_MISMATCH; - if (!pdb_getgrsid(&map, sid, MAPPING_WITHOUT_PRIV)) + if (!pdb_getgrsid(&map, sid)) return NT_STATUS_NO_SUCH_ALIAS; switch (q_u->switch_level) { @@ -2207,6 +2204,7 @@ NTSTATUS _api_samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_ uint32 acc_granted; SEC_DESC *psd; size_t sd_size; + uint32 new_rid = 0; /* check this, when giving away 'add computer to domain' privs */ uint32 des_access = GENERIC_RIGHTS_USER_ALL_ACCESS; @@ -2225,7 +2223,7 @@ NTSTATUS _api_samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_ */ rpcstr_pull(account, user_account.buffer, sizeof(account), user_account.uni_str_len*2, 0); - strlower(account); + strlower_m(account); pdb_init_sam(&sam_pass); @@ -2262,23 +2260,30 @@ NTSTATUS _api_samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_ */ DEBUG(10,("checking account %s at pos %d for $ termination\n",account, strlen(account)-1)); -#if 0 - if ((acb_info & ACB_WSTRUST) && (account[strlen(account)-1] == '$')) { - pstrcpy(add_script, lp_addmachine_script()); - } else if ((!(acb_info & ACB_WSTRUST)) && (account[strlen(account)-1] != '$')) { - pstrcpy(add_script, lp_adduser_script()); - } else { - DEBUG(0, ("_api_samr_create_user: mismatch between trust flags and $ termination\n")); - pdb_free_sam(&sam_pass); - return NT_STATUS_UNSUCCESSFUL; - } -#endif + + /* + * we used to have code here that made sure the acb_info flags + * matched with the users named (e.g. an account flags as a machine + * trust account ended in '$'). It has been ifdef'd out for a long + * time, so I replaced it with this comment. --jerry + */ /* the passdb lookup has failed; check to see if we need to run the add user/machine script */ pw = Get_Pwnam(account); + /********************************************************************* + * HEADS UP! If we have to create a new user account, we have to get + * a new RID from somewhere. This used to be done by the passdb + * backend. It has been moved into idmap now. Since idmap is now + * wrapped up behind winbind, this means you have to run winbindd if you + * want new accounts to get a new RID when "enable rid algorithm = no". + * Tough. We now have a uniform way of allocating RIDs regardless + * of what ever passdb backend people may use. + * --jerry (2003-07-10) + *********************************************************************/ + if ( !pw ) { /* * we can't check both the ending $ and the acb_info. @@ -2298,11 +2303,19 @@ NTSTATUS _api_samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_ add_ret = smbrun(add_script,NULL); DEBUG(3,("_api_samr_create_user: Running the command `%s' gave %d\n", add_script, add_ret)); } + else /* no add user script -- ask winbindd to do it */ + { + if ( !winbind_create_user( account, &new_rid ) ) { + DEBUG(3,("_api_samr_create_user: winbind_create_user(%s) failed\n", + account)); + } + } } - nt_status = pdb_init_sam_new(&sam_pass, account); - if (!NT_STATUS_IS_OK(nt_status)) + /* implicit call to getpwnam() next. we have a valid SID coming out of this call */ + + if ( !NT_STATUS_IS_OK(nt_status = pdb_init_sam_new(&sam_pass, account, new_rid)) ) return nt_status; pdb_set_acct_ctrl(sam_pass, acb_info, PDB_CHANGED); @@ -2575,17 +2588,10 @@ NTSTATUS _samr_enum_domains(pipes_struct *p, SAMR_Q_ENUM_DOMAINS *q_u, SAMR_R_EN return r_u->status; } - switch (lp_server_role()) { - case ROLE_DOMAIN_PDC: - case ROLE_DOMAIN_BDC: - name = lp_workgroup(); - break; - default: - name = global_myname(); - } + name = get_global_sam_name(); fstrcpy(dom[0],name); - strupper(dom[0]); + strupper_m(dom[0]); fstrcpy(dom[1],"Builtin"); if (!make_enum_domains(p->mem_ctx, &r_u->sam, &r_u->uni_dom_name, num_entries, dom)) @@ -2737,6 +2743,41 @@ static BOOL set_user_info_12(SAM_USER_INFO_12 *id12, DOM_SID *sid) return True; } +/******************************************************************* + The GROUPSID field in the SAM_ACCOUNT changed. Try to tell unix. + ********************************************************************/ +static BOOL set_unix_primary_group(SAM_ACCOUNT *sampass) +{ + struct group *grp; + gid_t gid; + + if (!NT_STATUS_IS_OK(sid_to_gid(pdb_get_group_sid(sampass), + &gid))) { + DEBUG(2,("Could not get gid for primary group of " + "user %s\n", pdb_get_username(sampass))); + return False; + } + + grp = getgrgid(gid); + + if (grp == NULL) { + DEBUG(2,("Could not find primary group %d for " + "user %s\n", gid, pdb_get_username(sampass))); + return False; + } + + if (smb_set_primary_group(grp->gr_name, + pdb_get_username(sampass)) != 0) { + DEBUG(2,("Could not set primary group for user %s to " + "%s\n", + pdb_get_username(sampass), grp->gr_name)); + return False; + } + + return True; +} + + /******************************************************************* set_user_info_21 ********************************************************************/ @@ -2766,6 +2807,9 @@ static BOOL set_user_info_21(SAM_USER_INFO_21 *id21, DOM_SID *sid) * id21. I don't know if they need to be set. --jerry */ + if (IS_SAM_CHANGED(pwd, PDB_GROUPSID)) + set_unix_primary_group(pwd); + /* write the change out */ if(!pdb_update_sam_account(pwd)) { pdb_free_sam(&pwd); @@ -2833,6 +2877,9 @@ static BOOL set_user_info_23(SAM_USER_INFO_23 *id23, DOM_SID *sid) ZERO_STRUCT(plaintext_buf); + if (IS_SAM_CHANGED(pwd, PDB_GROUPSID)) + set_unix_primary_group(pwd); + if(!pdb_update_sam_account(pwd)) { pdb_free_sam(&pwd); return False; @@ -3181,12 +3228,12 @@ NTSTATUS _samr_query_aliasmem(pipes_struct *p, SAMR_Q_QUERY_ALIASMEM *q_u, SAMR_ if (sid_equal(&alias_sid, &global_sid_Builtin)) { DEBUG(10, ("lookup on Builtin SID (S-1-5-32)\n")); - if(!get_builtin_group_from_sid(als_sid, &map, MAPPING_WITHOUT_PRIV)) + if(!get_builtin_group_from_sid(als_sid, &map)) return NT_STATUS_NO_SUCH_ALIAS; } else { if (sid_equal(&alias_sid, get_global_sam_sid())) { DEBUG(10, ("lookup on Server SID\n")); - if(!get_local_group_from_sid(als_sid, &map, MAPPING_WITHOUT_PRIV)) + if(!get_local_group_from_sid(als_sid, &map)) return NT_STATUS_NO_SUCH_ALIAS; } } @@ -3287,7 +3334,7 @@ NTSTATUS _samr_query_groupmem(pipes_struct *p, SAMR_Q_QUERY_GROUPMEM *q_u, SAMR_ sid_append_rid(&group_sid, group_rid); DEBUG(10, ("lookup on Domain SID\n")); - if(!get_domain_group_from_sid(group_sid, &map, MAPPING_WITHOUT_PRIV)) + if(!get_domain_group_from_sid(group_sid, &map)) return NT_STATUS_NO_SUCH_GROUP; if(!get_uid_list_of_group(map.gid, &uid, &num_uids)) @@ -3371,13 +3418,13 @@ NTSTATUS _samr_add_aliasmem(pipes_struct *p, SAMR_Q_ADD_ALIASMEM *q_u, SAMR_R_AD if (sid_compare(&alias_sid, get_global_sam_sid())>0) { DEBUG(10, ("adding member on Server SID\n")); - if(!get_local_group_from_sid(alias_sid, &map, MAPPING_WITHOUT_PRIV)) + if(!get_local_group_from_sid(alias_sid, &map)) return NT_STATUS_NO_SUCH_ALIAS; } else { if (sid_compare(&alias_sid, &global_sid_Builtin)>0) { DEBUG(10, ("adding member on BUILTIN SID\n")); - if( !get_local_group_from_sid(alias_sid, &map, MAPPING_WITHOUT_PRIV)) + if( !get_local_group_from_sid(alias_sid, &map)) return NT_STATUS_NO_SUCH_ALIAS; } else @@ -3396,7 +3443,7 @@ NTSTATUS _samr_add_aliasmem(pipes_struct *p, SAMR_Q_ADD_ALIASMEM *q_u, SAMR_R_AD } /* check a real user exist before we run the script to add a user to a group */ - if (NT_STATUS_IS_ERR(sid_to_uid(pdb_get_user_sid(sam_user), &uid))) { + if (!NT_STATUS_IS_OK(sid_to_uid(pdb_get_user_sid(sam_user), &uid))) { pdb_free_sam(&sam_user); return NT_STATUS_NO_SUCH_USER; } @@ -3468,7 +3515,7 @@ NTSTATUS _samr_del_aliasmem(pipes_struct *p, SAMR_Q_DEL_ALIASMEM *q_u, SAMR_R_DE return NT_STATUS_NO_SUCH_ALIAS; } - if( !get_local_group_from_sid(alias_sid, &map, MAPPING_WITHOUT_PRIV)) + if( !get_local_group_from_sid(alias_sid, &map)) return NT_STATUS_NO_SUCH_ALIAS; if ((grp=getgrgid(map.gid)) == NULL) @@ -3538,7 +3585,7 @@ NTSTATUS _samr_add_groupmem(pipes_struct *p, SAMR_Q_ADD_GROUPMEM *q_u, SAMR_R_AD DEBUG(10, ("lookup on Domain SID\n")); - if(!get_domain_group_from_sid(group_sid, &map, MAPPING_WITHOUT_PRIV)) + if(!get_domain_group_from_sid(group_sid, &map)) return NT_STATUS_NO_SUCH_GROUP; sid_copy(&user_sid, get_global_sam_sid()); @@ -3556,7 +3603,7 @@ NTSTATUS _samr_add_groupmem(pipes_struct *p, SAMR_Q_ADD_GROUPMEM *q_u, SAMR_R_AD } /* check a real user exist before we run the script to add a user to a group */ - if (NT_STATUS_IS_ERR(sid_to_uid(pdb_get_user_sid(sam_user), &uid))) { + if (!NT_STATUS_IS_OK(sid_to_uid(pdb_get_user_sid(sam_user), &uid))) { pdb_free_sam(&sam_user); return NT_STATUS_NO_SUCH_USER; } @@ -3633,7 +3680,7 @@ NTSTATUS _samr_del_groupmem(pipes_struct *p, SAMR_Q_DEL_GROUPMEM *q_u, SAMR_R_DE sid_copy(&user_sid, get_global_sam_sid()); sid_append_rid(&user_sid, q_u->rid); - if (!get_domain_group_from_sid(group_sid, &map, MAPPING_WITHOUT_PRIV)) + if (!get_domain_group_from_sid(group_sid, &map)) return NT_STATUS_NO_SUCH_GROUP; if ((grp=getgrgid(map.gid)) == NULL) @@ -3678,12 +3725,25 @@ static int smb_delete_user(const char *unix_user) pstring del_script; int ret; + /* try winbindd first since it is impossible to determine where + a user came from via NSS. Try the delete user script if this fails + meaning the user did not exist in winbindd's list of accounts */ + + if ( winbind_delete_user( unix_user ) ) { + DEBUG(3,("winbind_delete_user: removed user (%s)\n", unix_user)); + return 0; + } + + + /* fall back to 'delete user script' */ + pstrcpy(del_script, lp_deluser_script()); if (! *del_script) return -1; all_string_sub(del_script, "%u", unix_user, sizeof(pstring)); ret = smbrun(del_script,NULL); DEBUG(3,("smb_delete_user: Running the command `%s' gave %d\n",del_script,ret)); + return ret; } @@ -3778,7 +3838,7 @@ NTSTATUS _samr_delete_dom_group(pipes_struct *p, SAMR_Q_DELETE_DOM_GROUP *q_u, S DEBUG(10, ("lookup on Domain SID\n")); - if(!get_domain_group_from_sid(group_sid, &map, MAPPING_WITHOUT_PRIV)) + if(!get_domain_group_from_sid(group_sid, &map)) return NT_STATUS_NO_SUCH_GROUP; gid=map.gid; @@ -3840,7 +3900,7 @@ NTSTATUS _samr_delete_dom_alias(pipes_struct *p, SAMR_Q_DELETE_DOM_ALIAS *q_u, S DEBUG(10, ("lookup on Local SID\n")); - if(!get_local_group_from_sid(alias_sid, &map, MAPPING_WITHOUT_PRIV)) + if(!get_local_group_from_sid(alias_sid, &map)) return NT_STATUS_NO_SUCH_ALIAS; gid=map.gid; @@ -3877,12 +3937,9 @@ NTSTATUS _samr_create_dom_group(pipes_struct *p, SAMR_Q_CREATE_DOM_GROUP *q_u, S fstring sid_string; struct group *grp; struct samr_info *info; - PRIVILEGE_SET priv_set; uint32 acc_granted; gid_t gid; - init_privilege(&priv_set); - /* Find the policy handle. Open a policy on it. */ if (!get_lsa_policy_samr_sid(p, &q_u->pol, &dom_sid, &acc_granted)) return NT_STATUS_INVALID_HANDLE; @@ -3917,7 +3974,7 @@ NTSTATUS _samr_create_dom_group(pipes_struct *p, SAMR_Q_CREATE_DOM_GROUP *q_u, S sid_append_rid(&info_sid, r_u->rid); sid_to_string(sid_string, &info_sid); - if(!add_initial_entry(grp->gr_gid, sid_string, SID_NAME_DOM_GRP, name, NULL, priv_set, PR_ACCESS_FROM_NETWORK)) + if(!add_initial_entry(grp->gr_gid, sid_string, SID_NAME_DOM_GRP, name, NULL)) return NT_STATUS_ACCESS_DENIED; if ((info = get_samr_info_by_sid(&info_sid)) == NULL) @@ -3942,12 +3999,9 @@ NTSTATUS _samr_create_dom_alias(pipes_struct *p, SAMR_Q_CREATE_DOM_ALIAS *q_u, S fstring sid_string; struct group *grp; struct samr_info *info; - PRIVILEGE_SET priv_set; uint32 acc_granted; gid_t gid; - init_privilege(&priv_set); - /* Find the policy handle. Open a policy on it. */ if (!get_lsa_policy_samr_sid(p, &q_u->dom_pol, &dom_sid, &acc_granted)) return NT_STATUS_INVALID_HANDLE; @@ -3982,7 +4036,7 @@ NTSTATUS _samr_create_dom_alias(pipes_struct *p, SAMR_Q_CREATE_DOM_ALIAS *q_u, S sid_to_string(sid_string, &info_sid); /* add the group to the mapping table */ - if(!add_initial_entry(grp->gr_gid, sid_string, SID_NAME_ALIAS, name, NULL, priv_set, PR_ACCESS_FROM_NETWORK)) + if(!add_initial_entry(grp->gr_gid, sid_string, SID_NAME_ALIAS, name, NULL)) return NT_STATUS_ACCESS_DENIED; if ((info = get_samr_info_by_sid(&info_sid)) == NULL) @@ -4018,7 +4072,7 @@ NTSTATUS _samr_query_groupinfo(pipes_struct *p, SAMR_Q_QUERY_GROUPINFO *q_u, SAM return r_u->status; } - if (!get_domain_group_from_sid(group_sid, &map, MAPPING_WITHOUT_PRIV)) + if (!get_domain_group_from_sid(group_sid, &map)) return NT_STATUS_INVALID_HANDLE; ctr=(GROUP_INFO_CTR *)talloc_zero(p->mem_ctx, sizeof(GROUP_INFO_CTR)); @@ -4070,7 +4124,7 @@ NTSTATUS _samr_set_groupinfo(pipes_struct *p, SAMR_Q_SET_GROUPINFO *q_u, SAMR_R_ return r_u->status; } - if (!get_domain_group_from_sid(group_sid, &map, MAPPING_WITH_PRIV)) + if (!get_domain_group_from_sid(group_sid, &map)) return NT_STATUS_NO_SUCH_GROUP; ctr=q_u->ctr; @@ -4083,17 +4137,13 @@ NTSTATUS _samr_set_groupinfo(pipes_struct *p, SAMR_Q_SET_GROUPINFO *q_u, SAMR_R_ unistr2_to_ascii(map.comment, &(ctr->group.info4.uni_acct_desc), sizeof(map.comment)-1); break; default: - free_privilege(&map.priv_set); return NT_STATUS_INVALID_INFO_CLASS; } if(!pdb_update_group_mapping_entry(&map)) { - free_privilege(&map.priv_set); return NT_STATUS_NO_SUCH_GROUP; } - free_privilege(&map.priv_set); - return NT_STATUS_OK; } @@ -4117,7 +4167,7 @@ NTSTATUS _samr_set_aliasinfo(pipes_struct *p, SAMR_Q_SET_ALIASINFO *q_u, SAMR_R_ return r_u->status; } - if (!get_local_group_from_sid(group_sid, &map, MAPPING_WITH_PRIV)) + if (!get_local_group_from_sid(group_sid, &map)) return NT_STATUS_NO_SUCH_GROUP; ctr=&q_u->ctr; @@ -4127,17 +4177,13 @@ NTSTATUS _samr_set_aliasinfo(pipes_struct *p, SAMR_Q_SET_ALIASINFO *q_u, SAMR_R_ unistr2_to_ascii(map.comment, &(ctr->alias.info3.uni_acct_desc), sizeof(map.comment)-1); break; default: - free_privilege(&map.priv_set); return NT_STATUS_INVALID_INFO_CLASS; } if(!pdb_update_group_mapping_entry(&map)) { - free_privilege(&map.priv_set); return NT_STATUS_NO_SUCH_GROUP; } - free_privilege(&map.priv_set); - return NT_STATUS_OK; } @@ -4212,7 +4258,7 @@ NTSTATUS _samr_open_group(pipes_struct *p, SAMR_Q_OPEN_GROUP *q_u, SAMR_R_OPEN_G DEBUG(10, ("_samr_open_group:Opening SID: %s\n", sid_string)); /* check if that group really exists */ - if (!get_domain_group_from_sid(info->sid, &map, MAPPING_WITHOUT_PRIV)) + if (!get_domain_group_from_sid(info->sid, &map)) return NT_STATUS_NO_SUCH_GROUP; /* get a (unique) handle. open a policy on it. */ diff --git a/source3/rpc_server/srv_spoolss_nt.c b/source3/rpc_server/srv_spoolss_nt.c index 24459a26f0..2d316051af 100644 --- a/source3/rpc_server/srv_spoolss_nt.c +++ b/source3/rpc_server/srv_spoolss_nt.c @@ -273,7 +273,34 @@ static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd } /**************************************************************************** - find printer index by handle + look for a printer object cached on an open printer handle +****************************************************************************/ + +WERROR find_printer_in_print_hnd_cache( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL_2 **info2, + const char *printername ) +{ + Printer_entry *p; + + DEBUG(10,("find_printer_in_print_hnd_cache: printer [%s]\n", printername)); + + for ( p=printers_list; p; p=p->next ) + { + if ( p->printer_type==PRINTER_HANDLE_IS_PRINTER + && p->printer_info + && StrCaseCmp(p->dev.handlename, printername) == 0 ) + { + DEBUG(10,("Found printer\n")); + *info2 = dup_printer_2( ctx, p->printer_info->info_2 ); + if ( *info2 ) + return WERR_OK; + } + } + + return WERR_INVALID_PRINTER_NAME; +} + +/**************************************************************************** + destroy any cached printer_info_2 structures on open handles ****************************************************************************/ void invalidate_printer_hnd_cache( char *printername ) @@ -1025,9 +1052,9 @@ static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx ) } if ( sending_msg_count ) { - cli_spoolss_rrpcn( ¬ify_cli, mem_ctx, &p->notify.client_hnd, - data_len, data, p->notify.change, 0 ); - } + cli_spoolss_rrpcn( ¬ify_cli, mem_ctx, &p->notify.client_hnd, + data_len, data, p->notify.change, 0 ); + } } done: @@ -2339,7 +2366,6 @@ static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint return WERR_OK; } -#if 0 /* JERRY */ /* REG_BINARY * uint32 size = 0x114 * uint32 major = 5 @@ -2348,14 +2374,23 @@ static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint * extra unicode string = e.g. "Service Pack 3" */ if (!StrCaseCmp(value, "OSVersion")) { - *type = 0x4; - if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL) + *type = 0x3; + *needed = 0x114; + + if((*data = (uint8 *)talloc(ctx, (*needed)*sizeof(uint8) )) == NULL) return WERR_NOMEM; - SIVAL(*data, 0, 2); - *needed = 0x4; + ZERO_STRUCTP( *data ); + + SIVAL(*data, 0, *needed); /* size */ + SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */ + SIVAL(*data, 8, 0); + SIVAL(*data, 12, 2195); /* build */ + + /* leave extra string empty */ + return WERR_OK; } -#endif + if (!StrCaseCmp(value, "DefaultSpoolDirectory")) { fstring string; @@ -4330,8 +4365,8 @@ static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *p GUID guid; if (is_printer_published(print_hnd, snum, &guid)) { - asprintf(&guid_str, "{%s}", uuid_string_static(guid)); - strupper(guid_str); + asprintf(&guid_str, "{%s}", smb_uuid_string_static(guid)); + strupper_m(guid_str); init_unistr(&printer->guid, guid_str); printer->action = SPOOL_DS_PUBLISH; } else { @@ -4681,7 +4716,7 @@ WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_ */ unistr2_to_ascii(name, servername, sizeof(name)-1); - strupper(name); + strupper_m(name); switch (level) { case 1: @@ -7609,12 +7644,12 @@ static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environmen { pstring path; pstring long_archi; - pstring short_archi; + const char *short_archi; DRIVER_DIRECTORY_1 *info=NULL; unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1); - if (get_short_archi(short_archi, long_archi)==False) + if (!(short_archi = get_short_archi(long_archi))) return WERR_INVALID_ENVIRONMENT; if((info=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1))) == NULL) @@ -8440,7 +8475,7 @@ WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_ /**************************************************************************** ****************************************************************************/ -static WERROR getjob_level_1(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed) +static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed) { int i=0; BOOL found=False; @@ -8453,7 +8488,7 @@ static WERROR getjob_level_1(print_queue_struct *queue, int count, int snum, uin } for (i=0; idfs_root_flag = 0; + sh1005->share_info_flags = 0; if(lp_host_msdfs() && lp_msdfs_root(snum)) - sh1005->dfs_root_flag = 3; + sh1005->share_info_flags |= + SHARE_1005_IN_DFS | SHARE_1005_DFS_ROOT; + sh1005->share_info_flags |= + lp_csc_policy(snum) << SHARE_1005_CSC_POLICY_SHIFT; } /*************************************************************************** Fill in a share info level 1006 structure. @@ -1513,6 +1516,19 @@ WERROR _srv_net_share_set_info(pipes_struct *p, SRV_Q_NET_SHARE_SET_INFO *q_u, S type = STYPE_DISKTREE; break; case 1005: + /* XP re-sets the csc policy even if it wasn't changed by the + user, so we must compare it to see if it's what is set in + smb.conf, so that we can contine other ops like setting + ACLs on a share */ + if (((q_u->info.share.info1005.share_info_flags & + SHARE_1005_CSC_POLICY_MASK) >> + SHARE_1005_CSC_POLICY_SHIFT) == lp_csc_policy(snum)) + return WERR_OK; + else { + DEBUG(3, ("_srv_net_share_set_info: client is trying to change csc policy from the network; must be done with smb.conf\n")); + return WERR_ACCESS_DENIED; + } + break; case 1006: case 1007: return WERR_ACCESS_DENIED; @@ -1840,8 +1856,6 @@ WERROR _srv_net_file_query_secdesc(pipes_struct *p, SRV_Q_NET_FILE_QUERY_SECDESC struct current_user user; connection_struct *conn = NULL; BOOL became_user = False; - fstring dev; - fstrcpy(dev, "A:"); ZERO_STRUCT(st); @@ -1855,7 +1869,7 @@ WERROR _srv_net_file_query_secdesc(pipes_struct *p, SRV_Q_NET_FILE_QUERY_SECDESC get_current_user(&user, p); become_root(); - conn = make_connection(qualname, null_pw, dev, user.vuid, &nt_status); + conn = make_connection(qualname, null_pw, "A:", user.vuid, &nt_status); unbecome_root(); if (conn == NULL) { @@ -1889,7 +1903,7 @@ WERROR _srv_net_file_query_secdesc(pipes_struct *p, SRV_Q_NET_FILE_QUERY_SECDESC } } - sd_size = conn->vfs_ops.get_nt_acl(fsp, fsp->fsp_name, &psd); + sd_size = SMB_VFS_GET_NT_ACL(fsp, fsp->fsp_name, (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION), &psd); if (sd_size == 0) { DEBUG(3,("_srv_net_file_query_secdesc: Unable to get NT ACL for file %s\n", filename)); @@ -1945,12 +1959,9 @@ WERROR _srv_net_file_set_secdesc(pipes_struct *p, SRV_Q_NET_FILE_SET_SECDESC *q_ struct current_user user; connection_struct *conn = NULL; BOOL became_user = False; - fstring dev; - fstrcpy(dev, "A:"); ZERO_STRUCT(st); - r_u->status = WERR_OK; unistr2_to_ascii(qualname, &q_u->uni_qual_name, sizeof(qualname)); @@ -1961,7 +1972,7 @@ WERROR _srv_net_file_set_secdesc(pipes_struct *p, SRV_Q_NET_FILE_SET_SECDESC *q_ get_current_user(&user, p); become_root(); - conn = make_connection(qualname, null_pw, dev, user.vuid, &nt_status); + conn = make_connection(qualname, null_pw, "A:", user.vuid, &nt_status); unbecome_root(); if (conn == NULL) { @@ -1996,7 +2007,7 @@ WERROR _srv_net_file_set_secdesc(pipes_struct *p, SRV_Q_NET_FILE_SET_SECDESC *q_ } } - ret = conn->vfs_ops.set_nt_acl(fsp, fsp->fsp_name, q_u->sec_info, q_u->sec_desc); + ret = SMB_VFS_SET_NT_ACL(fsp, fsp->fsp_name, q_u->sec_info, q_u->sec_desc); if (ret == False) { DEBUG(3,("_srv_net_file_set_secdesc: Unable to set NT ACL on file %s\n", filename)); diff --git a/source3/rpc_server/srv_util.c b/source3/rpc_server/srv_util.c index f96ccaef67..03e53118a8 100644 --- a/source3/rpc_server/srv_util.c +++ b/source3/rpc_server/srv_util.c @@ -129,7 +129,7 @@ NTSTATUS get_alias_user_groups(TALLOC_CTX *ctx, DOM_SID *sid, int *numgroups, ui fstrcpy(user_name, pdb_get_username(sam_pass)); grid=pdb_get_group_rid(sam_pass); - if (NT_STATUS_IS_ERR(sid_to_gid(pdb_get_group_sid(sam_pass), &gid))) { + if (!NT_STATUS_IS_OK(sid_to_gid(pdb_get_group_sid(sam_pass), &gid))) { /* this should never happen */ DEBUG(2,("get_alias_user_groups: sid_to_gid failed!\n")); pdb_free_sam(&sam_pass); @@ -147,14 +147,17 @@ NTSTATUS get_alias_user_groups(TALLOC_CTX *ctx, DOM_SID *sid, int *numgroups, ui return NT_STATUS_UNSUCCESSFUL; } + become_root(); + for (i=0;i\n", argv[0]); - return NT_STATUS_OK; - } - - right = argv[1]; - - result = cli_lsa_open_policy2(cli, mem_ctx, True, - SEC_RIGHTS_MAXIMUM_ALLOWED, - &dom_pol); - - if (!NT_STATUS_IS_OK(result)) - goto done; - - result = cli_lsa_enum_account_with_right(cli, mem_ctx, &dom_pol, right, &count, &sids); - - if (!NT_STATUS_IS_OK(result)) - goto done; - - printf("found %d SIDs for '%s'\n", count, right); - - for (i = 0; i < count; i++) { - printf("\t%s\n", sid_string_static(&sids[i])); - } - - done: - return result; -} - - /* add some privileges to a SID via LsaAddAccountRights */ static NTSTATUS cmd_lsa_add_acct_rights(struct cli_state *cli, @@ -750,7 +706,6 @@ struct cmd_set lsarpc_commands[] = { { "lsaenumsid", RPC_RTYPE_NTSTATUS, cmd_lsa_enum_sids, NULL, PI_LSARPC, "Enumerate the LSA SIDS", "" }, { "lsaenumprivsaccount", RPC_RTYPE_NTSTATUS, cmd_lsa_enum_privsaccounts, NULL, PI_LSARPC, "Enumerate the privileges of an SID", "" }, { "lsaenumacctrights", RPC_RTYPE_NTSTATUS, cmd_lsa_enum_acct_rights, NULL, PI_LSARPC, "Enumerate the rights of an SID", "" }, - { "lsaenumacctwithright",RPC_RTYPE_NTSTATUS, cmd_lsa_enum_acct_with_right,NULL, PI_LSARPC,"Enumerate accounts with a right", "" }, { "lsaaddacctrights", RPC_RTYPE_NTSTATUS, cmd_lsa_add_acct_rights, NULL, PI_LSARPC, "Add rights to an account", "" }, { "lsaremoveacctrights", RPC_RTYPE_NTSTATUS, cmd_lsa_remove_acct_rights, NULL, PI_LSARPC, "Remove rights from an account", "" }, { "lsalookupprivvalue", RPC_RTYPE_NTSTATUS, cmd_lsa_lookupprivvalue, NULL, PI_LSARPC, "Get a privilege value given its name", "" }, diff --git a/source3/rpcclient/cmd_netlogon.c b/source3/rpcclient/cmd_netlogon.c index 32fa9c3699..0ec78a0673 100644 --- a/source3/rpcclient/cmd_netlogon.c +++ b/source3/rpcclient/cmd_netlogon.c @@ -275,6 +275,7 @@ static NTSTATUS cmd_netlogon_sam_logon(struct cli_state *cli, const char *username, *password; uint32 neg_flags = 0x000001ff; int auth_level = 2; + DOM_CRED ret_creds; /* Check arguments */ @@ -299,7 +300,13 @@ 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); + ZERO_STRUCT(ret_creds); + + result = cli_netlogon_sam_logon(cli, mem_ctx, &ret_creds, username, password, logon_type); + + clnt_deal_with_creds(cli->sess_key, &(cli->clnt_cred), &ret_creds); + + result = cli_netlogon_sam_logon(cli, mem_ctx, &ret_creds, username, password, logon_type); if (!NT_STATUS_IS_OK(result)) goto done; diff --git a/source3/rpcclient/cmd_samr.c b/source3/rpcclient/cmd_samr.c index e2232f0da7..40d01d0f5a 100644 --- a/source3/rpcclient/cmd_samr.c +++ b/source3/rpcclient/cmd_samr.c @@ -288,8 +288,8 @@ static NTSTATUS cmd_samr_query_user(struct cli_state *cli, sscanf(argv[3], "%x", &access_mask); - slprintf (server, sizeof(fstring)-1, "\\\\%s", cli->desthost); - strupper (server); + slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->desthost); + strupper_m(server); result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, &connect_pol); @@ -396,8 +396,8 @@ static NTSTATUS cmd_samr_query_group(struct cli_state *cli, if (argc > 3) sscanf(argv[3], "%x", &access_mask); - slprintf (server, sizeof(fstring)-1, "\\\\%s", cli->desthost); - strupper (server); + slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->desthost); + strupper_m(server); result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, &connect_pol); @@ -458,8 +458,8 @@ static NTSTATUS cmd_samr_query_usergroups(struct cli_state *cli, if (argc > 2) sscanf(argv[2], "%x", &access_mask); - slprintf (server, sizeof(fstring)-1, "\\\\%s", cli->desthost); - strupper (server); + slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->desthost); + strupper_m(server); result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, &connect_pol); @@ -524,8 +524,8 @@ static NTSTATUS cmd_samr_query_useraliases(struct cli_state *cli, if (argc > 3) sscanf(argv[3], "%x", &access_mask); - slprintf (server, sizeof(fstring)-1, "\\\\%s", cli->desthost); - strupper (server); + slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->desthost); + strupper_m(server); result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, &connect_pol); @@ -587,8 +587,8 @@ static NTSTATUS cmd_samr_query_groupmem(struct cli_state *cli, if (argc > 2) sscanf(argv[2], "%x", &access_mask); - slprintf (server, sizeof(fstring)-1, "\\\\%s", cli->desthost); - strupper (server); + slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->desthost); + strupper_m(server); result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, &connect_pol); @@ -1415,8 +1415,8 @@ static NTSTATUS cmd_samr_query_sec_obj(struct cli_state *cli, sscanf(argv[1], "%i", &user_rid); } - slprintf (server, sizeof(fstring)-1, "\\\\%s", cli->desthost); - strupper (server); + slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->desthost); + strupper_m(server); result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, &connect_pol); diff --git a/source3/rpcclient/cmd_spoolss.c b/source3/rpcclient/cmd_spoolss.c index 3ce7f9e6ac..b2fa802e9a 100644 --- a/source3/rpcclient/cmd_spoolss.c +++ b/source3/rpcclient/cmd_spoolss.c @@ -54,7 +54,7 @@ static const struct table_node archi_table[]= { function to do the mapping between the long architecture name and the short one. ****************************************************************************/ -BOOL get_short_archi(char *short_archi, const char *long_archi) +static const char *cmd_spoolss_get_short_archi(const char *long_archi) { int i=-1; @@ -66,18 +66,17 @@ BOOL get_short_archi(char *short_archi, const char *long_archi) if (archi_table[i].long_archi==NULL) { DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi)); - return False; + return NULL; } /* this might be client code - but shouldn't this be an fstrcpy etc? */ - StrnCpy (short_archi, archi_table[i].short_archi, strlen(archi_table[i].short_archi)); DEBUGADD(108,("index: [%d]\n", i)); - DEBUGADD(108,("long architecture: [%s]\n", long_archi)); - DEBUGADD(108,("short architecture: [%s]\n", short_archi)); + DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi)); + DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi)); - return True; + return archi_table[i].short_archi; } #if 0 @@ -113,10 +112,10 @@ static WERROR cmd_spoolss_open_printer_ex(struct cli_state *cli, if (!cli) return WERR_GENERAL_FAILURE; - slprintf (servername, sizeof(servername)-1, "\\\\%s", cli->desthost); - strupper (servername); - fstrcpy (user, cli->user_name); - fstrcpy (printername, argv[1]); + slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost); + strupper_m(servername); + fstrcpy(user, cli->user_name); + fstrcpy(printername, argv[1]); /* Open the printer handle */ @@ -321,7 +320,7 @@ static WERROR cmd_spoolss_enum_printers(struct cli_state *cli, fstrcpy(name, argv[2]); else { slprintf(name, sizeof(name)-1, "\\\\%s", cli->desthost); - strupper(name); + strupper_m(name); } /* Enumerate printers -- Should we enumerate types other @@ -481,14 +480,14 @@ static WERROR cmd_spoolss_setprinter(struct cli_state *cli, fstrcpy(comment, argv[2]); } - slprintf (servername, sizeof(servername)-1, "\\\\%s", cli->desthost); - strupper (servername); - fstrcpy (printername, argv[1]); - fstrcpy (user, cli->user_name); + slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost); + strupper_m(servername); + fstrcpy(printername, argv[1]); + fstrcpy(user, cli->user_name); /* get a printer handle */ result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, "", - MAXIMUM_ALLOWED_ACCESS, servername, + PRINTER_ALL_ACCESS, servername, user, &pol); if (!W_ERROR_IS_OK(result)) @@ -549,10 +548,10 @@ static WERROR cmd_spoolss_getprinter(struct cli_state *cli, info_level = atoi(argv[2]); } - slprintf (servername, sizeof(servername)-1, "\\\\%s", cli->desthost); - strupper (servername); - slprintf (printername, sizeof(printername)-1, "%s\\%s", servername, argv[1]); - fstrcpy (user, cli->user_name); + slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost); + strupper_m(servername); + slprintf(printername, sizeof(printername)-1, "%s\\%s", servername, argv[1]); + fstrcpy(user, cli->user_name); /* get a printer handle */ @@ -667,14 +666,14 @@ static WERROR cmd_spoolss_getprinterdata(struct cli_state *cli, /* Open a printer handle */ - slprintf (servername, sizeof(servername)-1, "\\\\%s", cli->desthost); - strupper (servername); + slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost); + strupper_m(servername); if (strncmp(argv[1], ".", sizeof(".")) == 0) fstrcpy(printername, servername); else - slprintf (printername, sizeof(servername)-1, "%s\\%s", + slprintf(printername, sizeof(servername)-1, "%s\\%s", servername, argv[1]); - fstrcpy (user, cli->user_name); + fstrcpy(user, cli->user_name); /* get a printer handle */ @@ -740,14 +739,14 @@ static WERROR cmd_spoolss_getprinterdataex(struct cli_state *cli, /* Open a printer handle */ - slprintf (servername, sizeof(servername)-1, "\\\\%s", cli->desthost); - strupper (servername); + slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost); + strupper_m(servername); if (strncmp(argv[1], ".", sizeof(".")) == 0) fstrcpy(printername, servername); else - slprintf (printername, sizeof(printername)-1, "%s\\%s", + slprintf(printername, sizeof(printername)-1, "%s\\%s", servername, argv[1]); - fstrcpy (user, cli->user_name); + fstrcpy(user, cli->user_name); /* get a printer handle */ @@ -921,10 +920,10 @@ static WERROR cmd_spoolss_getdriver(struct cli_state *cli, } /* get the arguments need to open the printer handle */ - slprintf (servername, sizeof(servername)-1, "\\\\%s", cli->desthost); - strupper (servername); - fstrcpy (user, cli->user_name); - fstrcpy (printername, argv[1]); + slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost); + strupper_m(servername); + fstrcpy(user, cli->user_name); + fstrcpy(printername, argv[1]); if (argc == 3) info_level = atoi(argv[2]); @@ -1153,7 +1152,7 @@ static char* get_driver_3_param (const char* str, const char* delim, UNISTR* des parameter because two consecutive delimiters will not return an empty string. See man strtok(3) for details */ - if (StrCaseCmp(ptr, "NULL") == 0) + if (ptr && (StrCaseCmp(ptr, "NULL") == 0)) ptr = NULL; if (dest != NULL) @@ -1227,7 +1226,7 @@ static WERROR cmd_spoolss_addprinterdriver(struct cli_state *cli, uint32 level = 3; PRINTER_DRIVER_CTR ctr; DRIVER_INFO_3 info3; - fstring arch; + const char *arch; fstring driver_name; /* parse the command arguements */ @@ -1243,7 +1242,7 @@ static WERROR cmd_spoolss_addprinterdriver(struct cli_state *cli, /* Fill in the DRIVER_INFO_3 struct */ ZERO_STRUCT(info3); - if (!get_short_archi(arch, argv[1])) + if (!(arch = cmd_spoolss_get_short_archi(argv[1]))) { printf ("Error Unknown architechture [%s]\n", argv[1]); return WERR_INVALID_PARAM; @@ -1289,8 +1288,8 @@ static WERROR cmd_spoolss_addprinterex(struct cli_state *cli, return WERR_OK; } - slprintf (servername, sizeof(servername)-1, "\\\\%s", cli->desthost); - strupper (servername); + slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost); + strupper_m(servername); /* Fill in the DRIVER_INFO_3 struct */ ZERO_STRUCT(info2); @@ -1351,10 +1350,10 @@ static WERROR cmd_spoolss_setdriver(struct cli_state *cli, return WERR_OK; } - slprintf (servername, sizeof(servername)-1, "\\\\%s", cli->desthost); - strupper (servername); - slprintf (printername, sizeof(printername)-1, "%s\\%s", servername, argv[1]); - fstrcpy (user, cli->user_name); + slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost); + strupper_m(servername); + slprintf(printername, sizeof(printername)-1, "%s\\%s", servername, argv[1]); + fstrcpy(user, cli->user_name); /* Get a printer handle */ @@ -1422,8 +1421,8 @@ static WERROR cmd_spoolss_deletedriver(struct cli_state *cli, return WERR_OK; } - slprintf (servername, sizeof(servername)-1, "\\\\%s", cli->desthost); - strupper (servername); + slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost); + strupper_m(servername); /* delete the driver for all architectures */ for (i=0; archi_table[i].long_archi; i++) @@ -1466,7 +1465,7 @@ static WERROR cmd_spoolss_getprintprocdir(struct cli_state *cli, if (asprintf(&servername, "\\\\%s", cli->desthost) < 0) return WERR_NOMEM; - strupper(servername); + strupper_m(servername); if (asprintf(&environment, "%s", (argc == 2) ? argv[1] : PRINTER_DRIVER_ARCHITECTURE) < 0) { @@ -1512,7 +1511,7 @@ static WERROR cmd_spoolss_addform(struct cli_state *cli, TALLOC_CTX *mem_ctx, /* Get a printer handle */ asprintf(&servername, "\\\\%s", cli->desthost); - strupper(servername); + strupper_m(servername); asprintf(&printername, "%s\\%s", servername, argv[1]); werror = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, "", @@ -1571,7 +1570,7 @@ static WERROR cmd_spoolss_setform(struct cli_state *cli, TALLOC_CTX *mem_ctx, /* Get a printer handle */ asprintf(&servername, "\\\\%s", cli->desthost); - strupper(servername); + strupper_m(servername); asprintf(&printername, "%s\\%s", servername, argv[1]); werror = cli_spoolss_open_printer_ex( @@ -1630,7 +1629,7 @@ static WERROR cmd_spoolss_getform(struct cli_state *cli, TALLOC_CTX *mem_ctx, /* Get a printer handle */ asprintf(&servername, "\\\\%s", cli->desthost); - strupper(servername); + strupper_m(servername); asprintf(&printername, "%s\\%s", servername, argv[1]); werror = cli_spoolss_open_printer_ex( @@ -1692,7 +1691,7 @@ static WERROR cmd_spoolss_deleteform(struct cli_state *cli, /* Get a printer handle */ asprintf(&servername, "\\\\%s", cli->desthost); - strupper(servername); + strupper_m(servername); asprintf(&printername, "%s\\%s", servername, argv[1]); werror = cli_spoolss_open_printer_ex( @@ -1741,7 +1740,7 @@ static WERROR cmd_spoolss_enum_forms(struct cli_state *cli, /* Get a printer handle */ asprintf(&servername, "\\\\%s", cli->desthost); - strupper(servername); + strupper_m(servername); asprintf(&printername, "%s\\%s", servername, argv[1]); werror = cli_spoolss_open_printer_ex( @@ -1807,10 +1806,10 @@ static WERROR cmd_spoolss_setprinterdata(struct cli_state *cli, return WERR_OK; } - slprintf (servername, sizeof(servername)-1, "\\\\%s", cli->desthost); - strupper (servername); - slprintf (printername, sizeof(servername)-1, "%s\\%s", servername, argv[1]); - fstrcpy (user, cli->user_name); + slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost); + strupper_m(servername); + slprintf(printername, sizeof(servername)-1, "%s\\%s", servername, argv[1]); + fstrcpy(user, cli->user_name); /* get a printer handle */ result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, "", @@ -1930,10 +1929,10 @@ static WERROR cmd_spoolss_enum_jobs(struct cli_state *cli, /* Open printer handle */ slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost); - strupper(servername); + strupper_m(servername); fstrcpy(user, cli->user_name); slprintf(printername, sizeof(servername)-1, "\\\\%s\\", cli->desthost); - strupper(printername); + strupper_m(printername); pstrcat(printername, argv[1]); result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, @@ -2001,10 +2000,10 @@ static WERROR cmd_spoolss_enum_data( struct cli_state *cli, /* Open printer handle */ slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost); - strupper(servername); + strupper_m(servername); fstrcpy(user, cli->user_name); slprintf(printername, sizeof(printername)-1, "\\\\%s\\", cli->desthost); - strupper(printername); + strupper_m(printername); pstrcat(printername, argv[1]); result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, @@ -2064,10 +2063,10 @@ static WERROR cmd_spoolss_enum_data_ex( struct cli_state *cli, /* Open printer handle */ slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost); - strupper(servername); + strupper_m(servername); fstrcpy(user, cli->user_name); slprintf(printername, sizeof(printername)-1, "\\\\%s\\", cli->desthost); - strupper(printername); + strupper_m(printername); pstrcat(printername, argv[1]); result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, @@ -2132,10 +2131,10 @@ static WERROR cmd_spoolss_enum_printerkey( struct cli_state *cli, /* Open printer handle */ slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost); - strupper(servername); + strupper_m(servername); fstrcpy(user, cli->user_name); slprintf(printername, sizeof(printername)-1, "\\\\%s\\", cli->desthost); - strupper(printername); + strupper_m(printername); pstrcat(printername, argv[1]); result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, @@ -2197,11 +2196,11 @@ static WERROR cmd_spoolss_rffpcnex(struct cli_state *cli, /* Open printer */ slprintf(servername, sizeof(servername) - 1, "\\\\%s", cli->desthost); - strupper(servername); + strupper_m(servername); slprintf(printername, sizeof(printername) - 1, "\\\\%s\\%s", cli->desthost, argv[1]); - strupper(printername); + strupper_m(printername); result = cli_spoolss_open_printer_ex( cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS, @@ -2240,7 +2239,7 @@ static WERROR cmd_spoolss_rffpcnex(struct cli_state *cli, /* Send rffpcnex */ slprintf(servername, sizeof(servername) - 1, "\\\\%s", myhostname()); - strupper(servername); + strupper_m(servername); result = cli_spoolss_rffpcnex( cli, mem_ctx, &hnd, 0, 0, servername, 123, &option); diff --git a/source3/rpcclient/cmd_wkssvc.c b/source3/rpcclient/cmd_wkssvc.c index bb118234c0..137ff3bdae 100644 --- a/source3/rpcclient/cmd_wkssvc.c +++ b/source3/rpcclient/cmd_wkssvc.c @@ -44,7 +44,7 @@ void cmd_wks_query_info(struct client_info *info) fstrcpy(dest_wks, "\\\\"); fstrcat(dest_wks, info->dest_host); - strupper(dest_wks); + strupper_m(dest_wks); if (next_token_nr(NULL, tmp, NULL, sizeof(tmp))) { diff --git a/source3/rpcclient/rpcclient.c b/source3/rpcclient/rpcclient.c index b01e2d694c..af021962f5 100644 --- a/source3/rpcclient/rpcclient.c +++ b/source3/rpcclient/rpcclient.c @@ -37,6 +37,21 @@ static struct cmd_list { struct cmd_set *cmd_set; } *cmd_list; +/***************************************************************************** + stubb functions +****************************************************************************/ + +void become_root( void ) +{ + return; +} + +void unbecome_root( void ) +{ + return; +} + + /**************************************************************************** handle completion of commands for readline ****************************************************************************/ @@ -304,6 +319,119 @@ static NTSTATUS cmd_quit(struct cli_state *cli, TALLOC_CTX *mem_ctx, return NT_STATUS_OK; /* NOTREACHED */ } +static NTSTATUS cmd_sign(struct cli_state *cli, TALLOC_CTX *mem_ctx, + int argc, const char **argv) +{ + if (cli->pipe_auth_flags == (AUTH_PIPE_NTLMSSP|AUTH_PIPE_SIGN)) { + return NT_STATUS_OK; + } else { + /* still have session, just need to use it again */ + cli->pipe_auth_flags = AUTH_PIPE_NTLMSSP; + cli->pipe_auth_flags |= AUTH_PIPE_SIGN; + if (cli->nt_pipe_fnum != 0) + cli_nt_session_close(cli); + } + + return NT_STATUS_OK; +} + +static NTSTATUS cmd_seal(struct cli_state *cli, TALLOC_CTX *mem_ctx, + int argc, const char **argv) +{ + if (cli->pipe_auth_flags == (AUTH_PIPE_NTLMSSP|AUTH_PIPE_SIGN|AUTH_PIPE_SEAL)) { + return NT_STATUS_OK; + } else { + /* still have session, just need to use it again */ + cli->pipe_auth_flags = AUTH_PIPE_NTLMSSP; + cli->pipe_auth_flags |= AUTH_PIPE_SIGN; + cli->pipe_auth_flags |= AUTH_PIPE_SEAL; + if (cli->nt_pipe_fnum != 0) + cli_nt_session_close(cli); + } + return NT_STATUS_OK; +} + +static NTSTATUS cmd_none(struct cli_state *cli, TALLOC_CTX *mem_ctx, + int argc, const char **argv) +{ + if (cli->pipe_auth_flags == 0) { + return NT_STATUS_OK; + } else { + /* still have session, just need to use it again */ + cli->pipe_auth_flags = 0; + if (cli->nt_pipe_fnum != 0) + cli_nt_session_close(cli); + } + cli->pipe_auth_flags = 0; + + return NT_STATUS_OK; +} + +static NTSTATUS cmd_schannel(struct cli_state *cli, TALLOC_CTX *mem_ctx, + int argc, const char **argv) +{ + uchar trust_password[16]; + uint32 sec_channel_type; + uint32 neg_flags = 0x000001ff; + NTSTATUS result; + static uchar zeros[16]; + + /* Cleanup */ + + if ((memcmp(cli->auth_info.sess_key, zeros, sizeof(cli->auth_info.sess_key)) != 0) + && (cli->saved_netlogon_pipe_fnum != 0)) { + if (cli->pipe_auth_flags == (AUTH_PIPE_NETSEC|AUTH_PIPE_SIGN|AUTH_PIPE_SEAL)) { + return NT_STATUS_OK; + } else { + /* still have session, just need to use it again */ + cli->pipe_auth_flags = AUTH_PIPE_NETSEC; + cli->pipe_auth_flags |= AUTH_PIPE_SIGN; + cli->pipe_auth_flags |= AUTH_PIPE_SEAL; + if (cli->nt_pipe_fnum != 0) + cli_nt_session_close(cli); + } + } + + if (cli->nt_pipe_fnum != 0) + cli_nt_session_close(cli); + + cli->pipe_auth_flags = 0; + + if (!secrets_fetch_trust_account_password(lp_workgroup(), + trust_password, + NULL, &sec_channel_type)) { + return NT_STATUS_UNSUCCESSFUL; + } + + if (!cli_nt_session_open(cli, PI_NETLOGON)) { + DEBUG(0, ("Could not initialise %s\n", + get_pipe_name_from_index(PI_NETLOGON))); + return NT_STATUS_UNSUCCESSFUL; + } + + neg_flags |= NETLOGON_NEG_SCHANNEL; + + result = cli_nt_setup_creds(cli, sec_channel_type, trust_password, + &neg_flags, 2); + + if (!NT_STATUS_IS_OK(result)) { + ZERO_STRUCT(cli->auth_info.sess_key); + cli->pipe_auth_flags = 0; + return result; + } + + memcpy(cli->auth_info.sess_key, cli->sess_key, + sizeof(cli->auth_info.sess_key)); + + cli->saved_netlogon_pipe_fnum = cli->nt_pipe_fnum; + + cli->pipe_auth_flags = AUTH_PIPE_NETSEC; + cli->pipe_auth_flags |= AUTH_PIPE_SIGN; + cli->pipe_auth_flags |= AUTH_PIPE_SEAL; + + return NT_STATUS_OK; +} + /* Built in rpcclient commands */ static struct cmd_set rpcclient_commands[] = { @@ -316,6 +444,10 @@ static struct cmd_set rpcclient_commands[] = { { "list", RPC_RTYPE_NTSTATUS, cmd_listcommands, NULL, -1, "List available commands on ", "pipe" }, { "exit", RPC_RTYPE_NTSTATUS, cmd_quit, NULL, -1, "Exit program", "" }, { "quit", RPC_RTYPE_NTSTATUS, cmd_quit, NULL, -1, "Exit program", "" }, + { "sign", RPC_RTYPE_NTSTATUS, cmd_sign, NULL, -1, "Force RPC pipe connections to be signed", "" }, + { "seal", RPC_RTYPE_NTSTATUS, cmd_seal, NULL, -1, "Force RPC pipe connections to be sealed", "" }, + { "schannel", RPC_RTYPE_NTSTATUS, cmd_schannel, NULL, -1, "Force RPC pipe connections to be sealed with 'schannel' (NETSEC). Assumes valid machine account to this domain controller.", "" }, + { "none", RPC_RTYPE_NTSTATUS, cmd_none, NULL, -1, "Force RPC pipe connections to have no special properties", "" }, { NULL } }; @@ -377,8 +509,9 @@ static NTSTATUS do_cmd(struct cli_state *cli, struct cmd_set *cmd_entry, int argc, char **argv) { - NTSTATUS ntresult; - WERROR wresult; + NTSTATUS ntresult; + WERROR wresult; + uchar trust_password[16]; TALLOC_CTX *mem_ctx; @@ -386,34 +519,42 @@ static NTSTATUS do_cmd(struct cli_state *cli, if (!(mem_ctx = talloc_init("do_cmd"))) { DEBUG(0, ("talloc_init() failed\n")); - return NT_STATUS_UNSUCCESSFUL; + return NT_STATUS_NO_MEMORY; } /* Open pipe */ - if (cmd_entry->pipe_idx == PI_NETLOGON) { - uchar trust_password[16]; - uint32 sec_channel_type; + if (cmd_entry->pipe_idx != -1 + && cmd_entry->pipe_idx != cli->pipe_idx) { + if (cli->nt_pipe_fnum != 0) + cli_nt_session_close(cli); + + if (!cli_nt_session_open(cli, cmd_entry->pipe_idx)) { + DEBUG(0, ("Could not initialise %s\n", + get_pipe_name_from_index(cmd_entry->pipe_idx))); + return NT_STATUS_UNSUCCESSFUL; + } + } + if ((cmd_entry->pipe_idx == PI_NETLOGON) && !(cli->pipe_auth_flags & AUTH_PIPE_NETSEC)) { + uint32 neg_flags = 0x000001ff; + uint32 sec_channel_type; + if (!secrets_fetch_trust_account_password(lp_workgroup(), trust_password, NULL, &sec_channel_type)) { return NT_STATUS_UNSUCCESSFUL; } - - if (!cli_nt_open_netlogon(cli, trust_password, - sec_channel_type)) { - DEBUG(0, ("Could not initialise NETLOGON pipe\n")); - return NT_STATUS_UNSUCCESSFUL; - } - } else { - if (cmd_entry->pipe_idx != -1) { - if (!cli_nt_session_open(cli, cmd_entry->pipe_idx)) { - DEBUG(0, ("Could not initialise %s\n", - get_pipe_name_from_index(cmd_entry->pipe_idx))); - return NT_STATUS_UNSUCCESSFUL; - } + + ntresult = cli_nt_setup_creds(cli, sec_channel_type, + trust_password, + &neg_flags, 2); + if (!NT_STATUS_IS_OK(ntresult)) { + ZERO_STRUCT(cli->auth_info.sess_key); + printf("nt_setup_creds failed with %s\n", nt_errstr(ntresult)); + return ntresult; } + } /* Run command */ @@ -435,9 +576,6 @@ static NTSTATUS do_cmd(struct cli_state *cli, /* Cleanup */ - if (cmd_entry->pipe_idx != -1) - cli_nt_session_close(cli); - talloc_destroy(mem_ctx); return ntresult; diff --git a/source3/sam/idmap.c b/source3/sam/idmap.c index 9695e7b764..7a8f270e15 100644 --- a/source3/sam/idmap.c +++ b/source3/sam/idmap.c @@ -4,6 +4,7 @@ Copyright (C) Tim Potter 2000 Copyright (C) Anthony Liguori 2003 Copyright (C) Simo Sorce 2003 + Copyright (C) Jeremy Allison 2003. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -24,189 +25,292 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_IDMAP -static struct { - +struct idmap_function_entry { const char *name; - /* Function to create a member of the idmap_methods list */ - NTSTATUS (*reg_meth)(struct idmap_methods **methods); struct idmap_methods *methods; - -} remote_idmap_functions[] = { - { NULL, NULL, NULL } + struct idmap_function_entry *prev,*next; }; -static struct idmap_methods *local_map; -static struct idmap_methods *remote_map; - -static void lazy_initialize_idmap(void) -{ - static BOOL initialized = False; - if (initialized) return; - idmap_init(); - initialized = True; -} +static struct idmap_function_entry *backends = NULL; +static struct idmap_methods *cache_map; +static struct idmap_methods *remote_map; +/********************************************************************** + Get idmap methods. Don't allow tdb to be a remote method. +**********************************************************************/ -static struct idmap_methods *get_methods(const char *name) +static struct idmap_methods *get_methods(const char *name, BOOL cache_method) { - int i = 0; - struct idmap_methods *ret = NULL; + struct idmap_function_entry *entry = backends; - while (remote_idmap_functions[i].name && strcmp(remote_idmap_functions[i].name, name)) { - i++; + for(entry = backends; entry; entry = entry->next) { + if (!cache_method && strequal(entry->name, "tdb")) + continue; /* tdb is only cache method. */ + if (strequal(entry->name, name)) + return entry->methods; } - if (remote_idmap_functions[i].name) { + return NULL; +} - if (!remote_idmap_functions[i].methods) { - remote_idmap_functions[i].reg_meth(&remote_idmap_functions[i].methods); - } +/********************************************************************** + Allow a module to register itself as a method. +**********************************************************************/ - ret = remote_idmap_functions[i].methods; +NTSTATUS smb_register_idmap(int version, const char *name, struct idmap_methods *methods) +{ + struct idmap_function_entry *entry; + + if ((version != SMB_IDMAP_INTERFACE_VERSION)) { + DEBUG(0, ("smb_register_idmap: Failed to register idmap module.\n" + "The module was compiled against SMB_IDMAP_INTERFACE_VERSION %d,\n" + "current SMB_IDMAP_INTERFACE_VERSION is %d.\n" + "Please recompile against the current version of samba!\n", + version, SMB_IDMAP_INTERFACE_VERSION)); + return NT_STATUS_OBJECT_TYPE_MISMATCH; + } + + if (!name || !name[0] || !methods) { + DEBUG(0,("smb_register_idmap: called with NULL pointer or empty name!\n")); + return NT_STATUS_INVALID_PARAMETER; } - return ret; + if (get_methods(name, False)) { + DEBUG(0,("smb_register_idmap: idmap module %s already registered!\n", name)); + return NT_STATUS_OBJECT_NAME_COLLISION; + } + + entry = smb_xmalloc(sizeof(struct idmap_function_entry)); + entry->name = smb_xstrdup(name); + entry->methods = methods; + + DLIST_ADD(backends, entry); + DEBUG(5, ("smb_register_idmap: Successfully added idmap backend '%s'\n", name)); + return NT_STATUS_OK; } -/* Initialize backend */ -BOOL idmap_init(void) +/********************************************************************** + Initialise idmap cache and a remote backend (if configured). +**********************************************************************/ + +BOOL idmap_init(const char *remote_backend) { - const char *remote_backend = lp_idmap_backend(); + if (!backends) + static_init_idmap; + + if (!cache_map) { + cache_map = get_methods("tdb", True); - if (!local_map) { - idmap_reg_tdb(&local_map); - if (NT_STATUS_IS_ERR(local_map->init())) { - DEBUG(0, ("idmap_init: could not load or create local backend!\n")); + if (!cache_map) { + DEBUG(0, ("idmap_init: could not find tdb cache backend!\n")); + return False; + } + + if (!NT_STATUS_IS_OK(cache_map->init( NULL ))) { + DEBUG(0, ("idmap_init: could not initialise tdb cache backend!\n")); return False; } } if (!remote_map && remote_backend && *remote_backend != 0) { - DEBUG(3, ("idmap_init: using '%s' as remote backend\n", remote_backend)); + char *rem_backend = smb_xstrdup(remote_backend); + fstring params = ""; + char *pparams; + + /* get any mode parameters passed in */ + + if ( (pparams = strchr( rem_backend, ':' )) != NULL ) { + *pparams = '\0'; + pparams++; + fstrcpy( params, pparams ); + } + + DEBUG(3, ("idmap_init: using '%s' as remote backend\n", rem_backend)); - remote_map = get_methods(remote_backend); - if (!remote_map) { - DEBUG(0, ("idmap_init: could not load remote backend '%s'\n", remote_backend)); + if((remote_map = get_methods(rem_backend, False)) || + (NT_STATUS_IS_OK(smb_probe_module("idmap", rem_backend)) && + (remote_map = get_methods(rem_backend, False)))) { + remote_map->init(params); + } else { + DEBUG(0, ("idmap_init: could not load remote backend '%s'\n", rem_backend)); + SAFE_FREE(rem_backend); return False; } - remote_map->init(); + SAFE_FREE(rem_backend); } return True; } +/************************************************************************** + This is a rare operation, designed to allow an explicit mapping to be + set up for a sid to a POSIX id. +**************************************************************************/ + NTSTATUS idmap_set_mapping(const DOM_SID *sid, unid_t id, int id_type) { - NTSTATUS ret; - - lazy_initialize_idmap(); - - ret = local_map->set_mapping(sid, id, id_type); - if (NT_STATUS_IS_ERR(ret)) { - DEBUG (0, ("idmap_set_mapping: Error, unable to modify local cache!\n")); - DEBUGADD(0, ("Error: %s", nt_errstr(ret))); - return ret; + struct idmap_methods *map = remote_map; + DOM_SID tmp_sid; + + DEBUG(10, ("idmap_set_mapping: Set %s to %s %d\n", + sid_string_static(sid), + ((id_type & ID_TYPEMASK) == ID_USERID) ? "UID" : "GID", + ((id_type & ID_TYPEMASK) == ID_USERID) ? id.uid : id.gid)); + + if ( (NT_STATUS_IS_OK(cache_map-> + get_sid_from_id(&tmp_sid, id, + id_type | ID_QUERY_ONLY))) && + sid_equal(sid, &tmp_sid) ) { + /* Nothing to do, we already have that mapping */ + DEBUG(10, ("idmap_set_mapping: Mapping already there\n")); + return NT_STATUS_OK; } - /* Being able to update the remote cache is seldomly right. - Generally this is a forbidden operation. */ - if (!(id_type & ID_CACHE) && (remote_map != NULL)) { - remote_map->set_mapping(sid, id, id_type); - if (NT_STATUS_IS_ERR(ret)) { - DEBUG (0, ("idmap_set_mapping: Error, unable to modify remote cache!\n")); - DEBUGADD(0, ("Error: %s", nt_errstr(ret))); - } + if (map == NULL) { + /* Ok, we don't have a authoritative remote + mapping. So update our local cache only. */ + map = cache_map; } - return ret; + return map->set_mapping(sid, id, id_type); } -/* Get ID from SID */ +/************************************************************************** + Get ID from SID. This can create a mapping for a SID to a POSIX id. +**************************************************************************/ + NTSTATUS idmap_get_id_from_sid(unid_t *id, int *id_type, const DOM_SID *sid) { NTSTATUS ret; int loc_type; - lazy_initialize_idmap(); - loc_type = *id_type; - if (remote_map) { /* We have a central remote idmap */ - loc_type |= ID_NOMAP; + + if (remote_map) { + /* We have a central remote idmap so only look in + cache, don't allocate */ + loc_type |= ID_QUERY_ONLY; } - ret = local_map->get_id_from_sid(id, &loc_type, sid); - if (NT_STATUS_IS_ERR(ret)) { - if (remote_map) { - ret = remote_map->get_id_from_sid(id, id_type, sid); - if (NT_STATUS_IS_ERR(ret)) { - DEBUG(3, ("idmap_get_id_from_sid: error fetching id!\n")); - return ret; - } else { - loc_type |= ID_CACHE; - idmap_set_mapping(sid, *id, loc_type); - } - } - } else { + + ret = cache_map->get_id_from_sid(id, &loc_type, sid); + + if (NT_STATUS_IS_OK(ret)) { *id_type = loc_type & ID_TYPEMASK; + return NT_STATUS_OK; + } + + if (remote_map == NULL) { + return ret; + } + + /* Ok, the mapping was not in the cache, give the remote map a + second try. */ + + ret = remote_map->get_id_from_sid(id, id_type, sid); + + if (NT_STATUS_IS_OK(ret)) { + /* The remote backend gave us a valid mapping, cache it. */ + ret = cache_map->set_mapping(sid, *id, *id_type); } return ret; } -/* Get SID from ID */ +/************************************************************************** + Get SID from ID. This must have been created before. +**************************************************************************/ + NTSTATUS idmap_get_sid_from_id(DOM_SID *sid, unid_t id, int id_type) { NTSTATUS ret; int loc_type; - lazy_initialize_idmap(); - loc_type = id_type; if (remote_map) { - loc_type = id_type | ID_NOMAP; + loc_type = id_type | ID_QUERY_ONLY; } - ret = local_map->get_sid_from_id(sid, id, loc_type); - if (NT_STATUS_IS_ERR(ret)) { - if (remote_map) { - ret = remote_map->get_sid_from_id(sid, id, id_type); - if (NT_STATUS_IS_ERR(ret)) { - DEBUG(3, ("idmap_get_sid_from_id: unable to fetch sid!\n")); - return ret; - } else { - loc_type |= ID_CACHE; - idmap_set_mapping(sid, id, loc_type); - } - } + + ret = cache_map->get_sid_from_id(sid, id, loc_type); + + if (NT_STATUS_IS_OK(ret)) + return ret; + + if (remote_map == NULL) + return ret; + + /* We have a second chance, ask our authoritative backend */ + + ret = remote_map->get_sid_from_id(sid, id, id_type); + + if (NT_STATUS_IS_OK(ret)) { + /* The remote backend gave us a valid mapping, cache it. */ + ret = cache_map->set_mapping(sid, id, id_type); } return ret; } -/* Close backend */ +/************************************************************************** + Alloocate a new UNIX uid/gid +**************************************************************************/ + +NTSTATUS idmap_allocate_id(unid_t *id, int id_type) +{ + /* we have to allocate from the authoritative backend */ + + if ( remote_map ) + return remote_map->allocate_id( id, id_type ); + + return cache_map->allocate_id( id, id_type ); +} + +/************************************************************************** + Alloocate a new RID +**************************************************************************/ + +NTSTATUS idmap_allocate_rid(uint32 *rid, int type) +{ + /* we have to allocate from the authoritative backend */ + + if ( remote_map ) + return remote_map->allocate_rid( rid, type ); + + return cache_map->allocate_rid( rid, type ); +} + +/************************************************************************** + Shutdown maps. +**************************************************************************/ + NTSTATUS idmap_close(void) { NTSTATUS ret; - ret = local_map->close(); - if (NT_STATUS_IS_ERR(ret)) { - DEBUG(3, ("idmap_close: failed to close local cache!\n")); + ret = cache_map->close(); + if (!NT_STATUS_IS_OK(ret)) { + DEBUG(3, ("idmap_close: failed to close local tdb cache!\n")); } + cache_map = NULL; if (remote_map) { ret = remote_map->close(); - if (NT_STATUS_IS_ERR(ret)) { + if (!NT_STATUS_IS_OK(ret)) { DEBUG(3, ("idmap_close: failed to close remote idmap repository!\n")); } + remote_map = NULL; } return ret; } -/* Dump backend status */ +/************************************************************************** + Dump backend status. +**************************************************************************/ + void idmap_status(void) { - lazy_initialize_idmap(); - - local_map->status(); - if (remote_map) remote_map->status(); + cache_map->status(); + if (remote_map) + remote_map->status(); } diff --git a/source3/sam/idmap_ldap.c b/source3/sam/idmap_ldap.c index 33cf5fb030..9a1ee039d0 100644 --- a/source3/sam/idmap_ldap.c +++ b/source3/sam/idmap_ldap.c @@ -3,9 +3,10 @@ idmap LDAP backend - Copyright (C) Tim Potter 2000 - Copyright (C) Anthony Liguori 2003 - Copyright (C) Simo Sorce 2003 + Copyright (C) Tim Potter 2000 + Copyright (C) Anthony Liguori 2003 + Copyright (C) Simo Sorce 2003 + Copyright (C) Gerald Carter 2003 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -31,781 +32,912 @@ #include #include +#include "smbldap.h" + +#define IDMAP_GROUP_SUFFIX "ou=idmap group" +#define IDMAP_USER_SUFFIX "ou=idmap people" + + struct ldap_idmap_state { - LDAP *ldap_struct; - time_t last_ping; - const char *uri; - char *bind_dn; - char *bind_secret; - unsigned int num_failures; - struct ldap_idmap_state *prev, *next; + struct smbldap_state *smbldap_state; + TALLOC_CTX *mem_ctx; + + uint32 low_allocated_user_rid; + uint32 high_allocated_user_rid; + uint32 low_allocated_group_rid; + uint32 high_allocated_group_rid; + }; -#define LDAP_IDMAP_DONT_PING_TIME 10 /* ping only all 10 seconds */ #define LDAP_MAX_ALLOC_ID 128 /* number tries while allocating new id */ static struct ldap_idmap_state ldap_state; -static int ldap_idmap_connect_system(struct ldap_idmap_state *state); static NTSTATUS ldap_set_mapping(const DOM_SID *sid, unid_t id, int id_type); +static NTSTATUS ldap_set_mapping_internals(const DOM_SID *sid, unid_t id, int id_type, + const char *ldap_dn, LDAPMessage *entry); static NTSTATUS ldap_idmap_close(void); -/******************************************************************* - find the ldap password -******************************************************************/ -static BOOL fetch_ldapsam_pw(char **dn, char** pw) -{ - char *key = NULL; - size_t size; - - *dn = smb_xstrdup(lp_ldap_admin_dn()); - - if (asprintf(&key, "%s/%s", SECRETS_LDAP_BIND_PW, *dn) < 0) { - SAFE_FREE(*dn); - DEBUG(0, ("fetch_ldapsam_pw: asprintf failed!\n")); - } - - *pw=secrets_fetch(key, &size); - SAFE_FREE(key); - - if (!size) { - /* Upgrade 2.2 style entry */ - char *p; - char* old_style_key = strdup(*dn); - char *data; - fstring old_style_pw; - - if (!old_style_key) { - DEBUG(0, ("fetch_ldapsam_pw: strdup failed!\n")); - return False; - } - - for (p=old_style_key; *p; p++) - if (*p == ',') *p = '/'; - - data=secrets_fetch(old_style_key, &size); - if (!size && size < sizeof(old_style_pw)) { - DEBUG(0,("fetch_ldap_pw: neither ldap secret retrieved!\n")); - SAFE_FREE(old_style_key); - SAFE_FREE(*dn); - return False; - } +/********************************************************************** + Even if the sambaDomain attribute in LDAP tells us that this RID is + safe to use, always check before use. +*********************************************************************/ - strncpy(old_style_pw, data, size); - old_style_pw[size] = 0; +static BOOL sid_in_use(struct ldap_idmap_state *state, + const DOM_SID *sid, int *error) +{ + fstring filter; + fstring sid_string; + LDAPMessage *result = NULL; + int count; + int rc; + char *sid_attr[] = {LDAP_ATTRIBUTE_SID, NULL}; - SAFE_FREE(data); + slprintf(filter, sizeof(filter)-1, "(%s=%s)", LDAP_ATTRIBUTE_SID, sid_to_string(sid_string, sid)); - if (!secrets_store_ldap_pw(*dn, old_style_pw)) { - DEBUG(0,("fetch_ldap_pw: ldap secret could not be upgraded!\n")); - SAFE_FREE(old_style_key); - SAFE_FREE(*dn); - return False; - } - if (!secrets_delete(old_style_key)) { - DEBUG(0,("fetch_ldap_pw: old ldap secret could not be deleted!\n")); - } + rc = smbldap_search_suffix(state->smbldap_state, + filter, sid_attr, &result); - SAFE_FREE(old_style_key); + if (rc != LDAP_SUCCESS) { + char *ld_error = NULL; + ldap_get_option(state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error); + DEBUG(2, ("Failed to check if sid %s is alredy in use: %s\n", + sid_string, ld_error)); + SAFE_FREE(ld_error); - *pw = smb_xstrdup(old_style_pw); + *error = rc; + return True; } - return True; + if ((count = ldap_count_entries(state->smbldap_state->ldap_struct, result)) > 0) { + DEBUG(3, ("Sid %s already in use - trying next RID\n", + sid_string)); + ldap_msgfree(result); + return True; + } + + ldap_msgfree(result); + + /* good, sid is not in use */ + return False; } -/******************************************************************* - open a connection to the ldap server. -******************************************************************/ -static int ldap_idmap_open_connection(struct ldap_idmap_state *state) +/********************************************************************** + Set the new nextRid attribute, and return one we can use. + + This also checks that this RID is actually free - in case the admin + manually stole it :-). +*********************************************************************/ +static NTSTATUS ldap_next_rid(struct ldap_idmap_state *state, uint32 *rid, + int rid_type) { - int rc = LDAP_SUCCESS; - int version; - BOOL ldap_v3 = False; + NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; + int rc; + LDAPMessage *domain_result = NULL; + LDAPMessage *entry = NULL; + char *dn; + LDAPMod **mods = NULL; + fstring old_rid_string; + fstring next_rid_string; + fstring algorithmic_rid_base_string; + uint32 next_rid; + uint32 alg_rid_base; + int attempts = 0; + char *ld_error = NULL; -#ifdef HAVE_LDAP_INITIALIZE - DEBUG(10, ("ldap_idmap_open_connection: %s\n", state->uri)); - - if ((rc = ldap_initialize(&state->ldap_struct, state->uri)) - != LDAP_SUCCESS) { - DEBUG(0, ("ldap_initialize: %s\n", ldap_err2string(rc))); - return rc; - } -#else - /* Parse the string manually */ + while (attempts < 10) { - int port = 0; - fstring protocol; - fstring host; - const char *p = state->uri; - SMB_ASSERT(sizeof(protocol)>10 && sizeof(host)>254); - - /* skip leading "URL:" (if any) */ - if ( strncasecmp( p, "URL:", 4 ) == 0 ) { - p += 4; + if (!NT_STATUS_IS_OK(ret = smbldap_search_domain_info(state->smbldap_state, + &domain_result, get_global_sam_name(), True))) + { + return ret; } - - sscanf(p, "%10[^:]://%254s[^:]:%d", protocol, host, &port); - - if (port == 0) { - if (strequal(protocol, "ldap")) { - port = LDAP_PORT; - } else if (strequal(protocol, "ldaps")) { - port = LDAPS_PORT; - } else { - DEBUG(0, ("unrecognised protocol (%s)!\n", - protocol)); - } + + entry = ldap_first_entry(state->smbldap_state->ldap_struct, domain_result); + if (!entry) { + DEBUG(0, ("Could not get domain info entry\n")); + ldap_msgfree(domain_result); + return ret; } - - if ((state->ldap_struct = ldap_init(host, port)) == NULL) { - DEBUG(0, ("ldap_init failed !\n")); - return LDAP_OPERATIONS_ERROR; + + if ((dn = ldap_get_dn(state->smbldap_state->ldap_struct, entry)) == NULL) { + DEBUG(0, ("Could not get domain info DN\n")); + ldap_msgfree(domain_result); + return ret; } + + /* yes, we keep 3 seperate counters, one for rids between 1000 (BASE_RID) and + algorithmic_rid_base. The other two are to avoid stomping on the + different sets of algorithmic RIDs */ - if (strequal(protocol, "ldaps")) { -#ifdef LDAP_OPT_X_TLS - int tls = LDAP_OPT_X_TLS_HARD; - if (ldap_set_option (state->ldap_struct, - LDAP_OPT_X_TLS, &tls) != - LDAP_SUCCESS) - { - DEBUG(0, ("Failed to setup a TLS session\n")); - } + if (smbldap_get_single_attribute(state->smbldap_state->ldap_struct, entry, + get_attr_key2string(dominfo_attr_list, LDAP_ATTR_ALGORITHMIC_RID_BASE), + algorithmic_rid_base_string)) + { - DEBUG(3,("LDAPS option set...!\n")); -#else - DEBUG(0,("ldap_idmap_open_connection: Secure " - "connection not supported by LDAP client " - "libraries!\n")); - return LDAP_OPERATIONS_ERROR; -#endif - } - } -#endif - - if (ldap_get_option(state->ldap_struct, LDAP_OPT_PROTOCOL_VERSION, - &version) == LDAP_OPT_SUCCESS) { - if (version != LDAP_VERSION3) { - version = LDAP_VERSION3; - if (ldap_set_option(state->ldap_struct, - LDAP_OPT_PROTOCOL_VERSION, - &version) == LDAP_OPT_SUCCESS) { - ldap_v3 = True; - } + alg_rid_base = (uint32)atol(algorithmic_rid_base_string); } else { - ldap_v3 = True; + alg_rid_base = algorithmic_rid_base(); + /* Try to make the modification atomically by enforcing the + old value in the delete mod. */ + slprintf(algorithmic_rid_base_string, sizeof(algorithmic_rid_base_string)-1, "%d", alg_rid_base); + smbldap_make_mod(state->smbldap_state->ldap_struct, entry, &mods, + get_attr_key2string(dominfo_attr_list, LDAP_ATTR_ALGORITHMIC_RID_BASE), + algorithmic_rid_base_string); } - } - if (lp_ldap_ssl() == LDAP_SSL_START_TLS) { -#ifdef LDAP_OPT_X_TLS - if (ldap_v3) { - if ((rc = ldap_start_tls_s(state->ldap_struct, NULL, - NULL)) != LDAP_SUCCESS) { - DEBUG(0,("Failed to issue the StartTLS " - "instruction: %s\n", - ldap_err2string(rc))); - return rc; + next_rid = 0; + + if (alg_rid_base > BASE_RID) { + /* we have a non-default 'algorithmic rid base', so we have 'low' rids that we + can allocate to new users */ + if (smbldap_get_single_attribute(state->smbldap_state->ldap_struct, entry, + get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_RID), + old_rid_string)) + { + *rid = (uint32)atol(old_rid_string); + } else { + *rid = BASE_RID; + } + + next_rid = *rid+1; + if (next_rid >= alg_rid_base) { + return NT_STATUS_UNSUCCESSFUL; } - DEBUG (3, ("StartTLS issued: using a TLS " - "connection\n")); - } else { - DEBUG(0, ("Need LDAPv3 for Start TLS\n")); - return LDAP_OPERATIONS_ERROR; + slprintf(next_rid_string, sizeof(next_rid_string)-1, "%d", next_rid); + + /* Try to make the modification atomically by enforcing the + old value in the delete mod. */ + smbldap_make_mod(state->smbldap_state->ldap_struct, entry, &mods, + get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_RID), + next_rid_string); } -#else - DEBUG(0,("ldap_idmap_open_connection: StartTLS not supported by " - "LDAP client libraries!\n")); - return LDAP_OPERATIONS_ERROR; -#endif - } - - DEBUG(2, ("ldap_idmap_open_connection: connection opened\n")); - return rc; -} -/********************************************************************** -Connect to LDAP server -*********************************************************************/ -static int ldap_idmap_open(struct ldap_idmap_state *state) -{ - int rc; - SMB_ASSERT(state); - -#ifndef NO_LDAP_SECURITY - if (geteuid() != 0) { - DEBUG(0, - ("ldap_idmap_open: cannot access LDAP when not root\n")); - return LDAP_INSUFFICIENT_ACCESS; - } -#endif - - if ((state->ldap_struct != NULL) && - ((state->last_ping + LDAP_IDMAP_DONT_PING_TIME)ldap_struct, LDAP_OPT_DESC, &sd)&& - getpeername(sd, (struct sockaddr *) &addr, &len) < 0) { - /* the other end has died. reopen. */ - ldap_unbind_ext(state->ldap_struct, NULL, NULL); - state->ldap_struct = NULL; - state->last_ping = (time_t)0; - } else { - state->last_ping = time(NULL); - } - } - - if (state->ldap_struct != NULL) { - DEBUG(5,("ldap_idmap_open: already connected to the LDAP " - "server\n")); - return LDAP_SUCCESS; - } - - if ((rc = ldap_idmap_open_connection(state))) { - return rc; - } - - if ((rc = ldap_idmap_connect_system(state))) { - ldap_unbind_ext(state->ldap_struct, NULL, NULL); - state->ldap_struct = NULL; - return rc; - } - - - state->last_ping = time(NULL); - DEBUG(4,("The LDAP server is succesful connected\n")); - - return LDAP_SUCCESS; -} + if (!next_rid) { /* not got one already */ + switch (rid_type) { + case USER_RID_TYPE: + if (smbldap_get_single_attribute(state->smbldap_state->ldap_struct, entry, + get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_USERRID), + old_rid_string)) + { + + *rid = (uint32)atol(old_rid_string); + + } else { + *rid = state->low_allocated_user_rid; + } + break; + case GROUP_RID_TYPE: + if (smbldap_get_single_attribute(state->smbldap_state->ldap_struct, entry, + get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_GROUPRID), + old_rid_string)) + { + *rid = (uint32)atol(old_rid_string); + } else { + *rid = state->low_allocated_group_rid; + } + break; + } + + /* This is the core of the whole routine. If we had + scheme-style closures, there would be a *lot* less code + duplication... */ -static int ldap_idmap_retry_open(struct ldap_idmap_state *state, int *attempts) -{ - int rc; + next_rid = *rid+RID_MULTIPLIER; + slprintf(next_rid_string, sizeof(next_rid_string)-1, "%d", next_rid); + + switch (rid_type) { + case USER_RID_TYPE: + if (next_rid > state->high_allocated_user_rid) { + return NT_STATUS_UNSUCCESSFUL; + } + + /* Try to make the modification atomically by enforcing the + old value in the delete mod. */ + smbldap_make_mod(state->smbldap_state->ldap_struct, entry, &mods, + get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_USERRID), + next_rid_string); + break; + + case GROUP_RID_TYPE: + if (next_rid > state->high_allocated_group_rid) { + return NT_STATUS_UNSUCCESSFUL; + } + + /* Try to make the modification atomically by enforcing the + old value in the delete mod. */ + smbldap_make_mod(state->smbldap_state->ldap_struct, entry, &mods, + get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_GROUPRID), + next_rid_string); + break; + } + } - SMB_ASSERT(state && attempts); + if ((rc = ldap_modify_s(state->smbldap_state->ldap_struct, dn, mods)) == LDAP_SUCCESS) { + DOM_SID dom_sid; + DOM_SID sid; + pstring domain_sid_string; + int error = 0; - if (*attempts != 0) { - unsigned int sleep_time; - uint8 rand_byte = 128; /* a reasonable place to start */ + if (!smbldap_get_single_attribute(state->smbldap_state->ldap_struct, domain_result, + get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOM_SID), + domain_sid_string)) + { + ldap_mods_free(mods, True); + ldap_memfree(dn); + ldap_msgfree(domain_result); + return ret; + } - generate_random_buffer(&rand_byte, 1, False); + if (!string_to_sid(&dom_sid, domain_sid_string)) { + ldap_mods_free(mods, True); + ldap_memfree(dn); + ldap_msgfree(domain_result); + return ret; + } - sleep_time = (((*attempts)*(*attempts))/2)*rand_byte*2; - /* we retry after (0.5, 1, 2, 3, 4.5, 6) seconds - on average. - */ - DEBUG(3, ("Sleeping for %u milliseconds before reconnecting\n", - sleep_time)); - msleep(sleep_time); - } - (*attempts)++; + ldap_mods_free(mods, True); + mods = NULL; + ldap_memfree(dn); + ldap_msgfree(domain_result); - if ((rc = ldap_idmap_open(state))) { - DEBUG(1,("Connection to LDAP Server failed for the %d try!\n", - *attempts)); - return rc; - } - - return LDAP_SUCCESS; -} + sid_copy(&sid, &dom_sid); + sid_append_rid(&sid, *rid); -/******************************************************************* - 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) -{ - struct ldap_idmap_state *state = arg; - - /** @TODO Should we be doing something to check what servers we rebind - to? Could we get a referral to a machine that we don't want to - give our username and password to? */ - - if (freeit) { - SAFE_FREE(*whop); - memset(*credp, '\0', strlen(*credp)); - SAFE_FREE(*credp); - } else { - DEBUG(5,("rebind_proc_with_state: Rebinding as \"%s\"\n", - state->bind_dn)); + /* check RID is not in use */ + if (sid_in_use(state, &sid, &error)) { + if (error) { + return ret; + } + continue; + } - *whop = strdup(state->bind_dn); - if (!*whop) { - return LDAP_NO_MEMORY; + return NT_STATUS_OK; } - *credp = strdup(state->bind_secret); - if (!*credp) { - SAFE_FREE(*whop); - return LDAP_NO_MEMORY; - } - *methodp = LDAP_AUTH_SIMPLE; - } - 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, - ber_int_t msgid, void *arg) -{ - struct ldap_idmap_state *state = arg; - int rc; - DEBUG(5,("rebindproc_connect_with_state: Rebinding as \"%s\"\n", - state->bind_dn)); - - /** @TODO Should we be doing something to check what servers we rebind - to? Could we get a referral to a machine that we don't want to - give our username and password to? */ - rc = ldap_simple_bind_s(ldap_struct, state->bind_dn, - state->bind_secret); - - 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 ) -{ - return rebindproc_with_state(ldap_struct, whop, credp, - method, freeit, &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, &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. -******************************************************************/ -static int ldap_idmap_connect_system(struct ldap_idmap_state *state) -{ - int rc; - char *ldap_dn; - char *ldap_secret; + ld_error = NULL; + ldap_get_option(state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error); + DEBUG(2, ("Failed to modify rid: %s\n", ld_error ? ld_error : "(NULL")); + SAFE_FREE(ld_error); - /* get the password */ - if (!fetch_ldapsam_pw(&ldap_dn, &ldap_secret)) - { - DEBUG(0, ("ldap_idmap_connect_system: Failed to retrieve " - "password from secrets.tdb\n")); - return LDAP_INVALID_CREDENTIALS; - } + ldap_mods_free(mods, True); + mods = NULL; - state->bind_dn = ldap_dn; - state->bind_secret = ldap_secret; + ldap_memfree(dn); + dn = NULL; - /* removed the sasl_bind_s "EXTERNAL" stuff, as my testsuite - (OpenLDAP) doesnt' seem to support it */ - - DEBUG(10,("ldap_idmap_connect_system: Binding to ldap server %s as " - "\"%s\"\n", state->uri, ldap_dn)); - -#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000) -# if LDAP_SET_REBIND_PROC_ARGS == 2 - ldap_set_rebind_proc(state->ldap_struct, &rebindproc_connect); -# endif -# if LDAP_SET_REBIND_PROC_ARGS == 3 - ldap_set_rebind_proc(state->ldap_struct, - &rebindproc_connect_with_state, (void *)state); -# endif -#else /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/ -# if LDAP_SET_REBIND_PROC_ARGS == 2 - ldap_set_rebind_proc(state->ldap_struct, &rebindproc); -# endif -# if LDAP_SET_REBIND_PROC_ARGS == 3 - ldap_set_rebind_proc(state->ldap_struct, &rebindproc_with_state, - (void *)state); -# endif -#endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/ - - rc = ldap_simple_bind_s(state->ldap_struct, ldap_dn, ldap_secret); + ldap_msgfree(domain_result); + domain_result = NULL; - if (rc != LDAP_SUCCESS) { - char *ld_error = NULL; - ldap_get_option(state->ldap_struct, LDAP_OPT_ERROR_STRING, - &ld_error); - DEBUG(state->num_failures ? 2 : 0, - ("failed to bind to server with dn= %s Error: " - "%s\n\t%s\n", - ldap_dn ? ld_error : "(unknown)", - ldap_err2string(rc), ld_error)); - SAFE_FREE(ld_error); - state->num_failures++; - return rc; + { + /* Sleep for a random timeout */ + unsigned sleeptime = (sys_random()*sys_getpid()*attempts); + attempts += 1; + + sleeptime %= 100; + msleep(sleeptime); + } } - state->num_failures = 0; - - DEBUG(3, ("ldap_idmap_connect_system: succesful connection to the " - "LDAP server\n")); - return rc; + DEBUG(0, ("Failed to set new RID\n")); + return ret; } -static int ldap_idmap_search(struct ldap_idmap_state *state, - const char *base, int scope, const char *filter, - const char *attrs[], int attrsonly, - LDAPMessage **res) -{ - int rc = LDAP_SERVER_DOWN; - int attempts = 0; - char *utf8_filter; - - SMB_ASSERT(state); - - if (push_utf8_allocate(&utf8_filter, filter) == (size_t)-1) { - return LDAP_NO_MEMORY; - } - - while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) { - if ((rc = ldap_idmap_retry_open(state, &attempts)) != - LDAP_SUCCESS) continue; - - rc = ldap_search_s(state->ldap_struct, base, scope, - utf8_filter, (char**)attrs, attrsonly, res); - } - - if (rc == LDAP_SERVER_DOWN) { - DEBUG(0,("ldap_idmap_search: LDAP server is down!\n")); - ldap_idmap_close(); - } - SAFE_FREE(utf8_filter); - return rc; -} +/***************************************************************************** + Allocate a new RID +*****************************************************************************/ -/******************************************************************* -search an attribute and return the first value found. -******************************************************************/ -static BOOL ldap_idmap_attribute (struct ldap_idmap_state *state, - LDAPMessage * entry, - const char *attribute, pstring value) +static NTSTATUS ldap_allocate_rid(uint32 *rid, int rid_type) { - char **values; - value[0] = '\0'; - - if ((values = ldap_get_values (state->ldap_struct, entry, attribute)) - == NULL) { - DEBUG(10,("get_single_attribute: [%s] = []\n", - attribute)); - return False; - } - if (convert_string(CH_UTF8, CH_UNIX, - values[0], -1, - value, sizeof(pstring)) == (size_t)-1) - { - DEBUG(1, ("ldap_idmap_attribute: string conversion of [%s] = " - "[%s] failed!\n", attribute, values[0])); - ldap_value_free(values); - return False; - } - ldap_value_free(values); - - return True; + return ldap_next_rid( &ldap_state, rid, rid_type ); } -static const char *attrs[] = {"objectClass", "uidNumber", "gidNumber", - "ntSid", NULL}; -static const char *pool_attr[] = {"uidNumber", "gidNumber", NULL}; +/***************************************************************************** + Allocate a new uid or gid +*****************************************************************************/ static NTSTATUS ldap_allocate_id(unid_t *id, int id_type) { NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; int rc = LDAP_SERVER_DOWN; int count = 0; - LDAPMessage *result = 0; - LDAPMessage *entry = 0; + LDAPMessage *result = NULL; + LDAPMessage *entry = NULL; pstring id_str, new_id_str; - LDAPMod mod[2]; - LDAPMod *mods[3]; - const char *type = (id_type & ID_USERID) ? "uidNumber" : "gidNumber"; - char *val[4]; + LDAPMod **mods = NULL; + const char *type; char *dn; + char **attr_list; + pstring filter; + uid_t luid, huid; + gid_t lgid, hgid; + - rc = ldap_idmap_search(&ldap_state, lp_ldap_suffix(), - LDAP_SCOPE_SUBTREE, "(objectClass=unixIdPool)", - pool_attr, 0, &result); + type = (id_type & ID_USERID) ? + get_attr_key2string( idpool_attr_list, LDAP_ATTR_UIDNUMBER ) : + get_attr_key2string( idpool_attr_list, LDAP_ATTR_GIDNUMBER ); + + snprintf(filter, sizeof(filter)-1, "(objectClass=%s)", LDAP_OBJ_IDPOOL); + + attr_list = get_attr_list( idpool_attr_list ); + + rc = smbldap_search(ldap_state.smbldap_state, lp_ldap_idmap_suffix(), + LDAP_SCOPE_SUBTREE, filter, + attr_list, 0, &result); + free_attr_list( attr_list ); + if (rc != LDAP_SUCCESS) { - DEBUG(0,("ldap_allocate_id: unixIdPool object not found\n")); + DEBUG(0,("ldap_allocate_id: %s object not found\n", LDAP_OBJ_IDPOOL)); goto out; } - count = ldap_count_entries(ldap_state.ldap_struct, result); + count = ldap_count_entries(ldap_state.smbldap_state->ldap_struct, result); if (count != 1) { - DEBUG(0,("ldap_allocate_id: single unixIdPool not found\n")); + DEBUG(0,("ldap_allocate_id: single %s object not found\n", LDAP_OBJ_IDPOOL)); goto out; } - dn = ldap_get_dn(ldap_state.ldap_struct, result); - entry = ldap_first_entry(ldap_state.ldap_struct, result); + dn = ldap_get_dn(ldap_state.smbldap_state->ldap_struct, result); + entry = ldap_first_entry(ldap_state.smbldap_state->ldap_struct, result); - if (!ldap_idmap_attribute(&ldap_state, entry, type, id_str)) { + if (!smbldap_get_single_attribute(ldap_state.smbldap_state->ldap_struct, entry, type, id_str)) { DEBUG(0,("ldap_allocate_id: %s attribute not found\n", type)); goto out; } + + /* this must succeed or else we wouldn't have initialized */ + + lp_idmap_uid( &luid, &huid); + lp_idmap_gid( &lgid, &hgid); + + /* make sure we still have room to grow */ + if (id_type & ID_USERID) { id->uid = strtoul(id_str, NULL, 10); - } else { + if (id->uid > huid ) { + DEBUG(0,("ldap_allocate_id: Cannot allocate uid above %d!\n", huid)); + goto out; + } + } + else { id->gid = strtoul(id_str, NULL, 10); + if (id->gid > hgid ) { + DEBUG(0,("ldap_allocate_id: Cannot allocate gid above %d!\n", hgid)); + goto out; + } } - - mod[0].mod_op = LDAP_MOD_DELETE; - mod[0].mod_type = strdup(type); - val[0] = id_str; val[1] = NULL; - mod[0].mod_values = val; - - pstr_sprintf(new_id_str, "%ud", + + snprintf(new_id_str, sizeof(new_id_str), "%u", ((id_type & ID_USERID) ? id->uid : id->gid) + 1); - mod[1].mod_op = LDAP_MOD_ADD; - mod[1].mod_type = strdup(type); - val[3] = new_id_str; val[4] = NULL; - mod[1].mod_values = val + 2; + + smbldap_set_mod( &mods, LDAP_MOD_DELETE, type, id_str ); + smbldap_set_mod( &mods, LDAP_MOD_ADD, type, new_id_str ); + + rc = ldap_modify_s(ldap_state.smbldap_state->ldap_struct, dn, mods); - mods[0] = mod; mods[1] = mod + 1; mods[2] = NULL; - rc = ldap_modify_s(ldap_state.ldap_struct, dn, mods); ldap_memfree(dn); - - if (rc == LDAP_SUCCESS) ret = NT_STATUS_OK; + ldap_mods_free( mods, True ); + + if (rc != LDAP_SUCCESS) { + DEBUG(0,("ldap_allocate_id: Failed to allocate new %s. ldap_modify() failed.\n", + type)); + goto out; + } + + ret = NT_STATUS_OK; out: return ret; } -/* Get a sid from an id */ +/***************************************************************************** + get a sid from an id +*****************************************************************************/ + static NTSTATUS ldap_get_sid_from_id(DOM_SID *sid, unid_t id, int id_type) { - LDAPMessage *result = 0; - LDAPMessage *entry = 0; + LDAPMessage *result = NULL; + LDAPMessage *entry = NULL; + fstring id_str; pstring sid_str; pstring filter; - char type = (id_type & ID_USERID) ? 'u' : 'g'; + pstring suffix; + const char *type; + const char *obj_class; int rc; int count; NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; - - pstr_sprintf(filter, "(&(%cidNumber=%ud)(objectClass=sambaAccount))", - type, ((id_type & ID_USERID) ? id.uid : id.gid)); - rc = ldap_idmap_search(&ldap_state, lp_ldap_suffix(), - LDAP_SCOPE_SUBTREE, filter, attrs, 0, - &result); - if (rc != LDAP_SUCCESS) { + char **attr_list; + + /* first we try for a samba user or group mapping */ + + if ( id_type & ID_USERID ) { + type = get_attr_key2string( idpool_attr_list, LDAP_ATTR_UIDNUMBER ); + obj_class = LDAP_OBJ_SAMBASAMACCOUNT; + snprintf(id_str, sizeof(id_str), "%u", id.uid ); + pstrcpy( suffix, lp_ldap_suffix()); + } + else { + type = get_attr_key2string( idpool_attr_list, LDAP_ATTR_GIDNUMBER ); + obj_class = LDAP_OBJ_GROUPMAP; + snprintf(id_str, sizeof(id_str), "%u", id.gid ); + pstrcpy( suffix, lp_ldap_group_suffix() ); + } + + attr_list = get_attr_list( sidmap_attr_list ); + snprintf(filter, sizeof(filter), "(&(|(objectClass=%s)(objectClass=%s))(%s=%s))", + LDAP_OBJ_IDMAP_ENTRY, obj_class, type, id_str); + + rc = smbldap_search(ldap_state.smbldap_state, suffix, LDAP_SCOPE_SUBTREE, + filter, attr_list, 0, &result); + + if (rc != LDAP_SUCCESS) goto out; - } + + count = ldap_count_entries(ldap_state.smbldap_state->ldap_struct, result); + + /* fall back to looking up an idmap entry if we didn't find and + actual user or group */ - count = ldap_count_entries(ldap_state.ldap_struct, result); if (count == 0) { - pstr_sprintf(filter, - "(&(objectClass=idmapEntry)(%cidNumber=%ud))", - type, ((id_type & ID_USERID) ? id.uid : id.gid)); - rc = ldap_idmap_search(&ldap_state, lp_ldap_suffix(), - LDAP_SCOPE_SUBTREE, filter, - attrs, 0, &result); - if (rc != LDAP_SUCCESS) { + ldap_msgfree(result); + result = NULL; + + snprintf(filter, sizeof(filter), "(&(objectClass=%s)(%s=%u))", + LDAP_OBJ_IDMAP_ENTRY, type, ((id_type & ID_USERID) ? id.uid : id.gid)); + + pstrcpy( suffix, lp_ldap_idmap_suffix() ); + + rc = smbldap_search(ldap_state.smbldap_state, suffix, LDAP_SCOPE_SUBTREE, + filter, attr_list, 0, &result); + + if (rc != LDAP_SUCCESS) goto out; - } - count = ldap_count_entries(ldap_state.ldap_struct, result); + + count = ldap_count_entries(ldap_state.smbldap_state->ldap_struct, result); } if (count != 1) { - DEBUG(0,("ldap_get_sid_from_id: mapping not found for " - "%cid: %ud\n", (id_type&ID_USERID)?'u':'g', - ((id_type & ID_USERID) ? id.uid : id.gid))); + DEBUG(0,("ldap_get_sid_from_id: mapping not found for %s: %u\n", + type, ((id_type & ID_USERID) ? id.uid : id.gid))); goto out; } - entry = ldap_first_entry(ldap_state.ldap_struct, result); + entry = ldap_first_entry(ldap_state.smbldap_state->ldap_struct, result); - if (!ldap_idmap_attribute(&ldap_state, entry, "ntSid", sid_str)) { + if ( !smbldap_get_single_attribute(ldap_state.smbldap_state->ldap_struct, entry, LDAP_ATTRIBUTE_SID, sid_str) ) goto out; - } - if (!string_to_sid(sid, sid_str)) { + if (!string_to_sid(sid, sid_str)) goto out; - } ret = NT_STATUS_OK; out: + free_attr_list( attr_list ); + + if (result) + ldap_msgfree(result); + return ret; } -/* Get an id from a sid */ -static NTSTATUS ldap_get_id_from_sid(unid_t *id, int *id_type, - const DOM_SID *sid) +/*********************************************************************** + Get an id from a sid +***********************************************************************/ + +static NTSTATUS ldap_get_id_from_sid(unid_t *id, int *id_type, const DOM_SID *sid) { - LDAPMessage *result = 0; - LDAPMessage *entry = 0; + LDAPMessage *result = NULL; + LDAPMessage *entry = NULL; pstring sid_str; pstring filter; pstring id_str; - const char *type = (*id_type & ID_USERID) ? "uidNumber" : "gidNumber"; - const char *class = - (*id_type & ID_USERID) ? "sambaAccount" : "sambaGroupMapping"; + const char *suffix; + const char *type; + const char *obj_class; + const char *posix_obj_class; int rc; int count; + char **attr_list; + char *dn = NULL; NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; - + + /* first try getting the mapping from a samba user or group */ + sid_to_string(sid_str, sid); - pstr_sprintf(filter, "(&(objectClass=%s)(ntSid=%s)", class, sid_str); - rc = ldap_idmap_search(&ldap_state, lp_ldap_suffix(), - LDAP_SCOPE_SUBTREE, filter, attrs, 0, &result); - if (rc != LDAP_SUCCESS) { - goto out; + if ( *id_type & ID_USERID ) { + type = get_attr_key2string( sidmap_attr_list, LDAP_ATTR_UIDNUMBER ); + obj_class = LDAP_OBJ_SAMBASAMACCOUNT; + posix_obj_class = LDAP_OBJ_POSIXACCOUNT; + suffix = lp_ldap_suffix(); + snprintf(filter, sizeof(filter), + "(&(|(&(objectClass=%s)(objectClass=%s))(objectClass=%s))(%s=%s))", + obj_class, posix_obj_class, LDAP_OBJ_IDMAP_ENTRY, + get_attr_key2string( sidmap_attr_list, LDAP_ATTR_SID ), + sid_str); + } + else { + type = get_attr_key2string( sidmap_attr_list, LDAP_ATTR_GIDNUMBER ); + obj_class = LDAP_OBJ_GROUPMAP; + posix_obj_class = LDAP_OBJ_POSIXGROUP; + suffix = lp_ldap_group_suffix(); + snprintf(filter, sizeof(filter), + "(&(|(objectClass=%s)(objectClass=%s))(%s=%s))", + obj_class, LDAP_OBJ_IDMAP_ENTRY, + get_attr_key2string( sidmap_attr_list, LDAP_ATTR_SID ), + sid_str); } - count = ldap_count_entries(ldap_state.ldap_struct, result); + + attr_list = get_attr_list( sidmap_attr_list ); + rc = smbldap_search(ldap_state.smbldap_state, suffix, LDAP_SCOPE_SUBTREE, + filter, attr_list, 0, &result); + + if (rc != LDAP_SUCCESS) + goto out; + + count = ldap_count_entries(ldap_state.smbldap_state->ldap_struct, result); + + /* fall back to looking up an idmap entry if we didn't find anything under the idmap + user or group suffix */ + if (count == 0) { - pstr_sprintf(filter, - "(&(objectClass=idmapEntry)(ntSid=%s))", sid_str); + ldap_msgfree(result); + + snprintf(filter, sizeof(filter), "(&(objectClass=%s)(%s=%s))", + LDAP_OBJ_IDMAP_ENTRY, LDAP_ATTRIBUTE_SID, sid_str); - rc = ldap_idmap_search(&ldap_state, lp_ldap_suffix(), - LDAP_SCOPE_SUBTREE, filter, - attrs, 0, &result); - if (rc != LDAP_SUCCESS) { - goto out; - } - count = ldap_count_entries(ldap_state.ldap_struct, result); - } + suffix = lp_ldap_idmap_suffix(); - /* our search filters may 2 objects in the case that a user and group - rid are the same */ - if (count != 1 && count != 2) { - DEBUG(0, - ("ldap_get_id_from_sid: incorrect number of objects\n")); + rc = smbldap_search(ldap_state.smbldap_state, suffix, LDAP_SCOPE_SUBTREE, + filter, attr_list, 0, &result); + + if (rc != LDAP_SUCCESS) + goto out; + + count = ldap_count_entries(ldap_state.smbldap_state->ldap_struct, result); + } + + if ( count > 1 ) { + DEBUG(0, ("ldap_get_id_from_sid: search %s returned more than on entry!\n", + filter)); goto out; } - entry = ldap_first_entry(ldap_state.ldap_struct, result); - if (!ldap_idmap_attribute(&ldap_state, entry, type, id_str)) { - entry = ldap_next_entry(ldap_state.ldap_struct, entry); - - if (!ldap_idmap_attribute(&ldap_state, entry, type, id_str)) { - int i; - - for (i = 0; i < LDAP_MAX_ALLOC_ID; i++) { - ret = ldap_allocate_id(id, *id_type); - if (NT_STATUS_IS_OK(ret)) { - break; - } - } - if (NT_STATUS_IS_OK(ret)) { - ret = ldap_set_mapping(sid, *id, *id_type); - } else { - DEBUG(0,("ldap_allocate_id: cannot acquire id" - " lock\n")); - } - } else { - if ((*id_type & ID_USERID)) { + /* we might have an existing entry to work with so pull out the requested information */ + + if ( count ) { + entry = ldap_first_entry(ldap_state.smbldap_state->ldap_struct, result); + + dn = ldap_get_dn(ldap_state.smbldap_state->ldap_struct, result); + DEBUG(10, ("Found mapping entry at dn=%s, looking for %s\n", dn, type)); + + if ( smbldap_get_single_attribute(ldap_state.smbldap_state->ldap_struct, entry, type, id_str) ) + { + if ( (*id_type & ID_USERID) ) id->uid = strtoul(id_str, NULL, 10); - } else { + else id->gid = strtoul(id_str, NULL, 10); - } + ret = NT_STATUS_OK; + goto out; } - } else { - if ((*id_type & ID_USERID)) { - id->uid = strtoul(id_str, NULL, 10); - } else { - id->gid = strtoul(id_str, NULL, 10); + } + + if (!(*id_type & ID_QUERY_ONLY)) { + /* if entry == NULL, and we are asked to - allocate a new id */ + int i; + + for (i = 0; i < LDAP_MAX_ALLOC_ID; i++) + { + ret = ldap_allocate_id(id, *id_type); + if ( NT_STATUS_IS_OK(ret) ) + break; + } + + if ( !NT_STATUS_IS_OK(ret) ) { + DEBUG(0,("ldap_allocate_id: cannot acquire id lock!\n")); + goto out; } - ret = NT_STATUS_OK; + + ret = ldap_set_mapping(sid, *id, *id_type); + } else { + /* no match, and not adding one */ + ret = NT_STATUS_UNSUCCESSFUL; } + out: + free_attr_list( attr_list ); + if (result) + ldap_msgfree(result); + if (dn) + ldap_memfree(dn); + return ret; } -/* This function cannot be called to modify a mapping, only set a new one */ -static NTSTATUS ldap_set_mapping(const DOM_SID *sid, unid_t id, int id_type) +/*********************************************************************** + This function cannot be called to modify a mapping, only set a new one + + This takes a possible pointer to the existing entry for the UID or SID + involved. +***********************************************************************/ + +static NTSTATUS ldap_set_mapping_internals(const DOM_SID *sid, unid_t id, + int id_type, const char *ldap_dn, + LDAPMessage *entry) { - pstring dn, sid_str, id_str; - const char *type = (id_type & ID_USERID) ? "uidNumber" : "gidNumber"; - LDAPMod *mods[3]; - LDAPMod mod[2]; - char *val[4]; - int rc; - int attempts = 0; + char *dn = NULL; + pstring id_str; + fstring type; + LDAPMod **mods = NULL; + int rc = -1; + int ldap_op; + fstring sid_string; + char **values = NULL; + int i; + + sid_to_string( sid_string, sid ); + + if (ldap_dn) { + DEBUG(10, ("Adding new IDMAP mapping on DN: %s", ldap_dn)); + ldap_op = LDAP_MOD_REPLACE; + dn = strdup(ldap_dn); + } else { + ldap_op = LDAP_MOD_ADD; + asprintf(&dn, "%s=%s,%s", get_attr_key2string( sidmap_attr_list, LDAP_ATTR_SID), + sid_string, lp_ldap_idmap_suffix()); + } + + if (!dn) { + DEBUG(0, ("ldap_set_mapping_internals: out of memory allocating DN!\n")); + return NT_STATUS_NO_MEMORY; + } - pstr_sprintf(id_str, "%ud", ((id_type & ID_USERID) ? id.uid : id.gid)); - sid_to_string(sid_str, sid); - pstr_sprintf(dn, "%s=%ud,%s", type, ((id_type & ID_USERID) ? id.uid : id.gid), lp_ldap_suffix()); - mod[0].mod_op = LDAP_MOD_REPLACE; - mod[0].mod_type = strdup(type); - val[0] = id_str; val[1] = NULL; - mod[0].mod_values = val; - - mod[1].mod_op = LDAP_MOD_REPLACE; - mod[1].mod_type = strdup("ntSid"); - val[2] = sid_str; val[3] = NULL; - mod[1].mod_values = val + 2; - - mods[0] = mod; mods[1] = mod + 1; mods[2] = NULL; - - do { - if ((rc = ldap_idmap_retry_open(&ldap_state, &attempts)) != - LDAP_SUCCESS) continue; + if ( id_type & ID_USERID ) + fstrcpy( type, get_attr_key2string( sidmap_attr_list, LDAP_ATTR_UIDNUMBER ) ); + else + fstrcpy( type, get_attr_key2string( sidmap_attr_list, LDAP_ATTR_GIDNUMBER ) ); + + snprintf(id_str, sizeof(id_str), "%u", ((id_type & ID_USERID) ? id.uid : id.gid)); + + if (entry) + values = ldap_get_values(ldap_state.smbldap_state->ldap_struct, entry, "objectClass"); + + if (values) { + BOOL found_idmap = False; + for (i=0; values[i]; i++) { + if (StrCaseCmp(values[i], LDAP_OBJ_IDMAP_ENTRY) == 0) { + found_idmap = True; + break; + } + } + if (!found_idmap) + smbldap_set_mod( &mods, LDAP_MOD_ADD, + "objectClass", LDAP_OBJ_IDMAP_ENTRY ); + } else { + smbldap_set_mod( &mods, LDAP_MOD_ADD, + "objectClass", LDAP_OBJ_IDMAP_ENTRY ); + } + + smbldap_make_mod( ldap_state.smbldap_state->ldap_struct, + entry, &mods, type, id_str ); + + smbldap_make_mod( ldap_state.smbldap_state->ldap_struct, + entry, &mods, + get_attr_key2string(sidmap_attr_list, LDAP_ATTR_SID), + sid_string ); + + /* There may well be nothing at all to do */ + if (mods) { + switch(ldap_op) + { + case LDAP_MOD_ADD: + smbldap_set_mod( &mods, LDAP_MOD_ADD, + "objectClass", LDAP_OBJ_SID_ENTRY ); + rc = smbldap_add(ldap_state.smbldap_state, dn, mods); + break; + case LDAP_MOD_REPLACE: + rc = smbldap_modify(ldap_state.smbldap_state, dn, mods); + break; + } - rc = ldap_modify_s(ldap_state.ldap_struct, dn, mods); - } while ((rc == LDAP_SERVER_DOWN) && (attempts <= 8)); + ldap_mods_free( mods, True ); + } else { + rc = LDAP_SUCCESS; + } if (rc != LDAP_SUCCESS) { + char *ld_error = NULL; + ldap_get_option(ldap_state.smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, + &ld_error); + DEBUG(0,("ldap_set_mapping_internals: Failed to %s mapping from %s to %u [%s]\n", + (ldap_op == LDAP_MOD_ADD) ? "add" : "replace", + sid_string, (unsigned int)((id_type & ID_USERID) ? id.uid : id.gid), type)); + DEBUG(0, ("ldap_set_mapping_internals: Error was: %s (%s)\n", ld_error ? ld_error : "(NULL)", ldap_err2string (rc))); return NT_STATUS_UNSUCCESSFUL; } + + DEBUG(10,("ldap_set_mapping: Successfully created mapping from %s to %d [%s]\n", + sid_string, ((id_type & ID_USERID) ? id.uid : id.gid), type)); return NT_STATUS_OK; } +/*********************************************************************** + This function cannot be called to modify a mapping, only set a new one +***********************************************************************/ + +static NTSTATUS ldap_set_mapping(const DOM_SID *sid, unid_t id, int id_type) +{ + NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; + char *dn = NULL; + LDAPMessage *result = NULL; + LDAPMessage *entry = NULL; + const char *type; + const char *obj_class; + const char *posix_obj_class; + const char *suffix; + fstring sid_str; + fstring id_str; + pstring filter; + char **attr_list; + int rc; + int count; + + /* try for a samba user or group mapping (looking for an entry with a SID) */ + if ( id_type & ID_USERID ) { + obj_class = LDAP_OBJ_SAMBASAMACCOUNT; + suffix = lp_ldap_suffix(); + type = get_attr_key2string( idpool_attr_list, LDAP_ATTR_UIDNUMBER ); + posix_obj_class = LDAP_OBJ_POSIXACCOUNT; + snprintf(id_str, sizeof(id_str), "%u", id.uid ); + } + else { + obj_class = LDAP_OBJ_GROUPMAP; + suffix = lp_ldap_group_suffix(); + type = get_attr_key2string( idpool_attr_list, LDAP_ATTR_GIDNUMBER ); + posix_obj_class = LDAP_OBJ_POSIXGROUP; + snprintf(id_str, sizeof(id_str), "%u", id.gid ); + } + + sid_to_string(sid_str, sid); + snprintf(filter, sizeof(filter), + "(|" + "(&(|(objectClass=%s)(|(objectClass=%s)(objectClass=%s)))(%s=%s))" + "(&(objectClass=%s)(%s=%s))" + ")", + /* objectClasses that might contain a SID */ + LDAP_OBJ_SID_ENTRY, LDAP_OBJ_IDMAP_ENTRY, obj_class, + get_attr_key2string( sidmap_attr_list, LDAP_ATTR_SID ), + sid_str, + + /* objectClasses that might contain a Unix UID/GID */ + posix_obj_class, + /* Unix UID/GID specifier*/ + type, + /* actual ID */ + id_str); + + attr_list = get_attr_list( sidmap_attr_list ); + rc = smbldap_search(ldap_state.smbldap_state, suffix, LDAP_SCOPE_SUBTREE, + filter, attr_list, 0, &result); + free_attr_list( attr_list ); + + if (rc != LDAP_SUCCESS) + goto out; + + count = ldap_count_entries(ldap_state.smbldap_state->ldap_struct, result); + + /* fall back to looking up an idmap entry if we didn't find anything under the idmap + user or group suffix */ + + if (count == 1) { + entry = ldap_first_entry(ldap_state.smbldap_state->ldap_struct, result); + + dn = ldap_get_dn(ldap_state.smbldap_state->ldap_struct, result); + DEBUG(10, ("Found partial mapping entry at dn=%s, looking for %s\n", dn, type)); + + ret = ldap_set_mapping_internals(sid, id, id_type, dn, entry); + + goto out; + } else if (count > 1) { + DEBUG(0, ("Too many entries trying to find DN to attach ldap \n")); + goto out; + } + + ret = ldap_set_mapping_internals(sid, id, id_type, NULL, NULL); + +out: + if (result) + ldap_msgfree(result); + if (dn) + ldap_memfree(dn); + + return ret; +} /***************************************************************************** Initialise idmap database. *****************************************************************************/ -static NTSTATUS ldap_idmap_init(void) +static NTSTATUS ldap_idmap_init( char *params ) { - /* We wait for the first search request before we try to connect to - the LDAP server. We may want to connect upon initialization though - -- aliguori */ + fstring filter; + int rc; + char **attr_list; + LDAPMessage *result = NULL; + LDAPMod **mods = NULL; + int count; + NTSTATUS nt_status; + + ldap_state.mem_ctx = talloc_init("idmap_ldap"); + if (!ldap_state.mem_ctx) { + return NT_STATUS_NO_MEMORY; + } + + /* assume location is the only parameter */ + if (!NT_STATUS_IS_OK(nt_status = + smbldap_init(ldap_state.mem_ctx, params, + &ldap_state.smbldap_state))) { + talloc_destroy(ldap_state.mem_ctx); + return nt_status; + } + + /* see if the idmap suffix and sub entries exists */ + + snprintf( filter, sizeof(filter), "(objectclass=%s)", LDAP_OBJ_IDPOOL ); + + attr_list = get_attr_list( idpool_attr_list ); + rc = smbldap_search(ldap_state.smbldap_state, lp_ldap_idmap_suffix(), + LDAP_SCOPE_SUBTREE, filter, attr_list, 0, &result); + free_attr_list ( attr_list ); + + if (rc != LDAP_SUCCESS) + return NT_STATUS_UNSUCCESSFUL; + + count = ldap_count_entries(ldap_state.smbldap_state->ldap_struct, result); + + if ( count > 1 ) { + DEBUG(0,("ldap_idmap_init: multiple entries returned from %s (base == %s)\n", + filter, lp_ldap_idmap_suffix() )); + return NT_STATUS_UNSUCCESSFUL; + } + else if (count == 0) { + uid_t luid, huid; + gid_t lgid, hgid; + fstring uid_str, gid_str; + + if ( !lp_idmap_uid(&luid, &huid) || !lp_idmap_gid( &lgid, &hgid ) ) { + DEBUG(0,("ldap_idmap_init: idmap uid/gid parameters not specified\n")); + return NT_STATUS_UNSUCCESSFUL; + } + + snprintf( uid_str, sizeof(uid_str), "%d", luid ); + snprintf( gid_str, sizeof(gid_str), "%d", lgid ); + + smbldap_set_mod( &mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_IDPOOL ); + smbldap_set_mod( &mods, LDAP_MOD_ADD, + get_attr_key2string(idpool_attr_list, LDAP_ATTR_UIDNUMBER), uid_str ); + smbldap_set_mod( &mods, LDAP_MOD_ADD, + get_attr_key2string(idpool_attr_list, LDAP_ATTR_GIDNUMBER), gid_str ); + + rc = smbldap_modify(ldap_state.smbldap_state, lp_ldap_idmap_suffix(), mods); + } + return NT_STATUS_OK; } -/* End the LDAP session */ +/***************************************************************************** + End the LDAP session +*****************************************************************************/ + static NTSTATUS ldap_idmap_close(void) { - if (ldap_state.ldap_struct != NULL) { - ldap_unbind_ext(ldap_state.ldap_struct, NULL, NULL); - ldap_state.ldap_struct = NULL; - } + + smbldap_free_struct(&(ldap_state).smbldap_state); + talloc_destroy(ldap_state.mem_ctx); DEBUG(5,("The connection to the LDAP server was closed\n")); /* maybe free the results here --metze */ @@ -823,6 +955,8 @@ static void ldap_idmap_status(void) static struct idmap_methods ldap_methods = { ldap_idmap_init, + ldap_allocate_rid, + ldap_allocate_id, ldap_get_sid_from_id, ldap_get_id_from_sid, ldap_set_mapping, @@ -833,6 +967,5 @@ static struct idmap_methods ldap_methods = { NTSTATUS idmap_ldap_init(void) { - DEBUG(0,("idmap_reg_ldap: no LDAP support\n")); return smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION, "ldap", &ldap_methods); } diff --git a/source3/sam/idmap_tdb.c b/source3/sam/idmap_tdb.c index 31c12241bf..7f8dce1f1a 100644 --- a/source3/sam/idmap_tdb.c +++ b/source3/sam/idmap_tdb.c @@ -45,44 +45,126 @@ static struct idmap_state { gid_t gid_low, gid_high; /* Range of gids to allocate */ } idmap_state; -/* Allocate either a user or group id from the pool */ +/********************************************************************** + Return the TDB_CONTEXT* for winbindd_idmap. I **really** feel + dirty doing this, but not so dirty that I want to create another + tdb +***********************************************************************/ + +TDB_CONTEXT *idmap_tdb_handle( void ) +{ + if ( idmap_tdb ) + return idmap_tdb; + + return NULL; +} + +/********************************************************************** + allocate a new RID; We don't care if is a user or group +**********************************************************************/ + +static NTSTATUS db_allocate_rid(uint32 *rid, int rid_type) +{ + uint32 lowrid, highrid; + uint32 tmp_rid; + + /* can't handle group rids right now. This is such a mess.... */ + + if ( rid_type == GROUP_RID_TYPE ) + return NT_STATUS_UNSUCCESSFUL; + + /* cannot fail since idmap is only called winbindd */ + + idmap_get_free_rid_range( &lowrid, &highrid ); + + tmp_rid = lowrid; + + if ( !tdb_change_uint32_atomic(idmap_tdb, "RID_COUNTER", &tmp_rid, RID_MULTIPLIER) ) { + DEBUG(3,("db_allocate_rid: Failed to locate next rid record in idmap db\n")); + return NT_STATUS_UNSUCCESSFUL; + } + + if ( tmp_rid > highrid ) { + DEBUG(0, ("db_allocate_rid: no RIDs available!\n")); + return NT_STATUS_UNSUCCESSFUL; + } + + *rid = tmp_rid; + + return NT_STATUS_OK; +} + +/********************************************************************** + Allocate either a user or group id from the pool +**********************************************************************/ + static NTSTATUS db_allocate_id(unid_t *id, int id_type) { + BOOL ret; int hwm; - if (!id) return NT_STATUS_INVALID_PARAMETER; + if (!id) + return NT_STATUS_INVALID_PARAMETER; /* Get current high water mark */ switch (id_type & ID_TYPEMASK) { case ID_USERID: + if ((hwm = tdb_fetch_int32(idmap_tdb, HWM_USER)) == -1) { return NT_STATUS_INTERNAL_DB_ERROR; } + /* check it is in the range */ if (hwm > idmap_state.uid_high) { DEBUG(0, ("idmap Fatal Error: UID range full!! (max: %u)\n", idmap_state.uid_high)); return NT_STATUS_UNSUCCESSFUL; } - (*id).uid = hwm++; + /* fetch a new id and increment it */ + ret = tdb_change_uint32_atomic(idmap_tdb, HWM_USER, &hwm, 1); + if (!ret) { + DEBUG(0, ("idmap_tdb: Fatal error while fetching a new id\n!")); + return NT_STATUS_UNSUCCESSFUL; + } + + /* recheck it is in the range */ + if (hwm > idmap_state.uid_high) { + DEBUG(0, ("idmap Fatal Error: UID range full!! (max: %u)\n", idmap_state.uid_high)); + return NT_STATUS_UNSUCCESSFUL; + } + + (*id).uid = hwm; + DEBUG(10,("db_allocate_id: ID_USERID (*id).uid = %d\n", (unsigned int)hwm)); - /* Store new high water mark */ - tdb_store_int32(idmap_tdb, HWM_USER, hwm); break; case ID_GROUPID: if ((hwm = tdb_fetch_int32(idmap_tdb, HWM_GROUP)) == -1) { return NT_STATUS_INTERNAL_DB_ERROR; } + /* check it is in the range */ if (hwm > idmap_state.gid_high) { DEBUG(0, ("idmap Fatal Error: GID range full!! (max: %u)\n", idmap_state.gid_high)); return NT_STATUS_UNSUCCESSFUL; } - (*id).gid = hwm++; + /* fetch a new id and increment it */ + ret = tdb_change_uint32_atomic(idmap_tdb, HWM_GROUP, &hwm, 1); + + if (!ret) { + DEBUG(0, ("idmap_tdb: Fatal error while fetching a new id\n!")); + return NT_STATUS_UNSUCCESSFUL; + } + + /* recheck it is in the range */ + if (hwm > idmap_state.gid_high) { + DEBUG(0, ("idmap Fatal Error: GID range full!! (max: %u)\n", idmap_state.gid_high)); + return NT_STATUS_UNSUCCESSFUL; + } + + (*id).gid = hwm; + DEBUG(10,("db_allocate_id: ID_GROUPID (*id).gid = %d\n", (unsigned int)hwm)); - /* Store new high water mark */ - tdb_store_int32(idmap_tdb, HWM_GROUP, hwm); break; default: return NT_STATUS_INVALID_PARAMETER; @@ -92,13 +174,14 @@ static NTSTATUS db_allocate_id(unid_t *id, int id_type) } /* Get a sid from an id */ -static NTSTATUS db_get_sid_from_id(DOM_SID *sid, unid_t id, int id_type) +static NTSTATUS internal_get_sid_from_id(DOM_SID *sid, unid_t id, int id_type) { TDB_DATA key, data; fstring keystr; NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; - if (!sid) return NT_STATUS_INVALID_PARAMETER; + if (!sid) + return NT_STATUS_INVALID_PARAMETER; switch (id_type & ID_TYPEMASK) { case ID_USERID: @@ -114,10 +197,13 @@ static NTSTATUS db_get_sid_from_id(DOM_SID *sid, unid_t id, int id_type) key.dptr = keystr; key.dsize = strlen(keystr) + 1; + DEBUG(10,("internal_get_sid_from_id: fetching record %s\n", keystr )); + data = tdb_fetch(idmap_tdb, key); if (data.dptr) { if (string_to_sid(sid, data.dptr)) { + DEBUG(10,("internal_get_sid_from_id: fetching record %s -> %s\n", keystr, data.dptr )); ret = NT_STATUS_OK; } SAFE_FREE(data.dptr); @@ -126,14 +212,15 @@ static NTSTATUS db_get_sid_from_id(DOM_SID *sid, unid_t id, int id_type) return ret; } -/* Get an id from a sid */ -static NTSTATUS db_get_id_from_sid(unid_t *id, int *id_type, const DOM_SID *sid) +/* Error codes for get_id_from_sid */ +enum getidfromsiderr { GET_ID_FROM_SID_OK = 0, GET_ID_FROM_SID_NOTFOUND, GET_ID_FROM_SID_WRONG_TYPE, GET_ID_FROM_SID_ERR }; + +static enum getidfromsiderr internal_get_id_from_sid(unid_t *id, int *id_type, const DOM_SID *sid) { - TDB_DATA data, key; + enum getidfromsiderr ret = GET_ID_FROM_SID_ERR; fstring keystr; - NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; - - if (!sid || !id || !id_type) return NT_STATUS_INVALID_PARAMETER; + TDB_DATA key, data; + int type = *id_type & ID_TYPEMASK; /* Check if sid is present in database */ sid_to_string(keystr, sid); @@ -141,71 +228,186 @@ static NTSTATUS db_get_id_from_sid(unid_t *id, int *id_type, const DOM_SID *sid) key.dptr = keystr; key.dsize = strlen(keystr) + 1; + DEBUG(10,("internal_get_id_from_sid: fetching record %s of type 0x%x\n", keystr, type )); + data = tdb_fetch(idmap_tdb, key); + if (!data.dptr) { + DEBUG(10,("internal_get_id_from_sid: record %s not found\n", keystr )); + return GET_ID_FROM_SID_NOTFOUND; + } else { + DEBUG(10,("internal_get_id_from_sid: record %s -> %s\n", keystr, data.dptr )); + } - if (data.dptr) { - int type = *id_type & ID_TYPEMASK; + if (type == ID_EMPTY || type == ID_USERID) { fstring scanstr; + /* Parse and return existing uid */ + fstrcpy(scanstr, "UID %d"); + + if (sscanf(data.dptr, scanstr, &((*id).uid)) == 1) { + /* uid ok? */ + if (type == ID_EMPTY) { + *id_type = ID_USERID; + } + DEBUG(10,("internal_get_id_from_sid: %s fetching record %s -> %s \n", + (type == ID_EMPTY) ? "ID_EMPTY" : "ID_USERID", + keystr, data.dptr )); + ret = GET_ID_FROM_SID_OK; + } else { + ret = GET_ID_FROM_SID_WRONG_TYPE; + } + } + + if ((ret != GET_ID_FROM_SID_OK) && (type == ID_EMPTY || type == ID_GROUPID)) { + fstring scanstr; + /* Parse and return existing gid */ + fstrcpy(scanstr, "GID %d"); + + if (sscanf(data.dptr, scanstr, &((*id).gid)) == 1) { + /* gid ok? */ + if (type == ID_EMPTY) { + *id_type = ID_GROUPID; + } + DEBUG(10,("internal_get_id_from_sid: %s fetching record %s -> %s \n", + (type == ID_EMPTY) ? "ID_EMPTY" : "ID_GROUPID", + keystr, data.dptr )); + ret = GET_ID_FROM_SID_OK; + } else { + ret = GET_ID_FROM_SID_WRONG_TYPE; + } + } + + SAFE_FREE(data.dptr); - if (type == ID_EMPTY || type == ID_USERID) { - /* Parse and return existing uid */ - fstrcpy(scanstr, "UID %d"); + return ret; +} - if (sscanf(data.dptr, scanstr, &((*id).uid)) == 1) { - /* uid ok? */ - if (type == ID_EMPTY) { - *id_type = ID_USERID; - } - ret = NT_STATUS_OK; - goto idok; - } +/* Get a sid from an id */ +static NTSTATUS db_get_sid_from_id(DOM_SID *sid, unid_t id, int id_type_in) +{ + NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; + enum getidfromsiderr iderr; + int id_type = id_type_in & ID_TYPEMASK; + unid_t id_tmp = id; + int id_type_tmp = id_type; + + DEBUG(10,("db_get_sid_from_id: id_type_in = 0x%x\n", id_type_in)); + + ret = internal_get_sid_from_id(sid, id, id_type); + if (!NT_STATUS_IS_OK(ret)) { + return ret; + } + + iderr = internal_get_id_from_sid(&id_tmp, &id_type_tmp, sid); + if (iderr != GET_ID_FROM_SID_OK) { + return NT_STATUS_UNSUCCESSFUL; + } + if (id_type_tmp != id_type) { + return NT_STATUS_UNSUCCESSFUL; + } else if (id_type == ID_USERID) { + if (id_tmp.uid != id.uid) { + return NT_STATUS_UNSUCCESSFUL; + } + } else if (id_type == ID_GROUPID) { + if (id_tmp.gid != id.gid) { + return NT_STATUS_UNSUCCESSFUL; } + } else { + return NT_STATUS_UNSUCCESSFUL; + } + return ret; +} +/* Get an id from a sid */ +static NTSTATUS db_get_id_from_sid(unid_t *id, int *id_type, const DOM_SID *sid) +{ + NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; + enum getidfromsiderr iderr; - if (type == ID_EMPTY || type == ID_GROUPID) { - /* Parse and return existing gid */ - fstrcpy(scanstr, "GID %d"); + DEBUG(10,("db_get_id_from_sid\n")); - if (sscanf(data.dptr, scanstr, &((*id).gid)) == 1) { - /* gid ok? */ - if (type == ID_EMPTY) { - *id_type = ID_GROUPID; - } - ret = NT_STATUS_OK; + if (!sid || !id || !id_type) + return NT_STATUS_INVALID_PARAMETER; + + iderr = internal_get_id_from_sid(id, id_type, sid); + if (iderr == GET_ID_FROM_SID_OK) { + DOM_SID sid_tmp; + ret = internal_get_sid_from_id(&sid_tmp, *id, *id_type); + if (NT_STATUS_IS_OK(ret)) { + if (!sid_equal(&sid_tmp, sid)) { + return NT_STATUS_UNSUCCESSFUL; } } -idok: - SAFE_FREE(data.dptr); + } else if (iderr == GET_ID_FROM_SID_WRONG_TYPE) { + /* We found a record but not the type we wanted. + * This is an error, not an opportunity to overwrite... + * JRA. + */ + return NT_STATUS_UNSUCCESSFUL; + } - } else if (!(*id_type & ID_NOMAP) && + if (!(*id_type & ID_QUERY_ONLY) && (iderr != GET_ID_FROM_SID_OK) && (((*id_type & ID_TYPEMASK) == ID_USERID) || (*id_type & ID_TYPEMASK) == ID_GROUPID)) { + TDB_DATA sid_data; + TDB_DATA ugid_data; + fstring sid_string; + + sid_to_string(sid_string, sid); + + sid_data.dptr = sid_string; + sid_data.dsize = strlen(sid_string)+1; + + /* Lock the record for this SID. */ + if (tdb_chainlock(idmap_tdb, sid_data) != 0) { + DEBUG(10,("db_get_id_from_sid: failed to lock record %s. Error %s\n", + sid_string, tdb_errorstr(idmap_tdb) )); + return NT_STATUS_UNSUCCESSFUL; + } - /* Allocate a new id for this sid */ - ret = db_allocate_id(id, *id_type); - if (NT_STATUS_IS_OK(ret)) { - fstring keystr2; + do { + fstring ugid_str; + /* Allocate a new id for this sid */ + ret = db_allocate_id(id, *id_type); + if (!NT_STATUS_IS_OK(ret)) + break; + + /* Store the UID side */ /* Store new id */ if (*id_type & ID_USERID) { - slprintf(keystr2, sizeof(keystr2), "UID %d", (*id).uid); + slprintf(ugid_str, sizeof(ugid_str), "UID %d", (*id).uid); } else { - slprintf(keystr2, sizeof(keystr2), "GID %d", (*id).gid); + slprintf(ugid_str, sizeof(ugid_str), "GID %d", (*id).gid); } + + ugid_data.dptr = ugid_str; + ugid_data.dsize = strlen(ugid_str) + 1; - data.dptr = keystr2; - data.dsize = strlen(keystr2) + 1; + DEBUG(10,("db_get_id_from_sid: storing %s -> %s\n", + ugid_data.dptr, sid_data.dptr )); - if (tdb_store(idmap_tdb, key, data, TDB_REPLACE) == -1) { - /* TODO: print tdb error !! */ - return NT_STATUS_UNSUCCESSFUL; + if (tdb_store(idmap_tdb, ugid_data, sid_data, TDB_INSERT) != -1) { + ret = NT_STATUS_OK; + break; } - if (tdb_store(idmap_tdb, data, key, TDB_REPLACE) == -1) { + if (tdb_error(idmap_tdb) != TDB_ERR_EXISTS) + DEBUG(10,("db_get_id_from_sid: error %s\n", tdb_errorstr(idmap_tdb) )); + ret = NT_STATUS_UNSUCCESSFUL; + } while (tdb_error(idmap_tdb) == TDB_ERR_EXISTS); + + if (NT_STATUS_IS_OK(ret)) { + + DEBUG(10,("db_get_id_from_sid: storing %s -> %s\n", + sid_data.dptr, ugid_data.dptr )); + + if (tdb_store(idmap_tdb, sid_data, ugid_data, TDB_REPLACE) == -1) { + DEBUG(10,("db_get_id_from_sid: error %s\n", tdb_errorstr(idmap_tdb) )); /* TODO: print tdb error !! */ + tdb_chainunlock(idmap_tdb, sid_data); return NT_STATUS_UNSUCCESSFUL; } - - ret = NT_STATUS_OK; } + + tdb_chainunlock(idmap_tdb, sid_data); } return ret; @@ -217,7 +419,10 @@ static NTSTATUS db_set_mapping(const DOM_SID *sid, unid_t id, int id_type) fstring ksidstr; fstring kidstr; - if (!sid) return NT_STATUS_INVALID_PARAMETER; + DEBUG(10,("db_set_mapping: id_type = 0x%x\n", id_type)); + + if (!sid) + return NT_STATUS_INVALID_PARAMETER; sid_to_string(ksidstr, sid); @@ -238,32 +443,51 @@ static NTSTATUS db_set_mapping(const DOM_SID *sid, unid_t id, int id_type) /* *DELETE* prevoius mappings if any. * This is done both SID and [U|G]ID passed in */ + /* Lock the record for this SID. */ + if (tdb_chainlock(idmap_tdb, ksid) != 0) { + DEBUG(10,("db_set_mapping: failed to lock record %s. Error %s\n", + ksidstr, tdb_errorstr(idmap_tdb) )); + return NT_STATUS_UNSUCCESSFUL; + } + + DEBUG(10,("db_set_mapping: fetching %s\n", ksid.dptr)); + data = tdb_fetch(idmap_tdb, ksid); if (data.dptr) { + DEBUG(10,("db_set_mapping: deleting %s and %s\n", data.dptr, ksid.dptr )); tdb_delete(idmap_tdb, data); tdb_delete(idmap_tdb, ksid); + SAFE_FREE(data.dptr); } data = tdb_fetch(idmap_tdb, kid); if (data.dptr) { + DEBUG(10,("db_set_mapping: deleting %s and %s\n", data.dptr, kid.dptr )); tdb_delete(idmap_tdb, data); tdb_delete(idmap_tdb, kid); + SAFE_FREE(data.dptr); } if (tdb_store(idmap_tdb, ksid, kid, TDB_INSERT) == -1) { DEBUG(0, ("idb_set_mapping: tdb_store 1 error: %s\n", tdb_errorstr(idmap_tdb))); + tdb_chainunlock(idmap_tdb, ksid); return NT_STATUS_UNSUCCESSFUL; } if (tdb_store(idmap_tdb, kid, ksid, TDB_INSERT) == -1) { DEBUG(0, ("idb_set_mapping: tdb_store 2 error: %s\n", tdb_errorstr(idmap_tdb))); + tdb_chainunlock(idmap_tdb, ksid); return NT_STATUS_UNSUCCESSFUL; } + + tdb_chainunlock(idmap_tdb, ksid); + DEBUG(10,("db_set_mapping: stored %s -> %s and %s -> %s\n", ksid.dptr, kid.dptr, kid.dptr, ksid.dptr )); return NT_STATUS_OK; } /***************************************************************************** Initialise idmap database. *****************************************************************************/ -static NTSTATUS db_idmap_init(void) + +static NTSTATUS db_idmap_init( char *params ) { SMB_STRUCT_STAT stbuf; char *tdbfile = NULL; @@ -271,30 +495,22 @@ static NTSTATUS db_idmap_init(void) BOOL tdb_is_new = False; /* use the old database if present */ - if (!file_exist(lock_path("idmap.tdb"), &stbuf)) { - if (file_exist(lock_path("winbindd_idmap.tdb"), &stbuf)) { - DEBUG(0, ("idmap_init: using winbindd_idmap.tdb file!\n")); - tdbfile = strdup(lock_path("winbindd_idmap.tdb")); - if (!tdbfile) { - DEBUG(0, ("idmap_init: out of memory!\n")); - return NT_STATUS_NO_MEMORY; - } - } else { - tdb_is_new = True; - } - } + tdbfile = strdup(lock_path("winbindd_idmap.tdb")); if (!tdbfile) { - tdbfile = strdup(lock_path("idmap.tdb")); - if (!tdbfile) { - DEBUG(0, ("idmap_init: out of memory!\n")); - return NT_STATUS_NO_MEMORY; - } + DEBUG(0, ("idmap_init: out of memory!\n")); + return NT_STATUS_NO_MEMORY; + } + + if (!file_exist(tdbfile, &stbuf)) { + tdb_is_new = True; } - /* Open tdb cache */ + DEBUG(10,("db_idmap_init: Opening tdbfile %s\n", tdbfile )); + + /* Open idmap repository */ if (!(idmap_tdb = tdb_open_log(tdbfile, 0, TDB_DEFAULT, O_RDWR | O_CREAT, - 0600))) { + 0644))) { DEBUG(0, ("idmap_init: Unable to open idmap database\n")); SAFE_FREE(tdbfile); return NT_STATUS_UNSUCCESSFUL; @@ -302,16 +518,20 @@ static NTSTATUS db_idmap_init(void) SAFE_FREE(tdbfile); - /* check against earlier versions */ if (tdb_is_new) { - /* TODO: delete the file if this fail */ + /* the file didn't existed before opening it, let's + * store idmap version as nobody else yet opened and + * stored it. I do not like this method but didn't + * found a way to understand if an opened tdb have + * been just created or not --- SSS */ tdb_store_int32(idmap_tdb, "IDMAP_VERSION", IDMAP_VERSION); - } else { - version = tdb_fetch_int32(idmap_tdb, "IDMAP_VERSION"); - if (version != IDMAP_VERSION) { - DEBUG(0, ("idmap_init: Unable to open idmap database, it's in an old format!\n")); - return NT_STATUS_INTERNAL_DB_ERROR; - } + } + + /* check against earlier versions */ + version = tdb_fetch_int32(idmap_tdb, "IDMAP_VERSION"); + if (version != IDMAP_VERSION) { + DEBUG(0, ("idmap_init: Unable to open idmap database, it's in an old format!\n")); + return NT_STATUS_INTERNAL_DB_ERROR; } /* Create high water marks for group and user id */ @@ -424,9 +644,11 @@ static void db_idmap_status(void) /* Display complete mapping of users and groups to rids */ } -struct idmap_methods db_methods = { +static struct idmap_methods db_methods = { db_idmap_init, + db_allocate_rid, + db_allocate_id, db_get_sid_from_id, db_get_id_from_sid, db_set_mapping, @@ -435,9 +657,7 @@ struct idmap_methods db_methods = { }; -NTSTATUS idmap_reg_tdb(struct idmap_methods **meth) +NTSTATUS idmap_tdb_init(void) { - *meth = &db_methods; - - return NT_STATUS_OK; + return smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION, "tdb", &db_methods); } diff --git a/source3/sam/idmap_util.c b/source3/sam/idmap_util.c index 8c3a378832..f767cc898c 100644 --- a/source3/sam/idmap_util.c +++ b/source3/sam/idmap_util.c @@ -22,10 +22,54 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_IDMAP +/********************************************************************** +**********************************************************************/ + +BOOL idmap_get_free_ugid_range(uint32 *low, uint32 *high) +{ + uid_t u_low, u_high; + gid_t g_low, g_high; + + if (!lp_idmap_uid(&u_low, &u_high) || !lp_idmap_gid(&g_low, &g_high)) { + return False; + } + + *low = (u_low < g_low) ? u_low : g_low; + *high = (u_high < g_high) ? u_high : g_high; + + return True; +} /****************************************************************** - * Get the free RID base if idmap is configured, otherwise return 0 - ******************************************************************/ + Get the the non-algorithmic RID range if idmap range are defined +******************************************************************/ + +BOOL idmap_get_free_rid_range(uint32 *low, uint32 *high) +{ + uint32 id_low, id_high; + + if (!lp_enable_rid_algorithm()) { + *low = BASE_RID; + *high = (uint32)-1; + } + + if (!idmap_get_free_ugid_range(&id_low, &id_high)) { + return False; + } + + *low = fallback_pdb_uid_to_user_rid(id_low); + if (fallback_pdb_user_rid_to_uid((uint32)-1) < id_high) { + *high = (uint32)-1; + } else { + *high = fallback_pdb_uid_to_user_rid(id_high); + } + + return True; +} + +/********************************************************************** + Get the free RID base if idmap is configured, otherwise return 0 +**********************************************************************/ uint32 idmap_get_free_rid_base(void) { @@ -36,6 +80,9 @@ uint32 idmap_get_free_rid_base(void) return 0; } +/********************************************************************** +**********************************************************************/ + BOOL idmap_check_ugid_is_in_free_range(uint32 id) { uint32 low, high; @@ -49,6 +96,9 @@ BOOL idmap_check_ugid_is_in_free_range(uint32 id) return True; } +/********************************************************************** +**********************************************************************/ + BOOL idmap_check_rid_is_in_free_range(uint32 rid) { uint32 low, high; @@ -56,13 +106,20 @@ BOOL idmap_check_rid_is_in_free_range(uint32 rid) if (!idmap_get_free_rid_range(&low, &high)) { return False; } + if (rid < algorithmic_rid_base()) { + return True; + } + if (rid < low || rid > high) { return False; } + return True; } -/* if it is a foreign SID or if the SID is in the free range, return true */ +/********************************************************************** + if it is a foreign SID or if the SID is in the free range, return true +**********************************************************************/ BOOL idmap_check_sid_is_in_free_range(const DOM_SID *sid) { @@ -80,182 +137,70 @@ BOOL idmap_check_sid_is_in_free_range(const DOM_SID *sid) return True; } -/****************************************************************** - * Get the the non-algorithmic RID range if idmap range are defined - ******************************************************************/ - -BOOL idmap_get_free_rid_range(uint32 *low, uint32 *high) -{ - uint32 id_low, id_high; - - if (lp_idmap_only()) { - *low = BASE_RID; - *high = (uint32)-1; - } - - if (!idmap_get_free_ugid_range(&id_low, &id_high)) { - return False; - } - - *low = fallback_pdb_uid_to_user_rid(id_low); - if (fallback_pdb_user_rid_to_uid((uint32)-1) < id_high) { - *high = (uint32)-1; - } else { - *high = fallback_pdb_uid_to_user_rid(id_high); - } - - return True; -} - -BOOL idmap_get_free_ugid_range(uint32 *low, uint32 *high) -{ - uid_t u_low, u_high; - gid_t g_low, g_high; - - if (!lp_idmap_uid(&u_low, &u_high) || !lp_idmap_gid(&g_low, &g_high)) { - return False; - } - if (u_low < g_low) { - *low = u_low; - } else { - *low = g_low; - } - if (u_high < g_high) { - *high = g_high; - } else { - *high = u_high; - } - return True; -} - /***************************************************************** - *THE CANONICAL* convert uid_t to SID function. - check idmap if uid is in idmap range, otherwise falls back to - the legacy algorithmic mapping. - A special cache is used for uids that maps to Wellknown SIDs Returns SID pointer. *****************************************************************/ -NTSTATUS uid_to_sid(DOM_SID *sid, uid_t uid) +NTSTATUS idmap_uid_to_sid(DOM_SID *sid, uid_t uid) { - NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; unid_t id; int flags; - DEBUG(10,("uid_to_sid: uid = [%d]\n", uid)); + DEBUG(10,("idmap_uid_to_sid: uid = [%d]\n", uid)); flags = ID_USERID; - if (!lp_idmap_only() && !idmap_check_ugid_is_in_free_range(uid)) { - flags |= ID_NOMAP; - } - id.uid = uid; - if (NT_STATUS_IS_ERR(ret = idmap_get_sid_from_id(sid, id, flags))) { - DEBUG(10, ("uid_to_sid: Failed to map uid = [%u]\n", (unsigned int)uid)); - if (flags & ID_NOMAP) { - sid_copy(sid, get_global_sam_sid()); - sid_append_rid(sid, fallback_pdb_uid_to_user_rid(uid)); - - DEBUG(10,("uid_to_sid: Fall back to algorithmic mapping: %u -> %s\n", (unsigned int)uid, sid_string_static(sid))); - ret = NT_STATUS_OK; - } - } - - return ret; + + return idmap_get_sid_from_id(sid, id, flags); } /***************************************************************** - *THE CANONICAL* convert gid_t to SID function. - check idmap if gid is in idmap range, otherwise falls back to - the legacy algorithmic mapping. Group mapping is used for gids that maps to Wellknown SIDs Returns SID pointer. *****************************************************************/ -NTSTATUS gid_to_sid(DOM_SID *sid, gid_t gid) +NTSTATUS idmap_gid_to_sid(DOM_SID *sid, gid_t gid) { - NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; unid_t id; int flags; - DEBUG(10,("gid_to_sid: gid = [%d]\n", gid)); + DEBUG(10,("idmap_gid_to_sid: gid = [%d]\n", gid)); flags = ID_GROUPID; - if (!lp_idmap_only() && !idmap_check_ugid_is_in_free_range(gid)) { - flags |= ID_NOMAP; +#if 0 /* JERRY */ + if (!idmap_check_ugid_is_in_free_range(gid)) { + flags |= ID_QUERY_ONLY; } - +#endif id.gid = gid; - if (NT_STATUS_IS_ERR(ret = idmap_get_sid_from_id(sid, id, flags))) { - DEBUG(10, ("gid_to_sid: Failed to map gid = [%u]\n", (unsigned int)gid)); - if (flags & ID_NOMAP) { - sid_copy(sid, get_global_sam_sid()); - sid_append_rid(sid, pdb_gid_to_group_rid(gid)); - - DEBUG(10,("gid_to_sid: Fall back to algorithmic mapping: %u -> %s\n", (unsigned int)gid, sid_string_static(sid))); - ret = NT_STATUS_OK; - } - } - - return ret; + return idmap_get_sid_from_id(sid, id, flags); } /***************************************************************** - *THE CANONICAL* convert SID to uid function. if it is a foreign sid or it is in idmap rid range check idmap, otherwise falls back to the legacy algorithmic mapping. - A special cache is used for uids that maps to Wellknown SIDs Returns True if this name is a user sid and the conversion was done correctly, False if not. *****************************************************************/ -NTSTATUS sid_to_uid(const DOM_SID *sid, uid_t *uid) +NTSTATUS idmap_sid_to_uid(const DOM_SID *sid, uid_t *uid, uint32 flags) { NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; - BOOL fallback = False; unid_t id; - int flags; - - DEBUG(10,("sid_to_uid: sid = [%s]\n", sid_string_static(sid))); - - flags = ID_USERID; - if (!lp_idmap_only()) { - if (!idmap_check_sid_is_in_free_range(sid)) { - flags |= ID_NOMAP; - fallback = True; - } - } - if (NT_STATUS_IS_OK(idmap_get_id_from_sid(&id, &flags, sid))) { + DEBUG(10,("idmap_sid_to_uid: sid = [%s]\n", sid_string_static(sid))); - DEBUG(10,("sid_to_uid: uid = [%d]\n", id.uid)); + flags |= ID_USERID; + ret = idmap_get_id_from_sid(&id, &flags, sid); + + if ( NT_STATUS_IS_OK(ret) ) { + DEBUG(10,("idmap_sid_to_uid: uid = [%d]\n", id.uid)); *uid = id.uid; - ret = NT_STATUS_OK; - - } else if (fallback) { - uint32 rid; - - if (!sid_peek_rid(sid, &rid)) { - DEBUG(10,("sid_to_uid: invalid SID!\n")); - ret = NT_STATUS_INVALID_PARAMETER; - goto done; - } - - DEBUG(10,("sid_to_uid: Fall back to algorithmic mapping\n")); - - if (!fallback_pdb_rid_is_user(rid)) { - DEBUG(3, ("sid_to_uid: SID %s is *NOT* a user\n", sid_string_static(sid))); - ret = NT_STATUS_UNSUCCESSFUL; - } else { - *uid = fallback_pdb_user_rid_to_uid(rid); - DEBUG(10,("sid_to_uid: mapping: %s -> %u\n", sid_string_static(sid), (unsigned int)(*uid))); - ret = NT_STATUS_OK; - } - } + } -done: return ret; + } /***************************************************************** @@ -267,56 +212,59 @@ done: was done correctly, False if not. *****************************************************************/ -NTSTATUS sid_to_gid(const DOM_SID *sid, gid_t *gid) +NTSTATUS idmap_sid_to_gid(const DOM_SID *sid, gid_t *gid, uint32 flags) { NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; - BOOL fallback = False; unid_t id; - int flags; DEBUG(10,("sid_to_gid: sid = [%s]\n", sid_string_static(sid))); - flags = ID_GROUPID; - if (!lp_idmap_only()) { - if (!idmap_check_sid_is_in_free_range(sid)) { - flags |= ID_NOMAP; - fallback = True; - } - } + flags |= ID_GROUPID; - if (NT_STATUS_IS_OK(idmap_get_id_from_sid(&id, &flags, sid))) { - - DEBUG(10,("sid_to_gid: gid = [%d]\n", id.gid)); + ret = idmap_get_id_from_sid(&id, &flags, sid); + + if ( NT_STATUS_IS_OK(ret) ) + { + DEBUG(10,("idmap_sid_to_gid: gid = [%d]\n", id.gid)); *gid = id.gid; - ret = NT_STATUS_OK; + } - } else if (fallback) { - uint32 rid; + return ret; +} - if (!sid_peek_rid(sid, &rid)) { - DEBUG(10,("sid_to_uid: invalid SID!\n")); - ret = NT_STATUS_INVALID_PARAMETER; - goto done; - } - DEBUG(10,("sid_to_gid: Fall back to algorithmic mapping\n")); +/*************************************************************************** + Check first, call set_mapping if it doesn't already exist. +***************************************************************************/ - if (fallback_pdb_rid_is_user(rid)) { - DEBUG(3, ("sid_to_gid: SID %s is *NOT* a group\n", sid_string_static(sid))); - ret = NT_STATUS_UNSUCCESSFUL; - } else { - *gid = pdb_group_rid_to_gid(rid); - DEBUG(10,("sid_to_gid: mapping: %s -> %u\n", sid_string_static(sid), (unsigned int)(*gid))); - ret = NT_STATUS_OK; +static NTSTATUS wellknown_id_init(DOM_SID *sid, unid_t id, int flags) +{ + unid_t storedid; + int qflags = flags | ID_QUERY_ONLY; + + if (!NT_STATUS_IS_OK(idmap_get_id_from_sid(&storedid, &qflags, sid))) { + return idmap_set_mapping(sid, id, flags); + } else { + if (flags == ID_USERID && id.uid != storedid.uid) { + DEBUG(0,("wellknown_id_init: WARNING ! Stored uid %u for SID %s is not the same as the requested uid %u\n", + (unsigned int)storedid.uid, sid_string_static(sid), (unsigned int)id.uid )); + DEBUG(0,("wellknown_id_init: Attempting to overwrite old mapping with new.\n")); + return idmap_set_mapping(sid, id, flags); + } else if (flags == ID_GROUPID && id.gid != storedid.gid) { + DEBUG(0,("wellknown_id_init: WARNING ! Stored gid %u for SID %s is not the same as the requested gid %u\n", + (unsigned int)storedid.gid, sid_string_static(sid), (unsigned int)id.gid )); + DEBUG(0,("wellknown_id_init: Attempting to overwrite old mapping with new.\n")); + return idmap_set_mapping(sid, id, flags); } } - -done: - return ret; + return NT_STATUS_OK; } -/* Initialize idmap withWellknown SIDs like Guest, that are necessary - * to make samba run properly */ +/*************************************************************************** + Initialize idmap withWellknown SIDs like Guest, that are necessary + to make samba run properly. +***************************************************************************/ + BOOL idmap_init_wellknown_sids(void) { const char *guest_account = lp_guestaccount(); @@ -325,7 +273,7 @@ BOOL idmap_init_wellknown_sids(void) int num_entries=0; DOM_SID sid; unid_t id; - int flags; + fstring sid_string; if (!(guest_account && *guest_account)) { DEBUG(1, ("NULL guest account!?!?\n")); @@ -337,39 +285,52 @@ BOOL idmap_init_wellknown_sids(void) return False; } - flags = ID_USERID; + /* Fill in the SID for the guest account. */ id.uid = pass->pw_uid; sid_copy(&sid, get_global_sam_sid()); sid_append_rid(&sid, DOMAIN_USER_RID_GUEST); - if (NT_STATUS_IS_ERR(idmap_set_mapping(&sid, id, flags))) { + + if (!NT_STATUS_IS_OK(wellknown_id_init(&sid, id, ID_USERID))) { + DEBUG(0, ("Failed to setup UID mapping for GUEST (%s) to (%u)\n", + sid_to_string(sid_string, &sid), (unsigned int)id.uid)); + passwd_free(&pass); + return False; + } + + /* check if DOMAIN_GROUP_RID_GUESTS SID is set, if not store the + * guest account gid as mapping */ + id.gid = pass->pw_gid; + sid_copy(&sid, get_global_sam_sid()); + sid_append_rid(&sid, DOMAIN_GROUP_RID_GUESTS); + if (!NT_STATUS_IS_OK(wellknown_id_init(&sid, id, ID_GROUPID))) { + DEBUG(0, ("Failed to setup GID mapping for Group DOMAIN GUESTS (%s) to (%u)\n", + sid_to_string(sid_string, &sid), (unsigned int)id.gid)); passwd_free(&pass); return False; } + passwd_free(&pass); /* now fill in group mappings */ - if(pdb_enum_group_mapping(SID_NAME_UNKNOWN, &map, &num_entries, ENUM_ONLY_MAPPED, MAPPING_WITHOUT_PRIV)) { + if(pdb_enum_group_mapping(SID_NAME_UNKNOWN, &map, &num_entries, ENUM_ONLY_MAPPED)) { int i; for (i = 0; i < num_entries; i++) { id.gid = map[i].gid; - idmap_set_mapping(&(map[i].sid), id, ID_GROUPID); + wellknown_id_init(&map[i].sid, id, ID_GROUPID); } + SAFE_FREE(map); } - /* check if DOMAIN_GROUP_RID_GUESTS SID is set, if not store the - * guest account gid as mapping */ - flags = ID_GROUPID | ID_NOMAP; + /* Fill in the SID for the administrator account. */ + id.uid = 0; sid_copy(&sid, get_global_sam_sid()); - sid_append_rid(&sid, DOMAIN_GROUP_RID_GUESTS); - if (NT_STATUS_IS_ERR(idmap_get_id_from_sid(&id, &flags, &sid))) { - flags = ID_GROUPID; - id.gid = pass->pw_gid; - if (NT_STATUS_IS_ERR(idmap_set_mapping(&sid, id, flags))) { - passwd_free(&pass); - return False; - } + sid_append_rid(&sid, DOMAIN_USER_RID_ADMIN); + + if (!NT_STATUS_IS_OK(wellknown_id_init(&sid, id, ID_USERID))) { + DEBUG(0, ("Failed to setup UID mapping for ADMINISTRATOR (%s) to (%u)\n", + sid_to_string(sid_string, &sid), (unsigned int)id.uid)); + return False; } - passwd_free(&pass); return True; } diff --git a/source3/script/.cvsignore b/source3/script/.cvsignore index 5efd0d33db..7a8114ecd7 100644 --- a/source3/script/.cvsignore +++ b/source3/script/.cvsignore @@ -1,2 +1 @@ findsmb -mkproto.sh diff --git a/source3/script/build_env.sh b/source3/script/build_env.sh index 0000759f16..eb54f37aed 100755 --- a/source3/script/build_env.sh +++ b/source3/script/build_env.sh @@ -1,25 +1,31 @@ #!/bin/sh +if [ $# -lt 3 ] +then + echo "Usage: $0 srcdir builddir compiler" + exit 1 +fi + uname=`uname -a` date=`date` srcdir=$1 builddir=$2 compiler=$3 - if [ ! "x$USER" = "x" ]; then - whoami=$USER - else - if [ ! "x$LOGNAME" = "x" ]; then - whoami=$LOGNAME - else - whoami=`whoami || id -un` - fi - fi +if [ ! "x$USER" = "x" ]; then + whoami=$USER +else + if [ ! "x$LOGNAME" = "x" ]; then + whoami=$LOGNAME + else + whoami=`whoami || id -un` + fi +fi host=`hostname` cat <fsp_name)); - if(fsp->conn->vfs_ops.unlink(conn,fsp->fsp_name) != 0) { + if(SMB_VFS_UNLINK(conn,fsp->fsp_name) != 0) { /* * This call can potentially fail as another smbd may have * had the file open with delete on close set and deleted diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index b6c7aa1076..eb2d2bbcbf 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -93,6 +93,7 @@ thinking the server is still available. ****************************************************************************/ connection_struct *conn_new(void) { + TALLOC_CTX *mem_ctx; connection_struct *conn; int i; @@ -103,10 +104,16 @@ connection_struct *conn_new(void) return NULL; } - conn = (connection_struct *)malloc(sizeof(*conn)); - if (!conn) return NULL; + if ((mem_ctx=talloc_init("connection_struct"))==NULL) { + DEBUG(0,("talloc_init(connection_struct) failed!\n")); + return NULL; + } - ZERO_STRUCTP(conn); + if ((conn=(connection_struct *)talloc_zero(mem_ctx, sizeof(*conn)))==NULL) { + DEBUG(0,("talloc_zero() failed!\n")); + return NULL; + } + conn->mem_ctx = mem_ctx; conn->cnum = i; bitmap_set(bmap, i); @@ -195,27 +202,16 @@ void conn_clear_vuid_cache(uint16 vuid) void conn_free(connection_struct *conn) { - smb_vfs_handle_struct *handle, *thandle; - void (*done_fptr)(connection_struct *the_conn); + vfs_handle_struct *handle = NULL, *thandle = NULL; + TALLOC_CTX *mem_ctx = NULL; /* Free vfs_connection_struct */ - handle = conn->vfs_private; + handle = conn->vfs_handles; while(handle) { - /* Only call dlclose for the old modules */ - if (handle->handle) { - /* Close dlopen() handle */ - done_fptr = (void (*)(connection_struct *))sys_dlsym(handle->handle, "vfs_done"); - - if (done_fptr == NULL) { - DEBUG(3, ("No vfs_done() symbol found in module with handle %p, ignoring\n", handle->handle)); - } else { - done_fptr(conn); - } - sys_dlclose(handle->handle); - } - DLIST_REMOVE(conn->vfs_private, handle); + DLIST_REMOVE(conn->vfs_handles, handle); thandle = handle->next; - SAFE_FREE(handle); + if (handle->free_data) + handle->free_data(&handle->data); handle = thandle; } @@ -238,8 +234,9 @@ void conn_free(connection_struct *conn) bitmap_clear(bmap, conn->cnum); num_open--; + mem_ctx = conn->mem_ctx; ZERO_STRUCTP(conn); - SAFE_FREE(conn); + talloc_destroy(mem_ctx); } diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index c2718d4d70..5bb76eb3bd 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -38,10 +38,17 @@ TDB_CONTEXT *conn_tdb_ctx(void) static void make_conn_key(connection_struct *conn, const char *name, TDB_DATA *pkbuf, struct connections_key *pkey) { ZERO_STRUCTP(pkey); - ZERO_STRUCTP(pkbuf); pkey->pid = sys_getpid(); pkey->cnum = conn?conn->cnum:-1; fstrcpy(pkey->name, name); +#ifdef DEVELOPER + /* valgrind fixer... */ + { + size_t sl = strlen(pkey->name); + if (sizeof(fstring)-sl) + memset(&pkey->name[sl], '\0', sizeof(fstring)-sl); + } +#endif pkbuf->dptr = (char *)pkey; pkbuf->dsize = sizeof(*pkey); diff --git a/source3/smbd/dfree.c b/source3/smbd/dfree.c index 71b3f2bf77..f93cdf3791 100644 --- a/source3/smbd/dfree.c +++ b/source3/smbd/dfree.c @@ -80,7 +80,7 @@ static SMB_BIG_UINT disk_free(const char *path, BOOL small_query, dfree_command = lp_dfree_command(); if (dfree_command && *dfree_command) { - char *p; + const char *p; char **lines; pstring syscmd; @@ -93,15 +93,15 @@ static SMB_BIG_UINT disk_free(const char *path, BOOL small_query, DEBUG (3, ("Read input from dfree, \"%s\"\n", line)); - *dsize = (SMB_BIG_UINT)strtoul(line, &p, 10); - while (p && *p & isspace(*p)) + *dsize = STR_TO_SMB_BIG_UINT(line, &p); + while (p && *p && isspace(*p)) p++; if (p && *p) - *dfree = (SMB_BIG_UINT)strtoul(p, &p, 10); - while (p && *p & isspace(*p)) + *dfree = STR_TO_SMB_BIG_UINT(p, &p); + while (p && *p && isspace(*p)) p++; if (p && *p) - *bsize = (SMB_BIG_UINT)strtoul(p, NULL, 10); + *bsize = STR_TO_SMB_BIG_UINT(p, NULL); else *bsize = 1024; file_lines_free(lines); diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index 6cf56fd373..94b605ee8f 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -643,7 +643,7 @@ BOOL get_dir_entry(connection_struct *conn,char *mask,int dirtype, pstring fname pstrcpy(pathreal,path); pstrcat(path,fname); pstrcat(pathreal,dname); - if (conn->vfs_ops.stat(conn, pathreal, &sbuf) != 0) { + if (SMB_VFS_STAT(conn, pathreal, &sbuf) != 0) { DEBUG(5,("Couldn't stat 1 [%s]. Error = %s\n",path, strerror(errno) )); continue; } @@ -700,7 +700,7 @@ static BOOL user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_S return True; /* If we can't stat it does not show it */ - if (!VALID_STAT(*pst) && (vfs_stat(conn, name, pst) != 0)) + if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0)) return False; /* Pseudo-open the file (note - no fd's created). */ @@ -715,7 +715,8 @@ static BOOL user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_S return False; /* Get NT ACL -allocated in main loop talloc context. No free needed here. */ - sd_size = conn->vfs_ops.fget_nt_acl(fsp, fsp->fd, &psd); + sd_size = SMB_VFS_FGET_NT_ACL(fsp, fsp->fd, + (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION), &psd); close_file(fsp, True); /* No access if SD get failed. */ @@ -753,7 +754,7 @@ static BOOL user_can_write_file(connection_struct *conn, char *name, SMB_STRUCT_ return True; /* If we can't stat it does not show it */ - if (!VALID_STAT(*pst) && (vfs_stat(conn, name, pst) != 0)) + if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0)) return False; /* Pseudo-open the file (note - no fd's created). */ @@ -768,7 +769,8 @@ static BOOL user_can_write_file(connection_struct *conn, char *name, SMB_STRUCT_ return False; /* Get NT ACL -allocated in main loop talloc context. No free needed here. */ - sd_size = conn->vfs_ops.fget_nt_acl(fsp, fsp->fd, &psd); + sd_size = SMB_VFS_FGET_NT_ACL(fsp, fsp->fd, + (OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION), &psd); close_file(fsp, False); /* No access if SD get failed. */ @@ -794,7 +796,7 @@ static BOOL file_is_special(connection_struct *conn, char *name, SMB_STRUCT_STAT return True; /* If we can't stat it does not show it */ - if (!VALID_STAT(*pst) && (vfs_stat(conn, name, pst) != 0)) + if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0)) return True; if (S_ISREG(pst->st_mode) || S_ISDIR(pst->st_mode) || S_ISLNK(pst->st_mode)) @@ -811,7 +813,7 @@ void *OpenDir(connection_struct *conn, const char *name, BOOL use_veto) { Dir *dirp; const char *n; - DIR *p = conn->vfs_ops.opendir(conn,name); + DIR *p = SMB_VFS_OPENDIR(conn,name); int used=0; if (!p) @@ -819,7 +821,7 @@ void *OpenDir(connection_struct *conn, const char *name, BOOL use_veto) dirp = (Dir *)malloc(sizeof(Dir)); if (!dirp) { DEBUG(0,("Out of memory in OpenDir\n")); - conn->vfs_ops.closedir(conn,p); + SMB_VFS_CLOSEDIR(conn,p); return(NULL); } dirp->pos = dirp->numentries = dirp->mallocsize = 0; @@ -912,7 +914,7 @@ void *OpenDir(connection_struct *conn, const char *name, BOOL use_veto) dirp->numentries++; } - conn->vfs_ops.closedir(conn,p); + SMB_VFS_CLOSEDIR(conn,p); return((void *)dirp); } diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 6c21dc04d0..aaee41b546 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -56,7 +56,7 @@ mode_t unix_mode(connection_struct *conn,int dosmode,const char *fname) dname = parent_dirname(fname); DEBUG(2,("unix_mode(%s) inheriting from %s\n",fname,dname)); - if (vfs_stat(conn,dname,&sbuf) != 0) { + if (SMB_VFS_STAT(conn,dname,&sbuf) != 0) { DEBUG(4,("unix_mode(%s) failed, [dir %s]: %s\n",fname,dname,strerror(errno))); return(0); /* *** shouldn't happen! *** */ } @@ -191,7 +191,7 @@ int file_chmod(connection_struct *conn,char *fname, uint32 dosmode,SMB_STRUCT_ST if (!st) { st = &st1; - if (vfs_stat(conn,fname,st)) + if (SMB_VFS_STAT(conn,fname,st)) return(-1); } @@ -235,7 +235,7 @@ int file_chmod(connection_struct *conn,char *fname, uint32 dosmode,SMB_STRUCT_ST unixmode |= (st->st_mode & (S_IWUSR|S_IWGRP|S_IWOTH)); } - if ((ret = vfs_chmod(conn,fname,unixmode)) == 0) + if ((ret = SMB_VFS_CHMOD(conn,fname,unixmode)) == 0) return 0; if((errno != EPERM) && (errno != EACCES)) @@ -262,7 +262,7 @@ int file_chmod(connection_struct *conn,char *fname, uint32 dosmode,SMB_STRUCT_ST if (!fsp) return -1; become_root(); - ret = conn->vfs_ops.fchmod(fsp, fsp->fd, unixmode); + ret = SMB_VFS_FCHMOD(fsp, fsp->fd, unixmode); unbecome_root(); close_file_fchmod(fsp); } @@ -283,7 +283,7 @@ int file_utime(connection_struct *conn, char *fname, struct utimbuf *times) errno = 0; - if(conn->vfs_ops.utime(conn,fname, times) == 0) + if(SMB_VFS_UTIME(conn,fname, times) == 0) return 0; if((errno != EPERM) && (errno != EACCES)) @@ -298,7 +298,7 @@ int file_utime(connection_struct *conn, char *fname, struct utimbuf *times) (as DOS does). */ - if(vfs_stat(conn,fname,&sb) != 0) + if(SMB_VFS_STAT(conn,fname,&sb) != 0) return -1; /* Check if we have write access. */ @@ -311,7 +311,7 @@ int file_utime(connection_struct *conn, char *fname, struct utimbuf *times) current_user.ngroups,current_user.groups)))) { /* We are allowed to become root and change the filetime. */ become_root(); - ret = conn->vfs_ops.utime(conn,fname, times); + ret = SMB_VFS_UTIME(conn,fname, times); unbecome_root(); } } diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index b612b1a451..6be5f6af7d 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -32,7 +32,7 @@ static SMB_OFF_T seek_file(files_struct *fsp,SMB_OFF_T pos) { SMB_OFF_T seek_ret; - seek_ret = fsp->conn->vfs_ops.lseek(fsp,fsp->fd,pos,SEEK_SET); + seek_ret = SMB_VFS_LSEEK(fsp,fsp->fd,pos,SEEK_SET); if(seek_ret == -1) { DEBUG(0,("seek_file: (%s) sys_lseek failed. Error was %s\n", @@ -101,7 +101,7 @@ ssize_t read_file(files_struct *fsp,char *data,SMB_OFF_T pos,size_t n) #ifdef DMF_FIX int numretries = 3; tryagain: - readret = fsp->conn->vfs_ops.read(fsp,fsp->fd,data,n); + readret = SMB_VFS_READ(fsp,fsp->fd,data,n); if (readret == -1) { if ((errno == EAGAIN) && numretries) { DEBUG(3,("read_file EAGAIN retry in 10 seconds\n")); @@ -112,7 +112,7 @@ tryagain: return -1; } #else /* NO DMF fix. */ - readret = fsp->conn->vfs_ops.read(fsp,fsp->fd,data,n); + readret = SMB_VFS_READ(fsp,fsp->fd,data,n); if (readret == -1) return -1; #endif @@ -181,7 +181,7 @@ ssize_t write_file(files_struct *fsp, char *data, SMB_OFF_T pos, size_t n) SMB_STRUCT_STAT st; fsp->modified = True; - if (fsp->conn->vfs_ops.fstat(fsp,fsp->fd,&st) == 0) { + if (SMB_VFS_FSTAT(fsp,fsp->fd,&st) == 0) { int dosmode = dos_mode(fsp->conn,fsp->fsp_name,&st); fsp->size = (SMB_BIG_UINT)st.st_size; if (MAP_ARCHIVE(fsp->conn) && !IS_DOS_ARCHIVE(dosmode)) @@ -760,7 +760,7 @@ void sync_file(connection_struct *conn, files_struct *fsp) { if(lp_strict_sync(SNUM(conn)) && fsp->fd != -1) { flush_write_cache(fsp, SYNC_FLUSH); - conn->vfs_ops.fsync(fsp,fsp->fd); + SMB_VFS_FSYNC(fsp,fsp->fd); } } @@ -772,7 +772,7 @@ void sync_file(connection_struct *conn, files_struct *fsp) int fsp_stat(files_struct *fsp, SMB_STRUCT_STAT *pst) { if (fsp->fd == -1) - return vfs_stat(fsp->conn, fsp->fsp_name, pst); + return SMB_VFS_STAT(fsp->conn, fsp->fsp_name, pst); else - return vfs_fstat(fsp,fsp->fd, pst); + return SMB_VFS_FSTAT(fsp,fsp->fd, pst); } diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index b9e33e8f93..ad107f9c3e 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -178,7 +178,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen * stat the name - if it exists then we are all done! */ - if (vfs_stat(conn,name,&st) == 0) { + if (SMB_VFS_STAT(conn,name,&st) == 0) { stat_cache_add(orig_path, name); DEBUG(5,("conversion finished %s -> %s\n",orig_path, name)); *pst = st; @@ -234,7 +234,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen * Check if the name exists up to this point. */ - if (vfs_stat(conn,name, &st) == 0) { + if (SMB_VFS_STAT(conn,name, &st) == 0) { /* * It exists. it must either be a directory or this must be * the last part of the path for it to be OK. @@ -342,7 +342,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen * JRA. */ - if (vfs_stat(conn,name, &st) == 0) { + if (SMB_VFS_STAT(conn,name, &st) == 0) { *pst = st; } else { ZERO_STRUCT(st); @@ -418,7 +418,7 @@ BOOL check_name(pstring name,connection_struct *conn) #ifdef S_ISLNK if (!lp_symlinks(SNUM(conn))) { SMB_STRUCT_STAT statbuf; - if ( (conn->vfs_ops.lstat(conn,name,&statbuf) != -1) && + if ( (SMB_VFS_LSTAT(conn,name,&statbuf) != -1) && (S_ISLNK(statbuf.st_mode)) ) { DEBUG(3,("check_name: denied: file path name %s is a symlink\n",name)); ret=0; diff --git a/source3/smbd/files.c b/source3/smbd/files.c index b9b27ad5ff..f0fd6b7a73 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -346,6 +346,10 @@ void file_free(files_struct *fsp) string_free(&fsp->fsp_name); + if (fsp->fake_file_handle) { + destroy_fake_file_handle(&fsp->fake_file_handle); + } + bitmap_clear(file_bmap, fsp->fnum - FILE_HANDLE_OFFSET); files_used--; diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 98857c6d32..04d6a9a8a8 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1649,7 +1649,7 @@ static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, char *param,c return False; /* get list of domain groups SID_DOMAIN_GRP=2 */ - if(!pdb_enum_group_mapping(SID_NAME_DOM_GRP , &group_list, &num_entries, False, False)) { + if(!pdb_enum_group_mapping(SID_NAME_DOM_GRP , &group_list, &num_entries, False)) { DEBUG(3,("api_RNetGroupEnum:failed to get group list")); return False; } @@ -2367,7 +2367,7 @@ static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */ pstrcpy(p2,local_machine); - strupper(p2); + strupper_m(p2); p2 = skip_string(p2,1); p += 4; @@ -2378,7 +2378,7 @@ static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */ pstrcpy(p2,lp_workgroup()); - strupper(p2); + strupper_m(p2); p2 = skip_string(p2,1); p += 4; @@ -2788,7 +2788,7 @@ static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param fstring mypath; fstrcpy(mypath,"\\\\"); fstrcat(mypath,local_machine); - strupper(mypath); + strupper_m(mypath); PACKS(&desc,"z",mypath); /* computer */ } PACKS(&desc,"z",lp_workgroup());/* domain */ @@ -3007,7 +3007,7 @@ static void fill_printdest_info(connection_struct *conn, int snum, int uLevel, char buf[100]; strncpy(buf,SERVICE(snum),sizeof(buf)-1); buf[sizeof(buf)-1] = 0; - strupper(buf); + strupper_m(buf); if (uLevel <= 1) { PACKS(desc,"B9",buf); /* szName */ if (uLevel == 1) { diff --git a/source3/smbd/mangle_hash.c b/source3/smbd/mangle_hash.c index e220d2f6d2..ac8e425fd3 100644 --- a/source3/smbd/mangle_hash.c +++ b/source3/smbd/mangle_hash.c @@ -217,7 +217,7 @@ static NTSTATUS is_valid_name(const smb_ucs2_t *fname, BOOL allow_wildcards) return NT_STATUS_UNSUCCESSFUL; ret = has_valid_chars(fname, allow_wildcards); - if (NT_STATUS_IS_ERR(ret)) + if (!NT_STATUS_IS_OK(ret)) return ret; str = strdup_w(fname); @@ -227,7 +227,8 @@ static NTSTATUS is_valid_name(const smb_ucs2_t *fname, BOOL allow_wildcards) SAFE_FREE(str); return NT_STATUS_UNSUCCESSFUL; } - if (p) *p = 0; + if (p) + *p = 0; strupper_w(str); p = &(str[1]); @@ -285,10 +286,10 @@ static NTSTATUS is_8_3_w(const smb_ucs2_t *fname, BOOL allow_wildcards) if (strcmp_wa(fname, ".") == 0 || strcmp_wa(fname, "..") == 0) return NT_STATUS_OK; - if (NT_STATUS_IS_ERR(is_valid_name(fname, allow_wildcards))) + if (!NT_STATUS_IS_OK(is_valid_name(fname, allow_wildcards))) goto done; - if (NT_STATUS_IS_ERR(mangle_get_prefix(fname, &pref, &ext, allow_wildcards))) + if (!NT_STATUS_IS_OK(mangle_get_prefix(fname, &pref, &ext, allow_wildcards))) goto done; plen = strlen_w(pref); @@ -556,8 +557,8 @@ static void cache_mangled_name( char *mangled_name, char *raw_name ) /* Fill the new cache entry, and add it to the cache. */ s1 = (char *)(new_entry + 1); s2 = (char *)&(s1[mangled_len + 1]); - (void)StrnCpy( s1, mangled_name, mangled_len ); - (void)StrnCpy( s2, raw_name, raw_len ); + safe_strcpy( s1, mangled_name, mangled_len ); + safe_strcpy( s2, raw_name, raw_len ); ubi_cachePut( mangled_cache, i, new_entry, s1 ); } @@ -660,7 +661,7 @@ static void to_8_3(char *s) } else csum = str_checksum(s); - strupper( s ); + strupper_m( s ); if( p ) { if( p == s ) @@ -735,7 +736,7 @@ static void name_map(char *OutName, BOOL need83, BOOL cache83) return; } - if( !need83 && NT_STATUS_IS_ERR(is_valid_name(OutName_ucs2, False))) + if( !need83 && !NT_STATUS_IS_OK(is_valid_name(OutName_ucs2, False))) need83 = True; /* check if it's already in 8.3 format */ diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 66cd835240..f452dd845b 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -100,8 +100,8 @@ static int reply_lanman1(char *inbuf, char *outbuf) SSVAL(outbuf,smb_vwv1,secword); /* Create a token value and add it to the outgoing packet. */ if (global_encrypted_passwords_negotiated) { - SSVAL(outbuf,smb_vwv11, 8); get_challenge(smb_buf(outbuf)); + SSVAL(outbuf,smb_vwv11, 8); } Protocol = PROTOCOL_LANMAN1; @@ -144,8 +144,8 @@ static int reply_lanman2(char *inbuf, char *outbuf) /* Create a token value and add it to the outgoing packet. */ if (global_encrypted_passwords_negotiated) { - SSVAL(outbuf,smb_vwv11, 8); get_challenge(smb_buf(outbuf)); + SSVAL(outbuf,smb_vwv11, 8); } Protocol = PROTOCOL_LANMAN2; @@ -182,7 +182,17 @@ static int negprot_spnego(char *p) ZERO_STRUCT(guid); safe_strcpy((char *)guid, global_myname(), sizeof(guid)-1); - strlower((char *)guid); + +#ifdef DEVELOPER + /* valgrind fixer... */ + { + size_t sl = strlen(guid); + if (sizeof(guid)-sl) + memset(&guid[sl], '\0', sizeof(guid)-sl); + } +#endif + + strlower_m((char *)guid); #if 0 /* strangely enough, NT does not sent the single OID NTLMSSP when diff --git a/source3/smbd/notify_hash.c b/source3/smbd/notify_hash.c index d8b35462ac..810e5079ba 100644 --- a/source3/smbd/notify_hash.c +++ b/source3/smbd/notify_hash.c @@ -48,7 +48,7 @@ static BOOL notify_hash(connection_struct *conn, char *path, uint32 flags, ZERO_STRUCTP(data); - if(vfs_stat(conn,path, &st) == -1) + if(SMB_VFS_STAT(conn,path, &st) == -1) return False; data->modify_time = st.st_mtime; @@ -100,7 +100,7 @@ static BOOL notify_hash(connection_struct *conn, char *path, uint32 flags, /* * Do the stat - but ignore errors. */ - vfs_stat(conn,full_name, &st); + SMB_VFS_STAT(conn,full_name, &st); /* * Always sum the times. diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 9f7fabb75e..c574d9d563 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1,7 +1,8 @@ /* Unix SMB/CIFS implementation. SMB NT transaction handling - Copyright (C) Jeremy Allison 1994-1998 + Copyright (C) Jeremy Allison 1994-1998 + Copyright (C) Stefan (metze) Metzmacher 2003 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -26,6 +27,7 @@ extern int global_oplock_break; extern BOOL case_sensitive; extern BOOL case_preserve; extern BOOL short_case_preserve; +extern struct current_user current_user; static const char *known_nt_pipes[] = { "\\LANMAN", @@ -53,6 +55,24 @@ struct generic_mapping file_generic_mapping = { FILE_GENERIC_ALL }; +char *nttrans_realloc(char **ptr, size_t size) +{ + char *tptr = NULL; + if (ptr==NULL) + smb_panic("nttrans_realloc() called with NULL ptr\n"); + + tptr = Realloc_zero(*ptr, size); + if(tptr == NULL) { + *ptr = NULL; + return NULL; + } + + *ptr = tptr; + + return tptr; +} + + /**************************************************************************** Send the required number of replies back. We assume all fields other than the data fields are @@ -542,6 +562,7 @@ int reply_ntcreate_and_X(connection_struct *conn, { int result; pstring fname; + enum FAKE_FILE_TYPE fake_file_type = FAKE_FILE_TYPE_NONE; uint32 flags = IVAL(inbuf,smb_ntcreate_Flags); uint32 desired_access = IVAL(inbuf,smb_ntcreate_DesiredAccess); uint32 file_attributes = IVAL(inbuf,smb_ntcreate_FileAttributes); @@ -669,8 +690,25 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib */ if( strchr_m(fname, ':')) { - END_PROFILE(SMBntcreateX); - return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); + +#ifdef HAVE_SYS_QUOTAS + if ((fake_file_type=is_fake_file(fname))!=FAKE_FILE_TYPE_NONE) { + /* + * here we go! support for changing the disk quotas --metze + * + * we need to fake up to open this MAGIC QUOTA file + * and return a valid FID + * + * w2k close this file directly after openening + * xp also tries a QUERY_FILE_INFO on the file and then close it + */ + } else { +#endif + END_PROFILE(SMBntcreateX); + return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); +#ifdef HAVE_SYS_QUOTAS + } +#endif } } @@ -746,12 +784,21 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib * before issuing an oplock break request to * our client. JRA. */ - fsp = open_file_shared1(conn,fname,&sbuf, + if (fake_file_type==FAKE_FILE_TYPE_NONE) { + fsp = open_file_shared1(conn,fname,&sbuf, desired_access, smb_open_mode, smb_ofun,unixmode, oplock_request, &rmode,&smb_action); - + } else { + /* to open a fake_file --metze */ + fsp = open_fake_file_shared1(fake_file_type,conn,fname,&sbuf, + desired_access, + smb_open_mode, + smb_ofun,unixmode, oplock_request, + &rmode,&smb_action); + } + if (!fsp) { /* We cheat here. There are two cases we * care about. One is a directory rename, @@ -917,13 +964,12 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib Reply to a NT_TRANSACT_CREATE call to open a pipe. ****************************************************************************/ -static int do_nt_transact_create_pipe( connection_struct *conn, - char *inbuf, char *outbuf, int length, - int bufsize, char **ppsetup, char **ppparams, - char **ppdata) +static int do_nt_transact_create_pipe( connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, + char **ppsetup, uint32 setup_count, + char **ppparams, uint32 parameter_count, + char **ppdata, uint32 data_count) { pstring fname; - int total_parameter_count = (int)IVAL(inbuf, smb_nt_TotalParameterCount); char *params = *ppparams; int ret; int pnum = -1; @@ -933,25 +979,21 @@ static int do_nt_transact_create_pipe( connection_struct *conn, * Ensure minimum number of parameters sent. */ - if(total_parameter_count < 54) { - DEBUG(0,("do_nt_transact_create_pipe - insufficient parameters (%u)\n", (unsigned int)total_parameter_count)); + if(parameter_count < 54) { + DEBUG(0,("do_nt_transact_create_pipe - insufficient parameters (%u)\n", (unsigned int)parameter_count)); return ERROR_DOS(ERRDOS,ERRnoaccess); } - srvstr_pull(inbuf, fname, params+53, sizeof(fname), total_parameter_count-53, STR_TERMINATE); + srvstr_pull(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE); if ((ret = nt_open_pipe(fname, conn, inbuf, outbuf, &pnum)) != 0) return ret; /* Realloc the size of parameters and data we will return */ - params = Realloc(*ppparams, 69); + params = nttrans_realloc(ppparams, 69); if(params == NULL) return ERROR_DOS(ERRDOS,ERRnomem); - *ppparams = params; - - memset((char *)params,'\0',69); - p = params; SCVAL(p,0,NO_OPLOCK_RETURN); @@ -1032,7 +1074,7 @@ static NTSTATUS set_sd(files_struct *fsp, char *data, uint32 sd_len, uint32 secu if (psd->off_dacl==0) security_info_sent &= ~DACL_SECURITY_INFORMATION; - ret = fsp->conn->vfs_ops.fset_nt_acl( fsp, fsp->fd, security_info_sent, psd); + ret = SMB_VFS_FSET_NT_ACL( fsp, fsp->fd, security_info_sent, psd); if (!ret) { talloc_destroy(mem_ctx); @@ -1048,15 +1090,14 @@ static NTSTATUS set_sd(files_struct *fsp, char *data, uint32 sd_len, uint32 secu Reply to a NT_TRANSACT_CREATE call (needs to process SD's). ****************************************************************************/ -static int call_nt_transact_create(connection_struct *conn, - char *inbuf, char *outbuf, int length, - int bufsize, char **ppsetup, char **ppparams, - char **ppdata) +static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, + char **ppsetup, uint32 setup_count, + char **ppparams, uint32 parameter_count, + char **ppdata, uint32 data_count) { pstring fname; char *params = *ppparams; char *data = *ppdata; - int total_parameter_count = (int)IVAL(inbuf, smb_nt_TotalParameterCount); /* Breakout the oplock request bits so we can set the reply bits separately. */ int oplock_request = 0; mode_t unixmode; @@ -1092,7 +1133,10 @@ static int call_nt_transact_create(connection_struct *conn, if (IS_IPC(conn)) { if (lp_nt_pipe_support()) return do_nt_transact_create_pipe(conn, inbuf, outbuf, length, - bufsize, ppsetup, ppparams, ppdata); + bufsize, + ppsetup, setup_count, + ppparams, parameter_count, + ppdata, data_count); else return ERROR_DOS(ERRDOS,ERRnoaccess); } @@ -1101,8 +1145,8 @@ static int call_nt_transact_create(connection_struct *conn, * Ensure minimum number of parameters sent. */ - if(total_parameter_count < 54) { - DEBUG(0,("call_nt_transact_create - insufficient parameters (%u)\n", (unsigned int)total_parameter_count)); + if(parameter_count < 54) { + DEBUG(0,("call_nt_transact_create - insufficient parameters (%u)\n", (unsigned int)parameter_count)); return ERROR_DOS(ERRDOS,ERRnoaccess); } @@ -1146,7 +1190,7 @@ static int call_nt_transact_create(connection_struct *conn, if(!dir_fsp->is_directory) { - srvstr_pull(inbuf, fname, params+53, sizeof(fname), total_parameter_count-53, STR_TERMINATE); + srvstr_pull(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE); /* * Check to see if this is a mac fork of some kind. @@ -1175,9 +1219,9 @@ static int call_nt_transact_create(connection_struct *conn, } srvstr_pull(inbuf, &fname[dir_name_len], params+53, sizeof(fname)-dir_name_len, - total_parameter_count-53, STR_TERMINATE); + parameter_count-53, STR_TERMINATE); } else { - srvstr_pull(inbuf, fname, params+53, sizeof(fname), total_parameter_count-53, STR_TERMINATE); + srvstr_pull(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE); /* * Check to see if this is a mac fork of some kind. @@ -1331,14 +1375,10 @@ static int call_nt_transact_create(connection_struct *conn, } /* Realloc the size of parameters and data we will return */ - params = Realloc(*ppparams, 69); + params = nttrans_realloc(ppparams, 69); if(params == NULL) return ERROR_DOS(ERRDOS,ERRnomem); - *ppparams = params; - - memset((char *)params,'\0',69); - p = params; if (extended_oplock_granted) SCVAL(p,0, BATCH_OPLOCK_RETURN); @@ -1428,11 +1468,10 @@ int reply_nttranss(connection_struct *conn, don't allow a directory to be opened. ****************************************************************************/ -static int call_nt_transact_notify_change(connection_struct *conn, - char *inbuf, char *outbuf, int length, - int bufsize, - char **ppsetup, - char **ppparams, char **ppdata) +static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, + char **ppsetup, uint32 setup_count, + char **ppparams, uint32 parameter_count, + char **ppdata, uint32 data_count) { char *setup = *ppsetup; files_struct *fsp; @@ -1462,17 +1501,22 @@ name = %s\n", fsp->fsp_name )); Reply to an NT transact rename command. ****************************************************************************/ -static int call_nt_transact_rename(connection_struct *conn, - char *inbuf, char *outbuf, int length, - int bufsize, - char **ppsetup, char **ppparams, char **ppdata) +static int call_nt_transact_rename(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, + char **ppsetup, uint32 setup_count, + char **ppparams, uint32 parameter_count, + char **ppdata, uint32 data_count) { char *params = *ppparams; pstring new_name; - files_struct *fsp = file_fsp(params, 0); - BOOL replace_if_exists = (SVAL(params,2) & RENAME_REPLACE_IF_EXISTS) ? True : False; + files_struct *fsp = NULL; + BOOL replace_if_exists = False; NTSTATUS status; + if(parameter_count < 4) + return ERROR_DOS(ERRDOS,ERRbadfunc); + + fsp = file_fsp(params, 0); + replace_if_exists = (SVAL(params,2) & RENAME_REPLACE_IF_EXISTS) ? True : False; CHECK_FSP(fsp, conn); srvstr_pull(inbuf, new_name, params+4, sizeof(new_name), -1, STR_TERMINATE); @@ -1518,15 +1562,13 @@ static size_t get_null_nt_acl(TALLOC_CTX *mem_ctx, SEC_DESC **ppsd) } /**************************************************************************** - Reply to query a security descriptor - currently this is not implemented (it - is planned to be though). Right now it just returns the same thing NT would - when queried on a FAT filesystem. JRA. + Reply to query a security descriptor. ****************************************************************************/ -static int call_nt_transact_query_security_desc(connection_struct *conn, - char *inbuf, char *outbuf, - int length, int bufsize, - char **ppsetup, char **ppparams, char **ppdata) +static int call_nt_transact_query_security_desc(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, + char **ppsetup, uint32 setup_count, + char **ppparams, uint32 parameter_count, + char **ppdata, uint32 data_count) { uint32 max_data_count = IVAL(inbuf,smb_nt_MaxDataCount); char *params = *ppparams; @@ -1534,21 +1576,25 @@ static int call_nt_transact_query_security_desc(connection_struct *conn, prs_struct pd; SEC_DESC *psd = NULL; size_t sd_size; + uint32 security_info_wanted; TALLOC_CTX *mem_ctx; + files_struct *fsp = NULL; - files_struct *fsp = file_fsp(params,0); + if(parameter_count < 8) + return ERROR_DOS(ERRDOS,ERRbadfunc); + fsp = file_fsp(params,0); if(!fsp) return ERROR_DOS(ERRDOS,ERRbadfid); + security_info_wanted = IVAL(params,4); + DEBUG(3,("call_nt_transact_query_security_desc: file = %s\n", fsp->fsp_name )); - params = Realloc(*ppparams, 4); + params = nttrans_realloc(ppparams, 4); if(params == NULL) return ERROR_DOS(ERRDOS,ERRnomem); - *ppparams = params; - if ((mem_ctx = talloc_init("call_nt_transact_query_security_desc")) == NULL) { DEBUG(0,("call_nt_transact_query_security_desc: talloc_init failed.\n")); return ERROR_DOS(ERRDOS,ERRnomem); @@ -1561,7 +1607,7 @@ static int call_nt_transact_query_security_desc(connection_struct *conn, if (!lp_nt_acl_support(SNUM(conn))) sd_size = get_null_nt_acl(mem_ctx, &psd); else - sd_size = conn->vfs_ops.fget_nt_acl(fsp, fsp->fd, &psd); + sd_size = SMB_VFS_FGET_NT_ACL(fsp, fsp->fd, security_info_wanted, &psd); if (sd_size == 0) { talloc_destroy(mem_ctx); @@ -1584,16 +1630,12 @@ static int call_nt_transact_query_security_desc(connection_struct *conn, * Allocate the data we will point this at. */ - data = Realloc(*ppdata, sd_size); + data = nttrans_realloc(ppdata, sd_size); if(data == NULL) { talloc_destroy(mem_ctx); return ERROR_DOS(ERRDOS,ERRnomem); } - *ppdata = data; - - memset(data, '\0', sd_size); - /* * Init the parse struct we will marshall into. */ @@ -1632,23 +1674,21 @@ security descriptor.\n")); } /**************************************************************************** - Reply to set a security descriptor. Map to UNIX perms. + Reply to set a security descriptor. Map to UNIX perms or POSIX ACLs. ****************************************************************************/ -static int call_nt_transact_set_security_desc(connection_struct *conn, - char *inbuf, char *outbuf, int length, - int bufsize, char **ppsetup, - char **ppparams, char **ppdata) +static int call_nt_transact_set_security_desc(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, + char **ppsetup, uint32 setup_count, + char **ppparams, uint32 parameter_count, + char **ppdata, uint32 data_count) { - uint32 total_parameter_count = IVAL(inbuf, smb_nts_TotalParameterCount); char *params= *ppparams; char *data = *ppdata; - uint32 total_data_count = (uint32)IVAL(inbuf, smb_nts_TotalDataCount); files_struct *fsp = NULL; uint32 security_info_sent = 0; NTSTATUS nt_status; - if(total_parameter_count < 8) + if(parameter_count < 8) return ERROR_DOS(ERRDOS,ERRbadfunc); if((fsp = file_fsp(params,0)) == NULL) @@ -1662,10 +1702,10 @@ static int call_nt_transact_set_security_desc(connection_struct *conn, DEBUG(3,("call_nt_transact_set_security_desc: file = %s, sent 0x%x\n", fsp->fsp_name, (unsigned int)security_info_sent )); - if (total_data_count == 0) + if (data_count == 0) return ERROR_DOS(ERRDOS, ERRnoaccess); - if (!NT_STATUS_IS_OK(nt_status = set_sd( fsp, data, total_data_count, security_info_sent))) + if (!NT_STATUS_IS_OK(nt_status = set_sd( fsp, data, data_count, security_info_sent))) return ERROR_NT(nt_status); done: @@ -1677,15 +1717,15 @@ static int call_nt_transact_set_security_desc(connection_struct *conn, /**************************************************************************** Reply to NT IOCTL ****************************************************************************/ -static int call_nt_transact_ioctl(connection_struct *conn, - char *inbuf, char *outbuf, int length, - int bufsize, - char **ppsetup, int setup_count, - char **ppparams, int parameter_count, - char **ppdata, int data_count) + +static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, + char **ppsetup, uint32 setup_count, + char **ppparams, uint32 parameter_count, + char **ppdata, uint32 data_count) { unsigned fnum, control; static BOOL logged_message; + char *pdata = *ppdata; if (setup_count != 8) { DEBUG(3,("call_nt_transact_ioctl: invalid setup count %d\n", setup_count)); @@ -1695,28 +1735,475 @@ static int call_nt_transact_ioctl(connection_struct *conn, fnum = SVAL(*ppsetup, 4); control = IVAL(*ppsetup, 0); - DEBUG(6,("call_nt_transact_ioctl: fnum=%d control=0x%x\n", + DEBUG(10,("call_nt_transact_ioctl: fnum=%d control=0x%08x\n", fnum, control)); switch (control) { - case NTIOCTL_SET_SPARSE: + case FSCTL_SET_SPARSE: /* pretend this succeeded - tho strictly we should mark the file sparse (if the local fs supports it) so we can know if we need to pre-allocate or not */ + + DEBUG(10,("FSCTL_SET_SPARSE: fnum=%d control=0x%08x\n",fnum,control)); send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL, 0); return -1; + + case FSCTL_0x000900C0: + /* pretend this succeeded - don't know what this really is + but works ok like this --metze + */ + + DEBUG(10,("FSCTL_GET_REPARSE_POINT: fnum=%d control=0x%08x\n",fnum,control)); + send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL, 0); + return -1; + + case FSCTL_GET_REPARSE_POINT: + /* pretend this fail - my winXP does it like this + * --metze + */ + DEBUG(10,("FSCTL_GET_REPARSE_POINT: fnum=%d control=0x%08x\n",fnum,control)); + send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_NOT_A_REPARSE_POINT, NULL, 0, NULL, 0); + return -1; + + case FSCTL_SET_REPARSE_POINT: + /* pretend this fail - I'm assuming this because of the FSCTL_GET_REPARSE_POINT case. + * --metze + */ + + DEBUG(10,("FSCTL_SET_REPARSE_POINT: fnum=%d control=0x%08x\n",fnum,control)); + send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_NOT_A_REPARSE_POINT, NULL, 0, NULL, 0); + return -1; + + case FSCTL_FIND_FILES_BY_SID: /* I hope this name is right */ + { + /* pretend this succeeded - + * + * we have to send back a list with all files owned by this SID + * + * but I have to check that --metze + */ + + DOM_SID sid; + uid_t uid; + size_t sid_len=SID_MAX_SIZE; + + DEBUG(10,("FSCTL_FIND_FILES_BY_SID: fnum=%d control=0x%08x\n",fnum,control)); + + /* this is not the length of the sid :-( so unknown 4 bytes */ + /*sid_len = IVAL(pdata,0); + DEBUGADD(0,("sid_len: (%u)\n",sid_len));*/ + + sid_parse(pdata+4,sid_len,&sid); + DEBUGADD(10,("SID: %s\n",sid_string_static(&sid))); + + if (!NT_STATUS_IS_OK(sid_to_uid(&sid, &uid))) { + DEBUG(0,("sid_to_uid: failed, sid[%s]\n", + sid_string_static(&sid))); + uid = (-1); + } + + /* we can take a look at the find source :-) + * + * find ./ -uid $uid -name '*' is what we need here + * + * + * and send 4bytes len and then NULL terminated unicode strings + * for each file + * + * but I don't know how to deal with the paged results + * + * we don't send all files at once + * and at the next we should *not* start from the beginning, + * so we have to cache the result + * + * --metze + */ + + /* this works for now... */ + send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL, 0); + return -1; + } default: if (!logged_message) { logged_message = True; /* Only print this once... */ - DEBUG(3,("call_nt_transact_ioctl(0x%x): Currently not implemented.\n", + DEBUG(0,("call_nt_transact_ioctl(0x%x): Currently not implemented.\n", control)); } } return ERROR_NT(NT_STATUS_NOT_SUPPORTED); } - + + +#ifdef HAVE_SYS_QUOTAS +/**************************************************************************** + Reply to get user quota +****************************************************************************/ + +static int call_nt_transact_get_user_quota(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, + char **ppsetup, uint32 setup_count, + char **ppparams, uint32 parameter_count, + char **ppdata, uint32 data_count) +{ + NTSTATUS nt_status = NT_STATUS_OK; + uint32 max_data_count = IVAL(inbuf,smb_nt_MaxDataCount); + char *params = *ppparams; + char *pdata = *ppdata; + char *entry; + int data_len=0,param_len=0; + int qt_len=0; + int entry_len = 0; + files_struct *fsp = NULL; + uint16 level = 0; + size_t sid_len; + DOM_SID sid; + BOOL start_enum = True; + SMB_NTQUOTA_STRUCT qt; + SMB_NTQUOTA_LIST *tmp_list; + SMB_NTQUOTA_HANDLE *qt_handle = NULL; + + ZERO_STRUCT(qt); + + /* access check */ + if (conn->admin_user != True) { + DEBUG(1,("set_user_quota: access_denied service [%s] user [%s]\n", + lp_servicename(SNUM(conn)),conn->user)); + return ERROR_DOS(ERRDOS,ERRnoaccess); + } + + /* + * Ensure minimum number of parameters sent. + */ + + if (parameter_count < 4) { + DEBUG(0,("TRANSACT_GET_USER_QUOTA: requires %d >= 4 bytes parameters\n",parameter_count)); + return ERROR_DOS(ERRDOS,ERRinvalidparam); + } + + /* maybe we can check the quota_fnum */ + fsp = file_fsp(params,0); + if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) { + DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n")); + return ERROR_NT(NT_STATUS_INVALID_HANDLE); + } + + /* the NULL pointer cheking for fsp->fake_file_handle->pd + * is done by CHECK_NTQUOTA_HANDLE_OK() + */ + qt_handle = (SMB_NTQUOTA_HANDLE *)fsp->fake_file_handle->pd; + + level = SVAL(params,2); + + /* unknown 12 bytes leading in params */ + + switch (level) { + case TRANSACT_GET_USER_QUOTA_LIST_CONTINUE: + /* seems that we should continue with the enum here --metze */ + + if (qt_handle->quota_list!=NULL && + qt_handle->tmp_list==NULL) { + + /* free the list */ + free_ntquota_list(&(qt_handle->quota_list)); + + /* Realloc the size of parameters and data we will return */ + param_len = 4; + params = nttrans_realloc(ppparams, param_len); + if(params == NULL) + return ERROR_DOS(ERRDOS,ERRnomem); + + data_len = 0; + SIVAL(params,0,data_len); + + break; + } + + start_enum = False; + + case TRANSACT_GET_USER_QUOTA_LIST_START: + + if (qt_handle->quota_list==NULL && + qt_handle->tmp_list==NULL) { + start_enum = True; + } + + if (start_enum && vfs_get_user_ntquota_list(fsp,&(qt_handle->quota_list))!=0) + return ERROR_DOS(ERRSRV,ERRerror); + + /* Realloc the size of parameters and data we will return */ + param_len = 4; + params = nttrans_realloc(ppparams, param_len); + if(params == NULL) + return ERROR_DOS(ERRDOS,ERRnomem); + + /* we should not trust the value in max_data_count*/ + max_data_count = MIN(max_data_count,2048); + + pdata = nttrans_realloc(ppdata, max_data_count);/* should be max data count from client*/ + if(pdata == NULL) + return ERROR_DOS(ERRDOS,ERRnomem); + + entry = pdata; + + + /* set params Size of returned Quota Data 4 bytes*/ + /* but set it later when we know it */ + + /* for each entry push the data */ + + if (start_enum) { + qt_handle->tmp_list = qt_handle->quota_list; + } + + tmp_list = qt_handle->tmp_list; + + for (;((tmp_list!=NULL)&&((qt_len +40+SID_MAX_SIZE)next,entry+=entry_len,qt_len+=entry_len) { + + sid_len = sid_size(&tmp_list->quotas->sid); + entry_len = 40 + sid_len; + + /* nextoffset entry 4 bytes */ + SIVAL(entry,0,entry_len); + + /* then the len of the SID 4 bytes */ + SIVAL(entry,4,sid_len); + + /* unknown data 8 bytes SMB_BIG_UINT */ + SBIG_UINT(entry,8,(SMB_BIG_UINT)0); /* this is not 0 in windows...-metze*/ + + /* the used disk space 8 bytes SMB_BIG_UINT */ + SBIG_UINT(entry,16,tmp_list->quotas->usedspace); + + /* the soft quotas 8 bytes SMB_BIG_UINT */ + SBIG_UINT(entry,24,tmp_list->quotas->softlim); + + /* the hard quotas 8 bytes SMB_BIG_UINT */ + SBIG_UINT(entry,32,tmp_list->quotas->hardlim); + + /* and now the SID */ + sid_linearize(entry+40, sid_len, &tmp_list->quotas->sid); + } + + qt_handle->tmp_list = tmp_list; + + /* overwrite the offset of the last entry */ + SIVAL(entry-entry_len,0,0); + + data_len = 4+qt_len; + /* overwrite the params quota_data_len */ + SIVAL(params,0,data_len); + + break; + + case TRANSACT_GET_USER_QUOTA_FOR_SID: + + /* unknown 4 bytes IVAL(pdata,0) */ + + if (data_count < 8) { + DEBUG(0,("TRANSACT_GET_USER_QUOTA_FOR_SID: requires %d >= %d bytes data\n",data_count,8)); + return ERROR_DOS(ERRDOS,ERRunknownlevel); + } + + sid_len = IVAL(pdata,4); + + if (data_count < 8+sid_len) { + DEBUG(0,("TRANSACT_GET_USER_QUOTA_FOR_SID: requires %d >= %d bytes data\n",data_count,8+sid_len)); + return ERROR_DOS(ERRDOS,ERRunknownlevel); + } + + data_len = 4+40+sid_len; + + if (max_data_count < data_len) { + DEBUG(0,("TRANSACT_GET_USER_QUOTA_FOR_SID: max_data_count(%d) < data_len(%d)\n", + max_data_count, data_len)); + param_len = 4; + SIVAL(params,0,data_len); + data_len = 0; + nt_status = NT_STATUS_BUFFER_TOO_SMALL; + break; + } + + sid_parse(pdata+8,sid_len,&sid); + + + if (vfs_get_ntquota(fsp, SMB_USER_QUOTA_TYPE, &sid, &qt)!=0) { + ZERO_STRUCT(qt); + /* + * we have to return zero's in all fields + * instead of returning an error here + * --metze + */ + } + + /* Realloc the size of parameters and data we will return */ + param_len = 4; + params = nttrans_realloc(ppparams, param_len); + if(params == NULL) + return ERROR_DOS(ERRDOS,ERRnomem); + + pdata = nttrans_realloc(ppdata, data_len); + if(pdata == NULL) + return ERROR_DOS(ERRDOS,ERRnomem); + + entry = pdata; + + /* set params Size of returned Quota Data 4 bytes*/ + SIVAL(params,0,data_len); + + /* nextoffset entry 4 bytes */ + SIVAL(entry,0,0); + + /* then the len of the SID 4 bytes */ + SIVAL(entry,4,sid_len); + + /* unknown data 8 bytes SMB_BIG_UINT */ + SBIG_UINT(entry,8,(SMB_BIG_UINT)0); /* this is not 0 in windows...-mezte*/ + + /* the used disk space 8 bytes SMB_BIG_UINT */ + SBIG_UINT(entry,16,qt.usedspace); + + /* the soft quotas 8 bytes SMB_BIG_UINT */ + SBIG_UINT(entry,24,qt.softlim); + + /* the hard quotas 8 bytes SMB_BIG_UINT */ + SBIG_UINT(entry,32,qt.hardlim); + + /* and now the SID */ + sid_linearize(entry+40, sid_len, &sid); + + break; + + default: + DEBUG(0,("do_nt_transact_get_user_quota: fnum %d unknown level 0x%04hX\n",fsp->fnum,level)); + return ERROR_DOS(ERRSRV,ERRerror); + break; + } + + send_nt_replies(inbuf, outbuf, bufsize, nt_status, params, param_len, pdata, data_len); + + return -1; +} + +/**************************************************************************** + Reply to set user quota +****************************************************************************/ + +static int call_nt_transact_set_user_quota(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, + char **ppsetup, uint32 setup_count, + char **ppparams, uint32 parameter_count, + char **ppdata, uint32 data_count) +{ + char *params = *ppparams; + char *pdata = *ppdata; + int data_len=0,param_len=0; + SMB_NTQUOTA_STRUCT qt; + size_t sid_len; + DOM_SID sid; + files_struct *fsp = NULL; + + ZERO_STRUCT(qt); + + /* access check */ + if (conn->admin_user != True) { + DEBUG(1,("set_user_quota: access_denied service [%s] user [%s]\n", + lp_servicename(SNUM(conn)),conn->user)); + return ERROR_DOS(ERRDOS,ERRnoaccess); + } + + /* + * Ensure minimum number of parameters sent. + */ + + if (parameter_count < 2) { + DEBUG(0,("TRANSACT_SET_USER_QUOTA: requires %d >= 2 bytes parameters\n",parameter_count)); + return ERROR_DOS(ERRDOS,ERRinvalidparam); + } + + /* maybe we can check the quota_fnum */ + fsp = file_fsp(params,0); + if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) { + DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n")); + return ERROR_NT(NT_STATUS_INVALID_HANDLE); + } + + if (data_count < 40) { + DEBUG(0,("TRANSACT_SET_USER_QUOTA: requires %d >= %d bytes data\n",data_count,40)); + return ERROR_DOS(ERRDOS,ERRunknownlevel); + } + + /* offset to next quota record. + * 4 bytes IVAL(pdata,0) + * unused here... + */ + + /* sid len */ + sid_len = IVAL(pdata,4); + + if (data_count < 40+sid_len) { + DEBUG(0,("TRANSACT_SET_USER_QUOTA: requires %d >= %d bytes data\n",data_count,40+sid_len)); + return ERROR_DOS(ERRDOS,ERRunknownlevel); + } + + /* unknown 8 bytes in pdata + * maybe its the change time in NTTIME + */ + + /* the used space 8 bytes (SMB_BIG_UINT)*/ + qt.usedspace = (SMB_BIG_UINT)IVAL(pdata,16); +#ifdef LARGE_SMB_OFF_T + qt.usedspace |= (((SMB_BIG_UINT)IVAL(pdata,20)) << 32); +#else /* LARGE_SMB_OFF_T */ + if ((IVAL(pdata,20) != 0)&& + ((qt.usedspace != 0xFFFFFFFF)|| + (IVAL(pdata,20)!=0xFFFFFFFF))) { + /* more than 32 bits? */ + return ERROR_DOS(ERRDOS,ERRunknownlevel); + } +#endif /* LARGE_SMB_OFF_T */ + + /* the soft quotas 8 bytes (SMB_BIG_UINT)*/ + qt.softlim = (SMB_BIG_UINT)IVAL(pdata,24); +#ifdef LARGE_SMB_OFF_T + qt.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32); +#else /* LARGE_SMB_OFF_T */ + if ((IVAL(pdata,28) != 0)&& + ((qt.softlim != 0xFFFFFFFF)|| + (IVAL(pdata,28)!=0xFFFFFFFF))) { + /* more than 32 bits? */ + return ERROR_DOS(ERRDOS,ERRunknownlevel); + } +#endif /* LARGE_SMB_OFF_T */ + + /* the hard quotas 8 bytes (SMB_BIG_UINT)*/ + qt.hardlim = (SMB_BIG_UINT)IVAL(pdata,32); +#ifdef LARGE_SMB_OFF_T + qt.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32); +#else /* LARGE_SMB_OFF_T */ + if ((IVAL(pdata,36) != 0)&& + ((qt.hardlim != 0xFFFFFFFF)|| + (IVAL(pdata,36)!=0xFFFFFFFF))) { + /* more than 32 bits? */ + return ERROR_DOS(ERRDOS,ERRunknownlevel); + } +#endif /* LARGE_SMB_OFF_T */ + + sid_parse(pdata+40,sid_len,&sid); + DEBUGADD(8,("SID: %s\n",sid_string_static(&sid))); + + /* 44 unknown bytes left... */ + + if (vfs_set_ntquota(fsp, SMB_USER_QUOTA_TYPE, &sid, &qt)!=0) { + return ERROR_DOS(ERRSRV,ERRerror); + } + + send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, params, param_len, pdata, data_len); + + return -1; +} +#endif /* HAVE_SYS_QUOTAS */ + /**************************************************************************** Reply to a SMBNTtrans. ****************************************************************************/ @@ -1918,8 +2405,10 @@ due to being in oplock break state.\n", (unsigned int)function_code )); case NT_TRANSACT_CREATE: START_PROFILE_NESTED(NT_transact_create); outsize = call_nt_transact_create(conn, inbuf, outbuf, - length, bufsize, - &setup, ¶ms, &data); + length, bufsize, + &setup, setup_count, + ¶ms, total_parameter_count, + &data, total_data_count); END_PROFILE_NESTED(NT_transact_create); break; case NT_TRANSACT_IOCTL: @@ -1927,39 +2416,67 @@ due to being in oplock break state.\n", (unsigned int)function_code )); outsize = call_nt_transact_ioctl(conn, inbuf, outbuf, length, bufsize, &setup, setup_count, - ¶ms, parameter_count, - &data, data_count); + ¶ms, total_parameter_count, + &data, total_data_count); END_PROFILE_NESTED(NT_transact_ioctl); break; case NT_TRANSACT_SET_SECURITY_DESC: START_PROFILE_NESTED(NT_transact_set_security_desc); outsize = call_nt_transact_set_security_desc(conn, inbuf, outbuf, - length, bufsize, - &setup, ¶ms, &data); + length, bufsize, + &setup, setup_count, + ¶ms, total_parameter_count, + &data, total_data_count); END_PROFILE_NESTED(NT_transact_set_security_desc); break; case NT_TRANSACT_NOTIFY_CHANGE: START_PROFILE_NESTED(NT_transact_notify_change); outsize = call_nt_transact_notify_change(conn, inbuf, outbuf, - length, bufsize, - &setup, ¶ms, &data); + length, bufsize, + &setup, setup_count, + ¶ms, total_parameter_count, + &data, total_data_count); END_PROFILE_NESTED(NT_transact_notify_change); break; case NT_TRANSACT_RENAME: START_PROFILE_NESTED(NT_transact_rename); outsize = call_nt_transact_rename(conn, inbuf, outbuf, - length, bufsize, - &setup, ¶ms, &data); + length, bufsize, + &setup, setup_count, + ¶ms, total_parameter_count, + &data, total_data_count); END_PROFILE_NESTED(NT_transact_rename); break; case NT_TRANSACT_QUERY_SECURITY_DESC: START_PROFILE_NESTED(NT_transact_query_security_desc); outsize = call_nt_transact_query_security_desc(conn, inbuf, outbuf, - length, bufsize, - &setup, ¶ms, &data); + length, bufsize, + &setup, setup_count, + ¶ms, total_parameter_count, + &data, total_data_count); END_PROFILE_NESTED(NT_transact_query_security_desc); break; +#ifdef HAVE_SYS_QUOTAS + case NT_TRANSACT_GET_USER_QUOTA: + START_PROFILE_NESTED(NT_transact_get_user_quota); + outsize = call_nt_transact_get_user_quota(conn, inbuf, outbuf, + length, bufsize, + &setup, setup_count, + ¶ms, total_parameter_count, + &data, total_data_count); + END_PROFILE_NESTED(NT_transact_get_user_quota); + break; + case NT_TRANSACT_SET_USER_QUOTA: + START_PROFILE_NESTED(NT_transact_set_user_quota); + outsize = call_nt_transact_set_user_quota(conn, inbuf, outbuf, + length, bufsize, + &setup, setup_count, + ¶ms, total_parameter_count, + &data, total_data_count); + END_PROFILE_NESTED(NT_transact_set_user_quota); + break; +#endif /* HAVE_SYS_QUOTAS */ default: /* Error in request */ DEBUG(0,("reply_nttrans: Unknown request %d in nttrans call\n", function_code)); diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 510b28172d..6d03eaa29a 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -38,13 +38,13 @@ static int fd_open(struct connection_struct *conn, char *fname, flags |= O_NOFOLLOW; #endif - fd = conn->vfs_ops.open(conn,fname,flags,mode); + fd = SMB_VFS_OPEN(conn,fname,flags,mode); /* Fix for files ending in '.' */ if((fd == -1) && (errno == ENOENT) && (strchr_m(fname,'.')==NULL)) { pstrcat(fname,"."); - fd = conn->vfs_ops.open(conn,fname,flags,mode); + fd = SMB_VFS_OPEN(conn,fname,flags,mode); } DEBUG(10,("fd_open: name %s, flags = 0%o mode = 0%o, fd = %d. %s\n", fname, @@ -74,7 +74,7 @@ static void check_for_pipe(char *fname) /* special case of pipe opens */ char s[10]; StrnCpy(s,fname,sizeof(s)-1); - strlower(s); + strlower_m(s); if (strstr(s,"pipe/")) { DEBUG(3,("Rejecting named pipe open for %s\n",fname)); unix_ERR_class = ERRSRV; @@ -186,9 +186,9 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, int ret; if (fsp->fd == -1) - ret = vfs_stat(conn, fname, psbuf); + ret = SMB_VFS_STAT(conn, fname, psbuf); else { - ret = vfs_fstat(fsp,fsp->fd,psbuf); + ret = SMB_VFS_FSTAT(fsp,fsp->fd,psbuf); /* If we have an fd, this stat should succeed. */ if (ret == -1) DEBUG(0,("Error doing fstat on open file %s (%s)\n", fname,strerror(errno) )); @@ -259,7 +259,7 @@ static int truncate_unless_locked(struct connection_struct *conn, files_struct * unix_ERR_ntstatus = dos_to_ntstatus(ERRDOS, ERRlock); return -1; } else { - return conn->vfs_ops.ftruncate(fsp,fsp->fd,0); + return SMB_VFS_FTRUNCATE(fsp,fsp->fd,0); } } @@ -1024,6 +1024,16 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", if (!file_existed) { + /* + * Now the file exists and fsp is successfully opened, + * fsp->dev and fsp->inode are valid and should replace the + * dev=0,inode=0 from a non existent file. Spotted by + * Nadav Danieli . JRA. + */ + + dev = fsp->dev; + inode = fsp->inode; + lock_share_entry_fsp(fsp); num_share_modes = open_mode_check(conn, fname, dev, inode, @@ -1073,7 +1083,7 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", /* * We are modifing the file after open - update the stat struct.. */ - if ((truncate_unless_locked(conn,fsp) == -1) || (vfs_fstat(fsp,fsp->fd,psbuf)==-1)) { + if ((truncate_unless_locked(conn,fsp) == -1) || (SMB_VFS_FSTAT(fsp,fsp->fd,psbuf)==-1)) { unlock_share_entry_fsp(fsp); fd_close(conn,fsp); file_free(fsp); @@ -1148,11 +1158,11 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", * selected. */ - if (!file_existed && !def_acl && (conn->vfs_ops.fchmod_acl != NULL)) { + if (!file_existed && !def_acl) { int saved_errno = errno; /* We might get ENOSYS in the next call.. */ - if (conn->vfs_ops.fchmod_acl(fsp, fsp->fd, mode) == -1 && errno == ENOSYS) + if (SMB_VFS_FCHMOD_ACL(fsp, fsp->fd, mode) == -1 && errno == ENOSYS) errno = saved_errno; /* Ignore ENOSYS */ } else if (new_mode) { @@ -1161,9 +1171,9 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", /* Attributes need changing. File already existed. */ - if (conn->vfs_ops.fchmod_acl != NULL) { + { int saved_errno = errno; /* We might get ENOSYS in the next call.. */ - ret = conn->vfs_ops.fchmod_acl(fsp, fsp->fd, new_mode); + ret = SMB_VFS_FCHMOD_ACL(fsp, fsp->fd, new_mode); if (ret == -1 && errno == ENOSYS) { errno = saved_errno; /* Ignore ENOSYS */ @@ -1174,7 +1184,7 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", } } - if ((ret == -1) && (conn->vfs_ops.fchmod(fsp, fsp->fd, new_mode) == -1)) + if ((ret == -1) && (SMB_VFS_FCHMOD(fsp, fsp->fd, new_mode) == -1)) DEBUG(5, ("open_file_shared: failed to reset attributes of file %s to 0%o\n", fname, (int)new_mode)); } @@ -1280,14 +1290,14 @@ files_struct *open_directory(connection_struct *conn, char *fname, SMB_STRUCT_ST return NULL; } - if(vfs_mkdir(conn,fname, unix_mode(conn,aDIR, fname)) < 0) { + if(vfs_MkDir(conn,fname, unix_mode(conn,aDIR, fname)) < 0) { DEBUG(2,("open_directory: unable to create %s. Error was %s\n", fname, strerror(errno) )); file_free(fsp); return NULL; } - if(vfs_stat(conn,fname, psbuf) != 0) { + if(SMB_VFS_STAT(conn,fname, psbuf) != 0) { file_free(fsp); return NULL; } diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 632dfe9e29..8525687793 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -391,7 +391,7 @@ pid %d, port %d, dev = %x, inode = %.0f, file_id = %lu\n", /* * Keep this as a debug case - eventually we can remove it. */ - case (CMD_REPLY | KERNEL_OPLOCK_BREAK_CMD): + case 0x8001: DEBUG(0,("process_local_message: Received unsolicited break \ reply - dumping info.\n")); diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 283eed73ef..e2c143f1e2 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -157,7 +157,7 @@ int register_vuid(auth_serversupplied_info *server_info, const char *smb_name) } vuser->guest = server_info->guest; - fstrcpy(vuser->user.unix_name, pdb_get_username(server_info->sam_account)); + fstrcpy(vuser->user.unix_name, server_info->unix_name); /* This is a potentially untrusted username */ alpha_strcpy(vuser->user.smb_name, smb_name, ". _-$", sizeof(vuser->user.smb_name)); @@ -168,16 +168,24 @@ int register_vuid(auth_serversupplied_info *server_info, const char *smb_name) { /* 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 *logon_script = pdb_get_logon_script(server_info->sam_account); + + if (!IS_SAM_DEFAULT(server_info->sam_account, PDB_UNIXHOMEDIR)) { + const char *unix_homedir = pdb_get_unix_homedir(server_info->sam_account); + if (unix_homedir) { + vuser->unix_homedir = smb_xstrdup(unix_homedir); + } + } else { + struct passwd *passwd = getpwnam_alloc(vuser->user.unix_name); + if (passwd) { + vuser->unix_homedir = smb_xstrdup(passwd->pw_dir); + passwd_free(&passwd); + } + } + if (homedir) { vuser->homedir = smb_xstrdup(homedir); } - - if (unix_homedir) { - vuser->unix_homedir = smb_xstrdup(unix_homedir); - } - if (logon_script) { vuser->logon_script = smb_xstrdup(logon_script); } diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index a362db7d56..95b45fcc99 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -42,10 +42,448 @@ typedef struct canon_ace { enum ace_owner owner_type; enum ace_attribute attr; posix_id unix_ug; + BOOL inherited; } canon_ace; #define ALL_ACE_PERMS (S_IRUSR|S_IWUSR|S_IXUSR) +/* + * EA format of user.SAMBA_PAI (Samba_Posix_Acl_Interitance) + * attribute on disk. + * + * | 1 | 1 | 2 | 2 | .... + * +------+------+-------------+---------------------+-------------+--------------------+ + * | vers | flag | num_entries | num_default_entries | ..entries.. | default_entries... | + * +------+------+-------------+---------------------+-------------+--------------------+ + */ + +#define SAMBA_POSIX_INHERITANCE_EA_NAME "user.SAMBA_PAI" + +#define PAI_VERSION_OFFSET 0 +#define PAI_FLAG_OFFSET 1 +#define PAI_NUM_ENTRIES_OFFSET 2 +#define PAI_NUM_DEFAULT_ENTRIES_OFFSET 4 +#define PAI_ENTRIES_BASE 6 + +#define PAI_VERSION 1 +#define PAI_ACL_FLAG_PROTECTED 0x1 +#define PAI_ENTRY_LENGTH 5 + +/* + * In memory format of user.SAMBA_PAI attribute. + */ + +struct pai_entry { + struct pai_entry *next, *prev; + enum ace_owner owner_type; + posix_id unix_ug; +}; + +struct pai_val { + BOOL protected; + unsigned int num_entries; + struct pai_entry *entry_list; + unsigned int num_def_entries; + struct pai_entry *def_entry_list; +}; + +/************************************************************************ + Return a uint32 of the pai_entry principal. +************************************************************************/ + +static uint32 get_pai_entry_val(struct pai_entry *paie) +{ + switch (paie->owner_type) { + case UID_ACE: + DEBUG(10,("get_pai_entry_val: uid = %u\n", (unsigned int)paie->unix_ug.uid )); + return (uint32)paie->unix_ug.uid; + case GID_ACE: + DEBUG(10,("get_pai_entry_val: gid = %u\n", (unsigned int)paie->unix_ug.gid )); + return (uint32)paie->unix_ug.gid; + case WORLD_ACE: + default: + DEBUG(10,("get_pai_entry_val: world ace\n")); + return (uint32)-1; + } +} + +/************************************************************************ + Return a uint32 of the entry principal. +************************************************************************/ + +static uint32 get_entry_val(canon_ace *ace_entry) +{ + switch (ace_entry->owner_type) { + case UID_ACE: + DEBUG(10,("get_entry_val: uid = %u\n", (unsigned int)ace_entry->unix_ug.uid )); + return (uint32)ace_entry->unix_ug.uid; + case GID_ACE: + DEBUG(10,("get_entry_val: gid = %u\n", (unsigned int)ace_entry->unix_ug.gid )); + return (uint32)ace_entry->unix_ug.gid; + case WORLD_ACE: + default: + DEBUG(10,("get_entry_val: world ace\n")); + return (uint32)-1; + } +} + +/************************************************************************ + Count the inherited entries. +************************************************************************/ + +static unsigned int num_inherited_entries(canon_ace *ace_list) +{ + unsigned int num_entries = 0; + + for (; ace_list; ace_list = ace_list->next) + if (ace_list->inherited) + num_entries++; + return num_entries; +} + +/************************************************************************ + Create the on-disk format. Caller must free. +************************************************************************/ + +static char *create_pai_buf(canon_ace *file_ace_list, canon_ace *dir_ace_list, BOOL protected, size_t *store_size) +{ + char *pai_buf = NULL; + canon_ace *ace_list = NULL; + char *entry_offset = NULL; + unsigned int num_entries = 0; + unsigned int num_def_entries = 0; + + for (ace_list = file_ace_list; ace_list; ace_list = ace_list->next) + if (ace_list->inherited) + num_entries++; + + for (ace_list = dir_ace_list; ace_list; ace_list = ace_list->next) + if (ace_list->inherited) + num_def_entries++; + + DEBUG(10,("create_pai_buf: num_entries = %u, num_def_entries = %u\n", num_entries, num_def_entries )); + + *store_size = PAI_ENTRIES_BASE + ((num_entries + num_def_entries)*PAI_ENTRY_LENGTH); + + pai_buf = malloc(*store_size); + if (!pai_buf) { + return NULL; + } + + /* Set up the header. */ + memset(pai_buf, '\0', PAI_ENTRIES_BASE); + SCVAL(pai_buf,PAI_VERSION_OFFSET,PAI_VERSION); + SCVAL(pai_buf,PAI_FLAG_OFFSET,(protected ? PAI_ACL_FLAG_PROTECTED : 0)); + SSVAL(pai_buf,PAI_NUM_ENTRIES_OFFSET,num_entries); + SSVAL(pai_buf,PAI_NUM_DEFAULT_ENTRIES_OFFSET,num_def_entries); + + entry_offset = pai_buf + PAI_ENTRIES_BASE; + + for (ace_list = dir_ace_list; ace_list; ace_list = ace_list->next) { + if (ace_list->inherited) { + uint8 type_val = (unsigned char)ace_list->owner_type; + uint32 entry_val = get_entry_val(ace_list); + + SCVAL(entry_offset,0,type_val); + SIVAL(entry_offset,1,entry_val); + entry_offset += PAI_ENTRY_LENGTH; + } + } + + for (ace_list = file_ace_list; ace_list; ace_list = ace_list->next) { + if (ace_list->inherited) { + uint8 type_val = (unsigned char)ace_list->owner_type; + uint32 entry_val = get_entry_val(ace_list); + + SCVAL(entry_offset,0,type_val); + SIVAL(entry_offset,1,entry_val); + entry_offset += PAI_ENTRY_LENGTH; + } + } + + return pai_buf; +} + +/************************************************************************ + Store the user.SAMBA_PAI attribute on disk. +************************************************************************/ + +static void store_inheritance_attributes(files_struct *fsp, canon_ace *file_ace_list, + canon_ace *dir_ace_list, BOOL protected) +{ + int ret; + size_t store_size; + char *pai_buf; + + if (!lp_map_acl_inherit(SNUM(fsp->conn))) + return; + + /* + * Don't store if this ACL isn't protected and + * none of the entries in it are marked as inherited. + */ + + if (!protected && num_inherited_entries(file_ace_list) == 0 && num_inherited_entries(dir_ace_list) == 0) { + /* Instead just remove the attribute if it exists. */ + if (fsp->fd != -1) + SMB_VFS_FREMOVEXATTR(fsp, fsp->fd, SAMBA_POSIX_INHERITANCE_EA_NAME); + else + SMB_VFS_REMOVEXATTR(fsp->conn, fsp->fsp_name, SAMBA_POSIX_INHERITANCE_EA_NAME); + return; + } + + pai_buf = create_pai_buf(file_ace_list, dir_ace_list, protected, &store_size); + + if (fsp->fd != -1) + ret = SMB_VFS_FSETXATTR(fsp, fsp->fd, SAMBA_POSIX_INHERITANCE_EA_NAME, + pai_buf, store_size, 0); + else + ret = SMB_VFS_SETXATTR(fsp->conn,fsp->fsp_name, SAMBA_POSIX_INHERITANCE_EA_NAME, + pai_buf, store_size, 0); + + SAFE_FREE(pai_buf); + + DEBUG(10,("store_inheritance_attribute:%s for file %s\n", protected ? " (protected)" : "", fsp->fsp_name)); + if (ret == -1 && errno != ENOSYS) + DEBUG(1,("store_inheritance_attribute: Error %s\n", strerror(errno) )); +} + +/************************************************************************ + Delete the in memory inheritance info. +************************************************************************/ + +static void free_inherited_info(struct pai_val *pal) +{ + if (pal) { + struct pai_entry *paie, *paie_next; + for (paie = pal->entry_list; paie; paie = paie_next) { + paie_next = paie->next; + SAFE_FREE(paie); + } + for (paie = pal->def_entry_list; paie; paie = paie_next) { + paie_next = paie->next; + SAFE_FREE(paie); + } + SAFE_FREE(pal); + } +} + +/************************************************************************ + Was this ACL protected ? +************************************************************************/ + +static BOOL get_protected_flag(struct pai_val *pal) +{ + if (!pal) + return False; + return pal->protected; +} + +/************************************************************************ + Was this ACE inherited ? +************************************************************************/ + +static BOOL get_inherited_flag(struct pai_val *pal, canon_ace *ace_entry, BOOL default_ace) +{ + struct pai_entry *paie; + + if (!pal) + return False; + + /* If the entry exists it is inherited. */ + for (paie = (default_ace ? pal->def_entry_list : pal->entry_list); paie; paie = paie->next) { + if (ace_entry->owner_type == paie->owner_type && + get_entry_val(ace_entry) == get_pai_entry_val(paie)) + return True; + } + return False; +} + +/************************************************************************ + Ensure an attribute just read is valid. +************************************************************************/ + +static BOOL check_pai_ok(char *pai_buf, size_t pai_buf_data_size) +{ + uint16 num_entries; + uint16 num_def_entries; + + if (pai_buf_data_size < PAI_ENTRIES_BASE) { + /* Corrupted - too small. */ + return False; + } + + if (CVAL(pai_buf,PAI_VERSION_OFFSET) != PAI_VERSION) + return False; + + num_entries = SVAL(pai_buf,PAI_NUM_ENTRIES_OFFSET); + num_def_entries = SVAL(pai_buf,PAI_NUM_DEFAULT_ENTRIES_OFFSET); + + /* Check the entry lists match. */ + /* Each entry is 5 bytes (type plus 4 bytes of uid or gid). */ + + if (((num_entries + num_def_entries)*PAI_ENTRY_LENGTH) + PAI_ENTRIES_BASE != pai_buf_data_size) + return False; + + return True; +} + + +/************************************************************************ + Convert to in-memory format. +************************************************************************/ + +static struct pai_val *create_pai_val(char *buf, size_t size) +{ + char *entry_offset; + struct pai_val *paiv = NULL; + int i; + + if (!check_pai_ok(buf, size)) + return NULL; + + paiv = malloc(sizeof(struct pai_val)); + if (!paiv) + return NULL; + + memset(paiv, '\0', sizeof(struct pai_val)); + + paiv->protected = (CVAL(buf,PAI_FLAG_OFFSET) == PAI_ACL_FLAG_PROTECTED); + + paiv->num_entries = SVAL(buf,PAI_NUM_ENTRIES_OFFSET); + paiv->num_def_entries = SVAL(buf,PAI_NUM_DEFAULT_ENTRIES_OFFSET); + + entry_offset = buf + PAI_ENTRIES_BASE; + + DEBUG(10,("create_pai_val:%s num_entries = %u, num_def_entries = %u\n", + paiv->protected ? " (protected)" : "", paiv->num_entries, paiv->num_def_entries )); + + for (i = 0; i < paiv->num_entries; i++) { + struct pai_entry *paie; + + paie = malloc(sizeof(struct pai_entry)); + if (!paie) { + free_inherited_info(paiv); + return NULL; + } + + paie->owner_type = (enum ace_owner)CVAL(entry_offset,0); + switch( paie->owner_type) { + case UID_ACE: + paie->unix_ug.uid = (uid_t)IVAL(entry_offset,1); + DEBUG(10,("create_pai_val: uid = %u\n", (unsigned int)paie->unix_ug.uid )); + break; + case GID_ACE: + paie->unix_ug.gid = (gid_t)IVAL(entry_offset,1); + DEBUG(10,("create_pai_val: gid = %u\n", (unsigned int)paie->unix_ug.gid )); + break; + case WORLD_ACE: + paie->unix_ug.world = -1; + DEBUG(10,("create_pai_val: world ace\n")); + break; + default: + free_inherited_info(paiv); + return NULL; + } + entry_offset += PAI_ENTRY_LENGTH; + DLIST_ADD(paiv->entry_list, paie); + } + + for (i = 0; i < paiv->num_def_entries; i++) { + struct pai_entry *paie; + + paie = malloc(sizeof(struct pai_entry)); + if (!paie) { + free_inherited_info(paiv); + return NULL; + } + + paie->owner_type = (enum ace_owner)CVAL(entry_offset,0); + switch( paie->owner_type) { + case UID_ACE: + paie->unix_ug.uid = (uid_t)IVAL(entry_offset,1); + DEBUG(10,("create_pai_val: (def) uid = %u\n", (unsigned int)paie->unix_ug.uid )); + break; + case GID_ACE: + paie->unix_ug.gid = (gid_t)IVAL(entry_offset,1); + DEBUG(10,("create_pai_val: (def) gid = %u\n", (unsigned int)paie->unix_ug.gid )); + break; + case WORLD_ACE: + paie->unix_ug.world = -1; + DEBUG(10,("create_pai_val: (def) world ace\n")); + break; + default: + free_inherited_info(paiv); + return NULL; + } + entry_offset += PAI_ENTRY_LENGTH; + DLIST_ADD(paiv->def_entry_list, paie); + } + + return paiv; +} + +/************************************************************************ + Load the user.SAMBA_PAI attribute. +************************************************************************/ + +static struct pai_val *load_inherited_info(files_struct *fsp) +{ + char *pai_buf; + size_t pai_buf_size = 1024; + struct pai_val *paiv = NULL; + ssize_t ret; + + if (!lp_map_acl_inherit(SNUM(fsp->conn))) + return NULL; + + if ((pai_buf = malloc(pai_buf_size)) == NULL) + return NULL; + + do { + if (fsp->fd != -1) + ret = SMB_VFS_FGETXATTR(fsp, fsp->fd, SAMBA_POSIX_INHERITANCE_EA_NAME, + pai_buf, pai_buf_size); + else + ret = SMB_VFS_GETXATTR(fsp->conn,fsp->fsp_name,SAMBA_POSIX_INHERITANCE_EA_NAME, + pai_buf, pai_buf_size); + + if (ret == -1) { + if (errno != ERANGE) { + break; + } + /* Buffer too small - enlarge it. */ + pai_buf_size *= 2; + SAFE_FREE(pai_buf); + if ((pai_buf = malloc(pai_buf_size)) == NULL) + return NULL; + } + } while (ret == -1); + + DEBUG(10,("load_inherited_info: ret = %d for file %s\n", ret, fsp->fsp_name)); + + if (ret == -1) { + /* No attribute or not supported. */ +#if defined(ENOATTR) + if (errno != ENOATTR) + DEBUG(10,("load_inherited_info: Error %s\n", strerror(errno) )); +#else + if (errno != ENOSYS) + DEBUG(10,("load_inherited_info: Error %s\n", strerror(errno) )); +#endif + SAFE_FREE(pai_buf); + return NULL; + } + + paiv = create_pai_val(pai_buf, ret); + + if (paiv && paiv->protected) + DEBUG(10,("load_inherited_info: ACL is protected for file %s\n", fsp->fsp_name)); + + SAFE_FREE(pai_buf); + return paiv; +} + /**************************************************************************** Functions to manipulate the internal ACE format. ****************************************************************************/ @@ -106,10 +544,10 @@ static void print_canon_ace(canon_ace *pace, int num) dbgtext( "SID = %s ", sid_to_string( str, &pace->trustee)); if (pace->owner_type == UID_ACE) { const char *u_name = uidtoname(pace->unix_ug.uid); - dbgtext( "uid %u (%s) ", (unsigned int)pace->unix_ug.uid, u_name); + dbgtext( "uid %u (%s) ", (unsigned int)pace->unix_ug.uid, u_name ); } else if (pace->owner_type == GID_ACE) { char *g_name = gidtoname(pace->unix_ug.gid); - dbgtext( "gid %u (%s) ", (unsigned int)pace->unix_ug.gid, g_name); + dbgtext( "gid %u (%s) ", (unsigned int)pace->unix_ug.gid, g_name ); } else dbgtext( "other "); switch (pace->type) { @@ -129,6 +567,8 @@ static void print_canon_ace(canon_ace *pace, int num) dbgtext( "SMB_ACL_OTHER "); break; } + if (pace->inherited) + dbgtext( "(inherited) "); dbgtext( "perms "); dbgtext( "%c", pace->perms & S_IRUSR ? 'r' : '-'); dbgtext( "%c", pace->perms & S_IWUSR ? 'w' : '-'); @@ -158,9 +598,9 @@ static mode_t convert_permset_to_mode_t(connection_struct *conn, SMB_ACL_PERMSET { mode_t ret = 0; - ret |= (conn->vfs_ops.sys_acl_get_perm(conn, permset, SMB_ACL_READ) ? S_IRUSR : 0); - ret |= (conn->vfs_ops.sys_acl_get_perm(conn, permset, SMB_ACL_WRITE) ? S_IWUSR : 0); - ret |= (conn->vfs_ops.sys_acl_get_perm(conn, permset, SMB_ACL_EXECUTE) ? S_IXUSR : 0); + ret |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? S_IRUSR : 0); + ret |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? S_IWUSR : 0); + ret |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? S_IXUSR : 0); return ret; } @@ -190,18 +630,18 @@ static mode_t unix_perms_to_acl_perms(mode_t mode, int r_mask, int w_mask, int x static int map_acl_perms_to_permset(connection_struct *conn, mode_t mode, SMB_ACL_PERMSET_T *p_permset) { - if (conn->vfs_ops.sys_acl_clear_perms(conn, *p_permset) == -1) + if (SMB_VFS_SYS_ACL_CLEAR_PERMS(conn, *p_permset) == -1) return -1; if (mode & S_IRUSR) { - if (conn->vfs_ops.sys_acl_add_perm(conn, *p_permset, SMB_ACL_READ) == -1) + if (SMB_VFS_SYS_ACL_ADD_PERM(conn, *p_permset, SMB_ACL_READ) == -1) return -1; } if (mode & S_IWUSR) { - if (conn->vfs_ops.sys_acl_add_perm(conn, *p_permset, SMB_ACL_WRITE) == -1) + if (SMB_VFS_SYS_ACL_ADD_PERM(conn, *p_permset, SMB_ACL_WRITE) == -1) return -1; } if (mode & S_IXUSR) { - if (conn->vfs_ops.sys_acl_add_perm(conn, *p_permset, SMB_ACL_EXECUTE) == -1) + if (SMB_VFS_SYS_ACL_ADD_PERM(conn, *p_permset, SMB_ACL_EXECUTE) == -1) return -1; } return 0; @@ -468,7 +908,7 @@ static BOOL unpack_nt_owners(SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *pgrp, if (security_info_sent & OWNER_SECURITY_INFORMATION) { sid_copy(&owner_sid, psd->owner_sid); - if (NT_STATUS_IS_ERR(sid_to_uid(&owner_sid, puser))) { + if (!NT_STATUS_IS_OK(sid_to_uid(&owner_sid, puser))) { #if ACL_FORCE_UNMAPPABLE /* this allows take ownership to work reasonably */ extern struct current_user current_user; @@ -488,7 +928,7 @@ static BOOL unpack_nt_owners(SMB_STRUCT_STAT *psbuf, uid_t *puser, gid_t *pgrp, if (security_info_sent & GROUP_SECURITY_INFORMATION) { sid_copy(&grp_sid, psd->grp_sid); - if (NT_STATUS_IS_ERR(sid_to_gid( &grp_sid, pgrp))) { + if (!NT_STATUS_IS_OK(sid_to_gid( &grp_sid, pgrp))) { #if ACL_FORCE_UNMAPPABLE /* this allows take group ownership to work reasonably */ extern struct current_user current_user; @@ -637,62 +1077,6 @@ static BOOL ensure_canon_entry_valid(canon_ace **pp_ace, } } - /* - * When setting ACLs and missing one out of SMB_ACL_USER_OBJ, - * SMB_ACL_GROUP_OBJ, SMB_ACL_OTHER, try to retrieve current - * values. For user and other a simple vfs_stat would do, but - * we would get mask instead of group. Let's do it via ACL. - */ - - if (setting_acl && (!got_user || !got_grp || !got_other)) { - - SMB_ACL_ENTRY_T entry; - int entry_id = SMB_ACL_FIRST_ENTRY; - - if(fsp->is_directory || fsp->fd == -1) { - current_posix_acl = conn->vfs_ops.sys_acl_get_file(conn, fsp->fsp_name, SMB_ACL_TYPE_ACCESS); - } else { - current_posix_acl = conn->vfs_ops.sys_acl_get_fd(fsp, fsp->fd); - } - - if (current_posix_acl) { - while (conn->vfs_ops.sys_acl_get_entry(conn, current_posix_acl, entry_id, &entry) == 1) { - SMB_ACL_TAG_T tagtype; - SMB_ACL_PERMSET_T permset; - - /* get_next... */ - if (entry_id == SMB_ACL_FIRST_ENTRY) - entry_id = SMB_ACL_NEXT_ENTRY; - - /* Is this a MASK entry ? */ - if (conn->vfs_ops.sys_acl_get_tag_type(conn, entry, &tagtype) == -1) - continue; - - if (conn->vfs_ops.sys_acl_get_permset(conn, entry, &permset) == -1) - continue; - - switch(tagtype) { - case SMB_ACL_USER_OBJ: - current_user_perms = convert_permset_to_mode_t(conn, permset); - got_current_user = True; - break; - case SMB_ACL_GROUP_OBJ: - current_grp_perms = convert_permset_to_mode_t(conn, permset); - got_current_grp = True; - break; - case SMB_ACL_OTHER: - current_other_perms = convert_permset_to_mode_t(conn, permset); - got_current_other = True; - break; - } - } - conn->vfs_ops.sys_acl_free_acl(conn, current_posix_acl); - } else { - DEBUG(10,("ensure_canon_entry_valid: failed to retrieve current ACL of %s\n", - fsp->fsp_name)); - } - } - if (!got_user) { if ((pace = (canon_ace *)malloc(sizeof(canon_ace))) == NULL) { DEBUG(0,("ensure_canon_entry_valid: malloc fail.\n")); @@ -822,7 +1206,7 @@ static void check_owning_objs(canon_ace *ace, DOM_SID *pfile_owner_sid, DOM_SID Unpack a SEC_DESC into two canonical ace lists. ****************************************************************************/ -static BOOL create_canon_ace_lists(files_struct *fsp, +static BOOL create_canon_ace_lists(files_struct *fsp, SMB_STRUCT_STAT *pst, DOM_SID *pfile_owner_sid, DOM_SID *pfile_grp_sid, canon_ace **ppfile_ace, canon_ace **ppdir_ace, @@ -957,7 +1341,7 @@ static BOOL create_canon_ace_lists(files_struct *fsp, current_ace->type = SMB_ACL_OTHER; } else if (sid_equal(¤t_ace->trustee, &global_sid_Creator_Owner)) { current_ace->owner_type = UID_ACE; - current_ace->unix_ug.world = -1; + current_ace->unix_ug.uid = pst->st_uid; current_ace->type = SMB_ACL_USER_OBJ; /* @@ -970,7 +1354,7 @@ static BOOL create_canon_ace_lists(files_struct *fsp, psa->flags |= SEC_ACE_FLAG_INHERIT_ONLY; } else if (sid_equal(¤t_ace->trustee, &global_sid_Creator_Group)) { current_ace->owner_type = GID_ACE; - current_ace->unix_ug.world = -1; + current_ace->unix_ug.gid = pst->st_gid; current_ace->type = SMB_ACL_GROUP_OBJ; /* @@ -1005,6 +1389,7 @@ static BOOL create_canon_ace_lists(files_struct *fsp, current_ace->perms |= map_nt_perms( psa->info, S_IRUSR); current_ace->attr = (psa->type == SEC_ACE_TYPE_ACCESS_ALLOWED) ? ALLOW_ACE : DENY_ACE; + current_ace->inherited = ((psa->flags & SEC_ACE_FLAG_INHERITED_ACE) ? True : False); /* * Now add the created ace to either the file list, the directory @@ -1529,7 +1914,7 @@ static BOOL unpack_canon_ace(files_struct *fsp, * Now go through the DACL and create the canon_ace lists. */ - if (!create_canon_ace_lists( fsp, pfile_owner_sid, pfile_grp_sid, + if (!create_canon_ace_lists( fsp, pst, pfile_owner_sid, pfile_grp_sid, &file_ace, &dir_ace, psd->dacl)) return False; @@ -1672,7 +2057,7 @@ static void arrange_posix_perms( char *filename, canon_ace **pp_list_head) ****************************************************************************/ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_STRUCT_STAT *psbuf, - DOM_SID *powner, DOM_SID *pgroup, SMB_ACL_TYPE_T the_acl_type) + DOM_SID *powner, DOM_SID *pgroup, struct pai_val *pal, SMB_ACL_TYPE_T the_acl_type) { extern DOM_SID global_sid_World; connection_struct *conn = fsp->conn; @@ -1684,7 +2069,7 @@ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_ SMB_ACL_ENTRY_T entry; size_t ace_count; - while ( posix_acl && (conn->vfs_ops.sys_acl_get_entry(conn, posix_acl, entry_id, &entry) == 1)) { + while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) { SMB_ACL_TAG_T tagtype; SMB_ACL_PERMSET_T permset; DOM_SID sid; @@ -1696,10 +2081,10 @@ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_ entry_id = SMB_ACL_NEXT_ENTRY; /* Is this a MASK entry ? */ - if (conn->vfs_ops.sys_acl_get_tag_type(conn, entry, &tagtype) == -1) + if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) continue; - if (conn->vfs_ops.sys_acl_get_permset(conn, entry, &permset) == -1) + if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) continue; /* Decide which SID to use based on the ACL type. */ @@ -1712,7 +2097,7 @@ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_ break; case SMB_ACL_USER: { - uid_t *puid = (uid_t *)conn->vfs_ops.sys_acl_get_qualifier(conn, entry); + uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry); if (puid == NULL) { DEBUG(0,("canonicalise_acl: Failed to get uid.\n")); continue; @@ -1729,7 +2114,7 @@ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_ uid_to_sid( &sid, *puid); unix_ug.uid = *puid; owner_type = UID_ACE; - conn->vfs_ops.sys_acl_free_qualifier(conn, (void *)puid,tagtype); + SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype); break; } case SMB_ACL_GROUP_OBJ: @@ -1740,7 +2125,7 @@ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_ break; case SMB_ACL_GROUP: { - gid_t *pgid = (gid_t *)conn->vfs_ops.sys_acl_get_qualifier(conn, entry); + gid_t *pgid = (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry); if (pgid == NULL) { DEBUG(0,("canonicalise_acl: Failed to get gid.\n")); continue; @@ -1748,7 +2133,7 @@ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_ gid_to_sid( &sid, *pgid); unix_ug.gid = *pgid; owner_type = GID_ACE; - conn->vfs_ops.sys_acl_free_qualifier(conn, (void *)pgid,tagtype); + SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype); break; } case SMB_ACL_MASK: @@ -1779,6 +2164,7 @@ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_ ace->trustee = sid; ace->unix_ug = unix_ug; ace->owner_type = owner_type; + ace->inherited = get_inherited_flag(pal, ace, (the_acl_type == SMB_ACL_TYPE_DEFAULT)); DLIST_ADD(list_head, ace); } @@ -1790,14 +2176,12 @@ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_ if (!ensure_canon_entry_valid(&list_head, fsp, powner, pgroup, psbuf, False)) goto fail; - arrange_posix_perms(fsp->fsp_name,&list_head ); - /* * Now go through the list, masking the permissions with the * acl_mask. Ensure all DENY Entries are at the start of the list. */ - DEBUG(10,("canonicalise_acl: ace entries before arrange :\n")); + DEBUG(10,("canonicalise_acl: %s ace entries before arrange :\n", the_acl_type == SMB_ACL_TYPE_ACCESS ? "Access" : "Default" )); for ( ace_count = 0, ace = list_head; ace; ace = next_ace, ace_count++) { next_ace = ace->next; @@ -1815,6 +2199,8 @@ static canon_ace *canonicalise_acl( files_struct *fsp, SMB_ACL_T posix_acl, SMB_ } } + arrange_posix_perms(fsp->fsp_name,&list_head ); + print_canon_ace_list( "canonicalise_acl: ace entries after arrange", list_head ); return list_head; @@ -1833,7 +2219,7 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau { connection_struct *conn = fsp->conn; BOOL ret = False; - SMB_ACL_T the_acl = conn->vfs_ops.sys_acl_init(conn, (int)count_canon_ace_list(the_ace) + 1); + SMB_ACL_T the_acl = SMB_VFS_SYS_ACL_INIT(conn, (int)count_canon_ace_list(the_ace) + 1); canon_ace *p_ace; int i; SMB_ACL_ENTRY_T mask_entry; @@ -1891,7 +2277,7 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau * Get the entry for this ACE. */ - if (conn->vfs_ops.sys_acl_create_entry(conn, &the_acl, &the_entry) == -1) { + if (SMB_VFS_SYS_ACL_CREATE_ENTRY(conn, &the_acl, &the_entry) == -1) { DEBUG(0,("set_canon_ace_list: Failed to create entry %d. (%s)\n", i, strerror(errno) )); goto done; @@ -1917,7 +2303,7 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau * First tell the entry what type of ACE this is. */ - if (conn->vfs_ops.sys_acl_set_tag_type(conn, the_entry, p_ace->type) == -1) { + if (SMB_VFS_SYS_ACL_SET_TAG_TYPE(conn, the_entry, p_ace->type) == -1) { DEBUG(0,("set_canon_ace_list: Failed to set tag type on entry %d. (%s)\n", i, strerror(errno) )); goto done; @@ -1929,7 +2315,7 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau */ if ((p_ace->type == SMB_ACL_USER) || (p_ace->type == SMB_ACL_GROUP)) { - if (conn->vfs_ops.sys_acl_set_qualifier(conn, the_entry,(void *)&p_ace->unix_ug.uid) == -1) { + if (SMB_VFS_SYS_ACL_SET_QUALIFIER(conn, the_entry,(void *)&p_ace->unix_ug.uid) == -1) { DEBUG(0,("set_canon_ace_list: Failed to set qualifier on entry %d. (%s)\n", i, strerror(errno) )); goto done; @@ -1940,7 +2326,7 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau * Convert the mode_t perms in the canon_ace to a POSIX permset. */ - if (conn->vfs_ops.sys_acl_get_permset(conn, the_entry, &the_permset) == -1) { + if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, the_entry, &the_permset) == -1) { DEBUG(0,("set_canon_ace_list: Failed to get permset on entry %d. (%s)\n", i, strerror(errno) )); goto done; @@ -1956,7 +2342,7 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau * ..and apply them to the entry. */ - if (conn->vfs_ops.sys_acl_set_permset(conn, the_entry, the_permset) == -1) { + if (SMB_VFS_SYS_ACL_SET_PERMSET(conn, the_entry, the_permset) == -1) { DEBUG(0,("set_canon_ace_list: Failed to add permset on entry %d. (%s)\n", i, strerror(errno) )); goto done; @@ -1964,20 +2350,21 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau if( DEBUGLVL( 10 )) print_canon_ace( p_ace, i); + } if (needs_mask && !got_mask_entry) { - if (conn->vfs_ops.sys_acl_create_entry(conn, &the_acl, &mask_entry) == -1) { + if (SMB_VFS_SYS_ACL_CREATE_ENTRY(conn, &the_acl, &mask_entry) == -1) { DEBUG(0,("set_canon_ace_list: Failed to create mask entry. (%s)\n", strerror(errno) )); goto done; } - if (conn->vfs_ops.sys_acl_set_tag_type(conn, mask_entry, SMB_ACL_MASK) == -1) { + if (SMB_VFS_SYS_ACL_SET_TAG_TYPE(conn, mask_entry, SMB_ACL_MASK) == -1) { DEBUG(0,("set_canon_ace_list: Failed to set tag type on mask entry. (%s)\n",strerror(errno) )); goto done; } - if (conn->vfs_ops.sys_acl_get_permset(conn, mask_entry, &mask_permset) == -1) { + if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, mask_entry, &mask_permset) == -1) { DEBUG(0,("set_canon_ace_list: Failed to get mask permset. (%s)\n", strerror(errno) )); goto done; } @@ -1987,7 +2374,7 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau goto done; } - if (conn->vfs_ops.sys_acl_set_permset(conn, mask_entry, mask_permset) == -1) { + if (SMB_VFS_SYS_ACL_SET_PERMSET(conn, mask_entry, mask_permset) == -1) { DEBUG(0,("set_canon_ace_list: Failed to add mask permset. (%s)\n", strerror(errno) )); goto done; } @@ -1997,7 +2384,7 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau * Check if the ACL is valid. */ - if (conn->vfs_ops.sys_acl_valid(conn, the_acl) == -1) { + if (SMB_VFS_SYS_ACL_VALID(conn, the_acl) == -1) { DEBUG(0,("set_canon_ace_list: ACL type (%s) is invalid for set (%s).\n", the_acl_type == SMB_ACL_TYPE_DEFAULT ? "directory default" : "file", strerror(errno) )); @@ -2009,7 +2396,7 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau */ if(default_ace || fsp->is_directory || fsp->fd == -1) { - if (conn->vfs_ops.sys_acl_set_file(conn, fsp->fsp_name, the_acl_type, the_acl) == -1) { + if (SMB_VFS_SYS_ACL_SET_FILE(conn, fsp->fsp_name, the_acl_type, the_acl) == -1) { /* * Some systems allow all the above calls and only fail with no ACL support * when attempting to apply the acl. HPUX with HFS is an example of this. JRA. @@ -2028,7 +2415,7 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau goto done; } } else { - if (conn->vfs_ops.sys_acl_set_fd(fsp, fsp->fd, the_acl) == -1) { + if (SMB_VFS_SYS_ACL_SET_FD(fsp, fsp->fd, the_acl) == -1) { /* * Some systems allow all the above calls and only fail with no ACL support * when attempting to apply the acl. HPUX with HFS is an example of this. JRA. @@ -2052,7 +2439,7 @@ static BOOL set_canon_ace_list(files_struct *fsp, canon_ace *the_ace, BOOL defau done: if (the_acl != NULL) - conn->vfs_ops.sys_acl_free_acl(conn, the_acl); + SMB_VFS_SYS_ACL_FREE_ACL(conn, the_acl); return ret; } @@ -2083,8 +2470,8 @@ SMB_ACL_T free_empty_sys_acl(connection_struct *conn, SMB_ACL_T the_acl) if (!the_acl) return NULL; - if (conn->vfs_ops.sys_acl_get_entry(conn, the_acl, SMB_ACL_FIRST_ENTRY, &entry) != 1) { - conn->vfs_ops.sys_acl_free_acl(conn, the_acl); + if (SMB_VFS_SYS_ACL_GET_ENTRY(conn, the_acl, SMB_ACL_FIRST_ENTRY, &entry) != 1) { + SMB_VFS_SYS_ACL_FREE_ACL(conn, the_acl); return NULL; } return the_acl; @@ -2165,16 +2552,6 @@ posix perms.\n", fsp->fsp_name )); return True; } -static int nt_ace_comp( SEC_ACE *a1, SEC_ACE *a2) -{ - if (a1->type == a2->type) - return 0; - - if (a1->type == SEC_ACE_TYPE_ACCESS_DENIED && a2->type == SEC_ACE_TYPE_ACCESS_ALLOWED) - return -1; - return 1; -} - /**************************************************************************** Incoming NT ACLs on a directory can be split into a default POSIX acl (CI|OI|IO) and a normal POSIX acl. Win2k needs these split acls re-merging into one ACL @@ -2188,24 +2565,51 @@ static size_t merge_default_aces( SEC_ACE *nt_ace_list, size_t num_aces) for (i = 0; i < num_aces; i++) { for (j = i+1; j < num_aces; j++) { + uint32 i_flags_ni = (nt_ace_list[i].flags & ~SEC_ACE_FLAG_INHERITED_ACE); + uint32 j_flags_ni = (nt_ace_list[j].flags & ~SEC_ACE_FLAG_INHERITED_ACE); + BOOL i_inh = (nt_ace_list[i].flags & SEC_ACE_FLAG_INHERITED_ACE) ? True : False; + BOOL j_inh = (nt_ace_list[j].flags & SEC_ACE_FLAG_INHERITED_ACE) ? True : False; + /* We know the lower number ACE's are file entries. */ if ((nt_ace_list[i].type == nt_ace_list[j].type) && (nt_ace_list[i].size == nt_ace_list[j].size) && (nt_ace_list[i].info.mask == nt_ace_list[j].info.mask) && sid_equal(&nt_ace_list[i].trustee, &nt_ace_list[j].trustee) && - (nt_ace_list[i].flags == 0) && - (nt_ace_list[j].flags == (SEC_ACE_FLAG_OBJECT_INHERIT| - SEC_ACE_FLAG_CONTAINER_INHERIT| - SEC_ACE_FLAG_INHERIT_ONLY))) { + (i_inh == j_inh) && + (i_flags_ni == 0) && + (j_flags_ni == (SEC_ACE_FLAG_OBJECT_INHERIT| + SEC_ACE_FLAG_CONTAINER_INHERIT| + SEC_ACE_FLAG_INHERIT_ONLY))) { /* - * These are identical except for the flags. - * Merge the inherited ACE onto the non-inherited ACE. + * W2K wants to have access allowed zero access ACE's + * at the end of the list. If the mask is zero, merge + * the non-inherited ACE onto the inherited ACE. */ - nt_ace_list[i].flags = SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT; - if (num_aces - j - 1 > 0) - memmove(&nt_ace_list[j], &nt_ace_list[j+1], (num_aces-j-1) * - sizeof(SEC_ACE)); + if (nt_ace_list[i].info.mask == 0) { + nt_ace_list[j].flags = SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT| + (i_inh ? SEC_ACE_FLAG_INHERITED_ACE : 0); + if (num_aces - i - 1 > 0) + memmove(&nt_ace_list[i], &nt_ace_list[i+1], (num_aces-i-1) * + sizeof(SEC_ACE)); + + DEBUG(10,("merge_default_aces: Merging zero access ACE %u onto ACE %u.\n", + (unsigned int)i, (unsigned int)j )); + } else { + /* + * These are identical except for the flags. + * Merge the inherited ACE onto the non-inherited ACE. + */ + + nt_ace_list[i].flags = SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT| + (i_inh ? SEC_ACE_FLAG_INHERITED_ACE : 0); + if (num_aces - j - 1 > 0) + memmove(&nt_ace_list[j], &nt_ace_list[j+1], (num_aces-j-1) * + sizeof(SEC_ACE)); + + DEBUG(10,("merge_default_aces: Merging ACE %u onto ACE %u.\n", + (unsigned int)j, (unsigned int)i )); + } num_aces--; break; } @@ -2221,7 +2625,7 @@ static size_t merge_default_aces( SEC_ACE *nt_ace_list, size_t num_aces) the UNIX style get ACL. ****************************************************************************/ -size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) +size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) { extern DOM_SID global_sid_Builtin_Administrators; extern DOM_SID global_sid_Builtin_Users; @@ -2242,7 +2646,9 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) canon_ace *file_ace = NULL; canon_ace *dir_ace = NULL; size_t num_profile_acls = 0; - + struct pai_val *pal = NULL; + SEC_DESC *psd = NULL; + *ppdesc = NULL; DEBUG(10,("get_nt_acl: called for file %s\n", fsp->fsp_name )); @@ -2250,40 +2656,42 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) if(fsp->is_directory || fsp->fd == -1) { /* Get the stat struct for the owner info. */ - if(vfs_stat(fsp->conn,fsp->fsp_name, &sbuf) != 0) { + if(SMB_VFS_STAT(fsp->conn,fsp->fsp_name, &sbuf) != 0) { return 0; } /* * Get the ACL from the path. */ - posix_acl = conn->vfs_ops.sys_acl_get_file(conn, fsp->fsp_name, SMB_ACL_TYPE_ACCESS); + posix_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_ACCESS); /* * If it's a directory get the default POSIX ACL. */ if(fsp->is_directory) { - dir_acl = conn->vfs_ops.sys_acl_get_file(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT); + dir_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT); dir_acl = free_empty_sys_acl(conn, dir_acl); } } else { /* Get the stat struct for the owner info. */ - if(vfs_fstat(fsp,fsp->fd,&sbuf) != 0) { + if(SMB_VFS_FSTAT(fsp,fsp->fd,&sbuf) != 0) { return 0; } /* * Get the ACL from the fd. */ - posix_acl = conn->vfs_ops.sys_acl_get_fd(fsp, fsp->fd); + posix_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fd); } DEBUG(5,("get_nt_acl : file ACL %s, directory ACL %s\n", posix_acl ? "present" : "absent", dir_acl ? "present" : "absent" )); + pal = load_inherited_info(fsp); + /* * Get the owner, group and world SIDs. */ @@ -2297,179 +2705,171 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) create_file_sids(&sbuf, &owner_sid, &group_sid); } - /* - * In the optimum case Creator Owner and Creator Group would be used for - * the ACL_USER_OBJ and ACL_GROUP_OBJ entries, respectively, but this - * would lead to usability problems under Windows: The Creator entries - * are only available in browse lists of directories and not for files; - * additionally the identity of the owning group couldn't be determined. - * We therefore use those identities only for Default ACLs. - */ - - /* Create the canon_ace lists. */ - file_ace = canonicalise_acl( fsp, posix_acl, &sbuf, &owner_sid, &group_sid, SMB_ACL_TYPE_ACCESS ); + if ((security_info & DACL_SECURITY_INFORMATION) && !(security_info & PROTECTED_DACL_SECURITY_INFORMATION)) { - /* We must have *some* ACLS. */ + /* + * In the optimum case Creator Owner and Creator Group would be used for + * the ACL_USER_OBJ and ACL_GROUP_OBJ entries, respectively, but this + * would lead to usability problems under Windows: The Creator entries + * are only available in browse lists of directories and not for files; + * additionally the identity of the owning group couldn't be determined. + * We therefore use those identities only for Default ACLs. + */ - if (count_canon_ace_list(file_ace) == 0) { - DEBUG(0,("get_nt_acl : No ACLs on file (%s) !\n", fsp->fsp_name )); - return 0; - } + /* Create the canon_ace lists. */ + file_ace = canonicalise_acl( fsp, posix_acl, &sbuf, &owner_sid, &group_sid, pal, SMB_ACL_TYPE_ACCESS ); - if (fsp->is_directory && dir_acl) { - dir_ace = canonicalise_acl(fsp, dir_acl, &sbuf, - &global_sid_Creator_Owner, - &global_sid_Creator_Group, SMB_ACL_TYPE_DEFAULT ); - } + /* We must have *some* ACLS. */ + + if (count_canon_ace_list(file_ace) == 0) { + DEBUG(0,("get_nt_acl : No ACLs on file (%s) !\n", fsp->fsp_name )); + return 0; + } - /* - * Create the NT ACE list from the canonical ace lists. - */ + if (fsp->is_directory && dir_acl) { + dir_ace = canonicalise_acl(fsp, dir_acl, &sbuf, + &global_sid_Creator_Owner, + &global_sid_Creator_Group, pal, SMB_ACL_TYPE_DEFAULT ); + } - { - canon_ace *ace; - int nt_acl_type; - int i; + /* + * Create the NT ACE list from the canonical ace lists. + */ - if (nt4_compatible_acls() && dir_ace) { - /* - * NT 4 chokes if an ACL contains an INHERIT_ONLY entry - * but no non-INHERIT_ONLY entry for one SID. So we only - * remove entries from the Access ACL if the - * corresponding Default ACL entries have also been - * removed. ACEs for CREATOR-OWNER and CREATOR-GROUP - * are exceptions. We can do nothing - * intelligent if the Default ACL contains entries that - * are not also contained in the Access ACL, so this - * case will still fail under NT 4. - */ + { + canon_ace *ace; + int nt_acl_type; + int i; - ace = canon_ace_entry_for(dir_ace, SMB_ACL_OTHER, NULL); - if (ace && !ace->perms) { - DLIST_REMOVE(dir_ace, ace); - SAFE_FREE(ace); + if (nt4_compatible_acls() && dir_ace) { + /* + * NT 4 chokes if an ACL contains an INHERIT_ONLY entry + * but no non-INHERIT_ONLY entry for one SID. So we only + * remove entries from the Access ACL if the + * corresponding Default ACL entries have also been + * removed. ACEs for CREATOR-OWNER and CREATOR-GROUP + * are exceptions. We can do nothing + * intelligent if the Default ACL contains entries that + * are not also contained in the Access ACL, so this + * case will still fail under NT 4. + */ - ace = canon_ace_entry_for(file_ace, SMB_ACL_OTHER, NULL); + ace = canon_ace_entry_for(dir_ace, SMB_ACL_OTHER, NULL); if (ace && !ace->perms) { - DLIST_REMOVE(file_ace, ace); + DLIST_REMOVE(dir_ace, ace); SAFE_FREE(ace); + + ace = canon_ace_entry_for(file_ace, SMB_ACL_OTHER, NULL); + if (ace && !ace->perms) { + DLIST_REMOVE(file_ace, ace); + SAFE_FREE(ace); + } } - } - /* - * WinNT doesn't usually have Creator Group - * in browse lists, so we send this entry to - * WinNT even if it contains no relevant - * permissions. Once we can add - * Creator Group to browse lists we can - * re-enable this. - */ + /* + * WinNT doesn't usually have Creator Group + * in browse lists, so we send this entry to + * WinNT even if it contains no relevant + * permissions. Once we can add + * Creator Group to browse lists we can + * re-enable this. + */ #if 0 - ace = canon_ace_entry_for(dir_ace, SMB_ACL_GROUP_OBJ, NULL); - if (ace && !ace->perms) { - DLIST_REMOVE(dir_ace, ace); - SAFE_FREE(ace); - } + ace = canon_ace_entry_for(dir_ace, SMB_ACL_GROUP_OBJ, NULL); + if (ace && !ace->perms) { + DLIST_REMOVE(dir_ace, ace); + SAFE_FREE(ace); + } #endif - ace = canon_ace_entry_for(file_ace, SMB_ACL_GROUP_OBJ, NULL); - if (ace && !ace->perms) { - DLIST_REMOVE(file_ace, ace); - SAFE_FREE(ace); - } - } else { - - ace = canon_ace_entry_for(dir_ace, SMB_ACL_OTHER, NULL); - if (ace && !ace->perms) { - DLIST_REMOVE(dir_ace, ace); - SAFE_FREE(ace); - } - ace = canon_ace_entry_for(dir_ace, SMB_ACL_GROUP_OBJ, NULL); - if (ace && !ace->perms) { - DLIST_REMOVE(dir_ace, ace); - SAFE_FREE(ace); + ace = canon_ace_entry_for(file_ace, SMB_ACL_GROUP_OBJ, NULL); + if (ace && !ace->perms) { + DLIST_REMOVE(file_ace, ace); + SAFE_FREE(ace); + } } - } - - num_acls = count_canon_ace_list(file_ace); - num_dir_acls = count_canon_ace_list(dir_ace); - - /* Allocate the ace list. */ - 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; - } - memset(nt_ace_list, '\0', (num_acls + num_dir_acls) * sizeof(SEC_ACE) ); - - /* - * Create the NT ACE list from the canonical ace lists. - */ + num_acls = count_canon_ace_list(file_ace); + num_dir_acls = count_canon_ace_list(dir_ace); - ace = file_ace; + /* Allocate the ace list. */ + 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; + } - for (i = 0; i < num_acls; i++, ace = ace->next) { - SEC_ACCESS acc; + memset(nt_ace_list, '\0', (num_acls + num_dir_acls) * sizeof(SEC_ACE) ); + + /* + * Create the NT ACE list from the canonical ace lists. + */ + + ace = file_ace; - acc = map_canon_ace_perms(&nt_acl_type, &owner_sid, ace ); - init_sec_ace(&nt_ace_list[num_aces++], &ace->trustee, nt_acl_type, acc, 0); - } + for (i = 0; i < num_acls; i++, ace = ace->next) { + SEC_ACCESS acc; - /* 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; + acc = map_canon_ace_perms(&nt_acl_type, &owner_sid, ace ); + init_sec_ace(&nt_ace_list[num_aces++], &ace->trustee, nt_acl_type, acc, ace->inherited ? SEC_ACE_FLAG_INHERITED_ACE : 0); + } - 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); - } + /* 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; - ace = dir_ace; + 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); + } - for (i = 0; i < num_dir_acls; i++, ace = ace->next) { - SEC_ACCESS acc; + ace = dir_ace; - acc = map_canon_ace_perms(&nt_acl_type, &owner_sid, ace ); - init_sec_ace(&nt_ace_list[num_aces++], &ace->trustee, nt_acl_type, acc, - SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_INHERIT_ONLY); - } + for (i = 0; i < num_dir_acls; i++, ace = ace->next) { + SEC_ACCESS acc; + + acc = map_canon_ace_perms(&nt_acl_type, &owner_sid, ace ); + init_sec_ace(&nt_ace_list[num_aces++], &ace->trustee, nt_acl_type, acc, + SEC_ACE_FLAG_OBJECT_INHERIT|SEC_ACE_FLAG_CONTAINER_INHERIT| + SEC_ACE_FLAG_INHERIT_ONLY| + (ace->inherited ? SEC_ACE_FLAG_INHERITED_ACE : 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; + /* 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); - } - - /* - * Merge POSIX default ACLs and normal ACLs into one NT ACE. - * Win2K needs this to get the inheritance correct when replacing ACLs - * on a directory tree. Based on work by Jim @ IBM. - */ + 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|0); + } - num_aces = merge_default_aces(nt_ace_list, num_aces); + /* + * Merge POSIX default ACLs and normal ACLs into one NT ACE. + * Win2K needs this to get the inheritance correct when replacing ACLs + * on a directory tree. Based on work by Jim @ IBM. + */ - /* - * Sort to force deny entries to the front. - */ + num_aces = merge_default_aces(nt_ace_list, num_aces); - if (num_aces) - qsort( nt_ace_list, num_aces, sizeof(nt_ace_list[0]), QSORT_CAST nt_ace_comp); - } + } - if (num_aces) { - if((psa = make_sec_acl( main_loop_talloc_get(), ACL_REVISION, num_aces, nt_ace_list)) == NULL) { - DEBUG(0,("get_nt_acl: Unable to malloc space for acl.\n")); - goto done; + if (num_aces) { + if((psa = make_sec_acl( main_loop_talloc_get(), ACL_REVISION, num_aces, nt_ace_list)) == NULL) { + DEBUG(0,("get_nt_acl: Unable to malloc space for acl.\n")); + goto done; + } } - } + } /* security_info & DACL_SECURITY_INFORMATION */ - *ppdesc = make_standard_sec_desc( main_loop_talloc_get(), &owner_sid, &group_sid, psa, &sd_size); + psd = make_standard_sec_desc( main_loop_talloc_get(), + (security_info & OWNER_SECURITY_INFORMATION) ? &owner_sid : NULL, + (security_info & GROUP_SECURITY_INFORMATION) ? &group_sid : NULL, + psa, + &sd_size); - if(!*ppdesc) { + if(!psd) { DEBUG(0,("get_nt_acl: Unable to malloc space for security descriptor.\n")); sd_size = 0; } else { @@ -2482,17 +2882,24 @@ size_t get_nt_acl(files_struct *fsp, SEC_DESC **ppdesc) * any ACEs that are inherited dynamically. The DACL_PROTECTED * flag doesn't seem to bother Windows NT. */ - (*ppdesc)->type |= SE_DESC_DACL_PROTECTED; + if (get_protected_flag(pal)) + psd->type |= SE_DESC_DACL_PROTECTED; } + if (psd->dacl) + dacl_sort_into_canonical_order(psd->dacl->ace, (unsigned int)psd->dacl->num_aces); + + *ppdesc = psd; + done: if (posix_acl) - conn->vfs_ops.sys_acl_free_acl(conn, posix_acl); + SMB_VFS_SYS_ACL_FREE_ACL(conn, posix_acl); if (dir_acl) - conn->vfs_ops.sys_acl_free_acl(conn, dir_acl); + SMB_VFS_SYS_ACL_FREE_ACL(conn, dir_acl); free_canon_ace_list(file_ace); free_canon_ace_list(dir_ace); + free_inherited_info(pal); SAFE_FREE(nt_ace_list); return sd_size; @@ -2514,14 +2921,14 @@ static int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_ SMB_STRUCT_STAT st; /* try the direct way first */ - ret = vfs_chown(conn, fname, uid, gid); + ret = SMB_VFS_CHOWN(conn, fname, uid, gid); if (ret == 0) return 0; if(!CAN_WRITE(conn) || !lp_dos_filemode(SNUM(conn))) return -1; - if (vfs_stat(conn,fname,&st)) + if (SMB_VFS_STAT(conn,fname,&st)) return -1; fsp = open_file_fchmod(conn,fname,&st); @@ -2536,7 +2943,7 @@ static int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_ become_root(); /* Keep the current file gid the same. */ - ret = vfswrap_fchown(fsp, fsp->fd, uid, (gid_t)-1); + ret = SMB_VFS_FCHOWN(fsp, fsp->fd, uid, (gid_t)-1); unbecome_root(); close_file_fchmod(fsp); @@ -2579,10 +2986,10 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) */ if(fsp->is_directory || fsp->fd == -1) { - if(vfs_stat(fsp->conn,fsp->fsp_name, &sbuf) != 0) + if(SMB_VFS_STAT(fsp->conn,fsp->fsp_name, &sbuf) != 0) return False; } else { - if(vfs_fstat(fsp,fsp->fd,&sbuf) != 0) + if(SMB_VFS_FSTAT(fsp,fsp->fd,&sbuf) != 0) return False; } @@ -2628,7 +3035,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) */ if(fsp->is_directory) { - if(vfs_stat(fsp->conn, fsp->fsp_name, &sbuf) != 0) { + if(SMB_VFS_STAT(fsp->conn, fsp->fsp_name, &sbuf) != 0) { return False; } } else { @@ -2636,9 +3043,9 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) int ret; if(fsp->fd == -1) - ret = vfs_stat(fsp->conn, fsp->fsp_name, &sbuf); + ret = SMB_VFS_STAT(fsp->conn, fsp->fsp_name, &sbuf); else - ret = vfs_fstat(fsp,fsp->fd,&sbuf); + ret = SMB_VFS_FSTAT(fsp,fsp->fd,&sbuf); if(ret != 0) return False; @@ -2706,7 +3113,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) * No default ACL - delete one if it exists. */ - if (conn->vfs_ops.sys_acl_delete_def_file(conn, fsp->fsp_name) == -1) { + if (SMB_VFS_SYS_ACL_DELETE_DEF_FILE(conn, fsp->fsp_name) == -1) { DEBUG(3,("set_nt_acl: sys_acl_delete_def_file failed (%s)\n", strerror(errno))); free_canon_ace_list(file_ace_list); free_canon_ace_list(dir_ace_list); @@ -2715,6 +3122,10 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) } } + if (acl_set_support) + store_inheritance_attributes(fsp, file_ace_list, dir_ace_list, + (psd->type & SE_DESC_DACL_PROTECTED) ? True : False); + /* * If we cannot set using POSIX ACLs we fall back to checking if we need to chmod. */ @@ -2735,7 +3146,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) DEBUG(3,("set_nt_acl: chmod %s. perms = 0%o.\n", fsp->fsp_name, (unsigned int)posix_perms )); - if(conn->vfs_ops.chmod(conn,fsp->fsp_name, posix_perms) == -1) { + if(SMB_VFS_CHMOD(conn,fsp->fsp_name, posix_perms) == -1) { DEBUG(3,("set_nt_acl: chmod %s, 0%o failed. Error = %s.\n", fsp->fsp_name, (unsigned int)posix_perms, strerror(errno) )); free_canon_ace_list(file_ace_list); @@ -2777,7 +3188,7 @@ static int chmod_acl_internals( connection_struct *conn, SMB_ACL_T posix_acl, mo SMB_ACL_ENTRY_T entry; int num_entries = 0; - while ( conn->vfs_ops.sys_acl_get_entry(conn, posix_acl, entry_id, &entry) == 1) { + while ( SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1) { SMB_ACL_TAG_T tagtype; SMB_ACL_PERMSET_T permset; mode_t perms; @@ -2786,10 +3197,10 @@ static int chmod_acl_internals( connection_struct *conn, SMB_ACL_T posix_acl, mo if (entry_id == SMB_ACL_FIRST_ENTRY) entry_id = SMB_ACL_NEXT_ENTRY; - if (conn->vfs_ops.sys_acl_get_tag_type(conn, entry, &tagtype) == -1) + if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) return -1; - if (conn->vfs_ops.sys_acl_get_permset(conn, entry, &permset) == -1) + if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) return -1; num_entries++; @@ -2820,7 +3231,7 @@ static int chmod_acl_internals( connection_struct *conn, SMB_ACL_T posix_acl, mo if (map_acl_perms_to_permset(conn, perms, &permset) == -1) return -1; - if (conn->vfs_ops.sys_acl_set_permset(conn, entry, permset) == -1) + if (SMB_VFS_SYS_ACL_SET_PERMSET(conn, entry, permset) == -1) return -1; } @@ -2846,17 +3257,17 @@ static int copy_access_acl(connection_struct *conn, const char *from, const char SMB_ACL_T posix_acl = NULL; int ret = -1; - if ((posix_acl = conn->vfs_ops.sys_acl_get_file(conn, from, SMB_ACL_TYPE_ACCESS)) == NULL) + if ((posix_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, from, SMB_ACL_TYPE_ACCESS)) == NULL) return -1; if ((ret = chmod_acl_internals(conn, posix_acl, mode)) == -1) goto done; - ret = conn->vfs_ops.sys_acl_set_file(conn, to, SMB_ACL_TYPE_ACCESS, posix_acl); + ret = SMB_VFS_SYS_ACL_SET_FILE(conn, to, SMB_ACL_TYPE_ACCESS, posix_acl); done: - conn->vfs_ops.sys_acl_free_acl(conn, posix_acl); + SMB_VFS_SYS_ACL_FREE_ACL(conn, posix_acl); return ret; } @@ -2898,17 +3309,17 @@ int fchmod_acl(files_struct *fsp, int fd, mode_t mode) SMB_ACL_T posix_acl = NULL; int ret = -1; - if ((posix_acl = conn->vfs_ops.sys_acl_get_fd(fsp, fd)) == NULL) + if ((posix_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fd)) == NULL) return -1; if ((ret = chmod_acl_internals(conn, posix_acl, mode)) == -1) goto done; - ret = conn->vfs_ops.sys_acl_set_fd(fsp, fd, posix_acl); + ret = SMB_VFS_SYS_ACL_SET_FD(fsp, fd, posix_acl); done: - conn->vfs_ops.sys_acl_free_acl(conn, posix_acl); + SMB_VFS_SYS_ACL_FREE_ACL(conn, posix_acl); return ret; } @@ -2918,14 +3329,14 @@ int fchmod_acl(files_struct *fsp, int fd, mode_t mode) BOOL directory_has_default_acl(connection_struct *conn, const char *fname) { - SMB_ACL_T dir_acl = conn->vfs_ops.sys_acl_get_file( conn, fname, SMB_ACL_TYPE_DEFAULT); + SMB_ACL_T dir_acl = SMB_VFS_SYS_ACL_GET_FILE( conn, fname, SMB_ACL_TYPE_DEFAULT); BOOL has_acl = False; SMB_ACL_ENTRY_T entry; - if (dir_acl != NULL && (conn->vfs_ops.sys_acl_get_entry(conn, dir_acl, SMB_ACL_FIRST_ENTRY, &entry) == 1)) + if (dir_acl != NULL && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, dir_acl, SMB_ACL_FIRST_ENTRY, &entry) == 1)) has_acl = True; if (dir_acl) - conn->vfs_ops.sys_acl_free_acl(conn, dir_acl); + SMB_VFS_SYS_ACL_FREE_ACL(conn, dir_acl); return has_acl; } diff --git a/source3/smbd/quotas.c b/source3/smbd/quotas.c index 5b843bd09a..91c952aa90 100644 --- a/source3/smbd/quotas.c +++ b/source3/smbd/quotas.c @@ -27,6 +27,15 @@ #include "includes.h" +#ifndef HAVE_SYS_QUOTAS + +/* just a quick hack because sysquotas.h is included before linux/quota.h */ +#ifdef QUOTABLOCK_SIZE +#undef QUOTABLOCK_SIZE +#endif + +#ifdef WITH_QUOTAS + #if defined(VXFS_QUOTA) /* @@ -1112,3 +1121,108 @@ BOOL disk_quotas_vxfs(const pstring name, char *path, SMB_BIG_UINT *bsize, SMB_B #endif /* SUNOS5 || ... */ #endif /* VXFS_QUOTA */ + +#else /* WITH_QUOTAS */ + +BOOL disk_quotas(const char *path,SMB_BIG_UINT *bsize,SMB_BIG_UINT *dfree,SMB_BIG_UINT *dsize) +{ + (*bsize) = 512; /* This value should be ignored */ + + /* And just to be sure we set some values that hopefully */ + /* will be larger that any possible real-world value */ + (*dfree) = (SMB_BIG_UINT)-1; + (*dsize) = (SMB_BIG_UINT)-1; + + /* As we have select not to use quotas, allways fail */ + return False; +} +#endif /* WITH_QUOTAS */ + +#else /* HAVE_SYS_QUOTAS */ +/* wrapper to the new sys_quota interface + this file should be removed later + */ +BOOL disk_quotas(const char *path,SMB_BIG_UINT *bsize,SMB_BIG_UINT *dfree,SMB_BIG_UINT *dsize) +{ + int r; + SMB_DISK_QUOTA D; + unid_t id; + + id.uid = geteuid(); + + r=sys_get_quota(path, SMB_USER_QUOTA_TYPE, id, &D); + + /* Use softlimit to determine disk space, except when it has been exceeded */ + *bsize = D.bsize; + if (r == -1) { + if (errno == EDQUOT) { + *dfree =0; + *dsize =D.curblocks; + return (True); + } else { + goto try_group_quota; + } + } + + /* Use softlimit to determine disk space, except when it has been exceeded */ + if ( + (D.softlimit && D.curblocks >= D.softlimit) || + (D.hardlimit && D.curblocks >= D.hardlimit) || + (D.isoftlimit && D.curinodes >= D.isoftlimit) || + (D.ihardlimit && D.curinodes>=D.ihardlimit) + ) { + *dfree = 0; + *dsize = D.curblocks; + } else if (D.softlimit==0 && D.hardlimit==0) { + goto try_group_quota; + } else { + if (D.softlimit == 0) + D.softlimit = D.hardlimit; + *dfree = D.softlimit - D.curblocks; + *dsize = D.softlimit; + } + + return True; + +try_group_quota: +#ifdef HAVE_GROUP_QUOTA + id.gid = getegid(); + + r=sys_get_quota(path, SMB_GROUP_QUOTA_TYPE, id, &D); + + /* Use softlimit to determine disk space, except when it has been exceeded */ + *bsize = D.bsize; + if (r == -1) { + if (errno == EDQUOT) { + *dfree =0; + *dsize =D.curblocks; + return (True); + } else { + return False; + } + } + + /* Use softlimit to determine disk space, except when it has been exceeded */ + if ( + (D.softlimit && D.curblocks >= D.softlimit) || + (D.hardlimit && D.curblocks >= D.hardlimit) || + (D.isoftlimit && D.curinodes >= D.isoftlimit) || + (D.ihardlimit && D.curinodes>=D.ihardlimit) + ) { + *dfree = 0; + *dsize = D.curblocks; + } else if (D.softlimit==0 && D.hardlimit==0) { + return False; + } else { + if (D.softlimit == 0) + D.softlimit = D.hardlimit; + *dfree = D.softlimit - D.curblocks; + *dsize = D.softlimit; + } + + return (True); +#else /* HAVE_GROUP_QUOTA */ + return False; +#endif /* HAVE_GROUP_QUOTA */ +} +#endif /* HAVE_SYS_QUOTAS */ diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index b2dab2fea2..e7f01ad02f 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -39,7 +39,7 @@ unsigned int smb_echo_count = 0; extern BOOL global_encrypted_passwords_negotiated; /**************************************************************************** - Reply to an special message. + Reply to a special message. ****************************************************************************/ int reply_special(char *inbuf,char *outbuf) @@ -148,7 +148,7 @@ int reply_tcon(connection_struct *conn, const char *service; pstring service_buf; pstring password; - fstring dev; + pstring dev; int outsize = 0; uint16 vuid = SVAL(inbuf,smb_uid); int pwlen=0; @@ -204,7 +204,7 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt { fstring service; DATA_BLOB password; - + /* what the cleint thinks the device is */ fstring client_devicetype; /* what the server tells the client the share represents */ @@ -283,15 +283,16 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt set_message_end(outbuf,p); } else { /* NT sets the fstype of IPC$ to the null string */ - const char *fsname = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn)); + const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn)); set_message(outbuf,3,0,True); - - p = smb_buf(outbuf); + + p = smb_buf(outbuf); p += srvstr_push(outbuf, p, server_devicetype, -1, - STR_TERMINATE|STR_ASCII); - p += srvstr_push(outbuf, p, fsname, -1, - STR_TERMINATE); + STR_TERMINATE|STR_ASCII); + p += srvstr_push(outbuf, p, fstype, -1, + STR_TERMINATE); + set_message_end(outbuf,p); /* what does setting this bit do? It is set by NT4 and @@ -398,7 +399,7 @@ int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size mode = SVAL(inbuf,smb_vwv0); if (check_name(name,conn)) { - if (VALID_STAT(sbuf) || vfs_stat(conn,name,&sbuf) == 0) + if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,name,&sbuf) == 0) if (!(ok = S_ISDIR(sbuf.st_mode))) errno = ENOTDIR; } @@ -457,7 +458,7 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size } else { unix_convert(fname,conn,0,&bad_path,&sbuf); if (check_name(fname,conn)) { - if (VALID_STAT(sbuf) || vfs_stat(conn,fname,&sbuf) == 0) { + if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,fname,&sbuf) == 0) { mode = dos_mode(conn,fname,&sbuf); size = sbuf.st_size; mtime = sbuf.st_mtime; @@ -552,7 +553,7 @@ int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_siz SMB_BIG_UINT dfree,dsize,bsize; START_PROFILE(SMBdskattr); - conn->vfs_ops.disk_free(conn,".",True,&bsize,&dfree,&dsize); + SMB_VFS_DISK_FREE(conn,".",True,&bsize,&dfree,&dsize); outsize = set_message(outbuf,5,0,True); @@ -1127,7 +1128,7 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return(UNIXERROR(ERRDOS,ERRnoaccess)); } - vfs_stat(conn,fname,&sbuf); + SMB_VFS_STAT(conn,fname,&sbuf); /* Open file in dos compatibility share mode. */ /* We should fail if file does not exist. */ @@ -1226,7 +1227,7 @@ static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype) if (!CAN_WRITE(conn)) return NT_STATUS_MEDIA_WRITE_PROTECTED; - if (conn->vfs_ops.lstat(conn,fname,&sbuf) != 0) + if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0) return NT_STATUS_OBJECT_NAME_NOT_FOUND; fmode = dos_mode(conn,fname,&sbuf); @@ -1312,7 +1313,7 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name) error = can_delete(directory,conn,dirtype); if (!NT_STATUS_IS_OK(error)) return error; - if (vfs_unlink(conn,directory) == 0) { + if (SMB_VFS_UNLINK(conn,directory) == 0) { count++; } } else { @@ -1342,7 +1343,7 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name) slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname); error = can_delete(fname,conn,dirtype); if (!NT_STATUS_IS_OK(error)) continue; - if (vfs_unlink(conn,fname) == 0) count++; + if (SMB_VFS_UNLINK(conn,fname) == 0) count++; DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname)); } CloseDir(dirptr); @@ -1428,7 +1429,7 @@ void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T st header.length = 4; header.free = NULL; - if ( conn->vfs_ops.sendfile( smbd_server_fd(), fsp, fsp->fd, &header, startpos, nread) == -1) { + if ( SMB_VFS_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. @@ -1463,6 +1464,7 @@ void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T st int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize) { + extern struct current_user current_user; ssize_t maxcount,mincount; size_t nread = 0; SMB_OFF_T startpos; @@ -1552,7 +1554,7 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s if (size < sizeneeded) { SMB_STRUCT_STAT st; - if (vfs_fstat(fsp,fsp->fd,&st) == 0) + if (SMB_VFS_FSTAT(fsp,fsp->fd,&st) == 0) size = st.st_size; if (!fsp->can_write) fsp->size = size; @@ -1721,7 +1723,7 @@ int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length SMB_STRUCT_STAT sbuf; DATA_BLOB header; - if(vfs_fstat(fsp,fsp->fd, &sbuf) == -1) + if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1) return(UNIXERROR(ERRDOS,ERRnoaccess)); if (startpos > sbuf.st_size) @@ -1748,7 +1750,7 @@ int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length header.length = data - outbuf; header.free = NULL; - if ( conn->vfs_ops.sendfile( smbd_server_fd(), fsp, fsp->fd, &header, startpos, smb_maxcnt) == -1) { + if ( SMB_VFS_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. @@ -2260,7 +2262,7 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int break; } - if((res = conn->vfs_ops.lseek(fsp,fsp->fd,startpos,umode)) == -1) { + if((res = SMB_VFS_LSEEK(fsp,fsp->fd,startpos,umode)) == -1) { /* * Check for the special case where a seek before the start * of the file sets the offset to zero. Added in the CIFS spec, @@ -2272,7 +2274,7 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int if(umode == SEEK_CUR) { - if((current_pos = conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_CUR)) == -1) { + if((current_pos = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_CUR)) == -1) { END_PROFILE(SMBlseek); return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -2283,7 +2285,7 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int SMB_STRUCT_STAT sbuf; - if(vfs_fstat(fsp,fsp->fd, &sbuf) == -1) { + if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1) { END_PROFILE(SMBlseek); return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -2292,7 +2294,7 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int } if(current_pos < 0) - res = conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_SET); + res = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_SET); } if(res == -1) { @@ -2360,6 +2362,7 @@ int reply_exit(connection_struct *conn, int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize) { + extern struct current_user current_user; int outsize = 0; time_t mtime; int32 eclass = 0, err = 0; @@ -2380,7 +2383,7 @@ int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size, * We can only use CHECK_FSP if we know it's not a directory. */ - if(!fsp || (fsp->conn != conn)) { + if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) { END_PROFILE(SMBclose); return ERROR_DOS(ERRDOS,ERRbadfid); } @@ -2827,7 +2830,7 @@ NTSTATUS mkdir_internal(connection_struct *conn, pstring directory) unix_convert(directory,conn,0,&bad_path,&sbuf); if (check_name(directory, conn)) - ret = vfs_mkdir(conn,directory,unix_mode(conn,aDIR,directory)); + ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory)); if (ret == -1) { NTSTATUS nterr = set_bad_path_error(errno, bad_path); @@ -2898,7 +2901,7 @@ static BOOL recursive_rmdir(connection_struct *conn, char *directory) pstrcat(fullname, "/"); pstrcat(fullname, dname); - if(conn->vfs_ops.lstat(conn,fullname, &st) != 0) { + if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) { ret = True; break; } @@ -2908,11 +2911,11 @@ static BOOL recursive_rmdir(connection_struct *conn, char *directory) ret = True; break; } - if(vfs_rmdir(conn,fullname) != 0) { + if(SMB_VFS_RMDIR(conn,fullname) != 0) { ret = True; break; } - } else if(vfs_unlink(conn,fullname) != 0) { + } else if(SMB_VFS_UNLINK(conn,fullname) != 0) { ret = True; break; } @@ -2929,7 +2932,7 @@ BOOL rmdir_internals(connection_struct *conn, char *directory) { BOOL ok; - ok = (vfs_rmdir(conn,directory) == 0); + ok = (SMB_VFS_RMDIR(conn,directory) == 0); if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) { /* * Check to see if the only thing in this directory are @@ -2971,21 +2974,21 @@ BOOL rmdir_internals(connection_struct *conn, char *directory) pstrcat(fullname, "/"); pstrcat(fullname, dname); - if(conn->vfs_ops.lstat(conn,fullname, &st) != 0) + if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) break; if(st.st_mode & S_IFDIR) { if(lp_recursive_veto_delete(SNUM(conn))) { if(recursive_rmdir(conn, fullname) != 0) break; } - if(vfs_rmdir(conn,fullname) != 0) + if(SMB_VFS_RMDIR(conn,fullname) != 0) break; - } else if(vfs_unlink(conn,fullname) != 0) + } else if(SMB_VFS_UNLINK(conn,fullname) != 0) break; } CloseDir(dirptr); /* Retry the rmdir */ - ok = (vfs_rmdir(conn,directory) == 0); + ok = (SMB_VFS_RMDIR(conn,directory) == 0); } else { CloseDir(dirptr); } @@ -3104,7 +3107,7 @@ static BOOL resolve_wildcards(const char *name1, char *name2) if (ext2[0]) { snprintf(pname2, available_space - 1, "%s.%s", root2, ext2); } else { - StrnCpy(pname2, root2, available_space - 1); + pstrcpy_base(pname2, root2, name2); } return(True); @@ -3281,7 +3284,7 @@ directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n", return NT_STATUS_OBJECT_NAME_COLLISION; } - if(conn->vfs_ops.rename(conn,directory, newname) == 0) { + if(SMB_VFS_RENAME(conn,directory, newname) == 0) { DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n", directory,newname)); return NT_STATUS_OK; @@ -3348,7 +3351,7 @@ directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n", continue; } - if (!conn->vfs_ops.rename(conn,fname,destname)) + if (!SMB_VFS_RENAME(conn,fname,destname)) count++; DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname)); } @@ -3442,7 +3445,7 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, if (!target_is_directory && count) ofun = FILE_EXISTS_OPEN; - if (vfs_stat(conn,dest,&sbuf2) == -1) + if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1) ZERO_STRUCTP(&sbuf2); fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY), @@ -3454,7 +3457,7 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun, } if ((ofun&3) == 1) { - if(conn->vfs_ops.lseek(fsp2,fsp2->fd,0,SEEK_END) == -1) { + if(SMB_VFS_LSEEK(fsp2,fsp2->fd,0,SEEK_END) == -1) { DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) )); /* * Stop the copy from occurring. @@ -3938,7 +3941,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+999)/1000); + lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+499)/500); /* Now do any requested locks */ data += ((large_file_format ? 20 : 10)*num_ulocks); @@ -4382,8 +4385,9 @@ int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, SIVAL(outbuf,smb_vwv6,0); SIVAL(outbuf,smb_vwv8,0); } else { + uint32 allocation_size = get_allocation_size(fsp, &sbuf); SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size); - SIVAL(outbuf,smb_vwv8,SMB_ROUNDUP(sbuf.st_size,1024)); + SIVAL(outbuf,smb_vwv8,allocation_size); } SSVAL(outbuf,smb_vwv10, mode); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index c24fc5134d..453ff54e4b 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -634,6 +634,12 @@ static BOOL init_structs(void ) main program. ****************************************************************************/ +/* Declare prototype for build_options() to avoid having to run it through + mkproto.h. Mixing $(builddir) and $(srcdir) source files in the current + prototype generation system is too complicated. */ + +void build_options(BOOL screen); + int main(int argc,const char *argv[]) { /* shall I run as a daemon */ @@ -836,29 +842,24 @@ static BOOL init_structs(void ) if (!init_registry()) exit(1); - if(!initialize_password_db(False)) - exit(1); + /* Initialise the password backed before the global_sam_sid + to ensure that we fetch from ldap before we make a domain sid up */ - if (!idmap_init()) + if(!initialize_password_db(False)) exit(1); - if (!idmap_init_wellknown_sids()) + if(!get_global_sam_sid()) { + DEBUG(0,("ERROR: Samba cannot create a SAM SID.\n")); exit(1); + } static_init_rpc; init_modules(); - uni_group_cache_init(); /* Non-critical */ - /* possibly reload the services file. */ reload_services(True); - if(!get_global_sam_sid()) { - DEBUG(0,("ERROR: Samba cannot create a SAM SID.\n")); - exit(1); - } - if (!init_account_policy()) { DEBUG(0,("Could not open account policy tdb.\n")); exit(1); @@ -877,10 +878,6 @@ static BOOL init_structs(void ) if (!init_change_notify()) exit(1); - /* Setup privileges database */ - if (!privilege_init()) - exit(1); - /* re-initialise the timezone */ TimeInit(); @@ -889,7 +886,6 @@ static BOOL init_structs(void ) smbd_process(); - uni_group_cache_shutdown(); namecache_shutdown(); exit_server("normal exit"); return(0); diff --git a/source3/smbd/service.c b/source3/smbd/service.c index c9f5330551..18e0887071 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -237,7 +237,7 @@ static NTSTATUS share_sanity_checks(int snum, fstring dev) } } - strupper(dev); + strupper_m(dev); if (lp_print_ok(snum)) { if (!strequal(dev, "LPT1:")) { @@ -359,13 +359,15 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, guest = True; pass = getpwnam_alloc(guestname); if (!pass) { - DEBUG(0,("authorise_login: Invalid guest account %s??\n",guestname)); + DEBUG(0,("make_connection_snum: Invalid guest account %s??\n",guestname)); conn_free(conn); *status = NT_STATUS_NO_SUCH_USER; return NULL; } fstrcpy(user,pass->pw_name); conn->force_user = True; + conn->uid = pass->pw_uid; + conn->gid = pass->pw_gid; string_set(&conn->user,pass->pw_name); passwd_free(&pass); DEBUG(3,("Guest only user %s\n",user)); @@ -704,14 +706,12 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, /* Invoke VFS make connection hook */ - if (conn->vfs_ops.connect) { - if (conn->vfs_ops.connect(conn, lp_servicename(snum), user) < 0) { - DEBUG(0,("make_connection: VFS make connection failed!\n")); - change_to_root_user(); - conn_free(conn); - *status = NT_STATUS_UNSUCCESSFUL; - return NULL; - } + if (SMB_VFS_CONNECT(conn, lp_servicename(snum), user) < 0) { + DEBUG(0,("make_connection: VFS make connection failed!\n")); + change_to_root_user(); + conn_free(conn); + *status = NT_STATUS_UNSUCCESSFUL; + return NULL; } /* we've finished with the user stuff - go back to root */ @@ -828,7 +828,7 @@ connection_struct *make_connection(const char *service_in, DATA_BLOB password, fstrcpy(service, service_in); - strlower(service); + strlower_m(service); snum = find_service(service); @@ -872,13 +872,8 @@ void close_cnum(connection_struct *conn, uint16 vuid) get_remote_machine_name(),conn->client_address, lp_servicename(SNUM(conn)))); - if (conn->vfs_ops.disconnect != NULL) { - - /* Call VFS disconnect hook */ - - conn->vfs_ops.disconnect(conn); - - } + /* Call VFS disconnect hook */ + SMB_VFS_DISCONNECT(conn); yield_connection(conn, lp_servicename(SNUM(conn))); diff --git a/source3/smbd/session.c b/source3/smbd/session.c index 07a9504234..4d8826d332 100644 --- a/source3/smbd/session.c +++ b/source3/smbd/session.c @@ -33,6 +33,8 @@ BOOL session_claim(user_struct *vuser) { int i = 0; TDB_DATA data; + struct sockaddr sa; + struct in_addr *client_ip; struct sessionid sessionid; uint32 pid = (uint32)sys_getpid(); TDB_DATA key; @@ -64,7 +66,6 @@ BOOL session_claim(user_struct *vuser) data.dptr = NULL; data.dsize = 0; -#if WITH_UTMP if (lp_utmp()) { for (i=1;isession_keystr = strdup(keystr); if (!vuser->session_keystr) { @@ -153,7 +154,8 @@ void session_yield(user_struct *vuser) { TDB_DATA dbuf; struct sessionid sessionid; - TDB_DATA key; + struct in_addr *client_ip; + TDB_DATA key; if (!tdb) return; @@ -171,14 +173,15 @@ void session_yield(user_struct *vuser) memcpy(&sessionid, dbuf.dptr, sizeof(sessionid)); + client_ip = interpret_addr2(sessionid.ip_addr); + SAFE_FREE(dbuf.dptr); -#if WITH_UTMP if (lp_utmp()) { sys_utmp_yield(sessionid.username, sessionid.hostname, + client_ip, sessionid.id_str, sessionid.id_num); } -#endif smb_pam_close_session(sessionid.username, sessionid.id_str, sessionid.hostname); diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 2631961739..7d77ed3071 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -53,10 +53,10 @@ static NTSTATUS do_map_to_guest(NTSTATUS status, auth_serversupplied_info **serv return status; } - /**************************************************************************** Add the standard 'Samba' signature to the end of the session setup. ****************************************************************************/ + static int add_signature(char *outbuf, char *p) { char *start = p; @@ -72,8 +72,9 @@ static int add_signature(char *outbuf, char *p) } /**************************************************************************** -send a security blob via a session setup reply + Send a security blob via a session setup reply. ****************************************************************************/ + static BOOL reply_sesssetup_blob(connection_struct *conn, char *outbuf, DATA_BLOB blob, NTSTATUS nt_status) { @@ -101,6 +102,7 @@ static BOOL reply_sesssetup_blob(connection_struct *conn, char *outbuf, /**************************************************************************** Do a 'guest' logon, getting back the ****************************************************************************/ + static NTSTATUS check_guest_password(auth_serversupplied_info **server_info) { struct auth_context *auth_context; @@ -267,12 +269,12 @@ static int reply_spnego_kerberos(connection_struct *conn, } #endif - /**************************************************************************** - send a session setup reply, wrapped in SPNEGO. - get vuid and check first. - end the NTLMSSP exchange context if we are OK/complete fail + Send a session setup reply, wrapped in SPNEGO. + Get vuid and check first. + End the NTLMSSP exchange context if we are OK/complete fail ***************************************************************************/ + static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *outbuf, AUTH_NTLMSSP_STATE **auth_ntlmssp_state, DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status) @@ -326,8 +328,9 @@ static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *outbuf, } /**************************************************************************** -reply to a session setup spnego negotiate packet + Reply to a session setup spnego negotiate packet. ****************************************************************************/ + static int reply_spnego_negotiate(connection_struct *conn, char *inbuf, char *outbuf, @@ -387,11 +390,11 @@ static int reply_spnego_negotiate(connection_struct *conn, /* already replied */ return -1; } - /**************************************************************************** -reply to a session setup spnego auth packet + Reply to a session setup spnego auth packet. ****************************************************************************/ + static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, DATA_BLOB blob1) @@ -425,10 +428,10 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, return -1; } - /**************************************************************************** -reply to a session setup command + Reply to a session setup command. ****************************************************************************/ + static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf, char *outbuf, int length,int bufsize) @@ -509,8 +512,9 @@ static void setup_new_vc_session(void) } /**************************************************************************** -reply to a session setup command + Reply to a session setup command. ****************************************************************************/ + int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, int length,int bufsize) { diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 44bae48990..22b8a33a1e 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -24,7 +24,6 @@ extern BOOL case_sensitive; - /**************************************************************************** Stat cache code used in unix_convert. *****************************************************************************/ @@ -53,123 +52,126 @@ static hash_table stat_cache; void stat_cache_add( const char *full_orig_name, const char *orig_translated_path) { - stat_cache_entry *scp; - stat_cache_entry *found_scp; - char *translated_path; - size_t translated_path_length; - - char *original_path; - size_t original_path_length; - - hash_element *hash_elem; - - if (!lp_stat_cache()) return; - - /* - * Don't cache trivial valid directory entries. - */ - if((*full_orig_name == '\0') || (strcmp(full_orig_name, ".") == 0) || - (strcmp(full_orig_name, "..") == 0)) - return; - - /* - * If we are in case insentive mode, we don't need to - * store names that need no translation - else, it - * would be a waste. - */ - - if(case_sensitive && (strcmp(full_orig_name, orig_translated_path) == 0)) - return; - - /* - * Remove any trailing '/' characters from the - * translated path. - */ - - translated_path = strdup(orig_translated_path); - if (!translated_path) - return; - - translated_path_length = strlen(translated_path); - - if(translated_path[translated_path_length-1] == '/') { - translated_path[translated_path_length-1] = '\0'; - translated_path_length--; - } - - original_path = strdup(full_orig_name); - if (!original_path) { - SAFE_FREE(translated_path); - return; - } - - original_path_length = strlen(original_path); - - if(original_path[original_path_length-1] == '/') { - original_path[original_path_length-1] = '\0'; - original_path_length--; - } - - if(!case_sensitive) - strupper(original_path); - - if (original_path_length != translated_path_length) { - if (original_path_length < translated_path_length) { - DEBUG(0, ("OOPS - tried to store stat cache entry for werid length paths [%s] %u and [%s] %u)!\n", original_path, original_path_length, translated_path, translated_path_length)); - SAFE_FREE(original_path); - SAFE_FREE(translated_path); - return; - } - - /* we only want to store the first part of original_path, - up to the length of translated_path */ - - original_path[translated_path_length] = '\0'; - original_path_length = translated_path_length; - } - - /* - * Check this name doesn't exist in the cache before we - * add it. - */ - - if ((hash_elem = hash_lookup(&stat_cache, original_path))) { - found_scp = (stat_cache_entry *)(hash_elem->value); - if (strcmp((found_scp->translated_path), orig_translated_path) == 0) { - /* already in hash table */ - SAFE_FREE(original_path); - SAFE_FREE(translated_path); - return; - } - /* hash collision - remove before we re-add */ - hash_remove(&stat_cache, hash_elem); - } + stat_cache_entry *scp; + stat_cache_entry *found_scp; + char *translated_path; + size_t translated_path_length; + + char *original_path; + size_t original_path_length; + + hash_element *hash_elem; + + if (!lp_stat_cache()) + return; + + /* + * Don't cache trivial valid directory entries. + */ + + if((*full_orig_name == '\0') || (strcmp(full_orig_name, ".") == 0) || + (strcmp(full_orig_name, "..") == 0)) + return; + + /* + * If we are in case insentive mode, we don't need to + * store names that need no translation - else, it + * would be a waste. + */ + + if(case_sensitive && (strcmp(full_orig_name, orig_translated_path) == 0)) + return; + + /* + * Remove any trailing '/' characters from the + * translated path. + */ + + translated_path = strdup(orig_translated_path); + if (!translated_path) + return; + + translated_path_length = strlen(translated_path); + + if(translated_path[translated_path_length-1] == '/') { + translated_path[translated_path_length-1] = '\0'; + translated_path_length--; + } + + original_path = strdup(full_orig_name); + if (!original_path) { + SAFE_FREE(translated_path); + return; + } + + original_path_length = strlen(original_path); + + if(original_path[original_path_length-1] == '/') { + original_path[original_path_length-1] = '\0'; + original_path_length--; + } + + if(!case_sensitive) + strupper_m(original_path); + + if (original_path_length != translated_path_length) { + if (original_path_length < translated_path_length) { + DEBUG(0, ("OOPS - tried to store stat cache entry for werid length paths [%s] %u and [%s] %u)!\n", + original_path, original_path_length, translated_path, translated_path_length)); + SAFE_FREE(original_path); + SAFE_FREE(translated_path); + return; + } + + /* we only want to store the first part of original_path, + up to the length of translated_path */ + + original_path[translated_path_length] = '\0'; + original_path_length = translated_path_length; + } + + /* + * Check this name doesn't exist in the cache before we + * add it. + */ + + if ((hash_elem = hash_lookup(&stat_cache, original_path))) { + found_scp = (stat_cache_entry *)(hash_elem->value); + if (strcmp((found_scp->translated_path), orig_translated_path) == 0) { + /* already in hash table */ + SAFE_FREE(original_path); + SAFE_FREE(translated_path); + return; + } + /* hash collision - remove before we re-add */ + hash_remove(&stat_cache, hash_elem); + } - /* - * New entry. - */ + /* + * New entry. + */ - if((scp = (stat_cache_entry *)malloc(sizeof(stat_cache_entry) - +original_path_length - +translated_path_length)) == NULL) { - DEBUG(0,("stat_cache_add: Out of memory !\n")); - SAFE_FREE(original_path); - SAFE_FREE(translated_path); - return; - } - - scp->original_path = scp->names; - scp->translated_path = scp->names + original_path_length + 1; - safe_strcpy(scp->original_path, original_path, original_path_length); - safe_strcpy(scp->translated_path, translated_path, translated_path_length); - scp->translated_path_length = translated_path_length; - - hash_insert(&stat_cache, (char *)scp, original_path); - - SAFE_FREE(original_path); - SAFE_FREE(translated_path); - - DEBUG(5,("stat_cache_add: Added entry %s -> %s\n", scp->original_path, scp->translated_path)); + if((scp = (stat_cache_entry *)malloc(sizeof(stat_cache_entry) + +original_path_length + +translated_path_length)) == NULL) { + DEBUG(0,("stat_cache_add: Out of memory !\n")); + SAFE_FREE(original_path); + SAFE_FREE(translated_path); + return; + } + + scp->original_path = scp->names; + scp->translated_path = scp->names + original_path_length + 1; + safe_strcpy(scp->original_path, original_path, original_path_length); + safe_strcpy(scp->translated_path, translated_path, translated_path_length); + scp->translated_path_length = translated_path_length; + + hash_insert(&stat_cache, (char *)scp, original_path); + + SAFE_FREE(original_path); + SAFE_FREE(translated_path); + + DEBUG(5,("stat_cache_add: Added entry %s -> %s\n", scp->original_path, scp->translated_path)); } /** @@ -191,73 +193,106 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, char **start, SMB_STRUCT_STAT *pst) { - stat_cache_entry *scp; - pstring chk_name; - size_t namelen; - hash_element *hash_elem; - char *sp; - - if (!lp_stat_cache()) - return False; + stat_cache_entry *scp; + pstring chk_name; + size_t namelen; + hash_element *hash_elem; + char *sp; + BOOL sizechanged = False; + unsigned int num_components = 0; + + if (!lp_stat_cache()) + return False; - namelen = strlen(name); - - *start = name; - - DO_PROFILE_INC(statcache_lookups); - - /* - * Don't lookup trivial valid directory entries. - */ - if((*name == '\0') || (strcmp(name, ".") == 0) || (strcmp(name, "..") == 0)) { - DO_PROFILE_INC(statcache_misses); - return False; - } - - pstrcpy(chk_name, name); - if(!case_sensitive) - strupper( chk_name ); - - while (1) { - hash_elem = hash_lookup(&stat_cache, chk_name); - if(hash_elem == NULL) { - /* - * Didn't find it - remove last component for next try. - */ - sp = strrchr_m(chk_name, '/'); - if (sp) { - *sp = '\0'; - } else { - /* - * We reached the end of the name - no match. - */ - DO_PROFILE_INC(statcache_misses); - return False; - } - if((*chk_name == '\0') || (strcmp(chk_name, ".") == 0) - || (strcmp(chk_name, "..") == 0)) { - DO_PROFILE_INC(statcache_misses); - return False; - } - } else { - scp = (stat_cache_entry *)(hash_elem->value); - DO_PROFILE_INC(statcache_hits); - if(vfs_stat(conn,scp->translated_path, pst) != 0) { - /* Discard this entry - it doesn't exist in the filesystem. */ - hash_remove(&stat_cache, hash_elem); - return False; - } - memcpy(name, scp->translated_path, MIN(sizeof(pstring)-1, scp->translated_path_length)); - - /* set pointer for 'where to start' on fixing the rest of the name */ - *start = &name[scp->translated_path_length]; - if(**start == '/') - ++*start; - - pstrcpy(dirpath, scp->translated_path); - return (namelen == scp->translated_path_length); - } - } + namelen = strlen(name); + + *start = name; + + DO_PROFILE_INC(statcache_lookups); + + /* + * Don't lookup trivial valid directory entries. + */ + if((*name == '\0') || (strcmp(name, ".") == 0) || (strcmp(name, "..") == 0)) { + DO_PROFILE_INC(statcache_misses); + return False; + } + + pstrcpy(chk_name, name); + + if(!case_sensitive) { + strupper_m( chk_name ); + /* + * In some language encodings the length changes + * if we uppercase. We need to treat this differently + * below. + */ + if (strlen(chk_name) != namelen) + sizechanged = True; + } + + while (1) { + hash_elem = hash_lookup(&stat_cache, chk_name); + if(hash_elem == NULL) { + /* + * Didn't find it - remove last component for next try. + */ + sp = strrchr_m(chk_name, '/'); + if (sp) { + *sp = '\0'; + /* + * Count the number of times we have done this, + * we'll need it when reconstructing the string. + */ + if (sizechanged) + num_components++; + + } else { + /* + * We reached the end of the name - no match. + */ + DO_PROFILE_INC(statcache_misses); + return False; + } + if((*chk_name == '\0') || (strcmp(chk_name, ".") == 0) + || (strcmp(chk_name, "..") == 0)) { + DO_PROFILE_INC(statcache_misses); + return False; + } + } else { + scp = (stat_cache_entry *)(hash_elem->value); + DO_PROFILE_INC(statcache_hits); + if(SMB_VFS_STAT(conn,scp->translated_path, pst) != 0) { + /* Discard this entry - it doesn't exist in the filesystem. */ + hash_remove(&stat_cache, hash_elem); + return False; + } + + if (!sizechanged) { + memcpy(name, scp->translated_path, MIN(sizeof(pstring)-1, scp->translated_path_length)); + } else if (num_components == 0) { + pstrcpy(name, scp->translated_path); + } else { + sp = strnrchr_m(name, '/', num_components); + if (sp) { + pstring last_component; + pstrcpy(last_component, sp); + pstrcpy(name, scp->translated_path); + pstrcat(name, last_component); + } else { + pstrcpy(name, scp->translated_path); + } + } + + /* set pointer for 'where to start' on fixing the rest of the name */ + *start = &name[scp->translated_path_length]; + if(**start == '/') + ++*start; + + pstrcpy(dirpath, scp->translated_path); + return (namelen == scp->translated_path_length); + } + } } /*************************************************************************** ** @@ -271,7 +306,8 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, BOOL reset_stat_cache( void ) { static BOOL initialised; - if (!lp_stat_cache()) return True; + if (!lp_stat_cache()) + return True; if (initialised) { hash_clear(&stat_cache); @@ -280,4 +316,4 @@ BOOL reset_stat_cache( void ) initialised = hash_table_init( &stat_cache, INIT_STAT_CACHE_SIZE, (compare_function)(strcmp)); return initialised; -} /* reset_stat_cache */ +} diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index de598d6713..bdcd04443e 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1,7 +1,8 @@ /* Unix SMB/CIFS implementation. SMB transaction2 handling - Copyright (C) Jeremy Allison 1994-2001 + Copyright (C) Jeremy Allison 1994-2001 + Copyright (C) Stefan (metze) Metzmacher 2003 Extensively modified by Andrew Tridgell, 1995 @@ -28,6 +29,7 @@ extern int smb_read_error; extern fstring local_machine; extern int global_oplock_break; extern uint32 global_client_caps; +extern struct current_user current_user; #define get_file_size(sbuf) ((sbuf).st_size) @@ -324,7 +326,7 @@ static BOOL exact_match(char *str,char *mask, BOOL case_sig) return False; if (case_sig) return strcmp(str,mask)==0; - return strcasecmp(str,mask) == 0; + return StrCaseCmp(str,mask) == 0; } /**************************************************************************** @@ -549,12 +551,12 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, pstrcat(pathreal,dname); if (INFO_LEVEL_IS_UNIX(info_level)) { - if (vfs_lstat(conn,pathreal,&sbuf) != 0) { + if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) { DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n", pathreal,strerror(errno))); continue; } - } else if (vfs_stat(conn,pathreal,&sbuf) != 0) { + } else if (SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) { /* Needed to show the msdfs symlinks as * directories */ @@ -647,8 +649,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, SIVAL(p,l2_cbList,0); /* No extended attributes */ p += l2_achName; nameptr = p; - p += align_string(outbuf, p, 0); - len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE); + len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN); if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) SCVAL(nameptr, -1, len-2); else @@ -680,14 +681,14 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, pstrcpy(mangled_name, fname); mangle_map(mangled_name,True,True,SNUM(conn)); mangled_name[12] = 0; - len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER); + len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE); SSVAL(p, 0, len); } else { SSVAL(p,0,0); *(p+2) = 0; } p += 2 + 24; - len = srvstr_push(outbuf, p, fname, -1, 0); + len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII); SIVAL(q,0,len); p += len; len = PTR_DIFF(p, pdata); @@ -708,7 +709,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, p += 16; SIVAL(p,0,nt_extmode); p += 4; p += 4; - len = srvstr_push(outbuf, p, fname, -1, 0); + len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII); SIVAL(p, -4, len); p += len; len = PTR_DIFF(p, pdata); @@ -727,13 +728,13 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, SOFF_T(p,0,file_size); SOFF_T(p,8,allocation_size); p += 16; - SIVAL(p,0,nt_extmode); p += 4; + SIVAL(p,0,nt_extmode); p += 4; - SIVAL(p,0,0); p += 4; - len = srvstr_push(outbuf, p, fname, -1, 0); - SIVAL(p, -4, len); - p += len; + SIVAL(p,4,0); /* ea size */ + len = srvstr_push(outbuf, p+8, fname, -1, STR_TERMINATE_ASCII); + SIVAL(p, 0, len); + p += 8 + len; len = PTR_DIFF(p, pdata); len = (len + 3) & ~3; @@ -747,7 +748,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, p += 4; /* this must *not* be null terminated or w2k gets in a loop trying to set an acl on a dir (tridge) */ - len = srvstr_push(outbuf, p, fname, -1, 0); + len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII); SIVAL(p, -4, len); p += len; len = PTR_DIFF(p, pdata); @@ -1318,10 +1319,11 @@ static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf char *vname = volume_label(SNUM(conn)); int snum = SNUM(conn); char *fstype = lp_fstype(SNUM(conn)); + int quota_flag = 0; DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level)); - if(vfs_stat(conn,".",&st)!=0) { + if(SMB_VFS_STAT(conn,".",&st)!=0) { DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno))); return ERROR_DOS(ERRSRV,ERRinvdevice); } @@ -1338,7 +1340,7 @@ static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf { SMB_BIG_UINT dfree,dsize,bsize; data_len = 18; - conn->vfs_ops.disk_free(conn,".",False,&bsize,&dfree,&dsize); + SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize); SIVAL(pdata,l1_idFileSystem,st.st_dev); SIVAL(pdata,l1_cSectorUnit,bsize/512); SIVAL(pdata,l1_cUnit,dsize); @@ -1357,7 +1359,7 @@ static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf * the called hostname and the service name. */ SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16) ); - len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_TERMINATE); + len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, 0); SCVAL(pdata,l2_vol_cch,len); data_len = l2_vol_szVolLabel + len; DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n", @@ -1367,19 +1369,26 @@ static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf case SMB_QUERY_FS_ATTRIBUTE_INFO: case SMB_FS_ATTRIBUTE_INFORMATION: + +#if defined(HAVE_SYS_QUOTAS) + quota_flag = FILE_VOLUME_QUOTAS; +#endif + SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH| - (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)); /* FS ATTRIBUTES */ + (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)| + quota_flag); /* FS ATTRIBUTES */ + SIVAL(pdata,4,255); /* Max filename component length */ /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it and will think we can't do long filenames */ - len = srvstr_push(outbuf, pdata+12, fstype, -1, 0); + len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE); SIVAL(pdata,8,len); data_len = 12 + len; break; case SMB_QUERY_FS_LABEL_INFO: case SMB_FS_LABEL_INFORMATION: - len = srvstr_push(outbuf, pdata+4, vname, -1, STR_TERMINATE); + len = srvstr_push(outbuf, pdata+4, vname, -1, 0); data_len = 4 + len; SIVAL(pdata,0,len); break; @@ -1394,7 +1403,7 @@ static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16)); - len = srvstr_push(outbuf, pdata+18, vname, -1, STR_TERMINATE); + len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE); SIVAL(pdata,12,len); data_len = 18+len; DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n", @@ -1406,7 +1415,7 @@ static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf { SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector; data_len = 24; - conn->vfs_ops.disk_free(conn,".",False,&bsize,&dfree,&dsize); + SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize); block_size = lp_block_size(snum); if (bsize < block_size) { SMB_BIG_UINT factor = block_size/bsize; @@ -1436,7 +1445,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned { SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector; data_len = 32; - conn->vfs_ops.disk_free(conn,".",False,&bsize,&dfree,&dsize); + SMB_VFS_DISK_FREE(conn,".",False,&bsize,&dfree,&dsize); block_size = lp_block_size(snum); if (bsize < block_size) { SMB_BIG_UINT factor = block_size/bsize; @@ -1470,6 +1479,78 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned SIVAL(pdata,4,0); /* characteristics */ break; +#ifdef HAVE_SYS_QUOTAS + case SMB_FS_QUOTA_INFORMATION: + /* + * what we have to send --metze: + * + * Unknown1: 24 NULL bytes + * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so + * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so + * Quota Flags: 2 byte : + * Unknown3: 6 NULL bytes + * + * 48 bytes total + * + * details for Quota Flags: + * + * 0x0020 Log Limit: log if the user exceeds his Hard Quota + * 0x0010 Log Warn: log if the user exceeds his Soft Quota + * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota + * 0x0001 Enable Quotas: enable quota for this fs + * + */ + { + /* we need to fake up a fsp here, + * because its not send in this call + */ + files_struct fsp; + SMB_NTQUOTA_STRUCT quotas; + + ZERO_STRUCT(fsp); + ZERO_STRUCT(quotas); + + fsp.conn = conn; + fsp.fnum = -1; + fsp.fd = -1; + + /* access check */ + if (conn->admin_user != True) { + DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n", + lp_servicename(SNUM(conn)),conn->user)); + return ERROR_DOS(ERRDOS,ERRnoaccess); + } + + if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) { + DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn)))); + return ERROR_DOS(ERRSRV,ERRerror); + } + + data_len = 48; + + DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn)))); + + /* Unknown1 24 NULL bytes*/ + SBIG_UINT(pdata,0,(SMB_BIG_UINT)0); + SBIG_UINT(pdata,8,(SMB_BIG_UINT)0); + SBIG_UINT(pdata,16,(SMB_BIG_UINT)0); + + /* Default Soft Quota 8 bytes */ + SBIG_UINT(pdata,24,quotas.softlim); + + /* Default Hard Quota 8 bytes */ + SBIG_UINT(pdata,32,quotas.hardlim); + + /* Quota flag 2 bytes */ + SSVAL(pdata,40,quotas.qflags); + + /* Unknown3 6 NULL bytes */ + SSVAL(pdata,42,0); + SIVAL(pdata,44,0); + + break; + } +#endif /* HAVE_SYS_QUOTAS */ case SMB_FS_OBJECTID_INFORMATION: data_len = 64; break; @@ -1511,6 +1592,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned return -1; } +#ifdef HAVE_SYS_QUOTAS /**************************************************************************** Reply to a TRANS2_SETFSINFO (set filesystem info). ****************************************************************************/ @@ -1519,18 +1601,110 @@ static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, char **pparams, int total_params, char **ppdata, int total_data) { - /* Just say yes we did it - there is nothing that - can be set here so it doesn't matter. */ + char *pdata = *ppdata; + char *params = *pparams; + files_struct *fsp = NULL; + uint16 info_level; int outsize; - DEBUG(3,("call_trans2setfsinfo\n")); + SMB_NTQUOTA_STRUCT quotas; + + ZERO_STRUCT(quotas); - if (!CAN_WRITE(conn)) + DEBUG(10,("call_trans2setfsinfo: SET_FS_QUOTA: for service [%s]\n",lp_servicename(SNUM(conn)))); + + /* access check */ + if ((conn->admin_user != True)||!CAN_WRITE(conn)) { + DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n", + lp_servicename(SNUM(conn)),conn->user)); return ERROR_DOS(ERRSRV,ERRaccess); + } + + /* */ + if (total_params < 4) { + DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n", + total_params)); + return ERROR_DOS(ERRDOS,ERRinvalidparam); + } + + fsp = file_fsp(params,0); + + if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) { + DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n")); + return ERROR_NT(NT_STATUS_INVALID_HANDLE); + } + info_level = SVAL(params,2); + + switch(info_level) { + case SMB_FS_QUOTA_INFORMATION: + /* note: normaly there're 48 bytes, + * but we didn't use the last 6 bytes for now + * --metze + */ + if (total_data < 42) { + DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n", + total_data)); + return ERROR_DOS(ERRDOS,ERRunknownlevel); + } + + /* unknown_1 24 NULL bytes in pdata*/ + + /* the soft quotas 8 bytes (SMB_BIG_UINT)*/ + quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24); +#ifdef LARGE_SMB_OFF_T + quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32); +#else /* LARGE_SMB_OFF_T */ + if ((IVAL(pdata,28) != 0)&& + ((quotas.softlim != 0xFFFFFFFF)|| + (IVAL(pdata,28)!=0xFFFFFFFF))) { + /* more than 32 bits? */ + return ERROR_DOS(ERRDOS,ERRunknownlevel); + } +#endif /* LARGE_SMB_OFF_T */ + + /* the hard quotas 8 bytes (SMB_BIG_UINT)*/ + quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32); +#ifdef LARGE_SMB_OFF_T + quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32); +#else /* LARGE_SMB_OFF_T */ + if ((IVAL(pdata,36) != 0)&& + ((quotas.hardlim != 0xFFFFFFFF)|| + (IVAL(pdata,36)!=0xFFFFFFFF))) { + /* more than 32 bits? */ + return ERROR_DOS(ERRDOS,ERRunknownlevel); + } +#endif /* LARGE_SMB_OFF_T */ + + /* quota_flags 2 bytes **/ + quotas.qflags = SVAL(pdata,40); + + /* unknown_2 6 NULL bytes follow*/ + + /* now set the quotas */ + if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) { + DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn)))); + return ERROR_DOS(ERRSRV,ERRerror); + } + + break; + default: + DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n", + info_level)); + return ERROR_DOS(ERRDOS,ERRunknownlevel); + break; + } + + /* + * sending this reply works fine, + * but I'm not sure it's the same + * like windows do... + * --metze + */ outsize = set_message(outbuf,10,0,True); return outsize; } +#endif /* HAVE_SYS_QUOTAS */ /**************************************************************************** * Utility function to set bad path error. @@ -1589,7 +1763,20 @@ static int call_trans2qfilepathinfo(connection_struct *conn, DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level)); - if(fsp && (fsp->is_directory || fsp->fd == -1)) { + if(fsp && (fsp->fake_file_handle)) { + /* + * This is actually for the QUOTA_FAKE_FILE --metze + */ + + pstrcpy(fname, fsp->fsp_name); + unix_convert(fname,conn,0,&bad_path,&sbuf); + if (!check_name(fname,conn)) { + DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed for fake_file(%s)\n",fname,strerror(errno))); + set_bad_path_error(errno, bad_path); + return(UNIXERROR(ERRDOS,ERRbadpath)); + } + + } else if(fsp && (fsp->is_directory || fsp->fd == -1)) { /* * This is actually a QFILEINFO on a directory * handle (returned from an NT SMB). NT5.0 seems @@ -1605,13 +1792,13 @@ static int call_trans2qfilepathinfo(connection_struct *conn, if (INFO_LEVEL_IS_UNIX(info_level)) { /* Always do lstat for UNIX calls. */ - if (vfs_lstat(conn,fname,&sbuf)) { - DEBUG(3,("call_trans2qfilepathinfo: vfs_lstat of %s failed (%s)\n",fname,strerror(errno))); + if (SMB_VFS_LSTAT(conn,fname,&sbuf)) { + DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno))); set_bad_path_error(errno, bad_path); return(UNIXERROR(ERRDOS,ERRbadpath)); } - } else if (!VALID_STAT(sbuf) && vfs_stat(conn,fname,&sbuf)) { - DEBUG(3,("call_trans2qfilepathinfo: vfs_stat of %s failed (%s)\n",fname,strerror(errno))); + } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) { + DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno))); set_bad_path_error(errno, bad_path); return(UNIXERROR(ERRDOS,ERRbadpath)); } @@ -1624,11 +1811,11 @@ static int call_trans2qfilepathinfo(connection_struct *conn, CHECK_FSP(fsp,conn); pstrcpy(fname, fsp->fsp_name); - if (vfs_fstat(fsp,fsp->fd,&sbuf) != 0) { + if (SMB_VFS_FSTAT(fsp,fsp->fd,&sbuf) != 0) { DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno))); return(UNIXERROR(ERRDOS,ERRbadfid)); } - if((pos = fsp->conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_CUR)) == -1) + if((pos = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_CUR)) == -1) return(UNIXERROR(ERRDOS,ERRnoaccess)); delete_pending = fsp->delete_on_close; @@ -1655,13 +1842,13 @@ static int call_trans2qfilepathinfo(connection_struct *conn, if (INFO_LEVEL_IS_UNIX(info_level)) { /* Always do lstat for UNIX calls. */ - if (vfs_lstat(conn,fname,&sbuf)) { - DEBUG(3,("call_trans2qfilepathinfo: vfs_lstat of %s failed (%s)\n",fname,strerror(errno))); + if (SMB_VFS_LSTAT(conn,fname,&sbuf)) { + DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno))); set_bad_path_error(errno, bad_path); return(UNIXERROR(ERRDOS,ERRbadpath)); } - } else if (!VALID_STAT(sbuf) && vfs_stat(conn,fname,&sbuf)) { - DEBUG(3,("call_trans2qfilepathinfo: vfs_stat of %s failed (%s)\n",fname,strerror(errno))); + } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) { + DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno))); set_bad_path_error(errno, bad_path); return(UNIXERROR(ERRDOS,ERRbadpath)); } @@ -1733,9 +1920,17 @@ static int call_trans2qfilepathinfo(connection_struct *conn, SIVAL(pdata,l1_cbFile,(uint32)file_size); SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size); SSVAL(pdata,l1_attrFile,mode); - SIVAL(pdata,l1_attrFile+2,4); /* this is what OS2 does */ + SIVAL(pdata,l1_attrFile+2,0); /* this is what win2003 does */ break; + case SMB_INFO_IS_NAME_VALID: + if (tran_call == TRANSACT2_QFILEINFO) { + /* os/2 needs this ? really ?*/ + return ERROR_DOS(ERRDOS,ERRbadfunc); + } + data_size = 0; + break; + case SMB_INFO_QUERY_EAS_FROM_LIST: data_size = 24; put_dos_date2(pdata,0,c_time); @@ -1748,12 +1943,9 @@ static int call_trans2qfilepathinfo(connection_struct *conn, case SMB_INFO_QUERY_ALL_EAS: data_size = 4; - SIVAL(pdata,0,data_size); + SIVAL(pdata,0,0); /* ea size */ break; - case 6: - return ERROR_DOS(ERRDOS,ERRbadfunc); /* os/2 needs this */ - case SMB_FILE_BASIC_INFORMATION: case SMB_QUERY_FILE_BASIC_INFO: @@ -1836,6 +2028,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, break; case SMB_QUERY_FILE_ALL_INFO: + case SMB_FILE_ALL_INFORMATION: put_long_date(pdata,c_time); put_long_date(pdata+8,sbuf.st_atime); put_long_date(pdata+16,sbuf.st_mtime); /* write time */ @@ -1848,20 +2041,8 @@ static int call_trans2qfilepathinfo(connection_struct *conn, SCVAL(pdata,20,delete_pending); SCVAL(pdata,21,(mode&aDIR)?1:0); pdata += 24; - SINO_T(pdata,0,(SMB_INO_T)sbuf.st_ino); - pdata += 8; /* index number */ pdata += 4; /* EA info */ - if (mode & aRONLY) - SIVAL(pdata,0,0xA9); - else - SIVAL(pdata,0,0xd01BF); - pdata += 4; - SOFF_T(pdata,0,pos); /* current offset */ - pdata += 8; - SIVAL(pdata,0,mode); /* is this the right sort of mode info? */ - pdata += 4; - pdata += 4; /* alignment */ - len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_TERMINATE); + len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE); SIVAL(pdata,0,len); pdata += 4 + len; data_size = PTR_DIFF(pdata,(*ppdata)); @@ -1914,28 +2095,6 @@ static int call_trans2qfilepathinfo(connection_struct *conn, data_size = 4; break; -#if 0 - /* Not yet finished... JRA */ - case 1018: - { - put_long_date(pdata,c_time); - put_long_date(pdata+8,sbuf.st_atime); - put_long_date(pdata+16,sbuf.st_mtime); /* write time */ - put_long_date(pdata+24,sbuf.st_mtime); /* change time */ - SIVAL(pdata,32,mode); - SIVAL(pdata,36,0); /* ??? */ - SIVAL(pdata,40,0x20); /* ??? */ - SIVAL(pdata,44,0); /* ??? */ - SOFF_T(pdata,48,size); - SIVAL(pdata,56,0x1); /* ??? */ - SIVAL(pdata,60,0); /* ??? */ - SIVAL(pdata,64,0); /* ??? */ - SIVAL(pdata,68,length); /* Following string length in bytes. */ - dos_PutUniCode(pdata+72,,False); - break; - } -#endif - #if 0 /* * NT4 server just returns "invalid query" to this - if we try to answer @@ -1958,8 +2117,9 @@ static int call_trans2qfilepathinfo(connection_struct *conn, } break; + case SMB_QUERY_COMPRESSION_INFO: case SMB_FILE_COMPRESSION_INFORMATION: - SOFF_T(pdata,0,allocation_size); + SOFF_T(pdata,0,file_size); SIVAL(pdata,8,0); /* ??? */ SIVAL(pdata,12,0); /* ??? */ data_size = 16; @@ -2054,7 +2214,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, #else return(UNIXERROR(ERRDOS,ERRbadlink)); #endif - len = conn->vfs_ops.readlink(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */ + len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1); /* read link */ if (len == -1) return(UNIXERROR(ERRDOS,ERRnoaccess)); buffer[len] = 0; @@ -2178,7 +2338,7 @@ static int ensure_link_is_safe(connection_struct *conn, const char *link_dest_in pstrcpy(link_dest, "./"); } - if (conn->vfs_ops.realpath(conn,link_dest,resolved_name) == NULL) + if (SMB_VFS_REALPATH(conn,link_dest,resolved_name) == NULL) return -1; pstrcpy(link_dest, resolved_name); @@ -2229,7 +2389,13 @@ static int call_trans2setfilepathinfo(connection_struct *conn, gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE; mode_t unixmode = 0; + if (!params) + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + if (tran_call == TRANSACT2_SETFILEINFO) { + if (total_params < 4) + return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + fsp = file_fsp(params,0); info_level = SVAL(params,2); @@ -2269,7 +2435,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, pstrcpy(fname, fsp->fsp_name); fd = fsp->fd; - if (vfs_fstat(fsp,fd,&sbuf) != 0) { + if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) { DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno))); return(UNIXERROR(ERRDOS,ERRbadfid)); } @@ -2461,7 +2627,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, if (new_fsp == NULL) return(UNIXERROR(ERRDOS,ERRbadpath)); ret = vfs_allocate_file_space(new_fsp, allocation_size); - if (vfs_fstat(new_fsp,new_fsp->fd,&new_sbuf) != 0) { + if (SMB_VFS_FSTAT(new_fsp,new_fsp->fd,&new_sbuf) != 0) { DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n", new_fsp->fnum, strerror(errno))); ret = -1; @@ -2469,7 +2635,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, close_file(new_fsp,True); } else { ret = vfs_allocate_file_space(fsp, allocation_size); - if (vfs_fstat(fsp,fd,&new_sbuf) != 0) { + if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) { DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno))); ret = -1; @@ -2609,7 +2775,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", 0%o for file %s\n", (double)dev, unixmode, fname )); /* Ok - do the mknod. */ - if (conn->vfs_ops.mknod(conn,dos_to_unix_static(fname), unixmode, dev) != 0) + if (SMB_VFS_MKNOD(conn,dos_to_unix_static(fname), unixmode, dev) != 0) return(UNIXERROR(ERRDOS,ERRnoaccess)); inherit_access_acl(conn, fname, unixmode); @@ -2628,7 +2794,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", if (raw_unixmode != SMB_MODE_NO_CHANGE) { DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n", (unsigned int)unixmode, fname )); - if (vfs_chmod(conn,fname,unixmode) != 0) + if (SMB_VFS_CHMOD(conn,fname,unixmode) != 0) return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -2639,7 +2805,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) { DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n", (unsigned int)set_owner, fname )); - if (vfs_chown(conn,fname,set_owner, (gid_t)-1) != 0) + if (SMB_VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0) return(UNIXERROR(ERRDOS,ERRnoaccess)); } @@ -2650,7 +2816,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) { DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n", (unsigned int)set_owner, fname )); - if (vfs_chown(conn,fname,(uid_t)-1, set_grp) != 0) + if (SMB_VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0) return(UNIXERROR(ERRDOS,ERRnoaccess)); } break; @@ -2677,7 +2843,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n", fname, link_dest )); - if (conn->vfs_ops.symlink(conn,link_dest,fname) != 0) + if (SMB_VFS_SYMLINK(conn,link_dest,fname) != 0) return(UNIXERROR(ERRDOS,ERRnoaccess)); SSVAL(params,0,0); send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); @@ -2702,7 +2868,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n", fname, link_dest )); - if (conn->vfs_ops.link(conn,link_dest,fname) != 0) + if (SMB_VFS_LINK(conn,link_dest,fname) != 0) return(UNIXERROR(ERRDOS,ERRnoaccess)); SSVAL(params,0,0); send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); @@ -2854,7 +3020,7 @@ static int call_trans2mkdir(connection_struct *conn, unix_convert(directory,conn,0,&bad_path,&sbuf); if (check_name(directory,conn)) - ret = vfs_mkdir(conn,directory,unix_mode(conn,aDIR,directory)); + ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory)); if(ret < 0) { DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno))); @@ -3298,13 +3464,14 @@ int reply_trans2(connection_struct *conn, END_PROFILE_NESTED(Trans2_qfsinfo); break; +#ifdef HAVE_SYS_QUOTAS case TRANSACT2_SETFSINFO: START_PROFILE_NESTED(Trans2_setfsinfo); outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize, ¶ms, total_params, &data, total_data); END_PROFILE_NESTED(Trans2_setfsinfo); break; - +#endif case TRANSACT2_QPATHINFO: case TRANSACT2_QFILEINFO: START_PROFILE_NESTED(Trans2_qpathinfo); diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index c68d00025c..8d3e7cd9be 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -529,3 +529,375 @@ BOOL lookup_sid(DOM_SID *sid, fstring dom_name, fstring name, enum SID_NAME_USE } return True; } + + +/***************************************************************** + Id mapping cache. This is to avoid Winbind mappings already + seen by smbd to be queried too frequently, keeping winbindd + busy, and blocking smbd while winbindd is busy with other + stuff. Written by Michael Steffens , + modified to use linked lists by jra. +*****************************************************************/ + +#define MAX_UID_SID_CACHE_SIZE 100 +#define TURNOVER_UID_SID_CACHE_SIZE 10 +#define MAX_GID_SID_CACHE_SIZE 100 +#define TURNOVER_GID_SID_CACHE_SIZE 10 + +static size_t n_uid_sid_cache = 0; +static size_t n_gid_sid_cache = 0; + +static struct uid_sid_cache { + struct uid_sid_cache *next, *prev; + uid_t uid; + DOM_SID sid; + enum SID_NAME_USE sidtype; +} *uid_sid_cache_head; + +static struct gid_sid_cache { + struct gid_sid_cache *next, *prev; + gid_t gid; + DOM_SID sid; + enum SID_NAME_USE sidtype; +} *gid_sid_cache_head; + +/***************************************************************** + Find a SID given a uid. +*****************************************************************/ + +static BOOL fetch_sid_from_uid_cache(DOM_SID *psid, uid_t uid) +{ + struct uid_sid_cache *pc; + + for (pc = uid_sid_cache_head; pc; pc = pc->next) { + if (pc->uid == uid) { + fstring sid; + *psid = pc->sid; + DEBUG(3,("fetch sid from uid cache %u -> %s\n", + (unsigned int)uid, sid_to_string(sid, psid))); + DLIST_PROMOTE(uid_sid_cache_head, pc); + return True; + } + } + return False; +} + +/***************************************************************** + Find a uid given a SID. +*****************************************************************/ + +static BOOL fetch_uid_from_cache( uid_t *puid, const DOM_SID *psid ) +{ + struct uid_sid_cache *pc; + + for (pc = uid_sid_cache_head; pc; pc = pc->next) { + if (sid_compare(&pc->sid, psid) == 0) { + fstring sid; + *puid = pc->uid; + DEBUG(3,("fetch uid from cache %u -> %s\n", + (unsigned int)*puid, sid_to_string(sid, psid))); + DLIST_PROMOTE(uid_sid_cache_head, pc); + return True; + } + } + return False; +} + +/***************************************************************** + Store uid to SID mapping in cache. +*****************************************************************/ + +static void store_uid_sid_cache(const DOM_SID *psid, uid_t uid) +{ + struct uid_sid_cache *pc; + + if (n_uid_sid_cache >= MAX_UID_SID_CACHE_SIZE && n_uid_sid_cache > TURNOVER_UID_SID_CACHE_SIZE) { + /* Delete the last TURNOVER_UID_SID_CACHE_SIZE entries. */ + struct uid_sid_cache *pc_next; + size_t i; + + for (i = 0, pc = uid_sid_cache_head; i < (n_uid_sid_cache - TURNOVER_UID_SID_CACHE_SIZE); i++, pc = pc->next) + ; + for(; pc; pc = pc_next) { + pc_next = pc->next; + DLIST_REMOVE(uid_sid_cache_head,pc); + SAFE_FREE(pc); + n_uid_sid_cache--; + } + } + + pc = (struct uid_sid_cache *)malloc(sizeof(struct uid_sid_cache)); + if (!pc) + return; + pc->uid = uid; + sid_copy(&pc->sid, psid); + DLIST_ADD(uid_sid_cache_head, pc); + n_uid_sid_cache++; +} + +/***************************************************************** + Find a SID given a gid. +*****************************************************************/ + +static BOOL fetch_sid_from_gid_cache(DOM_SID *psid, gid_t gid) +{ + struct gid_sid_cache *pc; + + for (pc = gid_sid_cache_head; pc; pc = pc->next) { + if (pc->gid == gid) { + fstring sid; + *psid = pc->sid; + DEBUG(3,("fetch sid from gid cache %u -> %s\n", + (unsigned int)gid, sid_to_string(sid, psid))); + DLIST_PROMOTE(gid_sid_cache_head, pc); + return True; + } + } + return False; +} + +/***************************************************************** + Find a gid given a SID. +*****************************************************************/ + +static BOOL fetch_gid_from_cache(gid_t *pgid, const DOM_SID *psid) +{ + struct gid_sid_cache *pc; + + for (pc = gid_sid_cache_head; pc; pc = pc->next) { + if (sid_compare(&pc->sid, psid) == 0) { + fstring sid; + *pgid = pc->gid; + DEBUG(3,("fetch uid from cache %u -> %s\n", + (unsigned int)*pgid, sid_to_string(sid, psid))); + DLIST_PROMOTE(gid_sid_cache_head, pc); + return True; + } + } + return False; +} + +/***************************************************************** + Store gid to SID mapping in cache. +*****************************************************************/ + +static void store_gid_sid_cache(const DOM_SID *psid, gid_t gid) +{ + struct gid_sid_cache *pc; + + if (n_gid_sid_cache >= MAX_GID_SID_CACHE_SIZE && n_gid_sid_cache > TURNOVER_GID_SID_CACHE_SIZE) { + /* Delete the last TURNOVER_GID_SID_CACHE_SIZE entries. */ + struct gid_sid_cache *pc_next; + size_t i; + + for (i = 0, pc = gid_sid_cache_head; i < (n_gid_sid_cache - TURNOVER_GID_SID_CACHE_SIZE); i++, pc = pc->next) + ; + for(; pc; pc = pc_next) { + pc_next = pc->next; + DLIST_REMOVE(gid_sid_cache_head,pc); + SAFE_FREE(pc); + n_gid_sid_cache--; + } + } + + pc = (struct gid_sid_cache *)malloc(sizeof(struct gid_sid_cache)); + if (!pc) + return; + pc->gid = gid; + sid_copy(&pc->sid, psid); + DLIST_ADD(gid_sid_cache_head, pc); + n_gid_sid_cache++; +} + +/***************************************************************** + *THE CANONICAL* convert uid_t to SID function. +*****************************************************************/ + +NTSTATUS uid_to_sid(DOM_SID *psid, uid_t uid) +{ + uid_t low, high; + fstring sid; + + ZERO_STRUCTP(psid); + + if (fetch_sid_from_uid_cache(psid, uid)) + return ( psid ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL ); + + if (lp_idmap_uid(&low, &high) && uid >= low && uid <= high) { + if (winbind_uid_to_sid(psid, uid)) { + + DEBUG(10,("uid_to_sid: winbindd %u -> %s\n", + (unsigned int)uid, sid_to_string(sid, psid))); + + if (psid) + store_uid_sid_cache(psid, uid); + return ( psid ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL ); + } + } + + if (!local_uid_to_sid(psid, uid)) { + DEBUG(10,("uid_to_sid: local %u failed to map to sid\n", (unsigned int)uid )); + return NT_STATUS_UNSUCCESSFUL; + } + + DEBUG(10,("uid_to_sid: local %u -> %s\n", (unsigned int)uid, sid_to_string(sid, psid))); + + store_uid_sid_cache(psid, uid); + return NT_STATUS_OK; +} + +/***************************************************************** + *THE CANONICAL* convert gid_t to SID function. +*****************************************************************/ + +NTSTATUS gid_to_sid(DOM_SID *psid, gid_t gid) +{ + gid_t low, high; + fstring sid; + + ZERO_STRUCTP(psid); + + if (fetch_sid_from_gid_cache(psid, gid)) + return ( psid ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL ); + + if (lp_idmap_gid(&low, &high) && gid >= low && gid <= high) { + if (winbind_gid_to_sid(psid, gid)) { + + DEBUG(10,("gid_to_sid: winbindd %u -> %s\n", + (unsigned int)gid, sid_to_string(sid, psid))); + + if (psid) + store_gid_sid_cache(psid, gid); + return ( psid ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL ); + } + } + + if (!local_gid_to_sid(psid, gid)) { + DEBUG(10,("gid_to_sid: local %u failed to map to sid\n", (unsigned int)gid )); + return NT_STATUS_UNSUCCESSFUL; + } + + DEBUG(10,("gid_to_sid: local %u -> %s\n", (unsigned int)gid, sid_to_string(sid, psid))); + + store_gid_sid_cache(psid, gid); + return NT_STATUS_OK; +} + +/***************************************************************** + *THE CANONICAL* convert SID to uid function. +*****************************************************************/ + +NTSTATUS sid_to_uid(const DOM_SID *psid, uid_t *puid) +{ + fstring dom_name, name, sid_str; + enum SID_NAME_USE name_type; + + if (fetch_uid_from_cache(puid, psid)) + return NT_STATUS_OK; + + /* if this is our SID then go straight to a local lookup */ + + if ( sid_compare_domain(get_global_sam_sid(), psid) == 0 ) { + DEBUG(10,("sid_to_uid: my domain (%s) - trying local.\n", + sid_string_static(psid) )); + + if ( local_sid_to_uid(puid, psid, &name_type) ) + goto success; + + DEBUG(10,("sid_to_uid: local lookup failed\n")); + + return NT_STATUS_UNSUCCESSFUL; + } + + /* If it is not our local domain, only hope is winbindd */ + + if ( !winbind_lookup_sid(psid, dom_name, name, &name_type) ) { + DEBUG(10,("sid_to_uid: winbind lookup for non-local sid %s failed\n", + sid_string_static(psid) )); + + return NT_STATUS_UNSUCCESSFUL; + } + + /* If winbindd does know the SID, ensure this is a user */ + + if (name_type != SID_NAME_USER) { + DEBUG(10,("sid_to_uid: winbind lookup succeeded but SID is not a user (%u)\n", + (unsigned int)name_type )); + return NT_STATUS_INVALID_PARAMETER; + } + + /* get the uid. Has to work or else we are dead in the water */ + + if ( !winbind_sid_to_uid(puid, psid) ) { + DEBUG(10,("sid_to_uid: winbind failed to allocate a new uid for sid %s\n", + sid_to_string(sid_str, psid) )); + return NT_STATUS_UNSUCCESSFUL; + } + +success: + DEBUG(10,("sid_to_uid: %s -> %u\n", sid_to_string(sid_str, psid), + (unsigned int)*puid )); + + store_uid_sid_cache(psid, *puid); + + return NT_STATUS_OK; +} +/***************************************************************** + *THE CANONICAL* convert SID to gid function. + Group mapping is used for gids that maps to Wellknown SIDs +*****************************************************************/ + +NTSTATUS sid_to_gid(const DOM_SID *psid, gid_t *pgid) +{ + fstring dom_name, name, sid_str; + enum SID_NAME_USE name_type; + + if (fetch_gid_from_cache(pgid, psid)) + return NT_STATUS_OK; + + /* + * First we must look up the name and decide if this is a group sid. + * Group mapping can deal with foreign SIDs + */ + + if (!winbind_lookup_sid(psid, dom_name, name, &name_type)) { + DEBUG(10,("sid_to_gid: winbind lookup for sid %s failed - trying local.\n", + sid_to_string(sid_str, psid) )); + + if ( local_sid_to_gid(pgid, psid, &name_type) ) + goto success; + + DEBUG(10,("sid_to_gid: no one knows this SID\n")); + + return NT_STATUS_UNSUCCESSFUL; + } + + /* winbindd knows it; Ensure this is a group sid */ + + if ((name_type != SID_NAME_DOM_GRP) && (name_type != SID_NAME_ALIAS) && (name_type != SID_NAME_WKN_GRP)) { + DEBUG(10,("sid_to_gid: winbind lookup succeeded but SID is not a known group (%u)\n", + (unsigned int)name_type )); + + /* winbindd is running and knows about this SID. Just the wrong type. + Don't fallback to a local lookup here */ + + return NT_STATUS_INVALID_PARAMETER; + } + + /* winbindd knows it and it is a type of group; sid_to_gid must succeed + or we are dead in the water */ + + if ( !winbind_sid_to_gid(pgid, psid) ) { + DEBUG(10,("sid_to_uid: winbind failed to allocate a new gid for sid %s\n", + sid_to_string(sid_str, psid) )); + return NT_STATUS_UNSUCCESSFUL; + } + +success: + DEBUG(10,("sid_to_gid: %s -> %u\n", sid_to_string(sid_str, psid), + (unsigned int)*pgid )); + + store_gid_sid_cache(psid, *pgid); + + return NT_STATUS_OK; +} diff --git a/source3/smbd/utmp.c b/source3/smbd/utmp.c index 6c12cfac62..9833a11f2d 100644 --- a/source3/smbd/utmp.c +++ b/source3/smbd/utmp.c @@ -21,8 +21,6 @@ #include "includes.h" -#ifdef WITH_UTMP - /**************************************************************************** Reflect connection status in utmp/wtmp files. T.D.Lee@durham.ac.uk September 1999 @@ -81,11 +79,11 @@ lastlog: Notes: Each connection requires a small number (starting at 0, working up) - to represent the line (unum). This must be unique within and across - all smbd processes. + to represent the line. This must be unique within and across all + smbd processes. It is the 'id_num' from Samba's session.c code. The 4 byte 'ut_id' component is vital to distinguish connections, - of which there could be several hundered or even thousand. + of which there could be several hundred or even thousand. Entries seem to be printable characters, with optional NULL pads. We need to be distinct from other entries in utmp/wtmp. @@ -105,14 +103,28 @@ Notes: Arbitrarily I have chosen to use a distinctive 'SM' for the first two bytes. - The remaining two encode the "unum" (see above). - - For "utmp consolidate" the suggestion was made to encode the pid into - those remaining two bytes (16 bits). But recent UNIX (e.g Solaris 8) - is migrating to pids > 16 bits, so we ought not to do this. + The remaining two bytes encode the session 'id_num' (see above). + Our caller (session.c) should note our 16-bit limitation. ****************************************************************************/ +#ifndef WITH_UTMP +/* + * Not WITH_UTMP? Simply supply dummy routines. + */ + +void sys_utmp_claim(const char *username, const char *hostname, + struct in_addr *ipaddr, + const char *id_str, int id_num) +{} + +void sys_utmp_yield(const char *username, const char *hostname, + struct in_addr *ipaddr, + const char *id_str, int id_num) +{} + +#else /* WITH_UTMP */ + #include #ifdef HAVE_UTMPX_H @@ -125,33 +137,6 @@ Notes: #include #endif -/**************************************************************************** - Obtain/release a small number (0 upwards) unique within and across smbds. -****************************************************************************/ -/* - * Need a "small" number to represent this connection, unique within this - * smbd and across all smbds. - * - * claim: - * Start at 0, hunt up for free, unique number "unum" by attempting to - * store it as a key in a tdb database: - * key: unum data: pid+conn - * Also store its inverse, ready for yield function: - * key: pid+conn data: unum - * - * yield: - * Find key: pid+conn; data is unum; delete record - * Find key: unum ; delete record. - * - * Comment: - * The claim algorithm (a "for" loop attempting to store numbers in a tdb - * database) will be increasingly inefficient with larger numbers of - * connections. Is it possible to write a suitable primitive within tdb? - * - * However, by also storing the inverse key/data pair, we at least make - * the yield algorithm efficient. - */ - /**************************************************************************** Default paths to various {u,w}tmp{,x} files. ****************************************************************************/ @@ -484,6 +469,7 @@ static int ut_id_encode(int i, char *fourbyte) */ static BOOL sys_utmp_fill(struct utmp *u, const char *username, const char *hostname, + struct in_addr *ipaddr, const char *id_str, int id_num) { struct timeval timeval; @@ -503,10 +489,6 @@ static BOOL sys_utmp_fill(struct utmp *u, /* * ut_line: * If size limit proves troublesome, then perhaps use "ut_id_encode()". - * - * Temporary variable "line_tmp" avoids trouble: - * o with unwanted trailing NULL if ut_line full; - * o with overflow if ut_line would be more than full. */ if (strlen(id_str) > sizeof(u->ut_line)) { DEBUG(1,("id_str [%s] is too long for %d char utmp field\n", @@ -538,8 +520,9 @@ static BOOL sys_utmp_fill(struct utmp *u, #if defined(HAVE_UT_UT_HOST) utmp_strcpy(u->ut_host, hostname, sizeof(u->ut_host)); #endif - #if defined(HAVE_UT_UT_ADDR) + if (ipaddr) + u->ut_addr = ipaddr->s_addr; /* * "(unsigned long) ut_addr" apparently exists on at least HP-UX 10.20. * Volunteer to implement, please ... @@ -561,6 +544,7 @@ static BOOL sys_utmp_fill(struct utmp *u, ****************************************************************************/ void sys_utmp_yield(const char *username, const char *hostname, + struct in_addr *ipaddr, const char *id_str, int id_num) { struct utmp u; @@ -576,7 +560,7 @@ void sys_utmp_yield(const char *username, const char *hostname, u.ut_type = DEAD_PROCESS; #endif - if (!sys_utmp_fill(&u, username, hostname, id_str, id_num)) return; + if (!sys_utmp_fill(&u, username, hostname, ipaddr, id_str, id_num)) return; sys_utmp_update(&u, NULL, False); } @@ -586,6 +570,7 @@ void sys_utmp_yield(const char *username, const char *hostname, ****************************************************************************/ void sys_utmp_claim(const char *username, const char *hostname, + struct in_addr *ipaddr, const char *id_str, int id_num) { struct utmp u; @@ -596,11 +581,9 @@ void sys_utmp_claim(const char *username, const char *hostname, u.ut_type = USER_PROCESS; #endif - if (!sys_utmp_fill(&u, username, hostname, id_str, id_num)) return; + if (!sys_utmp_fill(&u, username, hostname, ipaddr, id_str, id_num)) return; sys_utmp_update(&u, hostname, True); } -#else /* WITH_UTMP */ - void dummy_utmp(void) {} -#endif +#endif /* WITH_UTMP */ diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c index 491fa70e68..8d44a1a0fa 100644 --- a/source3/smbd/vfs-wrap.c +++ b/source3/smbd/vfs-wrap.c @@ -30,18 +30,18 @@ is sure to try and execute them. These stubs are used to prevent this possibility. */ -int vfswrap_dummy_connect(connection_struct *conn, const char *service, const char *user) +int vfswrap_dummy_connect(vfs_handle_struct *handle, connection_struct *conn, const char *service, const char *user) { return 0; /* Return >= 0 for success */ } -void vfswrap_dummy_disconnect(connection_struct *conn) +void vfswrap_dummy_disconnect(vfs_handle_struct *handle, connection_struct *conn) { } /* Disk operations */ -SMB_BIG_UINT vfswrap_disk_free(connection_struct *conn, const char *path, BOOL small_query, SMB_BIG_UINT *bsize, +SMB_BIG_UINT vfswrap_disk_free(vfs_handle_struct *handle, connection_struct *conn, const char *path, BOOL small_query, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) { SMB_BIG_UINT result; @@ -52,7 +52,7 @@ SMB_BIG_UINT vfswrap_disk_free(connection_struct *conn, const char *path, BOOL s /* Directory operations */ -DIR *vfswrap_opendir(connection_struct *conn, const char *fname) +DIR *vfswrap_opendir(vfs_handle_struct *handle, connection_struct *conn, const char *fname) { DIR *result; @@ -62,7 +62,7 @@ DIR *vfswrap_opendir(connection_struct *conn, const char *fname) return result; } -struct dirent *vfswrap_readdir(connection_struct *conn, DIR *dirp) +struct dirent *vfswrap_readdir(vfs_handle_struct *handle, connection_struct *conn, DIR *dirp) { struct dirent *result; @@ -72,7 +72,7 @@ struct dirent *vfswrap_readdir(connection_struct *conn, DIR *dirp) return result; } -int vfswrap_mkdir(connection_struct *conn, const char *path, mode_t mode) +int vfswrap_mkdir(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode) { int result; BOOL has_dacl = False; @@ -93,17 +93,15 @@ int vfswrap_mkdir(connection_struct *conn, const char *path, mode_t mode) * mess up any inherited ACL bits that were set. JRA. */ int saved_errno = errno; /* We may get ENOSYS */ - if (conn->vfs_ops.chmod_acl != NULL) { - if ((conn->vfs_ops.chmod_acl(conn, path, mode) == -1) && (errno == ENOSYS)) - errno = saved_errno; - } + if ((SMB_VFS_CHMOD_ACL(conn, path, mode) == -1) && (errno == ENOSYS)) + errno = saved_errno; } END_PROFILE(syscall_mkdir); return result; } -int vfswrap_rmdir(connection_struct *conn, const char *path) +int vfswrap_rmdir(vfs_handle_struct *handle, connection_struct *conn, const char *path) { int result; @@ -113,7 +111,7 @@ int vfswrap_rmdir(connection_struct *conn, const char *path) return result; } -int vfswrap_closedir(connection_struct *conn, DIR *dirp) +int vfswrap_closedir(vfs_handle_struct *handle, connection_struct *conn, DIR *dirp) { int result; @@ -125,7 +123,7 @@ int vfswrap_closedir(connection_struct *conn, DIR *dirp) /* File operations */ -int vfswrap_open(connection_struct *conn, const char *fname, int flags, mode_t mode) +int vfswrap_open(vfs_handle_struct *handle, connection_struct *conn, const char *fname, int flags, mode_t mode) { int result; @@ -135,7 +133,7 @@ int vfswrap_open(connection_struct *conn, const char *fname, int flags, mode_t m return result; } -int vfswrap_close(files_struct *fsp, int fd) +int vfswrap_close(vfs_handle_struct *handle, files_struct *fsp, int fd) { int result; @@ -146,7 +144,7 @@ int vfswrap_close(files_struct *fsp, int fd) return result; } -ssize_t vfswrap_read(files_struct *fsp, int fd, void *data, size_t n) +ssize_t vfswrap_read(vfs_handle_struct *handle, files_struct *fsp, int fd, void *data, size_t n) { ssize_t result; @@ -156,7 +154,7 @@ ssize_t vfswrap_read(files_struct *fsp, int fd, void *data, size_t n) return result; } -ssize_t vfswrap_write(files_struct *fsp, int fd, const void *data, size_t n) +ssize_t vfswrap_write(vfs_handle_struct *handle, files_struct *fsp, int fd, const void *data, size_t n) { ssize_t result; @@ -166,7 +164,7 @@ ssize_t vfswrap_write(files_struct *fsp, int fd, const void *data, size_t n) return result; } -SMB_OFF_T vfswrap_lseek(files_struct *fsp, int filedes, SMB_OFF_T offset, int whence) +SMB_OFF_T vfswrap_lseek(vfs_handle_struct *handle, files_struct *fsp, int filedes, SMB_OFF_T offset, int whence) { SMB_OFF_T result = 0; @@ -192,7 +190,7 @@ 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, +ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fsp, int fromfd, const DATA_BLOB *hdr, SMB_OFF_T offset, size_t n) { ssize_t result; @@ -203,7 +201,7 @@ ssize_t vfswrap_sendfile(int tofd, struct files_struct *fsp, int fromfd, const D return result; } -int vfswrap_rename(connection_struct *conn, const char *old, const char *new) +int vfswrap_rename(vfs_handle_struct *handle, connection_struct *conn, const char *old, const char *new) { int result; @@ -213,7 +211,7 @@ int vfswrap_rename(connection_struct *conn, const char *old, const char *new) return result; } -int vfswrap_fsync(files_struct *fsp, int fd) +int vfswrap_fsync(vfs_handle_struct *handle, files_struct *fsp, int fd) { #ifdef HAVE_FSYNC int result; @@ -228,7 +226,7 @@ int vfswrap_fsync(files_struct *fsp, int fd) #endif } -int vfswrap_stat(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *sbuf) +int vfswrap_stat(vfs_handle_struct *handle, connection_struct *conn, const char *fname, SMB_STRUCT_STAT *sbuf) { int result; @@ -238,7 +236,7 @@ int vfswrap_stat(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *sb return result; } -int vfswrap_fstat(files_struct *fsp, int fd, SMB_STRUCT_STAT *sbuf) +int vfswrap_fstat(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_STRUCT_STAT *sbuf) { int result; @@ -248,7 +246,7 @@ int vfswrap_fstat(files_struct *fsp, int fd, SMB_STRUCT_STAT *sbuf) return result; } -int vfswrap_lstat(connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbuf) +int vfswrap_lstat(vfs_handle_struct *handle, connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbuf) { int result; @@ -258,7 +256,7 @@ int vfswrap_lstat(connection_struct *conn, const char *path, SMB_STRUCT_STAT *sb return result; } -int vfswrap_unlink(connection_struct *conn, const char *path) +int vfswrap_unlink(vfs_handle_struct *handle, connection_struct *conn, const char *path) { int result; @@ -268,7 +266,7 @@ int vfswrap_unlink(connection_struct *conn, const char *path) return result; } -int vfswrap_chmod(connection_struct *conn, const char *path, mode_t mode) +int vfswrap_chmod(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode) { int result; @@ -281,9 +279,9 @@ int vfswrap_chmod(connection_struct *conn, const char *path, mode_t mode) */ - if (conn->vfs_ops.chmod_acl != NULL) { + { int saved_errno = errno; /* We might get ENOSYS */ - if ((result = conn->vfs_ops.chmod_acl(conn, path, mode)) == 0) { + if ((result = SMB_VFS_CHMOD_ACL(conn, path, mode)) == 0) { END_PROFILE(syscall_chmod); return result; } @@ -296,10 +294,9 @@ int vfswrap_chmod(connection_struct *conn, const char *path, mode_t mode) return result; } -int vfswrap_fchmod(files_struct *fsp, int fd, mode_t mode) +int vfswrap_fchmod(vfs_handle_struct *handle, files_struct *fsp, int fd, mode_t mode) { int result; - struct vfs_ops *vfs_ops = &fsp->conn->vfs_ops; START_PROFILE(syscall_fchmod); @@ -309,9 +306,9 @@ int vfswrap_fchmod(files_struct *fsp, int fd, mode_t mode) * group owner bits directly. JRA. */ - if (vfs_ops->fchmod_acl != NULL) { + { int saved_errno = errno; /* We might get ENOSYS */ - if ((result = vfs_ops->fchmod_acl(fsp, fd, mode)) == 0) { + if ((result = SMB_VFS_FCHMOD_ACL(fsp, fd, mode)) == 0) { END_PROFILE(syscall_chmod); return result; } @@ -330,7 +327,7 @@ int vfswrap_fchmod(files_struct *fsp, int fd, mode_t mode) return result; } -int vfswrap_chown(connection_struct *conn, const char *path, uid_t uid, gid_t gid) +int vfswrap_chown(vfs_handle_struct *handle, connection_struct *conn, const char *path, uid_t uid, gid_t gid) { int result; @@ -340,7 +337,7 @@ int vfswrap_chown(connection_struct *conn, const char *path, uid_t uid, gid_t gi return result; } -int vfswrap_fchown(files_struct *fsp, int fd, uid_t uid, gid_t gid) +int vfswrap_fchown(vfs_handle_struct *handle, files_struct *fsp, int fd, uid_t uid, gid_t gid) { #ifdef HAVE_FCHOWN int result; @@ -356,7 +353,7 @@ int vfswrap_fchown(files_struct *fsp, int fd, uid_t uid, gid_t gid) #endif } -int vfswrap_chdir(connection_struct *conn, const char *path) +int vfswrap_chdir(vfs_handle_struct *handle, connection_struct *conn, const char *path) { int result; @@ -366,7 +363,7 @@ int vfswrap_chdir(connection_struct *conn, const char *path) return result; } -char *vfswrap_getwd(connection_struct *conn, char *path) +char *vfswrap_getwd(vfs_handle_struct *handle, connection_struct *conn, char *path) { char *result; @@ -376,7 +373,7 @@ char *vfswrap_getwd(connection_struct *conn, char *path) return result; } -int vfswrap_utime(connection_struct *conn, const char *path, struct utimbuf *times) +int vfswrap_utime(vfs_handle_struct *handle, connection_struct *conn, const char *path, struct utimbuf *times) { int result; @@ -391,18 +388,17 @@ int vfswrap_utime(connection_struct *conn, const char *path, struct utimbuf *tim allocate is set. **********************************************************************/ -static int strict_allocate_ftruncate(files_struct *fsp, int fd, SMB_OFF_T len) +static int strict_allocate_ftruncate(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_OFF_T len) { - struct vfs_ops *vfs_ops = &fsp->conn->vfs_ops; SMB_STRUCT_STAT st; - SMB_OFF_T currpos = vfs_ops->lseek(fsp, fd, 0, SEEK_CUR); + SMB_OFF_T currpos = SMB_VFS_LSEEK(fsp, fd, 0, SEEK_CUR); unsigned char zero_space[4096]; SMB_OFF_T space_to_write; if (currpos == -1) return -1; - if (vfs_ops->fstat(fsp, fd, &st) == -1) + if (SMB_VFS_FSTAT(fsp, fd, &st) == -1) return -1; space_to_write = len - st.st_size; @@ -420,7 +416,7 @@ static int strict_allocate_ftruncate(files_struct *fsp, int fd, SMB_OFF_T len) return sys_ftruncate(fd, len); /* Write out the real space on disk. */ - if (vfs_ops->lseek(fsp, fd, st.st_size, SEEK_SET) != st.st_size) + if (SMB_VFS_LSEEK(fsp, fd, st.st_size, SEEK_SET) != st.st_size) return -1; space_to_write = len - st.st_size; @@ -430,7 +426,7 @@ static int strict_allocate_ftruncate(files_struct *fsp, int fd, SMB_OFF_T len) SMB_OFF_T retlen; SMB_OFF_T current_len_to_write = MIN(sizeof(zero_space),space_to_write); - retlen = vfs_ops->write(fsp,fsp->fd,(char *)zero_space,current_len_to_write); + retlen = SMB_VFS_WRITE(fsp,fsp->fd,(char *)zero_space,current_len_to_write); if (retlen <= 0) return -1; @@ -438,16 +434,15 @@ static int strict_allocate_ftruncate(files_struct *fsp, int fd, SMB_OFF_T len) } /* Seek to where we were */ - if (vfs_ops->lseek(fsp, fd, currpos, SEEK_SET) != currpos) + if (SMB_VFS_LSEEK(fsp, fd, currpos, SEEK_SET) != currpos) return -1; return 0; } -int vfswrap_ftruncate(files_struct *fsp, int fd, SMB_OFF_T len) +int vfswrap_ftruncate(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_OFF_T len) { int result = -1; - struct vfs_ops *vfs_ops = &fsp->conn->vfs_ops; SMB_STRUCT_STAT st; char c = 0; SMB_OFF_T currpos; @@ -455,7 +450,7 @@ int vfswrap_ftruncate(files_struct *fsp, int fd, SMB_OFF_T len) START_PROFILE(syscall_ftruncate); if (lp_strict_allocate(SNUM(fsp->conn))) { - result = strict_allocate_ftruncate(fsp, fd, len); + result = strict_allocate_ftruncate(handle, fsp, fd, len); END_PROFILE(syscall_ftruncate); return result; } @@ -473,7 +468,7 @@ int vfswrap_ftruncate(files_struct *fsp, int fd, SMB_OFF_T len) /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot extend a file with ftruncate. Provide alternate implementation for this */ - currpos = vfs_ops->lseek(fsp, fd, 0, SEEK_CUR); + currpos = SMB_VFS_LSEEK(fsp, fd, 0, SEEK_CUR); if (currpos == -1) { goto done; } @@ -482,7 +477,7 @@ int vfswrap_ftruncate(files_struct *fsp, int fd, SMB_OFF_T len) size in which case the ftruncate above should have succeeded or shorter, in which case seek to len - 1 and write 1 byte of zero */ - if (vfs_ops->fstat(fsp, fd, &st) == -1) { + if (SMB_VFS_FSTAT(fsp, fd, &st) == -1) { goto done; } @@ -503,14 +498,14 @@ int vfswrap_ftruncate(files_struct *fsp, int fd, SMB_OFF_T len) goto done; } - if (vfs_ops->lseek(fsp, fd, len-1, SEEK_SET) != len -1) + if (SMB_VFS_LSEEK(fsp, fd, len-1, SEEK_SET) != len -1) goto done; - if (vfs_ops->write(fsp, fd, &c, 1)!=1) + if (SMB_VFS_WRITE(fsp, fd, &c, 1)!=1) goto done; /* Seek to where we were */ - if (vfs_ops->lseek(fsp, fd, currpos, SEEK_SET) != currpos) + if (SMB_VFS_LSEEK(fsp, fd, currpos, SEEK_SET) != currpos) goto done; result = 0; @@ -520,7 +515,7 @@ int vfswrap_ftruncate(files_struct *fsp, int fd, SMB_OFF_T len) return result; } -BOOL vfswrap_lock(files_struct *fsp, int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type) +BOOL vfswrap_lock(vfs_handle_struct *handle, files_struct *fsp, int fd, int op, SMB_OFF_T offset, SMB_OFF_T count, int type) { BOOL result; @@ -531,7 +526,7 @@ BOOL vfswrap_lock(files_struct *fsp, int fd, int op, SMB_OFF_T offset, SMB_OFF_T return result; } -int vfswrap_symlink(connection_struct *conn, const char *oldpath, const char *newpath) +int vfswrap_symlink(vfs_handle_struct *handle, connection_struct *conn, const char *oldpath, const char *newpath) { int result; @@ -541,7 +536,7 @@ int vfswrap_symlink(connection_struct *conn, const char *oldpath, const char *ne return result; } -int vfswrap_readlink(connection_struct *conn, const char *path, char *buf, size_t bufsiz) +int vfswrap_readlink(vfs_handle_struct *handle, connection_struct *conn, const char *path, char *buf, size_t bufsiz) { int result; @@ -551,7 +546,7 @@ int vfswrap_readlink(connection_struct *conn, const char *path, char *buf, size_ return result; } -int vfswrap_link(connection_struct *conn, const char *oldpath, const char *newpath) +int vfswrap_link(vfs_handle_struct *handle, connection_struct *conn, const char *oldpath, const char *newpath) { int result; @@ -561,7 +556,7 @@ int vfswrap_link(connection_struct *conn, const char *oldpath, const char *newpa return result; } -int vfswrap_mknod(connection_struct *conn, const char *pathname, mode_t mode, SMB_DEV_T dev) +int vfswrap_mknod(vfs_handle_struct *handle, connection_struct *conn, const char *pathname, mode_t mode, SMB_DEV_T dev) { int result; @@ -571,7 +566,7 @@ int vfswrap_mknod(connection_struct *conn, const char *pathname, mode_t mode, SM return result; } -char *vfswrap_realpath(connection_struct *conn, const char *path, char *resolved_path) +char *vfswrap_realpath(vfs_handle_struct *handle, connection_struct *conn, const char *path, char *resolved_path) { char *result; @@ -581,27 +576,27 @@ char *vfswrap_realpath(connection_struct *conn, const char *path, char *resolved return result; } -size_t vfswrap_fget_nt_acl(files_struct *fsp, int fd, SEC_DESC **ppdesc) +size_t vfswrap_fget_nt_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, uint32 security_info, SEC_DESC **ppdesc) { size_t result; START_PROFILE(fget_nt_acl); - result = get_nt_acl(fsp, ppdesc); + result = get_nt_acl(fsp, security_info, ppdesc); END_PROFILE(fget_nt_acl); return result; } -size_t vfswrap_get_nt_acl(files_struct *fsp, const char *name, SEC_DESC **ppdesc) +size_t vfswrap_get_nt_acl(vfs_handle_struct *handle, files_struct *fsp, const char *name, uint32 security_info, SEC_DESC **ppdesc) { size_t result; START_PROFILE(get_nt_acl); - result = get_nt_acl(fsp, ppdesc); + result = get_nt_acl(fsp, security_info, ppdesc); END_PROFILE(get_nt_acl); return result; } -BOOL vfswrap_fset_nt_acl(files_struct *fsp, int fd, uint32 security_info_sent, SEC_DESC *psd) +BOOL vfswrap_fset_nt_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, uint32 security_info_sent, SEC_DESC *psd) { BOOL result; @@ -611,7 +606,7 @@ BOOL vfswrap_fset_nt_acl(files_struct *fsp, int fd, uint32 security_info_sent, S return result; } -BOOL vfswrap_set_nt_acl(files_struct *fsp, const char *name, uint32 security_info_sent, SEC_DESC *psd) +BOOL vfswrap_set_nt_acl(vfs_handle_struct *handle, files_struct *fsp, const char *name, uint32 security_info_sent, SEC_DESC *psd) { BOOL result; @@ -621,132 +616,236 @@ BOOL vfswrap_set_nt_acl(files_struct *fsp, const char *name, uint32 security_inf return result; } -int vfswrap_chmod_acl(connection_struct *conn, const char *name, mode_t mode) +int vfswrap_chmod_acl(vfs_handle_struct *handle, connection_struct *conn, const char *name, mode_t mode) { +#ifdef HAVE_NO_ACL + errno = ENOSYS; + return -1; +#else int result; START_PROFILE(chmod_acl); result = chmod_acl(conn, name, mode); END_PROFILE(chmod_acl); return result; +#endif } -int vfswrap_fchmod_acl(files_struct *fsp, int fd, mode_t mode) +int vfswrap_fchmod_acl(vfs_handle_struct *handle, files_struct *fsp, int fd, mode_t mode) { +#ifdef HAVE_NO_ACL + errno = ENOSYS; + return -1; +#else int result; START_PROFILE(fchmod_acl); result = fchmod_acl(fsp, fd, mode); END_PROFILE(fchmod_acl); return result; +#endif } -int vfswrap_sys_acl_get_entry(struct connection_struct *conn, SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p) +int vfswrap_sys_acl_get_entry(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_T theacl, int entry_id, SMB_ACL_ENTRY_T *entry_p) { return sys_acl_get_entry(theacl, entry_id, entry_p); } -int vfswrap_sys_acl_get_tag_type(struct connection_struct *conn, SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p) +int vfswrap_sys_acl_get_tag_type(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *tag_type_p) { return sys_acl_get_tag_type(entry_d, tag_type_p); } -int vfswrap_sys_acl_get_permset(struct connection_struct *conn, SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p) +int vfswrap_sys_acl_get_permset(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p) { return sys_acl_get_permset(entry_d, permset_p); } -void * vfswrap_sys_acl_get_qualifier(struct connection_struct *conn, SMB_ACL_ENTRY_T entry_d) +void * vfswrap_sys_acl_get_qualifier(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_ENTRY_T entry_d) { return sys_acl_get_qualifier(entry_d); } -SMB_ACL_T vfswrap_sys_acl_get_file(struct connection_struct *conn, const char *path_p, SMB_ACL_TYPE_T type) +SMB_ACL_T vfswrap_sys_acl_get_file(vfs_handle_struct *handle, connection_struct *conn, const char *path_p, SMB_ACL_TYPE_T type) { return sys_acl_get_file(path_p, type); } -SMB_ACL_T vfswrap_sys_acl_get_fd(struct files_struct *fsp, int fd) +SMB_ACL_T vfswrap_sys_acl_get_fd(vfs_handle_struct *handle, files_struct *fsp, int fd) { return sys_acl_get_fd(fd); } -int vfswrap_sys_acl_clear_perms(struct connection_struct *conn, SMB_ACL_PERMSET_T permset) +int vfswrap_sys_acl_clear_perms(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_PERMSET_T permset) { return sys_acl_clear_perms(permset); } -int vfswrap_sys_acl_add_perm(struct connection_struct *conn, SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm) +int vfswrap_sys_acl_add_perm(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm) { return sys_acl_add_perm(permset, perm); } -char * vfswrap_sys_acl_to_text(struct connection_struct *conn, SMB_ACL_T theacl, ssize_t *plen) +char * vfswrap_sys_acl_to_text(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_T theacl, ssize_t *plen) { return sys_acl_to_text(theacl, plen); } -SMB_ACL_T vfswrap_sys_acl_init(struct connection_struct *conn, int count) +SMB_ACL_T vfswrap_sys_acl_init(vfs_handle_struct *handle, connection_struct *conn, int count) { return sys_acl_init(count); } -int vfswrap_sys_acl_create_entry(struct connection_struct *conn, SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry) +int vfswrap_sys_acl_create_entry(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_T *pacl, SMB_ACL_ENTRY_T *pentry) { return sys_acl_create_entry(pacl, pentry); } -int vfswrap_sys_acl_set_tag_type(struct connection_struct *conn, SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype) +int vfswrap_sys_acl_set_tag_type(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_ENTRY_T entry, SMB_ACL_TAG_T tagtype) { return sys_acl_set_tag_type(entry, tagtype); } -int vfswrap_sys_acl_set_qualifier(struct connection_struct *conn, SMB_ACL_ENTRY_T entry, void *qual) +int vfswrap_sys_acl_set_qualifier(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_ENTRY_T entry, void *qual) { return sys_acl_set_qualifier(entry, qual); } -int vfswrap_sys_acl_set_permset(struct connection_struct *conn, SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset) +int vfswrap_sys_acl_set_permset(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_ENTRY_T entry, SMB_ACL_PERMSET_T permset) { return sys_acl_set_permset(entry, permset); } -int vfswrap_sys_acl_valid(struct connection_struct *conn, SMB_ACL_T theacl ) +int vfswrap_sys_acl_valid(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_T theacl ) { return sys_acl_valid(theacl ); } -int vfswrap_sys_acl_set_file(struct connection_struct *conn, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl) +int vfswrap_sys_acl_set_file(vfs_handle_struct *handle, connection_struct *conn, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl) { return sys_acl_set_file(name, acltype, theacl); } -int vfswrap_sys_acl_set_fd(struct files_struct *fsp, int fd, SMB_ACL_T theacl) +int vfswrap_sys_acl_set_fd(vfs_handle_struct *handle, files_struct *fsp, int fd, SMB_ACL_T theacl) { return sys_acl_set_fd(fd, theacl); } -int vfswrap_sys_acl_delete_def_file(struct connection_struct *conn, const char *path) +int vfswrap_sys_acl_delete_def_file(vfs_handle_struct *handle, connection_struct *conn, const char *path) { return sys_acl_delete_def_file(path); } -int vfswrap_sys_acl_get_perm(struct connection_struct *conn, SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm) +int vfswrap_sys_acl_get_perm(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_PERMSET_T permset, SMB_ACL_PERM_T perm) { return sys_acl_get_perm(permset, perm); } -int vfswrap_sys_acl_free_text(struct connection_struct *conn, char *text) +int vfswrap_sys_acl_free_text(vfs_handle_struct *handle, connection_struct *conn, char *text) { return sys_acl_free_text(text); } -int vfswrap_sys_acl_free_acl(struct connection_struct *conn, SMB_ACL_T posix_acl) +int vfswrap_sys_acl_free_acl(vfs_handle_struct *handle, connection_struct *conn, SMB_ACL_T posix_acl) { return sys_acl_free_acl(posix_acl); } -int vfswrap_sys_acl_free_qualifier(struct connection_struct *conn, void *qualifier, SMB_ACL_TAG_T tagtype) +int vfswrap_sys_acl_free_qualifier(vfs_handle_struct *handle, connection_struct *conn, void *qualifier, SMB_ACL_TAG_T tagtype) { return sys_acl_free_qualifier(qualifier, tagtype); } + +int vfswrap_get_quota(struct vfs_handle_struct *handle, struct connection_struct *conn, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt) +{ +#ifdef HAVE_SYS_QUOTAS + int result; + + START_PROFILE(syscall_get_quota); + result = sys_get_quota(conn->connectpath, qtype, id, qt); + END_PROFILE(syscall_get_quota); + return result; +#else + errno = ENOSYS; + return -1; +#endif +} + +int vfswrap_set_quota(struct vfs_handle_struct *handle, struct connection_struct *conn, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt) +{ +#ifdef HAVE_SYS_QUOTAS + int result; + + START_PROFILE(syscall_set_quota); + result = sys_set_quota(conn->connectpath, qtype, id, qt); + END_PROFILE(syscall_set_quota); + return result; +#else + errno = ENOSYS; + return -1; +#endif +} + +/**************************************************************** + Extended attribute operations. +*****************************************************************/ + +ssize_t vfswrap_getxattr(struct vfs_handle_struct *handle,struct connection_struct *conn,const char *path, const char *name, void *value, size_t size) +{ + return sys_getxattr(path, name, value, size); +} + +ssize_t vfswrap_lgetxattr(struct vfs_handle_struct *handle,struct connection_struct *conn,const char *path, const char *name, void *value, size_t size) +{ + return sys_lgetxattr(path, name, value, size); +} + +ssize_t vfswrap_fgetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp,int fd, const char *name, void *value, size_t size) +{ + return sys_fgetxattr(fd, name, value, size); +} + +ssize_t vfswrap_listxattr(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, char *list, size_t size) +{ + return sys_listxattr(path, list, size); +} + +ssize_t vfswrap_llistxattr(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, char *list, size_t size) +{ + return sys_llistxattr(path, list, size); +} + +ssize_t vfswrap_flistxattr(struct vfs_handle_struct *handle, struct files_struct *fsp,int fd, char *list, size_t size) +{ + return sys_flistxattr(fd, list, size); +} + +int vfswrap_removexattr(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name) +{ + return sys_removexattr(path, name); +} + +int vfswrap_lremovexattr(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name) +{ + return sys_lremovexattr(path, name); +} + +int vfswrap_fremovexattr(struct vfs_handle_struct *handle, struct files_struct *fsp,int fd, const char *name) +{ + return sys_fremovexattr(fd, name); +} + +int vfswrap_setxattr(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name, const void *value, size_t size, int flags) +{ + return sys_setxattr(path, name, value, size, flags); +} + +int vfswrap_lsetxattr(struct vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name, const void *value, size_t size, int flags) +{ + return sys_lsetxattr(path, name, value, size, flags); +} + +int vfswrap_fsetxattr(struct vfs_handle_struct *handle, struct files_struct *fsp,int fd, const char *name, const void *value, size_t size, int flags) +{ + return sys_fsetxattr(fd, name, value, size, flags); +} diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 5fcf9a575e..5f3abe7efe 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -28,9 +28,9 @@ #define DBGC_CLASS DBGC_VFS struct vfs_init_function_entry { - char *name; - vfs_op_tuple *ops, *(*init)(const struct vfs_ops *, struct smb_vfs_handle_struct *); - struct vfs_init_function_entry *prev, *next; + char *name; + vfs_op_tuple *vfs_op_tuples; + struct vfs_init_function_entry *prev, *next; }; static struct vfs_init_function_entry *backends = NULL; @@ -42,96 +42,106 @@ struct vfs_syminfo { void *fptr; }; -/* - Opaque (final) vfs operations. This is a combination of first-met opaque vfs operations - across all currently processed modules. */ - -static vfs_op_tuple vfs_opaque_ops[SMB_VFS_OP_LAST]; - /* Default vfs hooks. WARNING: The order of these initialisers is very important. They must be in the same order as defined in vfs.h. Change at your own peril. */ -static struct vfs_ops default_vfs_ops = { - - /* Disk operations */ - - vfswrap_dummy_connect, - vfswrap_dummy_disconnect, - vfswrap_disk_free, - - /* Directory operations */ - - vfswrap_opendir, - vfswrap_readdir, - vfswrap_mkdir, - vfswrap_rmdir, - vfswrap_closedir, - - /* File operations */ - - vfswrap_open, - vfswrap_close, - vfswrap_read, - vfswrap_write, - vfswrap_lseek, - vfswrap_sendfile, - vfswrap_rename, - vfswrap_fsync, - vfswrap_stat, - vfswrap_fstat, - vfswrap_lstat, - vfswrap_unlink, - vfswrap_chmod, - vfswrap_fchmod, - vfswrap_chown, - vfswrap_fchown, - vfswrap_chdir, - vfswrap_getwd, - vfswrap_utime, - vfswrap_ftruncate, - vfswrap_lock, - vfswrap_symlink, - vfswrap_readlink, - vfswrap_link, - vfswrap_mknod, - vfswrap_realpath, - - vfswrap_fget_nt_acl, - vfswrap_get_nt_acl, - vfswrap_fset_nt_acl, - vfswrap_set_nt_acl, - - /* POSIX ACL operations. */ -#if defined(HAVE_NO_ACLS) - NULL, - NULL, -#else - vfswrap_chmod_acl, - vfswrap_fchmod_acl, -#endif - vfswrap_sys_acl_get_entry, - vfswrap_sys_acl_get_tag_type, - vfswrap_sys_acl_get_permset, - vfswrap_sys_acl_get_qualifier, - vfswrap_sys_acl_get_file, - vfswrap_sys_acl_get_fd, - vfswrap_sys_acl_clear_perms, - vfswrap_sys_acl_add_perm, - vfswrap_sys_acl_to_text, - vfswrap_sys_acl_init, - vfswrap_sys_acl_create_entry, - vfswrap_sys_acl_set_tag_type, - vfswrap_sys_acl_set_qualifier, - vfswrap_sys_acl_set_permset, - vfswrap_sys_acl_valid, - vfswrap_sys_acl_set_file, - vfswrap_sys_acl_set_fd, - vfswrap_sys_acl_delete_def_file, - vfswrap_sys_acl_get_perm, - vfswrap_sys_acl_free_text, - vfswrap_sys_acl_free_acl, - vfswrap_sys_acl_free_qualifier +static struct vfs_ops default_vfs = { + + { + /* Disk operations */ + + vfswrap_dummy_connect, + vfswrap_dummy_disconnect, + vfswrap_disk_free, + vfswrap_get_quota, + vfswrap_set_quota, + + /* Directory operations */ + + vfswrap_opendir, + vfswrap_readdir, + vfswrap_mkdir, + vfswrap_rmdir, + vfswrap_closedir, + + /* File operations */ + + vfswrap_open, + vfswrap_close, + vfswrap_read, + vfswrap_write, + vfswrap_lseek, + vfswrap_sendfile, + vfswrap_rename, + vfswrap_fsync, + vfswrap_stat, + vfswrap_fstat, + vfswrap_lstat, + vfswrap_unlink, + vfswrap_chmod, + vfswrap_fchmod, + vfswrap_chown, + vfswrap_fchown, + vfswrap_chdir, + vfswrap_getwd, + vfswrap_utime, + vfswrap_ftruncate, + vfswrap_lock, + vfswrap_symlink, + vfswrap_readlink, + vfswrap_link, + vfswrap_mknod, + vfswrap_realpath, + + /* Windows ACL operations. */ + vfswrap_fget_nt_acl, + vfswrap_get_nt_acl, + vfswrap_fset_nt_acl, + vfswrap_set_nt_acl, + + /* POSIX ACL operations. */ + vfswrap_chmod_acl, + vfswrap_fchmod_acl, + + vfswrap_sys_acl_get_entry, + vfswrap_sys_acl_get_tag_type, + vfswrap_sys_acl_get_permset, + vfswrap_sys_acl_get_qualifier, + vfswrap_sys_acl_get_file, + vfswrap_sys_acl_get_fd, + vfswrap_sys_acl_clear_perms, + vfswrap_sys_acl_add_perm, + vfswrap_sys_acl_to_text, + vfswrap_sys_acl_init, + vfswrap_sys_acl_create_entry, + vfswrap_sys_acl_set_tag_type, + vfswrap_sys_acl_set_qualifier, + vfswrap_sys_acl_set_permset, + vfswrap_sys_acl_valid, + vfswrap_sys_acl_set_file, + vfswrap_sys_acl_set_fd, + vfswrap_sys_acl_delete_def_file, + vfswrap_sys_acl_get_perm, + vfswrap_sys_acl_free_text, + vfswrap_sys_acl_free_acl, + vfswrap_sys_acl_free_qualifier, + + /* EA operations. */ + vfswrap_getxattr, + vfswrap_lgetxattr, + vfswrap_fgetxattr, + vfswrap_listxattr, + vfswrap_llistxattr, + vfswrap_flistxattr, + vfswrap_removexattr, + vfswrap_lremovexattr, + vfswrap_fremovexattr, + vfswrap_setxattr, + vfswrap_lsetxattr, + vfswrap_fsetxattr + + } }; /**************************************************************************** @@ -140,52 +150,46 @@ static struct vfs_ops default_vfs_ops = { static struct vfs_init_function_entry *vfs_find_backend_entry(const char *name) { - struct vfs_init_function_entry *entry = backends; - pstring stripped; - - module_path_get_name(name, stripped); - - while(entry) { - if (strequal(entry->name, stripped)) return entry; - entry = entry->next; - } + struct vfs_init_function_entry *entry = backends; + + while(entry) { + if (strcmp(entry->name, name)==0) return entry; + entry = entry->next; + } - return NULL; + return NULL; } -NTSTATUS smb_register_vfs(int version, const char *name, vfs_op_tuple *(*init)(const struct vfs_ops *, struct smb_vfs_handle_struct *)) +NTSTATUS smb_register_vfs(int version, const char *name, vfs_op_tuple *vfs_op_tuples) { - struct vfs_init_function_entry *entry = backends; - - if ((version < SMB_VFS_INTERFACE_CASCADED)) { - DEBUG(0, ("vfs_init() returned wrong interface version info (was %d, should be no less than %d)\n", - version, SMB_VFS_INTERFACE_VERSION )); - return NT_STATUS_OBJECT_TYPE_MISMATCH; - } - - if ((version < SMB_VFS_INTERFACE_VERSION)) { - DEBUG(0, ("Warning: vfs_init() states that module confirms interface version #%d, current interface version is #%d.\n\ - Proceeding in compatibility mode, new operations (since version #%d) will fallback to default ones.\n", - version, SMB_VFS_INTERFACE_VERSION, version )); - return NT_STATUS_OBJECT_TYPE_MISMATCH; - } - - if (!name || !init) { - return NT_STATUS_INVALID_PARAMETER; - } - - if (vfs_find_backend_entry(name)) { - DEBUG(0,("VFS module %s already loaded!\n", name)); - return NT_STATUS_OBJECT_NAME_COLLISION; - } - - entry = smb_xmalloc(sizeof(struct vfs_init_function_entry)); - entry->name = smb_xstrdup(name); - entry->init = init; - - DLIST_ADD(backends, entry); - DEBUG(5, ("Successfully added vfs backend '%s'\n", name)); - return NT_STATUS_OK; + struct vfs_init_function_entry *entry = backends; + + if ((version != SMB_VFS_INTERFACE_VERSION)) { + DEBUG(0, ("Failed to register vfs module.\n" + "The module was compiled against SMB_VFS_INTERFACE_VERSION %d,\n" + "current SMB_VFS_INTERFACE_VERSION is %d.\n" + "Please recompile against the current Samba Version!\n", + version, SMB_VFS_INTERFACE_VERSION)); + return NT_STATUS_OBJECT_TYPE_MISMATCH; + } + + if (!name || !name[0] || !vfs_op_tuples) { + DEBUG(0,("smb_register_vfs() called with NULL pointer or empty name!\n")); + return NT_STATUS_INVALID_PARAMETER; + } + + if (vfs_find_backend_entry(name)) { + DEBUG(0,("VFS module %s already loaded!\n", name)); + return NT_STATUS_OBJECT_NAME_COLLISION; + } + + entry = smb_xmalloc(sizeof(struct vfs_init_function_entry)); + entry->name = smb_xstrdup(name); + entry->vfs_op_tuples = vfs_op_tuples; + + DLIST_ADD(backends, entry); + DEBUG(5, ("Successfully added vfs backend '%s'\n", name)); + return NT_STATUS_OK; } /**************************************************************************** @@ -196,62 +200,10 @@ static void vfs_init_default(connection_struct *conn) { DEBUG(3, ("Initialising default vfs hooks\n")); - memcpy(&conn->vfs_ops, &default_vfs_ops, sizeof(struct vfs_ops)); - conn->vfs_private = NULL; -} - -/*************************************************************************** - Function to load old VFS modules. Should go away after a while. - **************************************************************************/ - -static vfs_op_tuple *vfs_load_old_plugin(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 *); - /* Open object file */ - - if ((conn->vfs_private->handle = sys_dlopen(vfs_object, RTLD_NOW)) == NULL) { - DEBUG(0, ("Error opening %s: %s\n", vfs_object, sys_dlerror())); - return NULL; - } - - /* Get handle on vfs_init() symbol */ - - init_fptr = (vfs_op_tuple *(*)(int *, const struct vfs_ops *, struct smb_vfs_handle_struct *))sys_dlsym(conn->vfs_private->handle, "vfs_init"); - - if (init_fptr == NULL) { - DEBUG(0, ("No vfs_init() symbol found in %s\n", vfs_object)); - sys_dlclose(conn->vfs_private->handle); - return NULL; - } - - /* Initialise vfs_ops structure */ - if ((ops = init_fptr(&vfs_version, &conn->vfs_ops, conn->vfs_private)) == NULL) { - DEBUG(0, ("vfs_init() function from %s failed\n", vfs_object)); - sys_dlclose(conn->vfs_private->handle); - return NULL; - } - - if ((vfs_version < SMB_VFS_INTERFACE_CASCADED)) { - DEBUG(0, ("vfs_init() returned wrong interface version info (was %d, should be no less than %d)\n", - vfs_version, SMB_VFS_INTERFACE_VERSION )); - sys_dlclose(conn->vfs_private->handle); - return NULL; - } - - if ((vfs_version < SMB_VFS_INTERFACE_VERSION)) { - DEBUG(0, ("Warning: vfs_init() states that module confirms interface version #%d, current interface version is #%d.\n\ - Proceeding in compatibility mode, new operations (since version #%d) will fallback to default ones.\n", - vfs_version, SMB_VFS_INTERFACE_VERSION, vfs_version )); - sys_dlclose(conn->vfs_private->handle); - return NULL; - } - - return ops; + memcpy(&conn->vfs.ops, &default_vfs.ops, sizeof(default_vfs.ops)); + memcpy(&conn->vfs_opaque.ops, &default_vfs.ops, sizeof(default_vfs.ops)); } - - /**************************************************************************** initialise custom vfs hooks ****************************************************************************/ @@ -259,51 +211,82 @@ static vfs_op_tuple *vfs_load_old_plugin(connection_struct *conn, const char *vf BOOL vfs_init_custom(connection_struct *conn, const char *vfs_object) { vfs_op_tuple *ops; + char *module_name = NULL; + char *module_param = NULL, *p; int i; + vfs_handle_struct *handle; struct vfs_init_function_entry *entry; - - DEBUG(3, ("Initialising custom vfs hooks from %s\n", vfs_object)); + + if (!conn||!vfs_object||!vfs_object[0]) { + DEBUG(0,("vfs_init_custon() called with NULL pointer or emtpy vfs_object!\n")); + return False; + } if(!backends) static_init_vfs; + DEBUG(3, ("Initialising custom vfs hooks from [%s]\n", vfs_object)); + + module_name = smb_xstrdup(vfs_object); + + p = strchr(module_name, ':'); + + if (p) { + *p = 0; + module_param = p+1; + trim_string(module_param, " ", " "); + } + + trim_string(module_name, " ", " "); + /* First, try to load the module with the new module system */ - if((entry = vfs_find_backend_entry(vfs_object)) || - (NT_STATUS_IS_OK(smb_probe_module("vfs", vfs_object)) && - (entry = vfs_find_backend_entry(vfs_object)))) { + if((entry = vfs_find_backend_entry(module_name)) || + (NT_STATUS_IS_OK(smb_probe_module("vfs", module_name)) && + (entry = vfs_find_backend_entry(module_name)))) { - DEBUG(3,("Successfully loaded %s with the new modules system\n", vfs_object)); + DEBUGADD(5,("Successfully loaded vfs module [%s] with the new modules system\n", vfs_object)); - if ((ops = entry->init(&conn->vfs_ops, conn->vfs_private)) == NULL) { - DEBUG(0, ("vfs init function from %s failed\n", vfs_object)); - return False; - } + if ((ops = entry->vfs_op_tuples) == NULL) { + DEBUG(0, ("entry->vfs_op_tuples==NULL for [%s] failed\n", vfs_object)); + SAFE_FREE(module_name); + return False; + } } else { - /* If that doesn't work, fall back to the old system - * (This part should go away after a while, it's only here - * for backwards compatibility) */ - DEBUG(2, ("Can't load module %s with new modules system, falling back to compatibility\n", - vfs_object)); - if ((ops = vfs_load_old_plugin(conn, vfs_object)) == NULL) { - DEBUG(0, ("vfs init function from %s failed\n", vfs_object)); - return False; - } + DEBUG(0,("Can't find a vfs module [%s]\n",vfs_object)); + SAFE_FREE(module_name); + return False; + } + + handle = (vfs_handle_struct *)talloc_zero(conn->mem_ctx,sizeof(vfs_handle_struct)); + if (!handle) { + DEBUG(0,("talloc_zero() failed!\n")); + SAFE_FREE(module_name); + return False; } + memcpy(&handle->vfs_next, &conn->vfs, sizeof(struct vfs_ops)); + handle->conn = conn; + if (module_param) { + handle->param = talloc_strdup(conn->mem_ctx, module_param); + } + DLIST_ADD(conn->vfs_handles, handle); for(i=0; ops[i].op != NULL; i++) { - DEBUG(3, ("Checking operation #%d (type %d, layer %d)\n", i, ops[i].type, ops[i].layer)); + DEBUG(5, ("Checking operation #%d (type %d, layer %d)\n", i, ops[i].type, ops[i].layer)); if(ops[i].layer == SMB_VFS_LAYER_OPAQUE) { /* Check whether this operation was already made opaque by different module */ - if(vfs_opaque_ops[ops[i].type].op == ((void**)&default_vfs_ops)[ops[i].type]) { + if(((void**)&conn->vfs_opaque.ops)[ops[i].type] == ((void**)&default_vfs.ops)[ops[i].type]) { /* No, it isn't overloaded yet. Overload. */ - DEBUG(3, ("Making operation type %d opaque [module %s]\n", ops[i].type, vfs_object)); - vfs_opaque_ops[ops[i].type] = ops[i]; + DEBUGADD(5, ("Making operation type %d opaque [module %s]\n", ops[i].type, vfs_object)); + ((void**)&conn->vfs_opaque.ops)[ops[i].type] = ops[i].op; + ((vfs_handle_struct **)&conn->vfs_opaque.handles)[ops[i].type] = handle; } } /* Change current VFS disposition*/ - DEBUG(3, ("Accepting operation type %d from module %s\n", ops[i].type, vfs_object)); - ((void**)&conn->vfs_ops)[ops[i].type] = ops[i].op; + DEBUGADD(5, ("Accepting operation type %d from module %s\n", ops[i].type, vfs_object)); + ((void**)&conn->vfs.ops)[ops[i].type] = ops[i].op; + ((vfs_handle_struct **)&conn->vfs.handles)[ops[i].type] = handle; } + SAFE_FREE(module_name); return True; } @@ -314,70 +297,30 @@ BOOL vfs_init_custom(connection_struct *conn, const char *vfs_object) BOOL smbd_vfs_init(connection_struct *conn) { const char **vfs_objects; - char *vfs_module, *vfs_path; unsigned int i = 0; int j = 0; - struct smb_vfs_handle_struct *handle; /* Normal share - initialise with disk access functions */ vfs_init_default(conn); - vfs_objects = lp_vfsobj(SNUM(conn)); + vfs_objects = lp_vfs_objects(SNUM(conn)); /* Override VFS functions if 'vfs object' was not specified*/ if (!vfs_objects || !vfs_objects[0]) return True; - - for(i=0; i= 0; j--) { - conn->vfs_private = NULL; - handle = (struct smb_vfs_handle_struct *) smb_xmalloc(sizeof(smb_vfs_handle_struct)); - /* Loadable object file */ - handle->handle = NULL; - DLIST_ADD(conn->vfs_private, handle); - vfs_module = NULL; - if (vfs_path && *vfs_path) { - asprintf(&vfs_module, "%s/%s", vfs_path, vfs_objects[j]); - } else { - asprintf(&vfs_module, "%s", vfs_objects[j]); - } - if (!vfs_init_custom(conn, vfs_module)) { - DEBUG(0, ("smbd_vfs_init: vfs_init_custom failed for %s\n", vfs_module)); - SAFE_FREE(vfs_module); - DLIST_REMOVE(conn->vfs_private, handle); - SAFE_FREE(handle); + if (!vfs_init_custom(conn, vfs_objects[j])) { + DEBUG(0, ("smbd_vfs_init: vfs_init_custom failed for %s\n", vfs_objects[j])); return False; } - SAFE_FREE(vfs_module); } return True; } -/******************************************************************* - Create vfs_ops reflecting current vfs_opaque_ops -*******************************************************************/ - -struct vfs_ops *smb_vfs_get_opaque_ops(void) -{ - int i; - struct vfs_ops *ops; - - ops = smb_xmalloc(sizeof(struct vfs_ops)); - - for(i=0; ist_mode); @@ -400,25 +343,16 @@ BOOL vfs_directory_exist(connection_struct *conn, const char *dname, SMB_STRUCT_ return ret; } -/******************************************************************* - vfs getwd wrapper -********************************************************************/ - -static char *vfs_getwd(connection_struct *conn, char *path) -{ - return conn->vfs_ops.getwd(conn,path); -} - /******************************************************************* vfs mkdir wrapper ********************************************************************/ -int vfs_mkdir(connection_struct *conn, const char *name, mode_t mode) +int vfs_MkDir(connection_struct *conn, const char *name, mode_t mode) { int ret; SMB_STRUCT_STAT sbuf; - if(!(ret=conn->vfs_ops.mkdir(conn,name,mode))) { + if(!(ret=SMB_VFS_MKDIR(conn, name, mode))) { inherit_access_acl(conn, name, mode); @@ -428,8 +362,8 @@ int vfs_mkdir(connection_struct *conn, const char *name, mode_t mode) * Consider bits automagically set by UNIX, i.e. SGID bit from parent dir. */ if(mode & ~(S_IRWXU|S_IRWXG|S_IRWXO) && - !vfs_stat(conn,name,&sbuf) && (mode & ~sbuf.st_mode)) - vfs_chmod(conn,name,sbuf.st_mode | (mode & ~sbuf.st_mode)); + !SMB_VFS_STAT(conn,name,&sbuf) && (mode & ~sbuf.st_mode)) + SMB_VFS_CHMOD(conn,name,sbuf.st_mode | (mode & ~sbuf.st_mode)); } return ret; } @@ -447,7 +381,7 @@ BOOL vfs_object_exist(connection_struct *conn,const char *fname,SMB_STRUCT_STAT ZERO_STRUCTP(sbuf); - if (vfs_stat(conn,fname,sbuf) == -1) + if (SMB_VFS_STAT(conn,fname,sbuf) == -1) return(False); return True; } @@ -465,7 +399,7 @@ BOOL vfs_file_exist(connection_struct *conn, const char *fname,SMB_STRUCT_STAT * ZERO_STRUCTP(sbuf); - if (vfs_stat(conn,fname,sbuf) == -1) + if (SMB_VFS_STAT(conn,fname,sbuf) == -1) return False; return(S_ISREG(sbuf->st_mode)); } @@ -480,7 +414,7 @@ ssize_t vfs_read_data(files_struct *fsp, char *buf, size_t byte_count) while (total < byte_count) { - ssize_t ret = fsp->conn->vfs_ops.read(fsp, fsp->fd, buf + total, + ssize_t ret = SMB_VFS_READ(fsp, fsp->fd, buf + total, byte_count - total); if (ret == 0) return total; @@ -505,7 +439,7 @@ ssize_t vfs_write_data(files_struct *fsp,const char *buffer,size_t N) ssize_t ret; while (total < N) { - ret = fsp->conn->vfs_ops.write(fsp,fsp->fd,buffer + total,N - total); + ret = SMB_VFS_WRITE(fsp,fsp->fd,buffer + total,N - total); if (ret == -1) return -1; @@ -528,7 +462,6 @@ int vfs_allocate_file_space(files_struct *fsp, SMB_BIG_UINT len) int ret; SMB_STRUCT_STAT st; connection_struct *conn = fsp->conn; - struct vfs_ops *vfs_ops = &conn->vfs_ops; SMB_BIG_UINT space_avail; SMB_BIG_UINT bsize,dfree,dsize; @@ -545,7 +478,7 @@ int vfs_allocate_file_space(files_struct *fsp, SMB_BIG_UINT len) return -1; } - ret = vfs_fstat(fsp,fsp->fd,&st); + ret = SMB_VFS_FSTAT(fsp,fsp->fd,&st); if (ret == -1) return ret; @@ -559,7 +492,7 @@ int vfs_allocate_file_space(files_struct *fsp, SMB_BIG_UINT len) fsp->fsp_name, (double)st.st_size )); flush_write_cache(fsp, SIZECHANGE_FLUSH); - if ((ret = vfs_ops->ftruncate(fsp, fsp->fd, (SMB_OFF_T)len)) != -1) { + if ((ret = SMB_VFS_FTRUNCATE(fsp, fsp->fd, (SMB_OFF_T)len)) != -1) { set_filelen_write_cache(fsp, len); } return ret; @@ -572,7 +505,7 @@ int vfs_allocate_file_space(files_struct *fsp, SMB_BIG_UINT len) len -= st.st_size; len /= 1024; /* Len is now number of 1k blocks needed. */ - space_avail = conn->vfs_ops.disk_free(conn,fsp->fsp_name,False,&bsize,&dfree,&dsize); + space_avail = SMB_VFS_DISK_FREE(conn,fsp->fsp_name,False,&bsize,&dfree,&dsize); DEBUG(10,("vfs_allocate_file_space: file %s, grow. Current size %.0f, needed blocks = %.0f, space avail = %.0f\n", fsp->fsp_name, (double)st.st_size, (double)len, (double)space_avail )); @@ -598,7 +531,7 @@ int vfs_set_filelen(files_struct *fsp, SMB_OFF_T len) release_level_2_oplocks_on_change(fsp); DEBUG(10,("vfs_set_filelen: ftruncate %s to len %.0f\n", fsp->fsp_name, (double)len)); flush_write_cache(fsp, SIZECHANGE_FLUSH); - if ((ret = fsp->conn->vfs_ops.ftruncate(fsp, fsp->fd, len)) != -1) + if ((ret = SMB_VFS_FTRUNCATE(fsp, fsp->fd, len)) != -1) set_filelen_write_cache(fsp, len); return ret; @@ -613,12 +546,12 @@ static files_struct *out_fsp; static ssize_t read_fn(int fd, void *buf, size_t len) { - return in_fsp->conn->vfs_ops.read(in_fsp, fd, buf, len); + return SMB_VFS_READ(in_fsp, fd, buf, len); } static ssize_t write_fn(int fd, const void *buf, size_t len) { - return out_fsp->conn->vfs_ops.write(out_fsp, fd, buf, len); + return SMB_VFS_WRITE(out_fsp, fd, buf, len); } SMB_OFF_T vfs_transfer_file(files_struct *in, files_struct *out, SMB_OFF_T n) @@ -635,13 +568,13 @@ SMB_OFF_T vfs_transfer_file(files_struct *in, files_struct *out, SMB_OFF_T n) char *vfs_readdirname(connection_struct *conn, void *p) { - struct dirent *ptr; + struct dirent *ptr= NULL; char *dname; if (!p) return(NULL); - ptr = (struct dirent *)conn->vfs_ops.readdir(conn,p); + ptr = (struct dirent *)SMB_VFS_READDIR(conn,p); if (!ptr) return(NULL); @@ -660,72 +593,6 @@ char *vfs_readdirname(connection_struct *conn, void *p) return(dname); } -/* VFS options not quite working yet */ - -#if 0 - -/*************************************************************************** - handle the interpretation of the vfs option parameter - *************************************************************************/ -static BOOL handle_vfs_option(char *pszParmValue, char **ptr) -{ - struct vfs_options *new_option, **options = (struct vfs_options **)ptr; - int i; - - /* Create new vfs option */ - - new_option = (struct vfs_options *)malloc(sizeof(*new_option)); - if (new_option == NULL) { - return False; - } - - ZERO_STRUCTP(new_option); - - /* Get name and value */ - - new_option->name = strtok(pszParmValue, "="); - - if (new_option->name == NULL) { - return False; - } - - while(isspace(*new_option->name)) { - new_option->name++; - } - - for (i = strlen(new_option->name); i > 0; i--) { - if (!isspace(new_option->name[i - 1])) break; - } - - new_option->name[i] = '\0'; - new_option->name = strdup(new_option->name); - - new_option->value = strtok(NULL, "="); - - if (new_option->value != NULL) { - - while(isspace(*new_option->value)) { - new_option->value++; - } - - for (i = strlen(new_option->value); i > 0; i--) { - if (!isspace(new_option->value[i - 1])) break; - } - - new_option->value[i] = '\0'; - new_option->value = strdup(new_option->value); - } - - /* Add to list */ - - DLIST_ADD(*options, new_option); - - return True; -} - -#endif - - /******************************************************************* A wrapper for vfs_chdir(). ********************************************************************/ @@ -741,9 +608,9 @@ int vfs_ChDir(connection_struct *conn, const char *path) if (*path == '/' && strcsequal(LastDir,path)) return(0); - DEBUG(3,("vfs_ChDir to %s\n",path)); + DEBUG(4,("vfs_ChDir to %s\n",path)); - res = vfs_chdir(conn,path); + res = SMB_VFS_CHDIR(conn,path); if (!res) pstrcpy(LastDir,path); return(res); @@ -800,7 +667,7 @@ char *vfs_GetWd(connection_struct *conn, char *path) *s = 0; if (!use_getwd_cache) - return(vfs_getwd(conn,path)); + return(SMB_VFS_GETWD(conn,path)); /* init the cache */ if (!getwd_cache_init) { @@ -814,9 +681,9 @@ char *vfs_GetWd(connection_struct *conn, char *path) /* Get the inode of the current directory, if this doesn't work we're in trouble :-) */ - if (vfs_stat(conn, ".",&st) == -1) { + if (SMB_VFS_STAT(conn, ".",&st) == -1) { DEBUG(0,("Very strange, couldn't stat \".\" path=%s\n", path)); - return(vfs_getwd(conn,path)); + return(SMB_VFS_GETWD(conn,path)); } @@ -830,7 +697,7 @@ char *vfs_GetWd(connection_struct *conn, char *path) the same...) */ if (st.st_ino == ino_list[i].inode && st.st_dev == ino_list[i].dev) { - if (vfs_stat(conn,ino_list[i].dos_path,&st2) == 0) { + if (SMB_VFS_STAT(conn,ino_list[i].dos_path,&st2) == 0) { if (st.st_ino == st2.st_ino && st.st_dev == st2.st_dev && (st2.st_mode & S_IFMT) == S_IFDIR) { pstrcpy (path, ino_list[i].dos_path); @@ -852,8 +719,8 @@ char *vfs_GetWd(connection_struct *conn, char *path) The very slow getcwd, which spawns a process on some systems, or the not quite so bad getwd. */ - if (!vfs_getwd(conn,s)) { - DEBUG(0,("vfs_GetWd: vfs_getwd call failed, errno %s\n",strerror(errno))); + if (!SMB_VFS_GETWD(conn,s)) { + DEBUG(0,("vfs_GetWd: SMB_VFS_GETWD call failed, errno %s\n",strerror(errno))); return (NULL); } @@ -909,7 +776,7 @@ static BOOL readlink_check(connection_struct *conn, const char *dir, char *name) realdir[reallen] = 0; } - if (conn->vfs_ops.readlink(conn, name, flink, sizeof(pstring) -1) != -1) { + if (SMB_VFS_READLINK(conn, name, flink, sizeof(pstring) -1) != -1) { DEBUG(3,("reduce_name: file path name %s is a symlink\nChecking it's path\n", name)); if (*flink == '/') { pstrcpy(cleanlink, flink); diff --git a/source3/smbwrapper/shared.c b/source3/smbwrapper/shared.c index b4cfcf7148..ca8df5841d 100644 --- a/source3/smbwrapper/shared.c +++ b/source3/smbwrapper/shared.c @@ -179,8 +179,8 @@ void smbw_setshared(const char *name, const char *val) SSVAL(&variables[shared_size], 0, l1); SSVAL(&variables[shared_size], 2, l2); - pstrcpy(&variables[shared_size] + 4, name); - pstrcpy(&variables[shared_size] + 4 + l1, val); + safe_strcpy(&variables[shared_size] + 4, name, l1-1); + safe_strcpy(&variables[shared_size] + 4 + l1, val, l2-1); shared_size += l1+l2+4; diff --git a/source3/smbwrapper/smbw_dir.c b/source3/smbwrapper/smbw_dir.c index 31d81a1e7e..6d55c1d9da 100644 --- a/source3/smbwrapper/smbw_dir.c +++ b/source3/smbwrapper/smbw_dir.c @@ -216,7 +216,7 @@ int smbw_dir_open(const char *fname) smbw_NetServerEnum(&srv->cli, srv->server_name, SV_TYPE_ALL, smbw_server_add, NULL); *p = '#'; - } else if (strcmp(srv->cli.dev,"IPC") == 0) { + } else if ((strcmp(srv->cli.dev,"IPC") == 0) || (strcasecmp(share,"IPC$") == 0)) { DEBUG(4,("doing NetShareEnum\n")); smbw_share_add(".",0,"", NULL); smbw_share_add("..",0,"", NULL); @@ -412,7 +412,8 @@ int smbw_chdir(const char *name) goto failed; } - if (strncmp(srv->cli.dev,"IPC",3) && + if (strncmp(srv->cli.dev,"IPC",3) && + strcasecmp(share, "IPC$") && strncmp(srv->cli.dev,"LPT",3) && !smbw_getatr(srv, path, &mode, NULL, NULL, NULL, NULL, NULL)) { diff --git a/source3/tdb/tdb.c b/source3/tdb/tdb.c index c414ae0d31..34681ea78f 100644 --- a/source3/tdb/tdb.c +++ b/source3/tdb/tdb.c @@ -1257,7 +1257,8 @@ static int tdb_next_lock(TDB_CONTEXT *tdb, struct tdb_traverse_lock *tlock, /* Try to clean dead ones from old traverses */ current = tlock->off; tlock->off = rec->next; - if (do_delete(tdb, current, rec) != 0) + if (!tdb->read_only && + do_delete(tdb, current, rec) != 0) goto fail; } tdb_unlock(tdb, tlock->hash, F_WRLCK); diff --git a/source3/tdb/tdbbackup.c b/source3/tdb/tdbbackup.c index 36ba7db918..0eaf6b6c0b 100644 --- a/source3/tdb/tdbbackup.c +++ b/source3/tdb/tdbbackup.c @@ -55,175 +55,7 @@ #include #include #include "tdb.h" - -static int failed; - -static char *add_suffix(const char *name, const char *suffix) -{ - char *ret; - int len = strlen(name) + strlen(suffix) + 1; - ret = malloc(len); - if (!ret) { - fprintf(stderr,"Out of memory!\n"); - exit(1); - } - strncpy(ret, name, len); - strncat(ret, suffix, len); - return ret; -} - -static int copy_fn(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, void *state) -{ - TDB_CONTEXT *tdb_new = (TDB_CONTEXT *)state; - - if (tdb_store(tdb_new, key, dbuf, TDB_INSERT) != 0) { - fprintf(stderr,"Failed to insert into %s\n", tdb_new->name); - failed = 1; - return 1; - } - return 0; -} - - -static int test_fn(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, void *state) -{ - return 0; -} - -/* - carefully backup a tdb, validating the contents and - only doing the backup if its OK - this function is also used for restore -*/ -static int backup_tdb(const char *old_name, const char *new_name) -{ - TDB_CONTEXT *tdb; - TDB_CONTEXT *tdb_new; - char *tmp_name; - struct stat st; - int count1, count2; - - tmp_name = add_suffix(new_name, ".tmp"); - - /* stat the old tdb to find its permissions */ - if (stat(old_name, &st) != 0) { - perror(old_name); - return 1; - } - - /* open the old tdb */ - tdb = tdb_open(old_name, 0, 0, O_RDWR, 0); - if (!tdb) { - printf("Failed to open %s\n", old_name); - return 1; - } - - /* create the new tdb */ - unlink(tmp_name); - tdb_new = tdb_open(tmp_name, tdb->header.hash_size, - TDB_DEFAULT, O_RDWR|O_CREAT|O_EXCL, - st.st_mode & 0777); - if (!tdb_new) { - perror(tmp_name); - free(tmp_name); - return 1; - } - - /* lock the old tdb */ - if (tdb_lockall(tdb) != 0) { - fprintf(stderr,"Failed to lock %s\n", old_name); - tdb_close(tdb); - tdb_close(tdb_new); - unlink(tmp_name); - free(tmp_name); - return 1; - } - - failed = 0; - - /* traverse and copy */ - count1 = tdb_traverse(tdb, copy_fn, (void *)tdb_new); - if (count1 < 0 || failed) { - fprintf(stderr,"failed to copy %s\n", old_name); - tdb_close(tdb); - tdb_close(tdb_new); - unlink(tmp_name); - free(tmp_name); - return 1; - } - - /* close the old tdb */ - tdb_close(tdb); - - /* close the new tdb and re-open read-only */ - tdb_close(tdb_new); - tdb_new = tdb_open(tmp_name, 0, TDB_DEFAULT, O_RDONLY, 0); - if (!tdb_new) { - fprintf(stderr,"failed to reopen %s\n", tmp_name); - unlink(tmp_name); - perror(tmp_name); - free(tmp_name); - return 1; - } - - /* traverse the new tdb to confirm */ - count2 = tdb_traverse(tdb_new, test_fn, 0); - if (count2 != count1) { - fprintf(stderr,"failed to copy %s\n", old_name); - tdb_close(tdb_new); - unlink(tmp_name); - free(tmp_name); - return 1; - } - - /* make sure the new tdb has reached stable storage */ - fsync(tdb_new->fd); - - /* close the new tdb and rename it to .bak */ - tdb_close(tdb_new); - unlink(new_name); - if (rename(tmp_name, new_name) != 0) { - perror(new_name); - free(tmp_name); - return 1; - } - - printf("%s : %d records\n", old_name, count1); - free(tmp_name); - - return 0; -} - - - -/* - verify a tdb and if it is corrupt then restore from *.bak -*/ -static int verify_tdb(const char *fname, const char *bak_name) -{ - TDB_CONTEXT *tdb; - int count = -1; - - /* open the tdb */ - tdb = tdb_open(fname, 0, 0, O_RDONLY, 0); - - /* traverse the tdb, then close it */ - if (tdb) { - count = tdb_traverse(tdb, test_fn, NULL); - tdb_close(tdb); - } - - /* count is < 0 means an error */ - if (count < 0) { - printf("restoring %s\n", fname); - return backup_tdb(bak_name, fname); - } - - printf("%s : %d records\n", fname, count); - - return 0; -} - +#include "tdbback.h" /* see if one file is newer than another @@ -245,7 +77,7 @@ static void usage(void) printf("Usage: tdbbackup [options] \n\n"); printf(" -h this help message\n"); printf(" -s suffix set the backup suffix\n"); - printf(" -v veryify mode (restore if corrupt)\n"); + printf(" -v verify mode (restore if corrupt)\n"); } @@ -255,7 +87,7 @@ static void usage(void) int ret = 0; int c; int verify = 0; - char *suffix = ".bak"; + const char *suffix = ".bak"; extern int optind; extern char *optarg; diff --git a/source3/tdb/tdbutil.c b/source3/tdb/tdbutil.c index 19dfe642df..b01dacd0f5 100644 --- a/source3/tdb/tdbutil.c +++ b/source3/tdb/tdbutil.c @@ -266,7 +266,7 @@ BOOL tdb_store_uint32(TDB_CONTEXT *tdb, const char *keystr, uint32 value) on failure. ****************************************************************************/ -int tdb_store_by_string(TDB_CONTEXT *tdb, const char *keystr, TDB_DATA data, int flags) +int tdb_store_bystring(TDB_CONTEXT *tdb, const char *keystr, TDB_DATA data, int flags) { TDB_DATA key = make_tdb_data(keystr, strlen(keystr)+1); @@ -278,7 +278,7 @@ int tdb_store_by_string(TDB_CONTEXT *tdb, const char *keystr, TDB_DATA data, int free() on the result dptr. ****************************************************************************/ -TDB_DATA tdb_fetch_by_string(TDB_CONTEXT *tdb, const char *keystr) +TDB_DATA tdb_fetch_bystring(TDB_CONTEXT *tdb, const char *keystr) { TDB_DATA key = make_tdb_data(keystr, strlen(keystr)+1); @@ -289,7 +289,7 @@ TDB_DATA tdb_fetch_by_string(TDB_CONTEXT *tdb, const char *keystr) Delete an entry using a null terminated string key. ****************************************************************************/ -int tdb_delete_by_string(TDB_CONTEXT *tdb, const char *keystr) +int tdb_delete_bystring(TDB_CONTEXT *tdb, const char *keystr) { TDB_DATA key = make_tdb_data(keystr, strlen(keystr)+1); @@ -821,6 +821,7 @@ void tdb_search_list_free(TDB_LIST_NODE* node) while (node) { next_node = node->next; + SAFE_FREE(node->node_key.dptr); SAFE_FREE(node); node = next_node; }; diff --git a/source3/torture/cmd_vfs.c b/source3/torture/cmd_vfs.c index b90c53e9fe..f74fcedcf4 100644 --- a/source3/torture/cmd_vfs.c +++ b/source3/torture/cmd_vfs.c @@ -23,37 +23,28 @@ #include "includes.h" #include "vfstest.h" -static char *null_string = ""; +static const char *null_string = ""; -static NTSTATUS cmd_load_module(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv) +static NTSTATUS cmd_load_module(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv) { - struct smb_vfs_handle_struct *handle; - char *path = lp_vfs_path(0); - char name[PATH_MAX]; + int i; - if (argc != 2) { - printf("Usage: load \n"); + if (argc < 2) { + printf("Usage: load \n"); return NT_STATUS_OK; } - if (path != NULL && *path != '\0') { - snprintf(name, PATH_MAX, "%s/%s", path, argv[1]); - } else { - snprintf(name, PATH_MAX, "%s", argv[1]); - } - vfs->conn->vfs_private = NULL; - handle = (struct smb_vfs_handle_struct *) smb_xmalloc(sizeof(smb_vfs_handle_struct)); - handle->handle = NULL; - DLIST_ADD(vfs->conn->vfs_private, handle) - if (!vfs_init_custom(vfs->conn, name)) { - DEBUG(0, ("load: error=-1 (vfs_init_custom failed for %s)\n", argv[1])); - return NT_STATUS_UNSUCCESSFUL; + for (i=argc-1;i>0;i--) { + if (!vfs_init_custom(vfs->conn, argv[i])) { + DEBUG(0, ("load: (vfs_init_custom failed for %s)\n", argv[i])); + return NT_STATUS_UNSUCCESSFUL; + } } printf("load: ok\n"); return NT_STATUS_OK; } -static NTSTATUS cmd_populate(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv) +static NTSTATUS cmd_populate(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv) { char c; size_t size; @@ -73,7 +64,7 @@ static NTSTATUS cmd_populate(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int arg return NT_STATUS_OK; } -static NTSTATUS cmd_show_data(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv) +static NTSTATUS cmd_show_data(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv) { size_t offset; size_t len; @@ -101,19 +92,19 @@ static NTSTATUS cmd_show_data(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int ar return NT_STATUS_OK; } -static NTSTATUS cmd_connect(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv) +static NTSTATUS cmd_connect(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv) { - vfs->conn->vfs_ops.connect(vfs->conn, lp_servicename(vfs->conn->service), "vfstest"); + SMB_VFS_CONNECT(vfs->conn, lp_servicename(vfs->conn->service), "vfstest"); return NT_STATUS_OK; } -static NTSTATUS cmd_disconnect(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv) +static NTSTATUS cmd_disconnect(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv) { - vfs->conn->vfs_ops.disconnect(vfs->conn); + SMB_VFS_DISCONNECT(vfs->conn); return NT_STATUS_OK; } -static NTSTATUS cmd_disk_free(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv) +static NTSTATUS cmd_disk_free(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv) { SMB_BIG_UINT diskfree, bsize, dfree, dsize; if (argc != 2) { @@ -121,7 +112,7 @@ static NTSTATUS cmd_disk_free(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int ar return NT_STATUS_OK; } - diskfree = vfs->conn->vfs_ops.disk_free(vfs->conn, argv[1], False, &bsize, &dfree, &dsize); + diskfree = SMB_VFS_DISK_FREE(vfs->conn, argv[1], False, &bsize, &dfree, &dsize); printf("disk_free: %lu, bsize = %lu, dfree = %lu, dsize = %lu\n", (unsigned long)diskfree, (unsigned long)bsize, @@ -131,14 +122,14 @@ static NTSTATUS cmd_disk_free(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int ar } -static NTSTATUS cmd_opendir(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv) +static NTSTATUS cmd_opendir(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv) { if (argc != 2) { printf("Usage: opendir \n"); return NT_STATUS_OK; } - vfs->currentdir = vfs->conn->vfs_ops.opendir(vfs->conn, argv[1]); + vfs->currentdir = SMB_VFS_OPENDIR(vfs->conn, argv[1]); if (vfs->currentdir == NULL) { printf("opendir error=%d (%s)\n", errno, strerror(errno)); return NT_STATUS_UNSUCCESSFUL; @@ -149,7 +140,7 @@ static NTSTATUS cmd_opendir(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc } -static NTSTATUS cmd_readdir(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv) +static NTSTATUS cmd_readdir(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv) { struct dirent *dent; @@ -158,7 +149,7 @@ static NTSTATUS cmd_readdir(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc return NT_STATUS_UNSUCCESSFUL; } - dent = vfs->conn->vfs_ops.readdir(vfs->conn, vfs->currentdir); + dent = SMB_VFS_READDIR(vfs->conn, vfs->currentdir); if (dent == NULL) { printf("readdir: NULL\n"); return NT_STATUS_OK; @@ -169,14 +160,14 @@ static NTSTATUS cmd_readdir(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc } -static NTSTATUS cmd_mkdir(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv) +static NTSTATUS cmd_mkdir(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv) { if (argc != 2) { printf("Usage: mkdir \n"); return NT_STATUS_OK; } - if (vfs->conn->vfs_ops.mkdir(vfs->conn, argv[1], 00755) == -1) { + if (SMB_VFS_MKDIR(vfs->conn, argv[1], 00755) == -1) { printf("mkdir error=%d (%s)\n", errno, strerror(errno)); return NT_STATUS_UNSUCCESSFUL; } @@ -186,7 +177,7 @@ static NTSTATUS cmd_mkdir(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, } -static NTSTATUS cmd_closedir(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv) +static NTSTATUS cmd_closedir(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv) { int ret; @@ -195,7 +186,7 @@ static NTSTATUS cmd_closedir(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int arg return NT_STATUS_UNSUCCESSFUL; } - ret = vfs->conn->vfs_ops.closedir(vfs->conn, vfs->currentdir); + ret = SMB_VFS_CLOSEDIR(vfs->conn, vfs->currentdir); if (ret == -1) { printf("closedir failure: %s\n", strerror(errno)); return NT_STATUS_UNSUCCESSFUL; @@ -207,11 +198,11 @@ static NTSTATUS cmd_closedir(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int arg } -static NTSTATUS cmd_open(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv) +static NTSTATUS cmd_open(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv) { int flags, fd; mode_t mode; - char *flagstr; + const char *flagstr; mode = 00400; @@ -287,7 +278,7 @@ static NTSTATUS cmd_open(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, c } } - fd = vfs->conn->vfs_ops.open(vfs->conn, argv[1], flags, mode); + fd = SMB_VFS_OPEN(vfs->conn, argv[1], flags, mode); if (fd == -1) { printf("open: error=%d (%s)\n", errno, strerror(errno)); return NT_STATUS_UNSUCCESSFUL; @@ -302,7 +293,7 @@ static NTSTATUS cmd_open(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, c } -static NTSTATUS cmd_pathfunc(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv) +static NTSTATUS cmd_pathfunc(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv) { int ret = -1; @@ -312,11 +303,11 @@ static NTSTATUS cmd_pathfunc(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int arg } if (strcmp("rmdir", argv[0]) == 0 ) { - ret = vfs->conn->vfs_ops.rmdir(vfs->conn, argv[1]); + ret = SMB_VFS_RMDIR(vfs->conn, argv[1]); } else if (strcmp("unlink", argv[0]) == 0 ) { - ret = vfs->conn->vfs_ops.unlink(vfs->conn, argv[1]); + ret = SMB_VFS_UNLINK(vfs->conn, argv[1]); } else if (strcmp("chdir", argv[0]) == 0 ) { - ret = vfs->conn->vfs_ops.chdir(vfs->conn, argv[1]); + ret = SMB_VFS_CHDIR(vfs->conn, argv[1]); } else { printf("%s: error=%d (invalid function name!)\n", argv[0], errno); return NT_STATUS_UNSUCCESSFUL; @@ -332,7 +323,7 @@ static NTSTATUS cmd_pathfunc(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int arg } -static NTSTATUS cmd_close(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv) +static NTSTATUS cmd_close(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv) { int fd, ret; @@ -347,7 +338,7 @@ static NTSTATUS cmd_close(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, return NT_STATUS_OK; } - ret = vfs->conn->vfs_ops.close(vfs->files[fd], fd); + ret = SMB_VFS_CLOSE(vfs->files[fd], fd); if (ret == -1 ) printf("close: error=%d (%s)\n", errno, strerror(errno)); else @@ -360,7 +351,7 @@ static NTSTATUS cmd_close(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, } -static NTSTATUS cmd_read(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv) +static NTSTATUS cmd_read(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv) { int fd; size_t size, rsize; @@ -380,7 +371,7 @@ static NTSTATUS cmd_read(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, c } vfs->data_size = size; - rsize = vfs->conn->vfs_ops.read(vfs->files[fd], fd, vfs->data, size); + rsize = SMB_VFS_READ(vfs->files[fd], fd, vfs->data, size); if (rsize == -1) { printf("read: error=%d (%s)\n", errno, strerror(errno)); return NT_STATUS_UNSUCCESSFUL; @@ -391,7 +382,7 @@ static NTSTATUS cmd_read(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, c } -static NTSTATUS cmd_write(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv) +static NTSTATUS cmd_write(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv) { int fd, size, wsize; @@ -413,7 +404,7 @@ static NTSTATUS cmd_write(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, return NT_STATUS_UNSUCCESSFUL; } - wsize = vfs->conn->vfs_ops.write(vfs->files[fd], fd, vfs->data, size); + wsize = SMB_VFS_WRITE(vfs->files[fd], fd, vfs->data, size); if (wsize == -1) { printf("write: error=%d (%s)\n", errno, strerror(errno)); @@ -425,7 +416,7 @@ static NTSTATUS cmd_write(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, } -static NTSTATUS cmd_lseek(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv) +static NTSTATUS cmd_lseek(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv) { int fd, offset, whence; SMB_OFF_T pos; @@ -444,7 +435,7 @@ static NTSTATUS cmd_lseek(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, default: whence = SEEK_END; } - pos = vfs->conn->vfs_ops.lseek(vfs->files[fd], fd, offset, whence); + pos = SMB_VFS_LSEEK(vfs->files[fd], fd, offset, whence); if (pos == (SMB_OFF_T)-1) { printf("lseek: error=%d (%s)\n", errno, strerror(errno)); return NT_STATUS_UNSUCCESSFUL; @@ -455,7 +446,7 @@ static NTSTATUS cmd_lseek(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, } -static NTSTATUS cmd_rename(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv) +static NTSTATUS cmd_rename(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv) { int ret; if (argc != 3) { @@ -463,7 +454,7 @@ static NTSTATUS cmd_rename(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, return NT_STATUS_OK; } - ret = vfs->conn->vfs_ops.rename(vfs->conn, argv[1], argv[2]); + ret = SMB_VFS_RENAME(vfs->conn, argv[1], argv[2]); if (ret == -1) { printf("rename: error=%d (%s)\n", errno, strerror(errno)); return NT_STATUS_UNSUCCESSFUL; @@ -474,7 +465,7 @@ static NTSTATUS cmd_rename(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, } -static NTSTATUS cmd_fsync(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv) +static NTSTATUS cmd_fsync(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv) { int ret, fd; if (argc != 2) { @@ -483,7 +474,7 @@ static NTSTATUS cmd_fsync(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, } fd = atoi(argv[1]); - ret = vfs->conn->vfs_ops.fsync(vfs->files[fd], fd); + ret = SMB_VFS_FSYNC(vfs->files[fd], fd); if (ret == -1) { printf("fsync: error=%d (%s)\n", errno, strerror(errno)); return NT_STATUS_UNSUCCESSFUL; @@ -494,11 +485,11 @@ static NTSTATUS cmd_fsync(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, } -static NTSTATUS cmd_stat(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv) +static NTSTATUS cmd_stat(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv) { int ret; - char *user; - char *group; + const char *user; + const char *group; struct passwd *pwd; struct group *grp; SMB_STRUCT_STAT st; @@ -508,17 +499,17 @@ static NTSTATUS cmd_stat(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, c return NT_STATUS_OK; } - ret = vfs->conn->vfs_ops.stat(vfs->conn, argv[1], &st); + ret = SMB_VFS_STAT(vfs->conn, argv[1], &st); if (ret == -1) { printf("stat: error=%d (%s)\n", errno, strerror(errno)); return NT_STATUS_UNSUCCESSFUL; } pwd = sys_getpwuid(st.st_uid); - if (pwd != NULL) user = strdup(pwd->pw_name); + if (pwd != NULL) user = pwd->pw_name; else user = null_string; grp = sys_getgrgid(st.st_gid); - if (grp != NULL) group = strdup(grp->gr_name); + if (grp != NULL) group = grp->gr_name; else group = null_string; printf("stat: ok\n"); @@ -541,17 +532,17 @@ static NTSTATUS cmd_stat(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, c printf(" Access: %s", ctime(&(st.st_atime))); printf(" Modify: %s", ctime(&(st.st_mtime))); printf(" Change: %s", ctime(&(st.st_ctime))); - if (user != null_string) SAFE_FREE(user); - if (group!= null_string) SAFE_FREE(group); + SAFE_FREE(pwd); + SAFE_FREE(grp); return NT_STATUS_OK; } -static NTSTATUS cmd_fstat(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv) +static NTSTATUS cmd_fstat(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv) { int fd; - char *user; - char *group; + const char *user; + const char *group; struct passwd *pwd; struct group *grp; SMB_STRUCT_STAT st; @@ -572,16 +563,16 @@ static NTSTATUS cmd_fstat(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, return NT_STATUS_OK; } - if (vfs->conn->vfs_ops.fstat(vfs->files[fd], fd, &st) == -1) { + if (SMB_VFS_FSTAT(vfs->files[fd], fd, &st) == -1) { printf("fstat: error=%d (%s)\n", errno, strerror(errno)); return NT_STATUS_UNSUCCESSFUL; } pwd = sys_getpwuid(st.st_uid); - if (pwd != NULL) user = strdup(pwd->pw_name); + if (pwd != NULL) user = pwd->pw_name; else user = null_string; grp = sys_getgrgid(st.st_gid); - if (grp != NULL) group = strdup(grp->gr_name); + if (grp != NULL) group = grp->gr_name; else group = null_string; printf("fstat: ok\n"); @@ -603,16 +594,16 @@ static NTSTATUS cmd_fstat(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, printf(" Access: %s", ctime(&(st.st_atime))); printf(" Modify: %s", ctime(&(st.st_mtime))); printf(" Change: %s", ctime(&(st.st_ctime))); - if (user != null_string) SAFE_FREE(user); - if (group!= null_string) SAFE_FREE(group); + SAFE_FREE(pwd); + SAFE_FREE(grp); return NT_STATUS_OK; } -static NTSTATUS cmd_lstat(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv) +static NTSTATUS cmd_lstat(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv) { - char *user; - char *group; + const char *user; + const char *group; struct passwd *pwd; struct group *grp; SMB_STRUCT_STAT st; @@ -622,16 +613,16 @@ static NTSTATUS cmd_lstat(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, return NT_STATUS_OK; } - if (vfs->conn->vfs_ops.lstat(vfs->conn, argv[1], &st) == -1) { + if (SMB_VFS_LSTAT(vfs->conn, argv[1], &st) == -1) { printf("lstat: error=%d (%s)\n", errno, strerror(errno)); return NT_STATUS_UNSUCCESSFUL; } pwd = sys_getpwuid(st.st_uid); - if (pwd != NULL) user = strdup(pwd->pw_name); + if (pwd != NULL) user = pwd->pw_name; else user = null_string; grp = sys_getgrgid(st.st_gid); - if (grp != NULL) group = strdup(grp->gr_name); + if (grp != NULL) group = grp->gr_name; else group = null_string; printf("lstat: ok\n"); @@ -653,13 +644,13 @@ static NTSTATUS cmd_lstat(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, printf(" Access: %s", ctime(&(st.st_atime))); printf(" Modify: %s", ctime(&(st.st_mtime))); printf(" Change: %s", ctime(&(st.st_ctime))); - if (user != null_string) SAFE_FREE(user); - if (group!= null_string) SAFE_FREE(group); + SAFE_FREE(pwd); + SAFE_FREE(grp); return NT_STATUS_OK; } -static NTSTATUS cmd_chmod(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv) +static NTSTATUS cmd_chmod(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv) { mode_t mode; if (argc != 3) { @@ -668,7 +659,7 @@ static NTSTATUS cmd_chmod(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, } mode = atoi(argv[2]); - if (vfs->conn->vfs_ops.chmod(vfs->conn, argv[1], mode) == -1) { + if (SMB_VFS_CHMOD(vfs->conn, argv[1], mode) == -1) { printf("chmod: error=%d (%s)\n", errno, strerror(errno)); return NT_STATUS_UNSUCCESSFUL; } @@ -678,7 +669,7 @@ static NTSTATUS cmd_chmod(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, } -static NTSTATUS cmd_fchmod(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv) +static NTSTATUS cmd_fchmod(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv) { int fd; mode_t mode; @@ -698,7 +689,7 @@ static NTSTATUS cmd_fchmod(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, return NT_STATUS_OK; } - if (vfs->conn->vfs_ops.fchmod(vfs->files[fd], fd, mode) == -1) { + if (SMB_VFS_FCHMOD(vfs->files[fd], fd, mode) == -1) { printf("fchmod: error=%d (%s)\n", errno, strerror(errno)); return NT_STATUS_UNSUCCESSFUL; } @@ -708,7 +699,7 @@ static NTSTATUS cmd_fchmod(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, } -static NTSTATUS cmd_chown(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv) +static NTSTATUS cmd_chown(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv) { uid_t uid; gid_t gid; @@ -719,7 +710,7 @@ static NTSTATUS cmd_chown(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, uid = atoi(argv[2]); gid = atoi(argv[3]); - if (vfs->conn->vfs_ops.chown(vfs->conn, argv[1], uid, gid) == -1) { + if (SMB_VFS_CHOWN(vfs->conn, argv[1], uid, gid) == -1) { printf("chown: error=%d (%s)\n", errno, strerror(errno)); return NT_STATUS_UNSUCCESSFUL; } @@ -729,7 +720,7 @@ static NTSTATUS cmd_chown(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, } -static NTSTATUS cmd_fchown(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv) +static NTSTATUS cmd_fchown(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv) { uid_t uid; gid_t gid; @@ -750,7 +741,7 @@ static NTSTATUS cmd_fchown(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, printf("fchown: error=%d (invalid file descriptor)\n", EBADF); return NT_STATUS_OK; } - if (vfs->conn->vfs_ops.fchown(vfs->files[fd], fd, uid, gid) == -1) { + if (SMB_VFS_FCHOWN(vfs->files[fd], fd, uid, gid) == -1) { printf("fchown error=%d (%s)\n", errno, strerror(errno)); return NT_STATUS_UNSUCCESSFUL; } @@ -760,10 +751,10 @@ static NTSTATUS cmd_fchown(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, } -static NTSTATUS cmd_getwd(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv) +static NTSTATUS cmd_getwd(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv) { char buf[PATH_MAX]; - if (vfs->conn->vfs_ops.getwd(vfs->conn, buf) == NULL) { + if (SMB_VFS_GETWD(vfs->conn, buf) == NULL) { printf("getwd: error=%d (%s)\n", errno, strerror(errno)); return NT_STATUS_UNSUCCESSFUL; } @@ -772,7 +763,7 @@ static NTSTATUS cmd_getwd(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, return NT_STATUS_OK; } -static NTSTATUS cmd_utime(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv) +static NTSTATUS cmd_utime(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv) { struct utimbuf times; if (argc != 4) { @@ -781,7 +772,7 @@ static NTSTATUS cmd_utime(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, } times.actime = atoi(argv[2]); times.modtime = atoi(argv[3]); - if (vfs->conn->vfs_ops.utime(vfs->conn, argv[1], ×) != 0) { + if (SMB_VFS_UTIME(vfs->conn, argv[1], ×) != 0) { printf("utime: error=%d (%s)\n", errno, strerror(errno)); return NT_STATUS_UNSUCCESSFUL; } @@ -790,7 +781,7 @@ static NTSTATUS cmd_utime(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, return NT_STATUS_OK; } -static NTSTATUS cmd_ftruncate(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv) +static NTSTATUS cmd_ftruncate(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv) { int fd; SMB_OFF_T off; @@ -810,7 +801,7 @@ static NTSTATUS cmd_ftruncate(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int ar return NT_STATUS_OK; } - if (vfs->conn->vfs_ops.ftruncate(vfs->files[fd], fd, off) == -1) { + if (SMB_VFS_FTRUNCATE(vfs->files[fd], fd, off) == -1) { printf("ftruncate: error=%d (%s)\n", errno, strerror(errno)); return NT_STATUS_UNSUCCESSFUL; } @@ -819,7 +810,7 @@ static NTSTATUS cmd_ftruncate(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int ar return NT_STATUS_OK; } -static NTSTATUS cmd_lock(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv) +static NTSTATUS cmd_lock(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv) { BOOL ret; int fd; @@ -827,7 +818,7 @@ static NTSTATUS cmd_lock(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, c long offset; long count; int type; - char *typestr; + const char *typestr; if (argc != 6) { printf("Usage: lock \n"); @@ -893,7 +884,7 @@ static NTSTATUS cmd_lock(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, c printf("lock: debug lock(fd=%d, op=%d, offset=%ld, count=%ld, type=%d))\n", fd, op, offset, count, type); - if ((ret = vfs->conn->vfs_ops.lock(vfs->files[fd], fd, op, offset, count, type)) == False) { + if ((ret = SMB_VFS_LOCK(vfs->files[fd], fd, op, offset, count, type)) == False) { printf("lock: error=%d (%s)\n", errno, strerror(errno)); return NT_STATUS_UNSUCCESSFUL; } @@ -902,14 +893,14 @@ static NTSTATUS cmd_lock(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, c return NT_STATUS_OK; } -static NTSTATUS cmd_symlink(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv) +static NTSTATUS cmd_symlink(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv) { if (argc != 3) { printf("Usage: symlink \n"); return NT_STATUS_OK; } - if (vfs->conn->vfs_ops.symlink(vfs->conn, argv[1], argv[2]) == -1) { + if (SMB_VFS_SYMLINK(vfs->conn, argv[1], argv[2]) == -1) { printf("symlink: error=%d (%s)\n", errno, strerror(errno)); return NT_STATUS_UNSUCCESSFUL; } @@ -919,7 +910,7 @@ static NTSTATUS cmd_symlink(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc } -static NTSTATUS cmd_readlink(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv) +static NTSTATUS cmd_readlink(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv) { char buffer[PATH_MAX]; int size; @@ -929,7 +920,7 @@ static NTSTATUS cmd_readlink(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int arg return NT_STATUS_OK; } - if ((size = vfs->conn->vfs_ops.readlink(vfs->conn, argv[1], buffer, PATH_MAX)) == -1) { + if ((size = SMB_VFS_READLINK(vfs->conn, argv[1], buffer, PATH_MAX)) == -1) { printf("readlink: error=%d (%s)\n", errno, strerror(errno)); return NT_STATUS_UNSUCCESSFUL; } @@ -940,14 +931,14 @@ static NTSTATUS cmd_readlink(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int arg } -static NTSTATUS cmd_link(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv) +static NTSTATUS cmd_link(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv) { if (argc != 3) { printf("Usage: link \n"); return NT_STATUS_OK; } - if (vfs->conn->vfs_ops.link(vfs->conn, argv[1], argv[2]) == -1) { + if (SMB_VFS_LINK(vfs->conn, argv[1], argv[2]) == -1) { printf("link: error=%d (%s)\n", errno, strerror(errno)); return NT_STATUS_UNSUCCESSFUL; } @@ -956,7 +947,7 @@ static NTSTATUS cmd_link(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, c return NT_STATUS_OK; } -static NTSTATUS cmd_mknod(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv) +static NTSTATUS cmd_mknod(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv) { mode_t mode; unsigned int dev_val; @@ -980,7 +971,7 @@ static NTSTATUS cmd_mknod(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, } dev = (SMB_DEV_T)dev_val; - if (vfs->conn->vfs_ops.mknod(vfs->conn, argv[1], mode, dev) == -1) { + if (SMB_VFS_MKNOD(vfs->conn, argv[1], mode, dev) == -1) { printf("mknod: error=%d (%s)\n", errno, strerror(errno)); return NT_STATUS_UNSUCCESSFUL; } @@ -989,7 +980,7 @@ static NTSTATUS cmd_mknod(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, return NT_STATUS_OK; } -static NTSTATUS cmd_realpath(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv) +static NTSTATUS cmd_realpath(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv) { char respath[PATH_MAX]; @@ -998,7 +989,7 @@ static NTSTATUS cmd_realpath(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int arg return NT_STATUS_OK; } - if (vfs->conn->vfs_ops.realpath(vfs->conn, argv[1], respath) == NULL) { + if (SMB_VFS_REALPATH(vfs->conn, argv[1], respath) == NULL) { printf("realpath: error=%d (%s)\n", errno, strerror(errno)); return NT_STATUS_UNSUCCESSFUL; } diff --git a/source3/torture/mangle_test.c b/source3/torture/mangle_test.c index e4ccfc1b83..660d4d17af 100644 --- a/source3/torture/mangle_test.c +++ b/source3/torture/mangle_test.c @@ -82,7 +82,7 @@ static BOOL test_one(struct cli_state *cli, const char *name) } /* see if the short name is already in the tdb */ - data = tdb_fetch_by_string(tdb, shortname); + data = tdb_fetch_bystring(tdb, shortname); if (data.dptr) { /* maybe its a duplicate long name? */ if (strcasecmp(name, data.dptr) != 0) { @@ -98,7 +98,7 @@ static BOOL test_one(struct cli_state *cli, const char *name) /* store it for later */ namedata.dptr = name; namedata.dsize = strlen(name)+1; - tdb_store_by_string(tdb, shortname, namedata, TDB_REPLACE); + tdb_store_bystring(tdb, shortname, namedata, TDB_REPLACE); } return True; diff --git a/source3/torture/masktest.c b/source3/torture/masktest.c index 06dead3f16..fa901e3d63 100644 --- a/source3/torture/masktest.c +++ b/source3/torture/masktest.c @@ -279,9 +279,9 @@ static void get_real_name(struct cli_state *cli, } if (f_info) { fstrcpy(short_name, f_info->short_name); - strlower(short_name); + strlower_m(short_name); pstrcpy(long_name, f_info->name); - strlower(long_name); + strlower_m(long_name); } if (*short_name == 0) { diff --git a/source3/torture/nsstest.c b/source3/torture/nsstest.c index a82fa05203..0a08cb6e8f 100644 --- a/source3/torture/nsstest.c +++ b/source3/torture/nsstest.c @@ -2,6 +2,7 @@ Unix SMB/CIFS implementation. nss tester for winbindd Copyright (C) Andrew Tridgell 2001 + Copyright (C) Tim Potter 2003 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -44,6 +45,7 @@ static void *find_fn(const char *name) res = sys_dlsym(h, s); if (!res) { printf("Can't find function %s\n", s); + total_errors++; return NULL; } return res; @@ -65,6 +67,9 @@ static struct passwd *nss_getpwent(void) static char buf[1000]; NSS_STATUS status; + if (!_nss_getpwent_r) + return NULL; + status = _nss_getpwent_r(&pwd, buf, sizeof(buf), &nss_errno); if (status == NSS_STATUS_NOTFOUND) { return NULL; @@ -83,6 +88,9 @@ static struct passwd *nss_getpwnam(const char *name) static struct passwd pwd; static char buf[1000]; NSS_STATUS status; + + if (!_nss_getpwnam_r) + return NULL; status = _nss_getpwnam_r(name, &pwd, buf, sizeof(buf), &nss_errno); if (status == NSS_STATUS_NOTFOUND) { @@ -102,6 +110,9 @@ static struct passwd *nss_getpwuid(uid_t uid) static struct passwd pwd; static char buf[1000]; NSS_STATUS status; + + if (!_nss_getpwuid_r) + return NULL; status = _nss_getpwuid_r(uid, &pwd, buf, sizeof(buf), &nss_errno); if (status == NSS_STATUS_NOTFOUND) { @@ -118,6 +129,10 @@ static void nss_setpwent(void) { NSS_STATUS (*_nss_setpwent)(void) = find_fn("setpwent"); NSS_STATUS status; + + if (!_nss_setpwent) + return; + status = _nss_setpwent(); if (status != NSS_STATUS_SUCCESS) { report_nss_error("setpwent", status); @@ -128,6 +143,10 @@ static void nss_endpwent(void) { NSS_STATUS (*_nss_endpwent)(void) = find_fn("endpwent"); NSS_STATUS status; + + if (!_nss_endpwent) + return; + status = _nss_endpwent(); if (status != NSS_STATUS_SUCCESS) { report_nss_error("endpwent", status); @@ -144,7 +163,11 @@ static struct group *nss_getgrent(void) static int buflen = 1024; NSS_STATUS status; - if (!buf) buf = malloc(buflen); + if (!_nss_getgrent_r) + return NULL; + + if (!buf) + buf = malloc(buflen); again: status = _nss_getgrent_r(&grp, buf, buflen, &nss_errno); @@ -172,7 +195,11 @@ static struct group *nss_getgrnam(const char *name) static int buflen = 1000; NSS_STATUS status; - if (!buf) buf = malloc(buflen); + if (!_nss_getgrnam_r) + return NULL; + + if (!buf) + buf = malloc(buflen); again: status = _nss_getgrnam_r(name, &grp, buf, buflen, &nss_errno); if (status == NSS_STATUS_TRYAGAIN) { @@ -199,7 +226,12 @@ static struct group *nss_getgrgid(gid_t gid) static int buflen = 1000; NSS_STATUS status; - if (!buf) buf = malloc(buflen); + if (!_nss_getgrgid_r) + return NULL; + + if (!buf) + buf = malloc(buflen); + again: status = _nss_getgrgid_r(gid, &grp, buf, buflen, &nss_errno); if (status == NSS_STATUS_TRYAGAIN) { @@ -221,6 +253,10 @@ static void nss_setgrent(void) { NSS_STATUS (*_nss_setgrent)(void) = find_fn("setgrent"); NSS_STATUS status; + + if (!_nss_setgrent) + return; + status = _nss_setgrent(); if (status != NSS_STATUS_SUCCESS) { report_nss_error("setgrent", status); @@ -231,6 +267,10 @@ static void nss_endgrent(void) { NSS_STATUS (*_nss_endgrent)(void) = find_fn("endgrent"); NSS_STATUS status; + + if (!_nss_endgrent) + return; + status = _nss_endgrent(); if (status != NSS_STATUS_SUCCESS) { report_nss_error("endgrent", status); @@ -244,7 +284,8 @@ static int nss_initgroups(char *user, gid_t group, gid_t **groups, long int *sta find_fn("initgroups_dyn"); NSS_STATUS status; - if (!_nss_initgroups) return NSS_STATUS_UNAVAIL; + if (!_nss_initgroups) + return NSS_STATUS_UNAVAIL; status = _nss_initgroups(user, group, start, size, groups, 0, &nss_errno); if (status != NSS_STATUS_SUCCESS) { diff --git a/source3/torture/rpctorture.c b/source3/torture/rpctorture.c index 086f8d5d33..8dfaebd64f 100644 --- a/source3/torture/rpctorture.c +++ b/source3/torture/rpctorture.c @@ -363,7 +363,7 @@ enum client_action case 'S': { pstrcpy(cli_info.dest_host,optarg); - strupper(cli_info.dest_host); + strupper_m(cli_info.dest_host); cli_action = CLIENT_IPC; break; } @@ -486,7 +486,7 @@ enum client_action exit(1); } - strupper(global_myname); + strupper_m(global_myname); fstrcpy(cli_info.myhostname, global_myname); DEBUG(3,("%s client started (version %s)\n",timestring(False),VERSION)); @@ -495,7 +495,7 @@ enum client_action { pstrcpy(smb_cli->domain,lp_workgroup()); } - strupper(smb_cli->domain); + strupper_m(smb_cli->domain); load_interfaces(); @@ -506,7 +506,7 @@ enum client_action } fstrcpy(cli_info.mach_acct, cli_info.myhostname); - strupper(cli_info.mach_acct); + strupper_m(cli_info.mach_acct); fstrcat(cli_info.mach_acct, "$"); /* set the password cache info */ diff --git a/source3/torture/smbiconv.c b/source3/torture/smbiconv.c index ce21a09025..3524136fb1 100644 --- a/source3/torture/smbiconv.c +++ b/source3/torture/smbiconv.c @@ -198,6 +198,10 @@ int main(int argc, char *argv[]) while(poptGetNextOpt(pc) != -1); + /* the following functions are part of the Samba debugging + facilities. See lib/debug.c */ + setup_logging("smbiconv", True); + if(preload)smb_load_modules(str_list_make(preload, NULL)); if(output) { @@ -209,10 +213,6 @@ int main(int argc, char *argv[]) } } - /* the following functions are part of the Samba debugging - facilities. See lib/debug.c */ - setup_logging("smbiconv", True); - cd = smb_iconv_open(to, from); if((int)cd == -1) { DEBUG(0,("unable to find from or to encoding, exiting...\n")); diff --git a/source3/torture/torture.c b/source3/torture/torture.c index 07d7f1547e..f26ebb49b3 100644 --- a/source3/torture/torture.c +++ b/source3/torture/torture.c @@ -866,7 +866,7 @@ static BOOL run_locktest1(int dummy) 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, lock_timeout * 1000, WRITE_LOCK)) { + if (cli_lock(cli2, fnum3, 0, 4, lock_timeout * 500, WRITE_LOCK)) { printf("lock3 succeeded! This is a locking bug\n"); return False; } else { @@ -875,9 +875,10 @@ static BOOL run_locktest1(int dummy) } t2 = time(NULL); - if (t2 - t1 < 5) { + if (ABS(t2 - t1) < lock_timeout-1) { 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); diff --git a/source3/torture/vfstest.c b/source3/torture/vfstest.c index 3b28a3c496..88fe348649 100644 --- a/source3/torture/vfstest.c +++ b/source3/torture/vfstest.c @@ -106,7 +106,7 @@ static char* next_command(char** cmdstr) /* Load specified configuration file */ static NTSTATUS cmd_conf(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, - int argc, char **argv) + int argc, const char **argv) { if (argc != 2) { printf("Usage: %s \n", argv[0]); @@ -181,7 +181,7 @@ static NTSTATUS cmd_help(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, } /* Change the debug level */ -static NTSTATUS cmd_debuglevel(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv) +static NTSTATUS cmd_debuglevel(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv) { if (argc > 2) { printf("Usage: %s [debuglevel]\n", argv[0]); @@ -197,7 +197,7 @@ static NTSTATUS cmd_debuglevel(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int a return NT_STATUS_OK; } -static NTSTATUS cmd_freemem(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv) +static NTSTATUS cmd_freemem(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv) { /* Cleanup */ talloc_destroy(mem_ctx); @@ -207,7 +207,7 @@ static NTSTATUS cmd_freemem(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc return NT_STATUS_OK; } -static NTSTATUS cmd_quit(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, char **argv) +static NTSTATUS cmd_quit(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, const char **argv) { /* Cleanup */ talloc_destroy(mem_ctx); @@ -261,7 +261,8 @@ static void add_command_set(struct cmd_set *cmd_set) static NTSTATUS do_cmd(struct vfs_state *vfs, struct cmd_set *cmd_entry, char *cmd) { - char *p = cmd, **argv = NULL; + const char *p = cmd; + char **argv = NULL; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; pstring buf; TALLOC_CTX *mem_ctx = NULL; @@ -311,7 +312,7 @@ static NTSTATUS do_cmd(struct vfs_state *vfs, struct cmd_set *cmd_entry, char *c } /* Run command */ - result = cmd_entry->fn(vfs, mem_ctx, argc, argv); + result = cmd_entry->fn(vfs, mem_ctx, argc, (const char **)argv); } else { fprintf (stderr, "Invalid command\n"); @@ -338,7 +339,7 @@ static NTSTATUS process_cmd(struct vfs_state *vfs, char *cmd) struct cmd_list *temp_list; BOOL found = False; pstring buf; - char *p = cmd; + const char *p = cmd; NTSTATUS result = NT_STATUS_OK; int len = 0; @@ -478,7 +479,7 @@ int main(int argc, char *argv[]) struct cmd_set **cmd_set; static struct vfs_state vfs; int i; - static const char *filename = NULL; + static char *filename = NULL; /* make sure the vars that get altered (4th field) are in a fixed location or certain compilers complain */ @@ -520,9 +521,10 @@ int main(int argc, char *argv[]) } /* some basic initialization stuff */ + sec_init(); conn_init(); vfs.conn = conn_new(); - vfs.conn->user = "vfstest"; + string_set(&vfs.conn->user,"vfstest"); for (i=0; i < 1024; i++) vfs.files[i] = NULL; diff --git a/source3/torture/vfstest.h b/source3/torture/vfstest.h index 5910c5ce37..1e030fad04 100644 --- a/source3/torture/vfstest.h +++ b/source3/torture/vfstest.h @@ -39,7 +39,7 @@ struct vfs_state { struct cmd_set { const char *name; NTSTATUS (*fn)(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, - char **argv); + const char **argv); const char *description; const char *usage; }; diff --git a/source3/utils/editreg.c b/source3/utils/editreg.c index 54148fdcf8..a0cfa2bb07 100644 --- a/source3/utils/editreg.c +++ b/source3/utils/editreg.c @@ -1099,7 +1099,7 @@ VAL_KEY *nt_add_reg_value(REG_KEY *key, char *name, int type, char *value) tmp = (VAL_KEY *)malloc(sizeof(VAL_KEY)); if (!tmp) goto error; - bzero(tmp, sizeof(VAL_KEY)); + memset(tmp, 0, sizeof(VAL_KEY)); tmp->name = strdup(name); tmp->has_name = True; if (!tmp->name) goto error; @@ -1181,7 +1181,7 @@ int sid_string_to_sid(sid_t **sid, const char *sid_str) *sid = (sid_t *)malloc(sizeof(sid_t)); if (!*sid) return 0; - bzero(*sid, sizeof(sid_t)); + memset(*sid, 0, sizeof(sid_t)); if (strncmp(sid_str, "S-1-5", 5)) { fprintf(stderr, "Does not conform to S-1-5...: %s\n", sid_str); @@ -1402,7 +1402,7 @@ REG_KEY *nt_add_reg_key_list(REGF *regf, REG_KEY *key, char * name, int create) tmp = (REG_KEY *)malloc(sizeof(REG_KEY)); - bzero(tmp, sizeof(REG_KEY)); + memset(tmp, 0, sizeof(REG_KEY)); tmp->name = strdup(c1); if (!tmp->name) goto error; @@ -1466,7 +1466,7 @@ REG_KEY *nt_add_reg_key(REGF *regf, char *name, int create) tmp = (REG_KEY *)malloc(sizeof(REG_KEY)); if (!tmp) goto error; - bzero(tmp, sizeof(REG_KEY)); + memset(tmp, 0, sizeof(REG_KEY)); tmp->name = strdup(c1); if (!tmp->name) goto error; tmp->security = nt_create_init_sec(regf); @@ -1654,7 +1654,7 @@ REGF *nt_create_regf(void) { REGF *tmp = (REGF *)malloc(sizeof(REGF)); if (!tmp) return tmp; - bzero(tmp, sizeof(REGF)); + memset(tmp, 0, sizeof(REGF)); tmp->owner_sid_str = def_owner_sid_str; return tmp; } @@ -1815,7 +1815,7 @@ KEY_SEC_DESC *lookup_create_sec_key(REGF *regf, SK_MAP *sk_map, int sk_off) if (!tmp) { return NULL; } - bzero(tmp, sizeof(KEY_SEC_DESC)); /* Neatly sets offset to 0 */ + memset(tmp, 0, sizeof(KEY_SEC_DESC)); /* Neatly sets offset to 0 */ tmp->state = SEC_DESC_RES; if (!alloc_sk_map_entry(regf, tmp, sk_off)) { return NULL; @@ -1991,7 +1991,7 @@ KEY_SEC_DESC *process_sk(REGF *regf, SK_HDR *sk_hdr, int sk_off, int size) if (!tmp) { tmp = (KEY_SEC_DESC *)malloc(sizeof(KEY_SEC_DESC)); if (!tmp) return NULL; - bzero(tmp, sizeof(KEY_SEC_DESC)); + memset(tmp, 0, sizeof(KEY_SEC_DESC)); /* * Allocate an entry in the SK_MAP ... @@ -2059,7 +2059,7 @@ VAL_KEY *process_vk(REGF *regf, VK_HDR *vk_hdr, int size) if (!tmp) { goto error; } - bzero(tmp, sizeof(VAL_KEY)); + memset(tmp, 0, sizeof(VAL_KEY)); tmp->has_name = flag; tmp->data_type = dat_type; @@ -2268,7 +2268,7 @@ REG_KEY *nt_get_key_tree(REGF *regf, NK_HDR *nk_hdr, int size, REG_KEY *parent) /* Allocate the key struct now */ tmp = (REG_KEY *)malloc(sizeof(REG_KEY)); if (!tmp) return tmp; - bzero(tmp, sizeof(REG_KEY)); + memset(tmp, 0, sizeof(REG_KEY)); tmp->type = (SVAL(&nk_hdr->type)==0x2C?REG_ROOT_KEY:REG_SUB_KEY); @@ -2295,7 +2295,7 @@ REG_KEY *nt_get_key_tree(REGF *regf, NK_HDR *nk_hdr, int size, REG_KEY *parent) clsnamep = LOCN(regf->base, clsnam_off); if (verbose) fprintf(stdout, "Class Name Offset: %0X\n", clsnam_off); - bzero(cls_name, clsname_len); + memset(cls_name, 0, clsname_len); uni_to_ascii(clsnamep, cls_name, sizeof(cls_name), clsname_len); /* @@ -2494,12 +2494,12 @@ HBIN_BLK *nt_create_hbin_blk(REGF *regf, int size) size = (size + (REGF_HDR_BLKSIZ - 1)) & ~(REGF_HDR_BLKSIZ - 1); tmp = (HBIN_BLK *)malloc(sizeof(HBIN_BLK)); - bzero(tmp, sizeof(HBIN_BLK)); + memset(tmp, 0, sizeof(HBIN_BLK)); tmp->data = malloc(size); if (!tmp->data) goto error; - bzero(tmp->data, size); /* Make it pristine */ + memset(tmp->data, 0, size); /* Make it pristine */ tmp->size = size; tmp->file_offset = regf->blk_tail->file_offset + regf->blk_tail->size; @@ -2986,13 +2986,13 @@ REGF_HDR *nt_get_reg_header(REGF *regf) tmp = (HBIN_BLK *)malloc(sizeof(HBIN_BLK)); if (!tmp) return 0; - bzero(tmp, sizeof(HBIN_BLK)); + memset(tmp, 0, sizeof(HBIN_BLK)); tmp->type = REG_OUTBLK_HDR; tmp->size = REGF_HDR_BLKSIZ; tmp->data = malloc(REGF_HDR_BLKSIZ); if (!tmp->data) goto error; - bzero(tmp->data, REGF_HDR_BLKSIZ); /* Make it pristine, unlike Windows */ + memset(tmp->data, 0, REGF_HDR_BLKSIZ); /* Make it pristine, unlike Windows */ regf->blk_head = regf->blk_tail = tmp; return (REGF_HDR *)tmp->data; @@ -3921,7 +3921,7 @@ int print_val(const char *path, char *val_name, int val_type, int data_len, { char data_asc[1024]; - bzero(data_asc, sizeof(data_asc)); + memset(data_asc, 0, sizeof(data_asc)); if (!terminal && first) fprintf(stdout, "%s\n", path); data_to_ascii((unsigned char *)data_blk, data_len, val_type, data_asc, diff --git a/source3/utils/net.c b/source3/utils/net.c index aa245a920a..e643a3d10d 100644 --- a/source3/utils/net.c +++ b/source3/utils/net.c @@ -77,6 +77,21 @@ static int opt_machine_pass = 0; BOOL opt_have_ip = False; struct in_addr opt_dest_ip; +/***************************************************************************** + stubb functions +****************************************************************************/ + +void become_root( void ) +{ + return; +} + +void unbecome_root( void ) +{ + return; +} + + uint32 get_sec_channel_type(const char *param) { if (!(param && *param)) { @@ -206,7 +221,7 @@ BOOL net_find_server(unsigned flags, struct in_addr *server_ip, char **server_na if (is_zero_ip(pdc_ip)) return False; - if (!lookup_dc_name(global_myname(), opt_target_workgroup, &pdc_ip, dc_name)) + if ( !name_status_find(opt_target_workgroup, 0x1b, 0x20, pdc_ip, dc_name) ) return False; *server_name = strdup(dc_name); @@ -248,20 +263,18 @@ BOOL net_find_server(unsigned flags, struct in_addr *server_ip, char **server_na } -BOOL net_find_dc(struct in_addr *server_ip, fstring server_name, const char *domain_name) +BOOL net_find_pdc(struct in_addr *server_ip, fstring server_name, const char *domain_name) { if (get_pdc_ip(domain_name, server_ip)) { - fstring dc_name; - if (is_zero_ip(*server_ip)) return False; - if (!lookup_dc_name(global_myname(), domain_name, server_ip, dc_name)) + if (!name_status_find(domain_name, 0x1b, 0x20, *server_ip, server_name)) return False; - fstrcpy(server_name, dc_name); - return True; - } else + return True; + } + else return False; } @@ -348,26 +361,6 @@ static int net_file(int argc, const char **argv) return net_rap_file(argc, argv); } -/*********************************************************** - migrated functionality from smbgroupedit - **********************************************************/ -static int net_groupmap(int argc, const char **argv) -{ - if ( 0 == argc ) - return net_help_groupmap( argc, argv ); - - if ( !StrCaseCmp( argv[0], "add" ) ) - return net_groupmap_add(argc-1, argv+1); - else if ( !StrCaseCmp( argv[0], "modify" ) ) - return net_groupmap_modify(argc-1, argv+1); - else if ( !StrCaseCmp( argv[0], "delete" ) ) - return net_groupmap_delete(argc-1, argv+1); - else if ( !StrCaseCmp( argv[0], "list" ) ) - return net_groupmap_list(argc-1, argv+1); - - return net_help_groupmap( argc, argv ); -} - /* Retrieve our local SID or the SID for the specified name */ @@ -471,7 +464,7 @@ static uint32 get_maxrid(void) pdb_free_sam(&pwd); if (!pdb_enum_group_mapping(SID_NAME_UNKNOWN, &map, &num_entries, - ENUM_ONLY_MAPPED, MAPPING_WITHOUT_PRIV)) + ENUM_ONLY_MAPPED)) return max_rid; for (i = 0; i < num_entries; i++) { @@ -544,6 +537,7 @@ static struct functable net_func[] = { {"SETLOCALSID", net_setlocalsid}, {"GETDOMAINSID", net_getdomainsid}, {"MAXRID", net_maxrid}, + {"IDMAP", net_idmap}, {"HELP", net_help}, {NULL, NULL} @@ -655,6 +649,10 @@ static struct functable net_func[] = { exit(1); load_interfaces(); + + /* this makes sure that when we do things like call scripts, + that it won't assert becouse we are not root */ + sec_init(); if (opt_machine_pass) { char *user = NULL; diff --git a/source3/utils/net_ads.c b/source3/utils/net_ads.c index 203d849786..69d282420d 100644 --- a/source3/utils/net_ads.c +++ b/source3/utils/net_ads.c @@ -109,6 +109,9 @@ static int net_ads_info(int argc, const char **argv) d_printf("LDAP port: %d\n", ads->ldap_port); d_printf("Server time: %s\n", http_timestring(ads->config.current_time)); + d_printf("KDC server: %s\n", ads->auth.kdc_server ); + d_printf("Server time offset: %d\n", ads->auth.time_offset ); + return 0; } @@ -124,7 +127,7 @@ static ADS_STRUCT *ads_startup(void) ADS_STATUS status; BOOL need_password = False; BOOL second_time = False; - char *realm; + char *cp; ads = ads_init(NULL, NULL, opt_host); @@ -146,22 +149,24 @@ retry: if (opt_password) { use_in_memory_ccache(); - ads->auth.password = strdup(opt_password); + ads->auth.password = smb_xstrdup(opt_password); } - ads->auth.user_name = strdup(opt_user_name); + ads->auth.user_name = smb_xstrdup(opt_user_name); - /* - * If the username is of the form "name@realm", - * extract the realm and convert to upper case. - */ - if ((realm = strchr(ads->auth.user_name, '@'))) { - *realm++ = '\0'; - ads->auth.realm = strdup(realm); - strupper(ads->auth.realm); - } + /* + * If the username is of the form "name@realm", + * extract the realm and convert to upper case. + * This is only used to establish the connection. + */ + if ((cp = strchr(ads->auth.user_name, '@'))!=0) { + *cp++ = '\0'; + ads->auth.realm = smb_xstrdup(cp); + strupper_m(ads->auth.realm); + } status = ads_connect(ads); + if (!ADS_ERR_OK(status)) { if (!need_password && !second_time) { need_password = True; @@ -230,7 +235,7 @@ static BOOL usergrp_display(char *field, void **values, void *data_area) if (!field) { /* must be end of record */ if (!strchr_m(disp_fields[0], '$')) { if (disp_fields[1]) - d_printf("%-21.21s %-50.50s\n", + d_printf("%-21.21s %s\n", disp_fields[0], disp_fields[1]); else d_printf("%s\n", disp_fields[0]); @@ -295,7 +300,8 @@ 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], ads->auth.time_offset); + status = ads_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]); @@ -720,6 +726,8 @@ int net_ads_join(int argc, const char **argv) int net_ads_printer_usage(int argc, const char **argv) { d_printf( +"\nnet ads printer search " +"\n\tsearch for a printer in the directory" "\nnet ads printer info " "\n\tlookup info in directory for printer on server" "\n\t(note: printer defaults to \"*\", server defaults to local)\n" @@ -732,6 +740,35 @@ int net_ads_printer_usage(int argc, const char **argv) return -1; } +static int net_ads_printer_search(int argc, const char **argv) +{ + ADS_STRUCT *ads; + ADS_STATUS rc; + void *res = NULL; + + if (!(ads = ads_startup())) + return -1; + + rc = ads_find_printers(ads, &res); + + if (!ADS_ERR_OK(rc)) { + d_printf("ads_find_printer: %s\n", ads_errstr(rc)); + ads_msgfree(ads, res); + return -1; + } + + if (ads_count_replies(ads, res) == 0) { + d_printf("No results found\n"); + ads_msgfree(ads, res); + return -1; + } + + ads_dump(ads, res); + ads_msgfree(ads, res); + + return 0; +} + static int net_ads_printer_info(int argc, const char **argv) { ADS_STRUCT *ads; @@ -780,7 +817,7 @@ static int net_ads_printer_publish(int argc, const char **argv) { ADS_STRUCT *ads; ADS_STATUS rc; - const char *servername; + const char *servername, *printername; struct cli_state *cli; struct in_addr server_ip; NTSTATUS nt_status; @@ -794,15 +831,14 @@ static int net_ads_printer_publish(int argc, const char **argv) if (argc < 1) return net_ads_printer_usage(argc, argv); + printername = argv[0]; + if (argc == 2) servername = argv[1]; else servername = global_myname(); - ads_find_machine_acct(ads, &res, servername); - srv_dn = ldap_get_dn(ads->ld, res); - srv_cn = ldap_explode_dn(srv_dn, 1); - asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn[0], argv[0], srv_dn); + /* Get printer data from SPOOLSS */ resolve_name(servername, &server_ip, 0x20); @@ -814,8 +850,29 @@ static int net_ads_printer_publish(int argc, const char **argv) CLI_FULL_CONNECTION_USE_KERBEROS, NULL); + if (NT_STATUS_IS_ERR(nt_status)) { + d_printf("Unable to open a connnection to %s to obtain data " + "for %s\n", servername, printername); + return -1; + } + + /* Publish on AD server */ + + ads_find_machine_acct(ads, &res, servername); + + if (ads_count_replies(ads, res) == 0) { + d_printf("Could not find machine account for server %s\n", + servername); + return -1; + } + + srv_dn = ldap_get_dn(ads->ld, res); + srv_cn = ldap_explode_dn(srv_dn, 1); + + asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn[0], printername, srv_dn); + cli_nt_session_open(cli, PI_SPOOLSS); - get_remote_printer_publishing_data(cli, mem_ctx, &mods, argv[0]); + get_remote_printer_publishing_data(cli, mem_ctx, &mods, printername); rc = ads_add_printer_entry(ads, prt_dn, mem_ctx, &mods); if (!ADS_ERR_OK(rc)) { @@ -876,6 +933,7 @@ static int net_ads_printer_remove(int argc, const char **argv) static int net_ads_printer(int argc, const char **argv) { struct functable func[] = { + {"SEARCH", net_ads_printer_search}, {"INFO", net_ads_printer_info}, {"PUBLISH", net_ads_printer_publish}, {"REMOVE", net_ads_printer_remove}, @@ -893,20 +951,34 @@ static int net_ads_password(int argc, const char **argv) const char *auth_password = opt_password; char *realm = NULL; char *new_password = NULL; - char *c; - char *prompt; + char *c, *prompt; + const char *user; ADS_STATUS ret; + if (opt_user_name == NULL || opt_password == NULL) { + d_printf("You must supply an administrator username/password\n"); + return -1; + } + - if ((argc != 1) || (opt_user_name == NULL) || - (opt_password == NULL) || (strchr(opt_user_name, '@') == NULL) || - (strchr(argv[0], '@') == NULL)) { - return net_ads_usage(argc, argv); + if (argc != 1) { + d_printf("ERROR: You must say which username to change password for\n"); + return -1; + } + + user = argv[0]; + if (!strchr(user, '@')) { + asprintf(&c, "%s@%s", argv[0], lp_realm()); + user = c; } use_in_memory_ccache(); c = strchr(auth_principal, '@'); - realm = ++c; + if (c) { + realm = ++c; + } else { + realm = lp_realm(); + } /* use the realm so we can eventually change passwords for users in realms other than default */ @@ -921,12 +993,12 @@ static int net_ads_password(int argc, const char **argv) return -1; } - asprintf(&prompt, "Enter new password for %s:", argv[0]); + asprintf(&prompt, "Enter new password for %s:", user); new_password = getpass(prompt); ret = kerberos_set_password(ads->auth.kdc_server, auth_principal, - auth_password, argv[0], new_password, ads->auth.time_offset); + auth_password, user, new_password, ads->auth.time_offset); if (!ADS_ERR_OK(ret)) { d_printf("Password change failed :-( ...\n"); ads_destroy(&ads); @@ -934,7 +1006,7 @@ static int net_ads_password(int argc, const char **argv) return -1; } - d_printf("Password change for %s completed.\n", argv[0]); + d_printf("Password change for %s completed.\n", user); ads_destroy(&ads); free(prompt); @@ -967,7 +1039,7 @@ int net_ads_changetrustpw(int argc, const char **argv) } hostname = strdup(global_myname()); - strlower(hostname); + strlower_m(hostname); asprintf(&host_principal, "%s@%s", hostname, ads->config.realm); SAFE_FREE(hostname); d_printf("Changing password for principal: HOST/%s\n", host_principal); @@ -1012,7 +1084,7 @@ static int net_ads_search(int argc, const char **argv) { ADS_STRUCT *ads; ADS_STATUS rc; - const char *exp; + const char *ldap_exp; const char **attrs; void *res = NULL; @@ -1024,12 +1096,12 @@ static int net_ads_search(int argc, const char **argv) return -1; } - exp = argv[0]; + ldap_exp = argv[0]; attrs = (argv + 1); rc = ads_do_search_all(ads, ads->config.bind_path, LDAP_SCOPE_SUBTREE, - exp, attrs, &res); + ldap_exp, attrs, &res); if (!ADS_ERR_OK(rc)) { d_printf("search failed: %s\n", ads_errstr(rc)); return -1; diff --git a/source3/utils/net_ads_cldap.c b/source3/utils/net_ads_cldap.c index 86d5abea4b..e74e4b5a4c 100644 --- a/source3/utils/net_ads_cldap.c +++ b/source3/utils/net_ads_cldap.c @@ -24,28 +24,28 @@ #ifdef HAVE_ADS -struct netlogon_string { - uint32 comp_len; - char **component; - uint8 extra_flag; -}; +#define MAX_DNS_LABEL 255 + 1 struct cldap_netlogon_reply { uint32 type; uint32 flags; GUID guid; - struct netlogon_string forest; - struct netlogon_string domain; - struct netlogon_string hostname; - - struct netlogon_string netbios_domain; - struct netlogon_string netbios_hostname; + char forest[MAX_DNS_LABEL]; + char unk0[MAX_DNS_LABEL]; + char domain[MAX_DNS_LABEL]; + char hostname[MAX_DNS_LABEL]; - struct netlogon_string user_name; - struct netlogon_string site_name; + char netbios_domain[MAX_DNS_LABEL]; + char unk1[MAX_DNS_LABEL]; + char netbios_hostname[MAX_DNS_LABEL]; - struct netlogon_string unk0; + char unk2[MAX_DNS_LABEL]; + char user_name[MAX_DNS_LABEL]; + char unk3[MAX_DNS_LABEL]; + char site_name[MAX_DNS_LABEL]; + char unk4[MAX_DNS_LABEL]; + char site_name_2[MAX_DNS_LABEL]; uint32 version; uint16 lmnt_token; @@ -53,38 +53,69 @@ struct cldap_netlogon_reply { }; /* - These strings are rather interesting... They are composed of a series of - length encoded strings, terminated by either 1) a zero length string or 2) - a 0xc0 byte with what appears to be a one byte flags immediately following. + These seem to be strings as described in RFC1035 4.1.4 and can be: + + - a sequence of labels ending in a zero octet + - a pointer + - a sequence of labels ending with a pointer + + A label is a byte where the first two bits must be zero and the remaining + bits represent the length of the label followed by the label itself. + Therefore, the length of a label is at max 64 bytes. Under RFC1035, a + sequence of labels cannot exceed 255 bytes. + + A pointer consists of a 14 bit offset from the beginning of the data. + + struct ptr { + unsigned ident:2; // must be 11 + unsigned offset:14; // from the beginning of data + }; + + This is used as a method to compress the packet by eliminated duplicate + domain components. Since a UDP packet should probably be < 512 bytes and a + DNS name can be up to 255 bytes, this actually makes a lot of sense. */ -static unsigned pull_netlogon_string(struct netlogon_string *ret,const char *d) +static unsigned pull_netlogon_string(char *ret, const char *ptr, + const char *data) { - const char *p = (const char *)d; - - ZERO_STRUCTP(ret); + char *pret = ret; + int followed_ptr = 0; + unsigned ret_len = 0; + memset(pret, 0, MAX_DNS_LABEL); do { - unsigned len = (unsigned char)*p; - p++; - - if (len > 0 && len != 0xc0) { - ret->component = realloc(ret->component, - ++ret->comp_len * - sizeof(char *)); - - ret->component[ret->comp_len - 1] = - smb_xstrndup(p, len); - p += len; - } else { - if (len == 0xc0) { - ret->extra_flag = *p; - p++; - }; - break; + if ((*ptr & 0xc0) == 0xc0) { + uint16 len; + + if (!followed_ptr) { + ret_len += 2; + followed_ptr = 1; + } + len = ((ptr[0] & 0x3f) << 8) | ptr[1]; + ptr = data + len; + } else if (*ptr) { + uint8 len = (uint8)*(ptr++); + + if ((pret - ret + len + 1) >= MAX_DNS_LABEL) { + d_printf("DC returning too long DNS name\n"); + return 0; + } + + if (pret != ret) { + *pret = '.'; + pret++; + } + memcpy(pret, ptr, len); + pret += len; + ptr += len; + + if (!followed_ptr) { + ret_len += (len + 1); + } } - } while (1); + } while (*ptr); - return (p - d); + return ret_len ? ret_len : 1; } /* @@ -95,7 +126,11 @@ static int send_cldap_netlogon(int sock, const char *domain, { ASN1_DATA data; char ntver[4]; +#ifdef CLDAP_USER_QUERY + char aac[4]; + SIVAL(aac, 0, 0x00000180); +#endif SIVAL(ntver, 0, ntversion); memset(&data, 0, sizeof(data)); @@ -121,6 +156,18 @@ static int send_cldap_netlogon(int sock, const char *domain, asn1_write_OctetString(&data, hostname, strlen(hostname)); asn1_pop_tag(&data); +#ifdef CLDAP_USER_QUERY + asn1_push_tag(&data, ASN1_CONTEXT(3)); + asn1_write_OctetString(&data, "User", 4); + asn1_write_OctetString(&data, "SAMBA$", 6); + asn1_pop_tag(&data); + + asn1_push_tag(&data, ASN1_CONTEXT(3)); + asn1_write_OctetString(&data, "AAC", 4); + asn1_write_OctetString(&data, aac, 4); + asn1_pop_tag(&data); +#endif + asn1_push_tag(&data, ASN1_CONTEXT(3)); asn1_write_OctetString(&data, "NtVer", 5); asn1_write_OctetString(&data, ntver, 4); @@ -144,7 +191,6 @@ static int send_cldap_netlogon(int sock, const char *domain, d_printf("failed to send cldap query (%s)\n", strerror(errno)); } - file_save("cldap_query.dat", data.data, data.length); asn1_free(&data); return 0; @@ -173,8 +219,6 @@ static int recv_cldap_netlogon(int sock, struct cldap_netlogon_reply *reply) } blob.length = ret; - file_save("cldap_reply.dat", blob.data, blob.length); - asn1_load(&data, blob); asn1_start_tag(&data, ASN1_SEQUENCE(0)); asn1_read_Integer(&data, &i1); @@ -196,8 +240,6 @@ static int recv_cldap_netlogon(int sock, struct cldap_netlogon_reply *reply) return -1; } - file_save("cldap_reply_core.dat", os3.data, os3.length); - p = os3.data; reply->type = IVAL(p, 0); p += 4; @@ -206,15 +248,25 @@ static int recv_cldap_netlogon(int sock, struct cldap_netlogon_reply *reply) memcpy(&reply->guid.info, p, GUID_SIZE); p += GUID_SIZE; - p += pull_netlogon_string(&reply->forest, p); - p += pull_netlogon_string(&reply->domain, p); - p += pull_netlogon_string(&reply->hostname, p); - p += pull_netlogon_string(&reply->netbios_domain, p); - p += pull_netlogon_string(&reply->netbios_hostname, p); - p += pull_netlogon_string(&reply->user_name, p); - p += pull_netlogon_string(&reply->site_name, p); + p += pull_netlogon_string(reply->forest, p, os3.data); + p += pull_netlogon_string(reply->unk0, p, os3.data); + p += pull_netlogon_string(reply->domain, p, os3.data); + p += pull_netlogon_string(reply->hostname, p, os3.data); + p += pull_netlogon_string(reply->netbios_domain, p, os3.data); + p += pull_netlogon_string(reply->unk1, p, os3.data); + p += pull_netlogon_string(reply->netbios_hostname, p, os3.data); + p += pull_netlogon_string(reply->unk2, p, os3.data); + + if (reply->type == SAMLOGON_AD_R) { + p += pull_netlogon_string(reply->user_name, p, os3.data); + } else { + *reply->user_name = 0; + } - p += pull_netlogon_string(&reply->unk0, p); + p += pull_netlogon_string(reply->unk3, p, os3.data); + p += pull_netlogon_string(reply->site_name, p, os3.data); + p += pull_netlogon_string(reply->unk4, p, os3.data); + p += pull_netlogon_string(reply->site_name_2, p, os3.data); reply->version = IVAL(p, 0); reply->lmnt_token = SVAL(p, 4); @@ -228,52 +280,6 @@ static int recv_cldap_netlogon(int sock, struct cldap_netlogon_reply *reply) return 0; } -/* - free a netlogon string -*/ -static void netlogon_string_free(struct netlogon_string *str) -{ - unsigned int i; - - for (i = 0; i < str->comp_len; ++i) { - SAFE_FREE(str->component[i]); - } - SAFE_FREE(str->component); -} - -/* - free a cldap reply packet -*/ -static void cldap_reply_free(struct cldap_netlogon_reply *reply) -{ - netlogon_string_free(&reply->forest); - netlogon_string_free(&reply->domain); - netlogon_string_free(&reply->hostname); - netlogon_string_free(&reply->netbios_domain); - netlogon_string_free(&reply->netbios_hostname); - netlogon_string_free(&reply->user_name); - netlogon_string_free(&reply->site_name); - netlogon_string_free(&reply->unk0); -} - -static void d_print_netlogon_string(const char *label, - struct netlogon_string *str) -{ - unsigned int i; - - if (str->comp_len) { - d_printf("%s", label); - if (str->extra_flag) { - d_printf("[%d]", str->extra_flag); - } - d_printf(": "); - for (i = 0; i < str->comp_len; ++i) { - d_printf("%s%s", (i ? "." : ""), str->component[i]); - } - d_printf("\n"); - } -} - /* do a cldap netlogon query */ @@ -289,6 +295,7 @@ int ads_cldap_netlogon(ADS_STRUCT *ads) inet_ntoa(ads->ldap_ip), ads->ldap_port); return -1; + } ret = send_cldap_netlogon(sock, ads->config.realm, global_myname(), 6); @@ -305,7 +312,18 @@ int ads_cldap_netlogon(ADS_STRUCT *ads) d_printf("Information for Domain Controller: %s\n\n", ads->config.ldap_server_name); - d_printf("Response Type: 0x%x\n", reply.type); + d_printf("Response Type: "); + switch (reply.type) { + case SAMLOGON_AD_UNK_R: + d_printf("SAMLOGON\n"); + break; + case SAMLOGON_AD_R: + d_printf("SAMLOGON_USER\n"); + break; + default: + d_printf("0x%x\n", reply.type); + break; + } d_printf("GUID: "); print_guid(&reply.guid); d_printf("Flags:\n" @@ -330,23 +348,27 @@ int ads_cldap_netlogon(ADS_STRUCT *ads) (reply.flags & ADS_GOOD_TIMESERV) ? "yes" : "no", (reply.flags & ADS_NDNC) ? "yes" : "no"); - d_print_netlogon_string("Forest", &reply.forest); - d_print_netlogon_string("Domain", &reply.domain); - d_print_netlogon_string("Hostname", &reply.hostname); + printf("Forest:\t\t\t%s\n", reply.forest); + if (*reply.unk0) printf("Unk0:\t\t\t%s\n", reply.unk0); + printf("Domain:\t\t\t%s\n", reply.domain); + printf("Domain Controller:\t%s\n", reply.hostname); - d_print_netlogon_string("Pre-Win2k Domain", &reply.netbios_domain); - d_print_netlogon_string("Pre-Win2k Hostname", &reply.netbios_hostname); + printf("Pre-Win2k Domain:\t%s\n", reply.netbios_domain); + if (*reply.unk1) printf("Unk1:\t\t\t%s\n", reply.unk1); + printf("Pre-Win2k Hostname:\t%s\n", reply.netbios_hostname); - d_print_netlogon_string("User name", &reply.user_name); - d_print_netlogon_string("Site Name", &reply.site_name); - d_print_netlogon_string("Unknown Field", &reply.unk0); + if (*reply.unk2) printf("Unk2:\t\t\t%s\n", reply.unk2); + if (*reply.user_name) printf("User name:\t%s\n", reply.user_name); + + if (*reply.unk3) printf("Unk3:\t\t\t%s\n", reply.unk3); + printf("Site Name:\t\t%s\n", reply.site_name); + if (*reply.unk4) printf("Unk4:\t\t\t%s\n", reply.unk4); + printf("Site Name (2):\t\t%s\n", reply.site_name_2); d_printf("NT Version: %d\n", reply.version); d_printf("LMNT Token: %.2x\n", reply.lmnt_token); d_printf("LM20 Token: %.2x\n", reply.lm20_token); - cldap_reply_free(&reply); - return ret; } diff --git a/source3/utils/net_cache.c b/source3/utils/net_cache.c index 93c4f1aa1d..8dd9db599d 100644 --- a/source3/utils/net_cache.c +++ b/source3/utils/net_cache.c @@ -64,7 +64,7 @@ static void delete_cache_entry(const char* keystr, const char* datastr, const time_t timeout, void* dptr) { if (!gencache_del(keystr)) - d_printf("Couldn't delete entry! key = %s", keystr); + d_printf("Couldn't delete entry! key = %s\n", keystr); } diff --git a/source3/utils/net_groupmap.c b/source3/utils/net_groupmap.c index 905fdf6287..8831839e4e 100644 --- a/source3/utils/net_groupmap.c +++ b/source3/utils/net_groupmap.c @@ -65,7 +65,7 @@ static BOOL get_sid_from_input(DOM_SID *sid, char *input) if (StrnCaseCmp( input, "S-", 2)) { /* Perhaps its the NT group name? */ - if (!pdb_getgrnam(&map, input, MAPPING_WITHOUT_PRIV)) { + if (!pdb_getgrnam(&map, input)) { printf("NT Group %s doesn't exist in mapping DB\n", input); return False; } else { @@ -88,11 +88,9 @@ static void print_map_entry ( GROUP_MAP map, BOOL long_list ) { fstring string_sid; fstring group_type; - fstring priv_text; decode_sid_name_use(group_type, map.sid_name_use); sid_to_string(string_sid, &map.sid); - convert_priv_to_text(&(map.priv_set), priv_text); if (!long_list) d_printf("%s (%s) -> %s\n", map.nt_name, string_sid, gidtoname(map.gid)); @@ -102,14 +100,13 @@ static void print_map_entry ( GROUP_MAP map, BOOL long_list ) d_printf("\tUnix group: %s\n", gidtoname(map.gid)); d_printf("\tGroup type: %s\n", group_type); d_printf("\tComment : %s\n", map.comment); - d_printf("\tPrivilege : %s\n\n", priv_text); } } /********************************************************* List the groups. **********************************************************/ -int net_groupmap_list(int argc, const char **argv) +static int net_groupmap_list(int argc, const char **argv) { int entries; BOOL long_list = False; @@ -155,24 +152,24 @@ int net_groupmap_list(int argc, const char **argv) } /* Get the current mapping from the database */ - if(!pdb_getgrsid(&map, sid, MAPPING_WITH_PRIV)) { + if(!pdb_getgrsid(&map, sid)) { d_printf("Failure to local group SID in the database\n"); return -1; } print_map_entry( map, long_list ); - free_privilege(&(map.priv_set)); } else { GROUP_MAP *map=NULL; /* enumerate all group mappings */ - if ( !pdb_enum_group_mapping(SID_NAME_UNKNOWN, &map, &entries, ENUM_ALL_MAPPED, MAPPING_WITH_PRIV) ) + if (!pdb_enum_group_mapping(SID_NAME_UNKNOWN, &map, &entries, ENUM_ALL_MAPPED)) return -1; for (i=0; i] join [misc. options]\n" diff --git a/source3/utils/net_lookup.c b/source3/utils/net_lookup.c index 271094480c..8456da4e0c 100644 --- a/source3/utils/net_lookup.c +++ b/source3/utils/net_lookup.c @@ -124,11 +124,11 @@ static int net_lookup_ldap(int argc, const char **argv) static int net_lookup_dc(int argc, const char **argv) { - struct in_addr *ip_list, addr; + struct ip_service *ip_list; + struct in_addr addr; char *pdc_str = NULL; const char *domain=opt_target_workgroup; int count, i; - BOOL list_ordered; if (argc > 0) domain=argv[0]; @@ -140,12 +140,12 @@ static int net_lookup_dc(int argc, const char **argv) asprintf(&pdc_str, "%s", inet_ntoa(addr)); d_printf("%s\n", pdc_str); - if (!get_dc_list(domain, &ip_list, &count, &list_ordered)) { + if (!get_sorted_dc_list(domain, &ip_list, &count, False)) { SAFE_FREE(pdc_str); return 0; } for (i=0;i= 0) { + sec_channel_type = get_sec_channel_type(argv[0]); + } else { + sec_channel_type = get_sec_channel_type(NULL); + } + fstrcpy(trust_passwd, global_myname()); - strlower(trust_passwd); + strlower_m(trust_passwd); /* * Machine names can be 15 characters, but the max length on @@ -257,11 +268,7 @@ static NTSTATUS rpc_join_oldstyle_internals(const DOM_SID *domain_sid, struct cl result = trust_pw_change_and_store_it(cli, mem_ctx, opt_target_workgroup, orig_trust_passwd_hash, - SEC_CHAN_WKSTA); - - /* SEC_CHAN_WKSTA specified specifically, as you cannot use this - to join a BDC to the domain (MS won't allow it, and is *really* - insecure) */ + sec_channel_type); if (NT_STATUS_IS_OK(result)) printf("Joined domain %s.\n",opt_target_workgroup); @@ -275,35 +282,6 @@ static NTSTATUS rpc_join_oldstyle_internals(const DOM_SID *domain_sid, struct cl return result; } -/** - * Join a domain, the old way. - * - * @param argc Standard main() style argc - * @param argc Standard main() style argv. Initial components are already - * stripped - * - * @return A shell status integer (0 for success) - **/ - -static int net_rpc_join_oldstyle(int argc, const char **argv) -{ - uint32 sec_channel_type; - /* check what type of join */ - if (argc >= 0) { - sec_channel_type = get_sec_channel_type(argv[0]); - } else { - sec_channel_type = get_sec_channel_type(NULL); - } - - if (sec_channel_type != SEC_CHAN_WKSTA) - return 1; - - return run_rpc_command(NULL, PI_NETLOGON, - NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC, - rpc_join_oldstyle_internals, - argc, argv); -} - /** * Join a domain, the old way. * @@ -318,7 +296,7 @@ static int net_rpc_oldjoin(int argc, const char **argv) { return run_rpc_command(NULL, PI_NETLOGON, NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC, - rpc_join_oldstyle_internals, + rpc_oldjoin_internals, argc, argv); } @@ -351,13 +329,13 @@ static int rpc_join_usage(int argc, const char **argv) * * Main 'net_rpc_join()' (where the admain username/password is used) is * in net_rpc_join.c - * Assume if a -U is specified, it's the new style, otherwise it's the - * old style. If 'oldstyle' is specfied explicity, do it and don't prompt. + * Try to just change the password, but if that doesn't work, use/prompt + * for a username/password. **/ int net_rpc_join(int argc, const char **argv) { - if ((net_rpc_join_oldstyle(argc, argv) == 0)) + if ((net_rpc_oldjoin(argc, argv) == 0)) return 0; return net_rpc_join_newstyle(argc, argv); @@ -862,11 +840,11 @@ rpc_user_list_internals(const DOM_SID *domain_sid, struct cli_state *cli, unistr2_to_ascii(desc, &(&ctr.sam.info1->str[i])->uni_acct_desc, sizeof(desc)-1); if (opt_long_list_entries) - printf("%-21.21s %-50.50s\n", user, desc); + printf("%-21.21s %s\n", user, desc); else printf("%s\n", user); } - } while (!NT_STATUS_IS_OK(result)); + } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)); done: return result; @@ -937,7 +915,7 @@ rpc_group_list_internals(const DOM_SID *domain_sid, struct cli_state *cli, { POLICY_HND connect_pol, domain_pol; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; - uint32 start_idx=0, max_entries=250, num_entries, i; + uint32 start_idx=0, max_entries=250, num_entries, i, loop_count = 0; struct acct_info *groups; DOM_SID global_sid_Builtin; @@ -965,34 +943,75 @@ rpc_group_list_internals(const DOM_SID *domain_sid, struct cli_state *cli, d_printf("\nGroup name Comment"\ "\n-----------------------------\n"); do { - result = cli_samr_enum_dom_groups(cli, mem_ctx, &domain_pol, - &start_idx, max_entries, - &groups, &num_entries); + SAM_DISPINFO_CTR ctr; + SAM_DISPINFO_3 info3; + uint32 max_size; + + ZERO_STRUCT(ctr); + ZERO_STRUCT(info3); + ctr.sam.info3 = &info3; + + get_query_dispinfo_params( + loop_count, &max_entries, &max_size); + + result = cli_samr_query_dispinfo(cli, mem_ctx, &domain_pol, + &start_idx, 3, &num_entries, + max_entries, max_size, &ctr); for (i = 0; i < num_entries; i++) { + + fstring group, desc; + + unistr2_to_ascii(group, &(&ctr.sam.info3->str[i])->uni_grp_name, sizeof(group)-1); + unistr2_to_ascii(desc, &(&ctr.sam.info3->str[i])->uni_grp_desc, sizeof(desc)-1); + if (opt_long_list_entries) - printf("%-21.21s %-50.50s\n", - groups[i].acct_name, - groups[i].acct_desc); + printf("%-21.21s %-50.50s\n", + group, desc); else - printf("%-21.21s\n", groups[i].acct_name); + printf("%-21.21s\n", group); } - } while (NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES)); + } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)); /* query domain aliases */ + start_idx = 0; do { result = cli_samr_enum_als_groups(cli, mem_ctx, &domain_pol, &start_idx, max_entries, &groups, &num_entries); - + for (i = 0; i < num_entries; i++) { - if (opt_long_list_entries) + + char *description = NULL; + + if (opt_long_list_entries) { + + POLICY_HND alias_pol; + ALIAS_INFO_CTR ctr; + + if ((NT_STATUS_IS_OK(cli_samr_open_alias(cli, mem_ctx, + &domain_pol, + 0x8, + groups[i].rid, + &alias_pol))) && + (NT_STATUS_IS_OK(cli_samr_query_alias_info(cli, mem_ctx, + &alias_pol, 3, + &ctr))) && + (NT_STATUS_IS_OK(cli_samr_close(cli, mem_ctx, + &alias_pol)))) { + description = unistr2_tdup(mem_ctx, + &ctr.alias.info3.uni_acct_desc); + } + } + + if (description != NULL) { printf("%-21.21s %-50.50s\n", groups[i].acct_name, - groups[i].acct_desc); - else + description); + } else { printf("%-21.21s\n", groups[i].acct_name); + } } - } while (NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES)); + } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)); cli_samr_close(cli, mem_ctx, &domain_pol); /* Get builtin policy handle */ @@ -1003,20 +1022,45 @@ rpc_group_list_internals(const DOM_SID *domain_sid, struct cli_state *cli, goto done; } /* query builtin aliases */ + start_idx = 0; do { result = cli_samr_enum_als_groups(cli, mem_ctx, &domain_pol, &start_idx, max_entries, &groups, &num_entries); for (i = 0; i < num_entries; i++) { - if (opt_long_list_entries) + + char *description = NULL; + + if (opt_long_list_entries) { + + POLICY_HND alias_pol; + ALIAS_INFO_CTR ctr; + + if ((NT_STATUS_IS_OK(cli_samr_open_alias(cli, mem_ctx, + &domain_pol, + 0x8, + groups[i].rid, + &alias_pol))) && + (NT_STATUS_IS_OK(cli_samr_query_alias_info(cli, mem_ctx, + &alias_pol, 3, + &ctr))) && + (NT_STATUS_IS_OK(cli_samr_close(cli, mem_ctx, + &alias_pol)))) { + description = unistr2_tdup(mem_ctx, + &ctr.alias.info3.uni_acct_desc); + } + } + + if (description != NULL) { printf("%-21.21s %-50.50s\n", groups[i].acct_name, - groups[i].acct_desc); - else - printf("%s\n", groups[i].acct_name); + description); + } else { + printf("%-21.21s\n", groups[i].acct_name); + } } - } while (NT_STATUS_V(result) == NT_STATUS_V(STATUS_MORE_ENTRIES)); + } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)); done: return result; @@ -1576,8 +1620,8 @@ static NTSTATUS rpc_trustdom_add_internals(const DOM_SID *domain_sid, struct cli uint16 acb_info; uint32 unknown, user_rid; - if (argc != 1) { - d_printf("Usage: net rpc trustdom add \n"); + if (argc != 2) { + d_printf("Usage: net rpc trustdom add \n"); return NT_STATUS_INVALID_PARAMETER; } @@ -1589,7 +1633,7 @@ static NTSTATUS rpc_trustdom_add_internals(const DOM_SID *domain_sid, struct cli return NT_STATUS_NO_MEMORY; } - strupper(acct_name); + strupper_m(acct_name); /* Get samr policy handle */ result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, @@ -1608,7 +1652,7 @@ static NTSTATUS rpc_trustdom_add_internals(const DOM_SID *domain_sid, struct cli /* Create trusting domain's account */ acb_info = ACB_DOMTRUST; - unknown = 0xe005000b; /* No idea what this is - a permission mask? + unknown = 0xe00500b0; /* No idea what this is - a permission mask? mimir: yes, most probably it is */ result = cli_samr_create_dom_user(cli, mem_ctx, &domain_pol, @@ -1618,6 +1662,37 @@ static NTSTATUS rpc_trustdom_add_internals(const DOM_SID *domain_sid, struct cli goto done; } + { + SAM_USERINFO_CTR ctr; + SAM_USER_INFO_24 p24; + fstring ucs2_trust_password; + int ucs2_pw_len; + uchar pwbuf[516]; + + ucs2_pw_len = push_ucs2(NULL, ucs2_trust_password, argv[1], + sizeof(ucs2_trust_password), 0); + + encode_pw_buffer((char *)pwbuf, ucs2_trust_password, + ucs2_pw_len); + + ZERO_STRUCT(ctr); + ZERO_STRUCT(p24); + + init_sam_user_info24(&p24, (char *)pwbuf, 24); + + ctr.switch_value = 24; + ctr.info.id24 = &p24; + + result = cli_samr_set_userinfo(cli, mem_ctx, &user_pol, 24, + cli->user_session_key, &ctr); + + if (!NT_STATUS_IS_OK(result)) { + DEBUG(0,("Could not set trust account password: %s\n", + nt_errstr(result))); + goto done; + } + } + done: SAFE_FREE(acct_name); return result; @@ -1689,11 +1764,11 @@ static int rpc_trustdom_establish(int argc, const char **argv) } domain_name = smb_xstrdup(argv[0]); - strupper(domain_name); + strupper_m(domain_name); /* account name used at first is our domain's name with '$' */ asprintf(&acct_name, "%s$", lp_workgroup()); - strupper(acct_name); + strupper_m(acct_name); /* * opt_workgroup will be used by connection functions further, @@ -1706,7 +1781,7 @@ static int rpc_trustdom_establish(int argc, const char **argv) opt_user_name = acct_name; /* find the domain controller */ - if (!net_find_dc(&server_ip, pdc_name, domain_name)) { + if (!net_find_pdc(&server_ip, pdc_name, domain_name)) { DEBUG(0, ("Coulnd find domain controller for domain %s\n", domain_name)); return -1; } @@ -1785,7 +1860,7 @@ static int rpc_trustdom_establish(int argc, const char **argv) return -1; } - nt_status = cli_lsa_open_policy2(cli, mem_ctx, False, SEC_RIGHTS_QUERY_VALUE, + nt_status = cli_lsa_open_policy2(cli, mem_ctx, True, SEC_RIGHTS_QUERY_VALUE, &connect_hnd); if (NT_STATUS_IS_ERR(nt_status)) { DEBUG(0, ("Couldn't open policy handle. Error was %s\n", @@ -1804,6 +1879,9 @@ static int rpc_trustdom_establish(int argc, const char **argv) return -1; } + + + /* There should be actually query info level 3 (following nt serv behaviour), but I still don't know if it's _really_ necessary */ @@ -1855,7 +1933,7 @@ static int rpc_trustdom_revoke(int argc, const char **argv) /* generate upper cased domain name */ domain_name = smb_xstrdup(argv[0]); - strupper(domain_name); + strupper_m(domain_name); /* delete password of the trust */ if (!trusted_domain_password_delete(domain_name)) { @@ -2089,7 +2167,7 @@ static int rpc_trustdom_list(int argc, const char **argv) do padding[--pad_len] = ' '; while (pad_len); /* set opt_* variables to remote domain */ - strupper(trusting_dom_names[i]); + strupper_m(trusting_dom_names[i]); opt_workgroup = talloc_strdup(mem_ctx, trusting_dom_names[i]); opt_target_workgroup = opt_workgroup; diff --git a/source3/utils/net_rpc_join.c b/source3/utils/net_rpc_join.c index e389cf8ef8..22ed49c74f 100644 --- a/source3/utils/net_rpc_join.c +++ b/source3/utils/net_rpc_join.c @@ -49,7 +49,6 @@ 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))) { @@ -68,10 +67,12 @@ int net_rpc_join_ok(const char *domain) goto done; } - CHECK_RPC_ERR(cli_nt_setup_creds(cli, - channel, - stored_md4_trust_password, &neg_flags, 2), - "error in domain join verification"); + /* ensure that schannel uses the right domain */ + fstrcpy(cli->domain, domain); + if (! NT_STATUS_IS_OK(result = cli_nt_establish_netlogon(cli, channel, stored_md4_trust_password))) { + DEBUG(0,("Error in domain join verfication\n")); + goto done; + } retval = 0; /* Success! */ @@ -131,7 +132,6 @@ int net_rpc_join_newstyle(int argc, const char **argv) uint32 flags = 0x3e8; char *acct_name; const char *const_acct_name; - uint32 neg_flags = 0x000001ff; /* check what type of join */ if (argc >= 0) { @@ -167,7 +167,7 @@ int net_rpc_join_newstyle(int argc, const char **argv) /* Fetch domain sid */ if (!cli_nt_session_open(cli, PI_LSARPC)) { - DEBUG(0, ("Error connecting to SAM pipe\n")); + DEBUG(0, ("Error connecting to LSA pipe\n")); goto done; } @@ -204,7 +204,7 @@ int net_rpc_join_newstyle(int argc, const char **argv) /* Create domain user */ acct_name = talloc_asprintf(mem_ctx, "%s$", global_myname()); - strlower(acct_name); + strlower_m(acct_name); const_acct_name = acct_name; result = cli_samr_create_dom_user(cli, mem_ctx, &domain_pol, @@ -240,7 +240,7 @@ int net_rpc_join_newstyle(int argc, const char **argv) acct_name, nt_errstr(result))); if (name_types[0] != SID_NAME_USER) { - DEBUG(0, ("%s is not a user account\n", acct_name)); + DEBUG(0, ("%s is not a user account (type=%d)\n", acct_name, name_types[0])); goto done; } @@ -315,14 +315,29 @@ int net_rpc_join_newstyle(int argc, const char **argv) goto done; } - CHECK_RPC_ERR(cli_nt_setup_creds(cli, - sec_channel_type, - md4_trust_password, &neg_flags, 2), - "error in domain join verification"); - + /* ensure that schannel uses the right domain */ + fstrcpy(cli->domain, domain); + + result = cli_nt_establish_netlogon(cli, sec_channel_type, + md4_trust_password); + + if (!NT_STATUS_IS_OK(result)) { + DEBUG(0, ("Error domain join verification: %s\n\n", + nt_errstr(result))); + + if ( NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED) && + (sec_channel_type == SEC_CHAN_BDC) ) { + d_printf("Please make sure that no computer account\n" + "named like this machine (%s) exists in the domain\n", + global_myname()); + } + + goto done; + } + /* Now store the secret in the secrets database */ - strupper(domain); + strupper_m(domain); if (!secrets_store_domain_sid(domain, &domain_sid)) { DEBUG(0, ("error storing domain sid for %s\n", domain)); @@ -366,7 +381,7 @@ done: **/ int net_rpc_testjoin(int argc, const char **argv) { - char *domain = smb_xstrdup(lp_workgroup()); + char *domain = smb_xstrdup(opt_target_workgroup); /* Display success or failure */ if (net_rpc_join_ok(domain) != 0) { diff --git a/source3/utils/net_rpc_samsync.c b/source3/utils/net_rpc_samsync.c index 42bb480844..e5e9a68b2e 100644 --- a/source3/utils/net_rpc_samsync.c +++ b/source3/utils/net_rpc_samsync.c @@ -209,6 +209,11 @@ int rpc_samdump(int argc, const char **argv) fstrcpy(cli->domain, lp_workgroup()); + if (!cli_nt_session_open(cli, PI_NETLOGON)) { + DEBUG(0,("Could not open connection to NETLOGON pipe\n")); + goto fail; + } + if (!secrets_fetch_trust_account_password(lp_workgroup(), trust_password, NULL, &sec_channel)) { @@ -216,7 +221,8 @@ int rpc_samdump(int argc, const char **argv) goto fail; } - if (!cli_nt_open_netlogon(cli, trust_password, sec_channel)) { + if (!NT_STATUS_IS_OK(cli_nt_establish_netlogon(cli, sec_channel, + trust_password))) { DEBUG(0,("Error connecting to NETLOGON pipe\n")); goto fail; } @@ -403,8 +409,10 @@ fetch_account_info(uint32 rid, SAM_ACCOUNT_INFO *delta) SAM_ACCOUNT *sam_account=NULL; GROUP_MAP map; struct group *grp; - DOM_SID sid; - BOOL try_add = False; + DOM_SID user_sid; + DOM_SID group_sid; + struct passwd *passwd; + fstring sid_string; fstrcpy(account, unistr2_static(&delta->uni_acct_name)); d_printf("Creating account: %s\n", account); @@ -412,7 +420,7 @@ fetch_account_info(uint32 rid, SAM_ACCOUNT_INFO *delta) if (!NT_STATUS_IS_OK(nt_ret = pdb_init_sam(&sam_account))) return nt_ret; - if (!pdb_getsampwnam(sam_account, account)) { + if (!(passwd = Get_Pwnam(account))) { /* Create appropriate user */ if (delta->acb_info & ACB_NORMAL) { pstrcpy(add_script, lp_adduser_script()); @@ -423,8 +431,6 @@ fetch_account_info(uint32 rid, SAM_ACCOUNT_INFO *delta) } else { DEBUG(1, ("Unknown user type: %s\n", smbpasswd_encode_acb_info(delta->acb_info))); - pdb_free_sam(&sam_account); - return NT_STATUS_NO_SUCH_USER; } if (*add_script) { int add_ret; @@ -434,44 +440,68 @@ fetch_account_info(uint32 rid, SAM_ACCOUNT_INFO *delta) DEBUG(1,("fetch_account: Running the command `%s' " "gave %d\n", add_script, add_ret)); } - - try_add = True; + else { + DEBUG(8,("fetch_account_info: no add user/machine script. Asking winbindd\n")); + + /* don't need a RID allocated since the user already has a SID */ + if ( !winbind_create_user( account, NULL ) ) + DEBUG(4,("fetch_account_info: winbind_create_user() failed\n")); + } + + /* try and find the possible unix account again */ + if ( !(passwd = Get_Pwnam(account)) ) + return NT_STATUS_NO_SUCH_USER; + } - - sam_account_from_delta(sam_account, delta); - - if (try_add) { + + sid_copy(&user_sid, get_global_sam_sid()); + sid_append_rid(&user_sid, delta->user_rid); + + DEBUG(3, ("Attempting to find SID %s for user %s in the passdb\n", sid_to_string(sid_string, &user_sid), account)); + if (!pdb_getsampwsid(sam_account, &user_sid)) { + sam_account_from_delta(sam_account, delta); + DEBUG(3, ("Attempting to add user SID %s for user %s in the passdb\n", + sid_to_string(sid_string, &user_sid), pdb_get_username(sam_account))); if (!pdb_add_sam_account(sam_account)) { DEBUG(1, ("SAM Account for %s failed to be added to the passdb!\n", account)); + return NT_STATUS_ACCESS_DENIED; } } else { + sam_account_from_delta(sam_account, delta); + DEBUG(3, ("Attempting to update user SID %s for user %s in the passdb\n", + sid_to_string(sid_string, &user_sid), pdb_get_username(sam_account))); if (!pdb_update_sam_account(sam_account)) { DEBUG(1, ("SAM Account for %s failed to be updated in the passdb!\n", account)); + pdb_free_sam(&sam_account); + return NT_STATUS_ACCESS_DENIED; } } - sid = *pdb_get_group_sid(sam_account); + group_sid = *pdb_get_group_sid(sam_account); - if (!pdb_getgrsid(&map, sid, False)) { + if (!pdb_getgrsid(&map, group_sid)) { DEBUG(0, ("Primary group of %s has no mapping!\n", pdb_get_username(sam_account))); - pdb_free_sam(&sam_account); - return NT_STATUS_NO_SUCH_GROUP; - } + } else { + if (map.gid != passwd->pw_gid) { + if (!(grp = getgrgid(map.gid))) { + DEBUG(0, ("Could not find unix group %d for user %s (group SID=%s)\n", + map.gid, pdb_get_username(sam_account), sid_string_static(&group_sid))); + } else { + smb_set_primary_group(grp->gr_name, pdb_get_username(sam_account)); + } + } + } - if (!(grp = getgrgid(map.gid))) { - DEBUG(0, ("Could not find unix group %d for user %s (group SID=%s)\n", - map.gid, pdb_get_username(sam_account), sid_string_static(&sid))); - pdb_free_sam(&sam_account); - return NT_STATUS_NO_SUCH_GROUP; + if ( !passwd ) { + DEBUG(1, ("No unix user for this account (%s), cannot adjust mappings\n", + pdb_get_username(sam_account))); } - smb_set_primary_group(grp->gr_name, pdb_get_username(sam_account)); - pdb_free_sam(&sam_account); - return NT_STATUS_OK; + return nt_ret; } static NTSTATUS @@ -493,22 +523,26 @@ fetch_group_info(uint32 rid, SAM_GROUP_INFO *delta) sid_append_rid(&group_sid, rid); sid_to_string(sid_string, &group_sid); - if (pdb_getgrsid(&map, group_sid, False)) { - grp = getgrgid(map.gid); + if (pdb_getgrsid(&map, group_sid)) { + if ( map.gid != -1 ) + grp = getgrgid(map.gid); insert = False; } - if (grp == NULL) - { + if (grp == NULL) { gid_t gid; /* No group found from mapping, find it from its name. */ if ((grp = getgrnam(name)) == NULL) { + /* No appropriate group found, create one */ + d_printf("Creating unix group: '%s'\n", name); + if (smb_create_group(name, &gid) != 0) return NT_STATUS_ACCESS_DENIED; - if ((grp = getgrgid(gid)) == NULL) + + if ((grp = getgrnam(name)) == NULL) return NT_STATUS_ACCESS_DENIED; } } @@ -519,9 +553,6 @@ fetch_group_info(uint32 rid, SAM_GROUP_INFO *delta) fstrcpy(map.nt_name, name); fstrcpy(map.comment, comment); - map.priv_set.count = 0; - map.priv_set.set = NULL; - if (insert) pdb_add_group_mapping_entry(&map); else @@ -548,7 +579,7 @@ fetch_group_mem_info(uint32 rid, SAM_GROUP_MEM_INFO *delta) sid_copy(&group_sid, get_global_sam_sid()); sid_append_rid(&group_sid, rid); - if (!get_domain_group_from_sid(group_sid, &map, False)) { + if (!get_domain_group_from_sid(group_sid, &map)) { DEBUG(0, ("Could not find global group %d\n", rid)); return NT_STATUS_NO_SUCH_GROUP; } @@ -673,7 +704,7 @@ static NTSTATUS fetch_alias_info(uint32 rid, SAM_ALIAS_INFO *delta, sid_append_rid(&alias_sid, rid); sid_to_string(sid_string, &alias_sid); - if (pdb_getgrsid(&map, alias_sid, False)) { + if (pdb_getgrsid(&map, alias_sid)) { grp = getgrgid(map.gid); insert = False; } @@ -703,9 +734,6 @@ static NTSTATUS fetch_alias_info(uint32 rid, SAM_ALIAS_INFO *delta, fstrcpy(map.nt_name, name); fstrcpy(map.comment, comment); - map.priv_set.count = 0; - map.priv_set.set = NULL; - if (insert) pdb_add_group_mapping_entry(&map); else @@ -885,7 +913,7 @@ fetch_sam_entry(SAM_DELTA_HDR *hdr_delta, SAM_DELTA_CTR *delta, &delta->als_mem_info, dom_sid); break; case SAM_DELTA_DOMAIN_INFO: - d_printf("SAMBA_DELTA_DOMAIN_INFO not handled\n"); + d_printf("SAM_DELTA_DOMAIN_INFO not handled\n"); break; default: d_printf("Unknown delta record type %d\n", hdr_delta->type); @@ -893,7 +921,7 @@ fetch_sam_entry(SAM_DELTA_HDR *hdr_delta, SAM_DELTA_CTR *delta, } } -static void +static NTSTATUS fetch_database(struct cli_state *cli, unsigned db_type, DOM_CRED *ret_creds, DOM_SID dom_sid) { @@ -905,9 +933,8 @@ fetch_database(struct cli_state *cli, unsigned db_type, DOM_CRED *ret_creds, SAM_DELTA_CTR *deltas; uint32 num_deltas; - if (!(mem_ctx = talloc_init("fetch_database"))) { - return; - } + if (!(mem_ctx = talloc_init("fetch_database"))) + return NT_STATUS_NO_MEMORY; switch( db_type ) { case SAM_DATABASE_DOMAIN: @@ -929,15 +956,25 @@ fetch_database(struct cli_state *cli, unsigned db_type, DOM_CRED *ret_creds, db_type, sync_context, &num_deltas, &hdr_deltas, &deltas); - clnt_deal_with_creds(cli->sess_key, &(cli->clnt_cred), - ret_creds); - for (i = 0; i < num_deltas; i++) { - fetch_sam_entry(&hdr_deltas[i], &deltas[i], dom_sid); - } + + if (NT_STATUS_IS_OK(result) || + NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) { + + clnt_deal_with_creds(cli->sess_key, &(cli->clnt_cred), + ret_creds); + + for (i = 0; i < num_deltas; i++) { + fetch_sam_entry(&hdr_deltas[i], &deltas[i], dom_sid); + } + } else + return result; + sync_context += 1; } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)); talloc_destroy(mem_ctx); + + return result; } /* dump sam database via samsync rpc calls */ @@ -947,7 +984,6 @@ int rpc_vampire(int argc, const char **argv) struct cli_state *cli = NULL; uchar trust_password[16]; DOM_CRED ret_creds; - uint32 neg_flags = 0x000001ff; DOM_SID dom_sid; uint32 sec_channel; @@ -971,18 +1007,35 @@ int rpc_vampire(int argc, const char **argv) goto fail; } - result = cli_nt_setup_creds(cli, sec_channel, trust_password, - &neg_flags, 2); + result = cli_nt_establish_netlogon(cli, sec_channel, trust_password); + if (!NT_STATUS_IS_OK(result)) { d_printf("Failed to setup BDC creds\n"); goto fail; } - dom_sid = *get_global_sam_sid(); - fetch_database(cli, SAM_DATABASE_DOMAIN, &ret_creds, dom_sid); + sid_copy( &dom_sid, get_global_sam_sid() ); + result = fetch_database(cli, SAM_DATABASE_DOMAIN, &ret_creds, dom_sid); + + if (!NT_STATUS_IS_OK(result)) { + d_printf("Failed to fetch domain database: %s\n", + nt_errstr(result)); + if (NT_STATUS_EQUAL(result, NT_STATUS_NOT_SUPPORTED)) + d_printf("Perhaps %s is a Windows 2000 native mode " + "domain?\n", lp_workgroup()); + goto fail; + } sid_copy(&dom_sid, &global_sid_Builtin); - fetch_database(cli, SAM_DATABASE_BUILTIN, &ret_creds, dom_sid); + + result = fetch_database(cli, SAM_DATABASE_BUILTIN, &ret_creds, + dom_sid); + + if (!NT_STATUS_IS_OK(result)) { + d_printf("Failed to fetch builtin database: %s\n", + nt_errstr(result)); + goto fail; + } /* Currently we crash on PRIVS somewhere in unmarshalling */ /* Dump_database(cli, SAM_DATABASE_PRIVS, &ret_creds); */ @@ -992,8 +1045,8 @@ int rpc_vampire(int argc, const char **argv) return 0; fail: - if (cli) { + if (cli) cli_nt_session_close(cli); - } + return -1; } diff --git a/source3/utils/ntlm_auth.c b/source3/utils/ntlm_auth.c index 42490190f3..3dfa157bda 100644 --- a/source3/utils/ntlm_auth.c +++ b/source3/utils/ntlm_auth.c @@ -38,7 +38,6 @@ enum squid_mode { extern int winbindd_fd; -static const char *helper_protocol; static const char *opt_username; static const char *opt_domain; static const char *opt_workstation; @@ -48,7 +47,6 @@ static DATA_BLOB opt_lm_response; static DATA_BLOB opt_nt_response; static int request_lm_key; static int request_nt_key; -static int diagnostics; static char winbind_separator(void) @@ -184,7 +182,7 @@ static NTSTATUS contact_winbind_auth_crap(const char *username, const DATA_BLOB *lm_response, const DATA_BLOB *nt_response, uint32 flags, - uint8 lm_key[16], + uint8 lm_key[8], uint8 nt_key[16], char **error_string) { @@ -198,7 +196,7 @@ static NTSTATUS contact_winbind_auth_crap(const char *username, ZERO_STRUCT(request); ZERO_STRUCT(response); - request.data.auth_crap.flags = flags; + request.flags = flags; fstrcpy(request.data.auth_crap.user, username); @@ -235,13 +233,13 @@ static NTSTATUS contact_winbind_auth_crap(const char *username, return nt_status; } - if ((flags & WINBIND_PAM_LMKEY) && lm_key + if ((flags & WBFLAG_PAM_LMKEY) && lm_key && (memcmp(zeros, response.data.auth.first_8_lm_hash, sizeof(response.data.auth.first_8_lm_hash)) != 0)) { memcpy(lm_key, response.data.auth.first_8_lm_hash, sizeof(response.data.auth.first_8_lm_hash)); } - if ((flags & WINBIND_PAM_NTKEY) && nt_key + if ((flags & WBFLAG_PAM_NTKEY) && nt_key && (memcmp(zeros, response.data.auth.nt_session_key, sizeof(response.data.auth.nt_session_key)) != 0)) { memcpy(nt_key, response.data.auth.nt_session_key, @@ -410,14 +408,15 @@ static BOOL check_auth_crap(void) char *hex_lm_key; char *hex_nt_key; char *error_string; - static uint8 zeros[16]; + x_setbuf(x_stdout, NULL); + if (request_lm_key) - flags |= WINBIND_PAM_LMKEY; + flags |= WBFLAG_PAM_LMKEY; if (request_nt_key) - flags |= WINBIND_PAM_NTKEY; + flags |= WBFLAG_PAM_NTKEY; nt_status = contact_winbind_auth_crap(opt_username, opt_domain, opt_workstation, @@ -430,9 +429,9 @@ static BOOL check_auth_crap(void) &error_string); if (!NT_STATUS_IS_OK(nt_status)) { - d_printf("%s (0x%x)\n", - error_string, - NT_STATUS_V(nt_status)); + x_fprintf(x_stdout, "%s (0x%x)\n", + error_string, + NT_STATUS_V(nt_status)); SAFE_FREE(error_string); return False; } @@ -443,7 +442,7 @@ static BOOL check_auth_crap(void) hex_encode(lm_key, sizeof(lm_key), &hex_lm_key); - d_printf("LM_KEY: %s\n", hex_lm_key); + x_fprintf(x_stdout, "LM_KEY: %s\n", hex_lm_key); SAFE_FREE(hex_lm_key); } if (request_nt_key @@ -452,7 +451,7 @@ static BOOL check_auth_crap(void) hex_encode(nt_key, sizeof(nt_key), &hex_nt_key); - d_printf("NT_KEY: %s\n", hex_nt_key); + x_fprintf(x_stdout, "NT_KEY: %s\n", hex_nt_key); SAFE_FREE(hex_nt_key); } @@ -476,6 +475,10 @@ static DATA_BLOB get_challenge(void) return chal; } +/* + * Test LM authentication, no NT response supplied + */ + static BOOL test_lm(void) { NTSTATUS nt_status; @@ -483,13 +486,18 @@ static BOOL test_lm(void) DATA_BLOB lm_response = data_blob(NULL, 24); uchar lm_key[8]; + uchar nt_key[16]; uchar lm_hash[16]; DATA_BLOB chall = get_challenge(); char *error_string; - flags |= WINBIND_PAM_LMKEY; + ZERO_STRUCT(lm_key); + ZERO_STRUCT(nt_key); - SMBencrypt(opt_password,chall.data,lm_response.data); + flags |= WBFLAG_PAM_LMKEY; + flags |= WBFLAG_PAM_NTKEY; + + SMBencrypt(opt_password, chall.data, lm_response.data); E_deshash(opt_password, lm_hash); nt_status = contact_winbind_auth_crap(opt_username, opt_domain, opt_workstation, @@ -498,7 +506,7 @@ static BOOL test_lm(void) NULL, flags, lm_key, - NULL, + nt_key, &error_string); data_blob_free(&lm_response); @@ -518,9 +526,20 @@ static BOOL test_lm(void) DEBUG(1, ("expected:\n")); dump_data(1, lm_hash, 8); } + if (memcmp(lm_hash, nt_key, 8) != 0) { + DEBUG(1, ("Session Key (first 8, lm hash) does not match expectations!\n")); + DEBUG(1, ("nt_key:\n")); + dump_data(1, nt_key, 8); + DEBUG(1, ("expected:\n")); + dump_data(1, lm_hash, 8); + } return True; } +/* + * Test the normal 'LM and NTLM' combination + */ + static BOOL test_lm_ntlm(void) { BOOL pass = True; @@ -537,8 +556,11 @@ static BOOL test_lm_ntlm(void) DATA_BLOB chall = get_challenge(); char *error_string; - flags |= WINBIND_PAM_LMKEY; - flags |= WINBIND_PAM_NTKEY; + ZERO_STRUCT(lm_key); + ZERO_STRUCT(nt_key); + + flags |= WBFLAG_PAM_LMKEY; + flags |= WBFLAG_PAM_NTKEY; SMBencrypt(opt_password,chall.data,lm_response.data); E_deshash(opt_password, lm_hash); @@ -589,6 +611,10 @@ static BOOL test_lm_ntlm(void) return pass; } +/* + * Test the NTLM response only, no LM. + */ + static BOOL test_ntlm(void) { BOOL pass = True; @@ -597,24 +623,99 @@ static BOOL test_ntlm(void) DATA_BLOB nt_response = data_blob(NULL, 24); DATA_BLOB session_key = data_blob(NULL, 16); + char lm_key[8]; char nt_key[16]; + char lm_hash[16]; char nt_hash[16]; DATA_BLOB chall = get_challenge(); char *error_string; - flags |= WINBIND_PAM_NTKEY; + ZERO_STRUCT(lm_key); + ZERO_STRUCT(nt_key); + + flags |= WBFLAG_PAM_LMKEY; + flags |= WBFLAG_PAM_NTKEY; SMBNTencrypt(opt_password,chall.data,nt_response.data); E_md4hash(opt_password, nt_hash); SMBsesskeygen_ntv1(nt_hash, NULL, session_key.data); + E_deshash(opt_password, lm_hash); + nt_status = contact_winbind_auth_crap(opt_username, opt_domain, opt_workstation, &chall, NULL, &nt_response, flags, + lm_key, + nt_key, + &error_string); + + data_blob_free(&nt_response); + + if (!NT_STATUS_IS_OK(nt_status)) { + d_printf("%s (0x%x)\n", + error_string, + NT_STATUS_V(nt_status)); + SAFE_FREE(error_string); + return False; + } + + if (memcmp(lm_hash, lm_key, + sizeof(lm_key)) != 0) { + DEBUG(1, ("LM Key does not match expectations!\n")); + DEBUG(1, ("lm_key:\n")); + dump_data(1, lm_key, 8); + DEBUG(1, ("expected:\n")); + dump_data(1, lm_hash, 8); + pass = False; + } + if (memcmp(session_key.data, nt_key, + sizeof(nt_key)) != 0) { + DEBUG(1, ("NT Session Key does not match expectations!\n")); + DEBUG(1, ("nt_key:\n")); + dump_data(1, nt_key, 16); + DEBUG(1, ("expected:\n")); + dump_data(1, session_key.data, session_key.length); + pass = False; + } + return pass; +} + +/* + * Test the NTLM response only, but in the LM field. + */ + +static BOOL test_ntlm_in_lm(void) +{ + BOOL pass = True; + NTSTATUS nt_status; + uint32 flags = 0; + DATA_BLOB nt_response = data_blob(NULL, 24); + + uchar lm_key[8]; + uchar lm_hash[16]; + uchar nt_key[16]; + DATA_BLOB chall = get_challenge(); + char *error_string; + + ZERO_STRUCT(nt_key); + + flags |= WBFLAG_PAM_LMKEY; + flags |= WBFLAG_PAM_NTKEY; + + SMBNTencrypt(opt_password,chall.data,nt_response.data); + + E_deshash(opt_password, lm_hash); + + nt_status = contact_winbind_auth_crap(opt_username, opt_domain, + opt_workstation, + &chall, + &nt_response, NULL, + flags, + lm_key, nt_key, &error_string); @@ -628,6 +729,86 @@ static BOOL test_ntlm(void) return False; } + if (memcmp(lm_hash, lm_key, + sizeof(lm_key)) != 0) { + DEBUG(1, ("LM Key does not match expectations!\n")); + DEBUG(1, ("lm_key:\n")); + dump_data(1, lm_key, 8); + DEBUG(1, ("expected:\n")); + dump_data(1, lm_hash, 8); + pass = False; + } + if (memcmp(lm_hash, nt_key, 8) != 0) { + DEBUG(1, ("Session Key (first 8 lm hash) does not match expectations!\n")); + DEBUG(1, ("nt_key:\n")); + dump_data(1, nt_key, 16); + DEBUG(1, ("expected:\n")); + dump_data(1, lm_hash, 8); + pass = False; + } + return pass; +} + +/* + * Test the NTLM response only, but in the both the NT and LM fields. + */ + +static BOOL test_ntlm_in_both(void) +{ + BOOL pass = True; + NTSTATUS nt_status; + uint32 flags = 0; + DATA_BLOB nt_response = data_blob(NULL, 24); + DATA_BLOB session_key = data_blob(NULL, 16); + + char lm_key[8]; + char lm_hash[16]; + char nt_key[16]; + char nt_hash[16]; + DATA_BLOB chall = get_challenge(); + char *error_string; + + ZERO_STRUCT(lm_key); + ZERO_STRUCT(nt_key); + + flags |= WBFLAG_PAM_LMKEY; + flags |= WBFLAG_PAM_NTKEY; + + SMBNTencrypt(opt_password,chall.data,nt_response.data); + E_md4hash(opt_password, nt_hash); + SMBsesskeygen_ntv1(nt_hash, NULL, session_key.data); + + E_deshash(opt_password, lm_hash); + + nt_status = contact_winbind_auth_crap(opt_username, opt_domain, + opt_workstation, + &chall, + &nt_response, + &nt_response, + flags, + lm_key, + nt_key, + &error_string); + + data_blob_free(&nt_response); + + if (!NT_STATUS_IS_OK(nt_status)) { + d_printf("%s (0x%x)\n", + error_string, + NT_STATUS_V(nt_status)); + SAFE_FREE(error_string); + return False; + } + + if (memcmp(lm_hash, lm_key, + sizeof(lm_key)) != 0) { + DEBUG(1, ("LM Key does not match expectations!\n")); + DEBUG(1, ("lm_key:\n")); + dump_data(1, lm_key, 8); + DEBUG(1, ("expected:\n")); + dump_data(1, lm_hash, 8); + pass = False; + } if (memcmp(session_key.data, nt_key, sizeof(nt_key)) != 0) { DEBUG(1, ("NT Session Key does not match expectations!\n")); @@ -637,15 +818,347 @@ static BOOL test_ntlm(void) dump_data(1, session_key.data, session_key.length); pass = False; } + + return pass; } +/* + * Test the NTLMv2 response only + */ + +static BOOL test_ntlmv2(void) +{ + BOOL pass = True; + NTSTATUS nt_status; + uint32 flags = 0; + DATA_BLOB ntlmv2_response = data_blob(NULL, 0); + DATA_BLOB nt_session_key = data_blob(NULL, 0); + DATA_BLOB names_blob = NTLMv2_generate_names_blob(get_winbind_netbios_name(), get_winbind_domain()); + + uchar nt_key[16]; + DATA_BLOB chall = get_challenge(); + char *error_string; + + ZERO_STRUCT(nt_key); + + flags |= WBFLAG_PAM_NTKEY; + + if (!SMBNTLMv2encrypt(opt_username, opt_domain, opt_password, &chall, + &names_blob, + NULL, &ntlmv2_response, + &nt_session_key)) { + data_blob_free(&names_blob); + return False; + } + data_blob_free(&names_blob); + + nt_status = contact_winbind_auth_crap(opt_username, opt_domain, + opt_workstation, + &chall, + NULL, + &ntlmv2_response, + flags, + NULL, + nt_key, + &error_string); + + data_blob_free(&ntlmv2_response); + + if (!NT_STATUS_IS_OK(nt_status)) { + d_printf("%s (0x%x)\n", + error_string, + NT_STATUS_V(nt_status)); + SAFE_FREE(error_string); + return False; + } + + if (memcmp(nt_session_key.data, nt_key, + sizeof(nt_key)) != 0) { + DEBUG(1, ("NT Session Key does not match expectations!\n")); + DEBUG(1, ("nt_key:\n")); + dump_data(1, nt_key, 16); + DEBUG(1, ("expected:\n")); + dump_data(1, nt_session_key.data, nt_session_key.length); + pass = False; + } + return pass; +} + +/* + * Test the NTLMv2 and LMv2 responses + */ + +static BOOL test_lmv2_ntlmv2(void) +{ + BOOL pass = True; + NTSTATUS nt_status; + uint32 flags = 0; + DATA_BLOB ntlmv2_response = data_blob(NULL, 0); + DATA_BLOB lmv2_response = data_blob(NULL, 0); + DATA_BLOB nt_session_key = data_blob(NULL, 0); + DATA_BLOB names_blob = NTLMv2_generate_names_blob(get_winbind_netbios_name(), get_winbind_domain()); + + uchar nt_key[16]; + DATA_BLOB chall = get_challenge(); + char *error_string; + + ZERO_STRUCT(nt_key); + + flags |= WBFLAG_PAM_NTKEY; + + if (!SMBNTLMv2encrypt(opt_username, opt_domain, opt_password, &chall, + &names_blob, + &lmv2_response, &ntlmv2_response, + &nt_session_key)) { + data_blob_free(&names_blob); + return False; + } + data_blob_free(&names_blob); + + nt_status = contact_winbind_auth_crap(opt_username, opt_domain, + opt_workstation, + &chall, + &lmv2_response, + &ntlmv2_response, + flags, + NULL, + nt_key, + &error_string); + + data_blob_free(&lmv2_response); + data_blob_free(&ntlmv2_response); + + if (!NT_STATUS_IS_OK(nt_status)) { + d_printf("%s (0x%x)\n", + error_string, + NT_STATUS_V(nt_status)); + SAFE_FREE(error_string); + return False; + } + + if (memcmp(nt_session_key.data, nt_key, + sizeof(nt_key)) != 0) { + DEBUG(1, ("NT Session Key does not match expectations!\n")); + DEBUG(1, ("nt_key:\n")); + dump_data(1, nt_key, 16); + DEBUG(1, ("expected:\n")); + dump_data(1, nt_session_key.data, nt_session_key.length); + pass = False; + } + return pass; +} + +/* + * Test the LMv2 response only + */ + +static BOOL test_lmv2(void) +{ + BOOL pass = True; + NTSTATUS nt_status; + uint32 flags = 0; + DATA_BLOB lmv2_response = data_blob(NULL, 0); + + DATA_BLOB chall = get_challenge(); + char *error_string; + + if (!SMBNTLMv2encrypt(opt_username, opt_domain, opt_password, &chall, + NULL, + &lmv2_response, NULL, + NULL)) { + return False; + } + + nt_status = contact_winbind_auth_crap(opt_username, opt_domain, + opt_workstation, + &chall, + &lmv2_response, + NULL, + flags, + NULL, + NULL, + &error_string); + + data_blob_free(&lmv2_response); + + if (!NT_STATUS_IS_OK(nt_status)) { + d_printf("%s (0x%x)\n", + error_string, + NT_STATUS_V(nt_status)); + SAFE_FREE(error_string); + return False; + } + + return pass; +} + +/* + * Test the normal 'LM and NTLM' combination but deliberately break one + */ + +static BOOL test_ntlm_broken(BOOL break_lm) +{ + BOOL pass = True; + NTSTATUS nt_status; + uint32 flags = 0; + DATA_BLOB lm_response = data_blob(NULL, 24); + DATA_BLOB nt_response = data_blob(NULL, 24); + DATA_BLOB session_key = data_blob(NULL, 16); + + uchar lm_key[8]; + uchar nt_key[16]; + uchar lm_hash[16]; + uchar nt_hash[16]; + DATA_BLOB chall = get_challenge(); + char *error_string; + + ZERO_STRUCT(lm_key); + ZERO_STRUCT(nt_key); + + flags |= WBFLAG_PAM_LMKEY; + flags |= WBFLAG_PAM_NTKEY; + + SMBencrypt(opt_password,chall.data,lm_response.data); + E_deshash(opt_password, lm_hash); + + SMBNTencrypt(opt_password,chall.data,nt_response.data); + + E_md4hash(opt_password, nt_hash); + SMBsesskeygen_ntv1(nt_hash, NULL, session_key.data); + + if (break_lm) + lm_response.data[0]++; + else + nt_response.data[0]++; + + nt_status = contact_winbind_auth_crap(opt_username, opt_domain, + opt_workstation, + &chall, + &lm_response, + &nt_response, + flags, + lm_key, + nt_key, + &error_string); + + data_blob_free(&lm_response); + + if (!NT_STATUS_IS_OK(nt_status)) { + d_printf("%s (0x%x)\n", + error_string, + NT_STATUS_V(nt_status)); + SAFE_FREE(error_string); + return False; + } + + if (memcmp(lm_hash, lm_key, + sizeof(lm_key)) != 0) { + DEBUG(1, ("LM Key does not match expectations!\n")); + DEBUG(1, ("lm_key:\n")); + dump_data(1, lm_key, 8); + DEBUG(1, ("expected:\n")); + dump_data(1, lm_hash, 8); + pass = False; + } + if (memcmp(session_key.data, nt_key, + sizeof(nt_key)) != 0) { + DEBUG(1, ("NT Session Key does not match expectations!\n")); + DEBUG(1, ("nt_key:\n")); + dump_data(1, nt_key, 16); + DEBUG(1, ("expected:\n")); + dump_data(1, session_key.data, session_key.length); + pass = False; + } + return pass; +} + +static BOOL test_ntlm_lm_broken(void) +{ + return test_ntlm_broken(True); +} + +static BOOL test_ntlm_ntlm_broken(void) +{ + return test_ntlm_broken(False); +} + +static BOOL test_ntlmv2_broken(BOOL break_lmv2) +{ + BOOL pass = True; + NTSTATUS nt_status; + uint32 flags = 0; + DATA_BLOB ntlmv2_response = data_blob(NULL, 0); + DATA_BLOB lmv2_response = data_blob(NULL, 0); + DATA_BLOB nt_session_key = data_blob(NULL, 0); + DATA_BLOB names_blob = NTLMv2_generate_names_blob(get_winbind_netbios_name(), get_winbind_domain()); + + uchar nt_key[16]; + DATA_BLOB chall = get_challenge(); + char *error_string; + + ZERO_STRUCT(nt_key); + + flags |= WBFLAG_PAM_NTKEY; + + if (!SMBNTLMv2encrypt(opt_username, opt_domain, opt_password, &chall, + &names_blob, + &lmv2_response, &ntlmv2_response, + &nt_session_key)) { + data_blob_free(&names_blob); + return False; + } + data_blob_free(&names_blob); + + /* Heh - this should break the appropriate password hash nicely! */ + + if (break_lmv2) + lmv2_response.data[0]++; + else + ntlmv2_response.data[0]++; + + nt_status = contact_winbind_auth_crap(opt_username, opt_domain, + opt_workstation, + &chall, + &lmv2_response, + &ntlmv2_response, + flags, + NULL, + nt_key, + &error_string); + + data_blob_free(&lmv2_response); + data_blob_free(&ntlmv2_response); + + if (!NT_STATUS_IS_OK(nt_status)) { + d_printf("%s (0x%x)\n", + error_string, + NT_STATUS_V(nt_status)); + SAFE_FREE(error_string); + return False; + } + + return pass; +} + +static BOOL test_ntlmv2_lmv2_broken(void) +{ + return test_ntlmv2_broken(True); +} + +static BOOL test_ntlmv2_ntlmv2_broken(void) +{ + return test_ntlmv2_broken(False); +} + /* Tests: - LM only - NT and LM - NT + - NT in LM field + - NT in both fields - NTLMv2 - NTLMv2 and LMv2 - LMv2 @@ -659,12 +1172,18 @@ struct ntlm_tests { BOOL (*fn)(void); const char *name; } test_table[] = { - {test_lm, "test LM"}, - {test_lm_ntlm, "test LM and NTLM"}, - {test_ntlm, "test NTLM"} -/* {test_lm_ntlmv2, "test NTLMv2"}, */ -/* {test_lm_ntlmv2, "test NTLMv2 and LMv2"}, */ -/* {test_lm_ntlmv2, "test LMv2"} */ + {test_lm, "LM"}, + {test_lm_ntlm, "LM and NTLM"}, + {test_ntlm, "NTLM"}, + {test_ntlm_in_lm, "NTLM in LM"}, + {test_ntlm_in_both, "NTLM in both"}, + {test_ntlmv2, "NTLMv2"}, + {test_lmv2_ntlmv2, "NTLMv2 and LMv2"}, + {test_lmv2, "LMv2"}, + {test_ntlmv2_lmv2_broken, "NTLMv2 and LMv2, LMv2 broken"}, + {test_ntlmv2_ntlmv2_broken, "NTLMv2 and LMv2, NTLMv2 broken"}, + {test_ntlm_lm_broken, "NTLM and LM, LM broken"}, + {test_ntlm_ntlm_broken, "NTLM and LM, NTLM broken"} }; static BOOL diagnose_ntlm_auth(void) @@ -701,6 +1220,8 @@ enum { int main(int argc, const char **argv) { int opt; + static const char *helper_protocol; + static int diagnostics; static const char *hex_challenge; static const char *hex_lm_response; @@ -743,6 +1264,14 @@ enum { dbf = x_stderr; + /* Samba client initialisation */ + + if (!lp_load(dyn_CONFIGFILE, True, False, False)) { + d_fprintf(stderr, "wbinfo: error opening config file %s. Error was %s\n", + dyn_CONFIGFILE, strerror(errno)); + exit(1); + } + /* Parse options */ pc = poptGetContext("ntlm_auth", argc, argv, long_options, 0); @@ -760,7 +1289,7 @@ enum { while((opt = poptGetNextOpt(pc)) != -1) { switch (opt) { case OPT_CHALLENGE: - challenge = smb_xmalloc((strlen(hex_challenge)+1)/2); + challenge = smb_xmalloc((strlen(hex_challenge))/2+1); if ((challenge_len = strhex_to_str(challenge, strlen(hex_challenge), hex_challenge)) != 8) { @@ -772,7 +1301,7 @@ enum { SAFE_FREE(challenge); break; case OPT_LM: - lm_response = smb_xmalloc((strlen(hex_lm_response)+1)/2); + lm_response = smb_xmalloc((strlen(hex_lm_response))/2+1); lm_response_len = strhex_to_str(lm_response, strlen(hex_lm_response), hex_lm_response); @@ -784,7 +1313,7 @@ enum { SAFE_FREE(lm_response); break; case OPT_NT: - nt_response = smb_xmalloc((strlen(hex_nt_response)+1)/2); + nt_response = smb_xmalloc((strlen(hex_nt_response)+2)/2+1); nt_response_len = strhex_to_str(nt_response, strlen(hex_nt_response), hex_nt_response); diff --git a/source3/utils/pdbedit.c b/source3/utils/pdbedit.c index d540bf42de..96d0d3c057 100644 --- a/source3/utils/pdbedit.c +++ b/source3/utils/pdbedit.c @@ -51,6 +51,21 @@ #define MASK_ALWAYS_GOOD 0x0000001F #define MASK_USER_GOOD 0x00401F00 +/***************************************************************************** + stubb functions +****************************************************************************/ + +void become_root( void ) +{ + return; +} + +void unbecome_root( void ) +{ + return; +} + + /********************************************************* Add all currently available users to another db ********************************************************/ @@ -91,7 +106,7 @@ static int export_groups (struct pdb_context *in, struct pdb_context *out) { if (NT_STATUS_IS_ERR(in->pdb_enum_group_mapping(in, SID_NAME_UNKNOWN, &maps, &entries, - False, False))) { + False))) { fprintf(stderr, "Can't get group mappings!\n"); return 1; } @@ -157,8 +172,7 @@ static int print_sam_info (SAM_ACCOUNT *sam_pwent, BOOL verbosity, BOOL smbpwdst char lm_passwd[33]; char nt_passwd[33]; - uid = -1; - sid_to_uid(pdb_get_user_sid(sam_pwent), &uid); + uid = nametouid(pdb_get_username(sam_pwent)); pdb_sethexpwd(lm_passwd, pdb_get_lanman_passwd(sam_pwent), pdb_get_acct_ctrl(sam_pwent)); pdb_sethexpwd(nt_passwd, pdb_get_nt_passwd(sam_pwent), pdb_get_acct_ctrl(sam_pwent)); @@ -170,8 +184,7 @@ static int print_sam_info (SAM_ACCOUNT *sam_pwent, BOOL verbosity, BOOL smbpwdst pdb_encode_acct_ctrl(pdb_get_acct_ctrl(sam_pwent),NEW_PW_FORMAT_SPACE_PADDED_LEN), (uint32)pdb_get_pass_last_set_time(sam_pwent)); } else { - uid = -1; - sid_to_uid(pdb_get_user_sid(sam_pwent), &uid); + uid = nametouid(pdb_get_username(sam_pwent)); printf ("%s:%d:%s\n", pdb_get_username(sam_pwent), uid, pdb_get_fullname(sam_pwent)); } @@ -337,7 +350,7 @@ static int new_user (struct pdb_context *in, const char *username, NTSTATUS nt_status; char *password1, *password2, *staticpass; - if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam_new(&sam_pwent, username))) { + if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam_new(&sam_pwent, username, 0))) { DEBUG(0, ("could not create account to add new user %s\n", username)); return -1; } @@ -485,7 +498,7 @@ static int delete_user_entry (struct pdb_context *in, const char *username) return -1; } - if (NT_STATUS_IS_ERR(in->pdb_getsampwnam(in, samaccount, username))) { + if (!NT_STATUS_IS_OK(in->pdb_getsampwnam(in, samaccount, username))) { fprintf (stderr, "user %s does not exist in the passdb\n", username); return -1; } @@ -511,7 +524,7 @@ static int delete_machine_entry (struct pdb_context *in, const char *machinename return -1; } - if (NT_STATUS_IS_ERR(in->pdb_getsampwnam(in, samaccount, name))) { + if (!NT_STATUS_IS_OK(in->pdb_getsampwnam(in, samaccount, name))) { fprintf (stderr, "machine %s does not exist in the passdb\n", name); return -1; } @@ -606,13 +619,10 @@ int main (int argc, char **argv) exit(1); } - if (!init_names()) - exit(1); - - if (!idmap_init()) + if(!initialize_password_db(False)) exit(1); - if (!idmap_init_wellknown_sids()) + if (!init_names()) exit(1); setparms = (backend ? BIT_BACKEND : 0) + diff --git a/source3/utils/profiles.c b/source3/utils/profiles.c index afaa83f638..23df26d150 100644 --- a/source3/utils/profiles.c +++ b/source3/utils/profiles.c @@ -454,6 +454,8 @@ static int get_sid(DOM_SID *sid, const unsigned char *sid_str) return 1; } +#if 0 + /* * Replace SID1, component by component with SID2 * Assumes will never be called with unequal length SIDS @@ -470,6 +472,8 @@ static void change_sid(DOM_SID *s1, DOM_SID *s2) } } +#endif + static void print_sid(DOM_SID *sid) { int i, comps = sid->num_auths; diff --git a/source3/utils/smbcacls.c b/source3/utils/smbcacls.c index 9d8a657726..69dc2dd47a 100644 --- a/source3/utils/smbcacls.c +++ b/source3/utils/smbcacls.c @@ -30,7 +30,6 @@ static int test_args = False; static TALLOC_CTX *ctx; #define CREATE_ACCESS_READ READ_CONTROL_ACCESS -#define CREATE_ACCESS_WRITE (WRITE_DAC_ACCESS | WRITE_OWNER_ACCESS) /* numeric is set when the user wants numeric SIDs and ACEs rather than going via LSA calls to resolve them */ @@ -506,11 +505,11 @@ static int owner_set(struct cli_state *cli, enum chown_mode change_mode, } sd = make_sec_desc(ctx,old->revision, - (change_mode == REQUEST_CHOWN) ? &sid : old->owner_sid, - (change_mode == REQUEST_CHGRP) ? &sid : old->grp_sid, - NULL, old->dacl, &sd_size); + (change_mode == REQUEST_CHOWN) ? &sid : NULL, + (change_mode == REQUEST_CHGRP) ? &sid : NULL, + NULL, NULL, &sd_size); - fnum = cli_nt_create(cli, filename, CREATE_ACCESS_WRITE); + fnum = cli_nt_create(cli, filename, WRITE_OWNER_ACCESS); if (fnum == -1) { printf("Failed to open %s: %s\n", filename, cli_errstr(cli)); @@ -680,10 +679,10 @@ static int cacl_set(struct cli_state *cli, char *filename, sort_acl(old->dacl); /* Create new security descriptor and set it */ - sd = make_sec_desc(ctx,old->revision, old->owner_sid, old->grp_sid, + sd = make_sec_desc(ctx,old->revision, NULL, NULL, NULL, old->dacl, &sd_size); - fnum = cli_nt_create(cli, filename, CREATE_ACCESS_WRITE); + fnum = cli_nt_create(cli, filename, WRITE_DAC_ACCESS); if (fnum == -1) { printf("cacl_set failed to open %s: %s\n", filename, cli_errstr(cli)); diff --git a/source3/utils/smbcontrol.c b/source3/utils/smbcontrol.c index 06add6af22..b7333f2317 100644 --- a/source3/utils/smbcontrol.c +++ b/source3/utils/smbcontrol.c @@ -34,7 +34,7 @@ static int num_replies; /* Used by message callback fns */ /* Send a message to a destination pid. Zero means broadcast smbd. */ -static BOOL send_message(pid_t pid, int msg_type, void *buf, int len, +static BOOL send_message(pid_t pid, int msg_type, const void *buf, int len, BOOL duplicates) { TDB_CONTEXT *tdb; @@ -92,7 +92,7 @@ static void print_string_cb(int msg_type, pid_t pid, void *buf, size_t len) /* Send no message. Useful for testing. */ -static BOOL do_noop(const pid_t pid, const int argc, char **argv) +static BOOL do_noop(const pid_t pid, const int argc, const char **argv) { if (argc != 1) { fprintf(stderr, "Usage: smbcontrol noop\n"); @@ -106,7 +106,7 @@ static BOOL do_noop(const pid_t pid, const int argc, char **argv) /* Send a debug string */ -static BOOL do_debug(const pid_t pid, const int argc, char **argv) +static BOOL do_debug(const pid_t pid, const int argc, const char **argv) { if (argc != 2) { fprintf(stderr, "Usage: smbcontrol debug " @@ -120,7 +120,7 @@ static BOOL do_debug(const pid_t pid, const int argc, char **argv) /* Force a browser election */ -static BOOL do_election(const pid_t pid, const int argc, char **argv) +static BOOL do_election(const pid_t pid, const int argc, const char **argv) { if (argc != 1) { fprintf(stderr, "Usage: smbcontrol force-election\n"); @@ -139,7 +139,7 @@ static void pong_cb(int msg_type, pid_t pid, void *buf, size_t len) num_replies++; } -static BOOL do_ping(const pid_t pid, const int argc, char **argv) +static BOOL do_ping(const pid_t pid, const int argc, const char **argv) { if (argc != 1) { fprintf(stderr, "Usage: smbcontrol ping\n"); @@ -167,7 +167,7 @@ static BOOL do_ping(const pid_t pid, const int argc, char **argv) /* Set profiling options */ -static BOOL do_profile(const pid_t pid, const int argc, char **argv) +static BOOL do_profile(const pid_t pid, const int argc, const char **argv) { int v; @@ -239,7 +239,7 @@ static void profilelevel_rqst(int msg_type, pid_t pid, void *buf, size_t len) send_message(pid, MSG_PROFILELEVEL, &v, sizeof(int), False); } -static BOOL do_profilelevel(const pid_t pid, const int argc, char **argv) +static BOOL do_profilelevel(const pid_t pid, const int argc, const char **argv) { if (argc != 1) { fprintf(stderr, "Usage: smbcontrol profilelevel\n"); @@ -268,7 +268,7 @@ static BOOL do_profilelevel(const pid_t pid, const int argc, char **argv) /* Display debug level settings */ -static BOOL do_debuglevel(const pid_t pid, const int argc, char **argv) +static BOOL do_debuglevel(const pid_t pid, const int argc, const char **argv) { if (argc != 1) { fprintf(stderr, "Usage: smbcontrol debuglevel\n"); @@ -296,9 +296,9 @@ static BOOL do_debuglevel(const pid_t pid, const int argc, char **argv) /* Send a print notify message */ -static BOOL do_printnotify(const pid_t pid, const int argc, char **argv) +static BOOL do_printnotify(const pid_t pid, const int argc, const char **argv) { - char *cmd; + const char *cmd; /* Check for subcommand */ @@ -434,7 +434,7 @@ send: /* Close a share */ -static BOOL do_closeshare(const pid_t pid, const int argc, char **argv) +static BOOL do_closeshare(const pid_t pid, const int argc, const char **argv) { if (argc != 2) { fprintf(stderr, "Usage: smbcontrol close-share " @@ -448,7 +448,7 @@ static BOOL do_closeshare(const pid_t pid, const int argc, char **argv) /* Force a SAM synchronisation */ -static BOOL do_samsync(const pid_t pid, const int argc, char **argv) +static BOOL do_samsync(const pid_t pid, const int argc, const char **argv) { if (argc != 1) { fprintf(stderr, "Usage: smbcontrol samsync\n"); @@ -461,7 +461,7 @@ static BOOL do_samsync(const pid_t pid, const int argc, char **argv) /* Force a SAM replication */ -static BOOL do_samrepl(const pid_t pid, const int argc, char **argv) +static BOOL do_samrepl(const pid_t pid, const int argc, const char **argv) { if (argc != 1) { fprintf(stderr, "Usage: smbcontrol samrepl\n"); @@ -474,7 +474,7 @@ static BOOL do_samrepl(const pid_t pid, const int argc, char **argv) /* Display talloc pool usage */ -static BOOL do_poolusage(const pid_t pid, const int argc, char **argv) +static BOOL do_poolusage(const pid_t pid, const int argc, const char **argv) { if (argc != 1) { fprintf(stderr, "Usage: smbcontrol pool-usage\n"); @@ -502,7 +502,7 @@ static BOOL do_poolusage(const pid_t pid, const int argc, char **argv) /* Perform a dmalloc mark */ -static BOOL do_dmalloc_mark(const pid_t pid, const int argc, char **argv) +static BOOL do_dmalloc_mark(const pid_t pid, const int argc, const char **argv) { if (argc != 1) { fprintf(stderr, "Usage: smbcontrol dmalloc-mark\n"); @@ -515,8 +515,7 @@ static BOOL do_dmalloc_mark(const pid_t pid, const int argc, char **argv) /* Perform a dmalloc changed */ -static BOOL do_dmalloc_changed(const pid_t pid, const int argc, - char **argv) +static BOOL do_dmalloc_changed(const pid_t pid, const int argc, const char **argv) { if (argc != 1) { fprintf(stderr, "Usage: smbcontrol " @@ -530,7 +529,7 @@ static BOOL do_dmalloc_changed(const pid_t pid, const int argc, /* Shutdown a server process */ -static BOOL do_shutdown(const pid_t pid, const int argc, char **argv) +static BOOL do_shutdown(const pid_t pid, const int argc, const char **argv) { if (argc != 1) { fprintf(stderr, "Usage: smbcontrol shutdown\n"); @@ -542,7 +541,7 @@ static BOOL do_shutdown(const pid_t pid, const int argc, char **argv) /* Notify a driver upgrade */ -static BOOL do_drvupgrade(const pid_t pid, const int argc, char **argv) +static BOOL do_drvupgrade(const pid_t pid, const int argc, const char **argv) { if (argc != 2) { fprintf(stderr, "Usage: smbcontrol drvupgrade " @@ -554,11 +553,21 @@ static BOOL do_drvupgrade(const pid_t pid, const int argc, char **argv) pid, MSG_DEBUG, argv[1], strlen(argv[1]) + 1, False); } +static BOOL do_reload_config(const pid_t pid, const int argc, const char **argv) +{ + if (argc != 1) { + fprintf(stderr, "Usage: smbcontrol reload-config\n"); + return False; + } + + return send_message(pid, MSG_SMB_CONF_UPDATED, NULL, 0, False); +} + /* A list of message type supported */ static const struct { const char *name; /* Option name */ - BOOL (*fn)(const pid_t pid, const int argc, char **argv); + BOOL (*fn)(const pid_t pid, const int argc, const char **argv); const char *help; /* Short help text */ } msg_types[] = { { "debug", do_debug, "Set debuglevel" }, @@ -577,6 +586,7 @@ static const struct { { "dmalloc-log-changed", do_dmalloc_changed, "" }, { "shutdown", do_shutdown, "Shut down daemon" }, { "drvupgrade", do_drvupgrade, "Notify a printer driver has changed" }, + { "reload-config", do_reload_config, "Force smbd or winbindd to reload config file"}, { "noop", do_noop, "Do nothing" }, { NULL } }; @@ -613,7 +623,7 @@ static void usage(poptContext *pc) /* Return the pid number for a string destination */ -static pid_t parse_dest(char *dest) +static pid_t parse_dest(const char *dest) { pid_t pid; @@ -644,9 +654,9 @@ static pid_t parse_dest(char *dest) /* Execute smbcontrol command */ -static BOOL do_command(int argc, char **argv) +static BOOL do_command(int argc, const char **argv) { - char *dest = argv[0], *command = argv[1]; + const char *dest = argv[0], *command = argv[1]; pid_t pid; int i; @@ -669,7 +679,7 @@ static BOOL do_command(int argc, char **argv) /* Main program */ -int main(int argc, char **argv) +int main(int argc, const char **argv) { poptContext pc; int opt; @@ -726,7 +736,7 @@ int main(int argc, char **argv) argv. The argc parameter should have been decremented to the correct value in the above switch statement. */ - argv = (char **)poptGetArgs(pc); + argv = (const char **)poptGetArgs(pc); argc--; /* Don't forget about argv[0] */ if (argc == 1) diff --git a/source3/utils/smbpasswd.c b/source3/utils/smbpasswd.c index 577e467fbd..eade5331af 100644 --- a/source3/utils/smbpasswd.c +++ b/source3/utils/smbpasswd.c @@ -37,6 +37,21 @@ static const char *remote_machine = NULL; static fstring ldap_secret; +/***************************************************************************** + stubb functions +****************************************************************************/ + +void become_root( void ) +{ + return; +} + +void unbecome_root( void ) +{ + return; +} + + /********************************************************* Print command usage on stderr and die. **********************************************************/ @@ -392,7 +407,7 @@ static int process_root(int local_flags) if (local_flags & LOCAL_ADD_USER) { SAFE_FREE(new_passwd); new_passwd = smb_xstrdup(user_name); - strlower(new_passwd); + strlower_m(new_passwd); } /* @@ -405,7 +420,7 @@ static int process_root(int local_flags) } else if (local_flags & LOCAL_INTERDOM_ACCOUNT) { static fstring buf; - if (local_flags & LOCAL_ADD_USER) { + if ((local_flags & LOCAL_ADD_USER) && (new_passwd == NULL)) { /* * Prompt for trusting domain's account password */ @@ -450,7 +465,7 @@ static int process_root(int local_flags) } } - if(local_flags & LOCAL_SET_PASSWORD) { + if((local_flags & LOCAL_SET_PASSWORD) && (new_passwd == NULL)) { new_passwd = prompt_for_new_password(stdin_passwd_get); if(!new_passwd) { diff --git a/source3/utils/testparm.c b/source3/utils/testparm.c index e3d6ce0274..16918ecd4a 100644 --- a/source3/utils/testparm.c +++ b/source3/utils/testparm.c @@ -183,6 +183,10 @@ via the %%o substitution. With encrypted passwords this is not possible.\n", lp_ } #endif + if (!lp_passdb_backend()) { + printf("ERROR: passdb backend must have a value or be left out\n"); + } + return ret; } diff --git a/source3/web/swat.c b/source3/web/swat.c index 7f9492933a..d97278c485 100644 --- a/source3/web/swat.c +++ b/source3/web/swat.c @@ -31,8 +31,6 @@ #include "includes.h" #include "../web/swat_proto.h" -#define GLOBALS_SNUM -1 - static BOOL demo_mode = False; static BOOL have_write_access = False; static BOOL have_read_access = False; @@ -579,7 +577,7 @@ static void wizard_params_page(void) d_printf("

Wizard Parameter Edit Page

\n"); if (cgi_variable("Commit")) { - commit_parameters(GLOBALS_SNUM); + commit_parameters(GLOBAL_SECTION_SNUM); save_reload(0); } @@ -593,7 +591,7 @@ static void wizard_params_page(void) d_printf("

\n"); d_printf("\n"); - show_parameters(GLOBALS_SNUM, 1, parm_filter, 0); + show_parameters(GLOBAL_SECTION_SNUM, 1, parm_filter, 0); d_printf("
\n"); d_printf("\n"); } @@ -603,7 +601,7 @@ static void wizard_params_page(void) ****************************************************************************/ static void rewritecfg_file(void) { - commit_parameters(GLOBALS_SNUM); + commit_parameters(GLOBAL_SECTION_SNUM); save_reload(0); d_printf("

Note: smb.conf %s

\n", _("file has been read and rewritten")); } @@ -637,37 +635,37 @@ static void wizard_page(void) HomeExpo = atoi(cgi_variable("HomeExpo")); /* Plain text passwords are too badly broken - use encrypted passwords only */ - lp_do_parameter( GLOBALS_SNUM, "encrypt passwords", "Yes"); + lp_do_parameter( GLOBAL_SECTION_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" ); + lp_do_parameter( GLOBAL_SECTION_SNUM, "security", "USER" ); + lp_do_parameter( GLOBAL_SECTION_SNUM, "domain logons", "No" ); break; case 1: /* Domain Member */ - lp_do_parameter( GLOBALS_SNUM, "security", "DOMAIN" ); - lp_do_parameter( GLOBALS_SNUM, "domain logons", "No" ); + lp_do_parameter( GLOBAL_SECTION_SNUM, "security", "DOMAIN" ); + lp_do_parameter( GLOBAL_SECTION_SNUM, "domain logons", "No" ); break; case 2: /* Domain Controller */ - lp_do_parameter( GLOBALS_SNUM, "security", "USER" ); - lp_do_parameter( GLOBALS_SNUM, "domain logons", "Yes" ); + lp_do_parameter( GLOBAL_SECTION_SNUM, "security", "USER" ); + lp_do_parameter( GLOBAL_SECTION_SNUM, "domain logons", "Yes" ); break; } switch ( winstype ) { case 0: - lp_do_parameter( GLOBALS_SNUM, "wins support", "No" ); - lp_do_parameter( GLOBALS_SNUM, "wins server", "" ); + lp_do_parameter( GLOBAL_SECTION_SNUM, "wins support", "No" ); + lp_do_parameter( GLOBAL_SECTION_SNUM, "wins server", "" ); break; case 1: - lp_do_parameter( GLOBALS_SNUM, "wins support", "Yes" ); - lp_do_parameter( GLOBALS_SNUM, "wins server", "" ); + lp_do_parameter( GLOBAL_SECTION_SNUM, "wins support", "Yes" ); + lp_do_parameter( GLOBAL_SECTION_SNUM, "wins server", "" ); break; case 2: - lp_do_parameter( GLOBALS_SNUM, "wins support", "No" ); - lp_do_parameter( GLOBALS_SNUM, "wins server", cgi_variable("WINSAddr")); + lp_do_parameter( GLOBAL_SECTION_SNUM, "wins support", "No" ); + lp_do_parameter( GLOBAL_SECTION_SNUM, "wins server", cgi_variable("WINSAddr")); break; } @@ -677,7 +675,7 @@ static void wizard_page(void) pstrcpy(unix_share,HOMES_NAME); load_config(False); - lp_copy_service(GLOBALS_SNUM, unix_share); + lp_copy_service(GLOBAL_SECTION_SNUM, unix_share); iNumNonAutoPrintServices = lp_numservices(); have_home = lp_servicenumber(HOMES_NAME); lp_do_parameter( have_home, "read only", "No"); @@ -692,7 +690,7 @@ static void wizard_page(void) have_home = -1; } - commit_parameters(GLOBALS_SNUM); + commit_parameters(GLOBAL_SECTION_SNUM); save_reload(0); } else @@ -778,7 +776,7 @@ static void globals_page(void) d_printf("

%s

\n", _("Global Variables")); if (cgi_variable("Commit")) { - commit_parameters(GLOBALS_SNUM); + commit_parameters(GLOBAL_SECTION_SNUM); save_reload(0); } @@ -810,7 +808,7 @@ static void globals_page(void) d_printf("

\n"); d_printf("\n"); - show_parameters(GLOBALS_SNUM, 1, parm_filter, 0); + show_parameters(GLOBAL_SECTION_SNUM, 1, parm_filter, 0); d_printf("
\n"); d_printf("\n"); } @@ -847,7 +845,7 @@ static void shares_page(void) if (cgi_variable("createshare") && (share=cgi_variable("newshare"))) { load_config(False); - lp_copy_service(GLOBALS_SNUM, share); + lp_copy_service(GLOBAL_SECTION_SNUM, share); iNumNonAutoPrintServices = lp_numservices(); save_reload(0); snum = lp_servicenumber(share); @@ -1186,7 +1184,7 @@ static void printers_page(void) if (cgi_variable("createshare") && (share=cgi_variable("newshare"))) { load_config(False); - lp_copy_service(GLOBALS_SNUM, share); + lp_copy_service(GLOBAL_SECTION_SNUM, share); iNumNonAutoPrintServices = lp_numservices(); snum = lp_servicenumber(share); lp_do_parameter(snum, "print ok", "Yes"); -- cgit From 1caa6b23e417f77e7b38ecdfa47d9abe8c7b7d0e Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Wed, 16 Jul 2003 05:42:34 +0000 Subject: ading new files from 3.0 (This used to be commit 99feae7b5b1c229a925367b87c0c0f636d9a2d75) --- source3/build-me | 36 ++ source3/include/smbldap.h | 142 +++++ source3/include/sysquotas.h | 204 ++++++ source3/include/vfs_macros.h | 309 +++++++++ source3/intl/libgettext.h | 0 source3/lib/smbldap.c | 1262 +++++++++++++++++++++++++++++++++++++ source3/lib/sysquotas.c | 963 ++++++++++++++++++++++++++++ source3/libsmb/conncache.c | 158 +++++ source3/libsmb/samlogon_cache.c | 238 +++++++ source3/mainpage.dox | 7 + source3/modules/weird.c | 131 ++++ source3/nsswitch/winbindd_acct.c | 1209 +++++++++++++++++++++++++++++++++++ source3/pam_smbpass/.cvsignore | 1 + source3/passdb/pdb_plugin.c | 78 +++ source3/script/mkbuildoptions.awk | 262 ++++++++ source3/smbd/fake_file.c | 166 +++++ source3/smbd/ntquotas.c | 259 ++++++++ source3/tdb/tdbback.c | 201 ++++++ source3/tdb/tdbback.h | 23 + source3/utils/net_idmap.c | 156 +++++ 20 files changed, 5805 insertions(+) create mode 100755 source3/build-me create mode 100644 source3/include/smbldap.h create mode 100644 source3/include/sysquotas.h create mode 100644 source3/include/vfs_macros.h create mode 100644 source3/intl/libgettext.h create mode 100644 source3/lib/smbldap.c create mode 100644 source3/lib/sysquotas.c create mode 100644 source3/libsmb/conncache.c create mode 100644 source3/libsmb/samlogon_cache.c create mode 100644 source3/mainpage.dox create mode 100644 source3/modules/weird.c create mode 100644 source3/nsswitch/winbindd_acct.c create mode 100644 source3/pam_smbpass/.cvsignore create mode 100644 source3/passdb/pdb_plugin.c create mode 100644 source3/script/mkbuildoptions.awk create mode 100644 source3/smbd/fake_file.c create mode 100644 source3/smbd/ntquotas.c create mode 100644 source3/tdb/tdbback.c create mode 100644 source3/tdb/tdbback.h create mode 100644 source3/utils/net_idmap.c (limited to 'source3') diff --git a/source3/build-me b/source3/build-me new file mode 100755 index 0000000000..a5d3f32f70 --- /dev/null +++ b/source3/build-me @@ -0,0 +1,36 @@ +#!/bin/sh + +umask 022 + +## Build options +CONFIGUREOPT="--enable-debug --enable-developer --with-pam --with-libsmbclient=no --with-static-modules" +export CONFIGUREOPT + +./autogen.sh + +case "$1" in + dmalloc) + env CFLAGS="-Wall" ./configure \ + --enable-dmalloc \ + $CONFIGUREOPT + ;; + insure) + env CFLAGS="-g" CC="insure" ./configure \ + $CONFIGUREOPT + ;; + ccache) + env CFLAGS="-Wall" CC="ccache gcc" ./configure \ + $CONFIGUREOPT + ;; + *) + env CFLAGS="-Wall" ./configure \ + $CONFIGUREOPT + ;; +esac + +## disable optimization +sed 's/-O //g' Makefile | sed 's/-O2 //g' > Makefile.new; /bin/mv -f Makefile.new Makefile + +## build +make proto +make all modules diff --git a/source3/include/smbldap.h b/source3/include/smbldap.h new file mode 100644 index 0000000000..589d01aa6d --- /dev/null +++ b/source3/include/smbldap.h @@ -0,0 +1,142 @@ +/* + Unix SMB/CIFS mplementation. + LDAP protocol helper functions for SAMBA + Copyright (C) Gerald Carter 2001-2003 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifndef _SMBLDAP_H +#define _SMBLDAP_H + +#ifdef HAVE_LDAP + +/* specify schema versions between 2.2. and 3.0 */ + +#define SCHEMAVER_SAMBAACCOUNT 1 +#define SCHEMAVER_SAMBASAMACCOUNT 2 + +/* objectclass names */ + +#define LDAP_OBJ_SAMBASAMACCOUNT "sambaSamAccount" +#define LDAP_OBJ_SAMBAACCOUNT "sambaAccount" +#define LDAP_OBJ_GROUPMAP "sambaGroupMapping" +#define LDAP_OBJ_DOMINFO "sambaDomain" +#define LDAP_OBJ_IDPOOL "sambaUnixIdPool" +#define LDAP_OBJ_IDMAP_ENTRY "sambaIdmapEntry" +#define LDAP_OBJ_SID_ENTRY "sambaSidEntry" + +#define LDAP_OBJ_ACCOUNT "account" +#define LDAP_OBJ_POSIXACCOUNT "posixAccount" +#define LDAP_OBJ_POSIXGROUP "posixGroup" +#define LDAP_OBJ_OU "organizationalUnit" + +/* some generic attributes that get reused a lot */ + +#define LDAP_ATTRIBUTE_SID "sambaSID" +#define LDAP_ATTRIBUTE_UIDNUMBER "uidNumber" +#define LDAP_ATTRIBUTE_GIDNUMBER "gidNumber" + +/* attribute map table indexes */ + +#define LDAP_ATTR_LIST_END 0 +#define LDAP_ATTR_UID 1 +#define LDAP_ATTR_UIDNUMBER 2 +#define LDAP_ATTR_GIDNUMBER 3 +#define LDAP_ATTR_UNIX_HOME 4 +#define LDAP_ATTR_PWD_LAST_SET 5 +#define LDAP_ATTR_PWD_CAN_CHANGE 6 +#define LDAP_ATTR_PWD_MUST_CHANGE 7 +#define LDAP_ATTR_LOGON_TIME 8 +#define LDAP_ATTR_LOGOFF_TIME 9 +#define LDAP_ATTR_KICKOFF_TIME 10 +#define LDAP_ATTR_CN 11 +#define LDAP_ATTR_DISPLAY_NAME 12 +#define LDAP_ATTR_HOME_PATH 13 +#define LDAP_ATTR_LOGON_SCRIPT 14 +#define LDAP_ATTR_PROFILE_PATH 15 +#define LDAP_ATTR_DESC 16 +#define LDAP_ATTR_USER_WKS 17 +#define LDAP_ATTR_USER_SID 18 +#define LDAP_ATTR_USER_RID 18 +#define LDAP_ATTR_PRIMARY_GROUP_SID 19 +#define LDAP_ATTR_PRIMARY_GROUP_RID 20 +#define LDAP_ATTR_LMPW 21 +#define LDAP_ATTR_NTPW 22 +#define LDAP_ATTR_DOMAIN 23 +#define LDAP_ATTR_OBJCLASS 24 +#define LDAP_ATTR_ACB_INFO 25 +#define LDAP_ATTR_NEXT_USERRID 26 +#define LDAP_ATTR_NEXT_GROUPRID 27 +#define LDAP_ATTR_DOM_SID 28 +#define LDAP_ATTR_HOME_DRIVE 29 +#define LDAP_ATTR_GROUP_SID 30 +#define LDAP_ATTR_GROUP_TYPE 31 +#define LDAP_ATTR_SID 32 +#define LDAP_ATTR_ALGORITHMIC_RID_BASE 33 +#define LDAP_ATTR_NEXT_RID 34 + +typedef struct _attrib_map_entry { + int attrib; + const char *name; +} ATTRIB_MAP_ENTRY; + + +/* structures */ + +extern ATTRIB_MAP_ENTRY attrib_map_v22[]; +extern ATTRIB_MAP_ENTRY attrib_map_v30[]; +extern ATTRIB_MAP_ENTRY dominfo_attr_list[]; +extern ATTRIB_MAP_ENTRY groupmap_attr_list[]; +extern ATTRIB_MAP_ENTRY groupmap_attr_list_to_delete[]; +extern ATTRIB_MAP_ENTRY idpool_attr_list[]; +extern ATTRIB_MAP_ENTRY sidmap_attr_list[]; + +/* Function declarations -- not included in proto.h so we don't + have to worry about LDAP structure types */ + +const char* get_attr_key2string( ATTRIB_MAP_ENTRY table[], int key ); +char** get_attr_list( ATTRIB_MAP_ENTRY table[] ); +void free_attr_list( char **list ); +void smbldap_set_mod (LDAPMod *** modlist, int modop, const char *attribute, const char *value); +void smbldap_make_mod(LDAP *ldap_struct, LDAPMessage *existing, + LDAPMod ***mods, + const char *attribute, const char *newval); +BOOL smbldap_get_single_attribute (LDAP * ldap_struct, LDAPMessage * entry, + const char *attribute, pstring value); + +/** + * Struct to keep the state for all the ldap stuff + * + */ + +struct smbldap_state { + LDAP *ldap_struct; + time_t last_ping; + /* retrive-once info */ + const char *uri; + char *bind_dn; + char *bind_secret; + + unsigned int num_failures; +}; + +#endif /* HAVE_LDAP */ + +struct smbldap_state; + +#endif /* _SMBLDAP_H */ + diff --git a/source3/include/sysquotas.h b/source3/include/sysquotas.h new file mode 100644 index 0000000000..cfdac0609a --- /dev/null +++ b/source3/include/sysquotas.h @@ -0,0 +1,204 @@ +/* + Unix SMB/CIFS implementation. + SYS QUOTA code constants + Copyright (C) Stefan (metze) Metzmacher 2003 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef _SYSQUOTAS_H +#define _SYSQUOTAS_H + +#ifdef HAVE_SYS_QUOTAS + +/* Sometimes we need this on linux for linux/quota.h */ +#ifdef HAVE_SYS_TYPES_H +#include +#endif + +#ifdef HAVE_ASM_TYPES_H +#include +#endif + +/* + * This shouldn't be neccessary - it should be /usr/include/sys/quota.h + * Unfortunately, RH7.1 ships with a different quota system using struct mem_dqblk + * rather than the struct dqblk defined in /usr/include/sys/quota.h. + * This means we must include linux/quota.h to have a hope of working on + * RH7.1 systems. And it also means this breaks if the kernel is upgraded + * to a Linus 2.4.x (where x > the minor number shipped with RH7.1) until + * Linus synchronises with the AC patches. Sometimes I *hate* Linux :-). JRA. + */ +#ifdef HAVE_LINUX_QUOTA_H +#include +#elif defined(HAVE_SYS_QUOTA_H) +#include +#endif + +#if defined(HAVE_STRUCT_IF_DQBLK) +# define SYS_DQBLK if_dqblk +# define dqb_curblocks dqb_curspace/bsize +#elif defined(HAVE_STRUCT_MEM_DQBLK) +# define SYS_DQBLK mem_dqblk +# define dqb_curblocks dqb_curspace/bsize +#else /* STRUCT_DQBLK */ +# define SYS_DQBLK dqblk +#endif + +#ifndef Q_SETQLIM +#define Q_SETQLIM Q_SETQUOTA +#endif + +/********************************************* + check for XFS QUOTA MANAGER + *********************************************/ +/* on linux */ +#ifdef HAVE_LINUX_XQM_H +# include +# define HAVE_XFS_QUOTA +#else +# ifdef HAVE_XFS_XQM_H +# include +# define HAVE_XFS_QUOTA +# else +# ifdef HAVE_LINUX_DQBLK_XFS_H +# include +# define HAVE_XFS_QUOTA +# endif +# endif +#endif +/* on IRIX */ +#ifdef Q_XGETQUOTA +# ifndef HAVE_XFS_QUOTA +# define HAVE_XFS_QUOTA +# ifndef Q_XQUOTAON +# define Q_XQUOTAON Q_QUOTAON +# endif /* Q_XQUOTAON */ +# ifndef Q_XQUOTAOFF +# define Q_XQUOTAOFF Q_QUOTAOFF +# endif /* Q_XQUOTAOFF */ +# ifndef Q_XGETQSTAT +# define Q_XGETQSTAT Q_GETQSTAT +# endif /* Q_XGETQSTAT */ +# endif /* HAVE_XFS_QUOTA */ +#endif /* Q_XGETQUOTA */ + +#ifdef HAVE_XFS_QUOTA +/* Linux has BBSIZE in + * or + * IRIX has BBSIZE in + */ +#ifdef HAVE_LINUX_XFS_FS_H +#include +#elif defined(HAVE_XFS_XFS_FS_H) +#include +#endif /* *_XFS_FS_H */ + +#ifndef BBSHIFT +#define BBSHIFT 9 +#endif /* BBSHIFT */ +#ifndef BBSIZE +#define BBSIZE (1< +#define HAVE_MNTENT 1 +/*#endif defined(HAVE_MNTENT_H)&&defined(HAVE_SETMNTENT)&&defined(HAVE_GETMNTENT)&&defined(HAVE_ENDMNTENT) */ +#elif defined(HAVE_DEVNM_H)&&defined(HAVE_DEVNM) +#include +#endif /* defined(HAVE_DEVNM_H)&&defined(HAVE_DEVNM) */ + +#endif /* HAVE_SYS_QUOTAS */ + + +#ifndef QUOTABLOCK_SIZE +#define QUOTABLOCK_SIZE 1024 +#endif + +/************************************************** + Some stuff for the sys_quota api. + **************************************************/ + +#define SMB_QUOTAS_NO_LIMIT ((SMB_BIG_UINT)(0)) +#define SMB_QUOTAS_NO_SPACE ((SMB_BIG_UINT)(1)) + +typedef struct _SMB_DISK_QUOTA { + enum SMB_QUOTA_TYPE qtype; + SMB_BIG_UINT bsize; + SMB_BIG_UINT hardlimit; /* In bsize units. */ + SMB_BIG_UINT softlimit; /* In bsize units. */ + SMB_BIG_UINT curblocks; /* In bsize units. */ + SMB_BIG_UINT ihardlimit; /* inode hard limit. */ + SMB_BIG_UINT isoftlimit; /* inode soft limit. */ + SMB_BIG_UINT curinodes; /* Current used inodes. */ + uint32 qflags; +} SMB_DISK_QUOTA; + +#endif /*_SYSQUOTAS_H */ diff --git a/source3/include/vfs_macros.h b/source3/include/vfs_macros.h new file mode 100644 index 0000000000..fdbc1516e3 --- /dev/null +++ b/source3/include/vfs_macros.h @@ -0,0 +1,309 @@ +/* + Unix SMB/CIFS implementation. + VFS wrapper macros + Copyright (C) Stefan (metze) Metzmacher 2003 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef _VFS_MACROS_H +#define _VFS_MACROS_H + +/******************************************************************* + Don't access conn->vfs.ops.* directly!!! + Use this macros! + (Fixes should go also into the vfs_opaque_* and vfs_next_* macros!) +********************************************************************/ + +/* Disk operations */ +#define SMB_VFS_CONNECT(conn, service, user) ((conn)->vfs.ops.connect((conn)->vfs.handles.connect, (conn), (service), (user))) +#define SMB_VFS_DISCONNECT(conn) ((conn)->vfs.ops.disconnect((conn)->vfs.handles.disconnect, (conn))) +#define SMB_VFS_DISK_FREE(conn, path, small_query, bsize, dfree ,dsize) ((conn)->vfs.ops.disk_free((conn)->vfs.handles.disk_free, (conn), (path), (small_query), (bsize), (dfree), (dsize))) +#define SMB_VFS_GET_QUOTA(conn, qtype, id, qt) ((conn)->vfs.ops.get_quota((conn)->vfs.handles.get_quota, (conn), (qtype), (id), (qt))) +#define SMB_VFS_SET_QUOTA(conn, qtype, id, qt) ((conn)->vfs.ops.set_quota((conn)->vfs.handles.set_quota, (conn), (qtype), (id), (qt))) + +/* Directory operations */ +#define SMB_VFS_OPENDIR(conn, fname) ((conn)->vfs.ops.opendir((conn)->vfs.handles.opendir, (conn), (fname))) +#define SMB_VFS_READDIR(conn, dirp) ((conn)->vfs.ops.readdir((conn)->vfs.handles.readdir, (conn), (dirp))) +#define SMB_VFS_MKDIR(conn, path, mode) ((conn)->vfs.ops.mkdir((conn)->vfs.handles.mkdir,(conn), (path), (mode))) +#define SMB_VFS_RMDIR(conn, path) ((conn)->vfs.ops.rmdir((conn)->vfs.handles.rmdir, (conn), (path))) +#define SMB_VFS_CLOSEDIR(conn, dir) ((conn)->vfs.ops.closedir((conn)->vfs.handles.closedir, (conn), dir)) + +/* File operations */ +#define SMB_VFS_OPEN(conn, fname, flags, mode) ((conn)->vfs.ops.open((conn)->vfs.handles.open, (conn), (fname), (flags), (mode))) +#define SMB_VFS_CLOSE(fsp, fd) ((fsp)->conn->vfs.ops.close((fsp)->conn->vfs.handles.close, (fsp), (fd))) +#define SMB_VFS_READ(fsp, fd, data, n) ((fsp)->conn->vfs.ops.read((fsp)->conn->vfs.handles.read, (fsp), (fd), (data), (n))) +#define SMB_VFS_WRITE(fsp, fd, data, n) ((fsp)->conn->vfs.ops.write((fsp)->conn->vfs.handles.write, (fsp), (fd), (data), (n))) +#define SMB_VFS_LSEEK(fsp, fd, offset, whence) ((fsp)->conn->vfs.ops.lseek((fsp)->conn->vfs.handles.lseek, (fsp), (fd), (offset), (whence))) +#define SMB_VFS_SENDFILE(tofd, fsp, fromfd, header, offset, count) ((fsp)->conn->vfs.ops.sendfile((fsp)->conn->vfs.handles.sendfile, (tofd), (fsp), (fromfd), (header), (offset), (count))) +#define SMB_VFS_RENAME(conn, old, new) ((conn)->vfs.ops.rename((conn)->vfs.handles.rename, (conn), (old), (new))) +#define SMB_VFS_FSYNC(fsp, fd) ((fsp)->conn->vfs.ops.fsync((fsp)->conn->vfs.handles.fsync, (fsp), (fd))) +#define SMB_VFS_STAT(conn, fname, sbuf) ((conn)->vfs.ops.stat((conn)->vfs.handles.stat, (conn), (fname), (sbuf))) +#define SMB_VFS_FSTAT(fsp, fd, sbuf) ((fsp)->conn->vfs.ops.fstat((fsp)->conn->vfs.handles.fstat, (fsp) ,(fd) ,(sbuf))) +#define SMB_VFS_LSTAT(conn, path, sbuf) ((conn)->vfs.ops.lstat((conn)->vfs.handles.lstat, (conn), (path), (sbuf))) +#define SMB_VFS_UNLINK(conn, path) ((conn)->vfs.ops.unlink((conn)->vfs.handles.unlink, (conn), (path))) +#define SMB_VFS_CHMOD(conn, path, mode) ((conn)->vfs.ops.chmod((conn)->vfs.handles.chmod, (conn), (path), (mode))) +#define SMB_VFS_FCHMOD(fsp, fd, mode) ((fsp)->conn->vfs.ops.fchmod((fsp)->conn->vfs.handles.fchmod, (fsp), (fd), (mode))) +#define SMB_VFS_CHOWN(conn, path, uid, gid) ((conn)->vfs.ops.chown((conn)->vfs.handles.chown, (conn), (path), (uid), (gid))) +#define SMB_VFS_FCHOWN(fsp, fd, uid, gid) ((fsp)->conn->vfs.ops.fchown((fsp)->conn->vfs.handles.fchown, (fsp), (fd), (uid), (gid))) +#define SMB_VFS_CHDIR(conn, path) ((conn)->vfs.ops.chdir((conn)->vfs.handles.chdir, (conn), (path))) +#define SMB_VFS_GETWD(conn, buf) ((conn)->vfs.ops.getwd((conn)->vfs.handles.getwd, (conn), (buf))) +#define SMB_VFS_UTIME(conn, path, times) ((conn)->vfs.ops.utime((conn)->vfs.handles.utime, (conn), (path), (times))) +#define SMB_VFS_FTRUNCATE(fsp, fd, offset) ((fsp)->conn->vfs.ops.ftruncate((fsp)->conn->vfs.handles.ftruncate, (fsp), (fd), (offset))) +#define SMB_VFS_LOCK(fsp, fd, op, offset, count, type) ((fsp)->conn->vfs.ops.lock((fsp)->conn->vfs.handles.lock, (fsp), (fd) ,(op), (offset), (count), (type))) +#define SMB_VFS_SYMLINK(conn, oldpath, newpath) ((conn)->vfs.ops.symlink((conn)->vfs.handles.symlink, (conn), (oldpath), (newpath))) +#define SMB_VFS_READLINK(conn, path, buf, bufsiz) ((conn)->vfs.ops.readlink((conn)->vfs.handles.readlink, (conn), (path), (buf), (bufsiz))) +#define SMB_VFS_LINK(conn, oldpath, newpath) ((conn)->vfs.ops.link((conn)->vfs.handles.link, (conn), (oldpath), (newpath))) +#define SMB_VFS_MKNOD(conn, path, mode, dev) ((conn)->vfs.ops.mknod((conn)->vfs.handles.mknod, (conn), (path), (mode), (dev))) +#define SMB_VFS_REALPATH(conn, path, resolved_path) ((conn)->vfs.ops.realpath((conn)->vfs.handles.realpath, (conn), (path), (resolved_path))) + +/* NT ACL operations. */ +#define SMB_VFS_FGET_NT_ACL(fsp, fd, security_info, ppdesc) ((fsp)->conn->vfs.ops.fget_nt_acl((fsp)->conn->vfs.handles.fget_nt_acl, (fsp), (fd), (security_info), (ppdesc))) +#define SMB_VFS_GET_NT_ACL(fsp, name, security_info, ppdesc) ((fsp)->conn->vfs.ops.get_nt_acl((fsp)->conn->vfs.handles.get_nt_acl, (fsp), (name), (security_info), (ppdesc))) +#define SMB_VFS_FSET_NT_ACL(fsp, fd, security_info_sent, psd) ((fsp)->conn->vfs.ops.fset_nt_acl((fsp)->conn->vfs.handles.fset_nt_acl, (fsp), (fd), (security_info_sent), (psd))) +#define SMB_VFS_SET_NT_ACL(fsp, name, security_info_sent, psd) ((fsp)->conn->vfs.ops.set_nt_acl((fsp)->conn->vfs.handles.set_nt_acl, (fsp), (name), (security_info_sent), (psd))) + +/* POSIX ACL operations. */ +#define SMB_VFS_CHMOD_ACL(conn, name, mode) ((conn)->vfs.ops.chmod_acl((conn)->vfs.handles.chmod_acl, (conn), (name), (mode))) +#define SMB_VFS_FCHMOD_ACL(fsp, fd, mode) ((fsp)->conn->vfs.ops.fchmod_acl((fsp)->conn->vfs.handles.chmod_acl, (fsp), (fd), (mode))) + +#define SMB_VFS_SYS_ACL_GET_ENTRY(conn, theacl, entry_id, entry_p) ((conn)->vfs.ops.sys_acl_get_entry((conn)->vfs.handles.sys_acl_get_entry, (conn), (theacl), (entry_id), (entry_p))) +#define SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry_d, tag_type_p) ((conn)->vfs.ops.sys_acl_get_tag_type((conn)->vfs.handles.sys_acl_get_tag_type, (conn), (entry_d), (tag_type_p))) +#define SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry_d, permset_p) ((conn)->vfs.ops.sys_acl_get_permset((conn)->vfs.handles.sys_acl_get_permset, (conn), (entry_d), (permset_p))) +#define SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry_d) ((conn)->vfs.ops.sys_acl_get_qualifier((conn)->vfs.handles.sys_acl_get_qualifier, (conn), (entry_d))) +#define SMB_VFS_SYS_ACL_GET_FILE(conn, path_p, type) ((conn)->vfs.ops.sys_acl_get_file((conn)->vfs.handles.sys_acl_get_file, (conn), (path_p), (type))) +#define SMB_VFS_SYS_ACL_GET_FD(fsp, fd) ((fsp)->conn->vfs.ops.sys_acl_get_fd((fsp)->conn->vfs.handles.sys_acl_get_fd, (fsp), (fd))) +#define SMB_VFS_SYS_ACL_CLEAR_PERMS(conn, permset) ((conn)->vfs.ops.sys_acl_clear_perms((conn)->vfs.handles.sys_acl_clear_perms, (conn), (permset))) +#define SMB_VFS_SYS_ACL_ADD_PERM(conn, permset, perm) ((conn)->vfs.ops.sys_acl_add_perm((conn)->vfs.handles.sys_acl_add_perm, (conn), (permset), (perm))) +#define SMB_VFS_SYS_ACL_TO_TEXT(conn, theacl, plen) ((conn)->vfs.ops.sys_acl_to_text((conn)->vfs.handles.sys_acl_to_text, (conn), (theacl), (plen))) +#define SMB_VFS_SYS_ACL_INIT(conn, count) ((conn)->vfs.ops.sys_acl_init((conn)->vfs.handles.sys_acl_init, (conn), (count))) +#define SMB_VFS_SYS_ACL_CREATE_ENTRY(conn, pacl, pentry) ((conn)->vfs.ops.sys_acl_create_entry((conn)->vfs.handles.sys_acl_create_entry, (conn), (pacl), (pentry))) +#define SMB_VFS_SYS_ACL_SET_TAG_TYPE(conn, entry, tagtype) ((conn)->vfs.ops.sys_acl_set_tag_type((conn)->vfs.handles.sys_acl_set_tag_type, (conn), (entry), (tagtype))) +#define SMB_VFS_SYS_ACL_SET_QUALIFIER(conn, entry, qual) ((conn)->vfs.ops.sys_acl_set_qualifier((conn)->vfs.handles.sys_acl_set_qualifier, (conn), (entry), (qual))) +#define SMB_VFS_SYS_ACL_SET_PERMSET(conn, entry, permset) ((conn)->vfs.ops.sys_acl_set_permset((conn)->vfs.handles.sys_acl_set_permset, (conn), (entry), (permset))) +#define SMB_VFS_SYS_ACL_VALID(conn, theacl) ((conn)->vfs.ops.sys_acl_valid((conn)->vfs.handles.sys_acl_valid, (conn), (theacl))) +#define SMB_VFS_SYS_ACL_SET_FILE(conn, name, acltype, theacl) ((conn)->vfs.ops.sys_acl_set_file((conn)->vfs.handles.sys_acl_set_file, (conn), (name), (acltype), (theacl))) +#define SMB_VFS_SYS_ACL_SET_FD(fsp, fd, theacl) ((fsp)->conn->vfs.ops.sys_acl_set_fd((fsp)->conn->vfs.handles.sys_acl_set_fd, (fsp), (fd), (theacl))) +#define SMB_VFS_SYS_ACL_DELETE_DEF_FILE(conn, path) ((conn)->vfs.ops.sys_acl_delete_def_file((conn)->vfs.handles.sys_acl_delete_def_file, (conn), (path))) +#define SMB_VFS_SYS_ACL_GET_PERM(conn, permset, perm) ((conn)->vfs.ops.sys_acl_get_perm((conn)->vfs.handles.sys_acl_get_perm, (conn), (permset), (perm))) +#define SMB_VFS_SYS_ACL_FREE_TEXT(conn, text) ((conn)->vfs.ops.sys_acl_free_text((conn)->vfs.handles.sys_acl_free_text, (conn), (text))) +#define SMB_VFS_SYS_ACL_FREE_ACL(conn, posix_acl) ((conn)->vfs.ops.sys_acl_free_acl((conn)->vfs.handles.sys_acl_free_acl, (conn), (posix_acl))) +#define SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, qualifier, tagtype) ((conn)->vfs.ops.sys_acl_free_qualifier((conn)->vfs.handles.sys_acl_free_qualifier, (conn), (qualifier), (tagtype))) + +/* EA operations. */ +#define SMB_VFS_GETXATTR(conn,path,name,value,size) ((conn)->vfs.ops.getxattr((conn)->vfs.handles.getxattr,(conn),(path),(name),(value),(size))) +#define SMB_VFS_LGETXATTR(conn,path,name,value,size) ((conn)->vfs.ops.lgetxattr((conn)->vfs.handles.lgetxattr,(conn),(path),(name),(value),(size))) +#define SMB_VFS_FGETXATTR(fsp,fd,name,value,size) ((fsp)->conn->vfs.ops.fgetxattr((fsp)->conn->vfs.handles.fgetxattr,(fsp),(fd),(name),(value),(size))) +#define SMB_VFS_LISTXATTR(conn,path,list,size) ((conn)->vfs.ops.listxattr((conn)->vfs.handles.listxattr,(conn),(path),(list),(size))) +#define SMB_VFS_LLISTXATTR(conn,path,list,size) ((conn)->vfs.ops.llistxattr((conn)->vfs.handles.llistxattr,(conn),(path),(list),(size))) +#define SMB_VFS_FLISTXATTR(fsp,fd,list,size) ((fsp)->conn->vfs.ops.flistxattr((fsp)->conn->vfs.handles.flistxattr,(fsp),(fd),(list),(size))) +#define SMB_VFS_REMOVEXATTR(conn,path,name) ((conn)->vfs.ops.removexattr((conn)->vfs.handles.removexattr,(conn),(path),(name))) +#define SMB_VFS_LREMOVEXATTR(conn,path,name) ((conn)->vfs.ops.lremovexattr((conn)->vfs.handles.lremovexattr,(conn),(path),(name))) +#define SMB_VFS_FREMOVEXATTR(fsp,fd,name) ((fsp)->conn->vfs.ops.fremovexattr((fsp)->conn->vfs.handles.fremovexattr,(fsp),(fd),(name))) +#define SMB_VFS_SETXATTR(conn,path,name,value,size,flags) ((conn)->vfs.ops.setxattr((conn)->vfs.handles.setxattr,(conn),(path),(name),(value),(size),(flags))) +#define SMB_VFS_LSETXATTR(conn,path,name,value,size,flags) ((conn)->vfs.ops.lsetxattr((conn)->vfs.handles.lsetxattr,(conn),(path),(name),(value),(size),(flags))) +#define SMB_VFS_FSETXATTR(fsp,fd,name,value,size,flags) ((fsp)->conn->vfs.ops.fsetxattr((fsp)->conn->vfs.handles.fsetxattr,(fsp),(fd),(name),(value),(size),(flags))) + +/******************************************************************* + Don't access conn->vfs_opaque.ops directly!!! + Use this macros! + (Fixes should also go into the vfs_* and vfs_next_* macros!) +********************************************************************/ + +/* Disk operations */ +#define SMB_VFS_OPAQUE_CONNECT(conn, service, user) ((conn)->vfs_opaque.ops.connect((conn)->vfs_opaque.handles.connect, (conn), (service), (user))) +#define SMB_VFS_OPAQUE_DISCONNECT(conn) ((conn)->vfs_opaque.ops.disconnect((conn)->vfs_opaque.handles.disconnect, (conn))) +#define SMB_VFS_OPAQUE_DISK_FREE(conn, path, small_query, bsize, dfree ,dsize) ((conn)->vfs_opaque.ops.disk_free((conn)->vfs_opaque.handles.disk_free, (conn), (path), (small_query), (bsize), (dfree), (dsize))) +#define SMB_VFS_OPAQUE_GET_QUOTA(conn, qtype, id, qt) ((conn)->vfs_opaque.ops.get_quota((conn)->vfs_opaque.handles.get_quota, (conn), (qtype), (id), (qt))) +#define SMB_VFS_OPAQUE_SET_QUOTA(conn, qtype, id, qt) ((conn)->vfs_opaque.ops.set_quota((conn)->vfs_opaque.handles.set_quota, (conn), (qtype), (id), (qt))) + +/* Directory operations */ +#define SMB_VFS_OPAQUE_OPENDIR(conn, fname) ((conn)->vfs_opaque.ops.opendir((conn)->vfs_opaque.handles.opendir, (conn), (fname))) +#define SMB_VFS_OPAQUE_READDIR(conn, dirp) ((conn)->vfs_opaque.ops.readdir((conn)->vfs_opaque.handles.readdir, (conn), (dirp))) +#define SMB_VFS_OPAQUE_MKDIR(conn, path, mode) ((conn)->vfs_opaque.ops.mkdir((conn)->vfs_opaque.handles.mkdir,(conn), (path), (mode))) +#define SMB_VFS_OPAQUE_RMDIR(conn, path) ((conn)->vfs_opaque.ops.rmdir((conn)->vfs_opaque.handles.rmdir, (conn), (path))) +#define SMB_VFS_OPAQUE_CLOSEDIR(conn, dir) ((conn)->vfs_opaque.ops.closedir((conn)->vfs_opaque.handles.closedir, (conn), dir)) + +/* File operations */ +#define SMB_VFS_OPAQUE_OPEN(conn, fname, flags, mode) ((conn)->vfs_opaque.ops.open((conn)->vfs_opaque.handles.open, (conn), (fname), (flags), (mode))) +#define SMB_VFS_OPAQUE_CLOSE(fsp, fd) ((fsp)->conn->vfs_opaque.ops.close((fsp)->conn->vfs_opaque.handles.close, (fsp), (fd))) +#define SMB_VFS_OPAQUE_READ(fsp, fd, data, n) ((fsp)->conn->vfs_opaque.ops.read((fsp)->conn->vfs_opaque.handles.read, (fsp), (fd), (data), (n))) +#define SMB_VFS_OPAQUE_WRITE(fsp, fd, data, n) ((fsp)->conn->vfs_opaque.ops.write((fsp)->conn->vfs_opaque.handles.write, (fsp), (fd), (data), (n))) +#define SMB_VFS_OPAQUE_LSEEK(fsp, fd, offset, whence) ((fsp)->conn->vfs_opaque.ops.lseek((fsp)->conn->vfs_opaque.handles.lseek, (fsp), (fd), (offset), (whence))) +#define SMB_VFS_OPAQUE_SENDFILE(tofd, fsp, fromfd, header, offset, count) ((fsp)->conn->vfs_opaque.ops.sendfile((fsp)->conn->vfs_opaque.handles.sendfile, (tofd), (fsp), (fromfd), (header), (offset), (count))) +#define SMB_VFS_OPAQUE_RENAME(conn, old, new) ((conn)->vfs_opaque.ops.rename((conn)->vfs_opaque.handles.rename, (conn), (old), (new))) +#define SMB_VFS_OPAQUE_FSYNC(fsp, fd) ((fsp)->conn->vfs_opaque.ops.fsync((fsp)->conn->vfs_opaque.handles.fsync, (fsp), (fd))) +#define SMB_VFS_OPAQUE_STAT(conn, fname, sbuf) ((conn)->vfs_opaque.ops.stat((conn)->vfs_opaque.handles.stat, (conn), (fname), (sbuf))) +#define SMB_VFS_OPAQUE_FSTAT(fsp, fd, sbuf) ((fsp)->conn->vfs_opaque.ops.fstat((fsp)->conn->vfs_opaque.handles.fstat, (fsp) ,(fd) ,(sbuf))) +#define SMB_VFS_OPAQUE_LSTAT(conn, path, sbuf) ((conn)->vfs_opaque.ops.lstat((conn)->vfs_opaque.handles.lstat, (conn), (path), (sbuf))) +#define SMB_VFS_OPAQUE_UNLINK(conn, path) ((conn)->vfs_opaque.ops.unlink((conn)->vfs_opaque.handles.unlink, (conn), (path))) +#define SMB_VFS_OPAQUE_CHMOD(conn, path, mode) ((conn)->vfs_opaque.ops.chmod((conn)->vfs_opaque.handles.chmod, (conn), (path), (mode))) +#define SMB_VFS_OPAQUE_FCHMOD(fsp, fd, mode) ((fsp)->conn->vfs_opaque.ops.fchmod((fsp)->conn->vfs_opaque.handles.fchmod, (fsp), (fd), (mode))) +#define SMB_VFS_OPAQUE_CHOWN(conn, path, uid, gid) ((conn)->vfs_opaque.ops.chown((conn)->vfs_opaque.handles.chown, (conn), (path), (uid), (gid))) +#define SMB_VFS_OPAQUE_FCHOWN(fsp, fd, uid, gid) ((fsp)->conn->vfs_opaque.ops.fchown((fsp)->conn->vfs_opaque.handles.fchown, (fsp), (fd), (uid), (gid))) +#define SMB_VFS_OPAQUE_CHDIR(conn, path) ((conn)->vfs_opaque.ops.chdir((conn)->vfs_opaque.handles.chdir, (conn), (path))) +#define SMB_VFS_OPAQUE_GETWD(conn, buf) ((conn)->vfs_opaque.ops.getwd((conn)->vfs_opaque.handles.getwd, (conn), (buf))) +#define SMB_VFS_OPAQUE_UTIME(conn, path, times) ((conn)->vfs_opaque.ops.utime((conn)->vfs_opaque.handles.utime, (conn), (path), (times))) +#define SMB_VFS_OPAQUE_FTRUNCATE(fsp, fd, offset) ((fsp)->conn->vfs_opaque.ops.ftruncate((fsp)->conn->vfs_opaque.handles.ftruncate, (fsp), (fd), (offset))) +#define SMB_VFS_OPAQUE_LOCK(fsp, fd, op, offset, count, type) ((fsp)->conn->vfs_opaque.ops.lock((fsp)->conn->vfs_opaque.handles.lock, (fsp), (fd) ,(op), (offset), (count), (type))) +#define SMB_VFS_OPAQUE_SYMLINK(conn, oldpath, newpath) ((conn)->vfs_opaque.ops.symlink((conn)->vfs_opaque.handles.symlink, (conn), (oldpath), (newpath))) +#define SMB_VFS_OPAQUE_READLINK(conn, path, buf, bufsiz) ((conn)->vfs_opaque.ops.readlink((conn)->vfs_opaque.handles.readlink, (conn), (path), (buf), (bufsiz))) +#define SMB_VFS_OPAQUE_LINK(conn, oldpath, newpath) ((conn)->vfs_opaque.ops.link((conn)->vfs_opaque.handles.link, (conn), (oldpath), (newpath))) +#define SMB_VFS_OPAQUE_MKNOD(conn, path, mode, dev) ((conn)->vfs_opaque.ops.mknod((conn)->vfs_opaque.handles.mknod, (conn), (path), (mode), (dev))) +#define SMB_VFS_OPAQUE_REALPATH(conn, path, resolved_path) ((conn)->vfs_opaque.ops.realpath((conn)->vfs_opaque.handles.realpath, (conn), (path), (resolved_path))) + +/* NT ACL operations. */ +#define SMB_VFS_OPAQUE_FGET_NT_ACL(fsp, fd, security_info, ppdesc) ((fsp)->conn->vfs_opaque.ops.fget_nt_acl((fsp)->conn->vfs_opaque.handles.fget_nt_acl, (fsp), (fd), (security_info), (ppdesc))) +#define SMB_VFS_OPAQUE_GET_NT_ACL(fsp, name, security_info, ppdesc) ((fsp)->conn->vfs_opaque.ops.get_nt_acl((fsp)->conn->vfs_opaque.handles.get_nt_acl, (fsp), (name), (security_info), (ppdesc))) +#define SMB_VFS_OPAQUE_FSET_NT_ACL(fsp, fd, security_info_sent, psd) ((fsp)->conn->vfs_opaque.ops.fset_nt_acl((fsp)->conn->vfs_opaque.handles.fset_nt_acl, (fsp), (fd), (security_info_sent), (psd))) +#define SMB_VFS_OPAQUE_SET_NT_ACL(fsp, name, security_info_sent, psd) ((fsp)->conn->vfs_opaque.ops.set_nt_acl((fsp)->conn->vfs_opaque.handles.set_nt_acl, (fsp), (name), (security_info_sent), (psd))) + +/* POSIX ACL operations. */ +#define SMB_VFS_OPAQUE_CHMOD_ACL(conn, name, mode) ((conn)->vfs_opaque.ops.chmod_acl((conn)->vfs_opaque.handles.chmod_acl, (conn), (name), (mode))) +#define SMB_VFS_OPAQUE_FCHMOD_ACL(fsp, fd, mode) ((fsp)->conn->vfs_opaque.ops.fchmod_acl((fsp)->conn->vfs_opaque.handles.chmod_acl, (fsp), (fd), (mode))) + +#define SMB_VFS_OPAQUE_SYS_ACL_GET_ENTRY(conn, theacl, entry_id, entry_p) ((conn)->vfs_opaque.ops.sys_acl_get_entry((conn)->vfs_opaque.handles.sys_acl_get_entry, (conn), (theacl), (entry_id), (entry_p))) +#define SMB_VFS_OPAQUE_SYS_ACL_GET_TAG_TYPE(conn, entry_d, tag_type_p) ((conn)->vfs_opaque.ops.sys_acl_get_tag_type((conn)->vfs_opaque.handles.sys_acl_get_tag_type, (conn), (entry_d), (tag_type_p))) +#define SMB_VFS_OPAQUE_SYS_ACL_GET_PERMSET(conn, entry_d, permset_p) ((conn)->vfs_opaque.ops.sys_acl_get_permset((conn)->vfs_opaque.handles.sys_acl_get_permset, (conn), (entry_d), (permset_p))) +#define SMB_VFS_OPAQUE_SYS_ACL_GET_QUALIFIER(conn, entry_d) ((conn)->vfs_opaque.ops.sys_acl_get_qualifier((conn)->vfs_opaque.handles.sys_acl_get_qualifier, (conn), (entry_d))) +#define SMB_VFS_OPAQUE_SYS_ACL_GET_FILE(conn, path_p, type) ((conn)->vfs_opaque.ops.sys_acl_get_file((conn)->vfs_opaque.handles.sys_acl_get_file, (conn), (path_p), (type))) +#define SMB_VFS_OPAQUE_SYS_ACL_GET_FD(fsp, fd) ((fsp)->conn->vfs_opaque.ops.sys_acl_get_fd((fsp)->conn->vfs_opaque.handles.sys_acl_get_fd, (fsp), (fd))) +#define SMB_VFS_OPAQUE_SYS_ACL_CLEAR_PERMS(conn, permset) ((conn)->vfs_opaque.ops.sys_acl_clear_perms((conn)->vfs_opaque.handles.sys_acl_clear_perms, (conn), (permset))) +#define SMB_VFS_OPAQUE_SYS_ACL_ADD_PERM(conn, permset, perm) ((conn)->vfs_opaque.ops.sys_acl_add_perm((conn)->vfs_opaque.handles.sys_acl_add_perm, (conn), (permset), (perm))) +#define SMB_VFS_OPAQUE_SYS_ACL_TO_TEXT(conn, theacl, plen) ((conn)->vfs_opaque.ops.sys_acl_to_text((conn)->vfs_opaque.handles.sys_acl_to_text, (conn), (theacl), (plen))) +#define SMB_VFS_OPAQUE_SYS_ACL_INIT(conn, count) ((conn)->vfs_opaque.ops.sys_acl_init((conn)->vfs_opaque.handles.sys_acl_init, (conn), (count))) +#define SMB_VFS_OPAQUE_SYS_ACL_CREATE_ENTRY(conn, pacl, pentry) ((conn)->vfs_opaque.ops.sys_acl_create_entry((conn)->vfs_opaque.handles.sys_acl_create_entry, (conn), (pacl), (pentry))) +#define SMB_VFS_OPAQUE_SYS_ACL_SET_TAG_TYPE(conn, entry, tagtype) ((conn)->vfs_opaque.ops.sys_acl_set_tag_type((conn)->vfs_opaque.handles.sys_acl_set_tag_type, (conn), (entry), (tagtype))) +#define SMB_VFS_OPAQUE_SYS_ACL_SET_QUALIFIER(conn, entry, qual) ((conn)->vfs_opaque.ops.sys_acl_set_qualifier((conn)->vfs_opaque.handles.sys_acl_set_qualifier, (conn), (entry), (qual))) +#define SMB_VFS_OPAQUE_SYS_ACL_SET_PERMSET(conn, entry, permset) ((conn)->vfs_opaque.ops.sys_acl_set_permset((conn)->vfs_opaque.handles.sys_acl_set_permset, (conn), (entry), (permset))) +#define SMB_VFS_OPAQUE_SYS_ACL_VALID(conn, theacl) ((conn)->vfs_opaque.ops.sys_acl_valid((conn)->vfs_opaque.handles.sys_acl_valid, (conn), (theacl))) +#define SMB_VFS_OPAQUE_SYS_ACL_SET_FILE(conn, name, acltype, theacl) ((conn)->vfs_opaque.ops.sys_acl_set_file((conn)->vfs_opaque.handles.sys_acl_set_file, (conn), (name), (acltype), (theacl))) +#define SMB_VFS_OPAQUE_SYS_ACL_SET_FD(fsp, fd, theacl) ((fsp)->conn->vfs_opaque.ops.sys_acl_set_fd((fsp)->conn->vfs_opaque.handles.sys_acl_set_fd, (fsp), (fd), (theacl))) +#define SMB_VFS_OPAQUE_SYS_ACL_DELETE_DEF_FILE(conn, path) ((conn)->vfs_opaque.ops.sys_acl_delete_def_file((conn)->vfs_opaque.handles.sys_acl_delete_def_file, (conn), (path))) +#define SMB_VFS_OPAQUE_SYS_ACL_GET_PERM(conn, permset, perm) ((conn)->vfs_opaque.ops.sys_acl_get_perm((conn)->vfs_opaque.handles.sys_acl_get_perm, (conn), (permset), (perm))) +#define SMB_VFS_OPAQUE_SYS_ACL_FREE_TEXT(conn, text) ((conn)->vfs_opaque.ops.sys_acl_free_text((conn)->vfs_opaque.handles.sys_acl_free_text, (conn), (text))) +#define SMB_VFS_OPAQUE_SYS_ACL_FREE_ACL(conn, posix_acl) ((conn)->vfs_opaque.ops.sys_acl_free_acl((conn)->vfs_opaque.handles.sys_acl_free_acl, (conn), (posix_acl))) +#define SMB_VFS_OPAQUE_SYS_ACL_FREE_QUALIFIER(conn, qualifier, tagtype) ((conn)->vfs_opaque.ops.sys_acl_free_qualifier((conn)->vfs_opaque.handles.sys_acl_free_qualifier, (conn), (qualifier), (tagtype))) + +/* EA operations. */ +#define SMB_VFS_OPAQUE_GETXATTR(conn,path,name,value,size) ((conn)->vfs_opaque.ops.getxattr((conn)->vfs_opaque.handles.getxattr,(conn),(path),(name),(value),(size))) +#define SMB_VFS_OPAQUE_LGETXATTR(conn,path,name,value,size) ((conn)->vfs_opaque.ops.lgetxattr((conn)->vfs_opaque.handles.lgetxattr,(conn),(path),(name),(value),(size))) +#define SMB_VFS_OPAQUE_FGETXATTR(fsp,fd,name,value,size) ((fsp)->conn->vfs_opaque.ops.fgetxattr((fsp)->conn->vfs_opaque.handles.fgetxattr,(fsp),(fd),(name),(value),(size))) +#define SMB_VFS_OPAQUE_LISTXATTR(conn,path,list,size) ((conn)->vfs_opaque.ops.listxattr((conn)->vfs_opaque.handles.listxattr,(conn),(path),(list),(size))) +#define SMB_VFS_OPAQUE_LLISTXATTR(conn,path,list,size) ((conn)->vfs_opaque.ops.llistxattr((conn)->vfs_opaque.handles.llistxattr,(conn),(path),(list),(size))) +#define SMB_VFS_OPAQUE_FLISTXATTR(fsp,fd,list,size) ((fsp)->conn->vfs_opaque.ops.flistxattr((fsp)->conn->vfs_opaque.handles.flistxattr,(fsp),(fd),(list),(size))) +#define SMB_VFS_OPAQUE_REMOVEXATTR(conn,path,name) ((conn)->vfs_opaque.ops.removexattr((conn)->vfs_opaque.handles.removexattr,(conn),(path),(name))) +#define SMB_VFS_OPAQUE_LREMOVEXATTR(conn,path,name) ((conn)->vfs_opaque.ops.lremovexattr((conn)->vfs_opaque.handles.lremovexattr,(conn),(path),(name))) +#define SMB_VFS_OPAQUE_FREMOVEXATTR(fsp,fd,name) ((fsp)->conn->vfs_opaque.ops.fremovexattr((fsp)->conn->vfs_opaque.handles.fremovexattr,(fsp),(fd),(name))) +#define SMB_VFS_OPAQUE_SETXATTR(conn,path,name,value,size,flags) ((conn)->vfs_opaque.ops.setxattr((conn)->vfs_opaque.handles.setxattr,(conn),(path),(name),(value),(size),(flags))) +#define SMB_VFS_OPAQUE_LSETXATTR(conn,path,name,value,size,flags) ((conn)->vfs_opaque.ops.lsetxattr((conn)->vfs_opaque.handles.lsetxattr,(conn),(path),(name),(value),(size),(flags))) +#define SMB_VFS_OPAQUE_FSETXATTR(fsp,fd,name,value,size,flags) ((fsp)->conn->vfs_opaque.ops.fsetxattr((fsp)->conn->vfs_opaque.handles.fsetxattr,(fsp),(fd),(name),(value),(size),(flags))) + +/******************************************************************* + Don't access handle->vfs_next.ops.* directly!!! + Use this macros! + (Fixes should go also into the vfs_* and vfs_opaque_* macros!) +********************************************************************/ + +/* Disk operations */ +#define SMB_VFS_NEXT_CONNECT(handle, conn, service, user) ((handle)->vfs_next.ops.connect((handle)->vfs_next.handles.connect, (conn), (service), (user))) +#define SMB_VFS_NEXT_DISCONNECT(handle, conn) ((handle)->vfs_next.ops.disconnect((handle)->vfs_next.handles.disconnect, (conn))) +#define SMB_VFS_NEXT_DISK_FREE(handle, conn, path, small_query, bsize, dfree ,dsize) ((handle)->vfs_next.ops.disk_free((handle)->vfs_next.handles.disk_free, (conn), (path), (small_query), (bsize), (dfree), (dsize))) +#define SMB_VFS_NEXT_GET_QUOTA(handle, conn, qtype, id, qt) ((handle)->vfs_next.ops.get_quota((handle)->vfs_next.handles.get_quota, (conn), (qtype), (id), (qt))) +#define SMB_VFS_NEXT_SET_QUOTA(handle, conn, qtype, id, qt) ((handle)->vfs_next.ops.set_quota((handle)->vfs_next.handles.set_quota, (conn), (qtype), (id), (qt))) + +/* Directory operations */ +#define SMB_VFS_NEXT_OPENDIR(handle, conn, fname) ((handle)->vfs_next.ops.opendir((handle)->vfs_next.handles.opendir, (conn), (fname))) +#define SMB_VFS_NEXT_READDIR(handle, conn, dirp) ((handle)->vfs_next.ops.readdir((handle)->vfs_next.handles.readdir, (conn), (dirp))) +#define SMB_VFS_NEXT_MKDIR(handle, conn, path, mode) ((handle)->vfs_next.ops.mkdir((handle)->vfs_next.handles.mkdir,(conn), (path), (mode))) +#define SMB_VFS_NEXT_RMDIR(handle, conn, path) ((handle)->vfs_next.ops.rmdir((handle)->vfs_next.handles.rmdir, (conn), (path))) +#define SMB_VFS_NEXT_CLOSEDIR(handle, conn, dir) ((handle)->vfs_next.ops.closedir((handle)->vfs_next.handles.closedir, (conn), dir)) + +/* File operations */ +#define SMB_VFS_NEXT_OPEN(handle, conn, fname, flags, mode) ((handle)->vfs_next.ops.open((handle)->vfs_next.handles.open, (conn), (fname), (flags), (mode))) +#define SMB_VFS_NEXT_CLOSE(handle, fsp, fd) ((handle)->vfs_next.ops.close((handle)->vfs_next.handles.close, (fsp), (fd))) +#define SMB_VFS_NEXT_READ(handle, fsp, fd, data, n) ((handle)->vfs_next.ops.read((handle)->vfs_next.handles.read, (fsp), (fd), (data), (n))) +#define SMB_VFS_NEXT_WRITE(handle, fsp, fd, data, n) ((handle)->vfs_next.ops.write((handle)->vfs_next.handles.write, (fsp), (fd), (data), (n))) +#define SMB_VFS_NEXT_LSEEK(handle, fsp, fd, offset, whence) ((handle)->vfs_next.ops.lseek((handle)->vfs_next.handles.lseek, (fsp), (fd), (offset), (whence))) +#define SMB_VFS_NEXT_SENDFILE(handle, tofd, fsp, fromfd, header, offset, count) ((handle)->vfs_next.ops.sendfile((handle)->vfs_next.handles.sendfile, (tofd), (fsp), (fromfd), (header), (offset), (count))) +#define SMB_VFS_NEXT_RENAME(handle, conn, old, new) ((handle)->vfs_next.ops.rename((handle)->vfs_next.handles.rename, (conn), (old), (new))) +#define SMB_VFS_NEXT_FSYNC(handle, fsp, fd) ((handle)->vfs_next.ops.fsync((handle)->vfs_next.handles.fsync, (fsp), (fd))) +#define SMB_VFS_NEXT_STAT(handle, conn, fname, sbuf) ((handle)->vfs_next.ops.stat((handle)->vfs_next.handles.stat, (conn), (fname), (sbuf))) +#define SMB_VFS_NEXT_FSTAT(handle, fsp, fd, sbuf) ((handle)->vfs_next.ops.fstat((handle)->vfs_next.handles.fstat, (fsp) ,(fd) ,(sbuf))) +#define SMB_VFS_NEXT_LSTAT(handle, conn, path, sbuf) ((handle)->vfs_next.ops.lstat((handle)->vfs_next.handles.lstat, (conn), (path), (sbuf))) +#define SMB_VFS_NEXT_UNLINK(handle, conn, path) ((handle)->vfs_next.ops.unlink((handle)->vfs_next.handles.unlink, (conn), (path))) +#define SMB_VFS_NEXT_CHMOD(handle, conn, path, mode) ((handle)->vfs_next.ops.chmod((handle)->vfs_next.handles.chmod, (conn), (path), (mode))) +#define SMB_VFS_NEXT_FCHMOD(handle, fsp, fd, mode) ((handle)->vfs_next.ops.fchmod((handle)->vfs_next.handles.fchmod, (fsp), (fd), (mode))) +#define SMB_VFS_NEXT_CHOWN(handle, conn, path, uid, gid) ((handle)->vfs_next.ops.chown((handle)->vfs_next.handles.chown, (conn), (path), (uid), (gid))) +#define SMB_VFS_NEXT_FCHOWN(handle, fsp, fd, uid, gid) ((handle)->vfs_next.ops.fchown((handle)->vfs_next.handles.fchown, (fsp), (fd), (uid), (gid))) +#define SMB_VFS_NEXT_CHDIR(handle, conn, path) ((handle)->vfs_next.ops.chdir((handle)->vfs_next.handles.chdir, (conn), (path))) +#define SMB_VFS_NEXT_GETWD(handle, conn, buf) ((handle)->vfs_next.ops.getwd((handle)->vfs_next.handles.getwd, (conn), (buf))) +#define SMB_VFS_NEXT_UTIME(handle, conn, path, times) ((handle)->vfs_next.ops.utime((handle)->vfs_next.handles.utime, (conn), (path), (times))) +#define SMB_VFS_NEXT_FTRUNCATE(handle, fsp, fd, offset) ((handle)->vfs_next.ops.ftruncate((handle)->vfs_next.handles.ftruncate, (fsp), (fd), (offset))) +#define SMB_VFS_NEXT_LOCK(handle, fsp, fd, op, offset, count, type) ((handle)->vfs_next.ops.lock((handle)->vfs_next.handles.lock, (fsp), (fd) ,(op), (offset), (count), (type))) +#define SMB_VFS_NEXT_SYMLINK(handle, conn, oldpath, newpath) ((handle)->vfs_next.ops.symlink((handle)->vfs_next.handles.symlink, (conn), (oldpath), (newpath))) +#define SMB_VFS_NEXT_READLINK(handle, conn, path, buf, bufsiz) ((handle)->vfs_next.ops.readlink((handle)->vfs_next.handles.readlink, (conn), (path), (buf), (bufsiz))) +#define SMB_VFS_NEXT_LINK(handle, conn, oldpath, newpath) ((handle)->vfs_next.ops.link((handle)->vfs_next.handles.link, (conn), (oldpath), (newpath))) +#define SMB_VFS_NEXT_MKNOD(handle, conn, path, mode, dev) ((handle)->vfs_next.ops.mknod((handle)->vfs_next.handles.mknod, (conn), (path), (mode), (dev))) +#define SMB_VFS_NEXT_REALPATH(handle, conn, path, resolved_path) ((handle)->vfs_next.ops.realpath((handle)->vfs_next.handles.realpath, (conn), (path), (resolved_path))) + +/* NT ACL operations. */ +#define SMB_VFS_NEXT_FGET_NT_ACL(handle, fsp, fd, security_info, ppdesc) ((handle)->vfs_next.ops.fget_nt_acl((handle)->vfs_next.handles.fget_nt_acl, (fsp), (fd), (security_info), (ppdesc))) +#define SMB_VFS_NEXT_GET_NT_ACL(handle, fsp, name, security_info, ppdesc) ((handle)->vfs_next.ops.get_nt_acl((handle)->vfs_next.handles.get_nt_acl, (fsp), (name), (security_info), (ppdesc))) +#define SMB_VFS_NEXT_FSET_NT_ACL(handle, fsp, fd, security_info_sent, psd) ((handle)->vfs_next.ops.fset_nt_acl((handle)->vfs_next.handles.fset_nt_acl, (fsp), (fd), (security_info_sent), (psd))) +#define SMB_VFS_NEXT_SET_NT_ACL(handle, fsp, name, security_info_sent, psd) ((handle)->vfs_next.ops.set_nt_acl((handle)->vfs_next.handles.set_nt_acl, (fsp), (name), (security_info_sent), (psd))) + +/* POSIX ACL operations. */ +#define SMB_VFS_NEXT_CHMOD_ACL(handle, conn, name, mode) ((handle)->vfs_next.ops.chmod_acl((handle)->vfs_next.handles.chmod_acl, (conn), (name), (mode))) +#define SMB_VFS_NEXT_FCHMOD_ACL(handle, fsp, fd, mode) ((handle)->vfs_next.ops.fchmod_acl((handle)->vfs_next.handles.chmod_acl, (fsp), (fd), (mode))) + +#define SMB_VFS_NEXT_SYS_ACL_GET_ENTRY(handle, conn, theacl, entry_id, entry_p) ((handle)->vfs_next.ops.sys_acl_get_entry((handle)->vfs_next.handles.sys_acl_get_entry, (conn), (theacl), (entry_id), (entry_p))) +#define SMB_VFS_NEXT_SYS_ACL_GET_TAG_TYPE(handle, conn, entry_d, tag_type_p) ((handle)->vfs_next.ops.sys_acl_get_tag_type((handle)->vfs_next.handles.sys_acl_get_tag_type, (conn), (entry_d), (tag_type_p))) +#define SMB_VFS_NEXT_SYS_ACL_GET_PERMSET(handle, conn, entry_d, permset_p) ((handle)->vfs_next.ops.sys_acl_get_permset((handle)->vfs_next.handles.sys_acl_get_permset, (conn), (entry_d), (permset_p))) +#define SMB_VFS_NEXT_SYS_ACL_GET_QUALIFIER(handle, conn, entry_d) ((handle)->vfs_next.ops.sys_acl_get_qualifier((handle)->vfs_next.handles.sys_acl_get_qualifier, (conn), (entry_d))) +#define SMB_VFS_NEXT_SYS_ACL_GET_FILE(handle, conn, path_p, type) ((handle)->vfs_next.ops.sys_acl_get_file((handle)->vfs_next.handles.sys_acl_get_file, (conn), (path_p), (type))) +#define SMB_VFS_NEXT_SYS_ACL_GET_FD(handle, fsp, fd) ((handle)->vfs_next.ops.sys_acl_get_fd((handle)->vfs_next.handles.sys_acl_get_fd, (fsp), (fd))) +#define SMB_VFS_NEXT_SYS_ACL_CLEAR_PERMS(handle, conn, permset) ((handle)->vfs_next.ops.sys_acl_clear_perms((handle)->vfs_next.handles.sys_acl_clear_perms, (conn), (permset))) +#define SMB_VFS_NEXT_SYS_ACL_ADD_PERM(handle, conn, permset, perm) ((handle)->vfs_next.ops.sys_acl_add_perm((handle)->vfs_next.handles.sys_acl_add_perm, (conn), (permset), (perm))) +#define SMB_VFS_NEXT_SYS_ACL_TO_TEXT(handle, conn, theacl, plen) ((handle)->vfs_next.ops.sys_acl_to_text((handle)->vfs_next.handles.sys_acl_to_text, (conn), (theacl), (plen))) +#define SMB_VFS_NEXT_SYS_ACL_INIT(handle, conn, count) ((handle)->vfs_next.ops.sys_acl_init((handle)->vfs_next.handles.sys_acl_init, (conn), (count))) +#define SMB_VFS_NEXT_SYS_ACL_CREATE_ENTRY(handle, conn, pacl, pentry) ((handle)->vfs_next.ops.sys_acl_create_entry((handle)->vfs_next.handles.sys_acl_create_entry, (conn), (pacl), (pentry))) +#define SMB_VFS_NEXT_SYS_ACL_SET_TAG_TYPE(handle, conn, entry, tagtype) ((handle)->vfs_next.ops.sys_acl_set_tag_type((handle)->vfs_next.handles.sys_acl_set_tag_type, (conn), (entry), (tagtype))) +#define SMB_VFS_NEXT_SYS_ACL_SET_QUALIFIER(handle, conn, entry, qual) ((handle)->vfs_next.ops.sys_acl_set_qualifier((handle)->vfs_next.handles.sys_acl_set_qualifier, (conn), (entry), (qual))) +#define SMB_VFS_NEXT_SYS_ACL_SET_PERMSET(handle, conn, entry, permset) ((handle)->vfs_next.ops.sys_acl_set_permset((handle)->vfs_next.handles.sys_acl_set_permset, (conn), (entry), (permset))) +#define SMB_VFS_NEXT_SYS_ACL_VALID(handle, conn, theacl) ((handle)->vfs_next.ops.sys_acl_valid((handle)->vfs_next.handles.sys_acl_valid, (conn), (theacl))) +#define SMB_VFS_NEXT_SYS_ACL_SET_FILE(handle, conn, name, acltype, theacl) ((handle)->vfs_next.ops.sys_acl_set_file((handle)->vfs_next.handles.sys_acl_set_file, (conn), (name), (acltype), (theacl))) +#define SMB_VFS_NEXT_SYS_ACL_SET_FD(handle, fsp, fd, theacl) ((handle)->vfs_next.ops.sys_acl_set_fd((handle)->vfs_next.handles.sys_acl_set_fd, (fsp), (fd), (theacl))) +#define SMB_VFS_NEXT_SYS_ACL_DELETE_DEF_FILE(handle, conn, path) ((handle)->vfs_next.ops.sys_acl_delete_def_file((handle)->vfs_next.handles.sys_acl_delete_def_file, (conn), (path))) +#define SMB_VFS_NEXT_SYS_ACL_GET_PERM(handle, conn, permset, perm) ((handle)->vfs_next.ops.sys_acl_get_perm((handle)->vfs_next.handles.sys_acl_get_perm, (conn), (permset), (perm))) +#define SMB_VFS_NEXT_SYS_ACL_FREE_TEXT(handle, conn, text) ((handle)->vfs_next.ops.sys_acl_free_text((handle)->vfs_next.handles.sys_acl_free_text, (conn), (text))) +#define SMB_VFS_NEXT_SYS_ACL_FREE_ACL(handle, conn, posix_acl) ((handle)->vfs_next.ops.sys_acl_free_acl((handle)->vfs_next.handles.sys_acl_free_acl, (conn), (posix_acl))) +#define SMB_VFS_NEXT_SYS_ACL_FREE_QUALIFIER(handle, conn, qualifier, tagtype) ((handle)->vfs_next.ops.sys_acl_free_qualifier((handle)->vfs_next.handles.sys_acl_free_qualifier, (conn), (qualifier), (tagtype))) + +/* EA operations. */ +#define SMB_VFS_NEXT_GETXATTR(handle,conn,path,name,value,size) ((handle)->vfs_next.ops.getxattr((handle)->vfs_next.handles.getxattr,(conn),(path),(name),(value),(size))) +#define SMB_VFS_NEXT_LGETXATTR(handle,conn,path,name,value,size) ((handle)->vfs_next.ops.lgetxattr((handle)->vfs_next.handles.lgetxattr,(conn),(path),(name),(value),(size))) +#define SMB_VFS_NEXT_FGETXATTR(handle,fsp,fd,name,value,size) ((handle)->vfs_next.ops.fgetxattr((handle)->vfs_next.handles.fgetxattr,(fsp),(fd),(name),(value),(size))) +#define SMB_VFS_NEXT_LISTXATTR(handle,conn,path,list,size) ((handle)->vfs_next.ops.listxattr((handle)->vfs_next.handles.listxattr,(conn),(path),(list),(size))) +#define SMB_VFS_NEXT_LLISTXATTR(handle,conn,path,list,size) ((handle)->vfs_next.ops.llistxattr((handle)->vfs_next.handles.llistxattr,(conn),(path),(list),(size))) +#define SMB_VFS_NEXT_FLISTXATTR(handle,fsp,fd,list,size) ((handle)->vfs_next.ops.flistxattr((handle)->vfs_next.handles.flistxattr,(fsp),(fd),(list),(size))) +#define SMB_VFS_NEXT_REMOVEXATTR(handle,conn,path,name) ((handle)->vfs_next.ops.removexattr((handle)->vfs_next.handles.removexattr,(conn),(path),(name))) +#define SMB_VFS_NEXT_LREMOVEXATTR(handle,conn,path,name) ((handle)->vfs_next.ops.lremovexattr((handle)->vfs_next.handles.lremovexattr,(conn),(path),(name))) +#define SMB_VFS_NEXT_FREMOVEXATTR(handle,fsp,fd,name) ((handle)->vfs_next.ops.fremovexattr((handle)->vfs_next.handles.fremovexattr,(fsp),(fd),(name))) +#define SMB_VFS_NEXT_SETXATTR(handle,conn,path,name,value,size,flags) ((handle)->vfs_next.ops.setxattr((handle)->vfs_next.handles.setxattr,(conn),(path),(name),(value),(size),(flags))) +#define SMB_VFS_NEXT_LSETXATTR(handle,conn,path,name,value,size,flags) ((handle)->vfs_next.ops.lsetxattr((handle)->vfs_next.handles.lsetxattr,(conn),(path),(name),(value),(size),(flags))) +#define SMB_VFS_NEXT_FSETXATTR(handle,fsp,fd,name,value,size,flags) ((handle)->vfs_next.ops.fsetxattr((handle)->vfs_next.handles.fsetxattr,(fsp),(fd),(name),(value),(size),(flags))) + +#endif /* _VFS_MACROS_H */ diff --git a/source3/intl/libgettext.h b/source3/intl/libgettext.h new file mode 100644 index 0000000000..e69de29bb2 diff --git a/source3/lib/smbldap.c b/source3/lib/smbldap.c new file mode 100644 index 0000000000..39c1990dec --- /dev/null +++ b/source3/lib/smbldap.c @@ -0,0 +1,1262 @@ +/* + Unix SMB/CIFS mplementation. + LDAP protocol helper functions for SAMBA + Copyright (C) Jean François Micouleau 1998 + Copyright (C) Gerald Carter 2001-2003 + Copyright (C) Shahms King 2001 + Copyright (C) Andrew Bartlett 2002-2003 + 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include "includes.h" +#include "smbldap.h" + +#ifndef LDAP_OPT_SUCCESS +#define LDAP_OPT_SUCCESS 0 +#endif + +/* Try not to hit the up or down server forever */ + +#define SMBLDAP_DONT_PING_TIME 10 /* ping only all 10 seconds */ +#define SMBLDAP_NUM_RETRIES 8 /* retry only 8 times */ + + +/* attributes used by Samba 2.2 */ + +ATTRIB_MAP_ENTRY attrib_map_v22[] = { + { LDAP_ATTR_UID, "uid" }, + { LDAP_ATTR_UIDNUMBER, LDAP_ATTRIBUTE_UIDNUMBER}, + { LDAP_ATTR_GIDNUMBER, LDAP_ATTRIBUTE_GIDNUMBER}, + { LDAP_ATTR_UNIX_HOME, "homeDirectory" }, + { LDAP_ATTR_PWD_LAST_SET, "pwdLastSet" }, + { LDAP_ATTR_PWD_CAN_CHANGE, "pwdCanChange" }, + { LDAP_ATTR_PWD_MUST_CHANGE, "pwdMustChange" }, + { LDAP_ATTR_LOGON_TIME, "logonTime" }, + { LDAP_ATTR_LOGOFF_TIME, "logoffTime" }, + { LDAP_ATTR_KICKOFF_TIME, "kickoffTime" }, + { LDAP_ATTR_CN, "cn" }, + { LDAP_ATTR_DISPLAY_NAME, "displayName" }, + { LDAP_ATTR_HOME_PATH, "smbHome" }, + { LDAP_ATTR_HOME_DRIVE, "homeDrives" }, + { LDAP_ATTR_LOGON_SCRIPT, "scriptPath" }, + { LDAP_ATTR_PROFILE_PATH, "profilePath" }, + { LDAP_ATTR_DESC, "description" }, + { LDAP_ATTR_USER_WKS, "userWorkstations"}, + { LDAP_ATTR_USER_RID, "rid" }, + { LDAP_ATTR_PRIMARY_GROUP_RID, "primaryGroupID"}, + { LDAP_ATTR_LMPW, "lmPassword" }, + { LDAP_ATTR_NTPW, "ntPassword" }, + { LDAP_ATTR_DOMAIN, "domain" }, + { LDAP_ATTR_OBJCLASS, "objectClass" }, + { LDAP_ATTR_ACB_INFO, "acctFlags" }, + { LDAP_ATTR_LIST_END, NULL } +}; + +/* attributes used by Samba 3.0's sambaSamAccount */ + +ATTRIB_MAP_ENTRY attrib_map_v30[] = { + { LDAP_ATTR_UID, "uid" }, + { LDAP_ATTR_UIDNUMBER, LDAP_ATTRIBUTE_UIDNUMBER}, + { LDAP_ATTR_GIDNUMBER, LDAP_ATTRIBUTE_GIDNUMBER}, + { LDAP_ATTR_UNIX_HOME, "homeDirectory" }, + { LDAP_ATTR_PWD_LAST_SET, "sambaPwdLastSet" }, + { LDAP_ATTR_PWD_CAN_CHANGE, "sambaPwdCanChange" }, + { LDAP_ATTR_PWD_MUST_CHANGE, "sambaPwdMustChange" }, + { LDAP_ATTR_LOGON_TIME, "sambaLogonTime" }, + { LDAP_ATTR_LOGOFF_TIME, "sambaLogoffTime" }, + { LDAP_ATTR_KICKOFF_TIME, "sambaKickoffTime" }, + { LDAP_ATTR_CN, "cn" }, + { LDAP_ATTR_DISPLAY_NAME, "displayName" }, + { LDAP_ATTR_HOME_DRIVE, "sambaHomeDrive" }, + { LDAP_ATTR_HOME_PATH, "sambaHomePath" }, + { LDAP_ATTR_LOGON_SCRIPT, "sambaLogonScript" }, + { LDAP_ATTR_PROFILE_PATH, "sambaProfilePath" }, + { LDAP_ATTR_DESC, "description" }, + { LDAP_ATTR_USER_WKS, "sambaUserWorkstations" }, + { LDAP_ATTR_USER_SID, LDAP_ATTRIBUTE_SID }, + { LDAP_ATTR_PRIMARY_GROUP_SID, "sambaPrimaryGroupSID" }, + { LDAP_ATTR_LMPW, "sambaLMPassword" }, + { LDAP_ATTR_NTPW, "sambaNTPassword" }, + { LDAP_ATTR_DOMAIN, "sambaDomainName" }, + { LDAP_ATTR_OBJCLASS, "objectClass" }, + { LDAP_ATTR_ACB_INFO, "sambaAcctFlags" }, + { LDAP_ATTR_LIST_END, NULL } +}; + +/* attributes used for alalocating RIDs */ + +ATTRIB_MAP_ENTRY dominfo_attr_list[] = { + { LDAP_ATTR_DOMAIN, "sambaDomainName" }, + { LDAP_ATTR_NEXT_RID, "sambaNextRid" }, + { LDAP_ATTR_NEXT_USERRID, "sambaNextUserRid" }, + { LDAP_ATTR_NEXT_GROUPRID, "sambaNextGroupRid" }, + { LDAP_ATTR_DOM_SID, LDAP_ATTRIBUTE_SID }, + { LDAP_ATTR_ALGORITHMIC_RID_BASE,"sambaAlgorithmicRidBase"}, + { LDAP_ATTR_OBJCLASS, "objectClass" }, + { LDAP_ATTR_LIST_END, NULL }, +}; + +/* Samba 3.0 group mapping attributes */ + +ATTRIB_MAP_ENTRY groupmap_attr_list[] = { + { LDAP_ATTR_GIDNUMBER, LDAP_ATTRIBUTE_GIDNUMBER}, + { LDAP_ATTR_GROUP_SID, LDAP_ATTRIBUTE_SID }, + { LDAP_ATTR_GROUP_TYPE, "sambaGroupType" }, + { LDAP_ATTR_DESC, "description" }, + { LDAP_ATTR_DISPLAY_NAME, "displayName" }, + { LDAP_ATTR_CN, "cn" }, + { LDAP_ATTR_OBJCLASS, "objectClass" }, + { LDAP_ATTR_LIST_END, NULL } +}; + +ATTRIB_MAP_ENTRY groupmap_attr_list_to_delete[] = { + { LDAP_ATTR_GROUP_SID, LDAP_ATTRIBUTE_SID }, + { LDAP_ATTR_GROUP_TYPE, "sambaGroupType" }, + { LDAP_ATTR_DESC, "description" }, + { LDAP_ATTR_DISPLAY_NAME, "displayName" }, + { LDAP_ATTR_LIST_END, NULL } +}; + +/* idmap_ldap sambaUnixIdPool */ + +ATTRIB_MAP_ENTRY idpool_attr_list[] = { + { LDAP_ATTR_UIDNUMBER, LDAP_ATTRIBUTE_UIDNUMBER}, + { LDAP_ATTR_GIDNUMBER, LDAP_ATTRIBUTE_GIDNUMBER}, + { LDAP_ATTR_OBJCLASS, "objectClass" }, + { LDAP_ATTR_LIST_END, NULL } +}; + +ATTRIB_MAP_ENTRY sidmap_attr_list[] = { + { LDAP_ATTR_SID, LDAP_ATTRIBUTE_SID }, + { LDAP_ATTR_UIDNUMBER, LDAP_ATTRIBUTE_UIDNUMBER}, + { LDAP_ATTR_GIDNUMBER, LDAP_ATTRIBUTE_GIDNUMBER}, + { LDAP_ATTR_OBJCLASS, "objectClass" }, + { LDAP_ATTR_LIST_END, NULL } +}; + +/********************************************************************** + perform a simple table lookup and return the attribute name + **********************************************************************/ + + const char* get_attr_key2string( ATTRIB_MAP_ENTRY table[], int key ) +{ + int i = 0; + + while ( table[i].attrib != LDAP_ATTR_LIST_END ) { + if ( table[i].attrib == key ) + return table[i].name; + i++; + } + + return NULL; +} + + +/********************************************************************** + Return the list of attribute names from a mapping table + **********************************************************************/ + + char** get_attr_list( ATTRIB_MAP_ENTRY table[] ) +{ + char **names; + int i = 0; + + while ( table[i].attrib != LDAP_ATTR_LIST_END ) + i++; + i++; + + names = (char**)malloc( sizeof(char*)*i ); + if ( !names ) { + DEBUG(0,("get_attr_list: out of memory\n")); + return NULL; + } + + i = 0; + while ( table[i].attrib != LDAP_ATTR_LIST_END ) { + names[i] = strdup( table[i].name ); + i++; + } + names[i] = NULL; + + return names; +} + +/********************************************************************* + Cleanup + ********************************************************************/ + + void free_attr_list( char **list ) +{ + int i = 0; + + if ( !list ) + return; + + while ( list[i] ) { + SAFE_FREE( list[i] ); + i+=1; + } + + SAFE_FREE( list ); +} + +/******************************************************************* + find the ldap password +******************************************************************/ +BOOL fetch_ldap_pw(char **dn, char** pw) +{ + char *key = NULL; + size_t size; + + *dn = smb_xstrdup(lp_ldap_admin_dn()); + + if (asprintf(&key, "%s/%s", SECRETS_LDAP_BIND_PW, *dn) < 0) { + SAFE_FREE(*dn); + DEBUG(0, ("fetch_ldap_pw: asprintf failed!\n")); + } + + *pw=secrets_fetch(key, &size); + SAFE_FREE(key); + + if (!size) { + /* Upgrade 2.2 style entry */ + char *p; + char* old_style_key = strdup(*dn); + char *data; + fstring old_style_pw; + + if (!old_style_key) { + DEBUG(0, ("fetch_ldap_pw: strdup failed!\n")); + return False; + } + + for (p=old_style_key; *p; p++) + if (*p == ',') *p = '/'; + + data=secrets_fetch(old_style_key, &size); + if (!size && size < sizeof(old_style_pw)) { + DEBUG(0,("fetch_ldap_pw: neither ldap secret retrieved!\n")); + SAFE_FREE(old_style_key); + SAFE_FREE(*dn); + return False; + } + + strncpy(old_style_pw, data, size); + old_style_pw[size] = 0; + + SAFE_FREE(data); + + if (!secrets_store_ldap_pw(*dn, old_style_pw)) { + DEBUG(0,("fetch_ldap_pw: ldap secret could not be upgraded!\n")); + SAFE_FREE(old_style_key); + SAFE_FREE(*dn); + return False; + } + if (!secrets_delete(old_style_key)) { + DEBUG(0,("fetch_ldap_pw: old ldap secret could not be deleted!\n")); + } + + SAFE_FREE(old_style_key); + + *pw = smb_xstrdup(old_style_pw); + } + + return True; +} + +/******************************************************************* +search an attribute and return the first value found. +******************************************************************/ + BOOL smbldap_get_single_attribute (LDAP * ldap_struct, LDAPMessage * entry, + const char *attribute, pstring value) +{ + char **values; + + if ( !attribute ) + return False; + + value[0] = '\0'; + + if ((values = ldap_get_values (ldap_struct, entry, attribute)) == NULL) { + DEBUG (10, ("smbldap_get_single_attribute: [%s] = []\n", attribute)); + + return False; + } + + if (convert_string(CH_UTF8, CH_UNIX,values[0], -1, value, sizeof(pstring)) == (size_t)-1) + { + DEBUG(1, ("smbldap_get_single_attribute: string conversion of [%s] = [%s] failed!\n", + attribute, values[0])); + ldap_value_free(values); + return False; + } + + ldap_value_free(values); +#ifdef DEBUG_PASSWORDS + DEBUG (100, ("smbldap_get_single_attribute: [%s] = [%s]\n", attribute, value)); +#endif + return True; +} + +/************************************************************************ + Routine to manage the LDAPMod structure array + manage memory used by the array, by each struct, and values + ***********************************************************************/ + + void smbldap_set_mod (LDAPMod *** modlist, int modop, const char *attribute, const char *value) +{ + LDAPMod **mods; + int i; + int j; + + mods = *modlist; + + /* sanity checks on the mod values */ + + if (attribute == NULL || *attribute == '\0') + return; +#if 0 /* commented out after discussion with abartlet. Do not reenable. + left here so other so re-add similar code --jerry */ + if (value == NULL || *value == '\0') + return; +#endif + + if (mods == NULL) + { + mods = (LDAPMod **) malloc(sizeof(LDAPMod *)); + if (mods == NULL) + { + DEBUG(0, ("make_a_mod: out of memory!\n")); + return; + } + mods[0] = NULL; + } + + for (i = 0; mods[i] != NULL; ++i) { + if (mods[i]->mod_op == modop && !strcasecmp(mods[i]->mod_type, attribute)) + break; + } + + if (mods[i] == NULL) + { + mods = (LDAPMod **) Realloc (mods, (i + 2) * sizeof (LDAPMod *)); + if (mods == NULL) + { + DEBUG(0, ("make_a_mod: out of memory!\n")); + return; + } + mods[i] = (LDAPMod *) malloc(sizeof(LDAPMod)); + if (mods[i] == NULL) + { + DEBUG(0, ("make_a_mod: out of memory!\n")); + return; + } + mods[i]->mod_op = modop; + mods[i]->mod_values = NULL; + mods[i]->mod_type = strdup(attribute); + mods[i + 1] = NULL; + } + + if (value != NULL) + { + char *utf8_value = NULL; + + j = 0; + if (mods[i]->mod_values != NULL) { + for (; mods[i]->mod_values[j] != NULL; j++); + } + mods[i]->mod_values = (char **)Realloc(mods[i]->mod_values, + (j + 2) * sizeof (char *)); + + if (mods[i]->mod_values == NULL) { + DEBUG (0, ("make_a_mod: Memory allocation failure!\n")); + return; + } + + if (push_utf8_allocate(&utf8_value, value) == (size_t)-1) { + DEBUG (0, ("make_a_mod: String conversion failure!\n")); + return; + } + + mods[i]->mod_values[j] = utf8_value; + + mods[i]->mod_values[j + 1] = NULL; + } + *modlist = mods; +} + + +/********************************************************************** + Set attribute to newval in LDAP, regardless of what value the + attribute had in LDAP before. +*********************************************************************/ + void smbldap_make_mod(LDAP *ldap_struct, LDAPMessage *existing, + LDAPMod ***mods, + const char *attribute, const char *newval) +{ + char **values = NULL; + + if (existing != NULL) { + values = ldap_get_values(ldap_struct, existing, attribute); + } + + /* all of our string attributes are case insensitive */ + + if ((values != NULL) && (values[0] != NULL) && + StrCaseCmp(values[0], newval) == 0) + { + + /* Believe it or not, but LDAP will deny a delete and + an add at the same time if the values are the + same... */ + + ldap_value_free(values); + return; + } + + /* Regardless of the real operation (add or modify) + we add the new value here. We rely on deleting + the old value, should it exist. */ + + if ((newval != NULL) && (strlen(newval) > 0)) { + smbldap_set_mod(mods, LDAP_MOD_ADD, attribute, newval); + } + + if (values == NULL) { + /* There has been no value before, so don't delete it. + Here's a possible race: We might end up with + duplicate attributes */ + return; + } + + /* By deleting exactly the value we found in the entry this + should be race-free in the sense that the LDAP-Server will + deny the complete operation if somebody changed the + attribute behind our back. */ + + smbldap_set_mod(mods, LDAP_MOD_DELETE, attribute, values[0]); + ldap_value_free(values); +} + + +/********************************************************************** + Some varients of the LDAP rebind code do not pass in the third 'arg' + pointer to a void*, so we try and work around it by assuming that the + value of the 'LDAP *' pointer is the same as the one we had passed in + **********************************************************************/ + +struct smbldap_state_lookup { + LDAP *ld; + struct smbldap_state *smbldap_state; + struct smbldap_state_lookup *prev, *next; +}; + +static struct smbldap_state_lookup *smbldap_state_lookup_list; + +static struct smbldap_state *smbldap_find_state(LDAP *ld) +{ + struct smbldap_state_lookup *t; + + for (t = smbldap_state_lookup_list; t; t = t->next) { + if (t->ld == ld) { + return t->smbldap_state; + } + } + return NULL; +} + +static void smbldap_delete_state(struct smbldap_state *smbldap_state) +{ + struct smbldap_state_lookup *t; + + for (t = smbldap_state_lookup_list; t; t = t->next) { + if (t->smbldap_state == smbldap_state) { + DLIST_REMOVE(smbldap_state_lookup_list, t); + SAFE_FREE(t); + return; + } + } +} + +static void smbldap_store_state(LDAP *ld, struct smbldap_state *smbldap_state) +{ + struct smbldap_state *tmp_ldap_state; + struct smbldap_state_lookup *t; + struct smbldap_state_lookup *tmp; + + if ((tmp_ldap_state = smbldap_find_state(ld))) { + SMB_ASSERT(tmp_ldap_state == smbldap_state); + return; + } + + t = smb_xmalloc(sizeof(*t)); + ZERO_STRUCTP(t); + + DLIST_ADD_END(smbldap_state_lookup_list, t, tmp); + t->ld = ld; + t->smbldap_state = smbldap_state; +} + +/******************************************************************* + open a connection to the ldap server. +******************************************************************/ +static int smbldap_open_connection (struct smbldap_state *ldap_state) + +{ + int rc = LDAP_SUCCESS; + int version; + BOOL ldap_v3 = False; + LDAP **ldap_struct = &ldap_state->ldap_struct; + +#ifdef HAVE_LDAP_INITIALIZE + DEBUG(10, ("smbldap_open_connection: %s\n", ldap_state->uri)); + + if ((rc = ldap_initialize(ldap_struct, ldap_state->uri)) != LDAP_SUCCESS) { + DEBUG(0, ("ldap_initialize: %s\n", ldap_err2string(rc))); + return rc; + } +#else + + /* Parse the string manually */ + + { + int port = 0; + fstring protocol; + fstring host; + const char *p = ldap_state->uri; + SMB_ASSERT(sizeof(protocol)>10 && sizeof(host)>254); + + /* skip leading "URL:" (if any) */ + if ( strncasecmp( p, "URL:", 4 ) == 0 ) { + p += 4; + } + + sscanf(p, "%10[^:]://%254s[^:]:%d", protocol, host, &port); + + if (port == 0) { + if (strequal(protocol, "ldap")) { + port = LDAP_PORT; + } else if (strequal(protocol, "ldaps")) { + port = LDAPS_PORT; + } else { + DEBUG(0, ("unrecognised protocol (%s)!\n", protocol)); + } + } + + if ((*ldap_struct = ldap_init(host, port)) == NULL) { + DEBUG(0, ("ldap_init failed !\n")); + return LDAP_OPERATIONS_ERROR; + } + + if (strequal(protocol, "ldaps")) { +#ifdef LDAP_OPT_X_TLS + int tls = LDAP_OPT_X_TLS_HARD; + if (ldap_set_option (*ldap_struct, LDAP_OPT_X_TLS, &tls) != LDAP_SUCCESS) + { + DEBUG(0, ("Failed to setup a TLS session\n")); + } + + DEBUG(3,("LDAPS option set...!\n")); +#else + DEBUG(0,("smbldap_open_connection: Secure connection not supported by LDAP client libraries!\n")); + return LDAP_OPERATIONS_ERROR; +#endif + } + } +#endif + + /* Store the LDAP pointer in a lookup list */ + + smbldap_store_state(*ldap_struct, ldap_state); + + /* Upgrade to LDAPv3 if possible */ + + if (ldap_get_option(*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version) == LDAP_OPT_SUCCESS) + { + if (version != LDAP_VERSION3) + { + version = LDAP_VERSION3; + if (ldap_set_option (*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version) == LDAP_OPT_SUCCESS) { + ldap_v3 = True; + } + } else { + ldap_v3 = True; + } + } + + if (lp_ldap_ssl() == LDAP_SSL_START_TLS) { +#ifdef LDAP_OPT_X_TLS + if (ldap_v3) { + if ((rc = ldap_start_tls_s (*ldap_struct, NULL, NULL)) != LDAP_SUCCESS) + { + DEBUG(0,("Failed to issue the StartTLS instruction: %s\n", + ldap_err2string(rc))); + return rc; + } + DEBUG (3, ("StartTLS issued: using a TLS connection\n")); + } else { + + DEBUG(0, ("Need LDAPv3 for Start TLS\n")); + return LDAP_OPERATIONS_ERROR; + } +#else + DEBUG(0,("smbldap_open_connection: StartTLS not supported by LDAP client libraries!\n")); + return LDAP_OPERATIONS_ERROR; +#endif + } + + DEBUG(2, ("smbldap_open_connection: connection opened\n")); + return rc; +} + + +/******************************************************************* + 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) +{ + struct smbldap_state *ldap_state = arg; + + /** @TODO Should we be doing something to check what servers we rebind to? + Could we get a referral to a machine that we don't want to give our + username and password to? */ + + if (freeit) { + SAFE_FREE(*whop); + memset(*credp, '\0', strlen(*credp)); + SAFE_FREE(*credp); + } else { + DEBUG(5,("rebind_proc_with_state: Rebinding as \"%s\"\n", + ldap_state->bind_dn)); + + *whop = strdup(ldap_state->bind_dn); + if (!*whop) { + return LDAP_NO_MEMORY; + } + *credp = strdup(ldap_state->bind_secret); + if (!*credp) { + SAFE_FREE(*whop); + return LDAP_NO_MEMORY; + } + *methodp = LDAP_AUTH_SIMPLE; + } + 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, + ber_int_t msgid, void *arg) +{ + struct smbldap_state *ldap_state = arg; + int rc; + DEBUG(5,("rebindproc_connect_with_state: Rebinding as \"%s\"\n", + ldap_state->bind_dn)); + + /** @TODO Should we be doing something to check what servers we rebind to? + Could we get a referral to a machine that we don't want to give our + username and password to? */ + + rc = ldap_simple_bind_s(ldap_struct, ldap_state->bind_dn, ldap_state->bind_secret); + + 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 ) +{ + struct smbldap_state *ldap_state = smbldap_find_state(ldap_struct); + + return rebindproc_with_state(ldap_struct, whop, credp, + method, freeit, 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) +{ + struct smbldap_state *ldap_state = smbldap_find_state(ld); + + return rebindproc_connect_with_state(ld, url, (ber_tag_t)request, msgid, + 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. +******************************************************************/ +static int smbldap_connect_system(struct smbldap_state *ldap_state, LDAP * ldap_struct) +{ + int rc; + char *ldap_dn; + char *ldap_secret; + + /* get the password */ + if (!fetch_ldap_pw(&ldap_dn, &ldap_secret)) + { + DEBUG(0, ("ldap_connect_system: Failed to retrieve password from secrets.tdb\n")); + return LDAP_INVALID_CREDENTIALS; + } + + ldap_state->bind_dn = ldap_dn; + ldap_state->bind_secret = ldap_secret; + + /* removed the sasl_bind_s "EXTERNAL" stuff, as my testsuite + (OpenLDAP) doesnt' seem to support it */ + + DEBUG(10,("ldap_connect_system: Binding to ldap server %s as \"%s\"\n", + ldap_state->uri, ldap_dn)); + +#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000) +# if LDAP_SET_REBIND_PROC_ARGS == 2 + ldap_set_rebind_proc(ldap_struct, &rebindproc_connect); +# endif +# if LDAP_SET_REBIND_PROC_ARGS == 3 + ldap_set_rebind_proc(ldap_struct, &rebindproc_connect_with_state, (void *)ldap_state); +# endif +#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 /*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) { + char *ld_error = NULL; + ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, + &ld_error); + DEBUG(ldap_state->num_failures ? 2 : 0, + ("failed to bind to server with dn= %s Error: %s\n\t%s\n", + ldap_dn ? ldap_dn : "(unknown)", ldap_err2string(rc), + ld_error ? ld_error : "(unknown)")); + SAFE_FREE(ld_error); + ldap_state->num_failures++; + return rc; + } + + ldap_state->num_failures = 0; + + DEBUG(3, ("ldap_connect_system: succesful connection to the LDAP server\n")); + return rc; +} + +/********************************************************************** +Connect to LDAP server (called before every ldap operation) +*********************************************************************/ +static int smbldap_open(struct smbldap_state *ldap_state) +{ + int rc; + SMB_ASSERT(ldap_state); + +#ifndef NO_LDAP_SECURITY + if (geteuid() != 0) { + DEBUG(0, ("smbldap_open: cannot access LDAP when not root..\n")); + return LDAP_INSUFFICIENT_ACCESS; + } +#endif + + if ((ldap_state->ldap_struct != NULL) && ((ldap_state->last_ping + SMBLDAP_DONT_PING_TIME) < time(NULL))) { + struct sockaddr_un addr; + socklen_t len = sizeof(addr); + int sd; + if (ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_DESC, &sd) == 0 && + getpeername(sd, (struct sockaddr *) &addr, &len) < 0) { + /* the other end has died. reopen. */ + ldap_unbind_ext(ldap_state->ldap_struct, NULL, NULL); + ldap_state->ldap_struct = NULL; + ldap_state->last_ping = (time_t)0; + } else { + ldap_state->last_ping = time(NULL); + } + } + + if (ldap_state->ldap_struct != NULL) { + DEBUG(11,("smbldap_open: already connected to the LDAP server\n")); + return LDAP_SUCCESS; + } + + if ((rc = smbldap_open_connection(ldap_state))) { + return rc; + } + + if ((rc = smbldap_connect_system(ldap_state, ldap_state->ldap_struct))) { + ldap_unbind_ext(ldap_state->ldap_struct, NULL, NULL); + ldap_state->ldap_struct = NULL; + return rc; + } + + + ldap_state->last_ping = time(NULL); + DEBUG(4,("The LDAP server is succesful connected\n")); + + return LDAP_SUCCESS; +} + +/********************************************************************** +Disconnect from LDAP server +*********************************************************************/ +static NTSTATUS smbldap_close(struct smbldap_state *ldap_state) +{ + if (!ldap_state) + return NT_STATUS_INVALID_PARAMETER; + + if (ldap_state->ldap_struct != NULL) { + ldap_unbind_ext(ldap_state->ldap_struct, NULL, NULL); + ldap_state->ldap_struct = NULL; + } + + smbldap_delete_state(ldap_state); + + DEBUG(5,("The connection to the LDAP server was closed\n")); + /* maybe free the results here --metze */ + + + + return NT_STATUS_OK; +} + +int smbldap_retry_open(struct smbldap_state *ldap_state, int *attempts) +{ + int rc; + + SMB_ASSERT(ldap_state && attempts); + + if (*attempts != 0) { + unsigned int sleep_time; + uint8 rand_byte; + + /* Sleep for a random timeout */ + rand_byte = (char)(sys_random()); + + sleep_time = (((*attempts)*(*attempts))/2)*rand_byte*2; + /* we retry after (0.5, 1, 2, 3, 4.5, 6) seconds + on average. + */ + DEBUG(3, ("Sleeping for %u milliseconds before reconnecting\n", + sleep_time)); + msleep(sleep_time); + } + (*attempts)++; + + if ((rc = smbldap_open(ldap_state))) { + DEBUG(1,("Connection to LDAP Server failed for the %d try!\n",*attempts)); + return rc; + } + + return LDAP_SUCCESS; +} + + +/********************************************************************* + ********************************************************************/ + +int smbldap_search(struct smbldap_state *ldap_state, + const char *base, int scope, const char *filter, + char *attrs[], int attrsonly, + LDAPMessage **res) +{ + int rc = LDAP_SERVER_DOWN; + int attempts = 0; + char *utf8_filter; + + SMB_ASSERT(ldap_state); + + if (push_utf8_allocate(&utf8_filter, filter) == (size_t)-1) { + return LDAP_NO_MEMORY; + } + + while ((rc == LDAP_SERVER_DOWN) && (attempts < SMBLDAP_NUM_RETRIES)) { + + if ((rc = smbldap_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS) + continue; + + rc = ldap_search_s(ldap_state->ldap_struct, base, scope, + utf8_filter, attrs, attrsonly, res); + } + + if (rc == LDAP_SERVER_DOWN) { + DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO)); + smbldap_close(ldap_state); + } + + SAFE_FREE(utf8_filter); + return rc; +} + +int smbldap_modify(struct smbldap_state *ldap_state, const char *dn, LDAPMod *attrs[]) +{ + int rc = LDAP_SERVER_DOWN; + int attempts = 0; + char *utf8_dn; + + SMB_ASSERT(ldap_state); + + if (push_utf8_allocate(&utf8_dn, dn) == (size_t)-1) { + return LDAP_NO_MEMORY; + } + + while ((rc == LDAP_SERVER_DOWN) && (attempts < SMBLDAP_NUM_RETRIES)) { + + if ((rc = smbldap_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS) + continue; + + rc = ldap_modify_s(ldap_state->ldap_struct, utf8_dn, attrs); + } + + if (rc == LDAP_SERVER_DOWN) { + DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO)); + smbldap_close(ldap_state); + } + + SAFE_FREE(utf8_dn); + return rc; +} + +int smbldap_add(struct smbldap_state *ldap_state, const char *dn, LDAPMod *attrs[]) +{ + int rc = LDAP_SERVER_DOWN; + int attempts = 0; + char *utf8_dn; + + SMB_ASSERT(ldap_state); + + if (push_utf8_allocate(&utf8_dn, dn) == (size_t)-1) { + return LDAP_NO_MEMORY; + } + + while ((rc == LDAP_SERVER_DOWN) && (attempts < SMBLDAP_NUM_RETRIES)) { + + if ((rc = smbldap_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS) + continue; + + rc = ldap_add_s(ldap_state->ldap_struct, utf8_dn, attrs); + } + + if (rc == LDAP_SERVER_DOWN) { + DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO)); + smbldap_close(ldap_state); + } + + SAFE_FREE(utf8_dn); + return rc; +} + +int smbldap_delete(struct smbldap_state *ldap_state, const char *dn) +{ + int rc = LDAP_SERVER_DOWN; + int attempts = 0; + char *utf8_dn; + + SMB_ASSERT(ldap_state); + + if (push_utf8_allocate(&utf8_dn, dn) == (size_t)-1) { + return LDAP_NO_MEMORY; + } + + while ((rc == LDAP_SERVER_DOWN) && (attempts < SMBLDAP_NUM_RETRIES)) { + + if ((rc = smbldap_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS) + continue; + + rc = ldap_delete_s(ldap_state->ldap_struct, utf8_dn); + } + + if (rc == LDAP_SERVER_DOWN) { + DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO)); + smbldap_close(ldap_state); + } + + SAFE_FREE(utf8_dn); + return rc; +} + +int smbldap_extended_operation(struct smbldap_state *ldap_state, + LDAP_CONST char *reqoid, struct berval *reqdata, + LDAPControl **serverctrls, LDAPControl **clientctrls, + char **retoidp, struct berval **retdatap) +{ + int rc = LDAP_SERVER_DOWN; + int attempts = 0; + + if (!ldap_state) + return (-1); + + while ((rc == LDAP_SERVER_DOWN) && (attempts < SMBLDAP_NUM_RETRIES)) { + + if ((rc = smbldap_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS) + continue; + + rc = ldap_extended_operation_s(ldap_state->ldap_struct, reqoid, reqdata, + serverctrls, clientctrls, retoidp, retdatap); + } + + if (rc == LDAP_SERVER_DOWN) { + DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO)); + smbldap_close(ldap_state); + } + + return rc; +} + +/******************************************************************* + run the search by name. +******************************************************************/ +int smbldap_search_suffix (struct smbldap_state *ldap_state, const char *filter, + char **search_attr, LDAPMessage ** result) +{ + int scope = LDAP_SCOPE_SUBTREE; + int rc; + + DEBUG(2, ("smbldap_search_suffix: searching for:[%s]\n", filter)); + + rc = smbldap_search(ldap_state, lp_ldap_suffix(), scope, filter, search_attr, 0, result); + + if (rc != LDAP_SUCCESS) { + char *ld_error = NULL; + ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, + &ld_error); + DEBUG(0,("smbldap_search_suffix: Problem during the LDAP search: %s (%s)\n", + ld_error?ld_error:"(unknown)", ldap_err2string (rc))); + DEBUG(3,("smbldap_search_suffix: Query was: %s, %s\n", lp_ldap_suffix(), + filter)); + SAFE_FREE(ld_error); + } + + return rc; +} + +/********************************************************************** + Housekeeping + *********************************************************************/ + +void smbldap_free_struct(struct smbldap_state **ldap_state) +{ + smbldap_close(*ldap_state); + + if ((*ldap_state)->bind_secret) { + memset((*ldap_state)->bind_secret, '\0', strlen((*ldap_state)->bind_secret)); + } + + SAFE_FREE((*ldap_state)->bind_dn); + SAFE_FREE((*ldap_state)->bind_secret); + + *ldap_state = NULL; + + /* No need to free any further, as it is talloc()ed */ +} + + +/********************************************************************** + Intitalise the 'general' ldap structures, on which ldap operations may be conducted + *********************************************************************/ + +NTSTATUS smbldap_init(TALLOC_CTX *mem_ctx, const char *location, struct smbldap_state **smbldap_state) +{ + *smbldap_state = talloc_zero(mem_ctx, sizeof(**smbldap_state)); + if (!*smbldap_state) { + DEBUG(0, ("talloc() failed for ldapsam private_data!\n")); + return NT_STATUS_NO_MEMORY; + } + + if (location) { + (*smbldap_state)->uri = talloc_strdup(mem_ctx, location); + } else { + (*smbldap_state)->uri = "ldap://localhost"; + } + return NT_STATUS_OK; +} + +/********************************************************************** + Add the sambaDomain to LDAP, so we don't have to search for this stuff + again. This is a once-add operation for now. + + TODO: Add other attributes, and allow modification. +*********************************************************************/ +static NTSTATUS add_new_domain_info(struct smbldap_state *ldap_state, + const char *domain_name) +{ + fstring sid_string; + fstring algorithmic_rid_base_string; + pstring filter, dn; + LDAPMod **mods = NULL; + int rc; + int ldap_op; + LDAPMessage *result = NULL; + int num_result; + char **attr_list; + + slprintf (filter, sizeof (filter) - 1, "(&(%s=%s)(objectclass=%s))", + get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN), + domain_name, LDAP_OBJ_DOMINFO); + + attr_list = get_attr_list( dominfo_attr_list ); + rc = smbldap_search_suffix(ldap_state, filter, attr_list, &result); + free_attr_list( attr_list ); + + if (rc != LDAP_SUCCESS) { + return NT_STATUS_UNSUCCESSFUL; + } + + num_result = ldap_count_entries(ldap_state->ldap_struct, result); + + if (num_result > 1) { + DEBUG (0, ("More than domain with that name exists: bailing out!\n")); + ldap_msgfree(result); + return NT_STATUS_UNSUCCESSFUL; + } + + /* Check if we need to add an entry */ + DEBUG(3,("Adding new domain\n")); + ldap_op = LDAP_MOD_ADD; + + snprintf(dn, sizeof(dn), "%s=%s,%s", get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN), + domain_name, lp_ldap_suffix()); + + /* Free original search */ + ldap_msgfree(result); + + /* make the changes - the entry *must* not already have samba attributes */ + smbldap_set_mod(&mods, LDAP_MOD_ADD, get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN), + domain_name); + + /* If we don't have an entry, then ask secrets.tdb for what it thinks. + It may choose to make it up */ + + sid_to_string(sid_string, get_global_sam_sid()); + smbldap_set_mod(&mods, LDAP_MOD_ADD, get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOM_SID), sid_string); + + slprintf(algorithmic_rid_base_string, sizeof(algorithmic_rid_base_string) - 1, "%i", algorithmic_rid_base()); + smbldap_set_mod(&mods, LDAP_MOD_ADD, get_attr_key2string(dominfo_attr_list, LDAP_ATTR_ALGORITHMIC_RID_BASE), + algorithmic_rid_base_string); + smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_DOMINFO); + + switch(ldap_op) + { + case LDAP_MOD_ADD: + rc = smbldap_add(ldap_state, dn, mods); + break; + case LDAP_MOD_REPLACE: + rc = smbldap_modify(ldap_state, dn, mods); + break; + default: + DEBUG(0,("Wrong LDAP operation type: %d!\n", ldap_op)); + return NT_STATUS_INVALID_PARAMETER; + } + + if (rc!=LDAP_SUCCESS) { + char *ld_error = NULL; + ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error); + DEBUG(1,("failed to %s domain dn= %s with: %s\n\t%s\n", + ldap_op == LDAP_MOD_ADD ? "add" : "modify", + dn, ldap_err2string(rc), + ld_error?ld_error:"unknown")); + SAFE_FREE(ld_error); + + ldap_mods_free(mods, True); + return NT_STATUS_UNSUCCESSFUL; + } + + DEBUG(2,("added: domain = %s in the LDAP database\n", domain_name)); + ldap_mods_free(mods, True); + return NT_STATUS_OK; +} + +/********************************************************************** +Search for the domain info entry +*********************************************************************/ +NTSTATUS smbldap_search_domain_info(struct smbldap_state *ldap_state, + LDAPMessage ** result, const char *domain_name, + BOOL try_add) +{ + NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; + pstring filter; + int rc; + char **attr_list; + int count; + + snprintf(filter, sizeof(filter)-1, "(&(objectClass=%s)(%s=%s))", + LDAP_OBJ_DOMINFO, + get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN), + domain_name); + + DEBUG(2, ("Searching for:[%s]\n", filter)); + + + attr_list = get_attr_list( dominfo_attr_list ); + rc = smbldap_search_suffix(ldap_state, filter, attr_list , result); + free_attr_list( attr_list ); + + if (rc != LDAP_SUCCESS) { + DEBUG(2,("Problem during LDAPsearch: %s\n", ldap_err2string (rc))); + DEBUG(2,("Query was: %s, %s\n", lp_ldap_suffix(), filter)); + } else if (ldap_count_entries(ldap_state->ldap_struct, *result) < 1) { + DEBUG(3, ("Got no domain info entries for domain\n")); + ldap_msgfree(*result); + *result = NULL; + if (try_add && NT_STATUS_IS_OK(ret = add_new_domain_info(ldap_state, domain_name))) { + return smbldap_search_domain_info(ldap_state, result, domain_name, False); + } + else { + DEBUG(0, ("Adding domain info for %s failed with %s\n", + domain_name, nt_errstr(ret))); + return ret; + } + } else if ((count = ldap_count_entries(ldap_state->ldap_struct, *result)) > 1) { + DEBUG(0, ("Got too many (%d) domain info entries for domain %s\n", + count, domain_name)); + ldap_msgfree(*result); + *result = NULL; + return ret; + } else { + return NT_STATUS_OK; + } + + return ret; +} + diff --git a/source3/lib/sysquotas.c b/source3/lib/sysquotas.c new file mode 100644 index 0000000000..efc9e65b9d --- /dev/null +++ b/source3/lib/sysquotas.c @@ -0,0 +1,963 @@ +/* + Unix SMB/CIFS implementation. + System QUOTA function wrappers + Copyright (C) Stefan (metze) Metzmacher 2003 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + + +#ifndef AUTOCONF_TEST + +#include "includes.h" + +#ifdef HAVE_SYS_QUOTAS + +#if defined(HAVE_QUOTACTL_4A) +/* long quotactl(int cmd, char *special, qid_t id, caddr_t addr) */ +/* this is used by: linux,HPUX,IRIX */ + +/**************************************************************************** + Abstract out the old and new Linux quota get calls. +****************************************************************************/ +static int sys_get_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp) +{ + int ret = -1; + uint32 qflags = 0; + struct SYS_DQBLK D; + SMB_BIG_UINT bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE; + + if (!path||!bdev||!dp) + smb_panic("sys_get_vfs_quota: called with NULL pointer"); + + ZERO_STRUCT(D); + ZERO_STRUCT(*dp); + dp->qtype = qtype; + + switch (qtype) { + case SMB_USER_QUOTA_TYPE: + /* we use id.uid == 0 for default quotas */ + if (id.uid == 0) { + ret = 0; + break; + } + + if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, id.uid, (CADDR_T)&D))) { + return ret; + } + + if ((D.dqb_curblocks==0)&& + (D.dqb_bsoftlimit==0)&& + (D.dqb_bhardlimit==0)) { + /* the upper layer functions don't want empty quota records...*/ + return -1; + } + + break; +#ifdef HAVE_GROUP_QUOTA + case SMB_GROUP_QUOTA_TYPE: + if ((ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), bdev, id.gid, (CADDR_T)&D))) { + return ret; + } + + if ((D.dqb_curblocks==0)&& + (D.dqb_bsoftlimit==0)&& + (D.dqb_bhardlimit==0)) { + /* the upper layer functions don't want empty quota records...*/ + return -1; + } + + break; +#endif /* HAVE_GROUP_QUOTA */ + case SMB_USER_FS_QUOTA_TYPE: + id.uid = getuid(); + + if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, id.uid, (CADDR_T)&D))==0) { + qflags |= QUOTAS_DENY_DISK; + } + + /* get the default quotas stored in the root's (uid =0) record */ + if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, 0, (CADDR_T)&D))) { + return ret; + } + + ret = 0; + break; + default: + errno = ENOSYS; + return -1; + } + + dp->bsize = bsize; + dp->softlimit = (SMB_BIG_UINT)D.dqb_bsoftlimit; + dp->hardlimit = (SMB_BIG_UINT)D.dqb_bhardlimit; + dp->ihardlimit = (SMB_BIG_UINT)D.dqb_ihardlimit; + dp->isoftlimit = (SMB_BIG_UINT)D.dqb_isoftlimit; + dp->curinodes = (SMB_BIG_UINT)D.dqb_curinodes; + dp->curblocks = (SMB_BIG_UINT)D.dqb_curblocks; + + + dp->qflags = qflags; + + return ret; +} + +/**************************************************************************** + Abstract out the old and new Linux quota set calls. +****************************************************************************/ + +static int sys_set_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp) +{ + int ret = -1; + uint32 qflags = 0; + struct SYS_DQBLK D; + SMB_BIG_UINT bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE; + + if (!path||!bdev||!dp) + smb_panic("sys_set_vfs_quota: called with NULL pointer"); + + ZERO_STRUCT(D); + + if (bsize == dp->bsize) { + D.dqb_bsoftlimit = dp->softlimit; + D.dqb_bhardlimit = dp->hardlimit; + D.dqb_ihardlimit = dp->ihardlimit; + D.dqb_isoftlimit = dp->isoftlimit; + } else { + D.dqb_bsoftlimit = (dp->softlimit*dp->bsize)/bsize; + D.dqb_bhardlimit = (dp->hardlimit*dp->bsize)/bsize; + D.dqb_ihardlimit = (dp->ihardlimit*dp->bsize)/bsize; + D.dqb_isoftlimit = (dp->isoftlimit*dp->bsize)/bsize; + } + + qflags = dp->qflags; + + switch (qtype) { + case SMB_USER_QUOTA_TYPE: + /* we use id.uid == 0 for default quotas */ + if (id.uid>0) { + ret = quotactl(QCMD(Q_SETQLIM,USRQUOTA), bdev, id.uid, (CADDR_T)&D); + } + break; +#ifdef HAVE_GROUP_QUOTA + case SMB_GROUP_QUOTA_TYPE: + ret = quotactl(QCMD(Q_SETQLIM,GRPQUOTA), bdev, id.gid, (CADDR_T)&D); + break; +#endif /* HAVE_GROUP_QUOTA */ + case SMB_USER_FS_QUOTA_TYPE: + /* this stuff didn't work as it should: + * switching on/off quota via quotactl() + * didn't work! + * So we only set the default limits + * --metze + * + * On HPUX we didn't have the mount path, + * we need to fix sys_path_to_bdev() + * + */ +#if 0 + uid = getuid(); + + ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, uid, (CADDR_T)&D); + + if ((qflags"AS_DENY_DISK)||(qflags"AS_ENABLED)) { + if (ret == 0) { + char *quota_file = NULL; + + asprintf("a_file,"/%s/%s%s",path, QUOTAFILENAME,USERQUOTAFILE_EXTENSION); + if (quota_file == NULL) { + DEBUG(0,("asprintf() failed!\n")); + errno = ENOMEM; + return -1; + } + + ret = quotactl(QCMD(Q_QUOTAON,USRQUOTA), bdev, -1,(CADDR_T)quota_file); + } else { + ret = 0; + } + } else { + if (ret != 0) { + /* turn off */ + ret = quotactl(QCMD(Q_QUOTAOFF,USRQUOTA), bdev, -1, (CADDR_T)0); + } else { + ret = 0; + } + } + + DEBUG(0,("vfs_fs_quota: ret(%d) errno(%d)[%s] uid(%d) bdev[%s]\n", + ret,errno,strerror(errno),uid,bdev)); +#endif + + /* we use uid == 0 for default quotas */ + ret = quotactl(QCMD(Q_SETQLIM,USRQUOTA), bdev, 0, (CADDR_T)&D); + + break; + + default: + errno = ENOSYS; + return -1; + } + + return ret; +} + +/*#endif HAVE_QUOTACTL_4A */ +#elif defined(HAVE_QUOTACTL_4B) + +#error HAVE_QUOTACTL_4B not implemeted + +/*#endif HAVE_QUOTACTL_4B */ +#elif defined(HAVE_QUOTACTL_3) + +#error HAVE_QUOTACTL_3 not implemented + +/* #endif HAVE_QUOTACTL_3 */ +#else /* NO_QUOTACTL_USED */ + +static int sys_get_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp) +{ + int ret = -1; + + if (!path||!bdev||!dp) + smb_panic("sys_get_vfs_quota: called with NULL pointer"); + + errno = ENOSYS; + + return ret; +} + +static int sys_set_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp) +{ + int ret = -1; + + if (!path||!bdev||!dp) + smb_panic("sys_set_vfs_quota: called with NULL pointer"); + + errno = ENOSYS; + + return ret; +} + +#endif /* NO_QUOTACTL_USED */ + +#ifdef HAVE_MNTENT +static int sys_path_to_bdev(const char *path, char **mntpath, char **bdev, char **fs) +{ + int ret = -1; + SMB_STRUCT_STAT S; + FILE *fp; + struct mntent *mnt; + SMB_DEV_T devno; + + /* find the block device file */ + + if (!path||!mntpath||!bdev||!fs) + smb_panic("sys_path_to_bdev: called with NULL pointer"); + + (*mntpath) = NULL; + (*bdev) = NULL; + (*fs) = NULL; + + if ( sys_stat(path, &S) == -1 ) + return (-1); + + devno = S.st_dev ; + + fp = setmntent(MOUNTED,"r"); + + while ((mnt = getmntent(fp))) { + if ( sys_stat(mnt->mnt_dir,&S) == -1 ) + continue ; + + if (S.st_dev == devno) { + (*mntpath) = strdup(mnt->mnt_dir); + (*bdev) = strdup(mnt->mnt_fsname); + (*fs) = strdup(mnt->mnt_type); + if ((*mntpath)&&(*bdev)&&(*fs)) { + ret = 0; + } else { + SAFE_FREE(*mntpath); + SAFE_FREE(*bdev); + SAFE_FREE(*fs); + ret = -1; + } + + break; + } + } + + endmntent(fp) ; + + return ret; +} +/* #endif HAVE_MNTENT */ +#elif defined(HAVE_DEVNM) + +/* we have this on HPUX, ... */ +static int sys_path_to_bdev(const char *path, char **mntpath, char **bdev, char **fs) +{ + int ret = -1; + char dev_disk[256]; + SMB_STRUCT_STAT S; + + if (!path||!mntpath||!bdev||!fs) + smb_panic("sys_path_to_bdev: called with NULL pointer"); + + (*mntpath) = NULL; + (*bdev) = NULL; + (*fs) = NULL; + + /* find the block device file */ + + if ((ret=sys_stat(path, &S))!=0) { + return ret; + } + + if ((ret=devnm(S_IFBLK, S.st_dev, dev_disk, 256, 1))!=0) { + return ret; + } + + /* we should get the mntpath right... + * but I don't know how + * --metze + */ + (*mntpath) = strdup(path); + (*bdev) = strdup(dev_disk); + if ((*mntpath)&&(*bdev)) { + ret = 0; + } else { + SAFE_FREE(*mntpath); + SAFE_FREE(*bdev); + ret = -1; + } + + + return ret; +} + +/* #endif HAVE_DEVNM */ +#else +/* we should fake this up...*/ +static int sys_path_to_bdev(const char *path, char **mntpath, char **bdev, char **fs) +{ + int ret = -1; + + if (!path||!mntpath||!bdev||!fs) + smb_panic("sys_path_to_bdev: called with NULL pointer"); + + (*mntpath) = NULL; + (*bdev) = NULL; + (*fs) = NULL; + + (*mntpath) = strdup(path); + if (*mntpath) { + ret = 0; + } else { + SAFE_FREE(*mntpath); + ret = -1; + } + + return ret; +} +#endif + + +/********************************************************* + if we have XFS QUOTAS we should use them + *********************************************************/ +#ifdef HAVE_XFS_QUOTA +/**************************************************************************** + Abstract out the XFS Quota Manager quota get call. +****************************************************************************/ +static int sys_get_xfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp) +{ + int ret; + uint32 qflags = 0; + SMB_BIG_UINT bsize = (SMB_BIG_UINT)BBSIZE; + struct fs_disk_quota D; + struct fs_quota_stat F; + ZERO_STRUCT(D); + ZERO_STRUCT(F); + + if (!bdev||!dp) + smb_panic("sys_get_xfs_quota: called with NULL pointer"); + + ZERO_STRUCT(*dp); + dp->qtype = qtype; + + switch (qtype) { + case SMB_USER_QUOTA_TYPE: + /* we use id.uid == 0 for default quotas */ + if (id.uid == 0) { + ret = 0; + break; + } + if ((ret=quotactl(QCMD(Q_XGETQUOTA,USRQUOTA), bdev, id.uid, (CADDR_T)&D))) + return ret; + break; +#ifdef HAVE_GROUP_QUOTA + case SMB_GROUP_QUOTA_TYPE: + if ((ret=quotactl(QCMD(Q_XGETQUOTA,GRPQUOTA), bdev, id.gid, (CADDR_T)&D))) + return ret; + break; +#endif /* HAVE_GROUP_QUOTA */ + case SMB_USER_FS_QUOTA_TYPE: + /* TODO: get quota status from quotactl() ... */ + if ((ret = quotactl(QCMD(Q_XGETQSTAT,USRQUOTA), bdev, -1, (CADDR_T)&F))) + return ret; + + if (F.qs_flags & XFS_QUOTA_UDQ_ENFD) { + qflags |= QUOTAS_DENY_DISK; + } + else if (F.qs_flags & XFS_QUOTA_UDQ_ACCT) { + qflags |= QUOTAS_ENABLED; + } + + /* we use uid == 0 for default quotas */ + if ((ret=quotactl(QCMD(Q_XGETQUOTA,USRQUOTA), bdev, 0, (CADDR_T)&D))) + return ret; + + break; + default: + errno = ENOSYS; + return -1; + } + + dp->bsize = bsize; + dp->softlimit = (SMB_BIG_UINT)D.d_blk_softlimit; + dp->hardlimit = (SMB_BIG_UINT)D.d_blk_hardlimit; + dp->ihardlimit = (SMB_BIG_UINT)D.d_ino_hardlimit; + dp->isoftlimit = (SMB_BIG_UINT)D.d_ino_softlimit; + dp->curinodes = (SMB_BIG_UINT)D.d_icount; + dp->curblocks = (SMB_BIG_UINT)D.d_bcount; + dp->qflags = qflags; + + return ret; +} + +/**************************************************************************** + Abstract out the XFS Quota Manager quota set call. +****************************************************************************/ +static int sys_set_xfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp) +{ + int ret = -1; + uint32 qflags = 0; + SMB_BIG_UINT bsize = (SMB_BIG_UINT)BBSIZE; + struct fs_disk_quota D; + struct fs_quota_stat F; + int q_on = 0; + int q_off = 0; + ZERO_STRUCT(D); + ZERO_STRUCT(F); + + if (!bdev||!dp) + smb_panic("sys_set_xfs_quota: called with NULL pointer"); + + if (bsize == dp->bsize) { + D.d_blk_softlimit = dp->softlimit; + D.d_blk_hardlimit = dp->hardlimit; + D.d_ino_hardlimit = dp->ihardlimit; + D.d_ino_softlimit = dp->isoftlimit; + } else { + D.d_blk_softlimit = (dp->softlimit*dp->bsize)/bsize; + D.d_blk_hardlimit = (dp->hardlimit*dp->bsize)/bsize; + D.d_ino_hardlimit = (dp->ihardlimit*dp->bsize)/bsize; + D.d_ino_softlimit = (dp->isoftlimit*dp->bsize)/bsize; + } + + qflags = dp->qflags; + + switch (qtype) { + case SMB_USER_QUOTA_TYPE: + /* we use uid == 0 for default quotas */ + if (id.uid>0) { + D.d_fieldmask |= FS_DQ_LIMIT_MASK; + ret = quotactl(QCMD(Q_XSETQLIM,USRQUOTA), bdev, id.uid, (CADDR_T)&D); + } + break; +#ifdef HAVE_GROUP_QUOTA + case SMB_GROUP_QUOTA_TYPE: + D.d_fieldmask |= FS_DQ_LIMIT_MASK; + ret = quotactl(QCMD(Q_XSETQLIM,GRPQUOTA), bdev, id.gid, (CADDR_T)&D); + break; +#endif /* HAVE_GROUP_QUOTA */ + case SMB_USER_FS_QUOTA_TYPE: + /* TODO */ + quotactl(QCMD(Q_XGETQSTAT,USRQUOTA), bdev, -1, (CADDR_T)&F); + + if (qflags & QUOTAS_DENY_DISK) { + if (!(F.qs_flags & XFS_QUOTA_UDQ_ENFD)) + q_on |= XFS_QUOTA_UDQ_ENFD; + if (!(F.qs_flags & XFS_QUOTA_UDQ_ACCT)) + q_on |= XFS_QUOTA_UDQ_ACCT; + + if (q_on != 0) { + ret = quotactl(QCMD(Q_XQUOTAON,USRQUOTA),bdev, -1, (CADDR_T)&q_on); + } + + } else if (qflags & QUOTAS_ENABLED) { + if (F.qs_flags & XFS_QUOTA_UDQ_ENFD) + q_off |= XFS_QUOTA_UDQ_ENFD; + + if (q_off != 0) { + ret = quotactl(QCMD(Q_XQUOTAOFF,USRQUOTA),bdev, -1, (CADDR_T)&q_off); + } + + if (!(F.qs_flags & XFS_QUOTA_UDQ_ACCT)) + q_on |= XFS_QUOTA_UDQ_ACCT; + + if (q_on != 0) { + ret = quotactl(QCMD(Q_XQUOTAON,USRQUOTA),bdev, -1, (CADDR_T)&q_on); + } + } else { +#if 0 + /* Switch on XFS_QUOTA_UDQ_ACCT didn't work! + * only swittching off XFS_QUOTA_UDQ_ACCT work + */ + if (F.qs_flags & XFS_QUOTA_UDQ_ENFD) + q_off |= XFS_QUOTA_UDQ_ENFD; + if (F.qs_flags & XFS_QUOTA_UDQ_ACCT) + q_off |= XFS_QUOTA_UDQ_ACCT; + + if (q_off !=0) { + ret = quotactl(QCMD(Q_XQUOTAOFF,USRQUOTA),bdev, -1, (CADDR_T)&q_off); + } +#endif + } + + /* we use uid == 0 for default quotas */ + D.d_fieldmask |= FS_DQ_LIMIT_MASK; + ret = quotactl(QCMD(Q_XSETQLIM,USRQUOTA), bdev, 0, (CADDR_T)&D); + break; + default: + errno = ENOSYS; + return -1; + } + + return ret; +} +#endif /* HAVE_XFS_QUOTA */ + + + + + + + + + + + + + + + +/********************************************************************* + Now the list of all filesystem specific quota systems we have found +**********************************************************************/ +static struct { + const char *name; + int (*get_quota)(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp); + int (*set_quota)(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp); +} sys_quota_backends[] = { +#ifdef HAVE_XFS_QUOTA + {"xfs", sys_get_xfs_quota, sys_set_xfs_quota}, +#endif /* HAVE_XFS_QUOTA */ + {NULL, NULL, NULL} +}; + +static int command_get_quota(const char *path, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp) +{ + const char *get_quota_command; + + get_quota_command = lp_get_quota_command(); + if (get_quota_command && *get_quota_command) { + const char *p; + char *p2; + char **lines; + pstring syscmd; + int _id = -1; + + switch(qtype) { + case SMB_USER_QUOTA_TYPE: + case SMB_USER_FS_QUOTA_TYPE: + _id = id.uid; + break; + case SMB_GROUP_QUOTA_TYPE: + case SMB_GROUP_FS_QUOTA_TYPE: + _id = id.gid; + break; + default: + DEBUG(0,("invalid quota type.\n")); + return -1; + } + + slprintf(syscmd, sizeof(syscmd)-1, + "%s \"%s\" %d %d", + get_quota_command, path, qtype, _id); + + DEBUG (3, ("get_quota: Running command %s\n", syscmd)); + + lines = file_lines_pload(syscmd, NULL); + if (lines) { + char *line = lines[0]; + + DEBUG (3, ("Read output from get_quota, \"r%s\"\n", line)); + + /* we need to deal with long long unsigned here, if supported */ + + dp->qflags = (enum SMB_QUOTA_TYPE)strtoul(line, &p2, 10); + p = p2; + while (p && *p && isspace(*p)) + p++; + if (p && *p) + dp->curblocks = STR_TO_SMB_BIG_UINT(p, &p); + else + goto invalid_param; + while (p && *p && isspace(*p)) + p++; + if (p && *p) + dp->softlimit = STR_TO_SMB_BIG_UINT(p, &p); + else + goto invalid_param; + while (p && *p && isspace(*p)) + p++; + if (p && *p) + dp->hardlimit = STR_TO_SMB_BIG_UINT(p, &p); + else + goto invalid_param; + while (p && *p && isspace(*p)) + p++; + if (p && *p) + dp->curinodes = STR_TO_SMB_BIG_UINT(p, &p); + else + goto invalid_param; + while (p && *p && isspace(*p)) + p++; + if (p && *p) + dp->isoftlimit = STR_TO_SMB_BIG_UINT(p, &p); + else + goto invalid_param; + while (p && *p && isspace(*p)) + p++; + if (p && *p) + dp->ihardlimit = STR_TO_SMB_BIG_UINT(p, &p); + else + goto invalid_param; + while (p && *p && isspace(*p)) + p++; + if (p && *p) + dp->bsize = STR_TO_SMB_BIG_UINT(p, NULL); + else + dp->bsize = 1024; + file_lines_free(lines); + DEBUG (3, ("Parsed output of get_quota, ...\n")); + +#ifdef LARGE_SMB_OFF_T + DEBUGADD (5,( + "qflags:%u curblocks:%llu softlimit:%llu hardlimit:%llu\n" + "curinodes:%llu isoftlimit:%llu ihardlimit:%llu bsize:%llu\n", + dp->qflags,(long long unsigned)dp->curblocks, + (long long unsigned)dp->softlimit,(long long unsigned)dp->hardlimit, + (long long unsigned)dp->curinodes, + (long long unsigned)dp->isoftlimit,(long long unsigned)dp->ihardlimit, + (long long unsigned)dp->bsize)); +#else /* LARGE_SMB_OFF_T */ + DEBUGADD (5,( + "qflags:%u curblocks:%lu softlimit:%lu hardlimit:%lu\n" + "curinodes:%lu isoftlimit:%lu ihardlimit:%lu bsize:%lu\n", + dp->qflags,(long unsigned)dp->curblocks, + (long unsigned)dp->softlimit,(long unsigned)dp->hardlimit, + (long unsigned)dp->curinodes, + (long unsigned)dp->isoftlimit,(long unsigned)dp->ihardlimit, + (long unsigned)dp->bsize)); +#endif /* LARGE_SMB_OFF_T */ + return 0; + } + + DEBUG (0, ("get_quota_command failed!\n")); + return -1; + } + + errno = ENOSYS; + return -1; + +invalid_param: + DEBUG(0,("The output of get_quota_command is invalid!\n")); + return -1; +} + +static int command_set_quota(const char *path, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp) +{ + const char *set_quota_command; + + set_quota_command = lp_set_quota_command(); + if (set_quota_command && *set_quota_command) { + char **lines; + pstring syscmd; + int _id = -1; + + switch(qtype) { + case SMB_USER_QUOTA_TYPE: + case SMB_USER_FS_QUOTA_TYPE: + _id = id.uid; + break; + case SMB_GROUP_QUOTA_TYPE: + case SMB_GROUP_FS_QUOTA_TYPE: + _id = id.gid; + break; + default: + return -1; + } + +#ifdef LARGE_SMB_OFF_T + slprintf(syscmd, sizeof(syscmd)-1, + "%s \"%s\" %d %d " + "%u %llu %llu " + "%llu %llu %llu ", + set_quota_command, path, qtype, _id, dp->qflags, + (long long unsigned)dp->softlimit,(long long unsigned)dp->hardlimit, + (long long unsigned)dp->isoftlimit,(long long unsigned)dp->ihardlimit, + (long long unsigned)dp->bsize); +#else /* LARGE_SMB_OFF_T */ + slprintf(syscmd, sizeof(syscmd)-1, + "%s \"%s\" %d %d " + "%u %lu %lu " + "%lu %lu %lu ", + set_quota_command, path, qtype, _id, dp->qflags, + (long unsigned)dp->softlimit,(long unsigned)dp->hardlimit, + (long unsigned)dp->isoftlimit,(long unsigned)dp->ihardlimit, + (long unsigned)dp->bsize); +#endif /* LARGE_SMB_OFF_T */ + + + + DEBUG (3, ("get_quota: Running command %s\n", syscmd)); + + lines = file_lines_pload(syscmd, NULL); + if (lines) { + char *line = lines[0]; + + DEBUG (3, ("Read output from set_quota, \"%s\"\n", line)); + + file_lines_free(lines); + + return 0; + } + DEBUG (0, ("set_quota_command failed!\n")); + return -1; + } + + errno = ENOSYS; + return -1; +} + +int sys_get_quota(const char *path, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp) +{ + int ret = -1; + int i; + BOOL ready = False; + char *mntpath = NULL; + char *bdev = NULL; + char *fs = NULL; + + if (!path||!dp) + smb_panic("sys_get_quota: called with NULL pointer"); + + if (command_get_quota(path, qtype, id, dp)==0) { + return 0; + } else if (errno != ENOSYS) { + return -1; + } + + if ((ret=sys_path_to_bdev(path,&mntpath,&bdev,&fs))!=0) { + return ret; + } + + for (i=0;(fs && sys_quota_backends[i].name && sys_quota_backends[i].get_quota);i++) { + if (strcmp(fs,sys_quota_backends[i].name)==0) { + ret = sys_quota_backends[i].get_quota(mntpath, bdev, qtype, id, dp); + ready = True; + break; + } + } + + if (!ready) { + /* use the default vfs quota functions */ + ret = sys_get_vfs_quota(mntpath, bdev, qtype, id, dp); + } + + SAFE_FREE(mntpath); + SAFE_FREE(bdev); + SAFE_FREE(fs); + + if ((ret!=0)&& (errno == EDQUOT)) { + return 0; + } + + return ret; +} + +int sys_set_quota(const char *path, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp) +{ + int ret = -1; + int i; + BOOL ready = False; + char *mntpath = NULL; + char *bdev = NULL; + char *fs = NULL; + + /* find the block device file */ + + if (!path||!dp) + smb_panic("get_smb_quota: called with NULL pointer"); + + if (command_set_quota(path, qtype, id, dp)==0) { + return 0; + } else if (errno != ENOSYS) { + return -1; + } + + if ((ret=sys_path_to_bdev(path,&mntpath,&bdev,&fs))!=0) { + return ret; + } + + for (i=0;(fs && sys_quota_backends[i].name && sys_quota_backends[i].set_quota);i++) { + if (strcmp(fs,sys_quota_backends[i].name)==0) { + ret = sys_quota_backends[i].set_quota(mntpath, bdev, qtype, id, dp); + ready = True; + break; + } + } + + if (!ready) { + /* use the default vfs quota functions */ + ret=sys_set_vfs_quota(mntpath, bdev, qtype, id, dp); + } + + SAFE_FREE(mntpath); + SAFE_FREE(bdev); + SAFE_FREE(fs); + + if ((ret!=0)&& (errno == EDQUOT)) { + return 0; + } + + return ret; +} + +#else /* HAVE_SYS_QUOTAS */ + void dummy_sysquotas_c(void) +{ + return; +} +#endif /* HAVE_SYS_QUOTAS */ + +#else /* ! AUTOCONF_TEST */ +/* this is the autoconf driver to test witch quota system we should use */ + +#if defined(HAVE_QUOTACTL_4A) +/* long quotactl(int cmd, char *special, qid_t id, caddr_t addr) */ + +#ifdef HAVE_SYS_TYPES_H +#include +#endif + +#ifdef HAVE_ASM_TYPES_H +#include +#endif + +#if defined(HAVE_LINUX_QUOTA_H) +# include +# if defined(HAVE_STRUCT_IF_DQBLK) +# define SYS_DQBLK if_dqblk +# elif defined(HAVE_STRUCT_MEM_DQBLK) +# define SYS_DQBLK mem_dqblk +# endif +#elif defined(HAVE_SYS_QUOTA_H) +# include +#endif + +#ifndef SYS_DQBLK +#define SYS_DQBLK dqblk +#endif + + int autoconf_quota(void) +{ + int ret = -1; + struct SYS_DQBLK D; + + ret = quotactl(Q_GETQUOTA,"/dev/hda1",0,(void *)&D); + + return ret; +} + +#elif defined(HAVE_QUOTACTL_4B) +/* int quotactl(const char *path, int cmd, int id, char *addr); */ + +#ifdef HAVE_SYS_QUOTA_H +#include +#else /* *BSD */ +#include +#include +#include +#endif + + int autoconf_quota(void) +{ + int ret = -1; + struct dqblk D; + + ret = quotactl("/",Q_GETQUOTA,0,(char *) &D); + + return ret; +} + +#elif defined(HAVE_QUOTACTL_3) +/* int quotactl (char *spec, int request, char *arg); */ + +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_QUOTA_H +#include +#endif + + int autoconf_quota(void) +{ + int ret = -1; + struct q_request request; + + ret = quotactl("/", Q_GETQUOTA, &request); + + return ret; +} + +#elif defined(HAVE_QUOTACTL_2) + +#error HAVE_QUOTACTL_2 not implemented + +#else + +#error Unknow QUOTACTL prototype + +#endif + + int main(void) +{ + autoconf_quota(); + return 0; +} +#endif /* AUTOCONF_TEST */ diff --git a/source3/libsmb/conncache.c b/source3/libsmb/conncache.c new file mode 100644 index 0000000000..e6604617d6 --- /dev/null +++ b/source3/libsmb/conncache.c @@ -0,0 +1,158 @@ +/* + Unix SMB/CIFS implementation. + + Winbind daemon connection manager + + Copyright (C) Tim Potter 2001 + Copyright (C) Andrew Bartlett 2002 + Copyright (C) Gerald (Jerry) Carter 2003 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + + +#include "includes.h" + +#define FAILED_CONNECTION_CACHE_TIMEOUT 30 /* Seconds between attempts */ + +#define CONNCACHE_ADDR 1 +#define CONNCACHE_NAME 2 + +/* cache entry contains either a server name **or** and IP address as + the key. This means that a server could have two entries (one for each key) */ + +struct failed_connection_cache { + fstring domain_name; + fstring controller; + time_t lookup_time; + NTSTATUS nt_status; + struct failed_connection_cache *prev, *next; +}; + +static struct failed_connection_cache *failed_connection_cache; + +/********************************************************************** + Check for a previously failed connection +**********************************************************************/ + +NTSTATUS check_negative_conn_cache( const char *domain, const char *server ) +{ + struct failed_connection_cache *fcc; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + + /* can't check if we don't have strings */ + + if ( !domain || !server ) + return NT_STATUS_OK; + + for (fcc = failed_connection_cache; fcc; fcc = fcc->next) { + + if ( !(strequal(domain, fcc->domain_name) && strequal(server, fcc->controller)) ) + continue; /* no match; check the next entry */ + + /* we have a match so see if it is still current */ + + if ((time(NULL) - fcc->lookup_time) > FAILED_CONNECTION_CACHE_TIMEOUT) + { + /* Cache entry has expired, delete it */ + + DEBUG(10, ("check_negative_conn_cache: cache entry expired for %s, %s\n", + domain, server )); + + DLIST_REMOVE(failed_connection_cache, fcc); + SAFE_FREE(fcc); + + return NT_STATUS_OK; + } + + /* The timeout hasn't expired yet so return false */ + + DEBUG(10, ("check_negative_conn_cache: returning negative entry for %s, %s\n", + domain, server )); + + result = fcc->nt_status; + return result; + } + + /* end of function means no cache entry */ + return NT_STATUS_OK; +} + +/********************************************************************** + Add an entry to the failed conneciton cache (aither a name of dotted + decimal IP +**********************************************************************/ + +void add_failed_connection_entry(const char *domain, const char *server, NTSTATUS result) +{ + struct failed_connection_cache *fcc; + + SMB_ASSERT(!NT_STATUS_IS_OK(result)); + + /* Check we already aren't in the cache. We always have to have + a domain, but maybe not a specific DC name. */ + + for (fcc = failed_connection_cache; fcc; fcc = fcc->next) { + if ( strequal(fcc->domain_name, domain) && strequal(fcc->controller, server) ) + { + DEBUG(10, ("add_failed_connection_entry: domain %s (%s) already tried and failed\n", + domain, server )); + return; + } + } + + /* Create negative lookup cache entry for this domain and controller */ + + if ( !(fcc = (struct failed_connection_cache *)malloc(sizeof(struct failed_connection_cache))) ) + { + DEBUG(0, ("malloc failed in add_failed_connection_entry!\n")); + return; + } + + ZERO_STRUCTP(fcc); + + fstrcpy( fcc->domain_name, domain ); + fstrcpy( fcc->controller, server ); + fcc->lookup_time = time(NULL); + fcc->nt_status = result; + + DEBUG(10,("add_failed_connection_entry: added domain %s (%s) to failed conn cache\n", + domain, server )); + + DLIST_ADD(failed_connection_cache, fcc); +} + +/**************************************************************************** +****************************************************************************/ + +void flush_negative_conn_cache( void ) +{ + struct failed_connection_cache *fcc; + + fcc = failed_connection_cache; + + while (fcc) { + struct failed_connection_cache *fcc_next; + + fcc_next = fcc->next; + DLIST_REMOVE(failed_connection_cache, fcc); + free(fcc); + + fcc = fcc_next; + } + +} + + diff --git a/source3/libsmb/samlogon_cache.c b/source3/libsmb/samlogon_cache.c new file mode 100644 index 0000000000..72c10007bf --- /dev/null +++ b/source3/libsmb/samlogon_cache.c @@ -0,0 +1,238 @@ +/* + Unix SMB/CIFS implementation. + Net_sam_logon info3 helpers + Copyright (C) Alexander Bokovoy 2002. + Copyright (C) Andrew Bartlett 2002. + Copyright (C) Gerald Carter 2003. + Copyright (C) Tim Potter 2003. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +#define NETSAMLOGON_TDB "netsamlogon_cache.tdb" + +static TDB_CONTEXT *netsamlogon_tdb = NULL; + +/*********************************************************************** + open the tdb + ***********************************************************************/ + +BOOL netsamlogon_cache_init(void) +{ + if (!netsamlogon_tdb) { + netsamlogon_tdb = tdb_open_log(lock_path(NETSAMLOGON_TDB), 0, + TDB_DEFAULT, O_RDWR | O_CREAT, 0600); + } + + return (netsamlogon_tdb != NULL); +} + + +/*********************************************************************** + Shutdown samlogon_cache database +***********************************************************************/ + +BOOL netsamlogon_cache_shutdown(void) +{ + if(netsamlogon_tdb) + return (tdb_close(netsamlogon_tdb) == 0); + + return True; +} + +/*********************************************************************** + Clear cache getpwnam and getgroups entries from the winbindd cache +***********************************************************************/ +void netsamlogon_clear_cached_user(TDB_CONTEXT *tdb, NET_USER_INFO_3 *user) +{ + fstring domain; + TDB_DATA key; + BOOL got_tdb = False; + + /* We may need to call this function from smbd which will not have + winbindd_cache.tdb open. Open the tdb if a NULL is passed. */ + + if (!tdb) { + tdb = tdb_open_log(lock_path("winbindd_cache.tdb"), 5000, + TDB_DEFAULT, O_RDWR, 0600); + if (!tdb) { + DEBUG(5, ("netsamlogon_clear_cached_user: failed to open cache\n")); + return; + } + got_tdb = True; + } + + unistr2_to_ascii(domain, &user->uni_logon_dom, sizeof(domain) - 1); + + /* Clear U/DOMAIN/RID cache entry */ + + asprintf(&key.dptr, "U/%s/%d", domain, user->user_rid); + key.dsize = strlen(key.dptr) - 1; /* keys are not NULL terminated */ + + DEBUG(10, ("netsamlogon_clear_cached_user: clearing %s\n", key.dptr)); + + tdb_delete(tdb, key); + + SAFE_FREE(key.dptr); + + /* Clear UG/DOMAIN/RID cache entry */ + + asprintf(&key.dptr, "UG/%s/%d", domain, user->user_rid); + key.dsize = strlen(key.dptr) - 1; /* keys are not NULL terminated */ + + DEBUG(10, ("netsamlogon_clear_cached_user: clearing %s\n", key.dptr)); + + tdb_delete(tdb, key); + + SAFE_FREE(key.dptr); + + if (got_tdb) + tdb_close(tdb); +} + +/*********************************************************************** + Store a NET_USER_INFO_3 structure in a tdb for later user +***********************************************************************/ + +BOOL netsamlogon_cache_store(TALLOC_CTX *mem_ctx, NET_USER_INFO_3 *user) +{ + TDB_DATA data; + fstring keystr; + prs_struct ps; + BOOL result = False; + DOM_SID user_sid; + time_t t = time(NULL); + + + if (!netsamlogon_cache_init()) { + DEBUG(0,("netsamlogon_cache_store: cannot open %s for write!\n", NETSAMLOGON_TDB)); + return False; + } + + sid_copy( &user_sid, &user->dom_sid.sid ); + sid_append_rid( &user_sid, user->user_rid ); + + /* Prepare key as DOMAIN-SID/USER-RID string */ + slprintf(keystr, sizeof(keystr), "%s", sid_string_static(&user_sid)); + + DEBUG(10,("netsamlogon_cache_store: SID [%s]\n", keystr)); + + /* Prepare data */ + + prs_init( &ps,MAX_PDU_FRAG_LEN , mem_ctx, MARSHALL); + + if ( !prs_uint32( "timestamp", &ps, 0, (uint32*)&t ) ) + return False; + + if ( net_io_user_info3("", user, &ps, 0, 3) ) + { + data.dsize = prs_offset( &ps ); + data.dptr = prs_data_p( &ps ); + + if (tdb_store_bystring(netsamlogon_tdb, keystr, data, TDB_REPLACE) != -1) + result = True; + + prs_mem_free( &ps ); + } + + return result; +} + +/*********************************************************************** + Retrieves a NET_USER_INFO_3 structure from a tdb. Caller must + free the user_info struct (malloc()'d memory) +***********************************************************************/ + +NET_USER_INFO_3* netsamlogon_cache_get( TALLOC_CTX *mem_ctx, DOM_SID *user_sid) +{ + NET_USER_INFO_3 *user = NULL; + TDB_DATA data, key; + prs_struct ps; + fstring keystr; + uint32 t; + + if (!netsamlogon_cache_init()) { + DEBUG(0,("netsamlogon_cache_store: cannot open %s for write!\n", NETSAMLOGON_TDB)); + return False; + } + + /* Prepare key as DOMAIN-SID/USER-RID string */ + slprintf(keystr, sizeof(keystr), "%s", sid_string_static(user_sid)); + DEBUG(10,("netsamlogon_cache_get: SID [%s]\n", keystr)); + key.dptr = keystr; + key.dsize = strlen(keystr)+1; + data = tdb_fetch( netsamlogon_tdb, key ); + + if ( data.dptr ) { + + if ( (user = (NET_USER_INFO_3*)malloc(sizeof(NET_USER_INFO_3))) == NULL ) + return NULL; + + prs_init( &ps, 0, mem_ctx, UNMARSHALL ); + prs_give_memory( &ps, data.dptr, data.dsize, True ); + + if ( !prs_uint32( "timestamp", &ps, 0, &t ) ) { + prs_mem_free( &ps ); + return False; + } + + if ( !net_io_user_info3("", user, &ps, 0, 3) ) { + SAFE_FREE( user ); + } + + prs_mem_free( &ps ); + +#if 0 /* The netsamlogon cache needs to hang around. Something about + this feels wrong, but it is the only way we can get all of the + groups. The old universal groups cache didn't expire either. + --jerry */ + { + time_t now = time(NULL); + uint32 time_diff; + + /* is the entry expired? */ + time_diff = now - t; + + if ( (time_diff < 0 ) || (time_diff > lp_winbind_cache_time()) ) { + DEBUG(10,("netsamlogon_cache_get: cache entry expired \n")); + tdb_delete( netsamlogon_tdb, key ); + SAFE_FREE( user ); + } +#endif + } + + return user; +} + +BOOL netsamlogon_cache_have(DOM_SID *user_sid) +{ + TALLOC_CTX *mem_ctx = talloc_init("netsamlogon_cache_have"); + NET_USER_INFO_3 *user = NULL; + BOOL result; + + if (!mem_ctx) + return False; + + user = netsamlogon_cache_get(mem_ctx, user_sid); + + result = (user != NULL); + + talloc_destroy(mem_ctx); + SAFE_FREE(user); + + return result; +} diff --git a/source3/mainpage.dox b/source3/mainpage.dox new file mode 100644 index 0000000000..8b72f80462 --- /dev/null +++ b/source3/mainpage.dox @@ -0,0 +1,7 @@ +/** + +@mainpage + +@li \ref CodingSuggestions + +**/ diff --git a/source3/modules/weird.c b/source3/modules/weird.c new file mode 100644 index 0000000000..444853f383 --- /dev/null +++ b/source3/modules/weird.c @@ -0,0 +1,131 @@ +/* + Unix SMB/CIFS implementation. + Samba module with developer tools + Copyright (C) Andrew Tridgell 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 Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +static struct { + char from; + char *to; + int len; +} weird_table[] = { + {'q', "^q^", 3}, + {'Q', "^Q^", 3}, + {0, NULL} +}; + +static size_t weird_pull(void *cd, char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + while (*inbytesleft >= 1 && *outbytesleft >= 2) { + int i; + int done = 0; + for (i=0;weird_table[i].from;i++) { + if (strncmp((*inbuf), + weird_table[i].to, + weird_table[i].len) == 0) { + if (*inbytesleft < weird_table[i].len) { + DEBUG(0,("ERROR: truncated weird string\n")); + /* smb_panic("weird_pull"); */ + + } else { + (*outbuf)[0] = weird_table[i].from; + (*outbuf)[1] = 0; + (*inbytesleft) -= weird_table[i].len; + (*outbytesleft) -= 2; + (*inbuf) += weird_table[i].len; + (*outbuf) += 2; + done = 1; + break; + } + } + } + if (done) continue; + (*outbuf)[0] = (*inbuf)[0]; + (*outbuf)[1] = 0; + (*inbytesleft) -= 1; + (*outbytesleft) -= 2; + (*inbuf) += 1; + (*outbuf) += 2; + } + + if (*inbytesleft > 0) { + errno = E2BIG; + return -1; + } + + return 0; +} + +static size_t weird_push(void *cd, char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + int ir_count=0; + + while (*inbytesleft >= 2 && *outbytesleft >= 1) { + int i; + int done=0; + for (i=0;weird_table[i].from;i++) { + if ((*inbuf)[0] == weird_table[i].from && + (*inbuf)[1] == 0) { + if (*outbytesleft < weird_table[i].len) { + DEBUG(0,("No room for weird character\n")); + /* smb_panic("weird_push"); */ + } else { + memcpy(*outbuf, weird_table[i].to, + weird_table[i].len); + (*inbytesleft) -= 2; + (*outbytesleft) -= weird_table[i].len; + (*inbuf) += 2; + (*outbuf) += weird_table[i].len; + done = 1; + break; + } + } + } + if (done) continue; + + (*outbuf)[0] = (*inbuf)[0]; + if ((*inbuf)[1]) ir_count++; + (*inbytesleft) -= 2; + (*outbytesleft) -= 1; + (*inbuf) += 2; + (*outbuf) += 1; + } + + if (*inbytesleft == 1) { + errno = EINVAL; + return -1; + } + + if (*inbytesleft > 1) { + errno = E2BIG; + return -1; + } + + return ir_count; +} + +struct charset_functions weird_functions = {"WEIRD", weird_pull, weird_push}; + +NTSTATUS charset_weird_init(void) +{ + return smb_register_charset(&weird_functions); +} diff --git a/source3/nsswitch/winbindd_acct.c b/source3/nsswitch/winbindd_acct.c new file mode 100644 index 0000000000..a1cd1d5f19 --- /dev/null +++ b/source3/nsswitch/winbindd_acct.c @@ -0,0 +1,1209 @@ +/* + Unix SMB/CIFS implementation. + + Winbind account management functions + + Copyright (C) by Gerald (Jerry) Carter 2003 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "winbindd.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_WINBIND + +#define WBKEY_PASSWD "WBA_PASSWD" +#define WBKEY_GROUP "WBA_GROUP" + +#define NUM_PW_FIELDS 7 +#define NUM_GRP_FIELDS 4 + +/* Globals */ + +static TDB_CONTEXT *account_tdb; + +extern userdom_struct current_user_info; + +struct _check_primary_grp { + gid_t gid; + BOOL found; +}; + +/********************************************************************** +**********************************************************************/ + +static void free_winbindd_gr( WINBINDD_GR *grp ) +{ + int i; + + if ( !grp ) + return; + + for ( i=0; inum_gr_mem; i++ ) + SAFE_FREE( grp->gr_mem[i] ); + + SAFE_FREE( grp->gr_mem ); + + return; +} + +/***************************************************************************** + Initialise auto-account database. +*****************************************************************************/ + +static BOOL winbindd_accountdb_init(void) +{ + /* see if we've already opened the tdb */ + + if ( account_tdb ) + return True; + + /* Nope. Try to open it */ + + if (!(account_tdb = tdb_open_log(lock_path("winbindd_idmap.tdb"), 0, + TDB_DEFAULT, O_RDWR | O_CREAT, 0600))) + { + /* last chance -- maybe idmap has already opened it */ + if ( !(account_tdb = idmap_tdb_handle()) ) { + + DEBUG(0, ("winbindd_idmap_init: Unable to open idmap database\n")); + return False; + } + } + + /* yeah! */ + + return True; +} + +/********************************************************************** + Convert a string in /etc/passwd format to a struct passwd* entry +**********************************************************************/ + +static WINBINDD_PW* string2passwd( char *string ) +{ + static WINBINDD_PW pw; + char *p, *str; + char *fields[NUM_PW_FIELDS]; + int i; + + if ( !string ) + return NULL; + + ZERO_STRUCTP( &pw ); + + DEBUG(10,("string2passwd: converting \"%s\"\n", string)); + + ZERO_STRUCT( fields ); + + for ( i=0, str=string; ipw_name ) + return NULL; + + DEBUG(10,("passwd2string: converting passwd struct for %s\n", + pw->pw_name)); + + ret = snprintf( string, sizeof(string), "%s:%s:%d:%d:%s:%s:%s", + pw->pw_name, + pw->pw_passwd ? pw->pw_passwd : "x", + pw->pw_uid, + pw->pw_gid, + pw->pw_gecos, + pw->pw_dir, + pw->pw_shell ); + + if ( ret < 0 ) { + DEBUG(0,("passwd2string: snprintf() failed!\n")); + return NULL; + } + + return string; +} + +/********************************************************************** + Convert a string in /etc/group format to a struct group* entry +**********************************************************************/ + +static WINBINDD_GR* string2group( char *string ) +{ + static WINBINDD_GR grp; + char *p, *str; + char *fields[NUM_GRP_FIELDS]; + int i; + char **gr_members = NULL; + int num_gr_members = 0; + + if ( !string ) + return NULL; + + ZERO_STRUCTP( &grp ); + + DEBUG(10,("string2group: converting \"%s\"\n", string)); + + ZERO_STRUCT( fields ); + + for ( i=0, str=string; igr_name ) + return NULL; + + DEBUG(10,("group2string: converting passwd struct for %s\n", + grp->gr_name)); + + if ( grp->num_gr_mem ) { + int idx = 0; + + member = grp->gr_mem[0]; + size = 0; + num_members = 0; + + while ( member ) { + size += strlen(member) + 1; + num_members++; + member = grp->gr_mem[num_members]; + } + + gr_mem_str = smb_xmalloc(size); + + for ( i=0; igr_mem[i] ); + idx += strlen(grp->gr_mem[i]) + 1; + } + /* add trailing NULL (also removes trailing ',' */ + gr_mem_str[size-1] = '\0'; + } + else { + /* no members */ + gr_mem_str = smb_xmalloc(sizeof(fstring)); + fstrcpy( gr_mem_str, "" ); + } + + ret = snprintf( string, sizeof(string)-1, "%s:%s:%d:%s", + grp->gr_name, + grp->gr_passwd ? grp->gr_passwd : "*", + grp->gr_gid, + gr_mem_str ); + + SAFE_FREE( gr_mem_str ); + + if ( ret < 0 ) { + DEBUG(0,("group2string: snprintf() failed!\n")); + return NULL; + } + + return string; +} + +/********************************************************************** +**********************************************************************/ + +static char* acct_userkey_byname( const char *name ) +{ + static fstring key; + + snprintf( key, sizeof(key), "%s/NAME/%s", WBKEY_PASSWD, name ); + + return key; +} + +/********************************************************************** +**********************************************************************/ + +static char* acct_userkey_byuid( uid_t uid ) +{ + static fstring key; + + snprintf( key, sizeof(key), "%s/UID/%d", WBKEY_PASSWD, uid ); + + return key; +} + +/********************************************************************** +**********************************************************************/ + +static char* acct_groupkey_byname( const char *name ) +{ + static fstring key; + + snprintf( key, sizeof(key), "%s/NAME/%s", WBKEY_GROUP, name ); + + return key; +} + +/********************************************************************** +**********************************************************************/ + +static char* acct_groupkey_bygid( gid_t gid ) +{ + static fstring key; + + snprintf( key, sizeof(key), "%s/GID/%d", WBKEY_GROUP, gid ); + + return key; +} + +/********************************************************************** +**********************************************************************/ + +WINBINDD_PW* wb_getpwnam( const char * name ) +{ + char *keystr; + TDB_DATA data; + static WINBINDD_PW *pw; + + if ( !account_tdb && !winbindd_accountdb_init() ) { + DEBUG(0,("wb_getpwnam: Failed to open winbindd account db\n")); + return NULL; + } + + + keystr = acct_userkey_byname( name ); + + data = tdb_fetch_bystring( account_tdb, keystr ); + + pw = NULL; + + if ( data.dptr ) { + pw = string2passwd( data.dptr ); + SAFE_FREE( data.dptr ); + } + + DEBUG(5,("wb_getpwnam: %s user (%s)\n", + (pw ? "Found" : "Did not find"), name )); + + return pw; +} + +/********************************************************************** +**********************************************************************/ + +WINBINDD_PW* wb_getpwuid( const uid_t uid ) +{ + char *keystr; + TDB_DATA data; + static WINBINDD_PW *pw; + + if ( !account_tdb && !winbindd_accountdb_init() ) { + DEBUG(0,("wb_getpwuid: Failed to open winbindd account db\n")); + return NULL; + } + + data = tdb_fetch_bystring( account_tdb, acct_userkey_byuid(uid) ); + if ( !data.dptr ) { + DEBUG(4,("wb_getpwuid: failed to locate uid == %d\n", uid)); + return NULL; + } + keystr = acct_userkey_byname( data.dptr ); + + SAFE_FREE( data.dptr ); + + data = tdb_fetch_bystring( account_tdb, keystr ); + + pw = NULL; + + if ( data.dptr ) { + pw = string2passwd( data.dptr ); + SAFE_FREE( data.dptr ); + } + + DEBUG(5,("wb_getpwuid: %s user (uid == %d)\n", + (pw ? "Found" : "Did not find"), uid )); + + return pw; +} + +/********************************************************************** +**********************************************************************/ + +BOOL wb_storepwnam( const WINBINDD_PW *pw ) +{ + char *namekey, *uidkey; + TDB_DATA data; + char *str; + int ret = 0; + fstring username; + + if ( !account_tdb && !winbindd_accountdb_init() ) { + DEBUG(0,("wb_storepwnam: Failed to open winbindd account db\n")); + return False; + } + + namekey = acct_userkey_byname( pw->pw_name ); + + /* lock the main entry first */ + + if ( tdb_lock_bystring(account_tdb, namekey, 0) == -1 ) { + DEBUG(0,("wb_storepwnam: Failed to lock %s\n", namekey)); + return False; + } + + str = passwd2string( pw ); + + data.dptr = str; + data.dsize = strlen(str) + 1; + + if ( (tdb_store_bystring(account_tdb, namekey, data, TDB_REPLACE)) == -1 ) { + DEBUG(0,("wb_storepwnam: Failed to store \"%s\"\n", str)); + ret = -1; + goto done; + } + + /* store the uid index */ + + uidkey = acct_userkey_byuid(pw->pw_uid); + + fstrcpy( username, pw->pw_name ); + data.dptr = username; + data.dsize = strlen(username) + 1; + + if ( (tdb_store_bystring(account_tdb, uidkey, data, TDB_REPLACE)) == -1 ) { + DEBUG(0,("wb_storepwnam: Failed to store uid key \"%s\"\n", str)); + tdb_delete_bystring(account_tdb, namekey); + ret = -1; + goto done; + } + + DEBUG(10,("wb_storepwnam: Success -> \"%s\"\n", str)); + +done: + tdb_unlock_bystring( account_tdb, namekey ); + + return ( ret == 0 ); +} + +/********************************************************************** +**********************************************************************/ + +WINBINDD_GR* wb_getgrnam( const char * name ) +{ + char *keystr; + TDB_DATA data; + static WINBINDD_GR *grp; + + if ( !account_tdb && !winbindd_accountdb_init() ) { + DEBUG(0,("wb_getgrnam: Failed to open winbindd account db\n")); + return NULL; + } + + + keystr = acct_groupkey_byname( name ); + + data = tdb_fetch_bystring( account_tdb, keystr ); + + grp = NULL; + + if ( data.dptr ) { + grp = string2group( data.dptr ); + SAFE_FREE( data.dptr ); + } + + DEBUG(5,("wb_getgrnam: %s group (%s)\n", + (grp ? "Found" : "Did not find"), name )); + + return grp; +} + +/********************************************************************** +**********************************************************************/ + +WINBINDD_GR* wb_getgrgid( gid_t gid ) +{ + char *keystr; + TDB_DATA data; + static WINBINDD_GR *grp; + + if ( !account_tdb && !winbindd_accountdb_init() ) { + DEBUG(0,("wb_getgrgid: Failed to open winbindd account db\n")); + return NULL; + } + + data = tdb_fetch_bystring( account_tdb, acct_groupkey_bygid(gid) ); + if ( !data.dptr ) { + DEBUG(4,("wb_getgrgid: failed to locate gid == %d\n", gid)); + return NULL; + } + keystr = acct_groupkey_byname( data.dptr ); + + SAFE_FREE( data.dptr ); + + data = tdb_fetch_bystring( account_tdb, keystr ); + + grp = NULL; + + if ( data.dptr ) { + grp = string2group( data.dptr ); + SAFE_FREE( data.dptr ); + } + + DEBUG(5,("wb_getgrgid: %s group (gid == %d)\n", + (grp ? "Found" : "Did not find"), gid )); + + return grp; +} + +/********************************************************************** +**********************************************************************/ + +BOOL wb_storegrnam( const WINBINDD_GR *grp ) +{ + char *namekey, *gidkey; + TDB_DATA data; + char *str; + int ret = 0; + fstring groupname; + + if ( !account_tdb && !winbindd_accountdb_init() ) { + DEBUG(0,("wb_storepwnam: Failed to open winbindd account db\n")); + return False; + } + + namekey = acct_groupkey_byname( grp->gr_name ); + + /* lock the main entry first */ + + if ( tdb_lock_bystring(account_tdb, namekey, 0) == -1 ) { + DEBUG(0,("wb_storegrnam: Failed to lock %s\n", namekey)); + return False; + } + + str = group2string( grp ); + + data.dptr = str; + data.dsize = strlen(str) + 1; + + if ( (tdb_store_bystring(account_tdb, namekey, data, TDB_REPLACE)) == -1 ) { + DEBUG(0,("wb_storegrnam: Failed to store \"%s\"\n", str)); + ret = -1; + goto done; + } + + /* store the gid index */ + + gidkey = acct_groupkey_bygid(grp->gr_gid); + + fstrcpy( groupname, grp->gr_name ); + data.dptr = groupname; + data.dsize = strlen(groupname) + 1; + + if ( (tdb_store_bystring(account_tdb, gidkey, data, TDB_REPLACE)) == -1 ) { + DEBUG(0,("wb_storegrnam: Failed to store gid key \"%s\"\n", str)); + tdb_delete_bystring(account_tdb, namekey); + ret = -1; + goto done; + } + + DEBUG(10,("wb_storegrnam: Success -> \"%s\"\n", str)); + +done: + tdb_unlock_bystring( account_tdb, namekey ); + + return ( ret == 0 ); +} + +/********************************************************************** +**********************************************************************/ + +static BOOL wb_addgrpmember( WINBINDD_GR *grp, const char *user ) +{ + int i; + char **members; + + if ( !grp || !user ) + return False; + + for ( i=0; inum_gr_mem; i++ ) { + if ( StrCaseCmp( grp->gr_mem[i], user ) == 0 ) + return True; + } + + /* add one new slot and keep an extra for the terminating NULL */ + members = Realloc( grp->gr_mem, (grp->num_gr_mem+2)*sizeof(char*) ); + if ( !members ) + return False; + + grp->gr_mem = members; + grp->gr_mem[grp->num_gr_mem++] = smb_xstrdup(user); + grp->gr_mem[grp->num_gr_mem] = NULL; + + return True; +} + +/********************************************************************** +**********************************************************************/ + +static BOOL wb_delgrpmember( WINBINDD_GR *grp, const char *user ) +{ + int i; + BOOL found = False; + + if ( !grp || !user ) + return False; + + for ( i=0; inum_gr_mem && !found; i++ ) { + if ( StrCaseCmp( grp->gr_mem[i], user ) == 0 ) + found = True; + } + + if ( !found ) + return False; + + /* still some remaining members */ + + if ( grp->num_gr_mem > 1 ) { + memmove( grp->gr_mem[i], grp->gr_mem[i+1], sizeof(char*)*(grp->num_gr_mem-(i+1)) ); + grp->num_gr_mem--; + } + else { /* last one */ + free_winbindd_gr( grp ); + grp->gr_mem = NULL; + grp->num_gr_mem = 0; + } + + return True; +} + +/********************************************************************** +**********************************************************************/ + +static int cleangroups_traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, + void *state) +{ + int len; + fstring key; + char *name = (char*)state; + + snprintf( key, sizeof(key), "%s/NAME", WBKEY_GROUP ); + len = strlen(key); + + /* if this is a group entry then, check the members */ + + if ( (strncmp(kbuf.dptr, key, len) == 0) && dbuf.dptr ) { + WINBINDD_GR *grp; + + if ( !(grp = string2group( dbuf.dptr )) ) { + DEBUG(0,("cleangroups_traverse_fn: Failure to parse [%s]\n", + dbuf.dptr)); + return 0; + } + + /* just try to delete the user and rely on wb_delgrpmember() + to tell you whether or not the group changed. This is more + effecient than testing group membership first since the + checks for deleting a user from a group is essentially the + same as checking if he/she is a member */ + + if ( wb_delgrpmember( grp, name ) ) { + DEBUG(10,("cleanupgroups_traverse_fn: Removed user (%s) from group (%s)\n", + name, grp->gr_name)); + wb_storegrnam( grp ); + } + + free_winbindd_gr( grp ); + } + + return 0; +} + +/********************************************************************** +**********************************************************************/ + +static BOOL wb_delete_user( WINBINDD_PW *pw) +{ + char *namekey; + char *uidkey; + + if ( !account_tdb && !winbindd_accountdb_init() ) { + DEBUG(0,("wb_delete_user: Failed to open winbindd account db\n")); + return False; + } + + namekey = acct_userkey_byname( pw->pw_name ); + + /* lock the main entry first */ + + if ( tdb_lock_bystring(account_tdb, namekey, 0) == -1 ) { + DEBUG(0,("wb_delete_user: Failed to lock %s\n", namekey)); + return False; + } + + /* remove user from all groups */ + + tdb_traverse(account_tdb, cleangroups_traverse_fn, (void *)pw->pw_name); + + /* remove the user */ + uidkey = acct_userkey_byuid( pw->pw_uid ); + + tdb_delete_bystring( account_tdb, namekey ); + tdb_delete_bystring( account_tdb, uidkey ); + + tdb_unlock_bystring( account_tdb, namekey ); + + return True; +} + +/********************************************************************** +**********************************************************************/ + +static int isprimarygroup_traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, + TDB_DATA dbuf, void *params) +{ + int len; + fstring key; + struct _check_primary_grp *check = (struct _check_primary_grp*)params; + + snprintf( key, sizeof(key), "%s/NAME", WBKEY_PASSWD ); + len = strlen(key); + + /* if this is a group entry then, check the members */ + + if ( (strncmp(kbuf.dptr, key, len) == 0) && dbuf.dptr ) { + WINBINDD_PW *pw;; + + if ( !(pw = string2passwd( dbuf.dptr )) ) { + DEBUG(0,("isprimarygroup_traverse_fn: Failure to parse [%s]\n", + dbuf.dptr)); + return 0; + } + + if ( check->gid == pw->pw_gid ) { + check->found = True; + return 1; + } + } + + return 0; +} + + +/********************************************************************** +**********************************************************************/ + +static BOOL wb_delete_group( WINBINDD_GR *grp ) +{ + struct _check_primary_grp check; + char *namekey; + char *gidkey; + + if ( !account_tdb && !winbindd_accountdb_init() ) { + DEBUG(0,("wb_delete_group: Failed to open winbindd account db\n")); + return False; + } + + /* lock the main entry first */ + + namekey = acct_groupkey_byname( grp->gr_name ); + if ( tdb_lock_bystring(account_tdb, namekey, 0) == -1 ) { + DEBUG(0,("wb_delete_group: Failed to lock %s\n", namekey)); + return False; + } + + /* is this group the primary group for any user? If + so deny delete */ + + check.found = False; + tdb_traverse(account_tdb, isprimarygroup_traverse_fn, (void *)&check); + + if ( check.found ) { + DEBUG(4,("wb_delete_group: Cannot delete group (%s) since it " + "is the primary group for some users\n", grp->gr_name)); + return False; + } + + /* We're clear. Delete the group */ + + DEBUG(5,("wb_delete_group: Removing group (%s)\n", grp->gr_name)); + + gidkey = acct_groupkey_bygid( grp->gr_gid ); + + tdb_delete_bystring( account_tdb, namekey ); + tdb_delete_bystring( account_tdb, gidkey ); + + tdb_unlock_bystring( account_tdb, namekey ); + + return True; +} + +/********************************************************************** + Create a new "UNIX" user for the system given a username +**********************************************************************/ + +enum winbindd_result winbindd_create_user(struct winbindd_cli_state *state) +{ + char *user, *group; + unid_t id; + WINBINDD_PW pw; + WINBINDD_GR *wb_grp; + struct group *unix_grp; + gid_t primary_gid; + uint32 flags = state->request.flags; + uint32 rid; + + if ( !state->privileged ) { + DEBUG(2, ("winbindd_create_user: non-privileged access denied!\n")); + return WINBINDD_ERROR; + } + + /* Ensure null termination */ + state->request.data.acct_mgt.username[sizeof(state->request.data.acct_mgt.username)-1]='\0'; + state->request.data.acct_mgt.groupname[sizeof(state->request.data.acct_mgt.groupname)-1]='\0'; + + user = state->request.data.acct_mgt.username; + group = state->request.data.acct_mgt.groupname; + + DEBUG(3, ("[%5d]: create_user: user=>(%s), group=>(%s)\n", + state->pid, user, group)); + + if ( !*group ) + group = lp_template_primary_group(); + + /* validate the primary group + 1) lookup in local tdb first + 2) call getgrnam() as a last resort */ + + if ( (wb_grp=wb_getgrnam(group)) != NULL ) { + primary_gid = wb_grp->gr_gid; + free_winbindd_gr( wb_grp ); + } + else if ( (unix_grp=sys_getgrnam(group)) != NULL ) { + primary_gid = unix_grp->gr_gid; + } + else { + DEBUG(2,("winbindd_create_user: Cannot validate gid for group (%s)\n", group)); + return WINBINDD_ERROR; + } + + /* get a new uid */ + + if ( !NT_STATUS_IS_OK(idmap_allocate_id( &id, ID_USERID)) ) { + DEBUG(0,("winbindd_create_user: idmap_allocate_id() failed!\n")); + return WINBINDD_ERROR; + } + + /* The substitution of %U and %D in the 'template homedir' is done + by lp_string() calling standard_sub_basic(). */ + + fstrcpy( current_user_info.smb_name, user ); + sub_set_smb_name( user ); + fstrcpy( current_user_info.domain, get_global_sam_name() ); + + /* fill in the passwd struct */ + + fstrcpy( pw.pw_name, user ); + fstrcpy( pw.pw_passwd, "x" ); + fstrcpy( pw.pw_gecos, user); + fstrcpy( pw.pw_dir, lp_template_homedir() ); + fstrcpy( pw.pw_shell, lp_template_shell() ); + + pw.pw_uid = id.uid; + pw.pw_gid = primary_gid; + + /* store the new entry */ + + if ( !wb_storepwnam(&pw) ) + return WINBINDD_ERROR; + + /* do we need a new RID? */ + + if ( flags & WBFLAG_ALLOCATE_RID ) { + if ( !NT_STATUS_IS_OK(idmap_allocate_rid(&rid, USER_RID_TYPE)) ) { + DEBUG(0,("winbindd_create_user: RID allocation failure! Cannot create user (%s)\n", + user)); + wb_delete_user( &pw ); + + return WINBINDD_ERROR; + } + + state->response.data.rid = rid; + } + + return WINBINDD_OK; +} + +/********************************************************************** + Create a new "UNIX" group for the system given a username +**********************************************************************/ + +enum winbindd_result winbindd_create_group(struct winbindd_cli_state *state) +{ + char *group; + unid_t id; + WINBINDD_GR grp; + uint32 flags = state->request.flags; + uint32 rid; + + if ( !state->privileged ) { + DEBUG(2, ("winbindd_create_group: non-privileged access denied!\n")); + return WINBINDD_ERROR; + } + + /* Ensure null termination */ + state->request.data.acct_mgt.groupname[sizeof(state->request.data.acct_mgt.groupname)-1]='\0'; + group = state->request.data.acct_mgt.groupname; + + DEBUG(3, ("[%5d]: create_group: (%s)\n", state->pid, group)); + + /* get a new uid */ + + if ( !NT_STATUS_IS_OK(idmap_allocate_id( &id, ID_GROUPID)) ) { + DEBUG(0,("winbindd_create_group: idmap_allocate_id() failed!\n")); + return WINBINDD_ERROR; + } + + /* fill in the group struct */ + + fstrcpy( grp.gr_name, group ); + fstrcpy( grp.gr_passwd, "*" ); + + grp.gr_gid = id.gid; + grp.gr_mem = NULL; /* start with no members */ + grp.num_gr_mem = 0; + + if ( !wb_storegrnam(&grp) ) + return WINBINDD_ERROR; + + /* do we need a new RID? */ + + if ( flags & WBFLAG_ALLOCATE_RID ) { + if ( !NT_STATUS_IS_OK(idmap_allocate_rid(&rid, GROUP_RID_TYPE)) ) { + DEBUG(0,("winbindd_create_group: RID allocation failure! Cannot create group (%s)\n", + group)); + wb_delete_group( &grp ); + + return WINBINDD_ERROR; + } + + state->response.data.rid = rid; + } + + return WINBINDD_OK; +} + +/********************************************************************** + Add a user to the membership for a group. +**********************************************************************/ + +enum winbindd_result winbindd_add_user_to_group(struct winbindd_cli_state *state) +{ + WINBINDD_PW *pw; + WINBINDD_GR *grp; + char *user, *group; + BOOL ret; + + if ( !state->privileged ) { + DEBUG(2, ("winbindd_add_user_to_group: non-privileged access denied!\n")); + return WINBINDD_ERROR; + } + + /* Ensure null termination */ + state->request.data.acct_mgt.groupname[sizeof(state->request.data.acct_mgt.groupname)-1]='\0'; + state->request.data.acct_mgt.username[sizeof(state->request.data.acct_mgt.username)-1]='\0'; + group = state->request.data.acct_mgt.groupname; + user = state->request.data.acct_mgt.username; + + DEBUG(3, ("[%5d]: add_user_to_group: add %s to %s\n", state->pid, + user, group)); + + /* make sure it is a valid user */ + + if ( !(pw = wb_getpwnam( user )) ) { + DEBUG(4,("winbindd_add_user_to_group: Cannot add a non-existent user\n")); + return WINBINDD_ERROR; + } + + /* make sure it is a valid group */ + + if ( !(grp = wb_getgrnam( group )) ) { + DEBUG(4,("winbindd_add_user_to_group: Cannot add a user to a non-extistent group\n")); + return WINBINDD_ERROR; + } + + if ( !wb_addgrpmember( grp, user ) ) + return WINBINDD_ERROR; + + ret = wb_storegrnam(grp); + + free_winbindd_gr( grp ); + + return ( ret ? WINBINDD_OK : WINBINDD_ERROR ); +} + +/********************************************************************** + Remove a user from the membership of a group +**********************************************************************/ + +enum winbindd_result winbindd_remove_user_from_group(struct winbindd_cli_state *state) +{ + WINBINDD_GR *grp; + char *user, *group; + BOOL ret; + + if ( !state->privileged ) { + DEBUG(2, ("winbindd_remove_user_from_group: non-privileged access denied!\n")); + return WINBINDD_ERROR; + } + + /* Ensure null termination */ + state->request.data.acct_mgt.groupname[sizeof(state->request.data.acct_mgt.groupname)-1]='\0'; + state->request.data.acct_mgt.username[sizeof(state->request.data.acct_mgt.username)-1]='\0'; + group = state->request.data.acct_mgt.groupname; + user = state->request.data.acct_mgt.username; + + DEBUG(3, ("[%5d]: remove_user_to_group: delete %s from %s\n", state->pid, + user, group)); + + /* don't worry about checking the username since we're removing it anyways */ + + /* make sure it is a valid group */ + + if ( !(grp = wb_getgrnam( group )) ) { + DEBUG(4,("winbindd_remove_user_to_group: Cannot remove a user to a non-extistent group\n")); + return WINBINDD_ERROR; + } + + if ( !wb_delgrpmember( grp, user ) ) + return WINBINDD_ERROR; + + ret = wb_storegrnam(grp); + + free_winbindd_gr( grp ); + + return ( ret ? WINBINDD_OK : WINBINDD_ERROR ); +} + +/********************************************************************** + Set the primary group membership of a user +**********************************************************************/ + +enum winbindd_result winbindd_set_user_primary_group(struct winbindd_cli_state *state) +{ + WINBINDD_PW *pw; + WINBINDD_GR *grp; + char *user, *group; + + if ( !state->privileged ) { + DEBUG(2, ("winbindd_set_user_primary_group: non-privileged access denied!\n")); + return WINBINDD_ERROR; + } + + /* Ensure null termination */ + state->request.data.acct_mgt.groupname[sizeof(state->request.data.acct_mgt.groupname)-1]='\0'; + state->request.data.acct_mgt.username[sizeof(state->request.data.acct_mgt.username)-1]='\0'; + group = state->request.data.acct_mgt.groupname; + user = state->request.data.acct_mgt.username; + + DEBUG(3, ("[%5d]: set_user_primary_grou:p group %s for user %s\n", state->pid, + group, user)); + + /* make sure it is a valid user */ + + if ( !(pw = wb_getpwnam( user )) ) { + DEBUG(4,("winbindd_add_user_to_group: Cannot add a non-existent user\n")); + return WINBINDD_ERROR; + } + + /* make sure it is a valid group */ + + if ( !(grp = wb_getgrnam( group )) ) { + DEBUG(4,("winbindd_add_user_to_group: Cannot add a user to a non-extistent group\n")); + return WINBINDD_ERROR; + } + + pw->pw_gid = grp->gr_gid; + + free_winbindd_gr( grp ); + + return ( wb_storepwnam(pw) ? WINBINDD_OK : WINBINDD_ERROR ); +} + +/********************************************************************** + Delete a user from the winbindd account tdb. +**********************************************************************/ + +enum winbindd_result winbindd_delete_user(struct winbindd_cli_state *state) +{ + WINBINDD_PW *pw; + char *user; + + if ( !state->privileged ) { + DEBUG(2, ("winbindd_delete_user: non-privileged access denied!\n")); + return WINBINDD_ERROR; + } + + /* Ensure null termination */ + state->request.data.acct_mgt.username[sizeof(state->request.data.acct_mgt.username)-1]='\0'; + user = state->request.data.acct_mgt.username; + + DEBUG(3, ("[%5d]: delete_user: %s\n", state->pid, user)); + + /* make sure it is a valid user */ + + if ( !(pw = wb_getpwnam( user )) ) { + DEBUG(4,("winbindd_delete_user: Cannot delete a non-existent user\n")); + return WINBINDD_ERROR; + } + + return ( wb_delete_user(pw) ? WINBINDD_OK : WINBINDD_ERROR ); +} + +/********************************************************************** + Delete a group from winbindd's account tdb. +**********************************************************************/ + +enum winbindd_result winbindd_delete_group(struct winbindd_cli_state *state) +{ + WINBINDD_GR *grp; + char *group; + BOOL ret; + + if ( !state->privileged ) { + DEBUG(2, ("winbindd_delete_group: non-privileged access denied!\n")); + return WINBINDD_ERROR; + } + + /* Ensure null termination */ + state->request.data.acct_mgt.username[sizeof(state->request.data.acct_mgt.groupname)-1]='\0'; + group = state->request.data.acct_mgt.groupname; + + DEBUG(3, ("[%5d]: delete_group: %s\n", state->pid, group)); + + /* make sure it is a valid group */ + + if ( !(grp = wb_getgrnam( group )) ) { + DEBUG(4,("winbindd_delete_group: Cannot delete a non-existent group\n")); + return WINBINDD_ERROR; + } + + ret = wb_delete_group(grp); + + free_winbindd_gr( grp ); + + return ( ret ? WINBINDD_OK : WINBINDD_ERROR ); +} + + + diff --git a/source3/pam_smbpass/.cvsignore b/source3/pam_smbpass/.cvsignore new file mode 100644 index 0000000000..6d609cec52 --- /dev/null +++ b/source3/pam_smbpass/.cvsignore @@ -0,0 +1 @@ +*.po diff --git a/source3/passdb/pdb_plugin.c b/source3/passdb/pdb_plugin.c new file mode 100644 index 0000000000..ea67da23a5 --- /dev/null +++ b/source3/passdb/pdb_plugin.c @@ -0,0 +1,78 @@ +/* + Unix SMB/CIFS implementation. + Loadable passdb module interface. + Copyright (C) Jelmer Vernooij 2002 + Copyright (C) Andrew Bartlett 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 + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_PASSDB + +NTSTATUS pdb_init_plugin(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location) +{ + void * dl_handle; + char *plugin_location, *plugin_name, *p; + pdb_init_function plugin_init; + int (*plugin_version)(void); + + if (location == NULL) { + DEBUG(0, ("The plugin module needs an argument!\n")); + return NT_STATUS_UNSUCCESSFUL; + } + + plugin_name = smb_xstrdup(location); + p = strchr(plugin_name, ':'); + if (p) { + *p = 0; + plugin_location = p+1; + trim_string(plugin_location, " ", " "); + } else plugin_location = NULL; + trim_string(plugin_name, " ", " "); + + DEBUG(5, ("Trying to load sam plugin %s\n", plugin_name)); + 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; + } + + plugin_version = sys_dlsym(dl_handle, "pdb_version"); + if (!plugin_version) { + sys_dlclose(dl_handle); + DEBUG(0, ("Failed to find function 'pdb_version' using sys_dlsym in sam plugin %s (%s)\n", plugin_name, sys_dlerror())); + return NT_STATUS_UNSUCCESSFUL; + } + + 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)); + return NT_STATUS_UNSUCCESSFUL; + } + + plugin_init = sys_dlsym(dl_handle, "pdb_init"); + if (!plugin_init) { + sys_dlclose(dl_handle); + DEBUG(0, ("Failed to find function 'pdb_init' using sys_dlsym in sam plugin %s (%s)\n", plugin_name, sys_dlerror())); + return NT_STATUS_UNSUCCESSFUL; + } + + DEBUG(5, ("Starting sam plugin %s with location %s\n", plugin_name, plugin_location)); + return plugin_init(pdb_context, pdb_method, plugin_location); +} diff --git a/source3/script/mkbuildoptions.awk b/source3/script/mkbuildoptions.awk new file mode 100644 index 0000000000..cdc5bd9881 --- /dev/null +++ b/source3/script/mkbuildoptions.awk @@ -0,0 +1,262 @@ +BEGIN { + print "/* "; + print " Unix SMB/CIFS implementation."; + print " Build Options for Samba Suite"; + print " Copyright (C) Vance Lankhaar 2003"; + print " Copyright (C) Andrew Bartlett 2001"; + print " "; + print " This program is free software; you can redistribute it and/or modify"; + print " it under the terms of the GNU General Public License as published by"; + print " the Free Software Foundation; either version 2 of the License, or"; + print " (at your option) any later version."; + print " "; + print " This program is distributed in the hope that it will be useful,"; + print " but WITHOUT ANY WARRANTY; without even the implied warranty of"; + print " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the"; + print " GNU General Public License for more details."; + print " "; + print " You should have received a copy of the GNU General Public License"; + print " along with this program; if not, write to the Free Software"; + print " Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA."; + print "*/"; + print ""; + print "#include \"includes.h\""; + print "#include \"build_env.h\""; + print "#include \"dynconfig.h\""; + print ""; + print "static void output(BOOL screen, const char *format, ...) PRINTF_ATTRIBUTE(2,3);"; + print ""; + print ""; + print "/****************************************************************************"; + print "helper function for build_options"; + print "****************************************************************************/"; + print "static void output(BOOL screen, const char *format, ...)"; + print "{"; + print " char *ptr;"; + print " va_list ap;"; + print " "; + print " va_start(ap, format);"; + print " vasprintf(&ptr,format,ap);"; + print " va_end(ap);"; + print ""; + print " if (screen) {"; + print " d_printf(\"%s\", ptr);"; + print " } else {"; + print " DEBUG(4,(\"%s\", ptr));"; + print " }"; + print " "; + print " SAFE_FREE(ptr);"; + print "}"; + print ""; + print "/****************************************************************************"; + print "options set at build time for the samba suite"; + print "****************************************************************************/"; + print "void build_options(BOOL screen)"; + print "{"; + print " if ((DEBUGLEVEL < 4) && (!screen)) {"; + print " return;"; + print " }"; + print ""; + print "#ifdef _BUILD_ENV_H"; + print " /* Output information about the build environment */"; + print " output(screen,\"Build environment:\\n\");"; + print " output(screen,\" Built by: %s@%s\\n\",BUILD_ENV_USER,BUILD_ENV_HOST);"; + print " output(screen,\" Built on: %s\\n\",BUILD_ENV_DATE);"; + print ""; + print " output(screen,\" Built using: %s\\n\",BUILD_ENV_COMPILER);"; + print " output(screen,\" Build host: %s\\n\",BUILD_ENV_UNAME);"; + print " output(screen,\" SRCDIR: %s\\n\",BUILD_ENV_SRCDIR);"; + print " output(screen,\" BUILDDIR: %s\\n\",BUILD_ENV_BUILDDIR);"; + print ""; + print " "; + print "#endif"; + print ""; + + print " /* Output various paths to files and directories */"; + print " output(screen,\"\\nPaths:\\n\");"; + + print " output(screen,\" SBINDIR: %s\\n\", dyn_SBINDIR);"; + print " output(screen,\" BINDIR: %s\\n\", dyn_BINDIR);"; + print " output(screen,\" SWATDIR: %s\\n\", dyn_SWATDIR);"; + + print " output(screen,\" CONFIGFILE: %s\\n\", dyn_CONFIGFILE);"; + print " output(screen,\" LOGFILEBASE: %s\\n\", dyn_LOGFILEBASE);"; + print " output(screen,\" LMHOSTSFILE: %s\\n\",dyn_LMHOSTSFILE);"; + + print " output(screen,\" LIBDIR: %s\\n\",dyn_LIBDIR);"; + print " output(screen,\" SHLIBEXT: %s\\n\",dyn_SHLIBEXT);"; + + print " output(screen,\" LOCKDIR: %s\\n\",dyn_LOCKDIR);"; + print " output(screen,\" PIDDIR: %s\\n\", dyn_PIDDIR);"; + + print " output(screen,\" SMB_PASSWD_FILE: %s\\n\",dyn_SMB_PASSWD_FILE);"; + print " output(screen,\" PRIVATE_DIR: %s\\n\",dyn_PRIVATE_DIR);"; + print ""; + + +################################################## +# predefine first element of *_ary +# predefine *_i (num of elements in *_ary) + with_ary[0]=""; + with_i=0; + have_ary[0]=""; + have_i=0; + utmp_ary[0]=""; + utmp_i=0; + misc_ary[0]=""; + misc_i=0; + sys_ary[0]=""; + sys_i=0; + headers_ary[0]=""; + headers_i=0; + in_comment = 0; +} + +# capture single line comments +/^\/\* (.*?)\*\// { + last_comment = $0; + next; +} + +# end capture multi-line comments +/(.*?)\*\// { + last_comment = last_comment $0; + in_comment = 0; + next; +} + +# capture middle lines of multi-line comments +in_comment { + last_comment = last_comment $0; + next; +} + +# begin capture multi-line comments +/^\/\* (.*?)/ { + last_comment = $0; + in_comment = 1; + next +} + +################################################## +# if we have an #undef and a last_comment, store it +/^\#undef/ { + split($0,a); + comments_ary[a[2]] = last_comment; + last_comment = ""; +} + +################################################## +# for each line, sort into appropriate section +# then move on + +/^\#undef WITH/ { + with_ary[with_i++] = a[2]; + # we want (I think) to allow --with to show up in more than one place, so no next +} + + +/^\#undef HAVE_UT_UT_/ || /^\#undef .*UTMP/ { + utmp_ary[utmp_i++] = a[2]; + next; +} + +/^\#undef HAVE_SYS_.*?_H$/ { + sys_ary[sys_i++] = a[2]; + next; +} + +/^\#undef HAVE_.*?_H$/ { + headers_ary[headers_i++] = a[2]; + next; +} + +/^\#undef HAVE_/ { + have_ary[have_i++] = a[2]; + next; +} + +/^\#undef/ { + misc_ary[misc_i++] = a[2]; + next; +} + + +################################################## +# simple sort function +function sort(ARRAY, ELEMENTS) { + for (i = 1; i <= ELEMENTS; ++i) { + for (j = i; (j-1) in ARRAY && (j) in ARRAY && ARRAY[j-1] > ARRAY[j]; --j) { + temp = ARRAY[j]; + ARRAY[j] = ARRAY[j-1]; + ARRAY[j-1] = temp; + } + } + return; +} + + +################################################## +# output code from list of defined +# expects: ARRAY an array of things defined +# ELEMENTS number of elements in ARRAY +# TITLE title for section +# returns: nothing +function output(ARRAY, ELEMENTS, TITLE) { + + # add section header + print "\n\t/* Show " TITLE " */"; + print "\toutput(screen, \"\\n " TITLE ":\\n\");\n"; + + + # sort element using bubble sort (slow, but easy) + sort(ARRAY, ELEMENTS); + + # loop through array of defines, outputting code + for (i = 0; i < ELEMENTS; i++) { + print "#ifdef " ARRAY[i]; + + # I don't know which one to use.... + + print "\toutput(screen, \" " ARRAY[i] "\\n\");"; + #printf "\toutput(screen, \" %s\\n %s\\n\\n\");\n", comments_ary[ARRAY[i]], ARRAY[i]; + #printf "\toutput(screen, \" %-35s %s\\n\");\n", ARRAY[i], comments_ary[ARRAY[i]]; + + print "#endif"; + } + return; +} + +END { + ################################################## + # add code to show various options + print "/* Output various other options (as gleaned from include/config.h.in) */"; + output(sys_ary, sys_i, "System Headers"); + output(headers_ary, headers_i, "Headers"); + output(utmp_ary, utmp_i, "UTMP Options"); + output(have_ary, have_i, "HAVE_* Defines"); + output(with_ary, with_i, "--with Options"); + output(misc_ary, misc_i, "Build Options"); + + ################################################## + # add code to display the various type sizes + print " /* Output the sizes of the various types */"; + print " output(screen, \"\\nType sizes:\\n\");"; + print " output(screen, \" sizeof(char): %u\\n\",sizeof(char));"; + print " output(screen, \" sizeof(int): %u\\n\",sizeof(int));"; + print " output(screen, \" sizeof(long): %u\\n\",sizeof(long));"; + print " output(screen, \" sizeof(uint8): %u\\n\",sizeof(uint8));"; + print " output(screen, \" sizeof(uint16): %u\\n\",sizeof(uint16));"; + print " output(screen, \" sizeof(uint32): %u\\n\",sizeof(uint32));"; + print " output(screen, \" sizeof(short): %u\\n\",sizeof(short));"; + print " output(screen, \" sizeof(void*): %u\\n\",sizeof(void*));"; + + ################################################## + # add code to give information about modules + print " output(screen, \"\\nBuiltin modules:\\n\");"; + print " output(screen, \" %s\\n\", STRING_STATIC_MODULES);"; + + print "}"; + +} + diff --git a/source3/smbd/fake_file.c b/source3/smbd/fake_file.c new file mode 100644 index 0000000000..86d78e039a --- /dev/null +++ b/source3/smbd/fake_file.c @@ -0,0 +1,166 @@ +/* + Unix SMB/CIFS implementation. + FAKE FILE suppport, for faking up special files windows want access to + Copyright (C) Stefan (metze) Metzmacher 2003 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +/**************************************************************************** + Open a file with a share mode. +****************************************************************************/ +files_struct *open_fake_file_shared1(enum FAKE_FILE_TYPE fake_file_type, connection_struct *conn,char *fname, + SMB_STRUCT_STAT *psbuf, + uint32 desired_access, + int share_mode,int ofun, mode_t mode,int oplock_request, + int *Access,int *action) +{ + extern struct current_user current_user; + int flags=0; + files_struct *fsp = NULL; + + if (fake_file_type == 0) { + return open_file_shared1(conn,fname,psbuf,desired_access, + share_mode,ofun,mode, + oplock_request,Access,action); + } + + /* access check */ + if (conn->admin_user != True) { + DEBUG(1,("access_denied to service[%s] file[%s] user[%s]\n", + lp_servicename(SNUM(conn)),fname,conn->user)); + errno = EACCES; + return NULL; + } + + fsp = file_new(conn); + if(!fsp) + return NULL; + + DEBUG(5,("open_fake_file_shared1: fname = %s, FID = %d, share_mode = %x, ofun = %x, mode = %o, oplock request = %d\n", + fname, fsp->fnum, share_mode, ofun, (int)mode, oplock_request )); + + if (!check_name(fname,conn)) { + file_free(fsp); + return NULL; + } + + fsp->fd = -1; + fsp->mode = psbuf->st_mode; + fsp->inode = psbuf->st_ino; + fsp->dev = psbuf->st_dev; + fsp->vuid = current_user.vuid; + fsp->size = psbuf->st_size; + fsp->pos = -1; + fsp->can_lock = True; + fsp->can_read = ((flags & O_WRONLY)==0); + fsp->can_write = ((flags & (O_WRONLY|O_RDWR))!=0); + fsp->share_mode = 0; + fsp->desired_access = desired_access; + fsp->print_file = False; + fsp->modified = False; + fsp->oplock_type = NO_OPLOCK; + fsp->sent_oplock_break = NO_BREAK_SENT; + fsp->is_directory = False; + fsp->is_stat = False; + fsp->directory_delete_on_close = False; + fsp->conn = conn; + string_set(&fsp->fsp_name,fname); + fsp->wcp = NULL; /* Write cache pointer. */ + + fsp->fake_file_handle = init_fake_file_handle(fake_file_type); + + if (fsp->fake_file_handle==NULL) { + file_free(fsp); + return NULL; + } + + conn->num_files_open++; + return fsp; +} + +static FAKE_FILE fake_files[] = { +#ifdef WITH_QUOTAS + {FAKE_FILE_NAME_QUOTA, FAKE_FILE_TYPE_QUOTA, init_quota_handle, destroy_quota_handle}, +#endif /* WITH_QUOTAS */ + {NULL, FAKE_FILE_TYPE_NONE, NULL, NULL } +}; + +int is_fake_file(char *fname) +{ + int i; + + if (!fname) + return 0; + + for (i=0;fake_files[i].name!=NULL;i++) { + if (strncmp(fname,fake_files[i].name,strlen(fake_files[i].name))==0) { + DEBUG(5,("is_fake_file: [%s] is a fake file\n",fname)); + return fake_files[i].type; + } + } + + return FAKE_FILE_TYPE_NONE; +} + +struct _FAKE_FILE_HANDLE *init_fake_file_handle(enum FAKE_FILE_TYPE type) +{ + TALLOC_CTX *mem_ctx = NULL; + FAKE_FILE_HANDLE *fh = NULL; + int i; + + for (i=0;fake_files[i].name!=NULL;i++) { + if (fake_files[i].type==type) { + DEBUG(5,("init_fake_file_handle: for [%s]\n",fake_files[i].name)); + + if ((mem_ctx=talloc_init("fake_file_handle"))==NULL) { + DEBUG(0,("talloc_init(fake_file_handle) failed.\n")); + return NULL; + } + + if ((fh =(FAKE_FILE_HANDLE *)talloc_zero(mem_ctx, sizeof(FAKE_FILE_HANDLE)))==NULL) { + DEBUG(0,("talloc_zero() failed.\n")); + talloc_destroy(mem_ctx); + return NULL; + } + + fh->type = type; + fh->mem_ctx = mem_ctx; + + if (fake_files[i].init_pd) + fh->pd = fake_files[i].init_pd(fh->mem_ctx); + + fh->free_pd = fake_files[i].free_pd; + + return fh; + } + } + + return NULL; +} + +void destroy_fake_file_handle(FAKE_FILE_HANDLE **fh) +{ + if (!fh||!(*fh)) + return ; + + if ((*fh)->free_pd) + (*fh)->free_pd(&(*fh)->pd); + + talloc_destroy((*fh)->mem_ctx); + (*fh) = NULL; +} diff --git a/source3/smbd/ntquotas.c b/source3/smbd/ntquotas.c new file mode 100644 index 0000000000..2e865000ec --- /dev/null +++ b/source3/smbd/ntquotas.c @@ -0,0 +1,259 @@ +/* + Unix SMB/CIFS implementation. + NT QUOTA suppport + Copyright (C) Stefan (metze) Metzmacher 2003 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +static SMB_BIG_UINT limit_nt2unix(SMB_BIG_UINT in, SMB_BIG_UINT bsize) +{ + SMB_BIG_UINT ret = (SMB_BIG_UINT)0; + + ret = (SMB_BIG_UINT)(in/bsize); + if (in>0 && ret==0) { + /* we have to make sure that a overflow didn't set NO_LIMIT */ + ret = (SMB_BIG_UINT)1; + } + + if (in == SMB_NTQUOTAS_NO_LIMIT) + ret = SMB_QUOTAS_NO_LIMIT; + else if (in == SMB_NTQUOTAS_NO_SPACE) + ret = SMB_QUOTAS_NO_SPACE; + else if (in == SMB_NTQUOTAS_NO_ENTRY) + ret = SMB_QUOTAS_NO_LIMIT; + + return ret; +} + +static SMB_BIG_UINT limit_unix2nt(SMB_BIG_UINT in, SMB_BIG_UINT bsize) +{ + SMB_BIG_UINT ret = (SMB_BIG_UINT)0; + + ret = (SMB_BIG_UINT)(in*bsize); + + if (ret < in) { + /* we overflow */ + ret = SMB_NTQUOTAS_NO_LIMIT; + } + + if (in == SMB_QUOTAS_NO_LIMIT) + ret = SMB_NTQUOTAS_NO_LIMIT; + + return ret; +} + +static SMB_BIG_UINT limit_blk2inodes(SMB_BIG_UINT in) +{ + SMB_BIG_UINT ret = (SMB_BIG_UINT)0; + + ret = (SMB_BIG_UINT)(in/2); + + if (ret == 0 && in != 0) + ret = (SMB_BIG_UINT)1; + + return ret; +} + +int vfs_get_ntquota(files_struct *fsp, enum SMB_QUOTA_TYPE qtype, DOM_SID *psid, SMB_NTQUOTA_STRUCT *qt) +{ + int ret; + SMB_DISK_QUOTA D; + unid_t id; + + ZERO_STRUCT(D); + + if (!fsp||!fsp->conn||!qt) + return (-1); + + ZERO_STRUCT(*qt); + + id.uid = -1; + + if (psid && !NT_STATUS_IS_OK(sid_to_uid(psid, &id.uid))) { + DEBUG(0,("sid_to_uid: failed, SID[%s]\n", + sid_string_static(psid))); + } + + ret = SMB_VFS_GET_QUOTA(fsp->conn, qtype, id, &D); + + if (psid) + qt->sid = *psid; + + if (ret!=0) { + return ret; + } + + qt->usedspace = (SMB_BIG_UINT)D.curblocks*D.bsize; + qt->softlim = limit_unix2nt(D.softlimit, D.bsize); + qt->hardlim = limit_unix2nt(D.hardlimit, D.bsize); + qt->qflags = D.qflags; + + + return 0; +} + +int vfs_set_ntquota(files_struct *fsp, enum SMB_QUOTA_TYPE qtype, DOM_SID *psid, SMB_NTQUOTA_STRUCT *qt) +{ + int ret; + SMB_DISK_QUOTA D; + unid_t id; + ZERO_STRUCT(D); + + if (!fsp||!fsp->conn||!qt) + return (-1); + + id.uid = -1; + + D.bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE; + + D.softlimit = limit_nt2unix(qt->softlim,D.bsize); + D.hardlimit = limit_nt2unix(qt->hardlim,D.bsize); + D.qflags = qt->qflags; + + D.isoftlimit = limit_blk2inodes(D.softlimit); + D.ihardlimit = limit_blk2inodes(D.hardlimit); + + if (psid && !NT_STATUS_IS_OK(sid_to_uid(psid, &id.uid))) { + DEBUG(0,("sid_to_uid: failed, SID[%s]\n", + sid_string_static(psid))); + } + + ret = SMB_VFS_SET_QUOTA(fsp->conn, qtype, id, &D); + + return ret; +} + +static BOOL allready_in_quota_list(SMB_NTQUOTA_LIST *qt_list, uid_t uid) +{ + SMB_NTQUOTA_LIST *tmp_list = NULL; + + if (!qt_list) + return False; + + for (tmp_list=qt_list;tmp_list!=NULL;tmp_list=tmp_list->next) { + if (tmp_list->uid == uid) { + return True; + } + } + + return False; +} + +int vfs_get_user_ntquota_list(files_struct *fsp, SMB_NTQUOTA_LIST **qt_list) +{ + struct passwd *usr; + TALLOC_CTX *mem_ctx = NULL; + + if (!fsp||!fsp->conn||!qt_list) + return (-1); + + *qt_list = NULL; + + if ((mem_ctx=talloc_init("SMB_USER_QUOTA_LIST"))==NULL) { + DEBUG(0,("talloc_init() failed\n")); + return (-1); + } + + sys_setpwent(); + while ((usr = sys_getpwent()) != NULL) { + SMB_NTQUOTA_STRUCT tmp_qt; + SMB_NTQUOTA_LIST *tmp_list_ent; + DOM_SID sid; + + ZERO_STRUCT(tmp_qt); + + if (allready_in_quota_list((*qt_list),usr->pw_uid)) { + DEBUG(5,("record for uid[%ld] allready in the list\n",(long)usr->pw_uid)); + continue; + } + + if (!NT_STATUS_IS_OK(uid_to_sid(&sid, usr->pw_uid))) { + DEBUG(0,("uid_to_sid failed for %ld\n",(long)usr->pw_uid)); + continue; + } + + if (vfs_get_ntquota(fsp, SMB_USER_QUOTA_TYPE, &sid, &tmp_qt)!=0) { + DEBUG(1,("no quota entry for sid[%s] path[%s]\n", + sid_string_static(&sid),fsp->conn->connectpath)); + continue; + } + + DEBUG(15,("quota entry for id[%s] path[%s]\n", + sid_string_static(&sid),fsp->conn->connectpath)); + + if ((tmp_list_ent=(SMB_NTQUOTA_LIST *)talloc_zero(mem_ctx,sizeof(SMB_NTQUOTA_LIST)))==NULL) { + DEBUG(0,("talloc_zero() failed\n")); + *qt_list = NULL; + talloc_destroy(mem_ctx); + return (-1); + } + + if ((tmp_list_ent->quotas=(SMB_NTQUOTA_STRUCT *)talloc_zero(mem_ctx,sizeof(SMB_NTQUOTA_STRUCT)))==NULL) { + DEBUG(0,("talloc_zero() failed\n")); + *qt_list = NULL; + talloc_destroy(mem_ctx); + return (-1); + } + + tmp_list_ent->uid = usr->pw_uid; + memcpy(tmp_list_ent->quotas,&tmp_qt,sizeof(tmp_qt)); + tmp_list_ent->mem_ctx = mem_ctx; + + DLIST_ADD((*qt_list),tmp_list_ent); + + } + sys_endpwent(); + + return 0; +} + +void *init_quota_handle(TALLOC_CTX *mem_ctx) +{ + SMB_NTQUOTA_HANDLE *qt_handle; + + if (!mem_ctx) + return False; + + qt_handle = (SMB_NTQUOTA_HANDLE *)talloc_zero(mem_ctx,sizeof(SMB_NTQUOTA_HANDLE)); + if (qt_handle==NULL) { + DEBUG(0,("talloc_zero() failed\n")); + return NULL; + } + + return (void *)qt_handle; +} + +void destroy_quota_handle(void **pqt_handle) +{ + SMB_NTQUOTA_HANDLE *qt_handle = NULL; + if (!pqt_handle||!(*pqt_handle)) + return; + + qt_handle = (*pqt_handle); + + + if (qt_handle->quota_list) + free_ntquota_list(&qt_handle->quota_list); + + qt_handle->quota_list = NULL; + qt_handle->tmp_list = NULL; + qt_handle = NULL; + + return; +} + diff --git a/source3/tdb/tdbback.c b/source3/tdb/tdbback.c new file mode 100644 index 0000000000..744cface55 --- /dev/null +++ b/source3/tdb/tdbback.c @@ -0,0 +1,201 @@ +/* + Unix SMB/CIFS implementation. + low level tdb backup and restore utility + Copyright (C) Andrew Tridgell 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 + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "tdb.h" + +static int failed; + +char *add_suffix(const char *name, const char *suffix) +{ + char *ret; + int len = strlen(name) + strlen(suffix) + 1; + ret = malloc(len); + if (!ret) { + fprintf(stderr,"Out of memory!\n"); + exit(1); + } + strncpy(ret, name, len); + strncat(ret, suffix, len); + return ret; +} + +static int copy_fn(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, void *state) +{ + TDB_CONTEXT *tdb_new = (TDB_CONTEXT *)state; + + if (tdb_store(tdb_new, key, dbuf, TDB_INSERT) != 0) { + fprintf(stderr,"Failed to insert into %s\n", tdb_new->name); + failed = 1; + return 1; + } + return 0; +} + + +static int test_fn(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, void *state) +{ + return 0; +} + +/* + carefully backup a tdb, validating the contents and + only doing the backup if its OK + this function is also used for restore +*/ +int backup_tdb(const char *old_name, const char *new_name) +{ + TDB_CONTEXT *tdb; + TDB_CONTEXT *tdb_new; + char *tmp_name; + struct stat st; + int count1, count2; + + tmp_name = add_suffix(new_name, ".tmp"); + + /* stat the old tdb to find its permissions */ + if (stat(old_name, &st) != 0) { + perror(old_name); + return 1; + } + + /* open the old tdb */ + tdb = tdb_open(old_name, 0, 0, O_RDWR, 0); + if (!tdb) { + printf("Failed to open %s\n", old_name); + return 1; + } + + /* create the new tdb */ + unlink(tmp_name); + tdb_new = tdb_open(tmp_name, tdb->header.hash_size, + TDB_DEFAULT, O_RDWR|O_CREAT|O_EXCL, + st.st_mode & 0777); + if (!tdb_new) { + perror(tmp_name); + free(tmp_name); + return 1; + } + + /* lock the old tdb */ + if (tdb_lockall(tdb) != 0) { + fprintf(stderr,"Failed to lock %s\n", old_name); + tdb_close(tdb); + tdb_close(tdb_new); + unlink(tmp_name); + free(tmp_name); + return 1; + } + + failed = 0; + + /* traverse and copy */ + count1 = tdb_traverse(tdb, copy_fn, (void *)tdb_new); + if (count1 < 0 || failed) { + fprintf(stderr,"failed to copy %s\n", old_name); + tdb_close(tdb); + tdb_close(tdb_new); + unlink(tmp_name); + free(tmp_name); + return 1; + } + + /* close the old tdb */ + tdb_close(tdb); + + /* close the new tdb and re-open read-only */ + tdb_close(tdb_new); + tdb_new = tdb_open(tmp_name, 0, TDB_DEFAULT, O_RDONLY, 0); + if (!tdb_new) { + fprintf(stderr,"failed to reopen %s\n", tmp_name); + unlink(tmp_name); + perror(tmp_name); + free(tmp_name); + return 1; + } + + /* traverse the new tdb to confirm */ + count2 = tdb_traverse(tdb_new, test_fn, 0); + if (count2 != count1) { + fprintf(stderr,"failed to copy %s\n", old_name); + tdb_close(tdb_new); + unlink(tmp_name); + free(tmp_name); + return 1; + } + + /* make sure the new tdb has reached stable storage */ + fsync(tdb_new->fd); + + /* close the new tdb and rename it to .bak */ + tdb_close(tdb_new); + unlink(new_name); + if (rename(tmp_name, new_name) != 0) { + perror(new_name); + free(tmp_name); + return 1; + } + + free(tmp_name); + + return 0; +} + + + +/* + verify a tdb and if it is corrupt then restore from *.bak +*/ +int verify_tdb(const char *fname, const char *bak_name) +{ + TDB_CONTEXT *tdb; + int count = -1; + + /* open the tdb */ + tdb = tdb_open(fname, 0, 0, O_RDONLY, 0); + + /* traverse the tdb, then close it */ + if (tdb) { + count = tdb_traverse(tdb, test_fn, NULL); + tdb_close(tdb); + } + + /* count is < 0 means an error */ + if (count < 0) { + printf("restoring %s\n", fname); + return backup_tdb(bak_name, fname); + } + + printf("%s : %d records\n", fname, count); + + return 0; +} diff --git a/source3/tdb/tdbback.h b/source3/tdb/tdbback.h new file mode 100644 index 0000000000..7ebeaa494d --- /dev/null +++ b/source3/tdb/tdbback.h @@ -0,0 +1,23 @@ +/* + Unix SMB/CIFS implementation. + low level tdb backup and restore utility + Copyright (C) Andrew Tridgell 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 + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +char *add_suffix(const char *name, const char *suffix); +int backup_tdb(const char *old_name, const char *new_name); +int verify_tdb(const char *fname, const char *bak_name); diff --git a/source3/utils/net_idmap.c b/source3/utils/net_idmap.c new file mode 100644 index 0000000000..689d4ff813 --- /dev/null +++ b/source3/utils/net_idmap.c @@ -0,0 +1,156 @@ +/* + Samba Unix/Linux SMB client library + Distributed SMB/CIFS Server Management Utility + Copyright (C) 2003 Andrew Bartlett (abartlet@samba.org) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "includes.h" +#include "../utils/net.h" + + +/*********************************************************** + Helper function for net_idmap_dump. Dump one entry. + **********************************************************/ +static int net_idmap_dump_one_entry(TDB_CONTEXT *tdb, + TDB_DATA key, + TDB_DATA data, + void *unused) +{ + if (strcmp(key.dptr, "USER HWM") == 0) { + printf("USER HWM %d\n", IVAL(data.dptr,0)); + return 0; + } + + if (strcmp(key.dptr, "GROUP HWM") == 0) { + printf("GROUP HWM %d\n", IVAL(data.dptr,0)); + return 0; + } + + if (strncmp(key.dptr, "S-", 2) != 0) + return 0; + + printf("%s %s\n", data.dptr, key.dptr); + return 0; +} + +/*********************************************************** + Dump the current idmap + **********************************************************/ +static int net_idmap_dump(int argc, const char **argv) +{ + TDB_CONTEXT *idmap_tdb; + + if ( argc != 1 ) + return net_help_idmap( argc, argv ); + + idmap_tdb = tdb_open_log(argv[0], 0, TDB_DEFAULT, O_RDONLY, 0); + + if (idmap_tdb == NULL) { + d_printf("Could not open idmap: %s\n", argv[0]); + return -1; + } + + tdb_traverse(idmap_tdb, net_idmap_dump_one_entry, NULL); + + tdb_close(idmap_tdb); + + return 0; +} + +/*********************************************************** + Write entries from stdin to current local idmap + **********************************************************/ +static int net_idmap_restore(int argc, const char **argv) +{ + if (!idmap_init(lp_idmap_backend())) { + d_printf("Could not init idmap\n"); + return -1; + } + + while (!feof(stdin)) { + fstring line, sid_string; + int len; + unid_t id; + int type = ID_EMPTY; + DOM_SID sid; + + if (fgets(line, sizeof(line)-1, stdin) == NULL) + break; + + len = strlen(line); + + if ( (len > 0) && (line[len-1] == '\n') ) + line[len-1] = '\0'; + + if (sscanf(line, "GID %d %s", &id.gid, sid_string) == 2) { + type = ID_GROUPID; + } + + if (sscanf(line, "UID %d %s", &id.uid, sid_string) == 2) { + type = ID_USERID; + } + + if (type == ID_EMPTY) { + d_printf("ignoring invalid line [%s]\n", line); + continue; + } + + if (!string_to_sid(&sid, sid_string)) { + d_printf("ignoring invalid sid [%s]\n", sid_string); + continue; + } + + if (!NT_STATUS_IS_OK(idmap_set_mapping(&sid, id, type))) { + d_printf("Could not set mapping of %s %d to sid %s\n", + (type == ID_GROUPID) ? "GID" : "UID", + (type == ID_GROUPID) ? id.gid : id.uid, + sid_string_static(&sid)); + continue; + } + + } + + idmap_close(); + return 0; +} + +int net_help_idmap(int argc, const char **argv) +{ + d_printf("net idmap dump filename"\ + "\n Dump current id mapping\n"); + + d_printf("net idmap restore"\ + "\n Restore entries from stdin to current local idmap\n"); + + return -1; +} + +/*********************************************************** + Look at the current idmap + **********************************************************/ +int net_idmap(int argc, const char **argv) +{ + struct functable func[] = { + {"dump", net_idmap_dump}, + {"restore", net_idmap_restore}, + {"help", net_help_idmap}, + {NULL, NULL} + }; + + return net_run_function(argc, argv, func, net_help_idmap); +} + + -- cgit From 04382a5266fd618e81d8ac454db9a04a1fda7c1b Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Thu, 17 Jul 2003 01:58:36 +0000 Subject: should not have been checked in. My fault (This used to be commit af0efeeccfc6f4bc78c6baafd2bded404cc2a551) --- source3/build-me | 36 ------------------------------------ 1 file changed, 36 deletions(-) delete mode 100755 source3/build-me (limited to 'source3') diff --git a/source3/build-me b/source3/build-me deleted file mode 100755 index a5d3f32f70..0000000000 --- a/source3/build-me +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/sh - -umask 022 - -## Build options -CONFIGUREOPT="--enable-debug --enable-developer --with-pam --with-libsmbclient=no --with-static-modules" -export CONFIGUREOPT - -./autogen.sh - -case "$1" in - dmalloc) - env CFLAGS="-Wall" ./configure \ - --enable-dmalloc \ - $CONFIGUREOPT - ;; - insure) - env CFLAGS="-g" CC="insure" ./configure \ - $CONFIGUREOPT - ;; - ccache) - env CFLAGS="-Wall" CC="ccache gcc" ./configure \ - $CONFIGUREOPT - ;; - *) - env CFLAGS="-Wall" ./configure \ - $CONFIGUREOPT - ;; -esac - -## disable optimization -sed 's/-O //g' Makefile | sed 's/-O2 //g' > Makefile.new; /bin/mv -f Makefile.new Makefile - -## build -make proto -make all modules -- cgit From c39c02e1aeeb74e8c45b32d99d9354eb66040171 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Thu, 17 Jul 2003 02:49:26 +0000 Subject: fix the build. Ifdef out some code (This used to be commit e66541d0e1befec5d589890994454dd639ea0665) --- source3/rpc_client/cli_lsarpc.c | 3 + source3/rpc_parse/parse_lsa.c | 18 +- source3/smbd/build_options.c | 532 ---------------------------------------- 3 files changed, 13 insertions(+), 540 deletions(-) delete mode 100644 source3/smbd/build_options.c (limited to 'source3') diff --git a/source3/rpc_client/cli_lsarpc.c b/source3/rpc_client/cli_lsarpc.c index db873236e4..b01cf8ed4a 100644 --- a/source3/rpc_client/cli_lsarpc.c +++ b/source3/rpc_client/cli_lsarpc.c @@ -1257,6 +1257,7 @@ NTSTATUS cli_lsa_remove_account_rights(struct cli_state *cli, TALLOC_CTX *mem_ct POLICY_HND *pol, DOM_SID sid, BOOL removeall, uint32 count, const char **privs_name) { +#if 0 prs_struct qbuf, rbuf; LSA_Q_REMOVE_ACCT_RIGHTS q; LSA_R_REMOVE_ACCT_RIGHTS r; @@ -1290,6 +1291,8 @@ NTSTATUS cli_lsa_remove_account_rights(struct cli_state *cli, TALLOC_CTX *mem_ct done: return result; +#endif + return NT_STATUS_UNSUCCESSFUL; } diff --git a/source3/rpc_parse/parse_lsa.c b/source3/rpc_parse/parse_lsa.c index 7ff2aa7d01..d8c3b4e3c3 100644 --- a/source3/rpc_parse/parse_lsa.c +++ b/source3/rpc_parse/parse_lsa.c @@ -2382,10 +2382,11 @@ void init_r_add_acct_rights(LSA_R_ADD_ACCT_RIGHTS *q_r) } +#if 0 /******************************************************************* Inits an LSA_Q_REMOVE_ACCT_RIGHTS structure. ********************************************************************/ -void init_q_remove_acct_rights(LSA_Q_REMOVE_ACCT_RIGHTS *q_q, + void init_q_remove_acct_rights(LSA_Q_REMOVE_ACCT_RIGHTS *q_q, POLICY_HND *hnd, DOM_SID *sid, uint32 removeall, @@ -2404,7 +2405,7 @@ void init_q_remove_acct_rights(LSA_Q_REMOVE_ACCT_RIGHTS *q_q, /******************************************************************* reads or writes a LSA_Q_REMOVE_ACCT_RIGHTS structure. ********************************************************************/ -BOOL lsa_io_q_remove_acct_rights(const char *desc, LSA_Q_REMOVE_ACCT_RIGHTS *q_q, prs_struct *ps, int depth) + BOOL lsa_io_q_remove_acct_rights(const char *desc, LSA_Q_REMOVE_ACCT_RIGHTS *q_q, prs_struct *ps, int depth) { prs_debug(ps, depth, desc, "lsa_io_q_remove_acct_rights"); depth++; @@ -2430,7 +2431,7 @@ BOOL lsa_io_q_remove_acct_rights(const char *desc, LSA_Q_REMOVE_ACCT_RIGHTS *q_q /******************************************************************* reads or writes a LSA_R_REMOVE_ACCT_RIGHTS structure. ********************************************************************/ -BOOL lsa_io_r_remove_acct_rights(const char *desc, LSA_R_REMOVE_ACCT_RIGHTS *r_c, prs_struct *ps, int depth) + BOOL lsa_io_r_remove_acct_rights(const char *desc, LSA_R_REMOVE_ACCT_RIGHTS *r_c, prs_struct *ps, int depth) { prs_debug(ps, depth, desc, "lsa_io_r_remove_acct_rights"); depth++; @@ -2444,7 +2445,7 @@ BOOL lsa_io_r_remove_acct_rights(const char *desc, LSA_R_REMOVE_ACCT_RIGHTS *r_c /******************************************************************* Inits an LSA_R_REMOVE_ACCT_RIGHTS structure. ********************************************************************/ -void init_r_remove_acct_rights(LSA_R_REMOVE_ACCT_RIGHTS *q_r) + void init_r_remove_acct_rights(LSA_R_REMOVE_ACCT_RIGHTS *q_r) { DEBUG(5, ("init_r_remove_acct_rights\n")); } @@ -2452,7 +2453,7 @@ void init_r_remove_acct_rights(LSA_R_REMOVE_ACCT_RIGHTS *q_r) /******************************************************************* Inits an LSA_Q_ENUM_ACCT_WITH_RIGHT structure. ********************************************************************/ -void init_q_enum_acct_with_right(LSA_Q_ENUM_ACCT_WITH_RIGHT *q_q, + void init_q_enum_acct_with_right(LSA_Q_ENUM_ACCT_WITH_RIGHT *q_q, POLICY_HND *hnd, const char *right) { @@ -2469,7 +2470,7 @@ void init_q_enum_acct_with_right(LSA_Q_ENUM_ACCT_WITH_RIGHT *q_q, /******************************************************************* reads or writes a LSA_Q_ENUM_ACCT_WITH_RIGHT structure. ********************************************************************/ -BOOL lsa_io_q_enum_acct_with_right(const char *desc, LSA_Q_ENUM_ACCT_WITH_RIGHT *q_q, prs_struct *ps, int depth) + BOOL lsa_io_q_enum_acct_with_right(const char *desc, LSA_Q_ENUM_ACCT_WITH_RIGHT *q_q, prs_struct *ps, int depth) { prs_debug(ps, depth, desc, "lsa_io_q_enum_acct_with_right"); depth++; @@ -2497,7 +2498,7 @@ BOOL lsa_io_q_enum_acct_with_right(const char *desc, LSA_Q_ENUM_ACCT_WITH_RIGHT /******************************************************************* reads or writes a LSA_R_ENUM_ACCT_WITH_RIGHT structure. ********************************************************************/ -BOOL lsa_io_r_enum_acct_with_right(const char *desc, LSA_R_ENUM_ACCT_WITH_RIGHT *r_c, prs_struct *ps, int depth) + BOOL lsa_io_r_enum_acct_with_right(const char *desc, LSA_R_ENUM_ACCT_WITH_RIGHT *r_c, prs_struct *ps, int depth) { prs_debug(ps, depth, desc, "lsa_io_r_enum_acct_with_right"); depth++; @@ -2517,7 +2518,7 @@ BOOL lsa_io_r_enum_acct_with_right(const char *desc, LSA_R_ENUM_ACCT_WITH_RIGHT /******************************************************************* Inits an LSA_R_ENUM_ACCT_WITH_RIGHT structure. ********************************************************************/ -void init_r_enum_acct_with_right(LSA_R_ENUM_ACCT_WITH_RIGHT *r_c, + void init_r_enum_acct_with_right(LSA_R_ENUM_ACCT_WITH_RIGHT *r_c, uint32 count, DOM_SID *sids) { @@ -2526,3 +2527,4 @@ void init_r_enum_acct_with_right(LSA_R_ENUM_ACCT_WITH_RIGHT *r_c, r_c->count = count; init_sid_array(&r_c->sids, count, sids); } +#endif diff --git a/source3/smbd/build_options.c b/source3/smbd/build_options.c deleted file mode 100644 index 43335666a6..0000000000 --- a/source3/smbd/build_options.c +++ /dev/null @@ -1,532 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Build Options for Samba Suite - Copyright (C) Vance Lankhaar 2001 - Copyright (C) Andrew Bartlett 2001 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" -#include "build_env.h" -#include "dynconfig.h" - -static void output(BOOL screen, const char *format, ...) PRINTF_ATTRIBUTE(2,3); - -/* -#define OUTPUT(x) snprintf(outstring,sizeof(outstring),x); output(screen,outstring); -*/ -/**************************************************************************** -helper function for build_options -****************************************************************************/ -static void output(BOOL screen, const char *format, ...) -{ - char *ptr; - va_list ap; - - va_start(ap, format); - vasprintf(&ptr,format,ap); - va_end(ap); - - if (screen) { - d_printf("%s", ptr); - } else { - DEBUG(4,("%s", ptr)); - } - - SAFE_FREE(ptr); -} - -/**************************************************************************** -options set at build time for the samba suite -****************************************************************************/ -void build_options(BOOL screen) -{ - if ((DEBUGLEVEL < 4) && (!screen)) { - return; - } - -#ifdef _BUILD_ENV_H - /* Output information about the build environment */ - output(screen,"Build environment:\n"); - output(screen," Built by: %s@%s\n",BUILD_ENV_USER,BUILD_ENV_HOST); - output(screen," Built on: %s\n",BUILD_ENV_DATE); - - output(screen," Built using: %s\n",BUILD_ENV_COMPILER); - output(screen," Build host: %s\n",BUILD_ENV_UNAME); - output(screen," SRCDIR: %s\n",BUILD_ENV_SRCDIR); - output(screen," BUILDDIR: %s\n",BUILD_ENV_BUILDDIR); - - -#endif - - /* Output various options (most correspond to --with options) */ - output(screen,"\nBuild options:\n"); -#ifdef WITH_SMBWRAPPER - output(screen," WITH_SMBWRAPPER\n"); -#endif -#ifdef WITH_AFS - output(screen," WITH_AFS\n"); -#endif -#ifdef WITH_DFS - output(screen," WITH_DFS\n"); -#endif -#ifdef KRB4_AUTH - output(screen," KRB4_AUTH"); -#endif -#ifdef HAVE_KRB5 - output(screen," HAVE_KRB5"); -#endif -#ifdef HAVE_GSSAPI - output(screen," HAVE_GSSAPI"); -#endif -#ifdef HAVE_LDAP - output(screen," HAVE_LDAP"); -#endif -#ifdef WITH_AUTOMOUNT - output(screen," WITH_AUTOMOUNT\n"); -#endif -#ifdef WITH_SMBMOUNT - output(screen," WITH_SMBMOUNT\n"); -#endif -#ifdef WITH_PAM - output(screen," WITH_PAM\n"); -#endif -#ifdef WITH_NISPLUS_HOME - output(screen," WITH_NISPLUS_HOME\n"); -#endif -#ifdef WITH_SYSLOG - output(screen," WITH_SYSLOG\n"); -#endif -#ifdef WITH_PROFILE - output(screen," WITH_PROFILE\n"); -#endif -#ifdef WITH_QUOTAS - output(screen," WITH_QUOTAS\n"); -#endif -#ifdef WITH_VFS - output(screen," WITH_VFS\n"); -#endif -#ifdef USE_SPINLOCKS - output(screen," USE_SPINLOCKS\n"); -#endif -#ifdef SPARC_SPINLOCKS - output(screen," SPARC_SPINLOCKS\n"); -#endif -#ifdef INTEL_SPINLOCKS - output(screen," INTEL_SPINLOCKS\n"); -#endif -#ifdef MIPS_SPINLOCKS - output(screen," MIPS_SPINLOCKS\n"); -#endif -#ifdef POWERPC_SPINLOCKS - output(screen," POWERPC_SPINLOCKS\n"); -#endif -#ifdef HAVE_UNIXWARE_ACLS - output(screen," HAVE_UNIXWARE_ACLS\n"); -#endif -#ifdef HAVE_SOLARIS_ACLS - output(screen," HAVE_SOLARIS_ACLS\n"); -#endif -#ifdef HAVE_IRIX_ACLS - output(screen," HAVE_IRIX_ACLS\n"); -#endif -#ifdef HAVE_AIX_ACLS - output(screen," HAVE_AIX_ACLS\n"); -#endif -#ifdef HAVE_POSIX_ACLS - output(screen," HAVE_POSIX_ACLS\n"); -#endif -#ifdef HAVE_TRU64_ACLS - output(screen," HAVE_TRU64_ACLS\n"); -#endif - -#ifdef HAVE_ACL_GET_PERM_NP - output(screen," HAVE_ACL_GET_PERM_NP\n"); -#endif -#ifdef HAVE_NO_ACLS - output(screen," HAVE_NO_ACLS\n"); -#endif -#ifdef HAVE_LIBREADLINE - output(screen," HAVE_LIBREADLINE\n"); -#endif -#ifdef WITH_LIBICONV - output(screen," WITH_LIBICONV: %s\n",WITH_LIBICONV); -#endif - - - /* Output various paths to files and directories */ - output(screen,"\nPaths:\n"); - output(screen," CONFIGFILE: %s\n", dyn_CONFIGFILE); -#ifdef PRIVATE_DIR - output(screen," PRIVATE_DIR: %s\n",PRIVATE_DIR); -#endif -#ifdef LMHOSTSFILE - output(screen," LMHOSTSFILE: %s\n",LMHOSTSFILE); -#endif - output(screen," SBINDIR: %s\n", dyn_SBINDIR); - output(screen," BINDIR: %s\n", dyn_BINDIR); - output(screen," LOCKDIR: %s\n",dyn_LOCKDIR); - output(screen," LOGFILEBASE: %s\n", dyn_LOGFILEBASE); - - /*Output various other options (most map to defines in the configure script*/ - output(screen,"\nOther Build Options:\n"); -#ifdef HAVE_VOLATILE - output(screen," HAVE_VOLATILE\n"); -#endif -#ifdef HAVE_SHADOW_H - output(screen," HAVE_SHADOW_H\n"); -#endif -#ifdef HAVE_CRYPT - output(screen," HAVE_CRYPT\n"); -#endif -#ifdef USE_BOTH_CRYPT_CALLS - output(screen," USE_BOTH_CRYPT_CALLS\n"); -#endif -#ifdef HAVE_TRUNCATED_SALT - output(screen," HAVE_TRUNCATED_SALT\n"); -#endif -#ifdef HAVE_CUPS - output(screen," HAVE_CUPS\n"); -#endif -#ifdef HAVE_CUPS_CUPS_H - output(screen," HAVE_CUPS_CUPS_H\n"); -#endif -#ifdef HAVE_CUPS_LANGUAGE_H - output(screen," HAVE_CUPS_LANGUAGE_H\n"); -#endif -#ifdef HAVE_DLOPEN - output(screen," HAVE_DLOPEN\n"); -#endif -#ifdef HAVE_DLCLOSE - output(screen," HAVE_DLCLOSE\n"); -#endif -#ifdef HAVE_DLSYM - output(screen," HAVE_DLSYM\n"); -#endif -#ifdef HAVE_DLERROR - output(screen," HAVE_DLERROR\n"); -#endif -#ifdef HAVE_UNIXSOCKET - output(screen," HAVE_UNIXSOCKET\n"); -#endif -#ifdef HAVE_SOCKLEN_T_TYPE - output(screen," HAVE_SOCKLEN_T_TYPE\n"); -#endif -#ifdef HAVE_SIG_ATOMIC_T_TYPE - output(screen," HAVE_SIG_ATOMIC_T_TYPE\n"); -#endif -#ifdef HAVE_SETRESUID - output(screen," HAVE_SETRESUID\n"); -#endif -#ifdef HAVE_SETRESGID - output(screen," HAVE_SETRESGID\n"); -#endif -#ifdef HAVE_CONNECT - output(screen," HAVE_CONNECT\n"); -#endif -#ifdef HAVE_YP_GET_DEFAULT_DOMAIN - output(screen," HAVE_YP_GET_DEFAULT_DOMAIN\n"); -#endif -#ifdef HAVE_STAT64 - output(screen," HAVE_STAT64\n"); -#endif -#ifdef HAVE_LSTAT64 - output(screen," HAVE_LSTAT64\n"); -#endif -#ifdef HAVE_FSTAT64 - output(screen," HAVE_FSTAT64\n"); -#endif -#ifdef HAVE_STRCASECMP - output(screen," HAVE_STRCASECMP\n"); -#endif -#ifdef HAVE_MEMSET - output(screen," HAVE_MEMSET\n"); -#endif -#ifdef HAVE_LONGLONG - output(screen," HAVE_LONGLONG\n"); -#endif -#ifdef COMPILER_SUPPORTS_LL - output(screen," COMPILER_SUPPORTS_LL\n"); -#endif -#ifdef SIZEOF_OFF_T - output(screen," SIZEOF_OFF_T: %d\n",SIZEOF_OFF_T); -#endif -#ifdef HAVE_OFF64_T - output(screen," HAVE_OFF64_T\n"); -#endif -#ifdef SIZEOF_INO_T - output(screen," SIZEOF_INO_T: %d\n",SIZEOF_INO_T); -#endif -#ifdef HAVE_INO64_T - output(screen," HAVE_INO64_T\n"); -#endif -#ifdef HAVE_STRUCT_DIRENT64 - output(screen," HAVE_STRUCT_DIRENT64\n"); -#endif -#ifdef HAVE_UNSIGNED_CHAR - output(screen," HAVE_UNSIGNED_CHAR\n"); -#endif -#ifdef HAVE_SOCK_SIN_LEN - output(screen," HAVE_SOCK_SIN_LEN\n"); -#endif -#ifdef SEEKDIR_RETURNS_VOID - output(screen," SEEKDIR_RETURNS_VOID\n"); -#endif -#ifdef HAVE_FUNCTION_MACRO - output(screen," HAVE_FUNCTION_MACRO\n"); -#endif -#ifdef HAVE_GETTIMEOFDAY - output(screen," HAVE_GETTIMEOFDAY\n"); -#endif -#ifdef HAVE_C99_VSNPRINTF - output(screen," HAVE_C99_VSNPRINTF\n"); -#endif -#ifdef HAVE_BROKEN_READDIR - output(screen," HAVE_BROKEN_READDIR\n"); -#endif -#ifdef HAVE_NATIVE_ICONV - output(screen," HAVE_NATIVE_ICONV\n"); -#endif -#ifdef HAVE_KERNEL_OPLOCKS_LINUX - output(screen," HAVE_KERNEL_OPLOCKS_LINUX\n"); -#endif -#ifdef HAVE_KERNEL_CHANGE_NOTIFY - output(screen," HAVE_KERNEL_CHANGE_NOTIFY\n"); -#endif -#ifdef HAVE_KERNEL_SHARE_MODES - output(screen," HAVE_KERNEL_SHARE_MODES\n"); -#endif -#ifdef HAVE_KERNEL_OPLOCKS_IRIX - output(screen," HAVE_KERNEL_OPLOCKS_IRIX\n"); -#endif -#ifdef HAVE_IRIX_SPECIFIC_CAPABILITIES - output(screen," HAVE_IRIX_SPECIFIC_CAPABILITIES\n"); -#endif -#ifdef HAVE_INT16_FROM_RPC_RPC_H - output(screen," HAVE_INT16_FROM_RPC_RPC_H\n"); -#endif -#ifdef HAVE_UINT16_FROM_RPC_RPC_H - output(screen," HAVE_UINT16_FROM_RPC_RPC_H\n"); -#endif -#ifdef HAVE_INT32_FROM_RPC_RPC_H - output(screen," HAVE_INT16_FROM_RPC_RPC_H\n"); -#endif -#ifdef HAVE_UINT32_FROM_RPC_RPC_H - output(screen," HAVE_UINT32_FROM_RPC_RPC_H\n"); -#endif -#ifdef HAVE_RPC_AUTH_ERROR_CONFLICT - output(screen," HAVE_RPC_AUTH_ERROR_CONFLICT\n"); -#endif -#ifdef HAVE_FTRUNCATE_EXTEND - output(screen," HAVE_FTRUNCATE_EXTEND\n"); -#endif -#ifdef HAVE_WORKING_AF_LOCAL - output(screen," HAVE_WORKING_AF_LOCAL\n"); -#endif -#ifdef HAVE_BROKEN_GETGROUPS - output(screen," HAVE_BROKEN_GETGROUPS\n"); -#endif -#ifdef REPLACE_GETPASS - output(screen," REPLACE_GETPASS\n"); -#endif -#ifdef REPLACE_INET_NTOA - output(screen," REPLACE_INET_NTOA\n"); -#endif -#ifdef HAVE_SECURE_MKSTEMP - output(screen," HAVE_SECURE_MKSTEMP\n"); -#endif -#ifdef SYSCONF_SC_NGROUPS_MAX - output(screen," SYSCONF_SC_NGROUPS_MAX\n"); -#endif -#ifdef HAVE_IFACE_AIX - output(screen," HAVE_IFACE_AIX\n"); -#endif -#ifdef HAVE_IFACE_IFCONF - output(screen," HAVE_IFACE_IFCONF\n"); -#endif -#ifdef HAVE_IFACE_IFREQ - output(screen," HAVE_IFACE_IFREQ\n"); -#endif -#ifdef USE_SETRESUID - output(screen," USE_SETRESUID\n"); -#endif -#ifdef USE_SETRESGID - output(screen," USE_SETREUID\n"); -#endif -#ifdef USE_SETEUID - output(screen," USE_SETEUID\n"); -#endif -#ifdef USE_SETUIDX - output(screen," USE_SETUIDX\n"); -#endif -#ifdef HAVE_MMAP - output(screen," HAVE_MMAP\n"); -#endif -#ifdef MMAP_BLACKLIST - output(screen," MMAP_BLACKLIST\n"); -#endif -#ifdef FTRUNCATE_NEEDS_ROOT - output(screen," FTRUNCATE_NEEDS_ROOT\n"); -#endif -#ifdef HAVE_FCNTL_LOCK - output(screen," HAVE_FCNTL_LOCK\n"); -#endif -#ifdef HAVE_BROKEN_FCNTL64_LOCKS - output(screen," HAVE_BROKEN_FCNTL64_LOCKS\n"); -#endif -#ifdef HAVE_STRUCT_FLOCK64 - output(screen," HAVE_STRUCT_FLOCK64\n"); -#endif -#ifdef BROKEN_NISPLUS_INCLUDE_FILES - output(screen," BROKEN_NISPLUS_INCLUDE_FILES\n"); -#endif -#ifdef HAVE_LIBPAM - output(screen," HAVE_LIBPAM\n"); -#endif -#ifdef STAT_STATVFS64 - output(screen," STAT_STATVFS64\n"); -#endif -#ifdef STAT_STATVFS - output(screen," STAT_STATVFS\n"); -#endif -#ifdef STAT_STATFS3_OSF1 - output(screen," STAT_STATFS3_OSF1\n"); -#endif -#ifdef STAT_STATFS2_BSIZE - output(screen," STAT_STATFS2_BSIZE\n"); -#endif -#ifdef STAT_STATFS4 - output(screen," STAT_STATFS4\n"); -#endif -#ifdef STAT_STATFS2_FSIZE - output(screen," STAT_STATFS2_FSIZE\n"); -#endif -#ifdef STAT_STATFS2_FS_DATA - output(screen," STAT_STATFS2_FS_DATA\n"); -#endif -#ifdef HAVE_EXPLICIT_LARGEFILE_SUPPORT - output(screen," HAVE_EXPLICIT_LARGEFILE_SUPPORT\n"); -#endif - -#ifdef WITH_UTMP - /* Output UTMP Stuff */ - output(screen,"\nUTMP Related:\n"); - output(screen," WITH_UTMP\n"); - -#ifdef HAVE_UTIMBUF - output(screen," HAVE_UTIMBUF\n"); -#endif -#ifdef HAVE_UT_UT_NAME - output(screen," HAVE_UT_UT_NAME\n"); -#endif -#ifdef HAVE_UT_UT_USER - output(screen," HAVE_UT_UT_USER\n"); -#endif -#ifdef HAVE_UT_UT_ID - output(screen," HAVE_UT_UT_ID\n"); -#endif -#ifdef HAVE_UT_UT_HOST - output(screen," HAVE_UT_UT_HOST\n"); -#endif -#ifdef HAVE_UT_UT_TIME - output(screen," HAVE_UT_UT_TIME\n"); -#endif -#ifdef HAVE_UT_UT_TV - output(screen," HAVE_UT_UT_TV\n"); -#endif -#ifdef HAVE_UT_UT_TYPE - output(screen," HAVE_UT_UT_TYPE\n"); -#endif -#ifdef HAVE_UT_UT_PID - output(screen," HAVE_UT_UT_PID\n"); -#endif -#ifdef HAVE_UT_UT_EXIT - output(screen," HAVE_UT_UT_EXIT\n"); -#endif -#ifdef HAVE_UT_UT_ADDR - output(screen," HAVE_UT_UT_ADDR\n"); -#endif -#ifdef PUTUTLINE_RETURNS_UTMP - output(screen," PUTUTLINE_RETURNS_UTMP\n"); -#endif -#ifdef HAVE_UX_UT_SYSLEN - output(screen," HAVE_UX_UT_SYSLEN\n"); -#endif -#endif /* WITH_UTMP */ - - /* Output Build OS */ - output(screen,"\nBuilt for host os:\n"); -#ifdef LINUX - output(screen," LINUX\n"); -#endif -#ifdef SUNOS5 - output(screen," SUNOS5\n"); -#endif -#ifdef SUNOS4 - output(screen," SUNOS4\n"); -#endif - /* BSD Isn't Defined in the configure script, but there is something about it in include/config.h.in (and I guess acconfig.h) */ -#ifdef BSD - output(screen," BSD\n"); -#endif -#ifdef IRIX - output(screen," IRIX\n"); -#endif -#ifdef IRIX6 - output(screen," IRIX6\n"); -#endif -#ifdef AIX - output(screen," AIX\n"); -#endif -#ifdef HPUX - output(screen," HPUX\n"); -#endif -#ifdef QNX - output(screen," QNX\n"); -#endif -#ifdef OSF1 - output(screen," OSF1\n"); -#endif -#ifdef SCO - output(screen," SCO\n"); -#endif -#ifdef UNIXWARE - output(screen," UNIXWARE\n"); -#endif -#ifdef NEXT2 - output(screen," NEXT2\n"); -#endif -#ifdef RELIANTUNIX - output(screen," RELIANTUNIX\n"); -#endif - - /* Output the sizes of the various types */ - output(screen,"\nType sizes:\n"); - output(screen," sizeof(char): %d\n",sizeof(char)); - output(screen," sizeof(int): %d\n",sizeof(int)); - output(screen," sizeof(long): %d\n",sizeof(long)); - output(screen," sizeof(uint8): %d\n",sizeof(uint8)); - output(screen," sizeof(uint16): %d\n",sizeof(uint16)); - output(screen," sizeof(uint32): %d\n",sizeof(uint32)); - output(screen," sizeof(short): %d\n",sizeof(short)); - output(screen," sizeof(void*): %d\n",sizeof(void*)); - - output(screen,"\nBuiltin modules:\n"); - output(screen,"%s\n", STRING_STATIC_MODULES); -} - - - -- cgit From 7efce478976e2ac71bcaf4e4d1049bb263634711 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Wed, 23 Jul 2003 20:10:25 +0000 Subject: connect to the right realm or domain for trusted AD domains (This used to be commit ae14f8364398f07fc3e7c7861cd39fe528f3fe7a) --- source3/libads/ldap.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'source3') diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c index 92f7f7645a..cf6f9375f8 100644 --- a/source3/libads/ldap.c +++ b/source3/libads/ldap.c @@ -109,12 +109,8 @@ static BOOL ads_find_dc(ADS_STRUCT *ads) /* realm */ c_realm = ads->server.realm; - if (!c_realm || !*c_realm) { - c_realm = lp_realm(); - } - if ( c_realm ) + if (c_realm && *c_realm) got_realm = True; - again: /* we need to try once with the realm name and fallback to the @@ -122,10 +118,10 @@ again: if ( !got_realm && !lp_disable_netbios() ) { c_realm = ads->server.workgroup; - if (!c_realm || !*c_realm) - c_realm = lp_workgroup(); - if (!c_realm) + if (!c_realm || !*c_realm) { + DEBUG(0,("ads_find_dc: no realm or workgroup! Was the structure initialized?\n")); return False; + } } pstrcpy( realm, c_realm ); -- cgit From 04bf12b176d5abe06b7f1401810369bcafe0b611 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sat, 2 Aug 2003 20:06:57 +0000 Subject: port latest changes from SAMBA_3_0 tree (This used to be commit 3101c236b8241dc0183995ffceed551876427de4) --- source3/Makefile.in | 79 +- source3/aclocal.m4 | 107 ++ source3/auth/auth.c | 2 +- source3/auth/auth_domain.c | 4 +- source3/auth/auth_ntlmssp.c | 1 - source3/auth/auth_sam.c | 12 +- source3/auth/auth_util.c | 8 +- source3/client/client.c | 38 +- source3/client/clitar.c | 2550 +++++++++++++++++------------------ source3/client/smbspool.c | 2 +- source3/client/tree.c | 6 +- source3/configure.in | 418 +++--- source3/dynconfig.c | 2 +- source3/groupdb/mapping.c | 2 +- source3/include/authdata.h | 2 +- source3/include/byteorder.h | 2 +- source3/include/charset.h | 6 +- source3/include/client.h | 12 - source3/include/dynconfig.h | 2 +- source3/include/idmap.h | 2 +- source3/include/includes.h | 12 +- source3/include/popt_common.h | 1 + source3/include/rpc_ds.h | 62 +- source3/include/rpc_samr.h | 3 +- source3/include/rpc_secdes.h | 20 +- source3/include/smb.h | 26 +- source3/include/smbldap.h | 3 + source3/include/sysquotas.h | 16 + source3/include/version.h | 2 +- source3/include/vfs.h | 3 + source3/lib/account_pol.c | 2 +- source3/lib/charcnv.c | 120 +- source3/lib/popt_common.c | 25 +- source3/lib/replace.c | 18 - source3/lib/smbldap.c | 48 +- source3/lib/snprintf.c | 6 +- source3/lib/substitute.c | 4 +- source3/lib/sysquotas.c | 234 +++- source3/lib/username.c | 4 +- source3/lib/util.c | 4 +- source3/lib/util_file.c | 4 +- source3/lib/util_sock.c | 184 +-- source3/lib/util_str.c | 67 +- source3/lib/util_unistr.c | 76 -- source3/lib/util_uuid.c | 2 +- source3/libads/authdata.c | 2 +- source3/libads/kerberos_verify.c | 52 +- source3/libads/ldap.c | 94 +- source3/libads/ldap_printer.c | 2 +- source3/libads/ldap_user.c | 2 +- source3/libads/sasl.c | 3 +- source3/libsmb/asn1.c | 6 +- source3/libsmb/cliconnect.c | 34 +- source3/libsmb/clientgen.c | 27 +- source3/libsmb/clierror.c | 5 +- source3/libsmb/clikrb5.c | 36 +- source3/libsmb/clilist.c | 45 +- source3/libsmb/cliprint.c | 12 +- source3/libsmb/clispnego.c | 8 +- source3/libsmb/clitrans.c | 96 +- source3/libsmb/errormap.c | 1 + source3/libsmb/nmblib.c | 14 +- source3/libsmb/ntlmssp.c | 4 +- source3/libsmb/ntlmssp_parse.c | 2 +- source3/libsmb/ntlmssp_sign.c | 14 +- source3/libsmb/smb_signing.c | 730 ++++++++-- source3/libsmb/trustdom_cache.c | 2 +- source3/libsmb/trusts_util.c | 2 +- source3/locking/locking.c | 10 +- source3/nmbd/nmbd_processlogon.c | 3 +- source3/nsswitch/wb_common.c | 2 + source3/nsswitch/wbinfo.c | 2 +- source3/nsswitch/winbindd.c | 34 +- source3/nsswitch/winbindd.h | 2 +- source3/nsswitch/winbindd_acct.c | 63 +- source3/nsswitch/winbindd_ads.c | 85 +- source3/nsswitch/winbindd_cache.c | 8 +- source3/nsswitch/winbindd_cm.c | 39 +- source3/nsswitch/winbindd_group.c | 26 +- source3/nsswitch/winbindd_misc.c | 18 +- source3/nsswitch/winbindd_pam.c | 55 +- source3/nsswitch/winbindd_sid.c | 24 +- source3/nsswitch/winbindd_user.c | 24 +- source3/nsswitch/winbindd_util.c | 85 +- source3/nsswitch/winbindd_wins.c | 4 +- source3/nsswitch/wins.c | 48 +- source3/param/loadparm.c | 850 ++++++------ source3/passdb/passdb.c | 10 +- source3/passdb/pdb_get_set.c | 9 + source3/passdb/pdb_ldap.c | 60 +- source3/passdb/pdb_smbpasswd.c | 21 +- source3/passdb/pdb_tdb.c | 61 +- source3/passdb/secrets.c | 6 +- source3/printing/notify.c | 8 +- source3/printing/pcap.c | 4 +- source3/python/py_common.c | 2 +- source3/python/py_lsa.c | 27 +- source3/python/py_ntsec.c | 39 +- source3/python/py_smb.c | 42 +- source3/python/py_winbind.c | 6 +- source3/rpc_client/cli_ds.c | 68 +- source3/rpc_client/cli_lsarpc.c | 3 - source3/rpc_client/cli_netlogon.c | 3 +- source3/rpc_client/cli_pipe.c | 72 +- source3/rpc_client/cli_srvsvc.c | 2 +- source3/rpc_parse/parse_ds.c | 190 ++- source3/rpc_parse/parse_lsa.c | 145 +- source3/rpc_parse/parse_prs.c | 4 +- source3/rpc_parse/parse_samr.c | 3 +- source3/rpc_server/srv_dfs.c | 2 +- source3/rpc_server/srv_lsa.c | 3 +- source3/rpc_server/srv_lsa_nt.c | 2 +- source3/rpc_server/srv_netlog.c | 2 +- source3/rpc_server/srv_netlog_nt.c | 2 +- source3/rpc_server/srv_pipe.c | 7 +- source3/rpc_server/srv_reg.c | 2 +- source3/rpc_server/srv_reg_nt.c | 6 +- source3/rpc_server/srv_samr.c | 3 +- source3/rpc_server/srv_samr_nt.c | 34 +- source3/rpc_server/srv_spoolss.c | 2 +- source3/rpc_server/srv_spoolss_nt.c | 34 +- source3/rpc_server/srv_srvsvc.c | 2 +- source3/rpc_server/srv_wkssvc.c | 2 +- source3/rpcclient/cmd_ds.c | 22 +- source3/rpcclient/cmd_samr.c | 2 +- source3/rpcclient/rpcclient.c | 86 +- source3/sam/idmap.c | 7 +- source3/sam/idmap_tdb.c | 28 +- source3/sam/idmap_util.c | 8 +- source3/smbd/blocking.c | 498 +++---- source3/smbd/change_trust_pw.c | 2 +- source3/smbd/chgpasswd.c | 15 +- source3/smbd/close.c | 4 +- source3/smbd/ipc.c | 11 +- source3/smbd/lanman.c | 112 +- source3/smbd/mangle_hash.c | 7 +- source3/smbd/negprot.c | 20 + source3/smbd/notify.c | 6 +- source3/smbd/ntquotas.c | 2 +- source3/smbd/nttrans.c | 7 + source3/smbd/open.c | 24 +- source3/smbd/oplock.c | 14 +- source3/smbd/password.c | 56 +- source3/smbd/process.c | 671 +++++---- source3/smbd/reply.c | 58 +- source3/smbd/service.c | 2 +- source3/smbd/sesssetup.c | 71 +- source3/smbd/statcache.c | 33 +- source3/smbd/trans2.c | 16 +- source3/smbd/utmp.c | 4 +- source3/tdb/tdbtool.c | 73 +- source3/torture/cmd_vfs.c | 9 +- source3/torture/locktest.c | 2 +- source3/torture/locktest2.c | 4 +- source3/torture/mangle_test.c | 2 +- source3/torture/nsstest.c | 18 +- source3/torture/torture.c | 8 +- source3/utils/net.c | 32 +- source3/utils/net_ads.c | 8 +- source3/utils/net_cache.c | 2 +- source3/utils/net_idmap.c | 9 +- source3/utils/net_rpc_samsync.c | 13 +- source3/utils/net_time.c | 4 +- source3/utils/ntlm_auth.c | 509 ++++++- source3/utils/pdbedit.c | 22 +- source3/utils/smbcacls.c | 3 +- source3/utils/smbcontrol.c | 6 - source3/utils/smbcquotas.c | 3 +- source3/utils/smbpasswd.c | 15 - source3/utils/status.c | 5 - source3/web/statuspage.c | 2 +- source3/web/swat.c | 56 +- 172 files changed, 6162 insertions(+), 4095 deletions(-) (limited to 'source3') diff --git a/source3/Makefile.in b/source3/Makefile.in index 73ff436c6f..4674fd07ae 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -3,7 +3,7 @@ # Copyright Andrew Tridgell 1992-1998 # Copyright (C) 2001 by Martin Pool # Copyright Andrew Bartlett 2002 -# Copyright (C) 2003 Anthony Liguori +# Copyright (C) 2003 Jim McDonough # Copyright (C) 2002-2003 Jelmer Vernooij ########################################################################### @@ -32,7 +32,6 @@ AUTHLIBS=@AUTHLIBS@ ACLLIBS=@ACLLIBS@ PASSDBLIBS=@PASSDBLIBS@ IDMAP_LIBS=@IDMAP_LIBS@ -ADSLIBS=@ADSLIBS@ KRB5LIBS=@KRB5_LIBS@ LDAPLIBS=@LDAP_LIBS@ @@ -165,7 +164,7 @@ SMBLDAP_OBJ = @SMBLDAP@ 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/interfaces.o lib/pidfile.o lib/replace.o lib/replace1.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 \ @@ -176,7 +175,7 @@ LIB_OBJ = lib/charcnv.o lib/debug.o lib/fault.o \ lib/util.o lib/util_sock.o lib/sock_exec.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/messages.o \ - lib/tallocmsg.o lib/dmallocmsg.o \ + lib/tallocmsg.o lib/dmallocmsg.o libsmb/smb_signing.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 \ @@ -216,7 +215,7 @@ LIBSMB_OBJ = libsmb/clientgen.o libsmb/cliconnect.o libsmb/clifile.o \ libsmb/clirap.o libsmb/clierror.o libsmb/climessage.o \ libsmb/clireadwrite.o libsmb/clilist.o libsmb/cliprint.o \ libsmb/clitrans.o libsmb/clisecdesc.o libsmb/clidgram.o \ - libsmb/clistr.o libsmb/smb_signing.o \ + libsmb/clistr.o \ libsmb/cliquota.o libsmb/clifsinfo.o \ libsmb/smberr.o libsmb/credentials.o libsmb/pwd_cache.o \ libsmb/clioplock.o libsmb/errormap.o libsmb/clirap2.o \ @@ -300,6 +299,7 @@ VFS_EXTD_AUDIT_OBJ = modules/vfs_extd_audit.o VFS_FAKE_PERMS_OBJ = modules/vfs_fake_perms.o VFS_RECYCLE_OBJ = modules/vfs_recycle.o VFS_NETATALK_OBJ = modules/vfs_netatalk.o +VFS_DEFAULT_QUOTA_OBJ = modules/vfs_default_quota.o PLAINTEXT_AUTH_OBJ = auth/pampass.o auth/pass_check.o @@ -389,17 +389,18 @@ SWAT_OBJ1 = web/cgi.o web/diagnose.o web/startstop.o web/statuspage.o \ SWAT_OBJ = $(SWAT_OBJ1) $(PARAM_OBJ) $(PRINTING_OBJ) $(LIBSMB_OBJ) \ $(LOCKING_OBJ) $(PASSDB_OBJ) $(SECRETS_OBJ) $(KRBCLIENT_OBJ) \ $(UBIQX_OBJ) $(LIB_OBJ) $(GROUPDB_OBJ) $(PLAINTEXT_AUTH_OBJ) \ - $(POPT_LIB_OBJ) $(SMBLDAP_OBJ) + $(POPT_LIB_OBJ) $(SMBLDAP_OBJ) lib/dummyroot.o SMBSH_OBJ = smbwrapper/smbsh.o smbwrapper/shared.o \ $(PARAM_OBJ) $(UBIQX_OBJ) $(LIB_OBJ) STATUS_OBJ = utils/status.o $(LOCKING_OBJ) $(PARAM_OBJ) \ - $(UBIQX_OBJ) $(PROFILE_OBJ) $(LIB_OBJ) $(POPT_LIB_OBJ) + $(UBIQX_OBJ) $(PROFILE_OBJ) $(LIB_OBJ) $(POPT_LIB_OBJ) \ + lib/dummyroot.o libsmb/errormap.o SMBCONTROL_OBJ = utils/smbcontrol.o $(LOCKING_OBJ) $(PARAM_OBJ) \ $(UBIQX_OBJ) $(PROFILE_OBJ) $(LIB_OBJ) $(POPT_LIB_OBJ) \ - printing/notify.o printing/printing_db.o + printing/notify.o printing/printing_db.o lib/dummyroot.o libsmb/errormap.o SMBTREE_OBJ = utils/smbtree.o $(LOCKING_OBJ) $(PARAM_OBJ) \ $(UBIQX_OBJ) $(PROFILE_OBJ) $(LIB_OBJ) $(LIBSMB_OBJ) \ @@ -414,11 +415,11 @@ TESTPRNS_OBJ = utils/testprns.o $(PARAM_OBJ) $(PRINTING_OBJ) $(UBIQX_OBJ) \ SMBPASSWD_OBJ = utils/smbpasswd.o $(PARAM_OBJ) $(SECRETS_OBJ) \ $(LIBSMB_OBJ) $(PASSDB_OBJ) $(GROUPDB_OBJ)\ $(UBIQX_OBJ) $(LIB_OBJ) $(KRBCLIENT_OBJ) \ - $(SMBLDAP_OBJ) + $(SMBLDAP_OBJ) lib/dummyroot.o PDBEDIT_OBJ = utils/pdbedit.o $(PARAM_OBJ) $(PASSDB_OBJ) $(LIBSAMBA_OBJ) \ $(UBIQX_OBJ) $(LIB_OBJ) $(GROUPDB_OBJ) $(SECRETS_OBJ) \ - $(POPT_LIB_OBJ) $(SMBLDAP_OBJ) + $(POPT_LIB_OBJ) $(SMBLDAP_OBJ) lib/dummyroot.o RPCCLIENT_OBJ1 = rpcclient/rpcclient.o rpcclient/cmd_lsarpc.o \ rpcclient/cmd_samr.o rpcclient/cmd_spoolss.o \ @@ -432,9 +433,9 @@ RPCCLIENT_OBJ = $(RPCCLIENT_OBJ1) \ $(RPC_PARSE_OBJ) $(PASSDB_OBJ) $(LIBMSRPC_OBJ) \ $(READLINE_OBJ) $(GROUPDB_OBJ) $(KRBCLIENT_OBJ) \ $(LIBADS_OBJ) $(SECRETS_OBJ) $(POPT_LIB_OBJ) \ - $(SMBLDAP_OBJ) $(DCUTIL_OBJ) + $(SMBLDAP_OBJ) $(DCUTIL_OBJ) lib/dummyroot.o -PAM_WINBIND_OBJ = nsswitch/pam_winbind.po nsswitch/wb_common.po lib/snprintf.po +PAM_WINBIND_OBJ = nsswitch/pam_winbind.po nsswitch/wb_common.po lib/replace1.po lib/snprintf.po SMBW_OBJ1 = smbwrapper/smbw.o \ smbwrapper/smbw_dir.o smbwrapper/smbw_stat.o \ @@ -460,7 +461,7 @@ LIBBIGBALLOFMUD_MAJOR = 0 LIBBIGBALLOFMUD_OBJ = $(PARAM_OBJ) $(LIB_OBJ) $(UBIQX_OBJ) $(SECRETS_OBJ) \ $(LIBSMB_OBJ) $(LIBMSRPC_OBJ) $(RPC_PARSE_OBJ) $(PASSDB_OBJ) \ - $(GROUPDB_OBJ) $(KRBCLIENT_OBJ) $(SMBLDAP_OBJ) + $(GROUPDB_OBJ) $(KRBCLIENT_OBJ) $(SMBLDAP_OBJ) lib/dummyroot.o LIBBIGBALLOFMUD_PICOBJS = $(LIBBIGBALLOFMUD_OBJ:.o=.po) @@ -480,7 +481,7 @@ NET_OBJ = $(NET_OBJ1) $(PARAM_OBJ) $(SECRETS_OBJ) $(LIBSMB_OBJ) \ $(KRBCLIENT_OBJ) $(UBIQX_OBJ) $(LIB_OBJ) \ $(LIBMSRPC_OBJ) $(IDMAP_OBJ) \ $(LIBADS_OBJ) $(LIBADS_SERVER_OBJ) $(POPT_LIB_OBJ) \ - $(SMBLDAP_OBJ) $(DCUTIL_OBJ) + $(SMBLDAP_OBJ) $(DCUTIL_OBJ) lib/dummyroot.o lib/server_mutex.o CUPS_OBJ = client/smbspool.o $(PARAM_OBJ) $(LIBSMB_OBJ) $(UBIQX_OBJ) \ $(LIB_OBJ) $(KRBCLIENT_OBJ) @@ -559,7 +560,7 @@ PROTO_OBJ = $(SMBD_OBJ_MAIN) \ $(LIB_SMBD_OBJ) $(SAM_OBJ) $(REGISTRY_OBJ) $(POPT_LIB_OBJ) \ $(RPC_LSA_OBJ) $(RPC_NETLOG_OBJ) $(RPC_SAMR_OBJ) $(RPC_REG_OBJ) \ $(RPC_SVC_OBJ) $(RPC_WKS_OBJ) $(RPC_DFS_OBJ) $(RPC_SPOOLSS_OBJ) \ - $(RPC_ECHO_OBJ) $(SMBLDAP_OBJ) $(IDMAP_OBJ) + $(RPC_ECHO_OBJ) $(SMBLDAP_OBJ) $(IDMAP_OBJ) libsmb/spnego.o WINBIND_WINS_NSS_OBJ = nsswitch/wins.o $(PARAM_OBJ) $(UBIQX_OBJ) \ $(LIBSMB_OBJ) $(LIB_OBJ) $(NSSWINS_OBJ) @@ -601,21 +602,22 @@ WINBINDD_OBJ = \ $(LIBSMB_OBJ) $(LIBMSRPC_OBJ) $(RPC_PARSE_OBJ) \ $(PROFILE_OBJ) $(SLCACHE_OBJ) $(SMBLDAP_OBJ) \ $(SECRETS_OBJ) $(LIBADS_OBJ) $(KRBCLIENT_OBJ) $(POPT_LIB_OBJ) \ - $(DCUTIL_OBJ) $(IDMAP_OBJ) + $(DCUTIL_OBJ) $(IDMAP_OBJ) lib/dummyroot.o WBINFO_OBJ = nsswitch/wbinfo.o $(LIBSAMBA_OBJ) $(PARAM_OBJ) $(LIB_OBJ) \ $(UBIQX_OBJ) $(SECRETS_OBJ) $(POPT_LIB_OBJ) -WINBIND_NSS_OBJ = nsswitch/wb_common.o @WINBIND_NSS_EXTRA_OBJS@ +WINBIND_NSS_OBJ = nsswitch/wb_common.o lib/replace1.o @WINBIND_NSS_EXTRA_OBJS@ -WINBIND_NSS_PICOBJS = $(WINBIND_NSS_OBJ:.o=.po) +WINBIND_NSS_PICOBJS = $(WINBIND_NSS_OBJ:.o=.po) lib/snprintf.po POPT_OBJS=popt/findme.o popt/popt.o popt/poptconfig.o \ popt/popthelp.o popt/poptparse.o TDBBACKUP_OBJ = tdb/tdbbackup.o tdb/tdbback.o $(TDBBASE_OBJ) -NTLM_AUTH_OBJ = utils/ntlm_auth.o $(LIBSAMBA_OBJ) $(POPT_LIB_OBJ) +NTLM_AUTH_OBJ = utils/ntlm_auth.o $(LIBSAMBA_OBJ) $(POPT_LIB_OBJ) \ + libsmb/asn1.o libsmb/spnego.o ###################################################################### # now the rules... @@ -727,12 +729,12 @@ bin/.dummy: bin/smbd@EXEEXT@: $(SMBD_OBJ) @BUILD_POPT@ bin/.dummy @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(SMBD_OBJ) $(ADSLIBS) $(LDFLAGS) $(DYNEXP) $(PRINTLIBS) \ + @$(CC) $(FLAGS) -o $@ $(SMBD_OBJ) $(KRB5LIBS) $(LDAPLIBS) $(LDFLAGS) $(DYNEXP) $(PRINTLIBS) \ $(AUTHLIBS) $(ACLLIBS) $(PASSDBLIBS) $(LIBS) @POPTLIBS@ bin/nmbd@EXEEXT@: $(NMBD_OBJ) @BUILD_POPT@ bin/.dummy @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(NMBD_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) @POPTLIBS@ $(ADSLIBS) + @$(CC) $(FLAGS) -o $@ $(NMBD_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAPLIBS) bin/wrepld@EXEEXT@: $(WREPL_OBJ) @BUILD_POPT@ bin/.dummy @echo Linking $@ @@ -741,19 +743,19 @@ bin/wrepld@EXEEXT@: $(WREPL_OBJ) @BUILD_POPT@ bin/.dummy bin/swat@EXEEXT@: $(SWAT_OBJ) @BUILD_POPT@ bin/.dummy @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(SWAT_OBJ) $(LDFLAGS) $(DYNEXP) $(PRINTLIBS) \ - $(AUTHLIBS) $(LIBS) $(PASSDBLIBS) @POPTLIBS@ $(KRB5LIBS) + $(AUTHLIBS) $(LIBS) $(PASSDBLIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAPLIBS) bin/rpcclient@EXEEXT@: $(RPCCLIENT_OBJ) @BUILD_POPT@ bin/.dummy @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(PASSDBLIBS) $(RPCCLIENT_OBJ) $(LDFLAGS) $(DYNEXP) $(TERMLDFLAGS) $(TERMLIBS) $(LIBS) @POPTLIBS@ $(ADSLIBS) + @$(CC) $(FLAGS) -o $@ $(PASSDBLIBS) $(RPCCLIENT_OBJ) $(LDFLAGS) $(DYNEXP) $(TERMLDFLAGS) $(TERMLIBS) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAPLIBS) bin/smbclient@EXEEXT@: $(CLIENT_OBJ) @BUILD_POPT@ bin/.dummy @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(CLIENT_OBJ) $(LDFLAGS) $(DYNEXP) $(TERMLDFLAGS) $(TERMLIBS) $(LIBS) @POPTLIBS@ $(ADSLIBS) + @$(CC) $(FLAGS) -o $@ $(CLIENT_OBJ) $(LDFLAGS) $(DYNEXP) $(TERMLDFLAGS) $(TERMLIBS) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAPLIBS) bin/net@EXEEXT@: $(NET_OBJ) @BUILD_POPT@ bin/.dummy @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(NET_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) @POPTLIBS@ $(ADSLIBS) $(PASSDBLIBS) + @$(CC) $(FLAGS) -o $@ $(NET_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAPLIBS) $(PASSDBLIBS) bin/profiles@EXEEXT@: $(PROFILES_OBJ) @BUILD_POPT@ bin/.dummy @echo Linking $@ @@ -801,7 +803,7 @@ bin/smbtree@EXEEXT@: $(SMBTREE_OBJ) @BUILD_POPT@ bin/.dummy bin/smbpasswd@EXEEXT@: $(SMBPASSWD_OBJ) bin/.dummy @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(SMBPASSWD_OBJ) $(PASSDBLIBS) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) + @$(CC) $(FLAGS) -o $@ $(SMBPASSWD_OBJ) $(PASSDBLIBS) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAPLIBS) bin/pdbedit@EXEEXT@: $(PDBEDIT_OBJ) @BUILD_POPT@ bin/.dummy @echo Linking $@ @@ -873,7 +875,7 @@ bin/smbfilter@EXEEXT@: $(SMBFILTER_OBJ) bin/.dummy bin/smbw_sample@EXEEXT@: $(SMBW_OBJ) utils/smbw_sample.o bin/.dummy @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(SMBW_OBJ) utils/smbw_sample.o $(LDFLAGS) $(LIBS) $(KRB5LIBS) + @$(CC) $(FLAGS) -o $@ $(SMBW_OBJ) utils/smbw_sample.o $(LDFLAGS) $(LIBS) $(KRB5LIBS) $(LDAPLIBS) bin/smbsh@EXEEXT@: $(SMBSH_OBJ) bin/.dummy @echo Linking $@ @@ -882,12 +884,14 @@ bin/smbsh@EXEEXT@: $(SMBSH_OBJ) bin/.dummy bin/smbwrapper.@SHLIBEXT@: $(PICOBJS) bin/.dummy @echo Linking shared library $@ @$(SHLD) $(LDSHFLAGS) -o $@ $(PICOBJS) $(LIBS) \ - @SONAMEFLAG@`basename $@` $(KRB5LIBS) + $(KRB5LIBS) $(LDAPLIBS) \ + @SONAMEFLAG@`basename $@` bin/libsmbclient.@SHLIBEXT@: $(LIBSMBCLIENT_PICOBJS) @echo Linking libsmbclient shared library $@ @$(SHLD) $(LDSHFLAGS) -o $@ $(LIBSMBCLIENT_PICOBJS) $(LDFLAGS) $(LIBS) \ - $(KRB5LIBS) @SONAMEFLAG@`basename $@`.$(LIBSMBCLIENT_MAJOR) + $(KRB5LIBS) $(LDAPLIBS) \ + @SONAMEFLAG@`basename $@`.$(LIBSMBCLIENT_MAJOR) bin/libsmbclient.a: $(LIBSMBCLIENT_PICOBJS) @echo Linking libsmbclient non-shared library $@ @@ -897,7 +901,8 @@ bin/libsmbclient.a: $(LIBSMBCLIENT_PICOBJS) bin/libbigballofmud.@SHLIBEXT@: $(LIBBIGBALLOFMUD_PICOBJS) @echo Linking bigballofmud shared library $@ @$(SHLD) $(LDSHFLAGS) -o $@ $(LIBBIGBALLOFMUD_PICOBJS) $(LIBS) \ - @SONAMEFLAG@`basename $@`.$(LIBBIGBALLOFMUD_MAJOR) $(PASSDBLIBS) $(IDMAP_LIBS) $(ADSLIBS) + $(PASSDBLIBS) $(IDMAP_LIBS) $(KRB5LIBS) $(LDAPLIBS) \ + @SONAMEFLAG@`basename $@`.$(LIBBIGBALLOFMUD_MAJOR) ln -snf libbigballofmud.so bin/libbigballofmud.so.0 # It would be nice to build a static bigballofmud too, but when I try @@ -963,7 +968,8 @@ bin/winbindd@EXEEXT@: $(WINBINDD_OBJ) @BUILD_POPT@ bin/.dummy @WINBIND_WINS_NSS@: $(WINBIND_WINS_NSS_PICOBJS) @echo "Linking $@" - @$(SHLD) $(LDSHFLAGS) -o $@ $(WINBIND_WINS_NSS_PICOBJS) -lc \ + @$(SHLD) $(LDSHFLAGS) -o $@ $(WINBIND_WINS_NSS_PICOBJS) \ + $(KRBCLIENT_OBJ) $(LDAPLIBS) $(KRB5LIBS) -lc \ @SONAMEFLAG@`basename $@` nsswitch/pam_winbind.@SHLIBEXT@: $(PAM_WINBIND_OBJ) bin/.dummy @@ -1054,6 +1060,11 @@ bin/fake_perms.@SHLIBEXT@: $(VFS_FAKE_PERMS_OBJ:.o=.po) @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_FAKE_PERMS_OBJ:.o=.po) \ @SONAMEFLAG@`basename $@` +bin/default_quota.@SHLIBEXT@: $(VFS_DEFAULT_QUOTA_OBJ:.o=.po) + @echo "Building plugin $@" + @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_DEFAULT_QUOTA_OBJ:.o=.po) \ + @SONAMEFLAG@`basename $@` + bin/wbinfo@EXEEXT@: $(WBINFO_OBJ) @BUILD_POPT@ bin/.dummy @echo Linking $@ @$(LINK) -o $@ $(WBINFO_OBJ) $(LIBS) @POPTLIBS@ @@ -1138,7 +1149,7 @@ installclientlib: installdirs libsmbclient PYTHON_OBJS = $(PARAM_OBJ) $(LIB_OBJ) $(LIBSMB_OBJ) $(RPC_PARSE_OBJ) \ $(UBIQX_OBJ) $(LIBMSRPC_OBJ) $(PASSDB_OBJ) $(GROUPDB_OBJ) \ - $(SECRETS_OBJ) $(KRBCLIENT_OBJ) + $(SECRETS_OBJ) $(KRBCLIENT_OBJ) $(SMBLDAP_OBJ) lib/dummyroot.o PYTHON_PICOBJS = $(PYTHON_OBJS:.o=.po) @@ -1149,7 +1160,7 @@ python_ext: $(PYTHON_PICOBJS) fi PYTHON_OBJS="$(PYTHON_PICOBJS)" \ PYTHON_CFLAGS="$(CFLAGS) $(CPPFLAGS) $(FLAGS)" \ - LIBS="$(LIBS) $(PASSDBLIBS) $(IDMAP_LIBS) $(KRB5LIBS)" \ + LIBS="$(LIBS) $(PASSDBLIBS) $(IDMAP_LIBS) $(KRB5LIBS) $(LDAPLIBS)" \ $(PYTHON) python/setup.py build python_install: $(PYTHON_PICOBJS) @@ -1185,7 +1196,7 @@ showlayout: @echo " mandir: $(MANDIR)" -uninstall: uninstallman uninstallbin uninstallscripts +uninstall: uninstallman uninstallbin uninstallscripts uninstallmodules uninstallman: @$(SHELL) $(srcdir)/script/uninstallman.sh $(DESTDIR)$(MANDIR) $(srcdir) $(man_langs) diff --git a/source3/aclocal.m4 b/source3/aclocal.m4 index 21358e2a71..3a49f7e249 100644 --- a/source3/aclocal.m4 +++ b/source3/aclocal.m4 @@ -111,6 +111,113 @@ AC_DEFUN(AC_LIBTESTFUNC, esac ]) +# AC_CHECK_LIB_EXT(LIBRARY, [EXT_LIBS], [FUNCTION], +# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND], +# [ADD-ACTION-IF-FOUND],[OTHER-LIBRARIES]) +# ------------------------------------------------------ +# +# Use a cache variable name containing both the library and function name, +# because the test really is for library $1 defining function $3, not +# just for library $1. Separate tests with the same $1 and different $3s +# may have different results. +# +# Note that using directly AS_VAR_PUSHDEF([ac_Lib], [ac_cv_lib_$1_$3]) +# is asking for troubles, since AC_CHECK_LIB($lib, fun) would give +# ac_cv_lib_$lib_fun, which is definitely not what was meant. Hence +# the AS_LITERAL_IF indirection. +# +# FIXME: This macro is extremely suspicious. It DEFINEs unconditionnally, +# whatever the FUNCTION, in addition to not being a *S macro. Note +# that the cache does depend upon the function we are looking for. +# +# It is on purpose we used `ac_check_lib_ext_save_LIBS' and not just +# `ac_save_LIBS': there are many macros which don't want to see `LIBS' +# changed but still want to use AC_CHECK_LIB_EXT, so they save `LIBS'. +# And ``ac_save_LIBS' is too tempting a name, so let's leave them some +# freedom. +AC_DEFUN([AC_CHECK_LIB_EXT], +[ +AH_CHECK_LIB_EXT([$1]) +ac_check_lib_ext_save_LIBS=$LIBS +LIBS="-l$1 $$2 $7 $LIBS" +AS_LITERAL_IF([$1], + [AS_VAR_PUSHDEF([ac_Lib_ext], [ac_cv_lib_ext_$1])], + [AS_VAR_PUSHDEF([ac_Lib_ext], [ac_cv_lib_ext_$1''])])dnl + +m4_ifval([$3], + [ + AH_CHECK_FUNC_EXT([$3]) + AS_LITERAL_IF([$1], + [AS_VAR_PUSHDEF([ac_Lib_func], [ac_cv_lib_ext_$1_$3])], + [AS_VAR_PUSHDEF([ac_Lib_func], [ac_cv_lib_ext_$1''_$3])])dnl + AC_CACHE_CHECK([for $3 in -l$1], ac_Lib_func, + [AC_TRY_LINK_FUNC($3, + [AS_VAR_SET(ac_Lib_func, yes); + AS_VAR_SET(ac_Lib_ext, yes)], + [AS_VAR_SET(ac_Lib_func, no); + AS_VAR_SET(ac_Lib_ext, no)]) + ]) + AS_IF([test AS_VAR_GET(ac_Lib_func) = yes], + [AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_$3))])dnl + AS_VAR_POPDEF([ac_Lib_func])dnl + ],[ + AC_CACHE_CHECK([for -l$1], ac_Lib_ext, + [AC_TRY_LINK_FUNC([main], + [AS_VAR_SET(ac_Lib_ext, yes)], + [AS_VAR_SET(ac_Lib_ext, no)]) + ]) + ]) +LIBS=$ac_check_lib_ext_save_LIBS + +AS_IF([test AS_VAR_GET(ac_Lib_ext) = yes], + [m4_default([$4], + [AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_LIB$1)) + case "$$2" in + *-l$1*) + ;; + *) + $2="$$2 -l$1" + ;; + esac]) + [$6] + ], + [$5])dnl +AS_VAR_POPDEF([ac_Lib_ext])dnl +])# AC_CHECK_LIB_EXT + +# AH_CHECK_LIB_EXT(LIBNAME) +# --------------------- +m4_define([AH_CHECK_LIB_EXT], +[AH_TEMPLATE(AS_TR_CPP(HAVE_LIB$1), + [Define to 1 if you have the `]$1[' library (-l]$1[).])]) + +# AC_CHECK_FUNCS_EXT(FUNCTION, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +# ----------------------------------------------------------------- +dnl check for a function in a $LIBS and $OTHER_LIBS libraries variable. +dnl AC_CHECK_FUNC_EXT(func,OTHER_LIBS,IF-TRUE,IF-FALSE) +AC_DEFUN([AC_CHECK_FUNC_EXT], +[ + AH_CHECK_FUNC_EXT($1) + ac_check_func_ext_save_LIBS=$LIBS + LIBS="$2 $LIBS" + AS_VAR_PUSHDEF([ac_var], [ac_cv_func_ext_$1])dnl + AC_CACHE_CHECK([for $1], ac_var, + [AC_LINK_IFELSE([AC_LANG_FUNC_LINK_TRY([$1])], + [AS_VAR_SET(ac_var, yes)], + [AS_VAR_SET(ac_var, no)])]) + LIBS=$ac_check_func_ext_save_LIBS + AS_IF([test AS_VAR_GET(ac_var) = yes], + [AC_DEFINE_UNQUOTED(AS_TR_CPP([HAVE_$1])) $3], + [$4])dnl +AS_VAR_POPDEF([ac_var])dnl +])# AC_CHECK_FUNC + +# AH_CHECK_FUNC_EXT(FUNCNAME) +# --------------------- +m4_define([AH_CHECK_FUNC_EXT], +[AH_TEMPLATE(AS_TR_CPP(HAVE_$1), + [Define to 1 if you have the `]$1[' function.])]) + dnl Define an AC_DEFINE with ifndef guard. dnl AC_N_DEFINE(VARIABLE [, VALUE]) define(AC_N_DEFINE, diff --git a/source3/auth/auth.c b/source3/auth/auth.c index a2486acbd1..8316c4b617 100644 --- a/source3/auth/auth.c +++ b/source3/auth/auth.c @@ -512,7 +512,7 @@ NTSTATUS make_auth_context_fixed(struct auth_context **auth_context, uchar chal[ return nt_status; } - (*auth_context)->challenge = data_blob(chal, 8); + (*auth_context)->challenge = data_blob_talloc((*auth_context)->mem_ctx, chal, 8); (*auth_context)->challenge_set_by = "fixed"; return nt_status; } diff --git a/source3/auth/auth_domain.c b/source3/auth/auth_domain.c index 56bd6b9aca..aacea261fe 100644 --- a/source3/auth/auth_domain.c +++ b/source3/auth/auth_domain.c @@ -69,7 +69,7 @@ static NTSTATUS connect_to_domain_password_server(struct cli_state **cli, /* Attempt connection */ *retry = True; result = cli_full_connection(cli, global_myname(), dc_name, &dc_ip, 0, - "IPC$", "IPC", "", "", "", 0, retry); + "IPC$", "IPC", "", "", "", 0, Undefined, retry); if (!NT_STATUS_IS_OK(result)) { /* map to something more useful */ @@ -104,7 +104,7 @@ machine %s. Error was : %s.\n", dc_name, cli_errstr(*cli))); return NT_STATUS_NO_LOGON_SERVERS; } - snprintf((*cli)->mach_acct, sizeof((*cli)->mach_acct) - 1, "%s$", setup_creds_as); + fstr_sprintf((*cli)->mach_acct, "%s$", setup_creds_as); if (!(*cli)->mach_acct) { release_server_mutex(); diff --git a/source3/auth/auth_ntlmssp.c b/source3/auth/auth_ntlmssp.c index a381219d74..3af0cbaada 100644 --- a/source3/auth/auth_ntlmssp.c +++ b/source3/auth/auth_ntlmssp.c @@ -135,4 +135,3 @@ NTSTATUS auth_ntlmssp_update(AUTH_NTLMSSP_STATE *auth_ntlmssp_state, { return ntlmssp_server_update(auth_ntlmssp_state->ntlmssp_state, request, reply); } - diff --git a/source3/auth/auth_sam.c b/source3/auth/auth_sam.c index 012696f46a..fb66d53cd4 100644 --- a/source3/auth/auth_sam.c +++ b/source3/auth/auth_sam.c @@ -44,12 +44,12 @@ static BOOL smb_pwd_check_ntlmv1(const DATA_BLOB *nt_response, } if (sec_blob->length != 8) { - DEBUG(0, ("smb_pwd_check_ntlmv1: incorrect challenge size (%d)\n", sec_blob->length)); + DEBUG(0, ("smb_pwd_check_ntlmv1: incorrect challenge size (%lu)\n", (unsigned long)sec_blob->length)); return False; } if (nt_response->length != 24) { - DEBUG(0, ("smb_pwd_check_ntlmv1: incorrect password length (%d)\n", nt_response->length)); + DEBUG(0, ("smb_pwd_check_ntlmv1: incorrect password length (%lu)\n", (unsigned long)nt_response->length)); return False; } @@ -103,8 +103,8 @@ static BOOL smb_pwd_check_ntlmv2(const DATA_BLOB *ntv2_response, /* We MUST have more than 16 bytes, or the stuff below will go crazy. No known implementation sends less than the 24 bytes for LMv2, let alone NTLMv2. */ - DEBUG(0, ("smb_pwd_check_ntlmv2: incorrect password length (%d)\n", - ntv2_response->length)); + DEBUG(0, ("smb_pwd_check_ntlmv2: incorrect password length (%lu)\n", + (unsigned long)ntv2_response->length)); return False; } @@ -233,8 +233,8 @@ static NTSTATUS sam_password_ok(const struct auth_context *auth_context, if (auth_flags & AUTH_FLAG_LM_RESP) { if (user_info->lm_resp.length != 24) { - DEBUG(2,("sam_password_ok: invalid LanMan password length (%d) for user %s\n", - user_info->nt_resp.length, pdb_get_username(sampass))); + DEBUG(2,("sam_password_ok: invalid LanMan password length (%lu) for user %s\n", + (unsigned long)user_info->nt_resp.length, pdb_get_username(sampass))); } if (!lp_lanman_auth()) { diff --git a/source3/auth/auth_util.c b/source3/auth/auth_util.c index 8e1b420b47..5403ee8c39 100644 --- a/source3/auth/auth_util.c +++ b/source3/auth/auth_util.c @@ -68,7 +68,7 @@ void auth_add_user_script(const char *domain, const char *username) * user on the fly, do so. */ - if ( lp_adduser_script() ) + if ( *lp_adduser_script() ) smb_create_user(domain, username, NULL); else { DEBUG(10,("auth_add_user_script: no 'add user script'. Asking winbindd\n")); @@ -133,7 +133,7 @@ static NTSTATUS 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))); + DEBUG(0,("malloc failed for user_info (size %lu)\n", (unsigned long)sizeof(*user_info))); return NT_STATUS_NO_MEMORY; } @@ -489,9 +489,9 @@ void debug_nt_user_token(int dbg_class, int dbg_lev, NT_USER_TOKEN *token) 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)); + DEBUGADDC(dbg_class, dbg_lev, ("contains %lu SIDs\n", (unsigned long)token->num_sids)); for (i = 0; i < token->num_sids; i++) - DEBUGADDC(dbg_class, dbg_lev, ("SID[%3i]: %s\n", i, + DEBUGADDC(dbg_class, dbg_lev, ("SID[%3lu]: %s\n", (unsigned long)i, sid_to_string(sid_str, &token->user_sids[i]))); } diff --git a/source3/client/client.c b/source3/client/client.c index d9c3a7aa1b..ec29f44e6e 100644 --- a/source3/client/client.c +++ b/source3/client/client.c @@ -438,7 +438,8 @@ static void add_to_do_list_queue(const char* entry) } if (do_list_queue) { - pstrcpy(do_list_queue + do_list_queue_end, entry); + safe_strcpy_base(do_list_queue + do_list_queue_end, + entry, do_list_queue, do_list_queue_size); do_list_queue_end = new_end; DEBUG(4,("added %s to do_list_queue (start=%d, end=%d)\n", entry, (int)do_list_queue_start, (int)do_list_queue_end)); @@ -481,6 +482,11 @@ static void do_list_helper(file_info *f, const char *mask, void *state) pstring mask2; char *p; + if (!f->name[0]) { + d_printf("Empty dir name returned. Possible server misconfiguration.\n"); + return; + } + pstrcpy(mask2, mask); p = strrchr_m(mask2,'\\'); if (!p) return; @@ -2285,9 +2291,9 @@ static char **remote_completion(const char *text, int len) if (i > 0) { strncpy(info.dirmask, text, i+1); info.dirmask[i+1] = 0; - snprintf(dirmask, sizeof(dirmask), "%s%*s*", cur_dir, i-1, text); + pstr_sprintf(dirmask, "%s%*s*", cur_dir, i-1, text); } else - snprintf(dirmask, sizeof(dirmask), "%s*", cur_dir); + pstr_sprintf(dirmask, "%s*", cur_dir); if (cli_list(cli, dirmask, aDIR | aSYSTEM | aHIDDEN, completion_remote_filter, &info) < 0) goto cleanup; @@ -2523,6 +2529,8 @@ static struct cli_state *do_connect(const char *server, const char *share) c->protocol = max_protocol; c->use_kerberos = use_kerberos; + cli_setup_signing_state(c, cmdline_auth_info.signing_state); + if (!cli_session_request(c, &calling, &called)) { char *p; @@ -2816,9 +2824,25 @@ static void remember_query_host(const char *arg, max_protocol = interpret_protocol(poptGetOptArg(pc), max_protocol); break; case 'T': - if (!tar_parseargs(argc, argv, poptGetOptArg(pc), optind)) { - poptPrintUsage(pc, stderr, 0); - exit(1); + /* We must use old option processing for this. Find the + * position of the -T option in the raw argv[]. */ + { + int i, optnum; + for (i = 1; i < argc; i++) { + if (strncmp("-T", argv[i],2)==0) + break; + } + i++; + if (!(optnum = tar_parseargs(argc, argv, poptGetOptArg(pc), i))) { + poptPrintUsage(pc, stderr, 0); + exit(1); + } + /* Now we must eat (optnum - i) options - they have + * been processed by tar_parseargs(). + */ + optnum -= i; + for (i = 0; i < optnum; i++) + poptGetOptArg(pc); } break; case 'D': @@ -2843,7 +2867,7 @@ static void remember_query_host(const char *arg, } } - if (poptPeekArg(pc)) { + if (poptPeekArg(pc) && !cmdline_auth_info.got_pass) { cmdline_auth_info.got_pass = True; pstrcpy(cmdline_auth_info.password,poptGetArg(pc)); } diff --git a/source3/client/clitar.c b/source3/client/clitar.c index 765bc2a659..5295de8010 100644 --- a/source3/client/clitar.c +++ b/source3/client/clitar.c @@ -43,27 +43,23 @@ static int clipfind(char **aret, int ret, char *tok); typedef struct file_info_struct file_info2; -struct file_info_struct -{ - SMB_BIG_UINT size; - uint16 mode; - uid_t uid; - gid_t gid; - /* These times are normally kept in GMT */ - time_t mtime; - time_t atime; - time_t ctime; - char *name; /* This is dynamically allocate */ - - file_info2 *next, *prev; /* Used in the stack ... */ - +struct file_info_struct { + SMB_BIG_UINT size; + uint16 mode; + uid_t uid; + gid_t gid; + /* These times are normally kept in GMT */ + time_t mtime; + time_t atime; + time_t ctime; + char *name; /* This is dynamically allocate */ + + file_info2 *next, *prev; /* Used in the stack ... */ }; -typedef struct -{ - file_info2 *top; - int items; - +typedef struct { + file_info2 *top; + int items; } stack; #define SEPARATORS " \t\n\r" @@ -145,285 +141,284 @@ static void unfixtarname(char *tptr, char *fp, int l, BOOL first); /******************************************************************* Create a string of size size+1 (for the null) *******************************************************************/ + static char *string_create_s(int size) { - char *tmp; + char *tmp; - tmp = (char *)malloc(size+1); + tmp = (char *)malloc(size+1); - if (tmp == NULL) { - - DEBUG(0, ("Out of memory in string_create_s\n")); - - } - - return(tmp); + if (tmp == NULL) { + DEBUG(0, ("Out of memory in string_create_s\n")); + } + return(tmp); } /**************************************************************************** Write a tar header to buffer ****************************************************************************/ + static void writetarheader(int f, const char *aname, SMB_BIG_UINT size, time_t mtime, const char *amode, unsigned char ftype) { - union hblock hb; - int i, chk, l; - char *jp; + union hblock hb; + int i, chk, l; + char *jp; - DEBUG(5, ("WriteTarHdr, Type = %c, Size= %.0f, Name = %s\n", ftype, (double)size, aname)); + DEBUG(5, ("WriteTarHdr, Type = %c, Size= %.0f, Name = %s\n", ftype, (double)size, aname)); - memset(hb.dummy, 0, sizeof(hb.dummy)); + memset(hb.dummy, 0, sizeof(hb.dummy)); - l=strlen(aname); - if (l >= NAMSIZ - 1) { - /* write a GNU tar style long header */ - char *b; - b = (char *)malloc(l+TBLOCK+100); - if (!b) { - DEBUG(0,("out of memory\n")); - exit(1); - } - writetarheader(f, "/./@LongLink", l+2, 0, " 0 \0", 'L'); - memset(b, 0, l+TBLOCK+100); - fixtarname(b, aname, l); - i = strlen(b)+1; - DEBUG(5, ("File name in tar file: %s, size=%d, \n", b, (int)strlen(b))); - dotarbuf(f, b, TBLOCK*(((i-1)/TBLOCK)+1)); - SAFE_FREE(b); - } - - /* use l + 1 to do the null too */ - fixtarname(hb.dbuf.name, aname, (l >= NAMSIZ) ? NAMSIZ : l + 1); - - if (lowercase) - strlower_m(hb.dbuf.name); - - /* write out a "standard" tar format header */ - - hb.dbuf.name[NAMSIZ-1]='\0'; - safe_strcpy(hb.dbuf.mode, amode, sizeof(hb.dbuf.mode)-1); - oct_it((SMB_BIG_UINT)0, 8, hb.dbuf.uid); - oct_it((SMB_BIG_UINT)0, 8, hb.dbuf.gid); - oct_it((SMB_BIG_UINT) size, 13, hb.dbuf.size); - if (size > (SMB_BIG_UINT)077777777777LL) { - - /* This is a non-POSIX compatible extention to store files - greater than 8GB. */ - - memset(hb.dbuf.size, 0, 4); - hb.dbuf.size[0]=128; - for (i = 8, jp=(char*)&size; i; i--) - hb.dbuf.size[i+3] = *(jp++); - } - oct_it((SMB_BIG_UINT) mtime, 13, hb.dbuf.mtime); - memcpy(hb.dbuf.chksum, " ", sizeof(hb.dbuf.chksum)); - memset(hb.dbuf.linkname, 0, NAMSIZ); - hb.dbuf.linkflag=ftype; + l=strlen(aname); + if (l >= NAMSIZ - 1) { + /* write a GNU tar style long header */ + char *b; + b = (char *)malloc(l+TBLOCK+100); + if (!b) { + DEBUG(0,("out of memory\n")); + exit(1); + } + writetarheader(f, "/./@LongLink", l+2, 0, " 0 \0", 'L'); + memset(b, 0, l+TBLOCK+100); + fixtarname(b, aname, l); + i = strlen(b)+1; + DEBUG(5, ("File name in tar file: %s, size=%d, \n", b, (int)strlen(b))); + dotarbuf(f, b, TBLOCK*(((i-1)/TBLOCK)+1)); + SAFE_FREE(b); + } + + /* use l + 1 to do the null too */ + fixtarname(hb.dbuf.name, aname, (l >= NAMSIZ) ? NAMSIZ : l + 1); + + if (lowercase) + strlower_m(hb.dbuf.name); + + /* write out a "standard" tar format header */ + + hb.dbuf.name[NAMSIZ-1]='\0'; + safe_strcpy(hb.dbuf.mode, amode, sizeof(hb.dbuf.mode)-1); + oct_it((SMB_BIG_UINT)0, 8, hb.dbuf.uid); + oct_it((SMB_BIG_UINT)0, 8, hb.dbuf.gid); + oct_it((SMB_BIG_UINT) size, 13, hb.dbuf.size); + if (size > (SMB_BIG_UINT)077777777777LL) { + + /* This is a non-POSIX compatible extention to store files + greater than 8GB. */ + + memset(hb.dbuf.size, 0, 4); + hb.dbuf.size[0]=128; + for (i = 8, jp=(char*)&size; i; i--) + hb.dbuf.size[i+3] = *(jp++); + } + oct_it((SMB_BIG_UINT) mtime, 13, hb.dbuf.mtime); + memcpy(hb.dbuf.chksum, " ", sizeof(hb.dbuf.chksum)); + memset(hb.dbuf.linkname, 0, NAMSIZ); + hb.dbuf.linkflag=ftype; - for (chk=0, i=sizeof(hb.dummy), jp=hb.dummy; --i>=0;) chk+=(0xFF & *jp++); + for (chk=0, i=sizeof(hb.dummy), jp=hb.dummy; --i>=0;) + chk+=(0xFF & *jp++); - oct_it((SMB_BIG_UINT) chk, 8, hb.dbuf.chksum); - hb.dbuf.chksum[6] = '\0'; + oct_it((SMB_BIG_UINT) chk, 8, hb.dbuf.chksum); + hb.dbuf.chksum[6] = '\0'; - (void) dotarbuf(f, hb.dummy, sizeof(hb.dummy)); + (void) dotarbuf(f, hb.dummy, sizeof(hb.dummy)); } /**************************************************************************** Read a tar header into a hblock structure, and validate ***************************************************************************/ + static long readtarheader(union hblock *hb, file_info2 *finfo, char *prefix) { - long chk, fchk; - int i; - char *jp; - - /* - * read in a "standard" tar format header - we're not that interested - * in that many fields, though - */ - - /* check the checksum */ - for (chk=0, i=sizeof(hb->dummy), jp=hb->dummy; --i>=0;) chk+=(0xFF & *jp++); + long chk, fchk; + int i; + char *jp; - if (chk == 0) - return chk; - - /* compensate for blanks in chksum header */ - for (i=sizeof(hb->dbuf.chksum), jp=hb->dbuf.chksum; --i>=0;) - chk-=(0xFF & *jp++); + /* + * read in a "standard" tar format header - we're not that interested + * in that many fields, though + */ - chk += ' ' * sizeof(hb->dbuf.chksum); + /* check the checksum */ + for (chk=0, i=sizeof(hb->dummy), jp=hb->dummy; --i>=0;) + chk+=(0xFF & *jp++); - fchk=unoct(hb->dbuf.chksum, sizeof(hb->dbuf.chksum)); + if (chk == 0) + return chk; - DEBUG(5, ("checksum totals chk=%ld fchk=%ld chksum=%s\n", - chk, fchk, hb->dbuf.chksum)); + /* compensate for blanks in chksum header */ + for (i=sizeof(hb->dbuf.chksum), jp=hb->dbuf.chksum; --i>=0;) + chk-=(0xFF & *jp++); - if (fchk != chk) - { - DEBUG(0, ("checksums don't match %ld %ld\n", fchk, chk)); - dump_data(5, (char *)hb - TBLOCK, TBLOCK *3); - return -1; - } + chk += ' ' * sizeof(hb->dbuf.chksum); - if ((finfo->name = string_create_s(strlen(prefix) + strlen(hb -> dbuf.name) + 3)) == NULL) { + fchk=unoct(hb->dbuf.chksum, sizeof(hb->dbuf.chksum)); - DEBUG(0, ("Out of space creating file_info2 for %s\n", hb -> dbuf.name)); - return(-1); + DEBUG(5, ("checksum totals chk=%ld fchk=%ld chksum=%s\n", + chk, fchk, hb->dbuf.chksum)); - } + if (fchk != chk) { + DEBUG(0, ("checksums don't match %ld %ld\n", fchk, chk)); + dump_data(5, (char *)hb - TBLOCK, TBLOCK *3); + return -1; + } - safe_strcpy(finfo->name, prefix, strlen(prefix) + strlen(hb -> dbuf.name) + 3); + if ((finfo->name = string_create_s(strlen(prefix) + strlen(hb -> dbuf.name) + 3)) == NULL) { + DEBUG(0, ("Out of space creating file_info2 for %s\n", hb -> dbuf.name)); + return(-1); + } - /* use l + 1 to do the null too; do prefix - prefcnt to zap leading slash */ - unfixtarname(finfo->name + strlen(prefix), hb->dbuf.name, - strlen(hb->dbuf.name) + 1, True); + safe_strcpy(finfo->name, prefix, strlen(prefix) + strlen(hb -> dbuf.name) + 3); + + /* use l + 1 to do the null too; do prefix - prefcnt to zap leading slash */ + unfixtarname(finfo->name + strlen(prefix), hb->dbuf.name, + strlen(hb->dbuf.name) + 1, True); + + /* can't handle some links at present */ + if ((hb->dbuf.linkflag != '0') && (hb -> dbuf.linkflag != '5')) { + if (hb->dbuf.linkflag == 0) { + DEBUG(6, ("Warning: NULL link flag (gnu tar archive ?) %s\n", + finfo->name)); + } else { + if (hb -> dbuf.linkflag == 'L') { /* We have a longlink */ + /* Do nothing here at the moment. do_tarput will handle this + as long as the longlink gets back to it, as it has to advance + the buffer pointer, etc */ + } else { + DEBUG(0, ("this tar file appears to contain some kind \ +of link other than a GNUtar Longlink - ignoring\n")); + return -2; + } + } + } + + if ((unoct(hb->dbuf.mode, sizeof(hb->dbuf.mode)) & S_IFDIR) || + (*(finfo->name+strlen(finfo->name)-1) == '\\')) { + finfo->mode=aDIR; + } else { + finfo->mode=0; /* we don't care about mode at the moment, we'll + * just make it a regular file */ + } - /* can't handle some links at present */ - if ((hb->dbuf.linkflag != '0') && (hb -> dbuf.linkflag != '5')) { - if (hb->dbuf.linkflag == 0) { - DEBUG(6, ("Warning: NULL link flag (gnu tar archive ?) %s\n", - finfo->name)); - } else { - if (hb -> dbuf.linkflag == 'L') { /* We have a longlink */ - /* Do nothing here at the moment. do_tarput will handle this - as long as the longlink gets back to it, as it has to advance - the buffer pointer, etc */ + /* + * Bug fix by richard@sj.co.uk + * + * REC: restore times correctly (as does tar) + * We only get the modification time of the file; set the creation time + * from the mod. time, and the access time to current time + */ + finfo->mtime = finfo->ctime = strtol(hb->dbuf.mtime, NULL, 8); + finfo->atime = time(NULL); + finfo->size = unoct(hb->dbuf.size, sizeof(hb->dbuf.size)); - } else { - DEBUG(0, ("this tar file appears to contain some kind of link other than a GNUtar Longlink - ignoring\n")); - return -2; - } - } - } - - if ((unoct(hb->dbuf.mode, sizeof(hb->dbuf.mode)) & S_IFDIR) - || (*(finfo->name+strlen(finfo->name)-1) == '\\')) - { - finfo->mode=aDIR; - } - else - finfo->mode=0; /* we don't care about mode at the moment, we'll - * just make it a regular file */ - /* - * Bug fix by richard@sj.co.uk - * - * REC: restore times correctly (as does tar) - * We only get the modification time of the file; set the creation time - * from the mod. time, and the access time to current time - */ - finfo->mtime = finfo->ctime = strtol(hb->dbuf.mtime, NULL, 8); - finfo->atime = time(NULL); - finfo->size = unoct(hb->dbuf.size, sizeof(hb->dbuf.size)); - - return True; + return True; } /**************************************************************************** Write out the tar buffer to tape or wherever ****************************************************************************/ + static int dotarbuf(int f, char *b, int n) { - int fail=1, writ=n; - - if (dry_run) { - return writ; - } - /* This routine and the next one should be the only ones that do write()s */ - if (tp + n >= tbufsiz) - { - int diff; - - diff=tbufsiz-tp; - memcpy(tarbuf + tp, b, diff); - fail=fail && (1+write(f, tarbuf, tbufsiz)); - n-=diff; - b+=diff; - tp=0; - - while (n >= tbufsiz) - { - fail=fail && (1 + write(f, b, tbufsiz)); - n-=tbufsiz; - b+=tbufsiz; + int fail=1, writ=n; + + if (dry_run) { + return writ; + } + /* This routine and the next one should be the only ones that do write()s */ + if (tp + n >= tbufsiz) { + int diff; + + diff=tbufsiz-tp; + memcpy(tarbuf + tp, b, diff); + fail=fail && (1+write(f, tarbuf, tbufsiz)); + n-=diff; + b+=diff; + tp=0; + + while (n >= tbufsiz) { + fail=fail && (1 + write(f, b, tbufsiz)); + n-=tbufsiz; + b+=tbufsiz; + } } - } - if (n>0) { - memcpy(tarbuf+tp, b, n); - tp+=n; - } - return(fail ? writ : 0); + if (n>0) { + memcpy(tarbuf+tp, b, n); + tp+=n; + } + + return(fail ? writ : 0); } /**************************************************************************** Write zeros to buffer / tape ****************************************************************************/ + static void dozerobuf(int f, int n) { - /* short routine just to write out n zeros to buffer - - * used to round files to nearest block - * and to do tar EOFs */ + /* short routine just to write out n zeros to buffer - + * used to round files to nearest block + * and to do tar EOFs */ - if (dry_run) - return; + if (dry_run) + return; - if (n+tp >= tbufsiz) - { - memset(tarbuf+tp, 0, tbufsiz-tp); - - write(f, tarbuf, tbufsiz); - memset(tarbuf, 0, (tp+=n-tbufsiz)); - } - else - { - memset(tarbuf+tp, 0, n); - tp+=n; - } + if (n+tp >= tbufsiz) { + memset(tarbuf+tp, 0, tbufsiz-tp); + write(f, tarbuf, tbufsiz); + memset(tarbuf, 0, (tp+=n-tbufsiz)); + } else { + memset(tarbuf+tp, 0, n); + tp+=n; + } } /**************************************************************************** Malloc tape buffer ****************************************************************************/ + static void initarbuf(void) { - /* initialize tar buffer */ - tbufsiz=blocksize*TBLOCK; - tarbuf=malloc(tbufsiz); /* FIXME: We might not get the buffer */ + /* initialize tar buffer */ + tbufsiz=blocksize*TBLOCK; + tarbuf=malloc(tbufsiz); /* FIXME: We might not get the buffer */ - /* reset tar buffer pointer and tar file counter and total dumped */ - tp=0; ntarf=0; ttarf=0; + /* reset tar buffer pointer and tar file counter and total dumped */ + tp=0; ntarf=0; ttarf=0; } /**************************************************************************** Write two zero blocks at end of file ****************************************************************************/ + static void dotareof(int f) { - SMB_STRUCT_STAT stbuf; - /* Two zero blocks at end of file, write out full buffer */ + SMB_STRUCT_STAT stbuf; + /* Two zero blocks at end of file, write out full buffer */ - if (dry_run) - return; + if (dry_run) + return; - (void) dozerobuf(f, TBLOCK); - (void) dozerobuf(f, TBLOCK); + (void) dozerobuf(f, TBLOCK); + (void) dozerobuf(f, TBLOCK); - if (sys_fstat(f, &stbuf) == -1) - { - DEBUG(0, ("Couldn't stat file handle\n")); - return; - } + if (sys_fstat(f, &stbuf) == -1) { + DEBUG(0, ("Couldn't stat file handle\n")); + return; + } - /* Could be a pipe, in which case S_ISREG should fail, - * and we should write out at full size */ - if (tp > 0) write(f, tarbuf, S_ISREG(stbuf.st_mode) ? tp : tbufsiz); + /* Could be a pipe, in which case S_ISREG should fail, + * and we should write out at full size */ + if (tp > 0) + write(f, tarbuf, S_ISREG(stbuf.st_mode) ? tp : tbufsiz); } /**************************************************************************** (Un)mangle DOS pathname, make nonabsolute ****************************************************************************/ + static void fixtarname(char *tptr, const char *fp, int l) { /* add a '.' to start of file name, convert from ugly dos \'s in path @@ -437,43 +432,43 @@ static void fixtarname(char *tptr, const char *fp, int l) /**************************************************************************** Convert from decimal to octal string ****************************************************************************/ + static void oct_it (SMB_BIG_UINT value, int ndgs, char *p) { - /* Converts long to octal string, pads with leading zeros */ + /* Converts long to octal string, pads with leading zeros */ - /* skip final null, but do final space */ - --ndgs; - p[--ndgs] = ' '; + /* skip final null, but do final space */ + --ndgs; + p[--ndgs] = ' '; - /* Loop does at least one digit */ - do { - p[--ndgs] = '0' + (char) (value & 7); - value >>= 3; - } - while (ndgs > 0 && value != 0); + /* Loop does at least one digit */ + do { + p[--ndgs] = '0' + (char) (value & 7); + value >>= 3; + } while (ndgs > 0 && value != 0); - /* Do leading zeros */ - while (ndgs > 0) - p[--ndgs] = '0'; + /* Do leading zeros */ + while (ndgs > 0) + p[--ndgs] = '0'; } /**************************************************************************** Convert from octal string to long ***************************************************************************/ + static long unoct(char *p, int ndgs) { - long value=0; - /* Converts octal string to long, ignoring any non-digit */ + long value=0; + /* Converts octal string to long, ignoring any non-digit */ - while (--ndgs) - { - if (isdigit((int)*p)) - value = (value << 3) | (long) (*p - '0'); + while (--ndgs) { + if (isdigit((int)*p)) + value = (value << 3) | (long) (*p - '0'); - p++; - } + p++; + } - return value; + return value; } /**************************************************************************** @@ -481,90 +476,86 @@ Compare two strings in a slash insensitive way, allowing s1 to match s2 if s1 is an "initial" string (up to directory marker). Thus, if s2 is a file in any subdirectory of s1, declare a match. ***************************************************************************/ + static int strslashcmp(char *s1, char *s2) { - char *s1_0=s1; + char *s1_0=s1; - while(*s1 && *s2 && - (*s1 == *s2 - || tolower(*s1) == tolower(*s2) - || (*s1 == '\\' && *s2=='/') - || (*s1 == '/' && *s2=='\\'))) { - s1++; s2++; - } + while(*s1 && *s2 && (*s1 == *s2 || tolower(*s1) == tolower(*s2) || + (*s1 == '\\' && *s2=='/') || (*s1 == '/' && *s2=='\\'))) { + s1++; s2++; + } - /* if s1 has a trailing slash, it compared equal, so s1 is an "initial" - string of s2. - */ - if (!*s1 && s1 != s1_0 && (*(s1-1) == '/' || *(s1-1) == '\\')) return 0; + /* if s1 has a trailing slash, it compared equal, so s1 is an "initial" + string of s2. + */ + if (!*s1 && s1 != s1_0 && (*(s1-1) == '/' || *(s1-1) == '\\')) + return 0; - /* ignore trailing slash on s1 */ - if (!*s2 && (*s1 == '/' || *s1 == '\\') && !*(s1+1)) return 0; + /* ignore trailing slash on s1 */ + if (!*s2 && (*s1 == '/' || *s1 == '\\') && !*(s1+1)) + return 0; - /* check for s1 is an "initial" string of s2 */ - if ((*s2 == '/' || *s2 == '\\') && !*s1) return 0; + /* check for s1 is an "initial" string of s2 */ + if ((*s2 == '/' || *s2 == '\\') && !*s1) + return 0; - return *s1-*s2; + return *s1-*s2; } - /**************************************************************************** Ensure a remote path exists (make if necessary) ***************************************************************************/ + static BOOL ensurepath(char *fname) { - /* *must* be called with buffer ready malloc'ed */ - /* ensures path exists */ - - char *partpath, *ffname; - char *p=fname, *basehack; - - DEBUG(5, ( "Ensurepath called with: %s\n", fname)); + /* *must* be called with buffer ready malloc'ed */ + /* ensures path exists */ - partpath = string_create_s(strlen(fname)); - ffname = string_create_s(strlen(fname)); + char *partpath, *ffname; + char *p=fname, *basehack; - if ((partpath == NULL) || (ffname == NULL)){ + DEBUG(5, ( "Ensurepath called with: %s\n", fname)); - DEBUG(0, ("Out of memory in ensurepath: %s\n", fname)); - return(False); + partpath = string_create_s(strlen(fname)); + ffname = string_create_s(strlen(fname)); - } + if ((partpath == NULL) || (ffname == NULL)){ + DEBUG(0, ("Out of memory in ensurepath: %s\n", fname)); + return(False); + } - *partpath = 0; + *partpath = 0; - /* fname copied to ffname so can strtok */ + /* fname copied to ffname so can strtok */ - safe_strcpy(ffname, fname, strlen(fname)); + safe_strcpy(ffname, fname, strlen(fname)); - /* do a `basename' on ffname, so don't try and make file name directory */ - if ((basehack=strrchr_m(ffname, '\\')) == NULL) - return True; - else - *basehack='\0'; + /* do a `basename' on ffname, so don't try and make file name directory */ + if ((basehack=strrchr_m(ffname, '\\')) == NULL) + return True; + else + *basehack='\0'; - p=strtok(ffname, "\\"); + p=strtok(ffname, "\\"); - while (p) - { - safe_strcat(partpath, p, strlen(fname) + 1); + while (p) { + safe_strcat(partpath, p, strlen(fname) + 1); - if (!cli_chkpath(cli, partpath)) { - if (!cli_mkdir(cli, partpath)) - { - DEBUG(0, ("Error mkdirhiering\n")); - return False; - } - else - DEBUG(3, ("mkdirhiering %s\n", partpath)); - - } + if (!cli_chkpath(cli, partpath)) { + if (!cli_mkdir(cli, partpath)) { + DEBUG(0, ("Error mkdirhiering\n")); + return False; + } else { + DEBUG(3, ("mkdirhiering %s\n", partpath)); + } + } - safe_strcat(partpath, "\\", strlen(fname) + 1); - p = strtok(NULL,"/\\"); - } + safe_strcat(partpath, "\\", strlen(fname) + 1); + p = strtok(NULL,"/\\"); + } - return True; + return True; } static int padit(char *buf, int bufsize, int padsize) @@ -583,7 +574,6 @@ static int padit(char *buf, int bufsize, int padsize) return berr; } - static void do_setrattr(char *name, uint16 attr, int set) { uint16 oldattr; @@ -601,268 +591,258 @@ static void do_setrattr(char *name, uint16 attr, int set) } } - /**************************************************************************** append one remote file to the tar file ***************************************************************************/ + static void do_atar(char *rname,char *lname,file_info *finfo1) { - int fnum; - SMB_BIG_UINT nread=0; - char ftype; - file_info2 finfo; - BOOL close_done = False; - BOOL shallitime=True; - char data[65520]; - int read_size = 65520; - int datalen=0; - - struct timeval tp_start; - GetTimeOfDay(&tp_start); - - ftype = '0'; /* An ordinary file ... */ - - if (finfo1) { - finfo.size = finfo1 -> size; - finfo.mode = finfo1 -> mode; - finfo.uid = finfo1 -> uid; - finfo.gid = finfo1 -> gid; - finfo.mtime = finfo1 -> mtime; - finfo.atime = finfo1 -> atime; - finfo.ctime = finfo1 -> ctime; - finfo.name = finfo1 -> name; - } - else { - finfo.size = def_finfo.size; - finfo.mode = def_finfo.mode; - finfo.uid = def_finfo.uid; - finfo.gid = def_finfo.gid; - finfo.mtime = def_finfo.mtime; - finfo.atime = def_finfo.atime; - finfo.ctime = def_finfo.ctime; - finfo.name = def_finfo.name; - } - - if (dry_run) - { - DEBUG(3,("skipping file %s of size %12.0f bytes\n", - finfo.name, - (double)finfo.size)); - shallitime=0; - ttarf+=finfo.size + TBLOCK - (finfo.size % TBLOCK); - ntarf++; - return; - } - - fnum = cli_open(cli, rname, O_RDONLY, DENY_NONE); - - dos_clean_name(rname); - - if (fnum == -1) { - DEBUG(0,("%s opening remote file %s (%s)\n", - cli_errstr(cli),rname, cur_dir)); - return; - } - - finfo.name = string_create_s(strlen(rname)); - if (finfo.name == NULL) { - DEBUG(0, ("Unable to allocate space for finfo.name in do_atar\n")); - return; - } - - safe_strcpy(finfo.name,rname, strlen(rname)); - if (!finfo1) { - if (!cli_getattrE(cli, fnum, &finfo.mode, &finfo.size, NULL, &finfo.atime, &finfo.mtime)) { - DEBUG(0, ("getattrE: %s\n", cli_errstr(cli))); - return; - } - finfo.ctime = finfo.mtime; - } - - DEBUG(3,("file %s attrib 0x%X\n",finfo.name,finfo.mode)); - - if (tar_inc && !(finfo.mode & aARCH)) - { - DEBUG(4, ("skipping %s - archive bit not set\n", finfo.name)); - shallitime=0; - } - else if (!tar_system && (finfo.mode & aSYSTEM)) - { - DEBUG(4, ("skipping %s - system bit is set\n", finfo.name)); - shallitime=0; - } - else if (!tar_hidden && (finfo.mode & aHIDDEN)) - { - DEBUG(4, ("skipping %s - hidden bit is set\n", finfo.name)); - shallitime=0; - } - else - { - DEBUG(3,("getting file %s of size %.0f bytes as a tar file %s", - finfo.name, - (double)finfo.size, - lname)); + int fnum; + SMB_BIG_UINT nread=0; + char ftype; + file_info2 finfo; + BOOL close_done = False; + BOOL shallitime=True; + char data[65520]; + int read_size = 65520; + int datalen=0; + + struct timeval tp_start; + + GetTimeOfDay(&tp_start); + + ftype = '0'; /* An ordinary file ... */ + + if (finfo1) { + finfo.size = finfo1 -> size; + finfo.mode = finfo1 -> mode; + finfo.uid = finfo1 -> uid; + finfo.gid = finfo1 -> gid; + finfo.mtime = finfo1 -> mtime; + finfo.atime = finfo1 -> atime; + finfo.ctime = finfo1 -> ctime; + finfo.name = finfo1 -> name; + } else { + finfo.size = def_finfo.size; + finfo.mode = def_finfo.mode; + finfo.uid = def_finfo.uid; + finfo.gid = def_finfo.gid; + finfo.mtime = def_finfo.mtime; + finfo.atime = def_finfo.atime; + finfo.ctime = def_finfo.ctime; + finfo.name = def_finfo.name; + } + + if (dry_run) { + DEBUG(3,("skipping file %s of size %12.0f bytes\n", finfo.name, + (double)finfo.size)); + shallitime=0; + ttarf+=finfo.size + TBLOCK - (finfo.size % TBLOCK); + ntarf++; + return; + } + + fnum = cli_open(cli, rname, O_RDONLY, DENY_NONE); + + dos_clean_name(rname); + + if (fnum == -1) { + DEBUG(0,("%s opening remote file %s (%s)\n", + cli_errstr(cli),rname, cur_dir)); + return; + } + + finfo.name = string_create_s(strlen(rname)); + if (finfo.name == NULL) { + DEBUG(0, ("Unable to allocate space for finfo.name in do_atar\n")); + return; + } + + safe_strcpy(finfo.name,rname, strlen(rname)); + if (!finfo1) { + if (!cli_getattrE(cli, fnum, &finfo.mode, &finfo.size, NULL, &finfo.atime, &finfo.mtime)) { + DEBUG(0, ("getattrE: %s\n", cli_errstr(cli))); + return; + } + finfo.ctime = finfo.mtime; + } + + DEBUG(3,("file %s attrib 0x%X\n",finfo.name,finfo.mode)); + + if (tar_inc && !(finfo.mode & aARCH)) { + DEBUG(4, ("skipping %s - archive bit not set\n", finfo.name)); + shallitime=0; + } else if (!tar_system && (finfo.mode & aSYSTEM)) { + DEBUG(4, ("skipping %s - system bit is set\n", finfo.name)); + shallitime=0; + } else if (!tar_hidden && (finfo.mode & aHIDDEN)) { + DEBUG(4, ("skipping %s - hidden bit is set\n", finfo.name)); + shallitime=0; + } else { + DEBUG(3,("getting file %s of size %.0f bytes as a tar file %s", + finfo.name, (double)finfo.size, lname)); - /* write a tar header, don't bother with mode - just set to 100644 */ - writetarheader(tarhandle, rname, finfo.size, finfo.mtime, "100644 \0", ftype); + /* write a tar header, don't bother with mode - just set to 100644 */ + writetarheader(tarhandle, rname, finfo.size, finfo.mtime, "100644 \0", ftype); - while (nread < finfo.size && !close_done) { + while (nread < finfo.size && !close_done) { - DEBUG(3,("nread=%.0f\n",(double)nread)); + DEBUG(3,("nread=%.0f\n",(double)nread)); - datalen = cli_read(cli, fnum, data, nread, read_size); + datalen = cli_read(cli, fnum, data, nread, read_size); - if (datalen == -1) { - DEBUG(0,("Error reading file %s : %s\n", rname, cli_errstr(cli))); - break; - } + if (datalen == -1) { + DEBUG(0,("Error reading file %s : %s\n", rname, cli_errstr(cli))); + break; + } - nread += datalen; - - /* if file size has increased since we made file size query, truncate - read so tar header for this file will be correct. - */ - - if (nread > finfo.size) { - datalen -= nread - finfo.size; - DEBUG(0,("File size change - truncating %s to %.0f bytes\n", finfo.name, (double)finfo.size)); - } - - /* add received bits of file to buffer - dotarbuf will - * write out in 512 byte intervals */ - if (dotarbuf(tarhandle,data,datalen) != datalen) { - DEBUG(0,("Error writing to tar file - %s\n", strerror(errno))); - break; - } + nread += datalen; + + /* if file size has increased since we made file size query, truncate + read so tar header for this file will be correct. + */ + + if (nread > finfo.size) { + datalen -= nread - finfo.size; + DEBUG(0,("File size change - truncating %s to %.0f bytes\n", + finfo.name, (double)finfo.size)); + } + + /* add received bits of file to buffer - dotarbuf will + * write out in 512 byte intervals */ + + if (dotarbuf(tarhandle,data,datalen) != datalen) { + DEBUG(0,("Error writing to tar file - %s\n", strerror(errno))); + break; + } - if (datalen == 0) { - DEBUG(0,("Error reading file %s. Got 0 bytes\n", rname)); - break; - } - - datalen=0; - } - - /* pad tar file with zero's if we couldn't get entire file */ - if (nread < finfo.size) { - DEBUG(0, ("Didn't get entire file. size=%.0f, nread=%d\n", (double)finfo.size, (int)nread)); - if (padit(data, sizeof(data), finfo.size - nread)) - DEBUG(0,("Error writing tar file - %s\n", strerror(errno))); - } - - /* round tar file to nearest block */ - if (finfo.size % TBLOCK) - dozerobuf(tarhandle, TBLOCK - (finfo.size % TBLOCK)); + if (datalen == 0) { + DEBUG(0,("Error reading file %s. Got 0 bytes\n", rname)); + break; + } + + datalen=0; + } + + /* pad tar file with zero's if we couldn't get entire file */ + if (nread < finfo.size) { + DEBUG(0, ("Didn't get entire file. size=%.0f, nread=%d\n", + (double)finfo.size, (int)nread)); + if (padit(data, sizeof(data), finfo.size - nread)) + DEBUG(0,("Error writing tar file - %s\n", strerror(errno))); + } + + /* round tar file to nearest block */ + if (finfo.size % TBLOCK) + dozerobuf(tarhandle, TBLOCK - (finfo.size % TBLOCK)); - ttarf+=finfo.size + TBLOCK - (finfo.size % TBLOCK); - ntarf++; - } + ttarf+=finfo.size + TBLOCK - (finfo.size % TBLOCK); + ntarf++; + } - cli_close(cli, fnum); + cli_close(cli, fnum); - if (shallitime) - { - struct timeval tp_end; - int this_time; + if (shallitime) { + struct timeval tp_end; + int this_time; - /* if shallitime is true then we didn't skip */ - if (tar_reset && !dry_run) - (void) do_setrattr(finfo.name, aARCH, ATTRRESET); + /* if shallitime is true then we didn't skip */ + if (tar_reset && !dry_run) + (void) do_setrattr(finfo.name, aARCH, ATTRRESET); - GetTimeOfDay(&tp_end); - this_time = - (tp_end.tv_sec - tp_start.tv_sec)*1000 + - (tp_end.tv_usec - tp_start.tv_usec)/1000; - get_total_time_ms += this_time; - get_total_size += finfo.size; - - if (tar_noisy) - { - DEBUG(0, ("%12.0f (%7.1f kb/s) %s\n", - (double)finfo.size, finfo.size / MAX(0.001, (1.024*this_time)), - finfo.name)); - } + GetTimeOfDay(&tp_end); + this_time = (tp_end.tv_sec - tp_start.tv_sec)*1000 + (tp_end.tv_usec - tp_start.tv_usec)/1000; + get_total_time_ms += this_time; + get_total_size += finfo.size; + + if (tar_noisy) { + DEBUG(0, ("%12.0f (%7.1f kb/s) %s\n", + (double)finfo.size, finfo.size / MAX(0.001, (1.024*this_time)), + finfo.name)); + } - /* Thanks to Carel-Jan Engel (ease@mail.wirehub.nl) for this one */ - DEBUG(3,("(%g kb/s) (average %g kb/s)\n", - finfo.size / MAX(0.001, (1.024*this_time)), - get_total_size / MAX(0.001, (1.024*get_total_time_ms)))); - } + /* Thanks to Carel-Jan Engel (ease@mail.wirehub.nl) for this one */ + DEBUG(3,("(%g kb/s) (average %g kb/s)\n", + finfo.size / MAX(0.001, (1.024*this_time)), + get_total_size / MAX(0.001, (1.024*get_total_time_ms)))); + } } /**************************************************************************** Append single file to tar file (or not) ***************************************************************************/ + static void do_tar(file_info *finfo) { - pstring rname; + pstring rname; - if (strequal(finfo->name,"..") || strequal(finfo->name,".")) - return; + if (strequal(finfo->name,"..") || strequal(finfo->name,".")) + return; - /* Is it on the exclude list ? */ - if (!tar_excl && clipn) { - pstring exclaim; + /* Is it on the exclude list ? */ + if (!tar_excl && clipn) { + pstring exclaim; - DEBUG(5, ("Excl: strlen(cur_dir) = %d\n", (int)strlen(cur_dir))); + DEBUG(5, ("Excl: strlen(cur_dir) = %d\n", (int)strlen(cur_dir))); - pstrcpy(exclaim, cur_dir); - *(exclaim+strlen(exclaim)-1)='\0'; + pstrcpy(exclaim, cur_dir); + *(exclaim+strlen(exclaim)-1)='\0'; - pstrcat(exclaim, "\\"); - pstrcat(exclaim, finfo->name); + pstrcat(exclaim, "\\"); + pstrcat(exclaim, finfo->name); - DEBUG(5, ("...tar_re_search: %d\n", tar_re_search)); + DEBUG(5, ("...tar_re_search: %d\n", tar_re_search)); - if ((!tar_re_search && clipfind(cliplist, clipn, exclaim)) || + if ((!tar_re_search && clipfind(cliplist, clipn, exclaim)) || #ifdef HAVE_REGEX_H - (tar_re_search && !regexec(preg, exclaim, 0, NULL, 0))) { + (tar_re_search && !regexec(preg, exclaim, 0, NULL, 0))) { #else - (tar_re_search && mask_match(exclaim, cliplist[0], True))) { + (tar_re_search && mask_match(exclaim, cliplist[0], True))) { #endif - DEBUG(3,("Skipping file %s\n", exclaim)); - return; - } - } - - if (finfo->mode & aDIR) - { - pstring saved_curdir; - pstring mtar_mask; - - pstrcpy(saved_curdir, cur_dir); - - DEBUG(5, ("Sizeof(cur_dir)=%d, strlen(cur_dir)=%d, strlen(finfo->name)=%d\nname=%s,cur_dir=%s\n", (int)sizeof(cur_dir), (int)strlen(cur_dir), (int)strlen(finfo->name), finfo->name, cur_dir)); - - pstrcat(cur_dir,finfo->name); - pstrcat(cur_dir,"\\"); - - DEBUG(5, ("Writing a dir, Name = %s\n", cur_dir)); - - /* write a tar directory, don't bother with mode - just set it to - * 40755 */ - writetarheader(tarhandle, cur_dir, 0, finfo->mtime, "040755 \0", '5'); - if (tar_noisy) { - DEBUG(0,(" directory %s\n", cur_dir)); - } - ntarf++; /* Make sure we have a file on there */ - pstrcpy(mtar_mask,cur_dir); - pstrcat(mtar_mask,"*"); - DEBUG(5, ("Doing list with mtar_mask: %s\n", mtar_mask)); - do_list(mtar_mask, attribute, do_tar, False, True); - pstrcpy(cur_dir,saved_curdir); - } - else - { - pstrcpy(rname,cur_dir); - pstrcat(rname,finfo->name); - do_atar(rname,finfo->name,finfo); - } + DEBUG(3,("Skipping file %s\n", exclaim)); + return; + } + } + + if (finfo->mode & aDIR) { + pstring saved_curdir; + pstring mtar_mask; + + pstrcpy(saved_curdir, cur_dir); + + DEBUG(5, ("Sizeof(cur_dir)=%d, strlen(cur_dir)=%d, \ +strlen(finfo->name)=%d\nname=%s,cur_dir=%s\n", + (int)sizeof(cur_dir), (int)strlen(cur_dir), + (int)strlen(finfo->name), finfo->name, cur_dir)); + + pstrcat(cur_dir,finfo->name); + pstrcat(cur_dir,"\\"); + + DEBUG(5, ("Writing a dir, Name = %s\n", cur_dir)); + + /* write a tar directory, don't bother with mode - just set it to + * 40755 */ + writetarheader(tarhandle, cur_dir, 0, finfo->mtime, "040755 \0", '5'); + if (tar_noisy) { + DEBUG(0,(" directory %s\n", cur_dir)); + } + ntarf++; /* Make sure we have a file on there */ + pstrcpy(mtar_mask,cur_dir); + pstrcat(mtar_mask,"*"); + DEBUG(5, ("Doing list with mtar_mask: %s\n", mtar_mask)); + do_list(mtar_mask, attribute, do_tar, False, True); + pstrcpy(cur_dir,saved_curdir); + } else { + pstrcpy(rname,cur_dir); + pstrcat(rname,finfo->name); + do_atar(rname,finfo->name,finfo); + } } /**************************************************************************** Convert from UNIX to DOS file names ***************************************************************************/ + static void unfixtarname(char *tptr, char *fp, int l, BOOL first) { /* remove '.' from start of file name, convert from unix /'s to @@ -886,79 +866,72 @@ static void unfixtarname(char *tptr, char *fp, int l, BOOL first) string_replace(tptr, '/', '\\'); } - /**************************************************************************** Move to the next block in the buffer, which may mean read in another set of blocks. FIXME, we should allow more than one block to be skipped. ****************************************************************************/ + static int next_block(char *ltarbuf, char **bufferp, int bufsiz) { - int bufread, total = 0; - - DEBUG(5, ("Advancing to next block: %0lx\n", (unsigned long)*bufferp)); - *bufferp += TBLOCK; - total = TBLOCK; - - if (*bufferp >= (ltarbuf + bufsiz)) { - - DEBUG(5, ("Reading more data into ltarbuf ...\n")); - - /* - * Bugfix from Bob Boehmer - * Fixes bug where read can return short if coming from - * a pipe. - */ - - bufread = read(tarhandle, ltarbuf, bufsiz); - total = bufread; - - while (total < bufsiz) { - if (bufread < 0) { /* An error, return false */ - return (total > 0 ? -2 : bufread); - } - if (bufread == 0) { - if (total <= 0) { - return -2; - } - break; - } - bufread = read(tarhandle, <arbuf[total], bufsiz - total); - total += bufread; - } - - DEBUG(5, ("Total bytes read ... %i\n", total)); - - *bufferp = ltarbuf; + int bufread, total = 0; + + DEBUG(5, ("Advancing to next block: %0lx\n", (unsigned long)*bufferp)); + *bufferp += TBLOCK; + total = TBLOCK; + + if (*bufferp >= (ltarbuf + bufsiz)) { + + DEBUG(5, ("Reading more data into ltarbuf ...\n")); + + /* + * Bugfix from Bob Boehmer + * Fixes bug where read can return short if coming from + * a pipe. + */ + + bufread = read(tarhandle, ltarbuf, bufsiz); + total = bufread; + + while (total < bufsiz) { + if (bufread < 0) { /* An error, return false */ + return (total > 0 ? -2 : bufread); + } + if (bufread == 0) { + if (total <= 0) { + return -2; + } + break; + } + bufread = read(tarhandle, <arbuf[total], bufsiz - total); + total += bufread; + } - } + DEBUG(5, ("Total bytes read ... %i\n", total)); - return(total); + *bufferp = ltarbuf; + } + return(total); } /* Skip a file, even if it includes a long file name? */ static int skip_file(int skipsize) { - int dsize = skipsize; - - DEBUG(5, ("Skiping file. Size = %i\n", skipsize)); - - /* FIXME, we should skip more than one block at a time */ - - while (dsize > 0) { + int dsize = skipsize; - if (next_block(tarbuf, &buffer_p, tbufsiz) <= 0) { + DEBUG(5, ("Skiping file. Size = %i\n", skipsize)); - DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno))); - return(False); + /* FIXME, we should skip more than one block at a time */ - } - - dsize -= TBLOCK; - - } + while (dsize > 0) { + if (next_block(tarbuf, &buffer_p, tbufsiz) <= 0) { + DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno))); + return(False); + } + dsize -= TBLOCK; + } - return(True); + return(True); } /************************************************************* @@ -969,103 +942,94 @@ static int skip_file(int skipsize) static int get_file(file_info2 finfo) { - int fnum = -1, pos = 0, dsize = 0, bpos = 0; - SMB_BIG_UINT rsize = 0; - - DEBUG(5, ("get_file: file: %s, size %.0f\n", finfo.name, (double)finfo.size)); - - if (ensurepath(finfo.name) && - (fnum=cli_open(cli, finfo.name, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE)) == -1) { - DEBUG(0, ("abandoning restore\n")); - return(False); - } - - /* read the blocks from the tar file and write to the remote file */ - - rsize = finfo.size; /* This is how much to write */ - - while (rsize > 0) { + int fnum = -1, pos = 0, dsize = 0, bpos = 0; + SMB_BIG_UINT rsize = 0; - /* We can only write up to the end of the buffer */ + DEBUG(5, ("get_file: file: %s, size %.0f\n", finfo.name, (double)finfo.size)); - dsize = MIN(tbufsiz - (buffer_p - tarbuf) - bpos, 65520); /* Calculate the size to write */ - dsize = MIN(dsize, rsize); /* Should be only what is left */ - DEBUG(5, ("writing %i bytes, bpos = %i ...\n", dsize, bpos)); - - if (cli_write(cli, fnum, 0, buffer_p + bpos, pos, dsize) != dsize) { - DEBUG(0, ("Error writing remote file\n")); - return 0; - } - - rsize -= dsize; - pos += dsize; - - /* Now figure out how much to move in the buffer */ + if (ensurepath(finfo.name) && + (fnum=cli_open(cli, finfo.name, O_RDWR|O_CREAT|O_TRUNC, DENY_NONE)) == -1) { + DEBUG(0, ("abandoning restore\n")); + return(False); + } - /* FIXME, we should skip more than one block at a time */ + /* read the blocks from the tar file and write to the remote file */ - /* First, skip any initial part of the part written that is left over */ - /* from the end of the first TBLOCK */ + rsize = finfo.size; /* This is how much to write */ - if ((bpos) && ((bpos + dsize) >= TBLOCK)) { + while (rsize > 0) { - dsize -= (TBLOCK - bpos); /* Get rid of the end of the first block */ - bpos = 0; + /* We can only write up to the end of the buffer */ + dsize = MIN(tbufsiz - (buffer_p - tarbuf) - bpos, 65520); /* Calculate the size to write */ + dsize = MIN(dsize, rsize); /* Should be only what is left */ + DEBUG(5, ("writing %i bytes, bpos = %i ...\n", dsize, bpos)); - if (next_block(tarbuf, &buffer_p, tbufsiz) <=0) { /* and skip the block */ - DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno))); - return False; + if (cli_write(cli, fnum, 0, buffer_p + bpos, pos, dsize) != dsize) { + DEBUG(0, ("Error writing remote file\n")); + return 0; + } - } + rsize -= dsize; + pos += dsize; - } + /* Now figure out how much to move in the buffer */ - /* - * Bugfix from Bob Boehmer . - * If the file being extracted is an exact multiple of - * TBLOCK bytes then we don't want to extract the next - * block from the tarfile here, as it will be done in - * the caller of get_file(). - */ + /* FIXME, we should skip more than one block at a time */ - while (((rsize != 0) && (dsize >= TBLOCK)) || - ((rsize == 0) && (dsize > TBLOCK))) { + /* First, skip any initial part of the part written that is left over */ + /* from the end of the first TBLOCK */ - if (next_block(tarbuf, &buffer_p, tbufsiz) <=0) { - DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno))); - return False; - } + if ((bpos) && ((bpos + dsize) >= TBLOCK)) { + dsize -= (TBLOCK - bpos); /* Get rid of the end of the first block */ + bpos = 0; - dsize -= TBLOCK; - } + if (next_block(tarbuf, &buffer_p, tbufsiz) <=0) { /* and skip the block */ + DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno))); + return False; + } + } - bpos = dsize; + /* + * Bugfix from Bob Boehmer . + * If the file being extracted is an exact multiple of + * TBLOCK bytes then we don't want to extract the next + * block from the tarfile here, as it will be done in + * the caller of get_file(). + */ - } + while (((rsize != 0) && (dsize >= TBLOCK)) || + ((rsize == 0) && (dsize > TBLOCK))) { - /* Now close the file ... */ + if (next_block(tarbuf, &buffer_p, tbufsiz) <=0) { + DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno))); + return False; + } - if (!cli_close(cli, fnum)) { - DEBUG(0, ("Error closing remote file\n")); - return(False); - } + dsize -= TBLOCK; + } + bpos = dsize; + } - /* Now we update the creation date ... */ + /* Now close the file ... */ - DEBUG(5, ("Updating creation date on %s\n", finfo.name)); + if (!cli_close(cli, fnum)) { + DEBUG(0, ("Error closing remote file\n")); + return(False); + } - if (!cli_setatr(cli, finfo.name, finfo.mode, finfo.mtime)) { - if (tar_real_noisy) { - DEBUG(0, ("Could not set time on file: %s\n", finfo.name)); - /*return(False); */ /* Ignore, as Win95 does not allow changes */ - } - } + /* Now we update the creation date ... */ + DEBUG(5, ("Updating creation date on %s\n", finfo.name)); - ntarf++; + if (!cli_setatr(cli, finfo.name, finfo.mode, finfo.mtime)) { + if (tar_real_noisy) { + DEBUG(0, ("Could not set time on file: %s\n", finfo.name)); + /*return(False); */ /* Ignore, as Win95 does not allow changes */ + } + } - DEBUG(0, ("restore tar file %s of size %.0f bytes\n", finfo.name, (double)finfo.size)); - - return(True); + ntarf++; + DEBUG(0, ("restore tar file %s of size %.0f bytes\n", finfo.name, (double)finfo.size)); + return(True); } /* Create a directory. We just ensure that the path exists and return as there @@ -1073,214 +1037,167 @@ static int get_file(file_info2 finfo) */ static int get_dir(file_info2 finfo) { + DEBUG(0, ("restore directory %s\n", finfo.name)); - DEBUG(0, ("restore directory %s\n", finfo.name)); - - if (!ensurepath(finfo.name)) { - - DEBUG(0, ("Problems creating directory\n")); - return(False); - - } - - ntarf++; - return(True); - + if (!ensurepath(finfo.name)) { + DEBUG(0, ("Problems creating directory\n")); + return(False); + } + ntarf++; + return(True); } + /* Get a file with a long file name ... first file has file name, next file has the data. We only want the long file name, as the loop in do_tarput will deal with the rest. */ static char * get_longfilename(file_info2 finfo) { - int namesize = strlen(finfo.name) + strlen(cur_dir) + 2; - char *longname = malloc(namesize); - int offset = 0, left = finfo.size; - BOOL first = True; - - DEBUG(5, ("Restoring a long file name: %s\n", finfo.name)); - DEBUG(5, ("Len = %.0f\n", (double)finfo.size)); - - if (longname == NULL) { - - DEBUG(0, ("could not allocate buffer of size %d for longname\n", - namesize)); - return(NULL); - } - - /* First, add cur_dir to the long file name */ + int namesize = strlen(finfo.name) + strlen(cur_dir) + 2; + char *longname = malloc(namesize); + int offset = 0, left = finfo.size; + BOOL first = True; - if (strlen(cur_dir) > 0) { - strncpy(longname, cur_dir, namesize); - offset = strlen(cur_dir); - } + DEBUG(5, ("Restoring a long file name: %s\n", finfo.name)); + DEBUG(5, ("Len = %.0f\n", (double)finfo.size)); - /* Loop through the blocks picking up the name */ - - while (left > 0) { - - if (next_block(tarbuf, &buffer_p, tbufsiz) <= 0) { + if (longname == NULL) { + DEBUG(0, ("could not allocate buffer of size %d for longname\n", namesize)); + return(NULL); + } - DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno))); - return(NULL); + /* First, add cur_dir to the long file name */ - } + if (strlen(cur_dir) > 0) { + strncpy(longname, cur_dir, namesize); + offset = strlen(cur_dir); + } - unfixtarname(longname + offset, buffer_p, MIN(TBLOCK, finfo.size), first--); - DEBUG(5, ("UnfixedName: %s, buffer: %s\n", longname, buffer_p)); + /* Loop through the blocks picking up the name */ - offset += TBLOCK; - left -= TBLOCK; + while (left > 0) { + if (next_block(tarbuf, &buffer_p, tbufsiz) <= 0) { + DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno))); + return(NULL); + } - } + unfixtarname(longname + offset, buffer_p, MIN(TBLOCK, finfo.size), first--); + DEBUG(5, ("UnfixedName: %s, buffer: %s\n", longname, buffer_p)); - return(longname); + offset += TBLOCK; + left -= TBLOCK; + } + return(longname); } static void do_tarput(void) { - file_info2 finfo; - struct timeval tp_start; - char *longfilename = NULL, linkflag; - int skip = False; - - GetTimeOfDay(&tp_start); - - DEBUG(5, ("RJS do_tarput called ...\n")); - - buffer_p = tarbuf + tbufsiz; /* init this to force first read */ - - /* Now read through those files ... */ - - while (True) { - - /* Get us to the next block, or the first block first time around */ - - if (next_block(tarbuf, &buffer_p, tbufsiz) <= 0) { - - DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno))); - - return; - - } - - DEBUG(5, ("Reading the next header ...\n")); - - switch (readtarheader((union hblock *) buffer_p, &finfo, cur_dir)) { - - case -2: /* Hmm, not good, but not fatal */ - DEBUG(0, ("Skipping %s...\n", finfo.name)); - if ((next_block(tarbuf, &buffer_p, tbufsiz) <= 0) && - !skip_file(finfo.size)) { - - DEBUG(0, ("Short file, bailing out...\n")); - return; - - } - - break; - - case -1: - DEBUG(0, ("abandoning restore, -1 from read tar header\n")); - return; - - case 0: /* chksum is zero - looks like an EOF */ - DEBUG(0, ("tar: restored %d files and directories\n", ntarf)); - return; /* Hmmm, bad here ... */ - - default: - /* No action */ - - break; - - } + file_info2 finfo; + struct timeval tp_start; + char *longfilename = NULL, linkflag; + int skip = False; + + GetTimeOfDay(&tp_start); + DEBUG(5, ("RJS do_tarput called ...\n")); + + buffer_p = tarbuf + tbufsiz; /* init this to force first read */ + + /* Now read through those files ... */ + while (True) { + /* Get us to the next block, or the first block first time around */ + if (next_block(tarbuf, &buffer_p, tbufsiz) <= 0) { + DEBUG(0, ("Empty file, short tar file, or read error: %s\n", strerror(errno))); + return; + } - /* Now, do we have a long file name? */ + DEBUG(5, ("Reading the next header ...\n")); - if (longfilename != NULL) { + switch (readtarheader((union hblock *) buffer_p, &finfo, cur_dir)) { + case -2: /* Hmm, not good, but not fatal */ + DEBUG(0, ("Skipping %s...\n", finfo.name)); + if ((next_block(tarbuf, &buffer_p, tbufsiz) <= 0) && !skip_file(finfo.size)) { + DEBUG(0, ("Short file, bailing out...\n")); + return; + } + break; - SAFE_FREE(finfo.name); /* Free the space already allocated */ - finfo.name = longfilename; - longfilename = NULL; + case -1: + DEBUG(0, ("abandoning restore, -1 from read tar header\n")); + return; - } + case 0: /* chksum is zero - looks like an EOF */ + DEBUG(0, ("tar: restored %d files and directories\n", ntarf)); + return; /* Hmmm, bad here ... */ - /* Well, now we have a header, process the file ... */ + default: + /* No action */ + break; + } - /* Should we skip the file? We have the long name as well here */ + /* Now, do we have a long file name? */ + if (longfilename != NULL) { + SAFE_FREE(finfo.name); /* Free the space already allocated */ + finfo.name = longfilename; + longfilename = NULL; + } - skip = clipn && - ((!tar_re_search && clipfind(cliplist, clipn, finfo.name) ^ tar_excl) + /* Well, now we have a header, process the file ... */ + /* Should we skip the file? We have the long name as well here */ + skip = clipn && ((!tar_re_search && clipfind(cliplist, clipn, finfo.name) ^ tar_excl) || #ifdef HAVE_REGEX_H - || (tar_re_search && !regexec(preg, finfo.name, 0, NULL, 0))); + (tar_re_search && !regexec(preg, finfo.name, 0, NULL, 0))); #else - || (tar_re_search && mask_match(finfo.name, cliplist[0], True))); + (tar_re_search && mask_match(finfo.name, cliplist[0], True))); #endif - DEBUG(5, ("Skip = %i, cliplist=%s, file=%s\n", skip, (cliplist?cliplist[0]:NULL), finfo.name)); - - if (skip) { - - skip_file(finfo.size); - continue; - - } - - /* We only get this far if we should process the file */ - linkflag = ((union hblock *)buffer_p) -> dbuf.linkflag; - - switch (linkflag) { - - case '0': /* Should use symbolic names--FIXME */ - - /* - * Skip to the next block first, so we can get the file, FIXME, should - * be in get_file ... - * The 'finfo.size != 0' fix is from Bob Boehmer - * Fixes bug where file size in tarfile is zero. - */ - - if ((finfo.size != 0) && next_block(tarbuf, &buffer_p, tbufsiz) <=0) { - DEBUG(0, ("Short file, bailing out...\n")); - return; - } - if (!get_file(finfo)) { - DEBUG(0, ("Abandoning restore\n")); - return; - - } - break; - - case '5': - if (!get_dir(finfo)) { - DEBUG(0, ("Abandoning restore \n")); - return; - } - break; - - case 'L': - longfilename = get_longfilename(finfo); - if (!longfilename) { - DEBUG(0, ("abandoning restore\n")); - return; - - } - DEBUG(5, ("Long file name: %s\n", longfilename)); - break; - - default: - skip_file(finfo.size); /* Don't handle these yet */ - break; - - } - - } - + DEBUG(5, ("Skip = %i, cliplist=%s, file=%s\n", skip, (cliplist?cliplist[0]:NULL), finfo.name)); + if (skip) { + skip_file(finfo.size); + continue; + } + /* We only get this far if we should process the file */ + linkflag = ((union hblock *)buffer_p) -> dbuf.linkflag; + switch (linkflag) { + case '0': /* Should use symbolic names--FIXME */ + /* + * Skip to the next block first, so we can get the file, FIXME, should + * be in get_file ... + * The 'finfo.size != 0' fix is from Bob Boehmer + * Fixes bug where file size in tarfile is zero. + */ + if ((finfo.size != 0) && next_block(tarbuf, &buffer_p, tbufsiz) <=0) { + DEBUG(0, ("Short file, bailing out...\n")); + return; + } + if (!get_file(finfo)) { + DEBUG(0, ("Abandoning restore\n")); + return; + } + break; + case '5': + if (!get_dir(finfo)) { + DEBUG(0, ("Abandoning restore \n")); + return; + } + break; + case 'L': + longfilename = get_longfilename(finfo); + if (!longfilename) { + DEBUG(0, ("abandoning restore\n")); + return; + } + DEBUG(5, ("Long file name: %s\n", longfilename)); + break; + + default: + skip_file(finfo.size); /* Don't handle these yet */ + break; + } + } } - /* * samba interactive commands */ @@ -1288,577 +1205,594 @@ static void do_tarput(void) /**************************************************************************** Blocksize command ***************************************************************************/ + int cmd_block(void) { - fstring buf; - int block; - - if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) - { - DEBUG(0, ("blocksize \n")); - return 1; - } - - block=atoi(buf); - if (block < 0 || block > 65535) - { - DEBUG(0, ("blocksize out of range")); - return 1; - } - - blocksize=block; - DEBUG(2,("blocksize is now %d\n", blocksize)); - - return 0; + fstring buf; + int block; + + if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) { + DEBUG(0, ("blocksize \n")); + return 1; + } + + block=atoi(buf); + if (block < 0 || block > 65535) { + DEBUG(0, ("blocksize out of range")); + return 1; + } + + blocksize=block; + DEBUG(2,("blocksize is now %d\n", blocksize)); + + return 0; } /**************************************************************************** command to set incremental / reset mode ***************************************************************************/ + int cmd_tarmode(void) { - fstring buf; - - while (next_token_nr(NULL,buf,NULL,sizeof(buf))) { - if (strequal(buf, "full")) - tar_inc=False; - else if (strequal(buf, "inc")) - tar_inc=True; - else if (strequal(buf, "reset")) - tar_reset=True; - else if (strequal(buf, "noreset")) - tar_reset=False; - else if (strequal(buf, "system")) - tar_system=True; - else if (strequal(buf, "nosystem")) - tar_system=False; - else if (strequal(buf, "hidden")) - tar_hidden=True; - else if (strequal(buf, "nohidden")) - tar_hidden=False; - else if (strequal(buf, "verbose") || strequal(buf, "noquiet")) - tar_noisy=True; - else if (strequal(buf, "quiet") || strequal(buf, "noverbose")) - tar_noisy=False; - else DEBUG(0, ("tarmode: unrecognised option %s\n", buf)); - } - - DEBUG(0, ("tarmode is now %s, %s, %s, %s, %s\n", - tar_inc ? "incremental" : "full", - tar_system ? "system" : "nosystem", - tar_hidden ? "hidden" : "nohidden", - tar_reset ? "reset" : "noreset", - tar_noisy ? "verbose" : "quiet")); - - return 0; + fstring buf; + + while (next_token_nr(NULL,buf,NULL,sizeof(buf))) { + if (strequal(buf, "full")) + tar_inc=False; + else if (strequal(buf, "inc")) + tar_inc=True; + else if (strequal(buf, "reset")) + tar_reset=True; + else if (strequal(buf, "noreset")) + tar_reset=False; + else if (strequal(buf, "system")) + tar_system=True; + else if (strequal(buf, "nosystem")) + tar_system=False; + else if (strequal(buf, "hidden")) + tar_hidden=True; + else if (strequal(buf, "nohidden")) + tar_hidden=False; + else if (strequal(buf, "verbose") || strequal(buf, "noquiet")) + tar_noisy=True; + else if (strequal(buf, "quiet") || strequal(buf, "noverbose")) + tar_noisy=False; + else + DEBUG(0, ("tarmode: unrecognised option %s\n", buf)); + } + + DEBUG(0, ("tarmode is now %s, %s, %s, %s, %s\n", + tar_inc ? "incremental" : "full", + tar_system ? "system" : "nosystem", + tar_hidden ? "hidden" : "nohidden", + tar_reset ? "reset" : "noreset", + tar_noisy ? "verbose" : "quiet")); + return 0; } /**************************************************************************** Feeble attrib command ***************************************************************************/ + int cmd_setmode(void) { - char *q; - fstring buf; - pstring fname; - uint16 attra[2]; - int direct=1; - - attra[0] = attra[1] = 0; - - if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) - { - DEBUG(0, ("setmode <[+|-]rsha>\n")); - return 1; - } - - pstrcpy(fname, cur_dir); - pstrcat(fname, buf); - - while (next_token_nr(NULL,buf,NULL,sizeof(buf))) { - q=buf; - - while(*q) - switch (*q++) { - case '+': direct=1; - break; - case '-': direct=0; - break; - case 'r': attra[direct]|=aRONLY; - break; - case 'h': attra[direct]|=aHIDDEN; - break; - case 's': attra[direct]|=aSYSTEM; - break; - case 'a': attra[direct]|=aARCH; - break; - default: DEBUG(0, ("setmode \n")); - return 1; - } - } + char *q; + fstring buf; + pstring fname; + uint16 attra[2]; + int direct=1; + + attra[0] = attra[1] = 0; - if (attra[ATTRSET]==0 && attra[ATTRRESET]==0) - { - DEBUG(0, ("setmode <[+|-]rsha>\n")); - return 1; - } + if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) { + DEBUG(0, ("setmode <[+|-]rsha>\n")); + return 1; + } + + pstrcpy(fname, cur_dir); + pstrcat(fname, buf); + + while (next_token_nr(NULL,buf,NULL,sizeof(buf))) { + q=buf; + + while(*q) { + switch (*q++) { + case '+': + direct=1; + break; + case '-': + direct=0; + break; + case 'r': + attra[direct]|=aRONLY; + break; + case 'h': + attra[direct]|=aHIDDEN; + break; + case 's': + attra[direct]|=aSYSTEM; + break; + case 'a': + attra[direct]|=aARCH; + break; + default: + DEBUG(0, ("setmode \n")); + return 1; + } + } + } - DEBUG(2, ("\nperm set %d %d\n", attra[ATTRSET], attra[ATTRRESET])); - do_setrattr(fname, attra[ATTRSET], ATTRSET); - do_setrattr(fname, attra[ATTRRESET], ATTRRESET); + if (attra[ATTRSET]==0 && attra[ATTRRESET]==0) { + DEBUG(0, ("setmode <[+|-]rsha>\n")); + return 1; + } - return 0; + DEBUG(2, ("\nperm set %d %d\n", attra[ATTRSET], attra[ATTRRESET])); + do_setrattr(fname, attra[ATTRSET], ATTRSET); + do_setrattr(fname, attra[ATTRRESET], ATTRRESET); + return 0; } /**************************************************************************** Principal command for creating / extracting ***************************************************************************/ + int cmd_tar(void) { - fstring buf; - char **argl; - int argcl; - - if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) - { - DEBUG(0,("tar [IXbgan] \n")); - return 1; - } - - argl=toktocliplist(&argcl, NULL); - if (!tar_parseargs(argcl, argl, buf, 0)) - return 1; + fstring buf; + char **argl; + int argcl; - process_tar(); + if (!next_token_nr(NULL,buf,NULL,sizeof(buf))) { + DEBUG(0,("tar [IXbgan] \n")); + return 1; + } - SAFE_FREE(argl); + argl=toktocliplist(&argcl, NULL); + if (!tar_parseargs(argcl, argl, buf, 0)) + return 1; - return 0; + process_tar(); + SAFE_FREE(argl); + return 0; } /**************************************************************************** Command line (option) version ***************************************************************************/ + int process_tar(void) { - initarbuf(); - switch(tar_type) { - case 'x': + initarbuf(); + switch(tar_type) { + case 'x': #if 0 - do_tarput2(); + do_tarput2(); #else - do_tarput(); + do_tarput(); #endif - SAFE_FREE(tarbuf); - close(tarhandle); - break; - case 'r': - case 'c': - if (clipn && tar_excl) { - int i; - pstring tarmac; - - for (i=0; i= inclusion_buffer_size) { - char *ib; - inclusion_buffer_size *= 2; - ib = Realloc(inclusion_buffer,inclusion_buffer_size); - if (! ib) { - DEBUG(0,("failure enlarging inclusion buffer to %d bytes\n", - inclusion_buffer_size)); - error = 1; - break; - } - else inclusion_buffer = ib; - } + if ((strlen(buf) + 1 + inclusion_buffer_sofar) >= inclusion_buffer_size) { + char *ib; + inclusion_buffer_size *= 2; + ib = Realloc(inclusion_buffer,inclusion_buffer_size); + if (! ib) { + DEBUG(0,("failure enlarging inclusion buffer to %d bytes\n", + inclusion_buffer_size)); + error = 1; + break; + } else { + inclusion_buffer = ib; + } + } - safe_strcpy(inclusion_buffer + inclusion_buffer_sofar, buf, inclusion_buffer_size - inclusion_buffer_sofar); - inclusion_buffer_sofar += strlen(buf) + 1; - clipn++; - } - x_fclose(inclusion); - - if (! error) { - /* Allocate an array of clipn + 1 char*'s for cliplist */ - cliplist = malloc((clipn + 1) * sizeof(char *)); - if (cliplist == NULL) { - DEBUG(0,("failure allocating memory for cliplist\n")); - error = 1; - } else { - cliplist[clipn] = NULL; - p = inclusion_buffer; - for (i = 0; (! error) && (i < clipn); i++) { - /* set current item to NULL so array will be null-terminated even if - * malloc fails below. */ - cliplist[i] = NULL; - if ((tmpstr = (char *)malloc(strlen(p)+1)) == NULL) { - DEBUG(0, ("Could not allocate space for a cliplist item, # %i\n", i)); - error = 1; - } else { - unfixtarname(tmpstr, p, strlen(p) + 1, True); - cliplist[i] = tmpstr; - if ((p = strchr_m(p, '\000')) == NULL) { - DEBUG(0,("INTERNAL ERROR: inclusion_buffer is of unexpected contents.\n")); - abort(); - } + safe_strcpy(inclusion_buffer + inclusion_buffer_sofar, buf, inclusion_buffer_size - inclusion_buffer_sofar); + inclusion_buffer_sofar += strlen(buf) + 1; + clipn++; + } + x_fclose(inclusion); + + if (! error) { + /* Allocate an array of clipn + 1 char*'s for cliplist */ + cliplist = malloc((clipn + 1) * sizeof(char *)); + if (cliplist == NULL) { + DEBUG(0,("failure allocating memory for cliplist\n")); + error = 1; + } else { + cliplist[clipn] = NULL; + p = inclusion_buffer; + for (i = 0; (! error) && (i < clipn); i++) { + /* set current item to NULL so array will be null-terminated even if + * malloc fails below. */ + cliplist[i] = NULL; + if ((tmpstr = (char *)malloc(strlen(p)+1)) == NULL) { + DEBUG(0, ("Could not allocate space for a cliplist item, # %i\n", i)); + error = 1; + } else { + unfixtarname(tmpstr, p, strlen(p) + 1, True); + cliplist[i] = tmpstr; + if ((p = strchr_m(p, '\000')) == NULL) { + DEBUG(0,("INTERNAL ERROR: inclusion_buffer is of unexpected contents.\n")); + abort(); + } + } + ++p; + } + must_free_cliplist = True; + } + } + + SAFE_FREE(inclusion_buffer); + if (error) { + if (cliplist) { + char **pp; + /* We know cliplist is always null-terminated */ + for (pp = cliplist; *pp; ++pp) { + SAFE_FREE(*pp); + } + SAFE_FREE(cliplist); + cliplist = NULL; + must_free_cliplist = False; + } + return 0; } - ++p; - } - must_free_cliplist = True; - } - } - - SAFE_FREE(inclusion_buffer); - if (error) { - if (cliplist) { - char **pp; - /* We know cliplist is always null-terminated */ - for (pp = cliplist; *pp; ++pp) { - SAFE_FREE(*pp); - } - SAFE_FREE(cliplist); - cliplist = NULL; - must_free_cliplist = False; - } - return 0; - } - /* cliplist and its elements are freed at the end of process_tar. */ - return 1; + /* cliplist and its elements are freed at the end of process_tar. */ + return 1; } /**************************************************************************** Parse tar arguments. Sets tar_type, tar_excl, etc. ***************************************************************************/ + int tar_parseargs(int argc, char *argv[], char *Optarg, int Optind) { - char tar_clipfl='\0'; - - /* Reset back to defaults - could be from interactive version - * reset mode and archive mode left as they are though - */ - tar_type='\0'; - tar_excl=True; - dry_run=False; - - while (*Optarg) - switch(*Optarg++) { - case 'c': - tar_type='c'; - break; - case 'x': - if (tar_type=='c') { - printf("Tar must be followed by only one of c or x.\n"); - return 0; - } - tar_type='x'; - break; - case 'b': - if (Optind>=argc || !(blocksize=atoi(argv[Optind]))) { - DEBUG(0,("Option b must be followed by valid blocksize\n")); - return 0; - } else { - Optind++; - } - break; - case 'g': - tar_inc=True; - break; - case 'N': - if (Optind>=argc) { - DEBUG(0,("Option N must be followed by valid file name\n")); - return 0; - } else { - SMB_STRUCT_STAT stbuf; - extern time_t newer_than; + int newOptind = Optind; + char tar_clipfl='\0'; + + /* Reset back to defaults - could be from interactive version + * reset mode and archive mode left as they are though + */ + tar_type='\0'; + tar_excl=True; + dry_run=False; + + while (*Optarg) { + switch(*Optarg++) { + case 'c': + tar_type='c'; + break; + case 'x': + if (tar_type=='c') { + printf("Tar must be followed by only one of c or x.\n"); + return 0; + } + tar_type='x'; + break; + case 'b': + if (Optind>=argc || !(blocksize=atoi(argv[Optind]))) { + DEBUG(0,("Option b must be followed by valid blocksize\n")); + return 0; + } else { + Optind++; + newOptind++; + } + break; + case 'g': + tar_inc=True; + break; + case 'N': + if (Optind>=argc) { + DEBUG(0,("Option N must be followed by valid file name\n")); + return 0; + } else { + SMB_STRUCT_STAT stbuf; + extern time_t newer_than; - if (sys_stat(argv[Optind], &stbuf) == 0) { - newer_than = stbuf.st_mtime; - DEBUG(1,("Getting files newer than %s", - asctime(LocalTime(&newer_than)))); - Optind++; - } else { - DEBUG(0,("Error setting newer-than time\n")); - return 0; + if (sys_stat(argv[Optind], &stbuf) == 0) { + newer_than = stbuf.st_mtime; + DEBUG(1,("Getting files newer than %s", + asctime(LocalTime(&newer_than)))); + newOptind++; + Optind++; + } else { + DEBUG(0,("Error setting newer-than time\n")); + return 0; + } + } + break; + case 'a': + tar_reset=True; + break; + case 'q': + tar_noisy=False; + break; + case 'I': + if (tar_clipfl) { + DEBUG(0,("Only one of I,X,F must be specified\n")); + return 0; + } + tar_clipfl='I'; + break; + case 'X': + if (tar_clipfl) { + DEBUG(0,("Only one of I,X,F must be specified\n")); + return 0; + } + tar_clipfl='X'; + break; + case 'F': + if (tar_clipfl) { + DEBUG(0,("Only one of I,X,F must be specified\n")); + return 0; + } + tar_clipfl='F'; + break; + case 'r': + DEBUG(0, ("tar_re_search set\n")); + tar_re_search = True; + break; + case 'n': + if (tar_type == 'c') { + DEBUG(0, ("dry_run set\n")); + dry_run = True; + } else { + DEBUG(0, ("n is only meaningful when creating a tar-file\n")); + return 0; + } + break; + default: + DEBUG(0,("Unknown tar option\n")); + return 0; + } } - } - break; - case 'a': - tar_reset=True; - break; - case 'q': - tar_noisy=False; - break; - case 'I': - if (tar_clipfl) { - DEBUG(0,("Only one of I,X,F must be specified\n")); - return 0; - } - tar_clipfl='I'; - break; - case 'X': - if (tar_clipfl) { - DEBUG(0,("Only one of I,X,F must be specified\n")); - return 0; - } - tar_clipfl='X'; - break; - case 'F': - if (tar_clipfl) { - DEBUG(0,("Only one of I,X,F must be specified\n")); - return 0; - } - tar_clipfl='F'; - break; - case 'r': - DEBUG(0, ("tar_re_search set\n")); - tar_re_search = True; - break; - case 'n': - if (tar_type == 'c') { - DEBUG(0, ("dry_run set\n")); - dry_run = True; - } else { - DEBUG(0, ("n is only meaningful when creating a tar-file\n")); - return 0; - } - break; - default: - DEBUG(0,("Unknown tar option\n")); - return 0; - } - - if (!tar_type) { - printf("Option T must be followed by one of c or x.\n"); - return 0; - } - - /* tar_excl is true if cliplist lists files to be included. - * Both 'I' and 'F' mean include. */ - tar_excl=tar_clipfl!='X'; - - if (tar_clipfl=='F') { - if (argc-Optind-1 != 1) { - DEBUG(0,("Option F must be followed by exactly one filename.\n")); - return 0; - } - if (! read_inclusion_file(argv[Optind+1])) { - return 0; - } - } else if (Optind+1=argc || !strcmp(argv[Optind], "-")) { - /* Sets tar handle to either 0 or 1, as appropriate */ - tarhandle=(tar_type=='c'); - /* - * Make sure that dbf points to stderr if we are using stdout for - * tar output - */ - if (tarhandle == 1) - dbf = x_stderr; - } else { - if (tar_type=='c' && (dry_run || strcmp(argv[Optind], "/dev/null")==0)) - { - if (!dry_run) { - DEBUG(0,("Output is /dev/null, assuming dry_run\n")); - dry_run = True; + clipn=argc-Optind-1; + cliplist=argv+Optind+1; + newOptind += clipn; + } + + if (Optind>=argc || !strcmp(argv[Optind], "-")) { + /* Sets tar handle to either 0 or 1, as appropriate */ + tarhandle=(tar_type=='c'); + /* + * Make sure that dbf points to stderr if we are using stdout for + * tar output + */ + if (tarhandle == 1) { + dbf = x_stderr; + } + if (!strcmp(argv[Optind], "-")) { + newOptind++; + } + + } else { + if (tar_type=='c' && (dry_run || strcmp(argv[Optind], "/dev/null")==0)) { + if (!dry_run) { + DEBUG(0,("Output is /dev/null, assuming dry_run\n")); + dry_run = True; + } + tarhandle=-1; + } else if ((tar_type=='x' && (tarhandle = sys_open(argv[Optind], O_RDONLY, 0)) == -1) + || (tar_type=='c' && (tarhandle=sys_creat(argv[Optind], 0644)) < 0)) { + DEBUG(0,("Error opening local file %s - %s\n", argv[Optind], strerror(errno))); + return(0); + } + newOptind++; } - tarhandle=-1; - } else - if ((tar_type=='x' && (tarhandle = sys_open(argv[Optind], O_RDONLY, 0)) == -1) - || (tar_type=='c' && (tarhandle=sys_creat(argv[Optind], 0644)) < 0)) - { - DEBUG(0,("Error opening local file %s - %s\n", - argv[Optind], strerror(errno))); - return(0); - } - } - return 1; + return newOptind; } diff --git a/source3/client/smbspool.c b/source3/client/smbspool.c index 68165792da..5daefec5a5 100644 --- a/source3/client/smbspool.c +++ b/source3/client/smbspool.c @@ -282,7 +282,7 @@ smb_connect(const char *workgroup, /* I - Workgroup */ get_myname(myname); nt_status = cli_full_connection(&c, myname, server, NULL, 0, share, "?????", - username, workgroup, password, 0, NULL); + username, workgroup, password, 0, Undefined, NULL); if (!NT_STATUS_IS_OK(nt_status)) { fprintf(stderr, "ERROR: Connection failed with error %s\n", nt_errstr(nt_status)); diff --git a/source3/client/tree.c b/source3/client/tree.c index 3b90d15f65..97ad7742e3 100644 --- a/source3/client/tree.c +++ b/source3/client/tree.c @@ -69,7 +69,7 @@ static void tree_error_message(gchar *message) { * workgroup type and return a path from there */ -static char path_string[1024]; +static pstring path_string; char *get_path(GtkWidget *item) { @@ -112,7 +112,7 @@ char *get_path(GtkWidget *item) * Now, build the path */ - snprintf(path_string, sizeof(path_string), "smb:/"); + pstrcpy( path_string, "smb:/" ); for (j = i - 1; j >= 0; j--) { @@ -151,7 +151,7 @@ static void cb_select_child (GtkWidget *root_tree, GtkWidget *child, char dirbuf[512]; struct smbc_dirent *dirp; struct stat st1; - char path[1024], path1[1024]; + pstring path, path1; g_print ("select_child called for root tree %p, subtree %p, child %p\n", root_tree, subtree, child); diff --git a/source3/configure.in b/source3/configure.in index fd7ee9fc30..f964bc719f 100644 --- a/source3/configure.in +++ b/source3/configure.in @@ -152,12 +152,10 @@ AC_SUBST(LIBSMBCLIENT) AC_SUBST(PRINTLIBS) AC_SUBST(AUTHLIBS) AC_SUBST(ACLLIBS) -AC_SUBST(ADSLIBS) AC_SUBST(PASSDBLIBS) AC_SUBST(IDMAP_LIBS) AC_SUBST(KRB5_LIBS) AC_SUBST(LDAP_LIBS) -AC_SUBST(LDAP_OBJ) AC_SUBST(SHLIB_PROGS) AC_SUBST(SMBWRAPPER) AC_SUBST(EXTRA_BIN_PROGS) @@ -289,7 +287,7 @@ dnl These have to be built static: default_static_modules="pdb_smbpasswd pdb_tdbsam rpc_lsa rpc_samr rpc_reg rpc_wks rpc_net rpc_dfs rpc_srv rpc_spoolss auth_rhosts auth_sam auth_unix auth_winbind auth_server auth_domain auth_builtin" dnl These are preferably build shared, and static if dlopen() is not available -default_shared_modules="vfs_recycle vfs_audit vfs_extd_audit vfs_netatalk vfs_fake_perms" +default_shared_modules="vfs_recycle vfs_audit vfs_extd_audit vfs_netatalk vfs_fake_perms vfs_default_quota" if test "x$developer" = xyes; then default_static_modules="$default_static_modules rpc_echo" @@ -552,7 +550,7 @@ AC_CHECK_HEADERS(shadow.h netinet/ip.h netinet/tcp.h netinet/in_systm.h netinet/ AC_CHECK_HEADERS(nss.h nss_common.h ns_api.h sys/security.h security/pam_appl.h security/pam_modules.h) AC_CHECK_HEADERS(stropts.h poll.h) AC_CHECK_HEADERS(sys/capability.h syscall.h sys/syscall.h) -AC_CHECK_HEADERS(sys/acl.h attr/xattr.h sys/cdefs.h glob.h) +AC_CHECK_HEADERS(sys/acl.h sys/attributes.h attr/xattr.h sys/cdefs.h glob.h) # For experimental utmp support (lastlog on some BSD-like systems) AC_CHECK_HEADERS(utmp.h utmpx.h lastlog.h) @@ -843,7 +841,7 @@ AC_CHECK_FUNCS(setpriv setgidx setuidx setgroups sysconf mktime rename ftruncate AC_CHECK_FUNCS(lstat64 fopen64 atexit grantpt dup2 lseek64 ftruncate64 readdir64) AC_CHECK_FUNCS(fseek64 fseeko64 ftell64 ftello64 setluid getpwanam setlinebuf) AC_CHECK_FUNCS(srandom random srand rand setenv usleep strcasecmp fcvt fcvtl symlink readlink) -AC_CHECK_FUNCS(syslog vsyslog getgrouplist timegm) +AC_CHECK_FUNCS(syslog vsyslog timegm) AC_CHECK_FUNCS(setlocale nl_langinfo) # setbuffer, shmget, shm_open are needed for smbtorture AC_CHECK_FUNCS(setbuffer shmget shm_open backtrace_symbols) @@ -866,6 +864,38 @@ AC_CHECK_FUNCS(pread _pread __pread pread64 _pread64 __pread64) AC_CHECK_FUNCS(pwrite _pwrite __pwrite pwrite64 _pwrite64 __pwrite64) AC_CHECK_FUNCS(open64 _open64 __open64 creat64) +# +# +# +case "$host_os" in + *linux*) + # glibc <= 2.3.2 has a broken getgrouplist + AC_TRY_RUN([ +#include +#include +main() { + /* glibc up to 2.3 has a broken getgrouplist */ +#if defined(__GLIBC__) && defined(__GLIBC_MINOR__) + int libc_major = __GLIBC__; + int libc_minor = __GLIBC_MINOR__; + + if (libc_major < 2) + exit(1); + if ((libc_major == 2) && (libc_minor <= 3)) + exit(1); +#endif + exit(0); +} +], [linux_getgrouplist_ok=yes], [linux_getgrouplist_ok=no]) + if test x"$linux_getgrouplist_ok" = x"yes"; then + AC_DEFINE(HAVE_GETGROUPLIST, 1, [Have good getgrouplist]) + fi + ;; + *) + AC_CHECK_FUNCS(getgrouplist) + ;; +esac + # # stat64 family may need on some systems, notably ReliantUNIX # @@ -946,6 +976,8 @@ AC_SEARCH_LIBS(getxattr, [attr]) AC_CHECK_FUNCS(getxattr lgetxattr fgetxattr listxattr llistxattr) AC_CHECK_FUNCS(flistxattr removexattr lremovexattr fremovexattr) AC_CHECK_FUNCS(setxattr lsetxattr fsetxattr) +AC_CHECK_FUNCS(attr_get attr_list attr_set attr_remove) +AC_CHECK_FUNCS(attr_getf attr_listf attr_setf attr_removef) # Assume non-shared by default and override below BLDSHARED="false" @@ -2095,14 +2127,105 @@ AC_ARG_WITH(dfs, AC_MSG_RESULT(no) ) +######################################################## +# Compile with LDAP support? + +with_ldap_support=auto +AC_MSG_CHECKING([for LDAP support]) + +AC_ARG_WITH(ldap, +[ --with-ldap LDAP support (default yes)], +[ case "$withval" in + yes|no) + with_ldap_support=$withval + ;; + esac ]) + +AC_MSG_RESULT($with_ldap_support) + +SMBLDAP="" +AC_SUBST(SMBLDAP) +if test x"$with_ldap_support" != x"no"; then + + ################################################################## + # first test for ldap.h and lber.h + # (ldap.h is required for this test) + AC_CHECK_HEADERS(ldap.h lber.h) + + if test x"$ac_cv_header_ldap_h" != x"yes"; then + if test x"$with_ldap_support" = x"yes"; then + AC_MSG_ERROR(ldap.h is needed for LDAP support) + else + AC_MSG_WARN(ldap.h is needed for LDAP support) + fi + + with_ldap_support=no + fi +fi + +if test x"$with_ldap_support" != x"no"; then + ac_save_LIBS=$LIBS + + ################################################################## + # we might need the lber lib on some systems. To avoid link errors + # this test must be before the libldap test + AC_CHECK_LIB_EXT(lber, LDAP_LIBS, ber_scanf) + + ######################################################## + # now see if we can find the ldap libs in standard paths + AC_CHECK_LIB_EXT(ldap, LDAP_LIBS, ldap_init) + + AC_CHECK_FUNC_EXT(ldap_domain2hostlist,$LDAP_LIBS) + + ######################################################## + # If we have LDAP, does it's rebind procedure take 2 or 3 arguments? + # Check found in pam_ldap 145. + AC_CHECK_FUNC_EXT(ldap_set_rebind_proc,$LDAP_LIBS) + + LIBS="$LIBS $LDAP_LIBS" + AC_CACHE_CHECK(whether ldap_set_rebind_proc takes 3 arguments, smb_ldap_cv_ldap_set_rebind_proc, [ + AC_TRY_COMPILE([ + #include + #include ], + [ldap_set_rebind_proc(0, 0, 0);], + [smb_ldap_cv_ldap_set_rebind_proc=3], + [smb_ldap_cv_ldap_set_rebind_proc=2] + ) + ]) + + AC_DEFINE_UNQUOTED(LDAP_SET_REBIND_PROC_ARGS, $smb_ldap_cv_ldap_set_rebind_proc, [Number of arguments to ldap_set_rebind_proc]) + + AC_CHECK_FUNC_EXT(ldap_initialize,$LDAP_LIBS) + + if test x"$ac_cv_lib_ext_ldap_ldap_init" = x"yes" -a x"$ac_cv_func_ext_ldap_domain2hostlist" = x"yes"; then + AC_DEFINE(HAVE_LDAP,1,[Whether ldap is available]) + default_static_modules="$default_static_modules pdb_ldap idmap_ldap"; + SMBLDAP="lib/smbldap.o" + with_ldap_support=yes + AC_MSG_CHECKING(whether LDAP support is used) + AC_MSG_RESULT(yes) + else + if test x"$with_ldap_support" = x"yes"; then + AC_MSG_ERROR(libldap is needed for LDAP support) + else + AC_MSG_WARN(libldap is needed for LDAP support) + fi + + LDAP_LIBS="" + with_ldap_support=no + fi + LIBS=$ac_save_LIBS +fi + + ################################################# # active directory support with_ads_support=auto -AC_MSG_CHECKING([whether to use Active Directory]) +AC_MSG_CHECKING([for Active Directory and krb5 support]) AC_ARG_WITH(ads, -[ --with-ads Active Directory support (default yes)], +[ --with-ads Active Directory support (default auto)], [ case "$withval" in yes|no) with_ads_support="$withval" @@ -2114,22 +2237,34 @@ AC_MSG_RESULT($with_ads_support) FOUND_KRB5=no KRB5_LIBS="" +if test x"$with_ldap_support" != x"yes"; then + if test x"$with_ads_support" = x"yes"; then + AC_MSG_ERROR(Active Directory Support requires LDAP support) + elif test x"$with_ads_support" != x"no"; then + AC_MSG_WARN(Active Directory Support requires LDAP support) + fi + with_ads_support=no +fi + if test x"$with_ads_support" != x"no"; then # Do no harm to the values of CFLAGS and LIBS while testing for # Kerberos support. - ac_save_CFLAGS="$CFLAGS" - ac_save_LIBS="$LIBS" - ################################################# # check for krb5-config from recent MIT and Heimdal kerberos 5 AC_PATH_PROG(KRB5_CONFIG, krb5-config) AC_MSG_CHECKING(for working krb5-config) if test -x "$KRB5_CONFIG"; then - LIBS="$LIBS `$KRB5_CONFIG --libs`" - CFLAGS="$CFLAGS `$KRB5_CONFIG --cflags | sed s/@INCLUDE_des@//`" - CPPFLAGS="$CPPFLAGS `$KRB5_CONFIG --cflags | sed s/@INCLUDE_des@//`" + ac_save_CFLAGS=$CFLAGS + CFLAGS="";export CFLAGS + ac_save_LDFLAGS=$LDFLAGS + LDFLAGS="";export LDFLAGS + KRB5_LIBS="`$KRB5_CONFIG --libs gssapi`" + KRB5_CFLAGS="`$KRB5_CONFIG --cflags | sed s/@INCLUDE_des@//`" + KRB5_CPPFLAGS="`$KRB5_CONFIG --cflags | sed s/@INCLUDE_des@//`" + CFLAGS=$ac_save_CFLAGS;export CFLAGS + LDFLAGS=$ac_save_LDFLAGS;export LDFLAGS FOUND_KRB5=yes AC_MSG_RESULT(yes) else @@ -2144,18 +2279,21 @@ if test x"$with_ads_support" != x"no"; then [ --with-krb5=base-dir Locate Kerberos 5 support (default=/usr)], [ case "$withval" in no) - AC_MSG_RESULT(no) + AC_MSG_RESULT(no krb5-path given) + ;; + yes) + AC_MSG_RESULT(/usr) + FOUND_KRB5=yes ;; *) - AC_MSG_RESULT(yes) - LIBS="$LIBS -lkrb5" - CFLAGS="$CFLAGS -I$withval/include" - CPPFLAGS="$CPPFLAGS -I$withval/include" - LDFLAGS="$LDFLAGS -L$withval/lib" + AC_MSG_RESULT($withval) + KRB5_CFLAGS="-I$withval/include" + KRB5_CPPFLAGS="-I$withval/include" + KRB5_LDFLAGS="-L$withval/lib" FOUND_KRB5=yes ;; esac ], - AC_MSG_RESULT(no) + AC_MSG_RESULT(no krb5-path given) ) fi @@ -2165,15 +2303,13 @@ if test x"$with_ads_support" != x"no"; then AC_MSG_CHECKING(for /usr/include/heimdal) if test -d /usr/include/heimdal; then if test -f /usr/lib/heimdal/lib/libkrb5.a; then - LIBS="$LIBS -lkrb5" - CFLAGS="$CFLAGS -I/usr/include/heimdal" - CPPFLAGS="$CPPFLAGS -I/usr/include/heimdal" - LDFLAGS="$LDFLAGS -L/usr/lib/heimdal/lib" + KRB5_CFLAGS="-I/usr/include/heimdal" + KRB5_CPPFLAGS="-I/usr/include/heimdal" + KRB5_LDFLAGS="-L/usr/lib/heimdal/lib" AC_MSG_RESULT(yes) else - LIBS="$LIBS -lkrb5" - CFLAGS="$CFLAGS -I/usr/include/heimdal" - CPPFLAGS="$CPPFLAGS -I/usr/include/heimdal" + KRB5_CFLAGS="-I/usr/include/heimdal" + KRB5_CPPFLAGS="-I/usr/include/heimdal" AC_MSG_RESULT(yes) fi else @@ -2186,16 +2322,25 @@ if test x"$with_ads_support" != x"no"; then # see if this box has the RedHat location for kerberos AC_MSG_CHECKING(for /usr/kerberos) if test -d /usr/kerberos -a -f /usr/kerberos/lib/libkrb5.a; then - LIBS="$LIBS -lkrb5" - LDFLAGS="$LDFLAGS -L/usr/kerberos/lib" - CFLAGS="$CFLAGS -I/usr/kerberos/include" - CPPFLAGS="$CPPFLAGS -I/usr/kerberos/include" + KRB5_LDFLAGS="-L/usr/kerberos/lib" + KRB5_CFLAGS="-I/usr/kerberos/include" + KRB5_CPPFLAGS="-I/usr/kerberos/include" AC_MSG_RESULT(yes) else AC_MSG_RESULT(no) fi fi + ac_save_CFLAGS=$CFLAGS + ac_save_CPPFLAGS=$CPPFLAGS + ac_save_LDFLAGS=$LDFLAGS + + CFLAGS="$CFLAGS $KRB5_CFLAGS" + CPPFLAGS="$CPPFLAGS $KRB5_CPPFLAGS" + LDFLAGS="$LDFLAGS $KRB5_LDFLAGS" + + KRB5_LIBS="$KRB5_LDFLAGS $KRB5_LIBS" + # 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 @@ -2215,24 +2360,17 @@ if test x"$with_ads_support" != x"no"; then # Turn off AD support and restore CFLAGS and LIBS variables with_ads_support="no" - - CFLAGS="$ac_save_CFLAGS" - LIBS="$ac_save_LIBS" - - else - - # Get rid of case where $with_ads_support=auto - - with_ads_support="yes" - + + CFLAGS=$ac_save_CFLAGS + CPPFLAGS=$ac_save_CPPFLAGS + LDFLAGS=$ac_save_LDFLAGS fi fi # Now we have determined whether we really want ADS support -if test x"$with_ads_support" = x"yes"; then - - AC_DEFINE(WITH_ADS,1,[Whether to include Active Directory support]) +if test x"$with_ads_support" != x"no"; then + ac_save_LIBS=$LIBS # now check for gssapi headers. This is also done here to allow for # different kerberos include paths @@ -2240,62 +2378,46 @@ if test x"$with_ads_support" = x"yes"; then ################################################################## # we might need the k5crypto and com_err libraries on some systems - AC_CHECK_LIB(com_err, _et_list) - AC_CHECK_LIB(k5crypto, krb5_encrypt_data) + AC_CHECK_LIB_EXT(com_err, KRB5_LIBS, _et_list) + AC_CHECK_LIB_EXT(k5crypto, KRB5_LIBS, krb5_encrypt_data) # Heimdal checks. - AC_CHECK_LIB(crypto, des_set_key) - AC_CHECK_LIB(asn1, copy_Authenticator) - AC_CHECK_LIB(roken, roken_getaddrinfo_hostspec) + AC_CHECK_LIB_EXT(crypto, KRB5_LIBS, des_set_key) + AC_CHECK_LIB_EXT(asn1, KRB5_LIBS, copy_Authenticator) + AC_CHECK_LIB_EXT(roken, KRB5_LIBS, roken_getaddrinfo_hostspec) # Heimdal checks. On static Heimdal gssapi must be linked before krb5. - AC_CHECK_LIB(gssapi, gss_display_status, [LIBS="$LIBS -lgssapi -lkrb5"; - AC_DEFINE(HAVE_GSSAPI,1,[Whether GSSAPI is available])]) - - AC_CHECK_LIB(krb5, krb5_set_real_time, - [AC_DEFINE(HAVE_KRB5_SET_REAL_TIME,1, - [Whether krb5_set_real_time is available])]) - AC_CHECK_LIB(krb5, krb5_set_default_in_tkt_etypes, - [AC_DEFINE(HAVE_KRB5_SET_DEFAULT_IN_TKT_ETYPES,1, - [Whether krb5_set_default_in_tkt_etypes, is available])]) - AC_CHECK_LIB(krb5, krb5_set_default_tgs_ktypes, - [AC_DEFINE(HAVE_KRB5_SET_DEFAULT_TGS_KTYPES,1, - [Whether krb5_set_default_tgs_ktypes is available])]) - - AC_CHECK_LIB(krb5, krb5_principal2salt, - [AC_DEFINE(HAVE_KRB5_PRINCIPAL2SALT,1, - [Whether krb5_principal2salt is available])]) - AC_CHECK_LIB(krb5, krb5_use_enctype, - [AC_DEFINE(HAVE_KRB5_USE_ENCTYPE,1, - [Whether krb5_use_enctype is available])]) - AC_CHECK_LIB(krb5, krb5_string_to_key, - [AC_DEFINE(HAVE_KRB5_STRING_TO_KEY,1, - [Whether krb5_string_to_key is available])]) - AC_CHECK_LIB(krb5, krb5_get_pw_salt, - [AC_DEFINE(HAVE_KRB5_GET_PW_SALT,1, - [Whether krb5_get_pw_salt is available])]) - AC_CHECK_LIB(krb5, krb5_string_to_key_salt, - [AC_DEFINE(HAVE_KRB5_STRING_TO_KEY_SALT,1, - [Whether krb5_string_to_key_salt is available])]) - AC_CHECK_LIB(krb5, krb5_auth_con_setkey, - [AC_DEFINE(HAVE_KRB5_AUTH_CON_SETKEY,1, - [Whether krb5_auth_con_setkey is available])]) - AC_CHECK_LIB(krb5, krb5_auth_con_setuseruserkey, - [AC_DEFINE(HAVE_KRB5_AUTH_CON_SETUSERUSERKEY,1, - [Whether krb5_auth_con_setuseruserkey is available])]) - AC_CHECK_LIB(krb5, krb5_locate_kdc, - [AC_DEFINE(HAVE_KRB5_LOCATE_KDC,1, - [Whether krb5_locate_kdc is available])]) - AC_CHECK_LIB(krb5, krb5_get_permitted_enctypes, - [AC_DEFINE(HAVE_KRB5_GET_PERMITTED_ENCTYPES,1, - [Whether krb5_get_permitted_enctypes is available])]) - AC_CHECK_LIB(krb5, krb5_get_default_in_tkt_etypes, - [AC_DEFINE(HAVE_KRB5_GET_DEFAULT_IN_TKT_ETYPES,1, - [Whether krb5_get_default_in_tkt_etypes is available])]) - AC_CHECK_LIB(krb5, krb5_free_ktypes, - [AC_DEFINE(HAVE_KRB5_FREE_KTYPES,1, - [Whether krb5_free_ktypes is available])]) + AC_CHECK_LIB_EXT(gssapi, KRB5_LIBS, gss_display_status,[],[], + AC_DEFINE(HAVE_GSSAPI,1,[Whether GSSAPI is available])) + ######################################################## + # now see if we can find the krb5 libs in standard paths + # or as specified above + AC_CHECK_LIB_EXT(krb5, KRB5_LIBS, krb5_mk_req_extended) + + ######################################################## + # now see if we can find the gssapi libs in standard paths + AC_CHECK_LIB_EXT(gssapi_krb5, KRB5_LIBS,gss_display_status,[],[], + AC_DEFINE(HAVE_GSSAPI,1,[Whether GSSAPI is available])) + + AC_CHECK_FUNC_EXT(krb5_set_real_time, $KRB5_LIBS) + AC_CHECK_FUNC_EXT(krb5_set_default_in_tkt_etypes, $KRB5_LIBS) + AC_CHECK_FUNC_EXT(krb5_set_default_tgs_ktypes, $KRB5_LIBS) + AC_CHECK_FUNC_EXT(krb5_principal2salt, $KRB5_LIBS) + AC_CHECK_FUNC_EXT(krb5_use_enctype, $KRB5_LIBS) + AC_CHECK_FUNC_EXT(krb5_string_to_key, $KRB5_LIBS) + AC_CHECK_FUNC_EXT(krb5_get_pw_salt, $KRB5_LIBS) + AC_CHECK_FUNC_EXT(krb5_string_to_key_salt, $KRB5_LIBS) + AC_CHECK_FUNC_EXT(krb5_auth_con_setkey, $KRB5_LIBS) + AC_CHECK_FUNC_EXT(krb5_auth_con_setuseruserkey, $KRB5_LIBS) + AC_CHECK_FUNC_EXT(krb5_locate_kdc, $KRB5_LIBS) + AC_CHECK_FUNC_EXT(krb5_get_permitted_enctypes, $KRB5_LIBS) + AC_CHECK_FUNC_EXT(krb5_get_default_in_tkt_etypes, $KRB5_LIBS) + AC_CHECK_FUNC_EXT(krb5_free_ktypes, $KRB5_LIBS) + AC_CHECK_FUNC_EXT(krb5_principal_get_comp_string, $KRB5_LIBS) + + LIBS="$LIBS $KRB5_LIBS" + AC_CACHE_CHECK([for addrtype in krb5_address], samba_cv_HAVE_ADDRTYPE_IN_KRB5_ADDRESS,[ AC_TRY_COMPILE([#include ], @@ -2355,87 +2477,34 @@ if test x"$with_ads_support" = x"yes"; then [Whether the ENCTYPE_ARCFOUR_HMAC_MD5 key type is available]) fi - ######################################################## - # now see if we can find the krb5 libs in standard paths - # or as specified above - AC_CHECK_LIB(krb5, krb5_mk_req_extended, [KRB5_LIBS="$LIBS -lkrb5"; - KRB5_CFLAGS="$CFLAGS"; - AC_DEFINE(HAVE_KRB5,1,[Whether KRB5 is available])]) + AC_CACHE_CHECK([for the krb5_princ_component macro], + samba_cv_HAVE_KRB5_PRINC_COMPONENT,[ + AC_TRY_LINK([#include ], + [const krb5_data *pkdata; krb5_context context; krb5_principal principal; pkdata = krb5_princ_component(context, principal, 0);], + samba_cv_HAVE_KRB5_PRINC_COMPONENT=yes, + samba_cv_HAVE_KRB5_PRINC_COMPONENT=no)]) - ######################################################## - # now see if we can find the gssapi libs in standard paths - AC_CHECK_LIB(gssapi_krb5, gss_display_status, - [KRB5_LIBS="$KRB5_LIBS -lgssapi_krb5"; - AC_DEFINE(HAVE_GSSAPI,1,[Whether GSSAPI is available])]) - - CFLAGS="$ac_save_CFLAGS" - LIBS="$ac_save_LIBS" -fi - -######################################################## -# Compile with LDAP support? - -LDAP_OBJ="" -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"$samba_cv_HAVE_KRB5_PRINC_COMPONENT" = x"yes"; then + AC_DEFINE(HAVE_KRB5_PRINC_COMPONENT,1, + [Whether krb5_princ_component is available]) + fi -SMBLDAP="" -if test x"$with_ldap_support" = x"yes"; then - ac_save_LIBS="$LIBS" - LIBS="" - ################################################################## - # 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) - - ######################################################## - # now see if we can find the ldap libs in standard paths - if test x$have_ldap != xyes; then - AC_CHECK_LIB(ldap, ldap_init, [ - LIBS="$LIBS -lldap"; - AC_CHECK_LIB(ldap, ldap_domain2hostlist, [ - AC_DEFINE(HAVE_LDAP,1,[Whether ldap is available]) - AC_CHECK_HEADERS([ldap.h lber.h], - [default_static_modules="$default_static_modules pdb_ldap idmap_ldap"; - SMBLDAP="lib/smbldap.o"]) - ]) - ]) - - ######################################################## - # If we have LDAP, does it's rebind procedure take 2 or 3 arguments? - # Check found in pam_ldap 145. - AC_CHECK_FUNCS(ldap_set_rebind_proc) - AC_CACHE_CHECK(whether ldap_set_rebind_proc takes 3 arguments, pam_ldap_cv_ldap_set_rebind_proc, [ - AC_TRY_COMPILE([ - #include - #include ], [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, [Number of arguments to ldap_set_rebind_proc]) - AC_CHECK_FUNCS(ldap_initialize) - fi - - AC_SUBST(SMBLDAP) - LDAP_LIBS="$LIBS"; - LIBS="$ac_save_LIBS"; -else - # Can't have ADS support without LDAP + if test x"$ac_cv_lib_ext_krb5_krb5_mk_req_extended" = x"yes"; then + AC_DEFINE(HAVE_KRB5,1,[Whether to have KRB5 support]) + AC_DEFINE(WITH_ADS,1,[Whether to include Active Directory support]) + AC_MSG_CHECKING(whether Active Directory and krb5 support is used) + AC_MSG_RESULT(yes) + else if test x"$with_ads_support" = x"yes"; then - AC_MSG_ERROR(Active directory support requires LDAP) + AC_MSG_ERROR(libkrb5 is needed for Active Directory support) + else + AC_MSG_WARN(libkrb5 is needed for Active Directory support) fi -fi - -if test x"$with_ads_support" = x"yes"; then - ADSLIBS="$LDAP_LIBS $KRB5_LIBS" + KRB5_LIBS="" + with_ads_support=no + fi + LIBS="$ac_save_LIBS" fi ######################################################## @@ -3641,7 +3710,7 @@ WINBIND_WINS_NSS="nsswitch/libnss_wins.$SHLIBEXT" WINBIND_NSS_LDSHFLAGS=$LDSHFLAGS case "$host_os" in - *linux*) + *linux*|*freebsd*) WINBIND_NSS_EXTRA_OBJS="nsswitch/winbind_nss_linux.o" ;; *irix*) @@ -3887,6 +3956,7 @@ SMB_MODULE(vfs_audit, \$(VFS_AUDIT_OBJ), "bin/audit.$SHLIBEXT", VFS) SMB_MODULE(vfs_extd_audit, \$(VFS_EXTD_AUDIT_OBJ), "bin/extd_audit.$SHLIBEXT", VFS) SMB_MODULE(vfs_netatalk, \$(VFS_NETATALK_OBJ), "bin/netatalk.$SHLIBEXT", VFS) SMB_MODULE(vfs_fake_perms, \$(VFS_FAKE_PERMS_OBJ), "bin/fake_perms.$SHLIBEXT", VFS) +SMB_MODULE(vfs_default_quota, \$(VFS_DEFAULT_QUOTA_OBJ), "bin/default_quota.$SHLIBEXT", VFS) SMB_SUBSYSTEM(VFS) AC_DEFINE_UNQUOTED(STRING_STATIC_MODULES, "$string_static_modules", [String list of builtin modules]) @@ -3903,10 +3973,10 @@ fi AC_MSG_RESULT([Using libraries:]) AC_MSG_RESULT([ LIBS = $LIBS]) -if test x"$with_ads_support" = x"yes"; then +if test x"$with_ads_support" != x"no"; then AC_MSG_RESULT([ KRB5_LIBS = $KRB5_LIBS]) fi -if test x"$with_ldap_support" = x"yes"; then +if test x"$with_ldap_support" != x"no"; then AC_MSG_RESULT([ LDAP_LIBS = $LDAP_LIBS]) fi diff --git a/source3/dynconfig.c b/source3/dynconfig.c index 4577c3947c..34c716926c 100644 --- a/source3/dynconfig.c +++ b/source3/dynconfig.c @@ -1,7 +1,7 @@ /* Unix SMB/CIFS implementation. Copyright (C) 2001 by Martin Pool - Copyright (C) 2003 by Anthony Liguori + Copyright (C) 2003 by Jim McDonough 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 diff --git a/source3/groupdb/mapping.c b/source3/groupdb/mapping.c index 3d2af5d0ba..cd903fa28b 100644 --- a/source3/groupdb/mapping.c +++ b/source3/groupdb/mapping.c @@ -509,7 +509,7 @@ BOOL get_domain_group_from_sid(DOM_SID sid, GROUP_MAP *map) return False; } - DEBUG(10, ("get_domain_group_from_sid: SID is mapped to gid:%d\n",map->gid)); + DEBUG(10, ("get_domain_group_from_sid: SID is mapped to gid:%lu\n",(unsigned long)map->gid)); if ( (grp=getgrgid(map->gid)) == NULL) { DEBUG(10, ("get_domain_group_from_sid: gid DOESN'T exist in UNIX security\n")); diff --git a/source3/include/authdata.h b/source3/include/authdata.h index 0798b72bdf..9d80745fb0 100644 --- a/source3/include/authdata.h +++ b/source3/include/authdata.h @@ -1,7 +1,7 @@ /* Unix SMB/CIFS implementation. Kerberos authorization data - Copyright (C) Jim McDonough 2003 + Copyright (C) Jim McDonough 2003 This program is free software; you can redistribute it and/or modify diff --git a/source3/include/byteorder.h b/source3/include/byteorder.h index c262dd2d33..0eef557306 100644 --- a/source3/include/byteorder.h +++ b/source3/include/byteorder.h @@ -105,7 +105,7 @@ it also defines lots of intermediate macros, just ignore those :-) #define CAREFUL_ALIGNMENT 1 #endif -#define CVAL(buf,pos) (((const unsigned char *)(buf))[pos]) +#define CVAL(buf,pos) ((unsigned)(((const unsigned char *)(buf))[pos])) #define CVAL_NC(buf,pos) (((unsigned char *)(buf))[pos]) /* Non-const version of CVAL */ #define PVAL(buf,pos) (CVAL(buf,pos)) #define SCVAL(buf,pos,val) (CVAL_NC(buf,pos) = (val)) diff --git a/source3/include/charset.h b/source3/include/charset.h index c56984ca7b..f999a9cf72 100644 --- a/source3/include/charset.h +++ b/source3/include/charset.h @@ -24,9 +24,9 @@ typedef enum {CH_UCS2=0, CH_UNIX=1, CH_DISPLAY=2, CH_DOS=3, CH_UTF8=4} charset_t #define NUM_CHARSETS 5 -/* - * for each charset we have a function that pulls from that charset to - * a ucs2 buffer, and a function that pushes to a ucs2 buffer +/* + * for each charset we have a function that pushes from that charset to a ucs2 + * buffer, and a function that pulls from ucs2 buffer to that charset. * */ struct charset_functions { diff --git a/source3/include/client.h b/source3/include/client.h index fad2c099b9..598e6c0bda 100644 --- a/source3/include/client.h +++ b/source3/include/client.h @@ -57,18 +57,6 @@ struct print_job_info time_t t; }; -typedef struct smb_sign_info { - void (*sign_outgoing_message)(struct cli_state *cli); - BOOL (*check_incoming_message)(struct cli_state *cli); - void (*free_signing_context)(struct cli_state *cli); - void *signing_context; - - BOOL negotiated_smb_signing; - BOOL allow_smb_signing; - BOOL doing_signing; - BOOL mandatory_signing; -} smb_sign_info; - struct cli_state { int port; int fd; diff --git a/source3/include/dynconfig.h b/source3/include/dynconfig.h index ce256f0613..a74d77e41f 100644 --- a/source3/include/dynconfig.h +++ b/source3/include/dynconfig.h @@ -1,7 +1,7 @@ /* Unix SMB/CIFS implementation. Copyright (C) 2001 by Martin Pool - Copyright (C) 2003 by Anthony Liguori + Copyright (C) 2003 by Jim McDonough 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 diff --git a/source3/include/idmap.h b/source3/include/idmap.h index ae7e4e5101..20b1015285 100644 --- a/source3/include/idmap.h +++ b/source3/include/idmap.h @@ -5,7 +5,7 @@ Idmap headers - Copyright (C) Anthony Liguori 2003 + Copyright (C) Jim McDonough 2003 Copyright (C) Simo Sorce 2003 This library is free software; you can redistribute it and/or diff --git a/source3/include/includes.h b/source3/include/includes.h index edaeda3abe..eb7f73b9d3 100644 --- a/source3/include/includes.h +++ b/source3/include/includes.h @@ -835,6 +835,8 @@ extern int errno; #include "nsswitch/winbind_client.h" +#include "spnego.h" + /* * Type for wide character dirent structure. * Only d_name is defined by POSIX. @@ -1232,6 +1234,14 @@ int snprintf(char *,size_t ,const char *, ...) PRINTF_ATTRIBUTE(3,4); int asprintf(char **,const char *, ...) PRINTF_ATTRIBUTE(2,3); #endif +/* Fix prototype problem with non-C99 compliant snprintf implementations, esp + HPUX 11. Don't change the sense of this #if statement. Read the comments + in lib/snprint.c if you think you need to. See also bugzilla bug 174. */ + +#if !defined(HAVE_SNPRINTF) || !defined(HAVE_C99_VSNPRINTF) +#define snprintf smb_snprintf +#endif + void sys_adminlog(int priority, const char *format_str, ...) PRINTF_ATTRIBUTE(2,3); int pstr_sprintf(pstring s, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); @@ -1288,7 +1298,7 @@ krb5_const_principal get_principal_from_tkt(krb5_ticket *tkt); krb5_error_code krb5_locate_kdc(krb5_context ctx, const krb5_data *realm, struct sockaddr **addr_pp, int *naddrs, int get_masters); krb5_error_code get_kerberos_allowed_etypes(krb5_context context, krb5_enctype **enctypes); void free_kerberos_etypes(krb5_context context, krb5_enctype *enctypes); -BOOL get_krb5_smb_session_key(krb5_context context, krb5_auth_context auth_context, uint8 session_key[16]); +BOOL get_krb5_smb_session_key(krb5_context context, krb5_auth_context auth_context, uint8 session_key[16], BOOL remote); #endif /* HAVE_KRB5 */ /* TRUE and FALSE are part of the C99 standard and gcc, but diff --git a/source3/include/popt_common.h b/source3/include/popt_common.h index 57850bf682..6db30fbc0a 100644 --- a/source3/include/popt_common.h +++ b/source3/include/popt_common.h @@ -41,6 +41,7 @@ struct user_auth_info { pstring password; BOOL got_pass; BOOL use_kerberos; + int signing_state; }; extern struct user_auth_info cmdline_auth_info; diff --git a/source3/include/rpc_ds.h b/source3/include/rpc_ds.h index c01d10554e..7350fdba1f 100644 --- a/source3/include/rpc_ds.h +++ b/source3/include/rpc_ds.h @@ -28,6 +28,10 @@ #define DS_GETPRIMDOMINFO 0x00 +/* Opcodes available on PIPE_NETLOGON */ + +#define DS_ENUM_DOM_TRUSTS 0x28 + /* macros for RPC's */ @@ -50,10 +54,9 @@ typedef struct GUID domain_guid; UNISTR2 netbios_domain; - /* these 2 might be reversed in order. I can't tell from - my tests as both values are the same --jerry */ - UNISTR2 dns_domain; - UNISTR2 forest_domain; + + UNISTR2 dns_domain; /* our dns domain */ + UNISTR2 forest_domain; /* root domain of the forest to which we belong */ } DSROLE_PRIMARY_DOMAIN_INFO_BASIC; typedef struct @@ -85,7 +88,58 @@ typedef struct NTSTATUS status; } DS_R_GETPRIMDOMINFO; +typedef struct { + /* static portion of structure */ + uint32 netbios_ptr; + uint32 dns_ptr; + uint32 flags; + uint32 parent_index; + uint32 trust_type; + uint32 trust_attributes; + uint32 sid_ptr; + GUID guid; + + UNISTR2 netbios_domain; + UNISTR2 dns_domain; + DOM_SID2 sid; + +} DS_DOMAIN_TRUSTS; + +typedef struct { + + uint32 ptr; + uint32 max_count; + DS_DOMAIN_TRUSTS *trusts; + +} DS_DOMAIN_TRUSTS_CTR; + +#define DS_DOMAIN_IN_FOREST 0x0001 /* domains in the forest to which + we belong; even different domain trees */ +#define DS_DOMAIN_DIRECT_OUTBOUND 0x0002 /* trusted domains */ +#define DS_DOMAIN_TREE_ROOT 0x0004 /* root of our forest; also available in + DsRoleGetPrimaryDomainInfo() */ +#define DS_DOMAIN_PRIMARY 0x0008 /* our domain */ +#define DS_DOMAIN_NATIVE_MODE 0x0010 /* native mode AD servers */ +#define DS_DOMAIN_DIRECT_INBOUND 0x0020 /* trusting domains */ + +/* DS_Q_ENUM_DOM_TRUSTS - DsEnumerateDomainTrusts() request */ +typedef struct +{ + uint32 server_ptr; + UNISTR2 server; + uint32 flags; + +} DS_Q_ENUM_DOM_TRUSTS; + +/* DS_R_ENUM_DOM_TRUSTS - DsEnumerateDomainTrusts() response */ +typedef struct +{ + uint32 num_domains; + DS_DOMAIN_TRUSTS_CTR domains; + + NTSTATUS status; +} DS_R_ENUM_DOM_TRUSTS; #endif /* _RPC_DS_H */ diff --git a/source3/include/rpc_samr.h b/source3/include/rpc_samr.h index 7d28a0f3a7..8ec274176a 100644 --- a/source3/include/rpc_samr.h +++ b/source3/include/rpc_samr.h @@ -5,8 +5,7 @@ Copyright (C) Luke Kenneth Casson Leighton 1996-2000 Copyright (C) Paul Ashton 1997-2000 Copyright (C) Jean François Micouleau 1998-2001 - Copyright (C) Anthony Liguori 2002 - Copyright (C) Jim McDonough 2002 + Copyright (C) Jim McDonough 2002 This program is free software; you can redistribute it and/or modify diff --git a/source3/include/rpc_secdes.h b/source3/include/rpc_secdes.h index fb7060cde3..5e718f8167 100644 --- a/source3/include/rpc_secdes.h +++ b/source3/include/rpc_secdes.h @@ -305,12 +305,12 @@ typedef struct standard_mapping { SA_RIGHT_FILE_EXECUTE) -/* SAM Object specific access rights */ +/* SAM server specific access rights */ -#define SA_RIGHT_SAM_UNKNOWN_1 0x00000001 +#define SA_RIGHT_SAM_CONNECT_SERVER 0x00000001 #define SA_RIGHT_SAM_SHUTDOWN_SERVER 0x00000002 -#define SA_RIGHT_SAM_UNKNOWN_4 0x00000004 -#define SA_RIGHT_SAM_UNKNOWN_8 0x00000008 +#define SA_RIGHT_SAM_INITIALISE_SERVER 0x00000004 +#define SA_RIGHT_SAM_CREATE_DOMAIN 0x00000008 #define SA_RIGHT_SAM_ENUM_DOMAINS 0x00000010 #define SA_RIGHT_SAM_OPEN_DOMAIN 0x00000020 @@ -326,14 +326,14 @@ typedef struct standard_mapping { #define GENERIC_RIGHTS_SAM_WRITE \ (STANDARD_RIGHTS_WRITE_ACCESS | \ - SA_RIGHT_SAM_UNKNOWN_8 | \ - SA_RIGHT_SAM_UNKNOWN_4 | \ + SA_RIGHT_SAM_CREATE_DOMAIN | \ + SA_RIGHT_SAM_INITIALISE_SERVER | \ SA_RIGHT_SAM_SHUTDOWN_SERVER) #define GENERIC_RIGHTS_SAM_EXECUTE \ (STANDARD_RIGHTS_EXECUTE_ACCESS | \ SA_RIGHT_SAM_OPEN_DOMAIN | \ - SA_RIGHT_SAM_UNKNOWN_1) + SA_RIGHT_SAM_CONNECT_SERVER) /* Domain Object specific access rights */ @@ -388,8 +388,8 @@ typedef struct standard_mapping { #define SA_RIGHT_USER_CHANGE_PASSWORD 0x00000040 #define SA_RIGHT_USER_SET_PASSWORD 0x00000080 #define SA_RIGHT_USER_GET_GROUPS 0x00000100 -#define SA_RIGHT_USER_UNKNOWN_200 0x00000200 -#define SA_RIGHT_USER_UNKNOWN_400 0x00000400 +#define SA_RIGHT_USER_READ_GROUP_MEM 0x00000200 +#define SA_RIGHT_USER_CHANGE_GROUP_MEM 0x00000400 #define SA_RIGHT_USER_ALL_ACCESS 0x000007FF @@ -399,7 +399,7 @@ typedef struct standard_mapping { #define GENERIC_RIGHTS_USER_READ \ (STANDARD_RIGHTS_READ_ACCESS | \ - SA_RIGHT_USER_UNKNOWN_200 | \ + SA_RIGHT_USER_READ_GROUP_MEM | \ SA_RIGHT_USER_GET_GROUPS | \ SA_RIGHT_USER_ACCT_FLAGS_EXPIRY | \ SA_RIGHT_USER_GET_LOGONINFO | \ diff --git a/source3/include/smb.h b/source3/include/smb.h index d2714e78bc..deeb61034d 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -42,6 +42,7 @@ #define SMB_PORT2 139 #define SMB_PORTS "445 139" +#define Undefined (-1) #define False (0) #define True (1) #define Auto (2) @@ -79,9 +80,7 @@ typedef int BOOL; #define READ_TIMEOUT 1 #define READ_EOF 2 #define READ_ERROR 3 - -/* This error code can go into the client smb_rw_error. */ -#define WRITE_ERROR 4 +#define WRITE_ERROR 4 /* This error code can go into the client smb_rw_error. */ #define READ_BAD_SIG 5 #define DIR_STRUCT_SIZE 43 @@ -707,13 +706,14 @@ struct bitmap { unsigned int n; }; -#define FLAG_BASIC 0x0001 /* fundamental options */ +/* The following flags are used in SWAT */ +#define FLAG_BASIC 0x0001 /* Display only in BASIC view */ #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_ADVANCED 0x0020 /* Parameters that will be visible in advanced view */ +#define FLAG_DEVELOPER 0x0040 /* No longer used */ #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. */ @@ -1630,4 +1630,18 @@ struct ip_service { unsigned port; }; +/* Used by the SMB signing functions. */ + +typedef struct smb_sign_info { + void (*sign_outgoing_message)(char *outbuf, struct smb_sign_info *si); + BOOL (*check_incoming_message)(char *inbuf, struct smb_sign_info *si); + void (*free_signing_context)(struct smb_sign_info *si); + void *signing_context; + + BOOL negotiated_smb_signing; + BOOL allow_smb_signing; + BOOL doing_signing; + BOOL mandatory_signing; +} smb_sign_info; + #endif /* _SMB_H */ diff --git a/source3/include/smbldap.h b/source3/include/smbldap.h index 589d01aa6d..826fc3c55a 100644 --- a/source3/include/smbldap.h +++ b/source3/include/smbldap.h @@ -132,6 +132,9 @@ struct smbldap_state { char *bind_secret; unsigned int num_failures; + + time_t last_use; + smb_event_id_t event_id; }; #endif /* HAVE_LDAP */ diff --git a/source3/include/sysquotas.h b/source3/include/sysquotas.h index cfdac0609a..b803e6277a 100644 --- a/source3/include/sysquotas.h +++ b/source3/include/sysquotas.h @@ -189,6 +189,22 @@ #define SMB_QUOTAS_NO_LIMIT ((SMB_BIG_UINT)(0)) #define SMB_QUOTAS_NO_SPACE ((SMB_BIG_UINT)(1)) +#define SMB_QUOTAS_SET_NO_LIMIT(dp) \ +{\ + (dp)->softlimit = SMB_QUOTAS_NO_LIMIT;\ + (dp)->hardlimit = SMB_QUOTAS_NO_LIMIT;\ + (dp)->isoftlimit = SMB_QUOTAS_NO_LIMIT;\ + (dp)->ihardlimit = SMB_QUOTAS_NO_LIMIT;\ +} + +#define SMB_QUOTAS_SET_NO_SPACE(dp) \ +{\ + (dp)->softlimit = SMB_QUOTAS_NO_SPACE;\ + (dp)->hardlimit = SMB_QUOTAS_NO_SPACE;\ + (dp)->isoftlimit = SMB_QUOTAS_NO_SPACE;\ + (dp)->ihardlimit = SMB_QUOTAS_NO_SPACE;\ +} + typedef struct _SMB_DISK_QUOTA { enum SMB_QUOTA_TYPE qtype; SMB_BIG_UINT bsize; diff --git a/source3/include/version.h b/source3/include/version.h index 5e2d47e1de..68bc140daf 100644 --- a/source3/include/version.h +++ b/source3/include/version.h @@ -1 +1 @@ -#define VERSION "3.0.0beta3" +#define VERSION "3.0.0rc1" diff --git a/source3/include/vfs.h b/source3/include/vfs.h index 924d706321..452f4dc23b 100644 --- a/source3/include/vfs.h +++ b/source3/include/vfs.h @@ -466,6 +466,9 @@ typedef struct vfs_handle_struct { } \ } +/* Check whether module-specific data handle was already allocated or not */ +#define SMB_VFS_HANDLE_TEST_DATA(handle) ( !(handle) || !(handle)->data ? False : True ) + #define SMB_VFS_OP(x) ((void *) x) diff --git a/source3/lib/account_pol.c b/source3/lib/account_pol.c index e8b382c7ab..dc131985a1 100644 --- a/source3/lib/account_pol.c +++ b/source3/lib/account_pol.c @@ -53,7 +53,7 @@ BOOL init_account_policy(void) account_policy_set(AP_MIN_PASSWORD_LEN, MINPASSWDLENGTH); /* 5 chars minimum */ account_policy_set(AP_PASSWORD_HISTORY, 0); /* don't keep any old password */ account_policy_set(AP_USER_MUST_LOGON_TO_CHG_PASS, 0); /* don't force user to logon */ - account_policy_set(AP_MAX_PASSWORD_AGE, MAX_PASSWORD_AGE); /* 21 days */ + account_policy_set(AP_MAX_PASSWORD_AGE, (uint32)-1); /* don't expire */ account_policy_set(AP_MIN_PASSWORD_AGE, 0); /* 0 days */ account_policy_set(AP_LOCK_ACCOUNT_DURATION, 0); /* lockout for 0 minutes */ account_policy_set(AP_RESET_COUNT_TIME, 0); /* reset immediatly */ diff --git a/source3/lib/charcnv.c b/source3/lib/charcnv.c index 4e9c2c1592..ca5e378970 100644 --- a/source3/lib/charcnv.c +++ b/source3/lib/charcnv.c @@ -190,8 +190,8 @@ size_t convert_string(charset_t from, charset_t to, break; case E2BIG: reason="No more room"; - DEBUG(0, ("convert_string: Required %d, available %d\n", - srclen, destlen)); + DEBUG(0, ("convert_string: Required %lu, available %lu\n", + (unsigned long)srclen, (unsigned long)destlen)); /* we are not sure we need srclen bytes, may be more, may be less. We only know we need more than destlen @@ -319,8 +319,7 @@ size_t unix_strupper(const char *src, size_t srclen, char *dest, size_t destlen) size_t size; smb_ucs2_t *buffer; - size = convert_string_allocate(CH_UNIX, CH_UCS2, src, srclen, - (void **) &buffer); + size = push_ucs2_allocate(&buffer, src); if (size == -1) { smb_panic("failed to create UCS2 buffer"); } @@ -334,6 +333,33 @@ size_t unix_strupper(const char *src, size_t srclen, char *dest, size_t destlen) return size; } +/** + strdup() a unix string to upper case. +**/ + +char *strdup_upper(const char *s) +{ + size_t size; + smb_ucs2_t *buffer; + char *out_buffer; + + size = push_ucs2_allocate(&buffer, s); + if (size == -1) { + return NULL; + } + + strupper_w(buffer); + + size = pull_ucs2_allocate(&out_buffer, buffer); + SAFE_FREE(buffer); + + if (size == -1) { + return NULL; + } + + return out_buffer; +} + size_t unix_strlower(const char *src, size_t srclen, char *dest, size_t destlen) { size_t size; @@ -353,6 +379,32 @@ size_t unix_strlower(const char *src, size_t srclen, char *dest, size_t destlen) return size; } +/** + strdup() a unix string to lower case. +**/ + +char *strdup_lower(const char *s) +{ + size_t size; + smb_ucs2_t *buffer; + char *out_buffer; + + size = push_ucs2_allocate(&buffer, s); + if (size == -1) { + return NULL; + } + + strlower_w(buffer); + + size = pull_ucs2_allocate(&out_buffer, buffer); + SAFE_FREE(buffer); + + if (size == -1) { + return NULL; + } + + return out_buffer; +} static size_t ucs2_align(const void *base_ptr, const void *p, int flags) { @@ -480,18 +532,11 @@ size_t push_ucs2(const void *base_ptr, void *dest, const char *src, size_t dest_ { size_t len=0; size_t src_len = strlen(src); - pstring tmpbuf; /* treat a pstring as "unlimited" length */ if (dest_len == (size_t)-1) dest_len = sizeof(pstring); - if (flags & STR_UPPER) { - pstrcpy(tmpbuf, src); - strupper_m(tmpbuf); - src = tmpbuf; - } - if (flags & STR_TERMINATE) src_len++; @@ -506,6 +551,18 @@ size_t push_ucs2(const void *base_ptr, void *dest, const char *src, size_t dest_ dest_len &= ~1; len += convert_string(CH_UNIX, CH_UCS2, src, src_len, dest, dest_len); + + if (flags & STR_UPPER) { + smb_ucs2_t *dest_ucs2 = dest; + size_t i; + for (i = 0; i < (dest_len / 2) && dest_ucs2[i]; i++) { + smb_ucs2_t v = toupper_w(dest_ucs2[i]); + if (v != dest_ucs2[i]) { + dest_ucs2[i] = v; + } + } + } + return len; } @@ -809,44 +866,3 @@ size_t align_string(const void *base_ptr, const char *p, int flags) return 0; } -/** - Convert from unix to ucs2 charset and return the - allocated and converted string or NULL if an error occurred. - You must provide a zero terminated string. - The returning string will be zero terminated. -**/ - -smb_ucs2_t *acnv_uxu2(const char *src) -{ - size_t slen; - size_t dlen; - void *dest; - - slen = strlen(src) + 1; - dlen = convert_string_allocate(CH_UNIX, CH_UCS2, src, slen, &dest); - if (dlen == (size_t)-1) - return NULL; - else - return dest; -} - -/** - Convert from dos to ucs2 charset and return the - allocated and converted string or NULL if an error occurred. - You must provide a zero terminated string. - The returning string will be zero terminated. -**/ - -smb_ucs2_t *acnv_dosu2(const char *src) -{ - size_t slen; - size_t dlen; - void *dest; - - slen = strlen(src) + 1; - dlen = convert_string_allocate(CH_DOS, CH_UCS2, src, slen, &dest); - if (dlen == (size_t)-1) - return NULL; - else - return dest; -} diff --git a/source3/lib/popt_common.c b/source3/lib/popt_common.c index b8e77b2d9e..af1cbcfe80 100644 --- a/source3/lib/popt_common.c +++ b/source3/lib/popt_common.c @@ -258,19 +258,21 @@ static void get_credentials_file(const char *file, struct user_auth_info *info) * -A,--authentication-file * -k,--use-kerberos * -N,--no-pass + * -S,--signing */ static void popt_common_credentials_callback(poptContext con, - enum poptCallbackReason reason, - const struct poptOption *opt, - const char *arg, const void *data) + enum poptCallbackReason reason, + const struct poptOption *opt, + const char *arg, const void *data) { char *p; if (reason == POPT_CALLBACK_REASON_PRE) { cmdline_auth_info.use_kerberos = False; cmdline_auth_info.got_pass = False; + cmdline_auth_info.signing_state = Undefined; pstrcpy(cmdline_auth_info.username, "GUEST"); if (getenv("LOGNAME"))pstrcpy(cmdline_auth_info.username,getenv("LOGNAME")); @@ -327,6 +329,22 @@ static void popt_common_credentials_callback(poptContext con, cmdline_auth_info.got_pass = True; #endif break; + + case 'S': + { + cmdline_auth_info.signing_state = -1; + if (strequal(arg, "off") || strequal(arg, "no") || strequal(arg, "false")) + cmdline_auth_info.signing_state = False; + else if (strequal(arg, "on") || strequal(arg, "yes") || strequal(arg, "true")) + cmdline_auth_info.signing_state = True; + else if (strequal(arg, "force") || strequal(arg, "required") || strequal(arg, "forced")) + cmdline_auth_info.signing_state = Required; + else { + fprintf(stderr, "Unknown signing option %s\n", arg ); + exit(1); + } + } + break; } } @@ -338,5 +356,6 @@ struct poptOption popt_common_credentials[] = { { "no-pass", 'N', POPT_ARG_NONE, &cmdline_auth_info.got_pass, 0, "Don't ask for a password" }, { "kerberos", 'k', POPT_ARG_NONE, &cmdline_auth_info.use_kerberos, 'k', "Use kerberos (active directory) authentication" }, { "authentication-file", 'A', POPT_ARG_STRING, NULL, 'A', "Get the credentials from a file", "FILE" }, + { "signing", 'S', POPT_ARG_STRING, NULL, 'S', "Set the client signing state", "on|off|required" }, POPT_TABLEEND }; diff --git a/source3/lib/replace.c b/source3/lib/replace.c index 0c62ec9bfa..cd48b8d160 100644 --- a/source3/lib/replace.c +++ b/source3/lib/replace.c @@ -447,21 +447,3 @@ char *rep_inet_ntoa(struct in_addr ip) return t; } #endif - -#ifndef HAVE_SETENV - int setenv(const char *name, const char *value, int overwrite) -{ - char *p = NULL; - int ret = -1; - - asprintf(&p, "%s=%s", name, value); - - if (overwrite || getenv(name)) { - if (p) ret = putenv(p); - } else { - ret = 0; - } - - return ret; -} -#endif diff --git a/source3/lib/smbldap.c b/source3/lib/smbldap.c index 39c1990dec..3f56d066ec 100644 --- a/source3/lib/smbldap.c +++ b/source3/lib/smbldap.c @@ -5,7 +5,7 @@ Copyright (C) Gerald Carter 2001-2003 Copyright (C) Shahms King 2001 Copyright (C) Andrew Bartlett 2002-2003 - Copyright (C) Stefan (metze) Metzmacher 2002 + Copyright (C) Stefan (metze) Metzmacher 2002-2003 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -35,6 +35,8 @@ #define SMBLDAP_DONT_PING_TIME 10 /* ping only all 10 seconds */ #define SMBLDAP_NUM_RETRIES 8 /* retry only 8 times */ +#define SMBLDAP_IDLE_TIME 150 /* After 2.5 minutes disconnect */ + /* attributes used by Samba 2.2 */ @@ -925,6 +927,8 @@ int smbldap_search(struct smbldap_state *ldap_state, smbldap_close(ldap_state); } + ldap_state->last_use = time(NULL); + SAFE_FREE(utf8_filter); return rc; } @@ -954,6 +958,8 @@ int smbldap_modify(struct smbldap_state *ldap_state, const char *dn, LDAPMod *at smbldap_close(ldap_state); } + ldap_state->last_use = time(NULL); + SAFE_FREE(utf8_dn); return rc; } @@ -983,6 +989,8 @@ int smbldap_add(struct smbldap_state *ldap_state, const char *dn, LDAPMod *attrs smbldap_close(ldap_state); } + ldap_state->last_use = time(NULL); + SAFE_FREE(utf8_dn); return rc; } @@ -1012,6 +1020,8 @@ int smbldap_delete(struct smbldap_state *ldap_state, const char *dn) smbldap_close(ldap_state); } + ldap_state->last_use = time(NULL); + SAFE_FREE(utf8_dn); return rc; } @@ -1041,6 +1051,8 @@ int smbldap_extended_operation(struct smbldap_state *ldap_state, smbldap_close(ldap_state); } + ldap_state->last_use = time(NULL); + return rc; } @@ -1071,6 +1083,24 @@ int smbldap_search_suffix (struct smbldap_state *ldap_state, const char *filter, return rc; } +static void smbldap_idle_fn(void **data, time_t *interval, time_t now) +{ + struct smbldap_state *state = (struct smbldap_state *)(*data); + + if (state->ldap_struct == NULL) { + DEBUG(10,("ldap connection not connected...\n")); + return; + } + + if ((state->last_use+SMBLDAP_IDLE_TIME) > now) { + DEBUG(10,("ldap connection not idle...\n")); + return; + } + + DEBUG(7,("ldap connection idle...closing connection\n")); + smbldap_close(state); +} + /********************************************************************** Housekeeping *********************************************************************/ @@ -1086,6 +1116,8 @@ void smbldap_free_struct(struct smbldap_state **ldap_state) SAFE_FREE((*ldap_state)->bind_dn); SAFE_FREE((*ldap_state)->bind_secret); + smb_unregister_idle_event((*ldap_state)->event_id); + *ldap_state = NULL; /* No need to free any further, as it is talloc()ed */ @@ -1109,6 +1141,16 @@ NTSTATUS smbldap_init(TALLOC_CTX *mem_ctx, const char *location, struct smbldap_ } else { (*smbldap_state)->uri = "ldap://localhost"; } + + (*smbldap_state)->event_id = + smb_register_idle_event(smbldap_idle_fn, (void *)(*smbldap_state), + SMBLDAP_IDLE_TIME); + + if ((*smbldap_state)->event_id == SMB_EVENT_ID_INVALID) { + DEBUG(0,("Failed to register LDAP idle event!\n")); + return NT_STATUS_INVALID_HANDLE; + } + return NT_STATUS_OK; } @@ -1155,7 +1197,7 @@ static NTSTATUS add_new_domain_info(struct smbldap_state *ldap_state, DEBUG(3,("Adding new domain\n")); ldap_op = LDAP_MOD_ADD; - snprintf(dn, sizeof(dn), "%s=%s,%s", get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN), + pstr_sprintf(dn, "%s=%s,%s", get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN), domain_name, lp_ldap_suffix()); /* Free original search */ @@ -1220,7 +1262,7 @@ NTSTATUS smbldap_search_domain_info(struct smbldap_state *ldap_state, char **attr_list; int count; - snprintf(filter, sizeof(filter)-1, "(&(objectClass=%s)(%s=%s))", + pstr_sprintf(filter, "(&(objectClass=%s)(%s=%s))", LDAP_OBJ_DOMINFO, get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN), domain_name); diff --git a/source3/lib/snprintf.c b/source3/lib/snprintf.c index 9b9ceb60ca..a2f9f592db 100644 --- a/source3/lib/snprintf.c +++ b/source3/lib/snprintf.c @@ -823,12 +823,10 @@ static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c) * * The logic for these two is that we need our own definition if the * OS *either* has no definition of *sprintf, or if it does have one - * that doesn't work properly according to the autoconf test. Perhaps - * these should really be smb_snprintf to avoid conflicts with buggy - * linkers? -- mbp + * that doesn't work properly according to the autoconf test. */ #if !defined(HAVE_SNPRINTF) || !defined(HAVE_C99_VSNPRINTF) - int snprintf(char *str,size_t count,const char *fmt,...) +int smb_snprintf(char *str,size_t count,const char *fmt,...) { size_t ret; va_list ap; diff --git a/source3/lib/substitute.c b/source3/lib/substitute.c index ac2cf687c4..c0d0096806 100644 --- a/source3/lib/substitute.c +++ b/source3/lib/substitute.c @@ -58,8 +58,8 @@ void set_local_machine_name(const char* local_name, BOOL perm) fstrcpy(tmp_local_machine,local_name); trim_string(tmp_local_machine," "," "); - strlower_m(tmp_local_machine); alpha_strcpy(local_machine,tmp_local_machine,SAFE_NETBIOS_CHARS,sizeof(local_machine)-1); + strlower_m(local_machine); } /** @@ -80,8 +80,8 @@ void set_remote_machine_name(const char* remote_name, BOOL perm) fstrcpy(tmp_remote_machine,remote_name); trim_string(tmp_remote_machine," "," "); - strlower_m(tmp_remote_machine); alpha_strcpy(remote_machine,tmp_remote_machine,SAFE_NETBIOS_CHARS,sizeof(remote_machine)-1); + strlower_m(remote_machine); } const char* get_remote_machine_name(void) diff --git a/source3/lib/sysquotas.c b/source3/lib/sysquotas.c index efc9e65b9d..617f624dae 100644 --- a/source3/lib/sysquotas.c +++ b/source3/lib/sysquotas.c @@ -48,12 +48,6 @@ static int sys_get_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_ switch (qtype) { case SMB_USER_QUOTA_TYPE: - /* we use id.uid == 0 for default quotas */ - if (id.uid == 0) { - ret = 0; - break; - } - if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, id.uid, (CADDR_T)&D))) { return ret; } @@ -88,13 +82,19 @@ static int sys_get_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_ qflags |= QUOTAS_DENY_DISK; } - /* get the default quotas stored in the root's (uid =0) record */ - if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, 0, (CADDR_T)&D))) { - return ret; + ret = 0; + break; +#ifdef HAVE_GROUP_QUOTA + case SMB_GROUP_FS_QUOTA_TYPE: + id.gid = getgid(); + + if ((ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), bdev, id.gid, (CADDR_T)&D))==0) { + qflags |= QUOTAS_DENY_DISK; } ret = 0; break; +#endif /* HAVE_GROUP_QUOTA */ default: errno = ENOSYS; return -1; @@ -122,6 +122,7 @@ static int sys_set_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_ { int ret = -1; uint32 qflags = 0; + uint32 oldqflags = 0; struct SYS_DQBLK D; SMB_BIG_UINT bsize = (SMB_BIG_UINT)QUOTABLOCK_SIZE; @@ -146,10 +147,7 @@ static int sys_set_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_ switch (qtype) { case SMB_USER_QUOTA_TYPE: - /* we use id.uid == 0 for default quotas */ - if (id.uid>0) { - ret = quotactl(QCMD(Q_SETQLIM,USRQUOTA), bdev, id.uid, (CADDR_T)&D); - } + ret = quotactl(QCMD(Q_SETQLIM,USRQUOTA), bdev, id.uid, (CADDR_T)&D); break; #ifdef HAVE_GROUP_QUOTA case SMB_GROUP_QUOTA_TYPE: @@ -160,7 +158,7 @@ static int sys_set_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_ /* this stuff didn't work as it should: * switching on/off quota via quotactl() * didn't work! - * So we only set the default limits + * So we just return 0 * --metze * * On HPUX we didn't have the mount path, @@ -168,9 +166,9 @@ static int sys_set_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_ * */ #if 0 - uid = getuid(); + id.uid = getuid(); - ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, uid, (CADDR_T)&D); + ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, id.uid, (CADDR_T)&D); if ((qflags"AS_DENY_DISK)||(qflags"AS_ENABLED)) { if (ret == 0) { @@ -197,14 +195,79 @@ static int sys_set_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_ } DEBUG(0,("vfs_fs_quota: ret(%d) errno(%d)[%s] uid(%d) bdev[%s]\n", - ret,errno,strerror(errno),uid,bdev)); + ret,errno,strerror(errno),id.uid,bdev)); +#else + id.uid = getuid(); + + if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), bdev, id.uid, (CADDR_T)&D))==0) { + oldqflags |= QUOTAS_DENY_DISK; + } + + if (oldqflags == qflags) { + ret = 0; + } else { + ret = -1; + } #endif - - /* we use uid == 0 for default quotas */ - ret = quotactl(QCMD(Q_SETQLIM,USRQUOTA), bdev, 0, (CADDR_T)&D); - break; +#ifdef HAVE_GROUP_QUOTA + case SMB_GROUP_FS_QUOTA_TYPE: + /* this stuff didn't work as it should: + * switching on/off quota via quotactl() + * didn't work! + * So we just return 0 + * --metze + * + * On HPUX we didn't have the mount path, + * we need to fix sys_path_to_bdev() + * + */ +#if 0 + id.gid = getgid(); + + ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), bdev, id, (CADDR_T)&D); + + if ((qflags"AS_DENY_DISK)||(qflags"AS_ENABLED)) { + if (ret == 0) { + char *quota_file = NULL; + + asprintf("a_file,"/%s/%s%s",path, QUOTAFILENAME,GROUPQUOTAFILE_EXTENSION); + if (quota_file == NULL) { + DEBUG(0,("asprintf() failed!\n")); + errno = ENOMEM; + return -1; + } + + ret = quotactl(QCMD(Q_QUOTAON,GRPQUOTA), bdev, -1,(CADDR_T)quota_file); + } else { + ret = 0; + } + } else { + if (ret != 0) { + /* turn off */ + ret = quotactl(QCMD(Q_QUOTAOFF,GRPQUOTA), bdev, -1, (CADDR_T)0); + } else { + ret = 0; + } + } + + DEBUG(0,("vfs_fs_quota: ret(%d) errno(%d)[%s] uid(%d) bdev[%s]\n", + ret,errno,strerror(errno),id.gid,bdev)); +#else + id.gid = getgid(); + + if ((ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), bdev, id.gid, (CADDR_T)&D))==0) { + oldqflags |= QUOTAS_DENY_DISK; + } + if (oldqflags == qflags) { + ret = 0; + } else { + ret = -1; + } +#endif + break; +#endif /* HAVE_GROUP_QUOTA */ default: errno = ENOSYS; return -1; @@ -383,7 +446,7 @@ static int sys_path_to_bdev(const char *path, char **mntpath, char **bdev, char ****************************************************************************/ static int sys_get_xfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp) { - int ret; + int ret = -1; uint32 qflags = 0; SMB_BIG_UINT bsize = (SMB_BIG_UINT)BBSIZE; struct fs_disk_quota D; @@ -399,11 +462,6 @@ static int sys_get_xfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_ switch (qtype) { case SMB_USER_QUOTA_TYPE: - /* we use id.uid == 0 for default quotas */ - if (id.uid == 0) { - ret = 0; - break; - } if ((ret=quotactl(QCMD(Q_XGETQUOTA,USRQUOTA), bdev, id.uid, (CADDR_T)&D))) return ret; break; @@ -413,10 +471,8 @@ static int sys_get_xfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_ return ret; break; #endif /* HAVE_GROUP_QUOTA */ - case SMB_USER_FS_QUOTA_TYPE: - /* TODO: get quota status from quotactl() ... */ - if ((ret = quotactl(QCMD(Q_XGETQSTAT,USRQUOTA), bdev, -1, (CADDR_T)&F))) - return ret; + case SMB_USER_FS_QUOTA_TYPE: + quotactl(QCMD(Q_XGETQSTAT,USRQUOTA), bdev, -1, (CADDR_T)&F); if (F.qs_flags & XFS_QUOTA_UDQ_ENFD) { qflags |= QUOTAS_DENY_DISK; @@ -425,11 +481,24 @@ static int sys_get_xfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_ qflags |= QUOTAS_ENABLED; } - /* we use uid == 0 for default quotas */ - if ((ret=quotactl(QCMD(Q_XGETQUOTA,USRQUOTA), bdev, 0, (CADDR_T)&D))) - return ret; + ret = 0; break; +#ifdef HAVE_GROUP_QUOTA + case SMB_GROUP_FS_QUOTA_TYPE: + quotactl(QCMD(Q_XGETQSTAT,GRPQUOTA), bdev, -1, (CADDR_T)&F); + + if (F.qs_flags & XFS_QUOTA_UDQ_ENFD) { + qflags |= QUOTAS_DENY_DISK; + } + else if (F.qs_flags & XFS_QUOTA_UDQ_ACCT) { + qflags |= QUOTAS_ENABLED; + } + + ret = 0; + + break; +#endif /* HAVE_GROUP_QUOTA */ default: errno = ENOSYS; return -1; @@ -481,11 +550,8 @@ static int sys_set_xfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_ switch (qtype) { case SMB_USER_QUOTA_TYPE: - /* we use uid == 0 for default quotas */ - if (id.uid>0) { - D.d_fieldmask |= FS_DQ_LIMIT_MASK; - ret = quotactl(QCMD(Q_XSETQLIM,USRQUOTA), bdev, id.uid, (CADDR_T)&D); - } + D.d_fieldmask |= FS_DQ_LIMIT_MASK; + ret = quotactl(QCMD(Q_XSETQLIM,USRQUOTA), bdev, id.uid, (CADDR_T)&D); break; #ifdef HAVE_GROUP_QUOTA case SMB_GROUP_QUOTA_TYPE: @@ -494,7 +560,6 @@ static int sys_set_xfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_ break; #endif /* HAVE_GROUP_QUOTA */ case SMB_USER_FS_QUOTA_TYPE: - /* TODO */ quotactl(QCMD(Q_XGETQSTAT,USRQUOTA), bdev, -1, (CADDR_T)&F); if (qflags & QUOTAS_DENY_DISK) { @@ -505,6 +570,8 @@ static int sys_set_xfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_ if (q_on != 0) { ret = quotactl(QCMD(Q_XQUOTAON,USRQUOTA),bdev, -1, (CADDR_T)&q_on); + } else { + ret = 0; } } else if (qflags & QUOTAS_ENABLED) { @@ -513,6 +580,8 @@ static int sys_set_xfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_ if (q_off != 0) { ret = quotactl(QCMD(Q_XQUOTAOFF,USRQUOTA),bdev, -1, (CADDR_T)&q_off); + } else { + ret = 0; } if (!(F.qs_flags & XFS_QUOTA_UDQ_ACCT)) @@ -520,6 +589,8 @@ static int sys_set_xfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_ if (q_on != 0) { ret = quotactl(QCMD(Q_XQUOTAON,USRQUOTA),bdev, -1, (CADDR_T)&q_on); + } else { + ret = 0; } } else { #if 0 @@ -533,14 +604,71 @@ static int sys_set_xfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_ if (q_off !=0) { ret = quotactl(QCMD(Q_XQUOTAOFF,USRQUOTA),bdev, -1, (CADDR_T)&q_off); + } else { + ret = 0; } +#else + ret = -1; #endif } + + break; +#ifdef HAVE_GROUP_QUOTA + case SMB_GROUP_FS_QUOTA_TYPE: + quotactl(QCMD(Q_XGETQSTAT,GRPQUOTA), bdev, -1, (CADDR_T)&F); - /* we use uid == 0 for default quotas */ - D.d_fieldmask |= FS_DQ_LIMIT_MASK; - ret = quotactl(QCMD(Q_XSETQLIM,USRQUOTA), bdev, 0, (CADDR_T)&D); + if (qflags & QUOTAS_DENY_DISK) { + if (!(F.qs_flags & XFS_QUOTA_UDQ_ENFD)) + q_on |= XFS_QUOTA_UDQ_ENFD; + if (!(F.qs_flags & XFS_QUOTA_UDQ_ACCT)) + q_on |= XFS_QUOTA_UDQ_ACCT; + + if (q_on != 0) { + ret = quotactl(QCMD(Q_XQUOTAON,GRPQUOTA),bdev, -1, (CADDR_T)&q_on); + } else { + ret = 0; + } + + } else if (qflags & QUOTAS_ENABLED) { + if (F.qs_flags & XFS_QUOTA_UDQ_ENFD) + q_off |= XFS_QUOTA_UDQ_ENFD; + + if (q_off != 0) { + ret = quotactl(QCMD(Q_XQUOTAOFF,GRPQUOTA),bdev, -1, (CADDR_T)&q_off); + } else { + ret = 0; + } + + if (!(F.qs_flags & XFS_QUOTA_UDQ_ACCT)) + q_on |= XFS_QUOTA_UDQ_ACCT; + + if (q_on != 0) { + ret = quotactl(QCMD(Q_XQUOTAON,GRPQUOTA),bdev, -1, (CADDR_T)&q_on); + } else { + ret = 0; + } + } else { +#if 0 + /* Switch on XFS_QUOTA_UDQ_ACCT didn't work! + * only swittching off XFS_QUOTA_UDQ_ACCT work + */ + if (F.qs_flags & XFS_QUOTA_UDQ_ENFD) + q_off |= XFS_QUOTA_UDQ_ENFD; + if (F.qs_flags & XFS_QUOTA_UDQ_ACCT) + q_off |= XFS_QUOTA_UDQ_ACCT; + + if (q_off !=0) { + ret = quotactl(QCMD(Q_XQUOTAOFF,GRPQUOTA),bdev, -1, (CADDR_T)&q_off); + } else { + ret = 0; + } +#else + ret = -1; +#endif + } + break; +#endif /* HAVE_GROUP_QUOTA */ default: errno = ENOSYS; return -1; @@ -783,12 +911,17 @@ int sys_get_quota(const char *path, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DI } if ((ret=sys_path_to_bdev(path,&mntpath,&bdev,&fs))!=0) { + DEBUG(0,("sys_path_to_bdev() failed for path [%s]!\n",path)); return ret; } for (i=0;(fs && sys_quota_backends[i].name && sys_quota_backends[i].get_quota);i++) { if (strcmp(fs,sys_quota_backends[i].name)==0) { ret = sys_quota_backends[i].get_quota(mntpath, bdev, qtype, id, dp); + if (ret!=0) { + DEBUG(10,("sys_get_%s_quota() failed for mntpath[%s] bdev[%s] qtype[%d] id[%d] ret[%d].\n", + fs,mntpath,bdev,qtype,(qtype==SMB_GROUP_QUOTA_TYPE?id.gid:id.uid),ret)); + } ready = True; break; } @@ -796,7 +929,11 @@ int sys_get_quota(const char *path, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DI if (!ready) { /* use the default vfs quota functions */ - ret = sys_get_vfs_quota(mntpath, bdev, qtype, id, dp); + ret=sys_get_vfs_quota(mntpath, bdev, qtype, id, dp); + if (ret!=0) { + DEBUG(10,("sys_get_%s_quota() failed for mntpath[%s] bdev[%s] qtype[%d] id[%d] ret[%d].\n", + "vfs",mntpath,bdev,qtype,(qtype==SMB_GROUP_QUOTA_TYPE?id.gid:id.uid),ret)); + } } SAFE_FREE(mntpath); @@ -831,12 +968,17 @@ int sys_set_quota(const char *path, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DI } if ((ret=sys_path_to_bdev(path,&mntpath,&bdev,&fs))!=0) { + DEBUG(0,("sys_path_to_bdev() failed for path [%s]!\n",path)); return ret; } for (i=0;(fs && sys_quota_backends[i].name && sys_quota_backends[i].set_quota);i++) { if (strcmp(fs,sys_quota_backends[i].name)==0) { ret = sys_quota_backends[i].set_quota(mntpath, bdev, qtype, id, dp); + if (ret!=0) { + DEBUG(10,("sys_set_%s_quota() failed for mntpath[%s] bdev[%s] qtype[%d] id[%d] ret[%d].\n", + fs,mntpath,bdev,qtype,(qtype==SMB_GROUP_QUOTA_TYPE?id.gid:id.uid),ret)); + } ready = True; break; } @@ -845,6 +987,10 @@ int sys_set_quota(const char *path, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DI if (!ready) { /* use the default vfs quota functions */ ret=sys_set_vfs_quota(mntpath, bdev, qtype, id, dp); + if (ret!=0) { + DEBUG(10,("sys_set_%s_quota() failed for mntpath[%s] bdev[%s] qtype[%d] id[%d] ret[%d].\n", + "vfs",mntpath,bdev,qtype,(qtype==SMB_GROUP_QUOTA_TYPE?id.gid:id.uid),ret)); + } } SAFE_FREE(mntpath); diff --git a/source3/lib/username.c b/source3/lib/username.c index 98b8f33aae..6321d47021 100644 --- a/source3/lib/username.c +++ b/source3/lib/username.c @@ -386,7 +386,7 @@ static BOOL user_in_winbind_group_list(const char *user, const char *gname, BOOL if ( DEBUGLEVEL >= 10 ) { DEBUG(10,("user_in_winbind_group_list: using groups -- ")); for ( i=0; i 2003 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -2247,7 +2247,7 @@ char *pid_path(const char *name) char *lib_path(const char *name) { static pstring fname; - snprintf(fname, sizeof(fname), "%s/%s", dyn_LIBDIR, name); + fstr_sprintf(fname, "%s/%s", dyn_LIBDIR, name); return fname; } diff --git a/source3/lib/util_file.c b/source3/lib/util_file.c index 02acbd4d7e..638a6ca342 100644 --- a/source3/lib/util_file.c +++ b/source3/lib/util_file.c @@ -455,8 +455,8 @@ void *map_file(char *fname, size_t size) p = file_load(fname, &s2); if (!p) return NULL; if (s2 != size) { - DEBUG(1,("incorrect size for %s - got %d expected %d\n", - fname, s2, size)); + DEBUG(1,("incorrect size for %s - got %lu expected %lu\n", + fname, (unsigned long)s2, (unsigned long)size)); if (p) free(p); return NULL; } diff --git a/source3/lib/util_sock.c b/source3/lib/util_sock.c index 1bd4c3a96b..b8b8471708 100644 --- a/source3/lib/util_sock.c +++ b/source3/lib/util_sock.c @@ -289,7 +289,7 @@ ssize_t read_socket_with_timeout(int fd,char *buf,size_t mincnt,size_t maxcnt,un } /**************************************************************************** - read data from the client, reading exactly N bytes. + Read data from the client, reading exactly N bytes. ****************************************************************************/ ssize_t read_data(int fd,char *buffer,size_t N) @@ -397,7 +397,7 @@ static ssize_t write_socket_data(int fd,char *buffer,size_t N) } /**************************************************************************** -write to a socket + Write to a socket. ****************************************************************************/ ssize_t write_socket(int fd,char *buf,size_t len) @@ -416,7 +416,7 @@ ssize_t write_socket(int fd,char *buf,size_t len) } /**************************************************************************** -send a keepalive packet (rfc1002) + Send a keepalive packet (rfc1002). ****************************************************************************/ BOOL send_keepalive(int client) @@ -431,11 +431,11 @@ BOOL send_keepalive(int client) /**************************************************************************** -read 4 bytes of a smb packet and return the smb length of the packet -store the result in the buffer -This version of the function will return a length of zero on receiving -a keepalive packet. -timeout is in milliseconds. + Read 4 bytes of a smb packet and return the smb length of the packet. + Store the result in the buffer. + This version of the function will return a length of zero on receiving + a keepalive packet. + Timeout is in milliseconds. ****************************************************************************/ static ssize_t read_smb_length_return_keepalive(int fd,char *inbuf,unsigned int timeout) @@ -466,10 +466,10 @@ static ssize_t read_smb_length_return_keepalive(int fd,char *inbuf,unsigned int } /**************************************************************************** -read 4 bytes of a smb packet and return the smb length of the packet -store the result in the buffer. This version of the function will -never return a session keepalive (length of zero). -timeout is in milliseconds. + Read 4 bytes of a smb packet and return the smb length of the packet. + Store the result in the buffer. This version of the function will + never return a session keepalive (length of zero). + Timeout is in milliseconds. ****************************************************************************/ ssize_t read_smb_length(int fd,char *inbuf,unsigned int timeout) @@ -493,11 +493,10 @@ ssize_t read_smb_length(int fd,char *inbuf,unsigned int timeout) } /**************************************************************************** - read an smb from a fd. Note that the buffer *MUST* be of size - BUFFER_SIZE+SAFETY_MARGIN. - The timeout is in milliseconds. - This function will return on a - receipt of a session keepalive packet. + Read an smb from a fd. Note that the buffer *MUST* be of size + BUFFER_SIZE+SAFETY_MARGIN. + The timeout is in milliseconds. + This function will return on receipt of a session keepalive packet. ****************************************************************************/ BOOL receive_smb(int fd,char *buffer, unsigned int timeout) @@ -553,11 +552,19 @@ BOOL receive_smb(int fd,char *buffer, unsigned int timeout) } } + /* Check the incoming SMB signature. */ + if (!srv_check_sign_mac(buffer)) { + DEBUG(0, ("receive_smb: SMB Signature verification failed on incoming packet!\n")); + if (smb_read_error == 0) + smb_read_error = READ_BAD_SIG; + return False; + }; + return(True); } /**************************************************************************** - send an smb to a fd + Send an smb to a fd. ****************************************************************************/ BOOL send_smb(int fd,char *buffer) @@ -565,6 +572,10 @@ BOOL send_smb(int fd,char *buffer) size_t len; size_t nwritten=0; ssize_t ret; + + /* Sign the outgoing packet if required. */ + srv_calculate_sign_mac(buffer); + len = smb_len(buffer) + 4; while (nwritten < len) { @@ -647,80 +658,86 @@ int open_socket_in( int type, int port, int dlevel, uint32 socket_addr, BOOL reb } /**************************************************************************** - create an outgoing socket. timeout is in milliseconds. - **************************************************************************/ + Create an outgoing socket. timeout is in milliseconds. +**************************************************************************/ int open_socket_out(int type, struct in_addr *addr, int port ,int timeout) { - struct sockaddr_in sock_out; - int res,ret; - int connect_loop = 10; - int increment = 10; + struct sockaddr_in sock_out; + int res,ret; + int connect_loop = 10; + int increment = 10; - /* create a socket to write to */ - res = socket(PF_INET, type, 0); - if (res == -1) - { DEBUG(0,("socket error\n")); return -1; } + /* create a socket to write to */ + res = socket(PF_INET, type, 0); + if (res == -1) { + DEBUG(0,("socket error\n")); + return -1; + } - if (type != SOCK_STREAM) return(res); + if (type != SOCK_STREAM) + return(res); - memset((char *)&sock_out,'\0',sizeof(sock_out)); - putip((char *)&sock_out.sin_addr,(char *)addr); + memset((char *)&sock_out,'\0',sizeof(sock_out)); + putip((char *)&sock_out.sin_addr,(char *)addr); - sock_out.sin_port = htons( port ); - sock_out.sin_family = PF_INET; + sock_out.sin_port = htons( port ); + sock_out.sin_family = PF_INET; - /* set it non-blocking */ - set_blocking(res,False); + /* set it non-blocking */ + set_blocking(res,False); - DEBUG(3,("Connecting to %s at port %d\n",inet_ntoa(*addr),port)); + DEBUG(3,("Connecting to %s at port %d\n",inet_ntoa(*addr),port)); - /* and connect it to the destination */ -connect_again: - ret = connect(res,(struct sockaddr *)&sock_out,sizeof(sock_out)); - - /* Some systems return EAGAIN when they mean EINPROGRESS */ - if (ret < 0 && (errno == EINPROGRESS || errno == EALREADY || - errno == EAGAIN) && (connect_loop < timeout) ) { - msleep(connect_loop); - connect_loop += increment; - if (increment < 250) { - /* After 8 rounds we end up at a max of 255 msec */ - increment *= 1.5; - } - goto connect_again; - } - - if (ret < 0 && (errno == EINPROGRESS || errno == EALREADY || - errno == EAGAIN)) { - DEBUG(1,("timeout connecting to %s:%d\n",inet_ntoa(*addr),port)); - close(res); - return -1; - } + /* and connect it to the destination */ + connect_again: + + ret = connect(res,(struct sockaddr *)&sock_out,sizeof(sock_out)); + + /* Some systems return EAGAIN when they mean EINPROGRESS */ + if (ret < 0 && (errno == EINPROGRESS || errno == EALREADY || + errno == EAGAIN) && (connect_loop < timeout) ) { + msleep(connect_loop); + connect_loop += increment; + if (increment < 250) { + /* After 8 rounds we end up at a max of 255 msec */ + increment *= 1.5; + } + goto connect_again; + } + + if (ret < 0 && (errno == EINPROGRESS || errno == EALREADY || + errno == EAGAIN)) { + DEBUG(1,("timeout connecting to %s:%d\n",inet_ntoa(*addr),port)); + close(res); + return -1; + } #ifdef EISCONN - if (ret < 0 && errno == EISCONN) { - errno = 0; - ret = 0; - } + + if (ret < 0 && errno == EISCONN) { + errno = 0; + ret = 0; + } #endif - if (ret < 0) { - DEBUG(2,("error connecting to %s:%d (%s)\n", - inet_ntoa(*addr),port,strerror(errno))); - close(res); - return -1; - } + if (ret < 0) { + DEBUG(2,("error connecting to %s:%d (%s)\n", + inet_ntoa(*addr),port,strerror(errno))); + close(res); + return -1; + } - /* set it blocking again */ - set_blocking(res,True); + /* set it blocking again */ + set_blocking(res,True); - return res; + return res; } -/* - open a connected UDP socket to host on port -*/ +/**************************************************************************** + Open a connected UDP socket to host on port +**************************************************************************/ + int open_udp_socket(const char *host, int port) { int type = SOCK_DGRAM; @@ -783,9 +800,10 @@ struct in_addr *client_inaddr(struct sockaddr *sa) } /******************************************************************* - matchname - determine if host name matches IP address. Used to - confirm a hostname lookup to prevent spoof attacks - ******************************************************************/ + Matchname - determine if host name matches IP address. Used to + confirm a hostname lookup to prevent spoof attacks. +******************************************************************/ + static BOOL matchname(char *remotehost,struct in_addr addr) { struct hostent *hp; @@ -828,10 +846,10 @@ static BOOL matchname(char *remotehost,struct in_addr addr) return False; } - /******************************************************************* - return the DNS name of the remote end of a socket - ******************************************************************/ + Return the DNS name of the remote end of a socket. +******************************************************************/ + char *get_socket_name(int fd, BOOL force_lookup) { static pstring name_buf; @@ -881,8 +899,9 @@ char *get_socket_name(int fd, BOOL force_lookup) } /******************************************************************* - return the IP addr of the remote end of a socket as a string + Return the IP addr of the remote end of a socket as a string. ******************************************************************/ + char *get_socket_addr(int fd) { struct sockaddr sa; @@ -906,7 +925,6 @@ char *get_socket_addr(int fd) return addr_buf; } - /******************************************************************* Create protected unix domain socket. @@ -968,7 +986,7 @@ int create_pipe_sock(const char *socket_dir, goto out_umask; } - snprintf(path, sizeof(path), "%s/%s", socket_dir, socket_name); + pstr_sprintf(path, "%s/%s", socket_dir, socket_name); unlink(path); memset(&sunaddr, 0, sizeof(sunaddr)); diff --git a/source3/lib/util_str.c b/source3/lib/util_str.c index 96fbc3f124..7569a39e6a 100644 --- a/source3/lib/util_str.c +++ b/source3/lib/util_str.c @@ -181,7 +181,9 @@ int StrCaseCmp(const char *s, const char *t) { const char * ps, * pt; - pstring buf1, buf2; + size_t size; + smb_ucs2_t *buffer_s, *buffer_t; + int ret; for (ps = s, pt = t; ; ps++, pt++) { char us, ut; @@ -206,16 +208,25 @@ int StrCaseCmp(const char *s, const char *t) return +1; } - /* TODO: Don't do this with a fixed-length buffer. This could - * still be much more efficient. */ - /* TODO: Hardcode a char-by-char comparison for UTF-8, which - * can be much faster. */ - /* TODO: Test case for this! */ - - unix_strupper(ps, strlen(ps)+1, buf1, sizeof(buf1)); - unix_strupper(pt, strlen(pt)+1, buf2, sizeof(buf2)); - - return strcmp(buf1, buf2); + size = push_ucs2_allocate(&buffer_s, s); + if (size == (size_t)-1) { + return strcmp(s, t); + /* Not quite the right answer, but finding the right one + under this failure case is expensive, and it's pretty close */ + } + + size = push_ucs2_allocate(&buffer_t, t); + if (size == (size_t)-1) { + SAFE_FREE(buffer_s); + return strcmp(s, t); + /* Not quite the right answer, but finding the right one + under this failure case is expensive, and it's pretty close */ + } + + ret = strcasecmp_w(buffer_s, buffer_t); + SAFE_FREE(buffer_s); + SAFE_FREE(buffer_t); + return ret; } @@ -351,7 +362,7 @@ BOOL strisnormal(const char *s) NOTE: oldc and newc must be 7 bit characters **/ -void string_replace(char *s,char oldc,char newc) +void string_replace(pstring s,char oldc,char newc) { push_ucs2(NULL, tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE); string_replace_w(tmpbuf, UCS2_CHAR(oldc), UCS2_CHAR(newc)); @@ -1155,21 +1166,6 @@ void strlower_m(char *s) unix_strlower(s,strlen(s)+1,s,strlen(s)+1); } -/** - Duplicate convert a string to lower case. -**/ - -char *strdup_lower(const char *s) -{ - char *t = strdup(s); - if (t == NULL) { - DEBUG(0, ("strdup_lower: Out of memory!\n")); - return NULL; - } - strlower_m(t); - return t; -} - /** Convert a string to upper case. **/ @@ -1194,21 +1190,6 @@ void strupper_m(char *s) unix_strupper(s,strlen(s)+1,s,strlen(s)+1); } -/** - Convert a string to upper case. -**/ - -char *strdup_upper(const char *s) -{ - char *t = strdup(s); - if (t == NULL) { - DEBUG(0, ("strdup_upper: Out of memory!\n")); - return NULL; - } - strupper_m(t); - return t; -} - /** Return a RFC2254 binary string representation of a buffer. Used in LDAP filters. @@ -1575,7 +1556,7 @@ int ipstr_list_parse(const char* ipstr_list, struct ip_service **ip_list) count = count_chars(ipstr_list, IPSTR_LIST_CHAR) + 1; if ( (*ip_list = (struct ip_service*)malloc(count * sizeof(struct ip_service))) == NULL ) { - DEBUG(0,("ipstr_list_parse: malloc failed for %d entries\n", count)); + DEBUG(0,("ipstr_list_parse: malloc failed for %lu entries\n", (unsigned long)count)); return 0; } diff --git a/source3/lib/util_unistr.c b/source3/lib/util_unistr.c index ae000fba02..fd51f3c57d 100644 --- a/source3/lib/util_unistr.c +++ b/source3/lib/util_unistr.c @@ -759,82 +759,6 @@ smb_ucs2_t *strstr_wa(const smb_ucs2_t *s, const char *ins) return NULL; } -/******************************************************************* -copy a string with max len -********************************************************************/ - -smb_ucs2_t *strncpy_wa(smb_ucs2_t *dest, const char *src, const size_t max) -{ - smb_ucs2_t *ucs2_src; - - if (!dest || !src) return NULL; - if (!(ucs2_src = acnv_uxu2(src))) - return NULL; - - strncpy_w(dest, ucs2_src, max); - SAFE_FREE(ucs2_src); - return dest; -} - -/******************************************************************* -convert and duplicate an ascii string -********************************************************************/ -smb_ucs2_t *strdup_wa(const char *src) -{ - return strndup_wa(src, 0); -} - -/* if len == 0 then duplicate the whole string */ -smb_ucs2_t *strndup_wa(const char *src, size_t len) -{ - smb_ucs2_t *dest, *s; - - s = acnv_dosu2(src); - if (!len) len = strlen_w(s); - dest = (smb_ucs2_t *)malloc((len + 1) * sizeof(smb_ucs2_t)); - if (!dest) { - DEBUG(0,("strdup_w: out of memory!\n")); - SAFE_FREE(s); - return NULL; - } - - memcpy(dest, src, len * sizeof(smb_ucs2_t)); - dest[len] = 0; - - SAFE_FREE(s); - return dest; -} - -/******************************************************************* -append a string of len bytes and add a terminator -********************************************************************/ - -smb_ucs2_t *strncat_wa(smb_ucs2_t *dest, const char *src, const size_t max) -{ - smb_ucs2_t *ucs2_src; - - if (!dest || !src) return NULL; - if (!(ucs2_src = acnv_uxu2(src))) - return NULL; - - strncat_w(dest, ucs2_src, max); - SAFE_FREE(ucs2_src); - return dest; -} - -smb_ucs2_t *strcat_wa(smb_ucs2_t *dest, const char *src) -{ - smb_ucs2_t *ucs2_src; - - if (!dest || !src) return NULL; - if (!(ucs2_src = acnv_uxu2(src))) - return NULL; - - strcat_w(dest, ucs2_src); - SAFE_FREE(ucs2_src); - return dest; -} - BOOL trim_string_wa(smb_ucs2_t *s, const char *front, const char *back) { diff --git a/source3/lib/util_uuid.c b/source3/lib/util_uuid.c index 83553ec28e..56f0ecd85b 100644 --- a/source3/lib/util_uuid.c +++ b/source3/lib/util_uuid.c @@ -2,7 +2,7 @@ * Unix SMB/CIFS implementation. * UUID server routines * Copyright (C) Theodore Ts'o 1996, 1997, - * Copyright (C) Jim McDonough 2002. + * Copyright (C) Jim McDonough 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 diff --git a/source3/libads/authdata.c b/source3/libads/authdata.c index c554a02e90..50a9ef2718 100644 --- a/source3/libads/authdata.c +++ b/source3/libads/authdata.c @@ -1,7 +1,7 @@ /* Unix SMB/CIFS implementation. kerberos authorization data (PAC) utility library - Copyright (C) Jim McDonough 2003 + Copyright (C) Jim McDonough 2003 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/source3/libads/kerberos_verify.c b/source3/libads/kerberos_verify.c index 25b7f9d948..48b61cd1f2 100644 --- a/source3/libads/kerberos_verify.c +++ b/source3/libads/kerberos_verify.c @@ -60,13 +60,13 @@ NTSTATUS ads_verify_ticket(ADS_STRUCT *ads, const DATA_BLOB *ticket, ZERO_STRUCTP(ap_rep); if (!secrets_init()) { - DEBUG(1,("secrets_init failed\n")); + DEBUG(1,("ads_verify_ticket: secrets_init failed\n")); return NT_STATUS_LOGON_FAILURE; } password_s = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL); if (!password_s) { - DEBUG(1,("failed to fetch machine password\n")); + DEBUG(1,("ads_verify_ticket: failed to fetch machine password\n")); return NT_STATUS_LOGON_FAILURE; } @@ -75,13 +75,13 @@ NTSTATUS ads_verify_ticket(ADS_STRUCT *ads, const DATA_BLOB *ticket, ret = krb5_init_context(&context); if (ret) { - DEBUG(1,("krb5_init_context failed (%s)\n", error_message(ret))); + DEBUG(1,("ads_verify_ticket: krb5_init_context failed (%s)\n", error_message(ret))); return NT_STATUS_LOGON_FAILURE; } ret = krb5_set_default_realm(context, ads->auth.realm); if (ret) { - DEBUG(1,("krb5_set_default_realm failed (%s)\n", error_message(ret))); + DEBUG(1,("ads_verify_ticket: krb5_set_default_realm failed (%s)\n", error_message(ret))); sret = NT_STATUS_LOGON_FAILURE; goto out; } @@ -92,7 +92,7 @@ NTSTATUS ads_verify_ticket(ADS_STRUCT *ads, const DATA_BLOB *ticket, ret = krb5_auth_con_init(context, &auth_context); if (ret) { - DEBUG(1,("krb5_auth_con_init failed (%s)\n", error_message(ret))); + DEBUG(1,("ads_verify_ticket: krb5_auth_con_init failed (%s)\n", error_message(ret))); sret = NT_STATUS_LOGON_FAILURE; goto out; } @@ -102,32 +102,31 @@ NTSTATUS ads_verify_ticket(ADS_STRUCT *ads, const DATA_BLOB *ticket, asprintf(&host_princ_s, "HOST/%s@%s", myname, lp_realm()); ret = krb5_parse_name(context, host_princ_s, &host_princ); if (ret) { - DEBUG(1,("krb5_parse_name(%s) failed (%s)\n", host_princ_s, error_message(ret))); + DEBUG(1,("ads_verify_ticket: krb5_parse_name(%s) failed (%s)\n", + host_princ_s, error_message(ret))); sret = NT_STATUS_LOGON_FAILURE; goto out; } /* - * JRA. We must set the rcache and the allowed addresses in the auth_context - * here. This will prevent replay attacks and ensure the client has got a key from - * the correct IP address. + * JRA. We must set the rcache here. This will prevent replay attacks. */ ret = krb5_get_server_rcache(context, krb5_princ_component(context, host_princ, 0), &rcache); if (ret) { - DEBUG(1,("krb5_get_server_rcache failed (%s)\n", error_message(ret))); + DEBUG(1,("ads_verify_ticket: krb5_get_server_rcache failed (%s)\n", error_message(ret))); sret = NT_STATUS_LOGON_FAILURE; goto out; } ret = krb5_auth_con_setrcache(context, auth_context, rcache); if (ret) { - DEBUG(1,("krb5_auth_con_setrcache failed (%s)\n", error_message(ret))); + DEBUG(1,("ads_verify_ticket: krb5_auth_con_setrcache failed (%s)\n", error_message(ret))); sret = NT_STATUS_LOGON_FAILURE; goto out; } - /* Now we need to add the addresses.... JRA. */ + /* CIFS doesn't use addresses in tickets. This would breat NAT. JRA */ if (!(key = (krb5_keyblock *)malloc(sizeof(*key)))) { sret = NT_STATUS_NO_MEMORY; @@ -135,13 +134,22 @@ NTSTATUS ads_verify_ticket(ADS_STRUCT *ads, const DATA_BLOB *ticket, } if ((ret = get_kerberos_allowed_etypes(context, &enctypes))) { - DEBUG(1,("krb5_get_permitted_enctypes failed (%s)\n", + DEBUG(1,("ads_verify_ticket: krb5_get_permitted_enctypes failed (%s)\n", error_message(ret))); sret = NT_STATUS_LOGON_FAILURE; goto out; } - /* we need to setup a auth context with each possible encoding type in turn */ + /* Lock a mutex surrounding the replay as there is no locking in the MIT krb5 + * code surrounding the replay cache... */ + + if (!grab_server_mutex("replay cache mutex")) { + DEBUG(1,("ads_verify_ticket: unable to protect replay cache with mutex.\n")); + sret = NT_STATUS_LOGON_FAILURE; + goto out; + } + + /* We need to setup a auth context with each possible encoding type in turn. */ for (i=0;enctypes[i];i++) { if (create_kerberos_key_from_string(context, host_princ, &password, key, enctypes[i])) { continue; @@ -154,14 +162,22 @@ NTSTATUS ads_verify_ticket(ADS_STRUCT *ads, const DATA_BLOB *ticket, if (!(ret = krb5_rd_req(context, &auth_context, &packet, NULL, keytab, NULL, &tkt))) { + DEBUG(10,("ads_verify_ticket: enc type [%u] decrypted message !\n", + (unsigned int)enctypes[i] )); free_kerberos_etypes(context, enctypes); auth_ok = True; break; } + + DEBUG((ret != KRB5_BAD_ENCTYPE) ? 3 : 10, + ("ads_verify_ticket: enc type [%u] failed to decrypt with error %s\n", + (unsigned int)enctypes[i], error_message(ret))); } + release_server_mutex(); + if (!auth_ok) { - DEBUG(3,("krb5_rd_req with auth failed (%s)\n", + DEBUG(3,("ads_verify_ticket: krb5_rd_req with auth failed (%s)\n", error_message(ret))); sret = NT_STATUS_LOGON_FAILURE; goto out; @@ -169,7 +185,7 @@ NTSTATUS ads_verify_ticket(ADS_STRUCT *ads, const DATA_BLOB *ticket, ret = krb5_mk_rep(context, auth_context, &packet); if (ret) { - DEBUG(3,("Failed to generate mutual authentication reply (%s)\n", + DEBUG(3,("ads_verify_ticket: Failed to generate mutual authentication reply (%s)\n", error_message(ret))); sret = NT_STATUS_LOGON_FAILURE; goto out; @@ -178,7 +194,7 @@ NTSTATUS ads_verify_ticket(ADS_STRUCT *ads, const DATA_BLOB *ticket, *ap_rep = data_blob(packet.data, packet.length); free(packet.data); - get_krb5_smb_session_key(context, auth_context, session_key); + get_krb5_smb_session_key(context, auth_context, session_key, True); #ifdef DEBUG_PASSWORD DEBUG(10,("SMB session key (from ticket) follows:\n")); dump_data(10, session_key, 16); @@ -205,7 +221,7 @@ NTSTATUS ads_verify_ticket(ADS_STRUCT *ads, const DATA_BLOB *ticket, if ((ret = krb5_unparse_name(context, get_principal_from_tkt(tkt), principal))) { - DEBUG(3,("krb5_unparse_name failed (%s)\n", + DEBUG(3,("ads_verify_ticket: krb5_unparse_name failed (%s)\n", error_message(ret))); sret = NT_STATUS_LOGON_FAILURE; goto out; diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c index cf6f9375f8..5a12288b16 100644 --- a/source3/libads/ldap.c +++ b/source3/libads/ldap.c @@ -3,7 +3,7 @@ ads (active directory) utility library Copyright (C) Andrew Tridgell 2001 Copyright (C) Remus Koos 2001 - Copyright (C) Jim McDonough 2002 + Copyright (C) Jim McDonough 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 @@ -106,12 +106,24 @@ static BOOL ads_find_dc(ADS_STRUCT *ads) struct ip_service *ip_list; pstring realm; BOOL got_realm = False; + BOOL use_own_domain = False; + + /* if the realm and workgroup are both empty, assume they are ours */ /* realm */ c_realm = ads->server.realm; + + if ( !c_realm || !*c_realm ) { + /* special case where no realm and no workgroup means our own */ + if ( !ads->server.workgroup || !*ads->server.workgroup ) { + use_own_domain = True; + c_realm = lp_realm(); + } + } + if (c_realm && *c_realm) got_realm = True; - + again: /* we need to try once with the realm name and fallback to the netbios domain name if we fail (if netbios has not been disabled */ @@ -119,7 +131,12 @@ again: if ( !got_realm && !lp_disable_netbios() ) { c_realm = ads->server.workgroup; if (!c_realm || !*c_realm) { - DEBUG(0,("ads_find_dc: no realm or workgroup! Was the structure initialized?\n")); + if ( use_own_domain ) + c_realm = lp_workgroup(); + } + + if ( !c_realm || !*c_realm ) { + DEBUG(0,("ads_find_dc: no realm or workgroup! Don't know what to do\n")); return False; } } @@ -1871,77 +1888,6 @@ ADS_STATUS ads_server_info(ADS_STRUCT *ads) return ADS_SUCCESS; } - -/** - * find the list of trusted domains - * @param ads connection to ads server - * @param mem_ctx TALLOC_CTX for allocating results - * @param num_trusts pointer to number of trusts - * @param names pointer to trusted domain name list - * @param sids pointer to list of sids of trusted domains - * @return the count of SIDs pulled - **/ -ADS_STATUS ads_trusted_domains(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, - int *num_trusts, - char ***names, - char ***alt_names, - DOM_SID **sids) -{ - const char *attrs[] = {"name", "flatname", "securityIdentifier", - "trustDirection", NULL}; - ADS_STATUS status; - void *res, *msg; - int count, i; - - *num_trusts = 0; - - status = ads_search(ads, &res, "(objectcategory=trustedDomain)", attrs); - if (!ADS_ERR_OK(status)) return status; - - count = ads_count_replies(ads, res); - if (count == 0) { - ads_msgfree(ads, res); - return ADS_ERROR(LDAP_NO_RESULTS_RETURNED); - } - - (*names) = talloc(mem_ctx, sizeof(char *) * count); - (*alt_names) = talloc(mem_ctx, sizeof(char *) * count); - (*sids) = talloc(mem_ctx, sizeof(DOM_SID) * count); - if (! *names || ! *sids) return ADS_ERROR(LDAP_NO_MEMORY); - - for (i=0, msg = ads_first_entry(ads, res); msg; msg = ads_next_entry(ads, msg)) { - uint32 direction; - - /* direction is a 2 bit bitfield, 1 means they trust us - but we don't trust them, so we should not list them - as users from that domain can't login */ - if (ads_pull_uint32(ads, msg, "trustDirection", &direction) && - direction == 1) { - continue; - } - - (*names)[i] = ads_pull_string(ads, mem_ctx, msg, "name"); - (*alt_names)[i] = ads_pull_string(ads, mem_ctx, msg, "flatname"); - - if ((*alt_names)[i] && (*alt_names)[i][0]) { - /* we prefer the flatname as the primary name - for consistency with RPC */ - char *name = (*alt_names)[i]; - (*alt_names)[i] = (*names)[i]; - (*names)[i] = name; - } - if (ads_pull_sid(ads, msg, "securityIdentifier", &(*sids)[i])) { - i++; - } - } - - ads_msgfree(ads, res); - - *num_trusts = i; - - return ADS_SUCCESS; -} - /** * find the domain sid for our domain * @param ads connection to ads server diff --git a/source3/libads/ldap_printer.c b/source3/libads/ldap_printer.c index b650a5eb38..1448074ea0 100644 --- a/source3/libads/ldap_printer.c +++ b/source3/libads/ldap_printer.c @@ -1,7 +1,7 @@ /* Unix SMB/CIFS implementation. ads (active directory) printer utility library - Copyright (C) Jim McDonough 2002 + Copyright (C) Jim McDonough 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 diff --git a/source3/libads/ldap_user.c b/source3/libads/ldap_user.c index e70249dd78..56a0d8013b 100644 --- a/source3/libads/ldap_user.c +++ b/source3/libads/ldap_user.c @@ -1,7 +1,7 @@ /* Unix SMB/CIFS implementation. ads (active directory) utility library - Copyright (C) Jim McDonough 2002 + Copyright (C) Jim McDonough 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 diff --git a/source3/libads/sasl.c b/source3/libads/sasl.c index 598208b17f..910ff3f4dc 100644 --- a/source3/libads/sasl.c +++ b/source3/libads/sasl.c @@ -124,9 +124,10 @@ static ADS_STATUS ads_sasl_spnego_krb5_bind(ADS_STRUCT *ads, const char *princip { DATA_BLOB blob; struct berval cred, *scred; + unsigned char sk[16]; int rc; - blob = spnego_gen_negTokenTarg(principal, ads->auth.time_offset); + blob = spnego_gen_negTokenTarg(principal, ads->auth.time_offset, sk); if (!blob.data) { return ADS_ERROR(LDAP_OPERATIONS_ERROR); diff --git a/source3/libsmb/asn1.c b/source3/libsmb/asn1.c index 09d4fbb6c9..576491dd3b 100644 --- a/source3/libsmb/asn1.c +++ b/source3/libsmb/asn1.c @@ -322,9 +322,9 @@ BOOL asn1_read_OID(ASN1_DATA *data, char **OID) asn1_read_uint8(data, &b); oid[0] = 0; - snprintf(el, sizeof(el), "%u", b/40); + fstr_sprintf(el, "%u", b/40); pstrcat(oid, el); - snprintf(el, sizeof(el), " %u", b%40); + fstr_sprintf(el, " %u", b%40); pstrcat(oid, el); while (asn1_tag_remaining(data) > 0) { @@ -333,7 +333,7 @@ BOOL asn1_read_OID(ASN1_DATA *data, char **OID) asn1_read_uint8(data, &b); v = (v<<7) | (b&0x7f); } while (!data->has_error && b & 0x80); - snprintf(el, sizeof(el), " %u", v); + fstr_sprintf(el, " %u", v); pstrcat(oid, el); } diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c index fa9af19bf5..94fe04a480 100644 --- a/source3/libsmb/cliconnect.c +++ b/source3/libsmb/cliconnect.c @@ -190,7 +190,7 @@ static BOOL cli_session_setup_plaintext(struct cli_state *cli, const char *user, char *p; fstring lanman; - snprintf( lanman, sizeof(lanman), "Samba %s", VERSION ); + fstr_sprintf( lanman, "Samba %s", VERSION ); set_message(cli->outbuf,13,0,True); SCVAL(cli->outbuf,smb_com,SMBsesssetupX); @@ -301,7 +301,7 @@ static BOOL cli_session_setup_nt1(struct cli_state *cli, const char *user, lm_response = data_blob(NULL, 24); SMBencrypt(pass,cli->secblob.data, lm_response.data); } else { - /* LM disabled, place NT# in LM feild instead */ + /* LM disabled, place NT# in LM field instead */ lm_response = data_blob(nt_response.data, nt_response.length); } @@ -472,6 +472,7 @@ static DATA_BLOB cli_session_setup_blob(struct cli_state *cli, DATA_BLOB blob) /**************************************************************************** Use in-memory credentials cache ****************************************************************************/ + static void use_in_memory_ccache(void) { setenv(KRB5_ENV_CCNAME, "MEMORY:cliconnect", 1); } @@ -483,18 +484,23 @@ static void use_in_memory_ccache(void) { static BOOL cli_session_setup_kerberos(struct cli_state *cli, const char *principal, const char *workgroup) { DATA_BLOB blob2, negTokenTarg; - + unsigned char session_key_krb5[16]; + DATA_BLOB null_blob = data_blob(NULL, 0); + DEBUG(2,("Doing kerberos session setup\n")); /* generate the encapsulated kerberos5 ticket */ - negTokenTarg = spnego_gen_negTokenTarg(principal, 0); + negTokenTarg = spnego_gen_negTokenTarg(principal, 0, session_key_krb5); - if (!negTokenTarg.data) return False; + if (!negTokenTarg.data) + return False; #if 0 file_save("negTokenTarg.dat", negTokenTarg.data, negTokenTarg.length); #endif + cli_simple_set_signing(cli, session_key_krb5, null_blob); + blob2 = cli_session_setup_blob(cli, negTokenTarg); /* we don't need this blob for kerberos */ @@ -551,7 +557,7 @@ static BOOL cli_session_setup_ntlmssp(struct cli_state *cli, const char *user, blob_in, &blob_out); data_blob_free(&blob_in); if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { - DATA_BLOB null = data_blob(NULL, 0); + DATA_BLOB null_blob = data_blob(NULL, 0); if (turn == 1) { /* and wrap it in a SPNEGO wrapper */ msg1 = gen_negTokenInit(OID_NTLMSSP, blob_out); @@ -562,7 +568,7 @@ static BOOL cli_session_setup_ntlmssp(struct cli_state *cli, const char *user, cli_simple_set_signing(cli, ntlmssp_state->session_key.data, - null); + null_blob); /* now send that blob on its way */ if (!cli_session_setup_blob_send(cli, msg1)) { @@ -630,7 +636,7 @@ static BOOL cli_session_setup_spnego(struct cli_state *cli, const char *user, BOOL got_kerberos_mechanism = False; DATA_BLOB blob; - DEBUG(2,("Doing spnego session setup (blob length=%d)\n", cli->secblob.length)); + DEBUG(2,("Doing spnego session setup (blob length=%lu)\n", (unsigned long)cli->secblob.length)); /* the server might not even do spnego */ if (cli->secblob.length <= 16) { @@ -989,6 +995,11 @@ BOOL cli_negprot(struct cli_state *cli) cli->protocol = prots[SVAL(cli->inbuf,smb_vwv0)].prot; + if ((cli->protocol < PROTOCOL_NT1) && cli->sign_info.mandatory_signing) { + DEBUG(1,("cli_negprot: SMB signing is mandatory and the selected protocol level doesn't support it.\n")); + return False; + } + if (cli->protocol >= PROTOCOL_NT1) { /* NT protocol */ cli->sec_mode = CVAL(cli->inbuf,smb_vwv1); @@ -1015,7 +1026,7 @@ BOOL cli_negprot(struct cli_state *cli) if ((cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED)) { /* Fail if signing is mandatory and we don't want to support it. */ - if (!lp_client_signing()) { + if (!cli->sign_info.allow_smb_signing) { DEBUG(1,("cli_negprot: SMB signing is mandatory and we have disabled it.\n")); return False; } @@ -1248,6 +1259,7 @@ NTSTATUS cli_full_connection(struct cli_state **output_cli, const char *service, const char *service_type, const char *user, const char *domain, const char *password, int flags, + int signing_state, BOOL *retry) { struct ntuser_creds creds; @@ -1310,6 +1322,8 @@ again: return NT_STATUS_UNSUCCESSFUL; } + cli_setup_signing_state(cli, signing_state); + if (flags & CLI_FULL_CONNECTION_DONT_SPNEGO) cli->use_spnego = False; else if (flags & CLI_FULL_CONNECTION_USE_KERBEROS) @@ -1480,7 +1494,7 @@ struct cli_state *get_ipc_connect(char *server, struct in_addr *server_ip, nt_status = cli_full_connection(&cli, myname, server, server_ip, 0, "IPC$", "IPC", user_info->username, lp_workgroup(), user_info->password, - CLI_FULL_CONNECTION_ANNONYMOUS_FALLBACK, NULL); + CLI_FULL_CONNECTION_ANNONYMOUS_FALLBACK, Undefined, NULL); if (NT_STATUS_IS_OK(nt_status)) { return cli; diff --git a/source3/libsmb/clientgen.c b/source3/libsmb/clientgen.c index 58c5ad8cd3..bc5f1462cc 100644 --- a/source3/libsmb/clientgen.c +++ b/source3/libsmb/clientgen.c @@ -141,7 +141,7 @@ BOOL cli_send_smb(struct cli_state *cli) if (cli->fd == -1) return False; - cli_caclulate_sign_mac(cli); + cli_calculate_sign_mac(cli); len = smb_len(cli->outbuf) + 4; @@ -157,6 +157,10 @@ BOOL cli_send_smb(struct cli_state *cli) } nwritten += ret; } + /* Increment the mid so we can tell between responses. */ + cli->mid++; + if (!cli->mid) + cli->mid++; return True; } @@ -208,6 +212,27 @@ void cli_init_creds(struct cli_state *cli, const struct ntuser_creds *usr) cli->user_name, cli->domain)); } +/**************************************************************************** + Set the signing state (used from the command line). +****************************************************************************/ + +void cli_setup_signing_state(struct cli_state *cli, int signing_state) +{ + if (signing_state == Undefined) + return; + + if (signing_state == False) { + cli->sign_info.allow_smb_signing = False; + cli->sign_info.mandatory_signing = False; + return; + } + + cli->sign_info.allow_smb_signing = True; + + if (signing_state == Required) + cli->sign_info.mandatory_signing = True; +} + /**************************************************************************** Initialise a client structure. ****************************************************************************/ diff --git a/source3/libsmb/clierror.c b/source3/libsmb/clierror.c index 9ee181a90f..c27e1955e2 100644 --- a/source3/libsmb/clierror.c +++ b/source3/libsmb/clierror.c @@ -108,7 +108,7 @@ const char *cli_errstr(struct cli_state *cli) break; case READ_BAD_SIG: slprintf(cli_error_message, sizeof(cli_error_message) - 1, - "Server packet had invalid SMB signiture!"); + "Server packet had invalid SMB signature!"); break; default: slprintf(cli_error_message, sizeof(cli_error_message) - 1, @@ -371,6 +371,9 @@ BOOL cli_is_error(struct cli_state *cli) { uint32 flgs2 = SVAL(cli->inbuf,smb_flg2), rcls = 0; + if (cli->fd == -1 && cli->smb_rw_error != 0) + return True; + if (flgs2 & FLAGS2_32_BIT_ERROR_CODES) { /* Return error is error bits are set */ rcls = IVAL(cli->inbuf, smb_rcls); diff --git a/source3/libsmb/clikrb5.c b/source3/libsmb/clikrb5.c index fd5dd91325..beac8cb2c1 100644 --- a/source3/libsmb/clikrb5.c +++ b/source3/libsmb/clikrb5.c @@ -305,7 +305,7 @@ cleanup_princ: /* get a kerberos5 ticket for the given service */ -DATA_BLOB cli_krb5_get_ticket(const char *principal, time_t time_offset) +DATA_BLOB cli_krb5_get_ticket(const char *principal, time_t time_offset, unsigned char session_key_krb5[16]) { krb5_error_code retval; krb5_data packet; @@ -345,13 +345,15 @@ DATA_BLOB cli_krb5_get_ticket(const char *principal, time_t time_offset) } if ((retval = ads_krb5_mk_req(context, - &auth_context, - 0, - principal, - ccdef, &packet))) { + &auth_context, + AP_OPTS_USE_SUBKEY, + principal, + ccdef, &packet))) { goto failed; } + get_krb5_smb_session_key(context, auth_context, session_key_krb5, False); + ret = data_blob(packet.data, packet.length); /* Hmm, heimdal dooesn't have this - what's the correct call? */ /* krb5_free_data_contents(context, &packet); */ @@ -365,17 +367,22 @@ failed: return data_blob(NULL, 0); } - BOOL get_krb5_smb_session_key(krb5_context context, krb5_auth_context auth_context, uint8 session_key[16]) + BOOL get_krb5_smb_session_key(krb5_context context, krb5_auth_context auth_context, uint8 session_key[16], BOOL remote) { #ifdef ENCTYPE_ARCFOUR_HMAC krb5_keyblock *skey; #endif BOOL ret = False; + krb5_error_code err; memset(session_key, 0, 16); #ifdef ENCTYPE_ARCFOUR_HMAC - if (krb5_auth_con_getremotesubkey(context, auth_context, &skey) == 0 && skey != NULL) { + if (remote) + err = krb5_auth_con_getremotesubkey(context, auth_context, &skey); + else + err = krb5_auth_con_getlocalsubkey(context, auth_context, &skey); + if (err == 0 && skey != NULL) { if (KRB5_KEY_TYPE(skey) == ENCTYPE_ARCFOUR_HMAC && KRB5_KEY_LENGTH(skey) == 16) { @@ -388,9 +395,22 @@ failed: return ret; } + + +#if defined(HAVE_KRB5_PRINCIPAL_GET_COMP_STRING) && !defined(HAVE_KRB5_PRINC_COMPONENT) + const krb5_data *krb5_princ_component(krb5_context context, krb5_principal principal, int i ) +{ + static krb5_data kdata; + + kdata.data = krb5_principal_get_comp_string(context, principal, i); + kdata.length = strlen(kdata.data); + return &kdata; +} +#endif + #else /* HAVE_KRB5 */ /* this saves a few linking headaches */ -DATA_BLOB cli_krb5_get_ticket(const char *principal, time_t time_offset) +DATA_BLOB cli_krb5_get_ticket(const char *principal, time_t time_offset, unsigned char session_key_krb5[16]) { DEBUG(0,("NO KERBEROS SUPPORT\n")); return data_blob(NULL, 0); diff --git a/source3/libsmb/clilist.c b/source3/libsmb/clilist.c index 5bd1283ab7..7822987ada 100644 --- a/source3/libsmb/clilist.c +++ b/source3/libsmb/clilist.c @@ -101,13 +101,20 @@ static int interpret_long_filename(struct cli_state *cli, cheap to calculate, I suppose, as no DST tables will be needed */ - finfo->ctime = interpret_long_date(p); p += 8; - finfo->atime = interpret_long_date(p); p += 8; - finfo->mtime = interpret_long_date(p); p += 8; p += 8; - finfo->size = IVAL2_TO_SMB_BIG_UINT(p,0); p += 8; + finfo->ctime = interpret_long_date(p); + p += 8; + finfo->atime = interpret_long_date(p); + p += 8; + finfo->mtime = interpret_long_date(p); + p += 8; + p += 8; + finfo->size = IVAL2_TO_SMB_BIG_UINT(p,0); + p += 8; p += 8; /* alloc size */ - finfo->mode = CVAL(p,0); p += 4; - namelen = IVAL(p,0); p += 4; + finfo->mode = CVAL(p,0); + p += 4; + namelen = IVAL(p,0); + p += 4; p += 4; /* EA size */ slen = SVAL(p, 0); p += 2; @@ -138,7 +145,11 @@ static int interpret_long_filename(struct cli_state *cli, int cli_list_new(struct cli_state *cli,const char *Mask,uint16 attribute, void (*fn)(file_info *, const char *, void *), void *state) { +#if 0 + int max_matches = 1366; /* Match W2k - was 512. */ +#else int max_matches = 512; +#endif int info_level; char *p, *p2; pstring mask; @@ -200,7 +211,12 @@ int cli_list_new(struct cli_state *cli,const char *Mask,uint16 attribute, &setup, 1, 0, /* setup, length, max */ param, param_len, 10, /* param, length, max */ NULL, 0, - cli->max_xmit /* data, length, max */ +#if 0 + /* w2k value. */ + MIN(16384,cli->max_xmit) /* data, length, max. */ +#else + cli->max_xmit /* data, length, max. */ +#endif )) { break; } @@ -214,7 +230,8 @@ int cli_list_new(struct cli_state *cli,const char *Mask,uint16 attribute, uint8 eclass; uint32 ecode; cli_dos_error(cli, &eclass, &ecode); - if (eclass != ERRSRV || ecode != ERRerror) break; + if (eclass != ERRSRV || ecode != ERRerror) + break; msleep(100); continue; } @@ -222,7 +239,8 @@ int cli_list_new(struct cli_state *cli,const char *Mask,uint16 attribute, if (cli_is_error(cli) || !rdata || !rparam) break; - if (total_received == -1) total_received = 0; + if (total_received == -1) + total_received = 0; /* parse out some important return info */ p = rparam; @@ -245,8 +263,7 @@ int cli_list_new(struct cli_state *cli,const char *Mask,uint16 attribute, /* we might need the lastname for continuations */ if (ff_lastname > 0) { - switch(info_level) - { + switch(info_level) { case 260: clistr_pull(cli, mask, p+ff_lastname, sizeof(mask), @@ -270,8 +287,9 @@ int cli_list_new(struct cli_state *cli,const char *Mask,uint16 attribute, if (!tdl) { DEBUG(0,("cli_list_new: Failed to expand dirlist\n")); break; + } else { + dirlist = tdl; } - else dirlist = tdl; /* put in a length for the last entry, to ensure we can chain entries into the next packet */ @@ -291,7 +309,8 @@ int cli_list_new(struct cli_state *cli,const char *Mask,uint16 attribute, DEBUG(3,("received %d entries (eos=%d)\n", ff_searchcount,ff_eos)); - if (ff_searchcount > 0) loop_count = 0; + if (ff_searchcount > 0) + loop_count = 0; First = False; } diff --git a/source3/libsmb/cliprint.c b/source3/libsmb/cliprint.c index bfa33bc514..f302c045a5 100644 --- a/source3/libsmb/cliprint.c +++ b/source3/libsmb/cliprint.c @@ -65,16 +65,16 @@ int cli_print_queue(struct cli_state *cli, p = param; SSVAL(p,0,76); /* API function number 76 (DosPrintJobEnum) */ p += 2; - pstrcpy(p,"zWrLeh"); /* parameter description? */ + pstrcpy_base(p,"zWrLeh", param); /* parameter description? */ p = skip_string(p,1); - pstrcpy(p,"WWzWWDDzz"); /* returned data format */ + pstrcpy_base(p,"WWzWWDDzz", param); /* returned data format */ p = skip_string(p,1); - pstrcpy(p,cli->share); /* name of queue */ + pstrcpy_base(p,cli->share, param); /* name of queue */ p = skip_string(p,1); SSVAL(p,0,2); /* API function level 2, PRJINFO_2 data structure */ SSVAL(p,2,1000); /* size of bytes of returned data buffer */ p += 4; - pstrcpy(p,""); /* subformat */ + pstrcpy_base(p,"", param); /* subformat */ p = skip_string(p,1); DEBUG(4,("doing cli_print_queue for %s\n", cli->share)); @@ -133,9 +133,9 @@ int cli_printjob_del(struct cli_state *cli, int job) p = param; SSVAL(p,0,81); /* DosPrintJobDel() */ p += 2; - pstrcpy(p,"W"); + pstrcpy_base(p,"W", param); p = skip_string(p,1); - pstrcpy(p,""); + pstrcpy_base(p,"", param); p = skip_string(p,1); SSVAL(p,0,job); p += 2; diff --git a/source3/libsmb/clispnego.c b/source3/libsmb/clispnego.c index bb48f57915..b0570b09b6 100644 --- a/source3/libsmb/clispnego.c +++ b/source3/libsmb/clispnego.c @@ -2,7 +2,7 @@ Unix SMB/CIFS implementation. simple kerberos5/SPNEGO routines Copyright (C) Andrew Tridgell 2001 - Copyright (C) Jim McDonough 2002 + Copyright (C) Jim McDonough 2002 Copyright (C) Luke Howard 2003 This program is free software; you can redistribute it and/or modify @@ -323,13 +323,13 @@ BOOL spnego_parse_krb5_wrap(DATA_BLOB blob, DATA_BLOB *ticket, uint8 tok_id[2]) generate a SPNEGO negTokenTarg packet, ready for a EXTENDED_SECURITY kerberos session setup */ -DATA_BLOB spnego_gen_negTokenTarg(const char *principal, int time_offset) +DATA_BLOB spnego_gen_negTokenTarg(const char *principal, int time_offset, unsigned char session_key_krb5[16]) { DATA_BLOB tkt, tkt_wrapped, targ; const char *krb_mechs[] = {OID_KERBEROS5_OLD, OID_NTLMSSP, NULL}; - /* get a kerberos ticket for the service */ - tkt = cli_krb5_get_ticket(principal, time_offset); + /* get a kerberos ticket for the service and extract the session key */ + tkt = cli_krb5_get_ticket(principal, time_offset, session_key_krb5); /* wrap that up in a nice GSS-API wrapping */ tkt_wrapped = spnego_gen_krb5_wrap(tkt, TOK_ID_KRB_AP_REQ); diff --git a/source3/libsmb/clitrans.c b/source3/libsmb/clitrans.c index 3d3cd427d7..e6771ac688 100644 --- a/source3/libsmb/clitrans.c +++ b/source3/libsmb/clitrans.c @@ -40,6 +40,7 @@ BOOL cli_send_trans(struct cli_state *cli, int trans, char *outdata,*outparam; char *p; int pipe_name_len=0; + uint16 mid; this_lparam = MIN(lparam,cli->max_xmit - (500+lsetup*2)); /* hack */ this_ldata = MIN(ldata,cli->max_xmit - (500+lsetup*2+this_lparam)); @@ -49,6 +50,7 @@ BOOL cli_send_trans(struct cli_state *cli, int trans, SCVAL(cli->outbuf,smb_com,trans); SSVAL(cli->outbuf,smb_tid, cli->cnum); cli_setup_packet(cli); + mid = cli->mid; if (pipe_name) { pipe_name_len = clistr_push(cli, smb_buf(cli->outbuf), pipe_name, -1, STR_TERMINATE); @@ -84,13 +86,19 @@ BOOL cli_send_trans(struct cli_state *cli, int trans, cli_setup_bcc(cli, outdata+this_ldata); show_msg(cli->outbuf); - if (!cli_send_smb(cli)) + + cli_signing_trans_start(cli); + if (!cli_send_smb(cli)) { + cli_signing_trans_stop(cli); return False; + } if (this_ldata < ldata || this_lparam < lparam) { /* receive interim response */ - if (!cli_receive_smb(cli) || cli_is_error(cli)) + if (!cli_receive_smb(cli) || cli_is_error(cli)) { + cli_signing_trans_stop(cli); return(False); + } tot_data = this_ldata; tot_param = this_lparam; @@ -122,9 +130,15 @@ BOOL cli_send_trans(struct cli_state *cli, int trans, memcpy(outdata,data+tot_data,this_ldata); cli_setup_bcc(cli, outdata+this_ldata); + /* Ensure this packet has the same MID as + * the primary. Important in signing. JRA. */ + cli->mid = mid; + show_msg(cli->outbuf); - if (!cli_send_smb(cli)) + if (!cli_send_smb(cli)) { + cli_signing_trans_stop(cli); return False; + } tot_data += this_ldata; tot_param += this_lparam; @@ -151,8 +165,10 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans, *data_len = *param_len = 0; - if (!cli_receive_smb(cli)) + if (!cli_receive_smb(cli)) { + cli_signing_trans_stop(cli); return False; + } show_msg(cli->inbuf); @@ -161,6 +177,7 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans, DEBUG(0,("Expected %s response, got command 0x%02x\n", trans==SMBtrans?"SMBtrans":"SMBtrans2", CVAL(cli->inbuf,smb_com))); + cli_signing_trans_stop(cli); return(False); } @@ -171,8 +188,10 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans, */ status = cli_nt_error(cli); - if (NT_STATUS_IS_ERR(status)) + if (NT_STATUS_IS_ERR(status)) { + cli_signing_trans_stop(cli); return False; + } /* parse out the lengths */ total_data = SVAL(cli->inbuf,smb_tdrcnt); @@ -183,6 +202,7 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans, tdata = Realloc(*data,total_data); if (!tdata) { DEBUG(0,("cli_receive_trans: failed to enlarge data buffer\n")); + cli_signing_trans_stop(cli); return False; } else @@ -193,6 +213,7 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans, tparam = Realloc(*param,total_param); if (!tparam) { DEBUG(0,("cli_receive_trans: failed to enlarge param buffer\n")); + cli_signing_trans_stop(cli); return False; } else @@ -206,6 +227,7 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans, if (this_data + *data_len > total_data || this_param + *param_len > total_param) { DEBUG(1,("Data overflow in cli_receive_trans\n")); + cli_signing_trans_stop(cli); return False; } @@ -214,6 +236,7 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans, this_param + *param_len < this_param || this_param + *param_len < *param_len) { DEBUG(1,("Data overflow in cli_receive_trans\n")); + cli_signing_trans_stop(cli); return False; } @@ -226,6 +249,7 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans, data_offset_out + this_data < data_offset_out || data_offset_out + this_data < this_data) { DEBUG(1,("Data overflow in cli_receive_trans\n")); + cli_signing_trans_stop(cli); return False; } if (data_offset_in > cli->bufsize || @@ -233,6 +257,7 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans, data_offset_in + this_data < data_offset_in || data_offset_in + this_data < this_data) { DEBUG(1,("Data overflow in cli_receive_trans\n")); + cli_signing_trans_stop(cli); return False; } @@ -247,6 +272,7 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans, param_offset_out + this_param < param_offset_out || param_offset_out + this_param < this_param) { DEBUG(1,("Param overflow in cli_receive_trans\n")); + cli_signing_trans_stop(cli); return False; } if (param_offset_in > cli->bufsize || @@ -254,6 +280,7 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans, param_offset_in + this_param < param_offset_in || param_offset_in + this_param < this_param) { DEBUG(1,("Param overflow in cli_receive_trans\n")); + cli_signing_trans_stop(cli); return False; } @@ -265,8 +292,10 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans, if (total_data <= *data_len && total_param <= *param_len) break; - if (!cli_receive_smb(cli)) - return False; + if (!cli_receive_smb(cli)) { + cli_signing_trans_stop(cli); + return False; + } show_msg(cli->inbuf); @@ -275,9 +304,11 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans, DEBUG(0,("Expected %s response, got command 0x%02x\n", trans==SMBtrans?"SMBtrans":"SMBtrans2", CVAL(cli->inbuf,smb_com))); + cli_signing_trans_stop(cli); return(False); } if (NT_STATUS_IS_ERR(cli_nt_error(cli))) { + cli_signing_trans_stop(cli); return(False); } @@ -292,6 +323,7 @@ BOOL cli_receive_trans(struct cli_state *cli,int trans, } + cli_signing_trans_stop(cli); return(True); } @@ -309,6 +341,7 @@ BOOL cli_send_nt_trans(struct cli_state *cli, unsigned int i; unsigned int this_ldata,this_lparam; unsigned int tot_data=0,tot_param=0; + uint16 mid; char *outdata,*outparam; this_lparam = MIN(lparam,cli->max_xmit - (500+lsetup*2)); /* hack */ @@ -319,6 +352,7 @@ BOOL cli_send_nt_trans(struct cli_state *cli, SCVAL(cli->outbuf,smb_com,SMBnttrans); SSVAL(cli->outbuf,smb_tid, cli->cnum); cli_setup_packet(cli); + mid = cli->mid; outparam = smb_buf(cli->outbuf)+3; outdata = outparam+this_lparam; @@ -347,13 +381,18 @@ BOOL cli_send_nt_trans(struct cli_state *cli, cli_setup_bcc(cli, outdata+this_ldata); show_msg(cli->outbuf); - if (!cli_send_smb(cli)) + cli_signing_trans_start(cli); + if (!cli_send_smb(cli)) { + cli_signing_trans_stop(cli); return False; + } if (this_ldata < ldata || this_lparam < lparam) { /* receive interim response */ - if (!cli_receive_smb(cli) || cli_is_error(cli)) + if (!cli_receive_smb(cli) || cli_is_error(cli)) { + cli_signing_trans_stop(cli); return(False); + } tot_data = this_ldata; tot_param = this_lparam; @@ -384,9 +423,16 @@ BOOL cli_send_nt_trans(struct cli_state *cli, memcpy(outdata,data+tot_data,this_ldata); cli_setup_bcc(cli, outdata+this_ldata); + /* Ensure this packet has the same MID as + * the primary. Important in signing. JRA. */ + cli->mid = mid; + show_msg(cli->outbuf); - if (!cli_send_smb(cli)) + + if (!cli_send_smb(cli)) { + cli_signing_trans_stop(cli); return False; + } tot_data += this_ldata; tot_param += this_lparam; @@ -396,8 +442,6 @@ BOOL cli_send_nt_trans(struct cli_state *cli, return(True); } - - /**************************************************************************** receive a SMB nttrans response allocating the necessary memory ****************************************************************************/ @@ -416,8 +460,10 @@ BOOL cli_receive_nt_trans(struct cli_state *cli, *data_len = *param_len = 0; - if (!cli_receive_smb(cli)) + if (!cli_receive_smb(cli)) { + cli_signing_trans_stop(cli); return False; + } show_msg(cli->inbuf); @@ -425,6 +471,7 @@ BOOL cli_receive_nt_trans(struct cli_state *cli, if (CVAL(cli->inbuf,smb_com) != SMBnttrans) { DEBUG(0,("Expected SMBnttrans response, got command 0x%02x\n", CVAL(cli->inbuf,smb_com))); + cli_signing_trans_stop(cli); return(False); } @@ -435,8 +482,10 @@ BOOL cli_receive_nt_trans(struct cli_state *cli, */ if (cli_is_dos_error(cli)) { cli_dos_error(cli, &eclass, &ecode); - if (cli->nt_pipe_fnum == 0 || !(eclass == ERRDOS && ecode == ERRmoredata)) + if (cli->nt_pipe_fnum == 0 || !(eclass == ERRDOS && ecode == ERRmoredata)) { + cli_signing_trans_stop(cli); return(False); + } } /* parse out the lengths */ @@ -448,6 +497,7 @@ BOOL cli_receive_nt_trans(struct cli_state *cli, tdata = Realloc(*data,total_data); if (!tdata) { DEBUG(0,("cli_receive_nt_trans: failed to enlarge data buffer to %d\n",total_data)); + cli_signing_trans_stop(cli); return False; } else { *data = tdata; @@ -458,6 +508,7 @@ BOOL cli_receive_nt_trans(struct cli_state *cli, tparam = Realloc(*param,total_param); if (!tparam) { DEBUG(0,("cli_receive_nt_trans: failed to enlarge param buffer to %d\n", total_param)); + cli_signing_trans_stop(cli); return False; } else { *param = tparam; @@ -471,6 +522,7 @@ BOOL cli_receive_nt_trans(struct cli_state *cli, if (this_data + *data_len > total_data || this_param + *param_len > total_param) { DEBUG(1,("Data overflow in cli_receive_nt_trans\n")); + cli_signing_trans_stop(cli); return False; } @@ -479,6 +531,7 @@ BOOL cli_receive_nt_trans(struct cli_state *cli, this_param + *param_len < this_param || this_param + *param_len < *param_len) { DEBUG(1,("Data overflow in cli_receive_nt_trans\n")); + cli_signing_trans_stop(cli); return False; } @@ -491,6 +544,7 @@ BOOL cli_receive_nt_trans(struct cli_state *cli, data_offset_out + this_data < data_offset_out || data_offset_out + this_data < this_data) { DEBUG(1,("Data overflow in cli_receive_nt_trans\n")); + cli_signing_trans_stop(cli); return False; } if (data_offset_in > cli->bufsize || @@ -498,6 +552,7 @@ BOOL cli_receive_nt_trans(struct cli_state *cli, data_offset_in + this_data < data_offset_in || data_offset_in + this_data < this_data) { DEBUG(1,("Data overflow in cli_receive_nt_trans\n")); + cli_signing_trans_stop(cli); return False; } @@ -513,6 +568,7 @@ BOOL cli_receive_nt_trans(struct cli_state *cli, param_offset_out + this_param < param_offset_out || param_offset_out + this_param < this_param) { DEBUG(1,("Param overflow in cli_receive_nt_trans\n")); + cli_signing_trans_stop(cli); return False; } if (param_offset_in > cli->bufsize || @@ -520,6 +576,7 @@ BOOL cli_receive_nt_trans(struct cli_state *cli, param_offset_in + this_param < param_offset_in || param_offset_in + this_param < this_param) { DEBUG(1,("Param overflow in cli_receive_nt_trans\n")); + cli_signing_trans_stop(cli); return False; } @@ -532,8 +589,10 @@ BOOL cli_receive_nt_trans(struct cli_state *cli, if (total_data <= *data_len && total_param <= *param_len) break; - if (!cli_receive_smb(cli)) + if (!cli_receive_smb(cli)) { + cli_signing_trans_stop(cli); return False; + } show_msg(cli->inbuf); @@ -541,13 +600,15 @@ BOOL cli_receive_nt_trans(struct cli_state *cli, if (CVAL(cli->inbuf,smb_com) != SMBnttrans) { DEBUG(0,("Expected SMBnttrans response, got command 0x%02x\n", CVAL(cli->inbuf,smb_com))); + cli_signing_trans_stop(cli); return(False); } if (cli_is_dos_error(cli)) { cli_dos_error(cli, &eclass, &ecode); - if(cli->nt_pipe_fnum == 0 || - !(eclass == ERRDOS && ecode == ERRmoredata)) + if(cli->nt_pipe_fnum == 0 || !(eclass == ERRDOS && ecode == ERRmoredata)) { + cli_signing_trans_stop(cli); return(False); + } } /* parse out the total lengths again - they can shrink! */ if (SVAL(cli->inbuf,smb_ntr_TotalDataCount) < total_data) @@ -559,5 +620,6 @@ BOOL cli_receive_nt_trans(struct cli_state *cli, break; } + cli_signing_trans_stop(cli); return(True); } diff --git a/source3/libsmb/errormap.c b/source3/libsmb/errormap.c index 8ee5ee3d31..3d99e3d5e5 100644 --- a/source3/libsmb/errormap.c +++ b/source3/libsmb/errormap.c @@ -1498,6 +1498,7 @@ const struct unix_error_map unix_dos_nt_errmap[] = { { ENFILE, ERRDOS, ERRnofids, NT_STATUS_TOO_MANY_OPENED_FILES }, { EMFILE, ERRDOS, ERRnofids, NT_STATUS_TOO_MANY_OPENED_FILES }, { ENOSPC, ERRHRD, ERRdiskfull, NT_STATUS_DISK_FULL }, + { ENOMEM, ERRDOS, ERRnomem, NT_STATUS_NO_MEMORY }, #ifdef EDQUOT { EDQUOT, ERRHRD, ERRdiskfull, NT_STATUS_DISK_FULL }, #endif diff --git a/source3/libsmb/nmblib.c b/source3/libsmb/nmblib.c index 157a2bb43c..6ee05f0104 100644 --- a/source3/libsmb/nmblib.c +++ b/source3/libsmb/nmblib.c @@ -1129,12 +1129,14 @@ char *dns_to_netbios_name(char *dns_name) /**************************************************************************** -interpret the weird netbios "name". Return the name type +interpret the weird netbios "name" into a unix fstring. Return the name type ****************************************************************************/ -static int name_interpret(char *in,char *out) +static int name_interpret(char *in, fstring name) { int ret; int len = (*in++) / 2; + fstring out_string; + char *out = out_string; *out=0; @@ -1150,8 +1152,8 @@ static int name_interpret(char *in,char *out) in += 2; out++; } - *out = 0; ret = out[-1]; + out[-1] = 0; #ifdef NETBIOS_SCOPE /* Handle any scope names */ @@ -1165,6 +1167,8 @@ static int name_interpret(char *in,char *out) in += len; } #endif + pull_ascii(name, out_string, sizeof(fstring), sizeof(out_string), STR_TERMINATE); + return(ret); } @@ -1245,9 +1249,9 @@ static char *name_ptr(char *buf,int ofs) } /**************************************************************************** -extract a netbios name from a buf +extract a netbios name from a buf (into a unix string) return name type ****************************************************************************/ -int name_extract(char *buf,int ofs,char *name) +int name_extract(char *buf,int ofs, fstring name) { char *p = name_ptr(buf,ofs); int d = PTR_DIFF(p,buf+ofs); diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index 66dc6e08eb..a50ae9b70f 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -279,8 +279,8 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state, data_blob_free(&sess_key); - DEBUG(3,("Got user=[%s] domain=[%s] workstation=[%s] len1=%d len2=%d\n", - ntlmssp_state->user, ntlmssp_state->domain, ntlmssp_state->workstation, ntlmssp_state->lm_resp.length, ntlmssp_state->nt_resp.length)); + DEBUG(3,("Got user=[%s] domain=[%s] workstation=[%s] len1=%lu len2=%lu\n", + ntlmssp_state->user, ntlmssp_state->domain, ntlmssp_state->workstation, (unsigned long)ntlmssp_state->lm_resp.length, (unsigned long)ntlmssp_state->nt_resp.length)); #if 0 file_save("nthash1.dat", &ntlmssp_state->nt_resp.data, &ntlmssp_state->nt_resp.length); diff --git a/source3/libsmb/ntlmssp_parse.c b/source3/libsmb/ntlmssp_parse.c index f53afcdcd0..3c6da349e4 100644 --- a/source3/libsmb/ntlmssp_parse.c +++ b/source3/libsmb/ntlmssp_parse.c @@ -2,7 +2,7 @@ Unix SMB/CIFS implementation. simple kerberos5/SPNEGO routines Copyright (C) Andrew Tridgell 2001 - Copyright (C) Jim McDonough 2002 + Copyright (C) Jim McDonough 2002 Copyright (C) Andrew Bartlett 2002-2003 This program is free software; you can redistribute it and/or modify diff --git a/source3/libsmb/ntlmssp_sign.c b/source3/libsmb/ntlmssp_sign.c index 748c008963..ecaef808c9 100644 --- a/source3/libsmb/ntlmssp_sign.c +++ b/source3/libsmb/ntlmssp_sign.c @@ -102,7 +102,7 @@ enum ntlmssp_direction { NTLMSSP_RECEIVE }; -static NTSTATUS ntlmssp_make_packet_signiture(NTLMSSP_CLIENT_STATE *ntlmssp_state, +static NTSTATUS ntlmssp_make_packet_signature(NTLMSSP_CLIENT_STATE *ntlmssp_state, const uchar *data, size_t length, enum ntlmssp_direction direction, DATA_BLOB *sig) @@ -148,7 +148,7 @@ NTSTATUS ntlmssp_client_sign_packet(NTLMSSP_CLIENT_STATE *ntlmssp_state, const uchar *data, size_t length, DATA_BLOB *sig) { - NTSTATUS nt_status = ntlmssp_make_packet_signiture(ntlmssp_state, data, length, NTLMSSP_SEND, sig); + NTSTATUS nt_status = ntlmssp_make_packet_signature(ntlmssp_state, data, length, NTLMSSP_SEND, sig); /* increment counter on send */ ntlmssp_state->ntlmssp_seq_num++; @@ -169,11 +169,11 @@ NTSTATUS ntlmssp_client_check_packet(NTLMSSP_CLIENT_STATE *ntlmssp_state, NTSTATUS nt_status; if (sig->length < 8) { - DEBUG(0, ("NTLMSSP packet check failed due to short signiture (%u bytes)!\n", + DEBUG(0, ("NTLMSSP packet check failed due to short signature (%u bytes)!\n", sig->length)); } - nt_status = ntlmssp_make_packet_signiture(ntlmssp_state, data, + nt_status = ntlmssp_make_packet_signature(ntlmssp_state, data, length, NTLMSSP_RECEIVE, &local_sig); if (!NT_STATUS_IS_OK(nt_status)) { @@ -188,7 +188,7 @@ NTSTATUS ntlmssp_client_check_packet(NTLMSSP_CLIENT_STATE *ntlmssp_state, DEBUG(5, ("BAD SIG: got signature of\n")); dump_data(5, sig->data, sig->length); - DEBUG(0, ("NTLMSSP packet check failed due to invalid signiture!\n")); + DEBUG(0, ("NTLMSSP packet check failed due to invalid signature!\n")); return NT_STATUS_ACCESS_DENIED; } @@ -328,7 +328,7 @@ NTSTATUS ntlmssp_client_sign_init(NTLMSSP_CLIENT_STATE *ntlmssp_state) } else if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_LM_KEY) { if (!ntlmssp_state->session_key.data || ntlmssp_state->session_key.length < 8) { - /* can't sign or check signitures yet */ + /* can't sign or check signatures yet */ DEBUG(5, ("NTLMSSP Sign/Seal - cannot use LM KEY yet\n")); return NT_STATUS_UNSUCCESSFUL; } @@ -340,7 +340,7 @@ NTSTATUS ntlmssp_client_sign_init(NTLMSSP_CLIENT_STATE *ntlmssp_state) sizeof(ntlmssp_state->ntlmssp_hash)); } else { if (!ntlmssp_state->session_key.data || ntlmssp_state->session_key.length < 16) { - /* can't sign or check signitures yet */ + /* can't sign or check signatures yet */ DEBUG(5, ("NTLMSSP Sign/Seal - cannot use NT KEY yet\n")); return NT_STATUS_UNSUCCESSFUL; } diff --git a/source3/libsmb/smb_signing.c b/source3/libsmb/smb_signing.c index d4f77bf07c..4167452953 100644 --- a/source3/libsmb/smb_signing.c +++ b/source3/libsmb/smb_signing.c @@ -1,7 +1,7 @@ /* Unix SMB/CIFS implementation. SMB Signing Code - Copyright (C) Jeremy Allison 2002. + Copyright (C) Jeremy Allison 2003. Copyright (C) Andrew Bartlett 2002-2003 This program is free software; you can redistribute it and/or modify @@ -28,9 +28,17 @@ struct outstanding_packet_lookup { struct outstanding_packet_lookup *prev, *next; }; +/* Store the data for an ongoing trans/trans2/nttrans operation. */ +struct trans_info_context { + uint16 mid; + uint32 send_seq_num; + uint32 reply_seq_num; +}; + struct smb_basic_signing_context { DATA_BLOB mac_key; uint32 send_seq_num; + struct trans_info_context *trans_info; struct outstanding_packet_lookup *outstanding_packet_list; }; @@ -46,6 +54,8 @@ static void store_sequence_for_reply(struct outstanding_packet_lookup **list, DLIST_ADD_END(*list, t, tmp); t->mid = mid; t->reply_seq_num = reply_seq_num; + DEBUG(10,("store_sequence_for_reply: stored seq = %u mid = %u\n", + (unsigned int)reply_seq_num, (unsigned int)mid )); } static BOOL get_sequence_for_reply(struct outstanding_packet_lookup **list, @@ -56,12 +66,13 @@ static BOOL get_sequence_for_reply(struct outstanding_packet_lookup **list, for (t = *list; t; t = t->next) { if (t->mid == mid) { *reply_seq_num = t->reply_seq_num; + DEBUG(10,("get_sequence_for_reply: found seq = %u mid = %u\n", + (unsigned int)t->reply_seq_num, (unsigned int)t->mid )); DLIST_REMOVE(*list, t); + SAFE_FREE(t); return True; } } - DEBUG(0, ("Unexpected incoming packet, it's MID (%u) does not match" - " a MID in our outstanding list!\n", mid)); return False; } @@ -81,7 +92,7 @@ static BOOL cli_set_smb_signing_common(struct cli_state *cli) } if (cli->sign_info.free_signing_context) - cli->sign_info.free_signing_context(cli); + cli->sign_info.free_signing_context(&cli->sign_info); /* These calls are INCOMPATIBLE with SMB signing */ cli->readbraw_supported = False; @@ -94,42 +105,107 @@ static BOOL cli_set_smb_signing_common(struct cli_state *cli) SMB signing - Common code for 'real' implementations ************************************************************/ -static BOOL cli_set_smb_signing_real_common(struct cli_state *cli) +static BOOL set_smb_signing_real_common(struct smb_sign_info *si) { - if (cli->sign_info.mandatory_signing) { + if (si->mandatory_signing) { DEBUG(5, ("Mandatory SMB signing enabled!\n")); - cli->sign_info.doing_signing = True; } + si->doing_signing = True; DEBUG(5, ("SMB signing enabled!\n")); return True; } -static void cli_mark_packet_signed(struct cli_state *cli) +static void mark_packet_signed(char *outbuf) { uint16 flags2; - flags2 = SVAL(cli->outbuf,smb_flg2); + flags2 = SVAL(outbuf,smb_flg2); flags2 |= FLAGS2_SMB_SECURITY_SIGNATURES; - SSVAL(cli->outbuf,smb_flg2, flags2); + SSVAL(outbuf,smb_flg2, flags2); +} + +/*********************************************************** + SMB signing - NULL implementation - calculate a MAC to send. +************************************************************/ + +static void null_sign_outgoing_message(char *outbuf, struct smb_sign_info *si) +{ + /* we can't zero out the sig, as we might be trying to send a + session request - which is NBT-level, not SMB level and doesn't + have the field */ + return; +} + +/*********************************************************** + SMB signing - NULL implementation - check a MAC sent by server. +************************************************************/ + +static BOOL null_check_incoming_message(char *inbuf, struct smb_sign_info *si) +{ + return True; } -static BOOL cli_signing_good(struct cli_state *cli, BOOL good) +/*********************************************************** + SMB signing - NULL implementation - free signing context +************************************************************/ + +static void null_free_signing_context(struct smb_sign_info *si) { - DEBUG(10, ("got SMB signature of\n")); - dump_data(10,&cli->inbuf[smb_ss_field] , 8); + return; +} - if (good && !cli->sign_info.doing_signing) { - cli->sign_info.doing_signing = True; +/** + SMB signing - NULL implementation - setup the MAC key. + + @note Used as an initialisation only - it will not correctly + shut down a real signing mechanism +*/ + +static BOOL null_set_signing(struct smb_sign_info *si) +{ + si->signing_context = NULL; + + si->sign_outgoing_message = null_sign_outgoing_message; + si->check_incoming_message = null_check_incoming_message; + si->free_signing_context = null_free_signing_context; + + return True; +} + +/** + * Free the signing context + */ + +static void free_signing_context(struct smb_sign_info *si) +{ + if (si->free_signing_context) { + si->free_signing_context(si); + si->signing_context = NULL; + } + + null_set_signing(si); +} + + +static BOOL signing_good(char *inbuf, struct smb_sign_info *si, BOOL good) +{ + if (good && !si->doing_signing) { + si->doing_signing = True; } if (!good) { - if (cli->sign_info.doing_signing) { - DEBUG(1, ("SMB signature check failed!\n")); + if (si->doing_signing) { + struct smb_basic_signing_context *data = si->signing_context; + + /* W2K sends a bad first signature but the sign engine is on.... JRA. */ + if (data->send_seq_num > 1) + DEBUG(1, ("signing_good: SMB signature check failed!\n")); + return False; } else { - DEBUG(3, ("Server did not sign reply correctly\n")); - cli_free_signing_context(cli); + DEBUG(3, ("signing_good: Peer did not sign reply correctly\n")); + free_signing_context(si); return False; } } @@ -155,13 +231,15 @@ static void simple_packet_signature(struct smb_basic_signing_context *data, * We do this here, to avoid modifying the packet. */ + DEBUG(10,("simple_packet_signature: sequence number %u\n", seq_number )); + SIVAL(sequence_buf, 0, seq_number); SIVAL(sequence_buf, 4, 0); /* Calculate the 16 byte MAC - but don't alter the data in the incoming packet. - This makes for a bit for fussing about, but it's not too bad. + This makes for a bit of fussing about, but it's not too bad. */ MD5Init(&md5_ctx); @@ -179,82 +257,130 @@ static void simple_packet_signature(struct smb_basic_signing_context *data, MD5Update(&md5_ctx, buf + offset_end_of_sig, smb_len(buf) - (offset_end_of_sig - 4)); - /* caclulate the MD5 sig */ + /* calculate the MD5 sig */ MD5Final(calc_md5_mac, &md5_ctx); } /*********************************************************** - SMB signing - Simple implementation - send the MAC. + SMB signing - Client implementation - send the MAC. ************************************************************/ -static void cli_simple_sign_outgoing_message(struct cli_state *cli) +static void client_sign_outgoing_message(char *outbuf, struct smb_sign_info *si) { unsigned char calc_md5_mac[16]; - struct smb_basic_signing_context *data = cli->sign_info.signing_context; + struct smb_basic_signing_context *data = si->signing_context; + uint32 send_seq_num; + + if (!si->doing_signing) + return; + + /* JRA Paranioa test - we should be able to get rid of this... */ + if (smb_len(outbuf) < (smb_ss_field + 8 - 4)) { + DEBUG(1, ("client_sign_outgoing_message: Logic error. Can't check signature on short packet! smb_len = %u\n", + smb_len(outbuf) )); + abort(); + } /* mark the packet as signed - BEFORE we sign it...*/ - cli_mark_packet_signed(cli); + mark_packet_signed(outbuf); - simple_packet_signature(data, cli->outbuf, data->send_seq_num, - calc_md5_mac); + if (data->trans_info) + send_seq_num = data->trans_info->send_seq_num; + else + send_seq_num = data->send_seq_num; - DEBUG(10, ("sent SMB signature of\n")); + simple_packet_signature(data, outbuf, send_seq_num, calc_md5_mac); + + DEBUG(10, ("client_sign_outgoing_message: sent SMB signature of\n")); dump_data(10, calc_md5_mac, 8); - memcpy(&cli->outbuf[smb_ss_field], calc_md5_mac, 8); + memcpy(&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 signatures...*/ + if (data->trans_info) + return; + data->send_seq_num++; store_sequence_for_reply(&data->outstanding_packet_list, - cli->mid, + SVAL(outbuf,smb_mid), data->send_seq_num); data->send_seq_num++; } /*********************************************************** - SMB signing - Simple implementation - check a MAC sent by server. + SMB signing - Client implementation - check a MAC sent by server. ************************************************************/ -static BOOL cli_simple_check_incoming_message(struct cli_state *cli) +static BOOL client_check_incoming_message(char *inbuf, struct smb_sign_info *si) { BOOL good; uint32 reply_seq_number; unsigned char calc_md5_mac[16]; unsigned char *server_sent_mac; - struct smb_basic_signing_context *data = cli->sign_info.signing_context; + struct smb_basic_signing_context *data = si->signing_context; + + if (!si->doing_signing) + return True; - if (!get_sequence_for_reply(&data->outstanding_packet_list, - SVAL(cli->inbuf, smb_mid), + if (smb_len(inbuf) < (smb_ss_field + 8 - 4)) { + DEBUG(1, ("client_check_incoming_message: Can't check signature on short packet! smb_len = %u\n", smb_len(inbuf))); + return False; + } + + if (data->trans_info) { + reply_seq_number = data->trans_info->reply_seq_num; + } else if (!get_sequence_for_reply(&data->outstanding_packet_list, + SVAL(inbuf, smb_mid), &reply_seq_number)) { + DEBUG(1, ("client_check_incoming_message: failed to get sequence number %u for reply.\n", + (unsigned int) SVAL(inbuf, smb_mid) )); return False; } - simple_packet_signature(data, cli->inbuf, reply_seq_number, calc_md5_mac); + simple_packet_signature(data, inbuf, reply_seq_number, calc_md5_mac); - server_sent_mac = &cli->inbuf[smb_ss_field]; + server_sent_mac = &inbuf[smb_ss_field]; good = (memcmp(server_sent_mac, calc_md5_mac, 8) == 0); if (!good) { - DEBUG(5, ("BAD SIG: wanted SMB signature of\n")); + DEBUG(5, ("client_check_incoming_message: BAD SIG: wanted SMB signature of\n")); dump_data(5, calc_md5_mac, 8); - DEBUG(5, ("BAD SIG: got SMB signature of\n")); + DEBUG(5, ("client_check_incoming_message: BAD SIG: got SMB signature of\n")); dump_data(5, server_sent_mac, 8); +#if 1 /* JRATEST */ + { + int i; + reply_seq_number -= 5; + for (i = 0; i < 10; i++, reply_seq_number++) { + simple_packet_signature(data, inbuf, reply_seq_number, calc_md5_mac); + if (memcmp(server_sent_mac, calc_md5_mac, 8) == 0) { + DEBUG(0,("client_check_incoming_message: out of seq. seq num %u matches.\n", + reply_seq_number )); + break; + } + } + } +#endif /* JRATEST */ + + } else { + DEBUG(10, ("client_check_incoming_message:: seq %u: got good SMB signature of\n", (unsigned int)reply_seq_number)); + dump_data(10, server_sent_mac, 8); } - return cli_signing_good(cli, good); + return signing_good(inbuf, si, good); } /*********************************************************** SMB signing - Simple implementation - free signing context ************************************************************/ -static void cli_simple_free_signing_context(struct cli_state *cli) +static void simple_free_signing_context(struct smb_sign_info *si) { - struct smb_basic_signing_context *data = cli->sign_info.signing_context; + struct smb_basic_signing_context *data = si->signing_context; struct outstanding_packet_lookup *list = data->outstanding_packet_list; while (list) { @@ -264,7 +390,11 @@ static void cli_simple_free_signing_context(struct cli_state *cli) } data_blob_free(&data->mac_key); - SAFE_FREE(cli->sign_info.signing_context); + + if (data->trans_info) + SAFE_FREE(data->trans_info); + + SAFE_FREE(si->signing_context); return; } @@ -284,18 +414,29 @@ BOOL cli_simple_set_signing(struct cli_state *cli, const uchar user_session_key[ return False; } - if (!cli_set_smb_signing_real_common(cli)) { + if (!set_smb_signing_real_common(&cli->sign_info)) { return False; } data = smb_xmalloc(sizeof(*data)); + memset(data, '\0', sizeof(*data)); cli->sign_info.signing_context = data; data->mac_key = data_blob(NULL, response.length + 16); memcpy(&data->mac_key.data[0], user_session_key, 16); - memcpy(&data->mac_key.data[16],response.data, response.length); + + DEBUG(10, ("cli_simple_set_signing: user_session_key\n")); + dump_data(10, user_session_key, 16); + + if (response.length) { + memcpy(&data->mac_key.data[16],response.data, response.length); + DEBUG(10, ("cli_simple_set_signing: response_data\n")); + dump_data(10, response.data, response.length); + } else { + DEBUG(10, ("cli_simple_set_signing: NULL response_data\n")); + } /* Initialise the sequence number */ data->send_seq_num = 0; @@ -303,73 +444,68 @@ BOOL cli_simple_set_signing(struct cli_state *cli, const uchar user_session_key[ /* Initialise the list of outstanding packets */ data->outstanding_packet_list = NULL; - cli->sign_info.sign_outgoing_message = cli_simple_sign_outgoing_message; - cli->sign_info.check_incoming_message = cli_simple_check_incoming_message; - cli->sign_info.free_signing_context = cli_simple_free_signing_context; + cli->sign_info.sign_outgoing_message = client_sign_outgoing_message; + cli->sign_info.check_incoming_message = client_check_incoming_message; + cli->sign_info.free_signing_context = simple_free_signing_context; return True; } /*********************************************************** - SMB signing - NULL implementation - calculate a MAC to send. + Tell client code we are in a multiple trans reply state. ************************************************************/ -static void cli_null_sign_outgoing_message(struct cli_state *cli) +void cli_signing_trans_start(struct cli_state *cli) { - /* we can't zero out the sig, as we might be trying to send a - session request - which is NBT-level, not SMB level and doesn't - have the field */ - return; -} + struct smb_basic_signing_context *data = cli->sign_info.signing_context; -/*********************************************************** - SMB signing - NULL implementation - check a MAC sent by server. -************************************************************/ + if (!cli->sign_info.doing_signing || !data) + return; -static BOOL cli_null_check_incoming_message(struct cli_state *cli) -{ - return True; + data->trans_info = smb_xmalloc(sizeof(struct trans_info_context)); + ZERO_STRUCTP(data->trans_info); + + data->trans_info->send_seq_num = data->send_seq_num; + data->trans_info->mid = SVAL(cli->outbuf,smb_mid); + data->trans_info->reply_seq_num = data->send_seq_num+1; + + DEBUG(10,("cli_signing_trans_start: storing mid = %u, reply_seq_num = %u, send_seq_num = %u \ +data->send_seq_num = %u\n", + (unsigned int)data->trans_info->mid, + (unsigned int)data->trans_info->reply_seq_num, + (unsigned int)data->trans_info->send_seq_num, + (unsigned int)data->send_seq_num )); } /*********************************************************** - SMB signing - NULL implementation - free signing context + Tell client code we are out of a multiple trans reply state. ************************************************************/ -static void cli_null_free_signing_context(struct cli_state *cli) +void cli_signing_trans_stop(struct cli_state *cli) { - return; -} + struct smb_basic_signing_context *data = cli->sign_info.signing_context; -/** - SMB signing - NULL implementation - setup the MAC key. + if (!cli->sign_info.doing_signing || !data) + return; - @note Used as an initialisation only - it will not correctly - shut down a real signing mechanism -*/ + SAFE_FREE(data->trans_info); + data->trans_info = NULL; -BOOL cli_null_set_signing(struct cli_state *cli) -{ - cli->sign_info.signing_context = NULL; - - cli->sign_info.sign_outgoing_message = cli_null_sign_outgoing_message; - cli->sign_info.check_incoming_message = cli_null_check_incoming_message; - cli->sign_info.free_signing_context = cli_null_free_signing_context; - - return True; + data->send_seq_num += 2; } /*********************************************************** SMB signing - TEMP implementation - calculate a MAC to send. ************************************************************/ -static void cli_temp_sign_outgoing_message(struct cli_state *cli) +static void temp_sign_outgoing_message(char *outbuf, struct smb_sign_info *si) { /* mark the packet as signed - BEFORE we sign it...*/ - cli_mark_packet_signed(cli); + mark_packet_signed(outbuf); /* I wonder what BSRSPYL stands for - but this is what MS actually sends! */ - memcpy(&cli->outbuf[smb_ss_field], "BSRSPYL ", 8); + memcpy(&outbuf[smb_ss_field], "BSRSPYL ", 8); return; } @@ -377,7 +513,7 @@ static void cli_temp_sign_outgoing_message(struct cli_state *cli) SMB signing - TEMP implementation - check a MAC sent by server. ************************************************************/ -static BOOL cli_temp_check_incoming_message(struct cli_state *cli) +static BOOL temp_check_incoming_message(char *inbuf, struct smb_sign_info *si) { return True; } @@ -386,7 +522,7 @@ static BOOL cli_temp_check_incoming_message(struct cli_state *cli) SMB signing - TEMP implementation - free signing context ************************************************************/ -static void cli_temp_free_signing_context(struct cli_state *cli) +static void temp_free_signing_context(struct smb_sign_info *si) { return; } @@ -395,6 +531,15 @@ static void cli_temp_free_signing_context(struct cli_state *cli) SMB signing - NULL implementation - setup the MAC key. ************************************************************/ +BOOL cli_null_set_signing(struct cli_state *cli) +{ + return null_set_signing(&cli->sign_info); +} + +/*********************************************************** + SMB signing - temp implementation - setup the MAC key. +************************************************************/ + BOOL cli_temp_set_signing(struct cli_state *cli) { if (!cli_set_smb_signing_common(cli)) { @@ -403,58 +548,427 @@ BOOL cli_temp_set_signing(struct cli_state *cli) cli->sign_info.signing_context = NULL; - cli->sign_info.sign_outgoing_message = cli_temp_sign_outgoing_message; - cli->sign_info.check_incoming_message = cli_temp_check_incoming_message; - cli->sign_info.free_signing_context = cli_temp_free_signing_context; + cli->sign_info.sign_outgoing_message = temp_sign_outgoing_message; + cli->sign_info.check_incoming_message = temp_check_incoming_message; + cli->sign_info.free_signing_context = temp_free_signing_context; return True; } -/** - * Free the signing context - */ - -void cli_free_signing_context(struct cli_state *cli) +void cli_free_signing_context(struct cli_state *cli) { - if (cli->sign_info.free_signing_context) - cli->sign_info.free_signing_context(cli); - - cli_null_set_signing(cli); + free_signing_context(&cli->sign_info); } /** * Sign a packet with the current mechanism */ -void cli_caclulate_sign_mac(struct cli_state *cli) +void cli_calculate_sign_mac(struct cli_state *cli) { - cli->sign_info.sign_outgoing_message(cli); + cli->sign_info.sign_outgoing_message(cli->outbuf, &cli->sign_info); } /** * Check a packet with the current mechanism * @return False if we had an established signing connection - * which had a back checksum, True otherwise + * which had a bad checksum, True otherwise. */ BOOL cli_check_sign_mac(struct cli_state *cli) +{ + if (!cli->sign_info.check_incoming_message(cli->inbuf, &cli->sign_info)) { + free_signing_context(&cli->sign_info); + return False; + } + return True; +} + +static BOOL packet_is_oplock_break(char *buf) +{ + if (CVAL(buf,smb_com) != SMBlockingX) + return False; + + if (CVAL(buf,smb_vwv3) != LOCKING_ANDX_OPLOCK_RELEASE) + return False; + + return True; +} + +/*********************************************************** + SMB signing - Server implementation - send the MAC. +************************************************************/ + +static void srv_sign_outgoing_message(char *outbuf, struct smb_sign_info *si) +{ + unsigned char calc_md5_mac[16]; + struct smb_basic_signing_context *data = si->signing_context; + uint32 send_seq_number = data->send_seq_num; + BOOL was_deferred_packet = False; + uint16 mid; + + if (!si->doing_signing) { + if (si->allow_smb_signing && si->negotiated_smb_signing) { + mid = SVAL(outbuf, smb_mid); + + was_deferred_packet = get_sequence_for_reply(&data->outstanding_packet_list, + mid, &send_seq_number); + if (!was_deferred_packet) { + /* + * Is this an outgoing oplock break ? If so, store the + * mid in the outstanding list. + */ + + if (packet_is_oplock_break(outbuf)) { + store_sequence_for_reply(&data->outstanding_packet_list, + mid, data->send_seq_num); + } + + data->send_seq_num++; + } + } + return; + } + + /* JRA Paranioa test - we should be able to get rid of this... */ + if (smb_len(outbuf) < (smb_ss_field + 8 - 4)) { + DEBUG(1, ("srv_sign_outgoing_message: Logic error. Can't send signature on short packet! smb_len = %u\n", + smb_len(outbuf) )); + abort(); + } + + /* mark the packet as signed - BEFORE we sign it...*/ + mark_packet_signed(outbuf); + + mid = SVAL(outbuf, smb_mid); + + /* See if this is a reply for a deferred packet. */ + was_deferred_packet = get_sequence_for_reply(&data->outstanding_packet_list, mid, &send_seq_number); + + if (data->trans_info && (data->trans_info->mid == mid)) { + /* This is a reply in a trans stream. Use the sequence + * number associated with the stream mid. */ + send_seq_number = data->trans_info->send_seq_num; + } + + simple_packet_signature(data, outbuf, send_seq_number, calc_md5_mac); + + DEBUG(10, ("srv_sign_outgoing_message: seq %u: sent SMB signature of\n", (unsigned int)send_seq_number)); + dump_data(10, calc_md5_mac, 8); + + memcpy(&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 signatures...*/ + + if (!was_deferred_packet) { + if (!data->trans_info) { + /* Always increment if not in a trans stream. */ + data->send_seq_num++; + } else if ((data->trans_info->send_seq_num == data->send_seq_num) || (data->trans_info->mid != mid)) { + /* Increment if this is the first reply in a trans stream or a + * packet that doesn't belong to this stream (different mid). */ + data->send_seq_num++; + } + } +} + +/*********************************************************** + SMB signing - Server implementation - check a MAC sent by server. +************************************************************/ + +static BOOL srv_check_incoming_message(char *inbuf, struct smb_sign_info *si) { BOOL good; + struct smb_basic_signing_context *data = si->signing_context; + uint32 reply_seq_number = data->send_seq_num; + unsigned char calc_md5_mac[16]; + unsigned char *server_sent_mac; + uint mid; + + if (!si->doing_signing) + return True; - if (smb_len(cli->inbuf) < (smb_ss_field + 8 - 4)) { - DEBUG(cli->sign_info.doing_signing ? 1 : 10, ("Can't check signature on short packet! smb_len = %u\n", smb_len(cli->inbuf))); - good = False; + if (smb_len(inbuf) < (smb_ss_field + 8 - 4)) { + DEBUG(1, ("srv_check_incoming_message: Can't check signature on short packet! smb_len = %u\n", smb_len(inbuf))); + return False; + } + + mid = SVAL(inbuf, smb_mid); + + /* Is this part of a trans stream ? */ + if (data->trans_info && (data->trans_info->mid == mid)) { + /* If so we don't increment the sequence. */ + reply_seq_number = data->trans_info->reply_seq_num; } else { - good = cli->sign_info.check_incoming_message(cli); + /* We always increment the sequence number. */ + data->send_seq_num++; + /* Oplock break requests store an outgoing mid in the packet list. */ + if (packet_is_oplock_break(inbuf)) + get_sequence_for_reply(&data->outstanding_packet_list, mid, &reply_seq_number); } + simple_packet_signature(data, inbuf, reply_seq_number, calc_md5_mac); + + server_sent_mac = &inbuf[smb_ss_field]; + good = (memcmp(server_sent_mac, calc_md5_mac, 8) == 0); + if (!good) { - if (cli->sign_info.doing_signing) { - return False; - } else { - cli_free_signing_context(cli); + + DEBUG(5, ("srv_check_incoming_message: BAD SIG: wanted SMB signature of\n")); + dump_data(5, calc_md5_mac, 8); + + DEBUG(5, ("srv_check_incoming_message: BAD SIG: got SMB signature of\n")); + dump_data(5, server_sent_mac, 8); + +#if 1 /* JRATEST */ + { + int i; + reply_seq_number -= 5; + for (i = 0; i < 10; i++, reply_seq_number++) { + simple_packet_signature(data, inbuf, reply_seq_number, calc_md5_mac); + if (memcmp(server_sent_mac, calc_md5_mac, 8) == 0) { + DEBUG(0,("srv_check_incoming_message: out of seq. seq num %u matches.\n", + reply_seq_number )); + break; + } + } } +#endif /* JRATEST */ + + } else { + DEBUG(10, ("srv_check_incoming_message: seq %u: got good SMB signature of\n", (unsigned int)reply_seq_number)); + dump_data(10, server_sent_mac, 8); } + return signing_good(inbuf, si, good); +} - return True; +/*********************************************************** + SMB signing - server API's. +************************************************************/ + +static struct smb_sign_info srv_sign_info = { + null_sign_outgoing_message, + null_check_incoming_message, + null_free_signing_context, + NULL, + False, + False, + False, + False +}; + +/*********************************************************** + Turn signing off or on for oplock break code. +************************************************************/ + +BOOL srv_oplock_set_signing(BOOL onoff) +{ + BOOL ret = srv_sign_info.doing_signing; + srv_sign_info.doing_signing = onoff; + return ret; +} + +/*********************************************************** + Called to validate an incoming packet from the client. +************************************************************/ + +BOOL srv_check_sign_mac(char *inbuf) +{ + /* Check if it's a session keepalive. */ + if(CVAL(inbuf,0) == SMBkeepalive) + return True; + + return srv_sign_info.check_incoming_message(inbuf, &srv_sign_info); +} + +/*********************************************************** + Called to sign an outgoing packet to the client. +************************************************************/ + +void srv_calculate_sign_mac(char *outbuf) +{ + /* Check if it's a session keepalive. */ + /* JRA Paranioa test - do we ever generate these in the server ? */ + if(CVAL(outbuf,0) == SMBkeepalive) + return; + + srv_sign_info.sign_outgoing_message(outbuf, &srv_sign_info); +} + +/*********************************************************** + Called by server to defer an outgoing packet. +************************************************************/ + +void srv_defer_sign_response(uint16 mid) +{ + struct smb_basic_signing_context *data; + + if (!srv_sign_info.doing_signing) + return; + + data = (struct smb_basic_signing_context *)srv_sign_info.signing_context; + + if (!data) + return; + + store_sequence_for_reply(&data->outstanding_packet_list, + mid, data->send_seq_num); + data->send_seq_num++; +} + +/*********************************************************** + Called to remove sequence records when a deferred packet is + cancelled by mid. This should never find one.... +************************************************************/ + +void srv_cancel_sign_response(uint16 mid) +{ + struct smb_basic_signing_context *data; + uint32 dummy_seq; + + if (!srv_sign_info.doing_signing) + return; + + data = (struct smb_basic_signing_context *)srv_sign_info.signing_context; + + if (!data) + return; + + DEBUG(10,("srv_cancel_sign_response: for mid %u\n", (unsigned int)mid )); + + while (get_sequence_for_reply(&data->outstanding_packet_list, mid, &dummy_seq)) + ; +} + +/*********************************************************** + Called by server negprot when signing has been negotiated. +************************************************************/ + +void srv_set_signing_negotiated(void) +{ + srv_sign_info.allow_smb_signing = True; + srv_sign_info.negotiated_smb_signing = True; + if (lp_server_signing() == Required) + srv_sign_info.mandatory_signing = True; + + srv_sign_info.sign_outgoing_message = temp_sign_outgoing_message; + srv_sign_info.check_incoming_message = temp_check_incoming_message; + srv_sign_info.free_signing_context = temp_free_signing_context; +} + +/*********************************************************** + Returns whether signing is active. We can't use sendfile or raw + reads/writes if it is. +************************************************************/ + +BOOL srv_is_signing_active(void) +{ + return srv_sign_info.doing_signing; +} + +/*********************************************************** + Tell server code we are in a multiple trans reply state. +************************************************************/ + +void srv_signing_trans_start(uint16 mid) +{ + struct smb_basic_signing_context *data; + + if (!srv_sign_info.doing_signing) + return; + + data = (struct smb_basic_signing_context *)srv_sign_info.signing_context; + if (!data) + return; + + data->trans_info = smb_xmalloc(sizeof(struct trans_info_context)); + ZERO_STRUCTP(data->trans_info); + + data->trans_info->reply_seq_num = data->send_seq_num-1; + data->trans_info->mid = mid; + data->trans_info->send_seq_num = data->send_seq_num; + + DEBUG(10,("srv_signing_trans_start: storing mid = %u, reply_seq_num = %u, send_seq_num = %u \ +data->send_seq_num = %u\n", + (unsigned int)mid, + (unsigned int)data->trans_info->reply_seq_num, + (unsigned int)data->trans_info->send_seq_num, + (unsigned int)data->send_seq_num )); +} + +/*********************************************************** + Tell server code we are out of a multiple trans reply state. +************************************************************/ + +void srv_signing_trans_stop(void) +{ + struct smb_basic_signing_context *data; + + if (!srv_sign_info.doing_signing) + return; + + data = (struct smb_basic_signing_context *)srv_sign_info.signing_context; + if (!data || !data->trans_info) + return; + + DEBUG(10,("srv_signing_trans_stop: removing mid = %u, reply_seq_num = %u, send_seq_num = %u \ +data->send_seq_num = %u\n", + (unsigned int)data->trans_info->mid, + (unsigned int)data->trans_info->reply_seq_num, + (unsigned int)data->trans_info->send_seq_num, + (unsigned int)data->send_seq_num )); + + SAFE_FREE(data->trans_info); + data->trans_info = NULL; +} + +/*********************************************************** + Turn on signing from this packet onwards. +************************************************************/ + +void srv_set_signing(const uchar user_session_key[16], const DATA_BLOB response) +{ + struct smb_basic_signing_context *data; + + if (!user_session_key) + return; + + if (!srv_sign_info.negotiated_smb_signing && !srv_sign_info.mandatory_signing) { + DEBUG(5,("srv_set_signing: signing negotiated = %u, mandatory_signing = %u. Not allowing smb signing.\n", + (unsigned int)srv_sign_info.negotiated_smb_signing, + (unsigned int)srv_sign_info.mandatory_signing )); + return; + } + + /* Once we've turned on, ignore any more sessionsetups. */ + if (srv_sign_info.doing_signing) { + return; + } + + if (srv_sign_info.free_signing_context) + srv_sign_info.free_signing_context(&srv_sign_info); + + srv_sign_info.doing_signing = True; + + data = smb_xmalloc(sizeof(*data)); + memset(data, '\0', sizeof(*data)); + + srv_sign_info.signing_context = data; + + data->mac_key = data_blob(NULL, response.length + 16); + + memcpy(&data->mac_key.data[0], user_session_key, 16); + if (response.length) + memcpy(&data->mac_key.data[16],response.data, response.length); + + /* Initialise the sequence number */ + data->send_seq_num = 0; + + /* Initialise the list of outstanding packets */ + data->outstanding_packet_list = NULL; + + srv_sign_info.sign_outgoing_message = srv_sign_outgoing_message; + srv_sign_info.check_incoming_message = srv_check_incoming_message; + srv_sign_info.free_signing_context = simple_free_signing_context; } diff --git a/source3/libsmb/trustdom_cache.c b/source3/libsmb/trustdom_cache.c index 8378125088..0128d08006 100644 --- a/source3/libsmb/trustdom_cache.c +++ b/source3/libsmb/trustdom_cache.c @@ -223,7 +223,7 @@ BOOL trustdom_cache_store_timestamp( uint32 t, time_t timeout ) if (!gencache_init()) return False; - snprintf(value, sizeof(value), "%d", t ); + fstr_sprintf(value, "%d", t ); if (!gencache_set(TDOMTSKEY, value, timeout)) { DEBUG(5, ("failed to set timestamp for trustdom_cache\n")); diff --git a/source3/libsmb/trusts_util.c b/source3/libsmb/trusts_util.c index 77e63709aa..610f4b3c03 100644 --- a/source3/libsmb/trusts_util.c +++ b/source3/libsmb/trusts_util.c @@ -154,7 +154,7 @@ BOOL enumerate_domain_trusts( TALLOC_CTX *mem_ctx, const char *domain, /* setup the anonymous connection */ result = cli_full_connection( &cli, global_myname(), dc_name, &dc_ip, 0, "IPC$", "IPC", - "", "", "", 0, &retry); + "", "", "", 0, Undefined, &retry); if ( !NT_STATUS_IS_OK(result) ) goto done; diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 1a5757f817..4475f1446f 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -125,7 +125,11 @@ static NTSTATUS do_lock(files_struct *fsp,connection_struct *conn, uint16 lock_p */ if (!set_posix_lock(fsp, offset, count, lock_type)) { - status = NT_STATUS_LOCK_NOT_GRANTED; + if (errno == EACCES || errno == EAGAIN) + status = NT_STATUS_FILE_LOCK_CONFLICT; + else + status = map_nt_error_from_unix(errno); + /* * We failed to map - we must now remove the brl * lock entry. @@ -380,8 +384,8 @@ char *share_mode_str(int num, share_mode_entry *e) static pstring share_str; slprintf(share_str, sizeof(share_str)-1, "share_mode_entry[%d]: \ -pid = %u, share_mode = 0x%x, desired_access = 0x%x, port = 0x%x, type= 0x%x, file_id = %lu, dev = 0x%x, inode = %.0f", - num, e->pid, e->share_mode, (unsigned int)e->desired_access, e->op_port, e->op_type, e->share_file_id, +pid = %lu, share_mode = 0x%x, desired_access = 0x%x, port = 0x%x, type= 0x%x, file_id = %lu, dev = 0x%x, inode = %.0f", + num, (unsigned long)e->pid, e->share_mode, (unsigned int)e->desired_access, e->op_port, e->op_type, e->share_file_id, (unsigned int)e->dev, (double)e->inode ); return share_str; diff --git a/source3/nmbd/nmbd_processlogon.c b/source3/nmbd/nmbd_processlogon.c index 42edcc871f..bc3540af70 100644 --- a/source3/nmbd/nmbd_processlogon.c +++ b/source3/nmbd/nmbd_processlogon.c @@ -4,8 +4,7 @@ Copyright (C) Andrew Tridgell 1994-1998 Copyright (C) Luke Kenneth Casson Leighton 1994-1998 Copyright (C) Jeremy Allison 1994-1998 - Copyright (C) Jim McDonough 2002 - Copyright (C) Anthony Liguori 2002 + Copyright (C) Jim McDonough 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 diff --git a/source3/nsswitch/wb_common.c b/source3/nsswitch/wb_common.c index acaf0ed17c..79553e9e4f 100644 --- a/source3/nsswitch/wb_common.c +++ b/source3/nsswitch/wb_common.c @@ -239,6 +239,8 @@ int winbind_open_pipe_sock(void) } } + SAFE_FREE(response.extra_data); + return winbindd_fd; #else return -1; diff --git a/source3/nsswitch/wbinfo.c b/source3/nsswitch/wbinfo.c index f533799370..fcd7d2d508 100644 --- a/source3/nsswitch/wbinfo.c +++ b/source3/nsswitch/wbinfo.c @@ -1074,7 +1074,7 @@ int main(int argc, char **argv) goto done; } break; - case 'P': + case 'p': if (!wbinfo_ping()) { d_printf("could not ping winbindd!\n"); goto done; diff --git a/source3/nsswitch/winbindd.c b/source3/nsswitch/winbindd.c index 0860d701d8..8345fa11d0 100644 --- a/source3/nsswitch/winbindd.c +++ b/source3/nsswitch/winbindd.c @@ -27,20 +27,6 @@ BOOL opt_nocache = False; BOOL opt_dual_daemon = True; -/***************************************************************************** - stubb functions -****************************************************************************/ - -void become_root( void ) -{ - return; -} - -void unbecome_root( void ) -{ - return; -} - /* Reload configuration */ static BOOL reload_services_file(BOOL test) @@ -131,8 +117,8 @@ static void winbindd_status(void) if (DEBUGLEVEL >= 2 && winbindd_num_clients()) { DEBUG(2, ("\tclient list:\n")); for(tmp = winbindd_client_list(); tmp; tmp = tmp->next) { - DEBUG(2, ("\t\tpid %d, sock %d, rbl %d, wbl %d\n", - tmp->pid, tmp->sock, tmp->read_buf_len, + DEBUG(2, ("\t\tpid %lu, sock %d, rbl %d, wbl %d\n", + (unsigned long)tmp->pid, tmp->sock, tmp->read_buf_len, tmp->write_buf_len)); } } @@ -172,7 +158,7 @@ static void terminate(void) idmap_close(); /* Remove socket file */ - snprintf(path, sizeof(path), "%s/%s", + pstr_sprintf(path, "%s/%s", WINBINDD_SOCKET_DIR, WINBINDD_SOCKET_NAME); unlink(path); exit(0); @@ -471,8 +457,8 @@ void winbind_client_read(struct winbindd_cli_state *state) /* Read failed, kill client */ if (n == -1 || n == 0) { - DEBUG(5,("read failed on sock %d, pid %d: %s\n", - state->sock, state->pid, + DEBUG(5,("read failed on sock %d, pid %lu: %s\n", + state->sock, (unsigned long)state->pid, (n == -1) ? strerror(errno) : "EOF")); state->finished = True; @@ -519,8 +505,8 @@ static void client_write(struct winbindd_cli_state *state) if (num_written == -1 || num_written == 0) { - DEBUG(3,("write failed on sock %d, pid %d: %s\n", - state->sock, state->pid, + DEBUG(3,("write failed on sock %d, pid %lu: %s\n", + state->sock, (unsigned long)state->pid, (num_written == -1) ? strerror(errno) : "EOF")); state->finished = True; @@ -726,8 +712,8 @@ static void process_loop(void) if (state->read_buf_len >= sizeof(uint32) && *(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))); + DEBUG(0,("process_loop: Invalid request size from pid %lu: %d bytes sent, should be %d\n", + (unsigned long)state->request.pid, *(uint32 *) &state->request, sizeof(state->request))); remove_client(state); break; @@ -838,7 +824,7 @@ int main(int argc, char **argv) exit(1); } - snprintf(logfile, sizeof(logfile), "%s/log.winbindd", dyn_LOGFILEBASE); + pstr_sprintf(logfile, "%s/log.winbindd", dyn_LOGFILEBASE); lp_set_logfile(logfile); setup_logging("winbindd", log_stdout); reopen_logs(); diff --git a/source3/nsswitch/winbindd.h b/source3/nsswitch/winbindd.h index 2acb89b24b..677afa1849 100644 --- a/source3/nsswitch/winbindd.h +++ b/source3/nsswitch/winbindd.h @@ -4,7 +4,7 @@ Winbind daemon for ntdom nss module Copyright (C) Tim Potter 2000 - Copyright (C) Anthony Liguori 2003 + Copyright (C) Jim McDonough 2003 This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public diff --git a/source3/nsswitch/winbindd_acct.c b/source3/nsswitch/winbindd_acct.c index a1cd1d5f19..8abfd17110 100644 --- a/source3/nsswitch/winbindd_acct.c +++ b/source3/nsswitch/winbindd_acct.c @@ -136,8 +136,8 @@ static WINBINDD_PW* string2passwd( char *string ) /* last minute sanity checks */ if ( pw.pw_uid==0 || pw.pw_gid==0 ) { - DEBUG(0,("string2passwd: Failure! uid==%d, gid==%d\n", - pw.pw_uid, pw.pw_gid)); + DEBUG(0,("string2passwd: Failure! uid==%lu, gid==%lu\n", + (unsigned long)pw.pw_uid, (unsigned long)pw.pw_gid)); return NULL; } @@ -161,17 +161,17 @@ static char* passwd2string( const WINBINDD_PW *pw ) DEBUG(10,("passwd2string: converting passwd struct for %s\n", pw->pw_name)); - ret = snprintf( string, sizeof(string), "%s:%s:%d:%d:%s:%s:%s", + ret = pstr_sprintf( string, "%s:%s:%lu:%lu:%s:%s:%s", pw->pw_name, pw->pw_passwd ? pw->pw_passwd : "x", - pw->pw_uid, - pw->pw_gid, + (unsigned long)pw->pw_uid, + (unsigned long)pw->pw_gid, pw->pw_gecos, pw->pw_dir, pw->pw_shell ); if ( ret < 0 ) { - DEBUG(0,("passwd2string: snprintf() failed!\n")); + DEBUG(0,("passwd2string: pstr_sprintf() failed!\n")); return NULL; } @@ -247,7 +247,7 @@ static WINBINDD_GR* string2group( char *string ) /* last minute sanity checks */ if ( grp.gr_gid == 0 ) { - DEBUG(0,("string2group: Failure! gid==%d\n", grp.gr_gid)); + DEBUG(0,("string2group: Failure! gid==%lu\n", (unsigned long)grp.gr_gid)); SAFE_FREE( gr_members ); return NULL; } @@ -303,16 +303,16 @@ static char* group2string( const WINBINDD_GR *grp ) fstrcpy( gr_mem_str, "" ); } - ret = snprintf( string, sizeof(string)-1, "%s:%s:%d:%s", + ret = pstr_sprintf( string, "%s:%s:%lu:%s", grp->gr_name, grp->gr_passwd ? grp->gr_passwd : "*", - grp->gr_gid, + (unsigned long)grp->gr_gid, gr_mem_str ); SAFE_FREE( gr_mem_str ); if ( ret < 0 ) { - DEBUG(0,("group2string: snprintf() failed!\n")); + DEBUG(0,("group2string: pstr_sprintf() failed!\n")); return NULL; } @@ -326,7 +326,7 @@ static char* acct_userkey_byname( const char *name ) { static fstring key; - snprintf( key, sizeof(key), "%s/NAME/%s", WBKEY_PASSWD, name ); + fstr_sprintf( key, "%s/NAME/%s", WBKEY_PASSWD, name ); return key; } @@ -338,7 +338,7 @@ static char* acct_userkey_byuid( uid_t uid ) { static fstring key; - snprintf( key, sizeof(key), "%s/UID/%d", WBKEY_PASSWD, uid ); + fstr_sprintf( key, "%s/UID/%lu", WBKEY_PASSWD, (unsigned long)uid ); return key; } @@ -350,7 +350,7 @@ static char* acct_groupkey_byname( const char *name ) { static fstring key; - snprintf( key, sizeof(key), "%s/NAME/%s", WBKEY_GROUP, name ); + fstr_sprintf( key, "%s/NAME/%s", WBKEY_GROUP, name ); return key; } @@ -362,7 +362,7 @@ static char* acct_groupkey_bygid( gid_t gid ) { static fstring key; - snprintf( key, sizeof(key), "%s/GID/%d", WBKEY_GROUP, gid ); + fstr_sprintf( key, "%s/GID/%lu", WBKEY_GROUP, (unsigned long)gid ); return key; } @@ -415,7 +415,7 @@ WINBINDD_PW* wb_getpwuid( const uid_t uid ) data = tdb_fetch_bystring( account_tdb, acct_userkey_byuid(uid) ); if ( !data.dptr ) { - DEBUG(4,("wb_getpwuid: failed to locate uid == %d\n", uid)); + DEBUG(4,("wb_getpwuid: failed to locate uid == %lu\n", (unsigned long)uid)); return NULL; } keystr = acct_userkey_byname( data.dptr ); @@ -431,8 +431,8 @@ WINBINDD_PW* wb_getpwuid( const uid_t uid ) SAFE_FREE( data.dptr ); } - DEBUG(5,("wb_getpwuid: %s user (uid == %d)\n", - (pw ? "Found" : "Did not find"), uid )); + DEBUG(5,("wb_getpwuid: %s user (uid == %lu)\n", + (pw ? "Found" : "Did not find"), (unsigned long)uid )); return pw; } @@ -544,7 +544,8 @@ WINBINDD_GR* wb_getgrgid( gid_t gid ) data = tdb_fetch_bystring( account_tdb, acct_groupkey_bygid(gid) ); if ( !data.dptr ) { - DEBUG(4,("wb_getgrgid: failed to locate gid == %d\n", gid)); + DEBUG(4,("wb_getgrgid: failed to locate gid == %lu\n", + (unsigned long)gid)); return NULL; } keystr = acct_groupkey_byname( data.dptr ); @@ -560,8 +561,8 @@ WINBINDD_GR* wb_getgrgid( gid_t gid ) SAFE_FREE( data.dptr ); } - DEBUG(5,("wb_getgrgid: %s group (gid == %d)\n", - (grp ? "Found" : "Did not find"), gid )); + DEBUG(5,("wb_getgrgid: %s group (gid == %lu)\n", + (grp ? "Found" : "Did not find"), (unsigned long)gid )); return grp; } @@ -697,7 +698,7 @@ static int cleangroups_traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA fstring key; char *name = (char*)state; - snprintf( key, sizeof(key), "%s/NAME", WBKEY_GROUP ); + fstr_sprintf( key, "%s/NAME", WBKEY_GROUP ); len = strlen(key); /* if this is a group entry then, check the members */ @@ -776,7 +777,7 @@ static int isprimarygroup_traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, fstring key; struct _check_primary_grp *check = (struct _check_primary_grp*)params; - snprintf( key, sizeof(key), "%s/NAME", WBKEY_PASSWD ); + fstr_sprintf( key, "%s/NAME", WBKEY_PASSWD ); len = strlen(key); /* if this is a group entry then, check the members */ @@ -875,8 +876,8 @@ enum winbindd_result winbindd_create_user(struct winbindd_cli_state *state) user = state->request.data.acct_mgt.username; group = state->request.data.acct_mgt.groupname; - DEBUG(3, ("[%5d]: create_user: user=>(%s), group=>(%s)\n", - state->pid, user, group)); + DEBUG(3, ("[%5lu]: create_user: user=>(%s), group=>(%s)\n", + (unsigned long)state->pid, user, group)); if ( !*group ) group = lp_template_primary_group(); @@ -965,7 +966,7 @@ enum winbindd_result winbindd_create_group(struct winbindd_cli_state *state) state->request.data.acct_mgt.groupname[sizeof(state->request.data.acct_mgt.groupname)-1]='\0'; group = state->request.data.acct_mgt.groupname; - DEBUG(3, ("[%5d]: create_group: (%s)\n", state->pid, group)); + DEBUG(3, ("[%5lu]: create_group: (%s)\n", (unsigned long)state->pid, group)); /* get a new uid */ @@ -1025,7 +1026,7 @@ enum winbindd_result winbindd_add_user_to_group(struct winbindd_cli_state *state group = state->request.data.acct_mgt.groupname; user = state->request.data.acct_mgt.username; - DEBUG(3, ("[%5d]: add_user_to_group: add %s to %s\n", state->pid, + DEBUG(3, ("[%5lu]: add_user_to_group: add %s to %s\n", (unsigned long)state->pid, user, group)); /* make sure it is a valid user */ @@ -1073,7 +1074,7 @@ enum winbindd_result winbindd_remove_user_from_group(struct winbindd_cli_state * group = state->request.data.acct_mgt.groupname; user = state->request.data.acct_mgt.username; - DEBUG(3, ("[%5d]: remove_user_to_group: delete %s from %s\n", state->pid, + DEBUG(3, ("[%5lu]: remove_user_to_group: delete %s from %s\n", (unsigned long)state->pid, user, group)); /* don't worry about checking the username since we're removing it anyways */ @@ -1116,8 +1117,8 @@ enum winbindd_result winbindd_set_user_primary_group(struct winbindd_cli_state * group = state->request.data.acct_mgt.groupname; user = state->request.data.acct_mgt.username; - DEBUG(3, ("[%5d]: set_user_primary_grou:p group %s for user %s\n", state->pid, - group, user)); + DEBUG(3, ("[%5lu]: set_user_primary_group: group %s for user %s\n", + (unsigned long)state->pid, group, user)); /* make sure it is a valid user */ @@ -1158,7 +1159,7 @@ enum winbindd_result winbindd_delete_user(struct winbindd_cli_state *state) state->request.data.acct_mgt.username[sizeof(state->request.data.acct_mgt.username)-1]='\0'; user = state->request.data.acct_mgt.username; - DEBUG(3, ("[%5d]: delete_user: %s\n", state->pid, user)); + DEBUG(3, ("[%5lu]: delete_user: %s\n", (unsigned long)state->pid, user)); /* make sure it is a valid user */ @@ -1189,7 +1190,7 @@ enum winbindd_result winbindd_delete_group(struct winbindd_cli_state *state) state->request.data.acct_mgt.username[sizeof(state->request.data.acct_mgt.groupname)-1]='\0'; group = state->request.data.acct_mgt.groupname; - DEBUG(3, ("[%5d]: delete_group: %s\n", state->pid, group)); + DEBUG(3, ("[%5lu]: delete_group: %s\n", (unsigned long)state->pid, group)); /* make sure it is a valid group */ diff --git a/source3/nsswitch/winbindd_ads.c b/source3/nsswitch/winbindd_ads.c index 462dd21531..7140dc35a0 100644 --- a/source3/nsswitch/winbindd_ads.c +++ b/source3/nsswitch/winbindd_ads.c @@ -801,24 +801,91 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain, char ***alt_names, DOM_SID **dom_sids) { - ADS_STRUCT *ads; - ADS_STATUS rc; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + DS_DOMAIN_TRUSTS *domains = NULL; + int count = 0; + int i; + struct cli_state *cli = NULL; + /* i think we only need our forest and downlevel trusted domains */ + uint32 flags = DS_DOMAIN_IN_FOREST | DS_DOMAIN_DIRECT_OUTBOUND; DEBUG(3,("ads: trusted_domains\n")); *num_domains = 0; - *names = NULL; + *alt_names = NULL; + *names = NULL; + *dom_sids = NULL; + + if ( !NT_STATUS_IS_OK(result = cm_fresh_connection(domain->name, PI_NETLOGON, &cli)) ) { + DEBUG(5, ("trusted_domains: Could not open a connection to %s for PIPE_NETLOGON (%s)\n", + domain->name, nt_errstr(result))); + return NT_STATUS_UNSUCCESSFUL; + } + + if ( NT_STATUS_IS_OK(result) ) + result = cli_ds_enum_domain_trusts( cli, mem_ctx, cli->desthost, flags, &domains, &count ); + + if ( NT_STATUS_IS_OK(result) && count) { + + /* Allocate memory for trusted domain names and sids */ - ads = ads_cached_connection(domain); + if ( !(*names = (char **)talloc(mem_ctx, sizeof(char *) * count)) ) { + DEBUG(0, ("trusted_domains: out of memory\n")); + result = NT_STATUS_NO_MEMORY; + goto done; + } - if (!ads) { - domain->last_status = NT_STATUS_SERVER_DISABLED; - return NT_STATUS_UNSUCCESSFUL; + if ( !(*alt_names = (char **)talloc(mem_ctx, sizeof(char *) * count)) ) { + DEBUG(0, ("trusted_domains: out of memory\n")); + result = NT_STATUS_NO_MEMORY; + goto done; + } + + if ( !(*dom_sids = (DOM_SID *)talloc(mem_ctx, sizeof(DOM_SID) * count)) ) { + DEBUG(0, ("trusted_domains: out of memory\n")); + result = NT_STATUS_NO_MEMORY; + goto done; + } + + /* Copy across names and sids */ + + for (i = 0; i < count; i++) { + fstring tmp; + fstring tmp2; + + (*names)[i] = NULL; + (*alt_names)[i] = NULL; + ZERO_STRUCT( (*dom_sids)[i] ); + + if ( domains[i].netbios_ptr ) { + unistr2_to_ascii(tmp, &domains[i].netbios_domain, sizeof(tmp) - 1); + (*names)[i] = talloc_strdup(mem_ctx, tmp); + } + + if ( domains[i].dns_ptr ) { + unistr2_to_ascii(tmp2, &domains[i].dns_domain, sizeof(tmp2) - 1); + (*alt_names)[i] = talloc_strdup(mem_ctx, tmp2); + } + + /* sometimes we will get back a NULL SID from this call */ + + if ( domains[i].sid_ptr ) + sid_copy(&(*dom_sids)[i], &domains[i].sid.sid); + } + + *num_domains = count; } - rc = ads_trusted_domains(ads, mem_ctx, num_domains, names, alt_names, dom_sids); +done: + + SAFE_FREE( domains ); + + /* remove connection; This is a special case to the \NETLOGON pipe */ + + if ( cli ) + cli_shutdown( cli ); - return ads_ntstatus(rc); + return result; } /* find the domain sid for a domain */ diff --git a/source3/nsswitch/winbindd_cache.c b/source3/nsswitch/winbindd_cache.c index 2da2a9e641..2891a4fa68 100644 --- a/source3/nsswitch/winbindd_cache.c +++ b/source3/nsswitch/winbindd_cache.c @@ -106,7 +106,7 @@ static struct winbind_cache *get_cache(struct winbindd_domain *domain) case SEC_ADS: { extern struct winbindd_methods ads_methods; /* always obey the lp_security parameter for our domain */ - if ( strequal(lp_realm(), domain->alt_name) ) { + if ( strequal(lp_realm(), domain->alt_name) || strequal(lp_workgroup(), domain->name) ) { domain->backend = &ads_methods; break; } @@ -256,7 +256,7 @@ static NTSTATUS fetch_cache_seqnum( struct winbindd_domain *domain, time_t now ) return NT_STATUS_UNSUCCESSFUL; } - snprintf( key, sizeof(key), "SEQNUM/%s", domain->name ); + fstr_sprintf( key, "SEQNUM/%s", domain->name ); data = tdb_fetch_bystring( wcache->tdb, key ); if ( !data.dptr || data.dsize!=8 ) { @@ -295,7 +295,7 @@ static NTSTATUS store_cache_seqnum( struct winbindd_domain *domain ) return NT_STATUS_UNSUCCESSFUL; } - snprintf( key_str, sizeof(key_str), "SEQNUM/%s", domain->name ); + fstr_sprintf( key_str, "SEQNUM/%s", domain->name ); key.dptr = key_str; key.dsize = strlen(key_str)+1; @@ -328,6 +328,8 @@ static void refresh_sequence_number(struct winbindd_domain *domain, BOOL force) time_t t = time(NULL); unsigned cache_time = lp_winbind_cache_time(); + get_cache( domain ); + /* trying to reconnect is expensive, don't do it too often */ if (domain->sequence_number == DOM_SEQUENCE_NONE) { cache_time *= 8; diff --git a/source3/nsswitch/winbindd_cm.c b/source3/nsswitch/winbindd_cm.c index 7f35167778..f07117b5ab 100644 --- a/source3/nsswitch/winbindd_cm.c +++ b/source3/nsswitch/winbindd_cm.c @@ -152,7 +152,8 @@ static NTSTATUS cm_open_connection(const char *domain, const int pipe_index, result = cli_full_connection(&new_conn->cli, global_myname(), new_conn->controller, &dc_ip, 0, "IPC$", "IPC", ipc_username, ipc_domain, - ipc_password, CLI_FULL_CONNECTION_ANNONYMOUS_FALLBACK, &retry); + ipc_password, CLI_FULL_CONNECTION_ANNONYMOUS_FALLBACK, + Undefined, &retry); secrets_named_mutex_release(new_conn->controller); @@ -169,6 +170,11 @@ static NTSTATUS cm_open_connection(const char *domain, const int pipe_index, return result; } + /* set the domain if empty; needed for schannel connections */ + if ( !*new_conn->cli->domain ) + fstrcpy( new_conn->cli->domain, domain ); + + if ( !cli_nt_session_open (new_conn->cli, pipe_index) ) { result = NT_STATUS_PIPE_NOT_AVAILABLE; /* @@ -188,6 +194,25 @@ static NTSTATUS cm_open_connection(const char *domain, const int pipe_index, return NT_STATUS_OK; } +/************************************************************************ + Wrapper around statuc cm_open_connection to retreive a freshly + setup cli_state struct +************************************************************************/ + +NTSTATUS cm_fresh_connection(const char *domain, const int pipe_index, + struct cli_state **cli) +{ + NTSTATUS result; + struct winbindd_cm_conn conn; + + result = cm_open_connection( domain, pipe_index, &conn ); + + if ( NT_STATUS_IS_OK(result) ) + *cli = conn.cli; + + return result; +} + /* Return true if a connection is still alive */ static BOOL connection_ok(struct winbindd_cm_conn *conn) @@ -320,13 +345,11 @@ BOOL cm_check_for_native_mode_win2k( const char *domain ) done: -#if 0 - /* - * I don't think we need to shutdown here ? JRA. - */ + /* close the connection; no other cals use this pipe and it is called only + on reestablishing the domain list --jerry */ + if ( conn.cli ) cli_shutdown( conn.cli ); -#endif return ret; } @@ -488,14 +511,14 @@ NTSTATUS cm_get_netlogon_cli(const char *domain, if (!NT_STATUS_IS_OK(result)) return result; - snprintf(lock_name, sizeof(lock_name), "NETLOGON\\%s", conn->controller); + fstr_sprintf(lock_name, "NETLOGON\\%s", conn->controller); if (!(got_mutex = secrets_named_mutex(lock_name, WINBIND_SERVER_MUTEX_WAIT_TIME))) { DEBUG(0,("cm_get_netlogon_cli: mutex grab failed for %s\n", conn->controller)); } if ( sec_channel_type == SEC_CHAN_DOMAIN ) - snprintf(conn->cli->mach_acct, sizeof(conn->cli->mach_acct) - 1, "%s$", lp_workgroup()); + fstr_sprintf(conn->cli->mach_acct, "%s$", lp_workgroup()); result = cli_nt_establish_netlogon(conn->cli, sec_channel_type, trust_passwd); diff --git a/source3/nsswitch/winbindd_group.c b/source3/nsswitch/winbindd_group.c index d67d48d506..96c121685a 100644 --- a/source3/nsswitch/winbindd_group.c +++ b/source3/nsswitch/winbindd_group.c @@ -232,7 +232,7 @@ enum winbindd_result winbindd_getgrnam(struct winbindd_cli_state *state) /* Ensure null termination */ state->request.data.groupname[sizeof(state->request.data.groupname)-1]='\0'; - DEBUG(3, ("[%5d]: getgrnam %s\n", state->pid, + DEBUG(3, ("[%5lu]: getgrnam %s\n", (unsigned long)state->pid, state->request.data.groupname)); /* Parse domain and groupname */ @@ -334,8 +334,8 @@ enum winbindd_result winbindd_getgrgid(struct winbindd_cli_state *state) int gr_mem_len; char *gr_mem; - DEBUG(3, ("[%5d]: getgrgid %d\n", state->pid, - state->request.data.gid)); + DEBUG(3, ("[%5lu]: getgrgid %lu\n", (unsigned long)state->pid, + (unsigned long)state->request.data.gid)); /* Bug out if the gid isn't in the winbind range */ @@ -360,8 +360,8 @@ enum winbindd_result winbindd_getgrgid(struct winbindd_cli_state *state) /* Get rid from gid */ if (!NT_STATUS_IS_OK(idmap_gid_to_sid(&group_sid, state->request.data.gid))) { - DEBUG(1, ("could not convert gid %d to rid\n", - state->request.data.gid)); + DEBUG(1, ("could not convert gid %lu to rid\n", + (unsigned long)state->request.data.gid)); return WINBINDD_ERROR; } @@ -416,7 +416,7 @@ enum winbindd_result winbindd_setgrent(struct winbindd_cli_state *state) { struct winbindd_domain *domain; - DEBUG(3, ("[%5d]: setgrent\n", state->pid)); + DEBUG(3, ("[%5lu]: setgrent\n", (unsigned long)state->pid)); /* Check user has enabled this */ @@ -469,7 +469,7 @@ enum winbindd_result winbindd_setgrent(struct winbindd_cli_state *state) enum winbindd_result winbindd_endgrent(struct winbindd_cli_state *state) { - DEBUG(3, ("[%5d]: endgrent\n", state->pid)); + DEBUG(3, ("[%5lu]: endgrent\n", (unsigned long)state->pid)); free_getent_state(state->getgrent_state); state->getgrent_state = NULL; @@ -605,7 +605,7 @@ enum winbindd_result winbindd_getgrent(struct winbindd_cli_state *state) int num_groups, group_list_ndx = 0, i, gr_mem_list_len = 0; char *new_extra_data, *gr_mem_list = NULL; - DEBUG(3, ("[%5d]: getgrent\n", state->pid)); + DEBUG(3, ("[%5lu]: getgrent\n", (unsigned long)state->pid)); /* Check user has enabled this */ @@ -691,7 +691,7 @@ enum winbindd_result winbindd_getgrent(struct winbindd_cli_state *state) goto tryagain; } - DEBUG(10, ("got gid %d for group %x\n", group_gid, + DEBUG(10, ("got gid %lu for group %x\n", (unsigned long)group_gid, name_list[ent->sam_entry_index].rid)); /* Fill in group entry */ @@ -825,7 +825,7 @@ enum winbindd_result winbindd_list_groups(struct winbindd_cli_state *state) char *ted = NULL; unsigned int extra_data_len = 0, i; - DEBUG(3, ("[%5d]: list groups\n", state->pid)); + DEBUG(3, ("[%5lu]: list groups\n", (unsigned long)state->pid)); /* Enumerate over trusted domains */ @@ -915,7 +915,7 @@ enum winbindd_result winbindd_getgroups(struct winbindd_cli_state *state) /* Ensure null termination */ state->request.data.username[sizeof(state->request.data.username)-1]='\0'; - DEBUG(3, ("[%5d]: getgroups %s\n", state->pid, + DEBUG(3, ("[%5lu]: getgroups %s\n", (unsigned long)state->pid, state->request.data.username)); if (!(mem_ctx = talloc_init("winbindd_getgroups(%s)", @@ -1009,9 +1009,9 @@ enum winbindd_result winbindd_getgroups(struct winbindd_cli_state *state) /* We've jumped through a lot of hoops to get here */ DEBUG(10, ("winbindd_getgroups: mapped other sid %s to " - "gid %d\n", sid_string_static( + "gid %lu\n", sid_string_static( &info3->other_sids[i].sid), - gid_list[num_gids])); + (unsigned long)gid_list[num_gids])); num_gids++; } diff --git a/source3/nsswitch/winbindd_misc.c b/source3/nsswitch/winbindd_misc.c index 8d7cdc4731..740b760b93 100644 --- a/source3/nsswitch/winbindd_misc.c +++ b/source3/nsswitch/winbindd_misc.c @@ -35,7 +35,7 @@ enum winbindd_result winbindd_check_machine_acct(struct winbindd_cli_state *stat int num_retries = 0; struct cli_state *cli; uint32 sec_channel_type; - DEBUG(3, ("[%5d]: check machine account\n", state->pid)); + DEBUG(3, ("[%5lu]: check machine account\n", (unsigned long)state->pid)); /* Get trust account password */ @@ -95,7 +95,7 @@ enum winbindd_result winbindd_list_trusted_domains(struct winbindd_cli_state int total_entries = 0, extra_data_len = 0; char *ted, *extra_data = NULL; - DEBUG(3, ("[%5d]: list trusted domains\n", state->pid)); + DEBUG(3, ("[%5lu]: list trusted domains\n", (unsigned long)state->pid)); /* We need to refresh the trusted domain list as the domains may have changed since we last looked. There may be a sequence @@ -149,7 +149,7 @@ enum winbindd_result winbindd_show_sequence(struct winbindd_cli_state *state) struct winbindd_domain *domain; char *extra_data = NULL; - DEBUG(3, ("[%5d]: show sequence\n", state->pid)); + DEBUG(3, ("[%5lu]: show sequence\n", (unsigned long)state->pid)); extra_data = strdup(""); @@ -181,7 +181,7 @@ enum winbindd_result winbindd_show_sequence(struct winbindd_cli_state *state) enum winbindd_result winbindd_ping(struct winbindd_cli_state *state) { - DEBUG(3, ("[%5d]: ping\n", state->pid)); + DEBUG(3, ("[%5lu]: ping\n", (unsigned long)state->pid)); return WINBINDD_OK; } @@ -191,7 +191,7 @@ enum winbindd_result winbindd_ping(struct winbindd_cli_state enum winbindd_result winbindd_info(struct winbindd_cli_state *state) { - DEBUG(3, ("[%5d]: request misc info\n", state->pid)); + DEBUG(3, ("[%5lu]: request misc info\n", (unsigned long)state->pid)); state->response.data.info.winbind_separator = *lp_winbind_separator(); fstrcpy(state->response.data.info.samba_version, VERSION); @@ -204,7 +204,7 @@ enum winbindd_result winbindd_info(struct winbindd_cli_state *state) enum winbindd_result winbindd_interface_version(struct winbindd_cli_state *state) { - DEBUG(3, ("[%5d]: request interface version\n", state->pid)); + DEBUG(3, ("[%5lu]: request interface version\n", (unsigned long)state->pid)); state->response.data.interface_version = WINBIND_INTERFACE_VERSION; @@ -216,7 +216,7 @@ enum winbindd_result winbindd_interface_version(struct winbindd_cli_state *state enum winbindd_result winbindd_domain_name(struct winbindd_cli_state *state) { - DEBUG(3, ("[%5d]: request domain name\n", state->pid)); + DEBUG(3, ("[%5lu]: request domain name\n", (unsigned long)state->pid)); fstrcpy(state->response.data.domain_name, lp_workgroup()); @@ -228,7 +228,7 @@ enum winbindd_result winbindd_domain_name(struct winbindd_cli_state *state) enum winbindd_result winbindd_netbios_name(struct winbindd_cli_state *state) { - DEBUG(3, ("[%5d]: request netbios name\n", state->pid)); + DEBUG(3, ("[%5lu]: request netbios name\n", (unsigned long)state->pid)); fstrcpy(state->response.data.netbios_name, global_myname()); @@ -240,7 +240,7 @@ enum winbindd_result winbindd_netbios_name(struct winbindd_cli_state *state) enum winbindd_result winbindd_priv_pipe_dir(struct winbindd_cli_state *state) { - DEBUG(3, ("[%5d]: request location of privileged pipe\n", state->pid)); + DEBUG(3, ("[%5lu]: request location of privileged pipe\n", (unsigned long)state->pid)); state->response.extra_data = strdup(get_winbind_priv_pipe_dir()); if (!state->response.extra_data) diff --git a/source3/nsswitch/winbindd_pam.c b/source3/nsswitch/winbindd_pam.c index 8df0f621c0..a8908487c1 100644 --- a/source3/nsswitch/winbindd_pam.c +++ b/source3/nsswitch/winbindd_pam.c @@ -53,55 +53,6 @@ static NTSTATUS append_info3_as_ndr(TALLOC_CTX *mem_ctx, return NT_STATUS_OK; } -/******************************************************************* - wrapper around retreiving the trsut account password -*******************************************************************/ - -static BOOL get_trust_pw(const char *domain, uint8 ret_pwd[16], - time_t *pass_last_set_time, uint32 *channel) -{ - DOM_SID sid; - char *pwd; - - /* if we are a DC and this is not our domain, then lookup an account - for the domain trust */ - - if ( IS_DC && !strequal(domain, lp_workgroup()) && lp_allow_trusted_domains() ) - { - if ( !secrets_fetch_trusted_domain_password(domain, &pwd, &sid, - pass_last_set_time) ) - { - DEBUG(0, ("get_trust_pw: could not fetch trust account " - "password for trusted domain %s\n", domain)); - return False; - } - - *channel = SEC_CHAN_DOMAIN; - E_md4hash(pwd, ret_pwd); - SAFE_FREE(pwd); - - return True; - } - else /* just get the account for our domain (covers - ROLE_DOMAIN_MEMBER as well */ - { - /* get the machine trust account for our domain */ - - if ( !secrets_fetch_trust_account_password (lp_workgroup(), ret_pwd, - pass_last_set_time, channel) ) - { - DEBUG(0, ("get_trust_pw: could not fetch trust account " - "password for my domain %s\n", domain)); - return False; - } - - return True; - } - - /* Failure */ - return False; -} - /********************************************************************** Authenticate a user with a clear test password **********************************************************************/ @@ -131,7 +82,7 @@ enum winbindd_result winbindd_pam_auth(struct winbindd_cli_state *state) /* Ensure null termination */ state->request.data.auth.pass[sizeof(state->request.data.auth.pass)-1]='\0'; - DEBUG(3, ("[%5d]: pam auth %s\n", state->pid, + DEBUG(3, ("[%5lu]: pam auth %s\n", (unsigned long)state->pid, state->request.data.auth.user)); if (!(mem_ctx = talloc_init("winbind pam auth for %s", state->request.data.auth.user))) { @@ -305,7 +256,7 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state) goto done; } - DEBUG(3, ("[%5d]: pam auth crap domain: %s user: %s\n", state->pid, + DEBUG(3, ("[%5lu]: pam auth crap domain: %s user: %s\n", (unsigned long)state->pid, domain, user)); if ( !get_trust_pw(domain, trust_passwd, &last_change_time, &sec_channel_type) ) { @@ -436,7 +387,7 @@ enum winbindd_result winbindd_pam_chauthtok(struct winbindd_cli_state *state) fstring domain, user; CLI_POLICY_HND *hnd; - DEBUG(3, ("[%5d]: pam chauthtok %s\n", state->pid, + DEBUG(3, ("[%5lu]: pam chauthtok %s\n", (unsigned long)state->pid, state->request.data.chauthtok.user)); /* Setup crap */ diff --git a/source3/nsswitch/winbindd_sid.c b/source3/nsswitch/winbindd_sid.c index 676beae3aa..98a6fce24b 100644 --- a/source3/nsswitch/winbindd_sid.c +++ b/source3/nsswitch/winbindd_sid.c @@ -39,7 +39,7 @@ enum winbindd_result winbindd_lookupsid(struct winbindd_cli_state *state) /* Ensure null termination */ state->request.data.sid[sizeof(state->request.data.sid)-1]='\0'; - DEBUG(3, ("[%5d]: lookupsid %s\n", state->pid, + DEBUG(3, ("[%5lu]: lookupsid %s\n", (unsigned long)state->pid, state->request.data.sid)); /* Lookup sid from PDC using lsa_lookup_sids() */ @@ -90,7 +90,7 @@ enum winbindd_result winbindd_lookupname(struct winbindd_cli_state *state) /* Ensure null termination */ state->request.data.sid[sizeof(state->request.data.name.name)-1]='\0'; - DEBUG(3, ("[%5d]: lookupname %s%s%s\n", state->pid, + DEBUG(3, ("[%5lu]: lookupname %s%s%s\n", (unsigned long)state->pid, state->request.data.name.dom_name, lp_winbind_separator(), state->request.data.name.name)); @@ -127,7 +127,7 @@ enum winbindd_result winbindd_sid_to_uid(struct winbindd_cli_state *state) /* Ensure null termination */ state->request.data.sid[sizeof(state->request.data.sid)-1]='\0'; - DEBUG(3, ("[%5d]: sid to uid %s\n", state->pid, + DEBUG(3, ("[%5lu]: sid to uid %s\n", (unsigned long)state->pid, state->request.data.sid)); /* Split sid into domain sid and user rid */ @@ -159,7 +159,7 @@ enum winbindd_result winbindd_sid_to_gid(struct winbindd_cli_state *state) /* Ensure null termination */ state->request.data.sid[sizeof(state->request.data.sid)-1]='\0'; - DEBUG(3, ("[%5d]: sid to gid %s\n", state->pid, + DEBUG(3, ("[%5lu]: sid to gid %s\n", (unsigned long)state->pid, state->request.data.sid)); if (!string_to_sid(&sid, state->request.data.sid)) { @@ -192,13 +192,13 @@ enum winbindd_result winbindd_uid_to_sid(struct winbindd_cli_state *state) return WINBINDD_ERROR; } - DEBUG(3, ("[%5d]: uid to sid %d\n", state->pid, - state->request.data.uid)); + DEBUG(3, ("[%5lu]: uid to sid %lu\n", (unsigned long)state->pid, + (unsigned long)state->request.data.uid)); /* Lookup rid for this uid */ if (!NT_STATUS_IS_OK(idmap_uid_to_sid(&sid, state->request.data.uid))) { - DEBUG(1, ("Could not convert uid %d to rid\n", - state->request.data.uid)); + DEBUG(1, ("Could not convert uid %lu to rid\n", + (unsigned long)state->request.data.uid)); return WINBINDD_ERROR; } @@ -221,13 +221,13 @@ enum winbindd_result winbindd_gid_to_sid(struct winbindd_cli_state *state) return WINBINDD_ERROR; } - DEBUG(3, ("[%5d]: gid to sid %d\n", state->pid, - state->request.data.gid)); + DEBUG(3, ("[%5lu]: gid to sid %lu\n", (unsigned long)state->pid, + (unsigned long)state->request.data.gid)); /* Lookup sid for this uid */ if (!NT_STATUS_IS_OK(idmap_gid_to_sid(&sid, state->request.data.gid))) { - DEBUG(1, ("Could not convert gid %d to sid\n", - state->request.data.gid)); + DEBUG(1, ("Could not convert gid %lu to sid\n", + (unsigned long)state->request.data.gid)); return WINBINDD_ERROR; } diff --git a/source3/nsswitch/winbindd_user.c b/source3/nsswitch/winbindd_user.c index c49c41687b..c0b0d94167 100644 --- a/source3/nsswitch/winbindd_user.c +++ b/source3/nsswitch/winbindd_user.c @@ -108,7 +108,7 @@ enum winbindd_result winbindd_getpwnam(struct winbindd_cli_state *state) /* Ensure null termination */ state->request.data.username[sizeof(state->request.data.username)-1]='\0'; - DEBUG(3, ("[%5d]: getpwnam %s\n", state->pid, + DEBUG(3, ("[%5lu]: getpwnam %s\n", (unsigned long)state->pid, state->request.data.username)); /* Parse domain and username */ @@ -131,7 +131,7 @@ enum winbindd_result winbindd_getpwnam(struct winbindd_cli_state *state) /* should we deal with users for our domain? */ if ( lp_winbind_trusted_domains_only() && strequal(name_domain, lp_workgroup())) { - DEBUG(7,("winbindd_getpenam: My domain -- rejecting getpwnam() for %s\\%s.\n", + DEBUG(7,("winbindd_getpwnam: My domain -- rejecting getpwnam() for %s\\%s.\n", name_domain, name_user)); return WINBINDD_ERROR; } @@ -209,8 +209,8 @@ enum winbindd_result winbindd_getpwuid(struct winbindd_cli_state *state) (state->request.data.uid > server_state.uid_high)) return WINBINDD_ERROR; - DEBUG(3, ("[%5d]: getpwuid %d\n", state->pid, - state->request.data.uid)); + DEBUG(3, ("[%5lu]: getpwuid %lu\n", (unsigned long)state->pid, + (unsigned long)state->request.data.uid)); /* always try local tdb first */ @@ -222,8 +222,8 @@ enum winbindd_result winbindd_getpwuid(struct winbindd_cli_state *state) /* Get rid from uid */ if (!NT_STATUS_IS_OK(idmap_uid_to_sid(&user_sid, state->request.data.uid))) { - DEBUG(1, ("could not convert uid %d to SID\n", - state->request.data.uid)); + DEBUG(1, ("could not convert uid %lu to SID\n", + (unsigned long)state->request.data.uid)); return WINBINDD_ERROR; } @@ -246,8 +246,8 @@ enum winbindd_result winbindd_getpwuid(struct winbindd_cli_state *state) /* Get some user info */ - if (!(mem_ctx = talloc_init("winbind_getpwuid(%d)", - state->request.data.uid))) { + if (!(mem_ctx = talloc_init("winbind_getpwuid(%lu)", + (unsigned long)state->request.data.uid))) { DEBUG(1, ("out of memory\n")); return WINBINDD_ERROR; @@ -295,7 +295,7 @@ enum winbindd_result winbindd_setpwent(struct winbindd_cli_state *state) { struct winbindd_domain *domain; - DEBUG(3, ("[%5d]: setpwent\n", state->pid)); + DEBUG(3, ("[%5lu]: setpwent\n", (unsigned long)state->pid)); /* Check user has enabled this */ @@ -359,7 +359,7 @@ enum winbindd_result winbindd_setpwent(struct winbindd_cli_state *state) enum winbindd_result winbindd_endpwent(struct winbindd_cli_state *state) { - DEBUG(3, ("[%5d]: endpwent\n", state->pid)); + DEBUG(3, ("[%5lu]: endpwent\n", (unsigned long)state->pid)); free_getent_state(state->getpwent_state); state->getpwent_state = NULL; @@ -474,7 +474,7 @@ enum winbindd_result winbindd_getpwent(struct winbindd_cli_state *state) struct winbindd_pw *user_list; int num_users, user_list_ndx = 0, i; - DEBUG(3, ("[%5d]: getpwent\n", state->pid)); + DEBUG(3, ("[%5lu]: getpwent\n", (unsigned long)state->pid)); /* Check user has enabled this */ @@ -581,7 +581,7 @@ enum winbindd_result winbindd_list_users(struct winbindd_cli_state *state) TALLOC_CTX *mem_ctx; enum winbindd_result rv = WINBINDD_ERROR; - DEBUG(3, ("[%5d]: list users\n", state->pid)); + DEBUG(3, ("[%5lu]: list users\n", (unsigned long)state->pid)); if (!(mem_ctx = talloc_init("winbindd_list_users"))) return WINBINDD_ERROR; diff --git a/source3/nsswitch/winbindd_util.c b/source3/nsswitch/winbindd_util.c index 6177c46aef..a810e503a0 100644 --- a/source3/nsswitch/winbindd_util.c +++ b/source3/nsswitch/winbindd_util.c @@ -111,7 +111,7 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const fstrcpy(domain->name, alt_name); fstrcpy(domain->alt_name, domain_name); } else { - fstrcpy(domain->name, domain_name); + fstrcpy(domain->name, domain_name); if (alt_name) { fstrcpy(domain->alt_name, alt_name); } @@ -174,8 +174,11 @@ void rescan_trusted_domains(BOOL force) char **names; char **alt_names; int num_domains = 0; - DOM_SID *dom_sids; + DOM_SID *dom_sids, null_sid; int i; + struct winbindd_domain *new_domain; + + ZERO_STRUCTP(&null_sid); result = domain->methods->trusted_domains(domain, mem_ctx, &num_domains, &names, &alt_names, &dom_sids); @@ -183,12 +186,34 @@ void rescan_trusted_domains(BOOL force) continue; } - /* Add each domain to the trusted domain list. Each domain inherits - the access methods of its parent */ + /* Add each domain to the trusted domain list */ + for(i = 0; i < num_domains; i++) { DEBUG(10,("Found domain %s\n", names[i])); add_trusted_domain(names[i], alt_names?alt_names[i]:NULL, domain->methods, &dom_sids[i]); + + /* if the SID was empty, we better set it now */ + + if ( sid_equal(&dom_sids[i], &null_sid) ) { + + new_domain = find_domain_from_name(names[i]); + + /* this should never happen */ + if ( !new_domain ) { + DEBUG(0,("rescan_trust_domains: can't find the domain I just added! [%s]\n", + names[i])); + break; + } + + /* call the cache method; which will operate on the winbindd_domain \ + passed in and choose either rpc or ads as appropriate */ + + result = domain->methods->domain_sid( new_domain, &new_domain->sid ); + + if ( NT_STATUS_IS_OK(result) ) + sid_copy( &dom_sids[i], &domain->sid ); + } /* store trusted domain in the cache */ trustdom_cache_store(names[i], alt_names ? alt_names[i] : NULL, @@ -209,7 +234,7 @@ BOOL init_domain_list(void) free_domain_list(); /* Add ourselves as the first entry */ - domain = add_trusted_domain(lp_workgroup(), NULL, &cache_methods, NULL); + domain = add_trusted_domain( lp_workgroup(), NULL, &cache_methods, NULL); if (!secrets_fetch_domain_sid(domain->name, &domain->sid)) { DEBUG(1, ("Could not fetch sid for our domain %s\n", domain->name)); @@ -782,3 +807,53 @@ BOOL winbindd_upgrade_idmap(void) return idmap_convert(idmap_name); } + +/******************************************************************* + wrapper around retrieving the trust account password +*******************************************************************/ + +BOOL get_trust_pw(const char *domain, uint8 ret_pwd[16], + time_t *pass_last_set_time, uint32 *channel) +{ + DOM_SID sid; + char *pwd; + + /* if we are a DC and this is not our domain, then lookup an account + for the domain trust */ + + if ( IS_DC && !strequal(domain, lp_workgroup()) && lp_allow_trusted_domains() ) + { + if ( !secrets_fetch_trusted_domain_password(domain, &pwd, &sid, + pass_last_set_time) ) + { + DEBUG(0, ("get_trust_pw: could not fetch trust account " + "password for trusted domain %s\n", domain)); + return False; + } + + *channel = SEC_CHAN_DOMAIN; + E_md4hash(pwd, ret_pwd); + SAFE_FREE(pwd); + + return True; + } + else /* just get the account for our domain (covers + ROLE_DOMAIN_MEMBER as well */ + { + /* get the machine trust account for our domain */ + + if ( !secrets_fetch_trust_account_password (lp_workgroup(), ret_pwd, + pass_last_set_time, channel) ) + { + DEBUG(0, ("get_trust_pw: could not fetch trust account " + "password for my domain %s\n", domain)); + return False; + } + + return True; + } + + /* Failure */ + return False; +} + diff --git a/source3/nsswitch/winbindd_wins.c b/source3/nsswitch/winbindd_wins.c index 66903e250d..49bee2dc9f 100644 --- a/source3/nsswitch/winbindd_wins.c +++ b/source3/nsswitch/winbindd_wins.c @@ -137,7 +137,7 @@ enum winbindd_result winbindd_wins_byip(struct winbindd_cli_state *state) /* Ensure null termination */ state->request.data.winsreq[sizeof(state->request.data.winsreq)-1]='\0'; - DEBUG(3, ("[%5d]: wins_byip %s\n", state->pid, + DEBUG(3, ("[%5lu]: wins_byip %s\n", (unsigned long)state->pid, state->request.data.winsreq)); *response = '\0'; @@ -184,7 +184,7 @@ enum winbindd_result winbindd_wins_byname(struct winbindd_cli_state *state) /* Ensure null termination */ state->request.data.winsreq[sizeof(state->request.data.winsreq)-1]='\0'; - DEBUG(3, ("[%5d]: wins_byname %s\n", state->pid, + DEBUG(3, ("[%5lu]: wins_byname %s\n", (unsigned long)state->pid, state->request.data.winsreq)); *response = '\0'; diff --git a/source3/nsswitch/wins.c b/source3/nsswitch/wins.c index 62493ef0a9..87dac60192 100644 --- a/source3/nsswitch/wins.c +++ b/source3/nsswitch/wins.c @@ -86,29 +86,6 @@ static void nss_wins_init(void) load_interfaces(); } -static struct node_status *lookup_byaddr_backend(char *addr, int *count) -{ - int fd; - struct in_addr ip; - struct nmb_name nname; - struct node_status *status; - - if (!initialised) { - nss_wins_init(); - } - - fd = wins_lookup_open_socket_in(); - if (fd == -1) - return NULL; - - make_nmb_name(&nname, "*", 0); - ip = *interpret_addr2(addr); - status = node_status_query(fd,&nname,ip, count); - - close(fd); - return status; -} - static struct in_addr *lookup_byname_backend(const char *name, int *count) { int fd = -1; @@ -149,8 +126,31 @@ static struct in_addr *lookup_byname_backend(const char *name, int *count) return ret; } - #ifdef HAVE_NS_API_H + +static struct node_status *lookup_byaddr_backend(char *addr, int *count) +{ + int fd; + struct in_addr ip; + struct nmb_name nname; + struct node_status *status; + + if (!initialised) { + nss_wins_init(); + } + + fd = wins_lookup_open_socket_in(); + if (fd == -1) + return NULL; + + make_nmb_name(&nname, "*", 0); + ip = *interpret_addr2(addr); + status = node_status_query(fd,&nname,ip, count); + + close(fd); + return status; +} + /* IRIX version */ int init(void) diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index dd429fa688..8bd50f35de 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -8,7 +8,7 @@ Copyright (C) Simo Sorce 2001 Copyright (C) Alexander Bokovoy 2002 Copyright (C) Stefan (metze) Metzmacher 2002 - Copyright (C) Anthony Liguori 2003 + Copyright (C) Jim McDonough 2003 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -292,6 +292,7 @@ typedef struct int restrict_anonymous; int name_cache_timeout; int client_signing; + int server_signing; param_opt_struct *param_opt; } global; @@ -693,15 +694,17 @@ static const struct enum_list enum_smb_signing_vals[] = { {False, "False"}, {False, "0"}, {False, "Off"}, + {False, "disabled"}, {True, "Yes"}, {True, "True"}, {True, "1"}, {True, "On"}, - {Required, "Required"}, - {Required, "Mandatory"}, - {Required, "Force"}, - {Required, "Forced"}, - {Required, "Enforced"}, + {True, "enabled"}, + {Required, "required"}, + {Required, "mandatory"}, + {Required, "force"}, + {Required, "forced"}, + {Required, "enforced"}, {-1, NULL} }; @@ -735,427 +738,432 @@ static const struct enum_list enum_map_to_guest[] = { }; /* 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. + * + * NOTE: To display a parameter in BASIC view set FLAG_BASIC + * Any parameter that does NOT have FLAG_ADVANCED will not disply at all + * Set FLAG_SHARE and FLAG_PRINT to specifically display parameters in + * respective views. */ + static struct parm_struct parm_table[] = { - {"Base Options", P_SEP, P_SEPARATOR}, - - {"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, handle_workgroup, 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}, - {"netbios name", P_USTRING, P_GLOBAL, &Globals.szNetbiosName, handle_netbios_name, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER}, - {"netbios aliases", P_LIST, P_GLOBAL, &Globals.szNetbiosAliases, handle_netbios_aliases, NULL, FLAG_ADVANCED | FLAG_WIZARD | FLAG_DEVELOPER}, - {"netbios scope", P_USTRING, P_GLOBAL, &Globals.szNetbiosScope, handle_netbios_scope, 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 | 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}, - {"client schannel", P_ENUM, P_GLOBAL, &Globals.clientSchannel, NULL, enum_bool_auto, FLAG_BASIC | FLAG_ADVANCED | FLAG_DEVELOPER}, - {"server schannel", P_ENUM, P_GLOBAL, &Globals.serverSchannel, NULL, enum_bool_auto, 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_WIZARD | FLAG_DEVELOPER}, - {"algorithmic rid base", P_INTEGER, P_GLOBAL, &Globals.AlgorithmicRidBase, 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, 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}, - {"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}, - {"client NTLMv2 auth", P_BOOL, P_GLOBAL, &Globals.bClientNTLMv2Auth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, - {"client lanman auth", P_BOOL, P_GLOBAL, &Globals.bClientLanManAuth, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, - {"client plaintext auth", P_BOOL, P_GLOBAL, &Globals.bClientPlaintextAuth, 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, 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}, - {"admin users", P_LIST, P_LOCAL, &sDefault.szAdminUsers, NULL, NULL, FLAG_GLOBAL | FLAG_SHARE}, - {"read list", P_LIST, P_LOCAL, &sDefault.readlist, NULL, NULL, FLAG_GLOBAL | FLAG_SHARE}, - {"write list", P_LIST, P_LOCAL, &sDefault.writelist, NULL, NULL, FLAG_GLOBAL | FLAG_SHARE}, - {"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, FLAG_ADVANCED | FLAG_DEVELOPER}, - - {"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}, - {"force create mode", P_OCTAL, P_LOCAL, &sDefault.iCreate_force_mode, NULL, NULL, FLAG_GLOBAL | FLAG_SHARE}, - {"security mask", P_OCTAL, P_LOCAL, &sDefault.iSecurity_mask, NULL, NULL, FLAG_GLOBAL | FLAG_SHARE}, - {"force security mode", P_OCTAL, P_LOCAL, &sDefault.iSecurity_force_mode, NULL, NULL, FLAG_GLOBAL | FLAG_SHARE}, - {"directory mask", P_OCTAL, P_LOCAL, &sDefault.iDir_mask, NULL, NULL, FLAG_GLOBAL | FLAG_SHARE}, - {"directory mode", P_OCTAL, P_LOCAL, &sDefault.iDir_mask, NULL, NULL, FLAG_GLOBAL}, - {"force directory mode", P_OCTAL, P_LOCAL, &sDefault.iDir_force_mode, NULL, NULL, FLAG_GLOBAL | FLAG_SHARE}, - {"directory security mask", P_OCTAL, P_LOCAL, &sDefault.iDir_Security_mask, NULL, NULL, FLAG_GLOBAL | FLAG_SHARE}, - {"force directory security mode", P_OCTAL, P_LOCAL, &sDefault.iDir_Security_force_mode, NULL, NULL, FLAG_GLOBAL | FLAG_SHARE}, - {"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, FLAG_HIDE}, - - {"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_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}, - {"preload modules", P_LIST, P_GLOBAL, &Globals.szPreloadModules, NULL, NULL, FLAG_BASIC | FLAG_GLOBAL}, - - {"Logging Options", P_SEP, P_SEPARATOR}, - - {"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, 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, 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}, - - {"acl compatibility", P_STRING, P_GLOBAL, &Globals.szAclCompat, handle_acl_compatibility, NULL, FLAG_SHARE | FLAG_GLOBAL | FLAG_ADVANCED | FLAG_DEVELOPER}, - {"nt acl support", P_BOOL, P_LOCAL, &sDefault.bNTAclSupport, NULL, NULL, FLAG_GLOBAL | FLAG_SHARE | FLAG_ADVANCED | FLAG_DEVELOPER}, - {"nt pipe support", P_BOOL, P_GLOBAL, &Globals.bNTPipeSupport, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, - {"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}, - - {"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}, - {"map acl inherit", P_BOOL, P_LOCAL, &sDefault.bMap_acl_inherit, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL}, - {"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, 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}, - {"client signing", P_ENUM, P_GLOBAL, &Globals.client_signing, NULL, enum_smb_signing_vals, FLAG_ADVANCED | FLAG_DEVELOPER}, - {"client use spnego", P_BOOL, P_GLOBAL, &Globals.bClientUseSpnego, 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, 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}, - {"kernel change notify", P_BOOL, P_GLOBAL, &Globals.bKernelChangeNotify, NULL, NULL, FLAG_DEVELOPER}, - - {"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, 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, FLAG_DEVELOPER}, - - {"socket options", P_GSTRING, P_GLOBAL, user_socket_options, 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, FLAG_DEVELOPER}, - {"use sendfile", P_BOOL, P_LOCAL, &sDefault.bUseSendfile, NULL, NULL, FLAG_SHARE}, - {"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, FLAG_ADVANCED | FLAG_DEVELOPER}, - - {"Printing Options", P_SEP, P_SEPARATOR}, - - {"max reported print jobs", P_INTEGER, P_LOCAL, &sDefault.iMaxReportedPrintJobs, 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 | 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, FLAG_HIDE}, - {"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}, - {"disable spoolss", P_BOOL, P_GLOBAL, &Globals.bDisableSpoolss, NULL, NULL, FLAG_PRINT | FLAG_GLOBAL}, - {"lpq command", P_STRING, P_LOCAL, &sDefault.szLpqcommand, NULL, NULL, FLAG_PRINT | FLAG_GLOBAL}, - {"lprm command", P_STRING, P_LOCAL, &sDefault.szLprmcommand, NULL, NULL, FLAG_PRINT | FLAG_GLOBAL}, - {"lppause command", P_STRING, P_LOCAL, &sDefault.szLppausecommand, NULL, NULL, FLAG_PRINT | FLAG_GLOBAL}, - {"lpresume command", P_STRING, P_LOCAL, &sDefault.szLpresumecommand, NULL, NULL, FLAG_PRINT | FLAG_GLOBAL}, - {"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, 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, 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}, - - {"Filename Handling", P_SEP, P_SEPARATOR}, - {"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}, - {"mangle prefix", P_INTEGER, P_GLOBAL, &Globals.mangle_prefix, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, - - {"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, 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}, - {"veto files", P_STRING, P_LOCAL, &sDefault.szVetoFiles, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL }, - {"hide files", P_STRING, P_LOCAL, &sDefault.szHideFiles, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL }, - {"veto oplock files", P_STRING, P_LOCAL, &sDefault.szVetoOplockFiles, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL }, - {"map system", P_BOOL, P_LOCAL, &sDefault.bMap_system, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL}, - {"map hidden", P_BOOL, P_LOCAL, &sDefault.bMap_hidden, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL}, - {"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, FLAG_DEVELOPER}, - - {"Domain Options", P_SEP, P_SEPARATOR}, - - {"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, 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 | 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 | 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, 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 | 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}, + {"Base Options", P_SEP, P_SEPARATOR}, + + {"dos charset", P_STRING, P_GLOBAL, &Globals.dos_charset, NULL, NULL, FLAG_ADVANCED}, + {"unix charset", P_STRING, P_GLOBAL, &Globals.unix_charset, NULL, NULL, FLAG_ADVANCED}, + {"display charset", P_STRING, P_GLOBAL, &Globals.display_charset, NULL, NULL, FLAG_ADVANCED}, + {"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT}, + {"path", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT}, + {"directory", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, FLAG_HIDE}, + {"workgroup", P_USTRING, P_GLOBAL, &Globals.szWorkgroup, handle_workgroup, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD}, +#ifdef WITH_ADS + {"realm", P_USTRING, P_GLOBAL, &Globals.szRealm, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD}, +#endif + {"netbios name", P_USTRING, P_GLOBAL, &Globals.szNetbiosName, handle_netbios_name, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD}, + {"netbios aliases", P_LIST, P_GLOBAL, &Globals.szNetbiosAliases, handle_netbios_aliases, NULL, FLAG_ADVANCED}, + {"netbios scope", P_USTRING, P_GLOBAL, &Globals.szNetbiosScope, handle_netbios_scope, NULL, FLAG_ADVANCED}, + {"server string", P_STRING, P_GLOBAL, &Globals.szServerString, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED }, + {"interfaces", P_LIST, P_GLOBAL, &Globals.szInterfaces, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD}, + {"bind interfaces only", P_BOOL, P_GLOBAL, &Globals.bBindInterfacesOnly, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD}, + + {"Security Options", P_SEP, P_SEPARATOR}, + + {"security", P_ENUM, P_GLOBAL, &Globals.security, NULL, enum_security, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD}, + {"auth methods", P_LIST, P_GLOBAL, &Globals.AuthMethods, NULL, NULL, FLAG_ADVANCED}, + {"encrypt passwords", P_BOOL, P_GLOBAL, &Globals.bEncryptPasswords, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD}, + {"update encrypted", P_BOOL, P_GLOBAL, &Globals.bUpdateEncrypt, NULL, NULL, FLAG_ADVANCED}, + {"client schannel", P_ENUM, P_GLOBAL, &Globals.clientSchannel, NULL, enum_bool_auto, FLAG_BASIC | FLAG_ADVANCED}, + {"server schannel", P_ENUM, P_GLOBAL, &Globals.serverSchannel, NULL, enum_bool_auto, FLAG_BASIC | FLAG_ADVANCED}, + {"allow trusted domains", P_BOOL, P_GLOBAL, &Globals.bAllowTrustedDomains, NULL, NULL, FLAG_ADVANCED}, + {"hosts equiv", P_STRING, P_GLOBAL, &Globals.szHostsEquiv, NULL, NULL, FLAG_ADVANCED}, + {"min passwd length", P_INTEGER, P_GLOBAL, &Globals.min_passwd_length, NULL, NULL, FLAG_ADVANCED}, + {"min password length", P_INTEGER, P_GLOBAL, &Globals.min_passwd_length, NULL, NULL, FLAG_ADVANCED}, + {"map to guest", P_ENUM, P_GLOBAL, &Globals.map_to_guest, NULL, enum_map_to_guest, FLAG_ADVANCED}, + {"null passwords", P_BOOL, P_GLOBAL, &Globals.bNullPasswords, NULL, NULL, FLAG_ADVANCED}, + {"obey pam restrictions", P_BOOL, P_GLOBAL, &Globals.bObeyPamRestrictions, NULL, NULL, FLAG_ADVANCED}, + {"password server", P_STRING, P_GLOBAL, &Globals.szPasswordServer, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD}, + {"smb passwd file", P_STRING, P_GLOBAL, &Globals.szSMBPasswdFile, NULL, NULL, FLAG_ADVANCED}, + {"private dir", P_STRING, P_GLOBAL, &Globals.szPrivateDir, NULL, NULL, FLAG_ADVANCED}, + {"passdb backend", P_LIST, P_GLOBAL, &Globals.szPassdbBackend, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD}, + {"algorithmic rid base", P_INTEGER, P_GLOBAL, &Globals.AlgorithmicRidBase, NULL, NULL, FLAG_ADVANCED}, + {"root directory", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL, NULL, FLAG_ADVANCED}, + {"root dir", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL, NULL, FLAG_HIDE}, + {"root", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL, NULL, FLAG_HIDE}, + {"guest account", P_STRING, P_GLOBAL, &Globals.szGuestaccount, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED}, + + {"pam password change", P_BOOL, P_GLOBAL, &Globals.bPamPasswordChange, NULL, NULL, FLAG_ADVANCED}, + {"passwd program", P_STRING, P_GLOBAL, &Globals.szPasswdProgram, NULL, NULL, FLAG_ADVANCED}, + {"passwd chat", P_STRING, P_GLOBAL, &Globals.szPasswdChat, NULL, NULL, FLAG_ADVANCED}, + {"passwd chat debug", P_BOOL, P_GLOBAL, &Globals.bPasswdChatDebug, NULL, NULL, FLAG_ADVANCED}, + {"username map", P_STRING, P_GLOBAL, &Globals.szUsernameMap, NULL, NULL, FLAG_ADVANCED}, + {"password level", P_INTEGER, P_GLOBAL, &Globals.pwordlevel, NULL, NULL, FLAG_ADVANCED}, + {"username level", P_INTEGER, P_GLOBAL, &Globals.unamelevel, NULL, NULL, FLAG_ADVANCED}, + {"unix password sync", P_BOOL, P_GLOBAL, &Globals.bUnixPasswdSync, NULL, NULL, FLAG_ADVANCED}, + {"restrict anonymous", P_INTEGER, P_GLOBAL, &Globals.restrict_anonymous, NULL, NULL, FLAG_ADVANCED}, + {"lanman auth", P_BOOL, P_GLOBAL, &Globals.bLanmanAuth, NULL, NULL, FLAG_ADVANCED}, + {"ntlm auth", P_BOOL, P_GLOBAL, &Globals.bNTLMAuth, NULL, NULL, FLAG_ADVANCED}, + {"client NTLMv2 auth", P_BOOL, P_GLOBAL, &Globals.bClientNTLMv2Auth, NULL, NULL, FLAG_ADVANCED}, + {"client lanman auth", P_BOOL, P_GLOBAL, &Globals.bClientLanManAuth, NULL, NULL, FLAG_ADVANCED}, + {"client plaintext auth", P_BOOL, P_GLOBAL, &Globals.bClientPlaintextAuth, NULL, NULL, FLAG_ADVANCED}, + + {"username", P_STRING, P_LOCAL, &sDefault.szUsername, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, + {"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_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, + {"valid users", P_LIST, P_LOCAL, &sDefault.szValidUsers, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, + {"admin users", P_LIST, P_LOCAL, &sDefault.szAdminUsers, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, + {"read list", P_LIST, P_LOCAL, &sDefault.readlist, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, + {"write list", P_LIST, P_LOCAL, &sDefault.writelist, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, + {"printer admin", P_LIST, P_LOCAL, &sDefault.printer_admin, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_PRINT}, + {"force user", P_STRING, P_LOCAL, &sDefault.force_user, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, + {"force group", P_STRING, P_LOCAL, &sDefault.force_group, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, + {"group", P_STRING, P_LOCAL, &sDefault.force_group, NULL, NULL, FLAG_ADVANCED}, + + {"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_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, + {"create mode", P_OCTAL, P_LOCAL, &sDefault.iCreate_mask, NULL, NULL, FLAG_HIDE}, + {"force create mode", P_OCTAL, P_LOCAL, &sDefault.iCreate_force_mode, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, + {"security mask", P_OCTAL, P_LOCAL, &sDefault.iSecurity_mask, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, + {"force security mode", P_OCTAL, P_LOCAL, &sDefault.iSecurity_force_mode, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, + {"directory mask", P_OCTAL, P_LOCAL, &sDefault.iDir_mask, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, + {"directory mode", P_OCTAL, P_LOCAL, &sDefault.iDir_mask, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL}, + {"force directory mode", P_OCTAL, P_LOCAL, &sDefault.iDir_force_mode, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, + {"directory security mask", P_OCTAL, P_LOCAL, &sDefault.iDir_Security_mask, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, + {"force directory security mode", P_OCTAL, P_LOCAL, &sDefault.iDir_Security_force_mode, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, + {"inherit permissions", P_BOOL, P_LOCAL, &sDefault.bInheritPerms, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, + {"inherit acls", P_BOOL, P_LOCAL, &sDefault.bInheritACLS, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, + {"guest only", P_BOOL, P_LOCAL, &sDefault.bGuest_only, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, + {"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_ADVANCED | FLAG_SHARE | FLAG_PRINT}, + {"public", P_BOOL, P_LOCAL, &sDefault.bGuest_ok, NULL, NULL, FLAG_HIDE}, + + {"only user", P_BOOL, P_LOCAL, &sDefault.bOnlyUser, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, + {"hosts allow", P_LIST, P_LOCAL, &sDefault.szHostsallow, NULL, NULL, FLAG_GLOBAL | FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT}, + {"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}, + {"deny hosts", P_LIST, P_LOCAL, &sDefault.szHostsdeny, NULL, NULL, FLAG_HIDE}, + {"preload modules", P_LIST, P_GLOBAL, &Globals.szPreloadModules, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL}, + + {"Logging Options", P_SEP, P_SEPARATOR}, + + {"log level", P_STRING, P_GLOBAL, &Globals.szLogLevel, handle_debug_list, NULL, FLAG_ADVANCED}, + {"debuglevel", P_STRING, P_GLOBAL, &Globals.szLogLevel, handle_debug_list, NULL, FLAG_HIDE}, + {"syslog", P_INTEGER, P_GLOBAL, &Globals.syslog, NULL, NULL, FLAG_ADVANCED}, + {"syslog only", P_BOOL, P_GLOBAL, &Globals.bSyslogOnly, NULL, NULL, FLAG_ADVANCED}, + {"log file", P_STRING, P_GLOBAL, &Globals.szLogFile, NULL, NULL, FLAG_ADVANCED}, + + {"max log size", P_INTEGER, P_GLOBAL, &Globals.max_log_size, NULL, NULL, FLAG_ADVANCED}, + {"timestamp logs", P_BOOL, P_GLOBAL, &Globals.bTimestampLogs, NULL, NULL, FLAG_ADVANCED}, + {"debug timestamp", P_BOOL, P_GLOBAL, &Globals.bTimestampLogs, NULL, NULL, FLAG_ADVANCED}, + {"debug hires timestamp", P_BOOL, P_GLOBAL, &Globals.bDebugHiresTimestamp, NULL, NULL, FLAG_ADVANCED}, + {"debug pid", P_BOOL, P_GLOBAL, &Globals.bDebugPid, NULL, NULL, FLAG_ADVANCED}, + {"debug uid", P_BOOL, P_GLOBAL, &Globals.bDebugUid, NULL, NULL, FLAG_ADVANCED}, + + {"Protocol Options", P_SEP, P_SEPARATOR}, + + {"smb ports", P_STRING, P_GLOBAL, &Globals.smb_ports, NULL, NULL, FLAG_ADVANCED}, + {"protocol", P_ENUM, P_GLOBAL, &Globals.maxprotocol, NULL, enum_protocol, FLAG_ADVANCED}, + {"large readwrite", P_BOOL, P_GLOBAL, &Globals.bLargeReadwrite, NULL, NULL, FLAG_ADVANCED}, + {"max protocol", P_ENUM, P_GLOBAL, &Globals.maxprotocol, NULL, enum_protocol, FLAG_ADVANCED}, + {"min protocol", P_ENUM, P_GLOBAL, &Globals.minprotocol, NULL, enum_protocol, FLAG_ADVANCED}, + {"unicode", P_BOOL, P_GLOBAL, &Globals.bUnicode, NULL, NULL, FLAG_ADVANCED}, + {"read bmpx", P_BOOL, P_GLOBAL, &Globals.bReadbmpx, NULL, NULL, FLAG_ADVANCED}, + {"read raw", P_BOOL, P_GLOBAL, &Globals.bReadRaw, NULL, NULL, FLAG_ADVANCED}, + {"write raw", P_BOOL, P_GLOBAL, &Globals.bWriteRaw, NULL, NULL, FLAG_ADVANCED}, + {"disable netbios", P_BOOL, P_GLOBAL, &Globals.bDisableNetbios, NULL, NULL, FLAG_ADVANCED}, + + {"acl compatibility", P_STRING, P_GLOBAL, &Globals.szAclCompat, handle_acl_compatibility, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, + {"nt acl support", P_BOOL, P_LOCAL, &sDefault.bNTAclSupport, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, + {"nt pipe support", P_BOOL, P_GLOBAL, &Globals.bNTPipeSupport, NULL, NULL, FLAG_ADVANCED}, + {"nt status support", P_BOOL, P_GLOBAL, &Globals.bNTStatusSupport, NULL, NULL, FLAG_ADVANCED}, + {"profile acls", P_BOOL, P_LOCAL, &sDefault.bProfileAcls, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, + + {"announce version", P_STRING, P_GLOBAL, &Globals.szAnnounceVersion, NULL, NULL, FLAG_ADVANCED}, + {"announce as", P_ENUM, P_GLOBAL, &Globals.announce_as, NULL, enum_announce_as, FLAG_ADVANCED}, + {"map acl inherit", P_BOOL, P_LOCAL, &sDefault.bMap_acl_inherit, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, + {"max mux", P_INTEGER, P_GLOBAL, &Globals.max_mux, NULL, NULL, FLAG_ADVANCED}, + {"max xmit", P_INTEGER, P_GLOBAL, &Globals.max_xmit, NULL, NULL, FLAG_ADVANCED}, + + {"name resolve order", P_STRING, P_GLOBAL, &Globals.szNameResolveOrder, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD}, + {"max ttl", P_INTEGER, P_GLOBAL, &Globals.max_ttl, NULL, NULL, FLAG_ADVANCED}, + {"max wins ttl", P_INTEGER, P_GLOBAL, &Globals.max_wins_ttl, NULL, NULL, FLAG_ADVANCED}, + {"min wins ttl", P_INTEGER, P_GLOBAL, &Globals.min_wins_ttl, NULL, NULL, FLAG_ADVANCED}, + {"time server", P_BOOL, P_GLOBAL, &Globals.bTimeServer, NULL, NULL, FLAG_ADVANCED}, + {"unix extensions", P_BOOL, P_GLOBAL, &Globals.bUnixExtensions, NULL, NULL, FLAG_ADVANCED}, + {"use spnego", P_BOOL, P_GLOBAL, &Globals.bUseSpnego, NULL, NULL, FLAG_ADVANCED}, + {"client signing", P_ENUM, P_GLOBAL, &Globals.client_signing, NULL, enum_smb_signing_vals, FLAG_ADVANCED}, + {"server signing", P_ENUM, P_GLOBAL, &Globals.server_signing, NULL, enum_smb_signing_vals, FLAG_ADVANCED}, + {"client use spnego", P_BOOL, P_GLOBAL, &Globals.bClientUseSpnego, NULL, NULL, FLAG_ADVANCED}, + + {"Tuning Options", P_SEP, P_SEPARATOR}, + + {"block size", P_INTEGER, P_LOCAL, &sDefault.iBlock_size, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, + {"change notify timeout", P_INTEGER, P_GLOBAL, &Globals.change_notify_timeout, NULL, NULL, FLAG_ADVANCED}, + {"deadtime", P_INTEGER, P_GLOBAL, &Globals.deadtime, NULL, NULL, FLAG_ADVANCED}, + {"getwd cache", P_BOOL, P_GLOBAL, &use_getwd_cache, NULL, NULL, FLAG_ADVANCED}, + {"keepalive", P_INTEGER, P_GLOBAL, &keepalive, NULL, NULL, FLAG_ADVANCED}, + {"kernel change notify", P_BOOL, P_GLOBAL, &Globals.bKernelChangeNotify, NULL, NULL, FLAG_ADVANCED}, + + {"lpq cache time", P_INTEGER, P_GLOBAL, &Globals.lpqcachetime, NULL, NULL, FLAG_ADVANCED}, + {"max smbd processes", P_INTEGER, P_GLOBAL, &Globals.iMaxSmbdProcesses, NULL, NULL, FLAG_ADVANCED}, + {"max connections", P_INTEGER, P_LOCAL, &sDefault.iMaxConnections, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, + {"paranoid server security", P_BOOL, P_GLOBAL, &Globals.paranoid_server_security, NULL, NULL, FLAG_ADVANCED}, + {"max disk size", P_INTEGER, P_GLOBAL, &Globals.maxdisksize, NULL, NULL, FLAG_ADVANCED}, + {"max open files", P_INTEGER, P_GLOBAL, &Globals.max_open_files, NULL, NULL, FLAG_ADVANCED}, + {"min print space", P_INTEGER, P_LOCAL, &sDefault.iMinPrintSpace, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT}, + {"read size", P_INTEGER, P_GLOBAL, &Globals.ReadSize, NULL, NULL, FLAG_ADVANCED}, + + {"socket options", P_GSTRING, P_GLOBAL, user_socket_options, NULL, NULL, FLAG_ADVANCED}, + {"strict allocate", P_BOOL, P_LOCAL, &sDefault.bStrictAllocate, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, + {"strict sync", P_BOOL, P_LOCAL, &sDefault.bStrictSync, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, + {"sync always", P_BOOL, P_LOCAL, &sDefault.bSyncAlways, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, + {"use mmap", P_BOOL, P_GLOBAL, &Globals.bUseMmap, NULL, NULL, FLAG_ADVANCED}, + {"use sendfile", P_BOOL, P_LOCAL, &sDefault.bUseSendfile, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, + {"hostname lookups", P_BOOL, P_GLOBAL, &Globals.bHostnameLookups, NULL, NULL, FLAG_ADVANCED}, + {"write cache size", P_INTEGER, P_LOCAL, &sDefault.iWriteCacheSize, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, + + {"name cache timeout", P_INTEGER, P_GLOBAL, &Globals.name_cache_timeout, NULL, NULL, FLAG_ADVANCED}, + + {"Printing Options", P_SEP, P_SEPARATOR}, + + {"max reported print jobs", P_INTEGER, P_LOCAL, &sDefault.iMaxReportedPrintJobs, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT}, + {"max print jobs", P_INTEGER, P_LOCAL, &sDefault.iMaxPrintJobs, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT}, + {"load printers", P_BOOL, P_GLOBAL, &Globals.bLoadPrinters, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT}, + {"printcap name", P_STRING, P_GLOBAL, &Globals.szPrintcapname, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT}, + {"printcap", P_STRING, P_GLOBAL, &Globals.szPrintcapname, NULL, NULL, FLAG_HIDE}, + {"printable", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT}, + {"print ok", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL, NULL, FLAG_HIDE}, + {"printing", P_ENUM, P_LOCAL, &sDefault.iPrinting, NULL, enum_printing, FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL}, + {"print command", P_STRING, P_LOCAL, &sDefault.szPrintcommand, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL}, + {"disable spoolss", P_BOOL, P_GLOBAL, &Globals.bDisableSpoolss, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL}, + {"lpq command", P_STRING, P_LOCAL, &sDefault.szLpqcommand, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL}, + {"lprm command", P_STRING, P_LOCAL, &sDefault.szLprmcommand, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL}, + {"lppause command", P_STRING, P_LOCAL, &sDefault.szLppausecommand, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL}, + {"lpresume command", P_STRING, P_LOCAL, &sDefault.szLpresumecommand, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL}, + {"queuepause command", P_STRING, P_LOCAL, &sDefault.szQueuepausecommand, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL}, + {"queueresume command", P_STRING, P_LOCAL, &sDefault.szQueueresumecommand, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL}, + + {"enumports command", P_STRING, P_GLOBAL, &Globals.szEnumPortsCommand, NULL, NULL, FLAG_ADVANCED}, + {"addprinter command", P_STRING, P_GLOBAL, &Globals.szAddPrinterCommand, NULL, NULL, FLAG_ADVANCED}, + {"deleteprinter command", P_STRING, P_GLOBAL, &Globals.szDeletePrinterCommand, NULL, NULL, FLAG_ADVANCED}, + {"show add printer wizard", P_BOOL, P_GLOBAL, &Globals.bMsAddPrinterWizard, NULL, NULL, FLAG_ADVANCED}, + {"os2 driver map", P_STRING, P_GLOBAL, &Globals.szOs2DriverMap, NULL, NULL, FLAG_ADVANCED}, + + {"printer name", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT}, + {"printer", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL, NULL, FLAG_HIDE}, + {"use client driver", P_BOOL, P_LOCAL, &sDefault.bUseClientDriver, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT}, + {"default devmode", P_BOOL, P_LOCAL, &sDefault.bDefaultDevmode, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT}, + + {"Filename Handling", P_SEP, P_SEPARATOR}, + {"strip dot", P_BOOL, P_GLOBAL, &Globals.bStripDot, NULL, NULL, FLAG_ADVANCED}, + {"mangling method", P_STRING, P_GLOBAL, &Globals.szManglingMethod, NULL, NULL, FLAG_ADVANCED}, + {"mangle prefix", P_INTEGER, P_GLOBAL, &Globals.mangle_prefix, NULL, NULL, FLAG_ADVANCED}, + + {"mangled stack", P_INTEGER, P_GLOBAL, &Globals.mangled_stack, NULL, NULL, FLAG_ADVANCED}, + {"default case", P_ENUM, P_LOCAL, &sDefault.iDefaultCase, NULL, enum_case, FLAG_ADVANCED | FLAG_SHARE}, + {"case sensitive", P_BOOL, P_LOCAL, &sDefault.bCaseSensitive, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, + {"casesignames", P_BOOL, P_LOCAL, &sDefault.bCaseSensitive, NULL, NULL, FLAG_HIDE}, + {"preserve case", P_BOOL, P_LOCAL, &sDefault.bCasePreserve, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, + {"short preserve case", P_BOOL, P_LOCAL, &sDefault.bShortCasePreserve, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, + {"mangle case", P_BOOL, P_LOCAL, &sDefault.bCaseMangle, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, + {"mangling char", P_CHAR, P_LOCAL, &sDefault.magic_char, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, + {"hide dot files", P_BOOL, P_LOCAL, &sDefault.bHideDotFiles, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, + {"hide special files", P_BOOL, P_LOCAL, &sDefault.bHideSpecialFiles, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, + {"hide unreadable", P_BOOL, P_LOCAL, &sDefault.bHideUnReadable, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, + {"hide unwriteable files", P_BOOL, P_LOCAL, &sDefault.bHideUnWriteableFiles, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, + {"delete veto files", P_BOOL, P_LOCAL, &sDefault.bDeleteVetoFiles, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, + {"veto files", P_STRING, P_LOCAL, &sDefault.szVetoFiles, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL }, + {"hide files", P_STRING, P_LOCAL, &sDefault.szHideFiles, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL }, + {"veto oplock files", P_STRING, P_LOCAL, &sDefault.szVetoOplockFiles, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL }, + {"map system", P_BOOL, P_LOCAL, &sDefault.bMap_system, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, + {"map hidden", P_BOOL, P_LOCAL, &sDefault.bMap_hidden, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, + {"map archive", P_BOOL, P_LOCAL, &sDefault.bMap_archive, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, + {"mangled names", P_BOOL, P_LOCAL, &sDefault.bMangledNames, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, + {"mangled map", P_STRING, P_LOCAL, &sDefault.szMangledMap, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, + {"stat cache", P_BOOL, P_GLOBAL, &Globals.bStatCache, NULL, NULL, FLAG_ADVANCED}, + + {"Domain Options", P_SEP, P_SEPARATOR}, + + {"machine password timeout", P_INTEGER, P_GLOBAL, &Globals.machine_password_timeout, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD}, + + {"Logon Options", P_SEP, P_SEPARATOR}, + + {"add user script", P_STRING, P_GLOBAL, &Globals.szAddUserScript, NULL, NULL, FLAG_ADVANCED}, + {"delete user script", P_STRING, P_GLOBAL, &Globals.szDelUserScript, NULL, NULL, FLAG_ADVANCED}, + {"add group script", P_STRING, P_GLOBAL, &Globals.szAddGroupScript, NULL, NULL, FLAG_ADVANCED}, + {"delete group script", P_STRING, P_GLOBAL, &Globals.szDelGroupScript, NULL, NULL, FLAG_ADVANCED}, + {"add user to group script", P_STRING, P_GLOBAL, &Globals.szAddUserToGroupScript, NULL, NULL, FLAG_ADVANCED}, + {"delete user from group script", P_STRING, P_GLOBAL, &Globals.szDelUserFromGroupScript, NULL, NULL, FLAG_ADVANCED}, + {"set primary group script", P_STRING, P_GLOBAL, &Globals.szSetPrimaryGroupScript, NULL, NULL, FLAG_ADVANCED}, + {"add machine script", P_STRING, P_GLOBAL, &Globals.szAddMachineScript, NULL, NULL, FLAG_ADVANCED}, + {"shutdown script", P_STRING, P_GLOBAL, &Globals.szShutdownScript, NULL, NULL, FLAG_ADVANCED}, + {"abort shutdown script", P_STRING, P_GLOBAL, &Globals.szAbortShutdownScript, NULL, NULL, FLAG_ADVANCED}, + + {"logon script", P_STRING, P_GLOBAL, &Globals.szLogonScript, NULL, NULL, FLAG_ADVANCED}, + {"logon path", P_STRING, P_GLOBAL, &Globals.szLogonPath, NULL, NULL, FLAG_ADVANCED}, + {"logon drive", P_STRING, P_GLOBAL, &Globals.szLogonDrive, NULL, NULL, FLAG_ADVANCED}, + {"logon home", P_STRING, P_GLOBAL, &Globals.szLogonHome, NULL, NULL, FLAG_ADVANCED}, + {"domain logons", P_BOOL, P_GLOBAL, &Globals.bDomainLogons, NULL, NULL, FLAG_ADVANCED}, + + {"Browse Options", P_SEP, P_SEPARATOR}, + + {"os level", P_INTEGER, P_GLOBAL, &Globals.os_level, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED}, + {"lm announce", P_ENUM, P_GLOBAL, &Globals.lm_announce, NULL, enum_bool_auto, FLAG_ADVANCED}, + {"lm interval", P_INTEGER, P_GLOBAL, &Globals.lm_interval, NULL, NULL, FLAG_ADVANCED}, + {"preferred master", P_ENUM, P_GLOBAL, &Globals.bPreferredMaster, NULL, enum_bool_auto, FLAG_BASIC | FLAG_ADVANCED}, + {"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 | FLAG_ADVANCED}, + {"domain master", P_ENUM, P_GLOBAL, &Globals.bDomainMaster, NULL, enum_bool_auto, FLAG_BASIC | FLAG_ADVANCED}, + {"browse list", P_BOOL, P_GLOBAL, &Globals.bBrowseList, NULL, NULL, FLAG_ADVANCED}, + {"browseable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT}, + {"browsable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL, NULL, FLAG_HIDE}, + {"enhanced browsing", P_BOOL, P_GLOBAL, &Globals.enhanced_browsing, NULL, NULL, FLAG_ADVANCED}, + + {"WINS Options", P_SEP, P_SEPARATOR}, + + {"dns proxy", P_BOOL, P_GLOBAL, &Globals.bDNSproxy, NULL, NULL, FLAG_ADVANCED}, + {"wins proxy", P_BOOL, P_GLOBAL, &Globals.bWINSproxy, NULL, NULL, FLAG_ADVANCED}, + + {"wins server", P_LIST, P_GLOBAL, &Globals.szWINSservers, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD}, + {"wins support", P_BOOL, P_GLOBAL, &Globals.bWINSsupport, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD}, + {"wins hook", P_STRING, P_GLOBAL, &Globals.szWINSHook, NULL, NULL, FLAG_ADVANCED}, + {"wins partners", P_STRING, P_GLOBAL, &Globals.szWINSPartners, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD}, + + {"Locking Options", P_SEP, P_SEPARATOR}, + + {"blocking locks", P_BOOL, P_LOCAL, &sDefault.bBlockingLocks, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, + {"csc policy", P_ENUM, P_LOCAL, &sDefault.iCSCPolicy, NULL, enum_csc_policy, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, + {"fake oplocks", P_BOOL, P_LOCAL, &sDefault.bFakeOplocks, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, + {"kernel oplocks", P_BOOL, P_GLOBAL, &Globals.bKernelOplocks, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL}, + {"locking", P_BOOL, P_LOCAL, &sDefault.bLocking, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, + {"lock spin count", P_INTEGER, P_GLOBAL, &Globals.iLockSpinCount, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL}, + {"lock spin time", P_INTEGER, P_GLOBAL, &Globals.iLockSpinTime, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL}, + + {"oplocks", P_BOOL, P_LOCAL, &sDefault.bOpLocks, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, + {"level2 oplocks", P_BOOL, P_LOCAL, &sDefault.bLevel2OpLocks, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, + {"oplock break wait time", P_INTEGER, P_GLOBAL, &Globals.oplock_break_wait_time, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL}, + {"oplock contention limit", P_INTEGER, P_LOCAL, &sDefault.iOplockContentionLimit, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, + {"posix locking", P_BOOL, P_LOCAL, &sDefault.bPosixLocking, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, + {"strict locking", P_BOOL, P_LOCAL, &sDefault.bStrictLocking, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, + {"share modes", P_BOOL, P_LOCAL, &sDefault.bShareModes, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, + + {"Ldap Options", P_SEP, P_SEPARATOR}, - {"Locking Options", P_SEP, P_SEPARATOR}, - - {"blocking locks", P_BOOL, P_LOCAL, &sDefault.bBlockingLocks, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL}, - {"csc policy", P_ENUM, P_LOCAL, &sDefault.iCSCPolicy, NULL, enum_csc_policy, FLAG_SHARE | FLAG_GLOBAL}, - {"fake oplocks", P_BOOL, P_LOCAL, &sDefault.bFakeOplocks, NULL, NULL, FLAG_SHARE}, - {"kernel oplocks", P_BOOL, P_GLOBAL, &Globals.bKernelOplocks, NULL, NULL, FLAG_GLOBAL}, - {"locking", P_BOOL, P_LOCAL, &sDefault.bLocking, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL}, - {"lock spin count", P_INTEGER, P_GLOBAL, &Globals.iLockSpinCount, NULL, NULL, FLAG_GLOBAL}, - {"lock spin time", P_INTEGER, P_GLOBAL, &Globals.iLockSpinTime, NULL, NULL, FLAG_GLOBAL}, - - {"oplocks", P_BOOL, P_LOCAL, &sDefault.bOpLocks, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL}, - {"level2 oplocks", P_BOOL, P_LOCAL, &sDefault.bLevel2OpLocks, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL}, - {"oplock break wait time", P_INTEGER, P_GLOBAL, &Globals.oplock_break_wait_time, NULL, NULL, FLAG_GLOBAL}, - {"oplock contention limit", P_INTEGER, P_LOCAL, &sDefault.iOplockContentionLimit, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL}, - {"posix locking", P_BOOL, P_LOCAL, &sDefault.bPosixLocking, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL}, - {"strict locking", P_BOOL, P_LOCAL, &sDefault.bStrictLocking, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL}, - {"share modes", P_BOOL, P_LOCAL, &sDefault.bShareModes, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL}, - - {"Ldap Options", P_SEP, P_SEPARATOR}, - #ifdef WITH_LDAP_SAMCONFIG - {"ldap server", P_STRING, P_GLOBAL, &Globals.szLdapServer, NULL, NULL, 0}, - {"ldap port", P_INTEGER, P_GLOBAL, &Globals.ldap_port, NULL, NULL, 0}, + {"ldap server", P_STRING, P_GLOBAL, &Globals.szLdapServer, NULL, NULL, FLAG_ADVANCED}, + {"ldap port", P_INTEGER, P_GLOBAL, &Globals.ldap_port, NULL, NULL, FLAG_ADVANCED}, #endif - {"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_sub_suffix, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, - {"ldap user suffix", P_STRING, P_GLOBAL, &Globals.szLdapUserSuffix, handle_ldap_sub_suffix, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, - {"ldap group suffix", P_STRING, P_GLOBAL, &Globals.szLdapGroupSuffix, handle_ldap_sub_suffix, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, - {"ldap idmap suffix", P_STRING, P_GLOBAL, &Globals.szLdapIdmapSuffix, handle_ldap_sub_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}, - {"ldap trust ids", P_BOOL, P_GLOBAL, &Globals.ldap_trust_ids, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, - {"ldap delete dn", P_BOOL, P_GLOBAL, &Globals.ldap_delete_dn, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, - - {"Miscellaneous Options", P_SEP, P_SEPARATOR}, - {"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, FLAG_ADVANCED | FLAG_DEVELOPER}, - {"auto services", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, + {"ldap suffix", P_STRING, P_GLOBAL, &Globals.szLdapSuffix, handle_ldap_suffix, NULL, FLAG_ADVANCED}, + {"ldap machine suffix", P_STRING, P_GLOBAL, &Globals.szLdapMachineSuffix, handle_ldap_sub_suffix, NULL, FLAG_ADVANCED}, + {"ldap user suffix", P_STRING, P_GLOBAL, &Globals.szLdapUserSuffix, handle_ldap_sub_suffix, NULL, FLAG_ADVANCED}, + {"ldap group suffix", P_STRING, P_GLOBAL, &Globals.szLdapGroupSuffix, handle_ldap_sub_suffix, NULL, FLAG_ADVANCED}, + {"ldap idmap suffix", P_STRING, P_GLOBAL, &Globals.szLdapIdmapSuffix, handle_ldap_sub_suffix, NULL, FLAG_ADVANCED}, + {"ldap filter", P_STRING, P_GLOBAL, &Globals.szLdapFilter, NULL, NULL, FLAG_ADVANCED}, + {"ldap admin dn", P_STRING, P_GLOBAL, &Globals.szLdapAdminDn, NULL, NULL, FLAG_ADVANCED}, + {"ldap ssl", P_ENUM, P_GLOBAL, &Globals.ldap_ssl, NULL, enum_ldap_ssl, FLAG_ADVANCED}, + {"ldap passwd sync", P_ENUM, P_GLOBAL, &Globals.ldap_passwd_sync, NULL, enum_ldap_passwd_sync, FLAG_ADVANCED}, + {"ldap trust ids", P_BOOL, P_GLOBAL, &Globals.ldap_trust_ids, NULL, NULL, FLAG_ADVANCED}, + {"ldap delete dn", P_BOOL, P_GLOBAL, &Globals.ldap_delete_dn, NULL, NULL, FLAG_ADVANCED}, + + {"Miscellaneous Options", P_SEP, P_SEPARATOR}, + {"add share command", P_STRING, P_GLOBAL, &Globals.szAddShareCommand, NULL, NULL, FLAG_ADVANCED}, + {"change share command", P_STRING, P_GLOBAL, &Globals.szChangeShareCommand, NULL, NULL, FLAG_ADVANCED}, + {"delete share command", P_STRING, P_GLOBAL, &Globals.szDeleteShareCommand, NULL, NULL, FLAG_ADVANCED}, + + {"config file", P_STRING, P_GLOBAL, &Globals.szConfigFile, NULL, NULL, FLAG_HIDE}, + {"preload", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL, NULL, FLAG_ADVANCED}, + {"auto services", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL, NULL, FLAG_ADVANCED}, + {"lock directory", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL, NULL, FLAG_ADVANCED}, {"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}, + {"pid directory", P_STRING, P_GLOBAL, &Globals.szPidDir, NULL, NULL, FLAG_ADVANCED}, #ifdef WITH_UTMP - {"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}, + {"utmp directory", P_STRING, P_GLOBAL, &Globals.szUtmpDir, NULL, NULL, FLAG_ADVANCED}, + {"wtmp directory", P_STRING, P_GLOBAL, &Globals.szWtmpDir, NULL, NULL, FLAG_ADVANCED}, + {"utmp", P_BOOL, P_GLOBAL, &Globals.bUtmp, NULL, NULL, FLAG_ADVANCED}, #endif - - {"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}, - {"get quota command", P_STRING, P_GLOBAL, &Globals.szGetQuota, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, - {"set quota command", P_STRING, P_GLOBAL, &Globals.szSetQuota, 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, 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_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, 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}, - {"magic script", P_STRING, P_LOCAL, &sDefault.szMagicScript, NULL, NULL, FLAG_SHARE}, - {"magic output", P_STRING, P_LOCAL, &sDefault.szMagicOutput, NULL, NULL, FLAG_SHARE}, - {"delete readonly", P_BOOL, P_LOCAL, &sDefault.bDeleteReadonly, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL}, - {"dos filemode", P_BOOL, P_LOCAL, &sDefault.bDosFilemode, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL}, - {"dos filetimes", P_BOOL, P_LOCAL, &sDefault.bDosFiletimes, NULL, NULL, FLAG_SHARE | FLAG_GLOBAL}, - {"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, 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}, - - {"vfs objects", P_LIST, P_LOCAL, &sDefault.szVfsObjects, NULL, NULL, FLAG_SHARE}, - {"vfs object", P_LIST, P_LOCAL, &sDefault.szVfsObjects, NULL, NULL, FLAG_SHARE | FLAG_HIDE}, - - {"msdfs root", P_BOOL, P_LOCAL, &sDefault.bMSDfsRoot, NULL, NULL, FLAG_SHARE}, - {"msdfs proxy", P_STRING, P_LOCAL, &sDefault.szMSDfsProxy, NULL, NULL, FLAG_SHARE}, - {"host msdfs", P_BOOL, P_GLOBAL, &Globals.bHostMSDfs, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, - - {"Winbind options", P_SEP, P_SEPARATOR}, - - {"enable rid algorithm", P_BOOL, P_GLOBAL, &Globals.bEnableRidAlgorithm, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER | FLAG_DEPRECATED}, - {"idmap backend", P_STRING, P_GLOBAL, &Globals.szIdmapBackend, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, - {"idmap uid", P_STRING, P_GLOBAL, &Globals.szIdmapUID, handle_idmap_uid, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, - {"winbind uid", P_STRING, P_GLOBAL, &Globals.szIdmapUID, handle_idmap_uid, NULL, FLAG_ADVANCED | FLAG_DEVELOPER }, - {"idmap gid", P_STRING, P_GLOBAL, &Globals.szIdmapGID, handle_idmap_gid, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, - {"winbind gid", P_STRING, P_GLOBAL, &Globals.szIdmapGID, handle_idmap_gid, NULL, FLAG_ADVANCED | FLAG_DEVELOPER }, - {"template primary group", P_STRING, P_GLOBAL, &Globals.szTemplatePrimaryGroup, NULL, 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 enable local accounts", P_BOOL, P_GLOBAL, &Globals.bWinbindEnableLocalAccounts, 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}, - {"winbind trusted domains only", P_BOOL, P_GLOBAL, &Globals.bWinbindTrustedDomainsOnly, NULL, NULL, FLAG_ADVANCED | FLAG_DEVELOPER}, - - {NULL, P_BOOL, P_NONE, NULL, NULL, NULL, 0} + {"default service", P_STRING, P_GLOBAL, &Globals.szDefaultService, NULL, NULL, FLAG_ADVANCED}, + {"default", P_STRING, P_GLOBAL, &Globals.szDefaultService, NULL, NULL, FLAG_ADVANCED}, + {"message command", P_STRING, P_GLOBAL, &Globals.szMsgCommand, NULL, NULL, FLAG_ADVANCED}, + {"dfree command", P_STRING, P_GLOBAL, &Globals.szDfree, NULL, NULL, FLAG_ADVANCED}, + {"get quota command", P_STRING, P_GLOBAL, &Globals.szGetQuota, NULL, NULL, FLAG_ADVANCED}, + {"set quota command", P_STRING, P_GLOBAL, &Globals.szSetQuota, NULL, NULL, FLAG_ADVANCED}, + {"remote announce", P_STRING, P_GLOBAL, &Globals.szRemoteAnnounce, NULL, NULL, FLAG_ADVANCED}, + {"remote browse sync", P_STRING, P_GLOBAL, &Globals.szRemoteBrowseSync, NULL, NULL, FLAG_ADVANCED}, + {"socket address", P_STRING, P_GLOBAL, &Globals.szSocketAddress, NULL, NULL, FLAG_ADVANCED}, + {"homedir map", P_STRING, P_GLOBAL, &Globals.szNISHomeMapName, NULL, NULL, FLAG_ADVANCED}, + {"time offset", P_INTEGER, P_GLOBAL, &extra_time_offset, NULL, NULL, FLAG_ADVANCED}, + {"NIS homedir", P_BOOL, P_GLOBAL, &Globals.bNISHomeMap, NULL, NULL, FLAG_ADVANCED}, + {"-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_ADVANCED | FLAG_SHARE | FLAG_PRINT}, + {"preexec", P_STRING, P_LOCAL, &sDefault.szPreExec, NULL, NULL, FLAG_ADVANCED}, + + {"preexec close", P_BOOL, P_LOCAL, &sDefault.bPreexecClose, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, + {"postexec", P_STRING, P_LOCAL, &sDefault.szPostExec, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT}, + {"root preexec", P_STRING, P_LOCAL, &sDefault.szRootPreExec, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT}, + {"root preexec close", P_BOOL, P_LOCAL, &sDefault.bRootpreexecClose, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, + {"root postexec", P_STRING, P_LOCAL, &sDefault.szRootPostExec, NULL, NULL, FLAG_ADVANCED | 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_ADVANCED | FLAG_SHARE }, + {"fstype", P_STRING, P_LOCAL, &sDefault.fstype, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, + {"set directory", P_BOOLREV, P_LOCAL, &sDefault.bNo_set_dir, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, + {"source environment", P_STRING, P_GLOBAL, &Globals.szSourceEnv, handle_source_env, NULL, FLAG_ADVANCED}, + {"wide links", P_BOOL, P_LOCAL, &sDefault.bWidelinks, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, + {"follow symlinks", P_BOOL, P_LOCAL, &sDefault.bSymlinks, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, + {"dont descend", P_STRING, P_LOCAL, &sDefault.szDontdescend, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, + {"magic script", P_STRING, P_LOCAL, &sDefault.szMagicScript, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, + {"magic output", P_STRING, P_LOCAL, &sDefault.szMagicOutput, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, + {"delete readonly", P_BOOL, P_LOCAL, &sDefault.bDeleteReadonly, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, + {"dos filemode", P_BOOL, P_LOCAL, &sDefault.bDosFilemode, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, + {"dos filetimes", P_BOOL, P_LOCAL, &sDefault.bDosFiletimes, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, + {"dos filetime resolution", P_BOOL, P_LOCAL, &sDefault.bDosFiletimeResolution, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, + + {"fake directory create times", P_BOOL, P_LOCAL, &sDefault.bFakeDirCreateTimes, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, + {"panic action", P_STRING, P_GLOBAL, &Globals.szPanicAction, NULL, NULL, FLAG_ADVANCED}, + {"hide local users", P_BOOL, P_GLOBAL, &Globals.bHideLocalUsers, NULL, NULL, FLAG_ADVANCED}, + + {"VFS module options", P_SEP, P_SEPARATOR}, + + {"vfs objects", P_LIST, P_LOCAL, &sDefault.szVfsObjects, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, + {"vfs object", P_LIST, P_LOCAL, &sDefault.szVfsObjects, NULL, NULL, FLAG_HIDE}, + + + {"msdfs root", P_BOOL, P_LOCAL, &sDefault.bMSDfsRoot, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, + {"msdfs proxy", P_STRING, P_LOCAL, &sDefault.szMSDfsProxy, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, + {"host msdfs", P_BOOL, P_GLOBAL, &Globals.bHostMSDfs, NULL, NULL, FLAG_ADVANCED}, + + {"Winbind options", P_SEP, P_SEPARATOR}, + + {"enable rid algorithm", P_BOOL, P_GLOBAL, &Globals.bEnableRidAlgorithm, NULL, NULL, FLAG_DEPRECATED}, + {"idmap backend", P_STRING, P_GLOBAL, &Globals.szIdmapBackend, NULL, NULL, FLAG_ADVANCED}, + {"idmap uid", P_STRING, P_GLOBAL, &Globals.szIdmapUID, handle_idmap_uid, NULL, FLAG_ADVANCED}, + {"winbind uid", P_STRING, P_GLOBAL, &Globals.szIdmapUID, handle_idmap_uid, NULL, FLAG_ADVANCED}, + {"idmap gid", P_STRING, P_GLOBAL, &Globals.szIdmapGID, handle_idmap_gid, NULL, FLAG_ADVANCED}, + {"winbind gid", P_STRING, P_GLOBAL, &Globals.szIdmapGID, handle_idmap_gid, NULL, FLAG_ADVANCED}, + {"template primary group", P_STRING, P_GLOBAL, &Globals.szTemplatePrimaryGroup, NULL, NULL, FLAG_ADVANCED}, + {"template homedir", P_STRING, P_GLOBAL, &Globals.szTemplateHomedir, NULL, NULL, FLAG_ADVANCED}, + {"template shell", P_STRING, P_GLOBAL, &Globals.szTemplateShell, NULL, NULL, FLAG_ADVANCED}, + {"winbind separator", P_STRING, P_GLOBAL, &Globals.szWinbindSeparator, NULL, NULL, FLAG_ADVANCED}, + {"winbind cache time", P_INTEGER, P_GLOBAL, &Globals.winbind_cache_time, NULL, NULL, FLAG_ADVANCED}, + {"winbind enable local accounts", P_BOOL, P_GLOBAL, &Globals.bWinbindEnableLocalAccounts, NULL, NULL, FLAG_ADVANCED}, + {"winbind enum users", P_BOOL, P_GLOBAL, &Globals.bWinbindEnumUsers, NULL, NULL, FLAG_ADVANCED}, + {"winbind enum groups", P_BOOL, P_GLOBAL, &Globals.bWinbindEnumGroups, NULL, NULL, FLAG_ADVANCED}, + {"winbind use default domain", P_BOOL, P_GLOBAL, &Globals.bWinbindUseDefaultDomain, NULL, NULL, FLAG_ADVANCED}, + {"winbind trusted domains only", P_BOOL, P_GLOBAL, &Globals.bWinbindTrustedDomainsOnly, NULL, NULL, FLAG_ADVANCED}, + + {NULL, P_BOOL, P_NONE, NULL, NULL, NULL, 0} }; /*************************************************************************** @@ -1860,7 +1868,7 @@ 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) -FN_LOCAL_BOOL(lp_use_sendfile, bUseSendfile) +FN_LOCAL_BOOL(_lp_use_sendfile, bUseSendfile) FN_LOCAL_BOOL(lp_profile_acls, bProfileAcls) FN_LOCAL_BOOL(lp_map_acl_inherit, bMap_acl_inherit) FN_LOCAL_INTEGER(lp_create_mask, iCreate_mask) @@ -1885,7 +1893,8 @@ FN_GLOBAL_INTEGER(lp_winbind_cache_time, &Globals.winbind_cache_time) FN_GLOBAL_BOOL(lp_hide_local_users, &Globals.bHideLocalUsers) FN_GLOBAL_INTEGER(lp_algorithmic_rid_base, &Globals.AlgorithmicRidBase) FN_GLOBAL_INTEGER(lp_name_cache_timeout, &Globals.name_cache_timeout) -FN_GLOBAL_BOOL(lp_client_signing, &Globals.client_signing) +FN_GLOBAL_INTEGER(lp_client_signing, &Globals.client_signing) +FN_GLOBAL_INTEGER(lp_server_signing, &Globals.server_signing) /* local prototypes */ @@ -4286,3 +4295,12 @@ int lp_maxprintjobs(int snum) return maxjobs; } + +/******************************************************************* + Ensure we don't use sendfile if server smb signing is active. +********************************************************************/ + +BOOL lp_use_sendfile(int snum) +{ + return (_lp_use_sendfile(snum) && !srv_is_signing_active()); +} diff --git a/source3/passdb/passdb.c b/source3/passdb/passdb.c index 9a99e07d82..e440e064ef 100644 --- a/source3/passdb/passdb.c +++ b/source3/passdb/passdb.c @@ -1056,7 +1056,7 @@ DOM_SID *local_uid_to_sid(DOM_SID *psid, uid_t uid) unix_pw = sys_getpwuid( uid ); if ( !unix_pw ) { - DEBUG(4,("local_uid_to_sid: host has know idea of uid %d\n", uid)); + DEBUG(4,("local_uid_to_sid: host has know idea of uid %lu\n", (unsigned long)uid)); return NULL; } @@ -1072,8 +1072,8 @@ DOM_SID *local_uid_to_sid(DOM_SID *psid, uid_t uid) if ( ret ) sid_copy( psid, pdb_get_user_sid(sampw) ); else { - DEBUG(4,("local_uid_to_sid: User %s [uid == %d] has no samba account\n", - unix_pw->pw_name, uid)); + DEBUG(4,("local_uid_to_sid: User %s [uid == %lu] has no samba account\n", + unix_pw->pw_name, (unsigned long)uid)); if ( !lp_enable_rid_algorithm() ) return NULL; @@ -1667,8 +1667,8 @@ uint32 init_buffer_from_sam (uint8 **buf, const SAM_ACCOUNT *sampass, BOOL size_ /* check to make sure we got it correct */ if (buflen != len) { - DEBUG(0, ("init_buffer_from_sam: somthing odd is going on here: bufflen (%d) != len (%d) in tdb_pack operations!\n", - buflen, len)); + DEBUG(0, ("init_buffer_from_sam: somthing odd is going on here: bufflen (%lu) != len (%lu) in tdb_pack operations!\n", + (unsigned long)buflen, (unsigned long)len)); /* error */ SAFE_FREE (*buf); return (-1); diff --git a/source3/passdb/pdb_get_set.c b/source3/passdb/pdb_get_set.c index ba07a4e01c..1505458551 100644 --- a/source3/passdb/pdb_get_set.c +++ b/source3/passdb/pdb_get_set.c @@ -1027,9 +1027,18 @@ BOOL pdb_set_backend_private_data (SAM_ACCOUNT *sampass, void *private_data, if (!sampass) return False; +#if 0 + /* With this check backend_private_data_free_fn is *never* set + as the methods are never set anywhere. What is this + supposed to do ???? + + Volker + */ + /* does this backend 'own' this SAM_ACCOUNT? */ if (my_methods != sampass->private.backend_private_methods) return False; +#endif if (sampass->private.backend_private_data && sampass->private.backend_private_data_free_fn) { sampass->private.backend_private_data_free_fn(&sampass->private.backend_private_data); diff --git a/source3/passdb/pdb_ldap.c b/source3/passdb/pdb_ldap.c index a4ee4dbd4b..aee6495759 100644 --- a/source3/passdb/pdb_ldap.c +++ b/source3/passdb/pdb_ldap.c @@ -104,7 +104,7 @@ struct ldapsam_privates { static void private_data_free_fn(void **result) { - ldap_memfree(*result); + ldap_msgfree(*result); *result = NULL; } @@ -161,10 +161,10 @@ static const char* get_objclass_filter( int schema_ver ) switch( schema_ver ) { case SCHEMAVER_SAMBAACCOUNT: - snprintf( objclass_filter, sizeof(objclass_filter)-1, "(objectclass=%s)", LDAP_OBJ_SAMBAACCOUNT ); + fstr_sprintf( objclass_filter, "(objectclass=%s)", LDAP_OBJ_SAMBAACCOUNT ); break; case SCHEMAVER_SAMBASAMACCOUNT: - snprintf( objclass_filter, sizeof(objclass_filter)-1, "(objectclass=%s)", LDAP_OBJ_SAMBASAMACCOUNT ); + fstr_sprintf( objclass_filter, "(objectclass=%s)", LDAP_OBJ_SAMBASAMACCOUNT ); break; default: DEBUG(0,("pdb_ldapsam: get_objclass_filter(): Invalid schema version specified!\n")); @@ -192,7 +192,7 @@ static int ldapsam_search_suffix_by_name (struct ldapsam_privates *ldap_state, * in the filter expression, replace %u with the real name * so in ldap filter, %u MUST exist :-) */ - snprintf(filter, sizeof(filter)-1, "(&%s%s)", lp_ldap_filter(), + pstr_sprintf(filter, "(&%s%s)", lp_ldap_filter(), get_objclass_filter(ldap_state->schema_ver)); /* @@ -217,7 +217,7 @@ static int ldapsam_search_suffix_by_rid (struct ldapsam_privates *ldap_state, pstring filter; int rc; - snprintf(filter, sizeof(filter)-1, "(&(rid=%i)%s)", rid, + pstr_sprintf(filter, "(&(rid=%i)%s)", rid, get_objclass_filter(ldap_state->schema_ver)); rc = smbldap_search_suffix(ldap_state->smbldap_state, filter, attr, result); @@ -236,7 +236,7 @@ static int ldapsam_search_suffix_by_sid (struct ldapsam_privates *ldap_state, int rc; fstring sid_string; - snprintf(filter, sizeof(filter)-1, "(&(%s=%s)%s)", + pstr_sprintf(filter, "(&(%s=%s)%s)", get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID), sid_to_string(sid_string, sid), get_objclass_filter(ldap_state->schema_ver)); @@ -956,7 +956,7 @@ static NTSTATUS ldapsam_setsampwent(struct pdb_methods *my_methods, BOOL update) pstring filter; char **attr_list; - snprintf( filter, sizeof(filter)-1, "(&%s%s)", lp_ldap_filter(), + pstr_sprintf( filter, "(&%s%s)", lp_ldap_filter(), get_objclass_filter(ldap_state->schema_ver)); all_string_sub(filter, "%u", "*", sizeof(pstring)); @@ -1162,7 +1162,7 @@ static NTSTATUS ldapsam_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUNT } /******************************************************************** -Do the actual modification - also change a plaittext passord if +Do the actual modification - also change a plaintext passord if it it set. **********************************************************************/ @@ -1377,6 +1377,7 @@ static NTSTATUS ldapsam_update_sam_account(struct pdb_methods *my_methods, SAM_A if (!init_ldap_from_sam(ldap_state, entry, &mods, newpwd, element_is_changed)) { DEBUG(0, ("ldapsam_update_sam_account: init_ldap_from_sam failed!\n")); + ldap_memfree(dn); return NT_STATUS_UNSUCCESSFUL; } @@ -1384,11 +1385,13 @@ static NTSTATUS ldapsam_update_sam_account(struct pdb_methods *my_methods, SAM_A DEBUG(4,("mods is empty: nothing to update for user: %s\n", pdb_get_username(newpwd))); ldap_mods_free(mods, True); + ldap_memfree(dn); return NT_STATUS_OK; } ret = ldapsam_modify_entry(my_methods,newpwd,dn,mods,LDAP_MOD_REPLACE, element_is_changed); ldap_mods_free(mods,True); + ldap_memfree(dn); if (!NT_STATUS_IS_OK(ret)) { char *ld_error = NULL; @@ -1516,7 +1519,7 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCO /* There might be a SID for this account already - say an idmap entry */ - snprintf(filter, sizeof(filter)-1, "(&(%s=%s)(|(objectClass=%s)(objectClass=%s)))", + pstr_sprintf(filter, "(&(%s=%s)(|(objectClass=%s)(objectClass=%s)))", get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID), sid_to_string(sid_string, sid), LDAP_OBJ_IDMAP_ENTRY, @@ -1698,7 +1701,7 @@ static BOOL init_group_from_ldap(struct ldapsam_privates *ldap_state, get_attr_key2string( groupmap_attr_list, LDAP_ATTR_CN), temp)) { DEBUG(0, ("Attributes cn not found either " - "for gidNumber(%i)\n",map->gid)); + "for gidNumber(%lu)\n",(unsigned long)map->gid)); return False; } } @@ -1734,7 +1737,7 @@ static BOOL init_ldap_from_group(LDAP *ldap_struct, sid_to_string(tmp, &map->sid); smbldap_make_mod(ldap_struct, existing, mods, get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GROUP_SID), tmp); - snprintf(tmp, sizeof(tmp)-1, "%i", map->sid_name_use); + pstr_sprintf(tmp, "%i", map->sid_name_use); smbldap_make_mod(ldap_struct, existing, mods, get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GROUP_TYPE), tmp); @@ -1805,7 +1808,7 @@ static NTSTATUS ldapsam_getgrsid(struct pdb_methods *methods, GROUP_MAP *map, { pstring filter; - snprintf(filter, sizeof(filter)-1, "(&(objectClass=%s)(%s=%s))", + pstr_sprintf(filter, "(&(objectClass=%s)(%s=%s))", LDAP_OBJ_GROUPMAP, get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GROUP_SID), sid_string_static(&sid)); @@ -1821,10 +1824,10 @@ static NTSTATUS ldapsam_getgrgid(struct pdb_methods *methods, GROUP_MAP *map, { pstring filter; - snprintf(filter, sizeof(filter)-1, "(&(objectClass=%s)(%s=%d))", + pstr_sprintf(filter, "(&(objectClass=%s)(%s=%lu))", LDAP_OBJ_GROUPMAP, get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GIDNUMBER), - gid); + (unsigned long)gid); return ldapsam_getgroup(methods, filter, map); } @@ -1842,7 +1845,7 @@ static NTSTATUS ldapsam_getgrnam(struct pdb_methods *methods, GROUP_MAP *map, return NT_STATUS_NO_MEMORY; } - snprintf(filter, sizeof(filter)-1, "(&(objectClass=%s)(|(%s=%s)(%s=%s)))", + pstr_sprintf(filter, "(&(objectClass=%s)(|(%s=%s)(%s=%s)))", LDAP_OBJ_GROUPMAP, get_attr_key2string(groupmap_attr_list, LDAP_ATTR_DISPLAY_NAME), escape_name, get_attr_key2string(groupmap_attr_list, LDAP_ATTR_CN), escape_name); @@ -1861,10 +1864,10 @@ static int ldapsam_search_one_group_by_gid(struct ldapsam_privates *ldap_state, { pstring filter; - snprintf(filter, sizeof(filter)-1, "(&(objectClass=%s)(%s=%i))", + pstr_sprintf(filter, "(&(objectClass=%s)(%s=%lu))", LDAP_OBJ_POSIXGROUP, get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GIDNUMBER), - gid); + (unsigned long)gid); return ldapsam_search_one_group(ldap_state, filter, result); } @@ -1891,23 +1894,26 @@ static NTSTATUS ldapsam_add_group_mapping_entry(struct pdb_methods *methods, if (NT_STATUS_IS_OK(ldapsam_getgrgid(methods, &dummy, map->gid))) { - DEBUG(0, ("Group %i already exists in LDAP\n", map->gid)); + DEBUG(0, ("Group %ld already exists in LDAP\n", (unsigned long)map->gid)); return NT_STATUS_UNSUCCESSFUL; } rc = ldapsam_search_one_group_by_gid(ldap_state, map->gid, &result); if (rc != LDAP_SUCCESS) { + ldap_msgfree(result); return NT_STATUS_UNSUCCESSFUL; } count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result); - if ( count == 0 ) + if ( count == 0 ) { + ldap_msgfree(result); return NT_STATUS_UNSUCCESSFUL; + } if (count > 1) { - DEBUG(2, ("Group %i must exist exactly once in LDAP\n", - map->gid)); + DEBUG(2, ("Group %lu must exist exactly once in LDAP\n", + (unsigned long)map->gid)); ldap_msgfree(result); return NT_STATUS_UNSUCCESSFUL; } @@ -1941,13 +1947,13 @@ static NTSTATUS ldapsam_add_group_mapping_entry(struct pdb_methods *methods, char *ld_error = NULL; ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error); - DEBUG(0, ("failed to add group %i error: %s (%s)\n", map->gid, + DEBUG(0, ("failed to add group %lu error: %s (%s)\n", (unsigned long)map->gid, ld_error ? ld_error : "(unknown)", ldap_err2string(rc))); SAFE_FREE(ld_error); return NT_STATUS_UNSUCCESSFUL; } - DEBUG(2, ("successfully modified group %i in LDAP\n", map->gid)); + DEBUG(2, ("successfully modified group %lu in LDAP\n", (unsigned long)map->gid)); return NT_STATUS_OK; } @@ -2002,12 +2008,12 @@ static NTSTATUS ldapsam_update_group_mapping_entry(struct pdb_methods *methods, char *ld_error = NULL; ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error); - DEBUG(0, ("failed to modify group %i error: %s (%s)\n", map->gid, + DEBUG(0, ("failed to modify group %lu error: %s (%s)\n", (unsigned long)map->gid, ld_error ? ld_error : "(unknown)", ldap_err2string(rc))); SAFE_FREE(ld_error); } - DEBUG(2, ("successfully modified group %i in LDAP\n", map->gid)); + DEBUG(2, ("successfully modified group %lu in LDAP\n", (unsigned long)map->gid)); return NT_STATUS_OK; } @@ -2026,7 +2032,7 @@ static NTSTATUS ldapsam_delete_group_mapping_entry(struct pdb_methods *methods, sid_to_string(sidstring, &sid); - snprintf(filter, sizeof(filter)-1, "(&(objectClass=%s)(%s=%s))", + pstr_sprintf(filter, "(&(objectClass=%s)(%s=%s))", LDAP_OBJ_GROUPMAP, LDAP_ATTRIBUTE_SID, sidstring); rc = ldapsam_search_one_group(ldap_state, filter, &result); @@ -2054,7 +2060,7 @@ static NTSTATUS ldapsam_setsamgrent(struct pdb_methods *my_methods, BOOL update) int rc; char **attr_list; - snprintf( filter, sizeof(filter)-1, "(objectclass=%s)", LDAP_OBJ_GROUPMAP); + pstr_sprintf( filter, "(objectclass=%s)", LDAP_OBJ_GROUPMAP); attr_list = get_attr_list( groupmap_attr_list ); rc = smbldap_search(ldap_state->smbldap_state, lp_ldap_group_suffix(), LDAP_SCOPE_SUBTREE, filter, diff --git a/source3/passdb/pdb_smbpasswd.c b/source3/passdb/pdb_smbpasswd.c index 055e8e71ba..8171b65adc 100644 --- a/source3/passdb/pdb_smbpasswd.c +++ b/source3/passdb/pdb_smbpasswd.c @@ -179,8 +179,25 @@ static FILE *startsmbfilepwent(const char *pfile, enum pwf_access_type type, int DEBUG(10, ("startsmbfilepwent_internal: opening file %s\n", pfile)); if((fp = sys_fopen(pfile, open_mode)) == NULL) { - DEBUG(0, ("startsmbfilepwent_internal: unable to open file %s. Error was %s\n", pfile, strerror(errno) )); - return NULL; + + /* + * If smbpasswd file doesn't exist, then create new one. This helps to avoid + * confusing error msg when adding user account first time. + */ + if (errno == ENOENT) { + if ((fp = sys_fopen(pfile, "a+")) != NULL) { + DEBUG(0, ("startsmbfilepwent_internal: file %s did not exist. File successfully created.\n", pfile)); + + } else { + DEBUG(0, ("startsmbfilepwent_internal: file %s did not exist. Couldn't create new one. Error was: %s", + pfile, strerror(errno))); + return NULL; + } + + } else { + DEBUG(0, ("startsmbfilepwent_internal: unable to open file %s. Error was: %s\n", pfile, strerror(errno))); + return NULL; + } } if (!pw_file_lock(fileno(fp), lock_type, 5, lock_depth)) { diff --git a/source3/passdb/pdb_tdb.c b/source3/passdb/pdb_tdb.c index 1078a5bd26..7c2156455a 100644 --- a/source3/passdb/pdb_tdb.c +++ b/source3/passdb/pdb_tdb.c @@ -180,6 +180,24 @@ static NTSTATUS tdbsam_getsampwnam (struct pdb_methods *my_methods, SAM_ACCOUNT /* open the accounts TDB */ if (!(pwd_tdb = tdb_open_log(tdb_state->tdbsam_location, 0, TDB_DEFAULT, O_RDONLY, 0600))) { + + if (errno == ENOENT) { + /* + * TDB file doesn't exist, so try to create new one. This is useful to avoid + * confusing error msg when adding user account first time + */ + if (!(pwd_tdb = tdb_open_log(tdb_state->tdbsam_location, 0, TDB_DEFAULT, O_CREAT, 0600))) { + DEBUG(0, ("pdb_getsampwnam: TDB passwd (%s) did not exist. File successfully created.\n", + tdb_state->tdbsam_location)); + } else { + DEBUG(0, ("pdb_getsampwnam: TDB passwd (%s) does not exist. Couldn't create new one. Error was: %s\n", + tdb_state->tdbsam_location, strerror(errno))); + } + + /* requested user isn't there anyway */ + nt_status = NT_STATUS_NO_SUCH_USER; + return nt_status; + } DEBUG(0, ("pdb_getsampwnam: Unable to open TDB passwd (%s)!\n", tdb_state->tdbsam_location)); return nt_status; } @@ -419,49 +437,6 @@ done: return (ret); } -#if 0 -/*************************************************************************** - Allocates a new RID and returns it to the caller as a domain sid - - NOTE: Use carefullt, do not waste RIDs they are a limited resource! - - SSS - ***************************************************************************/ - -static NTSTATUS tdbsam_get_next_sid (struct pdb_methods *my_methods, DOM_SID *sid) -{ - NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; - struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)my_methods->private_data; - TDB_CONTEXT *pwd_tdb; - uint32 rid; - - if (sid == NULL) { - return NT_STATUS_INVALID_PARAMETER; - } - - pwd_tdb = tdb_open_log(tdb_state->tdbsam_location, 0, TDB_DEFAULT, O_RDWR | O_CREAT, 0600); - if (!pwd_tdb) - { - DEBUG(0, ("tdbsam_get_next_sid: Unable to open TDB passwd (%s)!\n", tdb_state->tdbsam_location)); - return NT_STATUS_UNSUCCESSFUL; - } - - rid = BASE_RID; - if (tdb_change_uint32_atomic(pwd_tdb, "RID_COUNTER", &rid, 1)) { - - sid_copy(sid, get_global_sam_sid()); - if (!sid_append_rid(sid, rid)) { - goto done; - } - - ret = NT_STATUS_OK; - } - -done: - tdb_close (pwd_tdb); - return ret; -} -#endif - /*************************************************************************** Modifies an existing SAM_ACCOUNT ****************************************************************************/ diff --git a/source3/passdb/secrets.c b/source3/passdb/secrets.c index bad8e96865..23413e4026 100644 --- a/source3/passdb/secrets.c +++ b/source3/passdb/secrets.c @@ -195,11 +195,11 @@ const char *trust_keystr(const char *domain) * * @return stored password's key **/ -char *trustdom_keystr(const char *domain) +static char *trustdom_keystr(const char *domain) { - static char* keystr; + static pstring keystr; - asprintf(&keystr, "%s/%s", SECRETS_DOMTRUST_ACCT_PASS, domain); + pstr_sprintf(keystr, "%s/%s", SECRETS_DOMTRUST_ACCT_PASS, domain); strupper_m(keystr); return keystr; diff --git a/source3/printing/notify.c b/source3/printing/notify.c index 479d883134..e2146d5018 100644 --- a/source3/printing/notify.c +++ b/source3/printing/notify.c @@ -164,8 +164,8 @@ static void print_notify_send_messages_to_printer(const char *printer, unsigned } } - DEBUG(5, ("print_notify_send_messages_to_printer: sending %d print notify message%s to printer %s\n", - msg_count, msg_count != 1 ? "s" : "", printer)); + DEBUG(5, ("print_notify_send_messages_to_printer: sending %lu print notify message%s to printer %s\n", + (unsigned long)msg_count, msg_count != 1 ? "s" : "", printer)); /* * Get the list of PID's to send to. @@ -272,8 +272,8 @@ in notify_queue\n", msg->type, msg->field, msg->printer)); /* allocate a new msg structure and copy the fields */ if ( !(pnqueue->msg = (SPOOLSS_NOTIFY_MSG*)talloc(send_ctx, sizeof(SPOOLSS_NOTIFY_MSG))) ) { - DEBUG(0,("send_spoolss_notify2_msg: talloc() of size [%d] failed!\n", - sizeof(SPOOLSS_NOTIFY_MSG))); + DEBUG(0,("send_spoolss_notify2_msg: talloc() of size [%lu] failed!\n", + (unsigned long)sizeof(SPOOLSS_NOTIFY_MSG))); return; } copy_notify2_msg(pnqueue->msg, msg); diff --git a/source3/printing/pcap.c b/source3/printing/pcap.c index 1bdbf4a789..a5fb53a320 100644 --- a/source3/printing/pcap.c +++ b/source3/printing/pcap.c @@ -208,7 +208,7 @@ static BOOL ScanQconfig(char *psz,char *pszPrintername) /* probably a good printer ??? */ free (line); SAFE_FREE(pName); - fclose(pfile); + x_fclose(pfile); return(True); } @@ -222,7 +222,7 @@ static BOOL ScanQconfig(char *psz,char *pszPrintername) /* it's a good virtual printer */ free (line); SAFE_FREE(pName); - fclose(pfile); + x_fclose(pfile); return(True); } break; diff --git a/source3/python/py_common.c b/source3/python/py_common.c index ea092d9370..02d22bbdab 100644 --- a/source3/python/py_common.c +++ b/source3/python/py_common.c @@ -223,7 +223,7 @@ struct cli_state *open_pipe_creds(char *server, PyObject *creds, result = cli_full_connection( &cli, NULL, server, NULL, 0, "IPC$", "IPC", - username, domain, password, 0, NULL); + username, domain, password, 0, Undefined, NULL); if (!NT_STATUS_IS_OK(result)) { *errstr = strdup("error connecting to IPC$ pipe"); diff --git a/source3/python/py_lsa.c b/source3/python/py_lsa.c index c063dcba81..4204f43f7b 100644 --- a/source3/python/py_lsa.c +++ b/source3/python/py_lsa.c @@ -213,6 +213,7 @@ static PyObject *lsa_lookup_sids(PyObject *self, PyObject *args, char **domains, **names; uint32 *types; lsa_policy_hnd_object *hnd = (lsa_policy_hnd_object *)self; + TALLOC_CTX *mem_ctx = NULL; DOM_SID *sids; if (!PyArg_ParseTuple(args, "O", &py_sids)) @@ -223,12 +224,17 @@ static PyObject *lsa_lookup_sids(PyObject *self, PyObject *args, return NULL; } + if (!(mem_ctx = talloc_init("lsa_open_policy"))) { + PyErr_SetString(lsa_error, "unable to init talloc context\n"); + goto done; + } + if (PyList_Check(py_sids)) { /* Convert dictionary to char ** array */ num_sids = PyList_Size(py_sids); - sids = (DOM_SID *)talloc(hnd->mem_ctx, num_sids * sizeof(DOM_SID)); + sids = (DOM_SID *)talloc(mem_ctx, num_sids * sizeof(DOM_SID)); memset(sids, 0, num_sids * sizeof(DOM_SID)); @@ -237,7 +243,8 @@ static PyObject *lsa_lookup_sids(PyObject *self, PyObject *args, if (!string_to_sid(&sids[i], PyString_AsString(obj))) { PyErr_SetString(PyExc_ValueError, "string_to_sid failed"); - return NULL; + result = NULL; + goto done; } } @@ -246,21 +253,23 @@ static PyObject *lsa_lookup_sids(PyObject *self, PyObject *args, /* Just a single element */ num_sids = 1; - sids = (DOM_SID *)talloc(hnd->mem_ctx, sizeof(DOM_SID)); + sids = (DOM_SID *)talloc(mem_ctx, sizeof(DOM_SID)); if (!string_to_sid(&sids[0], PyString_AsString(py_sids))) { PyErr_SetString(PyExc_ValueError, "string_to_sid failed"); - return NULL; + result = NULL; + goto done; } } - ntstatus = cli_lsa_lookup_sids(hnd->cli, hnd->mem_ctx, &hnd->pol, + ntstatus = cli_lsa_lookup_sids(hnd->cli, mem_ctx, &hnd->pol, num_sids, sids, &domains, &names, &types); if (!NT_STATUS_IS_OK(ntstatus)) { PyErr_SetObject(lsa_ntstatus, py_ntstatus_tuple(ntstatus)); - return NULL; + result = NULL; + goto done; } result = PyList_New(num_sids); @@ -274,7 +283,11 @@ static PyObject *lsa_lookup_sids(PyObject *self, PyObject *args, PyList_SetItem(result, i, obj); } - + + done: + if (mem_ctx) + talloc_destroy(mem_ctx); + return result; } diff --git a/source3/python/py_ntsec.c b/source3/python/py_ntsec.c index 47524d8e19..3d408e0bda 100644 --- a/source3/python/py_ntsec.c +++ b/source3/python/py_ntsec.c @@ -58,14 +58,14 @@ BOOL py_from_ACE(PyObject **dict, SEC_ACE *ace) return True; } - *dict = PyDict_New(); - - PyDict_SetItemString(*dict, "type", PyInt_FromLong(ace->type)); - PyDict_SetItemString(*dict, "flags", PyInt_FromLong(ace->flags)); - PyDict_SetItemString(*dict, "mask", PyInt_FromLong(ace->info.mask)); + *dict = Py_BuildValue("{sisisi}", "type", ace->type, + "flags", ace->flags, + "mask", ace->info.mask); - if (py_from_SID(&obj, &ace->trustee)) + if (py_from_SID(&obj, &ace->trustee)) { PyDict_SetItemString(*dict, "trustee", obj); + Py_DECREF(obj); + } return True; } @@ -125,10 +125,6 @@ BOOL py_from_ACL(PyObject **dict, SEC_ACL *acl) return True; } - *dict = PyDict_New(); - - PyDict_SetItemString(*dict, "revision", PyInt_FromLong(acl->revision)); - ace_list = PyList_New(acl->num_aces); for (i = 0; i < acl->num_aces; i++) { @@ -138,7 +134,8 @@ BOOL py_from_ACL(PyObject **dict, SEC_ACL *acl) PyList_SetItem(ace_list, i, obj); } - PyDict_SetItemString(*dict, "ace_list", ace_list); + *dict = Py_BuildValue("{sisN}", "revision", acl->revision, + "ace_list", ace_list); return True; } @@ -181,19 +178,29 @@ BOOL py_from_SECDESC(PyObject **dict, SEC_DESC *sd) *dict = PyDict_New(); - PyDict_SetItemString(*dict, "revision", PyInt_FromLong(sd->revision)); + obj = PyInt_FromLong(sd->revision); + PyDict_SetItemString(*dict, "revision", obj); + Py_DECREF(obj); - if (py_from_SID(&obj, sd->owner_sid)) + if (py_from_SID(&obj, sd->owner_sid)) { PyDict_SetItemString(*dict, "owner_sid", obj); + Py_DECREF(obj); + } - if (py_from_SID(&obj, sd->grp_sid)) + if (py_from_SID(&obj, sd->grp_sid)) { PyDict_SetItemString(*dict, "group_sid", obj); + Py_DECREF(obj); + } - if (py_from_ACL(&obj, sd->dacl)) + if (py_from_ACL(&obj, sd->dacl)) { PyDict_SetItemString(*dict, "dacl", obj); + Py_DECREF(obj); + } - if (py_from_ACL(&obj, sd->sacl)) + if (py_from_ACL(&obj, sd->sacl)) { PyDict_SetItemString(*dict, "sacl", obj); + Py_DECREF(obj); + } return True; } diff --git a/source3/python/py_smb.c b/source3/python/py_smb.c index d37b73cceb..bb84a337c9 100644 --- a/source3/python/py_smb.c +++ b/source3/python/py_smb.c @@ -238,7 +238,8 @@ static PyObject *py_smb_query_secdesc(PyObject *self, PyObject *args, if (cli_is_error(cli->cli)) { PyErr_SetString(PyExc_RuntimeError, "query_secdesc failed"); - return NULL; + result = NULL; + goto done; } if (!secdesc) { @@ -342,11 +343,48 @@ static PyMethodDef smb_methods[] = { { "connect", (PyCFunction)py_smb_connect, METH_VARARGS | METH_KEYWORDS, "Connect to a host" }, + /* Other stuff - this should really go into a samba config module + but for the moment let's leave it here. */ + + { "setup_logging", (PyCFunction)py_setup_logging, + METH_VARARGS | METH_KEYWORDS, + "Set up debug logging.\n" +"\n" +"Initialises Samba's debug logging system. One argument is expected which\n" +"is a boolean specifying whether debugging is interactive and sent to stdout\n" +"or logged to a file.\n" +"\n" +"Example:\n" +"\n" +">>> smb.setup_logging(interactive = 1)" }, + + { "get_debuglevel", (PyCFunction)get_debuglevel, + METH_VARARGS, + "Set the current debug level.\n" +"\n" +"Example:\n" +"\n" +">>> smb.get_debuglevel()\n" +"0" }, + + { "set_debuglevel", (PyCFunction)set_debuglevel, + METH_VARARGS, + "Get the current debug level.\n" +"\n" +"Example:\n" +"\n" +">>> smb.set_debuglevel(10)" }, + { NULL } }; static void py_cli_state_dealloc(PyObject* self) { + cli_state_object *cli = (cli_state_object *)self; + + if (cli->cli) + cli_shutdown(cli->cli); + PyObject_Del(self); } @@ -395,5 +433,5 @@ void initsmb(void) py_samba_init(); setup_logging("smb", True); - DEBUGLEVEL = 10; + DEBUGLEVEL = 3; } diff --git a/source3/python/py_winbind.c b/source3/python/py_winbind.c index db66be2321..ebceb95d71 100644 --- a/source3/python/py_winbind.c +++ b/source3/python/py_winbind.c @@ -259,14 +259,14 @@ static PyObject *py_config_dict(void) PyDict_SetItemString(result, "template_shell", PyString_FromString(lp_template_shell())); - /* Winbind uid/gid range */ + /* idmap uid/gid range */ - if (lp_winbind_uid(&ulow, &uhi)) { + if (lp_idmap_uid(&ulow, &uhi)) { PyDict_SetItemString(result, "uid_low", PyInt_FromLong(ulow)); PyDict_SetItemString(result, "uid_high", PyInt_FromLong(uhi)); } - if (lp_winbind_gid(&glow, &ghi)) { + if (lp_idmap_gid(&glow, &ghi)) { PyDict_SetItemString(result, "gid_low", PyInt_FromLong(glow)); PyDict_SetItemString(result, "gid_high", PyInt_FromLong(ghi)); } diff --git a/source3/rpc_client/cli_ds.c b/source3/rpc_client/cli_ds.c index f0edeca000..a7a093328c 100644 --- a/source3/rpc_client/cli_ds.c +++ b/source3/rpc_client/cli_ds.c @@ -22,6 +22,10 @@ /* implementations of client side DsXXX() functions */ +/******************************************************************** + Get information about the server and directory services +********************************************************************/ + NTSTATUS cli_ds_getprimarydominfo(struct cli_state *cli, TALLOC_CTX *mem_ctx, uint16 level, DS_DOMINFO_CTR *ctr) { @@ -40,7 +44,7 @@ NTSTATUS cli_ds_getprimarydominfo(struct cli_state *cli, TALLOC_CTX *mem_ctx, q.level = level; - if (!ds_io_q_getprimdominfo("", &q, &qbuf, 0) + if (!ds_io_q_getprimdominfo("", &qbuf, 0, &q) || !rpc_api_pipe_req(cli, DS_GETPRIMDOMINFO, &qbuf, &rbuf)) { result = NT_STATUS_UNSUCCESSFUL; goto done; @@ -48,7 +52,7 @@ NTSTATUS cli_ds_getprimarydominfo(struct cli_state *cli, TALLOC_CTX *mem_ctx, /* Unmarshall response */ - if (!ds_io_r_getprimdominfo("", &r, &rbuf, 0)) { + if (!ds_io_r_getprimdominfo("", &rbuf, 0, &r)) { result = NT_STATUS_UNSUCCESSFUL; goto done; } @@ -71,3 +75,63 @@ done: return result; } + +/******************************************************************** + Enumerate trusted domains in an AD forest +********************************************************************/ + +NTSTATUS cli_ds_enum_domain_trusts(struct cli_state *cli, TALLOC_CTX *mem_ctx, + const char *server, uint32 flags, + DS_DOMAIN_TRUSTS **trusts, uint32 *num_domains) +{ + prs_struct qbuf, rbuf; + DS_Q_ENUM_DOM_TRUSTS q; + DS_R_ENUM_DOM_TRUSTS r; + NTSTATUS result; + + 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); + + init_q_ds_enum_domain_trusts( &q, server, flags ); + + if (!ds_io_q_enum_domain_trusts("", &qbuf, 0, &q) + || !rpc_api_pipe_req(cli, DS_ENUM_DOM_TRUSTS, &qbuf, &rbuf)) { + result = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + /* Unmarshall response */ + + if (!ds_io_r_enum_domain_trusts("", &rbuf, 0, &r)) { + result = NT_STATUS_UNSUCCESSFUL; + goto done; + } + + result = r.status; + + if ( NT_STATUS_IS_OK(result) ) { + int i; + + *num_domains = r.num_domains; + *trusts = (DS_DOMAIN_TRUSTS*)smb_xmalloc(r.num_domains*sizeof(DS_DOMAIN_TRUSTS)); + + memcpy( *trusts, r.domains.trusts, r.num_domains*sizeof(DS_DOMAIN_TRUSTS) ); + for ( i=0; ipipe_auth_flags & AUTH_PIPE_NETSEC) { + } else if (cli->pipe_auth_flags & AUTH_PIPE_NETSEC) { RPC_AUTH_NETSEC_NEG netsec_neg; /* Use lp_workgroup() if domain not specified */ - if (!domain || !domain[0]) + if (!domain || !domain[0]) { + DEBUG(10,("create_rpc_bind_req: no domain; assuming my own\n")); domain = lp_workgroup(); + } init_rpc_auth_netsec_neg(&netsec_neg, domain, my_name); @@ -715,7 +717,8 @@ static NTSTATUS create_rpc_bind_req(struct cli_state *cli, prs_struct *rpc_out, /* Auth len in the rpc header doesn't include auth_header. */ auth_len = prs_offset(&auth_info) - saved_hdr_offset; } - /* create the request RPC_HDR */ + + /* Create the request RPC_HDR */ init_rpc_hdr(&hdr, RPC_BIND, 0x3, rpc_call_id, RPC_HEADER_LEN + RPC_HDR_RB_LEN + prs_offset(&auth_info), auth_len); @@ -1021,11 +1024,6 @@ BOOL rpc_api_pipe_req(struct cli_state *cli, uint8 op_num, static const uchar netsec_sig[8] = NETSEC_SIGNATURE; static const uchar nullbytes[8] = { 0,0,0,0,0,0,0,0 }; size_t parse_offset_marker; - if ((cli->auth_info.seq_num & 1) != 0) { - DEBUG(0,("SCHANNEL ERROR: seq_num must be even in client (seq_num=%d)\n", - cli->auth_info.seq_num)); - } - DEBUG(10,("SCHANNEL seq_num=%d\n", cli->auth_info.seq_num)); init_rpc_auth_netsec_chk(&verf, netsec_sig, nullbytes, @@ -1573,9 +1571,6 @@ NTSTATUS cli_nt_establish_netlogon(struct cli_state *cli, int sec_chan, } } - /* doing schannel, not per-user auth */ - cli->pipe_auth_flags = AUTH_PIPE_NETSEC | AUTH_PIPE_SIGN | AUTH_PIPE_SEAL; - if (!rpc_pipe_bind(cli, PI_NETLOGON, global_myname())) { DEBUG(2,("rpc bind to %s failed\n", PIPE_NETLOGON)); cli_close(cli, cli->nt_pipe_fnum); @@ -1586,6 +1581,57 @@ NTSTATUS cli_nt_establish_netlogon(struct cli_state *cli, int sec_chan, } +NTSTATUS cli_nt_setup_netsec(struct cli_state *cli, int sec_chan, + const uchar trust_password[16]) +{ + NTSTATUS result; + uint32 neg_flags = 0x000001ff; + cli->pipe_auth_flags = 0; + + if (lp_client_schannel() == False) { + return NT_STATUS_OK; + } + + if (!cli_nt_session_open(cli, PI_NETLOGON)) { + DEBUG(0, ("Could not initialise %s\n", + get_pipe_name_from_index(PI_NETLOGON))); + return NT_STATUS_UNSUCCESSFUL; + } + + if (lp_client_schannel() != False) + neg_flags |= NETLOGON_NEG_SCHANNEL; + + neg_flags |= NETLOGON_NEG_SCHANNEL; + + result = cli_nt_setup_creds(cli, sec_chan, trust_password, + &neg_flags, 2); + + if (!(neg_flags & NETLOGON_NEG_SCHANNEL) + && lp_client_schannel() == True) { + DEBUG(1, ("Could not negotiate SCHANNEL with the DC!\n")); + result = NT_STATUS_UNSUCCESSFUL; + } + + if (!NT_STATUS_IS_OK(result)) { + ZERO_STRUCT(cli->auth_info.sess_key); + ZERO_STRUCT(cli->sess_key); + cli->pipe_auth_flags = 0; + cli_nt_session_close(cli); + return result; + } + + memcpy(cli->auth_info.sess_key, cli->sess_key, + sizeof(cli->auth_info.sess_key)); + + cli->saved_netlogon_pipe_fnum = cli->nt_pipe_fnum; + cli->nt_pipe_fnum = 0; + + /* doing schannel, not per-user auth */ + cli->pipe_auth_flags = AUTH_PIPE_NETSEC | AUTH_PIPE_SIGN | AUTH_PIPE_SEAL; + + return NT_STATUS_OK; +} + const char *cli_pipe_get_name(struct cli_state *cli) { return cli->pipe_name; diff --git a/source3/rpc_client/cli_srvsvc.c b/source3/rpc_client/cli_srvsvc.c index 6cd18f2e43..27349b7295 100644 --- a/source3/rpc_client/cli_srvsvc.c +++ b/source3/rpc_client/cli_srvsvc.c @@ -4,7 +4,7 @@ Copyright (C) Andrew Tridgell 1994-2000 Copyright (C) Luke Kenneth Casson Leighton 1996-2000 Copyright (C) Tim Potter 2001 - Copyright (C) Jim McDonough 2002 + Copyright (C) Jim McDonough 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 diff --git a/source3/rpc_parse/parse_ds.c b/source3/rpc_parse/parse_ds.c index ab07631831..f954806036 100644 --- a/source3/rpc_parse/parse_ds.c +++ b/source3/rpc_parse/parse_ds.c @@ -1,7 +1,8 @@ /* * Unix SMB/CIFS implementation. * RPC Pipe client / server routines - * Copyright (C) Gerald Carter 2002 + + * Copyright (C) Gerald Carter 2002-2003 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -20,6 +21,9 @@ #include "includes.h" +/************************************************************************ +************************************************************************/ + static BOOL ds_io_dominfobasic( const char *desc, prs_struct *ps, int depth, DSROLE_PRIMARY_DOMAIN_INFO_BASIC **basic) { DSROLE_PRIMARY_DOMAIN_INFO_BASIC *p = *basic; @@ -68,7 +72,10 @@ static BOOL ds_io_dominfobasic( const char *desc, prs_struct *ps, int depth, DSR } -BOOL ds_io_q_getprimdominfo( const char *desc, DS_Q_GETPRIMDOMINFO *q_u, prs_struct *ps, int depth) +/************************************************************************ +************************************************************************/ + +BOOL ds_io_q_getprimdominfo( const char *desc, prs_struct *ps, int depth, DS_Q_GETPRIMDOMINFO *q_u) { prs_debug(ps, depth, desc, "ds_io_q_getprimdominfo"); depth++; @@ -82,7 +89,10 @@ BOOL ds_io_q_getprimdominfo( const char *desc, DS_Q_GETPRIMDOMINFO *q_u, prs_str return True; } -BOOL ds_io_r_getprimdominfo( const char *desc, DS_R_GETPRIMDOMINFO *r_u, prs_struct *ps, int depth) +/************************************************************************ +************************************************************************/ + +BOOL ds_io_r_getprimdominfo( const char *desc, prs_struct *ps, int depth, DS_R_GETPRIMDOMINFO *r_u) { prs_debug(ps, depth, desc, "ds_io_r_getprimdominfo"); depth++; @@ -120,3 +130,177 @@ BOOL ds_io_r_getprimdominfo( const char *desc, DS_R_GETPRIMDOMINFO *r_u, prs_str return True; } + +/************************************************************************ + initialize a DS_ENUM_DOM_TRUSTS structure +************************************************************************/ + +BOOL init_q_ds_enum_domain_trusts( DS_Q_ENUM_DOM_TRUSTS *q, const char *server, + uint32 flags ) +{ + int len; + + q->flags = flags; + + if ( server && *server ) + q->server_ptr = 1; + else + q->server_ptr = 0; + + len = q->server_ptr ? strlen(server)+1 : 0; + + init_unistr2( &q->server, server, len ); + + return True; +} + +/************************************************************************ +************************************************************************/ + +static BOOL ds_io_domain_trusts( const char *desc, prs_struct *ps, int depth, DS_DOMAIN_TRUSTS *trust) +{ + prs_debug(ps, depth, desc, "ds_io_dom_trusts_ctr"); + depth++; + + if ( !prs_uint32( "netbios_ptr", ps, depth, &trust->netbios_ptr ) ) + return False; + + if ( !prs_uint32( "dns_ptr", ps, depth, &trust->dns_ptr ) ) + return False; + + if ( !prs_uint32( "flags", ps, depth, &trust->flags ) ) + return False; + + if ( !prs_uint32( "parent_index", ps, depth, &trust->parent_index ) ) + return False; + + if ( !prs_uint32( "trust_type", ps, depth, &trust->trust_type ) ) + return False; + + if ( !prs_uint32( "trust_attributes", ps, depth, &trust->trust_attributes ) ) + return False; + + if ( !prs_uint32( "sid_ptr", ps, depth, &trust->sid_ptr ) ) + return False; + + if ( !prs_uint8s(False, "guid", ps, depth, trust->guid.info, GUID_SIZE) ) + return False; + + return True; +} + +/************************************************************************ +************************************************************************/ + +static BOOL ds_io_dom_trusts_ctr( const char *desc, prs_struct *ps, int depth, DS_DOMAIN_TRUSTS_CTR *ctr) +{ + int i; + + prs_debug(ps, depth, desc, "ds_io_dom_trusts_ctr"); + depth++; + + if ( !prs_uint32( "ptr", ps, depth, &ctr->ptr ) ) + return False; + + if ( !prs_uint32( "max_count", ps, depth, &ctr->max_count ) ) + return False; + + /* are we done? */ + + if ( ctr->max_count == 0 ) + return True; + + /* allocate the domain trusts array are parse it */ + + ctr->trusts = (DS_DOMAIN_TRUSTS*)talloc(ps->mem_ctx, sizeof(DS_DOMAIN_TRUSTS)*ctr->max_count); + + if ( !ctr->trusts ) + return False; + + /* this stinks; the static portion o fthe structure is read here and then + we need another loop to read the UNISTR2's and SID's */ + + for ( i=0; imax_count;i++ ) { + if ( !ds_io_domain_trusts("domain_trusts", ps, depth, &ctr->trusts[i] ) ) + return False; + } + + for ( i=0; imax_count; i++ ) { + + if ( !smb_io_unistr2("netbios_domain", &ctr->trusts[i].netbios_domain, ctr->trusts[i].netbios_ptr, ps, depth) ) + return False; + + if(!prs_align(ps)) + return False; + + if ( !smb_io_unistr2("dns_domain", &ctr->trusts[i].dns_domain, ctr->trusts[i].dns_ptr, ps, depth) ) + return False; + + if(!prs_align(ps)) + return False; + + if ( ctr->trusts[i].sid_ptr ) { + if ( !smb_io_dom_sid2("sid", &ctr->trusts[i].sid, ps, depth ) ) + return False; + } + } + + return True; +} + +/************************************************************************ + initialize a DS_ENUM_DOM_TRUSTS request +************************************************************************/ + +BOOL ds_io_q_enum_domain_trusts( const char *desc, prs_struct *ps, int depth, DS_Q_ENUM_DOM_TRUSTS *q_u) +{ + prs_debug(ps, depth, desc, "ds_io_q_enum_domain_trusts"); + depth++; + + if ( !prs_align(ps) ) + return False; + + if ( !prs_uint32( "server_ptr", ps, depth, &q_u->server_ptr ) ) + return False; + + if ( !smb_io_unistr2("server", &q_u->server, q_u->server_ptr, ps, depth) ) + return False; + + if ( !prs_align(ps) ) + return False; + + if ( !prs_uint32( "flags", ps, depth, &q_u->flags ) ) + return False; + + return True; +} + +/************************************************************************ +************************************************************************/ + +BOOL ds_io_r_enum_domain_trusts( const char *desc, prs_struct *ps, int depth, DS_R_ENUM_DOM_TRUSTS *r_u) +{ + prs_debug(ps, depth, desc, "ds_io_r_enum_domain_trusts"); + depth++; + + if(!prs_align(ps)) + return False; + + if ( !prs_uint32( "num_domains", ps, depth, &r_u->num_domains ) ) + return False; + + if ( r_u->num_domains ) { + if ( !ds_io_dom_trusts_ctr("domains", ps, depth, &r_u->domains ) ) + return False; + } + + if(!prs_align(ps)) + return False; + + if ( !prs_ntstatus("status", ps, depth, &r_u->status ) ) + return False; + + return True; +} + + diff --git a/source3/rpc_parse/parse_lsa.c b/source3/rpc_parse/parse_lsa.c index d8c3b4e3c3..07b0da7e9c 100644 --- a/source3/rpc_parse/parse_lsa.c +++ b/source3/rpc_parse/parse_lsa.c @@ -5,7 +5,7 @@ * Copyright (C) Luke Kenneth Casson Leighton 1996-1997, * Copyright (C) Paul Ashton 1997, * Copyright (C) Andrew Bartlett 2002, - * Copyright (C) Jim McDonough 2002. + * Copyright (C) Jim McDonough 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 @@ -2219,21 +2219,18 @@ BOOL lsa_io_r_query_info2(const char *desc, LSA_R_QUERY_INFO2 *r_c, if(!prs_uint32("ptr", ps, depth, &r_c->ptr)) return False; - - if (r_c->ptr != 0) { - if(!prs_uint16("info_class", ps, depth, &r_c->info_class)) + if(!prs_uint16("info_class", ps, depth, &r_c->info_class)) + return False; + switch(r_c->info_class) { + case 0x000c: + if (!lsa_io_dns_dom_info("info12", &r_c->info.dns_dom_info, + ps, depth)) return False; - switch(r_c->info_class) { - case 0x000c: - if (!lsa_io_dns_dom_info("info12", &r_c->info.dns_dom_info, - ps, depth)) - return False; break; - default: - DEBUG(0,("lsa_io_r_query_info2: unknown info class %d\n", - r_c->info_class)); - return False; - } + default: + DEBUG(0,("lsa_io_r_query_info2: unknown info class %d\n", + r_c->info_class)); + return False; } if(!prs_align(ps)) @@ -2304,19 +2301,6 @@ BOOL lsa_io_r_enum_acct_rights(const char *desc, LSA_R_ENUM_ACCT_RIGHTS *r_c, pr return True; } -/******************************************************************* - Inits an LSA_R_ENUM_ACCT_RIGHTS structure. -********************************************************************/ -void init_r_enum_acct_rights(LSA_R_ENUM_ACCT_RIGHTS *q_r, - uint32 count, - const char **rights) -{ - DEBUG(5, ("init_r_enum_acct_rights\n")); - - q_r->count = count; - init_unistr2_array(&q_r->rights, count, rights); -} - /******************************************************************* Inits an LSA_Q_ADD_ACCT_RIGHTS structure. @@ -2332,6 +2316,7 @@ void init_q_add_acct_rights(LSA_Q_ADD_ACCT_RIGHTS *q_q, q_q->pol = *hnd; init_dom_sid2(&q_q->sid, sid); init_unistr2_array(&q_q->rights, count, rights); + q_q->count = 5; } @@ -2372,21 +2357,11 @@ BOOL lsa_io_r_add_acct_rights(const char *desc, LSA_R_ADD_ACCT_RIGHTS *r_c, prs_ return True; } -/******************************************************************* - Inits an LSA_R_ADD_ACCT_RIGHTS structure. -********************************************************************/ -void init_r_add_acct_rights(LSA_R_ADD_ACCT_RIGHTS *q_r) -{ - DEBUG(5, ("init_r_add_acct_rights\n")); - /* oh what a silly function! */ -} - -#if 0 /******************************************************************* Inits an LSA_Q_REMOVE_ACCT_RIGHTS structure. ********************************************************************/ - void init_q_remove_acct_rights(LSA_Q_REMOVE_ACCT_RIGHTS *q_q, +void init_q_remove_acct_rights(LSA_Q_REMOVE_ACCT_RIGHTS *q_q, POLICY_HND *hnd, DOM_SID *sid, uint32 removeall, @@ -2399,13 +2374,14 @@ void init_r_add_acct_rights(LSA_R_ADD_ACCT_RIGHTS *q_r) init_dom_sid2(&q_q->sid, sid); q_q->removeall = removeall; init_unistr2_array(&q_q->rights, count, rights); + q_q->count = 5; } /******************************************************************* reads or writes a LSA_Q_REMOVE_ACCT_RIGHTS structure. ********************************************************************/ - BOOL lsa_io_q_remove_acct_rights(const char *desc, LSA_Q_REMOVE_ACCT_RIGHTS *q_q, prs_struct *ps, int depth) +BOOL lsa_io_q_remove_acct_rights(const char *desc, LSA_Q_REMOVE_ACCT_RIGHTS *q_q, prs_struct *ps, int depth) { prs_debug(ps, depth, desc, "lsa_io_q_remove_acct_rights"); depth++; @@ -2429,9 +2405,9 @@ reads or writes a LSA_Q_REMOVE_ACCT_RIGHTS structure. } /******************************************************************* -reads or writes a LSA_R_REMOVE_ACCT_RIGHTS structure. +reads or writes a LSA_R_ENUM_ACCT_RIGHTS structure. ********************************************************************/ - BOOL lsa_io_r_remove_acct_rights(const char *desc, LSA_R_REMOVE_ACCT_RIGHTS *r_c, prs_struct *ps, int depth) +BOOL lsa_io_r_remove_acct_rights(const char *desc, LSA_R_REMOVE_ACCT_RIGHTS *r_c, prs_struct *ps, int depth) { prs_debug(ps, depth, desc, "lsa_io_r_remove_acct_rights"); depth++; @@ -2441,90 +2417,3 @@ reads or writes a LSA_R_REMOVE_ACCT_RIGHTS structure. return True; } - -/******************************************************************* - Inits an LSA_R_REMOVE_ACCT_RIGHTS structure. -********************************************************************/ - void init_r_remove_acct_rights(LSA_R_REMOVE_ACCT_RIGHTS *q_r) -{ - DEBUG(5, ("init_r_remove_acct_rights\n")); -} - -/******************************************************************* - Inits an LSA_Q_ENUM_ACCT_WITH_RIGHT structure. -********************************************************************/ - void init_q_enum_acct_with_right(LSA_Q_ENUM_ACCT_WITH_RIGHT *q_q, - POLICY_HND *hnd, - const char *right) -{ - DEBUG(5, ("init_q_enum_acct_with_right\n")); - - q_q->pol = *hnd; - init_unistr2(&q_q->right, right, strlen(right)); - init_str_hdr(&q_q->right_hdr, - q_q->right.uni_max_len*2, - q_q->right.uni_max_len*2, right?1:0); -} - - -/******************************************************************* -reads or writes a LSA_Q_ENUM_ACCT_WITH_RIGHT structure. -********************************************************************/ - BOOL lsa_io_q_enum_acct_with_right(const char *desc, LSA_Q_ENUM_ACCT_WITH_RIGHT *q_q, prs_struct *ps, int depth) -{ - prs_debug(ps, depth, desc, "lsa_io_q_enum_acct_with_right"); - depth++; - - if (!smb_io_pol_hnd("", &q_q->pol, ps, depth)) - return False; - - if (!prs_uint32("ref_id ", ps, depth, &q_q->right_hdr.buffer)) - return False; - - if (UNMARSHALLING(ps) && q_q->right_hdr.buffer == 0) { - return True; - } - - if (!smb_io_strhdr("", &q_q->right_hdr, ps, depth)) - return False; - - if (!smb_io_unistr2("", &q_q->right, q_q->right_hdr.buffer, ps, depth)) - return False; - - return True; -} - - -/******************************************************************* -reads or writes a LSA_R_ENUM_ACCT_WITH_RIGHT structure. -********************************************************************/ - BOOL lsa_io_r_enum_acct_with_right(const char *desc, LSA_R_ENUM_ACCT_WITH_RIGHT *r_c, prs_struct *ps, int depth) -{ - prs_debug(ps, depth, desc, "lsa_io_r_enum_acct_with_right"); - depth++; - - if (!prs_uint32("count ", ps, depth, &r_c->count)) - return False; - - if (!smb_io_sid_array("sids ", &r_c->sids, ps, depth)) - return False; - - if(!prs_ntstatus("status", ps, depth, &r_c->status)) - return False; - - return True; -} - -/******************************************************************* - Inits an LSA_R_ENUM_ACCT_WITH_RIGHT structure. -********************************************************************/ - void init_r_enum_acct_with_right(LSA_R_ENUM_ACCT_WITH_RIGHT *r_c, - uint32 count, - DOM_SID *sids) -{ - DEBUG(5, ("init_r_enum_acct_with_right\n")); - - r_c->count = count; - init_sid_array(&r_c->sids, count, sids); -} -#endif diff --git a/source3/rpc_parse/parse_prs.c b/source3/rpc_parse/parse_prs.c index efd4914c66..11d8658b15 100644 --- a/source3/rpc_parse/parse_prs.c +++ b/source3/rpc_parse/parse_prs.c @@ -1473,7 +1473,7 @@ void netsec_encode(struct netsec_auth_struct *a, int auth_flags, { uchar digest_final[16]; - DEBUG(10,("SCHANNEL: netsec_encode seq_num=%d data_len=%d\n", a->seq_num, data_len)); + DEBUG(10,("SCHANNEL: netsec_encode seq_num=%d data_len=%lu\n", a->seq_num, (unsigned long)data_len)); dump_data_pw("a->sess_key:\n", a->sess_key, sizeof(a->sess_key)); RSIVAL(verf->seq_num, 0, a->seq_num); @@ -1544,7 +1544,7 @@ BOOL netsec_decode(struct netsec_auth_struct *a, int auth_flags, break; } - DEBUG(10,("SCHANNEL: netsec_decode seq_num=%d data_len=%d\n", a->seq_num, data_len)); + DEBUG(10,("SCHANNEL: netsec_decode seq_num=%d data_len=%lu\n", a->seq_num, (unsigned long)data_len)); dump_data_pw("a->sess_key:\n", a->sess_key, sizeof(a->sess_key)); dump_data_pw("seq_num:\n", seq_num, sizeof(seq_num)); diff --git a/source3/rpc_parse/parse_samr.c b/source3/rpc_parse/parse_samr.c index 45c81deb89..fce3195225 100644 --- a/source3/rpc_parse/parse_samr.c +++ b/source3/rpc_parse/parse_samr.c @@ -7,8 +7,7 @@ * Copyright (C) Elrond 2000, * Copyright (C) Jeremy Allison 2001, * Copyright (C) Jean François Micouleau 1998-2001, - * Copyright (C) Anthony Liguori 2002, - * Copyright (C) Jim McDonough 2002. + * Copyright (C) Jim McDonough 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 diff --git a/source3/rpc_server/srv_dfs.c b/source3/rpc_server/srv_dfs.c index 75a24174ea..27bb0732b4 100644 --- a/source3/rpc_server/srv_dfs.c +++ b/source3/rpc_server/srv_dfs.c @@ -5,7 +5,7 @@ * Copyright (C) Luke Kenneth Casson Leighton 1996-1997, * Copyright (C) Shirish Kalele 2000, * Copyright (C) Jeremy Allison 2001, - * Copyright (C) Anthony Liguori 2003. + * Copyright (C) Jim McDonough 2003. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/source3/rpc_server/srv_lsa.c b/source3/rpc_server/srv_lsa.c index 679cfb73bb..34812b15d9 100644 --- a/source3/rpc_server/srv_lsa.c +++ b/source3/rpc_server/srv_lsa.c @@ -5,8 +5,7 @@ * Copyright (C) Luke Kenneth Casson Leighton 1996-1997, * Copyright (C) Paul Ashton 1997, * Copyright (C) Jeremy Allison 2001, - * Copyright (C) Jim McDonough 2002, - * Copyright (C) Anthony Liguori 2003. + * Copyright (C) Jim McDonough 2002-2003. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/source3/rpc_server/srv_lsa_nt.c b/source3/rpc_server/srv_lsa_nt.c index ca3021a876..9eafcb8dc3 100644 --- a/source3/rpc_server/srv_lsa_nt.c +++ b/source3/rpc_server/srv_lsa_nt.c @@ -6,7 +6,7 @@ * Copyright (C) Paul Ashton 1997, * Copyright (C) Jeremy Allison 2001, * Copyright (C) Rafal Szczesniak 2002, - * Copyright (C) Jim McDonough 2002. + * Copyright (C) Jim McDonough 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 diff --git a/source3/rpc_server/srv_netlog.c b/source3/rpc_server/srv_netlog.c index 0cd4073177..d1be2f3723 100644 --- a/source3/rpc_server/srv_netlog.c +++ b/source3/rpc_server/srv_netlog.c @@ -5,7 +5,7 @@ * Copyright (C) Luke Kenneth Casson Leighton 1996-1997, * Copyright (C) Paul Ashton 1997, * Copyright (C) Jeremy Allison 1998-2001, - * Copyright (C) Anthony Liguori 2003. + * Copyright (C) Jim McDonough 2003. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/source3/rpc_server/srv_netlog_nt.c b/source3/rpc_server/srv_netlog_nt.c index c4a87d2e26..602cd7d2d5 100644 --- a/source3/rpc_server/srv_netlog_nt.c +++ b/source3/rpc_server/srv_netlog_nt.c @@ -5,7 +5,7 @@ * Copyright (C) Luke Kenneth Casson Leighton 1996-1997, * Copyright (C) Paul Ashton 1997. * Copyright (C) Jeremy Allison 1998-2001. - * Copyirht (C) Andrew Bartlett 2001. + * Copyright (C) Andrew Bartlett 2001. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c index 9a63ebc7a3..594cb3a9ae 100644 --- a/source3/rpc_server/srv_pipe.c +++ b/source3/rpc_server/srv_pipe.c @@ -5,7 +5,7 @@ * Copyright (C) Luke Kenneth Casson Leighton 1996-1998, * Copyright (C) Paul Ashton 1997-1998, * Copyright (C) Jeremy Allison 1999, - * Copyright (C) Anthony Liguori 2003. + * Copyright (C) Jim McDonough 2003. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -277,11 +277,6 @@ BOOL create_next_pdu(pipes_struct *p) prs_init(&rverf, 0, p->mem_ctx, MARSHALL); prs_init(&rauth, 0, p->mem_ctx, MARSHALL); - if ((p->netsec_auth.seq_num & 1) == 0) { - DEBUG(0,("SCHANNEL ERROR: seq_num must be odd in server! (seq_num=%d)\n", - p->netsec_auth.seq_num)); - } - init_rpc_auth_netsec_chk(&verf, netsec_sig, nullbytes, nullbytes, nullbytes); netsec_encode(&p->netsec_auth, diff --git a/source3/rpc_server/srv_reg.c b/source3/rpc_server/srv_reg.c index 43bb1ad86a..e1a02103f7 100644 --- a/source3/rpc_server/srv_reg.c +++ b/source3/rpc_server/srv_reg.c @@ -7,7 +7,7 @@ * Copyright (C) Marc Jacobsen 2000, * Copyright (C) Jeremy Allison 2001, * Copyright (C) Gerald Carter 2002, - * Copyright (C) Anthony Liguori 2003. + * Copyright (C) Jim McDonough 2003. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/source3/rpc_server/srv_reg_nt.c b/source3/rpc_server/srv_reg_nt.c index 5632544909..a4e3638be6 100644 --- a/source3/rpc_server/srv_reg_nt.c +++ b/source3/rpc_server/srv_reg_nt.c @@ -596,11 +596,11 @@ NTSTATUS _reg_shutdown(pipes_struct *p, REG_Q_SHUTDOWN *q_u, REG_R_SHUTDOWN *r_u /* security check */ alpha_strcpy (chkmsg, message, NULL, sizeof(message)); /* timeout */ - snprintf(timeout, sizeof(timeout), "%d", q_u->timeout); + fstr_sprintf(timeout, "%d", q_u->timeout); /* reboot */ - snprintf(r, sizeof(r), (q_u->reboot) ? SHUTDOWN_R_STRING : ""); + fstr_sprintf(r, (q_u->reboot) ? SHUTDOWN_R_STRING : ""); /* force */ - snprintf(f, sizeof(f), (q_u->force) ? SHUTDOWN_F_STRING : ""); + fstr_sprintf(f, (q_u->force) ? SHUTDOWN_F_STRING : ""); pstrcpy(shutdown_script, lp_shutdown_script()); diff --git a/source3/rpc_server/srv_samr.c b/source3/rpc_server/srv_samr.c index 9250b023d3..86ff039683 100644 --- a/source3/rpc_server/srv_samr.c +++ b/source3/rpc_server/srv_samr.c @@ -6,8 +6,7 @@ * Copyright (C) Paul Ashton 1997, * Copyright (C) Marc Jacobsen 1999, * Copyright (C) Jean François Micouleau 1998-2001, - * Copyright (C) Anthony Liguori 2002-2003, - * Copyright (C) Jim McDonough 2002. + * Copyright (C) Jim McDonough 2002-2003. * * Split into interface and implementation modules by, * diff --git a/source3/rpc_server/srv_samr_nt.c b/source3/rpc_server/srv_samr_nt.c index 9324fd4765..14aad5d6f8 100644 --- a/source3/rpc_server/srv_samr_nt.c +++ b/source3/rpc_server/srv_samr_nt.c @@ -7,8 +7,7 @@ * Copyright (C) Marc Jacobsen 1999, * Copyright (C) Jeremy Allison 2001-2002, * Copyright (C) Jean François Micouleau 1998-2001, - * Copyright (C) Anthony Liguori 2002, - * Copyright (C) Jim McDonough 2002. + * Copyright (C) Jim McDonough 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 @@ -1517,17 +1516,17 @@ NTSTATUS _samr_lookup_names(pipes_struct *p, SAMR_Q_LOOKUP_NAMES *q_u, SAMR_R_LO NTSTATUS _samr_chgpasswd_user(pipes_struct *p, SAMR_Q_CHGPASSWD_USER *q_u, SAMR_R_CHGPASSWD_USER *r_u) { - fstring user_name; - fstring wks; + fstring user_name; + fstring wks; - DEBUG(5,("_samr_chgpasswd_user: %d\n", __LINE__)); + DEBUG(5,("_samr_chgpasswd_user: %d\n", __LINE__)); - r_u->status = NT_STATUS_OK; + r_u->status = NT_STATUS_OK; - rpcstr_pull(user_name, q_u->uni_user_name.buffer, sizeof(user_name), q_u->uni_user_name.uni_str_len*2, 0); - rpcstr_pull(wks, q_u->uni_dest_host.buffer, sizeof(wks), q_u->uni_dest_host.uni_str_len*2,0); + rpcstr_pull(user_name, q_u->uni_user_name.buffer, sizeof(user_name), q_u->uni_user_name.uni_str_len*2, 0); + rpcstr_pull(wks, q_u->uni_dest_host.buffer, sizeof(wks), q_u->uni_dest_host.uni_str_len*2,0); - DEBUG(5,("samr_chgpasswd_user: user: %s wks: %s\n", user_name, wks)); + DEBUG(5,("samr_chgpasswd_user: user: %s wks: %s\n", user_name, wks)); /* * Pass the user through the NT -> unix user mapping @@ -1541,14 +1540,14 @@ NTSTATUS _samr_chgpasswd_user(pipes_struct *p, SAMR_Q_CHGPASSWD_USER *q_u, SAMR_ * is case insensitive. */ - r_u->status = pass_oem_change(user_name, q_u->lm_newpass.pass, q_u->lm_oldhash.hash, - q_u->nt_newpass.pass, q_u->nt_oldhash.hash); + r_u->status = pass_oem_change(user_name, q_u->lm_newpass.pass, q_u->lm_oldhash.hash, + q_u->nt_newpass.pass, q_u->nt_oldhash.hash); - init_samr_r_chgpasswd_user(r_u, r_u->status); + init_samr_r_chgpasswd_user(r_u, r_u->status); - DEBUG(5,("_samr_chgpasswd_user: %d\n", __LINE__)); + DEBUG(5,("_samr_chgpasswd_user: %d\n", __LINE__)); - return r_u->status; + return r_u->status; } /******************************************************************* @@ -2259,7 +2258,7 @@ NTSTATUS _api_samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_ * now have some sainity-checking to match. */ - DEBUG(10,("checking account %s at pos %d for $ termination\n",account, strlen(account)-1)); + DEBUG(10,("checking account %s at pos %lu for $ termination\n",account, (unsigned long)strlen(account)-1)); /* * we used to have code here that made sure the acb_info flags @@ -2761,8 +2760,9 @@ static BOOL set_unix_primary_group(SAM_ACCOUNT *sampass) grp = getgrgid(gid); if (grp == NULL) { - DEBUG(2,("Could not find primary group %d for " - "user %s\n", gid, pdb_get_username(sampass))); + DEBUG(2,("Could not find primary group %lu for " + "user %s\n", (unsigned long)gid, + pdb_get_username(sampass))); return False; } diff --git a/source3/rpc_server/srv_spoolss.c b/source3/rpc_server/srv_spoolss.c index 3e9ed9e39f..fa0ca8478c 100755 --- a/source3/rpc_server/srv_spoolss.c +++ b/source3/rpc_server/srv_spoolss.c @@ -6,7 +6,7 @@ * Copyright (C) Jean François Micouleau 1998-2000, * Copyright (C) Jeremy Allison 2001, * Copyright (C) Gerald Carter 2001-2002, - * Copyright (C) Anthony Liguori 2003. + * Copyright (C) Jim McDonough 2003. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/source3/rpc_server/srv_spoolss_nt.c b/source3/rpc_server/srv_spoolss_nt.c index 2d316051af..8237298ebb 100644 --- a/source3/rpc_server/srv_spoolss_nt.c +++ b/source3/rpc_server/srv_spoolss_nt.c @@ -478,7 +478,7 @@ static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename) fstring sname; BOOL found=False; - DEBUG(4,("Setting printer name=%s (len=%d)\n", handlename, strlen(handlename))); + DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename, (unsigned long)strlen(handlename))); if (Printer->printer_type==PRINTER_HANDLE_IS_PRINTSERVER) { ZERO_STRUCT(Printer->dev.printerservername); @@ -497,7 +497,7 @@ static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename) aprinter=handlename; } - DEBUGADD(5,("searching for [%s] (len=%d)\n", aprinter, strlen(aprinter))); + DEBUGADD(5,("searching for [%s] (len=%lu)\n", aprinter, (unsigned long)strlen(aprinter))); /* * The original code allowed smbd to store a printer name that @@ -563,7 +563,7 @@ static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint3 new_printer->notify.option=NULL; - if ( !(new_printer->ctx = talloc_init("Printer Entry [0x%x]", (uint32)hnd)) ) { + if ( !(new_printer->ctx = talloc_init("Printer Entry [%p]", hnd)) ) { DEBUG(0,("open_printer_hnd: talloc_init() failed!\n")); close_printer_handle(p, hnd); return False; @@ -1176,7 +1176,7 @@ static void receive_notify2_message_list(int msg_type, pid_t src, void *msg, siz msg_count = IVAL(buf, 0); msg_ptr = buf + 4; - DEBUG(5, ("receive_notify2_message_list: got %d messages in list\n", msg_count)); + DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count)); if (msg_count == 0) { DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n")); @@ -2393,9 +2393,7 @@ static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint if (!StrCaseCmp(value, "DefaultSpoolDirectory")) { - fstring string; - - fstrcpy(string, string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH)); + const char *string="C:\\PRINTERS"; *type = 0x1; *needed = 2*(strlen(string)+1); if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL) @@ -2411,7 +2409,7 @@ static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint } if (!StrCaseCmp(value, "Architecture")) { - pstring string="Windows NT x86"; + const char *string="Windows NT x86"; *type = 0x1; *needed = 2*(strlen(string)+1); if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL) @@ -5135,7 +5133,7 @@ static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const c else pstrcpy( line, v ); - DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line))); + DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line))); /* add one extra unit16 for the second terminating NULL */ @@ -7912,6 +7910,11 @@ WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SP return WERR_BADFID; } + if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) { + DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n")); + return WERR_INVALID_PARAM; + } + if (!get_printer_snum(p,handle, &snum)) return WERR_BADFID; @@ -8698,7 +8701,7 @@ WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, /* Is the handle to a printer or to the server? */ if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) { - DEBUG(10,("_spoolss_getprinterdatex: Not implemented for server handles yet\n")); + DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n")); status = WERR_INVALID_PARAM; goto done; } @@ -8780,10 +8783,15 @@ WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SetPrinterData if key is "PrinterDriverData" */ if (!Printer) { - DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle))); + DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle))); return WERR_BADFID; } + if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER ) { + DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n")); + return WERR_INVALID_PARAM; + } + if ( !get_printer_snum(p,handle, &snum) ) return WERR_BADFID; @@ -9092,8 +9100,8 @@ WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_ { if ( (enum_values=talloc(p->mem_ctx, num_entries*sizeof(PRINTER_ENUM_VALUES))) == NULL ) { - DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%d] bytes!\n", - num_entries*sizeof(PRINTER_ENUM_VALUES))); + DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n", + (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES))); result = WERR_NOMEM; goto done; } diff --git a/source3/rpc_server/srv_srvsvc.c b/source3/rpc_server/srv_srvsvc.c index deba122421..0da3cf70dd 100644 --- a/source3/rpc_server/srv_srvsvc.c +++ b/source3/rpc_server/srv_srvsvc.c @@ -5,7 +5,7 @@ * Copyright (C) Luke Kenneth Casson Leighton 1996-1997, * Copyright (C) Paul Ashton 1997, * Copyright (C) Jeremy Allison 2001, - * Copyright (C) Anthony Liguori 2003. + * Copyright (C) Jim McDonough 2003. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/source3/rpc_server/srv_wkssvc.c b/source3/rpc_server/srv_wkssvc.c index 8efa29fd0b..856f451779 100644 --- a/source3/rpc_server/srv_wkssvc.c +++ b/source3/rpc_server/srv_wkssvc.c @@ -4,7 +4,7 @@ * Copyright (C) Andrew Tridgell 1992-1997, * Copyright (C) Luke Kenneth Casson Leighton 1996-1997, * Copyright (C) Paul Ashton 1997, - * Copyright (C) Anthony Liguori 2003. + * Copyright (C) Jim McDonough 2003. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/source3/rpcclient/cmd_ds.c b/source3/rpcclient/cmd_ds.c index 4c2f52e291..721bd59ba0 100644 --- a/source3/rpcclient/cmd_ds.c +++ b/source3/rpcclient/cmd_ds.c @@ -47,13 +47,33 @@ static NTSTATUS cmd_ds_dsrole_getprimarydominfo(struct cli_state *cli, return result; } +static NTSTATUS cmd_ds_enum_domain_trusts(struct cli_state *cli, + TALLOC_CTX *mem_ctx, int argc, + const char **argv) +{ + NTSTATUS result; + uint32 flags = 0x1; + DS_DOMAIN_TRUSTS *trusts = NULL; + int num_domains = 0; + + result = cli_ds_enum_domain_trusts( cli, mem_ctx, cli->desthost, flags, + &trusts, &num_domains ); + + printf( "%d domains returned\n", num_domains ); + + SAFE_FREE( trusts ); + + return result; +} + /* List of commands exported by this module */ struct cmd_set ds_commands[] = { { "LSARPC-DS" }, - { "dsroledominfo", RPC_RTYPE_NTSTATUS, cmd_ds_dsrole_getprimarydominfo, NULL, PI_LSARPC_DS, "Get Primary Domain Information", "" }, + { "dsroledominfo", RPC_RTYPE_NTSTATUS, cmd_ds_dsrole_getprimarydominfo, NULL, PI_LSARPC_DS, "Get Primary Domain Information", "" }, + { "dsenumdomtrusts", RPC_RTYPE_NTSTATUS, cmd_ds_enum_domain_trusts, NULL, PI_NETLOGON, "Enumerate all trusted domains in an AD forest", "" }, { NULL } }; diff --git a/source3/rpcclient/cmd_samr.c b/source3/rpcclient/cmd_samr.c index 40d01d0f5a..722d66621a 100644 --- a/source3/rpcclient/cmd_samr.c +++ b/source3/rpcclient/cmd_samr.c @@ -125,7 +125,7 @@ static const char *display_time(NTTIME nttime) mins=(sec - (days*60*60*24) - (hours*60*60) ) / 60; secs=sec - (days*60*60*24) - (hours*60*60) - (mins*60); - snprintf(string, sizeof(string)-1, "%u days, %u hours, %u minutes, %u seconds", days, hours, mins, secs); + fstr_sprintf(string, "%u days, %u hours, %u minutes, %u seconds", days, hours, mins, secs); return (string); } diff --git a/source3/rpcclient/rpcclient.c b/source3/rpcclient/rpcclient.c index af021962f5..831d2beaa4 100644 --- a/source3/rpcclient/rpcclient.c +++ b/source3/rpcclient/rpcclient.c @@ -37,21 +37,6 @@ static struct cmd_list { struct cmd_set *cmd_set; } *cmd_list; -/***************************************************************************** - stubb functions -****************************************************************************/ - -void become_root( void ) -{ - return; -} - -void unbecome_root( void ) -{ - return; -} - - /**************************************************************************** handle completion of commands for readline ****************************************************************************/ @@ -370,66 +355,64 @@ static NTSTATUS cmd_none(struct cli_state *cli, TALLOC_CTX *mem_ctx, static NTSTATUS cmd_schannel(struct cli_state *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { + NTSTATUS ret; uchar trust_password[16]; uint32 sec_channel_type; - uint32 neg_flags = 0x000001ff; - NTSTATUS result; static uchar zeros[16]; + if (argc == 2) { + strhex_to_str(cli->auth_info.sess_key, + strlen(argv[1]), + argv[1]); + memcpy(cli->sess_key, cli->auth_info.sess_key, sizeof(cli->sess_key)); + + cli->pipe_auth_flags = AUTH_PIPE_NETSEC; + cli->pipe_auth_flags |= AUTH_PIPE_SIGN; + cli->pipe_auth_flags |= AUTH_PIPE_SEAL; + + return NT_STATUS_OK; + } + /* Cleanup */ - if ((memcmp(cli->auth_info.sess_key, zeros, sizeof(cli->auth_info.sess_key)) != 0) - && (cli->saved_netlogon_pipe_fnum != 0)) { + if ((memcmp(cli->auth_info.sess_key, zeros, sizeof(cli->auth_info.sess_key)) != 0)) { if (cli->pipe_auth_flags == (AUTH_PIPE_NETSEC|AUTH_PIPE_SIGN|AUTH_PIPE_SEAL)) { + /* already in this mode nothing to do */ return NT_STATUS_OK; } else { - /* still have session, just need to use it again */ + /* schannel is setup, just need to use it again */ cli->pipe_auth_flags = AUTH_PIPE_NETSEC; cli->pipe_auth_flags |= AUTH_PIPE_SIGN; cli->pipe_auth_flags |= AUTH_PIPE_SEAL; if (cli->nt_pipe_fnum != 0) cli_nt_session_close(cli); + return NT_STATUS_OK; } } if (cli->nt_pipe_fnum != 0) cli_nt_session_close(cli); - cli->pipe_auth_flags = 0; - + cli->pipe_auth_flags = AUTH_PIPE_NETSEC; + cli->pipe_auth_flags |= AUTH_PIPE_SIGN; + cli->pipe_auth_flags |= AUTH_PIPE_SEAL; + if (!secrets_fetch_trust_account_password(lp_workgroup(), trust_password, NULL, &sec_channel_type)) { return NT_STATUS_UNSUCCESSFUL; } - - if (!cli_nt_session_open(cli, PI_NETLOGON)) { - DEBUG(0, ("Could not initialise %s\n", - get_pipe_name_from_index(PI_NETLOGON))); - return NT_STATUS_UNSUCCESSFUL; - } - - neg_flags |= NETLOGON_NEG_SCHANNEL; - result = cli_nt_setup_creds(cli, sec_channel_type, trust_password, - &neg_flags, 2); - - if (!NT_STATUS_IS_OK(result)) { - ZERO_STRUCT(cli->auth_info.sess_key); - cli->pipe_auth_flags = 0; - return result; + ret = cli_nt_setup_netsec(cli, sec_channel_type, trust_password); + if (NT_STATUS_IS_OK(ret)) { + char *hex_session_key; + hex_encode(cli->auth_info.sess_key, + sizeof(cli->auth_info.sess_key), + &hex_session_key); + printf("Got Session key: %s\n", hex_session_key); + SAFE_FREE(hex_session_key); } - - memcpy(cli->auth_info.sess_key, cli->sess_key, - sizeof(cli->auth_info.sess_key)); - - cli->saved_netlogon_pipe_fnum = cli->nt_pipe_fnum; - - cli->pipe_auth_flags = AUTH_PIPE_NETSEC; - cli->pipe_auth_flags |= AUTH_PIPE_SIGN; - cli->pipe_auth_flags |= AUTH_PIPE_SEAL; - - return NT_STATUS_OK; + return ret; } /* Built in rpcclient commands */ @@ -536,7 +519,9 @@ static NTSTATUS do_cmd(struct cli_state *cli, } } - if ((cmd_entry->pipe_idx == PI_NETLOGON) && !(cli->pipe_auth_flags & AUTH_PIPE_NETSEC)) { + /* some of the DsXXX commands use the netlogon pipe */ + + if (lp_client_schannel() && (cmd_entry->pipe_idx == PI_NETLOGON) && !(cli->pipe_auth_flags & AUTH_PIPE_NETSEC)) { uint32 neg_flags = 0x000001ff; uint32 sec_channel_type; @@ -741,7 +726,8 @@ out_free: opt_ipaddr ? &server_ip : NULL, 0, "IPC$", "IPC", cmdline_auth_info.username, lp_workgroup(), - cmdline_auth_info.password, 0, NULL); + cmdline_auth_info.password, 0, + cmdline_auth_info.signing_state,NULL); if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(0,("Cannot connect to server. Error was %s\n", nt_errstr(nt_status))); diff --git a/source3/sam/idmap.c b/source3/sam/idmap.c index 7a8f270e15..4d8b768c2f 100644 --- a/source3/sam/idmap.c +++ b/source3/sam/idmap.c @@ -2,7 +2,7 @@ Unix SMB/CIFS implementation. ID Mapping Copyright (C) Tim Potter 2000 - Copyright (C) Anthony Liguori 2003 + Copyright (C) Jim McDonough 2003 Copyright (C) Simo Sorce 2003 Copyright (C) Jeremy Allison 2003. @@ -153,10 +153,11 @@ NTSTATUS idmap_set_mapping(const DOM_SID *sid, unid_t id, int id_type) struct idmap_methods *map = remote_map; DOM_SID tmp_sid; - DEBUG(10, ("idmap_set_mapping: Set %s to %s %d\n", + DEBUG(10, ("idmap_set_mapping: Set %s to %s %lu\n", sid_string_static(sid), ((id_type & ID_TYPEMASK) == ID_USERID) ? "UID" : "GID", - ((id_type & ID_TYPEMASK) == ID_USERID) ? id.uid : id.gid)); + ((id_type & ID_TYPEMASK) == ID_USERID) ? (unsigned long)id.uid : + (unsigned long)id.gid)); if ( (NT_STATUS_IS_OK(cache_map-> get_sid_from_id(&tmp_sid, id, diff --git a/source3/sam/idmap_tdb.c b/source3/sam/idmap_tdb.c index 7f8dce1f1a..2055103898 100644 --- a/source3/sam/idmap_tdb.c +++ b/source3/sam/idmap_tdb.c @@ -4,7 +4,7 @@ idmap TDB backend Copyright (C) Tim Potter 2000 - Copyright (C) Anthony Liguori 2003 + Copyright (C) Jim McDonough 2003 Copyright (C) Simo Sorce 2003 This program is free software; you can redistribute it and/or modify @@ -116,7 +116,8 @@ static NTSTATUS db_allocate_id(unid_t *id, int id_type) /* check it is in the range */ if (hwm > idmap_state.uid_high) { - DEBUG(0, ("idmap Fatal Error: UID range full!! (max: %u)\n", idmap_state.uid_high)); + DEBUG(0, ("idmap Fatal Error: UID range full!! (max: %lu)\n", + (unsigned long)idmap_state.uid_high)); return NT_STATUS_UNSUCCESSFUL; } @@ -129,7 +130,8 @@ static NTSTATUS db_allocate_id(unid_t *id, int id_type) /* recheck it is in the range */ if (hwm > idmap_state.uid_high) { - DEBUG(0, ("idmap Fatal Error: UID range full!! (max: %u)\n", idmap_state.uid_high)); + DEBUG(0, ("idmap Fatal Error: UID range full!! (max: %lu)\n", + (unsigned long)idmap_state.uid_high)); return NT_STATUS_UNSUCCESSFUL; } @@ -144,7 +146,8 @@ static NTSTATUS db_allocate_id(unid_t *id, int id_type) /* check it is in the range */ if (hwm > idmap_state.gid_high) { - DEBUG(0, ("idmap Fatal Error: GID range full!! (max: %u)\n", idmap_state.gid_high)); + DEBUG(0, ("idmap Fatal Error: GID range full!! (max: %lu)\n", + (unsigned long)idmap_state.gid_high)); return NT_STATUS_UNSUCCESSFUL; } @@ -158,7 +161,8 @@ static NTSTATUS db_allocate_id(unid_t *id, int id_type) /* recheck it is in the range */ if (hwm > idmap_state.gid_high) { - DEBUG(0, ("idmap Fatal Error: GID range full!! (max: %u)\n", idmap_state.gid_high)); + DEBUG(0, ("idmap Fatal Error: GID range full!! (max: %lu)\n", + (unsigned long)idmap_state.gid_high)); return NT_STATUS_UNSUCCESSFUL; } @@ -185,10 +189,10 @@ static NTSTATUS internal_get_sid_from_id(DOM_SID *sid, unid_t id, int id_type) switch (id_type & ID_TYPEMASK) { case ID_USERID: - slprintf(keystr, sizeof(keystr), "UID %d", id.uid); + slprintf(keystr, sizeof(keystr), "UID %lu", (unsigned long)id.uid); break; case ID_GROUPID: - slprintf(keystr, sizeof(keystr), "GID %d", id.gid); + slprintf(keystr, sizeof(keystr), "GID %lu", (unsigned long)id.gid); break; default: return NT_STATUS_UNSUCCESSFUL; @@ -374,9 +378,11 @@ static NTSTATUS db_get_id_from_sid(unid_t *id, int *id_type, const DOM_SID *sid) /* Store the UID side */ /* Store new id */ if (*id_type & ID_USERID) { - slprintf(ugid_str, sizeof(ugid_str), "UID %d", (*id).uid); + slprintf(ugid_str, sizeof(ugid_str), "UID %lu", + (unsigned long)((*id).uid)); } else { - slprintf(ugid_str, sizeof(ugid_str), "GID %d", (*id).gid); + slprintf(ugid_str, sizeof(ugid_str), "GID %lu", + (unsigned long)((*id).gid)); } ugid_data.dptr = ugid_str; @@ -430,9 +436,9 @@ static NTSTATUS db_set_mapping(const DOM_SID *sid, unid_t id, int id_type) ksid.dsize = strlen(ksidstr) + 1; if (id_type & ID_USERID) { - slprintf(kidstr, sizeof(kidstr), "UID %d", id.uid); + slprintf(kidstr, sizeof(kidstr), "UID %lu", (unsigned long)id.uid); } else if (id_type & ID_GROUPID) { - slprintf(kidstr, sizeof(kidstr), "GID %d", id.gid); + slprintf(kidstr, sizeof(kidstr), "GID %lu", (unsigned long)id.gid); } else { return NT_STATUS_INVALID_PARAMETER; } diff --git a/source3/sam/idmap_util.c b/source3/sam/idmap_util.c index f767cc898c..f794ea5173 100644 --- a/source3/sam/idmap_util.c +++ b/source3/sam/idmap_util.c @@ -146,7 +146,7 @@ NTSTATUS idmap_uid_to_sid(DOM_SID *sid, uid_t uid) unid_t id; int flags; - DEBUG(10,("idmap_uid_to_sid: uid = [%d]\n", uid)); + DEBUG(10,("idmap_uid_to_sid: uid = [%lu]\n", (unsigned long)uid)); flags = ID_USERID; id.uid = uid; @@ -164,7 +164,7 @@ NTSTATUS idmap_gid_to_sid(DOM_SID *sid, gid_t gid) unid_t id; int flags; - DEBUG(10,("idmap_gid_to_sid: gid = [%d]\n", gid)); + DEBUG(10,("idmap_gid_to_sid: gid = [%lu]\n", (unsigned long)gid)); flags = ID_GROUPID; #if 0 /* JERRY */ @@ -195,7 +195,7 @@ NTSTATUS idmap_sid_to_uid(const DOM_SID *sid, uid_t *uid, uint32 flags) ret = idmap_get_id_from_sid(&id, &flags, sid); if ( NT_STATUS_IS_OK(ret) ) { - DEBUG(10,("idmap_sid_to_uid: uid = [%d]\n", id.uid)); + DEBUG(10,("idmap_sid_to_uid: uid = [%lu]\n", (unsigned long)id.uid)); *uid = id.uid; } @@ -225,7 +225,7 @@ NTSTATUS idmap_sid_to_gid(const DOM_SID *sid, gid_t *gid, uint32 flags) if ( NT_STATUS_IS_OK(ret) ) { - DEBUG(10,("idmap_sid_to_gid: gid = [%d]\n", id.gid)); + DEBUG(10,("idmap_sid_to_gid: gid = [%lu]\n", (unsigned long)id.gid)); *gid = id.gid; } diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 2802fbb151..fed3a51b88 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -28,16 +28,16 @@ extern char *OutBuffer; *****************************************************************************/ typedef struct { - ubi_slNode msg_next; - int com_type; - files_struct *fsp; - time_t expire_time; - int lock_num; - SMB_BIG_UINT offset; - SMB_BIG_UINT count; - uint16 lock_pid; - char *inbuf; - int length; + ubi_slNode msg_next; + int com_type; + files_struct *fsp; + time_t expire_time; + int lock_num; + SMB_BIG_UINT offset; + SMB_BIG_UINT count; + uint16 lock_pid; + char *inbuf; + int length; } blocking_lock_record; static ubi_slList blocking_lock_queue = { NULL, (ubi_slNodePtr)&blocking_lock_queue, 0}; @@ -48,8 +48,8 @@ static ubi_slList blocking_lock_queue = { NULL, (ubi_slNodePtr)&blocking_lock_qu static void free_blocking_lock_record(blocking_lock_record *blr) { - SAFE_FREE(blr->inbuf); - SAFE_FREE(blr); + SAFE_FREE(blr->inbuf); + SAFE_FREE(blr); } /**************************************************************************** @@ -58,17 +58,17 @@ static void free_blocking_lock_record(blocking_lock_record *blr) static files_struct *get_fsp_from_pkt(char *inbuf) { - switch(CVAL(inbuf,smb_com)) { - case SMBlock: - case SMBlockread: - return file_fsp(inbuf,smb_vwv0); - case SMBlockingX: - return file_fsp(inbuf,smb_vwv2); - default: - DEBUG(0,("get_fsp_from_pkt: PANIC - unknown type on blocking lock queue - exiting.!\n")); - exit_server("PANIC - unknown type on blocking lock queue"); - } - return NULL; /* Keep compiler happy. */ + switch(CVAL(inbuf,smb_com)) { + case SMBlock: + case SMBlockread: + return file_fsp(inbuf,smb_vwv0); + case SMBlockingX: + return file_fsp(inbuf,smb_vwv2); + default: + DEBUG(0,("get_fsp_from_pkt: PANIC - unknown type on blocking lock queue - exiting.!\n")); + exit_server("PANIC - unknown type on blocking lock queue"); + } + return NULL; /* Keep compiler happy. */ } /**************************************************************************** @@ -77,7 +77,7 @@ static files_struct *get_fsp_from_pkt(char *inbuf) static BOOL in_chained_smb(void) { - return (chain_size != 0); + return (chain_size != 0); } static void received_unlock_msg(int msg_type, pid_t src, void *buf, size_t len); @@ -89,66 +89,68 @@ static void received_unlock_msg(int msg_type, pid_t src, void *buf, size_t len); BOOL push_blocking_lock_request( char *inbuf, int length, int lock_timeout, int lock_num, uint16 lock_pid, SMB_BIG_UINT offset, SMB_BIG_UINT count) { - static BOOL set_lock_msg; - blocking_lock_record *blr; - NTSTATUS status; - - if(in_chained_smb() ) { - DEBUG(0,("push_blocking_lock_request: cannot queue a chained request (currently).\n")); - return False; - } - - /* - * Now queue an entry on the blocking lock queue. We setup - * the expiration time here. - */ - - if((blr = (blocking_lock_record *)malloc(sizeof(blocking_lock_record))) == NULL) { - DEBUG(0,("push_blocking_lock_request: Malloc fail !\n" )); - return False; - } - - if((blr->inbuf = (char *)malloc(length)) == NULL) { - DEBUG(0,("push_blocking_lock_request: Malloc fail (2)!\n" )); - SAFE_FREE(blr); - return False; - } - - blr->com_type = CVAL(inbuf,smb_com); - blr->fsp = get_fsp_from_pkt(inbuf); - blr->expire_time = (lock_timeout == -1) ? (time_t)-1 : time(NULL) + (time_t)lock_timeout; - blr->lock_num = lock_num; - blr->lock_pid = lock_pid; - blr->offset = offset; - blr->count = count; - memcpy(blr->inbuf, inbuf, length); - blr->length = length; - - /* Add a pending lock record for this. */ - status = brl_lock(blr->fsp->dev, blr->fsp->inode, blr->fsp->fnum, - lock_pid, sys_getpid(), blr->fsp->conn->cnum, - offset, count, - PENDING_LOCK); - - if (!NT_STATUS_IS_OK(status)) { - DEBUG(0,("push_blocking_lock_request: failed to add PENDING_LOCK record.\n")); - free_blocking_lock_record(blr); - return False; - } + static BOOL set_lock_msg; + blocking_lock_record *blr; + NTSTATUS status; + + if(in_chained_smb() ) { + DEBUG(0,("push_blocking_lock_request: cannot queue a chained request (currently).\n")); + return False; + } + + /* + * Now queue an entry on the blocking lock queue. We setup + * the expiration time here. + */ - ubi_slAddTail(&blocking_lock_queue, blr); + if((blr = (blocking_lock_record *)malloc(sizeof(blocking_lock_record))) == NULL) { + DEBUG(0,("push_blocking_lock_request: Malloc fail !\n" )); + return False; + } + + if((blr->inbuf = (char *)malloc(length)) == NULL) { + DEBUG(0,("push_blocking_lock_request: Malloc fail (2)!\n" )); + SAFE_FREE(blr); + return False; + } - /* Ensure we'll receive messages when this is unlocked. */ - if (!set_lock_msg) { - message_register(MSG_SMB_UNLOCK, received_unlock_msg); - set_lock_msg = True; - } + blr->com_type = CVAL(inbuf,smb_com); + blr->fsp = get_fsp_from_pkt(inbuf); + blr->expire_time = (lock_timeout == -1) ? (time_t)-1 : time(NULL) + (time_t)lock_timeout; + blr->lock_num = lock_num; + blr->lock_pid = lock_pid; + blr->offset = offset; + blr->count = count; + memcpy(blr->inbuf, inbuf, length); + blr->length = length; + + /* Add a pending lock record for this. */ + status = brl_lock(blr->fsp->dev, blr->fsp->inode, blr->fsp->fnum, + lock_pid, sys_getpid(), blr->fsp->conn->cnum, + offset, count, PENDING_LOCK); + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("push_blocking_lock_request: failed to add PENDING_LOCK record.\n")); + free_blocking_lock_record(blr); + return False; + } + + ubi_slAddTail(&blocking_lock_queue, blr); + + /* Ensure we'll receive messages when this is unlocked. */ + if (!set_lock_msg) { + message_register(MSG_SMB_UNLOCK, received_unlock_msg); + set_lock_msg = True; + } - DEBUG(3,("push_blocking_lock_request: lock request length=%d blocked with expiry time %d (+%d) \ + DEBUG(3,("push_blocking_lock_request: lock request length=%d blocked with expiry time %d (+%d) \ for fnum = %d, name = %s\n", length, (int)blr->expire_time, lock_timeout, - blr->fsp->fnum, blr->fsp->fsp_name )); + blr->fsp->fnum, blr->fsp->fsp_name )); - return True; + /* Push the MID of this packet on the signing queue. */ + srv_defer_sign_response(SVAL(inbuf,smb_mid)); + + return True; } /**************************************************************************** @@ -170,27 +172,27 @@ static void send_blocking_reply(char *outbuf, int outsize) static void reply_lockingX_success(blocking_lock_record *blr) { - char *outbuf = OutBuffer; - int bufsize = BUFFER_SIZE; - char *inbuf = blr->inbuf; - int outsize = 0; + char *outbuf = OutBuffer; + int bufsize = BUFFER_SIZE; + char *inbuf = blr->inbuf; + int outsize = 0; - construct_reply_common(inbuf, outbuf); - set_message(outbuf,2,0,True); + construct_reply_common(inbuf, outbuf); + set_message(outbuf,2,0,True); - /* - * As this message is a lockingX call we must handle - * any following chained message correctly. - * This is normally handled in construct_reply(), - * but as that calls switch_message, we can't use - * that here and must set up the chain info manually. - */ + /* + * As this message is a lockingX call we must handle + * any following chained message correctly. + * This is normally handled in construct_reply(), + * but as that calls switch_message, we can't use + * that here and must set up the chain info manually. + */ - outsize = chain_reply(inbuf,outbuf,blr->length,bufsize); + outsize = chain_reply(inbuf,outbuf,blr->length,bufsize); - outsize += chain_size; + outsize += chain_size; - send_blocking_reply(outbuf,outsize); + send_blocking_reply(outbuf,outsize); } /**************************************************************************** @@ -492,18 +494,18 @@ Waiting....\n", static BOOL blocking_lock_record_process(blocking_lock_record *blr) { - switch(blr->com_type) { - case SMBlock: - return process_lock(blr); - case SMBlockread: - return process_lockread(blr); - case SMBlockingX: - return process_lockingX(blr); - default: - DEBUG(0,("blocking_lock_record_process: PANIC - unknown type on blocking lock queue - exiting.!\n")); - exit_server("PANIC - unknown type on blocking lock queue"); - } - return False; /* Keep compiler happy. */ + switch(blr->com_type) { + case SMBlock: + return process_lock(blr); + case SMBlockread: + return process_lockread(blr); + case SMBlockingX: + return process_lockingX(blr); + default: + DEBUG(0,("blocking_lock_record_process: PANIC - unknown type on blocking lock queue - exiting.!\n")); + exit_server("PANIC - unknown type on blocking lock queue"); + } + return False; /* Keep compiler happy. */ } /**************************************************************************** @@ -512,27 +514,27 @@ static BOOL blocking_lock_record_process(blocking_lock_record *blr) void remove_pending_lock_requests_by_fid(files_struct *fsp) { - blocking_lock_record *blr = (blocking_lock_record *)ubi_slFirst( &blocking_lock_queue ); - blocking_lock_record *prev = NULL; + blocking_lock_record *blr = (blocking_lock_record *)ubi_slFirst( &blocking_lock_queue ); + blocking_lock_record *prev = NULL; - while(blr != NULL) { - if(blr->fsp->fnum == fsp->fnum) { + while(blr != NULL) { + if(blr->fsp->fnum == fsp->fnum) { - DEBUG(10,("remove_pending_lock_requests_by_fid - removing request type %d for \ + DEBUG(10,("remove_pending_lock_requests_by_fid - removing request type %d for \ file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum )); - brl_unlock(blr->fsp->dev, blr->fsp->inode, blr->fsp->fnum, - blr->lock_pid, sys_getpid(), blr->fsp->conn->cnum, - blr->offset, blr->count, True, NULL, NULL); + brl_unlock(blr->fsp->dev, blr->fsp->inode, blr->fsp->fnum, + blr->lock_pid, sys_getpid(), blr->fsp->conn->cnum, + blr->offset, blr->count, True, NULL, NULL); - 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; - } + 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; + } - prev = blr; - blr = (blocking_lock_record *)ubi_slNext(blr); - } + prev = blr; + blr = (blocking_lock_record *)ubi_slNext(blr); + } } /**************************************************************************** @@ -541,28 +543,28 @@ file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum )); void remove_pending_lock_requests_by_mid(int mid) { - blocking_lock_record *blr = (blocking_lock_record *)ubi_slFirst( &blocking_lock_queue ); - blocking_lock_record *prev = NULL; + blocking_lock_record *blr = (blocking_lock_record *)ubi_slFirst( &blocking_lock_queue ); + blocking_lock_record *prev = NULL; - while(blr != NULL) { - if(SVAL(blr->inbuf,smb_mid) == mid) { - files_struct *fsp = blr->fsp; + while(blr != NULL) { + if(SVAL(blr->inbuf,smb_mid) == mid) { + files_struct *fsp = blr->fsp; - DEBUG(10,("remove_pending_lock_requests_by_mid - removing request type %d for \ + DEBUG(10,("remove_pending_lock_requests_by_mid - removing request type %d for \ file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum )); - blocking_lock_reply_error(blr,NT_STATUS_CANCELLED); - brl_unlock(blr->fsp->dev, blr->fsp->inode, blr->fsp->fnum, - blr->lock_pid, sys_getpid(), blr->fsp->conn->cnum, - blr->offset, blr->count, True, NULL, NULL); - 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; - } - - prev = blr; - blr = (blocking_lock_record *)ubi_slNext(blr); - } + blocking_lock_reply_error(blr,NT_STATUS_CANCELLED); + brl_unlock(blr->fsp->dev, blr->fsp->inode, blr->fsp->fnum, + blr->lock_pid, sys_getpid(), blr->fsp->conn->cnum, + blr->offset, blr->count, True, NULL, NULL); + 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; + } + + prev = blr; + blr = (blocking_lock_record *)ubi_slNext(blr); + } } /**************************************************************************** @@ -611,112 +613,112 @@ unsigned blocking_locks_timeout(unsigned default_timeout) void process_blocking_lock_queue(time_t t) { - blocking_lock_record *blr = (blocking_lock_record *)ubi_slFirst( &blocking_lock_queue ); - blocking_lock_record *prev = NULL; - - if(blr == NULL) - return; - - /* - * Go through the queue and see if we can get any of the locks. - */ - - while(blr != NULL) { - connection_struct *conn = NULL; - uint16 vuid; - files_struct *fsp = NULL; - - /* - * Ensure we don't have any old chain_fsp values - * sitting around.... - */ - chain_size = 0; - file_chain_reset(); - fsp = blr->fsp; - - conn = conn_find(SVAL(blr->inbuf,smb_tid)); - vuid = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : - SVAL(blr->inbuf,smb_uid); - - 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)) { - /* - * Lock expired - throw away all previously - * obtained locks and return lock error. - */ - DEBUG(5,("process_blocking_lock_queue: pending lock fnum = %d for file %s timed out.\n", - fsp->fnum, fsp->fsp_name )); - - brl_unlock(fsp->dev, fsp->inode, fsp->fnum, - blr->lock_pid, sys_getpid(), conn->cnum, - blr->offset, blr->count, True, NULL, NULL); - - 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; - } - - if(!change_to_user(conn,vuid)) { - DEBUG(0,("process_blocking_lock_queue: Unable to become user vuid=%d.\n", - vuid )); - /* - * Remove the entry and return an error to the client. - */ - blocking_lock_reply_error(blr,NT_STATUS_ACCESS_DENIED); - - brl_unlock(fsp->dev, fsp->inode, fsp->fnum, - blr->lock_pid, sys_getpid(), conn->cnum, - blr->offset, blr->count, True, NULL, NULL); - - 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; - } - - if(!set_current_service(conn,True)) { - DEBUG(0,("process_blocking_lock_queue: Unable to become service Error was %s.\n", strerror(errno) )); - /* - * Remove the entry and return an error to the client. - */ - blocking_lock_reply_error(blr,NT_STATUS_ACCESS_DENIED); - - brl_unlock(fsp->dev, fsp->inode, fsp->fnum, - blr->lock_pid, sys_getpid(), conn->cnum, - blr->offset, blr->count, True, NULL, NULL); - - 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)); - change_to_root_user(); - continue; - } - - /* - * Go through the remaining locks and try and obtain them. - * The call returns True if all locks were obtained successfully - * and False if we still need to wait. - */ - - if(blocking_lock_record_process(blr)) { - - brl_unlock(fsp->dev, fsp->inode, fsp->fnum, - blr->lock_pid, sys_getpid(), conn->cnum, - blr->offset, blr->count, True, NULL, NULL); - - 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)); - change_to_root_user(); - continue; - } - - change_to_root_user(); - - /* - * Move to the next in the list. - */ - prev = blr; - blr = (blocking_lock_record *)ubi_slNext(blr); - } + blocking_lock_record *blr = (blocking_lock_record *)ubi_slFirst( &blocking_lock_queue ); + blocking_lock_record *prev = NULL; + + if(blr == NULL) + return; + + /* + * Go through the queue and see if we can get any of the locks. + */ + + while(blr != NULL) { + connection_struct *conn = NULL; + uint16 vuid; + files_struct *fsp = NULL; + + /* + * Ensure we don't have any old chain_fsp values + * sitting around.... + */ + chain_size = 0; + file_chain_reset(); + fsp = blr->fsp; + + conn = conn_find(SVAL(blr->inbuf,smb_tid)); + vuid = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : + SVAL(blr->inbuf,smb_uid); + + 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)) { + /* + * Lock expired - throw away all previously + * obtained locks and return lock error. + */ + DEBUG(5,("process_blocking_lock_queue: pending lock fnum = %d for file %s timed out.\n", + fsp->fnum, fsp->fsp_name )); + + brl_unlock(fsp->dev, fsp->inode, fsp->fnum, + blr->lock_pid, sys_getpid(), conn->cnum, + blr->offset, blr->count, True, NULL, NULL); + + 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; + } + + if(!change_to_user(conn,vuid)) { + DEBUG(0,("process_blocking_lock_queue: Unable to become user vuid=%d.\n", + vuid )); + /* + * Remove the entry and return an error to the client. + */ + blocking_lock_reply_error(blr,NT_STATUS_ACCESS_DENIED); + + brl_unlock(fsp->dev, fsp->inode, fsp->fnum, + blr->lock_pid, sys_getpid(), conn->cnum, + blr->offset, blr->count, True, NULL, NULL); + + 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; + } + + if(!set_current_service(conn,True)) { + DEBUG(0,("process_blocking_lock_queue: Unable to become service Error was %s.\n", strerror(errno) )); + /* + * Remove the entry and return an error to the client. + */ + blocking_lock_reply_error(blr,NT_STATUS_ACCESS_DENIED); + + brl_unlock(fsp->dev, fsp->inode, fsp->fnum, + blr->lock_pid, sys_getpid(), conn->cnum, + blr->offset, blr->count, True, NULL, NULL); + + 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)); + change_to_root_user(); + continue; + } + + /* + * Go through the remaining locks and try and obtain them. + * The call returns True if all locks were obtained successfully + * and False if we still need to wait. + */ + + if(blocking_lock_record_process(blr)) { + + brl_unlock(fsp->dev, fsp->inode, fsp->fnum, + blr->lock_pid, sys_getpid(), conn->cnum, + blr->offset, blr->count, True, NULL, NULL); + + 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)); + change_to_root_user(); + continue; + } + + change_to_root_user(); + + /* + * Move to the next in the list. + */ + prev = blr; + blr = (blocking_lock_record *)ubi_slNext(blr); + } } diff --git a/source3/smbd/change_trust_pw.c b/source3/smbd/change_trust_pw.c index 4993e285ca..2eff77b1f7 100644 --- a/source3/smbd/change_trust_pw.c +++ b/source3/smbd/change_trust_pw.c @@ -58,7 +58,7 @@ NTSTATUS change_trust_account_password( const char *domain, const char *remote_m NULL, 0, "IPC$", "IPC", "", "", - "", 0, NULL))) + "", 0, Undefined, NULL))) { DEBUG(0,("modify_trust_password: Connection to %s failed!\n", remote_machine)); nt_status = NT_STATUS_UNSUCCESSFUL; diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 5c1d9a79a6..6bc8626d81 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -674,6 +674,8 @@ BOOL check_lanman_password(char *user, uchar * pass1, Code to change the lanman hashed password. It nulls out the NT hashed password as it will no longer be valid. + NOTE this function is designed to be called as root. Check the old password + is correct before calling. JRA. ************************************************************/ BOOL change_lanman_password(SAM_ACCOUNT *sampass, uchar *pass2) @@ -730,9 +732,7 @@ BOOL change_lanman_password(SAM_ACCOUNT *sampass, uchar *pass2) } /* Now flush the sam_passwd struct to persistent storage */ - become_root(); ret = pdb_update_sam_account (sampass); - unbecome_root(); return ret; } @@ -740,6 +740,7 @@ BOOL change_lanman_password(SAM_ACCOUNT *sampass, uchar *pass2) /*********************************************************** Code to check and change the OEM hashed password. ************************************************************/ + NTSTATUS pass_oem_change(char *user, uchar * lmdata, uchar * lmhash, uchar * ntdata, uchar * nthash) @@ -747,8 +748,7 @@ NTSTATUS pass_oem_change(char *user, fstring new_passwd; const char *unix_user; SAM_ACCOUNT *sampass = NULL; - NTSTATUS nt_status - = check_oem_password(user, lmdata, lmhash, ntdata, nthash, + NTSTATUS nt_status = check_oem_password(user, lmdata, lmhash, ntdata, nthash, &sampass, new_passwd, sizeof(new_passwd)); if (!NT_STATUS_IS_OK(nt_status)) @@ -765,7 +765,10 @@ NTSTATUS pass_oem_change(char *user, unix_user = pdb_get_username(sampass); + /* We've already checked the old password here.... */ + become_root(); nt_status = change_oem_password(sampass, NULL, new_passwd); + unbecome_root(); memset(new_passwd, 0, sizeof(new_passwd)); @@ -942,6 +945,8 @@ static NTSTATUS check_oem_password(const char *user, /*********************************************************** Code to change the oem password. Changes both the lanman and NT hashes. Old_passwd is almost always NULL. + NOTE this function is designed to be called as root. Check the old password + is correct before calling. JRA. ************************************************************/ NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passwd) @@ -997,9 +1002,7 @@ NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passw } /* Now write it into the file. */ - become_root(); ret = pdb_update_sam_account (hnd); - unbecome_root(); if (!ret) { return NT_STATUS_ACCESS_DENIED; diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 1be13270ba..0700aeaa0a 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -163,8 +163,8 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close) share_entry_count = del_share_mode(fsp, &share_entry); - DEBUG(10,("close_normal_file: share_entry_count = %d for file %s\n", - share_entry_count, fsp->fsp_name )); + DEBUG(10,("close_normal_file: share_entry_count = %lu for file %s\n", + (unsigned long)share_entry_count, fsp->fsp_name )); /* * We delete on close if it's the last open, and the diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 85e28f5d17..39072f9b91 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -428,6 +428,8 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int } + srv_signing_trans_start(SVAL(inbuf,smb_mid)); + if (pscnt < tpscnt || dscnt < tdscnt) { /* We need to send an interim response then receive the rest of the parameter/data bytes */ @@ -455,6 +457,7 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int SAFE_FREE(data); SAFE_FREE(setup); END_PROFILE(SMBtrans); + srv_signing_trans_stop(); return(ERROR_DOS(ERRSRV,ERRerror)); } @@ -506,11 +509,10 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int memcpy(data+ddisp,smb_base(inbuf)+doff,dcnt); } } - - + DEBUG(3,("trans <%s> data=%u params=%u setup=%u\n", name,tdscnt,tpscnt,suwcnt)); - + /* * WinCE wierdness.... */ @@ -542,6 +544,8 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int SAFE_FREE(params); SAFE_FREE(setup); + srv_signing_trans_stop(); + if (close_on_completion) close_cnum(conn,vuid); @@ -561,6 +565,7 @@ int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int bad_param: + srv_signing_trans_stop(); DEBUG(0,("reply_trans: invalid trans parameters\n")); SAFE_FREE(data); SAFE_FREE(params); diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 04d6a9a8a8..a5f7a7b2ea 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1897,76 +1897,78 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param char **rdata,char **rparam, int *rdata_len,int *rparam_len) { - char *p = skip_string(param+2,2); - fstring user; - fstring pass1,pass2; + char *p = skip_string(param+2,2); + fstring user; + fstring pass1,pass2; - pull_ascii_fstring(user,p); + pull_ascii_fstring(user,p); - p = skip_string(p,1); + p = skip_string(p,1); - memset(pass1,'\0',sizeof(pass1)); - memset(pass2,'\0',sizeof(pass2)); - memcpy(pass1,p,16); - memcpy(pass2,p+16,16); + memset(pass1,'\0',sizeof(pass1)); + memset(pass2,'\0',sizeof(pass2)); + memcpy(pass1,p,16); + memcpy(pass2,p+16,16); - *rparam_len = 4; - *rparam = REALLOC(*rparam,*rparam_len); + *rparam_len = 4; + *rparam = REALLOC(*rparam,*rparam_len); - *rdata_len = 0; + *rdata_len = 0; - SSVAL(*rparam,0,NERR_badpass); - SSVAL(*rparam,2,0); /* converter word */ + SSVAL(*rparam,0,NERR_badpass); + SSVAL(*rparam,2,0); /* converter word */ - DEBUG(3,("Set password for <%s>\n",user)); + DEBUG(3,("Set password for <%s>\n",user)); - /* - * Attempt to verify the old password against smbpasswd entries - * Win98 clients send old and new password in plaintext for this call. - */ + /* + * Attempt to verify the old password against smbpasswd entries + * Win98 clients send old and new password in plaintext for this call. + */ - { - auth_serversupplied_info *server_info = NULL; - DATA_BLOB password = data_blob(pass1, strlen(pass1)+1); - if (NT_STATUS_IS_OK(check_plaintext_password(user,password,&server_info))) { - - if (NT_STATUS_IS_OK(change_oem_password(server_info->sam_account, pass1, pass2))) - { - SSVAL(*rparam,0,NERR_Success); - } - - free_server_info(&server_info); - } - data_blob_clear_free(&password); - } + { + auth_serversupplied_info *server_info = NULL; + DATA_BLOB password = data_blob(pass1, strlen(pass1)+1); - /* - * If the plaintext change failed, attempt - * the old encrypted method. NT will generate this - * after trying the samr method. Note that this - * method is done as a last resort as this - * password change method loses the NT password hash - * and cannot change the UNIX password as no plaintext - * is received. - */ + if (NT_STATUS_IS_OK(check_plaintext_password(user,password,&server_info))) { - if(SVAL(*rparam,0) != NERR_Success) - { - SAM_ACCOUNT *hnd = NULL; + become_root(); + if (NT_STATUS_IS_OK(change_oem_password(server_info->sam_account, pass1, pass2))) { + SSVAL(*rparam,0,NERR_Success); + } + unbecome_root(); - if (check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &hnd) && - change_lanman_password(hnd,pass2)) - { - SSVAL(*rparam,0,NERR_Success); - } - pdb_free_sam(&hnd); - } + free_server_info(&server_info); + } + data_blob_clear_free(&password); + } + /* + * If the plaintext change failed, attempt + * the old encrypted method. NT will generate this + * after trying the samr method. Note that this + * method is done as a last resort as this + * password change method loses the NT password hash + * and cannot change the UNIX password as no plaintext + * is received. + */ + + if(SVAL(*rparam,0) != NERR_Success) { + SAM_ACCOUNT *hnd = NULL; - memset((char *)pass1,'\0',sizeof(fstring)); - memset((char *)pass2,'\0',sizeof(fstring)); + if (check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &hnd)) { + become_root(); + if (change_lanman_password(hnd,pass2)) { + SSVAL(*rparam,0,NERR_Success); + } + unbecome_root(); + pdb_free_sam(&hnd); + } + } + + memset((char *)pass1,'\0',sizeof(fstring)); + memset((char *)pass2,'\0',sizeof(fstring)); - return(True); + return(True); } /**************************************************************************** diff --git a/source3/smbd/mangle_hash.c b/source3/smbd/mangle_hash.c index ac8e425fd3..ac2d7681e8 100644 --- a/source3/smbd/mangle_hash.c +++ b/source3/smbd/mangle_hash.c @@ -313,6 +313,7 @@ static BOOL is_8_3(const char *fname, BOOL check_case, BOOL allow_wildcards) const char *f; smb_ucs2_t *ucs2name; NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; + size_t size; if (!fname || !*fname) return False; @@ -324,9 +325,9 @@ static BOOL is_8_3(const char *fname, BOOL check_case, BOOL allow_wildcards) if (strlen(f) > 12) return False; - ucs2name = acnv_uxu2(f); - if (!ucs2name) { - DEBUG(0,("is_8_3: internal error acnv_uxu2() failed!\n")); + size = push_ucs2_allocate(&ucs2name, f); + if (size == (size_t)-1) { + DEBUG(0,("is_8_3: internal error push_ucs2_allocate() failed!\n")); goto done; } diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index f452dd845b..28e3cf97d1 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -277,6 +277,22 @@ static int reply_nt1(char *inbuf, char *outbuf) if (global_encrypted_passwords_negotiated) secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE; + if (lp_server_signing()) { + if (lp_security() >= SEC_USER) { + secword |= NEGOTIATE_SECURITY_SIGNATURES_ENABLED; + /* No raw mode with smb signing. */ + capabilities &= ~CAP_RAW_MODE; + if (lp_server_signing() == Required) + secword |=NEGOTIATE_SECURITY_SIGNATURES_REQUIRED; + srv_set_signing_negotiated(); + } else { + DEBUG(0,("reply_nt1: smb signing is incompatible with share level security !\n")); + if (lp_server_signing() == Required) { + exit_server("reply_nt1: smb signing required and share level security selected."); + } + } + } + set_message(outbuf,17,0,True); SCVAL(outbuf,smb_vwv1,secword); @@ -521,6 +537,10 @@ int reply_negprot(connection_struct *conn, DEBUG( 5, ( "negprot index=%d\n", choice ) ); + if ((lp_server_signing() == Required) && (Protocol < PROTOCOL_NT1)) { + exit_server("SMB signing is required and client negotiated a downlevel protocol"); + } + END_PROFILE(SMBnegprot); return(outsize); } diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index de1b331778..9adf827c79 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -44,6 +44,7 @@ static struct change_notify *change_notify_list; /**************************************************************************** Setup the common parts of the return packet and send it. *****************************************************************************/ + static void change_notify_reply_packet(char *inbuf, NTSTATUS error_code) { char outbuf[smb_size+38]; @@ -178,7 +179,7 @@ BOOL change_notify_set(char *inbuf, files_struct *fsp, connection_struct *conn, struct change_notify *cnbp; if((cnbp = (struct change_notify *)malloc(sizeof(*cnbp))) == NULL) { - DEBUG(0,("call_nt_transact_notify_change: malloc fail !\n" )); + DEBUG(0,("change_notify_set: malloc fail !\n" )); return -1; } @@ -197,6 +198,9 @@ BOOL change_notify_set(char *inbuf, files_struct *fsp, connection_struct *conn, DLIST_ADD(change_notify_list, cnbp); + /* Push the MID of this packet on the signing queue. */ + srv_defer_sign_response(SVAL(inbuf,smb_mid)); + return True; } diff --git a/source3/smbd/ntquotas.c b/source3/smbd/ntquotas.c index 2e865000ec..88d7c4e164 100644 --- a/source3/smbd/ntquotas.c +++ b/source3/smbd/ntquotas.c @@ -188,7 +188,7 @@ int vfs_get_user_ntquota_list(files_struct *fsp, SMB_NTQUOTA_LIST **qt_list) } if (vfs_get_ntquota(fsp, SMB_USER_QUOTA_TYPE, &sid, &tmp_qt)!=0) { - DEBUG(1,("no quota entry for sid[%s] path[%s]\n", + DEBUG(5,("no quota entry for sid[%s] path[%s]\n", sid_string_static(&sid),fsp->conn->connectpath)); continue; } diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index c574d9d563..3ffa6efa77 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1443,6 +1443,7 @@ int reply_ntcancel(connection_struct *conn, START_PROFILE(SMBntcancel); remove_pending_change_notify_requests_by_mid(mid); remove_pending_lock_requests_by_mid(mid); + srv_cancel_sign_response(mid); DEBUG(3,("reply_ntcancel: cancel called on mid = %d.\n", mid)); @@ -2321,6 +2322,8 @@ due to being in oplock break state.\n", (unsigned int)function_code )); dump_data(10, data, data_count); } + srv_signing_trans_start(SVAL(inbuf,smb_mid)); + if(num_data_sofar < total_data_count || num_params_sofar < total_parameter_count) { /* We need to send an interim response then receive the rest of the parameter/data bytes */ @@ -2484,6 +2487,7 @@ due to being in oplock break state.\n", (unsigned int)function_code )); SAFE_FREE(params); SAFE_FREE(data); END_PROFILE(SMBnttrans); + srv_signing_trans_stop(); return ERROR_DOS(ERRSRV,ERRerror); } @@ -2494,6 +2498,8 @@ due to being in oplock break state.\n", (unsigned int)function_code )); an error packet. */ + srv_signing_trans_stop(); + SAFE_FREE(setup); SAFE_FREE(params); SAFE_FREE(data); @@ -2504,6 +2510,7 @@ due to being in oplock break state.\n", (unsigned int)function_code )); bad_param: + srv_signing_trans_stop(); SAFE_FREE(params); SAFE_FREE(data); SAFE_FREE(setup); diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 6d03eaa29a..5f49640aa4 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -125,6 +125,7 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, directory. */ flags &= ~O_CREAT; + local_flags &= ~O_CREAT; } } @@ -166,6 +167,14 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, local_flags |= O_NONBLOCK; #endif + /* Don't create files with Microsoft wildcard characters. */ + if ((local_flags & O_CREAT) && !VALID_STAT(*psbuf) && ms_has_wild(fname)) { + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRinvalidname; + unix_ERR_ntstatus = NT_STATUS_OBJECT_NAME_INVALID; + return False; + } + /* Actually do the open */ fsp->fd = fd_open(conn, fname, local_flags, mode); if (fsp->fd == -1) { @@ -675,8 +684,8 @@ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (dou dev = %x, inode = %.0f. Deleting it to continue...\n", (int)broken_entry.pid, fname, (unsigned int)dev, (double)inode)); if (process_exists(broken_entry.pid)) { - DEBUG(0,("open_mode_check: Existent process %d left active oplock.\n", - broken_entry.pid )); + DEBUG(0,("open_mode_check: Existent process %lu left active oplock.\n", + (unsigned long)broken_entry.pid )); } if (del_share_entry(dev, inode, &broken_entry, NULL) == -1) { @@ -874,7 +883,7 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ if (file_existed && (GET_FILE_OPEN_DISPOSITION(ofun) == FILE_EXISTS_TRUNCATE)) { if (!open_match_attributes(conn, fname, psbuf->st_mode, mode, &new_mode)) { DEBUG(5,("open_file_shared: attributes missmatch for file %s (0%o, 0%o)\n", - fname, psbuf->st_mode, mode )); + fname, (int)psbuf->st_mode, (int)mode )); file_free(fsp); errno = EACCES; return NULL; @@ -1290,6 +1299,15 @@ files_struct *open_directory(connection_struct *conn, char *fname, SMB_STRUCT_ST return NULL; } + if (ms_has_wild(fname)) { + file_free(fsp); + DEBUG(5,("open_directory: failing create on filename %s with wildcards\n", fname)); + unix_ERR_class = ERRDOS; + unix_ERR_code = ERRinvalidname; + unix_ERR_ntstatus = NT_STATUS_OBJECT_NAME_INVALID; + return NULL; + } + if(vfs_MkDir(conn,fname, unix_mode(conn,aDIR, fname)) < 0) { DEBUG(2,("open_directory: unable to create %s. Error was %s\n", fname, strerror(errno) )); diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 8525687793..19e6956d9e 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -660,6 +660,7 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_id, time_t start_time; BOOL shutdown_server = False; BOOL oplock_timeout = False; + BOOL sign_state; connection_struct *saved_user_conn; connection_struct *saved_fsp_conn; int saved_vuid; @@ -742,8 +743,16 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_id, /* Remember if we just sent a break to level II on this file. */ fsp->sent_oplock_break = using_levelII? LEVEL_II_BREAK_SENT:EXCLUSIVE_BREAK_SENT; - if (!send_smb(smbd_server_fd(), outbuf)) + /* Save the server smb signing state. */ + sign_state = srv_oplock_set_signing(False); + + if (!send_smb(smbd_server_fd(), outbuf)) { + srv_oplock_set_signing(sign_state); exit_server("oplock_break: send_smb failed."); + } + + /* Restore the sign state to what it was. */ + srv_oplock_set_signing(sign_state); /* We need this in case a readraw crosses on the wire. */ global_oplock_break = True; @@ -791,6 +800,9 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_id, } else if (smb_read_error == READ_ERROR) { DEBUG( 0, ("oplock_break: receive_smb error (%s)\n", strerror(errno)) ); shutdown_server = True; + } else if (smb_read_error == READ_BAD_SIG) { + DEBUG( 0, ("oplock_break: bad signature from client\n" )); + shutdown_server = True; } else if (smb_read_error == READ_TIMEOUT) { DEBUG( 0, ( "oplock_break: receive_smb timed out after %d seconds.\n", OPLOCK_BREAK_TIMEOUT ) ); oplock_timeout = True; diff --git a/source3/smbd/password.c b/source3/smbd/password.c index e2c143f1e2..b988f2ec74 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -29,10 +29,11 @@ static int next_vuid = VUID_OFFSET; static int num_validated_vuids; /**************************************************************************** -check if a uid has been validated, and return an pointer to the user_struct -if it has. NULL if not. vuid is biased by an offset. This allows us to -tell random client vuid's (normally zero) from valid vuids. + Check if a uid has been validated, and return an pointer to the user_struct + if it has. NULL if not. vuid is biased by an offset. This allows us to + tell random client vuid's (normally zero) from valid vuids. ****************************************************************************/ + user_struct *get_valid_user_struct(uint16 vuid) { user_struct *usp; @@ -54,8 +55,9 @@ user_struct *get_valid_user_struct(uint16 vuid) } /**************************************************************************** -invalidate a uid + Invalidate a uid. ****************************************************************************/ + void invalidate_vuid(uint16 vuid) { user_struct *vuser = get_valid_user_struct(vuid); @@ -85,8 +87,9 @@ void invalidate_vuid(uint16 vuid) } /**************************************************************************** -invalidate all vuid entries for this process + Invalidate all vuid entries for this process. ****************************************************************************/ + void invalidate_all_vuids(void) { user_struct *usp, *next=NULL; @@ -108,7 +111,7 @@ void invalidate_all_vuids(void) * */ -int register_vuid(auth_serversupplied_info *server_info, const char *smb_name) +int register_vuid(auth_serversupplied_info *server_info, DATA_BLOB response_blob, const char *smb_name) { user_struct *vuser = NULL; @@ -238,38 +241,42 @@ int register_vuid(auth_serversupplied_info *server_info, const char *smb_name) vuser->homes_snum = -1; } + if (lp_server_signing() && !vuser->guest && !srv_is_signing_active()) { + /* Try and turn on server signing on the first non-guest sessionsetup. */ + srv_set_signing(vuser->session_key, response_blob); + } + return vuser->vuid; } - /**************************************************************************** -add a name to the session users list + Add a name to the session users list. ****************************************************************************/ + void add_session_user(const char *user) { - fstring suser; - struct passwd *passwd; + fstring suser; + struct passwd *passwd; - if (!(passwd = Get_Pwnam(user))) return; + if (!(passwd = Get_Pwnam(user))) + return; - fstrcpy(suser,passwd->pw_name); + fstrcpy(suser,passwd->pw_name); - if (suser && *suser && !in_list(suser,session_users,False)) - { - if (strlen(suser) + strlen(session_users) + 2 >= sizeof(pstring)) - DEBUG(1,("Too many session users??\n")); - else - { - pstrcat(session_users," "); - pstrcat(session_users,suser); + if (suser && *suser && !in_list(suser,session_users,False)) { + if (strlen(suser) + strlen(session_users) + 2 >= sizeof(pstring)) { + DEBUG(1,("Too many session users??\n")); + } else { + pstrcat(session_users," "); + pstrcat(session_users,suser); + } } - } } - /**************************************************************************** -check if a username is valid + Check if a username is valid. ****************************************************************************/ + BOOL user_ok(const char *user,int snum, gid_t *groups, size_t n_groups) { char **valid, **invalid; @@ -308,8 +315,9 @@ BOOL user_ok(const char *user,int snum, gid_t *groups, size_t n_groups) } /**************************************************************************** -validate a group username entry. Return the username or NULL + Validate a group username entry. Return the username or NULL. ****************************************************************************/ + static char *validate_group(char *group, DATA_BLOB password,int snum) { #ifdef HAVE_NETGROUP diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 18acb35f7a..dce1c4bc03 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -53,9 +53,9 @@ extern int max_send; ****************************************************************************/ typedef struct { - ubi_slNode msg_next; - char *msg_buf; - int msg_len; + ubi_slNode msg_next; + char *msg_buf; + int msg_len; } pending_message_list; static ubi_slList smb_oplock_queue = { NULL, (ubi_slNodePtr)&smb_oplock_queue, 0}; @@ -67,29 +67,30 @@ static ubi_slList smb_oplock_queue = { NULL, (ubi_slNodePtr)&smb_oplock_queue, 0 static BOOL push_message(ubi_slList *list_head, char *buf, int msg_len) { - pending_message_list *msg = (pending_message_list *) + pending_message_list *msg = (pending_message_list *) malloc(sizeof(pending_message_list)); - if(msg == NULL) - { - DEBUG(0,("push_message: malloc fail (1)\n")); - return False; - } + if(msg == NULL) { + DEBUG(0,("push_message: malloc fail (1)\n")); + return False; + } - msg->msg_buf = (char *)malloc(msg_len); - if(msg->msg_buf == NULL) - { - DEBUG(0,("push_message: malloc fail (2)\n")); - SAFE_FREE(msg); - return False; - } + msg->msg_buf = (char *)malloc(msg_len); + if(msg->msg_buf == NULL) { + DEBUG(0,("push_message: malloc fail (2)\n")); + SAFE_FREE(msg); + return False; + } + + memcpy(msg->msg_buf, buf, msg_len); + msg->msg_len = msg_len; - memcpy(msg->msg_buf, buf, msg_len); - msg->msg_len = msg_len; + ubi_slAddTail( list_head, msg); - ubi_slAddTail( list_head, msg); + /* Push the MID of this packet on the signing queue. */ + srv_defer_sign_response(SVAL(buf,smb_mid)); - return True; + return True; } /**************************************************************************** @@ -295,28 +296,29 @@ BOOL receive_next_smb(char *inbuf, int bufsize, int timeout) void respond_to_all_remaining_local_messages(void) { - char buffer[1024]; - - /* - * Assert we have no exclusive open oplocks. - */ - - if(get_number_of_exclusive_open_oplocks()) { - DEBUG(0,("respond_to_all_remaining_local_messages: PANIC : we have %d exclusive oplocks.\n", - get_number_of_exclusive_open_oplocks() )); - return; - } - - /* - * Keep doing receive_local_message with a 1 ms timeout until - * we have no more messages. - */ - while(receive_local_message(buffer, sizeof(buffer), 1)) { - /* Deal with oplock break requests from other smbd's. */ - process_local_message(buffer, sizeof(buffer)); - } - - return; + char buffer[1024]; + + /* + * Assert we have no exclusive open oplocks. + */ + + if(get_number_of_exclusive_open_oplocks()) { + DEBUG(0,("respond_to_all_remaining_local_messages: PANIC : we have %d exclusive oplocks.\n", + get_number_of_exclusive_open_oplocks() )); + return; + } + + /* + * Keep doing receive_local_message with a 1 ms timeout until + * we have no more messages. + */ + + while(receive_local_message(buffer, sizeof(buffer), 1)) { + /* Deal with oplock break requests from other smbd's. */ + process_local_message(buffer, sizeof(buffer)); + } + + return; } @@ -339,13 +341,11 @@ force write permissions on print services. functions. Any message that has a NULL function is unimplemented - please feel free to contribute implementations! */ -static const struct smb_message_struct -{ - const char *name; - int (*fn)(connection_struct *conn, char *, char *, int, int); - int flags; -} - smb_messages[256] = { +static const struct smb_message_struct { + const char *name; + int (*fn)(connection_struct *conn, char *, char *, int, int); + int flags; +} smb_messages[256] = { /* 0x00 */ { "SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE}, /* 0x01 */ { "SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE}, @@ -849,67 +849,62 @@ set. Ignoring max smbd restriction.\n")); } /**************************************************************************** - process an smb from the client - split out from the smbd_process() code so - it can be used by the oplock break code. + Process an smb from the client - split out from the smbd_process() code so + it can be used by the oplock break code. ****************************************************************************/ + void process_smb(char *inbuf, char *outbuf) { - static int trans_num; - int msg_type = CVAL(inbuf,0); - int32 len = smb_len(inbuf); - int nread = len + 4; - - DO_PROFILE_INC(smb_count); - - if (trans_num == 0) { - /* on the first packet, check the global hosts allow/ hosts - deny parameters before doing any parsing of the packet - passed to us by the client. This prevents attacks on our - parsing code from hosts not in the hosts allow list */ - if (smbd_process_limit() || - !check_access(smbd_server_fd(), lp_hostsallow(-1), lp_hostsdeny(-1))) { - /* send a negative session response "not listening on calling - name" */ - static unsigned char buf[5] = {0x83, 0, 0, 1, 0x81}; - DEBUG( 1, ( "Connection denied from %s\n", - client_addr() ) ); - (void)send_smb(smbd_server_fd(),(char *)buf); - exit_server("connection denied"); - } - } - - DEBUG( 6, ( "got message type 0x%x of len 0x%x\n", msg_type, len ) ); - DEBUG( 3, ( "Transaction %d of length %d\n", trans_num, nread ) ); - - if (msg_type == 0) - show_msg(inbuf); - else if(msg_type == SMBkeepalive) - return; /* Keepalive packet. */ - - nread = construct_reply(inbuf,outbuf,nread,max_send); + static int trans_num; + int msg_type = CVAL(inbuf,0); + int32 len = smb_len(inbuf); + int nread = len + 4; + + DO_PROFILE_INC(smb_count); + + if (trans_num == 0) { + /* on the first packet, check the global hosts allow/ hosts + deny parameters before doing any parsing of the packet + passed to us by the client. This prevents attacks on our + parsing code from hosts not in the hosts allow list */ + if (smbd_process_limit() || + !check_access(smbd_server_fd(), lp_hostsallow(-1), lp_hostsdeny(-1))) { + /* send a negative session response "not listening on calling name" */ + static unsigned char buf[5] = {0x83, 0, 0, 1, 0x81}; + DEBUG( 1, ( "Connection denied from %s\n", client_addr() ) ); + (void)send_smb(smbd_server_fd(),(char *)buf); + exit_server("connection denied"); + } + } + + DEBUG( 6, ( "got message type 0x%x of len 0x%x\n", msg_type, len ) ); + DEBUG( 3, ( "Transaction %d of length %d\n", trans_num, nread ) ); + + if (msg_type == 0) + show_msg(inbuf); + else if(msg_type == SMBkeepalive) + return; /* Keepalive packet. */ + + nread = construct_reply(inbuf,outbuf,nread,max_send); - if(nread > 0) - { - if (CVAL(outbuf,0) == 0) - show_msg(outbuf); + if(nread > 0) { + if (CVAL(outbuf,0) == 0) + show_msg(outbuf); - if (nread != smb_len(outbuf) + 4) - { - DEBUG(0,("ERROR: Invalid message response size! %d %d\n", - nread, smb_len(outbuf))); - } - else - if (!send_smb(smbd_server_fd(),outbuf)) - exit_server("process_smb: send_smb failed."); - } - trans_num++; + if (nread != smb_len(outbuf) + 4) { + DEBUG(0,("ERROR: Invalid message response size! %d %d\n", + nread, smb_len(outbuf))); + } else if (!send_smb(smbd_server_fd(),outbuf)) { + exit_server("process_smb: send_smb failed."); + } + } + trans_num++; } - - /**************************************************************************** -return a string containing the function name of a SMB command + Return a string containing the function name of a SMB command. ****************************************************************************/ + const char *smb_fn_name(int type) { const char *unknown_name = "SMBunknown"; @@ -949,92 +944,94 @@ void construct_reply_common(char *inbuf,char *outbuf) } /**************************************************************************** - construct a chained reply and add it to the already made reply - **************************************************************************/ + Construct a chained reply and add it to the already made reply +****************************************************************************/ + int chain_reply(char *inbuf,char *outbuf,int size,int bufsize) { - static char *orig_inbuf; - static char *orig_outbuf; - int smb_com1, smb_com2 = CVAL(inbuf,smb_vwv0); - unsigned smb_off2 = SVAL(inbuf,smb_vwv1); - char *inbuf2, *outbuf2; - int outsize2; - char inbuf_saved[smb_wct]; - char outbuf_saved[smb_wct]; - int wct = CVAL(outbuf,smb_wct); - int outsize = smb_size + 2*wct + SVAL(outbuf,smb_vwv0+2*wct); - - /* maybe its not chained */ - if (smb_com2 == 0xFF) { - SCVAL(outbuf,smb_vwv0,0xFF); - return outsize; - } - - if (chain_size == 0) { - /* this is the first part of the chain */ - orig_inbuf = inbuf; - orig_outbuf = outbuf; - } - - /* - * The original Win95 redirector dies on a reply to - * a lockingX and read chain unless the chain reply is - * 4 byte aligned. JRA. - */ - - outsize = (outsize + 3) & ~3; - - /* we need to tell the client where the next part of the reply will be */ - SSVAL(outbuf,smb_vwv1,smb_offset(outbuf+outsize,outbuf)); - SCVAL(outbuf,smb_vwv0,smb_com2); - - /* remember how much the caller added to the chain, only counting stuff - after the parameter words */ - chain_size += outsize - smb_wct; - - /* work out pointers into the original packets. The - headers on these need to be filled in */ - inbuf2 = orig_inbuf + smb_off2 + 4 - smb_wct; - outbuf2 = orig_outbuf + SVAL(outbuf,smb_vwv1) + 4 - smb_wct; - - /* remember the original command type */ - smb_com1 = CVAL(orig_inbuf,smb_com); - - /* save the data which will be overwritten by the new headers */ - memcpy(inbuf_saved,inbuf2,smb_wct); - memcpy(outbuf_saved,outbuf2,smb_wct); - - /* give the new packet the same header as the last part of the SMB */ - memmove(inbuf2,inbuf,smb_wct); - - /* create the in buffer */ - SCVAL(inbuf2,smb_com,smb_com2); - - /* create the out buffer */ - construct_reply_common(inbuf2, outbuf2); - - DEBUG(3,("Chained message\n")); - show_msg(inbuf2); - - /* process the request */ - outsize2 = switch_message(smb_com2,inbuf2,outbuf2,size-chain_size, - bufsize-chain_size); - - /* copy the new reply and request headers over the old ones, but - preserve the smb_com field */ - memmove(orig_outbuf,outbuf2,smb_wct); - SCVAL(orig_outbuf,smb_com,smb_com1); - - /* restore the saved data, being careful not to overwrite any - data from the reply header */ - memcpy(inbuf2,inbuf_saved,smb_wct); - { - int ofs = smb_wct - PTR_DIFF(outbuf2,orig_outbuf); - if (ofs < 0) ofs = 0; - memmove(outbuf2+ofs,outbuf_saved+ofs,smb_wct-ofs); - } - - return outsize2; + static char *orig_inbuf; + static char *orig_outbuf; + int smb_com1, smb_com2 = CVAL(inbuf,smb_vwv0); + unsigned smb_off2 = SVAL(inbuf,smb_vwv1); + char *inbuf2, *outbuf2; + int outsize2; + char inbuf_saved[smb_wct]; + char outbuf_saved[smb_wct]; + int wct = CVAL(outbuf,smb_wct); + int outsize = smb_size + 2*wct + SVAL(outbuf,smb_vwv0+2*wct); + + /* maybe its not chained */ + if (smb_com2 == 0xFF) { + SCVAL(outbuf,smb_vwv0,0xFF); + return outsize; + } + + if (chain_size == 0) { + /* this is the first part of the chain */ + orig_inbuf = inbuf; + orig_outbuf = outbuf; + } + + /* + * The original Win95 redirector dies on a reply to + * a lockingX and read chain unless the chain reply is + * 4 byte aligned. JRA. + */ + + outsize = (outsize + 3) & ~3; + + /* we need to tell the client where the next part of the reply will be */ + SSVAL(outbuf,smb_vwv1,smb_offset(outbuf+outsize,outbuf)); + SCVAL(outbuf,smb_vwv0,smb_com2); + + /* remember how much the caller added to the chain, only counting stuff + after the parameter words */ + chain_size += outsize - smb_wct; + + /* work out pointers into the original packets. The + headers on these need to be filled in */ + inbuf2 = orig_inbuf + smb_off2 + 4 - smb_wct; + outbuf2 = orig_outbuf + SVAL(outbuf,smb_vwv1) + 4 - smb_wct; + + /* remember the original command type */ + smb_com1 = CVAL(orig_inbuf,smb_com); + + /* save the data which will be overwritten by the new headers */ + memcpy(inbuf_saved,inbuf2,smb_wct); + memcpy(outbuf_saved,outbuf2,smb_wct); + + /* give the new packet the same header as the last part of the SMB */ + memmove(inbuf2,inbuf,smb_wct); + + /* create the in buffer */ + SCVAL(inbuf2,smb_com,smb_com2); + + /* create the out buffer */ + construct_reply_common(inbuf2, outbuf2); + + DEBUG(3,("Chained message\n")); + show_msg(inbuf2); + + /* process the request */ + outsize2 = switch_message(smb_com2,inbuf2,outbuf2,size-chain_size, + bufsize-chain_size); + + /* copy the new reply and request headers over the old ones, but + preserve the smb_com field */ + memmove(orig_outbuf,outbuf2,smb_wct); + SCVAL(orig_outbuf,smb_com,smb_com1); + + /* restore the saved data, being careful not to overwrite any + data from the reply header */ + memcpy(inbuf2,inbuf_saved,smb_wct); + + { + int ofs = smb_wct - PTR_DIFF(outbuf2,orig_outbuf); + if (ofs < 0) ofs = 0; + memmove(outbuf2+ofs,outbuf_saved+ofs,smb_wct-ofs); + } + + return outsize2; } /**************************************************************************** @@ -1065,17 +1062,16 @@ static int setup_select_timeout(void) void check_reload(int t) { - static time_t last_smb_conf_reload_time = 0; + static time_t last_smb_conf_reload_time = 0; - if(last_smb_conf_reload_time == 0) - last_smb_conf_reload_time = t; + if(last_smb_conf_reload_time == 0) + last_smb_conf_reload_time = t; - if (reload_after_sighup || (t >= last_smb_conf_reload_time+SMBD_RELOAD_CHECK)) - { - reload_services(True); - reload_after_sighup = False; - last_smb_conf_reload_time = t; - } + if (reload_after_sighup || (t >= last_smb_conf_reload_time+SMBD_RELOAD_CHECK)) { + reload_services(True); + reload_after_sighup = False; + last_smb_conf_reload_time = t; + } } /**************************************************************************** @@ -1084,165 +1080,164 @@ void check_reload(int t) static BOOL timeout_processing(int deadtime, int *select_timeout, time_t *last_timeout_processing_time) { - static time_t last_keepalive_sent_time = 0; - static time_t last_idle_closed_check = 0; - time_t t; - BOOL allidle = True; - extern int keepalive; - - if (smb_read_error == READ_EOF) - { - DEBUG(3,("end of file from client\n")); - return False; - } - - if (smb_read_error == READ_ERROR) - { - DEBUG(3,("receive_smb error (%s) exiting\n", - strerror(errno))); - return False; - } - - *last_timeout_processing_time = t = time(NULL); - - if(last_keepalive_sent_time == 0) - last_keepalive_sent_time = t; - - if(last_idle_closed_check == 0) - last_idle_closed_check = t; - - /* become root again if waiting */ - change_to_root_user(); - - /* run all registered idle events */ - smb_run_idle_events(t); - - /* check if we need to reload services */ - check_reload(t); - - /* automatic timeout if all connections are closed */ - if (conn_num_open()==0 && (t - last_idle_closed_check) >= IDLE_CLOSED_TIMEOUT) - { - DEBUG( 2, ( "Closing idle connection\n" ) ); - return False; - } - else - last_idle_closed_check = t; - - if (keepalive && (t - last_keepalive_sent_time)>keepalive) - { - extern struct auth_context *negprot_global_auth_context; - if (!send_keepalive(smbd_server_fd())) { - DEBUG( 2, ( "Keepalive failed - exiting.\n" ) ); - return False; - } - - /* send a keepalive for a password server or the like. - This is attached to the auth_info created in the - negprot */ - if (negprot_global_auth_context - && negprot_global_auth_context->challenge_set_method - && negprot_global_auth_context->challenge_set_method->send_keepalive) { - negprot_global_auth_context->challenge_set_method->send_keepalive - (&negprot_global_auth_context->challenge_set_method->private_data); - } - - last_keepalive_sent_time = t; - } - - /* check for connection timeouts */ - allidle = conn_idle_all(t, deadtime); - - if (allidle && conn_num_open()>0) { - DEBUG(2,("Closing idle connection 2.\n")); - return False; - } - - if(global_machine_password_needs_changing && - /* for ADS we need to do a regular ADS password change, not a domain - password change */ - lp_security() == SEC_DOMAIN) - { - unsigned char trust_passwd_hash[16]; - time_t lct; - - /* - * We're in domain level security, and the code that - * read the machine password flagged that the machine - * password needs changing. - */ - - /* - * First, open the machine password file with an exclusive lock. - */ - - if (secrets_lock_trust_account_password(lp_workgroup(), True) == False) { - DEBUG(0,("process: unable to lock the machine account password for \ + static time_t last_keepalive_sent_time = 0; + static time_t last_idle_closed_check = 0; + time_t t; + BOOL allidle = True; + extern int keepalive; + + if (smb_read_error == READ_EOF) { + DEBUG(3,("timeout_processing: End of file from client (client has disconnected).\n")); + return False; + } + + if (smb_read_error == READ_ERROR) { + DEBUG(3,("timeout_processing: receive_smb error (%s) Exiting\n", + strerror(errno))); + return False; + } + + if (smb_read_error == READ_BAD_SIG) { + DEBUG(3,("timeout_processing: receive_smb error bad smb signature. Exiting\n")); + return False; + } + + *last_timeout_processing_time = t = time(NULL); + + if(last_keepalive_sent_time == 0) + last_keepalive_sent_time = t; + + if(last_idle_closed_check == 0) + last_idle_closed_check = t; + + /* become root again if waiting */ + change_to_root_user(); + + /* run all registered idle events */ + smb_run_idle_events(t); + + /* check if we need to reload services */ + check_reload(t); + + /* automatic timeout if all connections are closed */ + if (conn_num_open()==0 && (t - last_idle_closed_check) >= IDLE_CLOSED_TIMEOUT) { + DEBUG( 2, ( "Closing idle connection\n" ) ); + return False; + } else { + last_idle_closed_check = t; + } + + if (keepalive && (t - last_keepalive_sent_time)>keepalive) { + extern struct auth_context *negprot_global_auth_context; + if (!send_keepalive(smbd_server_fd())) { + DEBUG( 2, ( "Keepalive failed - exiting.\n" ) ); + return False; + } + + /* send a keepalive for a password server or the like. + This is attached to the auth_info created in the + negprot */ + if (negprot_global_auth_context && negprot_global_auth_context->challenge_set_method + && negprot_global_auth_context->challenge_set_method->send_keepalive) { + + negprot_global_auth_context->challenge_set_method->send_keepalive + (&negprot_global_auth_context->challenge_set_method->private_data); + } + + last_keepalive_sent_time = t; + } + + /* check for connection timeouts */ + allidle = conn_idle_all(t, deadtime); + + if (allidle && conn_num_open()>0) { + DEBUG(2,("Closing idle connection 2.\n")); + return False; + } + + if(global_machine_password_needs_changing && + /* for ADS we need to do a regular ADS password change, not a domain + password change */ + lp_security() == SEC_DOMAIN) { + + unsigned char trust_passwd_hash[16]; + time_t lct; + + /* + * We're in domain level security, and the code that + * read the machine password flagged that the machine + * password needs changing. + */ + + /* + * First, open the machine password file with an exclusive lock. + */ + + if (secrets_lock_trust_account_password(lp_workgroup(), True) == False) { + DEBUG(0,("process: unable to lock the machine account password for \ machine %s in domain %s.\n", global_myname(), lp_workgroup() )); - return True; - } + return True; + } - if(!secrets_fetch_trust_account_password(lp_workgroup(), - trust_passwd_hash, - &lct, NULL)) { - DEBUG(0,("process: unable to read the machine account password for \ + if(!secrets_fetch_trust_account_password(lp_workgroup(), trust_passwd_hash, &lct, NULL)) { + DEBUG(0,("process: unable to read the machine account password for \ machine %s in domain %s.\n", global_myname(), lp_workgroup())); - secrets_lock_trust_account_password(lp_workgroup(), False); - return True; - } + secrets_lock_trust_account_password(lp_workgroup(), False); + return True; + } - /* - * Make sure someone else hasn't already done this. - */ + /* + * Make sure someone else hasn't already done this. + */ - if(t < lct + lp_machine_password_timeout()) { - global_machine_password_needs_changing = False; - secrets_lock_trust_account_password(lp_workgroup(), False); - return True; - } + if(t < lct + lp_machine_password_timeout()) { + global_machine_password_needs_changing = False; + secrets_lock_trust_account_password(lp_workgroup(), False); + return True; + } - /* always just contact the PDC here */ + /* always just contact the PDC here */ - change_trust_account_password( lp_workgroup(), NULL); - global_machine_password_needs_changing = False; - secrets_lock_trust_account_password(lp_workgroup(), False); - } - - /* - * Check to see if we have any blocking locks - * outstanding on the queue. - */ - process_blocking_lock_queue(t); - - /* update printer queue caches if necessary */ + change_trust_account_password( lp_workgroup(), NULL); + global_machine_password_needs_changing = False; + secrets_lock_trust_account_password(lp_workgroup(), False); + } + + /* + * Check to see if we have any blocking locks + * outstanding on the queue. + */ + process_blocking_lock_queue(t); + + /* update printer queue caches if necessary */ - update_monitored_printq_cache(); + update_monitored_printq_cache(); - /* - * Check to see if we have any change notifies - * outstanding on the queue. - */ - process_pending_change_notify_queue(t); + /* + * Check to see if we have any change notifies + * outstanding on the queue. + */ + process_pending_change_notify_queue(t); - /* - * Now we are root, check if the log files need pruning. - * Force a log file check. - */ - force_check_log_size(); - check_log_size(); + /* + * Now we are root, check if the log files need pruning. + * Force a log file check. + */ + force_check_log_size(); + check_log_size(); - /* Send any queued printer notify message to interested smbd's. */ + /* Send any queued printer notify message to interested smbd's. */ - print_notify_send_messages(0); + print_notify_send_messages(0); - /* - * Modify the select timeout depending upon - * what we have remaining in our queues. - */ + /* + * Modify the select timeout depending upon + * what we have remaining in our queues. + */ - *select_timeout = setup_select_timeout(); + *select_timeout = setup_select_timeout(); - return True; + return True; } /**************************************************************************** diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index e7f01ad02f..71312295f4 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -48,8 +48,6 @@ int reply_special(char *inbuf,char *outbuf) int msg_type = CVAL(inbuf,0); int msg_flags = CVAL(inbuf,1); pstring name1,name2; - - int len; char name_type = 0; static BOOL already_got_session = False; @@ -75,23 +73,16 @@ int reply_special(char *inbuf,char *outbuf) return(0); } name_extract(inbuf,4,name1); - name_extract(inbuf,4 + name_len(inbuf + 4),name2); + name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2); DEBUG(2,("netbios connect: name1=%s name2=%s\n", name1,name2)); - name1[15] = 0; - - len = strlen(name2); - if (len == 16) { - name_type = name2[15]; - name2[15] = 0; - } - set_local_machine_name(name1, True); set_remote_machine_name(name2, True); - DEBUG(2,("netbios connect: local=%s remote=%s\n", - get_local_machine_name(), get_remote_machine_name() )); + DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n", + get_local_machine_name(), get_remote_machine_name(), + name_type)); if (name_type == 'R') { /* We are being asked for a pathworks session --- @@ -1281,6 +1272,16 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name) *directory = *mask = 0; + /* We must check for wildcards in the name given + * directly by the client - before any unmangling. + * This prevents an unmangling of a UNIX name containing + * a DOS wildcard like '*' or '?' from unmangling into + * a wildcard delete which was not intended. + * FIX for #226. JRA. + */ + + has_wild = ms_has_wild(name); + rc = unix_convert(name,conn,0,&bad_path,&sbuf); p = strrchr_m(name,'/'); @@ -1305,13 +1306,12 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name) if (!rc && mangle_is_mangled(mask)) mangle_check_cache( mask ); - has_wild = ms_has_wild(mask); - if (!has_wild) { pstrcat(directory,"/"); pstrcat(directory,mask); error = can_delete(directory,conn,dirtype); - if (!NT_STATUS_IS_OK(error)) return error; + if (!NT_STATUS_IS_OK(error)) + return error; if (SMB_VFS_UNLINK(conn,directory) == 0) { count++; @@ -1338,12 +1338,15 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name) pstring fname; pstrcpy(fname,dname); - if(!mask_match(fname, mask, case_sensitive)) continue; + if(!mask_match(fname, mask, case_sensitive)) + continue; slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname); error = can_delete(fname,conn,dirtype); - if (!NT_STATUS_IS_OK(error)) continue; - if (SMB_VFS_UNLINK(conn,fname) == 0) count++; + if (!NT_STATUS_IS_OK(error)) + continue; + if (SMB_VFS_UNLINK(conn,fname) == 0) + count++; DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname)); } CloseDir(dirptr); @@ -1379,7 +1382,8 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size DEBUG(3,("reply_unlink : %s\n",name)); status = unlink_internals(conn, dirtype, name); - if (!NT_STATUS_IS_OK(status)) return ERROR_NT(status); + if (!NT_STATUS_IS_OK(status)) + return ERROR_NT(status); /* * Win2k needs a changenotify request response before it will @@ -1472,6 +1476,10 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s files_struct *fsp; START_PROFILE(SMBreadbraw); + if (srv_is_signing_active()) { + exit_server("reply_readbraw: SMB signing is active - raw reads/writes are disallowed."); + } + /* * Special check if an oplock break has been issued * and the readraw request croses on the wire, we must @@ -1870,6 +1878,10 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int outsize = 0; START_PROFILE(SMBwritebraw); + if (srv_is_signing_active()) { + exit_server("reply_readbraw: SMB signing is active - raw reads/writes are disallowed."); + } + CHECK_FSP(fsp,conn); CHECK_WRITE(fsp); @@ -2828,7 +2840,11 @@ NTSTATUS mkdir_internal(connection_struct *conn, pstring directory) int ret= -1; unix_convert(directory,conn,0,&bad_path,&sbuf); - + + if (ms_has_wild(directory)) { + return NT_STATUS_OBJECT_NAME_INVALID; + } + if (check_name(directory, conn)) ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory)); diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 18e0887071..c2855487a5 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -661,7 +661,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, #else /* the alternative is just to check the directory exists */ if (stat(conn->connectpath, &st) != 0 || !S_ISDIR(st.st_mode)) { - DEBUG(0,("'%s' is not a directory, when connecting to [%s]\n", conn->connectpath, lp_servicename(SNUM(conn)))); + DEBUG(0,("'%s' does not exist or is not a directory, when connecting to [%s]\n", conn->connectpath, lp_servicename(SNUM(conn)))); change_to_root_user(); yield_connection(conn, lp_servicename(SNUM(conn))); conn_free(conn); diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 7d77ed3071..88b442215d 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -3,7 +3,7 @@ handle SMBsessionsetup Copyright (C) Andrew Tridgell 1998-2001 Copyright (C) Andrew Bartlett 2001 - Copyright (C) Jim McDonough 2002 + Copyright (C) Jim McDonough 2002 Copyright (C) Luke Howard 2003 This program is free software; you can redistribute it and/or modify @@ -62,7 +62,7 @@ static int add_signature(char *outbuf, char *p) char *start = p; fstring lanman; - snprintf( lanman, sizeof(lanman), "Samba %s", VERSION ); + fstr_sprintf( lanman, "Samba %s", VERSION ); p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE); p += srvstr_push(outbuf, p, lanman, -1, STR_TERMINATE); @@ -153,6 +153,7 @@ static int reply_spnego_kerberos(connection_struct *conn, uint8 session_key[16]; uint8 tok_id[2]; BOOL foreign = False; + DATA_BLOB nullblob = data_blob(NULL, 0); ZERO_STRUCT(ticket); ZERO_STRUCT(auth_data); @@ -235,7 +236,7 @@ static int reply_spnego_kerberos(connection_struct *conn, memcpy(server_info->session_key, session_key, sizeof(session_key)); /* register_vuid keeps the server info */ - sess_vuid = register_vuid(server_info, user); + sess_vuid = register_vuid(server_info, nullblob, user); free(user); @@ -250,6 +251,16 @@ static int reply_spnego_kerberos(connection_struct *conn, } SSVAL(outbuf, smb_uid, sess_vuid); + + if (!server_info->guest) { + /* We need to start the signing engine + * here but a W2K client sends the old + * "BSRSPYL " signature instead of the + * correct one. Subsequent packets will + * be correct. + */ + srv_check_sign_mac(inbuf); + } } /* wrap that up in a nice GSS-API wrapping */ @@ -275,7 +286,7 @@ static int reply_spnego_kerberos(connection_struct *conn, End the NTLMSSP exchange context if we are OK/complete fail ***************************************************************************/ -static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *outbuf, +static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *outbuf, AUTH_NTLMSSP_STATE **auth_ntlmssp_state, DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status) { @@ -294,8 +305,10 @@ static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *outbuf, if (NT_STATUS_IS_OK(nt_status)) { int sess_vuid; + DATA_BLOB nullblob = data_blob(NULL, 0); + /* register_vuid keeps the server info */ - sess_vuid = register_vuid(server_info, (*auth_ntlmssp_state)->ntlmssp_state->user); + sess_vuid = register_vuid(server_info, nullblob, (*auth_ntlmssp_state)->ntlmssp_state->user); (*auth_ntlmssp_state)->server_info = NULL; if (sess_vuid == -1) { @@ -310,6 +323,16 @@ static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *outbuf, } SSVAL(outbuf,smb_uid,sess_vuid); + + if (!server_info->guest) { + /* We need to start the signing engine + * here but a W2K client sends the old + * "BSRSPYL " signature instead of the + * correct one. Subsequent packets will + * be correct. + */ + srv_check_sign_mac(inbuf); + } } } @@ -348,16 +371,27 @@ static int reply_spnego_negotiate(connection_struct *conn, if (!parse_negTokenTarg(blob1, OIDs, &secblob)) { return ERROR_NT(NT_STATUS_LOGON_FAILURE); } + + /* only look at the first OID for determining the mechToken -- + accoirding to RFC2478, we should choose the one we want + and renegotiate, but i smell a client bug here.. + + Problem observed when connecting to a member (samba box) + of an AD domain as a user in a Samba domain. Samba member + server sent back krb5/mskrb5/ntlmssp as mechtypes, but the + client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an + NTLMSSP mechtoken. --jerry */ + if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 || + strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) { + got_kerberos = True; + } + for (i=0;OIDs[i];i++) { DEBUG(3,("Got OID %s\n", OIDs[i])); - if (strcmp(OID_KERBEROS5, OIDs[i]) == 0 || - strcmp(OID_KERBEROS5_OLD, OIDs[i]) == 0) { - got_kerberos = True; - } free(OIDs[i]); } - DEBUG(3,("Got secblob of size %d\n", secblob.length)); + DEBUG(3,("Got secblob of size %lu\n", (unsigned long)secblob.length)); #ifdef HAVE_KRB5 if (got_kerberos && (SEC_ADS == lp_security())) { @@ -382,7 +416,7 @@ static int reply_spnego_negotiate(connection_struct *conn, data_blob_free(&secblob); - reply_spnego_ntlmssp(conn, outbuf, &global_ntlmssp_state, + reply_spnego_ntlmssp(conn, inbuf, outbuf, &global_ntlmssp_state, &chal, nt_status); data_blob_free(&chal); @@ -419,7 +453,7 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf, data_blob_free(&auth); - reply_spnego_ntlmssp(conn, outbuf, &global_ntlmssp_state, + reply_spnego_ntlmssp(conn, inbuf, outbuf, &global_ntlmssp_state, &auth_reply, nt_status); data_blob_free(&auth_reply); @@ -742,7 +776,6 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, free_user_info(&user_info); data_blob_free(&lm_resp); - data_blob_free(&nt_resp); data_blob_clear_free(&plaintext_password); if (!NT_STATUS_IS_OK(nt_status)) { @@ -750,9 +783,10 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, } if (!NT_STATUS_IS_OK(nt_status)) { + data_blob_free(&nt_resp); return ERROR_NT(nt_status_squash(nt_status)); } - + /* it's ok - setup a reply */ set_message(outbuf,3,0,True); if (Protocol >= PROTOCOL_NT1) { @@ -770,12 +804,17 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, to a uid can get through without a password, on the same VC */ /* register_vuid keeps the server info */ - sess_vuid = register_vuid(server_info, sub_user); - + sess_vuid = register_vuid(server_info, nt_resp, sub_user); + data_blob_free(&nt_resp); + if (sess_vuid == -1) { return ERROR_NT(NT_STATUS_LOGON_FAILURE); } + if (!server_info->guest && !srv_check_sign_mac(inbuf)) { + exit_server("reply_sesssetup_and_X: bad smb signature"); + } + SSVAL(outbuf,smb_uid,sess_vuid); SSVAL(inbuf,smb_uid,sess_vuid); diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 22b8a33a1e..fbebdb240f 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -98,7 +98,12 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat translated_path_length--; } - original_path = strdup(full_orig_name); + if(case_sensitive) { + original_path = strdup(full_orig_name); + } else { + original_path = strdup_upper(full_orig_name); + } + if (!original_path) { SAFE_FREE(translated_path); return; @@ -111,9 +116,6 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat original_path_length--; } - if(!case_sensitive) - strupper_m(original_path); - if (original_path_length != translated_path_length) { if (original_path_length < translated_path_length) { DEBUG(0, ("OOPS - tried to store stat cache entry for werid length paths [%s] %u and [%s] %u)!\n", @@ -161,6 +163,7 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat } scp->original_path = scp->names; + /* pointer into the structure... */ scp->translated_path = scp->names + original_path_length + 1; safe_strcpy(scp->original_path, original_path, original_path_length); safe_strcpy(scp->translated_path, translated_path, translated_path_length); @@ -194,7 +197,7 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, char **start, SMB_STRUCT_STAT *pst) { stat_cache_entry *scp; - pstring chk_name; + char *chk_name; size_t namelen; hash_element *hash_elem; char *sp; @@ -218,10 +221,20 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, return False; } - pstrcpy(chk_name, name); + if (case_sensitive) { + chk_name = strdup(name); + if (!chk_name) { + DEBUG(0, ("stat_cache_lookup: strdup failed!\n")); + return False; + } + + } else { + chk_name = strdup_upper(name); + if (!chk_name) { + DEBUG(0, ("stat_cache_lookup: strdup_upper failed!\n")); + return False; + } - if(!case_sensitive) { - strupper_m( chk_name ); /* * In some language encodings the length changes * if we uppercase. We need to treat this differently @@ -252,11 +265,13 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, * We reached the end of the name - no match. */ DO_PROFILE_INC(statcache_misses); + SAFE_FREE(chk_name); return False; } if((*chk_name == '\0') || (strcmp(chk_name, ".") == 0) || (strcmp(chk_name, "..") == 0)) { DO_PROFILE_INC(statcache_misses); + SAFE_FREE(chk_name); return False; } } else { @@ -265,6 +280,7 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, if(SMB_VFS_STAT(conn,scp->translated_path, pst) != 0) { /* Discard this entry - it doesn't exist in the filesystem. */ hash_remove(&stat_cache, hash_elem); + SAFE_FREE(chk_name); return False; } @@ -290,6 +306,7 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, ++*start; pstrcpy(dirpath, scp->translated_path); + SAFE_FREE(chk_name); return (namelen == scp->translated_path_length); } } diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index bdcd04443e..86906fa5be 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -326,7 +326,13 @@ static BOOL exact_match(char *str,char *mask, BOOL case_sig) return False; if (case_sig) return strcmp(str,mask)==0; - return StrCaseCmp(str,mask) == 0; + if (StrCaseCmp(str,mask) != 0) { + return False; + } + if (ms_has_wild(str)) { + return False; + } + return True; } /**************************************************************************** @@ -1906,7 +1912,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, if (strequal(base_name,".")) { pstrcpy(dos_fname, "\\"); } else { - snprintf(dos_fname, sizeof(dos_fname), "\\%s", fname); + pstr_sprintf(dos_fname, "\\%s", fname); string_replace(dos_fname, '/', '\\'); } @@ -3353,6 +3359,8 @@ int reply_trans2(connection_struct *conn, memcpy( data, smb_base(inbuf) + dsoff, num_data); } + srv_signing_trans_start(SVAL(inbuf,smb_mid)); + if(num_data_sofar < total_data || num_params_sofar < total_params) { /* We need to send an interim response then receive the rest of the parameter/data bytes */ @@ -3525,6 +3533,7 @@ int reply_trans2(connection_struct *conn, SAFE_FREE(params); SAFE_FREE(data); END_PROFILE(SMBtrans2); + srv_signing_trans_stop(); return ERROR_DOS(ERRSRV,ERRerror); } @@ -3535,6 +3544,8 @@ int reply_trans2(connection_struct *conn, an error packet. */ + srv_signing_trans_stop(); + SAFE_FREE(params); SAFE_FREE(data); END_PROFILE(SMBtrans2); @@ -3544,6 +3555,7 @@ int reply_trans2(connection_struct *conn, bad_param: + srv_signing_trans_stop(); SAFE_FREE(params); SAFE_FREE(data); END_PROFILE(SMBtrans2); diff --git a/source3/smbd/utmp.c b/source3/smbd/utmp.c index 9833a11f2d..6ff2f586ba 100644 --- a/source3/smbd/utmp.c +++ b/source3/smbd/utmp.c @@ -491,8 +491,8 @@ static BOOL sys_utmp_fill(struct utmp *u, * If size limit proves troublesome, then perhaps use "ut_id_encode()". */ if (strlen(id_str) > sizeof(u->ut_line)) { - DEBUG(1,("id_str [%s] is too long for %d char utmp field\n", - id_str, sizeof(u->ut_line))); + DEBUG(1,("id_str [%s] is too long for %lu char utmp field\n", + id_str, (unsigned long)sizeof(u->ut_line))); return False; } utmp_strcpy(u->ut_line, id_str, sizeof(u->ut_line)); diff --git a/source3/tdb/tdbtool.c b/source3/tdb/tdbtool.c index 221ef4a5f2..92009dcef4 100644 --- a/source3/tdb/tdbtool.c +++ b/source3/tdb/tdbtool.c @@ -118,6 +118,7 @@ static void help(void) " erase : erase the database\n" " dump : dump the database as strings\n" " insert key data : insert a record\n" +" move key file : move a record to a destination tdb\n" " store key data : store a record (replace)\n" " show key : show a record by key\n" " delete key : delete a record by key\n" @@ -251,16 +252,26 @@ static void show_tdb(void) } key.dptr = k; -/* key.dsize = strlen(k)+1;*/ - key.dsize = strlen(k); + key.dsize = strlen(k)+1; dbuf = tdb_fetch(tdb, key); if (!dbuf.dptr) { - terror("fetch failed"); - return; + /* maybe it is non-NULL terminated key? */ + key.dsize = strlen(k); + dbuf = tdb_fetch(tdb, key); + + if ( !dbuf.dptr ) { + terror("fetch failed"); + return; + } } + /* printf("%s : %*.*s\n", k, (int)dbuf.dsize, (int)dbuf.dsize, dbuf.dptr); */ print_rec(tdb, key, dbuf, NULL); + + free( dbuf.dptr ); + + return; } static void delete_tdb(void) @@ -281,6 +292,57 @@ static void delete_tdb(void) } } +static void move_rec(void) +{ + char *k = get_token(1); + char *file = get_token(0); + TDB_DATA key, dbuf; + TDB_CONTEXT *dst_tdb; + + if (!k) { + help(); + return; + } + + if ( !file ) { + terror("need destination tdb name"); + return; + } + + key.dptr = k; + key.dsize = strlen(k)+1; + + dbuf = tdb_fetch(tdb, key); + if (!dbuf.dptr) { + /* maybe it is non-NULL terminated key? */ + key.dsize = strlen(k); + dbuf = tdb_fetch(tdb, key); + + if ( !dbuf.dptr ) { + terror("fetch failed"); + return; + } + } + + print_rec(tdb, key, dbuf, NULL); + + dst_tdb = tdb_open(file, 0, 0, O_RDWR, 0600); + if ( !dst_tdb ) { + terror("unable to open destination tdb"); + return; + } + + if ( tdb_store( dst_tdb, key, dbuf, TDB_REPLACE ) == -1 ) { + terror("failed to move record"); + } + else + printf("record moved\n"); + + tdb_close( dst_tdb ); + + return; +} + #if 0 static int print_conn_key(TDB_DATA key) { @@ -455,6 +517,9 @@ int main(int argc, char *argv[]) } else if (strcmp(tok,"dump") == 0) { bIterate = 0; tdb_traverse(tdb, print_rec, NULL); + } else if (strcmp(tok,"move") == 0) { + bIterate = 0; + move_rec(); } else if (strcmp(tok,"list") == 0) { tdb_dump_all(tdb); } else if (strcmp(tok, "free") == 0) { diff --git a/source3/torture/cmd_vfs.c b/source3/torture/cmd_vfs.c index f74fcedcf4..d91dbf50e0 100644 --- a/source3/torture/cmd_vfs.c +++ b/source3/torture/cmd_vfs.c @@ -528,7 +528,8 @@ static NTSTATUS cmd_stat(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, c printf(" Inode: %10u", (unsigned int)st.st_ino); printf(" Links: %10u\n", (unsigned int)st.st_nlink); printf(" Access: %05o", (st.st_mode) & 007777); - printf(" Uid: %5d/%.16s Gid: %5d/%.16s\n", st.st_uid, user, st.st_gid, group); + printf(" Uid: %5lu/%.16s Gid: %5lu/%.16s\n", (unsigned long)st.st_uid, user, + (unsigned long)st.st_gid, group); printf(" Access: %s", ctime(&(st.st_atime))); printf(" Modify: %s", ctime(&(st.st_mtime))); printf(" Change: %s", ctime(&(st.st_ctime))); @@ -590,7 +591,8 @@ static NTSTATUS cmd_fstat(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, printf(" Inode: %10u", (unsigned int)st.st_ino); printf(" Links: %10u\n", (unsigned int)st.st_nlink); printf(" Access: %05o", (st.st_mode) & 007777); - printf(" Uid: %5d/%.16s Gid: %5d/%.16s\n", st.st_uid, user, st.st_gid, group); + printf(" Uid: %5lu/%.16s Gid: %5lu/%.16s\n", (unsigned long)st.st_uid, user, + (unsigned long)st.st_gid, group); printf(" Access: %s", ctime(&(st.st_atime))); printf(" Modify: %s", ctime(&(st.st_mtime))); printf(" Change: %s", ctime(&(st.st_ctime))); @@ -640,7 +642,8 @@ static NTSTATUS cmd_lstat(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, printf(" Inode: %10u", (unsigned int)st.st_ino); printf(" Links: %10u\n", (unsigned int)st.st_nlink); printf(" Access: %05o", (st.st_mode) & 007777); - printf(" Uid: %5d/%.16s Gid: %5d/%.16s\n", st.st_uid, user, st.st_gid, group); + printf(" Uid: %5lu/%.16s Gid: %5lu/%.16s\n", (unsigned long)st.st_uid, user, + (unsigned long)st.st_gid, group); printf(" Access: %s", ctime(&(st.st_atime))); printf(" Modify: %s", ctime(&(st.st_mtime))); printf(" Change: %s", ctime(&(st.st_ctime))); diff --git a/source3/torture/locktest.c b/source3/torture/locktest.c index 63b9590dd6..86379bf3b6 100644 --- a/source3/torture/locktest.c +++ b/source3/torture/locktest.c @@ -157,7 +157,7 @@ static struct cli_state *connect_one(char *share, int snum) zero_ip(&ip); - slprintf(myname,sizeof(myname), "lock-%u-%u", getpid(), count++); + slprintf(myname,sizeof(myname), "lock-%lu-%u", (unsigned long)getpid(), count++); make_nmb_name(&calling, myname, 0x0); make_nmb_name(&called , server, 0x20); diff --git a/source3/torture/locktest2.c b/source3/torture/locktest2.c index 97844b5609..5fbaf9ec58 100644 --- a/source3/torture/locktest2.c +++ b/source3/torture/locktest2.c @@ -173,11 +173,11 @@ static struct cli_state *connect_one(char *share) } } - slprintf(myname,sizeof(myname), "lock-%u-%u", getpid(), count++); + slprintf(myname,sizeof(myname), "lock-%lu-%u", (unsigned long)getpid(), count++); nt_status = cli_full_connection(&c, myname, server_n, NULL, 0, share, "?????", username, lp_workgroup(), password, 0, - NULL); + Undefined, NULL); if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(0, ("cli_full_connection failed with error %s\n", nt_errstr(nt_status))); diff --git a/source3/torture/mangle_test.c b/source3/torture/mangle_test.c index 660d4d17af..9a719349b6 100644 --- a/source3/torture/mangle_test.c +++ b/source3/torture/mangle_test.c @@ -54,7 +54,7 @@ static BOOL test_one(struct cli_state *cli, const char *name) return False; } - snprintf(name2, sizeof(name2), "\\mangle_test\\%s", shortname); + fstr_sprintf(name2, "\\mangle_test\\%s", shortname); if (!cli_unlink(cli, name2)) { printf("unlink of %s (%s) failed (%s)\n", name2, name, cli_errstr(cli)); diff --git a/source3/torture/nsstest.c b/source3/torture/nsstest.c index 0a08cb6e8f..a803cd7e71 100644 --- a/source3/torture/nsstest.c +++ b/source3/torture/nsstest.c @@ -29,11 +29,11 @@ static int total_errors; static void *find_fn(const char *name) { - char s[1024]; + pstring s; static void *h; void *res; - snprintf(s,sizeof(s), "_nss_%s_%s", nss_name, name); + pstr_sprintf(s, "_nss_%s_%s", nss_name, name); if (!h) { h = sys_dlopen(so_path, RTLD_LAZY); @@ -296,11 +296,11 @@ static int nss_initgroups(char *user, gid_t group, gid_t **groups, long int *sta static void print_passwd(struct passwd *pwd) { - printf("%s:%s:%d:%d:%s:%s:%s\n", + printf("%s:%s:%lu:%lu:%s:%s:%s\n", pwd->pw_name, pwd->pw_passwd, - pwd->pw_uid, - pwd->pw_gid, + (unsigned long)pwd->pw_uid, + (unsigned long)pwd->pw_gid, pwd->pw_gecos, pwd->pw_dir, pwd->pw_shell); @@ -309,10 +309,10 @@ static void print_passwd(struct passwd *pwd) static void print_group(struct group *grp) { int i; - printf("%s:%s:%d: ", + printf("%s:%s:%lu: ", grp->gr_name, grp->gr_passwd, - grp->gr_gid); + (unsigned long)grp->gr_gid); if (!grp->gr_mem[0]) { printf("\n"); @@ -343,9 +343,9 @@ static void nss_test_initgroups(char *name, gid_t gid) } for (i=0; iauth.flags |= ADS_AUTH_NO_BIND; } @@ -89,7 +89,7 @@ static int net_ads_info(int argc, const char **argv) { ADS_STRUCT *ads; - ads = ads_init(NULL, NULL, opt_host); + ads = ads_init(NULL, opt_target_workgroup, opt_host); if (ads) { ads->auth.flags |= ADS_AUTH_NO_BIND; @@ -129,7 +129,7 @@ static ADS_STRUCT *ads_startup(void) BOOL second_time = False; char *cp; - ads = ads_init(NULL, NULL, opt_host); + ads = ads_init(NULL, opt_target_workgroup, opt_host); if (!opt_user_name) { opt_user_name = "administrator"; @@ -848,7 +848,7 @@ static int net_ads_printer_publish(int argc, const char **argv) opt_user_name, opt_workgroup, opt_password ? opt_password : "", CLI_FULL_CONNECTION_USE_KERBEROS, - NULL); + Undefined, NULL); if (NT_STATUS_IS_ERR(nt_status)) { d_printf("Unable to open a connnection to %s to obtain data " diff --git a/source3/utils/net_cache.c b/source3/utils/net_cache.c index 8dd9db599d..a955916458 100644 --- a/source3/utils/net_cache.c +++ b/source3/utils/net_cache.c @@ -214,7 +214,7 @@ static int net_cache_del(int argc, const char **argv) const char *keystr = argv[0]; if (argc < 1) { - d_printf("\nUsage: net cache add \n"); + d_printf("\nUsage: net cache del \n"); return -1; } diff --git a/source3/utils/net_idmap.c b/source3/utils/net_idmap.c index 689d4ff813..b035d8d2f1 100644 --- a/source3/utils/net_idmap.c +++ b/source3/utils/net_idmap.c @@ -95,10 +95,14 @@ static int net_idmap_restore(int argc, const char **argv) if ( (len > 0) && (line[len-1] == '\n') ) line[len-1] = '\0'; + /* Yuck - this is broken for sizeof(gid_t) != sizeof(int) */ + if (sscanf(line, "GID %d %s", &id.gid, sid_string) == 2) { type = ID_GROUPID; } + /* Yuck - this is broken for sizeof(uid_t) != sizeof(int) */ + if (sscanf(line, "UID %d %s", &id.uid, sid_string) == 2) { type = ID_USERID; } @@ -114,9 +118,10 @@ static int net_idmap_restore(int argc, const char **argv) } if (!NT_STATUS_IS_OK(idmap_set_mapping(&sid, id, type))) { - d_printf("Could not set mapping of %s %d to sid %s\n", + d_printf("Could not set mapping of %s %lu to sid %s\n", (type == ID_GROUPID) ? "GID" : "UID", - (type == ID_GROUPID) ? id.gid : id.uid, + (type == ID_GROUPID) ? (unsigned long)id.gid: + (unsigned long)id.uid, sid_string_static(&sid)); continue; } diff --git a/source3/utils/net_rpc_samsync.c b/source3/utils/net_rpc_samsync.c index e5e9a68b2e..9eadbbbade 100644 --- a/source3/utils/net_rpc_samsync.c +++ b/source3/utils/net_rpc_samsync.c @@ -400,8 +400,7 @@ sam_account_from_delta(SAM_ACCOUNT *account, SAM_ACCOUNT_INFO *delta) return NT_STATUS_OK; } -static NTSTATUS -fetch_account_info(uint32 rid, SAM_ACCOUNT_INFO *delta) +static NTSTATUS fetch_account_info(uint32 rid, SAM_ACCOUNT_INFO *delta) { NTSTATUS nt_ret; fstring account; @@ -429,6 +428,7 @@ fetch_account_info(uint32 rid, SAM_ACCOUNT_INFO *delta) (delta->acb_info & ACB_DOMTRUST) ) { pstrcpy(add_script, lp_addmachine_script()); } else { + *add_script = '\0'; DEBUG(1, ("Unknown user type: %s\n", smbpasswd_encode_acb_info(delta->acb_info))); } @@ -439,8 +439,7 @@ fetch_account_info(uint32 rid, SAM_ACCOUNT_INFO *delta) add_ret = smbrun(add_script,NULL); DEBUG(1,("fetch_account: Running the command `%s' " "gave %d\n", add_script, add_ret)); - } - else { + } else { DEBUG(8,("fetch_account_info: no add user/machine script. Asking winbindd\n")); /* don't need a RID allocated since the user already has a SID */ @@ -487,8 +486,8 @@ fetch_account_info(uint32 rid, SAM_ACCOUNT_INFO *delta) } else { if (map.gid != passwd->pw_gid) { if (!(grp = getgrgid(map.gid))) { - DEBUG(0, ("Could not find unix group %d for user %s (group SID=%s)\n", - map.gid, pdb_get_username(sam_account), sid_string_static(&group_sid))); + DEBUG(0, ("Could not find unix group %lu for user %s (group SID=%s)\n", + (unsigned long)map.gid, pdb_get_username(sam_account), sid_string_static(&group_sid))); } else { smb_set_primary_group(grp->gr_name, pdb_get_username(sam_account)); } @@ -585,7 +584,7 @@ fetch_group_mem_info(uint32 rid, SAM_GROUP_MEM_INFO *delta) } if (!(grp = getgrgid(map.gid))) { - DEBUG(0, ("Could not find unix group %d\n", map.gid)); + DEBUG(0, ("Could not find unix group %lu\n", (unsigned long)map.gid)); return NT_STATUS_NO_SUCH_GROUP; } diff --git a/source3/utils/net_time.c b/source3/utils/net_time.c index 40619a0796..45c1783805 100644 --- a/source3/utils/net_time.c +++ b/source3/utils/net_time.c @@ -71,12 +71,12 @@ static time_t nettime(int *zone) /* return a time as a string ready to be passed to /bin/date */ static char *systime(time_t t) { - static char s[100]; + static fstring s; struct tm *tm; tm = localtime(&t); - snprintf(s, sizeof(s), "%02d%02d%02d%02d%04d.%02d", + fstr_sprintf(s, "%02d%02d%02d%02d%04d.%02d", tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_year + 1900, tm->tm_sec); return s; diff --git a/source3/utils/ntlm_auth.c b/source3/utils/ntlm_auth.c index 3dfa157bda..1d36a7ce52 100644 --- a/source3/utils/ntlm_auth.c +++ b/source3/utils/ntlm_auth.c @@ -32,7 +32,9 @@ enum squid_mode { SQUID_2_4_BASIC, SQUID_2_5_BASIC, - SQUID_2_5_NTLMSSP + SQUID_2_5_NTLMSSP, + GSS_SPNEGO, + GSS_SPNEGO_CLIENT }; @@ -342,6 +344,501 @@ static void manage_squid_basic_request(enum squid_mode squid_mode, } } +static void offer_gss_spnego_mechs(void) { + + DATA_BLOB token; + ASN1_DATA asn1; + SPNEGO_DATA spnego; + ssize_t len; + char *reply_base64; + + ZERO_STRUCT(spnego); + + /* Server negTokenInit (mech offerings) */ + spnego.type = SPNEGO_NEG_TOKEN_INIT; + spnego.negTokenInit.mechTypes = smb_xmalloc(sizeof(char *) * 2); + spnego.negTokenInit.mechTypes[0] = smb_xstrdup(OID_NTLMSSP); + spnego.negTokenInit.mechTypes[1] = NULL; + + ZERO_STRUCT(asn1); + asn1_push_tag(&asn1, ASN1_SEQUENCE(0)); + asn1_push_tag(&asn1, ASN1_CONTEXT(0)); + asn1_write_GeneralString(&asn1, "NONE"); + asn1_pop_tag(&asn1); + asn1_pop_tag(&asn1); + spnego.negTokenInit.mechListMIC = data_blob(asn1.data, asn1.length); + asn1_free(&asn1); + + len = write_spnego_data(&token, &spnego); + free_spnego_data(&spnego); + + if (len == -1) { + DEBUG(1, ("Could not write SPNEGO data blob\n")); + x_fprintf(x_stdout, "BH\n"); + return; + } + + reply_base64 = base64_encode_data_blob(token); + x_fprintf(x_stdout, "TT %s *\n", reply_base64); + + SAFE_FREE(reply_base64); + data_blob_free(&token); + DEBUG(10, ("sent SPNEGO negTokenInit\n")); + return; +} + +static void manage_gss_spnego_request(enum squid_mode squid_mode, + char *buf, int length) +{ + static NTLMSSP_STATE *ntlmssp_state = NULL; + SPNEGO_DATA spnego; + DATA_BLOB request, token; + NTSTATUS status; + ssize_t len; + + const char *reply_code; + char *reply_base64; + pstring reply_argument; + + if (strlen(buf) < 2) { + + if (ntlmssp_state != NULL) { + DEBUG(1, ("Request for initial SPNEGO request where " + "we already have a state\n")); + x_fprintf(x_stdout, "BH\n"); + return; + } + + DEBUG(1, ("NTLMSSP query [%s] invalid", buf)); + x_fprintf(x_stdout, "BH\n"); + return; + } + + if ( (strlen(buf) == 2) && (strcmp(buf, "YR") == 0) ) { + + /* Initial request, get the negTokenInit offering + mechanisms */ + + offer_gss_spnego_mechs(); + return; + } + + /* All subsequent requests are "KK" (Knock, Knock ;)) and have + a blob. This might be negTokenInit or negTokenTarg */ + + if ( (strlen(buf) <= 3) || (strncmp(buf, "KK", 2) != 0) ) { + DEBUG(1, ("GSS-SPNEGO query [%s] invalid\n", buf)); + x_fprintf(x_stdout, "BH\n"); + return; + } + + request = base64_decode_data_blob(buf + 3); + len = read_spnego_data(request, &spnego); + data_blob_free(&request); + + if (len == -1) { + DEBUG(1, ("GSS-SPNEGO query [%s] invalid", buf)); + x_fprintf(x_stdout, "BH\n"); + return; + } + + if (spnego.type == SPNEGO_NEG_TOKEN_INIT) { + + /* Second request from Client. This is where the + client offers its mechanism to use. We currently + only support NTLMSSP, the decision for Kerberos + would be taken here. */ + + if ( (spnego.negTokenInit.mechTypes == NULL) || + (spnego.negTokenInit.mechTypes[0] == NULL) ) { + DEBUG(1, ("Client did not offer any mechanism")); + x_fprintf(x_stdout, "BH\n"); + return; + } + + if ( strcmp(spnego.negTokenInit.mechTypes[0], OID_NTLMSSP) != 0 ) { + DEBUG(1, ("Client did not choose NTLMSSP but %s\n", + spnego.negTokenInit.mechTypes[0])); + x_fprintf(x_stdout, "BH\n"); + return; + } + + if ( spnego.negTokenInit.mechToken.data == NULL ) { + DEBUG(1, ("Client did not provide NTLMSSP data\n")); + x_fprintf(x_stdout, "BH\n"); + return; + } + + if ( ntlmssp_state != NULL ) { + DEBUG(1, ("Client wants a new NTLMSSP challenge, but " + "already got one\n")); + x_fprintf(x_stdout, "BH\n"); + ntlmssp_server_end(&ntlmssp_state); + return; + } + + ntlmssp_server_start(&ntlmssp_state); + ntlmssp_state->check_password = winbind_pw_check; + ntlmssp_state->get_domain = get_winbind_domain; + ntlmssp_state->get_global_myname = get_winbind_netbios_name; + + DEBUG(10, ("got NTLMSSP packet:\n")); + dump_data(10, spnego.negTokenInit.mechToken.data, + spnego.negTokenInit.mechToken.length); + + free_spnego_data(&spnego); + + spnego.type = SPNEGO_NEG_TOKEN_TARG; + spnego.negTokenTarg.negResult = SPNEGO_ACCEPT_INCOMPLETE; + spnego.negTokenTarg.supportedMech = strdup(OID_NTLMSSP); + + status = ntlmssp_server_update(ntlmssp_state, + spnego.negTokenInit.mechToken, + &spnego.negTokenTarg.responseToken); + + } else { + + /* spnego.type == SPNEGO_NEG_TOKEN_TARG */ + + DATA_BLOB response; + + if (spnego.negTokenTarg.responseToken.data == NULL) { + DEBUG(1, ("Got a negTokenArg without a responseToken!\n")); + x_fprintf(x_stdout, "BH\n"); + return; + } + + status = ntlmssp_server_update(ntlmssp_state, + spnego.negTokenTarg.responseToken, + &response); + + data_blob_free(&spnego.negTokenTarg.responseToken); + + spnego.negTokenTarg.responseToken = response; + + } + + if (NT_STATUS_IS_OK(status)) { + spnego.negTokenTarg.negResult = SPNEGO_ACCEPT_COMPLETED; + reply_code = "AF"; + pstr_sprintf(reply_argument, "%s\\%s", + ntlmssp_state->domain, ntlmssp_state->user); + } else if (NT_STATUS_EQUAL(status, + NT_STATUS_MORE_PROCESSING_REQUIRED)) { + spnego.negTokenTarg.negResult = SPNEGO_ACCEPT_INCOMPLETE; + reply_code = "TT"; + pstr_sprintf(reply_argument, "*"); + } else { + spnego.negTokenTarg.negResult = SPNEGO_REJECT; + reply_code = "NA"; + pstrcpy(reply_argument, nt_errstr(status)); + } + + len = write_spnego_data(&token, &spnego); + free_spnego_data(&spnego); + + if (len == -1) { + DEBUG(1, ("Could not write SPNEGO data blob\n")); + x_fprintf(x_stdout, "BH\n"); + return; + } + + reply_base64 = base64_encode_data_blob(token); + + x_fprintf(x_stdout, "%s %s %s\n", + reply_code, reply_base64, reply_argument); + + SAFE_FREE(reply_base64); + data_blob_free(&token); + + if (NT_STATUS_IS_OK(status)) { + ntlmssp_server_end(&ntlmssp_state); + } + + return; +} + +static NTLMSSP_CLIENT_STATE *client_ntlmssp_state = NULL; + +static void manage_client_ntlmssp_init(SPNEGO_DATA spnego) +{ + NTSTATUS status; + DATA_BLOB null_blob = data_blob(NULL, 0); + DATA_BLOB to_server; + char *to_server_base64; + const char *my_mechs[] = {OID_NTLMSSP, NULL}; + + DEBUG(10, ("Got spnego negTokenInit with NTLMSSP\n")); + + if (client_ntlmssp_state != NULL) { + DEBUG(1, ("Request for initial SPNEGO request where " + "we already have a state\n")); + x_fprintf(x_stdout, "BH\n"); + return; + } + + if ( (opt_username == NULL) || (opt_domain == NULL) ) { + DEBUG(1, ("Need username and domain for NTLMSSP\n")); + x_fprintf(x_stdout, "BH\n"); + return; + } + + if (opt_password == NULL) { + + /* Request a password from the calling process. After + sending it, the calling process should retry with + the negTokenInit. */ + + DEBUG(10, ("Requesting password\n")); + x_fprintf(x_stdout, "PW\n"); + return; + } + + status = ntlmssp_client_start(&client_ntlmssp_state); + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(1, ("Could not start NTLMSSP client: %s\n", + nt_errstr(status))); + x_fprintf(x_stdout, "BH\n"); + ntlmssp_client_end(&client_ntlmssp_state); + return; + } + + status = ntlmssp_set_username(client_ntlmssp_state, opt_username); + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(1, ("Could not set username: %s\n", + nt_errstr(status))); + x_fprintf(x_stdout, "BH\n"); + ntlmssp_client_end(&client_ntlmssp_state); + return; + } + + status = ntlmssp_set_domain(client_ntlmssp_state, opt_domain); + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(1, ("Could not set domain: %s\n", + nt_errstr(status))); + x_fprintf(x_stdout, "BH\n"); + ntlmssp_client_end(&client_ntlmssp_state); + return; + } + + status = ntlmssp_set_password(client_ntlmssp_state, opt_password); + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(1, ("Could not set password: %s\n", + nt_errstr(status))); + x_fprintf(x_stdout, "BH\n"); + ntlmssp_client_end(&client_ntlmssp_state); + return; + } + + spnego.type = SPNEGO_NEG_TOKEN_INIT; + spnego.negTokenInit.mechTypes = my_mechs; + spnego.negTokenInit.reqFlags = 0; + spnego.negTokenInit.mechListMIC = null_blob; + + status = ntlmssp_client_update(client_ntlmssp_state, null_blob, + &spnego.negTokenInit.mechToken); + + if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { + DEBUG(1, ("Expected MORE_PROCESSING_REQUIRED, got: %s\n", + nt_errstr(status))); + x_fprintf(x_stdout, "BH\n"); + ntlmssp_client_end(&client_ntlmssp_state); + return; + } + + write_spnego_data(&to_server, &spnego); + data_blob_free(&spnego.negTokenInit.mechToken); + + to_server_base64 = base64_encode_data_blob(to_server); + data_blob_free(&to_server); + x_fprintf(x_stdout, "KK %s\n", to_server_base64); + SAFE_FREE(to_server_base64); + return; +} + +static void manage_client_ntlmssp_targ(SPNEGO_DATA spnego) +{ + NTSTATUS status; + DATA_BLOB null_blob = data_blob(NULL, 0); + DATA_BLOB request; + DATA_BLOB to_server; + char *to_server_base64; + + DEBUG(10, ("Got spnego negTokenTarg with NTLMSSP\n")); + + if (client_ntlmssp_state == NULL) { + DEBUG(1, ("Got NTLMSSP tArg without a client state\n")); + x_fprintf(x_stdout, "BH\n"); + ntlmssp_client_end(&client_ntlmssp_state); + return; + } + + if (spnego.negTokenTarg.negResult == SPNEGO_REJECT) { + x_fprintf(x_stdout, "NA\n"); + ntlmssp_client_end(&client_ntlmssp_state); + return; + } + + if (spnego.negTokenTarg.negResult == SPNEGO_ACCEPT_COMPLETED) { + x_fprintf(x_stdout, "AF\n"); + ntlmssp_client_end(&client_ntlmssp_state); + return; + } + + status = ntlmssp_client_update(client_ntlmssp_state, + spnego.negTokenTarg.responseToken, + &request); + + if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { + DEBUG(1, ("Expected MORE_PROCESSING_REQUIRED from " + "ntlmssp_client_update, got: %s\n", + nt_errstr(status))); + x_fprintf(x_stdout, "BH\n"); + data_blob_free(&request); + ntlmssp_client_end(&client_ntlmssp_state); + return; + } + + spnego.type = SPNEGO_NEG_TOKEN_TARG; + spnego.negTokenTarg.negResult = SPNEGO_ACCEPT_INCOMPLETE; + spnego.negTokenTarg.supportedMech = OID_NTLMSSP; + spnego.negTokenTarg.responseToken = request; + spnego.negTokenTarg.mechListMIC = null_blob; + + write_spnego_data(&to_server, &spnego); + data_blob_free(&request); + + to_server_base64 = base64_encode_data_blob(to_server); + data_blob_free(&to_server); + x_fprintf(x_stdout, "KK %s\n", to_server_base64); + SAFE_FREE(to_server_base64); + return; +} + +static void manage_client_krb5_init(SPNEGO_DATA spnego) +{ + DEBUG(1, ("to be done ... \n")); + x_fprintf(x_stdout, "BH\n"); + return; +} + +static void manage_client_krb5_targ(SPNEGO_DATA spnego) +{ + DEBUG(1, ("Got a negTokenTarg with a Kerberos token. This should not " + "happen!\n")); + x_fprintf(x_stdout, "BH\n"); + return; +} + +static void manage_gss_spnego_client_request(enum squid_mode squid_mode, + char *buf, int length) +{ + DATA_BLOB request; + SPNEGO_DATA spnego; + ssize_t len; + + if (strlen(buf) <= 3) { + DEBUG(1, ("SPNEGO query [%s] too short\n", buf)); + x_fprintf(x_stdout, "BH\n"); + return; + } + + request = base64_decode_data_blob(buf+3); + + if (strncmp(buf, "PW ", 3) == 0) { + + /* We asked for a password and obviously got it :-) */ + + opt_password = strndup(request.data, request.length); + + if (opt_password == NULL) { + DEBUG(1, ("Out of memory\n")); + x_fprintf(x_stdout, "BH\n"); + data_blob_free(&request); + return; + } + + x_fprintf(x_stdout, "OK\n"); + data_blob_free(&request); + return; + } + + if ( (strncmp(buf, "TT ", 3) != 0) && + (strncmp(buf, "AF ", 3) != 0) && + (strncmp(buf, "NA ", 3) != 0) ) { + DEBUG(1, ("SPNEGO request [%s] invalid\n", buf)); + x_fprintf(x_stdout, "BH\n"); + data_blob_free(&request); + return; + } + + /* So we got a server challenge to generate a SPNEGO + client-to-server request... */ + + len = read_spnego_data(request, &spnego); + data_blob_free(&request); + + if (len == -1) { + DEBUG(1, ("Could not read SPNEGO data for [%s]\n", buf)); + x_fprintf(x_stdout, "BH\n"); + return; + } + + if (spnego.type == SPNEGO_NEG_TOKEN_INIT) { + + /* The server offers a list of mechanisms */ + + const char **mechType = spnego.negTokenInit.mechTypes; + + while (*mechType != NULL) { + + if (strcmp(*mechType, OID_NTLMSSP) == 0) { + manage_client_ntlmssp_init(spnego); + goto out; + } + + if (strcmp(*mechType, OID_KERBEROS5_OLD) == 0) { + manage_client_krb5_init(spnego); + goto out; + } + + mechType++; + } + + DEBUG(1, ("Server offered no compatible mechanism\n")); + x_fprintf(x_stdout, "BH\n"); + return; + } + + if (spnego.type == SPNEGO_NEG_TOKEN_TARG) { + + if (strcmp(spnego.negTokenTarg.supportedMech, + OID_NTLMSSP) == 0) { + manage_client_ntlmssp_targ(spnego); + goto out; + } + + if (strcmp(spnego.negTokenTarg.supportedMech, + OID_KERBEROS5_OLD) == 0) { + manage_client_krb5_targ(spnego); + goto out; + } + + } + + DEBUG(1, ("Got an SPNEGO token I could not handle [%s]!\n", buf)); + x_fprintf(x_stdout, "BH\n"); + return; + + out: + free_spnego_data(&spnego); + return; +} + static void manage_squid_request(enum squid_mode squid_mode) { char buf[SQUID_BUFFER_SIZE+1]; @@ -383,6 +880,10 @@ static void manage_squid_request(enum squid_mode squid_mode) manage_squid_basic_request(squid_mode, buf, length); } else if (squid_mode == SQUID_2_5_NTLMSSP) { manage_squid_ntlmssp_request(squid_mode, buf, length); + } else if (squid_mode == GSS_SPNEGO) { + manage_gss_spnego_request(squid_mode, buf, length); + } else if (squid_mode == GSS_SPNEGO_CLIENT) { + manage_gss_spnego_client_request(squid_mode, buf, length); } } @@ -1334,6 +1835,10 @@ enum { squid_stream(SQUID_2_5_BASIC); } else if (strcmp(helper_protocol, "squid-2.4-basic")== 0) { squid_stream(SQUID_2_4_BASIC); + } else if (strcmp(helper_protocol, "gss-spnego")== 0) { + squid_stream(GSS_SPNEGO); + } else if (strcmp(helper_protocol, "gss-spnego-client") == 0) { + squid_stream(GSS_SPNEGO_CLIENT); } else { x_fprintf(x_stderr, "unknown helper protocol [%s]\n", helper_protocol); exit(1); @@ -1372,7 +1877,7 @@ enum { } else { fstring user; - snprintf(user, sizeof(user)-1, "%s%c%s", opt_domain, winbind_separator(), opt_username); + fstr_sprintf(user, "%s%c%s", opt_domain, winbind_separator(), opt_username); if (!check_plaintext_auth(user, opt_password, True)) { exit(1); } diff --git a/source3/utils/pdbedit.c b/source3/utils/pdbedit.c index 96d0d3c057..0f1f6edf08 100644 --- a/source3/utils/pdbedit.c +++ b/source3/utils/pdbedit.c @@ -51,21 +51,6 @@ #define MASK_ALWAYS_GOOD 0x0000001F #define MASK_USER_GOOD 0x00401F00 -/***************************************************************************** - stubb functions -****************************************************************************/ - -void become_root( void ) -{ - return; -} - -void unbecome_root( void ) -{ - return; -} - - /********************************************************* Add all currently available users to another db ********************************************************/ @@ -176,16 +161,17 @@ static int print_sam_info (SAM_ACCOUNT *sam_pwent, BOOL verbosity, BOOL smbpwdst pdb_sethexpwd(lm_passwd, pdb_get_lanman_passwd(sam_pwent), pdb_get_acct_ctrl(sam_pwent)); pdb_sethexpwd(nt_passwd, pdb_get_nt_passwd(sam_pwent), pdb_get_acct_ctrl(sam_pwent)); - printf("%s:%d:%s:%s:%s:LCT-%08X:\n", + printf("%s:%lu:%s:%s:%s:LCT-%08X:\n", pdb_get_username(sam_pwent), - uid, + (unsigned long)uid, lm_passwd, nt_passwd, pdb_encode_acct_ctrl(pdb_get_acct_ctrl(sam_pwent),NEW_PW_FORMAT_SPACE_PADDED_LEN), (uint32)pdb_get_pass_last_set_time(sam_pwent)); } else { uid = nametouid(pdb_get_username(sam_pwent)); - printf ("%s:%d:%s\n", pdb_get_username(sam_pwent), uid, pdb_get_fullname(sam_pwent)); + printf ("%s:%lu:%s\n", pdb_get_username(sam_pwent), (unsigned long)uid, + pdb_get_fullname(sam_pwent)); } return 0; diff --git a/source3/utils/smbcacls.c b/source3/utils/smbcacls.c index 69dc2dd47a..c90c042106 100644 --- a/source3/utils/smbcacls.c +++ b/source3/utils/smbcacls.c @@ -724,7 +724,8 @@ static struct cli_state *connect_one(const char *share) &ip, 0, share, "?????", cmdline_auth_info.username, lp_workgroup(), - cmdline_auth_info.password, 0, NULL))) { + cmdline_auth_info.password, 0, + cmdline_auth_info.signing_state, NULL))) { return c; } else { DEBUG(0,("cli_full_connection failed! (%s)\n", nt_errstr(nt_status))); diff --git a/source3/utils/smbcontrol.c b/source3/utils/smbcontrol.c index b7333f2317..190627e2a5 100644 --- a/source3/utils/smbcontrol.c +++ b/source3/utils/smbcontrol.c @@ -591,12 +591,6 @@ static const struct { { NULL } }; -/* Yuck - we need these because we link to printing*.o even though - they aren't used. */ - -void become_root(void) {} -void unbecome_root(void) {} - /* Display usage information */ static void usage(poptContext *pc) diff --git a/source3/utils/smbcquotas.c b/source3/utils/smbcquotas.c index 9c7379ca2a..64321d5bfc 100644 --- a/source3/utils/smbcquotas.c +++ b/source3/utils/smbcquotas.c @@ -371,7 +371,8 @@ static struct cli_state *connect_one(const char *share) &ip, 0, share, "?????", cmdline_auth_info.username, lp_workgroup(), - cmdline_auth_info.password, 0, NULL))) { + cmdline_auth_info.password, 0, + cmdline_auth_info.signing_state, NULL))) { return c; } else { DEBUG(0,("cli_full_connection failed! (%s)\n", nt_errstr(nt_status))); diff --git a/source3/utils/smbpasswd.c b/source3/utils/smbpasswd.c index eade5331af..6ab6d35e73 100644 --- a/source3/utils/smbpasswd.c +++ b/source3/utils/smbpasswd.c @@ -37,21 +37,6 @@ static const char *remote_machine = NULL; static fstring ldap_secret; -/***************************************************************************** - stubb functions -****************************************************************************/ - -void become_root( void ) -{ - return; -} - -void unbecome_root( void ) -{ - return; -} - - /********************************************************* Print command usage on stderr and die. **********************************************************/ diff --git a/source3/utils/status.c b/source3/utils/status.c index bbaeecdd6b..8bf67fc4d6 100644 --- a/source3/utils/status.c +++ b/source3/utils/status.c @@ -45,11 +45,6 @@ static int locks_only = 0; /* Added by RJS */ static BOOL processes_only=False; static int show_brl; -/* we need these because we link to locking*.o */ - void become_root(void) {} - void unbecome_root(void) {} - - /* added by OH */ static void Ucrit_addUsername(const char *username) { diff --git a/source3/web/statuspage.c b/source3/web/statuspage.c index 44461232b8..c579e8f112 100644 --- a/source3/web/statuspage.c +++ b/source3/web/statuspage.c @@ -93,7 +93,7 @@ static char *mapPid2Machine (pid_t pid) } /* PID not in list or machine name NULL? return pid as string */ - snprintf (pidbuf, sizeof (pidbuf) - 1, "%d", pid); + snprintf (pidbuf, sizeof (pidbuf) - 1, "%lu", (unsigned long)pid); return pidbuf; } diff --git a/source3/web/swat.c b/source3/web/swat.c index d97278c485..a1c132a088 100644 --- a/source3/web/swat.c +++ b/source3/web/swat.c @@ -51,10 +51,6 @@ static int iNumNonAutoPrintServices = 0; #define ENABLE_USER_FLAG "enable_user_flag" #define RHOST "remote_host" -/* we need these because we link to locking*.o */ - void become_root(void) {} - void unbecome_root(void) {} - /**************************************************************************** ****************************************************************************/ static int enum_index(int value, const struct enum_list *enumlist) @@ -168,12 +164,12 @@ static const char* get_parm_translated( static pstring output; if(strcmp(pLabel, pTranslated) != 0) { - snprintf(output, sizeof(output), + pstr_sprintf(output, " %s       %s
%s", pAnchor, pHelp, pLabel, pTranslated); return output; } - snprintf(output, sizeof(output), + pstr_sprintf(output, " %s       %s", pAnchor, pHelp, pLabel); return output; @@ -316,9 +312,10 @@ static void show_parameters(int snum, int allparameters, unsigned int parm_filte if (printers & !(parm->flags & FLAG_PRINT)) continue; if (!printers & !(parm->flags & FLAG_SHARE)) continue; } - if (parm_filter == FLAG_BASIC) { + + if (!( parm_filter & FLAG_ADVANCED )) { if (!(parm->flags & FLAG_BASIC)) { - void *ptr = parm->ptr; + void *ptr = parm->ptr; if (parm->class == P_LOCAL && snum >= 0) { ptr = lp_local_ptr(snum, ptr); @@ -359,16 +356,15 @@ static void show_parameters(int snum, int allparameters, unsigned int parm_filte break; case P_SEP: continue; - } + } } 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 ((parm_filter & FLAG_WIZARD) && !(parm->flags & FLAG_WIZARD)) continue; + + if ((parm_filter & FLAG_ADVANCED) && !(parm->flags & FLAG_ADVANCED)) continue; + if (heading && heading != last_heading) { d_printf("%s\n", _(heading)); last_heading = heading; @@ -523,10 +519,12 @@ static void show_main_buttons(void) ****************************************************************************/ static void ViewModeBoxes(int mode) { - d_printf("

%s\n", _("Configuration View: ")); + d_printf("

%s\n", _("Current View Is:  \n")); d_printf("Basic\n", (mode == 0) ? "checked" : ""); d_printf("Advanced\n", (mode == 1) ? "checked" : ""); - d_printf("Developer\n", (mode == 2) ? "checked" : ""); + d_printf("
%s\n", _("Change View To: ")); + d_printf("\n", _("Basic")); + d_printf("\n", _("Advanced")); d_printf("


\n"); } @@ -782,6 +780,10 @@ static void globals_page(void) if ( cgi_variable("ViewMode") ) mode = atoi(cgi_variable("ViewMode")); + if ( cgi_variable("BasicMode")) + mode = 0; + if ( cgi_variable("AdvMode")) + mode = 1; d_printf("
\n"); @@ -793,9 +795,6 @@ static void globals_page(void) case 1: parm_filter = FLAG_ADVANCED; break; - case 2: - parm_filter = FLAG_DEVELOPER; - break; } d_printf("
\n"); if (have_write_access) { @@ -854,8 +853,14 @@ static void shares_page(void) d_printf("\n"); d_printf("\n"); + if ( cgi_variable("ViewMode") ) mode = atoi(cgi_variable("ViewMode")); + if ( cgi_variable("BasicMode")) + mode = 0; + if ( cgi_variable("AdvMode")) + mode = 1; + ViewModeBoxes( mode ); switch ( mode ) { case 0: @@ -864,9 +869,6 @@ static void shares_page(void) case 1: parm_filter = FLAG_ADVANCED; break; - case 2: - parm_filter = FLAG_DEVELOPER; - break; } d_printf("
\n"); d_printf("\n", _("Choose Share")); @@ -1196,6 +1198,11 @@ static void printers_page(void) if ( cgi_variable("ViewMode") ) mode = atoi(cgi_variable("ViewMode")); + if ( cgi_variable("BasicMode")) + mode = 0; + if ( cgi_variable("AdvMode")) + mode = 1; + ViewModeBoxes( mode ); switch ( mode ) { case 0: @@ -1204,9 +1211,6 @@ static void printers_page(void) case 1: parm_filter = FLAG_ADVANCED; break; - case 2: - parm_filter = FLAG_DEVELOPER; - break; } d_printf("
\n"); d_printf("\n", _("Choose Printer")); -- cgit From 4093bf7ff8c8861cf7b941945ede53a8ec5bb6c8 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Tue, 9 Sep 2003 04:07:32 +0000 Subject: sync 3.0 into HEAD for the last time (This used to be commit c17a7dc9a190156a069da3e861c18fd3f81224ad) --- source3/.cvsignore | 1 + source3/Makefile.in | 229 ++- source3/VERSION | 123 ++ source3/aclocal.m4 | 157 +- source3/auth/auth.c | 8 +- source3/auth/auth_domain.c | 3 - source3/auth/auth_rhosts.c | 2 +- source3/auth/auth_sam.c | 87 +- source3/auth/auth_util.c | 126 +- source3/auth/auth_winbind.c | 2 +- source3/auth/pampass.c | 8 +- source3/autogen.sh | 5 + source3/bin/.cvsignore | 2 + source3/client/client.c | 439 +++--- source3/client/clitar.c | 27 +- source3/client/mount.cifs.c | 62 +- source3/client/smbmnt.c | 6 +- source3/client/smbmount.c | 6 +- source3/configure.in | 273 +++- source3/groupdb/mapping.c | 34 +- source3/include/.cvsignore | 1 + source3/include/ads.h | 2 +- source3/include/charset.h | 87 ++ source3/include/includes.h | 10 +- source3/include/nameserv.h | 367 +++-- source3/include/ntdomain.h | 20 +- source3/include/ntioctl.h | 19 + source3/include/ntlmssp.h | 1 + source3/include/ntquotas.h | 2 +- source3/include/rpc_dce.h | 8 +- source3/include/rpc_ds.h | 13 + source3/include/rpc_lsa.h | 6 + source3/include/rpc_samr.h | 14 +- source3/include/rpc_spoolss.h | 6 + source3/include/safe_string.h | 1 + source3/include/secrets.h | 17 + source3/include/smb.h | 12 +- source3/include/smb_macros.h | 6 + source3/include/spnego.h | 65 + source3/include/trans2.h | 2 + source3/include/version.h | 9 +- source3/include/vfs.h | 9 +- source3/include/vfs_macros.h | 3 + source3/intl/lang_tdb.c | 4 +- source3/lib/access.c | 3 +- source3/lib/afs.c | 248 +++ source3/lib/charcnv.c | 331 +++- source3/lib/dummyroot.c | 33 + source3/lib/fault.c | 2 +- source3/lib/gencache.c | 9 +- source3/lib/hash.c | 15 +- source3/lib/module.c | 30 +- source3/lib/ms_fnmatch.c | 82 +- source3/lib/popt_common.c | 35 +- source3/lib/readline.c | 4 +- source3/lib/replace1.c | 42 + source3/lib/smbldap.c | 27 + source3/lib/substitute.c | 31 +- source3/lib/system.c | 159 +- source3/lib/util.c | 81 +- source3/lib/util_file.c | 5 + source3/lib/util_sid.c | 2 +- source3/lib/util_str.c | 202 ++- source3/lib/version.c | 42 + source3/libads/ads_status.c | 2 +- source3/libads/authdata.c | 7 +- source3/libads/kerberos_verify.c | 165 +- source3/libads/krb5_setpw.c | 17 +- source3/libads/ldap.c | 6 +- source3/libads/ldap_utils.c | 5 +- source3/libads/sasl.c | 18 +- source3/libsmb/cliconnect.c | 114 +- source3/libsmb/clientgen.c | 7 +- source3/libsmb/clifile.c | 5 +- source3/libsmb/clikrb5.c | 20 +- source3/libsmb/climessage.c | 2 +- source3/libsmb/cliprint.c | 5 +- source3/libsmb/clirap.c | 10 +- source3/libsmb/clirap2.c | 63 +- source3/libsmb/clireadwrite.c | 2 +- source3/libsmb/clisecdesc.c | 4 +- source3/libsmb/clispnego.c | 3 + source3/libsmb/namequery.c | 2 +- source3/libsmb/namequery_dc.c | 16 +- source3/libsmb/nmblib.c | 34 +- source3/libsmb/ntlmssp.c | 102 +- source3/libsmb/ntlmssp_parse.c | 3 +- source3/libsmb/ntlmssp_sign.c | 24 +- source3/libsmb/smb_signing.c | 160 +- source3/libsmb/smbencrypt.c | 4 +- source3/libsmb/spnego.c | 343 +++++ source3/libsmb/trusts_util.c | 9 +- source3/locking/locking.c | 32 +- source3/modules/CP437.c | 136 ++ source3/modules/CP850.c | 122 ++ source3/modules/getdate.c | 2460 ++++++++++++++++++++++++++++++ source3/modules/getdate.h | 46 + source3/modules/getdate.y | 1115 ++++++++++++++ source3/modules/vfs_cap.c | 448 ++++++ source3/modules/vfs_default_quota.c | 180 +++ source3/modules/vfs_readonly.c | 98 ++ source3/modules/vfs_recycle.c | 5 +- source3/msdfs/README | 32 - source3/msdfs/msdfs.c | 85 +- source3/nmbd/asyncdns.c | 73 +- source3/nmbd/nmbd.c | 208 ++- source3/nmbd/nmbd_become_dmb.c | 522 ++++--- source3/nmbd/nmbd_become_lmb.c | 688 +++++---- source3/nmbd/nmbd_browserdb.c | 10 +- source3/nmbd/nmbd_browsesync.c | 845 +++++------ source3/nmbd/nmbd_elections.c | 530 ++++--- source3/nmbd/nmbd_incomingdgrams.c | 1086 +++++++------- source3/nmbd/nmbd_incomingrequests.c | 606 ++++---- source3/nmbd/nmbd_lmhosts.c | 91 +- source3/nmbd/nmbd_logonnames.c | 195 +-- source3/nmbd/nmbd_mynames.c | 184 ++- source3/nmbd/nmbd_namelistdb.c | 800 +++++----- source3/nmbd/nmbd_namequery.c | 414 +++-- source3/nmbd/nmbd_nameregister.c | 42 +- source3/nmbd/nmbd_nodestatus.c | 68 +- source3/nmbd/nmbd_packets.c | 2499 +++++++++++++++---------------- source3/nmbd/nmbd_processlogon.c | 813 +++++----- source3/nmbd/nmbd_responserecordsdb.c | 318 ++-- source3/nmbd/nmbd_sendannounce.c | 765 +++++----- source3/nmbd/nmbd_serverlistdb.c | 520 +++---- source3/nmbd/nmbd_subnetdb.c | 395 +++-- source3/nmbd/nmbd_synclists.c | 40 +- source3/nmbd/nmbd_winsproxy.c | 260 ++-- source3/nmbd/nmbd_winsserver.c | 2661 ++++++++++++++++----------------- source3/nmbd/nmbd_workgroupdb.c | 364 +++-- source3/nsswitch/pam_winbind.h | 5 +- source3/nsswitch/wb_client.c | 74 + source3/nsswitch/wbinfo.c | 74 +- source3/nsswitch/winbindd.c | 8 +- source3/nsswitch/winbindd_acct.c | 15 +- source3/nsswitch/winbindd_ads.c | 74 +- source3/nsswitch/winbindd_cache.c | 8 +- source3/nsswitch/winbindd_cm.c | 126 +- source3/nsswitch/winbindd_group.c | 12 + source3/nsswitch/winbindd_misc.c | 30 +- source3/nsswitch/winbindd_nss.h | 1 + source3/nsswitch/winbindd_pam.c | 36 +- source3/nsswitch/winbindd_rpc.c | 4 +- source3/nsswitch/winbindd_sid.c | 18 +- source3/nsswitch/winbindd_user.c | 14 +- source3/nsswitch/winbindd_util.c | 131 +- source3/nsswitch/wins.c | 110 +- source3/param/loadparm.c | 65 +- source3/passdb/lookup_sid.c | 488 ++++++ source3/passdb/passdb.c | 105 +- source3/passdb/pdb_interface.c | 4 +- source3/passdb/pdb_ldap.c | 21 +- source3/passdb/pdb_mysql.c | 4 +- source3/passdb/pdb_plugin.c | 8 +- source3/passdb/pdb_tdb.c | 6 +- source3/passdb/secrets.c | 61 +- source3/printing/lpq_parse.c | 8 +- source3/printing/nt_printing.c | 39 +- source3/python/py_lsa.c | 43 +- source3/python/py_smb.c | 25 +- source3/python/py_spoolss_drivers.c | 5 +- source3/python/py_winbind.c | 10 +- source3/rpc_client/cli_netlogon.c | 21 +- source3/rpc_client/cli_pipe.c | 25 +- source3/rpc_client/cli_spoolss.c | 10 +- source3/rpc_parse/parse_echo.c | 8 +- source3/rpc_parse/parse_net.c | 22 +- source3/rpc_parse/parse_prs.c | 16 +- source3/rpc_parse/parse_reg.c | 2 +- source3/rpc_parse/parse_samr.c | 12 +- source3/rpc_parse/parse_spoolss.c | 10 +- source3/rpc_server/srv_dfs.c | 16 +- source3/rpc_server/srv_dfs_nt.c | 4 +- source3/rpc_server/srv_echo.c | 27 +- source3/rpc_server/srv_lsa.c | 43 +- source3/rpc_server/srv_lsa_ds.c | 93 ++ source3/rpc_server/srv_lsa_ds_nt.c | 127 ++ source3/rpc_server/srv_lsa_nt.c | 2 +- source3/rpc_server/srv_netlog.c | 13 +- source3/rpc_server/srv_pipe.c | 209 ++- source3/rpc_server/srv_pipe_hnd.c | 2 + source3/rpc_server/srv_reg.c | 18 +- source3/rpc_server/srv_samr.c | 49 +- source3/rpc_server/srv_samr_nt.c | 112 +- source3/rpc_server/srv_spoolss.c | 13 +- source3/rpc_server/srv_spoolss_nt.c | 26 +- source3/rpc_server/srv_srvsvc.c | 16 +- source3/rpc_server/srv_util.c | 11 +- source3/rpc_server/srv_wkssvc.c | 15 +- source3/rpcclient/cmd_ds.c | 2 +- source3/rpcclient/cmd_netlogon.c | 86 +- source3/rpcclient/cmd_spoolss.c | 44 +- source3/rpcclient/rpcclient.c | 12 +- source3/sam/idmap_ldap.c | 352 +++-- source3/sam/idmap_tdb.c | 41 +- source3/sam/idmap_util.c | 51 +- source3/script/.cvsignore | 1 + source3/script/find_missing_doc.pl | 90 -- source3/script/findsmb.in | 210 +-- source3/script/gap.awk | 39 + source3/script/gaptab.awk | 48 + source3/script/gen-8bit-gap.awk | 18 + source3/script/gen-8bit-gap.sh.in | 49 + source3/script/installmodules.sh | 9 - source3/script/installswat.sh | 18 +- source3/script/linkmodules.sh | 12 + source3/script/mkproto.awk | 14 - source3/script/mkproto.sh | 2 +- source3/script/mkversion.sh | 87 ++ source3/smbadduser | 14 +- source3/smbadduser.in | 79 + source3/smbd/blocking.c | 2 +- source3/smbd/change_trust_pw.c | 5 + source3/smbd/chgpasswd.c | 113 +- source3/smbd/fileio.c | 22 +- source3/smbd/filename.c | 4 +- source3/smbd/files.c | 28 + source3/smbd/lanman.c | 131 +- source3/smbd/mangle_hash2.c | 49 +- source3/smbd/message.c | 2 +- source3/smbd/notify.c | 2 +- source3/smbd/nttrans.c | 189 ++- source3/smbd/open.c | 13 +- source3/smbd/password.c | 5 +- source3/smbd/process.c | 17 +- source3/smbd/reply.c | 307 +++- source3/smbd/sec_ctx.c | 2 +- source3/smbd/server.c | 2 +- source3/smbd/service.c | 9 +- source3/smbd/sesssetup.c | 22 +- source3/smbd/statcache.c | 15 +- source3/smbd/trans2.c | 253 +++- source3/smbd/uid.c | 465 +----- source3/smbd/utmp.c | 10 +- source3/smbd/vfs-wrap.c | 66 +- source3/smbd/vfs.c | 6 +- source3/tdb/tdb.c | 49 +- source3/torture/cmd_vfs.c | 15 +- source3/torture/masktest.c | 2 +- source3/torture/rpctorture.c | 4 +- source3/torture/smbiconv.c | 16 +- source3/utils/log2pcaphex.c | 294 ++++ source3/utils/net.c | 111 +- source3/utils/net_ads.c | 91 +- source3/utils/net_ads_cldap.c | 28 +- source3/utils/net_groupmap.c | 17 +- source3/utils/net_help.c | 10 +- source3/utils/net_lookup.c | 38 +- source3/utils/net_rpc.c | 34 +- source3/utils/net_rpc_samsync.c | 37 +- source3/utils/nmblookup.c | 2 +- source3/utils/ntlm_auth.c | 474 ++++-- source3/utils/profiles.c | 2 +- source3/utils/smbcacls.c | 4 +- source3/utils/smbgroupedit.c | 405 ----- source3/utils/status.c | 2 +- source3/utils/testparm.c | 21 + source3/web/statuspage.c | 2 +- source3/web/swat.c | 11 +- source3/wrepld/server.c | 2 +- 260 files changed, 20170 insertions(+), 11647 deletions(-) create mode 100644 source3/VERSION create mode 100644 source3/include/spnego.h create mode 100644 source3/lib/afs.c create mode 100644 source3/lib/dummyroot.c create mode 100644 source3/lib/replace1.c create mode 100644 source3/lib/version.c create mode 100644 source3/libsmb/spnego.c create mode 100644 source3/modules/CP437.c create mode 100644 source3/modules/CP850.c create mode 100644 source3/modules/getdate.c create mode 100644 source3/modules/getdate.h create mode 100644 source3/modules/getdate.y create mode 100644 source3/modules/vfs_cap.c create mode 100644 source3/modules/vfs_default_quota.c create mode 100644 source3/modules/vfs_readonly.c delete mode 100644 source3/msdfs/README create mode 100644 source3/passdb/lookup_sid.c create mode 100644 source3/rpc_server/srv_lsa_ds.c create mode 100644 source3/rpc_server/srv_lsa_ds_nt.c delete mode 100755 source3/script/find_missing_doc.pl create mode 100644 source3/script/gap.awk create mode 100644 source3/script/gaptab.awk create mode 100644 source3/script/gen-8bit-gap.awk create mode 100755 source3/script/gen-8bit-gap.sh.in create mode 100755 source3/script/linkmodules.sh create mode 100755 source3/script/mkversion.sh create mode 100644 source3/smbadduser.in create mode 100644 source3/utils/log2pcaphex.c delete mode 100644 source3/utils/smbgroupedit.c (limited to 'source3') diff --git a/source3/.cvsignore b/source3/.cvsignore index 074a88cef2..31dd2c3a7a 100644 --- a/source3/.cvsignore +++ b/source3/.cvsignore @@ -28,3 +28,4 @@ testtmp trace.out typescript* configure +smbadduser diff --git a/source3/Makefile.in b/source3/Makefile.in index 4674fd07ae..f7ec500d06 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -3,7 +3,7 @@ # Copyright Andrew Tridgell 1992-1998 # Copyright (C) 2001 by Martin Pool # Copyright Andrew Bartlett 2002 -# Copyright (C) 2003 Jim McDonough +# Copyright (C) 2003 Jim McDonough # Copyright (C) 2002-2003 Jelmer Vernooij ########################################################################### @@ -27,13 +27,13 @@ PERL=@PERL@ TERMLDFLAGS=@TERMLDFLAGS@ TERMLIBS=@TERMLIBS@ -PRINTLIBS=@PRINTLIBS@ -AUTHLIBS=@AUTHLIBS@ -ACLLIBS=@ACLLIBS@ -PASSDBLIBS=@PASSDBLIBS@ +PRINT_LIBS=@PRINT_LIBS@ +AUTH_LIBS=@AUTH_LIBS@ +ACL_LIBS=@ACL_LIBS@ +PASSDB_LIBS=@PASSDB_LIBS@ IDMAP_LIBS=@IDMAP_LIBS@ KRB5LIBS=@KRB5_LIBS@ -LDAPLIBS=@LDAP_LIBS@ +LDAP_LIBS=@LDAP_LIBS@ LINK=$(CC) $(FLAGS) $(LDFLAGS) @@ -51,7 +51,7 @@ SHELL=/bin/sh # /bin/sh on some platforms. I guess it's not a big problem -- mbp # See the autoconf manual "Installation Directory Variables" for a -# discussion of thesubtle use of these variables. +# discussion of the subtle use of these variables. BASEDIR= @prefix@ BINDIR = @bindir@ @@ -139,7 +139,8 @@ TORTURE_PROGS = bin/smbtorture@EXEEXT@ bin/msgtest@EXEEXT@ \ BIN_PROGS = $(BIN_PROGS1) $(BIN_PROGS2) $(BIN_PROGS3) @EXTRA_BIN_PROGS@ -EVERYTHING_PROGS = bin/debug2html@EXEEXT@ bin/smbfilter@EXEEXT@ bin/talloctort@EXEEXT@ +EVERYTHING_PROGS = bin/debug2html@EXEEXT@ bin/smbfilter@EXEEXT@ bin/talloctort@EXEEXT@ \ + bin/log2pcap@EXEEXT@ SHLIBS = @SHLIB_PROGS@ @LIBSMBCLIENT@ @@ -162,7 +163,7 @@ TDB_OBJ = $(TDBBASE_OBJ) tdb/tdbutil.o tdb/tdbback.o SMBLDAP_OBJ = @SMBLDAP@ -LIB_OBJ = lib/charcnv.o lib/debug.o lib/fault.o \ +LIB_OBJ = lib/version.o 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/replace1.o \ lib/signal.o lib/system.o lib/sendfile.o lib/time.o \ @@ -186,6 +187,8 @@ LIB_SMBD_OBJ = lib/system_smbd.o lib/util_smbd.o READLINE_OBJ = lib/readline.o +# Also depends on $(SECRETS_OBJ) $(LIBSAMBA_OBJ) +# Be sure to include them into your application POPT_LIB_OBJ = lib/popt_common.o UBIQX_OBJ = ubiqx/ubi_BinTree.o ubiqx/ubi_Cache.o ubiqx/ubi_SplayTree.o \ @@ -242,6 +245,8 @@ RPC_SAMR_OBJ = rpc_server/srv_samr.o rpc_server/srv_samr_nt.o \ RPC_REG_OBJ = rpc_server/srv_reg.o rpc_server/srv_reg_nt.o +RPC_LSA_DS_OBJ = rpc_server/srv_lsa_ds.o rpc_server/srv_lsa_ds_nt.o + RPC_SVC_OBJ = rpc_server/srv_srvsvc.o rpc_server/srv_srvsvc_nt.o RPC_WKS_OBJ = rpc_server/srv_wkssvc.o rpc_server/srv_wkssvc_nt.o @@ -278,11 +283,13 @@ 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/util_sam_sid.o passdb/pdb_compat.o \ - passdb/privileges.o @PDB_STATIC@ + passdb/privileges.o passdb/lookup_sid.o @PDB_STATIC@ XML_OBJ = passdb/pdb_xml.o MYSQL_OBJ = passdb/pdb_mysql.o -DEVEL_HELP_OBJ = modules/weird.o +DEVEL_HELP_WEIRD_OBJ = modules/weird.o +DEVEL_HELP_CP850_OBJ = modules/CP850.o +DEVEL_HELP_CP437_OBJ = modules/CP437.o GROUPDB_OBJ = groupdb/mapping.o @@ -300,6 +307,8 @@ VFS_FAKE_PERMS_OBJ = modules/vfs_fake_perms.o VFS_RECYCLE_OBJ = modules/vfs_recycle.o VFS_NETATALK_OBJ = modules/vfs_netatalk.o VFS_DEFAULT_QUOTA_OBJ = modules/vfs_default_quota.o +VFS_READONLY_OBJ = modules/vfs_readonly.o modules/getdate.o +VFS_CAP_OBJ = modules/vfs_cap.o PLAINTEXT_AUTH_OBJ = auth/pampass.o auth/pass_check.o @@ -338,7 +347,7 @@ SMBD_OBJ_SRV = smbd/files.o smbd/chgpasswd.o smbd/connection.o \ smbd/process.o smbd/service.o smbd/error.o \ printing/printfsp.o lib/util_seaccess.o \ lib/sysquotas.o smbd/change_trust_pw.o smbd/fake_file.o \ - smbd/quotas.o smbd/ntquotas.o \ + smbd/quotas.o smbd/ntquotas.o lib/afs.o \ $(MANGLE_OBJ) @VFS_STATIC@ SMBD_OBJ_BASE = $(PARAM_OBJ) $(SMBD_OBJ_SRV) $(MSDFS_OBJ) $(LIBSMB_OBJ) \ @@ -396,18 +405,20 @@ SMBSH_OBJ = smbwrapper/smbsh.o smbwrapper/shared.o \ STATUS_OBJ = utils/status.o $(LOCKING_OBJ) $(PARAM_OBJ) \ $(UBIQX_OBJ) $(PROFILE_OBJ) $(LIB_OBJ) $(POPT_LIB_OBJ) \ - lib/dummyroot.o libsmb/errormap.o + $(SECRETS_OBJ) $(LIBSAMBA_OBJ) lib/dummyroot.o libsmb/errormap.o SMBCONTROL_OBJ = utils/smbcontrol.o $(LOCKING_OBJ) $(PARAM_OBJ) \ $(UBIQX_OBJ) $(PROFILE_OBJ) $(LIB_OBJ) $(POPT_LIB_OBJ) \ + $(SECRETS_OBJ) $(LIBSAMBA_OBJ) \ printing/notify.o printing/printing_db.o lib/dummyroot.o libsmb/errormap.o SMBTREE_OBJ = utils/smbtree.o $(LOCKING_OBJ) $(PARAM_OBJ) \ $(UBIQX_OBJ) $(PROFILE_OBJ) $(LIB_OBJ) $(LIBSMB_OBJ) \ - $(KRBCLIENT_OBJ) $(POPT_LIB_OBJ) + $(KRBCLIENT_OBJ) $(POPT_LIB_OBJ) $(SECRETS_OBJ) TESTPARM_OBJ = utils/testparm.o \ - $(PARAM_OBJ) $(UBIQX_OBJ) $(LIB_OBJ) $(POPT_LIB_OBJ) + $(PARAM_OBJ) $(UBIQX_OBJ) $(LIB_OBJ) $(POPT_LIB_OBJ) \ + $(SECRETS_OBJ) $(LIBSAMBA_OBJ) TESTPRNS_OBJ = utils/testprns.o $(PARAM_OBJ) $(PRINTING_OBJ) $(UBIQX_OBJ) \ $(LIB_OBJ) @@ -435,7 +446,7 @@ RPCCLIENT_OBJ = $(RPCCLIENT_OBJ1) \ $(LIBADS_OBJ) $(SECRETS_OBJ) $(POPT_LIB_OBJ) \ $(SMBLDAP_OBJ) $(DCUTIL_OBJ) lib/dummyroot.o -PAM_WINBIND_OBJ = nsswitch/pam_winbind.po nsswitch/wb_common.po lib/replace1.po lib/snprintf.po +PAM_WINBIND_PICOBJ = nsswitch/pam_winbind.po nsswitch/wb_common.po lib/replace1.po lib/snprintf.po SMBW_OBJ1 = smbwrapper/smbw.o \ smbwrapper/smbw_dir.o smbwrapper/smbw_stat.o \ @@ -469,7 +480,7 @@ CLIENT_OBJ1 = client/client.o client/clitar.o CLIENT_OBJ = $(CLIENT_OBJ1) $(PARAM_OBJ) $(LIBSMB_OBJ) $(UBIQX_OBJ) \ $(LIB_OBJ) $(KRBCLIENT_OBJ) \ - $(READLINE_OBJ) $(POPT_LIB_OBJ) + $(READLINE_OBJ) $(POPT_LIB_OBJ) $(SECRETS_OBJ) 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 \ @@ -481,20 +492,20 @@ NET_OBJ = $(NET_OBJ1) $(PARAM_OBJ) $(SECRETS_OBJ) $(LIBSMB_OBJ) \ $(KRBCLIENT_OBJ) $(UBIQX_OBJ) $(LIB_OBJ) \ $(LIBMSRPC_OBJ) $(IDMAP_OBJ) \ $(LIBADS_OBJ) $(LIBADS_SERVER_OBJ) $(POPT_LIB_OBJ) \ - $(SMBLDAP_OBJ) $(DCUTIL_OBJ) lib/dummyroot.o lib/server_mutex.o + $(SMBLDAP_OBJ) $(DCUTIL_OBJ) lib/dummyroot.o lib/server_mutex.o lib/afs.o CUPS_OBJ = client/smbspool.o $(PARAM_OBJ) $(LIBSMB_OBJ) $(UBIQX_OBJ) \ - $(LIB_OBJ) $(KRBCLIENT_OBJ) + $(LIB_OBJ) $(KRBCLIENT_OBJ) $(SECRETS_OBJ) MOUNT_OBJ = client/smbmount.o \ $(PARAM_OBJ) $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) $(UBIQX_OBJ) $(LIB_OBJ) -MNT_OBJ = client/smbmnt.o +MNT_OBJ = client/smbmnt.o lib/version.o lib/snprintf.o UMOUNT_OBJ = client/smbumount.o NMBLOOKUP_OBJ = utils/nmblookup.o $(PARAM_OBJ) $(UBIQX_OBJ) $(LIBNMB_OBJ) \ - $(LIB_OBJ) $(POPT_LIB_OBJ) + $(LIB_OBJ) $(POPT_LIB_OBJ) $(SECRETS_OBJ) $(LIBSAMBA_OBJ) SMBTORTURE_OBJ1 = torture/torture.o torture/nbio.o torture/scanner.o torture/utable.o \ torture/denytest.o torture/mangle_test.o @@ -516,7 +527,9 @@ NSSTEST_OBJ = torture/nsstest.o $(PARAM_OBJ) $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) \ VFSTEST_OBJ = torture/cmd_vfs.o torture/vfstest.o $(SMBD_OBJ_BASE) $(READLINE_OBJ) -SMBICONV_OBJ = $(PARAM_OBJ) torture/smbiconv.o $(LIB_OBJ) $(UBIQX_OBJ) $(POPT_LIB_OBJ) +SMBICONV_OBJ = $(PARAM_OBJ) torture/smbiconv.o $(LIB_OBJ) $(UBIQX_OBJ) $(POPT_LIB_OBJ) $(SECRETS_OBJ) $(LIBSAMBA_OBJ) + +LOG2PCAP_OBJ = utils/log2pcaphex.o LOCKTEST2_OBJ = torture/locktest2.o $(PARAM_OBJ) $(LOCKING_OBJ) $(LIBSMB_OBJ) \ $(KRBCLIENT_OBJ) $(UBIQX_OBJ) $(LIB_OBJ) @@ -558,12 +571,12 @@ PROTO_OBJ = $(SMBD_OBJ_MAIN) \ $(PASSDB_OBJ) $(GROUPDB_OBJ) $(MSDFS_OBJ) \ $(READLINE_OBJ) $(PROFILE_OBJ) $(LIBADS_OBJ) $(LIBADS_SERVER_OBJ) \ $(LIB_SMBD_OBJ) $(SAM_OBJ) $(REGISTRY_OBJ) $(POPT_LIB_OBJ) \ - $(RPC_LSA_OBJ) $(RPC_NETLOG_OBJ) $(RPC_SAMR_OBJ) $(RPC_REG_OBJ) \ + $(RPC_LSA_OBJ) $(RPC_NETLOG_OBJ) $(RPC_SAMR_OBJ) $(RPC_REG_OBJ) $(RPC_LSA_DS_OBJ) \ $(RPC_SVC_OBJ) $(RPC_WKS_OBJ) $(RPC_DFS_OBJ) $(RPC_SPOOLSS_OBJ) \ $(RPC_ECHO_OBJ) $(SMBLDAP_OBJ) $(IDMAP_OBJ) libsmb/spnego.o WINBIND_WINS_NSS_OBJ = nsswitch/wins.o $(PARAM_OBJ) $(UBIQX_OBJ) \ - $(LIBSMB_OBJ) $(LIB_OBJ) $(NSSWINS_OBJ) + $(LIBSMB_OBJ) $(LIB_OBJ) $(NSSWINS_OBJ) $(KRBCLIENT_OBJ) WINBIND_WINS_NSS_PICOBJS = $(WINBIND_WINS_NSS_OBJ:.o=.po) @@ -572,9 +585,8 @@ LIBSMBCLIENT_PICOBJS = $(LIBSMBCLIENT_OBJ:.o=.po) PAM_SMBPASS_OBJ_0 = pam_smbpass/pam_smb_auth.o pam_smbpass/pam_smb_passwd.o \ pam_smbpass/pam_smb_acct.o pam_smbpass/support.o \ - libsmb/smbencrypt.o libsmb/smbdes.o libsmb/nterr.o \ - $(PARAM_OBJ) $(LIB_OBJ) $(PASSDB_OBJ) $(GROUPDB_OBJ) \ - $(SECRETS_OBJ) $(UBIQX_OBJ) + lib/dummyroot.o $(PARAM_OBJ) $(LIB_OBJ) $(PASSDB_OBJ) $(GROUPDB_OBJ) \ + $(SECRETS_OBJ) $(UBIQX_OBJ) $(SMBLDAP_OBJ) $(LIBSAMBA_OBJ) PAM_SMBPASS_PICOOBJ = $(PAM_SMBPASS_OBJ_0:.o=.po) @@ -617,7 +629,10 @@ POPT_OBJS=popt/findme.o popt/popt.o popt/poptconfig.o \ TDBBACKUP_OBJ = tdb/tdbbackup.o tdb/tdbback.o $(TDBBASE_OBJ) NTLM_AUTH_OBJ = utils/ntlm_auth.o $(LIBSAMBA_OBJ) $(POPT_LIB_OBJ) \ - libsmb/asn1.o libsmb/spnego.o + libsmb/asn1.o libsmb/spnego.o libsmb/clikrb5.o libads/kerberos.o \ + libads/kerberos_verify.o $(SECRETS_OBJ) lib/server_mutex.o \ + libads/authdata.o rpc_parse/parse_prs.o rpc_parse/parse_misc.o \ + libsmb/doserr.o ###################################################################### # now the rules... @@ -660,7 +675,8 @@ wins : SHOWFLAGS @WINBIND_WINS_NSS@ modules: SHOWFLAGS proto_exists $(MODULES) -everything: all libsmbclient debug2html smbfilter talloctort modules torture +everything: all libsmbclient debug2html smbfilter talloctort modules torture \ + $(EVERYTHING_PROGS) .SUFFIXES: .SUFFIXES: .c .o .po .lo @@ -694,7 +710,6 @@ MAKEDIR = || exec false; \ # rebuild it's a bit hard. dynconfig.o: dynconfig.c Makefile - @$(MAKE) modules_clean @echo Compiling $*.c @$(CC) $(FLAGS) $(PATH_FLAGS) -c $< -o $@ @@ -706,6 +721,18 @@ dynconfig.po: dynconfig.c Makefile @BROKEN_CC@ -mv `echo $@ | sed -e 's%^.*/%%g' -e 's%\.po$$%.o%'` $@ @POBAD_CC@ @mv $*.po.o $@ +lib/version.o: lib/version.c include/version.h + @echo Compiling $*.c + @$(CC) -I. -I$(srcdir) $(FLAGS) $(PATH_FLAGS) -c $< -o $@ + +lib/version.po: lib/version.c include/version.h + @if (: >> $@ || : > $@) >/dev/null 2>&1; then rm -f $@; else \ + dir=`echo $@ | sed 's,/[^/]*$$,,;s,^$$,.,'` $(MAKEDIR); fi + @echo Compiling $*.c with @PICFLAG@ + @$(CC) -I. -I$(srcdir) $(FLAGS) $(PATH_FLAGS) @PICFLAG@ -c $< -o $*.@PICSUFFIX@ +@BROKEN_CC@ -mv `echo $@ | sed -e 's%^.*/%%g' -e 's%\.po$$%.o%'` $@ +@POBAD_CC@ @mv $*.po.o $@ + smbd/build_options.o: smbd/build_options.c Makefile include/config.h include/build_env.h include/proto.h @echo Compiling $*.c @$(CC) $(FLAGS) $(PATH_FLAGS) -c $< -o $@ @@ -729,12 +756,12 @@ bin/.dummy: bin/smbd@EXEEXT@: $(SMBD_OBJ) @BUILD_POPT@ bin/.dummy @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(SMBD_OBJ) $(KRB5LIBS) $(LDAPLIBS) $(LDFLAGS) $(DYNEXP) $(PRINTLIBS) \ - $(AUTHLIBS) $(ACLLIBS) $(PASSDBLIBS) $(LIBS) @POPTLIBS@ + @$(CC) $(FLAGS) -o $@ $(SMBD_OBJ) $(KRB5LIBS) $(LDAP_LIBS) $(LDFLAGS) $(DYNEXP) $(PRINT_LIBS) \ + $(AUTH_LIBS) $(ACL_LIBS) $(PASSDB_LIBS) $(LIBS) @POPTLIBS@ bin/nmbd@EXEEXT@: $(NMBD_OBJ) @BUILD_POPT@ bin/.dummy @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(NMBD_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAPLIBS) + @$(CC) $(FLAGS) -o $@ $(NMBD_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS) bin/wrepld@EXEEXT@: $(WREPL_OBJ) @BUILD_POPT@ bin/.dummy @echo Linking $@ @@ -742,20 +769,20 @@ bin/wrepld@EXEEXT@: $(WREPL_OBJ) @BUILD_POPT@ bin/.dummy bin/swat@EXEEXT@: $(SWAT_OBJ) @BUILD_POPT@ bin/.dummy @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(SWAT_OBJ) $(LDFLAGS) $(DYNEXP) $(PRINTLIBS) \ - $(AUTHLIBS) $(LIBS) $(PASSDBLIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAPLIBS) + @$(CC) $(FLAGS) -o $@ $(SWAT_OBJ) $(LDFLAGS) $(DYNEXP) $(PRINT_LIBS) \ + $(AUTH_LIBS) $(LIBS) $(PASSDB_LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS) bin/rpcclient@EXEEXT@: $(RPCCLIENT_OBJ) @BUILD_POPT@ bin/.dummy @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(PASSDBLIBS) $(RPCCLIENT_OBJ) $(LDFLAGS) $(DYNEXP) $(TERMLDFLAGS) $(TERMLIBS) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAPLIBS) + @$(CC) $(FLAGS) -o $@ $(PASSDB_LIBS) $(RPCCLIENT_OBJ) $(LDFLAGS) $(DYNEXP) $(TERMLDFLAGS) $(TERMLIBS) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS) bin/smbclient@EXEEXT@: $(CLIENT_OBJ) @BUILD_POPT@ bin/.dummy @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(CLIENT_OBJ) $(LDFLAGS) $(DYNEXP) $(TERMLDFLAGS) $(TERMLIBS) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAPLIBS) + @$(CC) $(FLAGS) -o $@ $(CLIENT_OBJ) $(LDFLAGS) $(DYNEXP) $(TERMLDFLAGS) $(TERMLIBS) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS) bin/net@EXEEXT@: $(NET_OBJ) @BUILD_POPT@ bin/.dummy @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(NET_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAPLIBS) $(PASSDBLIBS) + @$(CC) $(FLAGS) -o $@ $(NET_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS) $(PASSDB_LIBS) bin/profiles@EXEEXT@: $(PROFILES_OBJ) @BUILD_POPT@ bin/.dummy @echo Linking $@ @@ -767,11 +794,11 @@ bin/editreg@EXEEXT@: $(EDITREG_OBJ) @BUILD_POPT@ bin/.dummy bin/smbspool@EXEEXT@: $(CUPS_OBJ) bin/.dummy @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(CUPS_OBJ) $(LDFLAGS) $(LIBS) $(KRB5LIBS) $(LDAPLIBS) + @$(CC) $(FLAGS) -o $@ $(CUPS_OBJ) $(LDFLAGS) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) bin/smbmount@EXEEXT@: $(MOUNT_OBJ) bin/.dummy @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(MOUNT_OBJ) $(LDFLAGS) $(LIBS) $(KRB5LIBS) $(LDAPLIBS) + @$(CC) $(FLAGS) -o $@ $(MOUNT_OBJ) $(LDFLAGS) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) bin/smbmnt@EXEEXT@: $(MNT_OBJ) bin/.dummy @echo Linking $@ @@ -787,39 +814,42 @@ bin/testparm@EXEEXT@: $(TESTPARM_OBJ) @BUILD_POPT@ bin/.dummy bin/testprns@EXEEXT@: $(TESTPRNS_OBJ) bin/.dummy @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(TESTPRNS_OBJ) $(LDFLAGS) $(DYNEXP) $(PRINTLIBS) $(LIBS) + @$(CC) $(FLAGS) -o $@ $(TESTPRNS_OBJ) $(LDFLAGS) $(DYNEXP) $(PRINT_LIBS) $(LIBS) bin/smbstatus@EXEEXT@: $(STATUS_OBJ) @BUILD_POPT@ bin/.dummy @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(STATUS_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) @POPTLIBS@ + @$(CC) $(FLAGS) -o $@ $(STATUS_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) \ + @POPTLIBS@ bin/smbcontrol@EXEEXT@: $(SMBCONTROL_OBJ) @BUILD_POPT@ bin/.dummy @echo Linking $@ - @$(CC) -DUSING_SMBCONTROL $(FLAGS) -o $@ $(SMBCONTROL_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) @POPTLIBS@ + @$(CC) -DUSING_SMBCONTROL $(FLAGS) -o $@ $(SMBCONTROL_OBJ) $(DYNEXP) \ + $(LDFLAGS) $(LIBS) \ + @POPTLIBS@ bin/smbtree@EXEEXT@: $(SMBTREE_OBJ) @BUILD_POPT@ bin/.dummy @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(SMBTREE_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAPLIBS) + @$(CC) $(FLAGS) -o $@ $(SMBTREE_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS) bin/smbpasswd@EXEEXT@: $(SMBPASSWD_OBJ) bin/.dummy @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(SMBPASSWD_OBJ) $(PASSDBLIBS) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAPLIBS) + @$(CC) $(FLAGS) -o $@ $(SMBPASSWD_OBJ) $(PASSDB_LIBS) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) bin/pdbedit@EXEEXT@: $(PDBEDIT_OBJ) @BUILD_POPT@ bin/.dummy @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(PDBEDIT_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) @POPTLIBS@ $(PASSDBLIBS) + @$(CC) $(FLAGS) -o $@ $(PDBEDIT_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) @POPTLIBS@ $(PASSDB_LIBS) bin/samtest@EXEEXT@: $(SAMTEST_OBJ) @BUILD_POPT@ bin/.dummy @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(SAMTEST_OBJ) $(LDFLAGS) $(TERMLDFLAGS) $(TERMLIBS) $(DYNEXP) $(LIBS) @POPTLIBS@ $(PASSDBLIBS) $(KRB5LIBS) $(LDAPLIBS) + @$(CC) $(FLAGS) -o $@ $(SAMTEST_OBJ) $(LDFLAGS) $(TERMLDFLAGS) $(TERMLIBS) $(DYNEXP) $(LIBS) @POPTLIBS@ $(PASSDB_LIBS) $(KRB5LIBS) $(LDAP_LIBS) bin/nmblookup@EXEEXT@: $(NMBLOOKUP_OBJ) @BUILD_POPT@ bin/.dummy @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(NMBLOOKUP_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) @POPTLIBS@ $(LDAPLIBS) + @$(CC) $(FLAGS) -o $@ $(NMBLOOKUP_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) @POPTLIBS@ $(LDAP_LIBS) bin/smbtorture@EXEEXT@: $(SMBTORTURE_OBJ) bin/.dummy @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(SMBTORTURE_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAPLIBS) + @$(CC) $(FLAGS) -o $@ $(SMBTORTURE_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) $(SECRETS_OBJ) bin/talloctort@EXEEXT@: $(TALLOCTORT_OBJ) bin/.dummy @echo Linking $@ @@ -827,43 +857,47 @@ bin/talloctort@EXEEXT@: $(TALLOCTORT_OBJ) bin/.dummy bin/masktest@EXEEXT@: $(MASKTEST_OBJ) bin/.dummy @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(MASKTEST_OBJ) $(LDFLAGS) $(LIBS) $(KRB5LIBS) $(LDAPLIBS) + @$(CC) $(FLAGS) -o $@ $(MASKTEST_OBJ) $(LDFLAGS) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) $(SECRETS_OBJ) bin/msgtest@EXEEXT@: $(MSGTEST_OBJ) bin/.dummy @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(MSGTEST_OBJ) $(LDFLAGS) $(LIBS) $(KRB5LIBS) $(LDAPLIBS) + @$(CC) $(FLAGS) -o $@ $(MSGTEST_OBJ) $(LDFLAGS) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) bin/smbcacls@EXEEXT@: $(SMBCACLS_OBJ) @BUILD_POPT@ bin/.dummy @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(SMBCACLS_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAPLIBS) + @$(CC) $(FLAGS) -o $@ $(SMBCACLS_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS) bin/smbcquotas@EXEEXT@: $(SMBCQUOTAS_OBJ) @BUILD_POPT@ bin/.dummy @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(SMBCQUOTAS_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAPLIBS) + @$(CC) $(FLAGS) -o $@ $(SMBCQUOTAS_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS) bin/locktest@EXEEXT@: $(LOCKTEST_OBJ) bin/.dummy @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(LOCKTEST_OBJ) $(LDFLAGS) $(LIBS) $(KRB5LIBS) $(LDAPLIBS) + @$(CC) $(FLAGS) -o $@ $(LOCKTEST_OBJ) $(LDFLAGS) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) bin/nsstest@EXEEXT@: $(NSSTEST_OBJ) bin/.dummy @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(NSSTEST_OBJ) $(LDFLAGS) $(LIBS) $(KRB5LIBS) $(LDAPLIBS) + @$(CC) $(FLAGS) -o $@ $(NSSTEST_OBJ) $(LDFLAGS) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) bin/vfstest@EXEEXT@: $(VFSTEST_OBJ) @BUILD_POPT@ bin/.dummy @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(VFSTEST_OBJ) $(LDFLAGS) $(TERMLDFLAGS) $(TERMLIBS) $(DYNEXP) $(PRINTLIBS) $(AUTHLIBS) $(ACLLIBS) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAPLIBS) + @$(CC) $(FLAGS) -o $@ $(VFSTEST_OBJ) $(LDFLAGS) $(TERMLDFLAGS) $(TERMLIBS) $(DYNEXP) $(PRINT_LIBS) $(AUTH_LIBS) $(ACL_LIBS) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS) bin/smbiconv@EXEEXT@: $(SMBICONV_OBJ) @BUILD_POPT@ bin/.dummy @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(SMBICONV_OBJ) $(LDFLAGS) $(TERMLDFLAGS) $(TERMLIBS) $(DYNEXP) $(LIBS) @POPTLIBS@ +bin/log2pcap@EXEEXT@: $(LOG2PCAP_OBJ) @BUILD_POPT@ bin/.dummy + @echo Linking $@ + @$(CC) $(FLAGS) -o $@ $(LOG2PCAP_OBJ) $(LDFLAGS) @POPTLIBS@ $(LIBS) + bin/locktest2@EXEEXT@: $(LOCKTEST2_OBJ) bin/.dummy @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(LOCKTEST2_OBJ) $(LDFLAGS) $(LIBS) $(KRB5LIBS) $(LDAPLIBS) + @$(CC) $(FLAGS) -o $@ $(LOCKTEST2_OBJ) $(LDFLAGS) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) bin/rpctorture@EXEEXT@: $(RPCTORTURE_OBJ) bin/.dummy @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(RPCTORTURE_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) $(KRB5LIBS) $(LDAPLIBS) + @$(CC) $(FLAGS) -o $@ $(RPCTORTURE_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) bin/debug2html@EXEEXT@: $(DEBUG2HTML_OBJ) bin/.dummy @echo Linking $@ @@ -871,11 +905,11 @@ bin/debug2html@EXEEXT@: $(DEBUG2HTML_OBJ) bin/.dummy bin/smbfilter@EXEEXT@: $(SMBFILTER_OBJ) bin/.dummy @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(SMBFILTER_OBJ) $(LDFLAGS) $(LIBS) $(KRB5LIBS) $(LDAPLIBS) + @$(CC) $(FLAGS) -o $@ $(SMBFILTER_OBJ) $(LDFLAGS) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) bin/smbw_sample@EXEEXT@: $(SMBW_OBJ) utils/smbw_sample.o bin/.dummy @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(SMBW_OBJ) utils/smbw_sample.o $(LDFLAGS) $(LIBS) $(KRB5LIBS) $(LDAPLIBS) + @$(CC) $(FLAGS) -o $@ $(SMBW_OBJ) utils/smbw_sample.o $(LDFLAGS) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) bin/smbsh@EXEEXT@: $(SMBSH_OBJ) bin/.dummy @echo Linking $@ @@ -884,13 +918,13 @@ bin/smbsh@EXEEXT@: $(SMBSH_OBJ) bin/.dummy bin/smbwrapper.@SHLIBEXT@: $(PICOBJS) bin/.dummy @echo Linking shared library $@ @$(SHLD) $(LDSHFLAGS) -o $@ $(PICOBJS) $(LIBS) \ - $(KRB5LIBS) $(LDAPLIBS) \ + $(KRB5LIBS) $(LDAP_LIBS) \ @SONAMEFLAG@`basename $@` bin/libsmbclient.@SHLIBEXT@: $(LIBSMBCLIENT_PICOBJS) @echo Linking libsmbclient shared library $@ @$(SHLD) $(LDSHFLAGS) -o $@ $(LIBSMBCLIENT_PICOBJS) $(LDFLAGS) $(LIBS) \ - $(KRB5LIBS) $(LDAPLIBS) \ + $(KRB5LIBS) $(LDAP_LIBS) \ @SONAMEFLAG@`basename $@`.$(LIBSMBCLIENT_MAJOR) bin/libsmbclient.a: $(LIBSMBCLIENT_PICOBJS) @@ -901,7 +935,7 @@ bin/libsmbclient.a: $(LIBSMBCLIENT_PICOBJS) bin/libbigballofmud.@SHLIBEXT@: $(LIBBIGBALLOFMUD_PICOBJS) @echo Linking bigballofmud shared library $@ @$(SHLD) $(LDSHFLAGS) -o $@ $(LIBBIGBALLOFMUD_PICOBJS) $(LIBS) \ - $(PASSDBLIBS) $(IDMAP_LIBS) $(KRB5LIBS) $(LDAPLIBS) \ + $(PASSDB_LIBS) $(IDMAP_LIBS) $(KRB5LIBS) $(LDAP_LIBS) \ @SONAMEFLAG@`basename $@`.$(LIBBIGBALLOFMUD_MAJOR) ln -snf libbigballofmud.so bin/libbigballofmud.so.0 @@ -942,6 +976,11 @@ bin/librpc_winreg.@SHLIBEXT@: $(RPC_REG_OBJ) @$(SHLD) $(LDSHFLAGS) -o $@ $(RPC_REG_OBJ) -lc \ @SONAMEFLAG@`basename $@` +bin/librpc_lsa_ds.@SHLIBEXT@: $(RPC_LSA_DS_OBJ) + @echo "Linking $@" + @$(SHLD) $(LDSHFLAGS) -o $@ $(RPC_LSA_DS_OBJ) -lc \ + @SONAMEFLAG@`basename $@` + bin/librpc_spoolss.@SHLIBEXT@: $(RPC_SPOOLSS_OBJ) @echo "Linking $@" @$(SHLD) $(LDSHFLAGS) -o $@ $(RPC_SPOOLSS_OBJ) -lc \ @@ -959,7 +998,10 @@ bin/librpc_echo.@SHLIBEXT@: $(RPC_ECHO_OBJ) bin/winbindd@EXEEXT@: $(WINBINDD_OBJ) @BUILD_POPT@ bin/.dummy @echo "Linking $@" - @$(LINK) -o $@ $(WINBINDD_OBJ) $(DYNEXP) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAPLIBS) + @$(LINK) -o $@ $(WINBINDD_OBJ) $(DYNEXP) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS) + +# Please don't add .o files to libnss_winbind, libnss_wins, or the pam_winbind +# libraries. Add to the appropriate PICOBJ variable instead. @WINBIND_NSS@: $(WINBIND_NSS_PICOBJS) @echo "Linking $@" @@ -969,12 +1011,12 @@ bin/winbindd@EXEEXT@: $(WINBINDD_OBJ) @BUILD_POPT@ bin/.dummy @WINBIND_WINS_NSS@: $(WINBIND_WINS_NSS_PICOBJS) @echo "Linking $@" @$(SHLD) $(LDSHFLAGS) -o $@ $(WINBIND_WINS_NSS_PICOBJS) \ - $(KRBCLIENT_OBJ) $(LDAPLIBS) $(KRB5LIBS) -lc \ + $(LDAP_LIBS) $(KRB5LIBS) -lc \ @SONAMEFLAG@`basename $@` -nsswitch/pam_winbind.@SHLIBEXT@: $(PAM_WINBIND_OBJ) bin/.dummy +nsswitch/pam_winbind.@SHLIBEXT@: $(PAM_WINBIND_PICOBJ) bin/.dummy @echo "Linking $@" - @$(SHLD) $(LDSHFLAGS) -o $@ $(PAM_WINBIND_OBJ) \ + @$(SHLD) $(LDSHFLAGS) -o $@ $(PAM_WINBIND_PICOBJ) \ @SONAMEFLAG@`basename $@` -lpam bin/rhosts.@SHLIBEXT@: $(AUTH_RHOSTS_OBJ:.o=.po) @@ -989,7 +1031,7 @@ bin/domain.@SHLIBEXT@: $(AUTH_DOMAIN_OBJ:.o=.po) @echo "Building plugin $@" @$(SHLD) $(LDSHFLAGS) -o $@ $(AUTH_DOMAIN_OBJ:.o=.po) @SONAMEFLAG@`basename $@` -bin/server.@SHLIBEXT@: $(AUTH_SERVER_OBJ:.o=.po) +bin/smbserver.@SHLIBEXT@: $(AUTH_SERVER_OBJ:.o=.po) @echo "Building plugin $@" @$(SHLD) $(LDSHFLAGS) -o $@ $(AUTH_SERVER_OBJ:.o=.po) @SONAMEFLAG@`basename $@` @@ -1012,7 +1054,7 @@ bin/mysql.@SHLIBEXT@: $(MYSQL_OBJ:.o=.po) bin/ldapsam.@SHLIBEXT@: passdb/pdb_ldap.po @echo "Building plugin $@" - @$(SHLD) $(LDSHFLAGS) $(LDAPLIBS) -o $@ passdb/pdb_ldap.po \ + @$(SHLD) $(LDSHFLAGS) $(LDAP_LIBS) -o $@ passdb/pdb_ldap.po \ @SONAMEFLAG@`basename $@` bin/tdbsam.@SHLIBEXT@: passdb/pdb_tdb.po @@ -1025,9 +1067,19 @@ bin/smbpasswd.@SHLIBEXT@: passdb/pdb_smbpasswd.po @$(SHLD) $(LDSHFLAGS) -o $@ passdb/pdb_smbpasswd.po \ @SONAMEFLAG@`basename $@` -bin/weird.@SHLIBEXT@: $(DEVEL_HELP_OBJ:.o=.po) +bin/weird.@SHLIBEXT@: $(DEVEL_HELP_WEIRD_OBJ:.o=.po) + @echo "Building plugin $@" + @$(SHLD) $(LDSHFLAGS) -o $@ $(DEVEL_HELP_WEIRD_OBJ:.o=.po) \ + @SONAMEFLAG@`basename $@` + +bin/CP850.@SHLIBEXT@: $(DEVEL_HELP_CP850_OBJ:.o=.po) @echo "Building plugin $@" - @$(SHLD) $(LDSHFLAGS) -o $@ $(DEVEL_HELP_OBJ:.o=.po) \ + @$(SHLD) $(LDSHFLAGS) -o $@ $(DEVEL_HELP_CP850_OBJ:.o=.po) \ + @SONAMEFLAG@`basename $@` + +bin/CP437.@SHLIBEXT@: $(DEVEL_HELP_CP437_OBJ:.o=.po) + @echo "Building plugin $@" + @$(SHLD) $(LDSHFLAGS) -o $@ $(DEVEL_HELP_CP437_OBJ:.o=.po) \ @SONAMEFLAG@`basename $@` bin/xml.@SHLIBEXT@: $(XML_OBJ:.o=.po) @@ -1065,6 +1117,16 @@ bin/default_quota.@SHLIBEXT@: $(VFS_DEFAULT_QUOTA_OBJ:.o=.po) @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_DEFAULT_QUOTA_OBJ:.o=.po) \ @SONAMEFLAG@`basename $@` +bin/readonly.@SHLIBEXT@: $(VFS_READONLY_OBJ:.o=.po) + @echo "Building plugin $@" + @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_READONLY_OBJ:.o=.po) \ + @SONAMEFLAG@`basename $@` + +bin/cap.@SHLIBEXT@: $(VFS_CAP_OBJ:.o=.po) + @echo "Building plugin $@" + @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_CAP_OBJ:.o=.po) \ + @SONAMEFLAG@`basename $@` + bin/wbinfo@EXEEXT@: $(WBINFO_OBJ) @BUILD_POPT@ bin/.dummy @echo Linking $@ @$(LINK) -o $@ $(WBINFO_OBJ) $(LIBS) @POPTLIBS@ @@ -1073,11 +1135,11 @@ bin/ntlm_auth@EXEEXT@: $(NTLM_AUTH_OBJ) $(PARAM_OBJ) $(LIB_OBJ) \ $(UBIQX_OBJ) @BUILD_POPT@ bin/.dummy @echo Linking $@ @$(LINK) -o $@ $(NTLM_AUTH_OBJ) $(PARAM_OBJ) $(LIB_OBJ) \ - $(UBIQX_OBJ) $(LIBS) @POPTLIBS@ + $(UBIQX_OBJ) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS) bin/pam_smbpass.@SHLIBEXT@: $(PAM_SMBPASS_PICOOBJ) @echo "Linking shared library $@" - @$(SHLD) $(LDSHFLAGS) -o $@ $(PAM_SMBPASS_PICOOBJ) -lpam $(DYNEXP) $(LIBS) -lc + @$(SHLD) $(LDSHFLAGS) -o $@ $(PAM_SMBPASS_PICOOBJ) -lpam $(DYNEXP) $(LIBS) -lc $(LDAP_LIBS) $(KRB5LIBS) bin/libmsrpc.a: $(LIBMSRPC_PICOBJ) @-$(AR) -rc $@ $(LIBMSRPC_PICOBJ) @@ -1099,7 +1161,7 @@ bin/t_push_ucs2@EXEEXT@: bin/libbigballofmud.@SHLIBEXT@ torture/t_push_ucs2.o bin/t_snprintf@EXEEXT@: lib/snprintf.c $(CC) $(FLAGS) -o $@ -DTEST_SNPRINTF lib/snprintf.c -lm -install: installbin installman installscripts installdat installswat installmodules +install: installbin installman installscripts installdat installswat installmodules @INSTALLCLIENT@ install-everything: install installmodules @@ -1129,6 +1191,13 @@ installmodules: modules installdirs @$(SHELL) $(srcdir)/script/installmodules.sh $(INSTALLPERMS) $(DESTDIR)$(BASEDIR) $(DESTDIR)$(IDMAPLIBDIR) $(IDMAP_MODULES) @$(SHELL) $(srcdir)/script/installmodules.sh $(INSTALLPERMS) $(DESTDIR)$(BASEDIR) $(DESTDIR)$(CHARSETLIBDIR) $(CHARSET_MODULES) @$(SHELL) $(srcdir)/script/installmodules.sh $(INSTALLPERMS) $(DESTDIR)$(BASEDIR) $(DESTDIR)$(AUTHLIBDIR) $(AUTH_MODULES) + @# These symlinks are required for the 'probing' of modules. + @# This mechanism should go at some point.. + @$(SHELL) $(srcdir)/script/linkmodules.sh $(DESTDIR)$(PDBLIBDIR) ldapsam.@SHLIBEXT@ ldapsam_compat.@SHLIBEXT@ + @$(SHELL) $(srcdir)/script/linkmodules.sh $(DESTDIR)$(AUTHLIBDIR) rhosts.@SHLIBEXT@ hostsequiv.@SHLIBEXT@ + @$(SHELL) $(srcdir)/script/linkmodules.sh $(DESTDIR)$(AUTHLIBDIR) sam.@SHLIBEXT@ sam_ignoredomain.@SHLIBEXT@ + @$(SHELL) $(srcdir)/script/linkmodules.sh $(DESTDIR)$(AUTHLIBDIR) domain.@SHLIBEXT@ trustdomain.@SHLIBEXT@ ntdomain.@SHLIBEXT@ + @$(SHELL) $(srcdir)/script/linkmodules.sh $(DESTDIR)$(AUTHLIBDIR) builtin.@SHLIBEXT@ guest.@SHLIBEXT@ fixed_challenge.@SHLIBEXT@ name_to_ntstatus.@SHLIBEXT@ installscripts: installdirs @$(SHELL) $(srcdir)/script/installscripts.sh $(INSTALLPERMS) $(DESTDIR)$(BINDIR) $(SCRIPTS) @@ -1160,7 +1229,7 @@ python_ext: $(PYTHON_PICOBJS) fi PYTHON_OBJS="$(PYTHON_PICOBJS)" \ PYTHON_CFLAGS="$(CFLAGS) $(CPPFLAGS) $(FLAGS)" \ - LIBS="$(LIBS) $(PASSDBLIBS) $(IDMAP_LIBS) $(KRB5LIBS) $(LDAPLIBS)" \ + LIBS="$(LIBS) $(PASSDB_LIBS) $(IDMAP_LIBS) $(KRB5LIBS) $(LDAP_LIBS)" \ $(PYTHON) python/setup.py build python_install: $(PYTHON_PICOBJS) @@ -1223,11 +1292,6 @@ clean: delheaders python_clean $(TOPFILES) $(BIN_PROGS) $(SBIN_PROGS) $(MODULES) $(TORTURE_PROGS) \ $(LIBSMBCLIENT) $(EVERYTHING_PROGS) .headers.stamp -# This is quite ugly actually.. But we need to make -# sure the changes to include/config.h are used. -modules_clean: - @-rm -f auth/auth.o passdb/pdb_interface.o smbd/server.o lib/iconv.o smbd/vfs.o sam/idmap.o - # Making this target will just make sure that the prototype files # exist, not necessarily that they are up to date. Since they're # removed by "make clean" this will always be run when you do anything @@ -1315,6 +1379,11 @@ distclean: realclean -rm -f config.status config.cache so_locations -rm -rf .deps +realdistclean: distclean + -rm -f include/config.h.in + -rm -f include/version.h + -rm -f configure + # this target is really just for my use. It only works on a limited # range of machines and is used to produce a list of potentially # dead (ie. unused) functions in the code. (tridge) diff --git a/source3/VERSION b/source3/VERSION new file mode 100644 index 0000000000..9cf8b11ef1 --- /dev/null +++ b/source3/VERSION @@ -0,0 +1,123 @@ +######################################################## +# SAMBA Version # +# # +# script/mkversion.sh # +# will use this file to create # +# include/version.h # +# # +######################################################## + +######################################################## +# This are the main SAMBA version numbers # +# # +# .. # +# # +# e.g. SAMBA_VERSION_MAJOR=3 # +# SAMBA_VERSION_MINOR=0 # +# SAMBA_VERSION_RELEASE=0 # +# -> "3.0.0" # +######################################################## +SAMBA_VERSION_MAJOR=3 +SAMBA_VERSION_MINOR=0 +SAMBA_VERSION_RELEASE=1 + +######################################################## +# If a official release has a serious bug # +# a security release will have 'a' sufffix # +# # +# so SAMBA's version will be # +# .. # +# # +# e.g. SAMBA_VERSION_PRE_RELEASE=a # +# -> "2.2.8a" # +######################################################## +SAMBA_VERSION_REVISION= + +######################################################## +# For 'pre' releases the version will be # +# # +# ..pre # +# # +# e.g. SAMBA_VERSION_PRE_RELEASE=1 # +# -> "2.2.9pre1" # +######################################################## +SAMBA_VERSION_PRE_RELEASE=1 + +######################################################## +# For 'rc' releases the version will be # +# # +# ..rc # +# # +# e.g. SAMBA_VERSION_RC_RELEASE=1 # +# -> "3.0.0rc1" # +######################################################## +SAMBA_VERSION_RC_RELEASE= + +######################################################## +# For 'beta' releases the version will be # +# # +# ..beta # +# # +# e.g. SAMBA_VERSION_BETA_RELEASE=3 # +# -> "3.0.0beta3" # +######################################################## +SAMBA_VERSION_BETA_RELEASE= + +######################################################## +# For 'alpha' releases the version will be # +# # +# ..alpha # +# # +# e.g. SAMBA_VERSION_ALPHA_RELEASE=1 # +# -> "4.0.0alpha1" # +######################################################## +SAMBA_VERSION_ALPHA_RELEASE= + +######################################################## +# For 'test' releases the version will be # +# # +# ..test # +# # +# e.g. SAMBA_VERSION_TEST_RELEASE=1 # +# -> "4.0.0test1" # +######################################################## +SAMBA_VERSION_TEST_RELEASE= + +######################################################## +# To mark CVS snapshots this should be set to 'yes' # +# in the development BRANCH, and set to 'no' only in # +# the SAMBA_X_X_RELEASE BRANCH # +# # +# ..[...]cvs # +# # +# e.g. SAMBA_VERSION_IS_CVS_SNAPSHOT=yes # +# -> "CVS 3.0.0rc2" # +######################################################## +SAMBA_VERSION_IS_CVS_SNAPSHOT=yes + +######################################################## +# This can be set by vendors if they want... # +# This can be a string constant or a function which # +# returns a string (const char *) # +# # +# ..[...]- # +# # +# Note the '-' is automaticaly added # +# # +# e.g. SAMBA_VERSION_VENDOR_SUFFIX="VendorVersion" # +# -> "CVS 3.0.0rc2-VendorVersion" # +# # +# Note: If you want to use a function, # +# then patch lib/version.c and add this function # +# there, because the symbol must be available in # +# binary. # +# # +# const char *vendor_version(void) # +# { # +# return "VendorVersion"; # +# } # +# # +# e.g. SAMBA_VERSION_VENDOR_SUFFIX=vendor_version() # +# -> "CVS 3.0.0rc2-VendorVersion" # +######################################################## +SAMBA_VERSION_VENDOR_SUFFIX= diff --git a/source3/aclocal.m4 b/source3/aclocal.m4 index 3a49f7e249..52396e56d6 100644 --- a/source3/aclocal.m4 +++ b/source3/aclocal.m4 @@ -54,6 +54,7 @@ AC_DEFUN(SMB_MODULE, $4_MODULES="$$4_MODULES $3" AC_MSG_RESULT([shared]) [$6] + string_shared_modules="$string_shared_modules $1" elif test x"$DEST" = xSTATIC; then [init_static_modules_]translit([$4], [A-Z], [a-z])="$[init_static_modules_]translit([$4], [A-Z], [a-z]) $1_init();" string_static_modules="$string_static_modules $1" @@ -62,6 +63,7 @@ AC_DEFUN(SMB_MODULE, [$5] AC_MSG_RESULT([static]) else + string_ignored_modules="$string_ignored_modules $1" AC_MSG_RESULT([not]) fi ]) @@ -71,6 +73,7 @@ AC_DEFUN(SMB_SUBSYSTEM, AC_SUBST($1_STATIC) AC_SUBST($1_MODULES) AC_DEFINE_UNQUOTED([static_init_]translit([$1], [A-Z], [a-z]), [{$init_static_modules_]translit([$1], [A-Z], [a-z])[}], [Static init functions]) + ifelse([$2], , :, [touch $2]) ]) dnl AC_PROG_CC_FLAG(flag) @@ -448,8 +451,6 @@ AC_ARG_WITH(mysql-prefix,[ --with-mysql-prefix=PFX Prefix where MYSQL is inst mysql_prefix="$withval", mysql_prefix="") AC_ARG_WITH(mysql-exec-prefix,[ --with-mysql-exec-prefix=PFX Exec prefix where MYSQL is installed (optional)], mysql_exec_prefix="$withval", mysql_exec_prefix="") -AC_ARG_ENABLE(mysqltest, [ --disable-mysqltest Do not try to compile and run a test MYSQL program], - , enable_mysqltest=yes) if test x$mysql_exec_prefix != x ; then mysql_args="$mysql_args --exec-prefix=$mysql_exec_prefix" @@ -466,143 +467,21 @@ AC_ARG_ENABLE(mysqltest, [ --disable-mysqltest Do not try to compile and AC_REQUIRE([AC_CANONICAL_TARGET]) AC_PATH_PROG(MYSQL_CONFIG, mysql_config, no) - min_mysql_version=ifelse([$1], ,0.11.0,$1) - AC_MSG_CHECKING(for MYSQL - version >= $min_mysql_version) + AC_MSG_CHECKING(for MYSQL) no_mysql="" if test "$MYSQL_CONFIG" = "no" ; then - no_mysql=yes + MYSQL_CFLAGS="" + MYSQL_LIBS="" + AC_MSG_RESULT(no) + ifelse([$2], , :, [$2]) else MYSQL_CFLAGS=`$MYSQL_CONFIG $mysqlconf_args --cflags | sed -e "s/'//g"` MYSQL_LIBS=`$MYSQL_CONFIG $mysqlconf_args --libs | sed -e "s/'//g"` - - mysql_major_version=`$MYSQL_CONFIG $mysql_args --version | \ - sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` - mysql_minor_version=`$MYSQL_CONFIG $mysql_args --version | \ - sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` - mysql_micro_version=`$MYSQL_CONFIG $mysql_config_args --version | \ - sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` - if test "x$enable_mysqltest" = "xyes" ; then - ac_save_CFLAGS="$CFLAGS" - ac_save_LIBS="$LIBS" - CFLAGS="$CFLAGS $MYSQL_CFLAGS" - LIBS="$LIBS $MYSQL_LIBS" -dnl -dnl Now check if the installed MYSQL is sufficiently new. (Also sanity -dnl checks the results of mysql_config to some extent -dnl - rm -f conf.mysqltest - AC_TRY_RUN([ -#include -#include -#include -#include - -char* -my_strdup (char *str) -{ - char *new_str; - - if (str) - { - new_str = (char *)malloc ((strlen (str) + 1) * sizeof(char)); - strcpy (new_str, str); - } - else - new_str = NULL; - - return new_str; -} - -int main (int argc, char *argv[]) -{ -int major, minor, micro; - char *tmp_version; - - /* This hangs on some systems (?) - system ("touch conf.mysqltest"); - */ - { FILE *fp = fopen("conf.mysqltest", "a"); if ( fp ) fclose(fp); } - - /* HP/UX 9 (%@#!) writes to sscanf strings */ - tmp_version = my_strdup("$min_mysql_version"); - if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, µ) != 3) { - printf("%s, bad version string\n", "$min_mysql_version"); - exit(1); - } - - if (($mysql_major_version > major) || - (($mysql_major_version == major) && ($mysql_minor_version > minor)) || - (($mysql_major_version == major) && ($mysql_minor_version == minor) && ($mysql_micro_version >= micro))) - { - return 0; - } - else - { - printf("\n*** 'mysql_config --version' returned %d.%d.%d, but the minimum version\n", $mysql_major_version, $mysql_minor_version, $mysql_micro_version); - printf("*** of MYSQL required is %d.%d.%d. If mysql_config is correct, then it is\n", major, minor, micro); - printf("*** best to upgrade to the required version.\n"); - printf("*** If mysql_config was wrong, set the environment variable MYSQL_CONFIG\n"); - printf("*** to point to the correct copy of mysql_config, and remove the file\n"); - printf("*** config.cache before re-running configure\n"); - return 1; - } -} - -],, no_mysql=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"]) - CFLAGS="$ac_save_CFLAGS" - LIBS="$ac_save_LIBS" - fi - fi - if test "x$no_mysql" = x ; then - AC_MSG_RESULT(yes) - ifelse([$2], , :, [$2]) - else - AC_MSG_RESULT(no) - if test "$MYSQL_CONFIG" = "no" ; then - echo "*** The mysql_config script installed by MYSQL could not be found" - echo "*** If MYSQL was installed in PREFIX, make sure PREFIX/bin is in" - echo "*** your path, or set the MYSQL_CONFIG environment variable to the" - echo "*** full path to mysql_config." - else - if test -f conf.mysqltest ; then - : - else - echo "*** Could not run MYSQL test program, checking why..." - CFLAGS="$CFLAGS $MYSQL_CFLAGS" - LIBS="$LIBS $MYSQL_LIBS" - AC_TRY_LINK([ -#include -#include - -int main(int argc, char *argv[]) -{ return 0; } -#undef main -#define main K_and_R_C_main -], [ return 0; ], - [ echo "*** The test program compiled, but did not run. This usually means" - echo "*** that the run-time linker is not finding MYSQL or finding the wrong" - echo "*** version of MYSQL. If it is not finding MYSQL, you'll need to set your" - echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" - echo "*** to the installed location Also, make sure you have run ldconfig if that" - echo "*** is required on your system" - echo "***" - echo "*** If you have an old version installed, it is best to remove it, although" - echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"], - [ echo "*** The test program failed to compile or link. See the file config.log for the" - echo "*** exact error that occured. This usually means MYSQL was incorrectly installed" - echo "*** or that you have moved MYSQL since it was installed. In the latter case, you" - echo "*** may want to edit the mysql_config script: $MYSQL_CONFIG" ]) - CFLAGS="$ac_save_CFLAGS" - LIBS="$ac_save_LIBS" - fi - fi - MYSQL_CFLAGS="" - MYSQL_LIBS="" - ifelse([$3], , :, [$3]) + AC_MSG_RESULT(yes) + ifelse([$1], , :, [$1]) fi AC_SUBST(MYSQL_CFLAGS) AC_SUBST(MYSQL_LIBS) - rm -f conf.mysqltest ]) dnl Removes -I/usr/include/? from given variable @@ -733,6 +612,22 @@ AC_DEFUN(jm_ICONV, fi ]) +AC_DEFUN(rjs_CHARSET,[ + dnl Find out if we can convert from $1 to UCS2-LE + AC_MSG_CHECKING([can we convert from $1 to UCS2-LE?]) + AC_TRY_RUN([ +#include <$jm_cv_include> +main(){ + iconv_t cd = iconv_open("$1", "UCS-2LE"); + if (cd == 0 || cd == (iconv_t)-1) { + return -1; + } + return 0; +} + ],ICONV_CHARSET=$1,ICONV_CHARSET=no,ICONV_CHARSET=cross) + AC_MSG_RESULT($ICONV_CHARSET) +]) + dnl CFLAGS_ADD_DIR(CFLAGS, $INCDIR) dnl This function doesn't add -I/usr/include into CFLAGS AC_DEFUN(CFLAGS_ADD_DIR,[ diff --git a/source3/auth/auth.c b/source3/auth/auth.c index 8316c4b617..553d9a686e 100644 --- a/source3/auth/auth.c +++ b/source3/auth/auth.c @@ -131,7 +131,7 @@ static const uint8 *get_ntlm_challenge(struct auth_context *auth_context) DEBUG(5, ("auth_context challenge created by %s\n", challenge_set_by)); DEBUG(5, ("challenge is: \n")); - dump_data(5, auth_context->challenge.data, auth_context->challenge.length); + dump_data(5, (const char *)auth_context->challenge.data, auth_context->challenge.length); SMB_ASSERT(auth_context->challenge.length == 8); @@ -228,7 +228,7 @@ static NTSTATUS check_ntlm_password(const struct auth_context *auth_context, auth_context->challenge_set_by)); DEBUG(10, ("challenge is: \n")); - dump_data(5, auth_context->challenge.data, auth_context->challenge.length); + dump_data(5, (const char *)auth_context->challenge.data, auth_context->challenge.length); #ifdef DEBUG_PASSWORD DEBUG(100, ("user_info has passwords of length %d and %d\n", @@ -373,10 +373,10 @@ BOOL load_auth_module(struct auth_context *auth_context, if (p) { *p = 0; module_params = p+1; - trim_string(module_params, " ", " "); + trim_char(module_params, ' ', ' '); } - trim_string(module_name, " ", " "); + trim_char(module_name, ' ', ' '); entry = auth_find_backend_entry(module_name); diff --git a/source3/auth/auth_domain.c b/source3/auth/auth_domain.c index aacea261fe..43e7597cd9 100644 --- a/source3/auth/auth_domain.c +++ b/source3/auth/auth_domain.c @@ -26,9 +26,6 @@ extern BOOL global_machine_password_needs_changing; -extern userdom_struct current_user_info; - - /** * Connect to a remote server for domain security authenticaion. * diff --git a/source3/auth/auth_rhosts.c b/source3/auth/auth_rhosts.c index fab2d551f2..b295df9328 100644 --- a/source3/auth/auth_rhosts.c +++ b/source3/auth/auth_rhosts.c @@ -40,7 +40,7 @@ static BOOL check_user_equiv(const char *user, const char *remote, const char *e if (! lines) return False; for (i=0; lines[i]; i++) { char *buf = lines[i]; - trim_string(buf," "," "); + trim_char(buf,' ',' '); if (buf[0] != '#' && buf[0] != '\n') { diff --git a/source3/auth/auth_sam.c b/source3/auth/auth_sam.c index fb66d53cd4..ce97bd7df2 100644 --- a/source3/auth/auth_sam.c +++ b/source3/auth/auth_sam.c @@ -27,8 +27,9 @@ #define DBGC_CLASS DBGC_AUTH /**************************************************************************** -core of smb password checking routine. + Core of smb password checking routine. ****************************************************************************/ + static BOOL smb_pwd_check_ntlmv1(const DATA_BLOB *nt_response, const uchar *part_passwd, const DATA_BLOB *sec_blob, @@ -54,8 +55,7 @@ static BOOL smb_pwd_check_ntlmv1(const DATA_BLOB *nt_response, } SMBOWFencrypt(part_passwd, sec_blob->data, p24); - if (user_sess_key != NULL) - { + if (user_sess_key != NULL) { SMBsesskeygen_ntv1(part_passwd, NULL, user_sess_key); } @@ -74,12 +74,11 @@ static BOOL smb_pwd_check_ntlmv1(const DATA_BLOB *nt_response, return (memcmp(p24, nt_response->data, 24) == 0); } - /**************************************************************************** -core of smb password checking routine. (NTLMv2, LMv2) - -Note: The same code works with both NTLMv2 and LMv2. + Core of smb password checking routine. (NTLMv2, LMv2) + Note: The same code works with both NTLMv2 and LMv2. ****************************************************************************/ + static BOOL smb_pwd_check_ntlmv2(const DATA_BLOB *ntv2_response, const uchar *part_passwd, const DATA_BLOB *sec_blob, @@ -92,8 +91,7 @@ static BOOL smb_pwd_check_ntlmv2(const DATA_BLOB *ntv2_response, uchar client_response[16]; DATA_BLOB client_key_data; - if (part_passwd == NULL) - { + if (part_passwd == NULL) { DEBUG(10,("No password set - DISALLOWING access\n")); /* No password set - always False */ return False; @@ -121,8 +119,7 @@ static BOOL smb_pwd_check_ntlmv2(const DATA_BLOB *ntv2_response, } SMBOWFencrypt_ntv2(kr, sec_blob, &client_key_data, value_from_encryption); - if (user_sess_key != NULL) - { + if (user_sess_key != NULL) { SMBsesskeygen_ntv2(kr, value_from_encryption, user_sess_key); } @@ -142,11 +139,11 @@ static BOOL smb_pwd_check_ntlmv2(const DATA_BLOB *ntv2_response, return (memcmp(value_from_encryption, client_response, 16) == 0); } - /**************************************************************************** Do a specific test for an smb password being correct, given a smb_password and the lanman and NT responses. ****************************************************************************/ + static NTSTATUS sam_password_ok(const struct auth_context *auth_context, TALLOC_CTX *mem_ctx, SAM_ACCOUNT *sampass, @@ -158,15 +155,11 @@ static NTSTATUS sam_password_ok(const struct auth_context *auth_context, uint32 auth_flags; acct_ctrl = pdb_get_acct_ctrl(sampass); - if (acct_ctrl & ACB_PWNOTREQ) - { - if (lp_null_passwords()) - { + if (acct_ctrl & ACB_PWNOTREQ) { + if (lp_null_passwords()) { DEBUG(3,("Account for user '%s' has no password and null passwords are allowed.\n", pdb_get_username(sampass))); return(NT_STATUS_OK); - } - else - { + } else { DEBUG(3,("Account for user '%s' has no password and null passwords are NOT allowed.\n", pdb_get_username(sampass))); return(NT_STATUS_LOGON_FAILURE); } @@ -191,8 +184,7 @@ static NTSTATUS sam_password_ok(const struct auth_context *auth_context, nt_pw, &auth_context->challenge, user_info->smb_name.str, user_info->client_domain.str, - user_sess_key)) - { + user_sess_key)) { return NT_STATUS_OK; } @@ -201,9 +193,7 @@ static NTSTATUS sam_password_ok(const struct auth_context *auth_context, nt_pw, &auth_context->challenge, user_info->smb_name.str, "", - user_sess_key)) - - { + user_sess_key)) { return NT_STATUS_OK; } else { DEBUG(3,("sam_password_ok: NTLMv2 password check failed\n")); @@ -218,8 +208,7 @@ static NTSTATUS sam_password_ok(const struct auth_context *auth_context, DEBUG(4,("sam_password_ok: Checking NT MD4 password\n")); if (smb_pwd_check_ntlmv1(&user_info->nt_resp, nt_pw, &auth_context->challenge, - user_sess_key)) - { + user_sess_key)) { return NT_STATUS_OK; } else { DEBUG(3,("sam_password_ok: NT MD4 password check failed for user %s\n",pdb_get_username(sampass))); @@ -247,8 +236,7 @@ static NTSTATUS sam_password_ok(const struct auth_context *auth_context, DEBUG(4,("sam_password_ok: Checking LM password\n")); if (smb_pwd_check_ntlmv1(&user_info->lm_resp, lm_pw, &auth_context->challenge, - user_sess_key)) - { + user_sess_key)) { return NT_STATUS_OK; } } @@ -268,8 +256,7 @@ static NTSTATUS sam_password_ok(const struct auth_context *auth_context, nt_pw, &auth_context->challenge, user_info->smb_name.str, user_info->client_domain.str, - user_sess_key)) - { + user_sess_key)) { return NT_STATUS_OK; } @@ -278,8 +265,7 @@ static NTSTATUS sam_password_ok(const struct auth_context *auth_context, nt_pw, &auth_context->challenge, user_info->smb_name.str, "", - user_sess_key)) - { + user_sess_key)) { return NT_STATUS_OK; } @@ -287,12 +273,10 @@ static NTSTATUS sam_password_ok(const struct auth_context *auth_context, - I think this is related to Win9X pass-though authentication */ DEBUG(4,("sam_password_ok: Checking NT MD4 password in LM field\n")); - if (lp_ntlm_auth()) - { + if (lp_ntlm_auth()) { if (smb_pwd_check_ntlmv1(&user_info->lm_resp, nt_pw, &auth_context->challenge, - user_sess_key)) - { + user_sess_key)) { return NT_STATUS_OK; } DEBUG(3,("sam_password_ok: LM password, NT MD4 password in LM field and LMv2 failed for user %s\n",pdb_get_username(sampass))); @@ -313,6 +297,7 @@ static NTSTATUS sam_password_ok(const struct auth_context *auth_context, Do a specific test for a SAM_ACCOUNT being vaild for this connection (ie not disabled, expired and the like). ****************************************************************************/ + static NTSTATUS sam_account_ok(TALLOC_CTX *mem_ctx, SAM_ACCOUNT *sampass, const auth_usersupplied_info *user_info) @@ -325,16 +310,22 @@ static NTSTATUS sam_account_ok(TALLOC_CTX *mem_ctx, /* Quit if the account was disabled. */ if (acct_ctrl & ACB_DISABLED) { - DEBUG(1,("Account for user '%s' was disabled.\n", pdb_get_username(sampass))); + DEBUG(1,("sam_account_ok: Account for user '%s' was disabled.\n", pdb_get_username(sampass))); return NT_STATUS_ACCOUNT_DISABLED; } + /* Quit if the account was locked out. */ + if (acct_ctrl & ACB_AUTOLOCK) { + DEBUG(1,("sam_account_ok: Account for user %s was locked out.\n", pdb_get_username(sampass))); + return NT_STATUS_ACCOUNT_LOCKED_OUT; + } + /* Test account expire time */ kickoff_time = pdb_get_kickoff_time(sampass); if (kickoff_time != 0 && time(NULL) > kickoff_time) { - DEBUG(1,("Account for user '%s' has expired.\n", pdb_get_username(sampass))); - DEBUG(3,("Account expired at '%ld' unix time.\n", (long)kickoff_time)); + DEBUG(1,("sam_account_ok: Account for user '%s' has expired.\n", pdb_get_username(sampass))); + DEBUG(3,("sam_account_ok: Account expired at '%ld' unix time.\n", (long)kickoff_time)); return NT_STATUS_ACCOUNT_EXPIRED; } @@ -344,14 +335,14 @@ static NTSTATUS sam_account_ok(TALLOC_CTX *mem_ctx, /* check for immediate expiry "must change at next logon" */ if (must_change_time == 0 && last_set_time != 0) { - DEBUG(1,("Account for user '%s' password must change!.\n", pdb_get_username(sampass))); + DEBUG(1,("sam_account_ok: Account for user '%s' password must change!.\n", pdb_get_username(sampass))); return NT_STATUS_PASSWORD_MUST_CHANGE; } /* check for expired password */ if (must_change_time < time(NULL) && must_change_time != 0) { - DEBUG(1,("Account for user '%s' password expired!.\n", pdb_get_username(sampass))); - DEBUG(1,("Password expired at '%s' (%ld) unix time.\n", http_timestring(must_change_time), (long)must_change_time)); + DEBUG(1,("sam_account_ok: Account for user '%s' password expired!.\n", pdb_get_username(sampass))); + DEBUG(1,("sam_account_ok: Password expired at '%s' (%ld) unix time.\n", http_timestring(must_change_time), (long)must_change_time)); return NT_STATUS_PASSWORD_EXPIRED; } } @@ -359,8 +350,8 @@ static NTSTATUS sam_account_ok(TALLOC_CTX *mem_ctx, /* Test workstation. Workstation list is comma separated. */ workstation_list = talloc_strdup(mem_ctx, pdb_get_workstations(sampass)); - - if (!workstation_list) return NT_STATUS_NO_MEMORY; + if (!workstation_list) + return NT_STATUS_NO_MEMORY; if (*workstation_list) { BOOL invalid_ws = True; @@ -369,7 +360,7 @@ static NTSTATUS sam_account_ok(TALLOC_CTX *mem_ctx, fstring tok; while (next_token(&s, tok, ",", sizeof(tok))) { - DEBUG(10,("checking for workstation match %s and %s (len=%d)\n", + DEBUG(10,("sam_account_ok: checking for workstation match %s and %s (len=%d)\n", tok, user_info->wksta_name.str, user_info->wksta_name.len)); if(strequal(tok, user_info->wksta_name.str)) { invalid_ws = False; @@ -399,7 +390,6 @@ static NTSTATUS sam_account_ok(TALLOC_CTX *mem_ctx, return NT_STATUS_OK; } - /**************************************************************************** check if a username/password is OK assuming the password is a 24 byte SMB hash supplied in the user_info structure @@ -434,9 +424,8 @@ static NTSTATUS check_sam_security(const struct auth_context *auth_context, ret = pdb_getsampwnam(sampass, user_info->internal_username.str); unbecome_root(); - if (ret == False) - { - DEBUG(3,("Couldn't find user '%s' in passdb file.\n", user_info->internal_username.str)); + if (ret == False) { + DEBUG(3,("check_sam_security: Couldn't find user '%s' in passdb file.\n", user_info->internal_username.str)); pdb_free_sam(&sampass); return NT_STATUS_NO_SUCH_USER; } diff --git a/source3/auth/auth_util.c b/source3/auth/auth_util.c index 5403ee8c39..952aa8ba59 100644 --- a/source3/auth/auth_util.c +++ b/source3/auth/auth_util.c @@ -216,8 +216,8 @@ NTSTATUS make_user_info_map(auth_usersupplied_info **user_info, client_domain, smb_name, wksta_name)); /* don't allow "" as a domain, fixes a Win9X bug - where it doens't supply a domain for logon script - 'net use' commands.*/ + where it doens't supply a domain for logon script + 'net use' commands. */ if ( *client_domain ) domain = client_domain; @@ -227,7 +227,7 @@ NTSTATUS make_user_info_map(auth_usersupplied_info **user_info, /* do what win2k does. Always map unknown domains to our own and let the "passdb backend" handle unknown users. */ - if ( !is_trusted_domain(domain) ) + if ( !is_trusted_domain(domain) && !strequal(domain, get_global_sam_name()) ) domain = get_default_sam_name(); /* we know that it is a trusted domain (and we are allowing them) or it is our domain */ @@ -393,7 +393,7 @@ BOOL make_user_info_for_reply(auth_usersupplied_info **user_info, dump_data(100, plaintext_password.data, plaintext_password.length); #endif - SMBencrypt( (const uchar *)plaintext_password.data, (const uchar*)chal, local_lm_response); + SMBencrypt( (const char *)plaintext_password.data, (const uchar*)chal, local_lm_response); local_lm_blob = data_blob(local_lm_response, 24); /* We can't do an NT hash here, as the password needs to be @@ -646,43 +646,66 @@ NT_USER_TOKEN *create_nt_token(uid_t uid, gid_t gid, int ngroups, gid_t *groups, * of groups. ******************************************************************************/ -static NTSTATUS get_user_groups_from_local_sam(const char *username, uid_t uid, gid_t gid, - int *n_groups, DOM_SID **groups, gid_t **unix_groups) +static NTSTATUS get_user_groups(const char *username, uid_t uid, gid_t gid, + int *n_groups, DOM_SID **groups, gid_t **unix_groups) { - int n_unix_groups; - int i; + int n_unix_groups; + int i; *n_groups = 0; *groups = NULL; + + /* Try winbind first */ - n_unix_groups = groups_max(); - if ((*unix_groups = malloc( sizeof(gid_t) * n_unix_groups ) ) == NULL) { - DEBUG(0, ("get_user_groups_from_local_sam: Out of memory allocating unix group list\n")); - return NT_STATUS_NO_MEMORY; + if ( strchr(username, *lp_winbind_separator()) ) { + n_unix_groups = winbind_getgroups( username, unix_groups ); + + DEBUG(10,("get_user_groups: winbind_getgroups(%s): result = %s\n", username, + n_unix_groups == -1 ? "FAIL" : "SUCCESS")); + + if ( n_unix_groups == -1 ) + return NT_STATUS_NO_SUCH_USER; /* what should this return value be? */ } - - if (sys_getgrouplist(username, gid, *unix_groups, &n_unix_groups) == -1) { - gid_t *groups_tmp; - groups_tmp = Realloc(*unix_groups, sizeof(gid_t) * n_unix_groups); - if (!groups_tmp) { - SAFE_FREE(*unix_groups); + else { + /* fallback to getgrouplist() */ + + n_unix_groups = groups_max(); + + if ((*unix_groups = malloc( sizeof(gid_t) * n_unix_groups ) ) == NULL) { + DEBUG(0, ("get_user_groups: Out of memory allocating unix group list\n")); return NT_STATUS_NO_MEMORY; } - *unix_groups = groups_tmp; - + if (sys_getgrouplist(username, 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); - return NT_STATUS_NO_SUCH_USER; /* what should this return value be? */ + + gid_t *groups_tmp; + + groups_tmp = Realloc(*unix_groups, sizeof(gid_t) * n_unix_groups); + + if (!groups_tmp) { + SAFE_FREE(*unix_groups); + return NT_STATUS_NO_MEMORY; + } + *unix_groups = groups_tmp; + + if (sys_getgrouplist(username, gid, *unix_groups, &n_unix_groups) == -1) { + DEBUG(0, ("get_user_groups: failed to get the unix group list\n")); + SAFE_FREE(*unix_groups); + return NT_STATUS_NO_SUCH_USER; /* what should this return value be? */ + } } } debug_unix_user_token(DBGC_CLASS, 5, uid, gid, n_unix_groups, *unix_groups); + /* now setup the space for storing the SIDS */ + 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")); + DEBUG(0, ("get_user_group: malloc() failed for DOM_SID list!\n")); SAFE_FREE(*unix_groups); return NT_STATUS_NO_MEMORY; } @@ -692,7 +715,8 @@ static NTSTATUS get_user_groups_from_local_sam(const char *username, uid_t uid, for (i = 0; i < *n_groups; i++) { if (!NT_STATUS_IS_OK(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])); + DEBUG(1, ("get_user_groups: 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; @@ -743,10 +767,9 @@ static NTSTATUS add_user_groups(auth_serversupplied_info **server_info, BOOL is_guest; uint32 rid; - nt_status = get_user_groups_from_local_sam(pdb_get_username(sampass), - uid, gid, - &n_groupSIDs, &groupSIDs, - &unix_groups); + nt_status = get_user_groups(pdb_get_username(sampass), uid, gid, + &n_groupSIDs, &groupSIDs, &unix_groups); + if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(4,("get_user_groups_from_local_sam failed\n")); free_server_info(server_info); @@ -1068,11 +1091,11 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx, /* Store the user group information in the server_info returned to the caller. */ - nt_status = get_user_groups_from_local_sam((*server_info)->unix_name, + nt_status = get_user_groups((*server_info)->unix_name, uid, gid, &n_lgroupSIDs, &lgroupSIDs, &unix_groups); - if ( !NT_STATUS_IS_OK(nt_status) ) - { - DEBUG(4,("get_user_groups_from_local_sam failed\n")); + + if ( !NT_STATUS_IS_OK(nt_status) ) { + DEBUG(4,("get_user_groups failed\n")); return nt_status; } @@ -1080,9 +1103,9 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx, (*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)); + + all_group_SIDs = malloc(sizeof(DOM_SID) * (info3->num_groups2 +info3->num_other_sids)); + if (!all_group_SIDs) { DEBUG(0, ("malloc() failed for DOM_SID list!\n")); SAFE_FREE(lgroupSIDs); @@ -1090,20 +1113,30 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx, return NT_STATUS_NO_MEMORY; } +#if 0 /* JERRY -- no such thing as local groups in current code */ /* Copy the 'local' sids */ memcpy(all_group_SIDs, lgroupSIDs, sizeof(DOM_SID) * n_lgroupSIDs); SAFE_FREE(lgroupSIDs); +#endif /* 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)) { + + sid_copy(&all_group_SIDs[i], &(info3->dom_sid.sid)); + + if (!sid_append_rid(&all_group_SIDs[i], info3->gids[i].g_rid)) { + nt_status = NT_STATUS_INVALID_PARAMETER; + DEBUG(3,("could not append additional group rid 0x%x\n", info3->gids[i].g_rid)); + SAFE_FREE(lgroupSIDs); free_server_info(server_info); + return nt_status; + } } @@ -1113,19 +1146,20 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx, 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], + for (i = 0; i < info3->num_other_sids; i++) { + sid_copy(&all_group_SIDs[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))) { + + nt_status = create_nt_user_token(&user_sid, &group_sid, + info3->num_groups2 + info3->num_other_sids, + all_group_SIDs, False, &token); + + if ( !NT_STATUS_IS_OK(nt_status) ) { DEBUG(4,("create_nt_user_token failed\n")); SAFE_FREE(all_group_SIDs); free_server_info(server_info); diff --git a/source3/auth/auth_winbind.c b/source3/auth/auth_winbind.c index aa8f345a5b..cae7aadd0c 100644 --- a/source3/auth/auth_winbind.c +++ b/source3/auth/auth_winbind.c @@ -36,7 +36,7 @@ static NTSTATUS get_info3_from_ndr(TALLOC_CTX *mem_ctx, struct winbindd_response if (!prs_init(&ps, len, mem_ctx, UNMARSHALL)) { return NT_STATUS_NO_MEMORY; } - prs_copy_data_in(&ps, info3_ndr, len); + prs_copy_data_in(&ps, (char *)info3_ndr, len); prs_set_offset(&ps,0); if (!net_io_user_info3("", info3, &ps, 1, 3)) { DEBUG(2, ("get_info3_from_ndr: could not parse info3 struct!\n")); diff --git a/source3/auth/pampass.c b/source3/auth/pampass.c index d666e439b0..3239686a20 100644 --- a/source3/auth/pampass.c +++ b/source3/auth/pampass.c @@ -230,7 +230,7 @@ static struct chat_struct *make_pw_chat(char *p) special_char_sub(prompt); fstrcpy(t->prompt, prompt); strlower_m(t->prompt); - trim_string(t->prompt, " ", " "); + trim_char(t->prompt, ' ', ' '); if (!next_token(&p, reply, NULL, sizeof(fstring))) break; @@ -241,7 +241,7 @@ static struct chat_struct *make_pw_chat(char *p) special_char_sub(reply); fstrcpy(t->reply, reply); strlower_m(t->reply); - trim_string(t->reply, " ", " "); + trim_char(t->reply, ' ', ' '); } return list; @@ -304,7 +304,7 @@ static int smb_pam_passchange_conv(int num_msg, case PAM_PROMPT_ECHO_ON: DEBUG(10,("smb_pam_passchange_conv: PAM_PROMPT_ECHO_ON: PAM said: %s\n", msg[replies]->msg)); fstrcpy(current_prompt, msg[replies]->msg); - trim_string(current_prompt, " ", " "); + trim_char(current_prompt, ' ', ' '); for (t=pw_chat; t; t=t->next) { DEBUG(10,("smb_pam_passchange_conv: PAM_PROMPT_ECHO_ON: trying to match |%s| to |%s|\n", @@ -335,7 +335,7 @@ static int smb_pam_passchange_conv(int num_msg, case PAM_PROMPT_ECHO_OFF: DEBUG(10,("smb_pam_passchange_conv: PAM_PROMPT_ECHO_OFF: PAM said: %s\n", msg[replies]->msg)); fstrcpy(current_prompt, msg[replies]->msg); - trim_string(current_prompt, " ", " "); + trim_char(current_prompt, ' ', ' '); for (t=pw_chat; t; t=t->next) { DEBUG(10,("smb_pam_passchange_conv: PAM_PROMPT_ECHO_OFF: trying to match |%s| to |%s|\n", diff --git a/source3/autogen.sh b/source3/autogen.sh index 2d91173f4a..6042b82cdc 100755 --- a/source3/autogen.sh +++ b/source3/autogen.sh @@ -55,6 +55,11 @@ $AUTOHEADER || exit 1 echo "$0: running $AUTOCONF" $AUTOCONF || exit 1 +echo "$0: running script/mkversion.sh" +./script/mkversion.sh || exit 1 + +rm -rf autom4te.cache autom4te-2.53.cache + echo "Now run ./configure and then make." exit 0 diff --git a/source3/bin/.cvsignore b/source3/bin/.cvsignore index 770100fd31..31af1fe22d 100644 --- a/source3/bin/.cvsignore +++ b/source3/bin/.cvsignore @@ -37,6 +37,7 @@ smbstatus smbtorture smbtree smbumount +smbiconv swat t_push_ucs2 t_snprintf @@ -47,6 +48,7 @@ tdbbackup testparm testprns vfstest +log2pcap wbinfo winbindd wrepld diff --git a/source3/client/client.c b/source3/client/client.c index ec29f44e6e..ecece8942e 100644 --- a/source3/client/client.c +++ b/source3/client/client.c @@ -102,9 +102,10 @@ static double dir_total; static struct cli_state *do_connect(const char *server, const char *share); /**************************************************************************** -write to a local file with CR/LF->LF translation if appropriate. return the -number taken from the buffer. This may not equal the number written. + Write to a local file with CR/LF->LF translation if appropriate. Return the + number taken from the buffer. This may not equal the number written. ****************************************************************************/ + static int writefile(int f, char *b, int n) { int i; @@ -129,9 +130,10 @@ static int writefile(int f, char *b, int n) } /**************************************************************************** - read from a file with LF->CR/LF translation if appropriate. return the - number read. read approx n bytes. + Read from a file with LF->CR/LF translation if appropriate. Return the + number read. read approx n bytes. ****************************************************************************/ + static int readfile(char *b, int n, XFILE *f) { int i; @@ -156,10 +158,10 @@ static int readfile(char *b, int n, XFILE *f) return(i); } - /**************************************************************************** -send a message + Send a message. ****************************************************************************/ + static void send_message(void) { int total_len = 0; @@ -206,11 +208,10 @@ static void send_message(void) } } - - /**************************************************************************** -check the space on a device + Check the space on a device. ****************************************************************************/ + static int do_dskattr(void) { int total, bsize, avail; @@ -227,8 +228,9 @@ static int do_dskattr(void) } /**************************************************************************** -show cd/pwd + Show cd/pwd. ****************************************************************************/ + static int cmd_pwd(void) { d_printf("Current directory is %s",service); @@ -236,10 +238,10 @@ static int cmd_pwd(void) return 0; } - /**************************************************************************** -change directory - inner section + Change directory - inner section. ****************************************************************************/ + static int do_cd(char *newdir) { char *p = newdir; @@ -276,8 +278,9 @@ static int do_cd(char *newdir) } /**************************************************************************** -change directory + Change directory. ****************************************************************************/ + static int cmd_cd(void) { fstring buf; @@ -291,13 +294,14 @@ static int cmd_cd(void) return rc; } - /******************************************************************* - decide if a file should be operated on - ********************************************************************/ + Decide if a file should be operated on. +********************************************************************/ + static BOOL do_this_one(file_info *finfo) { - if (finfo->mode & aDIR) return(True); + if (finfo->mode & aDIR) + return(True); if (*fileselection && !mask_match(finfo->name,fileselection,False)) { @@ -319,8 +323,9 @@ static BOOL do_this_one(file_info *finfo) } /**************************************************************************** - display info about a file - ****************************************************************************/ + Display info about a file. +****************************************************************************/ + static void display_finfo(file_info *finfo) { if (do_this_one(finfo)) { @@ -334,10 +339,10 @@ static void display_finfo(file_info *finfo) } } - /**************************************************************************** - accumulate size of a file - ****************************************************************************/ + Accumulate size of a file. +****************************************************************************/ + static void do_du(file_info *finfo) { if (do_this_one(finfo)) { @@ -354,8 +359,8 @@ static long do_list_queue_end = 0; static void (*do_list_fn)(file_info *); /**************************************************************************** -functions for do_list_queue - ****************************************************************************/ + Functions for do_list_queue. +****************************************************************************/ /* * The do_list_queue is a NUL-separated list of strings stored in a @@ -368,6 +373,7 @@ functions for do_list_queue * Functions check to ensure that do_list_queue is non-NULL before * accessing it. */ + static void reset_do_list_queue(void) { SAFE_FREE(do_list_queue); @@ -396,14 +402,11 @@ static void adjust_do_list_queue(void) * If the starting point of the queue is more than half way through, * move everything toward the beginning. */ - if (do_list_queue && (do_list_queue_start == do_list_queue_end)) - { + if (do_list_queue && (do_list_queue_start == do_list_queue_end)) { DEBUG(4,("do_list_queue is empty\n")); do_list_queue_start = do_list_queue_end = 0; *do_list_queue = '\0'; - } - else if (do_list_queue_start > (do_list_queue_size / 2)) - { + } else if (do_list_queue_start > (do_list_queue_size / 2)) { DEBUG(4,("sliding do_list_queue backward\n")); memmove(do_list_queue, do_list_queue + do_list_queue_start, @@ -411,15 +414,13 @@ static void adjust_do_list_queue(void) do_list_queue_end -= do_list_queue_start; do_list_queue_start = 0; } - } static void add_to_do_list_queue(const char* entry) { char *dlq; long new_end = do_list_queue_end + ((long)strlen(entry)) + 1; - while (new_end > do_list_queue_size) - { + while (new_end > do_list_queue_size) { do_list_queue_size *= 2; DEBUG(4,("enlarging do_list_queue to %d\n", (int)do_list_queue_size)); @@ -428,16 +429,13 @@ static void add_to_do_list_queue(const char* entry) d_printf("failure enlarging do_list_queue to %d bytes\n", (int)do_list_queue_size); reset_do_list_queue(); - } - else - { + } else { do_list_queue = dlq; memset(do_list_queue + do_list_queue_size / 2, 0, do_list_queue_size / 2); } } - if (do_list_queue) - { + if (do_list_queue) { safe_strcpy_base(do_list_queue + do_list_queue_end, entry, do_list_queue, do_list_queue_size); do_list_queue_end = new_end; @@ -453,8 +451,7 @@ static char *do_list_queue_head(void) static void remove_do_list_queue_head(void) { - if (do_list_queue_end > do_list_queue_start) - { + if (do_list_queue_end > do_list_queue_start) { do_list_queue_start += strlen(do_list_queue_head()) + 1; adjust_do_list_queue(); DEBUG(4,("removed head of do_list_queue (start=%d, end=%d)\n", @@ -468,8 +465,9 @@ static int do_list_queue_empty(void) } /**************************************************************************** -a helper for do_list - ****************************************************************************/ + A helper for do_list. +****************************************************************************/ + static void do_list_helper(file_info *f, const char *mask, void *state) { if (f->mode & aDIR) { @@ -489,7 +487,8 @@ static void do_list_helper(file_info *f, const char *mask, void *state) pstrcpy(mask2, mask); p = strrchr_m(mask2,'\\'); - if (!p) return; + if (!p) + return; p[1] = 0; pstrcat(mask2, f->name); pstrcat(mask2,"\\*"); @@ -503,16 +502,15 @@ static void do_list_helper(file_info *f, const char *mask, void *state) } } - /**************************************************************************** -a wrapper around cli_list that adds recursion - ****************************************************************************/ + A wrapper around cli_list that adds recursion. +****************************************************************************/ + void do_list(const char *mask,uint16 attribute,void (*fn)(file_info *),BOOL rec, BOOL dirs) { static int in_do_list = 0; - if (in_do_list && rec) - { + if (in_do_list && rec) { fprintf(stderr, "INTERNAL ERROR: do_list called recursively when the recursive flag is true\n"); exit(1); } @@ -523,13 +521,11 @@ void do_list(const char *mask,uint16 attribute,void (*fn)(file_info *),BOOL rec, do_list_dirs = dirs; do_list_fn = fn; - if (rec) - { + if (rec) { init_do_list_queue(); add_to_do_list_queue(mask); - while (! do_list_queue_empty()) - { + while (! do_list_queue_empty()) { /* * Need to copy head so that it doesn't become * invalid inside the call to cli_list. This @@ -541,30 +537,24 @@ void do_list(const char *mask,uint16 attribute,void (*fn)(file_info *),BOOL rec, pstrcpy(head, do_list_queue_head()); cli_list(cli, head, attribute, do_list_helper, NULL); remove_do_list_queue_head(); - if ((! do_list_queue_empty()) && (fn == display_finfo)) - { + if ((! do_list_queue_empty()) && (fn == display_finfo)) { char* next_file = do_list_queue_head(); char* save_ch = 0; if ((strlen(next_file) >= 2) && (next_file[strlen(next_file) - 1] == '*') && - (next_file[strlen(next_file) - 2] == '\\')) - { + (next_file[strlen(next_file) - 2] == '\\')) { save_ch = next_file + strlen(next_file) - 2; *save_ch = '\0'; } d_printf("\n%s\n",next_file); - if (save_ch) - { + if (save_ch) { *save_ch = '\\'; } } } - } - else - { - if (cli_list(cli, mask, attribute, do_list_helper, NULL) == -1) - { + } else { + if (cli_list(cli, mask, attribute, do_list_helper, NULL) == -1) { d_printf("%s listing %s\n", cli_errstr(cli), mask); } } @@ -574,8 +564,9 @@ void do_list(const char *mask,uint16 attribute,void (*fn)(file_info *),BOOL rec, } /**************************************************************************** - get a directory listing - ****************************************************************************/ + Get a directory listing. +****************************************************************************/ + static int cmd_dir(void) { uint16 attribute = aDIR | aSYSTEM | aHIDDEN; @@ -595,8 +586,7 @@ static int cmd_dir(void) pstrcpy(mask,p); else pstrcat(mask,p); - } - else { + } else { pstrcat(mask,"*"); } @@ -609,10 +599,10 @@ static int cmd_dir(void) return rc; } - /**************************************************************************** - get a directory listing - ****************************************************************************/ + Get a directory listing. +****************************************************************************/ + static int cmd_du(void) { uint16 attribute = aDIR | aSYSTEM | aHIDDEN; @@ -645,10 +635,10 @@ static int cmd_du(void) return rc; } - /**************************************************************************** - get a file from rname to lname - ****************************************************************************/ + Get a file from rname to lname +****************************************************************************/ + static int do_get(char *rname, char *lname, BOOL reget) { int handle = 0, fnum; @@ -718,7 +708,8 @@ static int do_get(char *rname, char *lname, BOOL reget) while (1) { int n = cli_read(cli, fnum, data, nread + start, read_size); - if (n <= 0) break; + if (n <= 0) + break; if (writefile(handle,data, n) != n) { d_printf("Error writing local file\n"); @@ -770,10 +761,10 @@ static int do_get(char *rname, char *lname, BOOL reget) return rc; } - /**************************************************************************** - get a file - ****************************************************************************/ + Get a file. +****************************************************************************/ + static int cmd_get(void) { pstring lname; @@ -797,10 +788,10 @@ static int cmd_get(void) return do_get(rname, lname, False); } - /**************************************************************************** - do a mget operation on one file - ****************************************************************************/ + Do an mget operation on one file. +****************************************************************************/ + static void do_mget(file_info *finfo) { pstring rname; @@ -823,7 +814,8 @@ static void do_mget(file_info *finfo) slprintf(quest,sizeof(pstring)-1, "Get file %s? ",finfo->name); - if (prompt && !yesno(quest)) return; + if (prompt && !yesno(quest)) + return; if (!(finfo->mode & aDIR)) { pstrcpy(rname,cur_dir); @@ -863,10 +855,10 @@ static void do_mget(file_info *finfo) pstrcpy(cur_dir,saved_curdir); } - /**************************************************************************** -view the file using the pager + View the file using the pager. ****************************************************************************/ + static int cmd_more(void) { fstring rname,lname,pager_cmd; @@ -904,11 +896,10 @@ static int cmd_more(void) return rc; } - - /**************************************************************************** -do a mget command + Do a mget command. ****************************************************************************/ + static int cmd_mget(void) { uint16 attribute = aSYSTEM | aHIDDEN; @@ -946,10 +937,10 @@ static int cmd_mget(void) return 0; } - /**************************************************************************** -make a directory of name "name" + Make a directory of name "name". ****************************************************************************/ + static BOOL do_mkdir(char *name) { if (!cli_mkdir(cli, name)) { @@ -962,8 +953,9 @@ static BOOL do_mkdir(char *name) } /**************************************************************************** -show 8.3 name of a file + Show 8.3 name of a file. ****************************************************************************/ + static BOOL do_altname(char *name) { fstring altname; @@ -977,10 +969,10 @@ static BOOL do_altname(char *name) return(True); } - /**************************************************************************** Exit client. ****************************************************************************/ + static int cmd_quit(void) { cli_shutdown(cli); @@ -989,10 +981,10 @@ static int cmd_quit(void) return 0; } - /**************************************************************************** - make a directory - ****************************************************************************/ + Make a directory. +****************************************************************************/ + static int cmd_mkdir(void) { pstring mask; @@ -1014,7 +1006,7 @@ static int cmd_mkdir(void) *ddir2 = 0; pstrcpy(ddir,mask); - trim_string(ddir,".",NULL); + trim_char(ddir,'.','\0'); p = strtok(ddir,"/\\"); while (p) { pstrcat(ddir2,p); @@ -1031,10 +1023,10 @@ static int cmd_mkdir(void) return 0; } - /**************************************************************************** - show alt name - ****************************************************************************/ + Show alt name. +****************************************************************************/ + static int cmd_altname(void) { pstring name; @@ -1054,10 +1046,10 @@ static int cmd_altname(void) return 0; } - /**************************************************************************** - put a single file - ****************************************************************************/ + Put a single file. +****************************************************************************/ + static int do_put(char *rname, char *lname, BOOL reput) { int fnum; @@ -1111,7 +1103,6 @@ static int do_put(char *rname, char *lname, BOOL reput) d_printf("Error opening local file %s\n",lname); return 1; } - DEBUG(1,("putting file %s as %s ",lname, rname)); @@ -1183,11 +1174,10 @@ static int do_put(char *rname, char *lname, BOOL reput) return rc; } - - /**************************************************************************** - put a file - ****************************************************************************/ + Put a file. +****************************************************************************/ + static int cmd_put(void) { pstring lname; @@ -1226,7 +1216,7 @@ static int cmd_put(void) } /************************************* - File list structure + File list structure. *************************************/ static struct file_list { @@ -1236,15 +1226,14 @@ static struct file_list { } *file_list; /**************************************************************************** - Free a file_list structure + Free a file_list structure. ****************************************************************************/ static void free_file_list (struct file_list * list) { struct file_list *tmp; - while (list) - { + while (list) { tmp = list; DLIST_REMOVE(list, list); SAFE_FREE(tmp->file_path); @@ -1253,9 +1242,10 @@ static void free_file_list (struct file_list * list) } /**************************************************************************** - seek in a directory/file list until you get something that doesn't start with - the specified name - ****************************************************************************/ + Seek in a directory/file list until you get something that doesn't start with + the specified name. +****************************************************************************/ + static BOOL seek_list(struct file_list *list, char *name) { while (list) { @@ -1270,8 +1260,9 @@ static BOOL seek_list(struct file_list *list, char *name) } /**************************************************************************** - set the file selection mask - ****************************************************************************/ + Set the file selection mask. +****************************************************************************/ + static int cmd_select(void) { pstrcpy(fileselection,""); @@ -1284,6 +1275,7 @@ static int cmd_select(void) Recursive file matching function act as find match must be always set to True when calling this function ****************************************************************************/ + static int file_find(struct file_list **list, const char *directory, const char *expression, BOOL match) { @@ -1296,11 +1288,14 @@ static int file_find(struct file_list **list, const char *directory, const char *dname; dir = opendir(directory); - if (!dir) return -1; + if (!dir) + return -1; while ((dname = readdirname(dir))) { - if (!strcmp("..", dname)) continue; - if (!strcmp(".", dname)) continue; + if (!strcmp("..", dname)) + continue; + if (!strcmp(".", dname)) + continue; if (asprintf(&path, "%s/%s", directory, dname) <= 0) { continue; @@ -1344,8 +1339,9 @@ static int file_find(struct file_list **list, const char *directory, } /**************************************************************************** - mput some files - ****************************************************************************/ + mput some files. +****************************************************************************/ + static int cmd_mput(void) { fstring buf; @@ -1425,10 +1421,10 @@ static int cmd_mput(void) return 0; } - /**************************************************************************** - cancel a print job - ****************************************************************************/ + Cancel a print job. +****************************************************************************/ + static int do_cancel(int job) { if (cli_printjob_del(cli, job)) { @@ -1440,10 +1436,10 @@ static int do_cancel(int job) } } - /**************************************************************************** - cancel a print job - ****************************************************************************/ + Cancel a print job. +****************************************************************************/ + static int cmd_cancel(void) { fstring buf; @@ -1461,10 +1457,10 @@ static int cmd_cancel(void) return 0; } - /**************************************************************************** - print a file - ****************************************************************************/ + Print a file. +****************************************************************************/ + static int cmd_print(void) { pstring lname; @@ -1489,18 +1485,19 @@ static int cmd_print(void) return do_put(rname, lname, False); } - /**************************************************************************** - show a print queue entry + Show a print queue entry. ****************************************************************************/ + static void queue_fn(struct print_job_info *p) { d_printf("%-6d %-9d %s\n", (int)p->id, (int)p->size, p->name); } /**************************************************************************** - show a print queue + Show a print queue. ****************************************************************************/ + static int cmd_queue(void) { cli_print_queue(cli, queue_fn); @@ -1509,8 +1506,9 @@ static int cmd_queue(void) } /**************************************************************************** -delete some files + Delete some files. ****************************************************************************/ + static void do_del(file_info *finfo) { pstring mask; @@ -1527,8 +1525,9 @@ static void do_del(file_info *finfo) } /**************************************************************************** -delete some files + Delete some files. ****************************************************************************/ + static int cmd_del(void) { pstring mask; @@ -1553,6 +1552,7 @@ static int cmd_del(void) /**************************************************************************** ****************************************************************************/ + static int cmd_open(void) { pstring mask; @@ -1573,8 +1573,9 @@ static int cmd_open(void) /**************************************************************************** -remove a directory + Remove a directory. ****************************************************************************/ + static int cmd_rmdir(void) { pstring mask; @@ -1739,8 +1740,9 @@ static int cmd_chown(void) } /**************************************************************************** -rename some files + Rename some file. ****************************************************************************/ + static int cmd_rename(void) { pstring src,dest; @@ -1766,10 +1768,10 @@ static int cmd_rename(void) return 0; } - /**************************************************************************** -toggle the prompt flag + Toggle the prompt flag. ****************************************************************************/ + static int cmd_prompt(void) { prompt = !prompt; @@ -1778,10 +1780,10 @@ static int cmd_prompt(void) return 1; } - /**************************************************************************** -set the newer than time + Set the newer than time. ****************************************************************************/ + static int cmd_newer(void) { fstring buf; @@ -1806,8 +1808,9 @@ static int cmd_newer(void) } /**************************************************************************** -set the archive level + Set the archive level. ****************************************************************************/ + static int cmd_archive(void) { fstring buf; @@ -1821,8 +1824,9 @@ static int cmd_archive(void) } /**************************************************************************** -toggle the lowercaseflag + Toggle the lowercaseflag. ****************************************************************************/ + static int cmd_lowercase(void) { lowercase = !lowercase; @@ -1831,12 +1835,10 @@ static int cmd_lowercase(void) return 0; } - - - /**************************************************************************** -toggle the recurse flag + Toggle the recurse flag. ****************************************************************************/ + static int cmd_recurse(void) { recurse = !recurse; @@ -1846,8 +1848,9 @@ static int cmd_recurse(void) } /**************************************************************************** -toggle the translate flag + Toggle the translate flag. ****************************************************************************/ + static int cmd_translate(void) { translation = !translation; @@ -1857,10 +1860,10 @@ static int cmd_translate(void) return 0; } - /**************************************************************************** -do a printmode command + Do a printmode command. ****************************************************************************/ + static int cmd_printmode(void) { fstring buf; @@ -1877,8 +1880,7 @@ static int cmd_printmode(void) } } - switch(printmode) - { + switch(printmode) { case 0: fstrcpy(mode,"text"); break; @@ -1888,7 +1890,7 @@ static int cmd_printmode(void) default: slprintf(mode,sizeof(mode)-1,"%d",printmode); break; - } + } DEBUG(2,("the printmode is now %s\n",mode)); @@ -1896,8 +1898,9 @@ static int cmd_printmode(void) } /**************************************************************************** - do the lcd command + Do the lcd command. ****************************************************************************/ + static int cmd_lcd(void) { fstring buf; @@ -1911,8 +1914,9 @@ static int cmd_lcd(void) } /**************************************************************************** - get a file restarting at end of local file + Get a file restarting at end of local file. ****************************************************************************/ + static int cmd_reget(void) { pstring local_name; @@ -1937,8 +1941,9 @@ static int cmd_reget(void) } /**************************************************************************** - put a file restarting at end of local file + Put a file restarting at end of local file. ****************************************************************************/ + static int cmd_reput(void) { pstring local_name; @@ -1971,10 +1976,10 @@ static int cmd_reput(void) return do_put(remote_name, local_name, True); } - /**************************************************************************** - list a share name + List a share name. ****************************************************************************/ + static void browse_fn(const char *name, uint32 m, const char *comment, void *state) { @@ -2000,10 +2005,10 @@ static void browse_fn(const char *name, uint32 m, name,typestr,comment); } - /**************************************************************************** -try and browse available connections on a host + Try and browse available connections on a host. ****************************************************************************/ + static BOOL browse_host(BOOL sort) { int ret; @@ -2018,8 +2023,9 @@ static BOOL browse_host(BOOL sort) } /**************************************************************************** -list a server name + List a server name. ****************************************************************************/ + static void server_fn(const char *name, uint32 m, const char *comment, void *state) { @@ -2027,11 +2033,13 @@ static void server_fn(const char *name, uint32 m, } /**************************************************************************** -try and browse available connections on a host + Try and browse available connections on a host. ****************************************************************************/ + static BOOL list_servers(char *wk_grp) { - if (!cli->server_domain) return False; + if (!cli->server_domain) + return False; d_printf("\n\tServer Comment\n"); d_printf("\t--------- -------\n"); @@ -2062,8 +2070,7 @@ static struct int (*fn)(void); const char *description; char compl_args[2]; /* Completion argument info */ -} commands[] = -{ +} commands[] = { {"?",cmd_help,"[command] give help on a command",{COMPL_NONE,COMPL_NONE}}, {"altname",cmd_altname," show alt name",{COMPL_NONE,COMPL_NONE}}, {"archive",cmd_archive,"\n0=ignore archive bit\n1=only get archive files\n2=only get archive files and reset archive bit\n3=get all files and reset archive bit",{COMPL_NONE,COMPL_NONE}}, @@ -2117,11 +2124,11 @@ static struct {NULL,NULL,NULL,{COMPL_NONE,COMPL_NONE}} }; - /******************************************************************* - lookup a command string in the list of commands, including - abbreviations - ******************************************************************/ + Lookup a command string in the list of commands, including + abbreviations. +******************************************************************/ + static int process_tok(fstring tok) { int i = 0, matches = 0; @@ -2149,8 +2156,9 @@ static int process_tok(fstring tok) } /**************************************************************************** -help + Help. ****************************************************************************/ + static int cmd_help(void) { int i=0,j; @@ -2172,8 +2180,9 @@ static int cmd_help(void) } /**************************************************************************** -process a -c command string + Process a -c command string. ****************************************************************************/ + static int process_command_string(char *cmd) { pstring line; @@ -2198,7 +2207,8 @@ static int process_command_string(char *cmd) line[1000] = '\0'; cmd += strlen(cmd); } else { - if (p - cmd > 999) p = cmd + 999; + if (p - cmd > 999) + p = cmd + 999; strncpy(line, cmd, p - cmd); line[p - cmd] = '\0'; cmd = p + 1; @@ -2403,8 +2413,9 @@ cleanup: } /**************************************************************************** -make sure we swallow keepalives during idle time + Make sure we swallow keepalives during idle time. ****************************************************************************/ + static void readline_callback(void) { fd_set fds; @@ -2414,7 +2425,8 @@ static void readline_callback(void) t = time(NULL); - if (t - last_t < 5) return; + if (t - last_t < 5) + return; last_t = t; @@ -2442,10 +2454,10 @@ static void readline_callback(void) cli_chkpath(cli, "\\"); } - /**************************************************************************** -process commands on stdin + Process commands on stdin. ****************************************************************************/ + static void process_stdin(void) { const char *ptr; @@ -2485,10 +2497,10 @@ static void process_stdin(void) } } - /***************************************************** -return a connection to a server + Return a connection to a server. *******************************************************/ + static struct cli_state *do_connect(const char *server, const char *share) { struct cli_state *c; @@ -2560,6 +2572,7 @@ static struct cli_state *do_connect(const char *server, const char *share) char *pass = getpass("Password: "); if (pass) { pstrcpy(password, pass); + got_pass = 1; } } @@ -2602,10 +2615,10 @@ static struct cli_state *do_connect(const char *server, const char *share) return c; } - /**************************************************************************** - process commands from the client + Process commands from the client. ****************************************************************************/ + static int process(char *base_directory) { int rc = 0; @@ -2628,8 +2641,9 @@ static int process(char *base_directory) } /**************************************************************************** -handle a -L query + Handle a -L query. ****************************************************************************/ + static int do_host_query(char *query_host) { cli = do_connect(query_host, "IPC$"); @@ -2637,6 +2651,22 @@ static int do_host_query(char *query_host) return 1; browse_host(True); + + if (port != 139) { + + /* Workgroups simply don't make sense over anything + else but port 139... */ + + cli_shutdown(cli); + port = 139; + cli = do_connect(query_host, "IPC$"); + } + + if (cli == NULL) { + d_printf("NetBIOS over TCP disabled -- no workgroup available\n"); + return 1; + } + list_servers(lp_workgroup()); cli_shutdown(cli); @@ -2646,8 +2676,9 @@ static int do_host_query(char *query_host) /**************************************************************************** -handle a tar operation + Handle a tar operation. ****************************************************************************/ + static int do_tar_op(char *base_directory) { int ret; @@ -2671,8 +2702,9 @@ static int do_tar_op(char *base_directory) } /**************************************************************************** -handle a message operation + Handle a message operation. ****************************************************************************/ + static int do_message_op(void) { struct in_addr ip; @@ -2715,6 +2747,7 @@ static int do_message_op(void) * We don't actually do anything yet -- we just stash the name in a * global variable and do the query when all options have been read. **/ + static void remember_query_host(const char *arg, pstring query_host) { @@ -2729,12 +2762,13 @@ static void remember_query_host(const char *arg, } } - /**************************************************************************** main program ****************************************************************************/ + int main(int argc,char *argv[]) { + extern BOOL AllowDebugChange; fstring base_directory; int opt; pstring query_host; @@ -2745,6 +2779,7 @@ static void remember_query_host(const char *arg, poptContext pc; char *p; int rc = 0; + fstring new_workgroup; struct poptOption long_options[] = { POPT_AUTOHELP @@ -2775,14 +2810,17 @@ static void remember_query_host(const char *arg, *query_host = 0; *base_directory = 0; + + /* initialize the workgroup name so we can determine whether or + not it was set by a command line option */ + + set_global_myworkgroup( "" ); - setup_logging(argv[0],True); + /* set default debug level to 0 regardless of what smb.conf sets */ + DEBUGLEVEL_CLASS[DBGC_ALL] = 0; + dbf = x_stderr; + x_setbuf( x_stderr, NULL ); - if (!lp_load(dyn_CONFIGFILE,True,False,False)) { - fprintf(stderr, "%s: Can't load %s - run testparm to debug it\n", - argv[0], dyn_CONFIGFILE); - } - pc = poptGetContext("smbclient", argc, (const char **) argv, long_options, POPT_CONTEXT_KEEP_FIRST); poptSetOtherOptionHelp(pc, "service "); @@ -2798,7 +2836,8 @@ static void remember_query_host(const char *arg, */ name_type = 0x03; pstrcpy(desthost,poptGetOptArg(pc)); - if( 0 == port ) port = 139; + if( 0 == port ) + port = 139; message = True; break; case 'I': @@ -2853,7 +2892,29 @@ static void remember_query_host(const char *arg, poptGetArg(pc); + /* + * Don't load debug level from smb.conf. It should be + * set by cmdline arg or remain default (0) + */ + AllowDebugChange = False; + + /* save the workgroup... + + FIXME!! do we need to do tyhis for other options as well + (or maybe a generic way to keep lp_load() from overwriting + everything)? */ + + fstrcpy( new_workgroup, lp_workgroup() ); + + if (!lp_load(dyn_CONFIGFILE,True,False,False)) { + fprintf(stderr, "%s: Can't load %s - run testparm to debug it\n", + argv[0], dyn_CONFIGFILE); + } + load_interfaces(); + + if ( strlen(new_workgroup) != 0 ) + set_global_myworkgroup( new_workgroup ); if(poptPeekArg(pc)) { pstrcpy(service,poptGetArg(pc)); @@ -2890,7 +2951,7 @@ static void remember_query_host(const char *arg, use_kerberos = cmdline_auth_info.use_kerberos; got_pass = cmdline_auth_info.got_pass; - DEBUG( 3, ( "Client started (version %s).\n", VERSION ) ); + DEBUG(3,("Client started (version %s).\n", SAMBA_VERSION_STRING)); if (tar_type) { if (cmdstr) diff --git a/source3/client/clitar.c b/source3/client/clitar.c index 5295de8010..b01de5b8e7 100644 --- a/source3/client/clitar.c +++ b/source3/client/clitar.c @@ -122,7 +122,7 @@ static void writetarheader(int f, const char *aname, SMB_BIG_UINT size, time_t static void do_atar(char *rname,char *lname,file_info *finfo1); static void do_tar(file_info *finfo); static void oct_it(SMB_BIG_UINT value, int ndgs, char *p); -static void fixtarname(char *tptr, const char *fp, int l); +static void fixtarname(char *tptr, const char *fp, size_t l); static int dotarbuf(int f, char *b, int n); static void dozerobuf(int f, int n); static void dotareof(int f); @@ -171,7 +171,10 @@ static void writetarheader(int f, const char *aname, SMB_BIG_UINT size, time_t m memset(hb.dummy, 0, sizeof(hb.dummy)); l=strlen(aname); - if (l >= NAMSIZ - 1) { + /* We will be prepending a '.' in fixtarheader so use +2 to + * take care of the . and terminating zero. JRA. + */ + if (l+2 >= NAMSIZ) { /* write a GNU tar style long header */ char *b; b = (char *)malloc(l+TBLOCK+100); @@ -181,15 +184,14 @@ static void writetarheader(int f, const char *aname, SMB_BIG_UINT size, time_t m } writetarheader(f, "/./@LongLink", l+2, 0, " 0 \0", 'L'); memset(b, 0, l+TBLOCK+100); - fixtarname(b, aname, l); + fixtarname(b, aname, l+2); i = strlen(b)+1; DEBUG(5, ("File name in tar file: %s, size=%d, \n", b, (int)strlen(b))); dotarbuf(f, b, TBLOCK*(((i-1)/TBLOCK)+1)); SAFE_FREE(b); } - /* use l + 1 to do the null too */ - fixtarname(hb.dbuf.name, aname, (l >= NAMSIZ) ? NAMSIZ : l + 1); + fixtarname(hb.dbuf.name, aname, (l+2 >= NAMSIZ) ? NAMSIZ : l + 2); if (lowercase) strlower_m(hb.dbuf.name); @@ -419,13 +421,14 @@ static void dotareof(int f) (Un)mangle DOS pathname, make nonabsolute ****************************************************************************/ -static void fixtarname(char *tptr, const char *fp, int l) +static void fixtarname(char *tptr, const char *fp, size_t l) { /* add a '.' to start of file name, convert from ugly dos \'s in path * to lovely unix /'s :-} */ *tptr++='.'; + l--; - safe_strcpy(tptr, fp, l); + StrnCpy(tptr, fp, l-1); string_replace(tptr, '\\', '/'); } @@ -1477,7 +1480,7 @@ accordingly. static int read_inclusion_file(char *filename) { XFILE *inclusion = NULL; - char buf[MAXPATHLEN + 1]; + char buf[PATH_MAX + 1]; char *inclusion_buffer = NULL; int inclusion_buffer_size = 0; int inclusion_buffer_sofar = 0; @@ -1487,7 +1490,7 @@ static int read_inclusion_file(char *filename) int error = 0; clipn = 0; - buf[MAXPATHLEN] = '\0'; /* guarantee null-termination */ + buf[PATH_MAX] = '\0'; /* guarantee null-termination */ if ((inclusion = x_fopen(filename, O_RDONLY, 0)) == NULL) { /* XXX It would be better to include a reason for failure, but without * autoconf, it's hard to use strerror, sys_errlist, etc. @@ -1583,7 +1586,7 @@ static int read_inclusion_file(char *filename) Parse tar arguments. Sets tar_type, tar_excl, etc. ***************************************************************************/ -int tar_parseargs(int argc, char *argv[], char *Optarg, int Optind) +int tar_parseargs(int argc, char *argv[], const char *Optarg, int Optind) { int newOptind = Optind; char tar_clipfl='\0'; @@ -1775,6 +1778,10 @@ int tar_parseargs(int argc, char *argv[], char *Optarg, int Optind) if (tarhandle == 1) { dbf = x_stderr; } + if (!argv[Optind]) { + DEBUG(0,("Must specify tar filename\n")); + return 0; + } if (!strcmp(argv[Optind], "-")) { newOptind++; } diff --git a/source3/client/mount.cifs.c b/source3/client/mount.cifs.c index 9592dbdf96..7ab17a2b02 100755 --- a/source3/client/mount.cifs.c +++ b/source3/client/mount.cifs.c @@ -32,6 +32,15 @@ static char * user_name = NULL; char * mountpassword = NULL; +/* BB finish BB + + cifs_umount + open nofollow - avoid symlink exposure? + get owner of dir see if matches self or if root + call system(umount argv) etc. + +BB end finish BB */ + void mount_cifs_usage() { printf("\nUsage: %s remotetarget dir\n", thisprogram); @@ -155,17 +164,36 @@ int parse_options(char * options) if (value && *value) { got_gid = 1; } - } /* else if (strnicmp(data, "file_mode", 4) == 0) { - if (value && *value) { - vol->file_mode = - simple_strtoul(value, &value, 0); + /* fmask and dmask synonyms for people used to smbfs syntax */ + } else if (strcmp(data, "file_mode") == 0 || strcmp(data, "fmask")==0) { + if (!value || !*value) { + printf ("Option '%s' requires a numerical argument\n", data); + return 1; } - } else if (strnicmp(data, "dir_mode", 3) == 0) { - if (value && *value) { - vol->dir_mode = - simple_strtoul(value, &value, 0); + + if (value[0] != '0') { + printf ("WARNING: '%s' not expressed in octal.\n", data); } - } else if (strnicmp(data, "port", 4) == 0) { + + if (strcmp (data, "fmask") == 0) { + printf ("WARNING: CIFS mount option 'fmask' is deprecated. Use 'file_mode' instead.\n"); + data = "file_mode"; + } + } else if (strcmp(data, "dir_mode") == 0 || strcmp(data, "dmask")==0) { + if (!value || !*value) { + printf ("Option '%s' requires a numerical argument\n", data); + return 1; + } + + if (value[0] != '0') { + printf ("WARNING: '%s' not expressed in octal.\n", data); + } + + if (strcmp (data, "dmask") == 0) { + printf ("WARNING: CIFS mount option 'dmask' is deprecated. Use 'dir_mode' instead.\n"); + data = "dir_mode"; + } + } /* else if (strnicmp(data, "port", 4) == 0) { if (value && *value) { vol->port = simple_strtoul(value, &value, 0); @@ -446,18 +474,28 @@ int main(int argc, char ** argv) /* canonicalize the path in argv[1]? */ + /* BB save off path and pop after mount returns */ + if(chdir(mountpoint)) { + printf("mount error: can not change directory into mount target %s\n",mountpoint); + } + if(stat (mountpoint, &statbuf)) { printf("mount error: mount point %s does not exist\n",mountpoint); return -1; } + if (S_ISDIR(statbuf.st_mode) == 0) { printf("mount error: mount point %s is not a directory\n",mountpoint); return -1; } - if(geteuid()) { - printf("mount error: permission denied, not superuser and cifs.mount not installed SUID\n"); - return -1; + if((getuid() != 0) && (geteuid() == 0)) { + if((statbuf.st_uid == getuid()) && (S_IRWXU == statbuf.st_mode & S_IRWXU)) { + printf("setuid mount allowed\n"); + } else { + printf("mount error: permission denied, not superuser and cifs.mount not installed SUID\n"); + return -1; + } } ipaddr = parse_server(share_name); diff --git a/source3/client/smbmnt.c b/source3/client/smbmnt.c index ce406179cf..c04be3b7af 100644 --- a/source3/client/smbmnt.c +++ b/source3/client/smbmnt.c @@ -38,7 +38,7 @@ help(void) { printf("\n"); printf("Usage: smbmnt mount-point [options]\n"); - printf("Version %s\n\n",VERSION); + printf("Version %s\n\n",SAMBA_VERSION_STRING); printf("-s share share name on server\n" "-r mount read-only\n" "-u uid mount as uid\n" @@ -94,9 +94,9 @@ parse_args(int argc, char *argv[], struct smb_mount_data *data, char **share) static char * fullpath(const char *p) { - char path[MAXPATHLEN]; + char path[PATH_MAX+1]; - if (strlen(p) > MAXPATHLEN-1) { + if (strlen(p) > PATH_MAX) { return NULL; } diff --git a/source3/client/smbmount.c b/source3/client/smbmount.c index 343d4f2675..6e8d9f5bca 100644 --- a/source3/client/smbmount.c +++ b/source3/client/smbmount.c @@ -428,7 +428,7 @@ static void send_fs_socket(char *the_service, char *mount_point, struct cli_stat **/ static void init_mount(void) { - char mount_point[MAXPATHLEN+1]; + char mount_point[PATH_MAX+1]; pstring tmp; pstring svc2; struct cli_state *c; @@ -663,7 +663,7 @@ static void usage(void) { printf("Usage: mount.smbfs service mountpoint [-o options,...]\n"); - printf("Version %s\n\n",VERSION); + printf("Version %s\n\n",SAMBA_VERSION_STRING); printf( "Options:\n\ @@ -923,7 +923,7 @@ static void parse_mount_smb(int argc, char **argv) read_credentials_file(credentials); } - DEBUG(3,("mount.smbfs started (version %s)\n", VERSION)); + DEBUG(3,("mount.smbfs started (version %s)\n", SAMBA_VERSION_STRING)); if (*workgroup == 0) { pstrcpy(workgroup,lp_workgroup()); diff --git a/source3/configure.in b/source3/configure.in index f964bc719f..a2e04b5d48 100644 --- a/source3/configure.in +++ b/source3/configure.in @@ -145,14 +145,15 @@ AC_SUBST(PICFLAG) AC_SUBST(PICSUFFIX) AC_SUBST(POBAD_CC) AC_SUBST(SHLIBEXT) +AC_SUBST(INSTALLCLIENT) AC_SUBST(INSTALLCLIENTCMD_SH) AC_SUBST(INSTALLCLIENTCMD_A) AC_SUBST(LIBSMBCLIENT_SHARED) AC_SUBST(LIBSMBCLIENT) -AC_SUBST(PRINTLIBS) -AC_SUBST(AUTHLIBS) -AC_SUBST(ACLLIBS) -AC_SUBST(PASSDBLIBS) +AC_SUBST(PRINT_LIBS) +AC_SUBST(AUTH_LIBS) +AC_SUBST(ACL_LIBS) +AC_SUBST(PASSDB_LIBS) AC_SUBST(IDMAP_LIBS) AC_SUBST(KRB5_LIBS) AC_SUBST(LDAP_LIBS) @@ -284,10 +285,10 @@ DYNEXP= dnl Add modules that have to be built by default here dnl These have to be built static: -default_static_modules="pdb_smbpasswd pdb_tdbsam rpc_lsa rpc_samr rpc_reg rpc_wks rpc_net rpc_dfs rpc_srv rpc_spoolss auth_rhosts auth_sam auth_unix auth_winbind auth_server auth_domain auth_builtin" +default_static_modules="pdb_smbpasswd pdb_tdbsam rpc_lsa rpc_samr rpc_reg rpc_lsa_ds rpc_wks rpc_net rpc_dfs rpc_srv rpc_spoolss auth_rhosts auth_sam auth_unix auth_winbind auth_server auth_domain auth_builtin" dnl These are preferably build shared, and static if dlopen() is not available -default_shared_modules="vfs_recycle vfs_audit vfs_extd_audit vfs_netatalk vfs_fake_perms vfs_default_quota" +default_shared_modules="vfs_recycle vfs_audit vfs_extd_audit vfs_netatalk vfs_fake_perms vfs_default_quota vfs_readonly vfs_cap charset_CP850 charset_CP437" if test "x$developer" = xyes; then default_static_modules="$default_static_modules rpc_echo" @@ -358,8 +359,11 @@ case "$host_os" in # recommendations on large file support, however it makes the # compile work using gcc 2.7 and 2.8, whereas using the Sun # recommendation makes the compile fail on gcc2.7. JRA. +# +# Solaris uses SYSV printing. Make sure to set that here. --jerry # *solaris*) + AC_DEFINE(SYSV, 1, [Whether to enable System V compatibility]) case `uname -r` in 5.0*|5.1*|5.2*|5.3*|5.5*) AC_MSG_RESULT([no large file support]) @@ -390,6 +394,16 @@ case "$host_os" in esac ;; # +# IRIX uses SYSV printing. Make sure to set that here +# + *irix*) + AC_DEFINE(SYSV, 1, [Whether to enable System V compatibility]) + ;; + *freebsd*) + AC_DEFINE(FREEBSD, 1, [Whether the host os is FreeBSD]) + ;; + +# # VOS may need to have POSIX support and System V compatibility enabled. # *vos*) @@ -407,7 +421,7 @@ case "$host_os" in *) CPPFLAGS="$CPPFLAGS -D_SYSV" AC_DEFINE(_SYSV, 1, [Whether to enable System V compatibility]) - esac + esac ;; # # Tests needed for SINIX large file support. @@ -591,7 +605,7 @@ if test x$enable_cups != xno; then AC_DEFINE(HAVE_CUPS,1,[Whether we have CUPS]) CFLAGS="$CFLAGS `$CUPS_CONFIG --cflags`" LDFLAGS="$LDFLAGS `$CUPS_CONFIG --ldflags`" - PRINTLIBS="$PRINTLIBS `$CUPS_CONFIG --libs`" + PRINT_LIBS="$PRINT_LIBS `$CUPS_CONFIG --libs`" fi fi @@ -1090,6 +1104,8 @@ if test "$enable_shared" = "yes"; then LDSHFLAGS="-B symbolic -b -z" SONAMEFLAG="+h " PICFLAG="+z" + elif test "${GCC}" = "yes"; then + PICFLAG="-fPIC" fi DYNEXP="-Wl,-E" AC_DEFINE(STAT_ST_BLOCKSIZE,8192,[The size of a block]) @@ -1533,7 +1549,8 @@ AC_ARG_WITH(libiconv, AC_MSG_ERROR(I won't take no for an answer) else if test "$withval" != "yes" ; then - LOOK_DIRS="$withval $LOOK_DIRS" + ICONV_PATH_SPEC=yes + LOOK_DIRS="$withval" fi fi ]) @@ -1543,51 +1560,108 @@ for i in $LOOK_DIRS ; do save_LIBS=$LIBS save_LDFLAGS=$LDFLAGS save_CPPFLAGS=$CPPFLAGS - CPPFLAGS="-I$i/include" - LDFLAGS="-L$i/lib" + CPPFLAGS="$CPPFLAGS -I$i/include" +dnl This is here to handle -withval stuff for --with-libiconv + if test x"$ICONV_PATH_SPEC" = "xyes" ; then + LDFLAGS="-L$i/lib" + fi LIBS= export LDFLAGS LIBS CPPFLAGS dnl Try to find iconv(3) jm_ICONV($i) - CPPFLAGS=$save_CPPFLAGS if test "$ICONV_FOUND" = yes; then - LDFLAGS=$save_LDFLAGS LIB_ADD_DIR(LDFLAGS, "$i/lib") CFLAGS_ADD_DIR(CPPFLAGS, "$i/include") LIBS="$save_LIBS $LIBS" ICONV_LOCATION=$i export LDFLAGS LIBS CPPFLAGS - break - else - LDFLAGS=$save_LDFLAGS - LIBS=$save_LIBS - export LDFLAGS LIBS CPPFLAGS +dnl Now, check for a working iconv ... we want to do it here because +dnl there might be a working iconv further down the list of LOOK_DIRS + + ############ + # check for iconv in libc + ic_save_LIBS="$LIBS" + if test x"$ICONV_PATH_SPEC" = "xyes" ; then + LIBS="$LIBS -L$ICONV_LOCATION/lib" + fi +dnl AC_CACHE_CHECK([for working iconv],samba_cv_HAVE_NATIVE_ICONV,[ + default_dos_charset=no + default_display_charset=no + default_unix_charset=no + echo + + # check for default dos charset name + for j in CP850 IBM850 ; do + rjs_CHARSET($j) + if test x"$ICONV_CHARSET" = x"$j"; then + default_dos_charset="\"$j\"" + break + fi + done + # check for default display charset name + for j in ASCII 646 ; do + rjs_CHARSET($j) + if test x"$ICONV_CHARSET" = x"$j"; then + default_display_charset="\"$j\"" + break + fi + done + # check for default unix charset name + for j in UTF-8 UTF8 ; do + rjs_CHARSET($j) + if test x"$ICONV_CHARSET" = x"$j"; then + default_unix_charset="\"$j\"" + break + fi + done + + if test "$default_dos_charset" != "no" -a \ + "$default_dos_charset" != "cross" -a \ + "$default_display_charset" != "no" -a \ + "$default_display_charset" != "cross" -a \ + "$default_unix_charset" != "no" -a \ + "$default_unix_charset" != "cross" + then + samba_cv_HAVE_NATIVE_ICONV=yes + else if test "$default_dos_charset" = "cross" -o \ + "$default_display_charset" = "cross" -o \ + "$default_unix_charset" = "cross" + then + samba_cv_HAVE_NATIVE_ICONV=cross + else + samba_cv_HAVE_NATIVE_ICONV=no + fi + fi +dnl ]) + + LIBS="$ic_save_LIBS" + if test x"$samba_cv_HAVE_NATIVE_ICONV" = x"yes"; then + CPPFLAGS=$save_CPPFLAGS + CFLAGS_ADD_DIR(CPPFLAGS, "$i/include") + export CPPFLAGS + AC_DEFINE(HAVE_NATIVE_ICONV,1,[Whether to use native iconv]) + AC_DEFINE_UNQUOTED(DEFAULT_DOS_CHARSET,$default_dos_charset,[Default dos charset name]) + AC_DEFINE_UNQUOTED(DEFAULT_DISPLAY_CHARSET,$default_display_charset,[Default display charset name]) + AC_DEFINE_UNQUOTED(DEFAULT_UNIX_CHARSET,$default_unix_charset,[Default unix charset name]) + break + fi +dnl We didn't find a working iconv, so keep going fi +dnl We only need to clean these up here for the next pass through the loop + CPPFLAGS=$save_CPPFLAGS + LDFLAGS=$save_LDFLAGS + LIBS=$save_LIBS + export LDFLAGS LIBS CPPFLAGS done -############ -# check for iconv in libc -ic_save_LIBS="$LIBS" -LIBS="$LIBS -L$ICONV_LOCATION/lib" -AC_CACHE_CHECK([for working iconv],samba_cv_HAVE_NATIVE_ICONV,[ -AC_TRY_RUN([ -#include <$jm_cv_include> -main() { - iconv_t cd = iconv_open("ASCII", "UCS-2LE"); - if (cd == 0 || cd == (iconv_t)-1) return -1; - return 0; -} -], -samba_cv_HAVE_NATIVE_ICONV=yes,samba_cv_HAVE_NATIVE_ICONV=no,samba_cv_HAVE_NATIVE_ICONV=cross)]) -if test x"$samba_cv_HAVE_NATIVE_ICONV" = x"yes"; then - AC_DEFINE(HAVE_NATIVE_ICONV,1,[Whether to use native iconv]) -fi -LIBS="$ic_save_LIBS" if test x"$ICONV_FOUND" = x"no" -o x"$samba_cv_HAVE_NATIVE_ICONV" != x"yes" ; then AC_MSG_WARN([Sufficient support for iconv function was not found. Install libiconv from http://freshmeat.net/projects/libiconv/ for better charset compatibility!]) + AC_DEFINE_UNQUOTED(DEFAULT_DOS_CHARSET,"CP850",[Default dos charset name]) + AC_DEFINE_UNQUOTED(DEFAULT_DISPLAY_CHARSET,"ASCII",[Default display charset name]) + AC_DEFINE_UNQUOTED(DEFAULT_UNIX_CHARSET,"UTF8",[Default unix charset name]) fi @@ -2109,6 +2183,22 @@ AC_ARG_WITH(afs, AC_MSG_RESULT(no) ) +#################################################### +# check for Linux-specific AFS fake-kaserver support +AC_MSG_CHECKING(whether to use AFS fake-kaserver) +AC_ARG_WITH(fake-kaserver, +[ --with-fake-kaserver Include AFS fake-kaserver support (default=no) ], +[ case "$withval" in + yes) + AC_MSG_RESULT(yes) + AC_DEFINE(WITH_FAKE_KASERVER,1,[Whether to include AFS fake-kaserver support]) + ;; + *) + AC_MSG_RESULT(no) + ;; + esac ], + AC_MSG_RESULT(no) +) ################################################# # check for the DFS clear-text auth system @@ -2471,12 +2561,32 @@ if test x"$with_ads_support" != x"no"; then [krb5_enctype enctype; enctype = ENCTYPE_ARCFOUR_HMAC_MD5;], samba_cv_HAVE_ENCTYPE_ARCFOUR_HMAC_MD5=yes, samba_cv_HAVE_ENCTYPE_ARCFOUR_HMAC_MD5=no)]) - - if test x"$samba_cv_HAVE_ENCTYPE_ARCFOUR_HMAC_MD5" = x"yes"; then + AC_CACHE_CHECK([for KEYTYPE_ARCFOUR_56], + samba_cv_HAVE_KEYTYPE_ARCFOUR_56,[ + AC_TRY_COMPILE([#include ], + [krb5_keytype keytype; keytype = KEYTYPE_ARCFOUR_56;], + samba_cv_HAVE_KEYTYPE_ARCFOUR_56=yes, + samba_cv_HAVE_KEYTYPE_ARCFOUR_56=no)]) +# Heimdals with KEYTYPE_ARCFOUR but not KEYTYPE_ARCFOUR_56 are broken +# w.r.t. arcfour and windows, so we must not enable it here + if test x"$samba_cv_HAVE_ENCTYPE_ARCFOUR_HMAC_MD5" = x"yes" -a\ + x"$samba_cv_HAVE_KEYTYPE_ARCFOUR_56" = x"yes"; then AC_DEFINE(HAVE_ENCTYPE_ARCFOUR_HMAC_MD5,1, [Whether the ENCTYPE_ARCFOUR_HMAC_MD5 key type is available]) fi + AC_CACHE_CHECK([for AP_OPTS_USE_SUBKEY], + samba_cv_HAVE_AP_OPTS_USE_SUBKEY,[ + AC_TRY_COMPILE([#include ], + [krb5_flags ap_options; ap_options = AP_OPTS_USE_SUBKEY;], + samba_cv_HAVE_AP_OPTS_USE_SUBKEY=yes, + samba_cv_HAVE_AP_OPTS_USE_SUBKEY=no)]) + + if test x"$samba_cv_HAVE_AP_OPTS_USE_SUBKEY" = x"yes"; then + AC_DEFINE(HAVE_AP_OPTS_USE_SUBKEY,1, + [Whether the AP_OPTS_USE_SUBKEY ap option is available]) + fi + AC_CACHE_CHECK([for the krb5_princ_component macro], samba_cv_HAVE_KRB5_PRINC_COMPONENT,[ AC_TRY_LINK([#include ], @@ -2489,6 +2599,28 @@ if test x"$with_ads_support" != x"no"; then [Whether krb5_princ_component is available]) fi + AC_CACHE_CHECK([for memory keytab support], + samba_cv_HAVE_MEMORY_KEYTAB,[ + AC_TRY_RUN([ +#include + main() + { + krb5_context context; + krb5_keytab keytab; + + krb5_init_context(&context); + if (krb5_kt_resolve(context, "MEMORY:", &keytab)) + exit(0); + exit(1); + }], + samba_cv_HAVE_MEMORY_KEYTAB=no, + samba_cv_HAVE_MEMORY_KEYTAB=yes)]) + + if test x"$samba_cv_HAVE_MEMORY_KEYTAB" = x"yes"; then + AC_DEFINE(HAVE_MEMORY_KEYTAB,1, + [Whether in-memory keytabs are supported]) + fi + if test x"$ac_cv_lib_ext_krb5_krb5_mk_req_extended" = x"yes"; then AC_DEFINE(HAVE_KRB5,1,[Whether to have KRB5 support]) @@ -2530,7 +2662,7 @@ AC_ARG_WITH(expsam, ;; mysql) ## pdb_mysql - AM_PATH_MYSQL([0.11.0],[default_shared_modules="$default_shared_modules pdb_mysql"],[]) + AM_PATH_MYSQL([default_shared_modules="$default_shared_modules pdb_mysql"],[]) CFLAGS="$CFLAGS $MYSQL_CFLAGS" ;; no) @@ -2596,8 +2728,15 @@ AC_ARG_WITH(pam, [ case "$withval" in yes) AC_MSG_RESULT(yes) + if test x"$ac_cv_header_security_pam_appl_h" = x"no"; then + if test x"$ac_cv_header_security_pam_modules_h" = x"no"; then + if test x"$ac_cv_header_security__pam_macros_h" = x"no"; then + AC_MSG_ERROR(--with-pam specified but no PAM headers found) + fi + fi + fi AC_DEFINE(WITH_PAM,1,[Whether to include PAM support]) - AUTHLIBS="$AUTHLIBS -lpam" + AUTH_LIBS="$AUTH_LIBS -lpam" with_pam_for_crypt=yes ;; *) @@ -2619,13 +2758,16 @@ AC_ARG_WITH(pam_smbpass, yes) AC_MSG_RESULT(yes) -# Conditions under which pam_smbpass should not be built. + # Conditions under which pam_smbpass should not be built. if test x$PICFLAG = x; then - AC_MSG_RESULT([No support for PIC code - disabling pam_smbpass]) + AC_MSG_ERROR([No support for PIC code]) + elif test x"$ac_cv_header_security_pam_appl_h" = x"no"; then + AC_MSG_ERROR([No security/pam_appl.h found]) elif test x$ac_cv_lib_pam_pam_get_data = xno; then - AC_MSG_RESULT([No libpam found -- disabling pam_smbpass]) + AC_MSG_ERROR([No libpam found]) else + AUTH_LIBS="$AUTH_LIBS -lpam" SHLIB_PROGS="$SHLIB_PROGS bin/pam_smbpass.$SHLIBEXT" fi ;; @@ -2640,7 +2782,7 @@ AC_ARG_WITH(pam_smbpass, ############################################### # test for where we get crypt() from AC_SEARCH_LIBS(crypt, [crypt], - [test "$ac_cv_search_crypt" = "none required" || AUTHLIBS="-lcrypt $AUTHLIBS" + [test "$ac_cv_search_crypt" = "none required" || AUTH_LIBS="-lcrypt $AUTH_LIBS" AC_DEFINE(HAVE_CRYPT,1,[Whether the system has the crypt() function])]) ## @@ -2652,7 +2794,7 @@ AC_SEARCH_LIBS(crypt, [crypt], if test $with_pam_for_crypt = no; then AC_CACHE_CHECK([for a crypt that needs truncated salt],samba_cv_HAVE_TRUNCATED_SALT,[ crypt_LIBS="$LIBS" -LIBS="$AUTHLIBS $LIBS" +LIBS="$AUTH_LIBS $LIBS" AC_TRY_RUN([#include "${srcdir-.}/tests/crypttest.c"], samba_cv_HAVE_TRUNCATED_SALT=no,samba_cv_HAVE_TRUNCATED_SALT=yes,samba_cv_HAVE_TRUNCATED_SALT=cross) LIBS="$crypt_LIBS"]) @@ -3085,6 +3227,7 @@ AC_ARG_WITH(manpages-langs, INSTALLCLIENTCMD_SH=: INSTALLCLIENTCMD_A=: +INSTALLCLIENT= LIBSMBCLIENT_SHARED= LIBSMBCLIENT= AC_MSG_CHECKING(whether to build the libsmbclient shared library) @@ -3097,6 +3240,8 @@ AC_ARG_WITH(libsmbclient, *) if test $BLDSHARED = true; then INSTALLCLIENTCMD_SH="\$(INSTALLCMD)" + ## build the static version of libsmbclient as well + INSTALLCLIENTCMD_A="\$(INSTALLCMD)" LIBSMBCLIENT_SHARED=bin/libsmbclient.$SHLIBEXT LIBSMBCLIENT=libsmbclient AC_MSG_RESULT(yes) @@ -3108,6 +3253,7 @@ AC_ARG_WITH(libsmbclient, INSTALLCLIENTCMD_A="\$(INSTALLCMD)" LIBSMBCLIENT=libsmbclient fi + INSTALLCLIENT=installclientlib ;; esac ], [ @@ -3125,6 +3271,7 @@ AC_ARG_WITH(libsmbclient, INSTALLCLIENTCMD_A="\$(INSTALLCMD)" LIBSMBCLIENT=libsmbclient fi] + INSTALLCLIENT=installclientlib ) @@ -3392,7 +3539,7 @@ AC_ARG_WITH(acl-support, *osf*) AC_MSG_RESULT(Using Tru64 ACLs) AC_DEFINE(HAVE_TRU64_ACLS,1,[Whether Tru64 ACLs are available]) - ACLLIBS="$ACLLIBS -lpacl" + ACL_LIBS="$ACL_LIBS -lpacl" ;; *freebsd5*) AC_MSG_RESULT(Using FreeBSD posix ACLs) @@ -3400,8 +3547,8 @@ AC_ARG_WITH(acl-support, AC_DEFINE(HAVE_ACL_GET_PERM_NP,1,[Whether acl_get_perm_np() is available]) ;; *linux*) - AC_CHECK_LIB(attr,getxattr,[ACLLIBS="$ACLLIBS -lattr"]) - AC_CHECK_LIB(acl,acl_get_file,[ACLLIBS="$ACLLIBS -lacl"]) + AC_CHECK_LIB(attr,getxattr,[ACL_LIBS="$ACL_LIBS -lattr"]) + AC_CHECK_LIB(acl,acl_get_file,[ACL_LIBS="$ACL_LIBS -lacl"]) AC_CACHE_CHECK([for ACL support],samba_cv_HAVE_POSIX_ACLS,[ acl_LIBS=$LIBS LIBS="$LIBS -lacl" @@ -3427,7 +3574,7 @@ samba_cv_HAVE_ACL_GET_PERM_NP=yes,samba_cv_HAVE_ACL_GET_PERM_NP=no) fi ;; *) - AC_CHECK_LIB(acl,acl_get_file,[ACLLIBS="$ACLLIBS -lacl"]) + AC_CHECK_LIB(acl,acl_get_file,[ACL_LIBS="$ACL_LIBS -lacl"]) AC_CACHE_CHECK([for ACL support],samba_cv_HAVE_POSIX_ACLS,[ acl_LIBS=$LIBS LIBS="$LIBS -lacl" @@ -3910,22 +4057,23 @@ fi ]) ## contributed pdb_modules SMB_MODULE(pdb_xml, passdb/pdb_xml.o, "bin/xml.$SHLIBEXT", PDB, - [ PASSDBLIBS="$PASSDBLIBS $XML_LIBS" ] ) + [ PASSDB_LIBS="$PASSDB_LIBS $XML_LIBS" ] ) SMB_MODULE(pdb_mysql, passdb/pdb_mysql.o, "bin/mysql.$SHLIBEXT", PDB, - [ PASSDBLIBS="$PASSDBLIBS $MYSQL_LIBS" ] ) + [ PASSDB_LIBS="$PASSDB_LIBS $MYSQL_LIBS" ] ) ## end of contributed pdb_modules ########################################################################### SMB_MODULE(pdb_ldap, passdb/pdb_ldap.o, "bin/ldapsam.$SHLIBEXT", PDB, - [ PASSDBLIBS="$PASSDBLIBS $LDAP_LIBS" ] ) + [ PASSDB_LIBS="$PASSDB_LIBS $LDAP_LIBS" ] ) SMB_MODULE(pdb_smbpasswd, passdb/pdb_smbpasswd.o, "bin/smbpasswd.$SHLIBEXT", PDB) SMB_MODULE(pdb_tdbsam, passdb/pdb_tdb.o, "bin/tdbsam.$SHLIBEXT", PDB) SMB_MODULE(pdb_guest, passdb/pdb_guest.o, "bin/guest.$SHLIBEXT", PDB) -SMB_SUBSYSTEM(PDB) +SMB_SUBSYSTEM(PDB,passdb/pdb_interface.c) SMB_MODULE(rpc_lsa, \$(RPC_LSA_OBJ), "bin/librpc_lsarpc.$SHLIBEXT", RPC) SMB_MODULE(rpc_reg, \$(RPC_REG_OBJ), "bin/librpc_winreg.$SHLIBEXT", RPC) +SMB_MODULE(rpc_lsa_ds, \$(RPC_LSA_DS_OBJ), "bin/librpc_lsa_ds.$SHLIBEXT", RPC) SMB_MODULE(rpc_wks, \$(RPC_WKS_OBJ), "bin/librpc_wkssvc.$SHLIBEXT", RPC) SMB_MODULE(rpc_net, \$(RPC_NETLOG_OBJ), "bin/librpc_NETLOGON.$SHLIBEXT", RPC) SMB_MODULE(rpc_dfs, \$(RPC_DFS_OBJ), "bin/librpc_netdfs.$SHLIBEXT", RPC) @@ -3933,23 +4081,25 @@ SMB_MODULE(rpc_srv, \$(RPC_SVC_OBJ), "bin/librpc_srvsvc.$SHLIBEXT", RPC) SMB_MODULE(rpc_spoolss, \$(RPC_SPOOLSS_OBJ), "bin/librpc_spoolss.$SHLIBEXT", RPC) SMB_MODULE(rpc_samr, \$(RPC_SAMR_OBJ), "bin/librpc_samr.$SHLIBEXT", RPC) SMB_MODULE(rpc_echo, \$(RPC_ECHO_OBJ), "bin/librpc_echo.$SHLIBEXT", RPC) -SMB_SUBSYSTEM(RPC) +SMB_SUBSYSTEM(RPC,smbd/server.c) SMB_MODULE(idmap_ldap, sam/idmap_ldap.o, "bin/idmap_ldap.$SHLIBEXT", IDMAP) SMB_MODULE(idmap_tdb, sam/idmap_tdb.o, "bin/idmap_tdb.$SHLIBEXT", IDMAP) -SMB_SUBSYSTEM(IDMAP) +SMB_SUBSYSTEM(IDMAP,sam/idmap.c) SMB_MODULE(charset_weird, modules/weird.o, "bin/weird.$SHLIBEXT", CHARSET) -SMB_SUBSYSTEM(CHARSET) +SMB_MODULE(charset_CP850, modules/CP850.o, "bin/CP850.$SHLIBEXT", CHARSET) +SMB_MODULE(charset_CP437, modules/CP437.o, "bin/CP437.$SHLIBEXT", CHARSET) +SMB_SUBSYSTEM(CHARSET,lib/iconv.c) SMB_MODULE(auth_rhosts, \$(AUTH_RHOSTS_OBJ), "bin/rhosts.$SHLIBEXT", AUTH) SMB_MODULE(auth_sam, \$(AUTH_SAM_OBJ), "bin/sam.$SHLIBEXT", AUTH) SMB_MODULE(auth_unix, \$(AUTH_UNIX_OBJ), "bin/unix.$SHLIBEXT", AUTH) SMB_MODULE(auth_winbind, \$(AUTH_WINBIND_OBJ), "bin/winbind.$SHLIBEXT", AUTH) -SMB_MODULE(auth_server, \$(AUTH_SERVER_OBJ), "bin/server.$SHLIBEXT", AUTH) +SMB_MODULE(auth_server, \$(AUTH_SERVER_OBJ), "bin/smbserver.$SHLIBEXT", AUTH) SMB_MODULE(auth_domain, \$(AUTH_DOMAIN_OBJ), "bin/domain.$SHLIBEXT", AUTH) SMB_MODULE(auth_builtin, \$(AUTH_BUILTIN_OBJ), "bin/builtin.$SHLIBEXT", AUTH) -SMB_SUBSYSTEM(AUTH) +SMB_SUBSYSTEM(AUTH,auth/auth.c) SMB_MODULE(vfs_recycle, \$(VFS_RECYCLE_OBJ), "bin/recycle.$SHLIBEXT", VFS) SMB_MODULE(vfs_audit, \$(VFS_AUDIT_OBJ), "bin/audit.$SHLIBEXT", VFS) @@ -3957,7 +4107,9 @@ SMB_MODULE(vfs_extd_audit, \$(VFS_EXTD_AUDIT_OBJ), "bin/extd_audit.$SHLIBEXT", V SMB_MODULE(vfs_netatalk, \$(VFS_NETATALK_OBJ), "bin/netatalk.$SHLIBEXT", VFS) SMB_MODULE(vfs_fake_perms, \$(VFS_FAKE_PERMS_OBJ), "bin/fake_perms.$SHLIBEXT", VFS) SMB_MODULE(vfs_default_quota, \$(VFS_DEFAULT_QUOTA_OBJ), "bin/default_quota.$SHLIBEXT", VFS) -SMB_SUBSYSTEM(VFS) +SMB_MODULE(vfs_readonly, \$(VFS_READONLY_OBJ), "bin/readonly.$SHLIBEXT", VFS) +SMB_MODULE(vfs_cap, \$(VFS_CAP_OBJ), "bin/cap.$SHLIBEXT", VFS) +SMB_SUBSYSTEM(VFS,smbd/vfs.c) AC_DEFINE_UNQUOTED(STRING_STATIC_MODULES, "$string_static_modules", [String list of builtin modules]) @@ -3979,6 +4131,7 @@ fi if test x"$with_ldap_support" != x"no"; then AC_MSG_RESULT([ LDAP_LIBS = $LDAP_LIBS]) fi +AC_MSG_RESULT([ AUTH_LIBS = $AUTH_LIBS]) ################################################# # final configure stuff @@ -4000,7 +4153,7 @@ dnl Remove -I/usr/include/? from CFLAGS and CPPFLAGS CFLAGS_REMOVE_USR_INCLUDE(CFLAGS) CFLAGS_REMOVE_USR_INCLUDE(CPPFLAGS) -AC_OUTPUT(include/stamp-h Makefile script/findsmb) +AC_OUTPUT(include/stamp-h Makefile script/findsmb smbadduser script/gen-8bit-gap.sh) ################################################# # Print very concise instructions on building/use diff --git a/source3/groupdb/mapping.c b/source3/groupdb/mapping.c index cd903fa28b..7a07b5c344 100644 --- a/source3/groupdb/mapping.c +++ b/source3/groupdb/mapping.c @@ -234,7 +234,7 @@ static BOOL get_group_map_from_sid(DOM_SID sid, GROUP_MAP *map) TDB_DATA kbuf, dbuf; pstring key; fstring string_sid; - int ret; + int ret = 0; if(!init_group_mapping()) { DEBUG(0,("failed to initialize group mapping")); @@ -257,6 +257,11 @@ static BOOL get_group_map_from_sid(DOM_SID sid, GROUP_MAP *map) &map->gid, &map->sid_name_use, &map->nt_name, &map->comment); SAFE_FREE(dbuf.dptr); + + if ( ret == -1 ) { + DEBUG(3,("get_group_map_from_sid: tdb_unpack failure\n")); + return False; + } sid_copy(&map->sid, &sid); @@ -299,6 +304,11 @@ static BOOL get_group_map_from_gid(gid_t gid, GROUP_MAP *map) SAFE_FREE(dbuf.dptr); + if ( ret == -1 ) { + DEBUG(3,("get_group_map_from_gid: tdb_unpack failure\n")); + return False; + } + if (gid==map->gid) { SAFE_FREE(kbuf.dptr); return True; @@ -343,6 +353,11 @@ static BOOL get_group_map_from_ntname(const char *name, GROUP_MAP *map) &map->gid, &map->sid_name_use, &map->nt_name, &map->comment); SAFE_FREE(dbuf.dptr); + + if ( ret == -1 ) { + DEBUG(3,("get_group_map_from_ntname: tdb_unpack failure\n")); + return False; + } if (StrCaseCmp(name, map->nt_name)==0) { SAFE_FREE(kbuf.dptr); @@ -429,6 +444,11 @@ static BOOL enum_group_mapping(enum SID_NAME_USE sid_name_use, GROUP_MAP **rmap, SAFE_FREE(dbuf.dptr); + if ( ret == -1 ) { + DEBUG(3,("enum_group_mapping: tdb_unpack failure\n")); + continue; + } + /* list only the type or everything if UNKNOWN */ if (sid_name_use!=SID_NAME_UNKNOWN && sid_name_use!=map.sid_name_use) { DEBUG(11,("enum_group_mapping: group %s is not of the requested type\n", map.nt_name)); @@ -510,8 +530,9 @@ BOOL get_domain_group_from_sid(DOM_SID sid, GROUP_MAP *map) } DEBUG(10, ("get_domain_group_from_sid: SID is mapped to gid:%lu\n",(unsigned long)map->gid)); - - if ( (grp=getgrgid(map->gid)) == NULL) { + + grp = getgrgid(map->gid); + if ( !grp ) { DEBUG(10, ("get_domain_group_from_sid: gid DOESN'T exist in UNIX security\n")); return False; } @@ -553,9 +574,12 @@ BOOL get_local_group_from_sid(DOM_SID sid, GROUP_MAP *map) sid_peek_rid(&sid, &alias_rid); map->gid=pdb_group_rid_to_gid(alias_rid); - - if ((grp=getgrgid(map->gid)) == NULL) + + grp = getgrgid(map->gid); + if ( !grp ) { + DEBUG(3,("get_local_group_from_sid: No unix group for [%ul]\n", map->gid)); return False; + } map->sid_name_use=SID_NAME_ALIAS; diff --git a/source3/include/.cvsignore b/source3/include/.cvsignore index bff248727f..7dff121f14 100644 --- a/source3/include/.cvsignore +++ b/source3/include/.cvsignore @@ -4,3 +4,4 @@ stamp-h proto.h wrepld_proto.h config.h.in +version.h diff --git a/source3/include/ads.h b/source3/include/ads.h index 0961c9581c..b85ad21fba 100644 --- a/source3/include/ads.h +++ b/source3/include/ads.h @@ -218,6 +218,6 @@ typedef void **ADS_MODLIST; /* The older versions of heimdal that don't have this define don't seem to use it anyway. I'm told they always use a subkey */ -#ifndef AP_OPTS_USE_SUBKEY +#ifndef HAVE_AP_OPTS_USE_SUBKEY #define AP_OPTS_USE_SUBKEY 0 #endif diff --git a/source3/include/charset.h b/source3/include/charset.h index f999a9cf72..7a9b12ef55 100644 --- a/source3/include/charset.h +++ b/source3/include/charset.h @@ -38,3 +38,90 @@ struct charset_functions { struct charset_functions *prev, *next; }; +/* + * This is auxiliary struct used by source/script/gen-8-bit-gap.sh script + * during generation of an encoding table for charset module + * */ + +struct charset_gap_table { + uint16 start; + uint16 end; + int32 idx; +}; + +/* + * Define stub for charset module which implements 8-bit encoding with gaps. + * Encoding tables for such module should be produced from glibc's CHARMAPs + * using script source/script/gen-8bit-gap.sh + * CHARSETNAME is CAPITALIZED charset name + * + * */ +#define SMB_GENERATE_CHARSET_MODULE_8_BIT_GAP(CHARSETNAME) \ +static size_t CHARSETNAME ## _push(void *cd, char **inbuf, size_t *inbytesleft, \ + char **outbuf, size_t *outbytesleft) \ +{ \ + while (*inbytesleft >= 2 && *outbytesleft >= 1) { \ + int i; \ + int done = 0; \ + \ + uint16 ch = SVAL(*inbuf,0); \ + \ + for (i=0; from_idx[i].start != 0xffff; i++) { \ + if ((from_idx[i].start <= ch) && (from_idx[i].end >= ch)) { \ + ((unsigned char*)(*outbuf))[0] = from_ucs2[from_idx[i].idx+ch]; \ + (*inbytesleft) -= 2; \ + (*outbytesleft) -= 1; \ + (*inbuf) += 2; \ + (*outbuf) += 1; \ + done = 1; \ + break; \ + } \ + } \ + if (!done) { \ + errno = EINVAL; \ + return -1; \ + } \ + \ + } \ + \ + if (*inbytesleft == 1) { \ + errno = EINVAL; \ + return -1; \ + } \ + \ + if (*inbytesleft > 1) { \ + errno = E2BIG; \ + return -1; \ + } \ + \ + return 0; \ +} \ + \ +static size_t CHARSETNAME ## _pull(void *cd, char **inbuf, size_t *inbytesleft, \ + char **outbuf, size_t *outbytesleft) \ +{ \ + while (*inbytesleft >= 1 && *outbytesleft >= 2) { \ + *(uint16*)(*outbuf) = to_ucs2[((unsigned char*)(*inbuf))[0]]; \ + (*inbytesleft) -= 1; \ + (*outbytesleft) -= 2; \ + (*inbuf) += 1; \ + (*outbuf) += 2; \ + } \ + \ + if (*inbytesleft > 0) { \ + errno = E2BIG; \ + return -1; \ + } \ + \ + return 0; \ +} \ + \ +struct charset_functions CHARSETNAME ## _functions = \ + {#CHARSETNAME, CHARSETNAME ## _pull, CHARSETNAME ## _push}; \ + \ +NTSTATUS charset_ ## CHARSETNAME ## _init(void) \ +{ \ + return smb_register_charset(& CHARSETNAME ## _functions); \ +} \ + + diff --git a/source3/include/includes.h b/source3/include/includes.h index eb7f73b9d3..29bb53980f 100644 --- a/source3/include/includes.h +++ b/source3/include/includes.h @@ -437,6 +437,10 @@ #include #endif +#if HAVE_SYS_ATTRIBUTES_H +#include +#endif + #if HAVE_ATTR_XATTR_H #include #endif @@ -958,10 +962,6 @@ struct smb_ldap_privates; #define SYNC_DNS 1 #endif -#ifndef MAXPATHLEN -#define MAXPATHLEN 256 -#endif - #ifndef SEEK_SET #define SEEK_SET 0 #endif @@ -1278,7 +1278,7 @@ time_t timegm(struct tm *tm); #if defined(HAVE_KRB5) -#ifndef KRB5_SET_REAL_TIME +#ifndef HAVE_KRB5_SET_REAL_TIME krb5_error_code krb5_set_real_time(krb5_context context, int32_t seconds, int32_t microseconds); #endif diff --git a/source3/include/nameserv.h b/source3/include/nameserv.h index 14561cf44d..1e867d620b 100644 --- a/source3/include/nameserv.h +++ b/source3/include/nameserv.h @@ -176,124 +176,116 @@ enum name_source {LMHOSTS_NAME, REGISTER_NAME, SELF_NAME, DNS_NAME, enum node_type {B_NODE=0, P_NODE=1, M_NODE=2, NBDD_NODE=3}; enum packet_type {NMB_PACKET, DGRAM_PACKET}; -enum master_state -{ - MST_NONE, - MST_POTENTIAL, - MST_BACKUP, - MST_MSB, - MST_BROWSER, - MST_UNBECOMING_MASTER +enum master_state { + MST_NONE, + MST_POTENTIAL, + MST_BACKUP, + MST_MSB, + MST_BROWSER, + MST_UNBECOMING_MASTER }; -enum domain_state -{ - DOMAIN_NONE, - DOMAIN_WAIT, - DOMAIN_MST +enum domain_state { + DOMAIN_NONE, + DOMAIN_WAIT, + DOMAIN_MST }; -enum logon_state -{ - LOGON_NONE, - LOGON_WAIT, - LOGON_SRV +enum logon_state { + LOGON_NONE, + LOGON_WAIT, + LOGON_SRV }; struct subnet_record; -struct nmb_data -{ - uint16 nb_flags; /* Netbios flags. */ - int num_ips; /* Number of ip entries. */ - struct in_addr *ip; /* The ip list for this name. */ +struct nmb_data { + uint16 nb_flags; /* Netbios flags. */ + int num_ips; /* Number of ip entries. */ + struct in_addr *ip; /* The ip list for this name. */ - enum name_source source; /* Where the name came from. */ + enum name_source source; /* Where the name came from. */ - time_t death_time; /* The time the record must be removed (do not remove if 0). */ - time_t refresh_time; /* The time the record should be refreshed. */ + time_t death_time; /* The time the record must be removed (do not remove if 0). */ + time_t refresh_time; /* The time the record should be refreshed. */ - SMB_BIG_UINT id; /* unique id */ - struct in_addr wins_ip; /* the adress of the wins server this record comes from */ + SMB_BIG_UINT id; /* unique id */ + struct in_addr wins_ip; /* the adress of the wins server this record comes from */ - int wins_flags; /* similar to the netbios flags but different ! */ + int wins_flags; /* similar to the netbios flags but different ! */ }; /* This structure represents an entry in a local netbios name list. */ -struct name_record - { - ubi_trNode node[1]; - struct subnet_record *subnet; - struct nmb_name name; /* The netbios name. */ - struct nmb_data data; /* The netbios data. */ - }; +struct name_record { + ubi_trNode node[1]; + struct subnet_record *subnet; + struct nmb_name name; /* The netbios name. */ + struct nmb_data data; /* The netbios data. */ +}; /* Browser cache for synchronising browse lists. */ -struct browse_cache_record - { - ubi_dlNode node[1]; - pstring lmb_name; - pstring work_group; - struct in_addr ip; - time_t sync_time; - time_t death_time; /* The time the record must be removed. */ - }; +struct browse_cache_record { + ubi_dlNode node[1]; + nstring lmb_name; + nstring work_group; + struct in_addr ip; + time_t sync_time; + time_t death_time; /* The time the record must be removed. */ +}; /* This is used to hold the list of servers in my domain, and is contained within lists of domains. */ -struct server_record -{ - struct server_record *next; - struct server_record *prev; +struct server_record { + struct server_record *next; + struct server_record *prev; - struct subnet_record *subnet; + struct subnet_record *subnet; - struct server_info_struct serv; - time_t death_time; + struct server_info_struct serv; + time_t death_time; }; /* A workgroup structure. It contains a list of servers. */ -struct work_record -{ - struct work_record *next; - struct work_record *prev; +struct work_record { + struct work_record *next; + struct work_record *prev; - struct subnet_record *subnet; + struct subnet_record *subnet; - struct server_record *serverlist; + struct server_record *serverlist; - /* Stage of development from non-local-master up to local-master browser. */ - enum master_state mst_state; + /* Stage of development from non-local-master up to local-master browser. */ + enum master_state mst_state; - /* Stage of development from non-domain-master to domain-master browser. */ - enum domain_state dom_state; + /* Stage of development from non-domain-master to domain-master browser. */ + enum domain_state dom_state; - /* Stage of development from non-logon-server to logon server. */ - enum logon_state log_state; + /* Stage of development from non-logon-server to logon server. */ + enum logon_state log_state; - /* Work group info. */ - fstring work_group; - int token; /* Used when communicating with backup browsers. */ - fstring local_master_browser_name; /* Current local master browser. */ + /* Work group info. */ + nstring work_group; + int token; /* Used when communicating with backup browsers. */ + nstring local_master_browser_name; /* Current local master browser. */ - /* Announce info. */ - time_t lastannounce_time; - int announce_interval; - BOOL needannounce; + /* Announce info. */ + time_t lastannounce_time; + int announce_interval; + BOOL needannounce; - /* Timeout time for this workgroup. 0 means permanent. */ - time_t death_time; + /* Timeout time for this workgroup. 0 means permanent. */ + time_t death_time; - /* Election info */ - BOOL RunningElection; - BOOL needelection; - int ElectionCount; - uint32 ElectionCriterion; + /* Election info */ + BOOL RunningElection; + BOOL needelection; + int ElectionCount; + uint32 ElectionCriterion; - /* Domain master browser info. Used for efficient syncs. */ - struct nmb_name dmb_name; - struct in_addr dmb_addr; + /* Domain master browser info. Used for efficient syncs. */ + struct nmb_name dmb_name; + struct in_addr dmb_addr; }; /* typedefs needed to define copy & free functions for userdata. */ @@ -305,10 +297,10 @@ typedef void (*userdata_free_fn)(struct userdata_struct *); /* Structure to define any userdata passed around. */ struct userdata_struct { - userdata_copy_fn copy_fn; - userdata_free_fn free_fn; - unsigned int userdata_len; - char data[16]; /* 16 is to ensure alignment/padding on all systems */ + userdata_copy_fn copy_fn; + userdata_free_fn free_fn; + unsigned int userdata_len; + char data[16]; /* 16 is to ensure alignment/padding on all systems */ }; struct response_record; @@ -382,33 +374,32 @@ typedef void (*node_status_fail_function)( struct subnet_record *, /* Initiated name queries are recorded in this list to track any responses. */ -struct response_record -{ - struct response_record *next; - struct response_record *prev; +struct response_record { + struct response_record *next; + struct response_record *prev; - uint16 response_id; + uint16 response_id; - /* Callbacks for packets received or not. */ - response_function resp_fn; - timeout_response_function timeout_fn; + /* Callbacks for packets received or not. */ + response_function resp_fn; + timeout_response_function timeout_fn; - /* Callbacks for the request succeeding or not. */ - success_function success_fn; - fail_function fail_fn; + /* Callbacks for the request succeeding or not. */ + success_function success_fn; + fail_function fail_fn; - struct packet_struct *packet; + struct packet_struct *packet; - struct userdata_struct *userdata; + struct userdata_struct *userdata; - int num_msgs; + int num_msgs; - time_t repeat_time; - time_t repeat_interval; - int repeat_count; + time_t repeat_time; + time_t repeat_interval; + int repeat_count; - /* Recursion protection. */ - BOOL in_expiration_processing; + /* Recursion protection. */ + BOOL in_expiration_processing; }; /* A subnet structure. It contains a list of workgroups and netbios names. */ @@ -420,42 +411,41 @@ struct response_record */ enum subnet_type { - NORMAL_SUBNET = 0, /* Subnet listed in interfaces list. */ - UNICAST_SUBNET = 1, /* Subnet for unicast packets. */ - REMOTE_BROADCAST_SUBNET = 2, /* Subnet for remote broadcasts. */ - WINS_SERVER_SUBNET = 3 /* Only created if we are a WINS server. */ + NORMAL_SUBNET = 0, /* Subnet listed in interfaces list. */ + UNICAST_SUBNET = 1, /* Subnet for unicast packets. */ + REMOTE_BROADCAST_SUBNET = 2, /* Subnet for remote broadcasts. */ + WINS_SERVER_SUBNET = 3 /* Only created if we are a WINS server. */ }; -struct subnet_record -{ - struct subnet_record *next; - struct subnet_record *prev; +struct subnet_record { + struct subnet_record *next; + struct subnet_record *prev; - char *subnet_name; /* For Debug identification. */ - enum subnet_type type; /* To catagorize the subnet. */ + char *subnet_name; /* For Debug identification. */ + enum subnet_type type; /* To catagorize the subnet. */ - struct work_record *workgrouplist; /* List of workgroups. */ - ubi_trRoot namelist[1]; /* List of netbios names. */ - struct response_record *responselist; /* List of responses expected. */ + struct work_record *workgrouplist; /* List of workgroups. */ + ubi_trRoot namelist[1]; /* List of netbios names. */ + struct response_record *responselist; /* List of responses expected. */ - BOOL namelist_changed; - BOOL work_changed; + BOOL namelist_changed; + BOOL work_changed; - struct in_addr bcast_ip; - struct in_addr mask_ip; - struct in_addr myip; - int nmb_sock; /* socket to listen for unicast 137. */ - int dgram_sock; /* socket to listen for unicast 138. */ + struct in_addr bcast_ip; + struct in_addr mask_ip; + struct in_addr myip; + int nmb_sock; /* socket to listen for unicast 137. */ + int dgram_sock; /* socket to listen for unicast 138. */ }; /* A resource record. */ struct res_rec { - struct nmb_name rr_name; - int rr_type; - int rr_class; - int ttl; - int rdlength; - char rdata[MAX_DGRAM_SIZE]; + struct nmb_name rr_name; + int rr_type; + int rr_class; + int ttl; + int rdlength; + char rdata[MAX_DGRAM_SIZE]; }; /* Define these so we can pass info back to caller of name_query */ @@ -467,35 +457,34 @@ struct res_rec { #define NM_FLAGS_B 0x01 /* Broadcast */ /* An nmb packet. */ -struct nmb_packet -{ - struct { - int name_trn_id; - int opcode; - BOOL response; - struct { - BOOL bcast; - BOOL recursion_available; - BOOL recursion_desired; - BOOL trunc; - BOOL authoritative; - } nm_flags; - int rcode; - int qdcount; - int ancount; - int nscount; - int arcount; - } header; - - struct { - struct nmb_name question_name; - int question_type; - int question_class; - } question; - - struct res_rec *answers; - struct res_rec *nsrecs; - struct res_rec *additional; +struct nmb_packet { + struct { + int name_trn_id; + int opcode; + BOOL response; + struct { + BOOL bcast; + BOOL recursion_available; + BOOL recursion_desired; + BOOL trunc; + BOOL authoritative; + } nm_flags; + int rcode; + int qdcount; + int ancount; + int nscount; + int arcount; + } header; + + struct { + struct nmb_name question_name; + int question_type; + int question_class; + } question; + + struct res_rec *answers; + struct res_rec *nsrecs; + struct res_rec *additional; }; /* msg_type field options - from rfc1002. */ @@ -511,23 +500,23 @@ struct nmb_packet /* A datagram - this normally contains SMB data in the data[] array. */ struct dgram_packet { - struct { - int msg_type; - struct { - enum node_type node_type; - BOOL first; - BOOL more; - } flags; - int dgm_id; - struct in_addr source_ip; - int source_port; - int dgm_length; - int packet_offset; - } header; - struct nmb_name source_name; - struct nmb_name dest_name; - int datasize; - char data[MAX_DGRAM_SIZE]; + struct { + int msg_type; + struct { + enum node_type node_type; + BOOL first; + BOOL more; + } flags; + int dgm_id; + struct in_addr source_ip; + int source_port; + int dgm_length; + int packet_offset; + } header; + struct nmb_name source_name; + struct nmb_name dest_name; + int datasize; + char data[MAX_DGRAM_SIZE]; }; /* Define a structure used to queue packets. This will be a linked @@ -535,18 +524,18 @@ struct dgram_packet { struct packet_struct { - struct packet_struct *next; - struct packet_struct *prev; - BOOL locked; - struct in_addr ip; - int port; - int fd; - time_t timestamp; - enum packet_type packet_type; - union { - struct nmb_packet nmb; - struct dgram_packet dgram; - } packet; + struct packet_struct *next; + struct packet_struct *prev; + BOOL locked; + struct in_addr ip; + int port; + int fd; + time_t timestamp; + enum packet_type packet_type; + union { + struct nmb_packet nmb; + struct dgram_packet dgram; + } packet; }; /* NETLOGON opcodes */ diff --git a/source3/include/ntdomain.h b/source3/include/ntdomain.h index b6ab4fd0c5..ccbc190c59 100644 --- a/source3/include/ntdomain.h +++ b/source3/include/ntdomain.h @@ -165,10 +165,21 @@ struct dcinfo }; +typedef struct pipe_rpc_fns { + + struct pipe_rpc_fns *next, *prev; + + /* RPC function table associated with the current rpc_bind (associated by context) */ + + struct api_struct *cmds; + int n_cmds; + uint32 context_id; + +} PIPE_RPC_FNS; + /* * DCE/RPC-specific samba-internal-specific handling of data on * NamedPipes. - * */ typedef struct pipes_struct @@ -180,7 +191,12 @@ typedef struct pipes_struct fstring name; fstring pipe_srv_name; - + + /* linked list of rpc dispatch tables associated + with the open rpc contexts */ + + PIPE_RPC_FNS *contexts; + RPC_HDR hdr; /* Incoming RPC header. */ RPC_HDR_REQ hdr_req; /* Incoming request header. */ diff --git a/source3/include/ntioctl.h b/source3/include/ntioctl.h index 17791fde18..9814c88e5e 100644 --- a/source3/include/ntioctl.h +++ b/source3/include/ntioctl.h @@ -23,6 +23,8 @@ we only need the sparse flag */ +#ifndef _NTIOCTL_H +#define _NTIOCTL_H /* IOCTL information */ /* List of ioctl function codes that look to be of interest to remote clients like this. */ @@ -53,6 +55,8 @@ #define FSCTL_SIS_COPYFILE 0x00090100 #define FSCTL_SIS_LINK_FILES 0x0009C104 +#define FSCTL_GET_SHADOW_COPY_DATA 0x00144064 /* KJC -- Shadow Copy information */ + #if 0 #define FSCTL_SECURITY_ID_CHECK #define FSCTL_DISMOUNT_VOLUME @@ -66,3 +70,18 @@ #define IO_REPARSE_TAG_MOUNT_POINT 0xA0000003 #define IO_REPARSE_TAG_HSM 0xC0000004 #define IO_REPARSE_TAG_SIS 0x80000007 + + +/* For FSCTL_GET_SHADOW_COPY_DATA ...*/ +typedef char SHADOW_COPY_LABEL[25]; + +typedef struct shadow_copy_data { + TALLOC_CTX *mem_ctx; + /* Total number of shadow volumes currently mounted */ + uint32 num_volumes; + /* Concatenated list of labels */ + SHADOW_COPY_LABEL *labels; +} SHADOW_COPY_DATA; + + +#endif /* _NTIOCTL_H */ diff --git a/source3/include/ntlmssp.h b/source3/include/ntlmssp.h index 562e4853cc..f1b1bc25e4 100644 --- a/source3/include/ntlmssp.h +++ b/source3/include/ntlmssp.h @@ -100,6 +100,7 @@ typedef struct ntlmssp_client_state char *domain; char *workstation; char *password; + char *server_domain; const char *(*get_global_myname)(void); const char *(*get_domain)(void); diff --git a/source3/include/ntquotas.h b/source3/include/ntquotas.h index 1425e59bb8..dac1173770 100644 --- a/source3/include/ntquotas.h +++ b/source3/include/ntquotas.h @@ -72,7 +72,7 @@ typedef struct _SMB_NTQUOTA_STRUCT { SMB_BIG_UINT usedspace; SMB_BIG_UINT softlim; SMB_BIG_UINT hardlim; - enum SMB_QUOTA_TYPE qflags; + uint32 qflags; DOM_SID sid; } SMB_NTQUOTA_STRUCT; diff --git a/source3/include/rpc_dce.h b/source3/include/rpc_dce.h index dc82f45368..2e4a418bb7 100644 --- a/source3/include/rpc_dce.h +++ b/source3/include/rpc_dce.h @@ -78,8 +78,8 @@ enum netsec_direction #define AUTH_PIPE_NETSEC 0x0008 /* Maximum PDU fragment size. */ -#define MAX_PDU_FRAG_LEN 0x1630 -/* #define MAX_PDU_FRAG_LEN 0x10b8 this is what w2k sets */ +/* #define MAX_PDU_FRAG_LEN 0x1630 this is what wnt sets */ +#define MAX_PDU_FRAG_LEN 0x10b8 /* this is what w2k sets */ /* * Actual structure of a DCE UUID @@ -136,8 +136,8 @@ typedef struct rpc_hdr_info typedef struct rpc_hdr_req_info { uint32 alloc_hint; /* allocation hint - data size (bytes) minus header and tail. */ - uint16 context_id; /* 0 - presentation context identifier */ - uint16 opnum; /* opnum */ + uint16 context_id; /* presentation context identifier */ + uint16 opnum; /* opnum */ } RPC_HDR_REQ; diff --git a/source3/include/rpc_ds.h b/source3/include/rpc_ds.h index 7350fdba1f..e2622be532 100644 --- a/source3/include/rpc_ds.h +++ b/source3/include/rpc_ds.h @@ -27,6 +27,7 @@ /* Opcodes available on PIPE_LSARPC_DS */ #define DS_GETPRIMDOMINFO 0x00 +#define DS_NOP 0xFF /* no op -- placeholder */ /* Opcodes available on PIPE_NETLOGON */ @@ -35,11 +36,23 @@ /* macros for RPC's */ +/* DSROLE_PRIMARY_DOMAIN_INFO_BASIC */ + +/* flags */ + #define DSROLE_PRIMARY_DS_RUNNING 0x00000001 #define DSROLE_PRIMARY_DS_MIXED_MODE 0x00000002 #define DSROLE_UPGRADE_IN_PROGRESS 0x00000004 #define DSROLE_PRIMARY_DOMAIN_GUID_PRESENT 0x01000000 +/* machine role */ + +#define DSROLE_STANDALONE_SRV 2 +#define DSROLE_DOMAIN_MEMBER_SRV 3 +#define DSROLE_BDC 4 +#define DSROLE_PDC 5 + + typedef struct { uint16 machine_role; diff --git a/source3/include/rpc_lsa.h b/source3/include/rpc_lsa.h index 135fd76d6c..fa49d76c88 100644 --- a/source3/include/rpc_lsa.h +++ b/source3/include/rpc_lsa.h @@ -27,6 +27,12 @@ /* Opcodes available on PIPE_LSARPC */ +#if 0 /* UNIMPLEMENTED */ + +#define LSA_LOOKUPSIDS2 0x39 + +#endif + #define LSA_CLOSE 0x00 #define LSA_DELETE 0x01 #define LSA_ENUM_PRIVS 0x02 diff --git a/source3/include/rpc_samr.h b/source3/include/rpc_samr.h index 8ec274176a..4d9ad0b2e1 100644 --- a/source3/include/rpc_samr.h +++ b/source3/include/rpc_samr.h @@ -127,7 +127,7 @@ SamrTestPrivateFunctionsUser #define SAMR_UNKNOWN_2a 0x2a #define SAMR_UNKNOWN_2b 0x2b #define SAMR_GET_USRDOM_PWINFO 0x2c -#define SAMR_UNKNOWN_2D 0x2d +#define SAMR_REMOVE_USER_FOREIGN_DOMAIN 0x2d #define SAMR_UNKNOWN_2E 0x2e /* looks like an alias for SAMR_QUERY_DOMAIN_INFO */ #define SAMR_UNKNOWN_2f 0x2f #define SAMR_QUERY_DISPINFO3 0x30 /* Alias for SAMR_QUERY_DISPINFO @@ -1786,21 +1786,21 @@ typedef struct r_samr_chgpasswd_user_info } SAMR_R_CHGPASSWD_USER; -/* SAMR_Q_UNKNOWN_2D */ -typedef struct q_samr_unknown_2d_info +/* SAMR_Q_REMOVE_USER_FOREIGN_DOMAIN */ +typedef struct q_samr_remove_user_foreign_domain_info { POLICY_HND dom_pol; /* policy handle */ DOM_SID2 sid; /* SID */ -} SAMR_Q_UNKNOWN_2D; +} SAMR_Q_REMOVE_USER_FOREIGN_DOMAIN; -/* SAMR_R_UNKNOWN_2D - probably an open */ -typedef struct r_samr_unknown_2d_info +/* SAMR_R_REMOVE_USER_FOREIGN_DOMAIN */ +typedef struct r_samr_remove_user_foreign_domain_info { NTSTATUS status; /* return status */ -} SAMR_R_UNKNOWN_2D; +} SAMR_R_REMOVE_USER_FOREIGN_DOMAIN; diff --git a/source3/include/rpc_spoolss.h b/source3/include/rpc_spoolss.h index c2e3d92787..f96b4fa96a 100755 --- a/source3/include/rpc_spoolss.h +++ b/source3/include/rpc_spoolss.h @@ -1302,6 +1302,12 @@ typedef struct s_port_info_2 } PORT_INFO_2; +/* Port Type bits */ +#define PORT_TYPE_WRITE 0x0001 +#define PORT_TYPE_READ 0x0002 +#define PORT_TYPE_REDIRECTED 0x0004 +#define PORT_TYPE_NET_ATTACHED 0x0008 + typedef struct spool_q_enumports { uint32 name_ptr; diff --git a/source3/include/safe_string.h b/source3/include/safe_string.h index 6656f4f6bb..07578b2424 100644 --- a/source3/include/safe_string.h +++ b/source3/include/safe_string.h @@ -124,6 +124,7 @@ size_t __unsafe_string_function_usage_here_char__(void); #define pstrcat(d,s) safe_strcat((d), (s),sizeof(pstring)-1) #define fstrcpy(d,s) safe_strcpy((d),(s),sizeof(fstring)-1) #define fstrcat(d,s) safe_strcat((d),(s),sizeof(fstring)-1) +#define nstrcpy(d,s) safe_strcpy((d), (s),sizeof(nstring)-1) /* the addition of the DEVELOPER checks in safe_strcpy means we must * update a lot of code. To make this a little easier here are some diff --git a/source3/include/secrets.h b/source3/include/secrets.h index dacfef26ea..cb4fbd043a 100644 --- a/source3/include/secrets.h +++ b/source3/include/secrets.h @@ -77,5 +77,22 @@ typedef struct trustdom { DOM_SID sid; } TRUSTDOM; +/* + * Format of an OpenAFS keyfile + */ + +#define SECRETS_AFS_MAXKEYS 8 + +struct afs_key { + uint32 kvno; + char key[8]; +}; + +struct afs_keyfile { + uint32 nkeys; + struct afs_key entry[SECRETS_AFS_MAXKEYS]; +}; + +#define SECRETS_AFS_KEYFILE "SECRETS/AFS_KEYFILE" #endif /* _SECRETS_H */ diff --git a/source3/include/smb.h b/source3/include/smb.h index deeb61034d..8c6f47f23f 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -390,7 +390,9 @@ typedef struct files_struct SMB_OFF_T pos; SMB_BIG_UINT size; SMB_BIG_UINT initial_allocation_size; /* Faked up initial allocation on disk. */ + SMB_BIG_UINT position_information; mode_t mode; + uint16 file_pid; uint16 vuid; write_bmpx_struct *wbmpx_ptr; write_cache *wcp; @@ -1482,17 +1484,19 @@ struct cnotify_fns { #include "smb_macros.h" +typedef char nstring[16]; + /* A netbios name structure. */ struct nmb_name { - char name[17]; - char scope[64]; - unsigned int name_type; + nstring name; + char scope[64]; + unsigned int name_type; }; /* A netbios node status array element. */ struct node_status { - char name[16]; + nstring name; unsigned char type; unsigned char flags; }; diff --git a/source3/include/smb_macros.h b/source3/include/smb_macros.h index 21ccdf295c..178fd9c358 100644 --- a/source3/include/smb_macros.h +++ b/source3/include/smb_macros.h @@ -77,6 +77,12 @@ #define OPEN_CONN(conn) ((conn) && (conn)->open) #define IS_IPC(conn) ((conn) && (conn)->ipc) #define IS_PRINT(conn) ((conn) && (conn)->printer) +#define FSP_BELONGS_CONN(fsp,conn) do {\ + extern struct current_user current_user;\ + if (!((fsp) && (conn) && ((conn)==(fsp)->conn) && (current_user.vuid==(fsp)->vuid))) \ + return(ERROR_DOS(ERRDOS,ERRbadfid));\ + } while(0) + #define FNUM_OK(fsp,c) (OPEN_FSP(fsp) && (c)==(fsp)->conn && current_user.vuid==(fsp)->vuid) #define CHECK_FSP(fsp,conn) do {\ diff --git a/source3/include/spnego.h b/source3/include/spnego.h new file mode 100644 index 0000000000..b6492ee3c8 --- /dev/null +++ b/source3/include/spnego.h @@ -0,0 +1,65 @@ +/* + Unix SMB/CIFS implementation. + + RFC2478 Compliant SPNEGO implementation + + Copyright (C) Jim McDonough 2003 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef SAMBA_SPNEGO_H +#define SAMBA_SPNEGO_H + +#define SPNEGO_DELEG_FLAG 0x01 +#define SPNEGO_MUTUAL_FLAG 0x02 +#define SPNEGO_REPLAY_FLAG 0x04 +#define SPNEGO_SEQUENCE_FLAG 0x08 +#define SPNEGO_ANON_FLAG 0x10 +#define SPNEGO_CONF_FLAG 0x20 +#define SPNEGO_INTEG_FLAG 0x40 +#define SPNEGO_REQ_FLAG 0x80 + +#define SPNEGO_NEG_TOKEN_INIT 0 +#define SPNEGO_NEG_TOKEN_TARG 1 + +typedef enum _spnego_negResult { + SPNEGO_ACCEPT_COMPLETED = 0, + SPNEGO_ACCEPT_INCOMPLETE = 1, + SPNEGO_REJECT = 2 +} negResult_t; + +typedef struct spnego_negTokenInit { + const char **mechTypes; + int reqFlags; + DATA_BLOB mechToken; + DATA_BLOB mechListMIC; +} negTokenInit_t; + +typedef struct spnego_negTokenTarg { + uint8 negResult; + const char *supportedMech; + DATA_BLOB responseToken; + DATA_BLOB mechListMIC; +} negTokenTarg_t; + +typedef struct spnego_spnego { + int type; + negTokenInit_t negTokenInit; + negTokenTarg_t negTokenTarg; +} SPNEGO_DATA; + +#endif diff --git a/source3/include/trans2.h b/source3/include/trans2.h index eb5b1bc79f..168e647721 100644 --- a/source3/include/trans2.h +++ b/source3/include/trans2.h @@ -230,6 +230,8 @@ Byte offset Type name description #define SMB_FIND_FILE_FULL_DIRECTORY_INFO 0x102 #define SMB_FIND_FILE_NAMES_INFO 0x103 #define SMB_FIND_FILE_BOTH_DIRECTORY_INFO 0x104 +#define SMB_FIND_FILE_LEVEL_261 0x105 +#define SMB_FIND_FILE_LEVEL_262 0x106 #define SMB_SET_FILE_BASIC_INFO 0x101 #define SMB_SET_FILE_DISPOSITION_INFO 0x102 diff --git a/source3/include/version.h b/source3/include/version.h index 68bc140daf..51e8c408e6 100644 --- a/source3/include/version.h +++ b/source3/include/version.h @@ -1 +1,8 @@ -#define VERSION "3.0.0rc1" +/* Autogenerated by script/mkversion.sh */ +#define SAMBA_VERSION_MAJOR 3 +#define SAMBA_VERSION_MINOR 0 +#define SAMBA_VERSION_RELEASE 1 +#define SAMBA_VERSION_PRE_RELEASE 1 +#define SAMBA_VERSION_IS_CVS_SNAPSHOT 1 +#define SAMBA_VERSION_OFFICIAL_STRING "CVS 3.0.1pre1" +#define SAMBA_VERSION_STRING samba_version_string() diff --git a/source3/include/vfs.h b/source3/include/vfs.h index 452f4dc23b..dd489702aa 100644 --- a/source3/include/vfs.h +++ b/source3/include/vfs.h @@ -50,8 +50,8 @@ /* Changed to version 6 for the new module system, fixed cascading and quota functions. --metze */ /* Changed to version 7 to include the get_nt_acl info parameter. JRA. */ /* Changed to version 8 includes EA calls. JRA. */ - -#define SMB_VFS_INTERFACE_VERSION 8 +/* Changed to version 9 to include the get_shadow_data call. --metze */ +#define SMB_VFS_INTERFACE_VERSION 9 /* to bug old modules witch are trying to compile with the old functions */ @@ -91,6 +91,8 @@ typedef enum _vfs_op_type { SMB_VFS_OP_DISK_FREE, SMB_VFS_OP_GET_QUOTA, SMB_VFS_OP_SET_QUOTA, + SMB_VFS_OP_GET_SHADOW_COPY_DATA, + /* Directory operations */ @@ -196,6 +198,7 @@ struct vfs_ops { SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize); int (*get_quota)(struct vfs_handle_struct *handle, struct connection_struct *conn, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt); int (*set_quota)(struct vfs_handle_struct *handle, struct connection_struct *conn, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt); + int (*get_shadow_copy_data)(struct vfs_handle_struct *handle, struct files_struct *fsp, SHADOW_COPY_DATA *shadow_copy_data, BOOL labels); /* Directory operations */ @@ -293,6 +296,7 @@ struct vfs_ops { struct vfs_handle_struct *disk_free; struct vfs_handle_struct *get_quota; struct vfs_handle_struct *set_quota; + struct vfs_handle_struct *get_shadow_copy_data; /* Directory operations */ @@ -379,6 +383,7 @@ struct vfs_ops { struct vfs_handle_struct *setxattr; struct vfs_handle_struct *lsetxattr; struct vfs_handle_struct *fsetxattr; + } handles; }; diff --git a/source3/include/vfs_macros.h b/source3/include/vfs_macros.h index fdbc1516e3..c4f63c352e 100644 --- a/source3/include/vfs_macros.h +++ b/source3/include/vfs_macros.h @@ -33,6 +33,7 @@ #define SMB_VFS_DISK_FREE(conn, path, small_query, bsize, dfree ,dsize) ((conn)->vfs.ops.disk_free((conn)->vfs.handles.disk_free, (conn), (path), (small_query), (bsize), (dfree), (dsize))) #define SMB_VFS_GET_QUOTA(conn, qtype, id, qt) ((conn)->vfs.ops.get_quota((conn)->vfs.handles.get_quota, (conn), (qtype), (id), (qt))) #define SMB_VFS_SET_QUOTA(conn, qtype, id, qt) ((conn)->vfs.ops.set_quota((conn)->vfs.handles.set_quota, (conn), (qtype), (id), (qt))) +#define SMB_VFS_GET_SHADOW_COPY_DATA(fsp,shadow_copy_data,labels) ((fsp)->conn->vfs.ops.get_shadow_copy_data((fsp)->conn->vfs.handles.get_shadow_copy_data,(fsp),(shadow_copy_data),(labels))) /* Directory operations */ #define SMB_VFS_OPENDIR(conn, fname) ((conn)->vfs.ops.opendir((conn)->vfs.handles.opendir, (conn), (fname))) @@ -128,6 +129,7 @@ #define SMB_VFS_OPAQUE_DISK_FREE(conn, path, small_query, bsize, dfree ,dsize) ((conn)->vfs_opaque.ops.disk_free((conn)->vfs_opaque.handles.disk_free, (conn), (path), (small_query), (bsize), (dfree), (dsize))) #define SMB_VFS_OPAQUE_GET_QUOTA(conn, qtype, id, qt) ((conn)->vfs_opaque.ops.get_quota((conn)->vfs_opaque.handles.get_quota, (conn), (qtype), (id), (qt))) #define SMB_VFS_OPAQUE_SET_QUOTA(conn, qtype, id, qt) ((conn)->vfs_opaque.ops.set_quota((conn)->vfs_opaque.handles.set_quota, (conn), (qtype), (id), (qt))) +#define SMB_VFS_OPAQUE_GET_SHADOW_COPY_DATA(fsp,shadow_copy_data,labels) ((fsp)->conn->vfs_opaque.ops.get_shadow_copy_data((fsp)->conn->vfs_opaque.handles.get_shadow_copy_data,(fsp),(shadow_copy_data),(labels))) /* Directory operations */ #define SMB_VFS_OPAQUE_OPENDIR(conn, fname) ((conn)->vfs_opaque.ops.opendir((conn)->vfs_opaque.handles.opendir, (conn), (fname))) @@ -223,6 +225,7 @@ #define SMB_VFS_NEXT_DISK_FREE(handle, conn, path, small_query, bsize, dfree ,dsize) ((handle)->vfs_next.ops.disk_free((handle)->vfs_next.handles.disk_free, (conn), (path), (small_query), (bsize), (dfree), (dsize))) #define SMB_VFS_NEXT_GET_QUOTA(handle, conn, qtype, id, qt) ((handle)->vfs_next.ops.get_quota((handle)->vfs_next.handles.get_quota, (conn), (qtype), (id), (qt))) #define SMB_VFS_NEXT_SET_QUOTA(handle, conn, qtype, id, qt) ((handle)->vfs_next.ops.set_quota((handle)->vfs_next.handles.set_quota, (conn), (qtype), (id), (qt))) +#define SMB_VFS_NEXT_GET_SHADOW_COPY_DATA(handle, fsp, shadow_copy_data ,labels) ((handle)->vfs_next.ops.get_shadow_copy_data((handle)->vfs_next.handles.get_shadow_copy_data,(fsp),(shadow_copy_data),(labels))) /* Directory operations */ #define SMB_VFS_NEXT_OPENDIR(handle, conn, fname) ((handle)->vfs_next.ops.opendir((handle)->vfs_next.handles.opendir, (conn), (fname))) diff --git a/source3/intl/lang_tdb.c b/source3/intl/lang_tdb.c index 87ef4e39c7..f12b9b6f15 100644 --- a/source3/intl/lang_tdb.c +++ b/source3/intl/lang_tdb.c @@ -53,8 +53,8 @@ static BOOL load_msg(const char *msg_file) } if (msgid && strncmp(lines[i], "msgstr \"", 8) == 0) { msgstr = lines[i] + 8; - trim_string(msgid, NULL, "\""); - trim_string(msgstr, NULL, "\""); + trim_char(msgid, '\0', '\"'); + trim_char(msgstr, '\0', '\"'); if (*msgstr == 0) { msgstr = msgid; } diff --git a/source3/lib/access.c b/source3/lib/access.c index c30b3c33cc..a874c8b1e2 100644 --- a/source3/lib/access.c +++ b/source3/lib/access.c @@ -281,13 +281,12 @@ static BOOL only_ipaddrs_in_list(const char** list) } if (!is_ipaddress(*list)) { - char *p; /* * if we failed, make sure that it was not because the token * was a network/netmask pair. Only network/netmask pairs * have a '/' in them */ - if ((p=strchr_m(*list, '/')) == NULL) { + if ((strchr_m(*list, '/')) == NULL) { only_ip = False; DEBUG(3,("only_ipaddrs_in_list: list has non-ip address (%s)\n", *list)); break; diff --git a/source3/lib/afs.c b/source3/lib/afs.c new file mode 100644 index 0000000000..b96703e986 --- /dev/null +++ b/source3/lib/afs.c @@ -0,0 +1,248 @@ +/* + * Unix SMB/CIFS implementation. + * Generate AFS tickets + * Copyright (C) Volker Lendecke 2003 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "includes.h" + +#ifdef WITH_FAKE_KASERVER + +#include +#include +#include +#include +#include +#include + +_syscall5(int, afs_syscall, int, subcall, + char *, path, + int, cmd, + char *, cmarg, + int, follow); + +char *afs_cell(void) +{ + static char *cell = NULL; + + if (cell == NULL) { + cell = strdup(lp_realm()); + strlower_m(cell); + } + + return cell; +} + +struct ClearToken { + uint32 AuthHandle; + char HandShakeKey[8]; + uint32 ViceId; + uint32 BeginTimestamp; + uint32 EndTimestamp; +}; + +/* + Put an AFS token into the Kernel so that it can authenticate against + the AFS server. This assumes correct local uid settings. + + This is currently highly Linux and OpenAFS-specific. The correct API + call for this would be ktc_SetToken. But to do that we would have to + import a REALLY big bunch of libraries which I would currently like + to avoid. +*/ + +static BOOL afs_settoken(char *username, const struct ClearToken *ctok, + char *v4tkt_data, int v4tkt_length) +{ + int ret; + struct { + char *in, *out; + uint16 in_size, out_size; + } iob; + + char buf[1024]; + char *p = buf; + int tmp; + + memcpy(p, &v4tkt_length, sizeof(uint32)); + p += sizeof(uint32); + memcpy(p, v4tkt_data, v4tkt_length); + p += v4tkt_length; + + tmp = sizeof(struct ClearToken); + memcpy(p, &tmp, sizeof(uint32)); + p += sizeof(uint32); + memcpy(p, ctok, tmp); + p += tmp; + + tmp = 0; + + memcpy(p, &tmp, sizeof(uint32)); + p += sizeof(uint32); + + tmp = strlen(afs_cell()); + if (tmp >= MAXKTCREALMLEN) { + DEBUG(1, ("Realm too long\n")); + return False; + } + + strncpy(p, afs_cell(), tmp); + p += tmp; + *p = 0; + p +=1; + + iob.in = buf; + iob.in_size = PTR_DIFF(p,buf); + iob.out = buf; + iob.out_size = sizeof(buf); + +#if 0 + file_save("/tmp/ioctlbuf", iob.in, iob.in_size); +#endif + + ret = afs_syscall(AFSCALL_PIOCTL, 0, VIOCSETTOK, (char *)&iob, 0); + + DEBUG(10, ("afs VIOCSETTOK returned %d\n", ret)); + return (ret == 0); +} + +/* + This routine takes a radical approach completely defeating the + Kerberos idea of security and using AFS simply as an intelligent + file backend. Samba has persuaded itself somehow that the user is + actually correctly identified and then we create a ticket that the + AFS server hopefully accepts using its KeyFile that the admin has + kindly stored to our secrets.tdb. + + Thanks to the book "Network Security -- PRIVATE Communication in a + PUBLIC World" by Charlie Kaufman, Radia Perlman and Mike Speciner + Kerberos 4 tickets are not really hard to construct. + + For the comments "Alice" is the User to be auth'ed, and "Bob" is the + AFS server. */ + +BOOL afs_login(char *username) +{ + fstring ticket; + char *p = ticket; + uint32 len; + struct afs_key key; + + struct ClearToken ct; + + uint32 now; /* I assume time() returns 32 bit */ + + des_key_schedule key_schedule; + + DEBUG(10, ("Trying to log into AFS for user %s@%s\n", + username, afs_cell())); + + if (!secrets_init()) + return False; + + if (!secrets_fetch_afs_key(afs_cell(), &key)) { + DEBUG(5, ("Could not fetch AFS service key\n")); + return False; + } + + ct.AuthHandle = key.kvno; + + /* Build the ticket. This is going to be encrypted, so in our + way we fill in ct while we still have the unencrypted + form. */ + + p = ticket; + + /* The byte-order */ + *p = 1; + p += 1; + + /* "Alice", the client username */ + strncpy(p, username, sizeof(ticket)-PTR_DIFF(p,ticket)-1); + p += strlen(p)+1; + strncpy(p, "", sizeof(ticket)-PTR_DIFF(p,ticket)-1); + p += strlen(p)+1; + strncpy(p, afs_cell(), sizeof(ticket)-PTR_DIFF(p,ticket)-1); + p += strlen(p)+1; + + ct.ViceId = getuid(); + DEBUG(10, ("Creating Token for uid %d\n", ct.ViceId)); + + /* Alice's network layer address. At least Openafs-1.2.10 + ignores this, so we fill in a dummy value here. */ + SIVAL(p, 0, 0); + p += 4; + + /* We need to create a session key */ + generate_random_buffer(p, 8, False); + + /* Our client code needs the the key in the clear, it does not + know the server-key ... */ + memcpy(ct.HandShakeKey, p, 8); + + p += 8; + + /* Ticket lifetime. We fake everything here, so go as long as + possible. This is in 5-minute intervals, so 255 is 21 hours + and 15 minutes.*/ + *p = 255; + p += 1; + + /* Ticket creation time */ + now = time(NULL); + SIVAL(p, 0, now); + ct.BeginTimestamp = now; + + ct.EndTimestamp = now + (255*60*5); + if (((ct.EndTimestamp - ct.BeginTimestamp) & 1) == 1) { + ct.BeginTimestamp += 1; /* Lifetime must be even */ + } + p += 4; + + /* And here comes Bob's name and instance, in this case the + AFS server. */ + strncpy(p, "afs", sizeof(ticket)-PTR_DIFF(p,ticket)-1); + p += strlen(p)+1; + strncpy(p, "", sizeof(ticket)-PTR_DIFF(p,ticket)-1); + p += strlen(p)+1; + + /* And zero-pad to a multiple of 8 bytes */ + len = PTR_DIFF(p, ticket); + if (len & 7) { + uint32 extra_space = 8-(len & 7); + memset(p, 0, extra_space); + p+=extra_space; + } + len = PTR_DIFF(p, ticket); + + des_key_sched((const_des_cblock *)key.key, key_schedule); + des_pcbc_encrypt(ticket, ticket, + len, key_schedule, (C_Block *)key.key, 1); + + ZERO_STRUCT(key); + + return afs_settoken(username, &ct, ticket, len); +} + +#else + +BOOL afs_login(char *username) +{ + return True; +} + +#endif /* WITH_FAKE_KASERVER */ diff --git a/source3/lib/charcnv.c b/source3/lib/charcnv.c index ca5e378970..5f3cf64a68 100644 --- a/source3/lib/charcnv.c +++ b/source3/lib/charcnv.c @@ -40,7 +40,7 @@ static smb_iconv_t conv_handles[NUM_CHARSETS][NUM_CHARSETS]; - +static BOOL conv_silent; /* Should we do a debug if the conversion fails ? */ /** * Return the name of a charset to give to iconv(). @@ -141,21 +141,28 @@ void init_iconv(void) /* XXX: Does this really get called every time the dos * codepage changes? */ /* XXX: Is the did_reload test too strict? */ + conv_silent = True; init_doschar_table(); init_valid_table(); + conv_silent = False; } } /** * Convert string from one encoding to another, making error checking etc + * Slow path version - uses (slow) iconv. * * @param src pointer to source string (multibyte or singlebyte) * @param srclen length of the source string in bytes * @param dest pointer to destination string (multibyte or singlebyte) * @param destlen maximal length allowed for string * @returns the number of bytes occupied in the destination + * + * Ensure the srclen contains the terminating zero. + * **/ -size_t convert_string(charset_t from, charset_t to, + +static size_t convert_string_internal(charset_t from, charset_t to, void const *src, size_t srclen, void *dest, size_t destlen) { @@ -165,18 +172,14 @@ size_t convert_string(charset_t from, charset_t to, char* outbuf = (char*)dest; smb_iconv_t descriptor; - if (srclen == (size_t)-1) - srclen = strlen(src)+1; - lazy_initialize_conv(); descriptor = conv_handles[from][to]; if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) { - /* conversion not supported, use as is */ - size_t len = MIN(srclen,destlen); - memcpy(dest,src,len); - return len; + if (!conv_silent) + DEBUG(0,("convert_string_internal: Conversion not supported.\n")); + goto use_as_is; } i_len=srclen; @@ -187,67 +190,208 @@ size_t convert_string(charset_t from, charset_t to, switch(errno) { case EINVAL: reason="Incomplete multibyte sequence"; - break; + if (!conv_silent) + DEBUG(3,("convert_string_internal: Conversion error: %s(%s)\n",reason,inbuf)); + goto use_as_is; case E2BIG: reason="No more room"; - DEBUG(0, ("convert_string: Required %lu, available %lu\n", - (unsigned long)srclen, (unsigned long)destlen)); + if (!conv_silent) + DEBUG(3, ("convert_string_internal: Required %lu, available %lu\n", + (unsigned long)srclen, (unsigned long)destlen)); /* we are not sure we need srclen bytes, may be more, may be less. We only know we need more than destlen bytes ---simo */ break; case EILSEQ: - reason="Illegal multibyte sequence"; - break; + reason="Illegal multibyte sequence"; + if (!conv_silent) + DEBUG(3,("convert_string_internal: Conversion error: %s(%s)\n",reason,inbuf)); + goto use_as_is; + default: + if (!conv_silent) + DEBUG(0,("convert_string_internal: Conversion error: %s(%s)\n",reason,inbuf)); + break; } /* smb_panic(reason); */ } return destlen-o_len; + + use_as_is: + + /* conversion not supported, use as is */ + { + size_t len = MIN(srclen,destlen); + if (len) + memcpy(dest,src,len); + return len; + } +} + +/** + * Convert string from one encoding to another, making error checking etc + * Fast path version - handles ASCII first. + * + * @param src pointer to source string (multibyte or singlebyte) + * @param srclen length of the source string in bytes + * @param dest pointer to destination string (multibyte or singlebyte) + * @param destlen maximal length allowed for string + * @returns the number of bytes occupied in the destination + * + * Ensure the srclen contains the terminating zero. + * + * This function has been hand-tuned to provide a fast path. + * Don't change unless you really know what you are doing. JRA. + **/ + +size_t convert_string(charset_t from, charset_t to, + void const *src, size_t srclen, + void *dest, size_t destlen) +{ + if (srclen == 0) + return 0; + + if (from != CH_UCS2 && to != CH_UCS2) { + const unsigned char *p = (const unsigned char *)src; + unsigned char *q = (unsigned char *)dest; + unsigned char lastp; + size_t retval = 0; + + /* If all characters are ascii, fast path here. */ + while (srclen && destlen) { + if ((lastp = *p) <= 0x7f) { + *q++ = *p++; + if (srclen != (size_t)-1) { + srclen--; + } + destlen--; + retval++; + if (!lastp) + break; + } else { + if (srclen == (size_t)-1) { + srclen = strlen(p)+1; + } + return retval + convert_string_internal(from, to, p, srclen, q, destlen); + } + } + return retval; + } else if (from == CH_UCS2 && to != CH_UCS2) { + const unsigned char *p = (const unsigned char *)src; + unsigned char *q = (unsigned char *)dest; + size_t retval = 0; + unsigned char lastp; + + /* If all characters are ascii, fast path here. */ + while ((srclen >= 2) && destlen) { + if ((lastp = *p) <= 0x7f && p[1] == 0) { + *q++ = *p; + if (srclen != (size_t)-1) { + srclen -= 2; + } + p += 2; + destlen--; + retval++; + if (!lastp) + break; + } else { + if (srclen == (size_t)-1) { + srclen = strlen_w((const void *)p)+2; + } + return retval + convert_string_internal(from, to, p, srclen, q, destlen); + } + } + return retval; + } else if (from != CH_UCS2 && to == CH_UCS2) { + const unsigned char *p = (const unsigned char *)src; + unsigned char *q = (unsigned char *)dest; + size_t retval = 0; + unsigned char lastp; + + /* If all characters are ascii, fast path here. */ + while (srclen && (destlen >= 2)) { + if ((lastp = *p) <= 0x7F) { + *q++ = *p++; + *q++ = '\0'; + if (srclen != (size_t)-1) { + srclen--; + } + destlen -= 2; + retval += 2; + if (!lastp) + break; + } else { + if (srclen == (size_t)-1) { + srclen = strlen(p)+1; + } + return retval + convert_string_internal(from, to, p, srclen, q, destlen); + } + } + return retval; + } + return convert_string_internal(from, to, src, srclen, dest, destlen); } /** * Convert between character sets, allocating a new buffer for the result. * + * @param ctx TALLOC_CTX to use to allocate with. If NULL use malloc. * @param srclen length of source buffer. * @param dest always set at least to NULL * @note -1 is not accepted for srclen. * * @returns Size in bytes of the converted string; or -1 in case of error. + * + * Ensure the srclen contains the terminating zero. **/ -size_t convert_string_allocate(charset_t from, charset_t to, +size_t convert_string_allocate(TALLOC_CTX *ctx, charset_t from, charset_t to, void const *src, size_t srclen, void **dest) { - size_t i_len, o_len, destlen; + size_t i_len, o_len, destlen = MAX(srclen, 512); size_t retval; const char *inbuf = (const char *)src; - char *outbuf, *ob; + char *outbuf = NULL, *ob = NULL; smb_iconv_t descriptor; *dest = NULL; if (src == NULL || srclen == (size_t)-1) return (size_t)-1; + if (srclen == 0) + return 0; lazy_initialize_conv(); descriptor = conv_handles[from][to]; if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) { - /* conversion not supported, return -1*/ - DEBUG(3, ("convert_string_allocate: conversion not supported!\n")); - return -1; + if (!conv_silent) + DEBUG(0,("convert_string_allocate: Conversion not supported.\n")); + goto use_as_is; } - destlen = MAX(srclen, 512); - outbuf = NULL; convert: - destlen = destlen * 2; - ob = (char *)Realloc(outbuf, destlen); + if ((destlen*2) < destlen) { + /* wrapped ! abort. */ + if (!conv_silent) + DEBUG(0, ("convert_string_allocate: destlen wrapped !\n")); + if (!ctx) + SAFE_FREE(outbuf); + return (size_t)-1; + } else { + destlen = destlen * 2; + } + + if (ctx) + ob = (char *)talloc_realloc(ctx, ob, destlen); + else + ob = (char *)Realloc(ob, destlen); + if (!ob) { DEBUG(0, ("convert_string_allocate: realloc failed!\n")); - SAFE_FREE(outbuf); + if (!ctx) + SAFE_FREE(outbuf); return (size_t)-1; } else { outbuf = ob; @@ -262,27 +406,59 @@ convert: switch(errno) { case EINVAL: reason="Incomplete multibyte sequence"; - break; + if (!conv_silent) + DEBUG(3,("convert_string_allocate: Conversion error: %s(%s)\n",reason,inbuf)); + goto use_as_is; case E2BIG: goto convert; case EILSEQ: reason="Illegal multibyte sequence"; - break; + if (!conv_silent) + DEBUG(3,("convert_string_allocate: Conversion error: %s(%s)\n",reason,inbuf)); + goto use_as_is; } - DEBUG(0,("Conversion error: %s(%s)\n",reason,inbuf)); + if (!conv_silent) + DEBUG(0,("Conversion error: %s(%s)\n",reason,inbuf)); /* smb_panic(reason); */ return (size_t)-1; } destlen = destlen - o_len; - *dest = (char *)Realloc(ob,destlen); + if (ctx) + *dest = (char *)talloc_realloc(ctx,ob,destlen); + else + *dest = (char *)Realloc(ob,destlen); if (destlen && !*dest) { DEBUG(0, ("convert_string_allocate: out of memory!\n")); - SAFE_FREE(ob); + if (!ctx) + SAFE_FREE(ob); return (size_t)-1; } return destlen; + + use_as_is: + + /* conversion not supported, use as is */ + { + if (srclen && (destlen != srclen)) { + destlen = srclen; + if (ctx) + ob = (char *)talloc_realloc(ctx, ob, destlen); + else + ob = (char *)Realloc(ob, destlen); + if (!ob) { + DEBUG(0, ("convert_string_allocate: realloc failed!\n")); + if (!ctx) + SAFE_FREE(outbuf); + return (size_t)-1; + } + } + if (srclen && ob) + memcpy(ob,(const char *)src,srclen); + *dest = (char *)ob; + return srclen; + } } @@ -298,17 +474,12 @@ convert: static size_t convert_string_talloc(TALLOC_CTX *ctx, charset_t from, charset_t to, void const *src, size_t srclen, void **dest) { - void *alloced_string; size_t dest_len; - /* FIXME: Ridiculous to allocate two buffers and then copy the string! */ - *dest = NULL; - dest_len=convert_string_allocate(from, to, src, srclen, &alloced_string); + dest_len=convert_string_allocate(ctx, from, to, src, srclen, dest); if (dest_len == (size_t)-1) return (size_t)-1; - *dest = talloc_memdup(ctx, alloced_string, dest_len); - SAFE_FREE(alloced_string); if (*dest == NULL) return (size_t)-1; return dest_len; @@ -335,29 +506,49 @@ size_t unix_strupper(const char *src, size_t srclen, char *dest, size_t destlen) /** strdup() a unix string to upper case. + Max size is pstring. **/ char *strdup_upper(const char *s) { - size_t size; - smb_ucs2_t *buffer; - char *out_buffer; - - size = push_ucs2_allocate(&buffer, s); - if (size == -1) { - return NULL; + pstring out_buffer; + const unsigned char *p = (const unsigned char *)s; + unsigned char *q = (unsigned char *)out_buffer; + + /* this is quite a common operation, so we want it to be + fast. We optimise for the ascii case, knowing that all our + supported multi-byte character sets are ascii-compatible + (ie. they match for the first 128 chars) */ + + while (1) { + if (*p & 0x80) + break; + *q++ = toupper(*p); + if (!*p) + break; + p++; + if (p - ( const unsigned char *)s >= sizeof(pstring)) + break; } - strupper_w(buffer); - - size = pull_ucs2_allocate(&out_buffer, buffer); - SAFE_FREE(buffer); + if (*p) { + /* MB case. */ + size_t size; + wpstring buffer; + size = convert_string(CH_UNIX, CH_UCS2, s, -1, buffer, sizeof(buffer)); + if (size == -1) { + return NULL; + } - if (size == -1) { - return NULL; - } + strupper_w(buffer); - return out_buffer; + size = convert_string(CH_UCS2, CH_UNIX, buffer, sizeof(buffer), out_buffer, sizeof(out_buffer)); + if (size == -1) { + return NULL; + } + } + + return strdup(out_buffer); } size_t unix_strlower(const char *src, size_t srclen, char *dest, size_t destlen) @@ -365,7 +556,7 @@ size_t unix_strlower(const char *src, size_t srclen, char *dest, size_t destlen) size_t size; smb_ucs2_t *buffer; - size = convert_string_allocate(CH_UNIX, CH_UCS2, src, srclen, + size = convert_string_allocate(NULL, CH_UNIX, CH_UCS2, src, srclen, (void **) &buffer); if (size == -1) { smb_panic("failed to create UCS2 buffer"); @@ -459,6 +650,11 @@ size_t push_ascii_pstring(void *dest, const char *src) return push_ascii(dest, src, sizeof(pstring), STR_TERMINATE); } +size_t push_ascii_nstring(void *dest, const char *src) +{ + return push_ascii(dest, src, sizeof(nstring), STR_TERMINATE); +} + /** * Copy a string from a dos codepage source to a unix char* destination. * @@ -512,6 +708,11 @@ size_t pull_ascii_fstring(char *dest, const void *src) return pull_ascii(dest, src, sizeof(fstring), -1, STR_TERMINATE); } +size_t pull_ascii_nstring(char *dest, const void *src) +{ + return pull_ascii(dest, src, sizeof(nstring), sizeof(nstring), STR_TERMINATE); +} + /** * Copy a string from a char* src to a unicode destination. * @@ -528,22 +729,26 @@ size_t pull_ascii_fstring(char *dest, const void *src) * @param dest_len is the maximum length allowed in the * destination. If dest_len is -1 then no maxiumum is used. **/ + size_t push_ucs2(const void *base_ptr, void *dest, const char *src, size_t dest_len, int flags) { size_t len=0; - size_t src_len = strlen(src); + size_t src_len; /* treat a pstring as "unlimited" length */ if (dest_len == (size_t)-1) dest_len = sizeof(pstring); if (flags & STR_TERMINATE) - src_len++; + src_len = (size_t)-1; + else + src_len = strlen(src); if (ucs2_align(base_ptr, dest, flags)) { *(char *)dest = 0; dest = (void *)((char *)dest + 1); - if (dest_len) dest_len--; + if (dest_len) + dest_len--; len++; } @@ -599,7 +804,7 @@ size_t push_ucs2_allocate(smb_ucs2_t **dest, const char *src) size_t src_len = strlen(src)+1; *dest = NULL; - return convert_string_allocate(CH_UNIX, CH_UCS2, src, src_len, (void **)dest); + return convert_string_allocate(NULL, CH_UNIX, CH_UCS2, src, src_len, (void **)dest); } /** @@ -667,7 +872,7 @@ size_t push_utf8_allocate(char **dest, const char *src) size_t src_len = strlen(src)+1; *dest = NULL; - return convert_string_allocate(CH_UNIX, CH_UTF8, src, src_len, (void **)dest); + return convert_string_allocate(NULL, CH_UNIX, CH_UTF8, src, src_len, (void **)dest); } /** @@ -695,9 +900,8 @@ size_t pull_ucs2(const void *base_ptr, char *dest, const void *src, size_t dest_ } if (flags & STR_TERMINATE) { - if (src_len == (size_t)-1) { - src_len = strlen_w(src)*2 + 2; - } else { + /* src_len -1 is the default for null terminated strings. */ + if (src_len != (size_t)-1) { size_t len = strnlen_w(src, src_len/2); if (len < src_len/2) len++; @@ -755,7 +959,7 @@ size_t pull_ucs2_allocate(char **dest, const smb_ucs2_t *src) { size_t src_len = (strlen_w(src)+1) * sizeof(smb_ucs2_t); *dest = NULL; - return convert_string_allocate(CH_UCS2, CH_UNIX, src, src_len, (void **)dest); + return convert_string_allocate(NULL, CH_UCS2, CH_UNIX, src, src_len, (void **)dest); } /** @@ -785,7 +989,7 @@ size_t pull_utf8_allocate(void **dest, const char *src) { size_t src_len = strlen(src)+1; *dest = NULL; - return convert_string_allocate(CH_UTF8, CH_UNIX, src, src_len, dest); + return convert_string_allocate(NULL, CH_UTF8, CH_UNIX, src, src_len, dest); } /** @@ -845,8 +1049,10 @@ size_t push_string_fn(const char *function, unsigned int line, const void *base_ size_t pull_string_fn(const char *function, unsigned int line, const void *base_ptr, char *dest, const void *src, size_t dest_len, size_t src_len, int flags) { +#ifdef DEVELOPER if (dest_len != (size_t)-1) clobber_region(function, line, dest, dest_len); +#endif if (!(flags & STR_ASCII) && \ ((flags & STR_UNICODE || \ @@ -865,4 +1071,3 @@ size_t align_string(const void *base_ptr, const char *p, int flags) } return 0; } - diff --git a/source3/lib/dummyroot.c b/source3/lib/dummyroot.c new file mode 100644 index 0000000000..c8465cb791 --- /dev/null +++ b/source3/lib/dummyroot.c @@ -0,0 +1,33 @@ +/* + Unix SMB/CIFS implementation. + RPC pipe client + + Copyright (C) Tim Potter 2003 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* Stupid dummy functions required due to the horrible dependency mess + in Samba. */ + +void become_root(void) +{ + return; +} + +void unbecome_root(void) +{ + return; +} diff --git a/source3/lib/fault.c b/source3/lib/fault.c index a9e1b7bbb9..df7830ef83 100644 --- a/source3/lib/fault.c +++ b/source3/lib/fault.c @@ -34,7 +34,7 @@ static void fault_report(int sig) counter++; DEBUG(0,("===============================================================\n")); - DEBUG(0,("INTERNAL ERROR: Signal %d in pid %d (%s)",sig,(int)sys_getpid(),VERSION)); + DEBUG(0,("INTERNAL ERROR: Signal %d in pid %d (%s)",sig,(int)sys_getpid(),SAMBA_VERSION_STRING)); DEBUG(0,("\nPlease read the appendix Bugs of the Samba HOWTO collection\n")); DEBUG(0,("===============================================================\n")); diff --git a/source3/lib/gencache.c b/source3/lib/gencache.c index f3740e3e12..da8808af16 100644 --- a/source3/lib/gencache.c +++ b/source3/lib/gencache.c @@ -121,10 +121,11 @@ BOOL gencache_set(const char *keystr, const char *value, time_t timeout) keybuf.dsize = strlen(keystr)+1; databuf.dptr = strdup(valstr); databuf.dsize = strlen(valstr)+1; - DEBUG(10, ("Adding cache entry with key = %s; value = %s and timeout \ - = %s (%d seconds %s)\n", keybuf.dptr, value, ctime(&timeout), - (int)(timeout - time(NULL)), timeout > time(NULL) ? "ahead" : "in the past")); - + DEBUG(10, ("Adding cache entry with key = %s; value = %s and timeout =" + " %s (%d seconds %s)\n", keybuf.dptr, value,ctime(&timeout), + (int)(timeout - time(NULL)), + timeout > time(NULL) ? "ahead" : "in the past")); + ret = tdb_store(cache, keybuf, databuf, 0); SAFE_FREE(valstr); SAFE_FREE(keybuf.dptr); diff --git a/source3/lib/hash.c b/source3/lib/hash.c index c7b1493b4c..18b6534dec 100644 --- a/source3/lib/hash.c +++ b/source3/lib/hash.c @@ -84,21 +84,20 @@ BOOL hash_table_init(hash_table *table, unsigned num_buckets, compare_function c * For the last few chars that cannot be int'ed, use char instead. * The function returns the bucket index number for the hashed * key. + * JRA. Use a djb-algorithm hash for speed. ************************************************************** */ static int string_hash(int hash_size, const char *key) { - u32 value; /* Used to compute the hash value. */ - u32 i; /* Used to cycle through random values. */ - - for (value = 0x238F13AF, i=0; key[i]; i++) - value = (value + (key[i] << (i*5 % 24))); - - return (1103515243 * value + 12345) % hash_size; + u32 n = 0; + const char *p; + for (p = key; *p != '\0'; p++) { + n = ((n << 5) + n) ^ (u32)(*p); + } + return (n % hash_size); } - /* ************************************************************************* * Search the hash table for the entry in the hash chain. * The function returns the pointer to the diff --git a/source3/lib/module.c b/source3/lib/module.c index ac4fe57a2c..e2c6f6dcf5 100644 --- a/source3/lib/module.c +++ b/source3/lib/module.c @@ -23,7 +23,11 @@ #include "includes.h" #ifdef HAVE_DLOPEN -NTSTATUS smb_load_module(const char *module_name) + +/* Load a dynamic module. Only log a level 0 error if we are not checking + for the existence of a module (probling). */ + +static NTSTATUS do_smb_load_module(const char *module_name, BOOL is_probe) { void *handle; init_module_function *init; @@ -37,17 +41,21 @@ NTSTATUS smb_load_module(const char *module_name) handle = sys_dlopen(module_name, RTLD_LAZY); if(!handle) { - DEBUG(0, ("Error loading module '%s': %s\n", module_name, sys_dlerror())); + int level = is_probe ? 2 : 0; + DEBUG(level, ("Error loading module '%s': %s\n", module_name, + sys_dlerror())); + return NT_STATUS_UNSUCCESSFUL; } - init = sys_dlsym(handle, "init_module"); + init = (init_module_function *)sys_dlsym(handle, "init_module"); /* we must check sys_dlerror() to determine if it worked, because sys_dlsym() can validly return NULL */ error = sys_dlerror(); if (error) { - DEBUG(0, ("Error trying to resolve symbol 'init_module' in %s: %s\n", module_name, error)); + DEBUG(0, ("Error trying to resolve symbol 'init_module' in %s: %s\n", + module_name, error)); return NT_STATUS_UNSUCCESSFUL; } @@ -58,6 +66,11 @@ NTSTATUS smb_load_module(const char *module_name) return status; } +NTSTATUS smb_load_module(const char *module_name) +{ + return do_smb_load_module(module_name, False); +} + /* Load all modules in list and return number of * modules that has been successfully loaded */ int smb_load_modules(const char **modules) @@ -85,8 +98,11 @@ NTSTATUS smb_probe_module(const char *subsystem, const char *module) /* if we make any 'samba multibyte string' calls here, we break for loading string modules */ + + DEBUG(5, ("Probing module '%s'\n", module)); + if (module[0] == '/') - return smb_load_module(module); + return do_smb_load_module(module, True); pstrcpy(full_path, lib_path(subsystem)); pstrcat(full_path, "/"); @@ -94,9 +110,9 @@ NTSTATUS smb_probe_module(const char *subsystem, const char *module) pstrcat(full_path, "."); pstrcat(full_path, shlib_ext()); - DEBUG(5, ("Probing module %s: Trying to load from %s\n", module, full_path)); + DEBUG(5, ("Probing module '%s': Trying to load from %s\n", module, full_path)); - return smb_load_module(full_path); + return do_smb_load_module(full_path, True); } #else /* HAVE_DLOPEN */ diff --git a/source3/lib/ms_fnmatch.c b/source3/lib/ms_fnmatch.c index 106efa5bbc..24232c3b52 100644 --- a/source3/lib/ms_fnmatch.c +++ b/source3/lib/ms_fnmatch.c @@ -35,7 +35,8 @@ of the protocol. This is not yet perfect, but its a lot better than what we had */ static int ms_fnmatch_lanman_core(const smb_ucs2_t *pattern, - const smb_ucs2_t *string) + const smb_ucs2_t *string, + BOOL case_sensitive) { const smb_ucs2_t *p = pattern, *n = string; smb_ucs2_t c; @@ -61,8 +62,8 @@ static int ms_fnmatch_lanman_core(const smb_ucs2_t *pattern, case UCS2_CHAR('>'): if (! *n) goto next; if (n[0] == UCS2_CHAR('.')) { - if (! n[1] && ms_fnmatch_lanman_core(p, n+1) == 0) goto match; - if (ms_fnmatch_lanman_core(p, n) == 0) goto match; + if (! n[1] && ms_fnmatch_lanman_core(p, n+1, case_sensitive) == 0) goto match; + if (ms_fnmatch_lanman_core(p, n, case_sensitive) == 0) goto match; goto nomatch; } n++; @@ -72,13 +73,13 @@ static int ms_fnmatch_lanman_core(const smb_ucs2_t *pattern, if (! *n) goto next; if (! *p) goto match; for (; *n; n++) { - if (ms_fnmatch_lanman_core(p, n) == 0) goto match; + if (ms_fnmatch_lanman_core(p, n, case_sensitive) == 0) goto match; } break; case UCS2_CHAR('<'): for (; *n; n++) { - if (ms_fnmatch_lanman_core(p, n) == 0) goto match; + if (ms_fnmatch_lanman_core(p, n, case_sensitive) == 0) goto match; if (*n == UCS2_CHAR('.') && !strchr_w(n+1,UCS2_CHAR('.'))) { n++; @@ -88,13 +89,17 @@ static int ms_fnmatch_lanman_core(const smb_ucs2_t *pattern, break; case UCS2_CHAR('"'): - if (*n == 0 && ms_fnmatch_lanman_core(p, n) == 0) goto match; + if (*n == 0 && ms_fnmatch_lanman_core(p, n, case_sensitive) == 0) goto match; if (*n != UCS2_CHAR('.')) goto nomatch; n++; break; default: - if (c != *n) goto nomatch; + if (case_sensitive) { + if (c != *n) goto nomatch; + } else { + if (tolower_w(c) != tolower_w(*n)) goto nomatch; + } n++; } } @@ -108,7 +113,7 @@ static int ms_fnmatch_lanman_core(const smb_ucs2_t *pattern, return -1; next: - if (ms_fnmatch_lanman_core(p, n) == 0) goto match; + if (ms_fnmatch_lanman_core(p, n, case_sensitive) == 0) goto match; goto nomatch; match: @@ -118,7 +123,8 @@ next: return 0; } -static int ms_fnmatch_lanman1(const smb_ucs2_t *pattern, const smb_ucs2_t *string) +static int ms_fnmatch_lanman1(const smb_ucs2_t *pattern, + const smb_ucs2_t *string, BOOL case_sensitive) { if (!strpbrk_wa(pattern, "?*<>\"")) { smb_ucs2_t s[] = {UCS2_CHAR('.'), 0}; @@ -129,11 +135,11 @@ static int ms_fnmatch_lanman1(const smb_ucs2_t *pattern, const smb_ucs2_t *strin if (strcmp_wa(string,"..") == 0 || strcmp_wa(string,".") == 0) { smb_ucs2_t dot[] = {UCS2_CHAR('.'), 0}; smb_ucs2_t dotdot[] = {UCS2_CHAR('.'), UCS2_CHAR('.'), 0}; - return ms_fnmatch_lanman_core(pattern, dotdot) && - ms_fnmatch_lanman_core(pattern, dot); + return ms_fnmatch_lanman_core(pattern, dotdot, case_sensitive) && + ms_fnmatch_lanman_core(pattern, dot, case_sensitive); } - return ms_fnmatch_lanman_core(pattern, string); + return ms_fnmatch_lanman_core(pattern, string, case_sensitive); } @@ -145,13 +151,14 @@ static int ms_fnmatch_lanman1(const smb_ucs2_t *pattern, const smb_ucs2_t *strin Returns 0 on match, -1 on fail. */ -static int ms_fnmatch_w(const smb_ucs2_t *pattern, const smb_ucs2_t *string, int protocol) +static int ms_fnmatch_w(const smb_ucs2_t *pattern, const smb_ucs2_t *string, + int protocol, BOOL case_sensitive) { const smb_ucs2_t *p = pattern, *n = string; smb_ucs2_t c; if (protocol <= PROTOCOL_LANMAN2) { - return ms_fnmatch_lanman1(pattern, string); + return ms_fnmatch_lanman1(pattern, string, case_sensitive); } while ((c = *p++)) { @@ -163,23 +170,23 @@ static int ms_fnmatch_w(const smb_ucs2_t *pattern, const smb_ucs2_t *string, int case UCS2_CHAR('>'): if (n[0] == UCS2_CHAR('.')) { - if (! n[1] && ms_fnmatch_w(p, n+1, protocol) == 0) return 0; - if (ms_fnmatch_w(p, n, protocol) == 0) return 0; + if (! n[1] && ms_fnmatch_w(p, n+1, protocol, case_sensitive) == 0) return 0; + if (ms_fnmatch_w(p, n, protocol, case_sensitive) == 0) return 0; return -1; } - if (! *n) return ms_fnmatch_w(p, n, protocol); + if (! *n) return ms_fnmatch_w(p, n, protocol, case_sensitive); n++; break; case UCS2_CHAR('*'): for (; *n; n++) { - if (ms_fnmatch_w(p, n, protocol) == 0) return 0; + if (ms_fnmatch_w(p, n, protocol, case_sensitive) == 0) return 0; } break; case UCS2_CHAR('<'): for (; *n; n++) { - if (ms_fnmatch_w(p, n, protocol) == 0) return 0; + if (ms_fnmatch_w(p, n, protocol, case_sensitive) == 0) return 0; if (*n == UCS2_CHAR('.') && !strchr_wa(n+1,'.')) { n++; break; @@ -188,13 +195,17 @@ static int ms_fnmatch_w(const smb_ucs2_t *pattern, const smb_ucs2_t *string, int break; case UCS2_CHAR('"'): - if (*n == 0 && ms_fnmatch_w(p, n, protocol) == 0) return 0; + if (*n == 0 && ms_fnmatch_w(p, n, protocol, case_sensitive) == 0) return 0; if (*n != UCS2_CHAR('.')) return -1; n++; break; default: - if (c != *n) return -1; + if (case_sensitive) { + if (c != *n) return -1; + } else { + if (tolower_w(c) != tolower_w(*n)) return -1; + } n++; } } @@ -204,22 +215,35 @@ static int ms_fnmatch_w(const smb_ucs2_t *pattern, const smb_ucs2_t *string, int return -1; } - -int ms_fnmatch(const char *pattern, const char *string, int protocol) +int ms_fnmatch(const char *pattern, const char *string, int protocol, + BOOL case_senstive) { - wpstring p, s; + wpstring buffer_pattern, buffer_string; int ret; + size_t size; + + size = push_ucs2(NULL, buffer_pattern, pattern, sizeof(buffer_pattern), STR_TERMINATE); + if (size == (size_t)-1) { + return -1; + /* Not quite the right answer, but finding the right one + under this failure case is expensive, and it's pretty close */ + } + + size = push_ucs2(NULL, buffer_string, string, sizeof(buffer_string), STR_TERMINATE); + if (size == (size_t)-1) { + return -1; + /* Not quite the right answer, but finding the right one + under this failure case is expensive, and it's pretty close */ + } - pstrcpy_wa(p, pattern); - pstrcpy_wa(s, string); + ret = ms_fnmatch_w(buffer_pattern, buffer_string, protocol, case_senstive); + DEBUG(10,("ms_fnmatch(%s,%s) -> %d\n", pattern, string, ret)); - ret = ms_fnmatch_w(p, s, protocol); -/* DEBUG(0,("ms_fnmatch(%s,%s) -> %d\n", pattern, string, ret)); */ return ret; } /* a generic fnmatch function - uses for non-CIFS pattern matching */ int gen_fnmatch(const char *pattern, const char *string) { - return ms_fnmatch(pattern, string, PROTOCOL_NT1); + return ms_fnmatch(pattern, string, PROTOCOL_NT1, True); } diff --git a/source3/lib/popt_common.c b/source3/lib/popt_common.c index af1cbcfe80..9a5a112022 100644 --- a/source3/lib/popt_common.c +++ b/source3/lib/popt_common.c @@ -69,7 +69,7 @@ static void popt_common_callback(poptContext con, break; case 'V': - printf( "Version %s\n", VERSION ); + printf( "Version %s\n", SAMBA_VERSION_STRING); exit(0); break; @@ -119,6 +119,7 @@ struct poptOption popt_common_connection[] = { { "netbiosname", 'n', POPT_ARG_STRING, NULL, 'n', "Primary netbios name", "NETBIOSNAME" }, { "workgroup", 'W', POPT_ARG_STRING, NULL, 'W', "Set the workgroup name", "WORKGROUP" }, { "scope", 'i', POPT_ARG_STRING, NULL, 'i', "Use this Netbios scope", "SCOPE" }, + POPT_TABLEEND }; @@ -259,6 +260,7 @@ static void get_credentials_file(const char *file, struct user_auth_info *info) * -k,--use-kerberos * -N,--no-pass * -S,--signing + * -P --machine-pass */ @@ -335,7 +337,8 @@ static void popt_common_credentials_callback(poptContext con, cmdline_auth_info.signing_state = -1; if (strequal(arg, "off") || strequal(arg, "no") || strequal(arg, "false")) cmdline_auth_info.signing_state = False; - else if (strequal(arg, "on") || strequal(arg, "yes") || strequal(arg, "true")) + else if (strequal(arg, "on") || strequal(arg, "yes") || strequal(arg, "true") || + strequal(arg, "auto") ) cmdline_auth_info.signing_state = True; else if (strequal(arg, "force") || strequal(arg, "required") || strequal(arg, "forced")) cmdline_auth_info.signing_state = Required; @@ -345,6 +348,33 @@ static void popt_common_credentials_callback(poptContext con, } } break; + case 'P': + { + char *opt_password = NULL; + /* it is very useful to be able to make ads queries as the + machine account for testing purposes and for domain leave */ + + if (!secrets_init()) { + d_printf("ERROR: Unable to open secrets database\n"); + exit(1); + } + + opt_password = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL); + + if (!opt_password) { + d_printf("ERROR: Unable to fetch machine password\n"); + exit(1); + } + pstr_sprintf(cmdline_auth_info.username, "%s$", + global_myname()); + pstrcpy(cmdline_auth_info.password,opt_password); + SAFE_FREE(opt_password); + + /* machine accounts only work with kerberos */ + cmdline_auth_info.use_kerberos = True; + cmdline_auth_info.got_pass = True; + } + break; } } @@ -357,5 +387,6 @@ struct poptOption popt_common_credentials[] = { { "kerberos", 'k', POPT_ARG_NONE, &cmdline_auth_info.use_kerberos, 'k', "Use kerberos (active directory) authentication" }, { "authentication-file", 'A', POPT_ARG_STRING, NULL, 'A', "Get the credentials from a file", "FILE" }, { "signing", 'S', POPT_ARG_STRING, NULL, 'S', "Set the client signing state", "on|off|required" }, + {"machine-pass", 'P', POPT_ARG_NONE, NULL, 'P', "Use stored machine account password" }, POPT_TABLEEND }; diff --git a/source3/lib/readline.c b/source3/lib/readline.c index ceb02ef749..78b99fd7fb 100644 --- a/source3/lib/readline.c +++ b/source3/lib/readline.c @@ -51,7 +51,7 @@ ****************************************************************************/ static char *smb_readline_replacement(char *prompt, void (*callback)(void), - char **(completion_fn)(char *text, int start, int end)) + char **(completion_fn)(const char *text, int start, int end)) { fd_set fds; static pstring line; @@ -83,7 +83,7 @@ static char *smb_readline_replacement(char *prompt, void (*callback)(void), ****************************************************************************/ char *smb_readline(char *prompt, void (*callback)(void), - char **(completion_fn)(char *text, int start, int end)) + char **(completion_fn)(const char *text, int start, int end)) { #if HAVE_LIBREADLINE if (isatty(x_fileno(x_stdin))) { diff --git a/source3/lib/replace1.c b/source3/lib/replace1.c new file mode 100644 index 0000000000..e1be56eb12 --- /dev/null +++ b/source3/lib/replace1.c @@ -0,0 +1,42 @@ +/* + Unix SMB/CIFS implementation. + replacement routines for broken systems + Copyright (C) Andrew Tridgell 1992-1998 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + + void replace1_dummy(void); + void replace1_dummy(void) {} + +#ifndef HAVE_SETENV + int setenv(const char *name, const char *value, int overwrite) +{ + char *p = NULL; + int ret = -1; + + asprintf(&p, "%s=%s", name, value); + + if (overwrite || getenv(name)) { + if (p) ret = putenv(p); + } else { + ret = 0; + } + + return ret; +} +#endif diff --git a/source3/lib/smbldap.c b/source3/lib/smbldap.c index 3f56d066ec..1ce03491da 100644 --- a/source3/lib/smbldap.c +++ b/source3/lib/smbldap.c @@ -1172,6 +1172,9 @@ static NTSTATUS add_new_domain_info(struct smbldap_state *ldap_state, LDAPMessage *result = NULL; int num_result; char **attr_list; + uid_t u_low, u_high; + gid_t g_low, g_high; + uint32 rid_low, rid_high; slprintf (filter, sizeof (filter) - 1, "(&(%s=%s)(objectclass=%s))", get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN), @@ -1217,6 +1220,30 @@ static NTSTATUS add_new_domain_info(struct smbldap_state *ldap_state, smbldap_set_mod(&mods, LDAP_MOD_ADD, get_attr_key2string(dominfo_attr_list, LDAP_ATTR_ALGORITHMIC_RID_BASE), algorithmic_rid_base_string); smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_DOMINFO); + + /* add the sambaNext[User|Group]Rid attributes if the idmap ranges are set. + TODO: fix all the places where the line between idmap and normal operations + needed by smbd gets fuzzy --jerry 2003-08-11 */ + + if ( lp_idmap_uid(&u_low, &u_high) && lp_idmap_gid(&g_low, &g_high) + && get_free_rid_range(&rid_low, &rid_high) ) + { + fstring rid_str; + + fstr_sprintf( rid_str, "%i", rid_high|USER_RID_TYPE ); + DEBUG(10,("setting next available user rid [%s]\n", rid_str)); + smbldap_set_mod(&mods, LDAP_MOD_ADD, + get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_USERRID), + rid_str); + + fstr_sprintf( rid_str, "%i", rid_high|GROUP_RID_TYPE ); + DEBUG(10,("setting next available group rid [%s]\n", rid_str)); + smbldap_set_mod(&mods, LDAP_MOD_ADD, + get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_GROUPRID), + rid_str); + + } + switch(ldap_op) { diff --git a/source3/lib/substitute.c b/source3/lib/substitute.c index c0d0096806..28466e43f2 100644 --- a/source3/lib/substitute.c +++ b/source3/lib/substitute.c @@ -57,7 +57,7 @@ void set_local_machine_name(const char* local_name, BOOL perm) already_perm = perm; fstrcpy(tmp_local_machine,local_name); - trim_string(tmp_local_machine," "," "); + trim_char(tmp_local_machine,' ',' '); alpha_strcpy(local_machine,tmp_local_machine,SAFE_NETBIOS_CHARS,sizeof(local_machine)-1); strlower_m(local_machine); } @@ -79,7 +79,7 @@ void set_remote_machine_name(const char* remote_name, BOOL perm) already_perm = perm; fstrcpy(tmp_remote_machine,remote_name); - trim_string(tmp_remote_machine," "," "); + trim_char(tmp_remote_machine,' ',' '); alpha_strcpy(remote_machine,tmp_remote_machine,SAFE_NETBIOS_CHARS,sizeof(remote_machine)-1); strlower_m(remote_machine); } @@ -98,23 +98,36 @@ const char* get_local_machine_name(void) return local_machine; } +/******************************************************************* + Setup the string used by %U substitution. +********************************************************************/ -/* - setup the string used by %U substitution -*/ void sub_set_smb_name(const char *name) { fstring tmp; /* don't let anonymous logins override the name */ - if (! *name) return; + if (! *name) + return; fstrcpy(tmp,name); - trim_string(tmp," "," "); + trim_char(tmp,' ',' '); strlower_m(tmp); alpha_strcpy(smb_user_name,tmp,SAFE_NETBIOS_CHARS,sizeof(smb_user_name)-1); } +/******************************************************************* + Setup the strings used by substitutions. Called per packet. Ensure + %U name is set correctly also. +********************************************************************/ + +void set_current_user_info(const userdom_struct *pcui) +{ + current_user_info = *pcui; + /* The following is safe as current_user_info.smb_name + * has already been sanitised in register_vuid. */ + fstrcpy(smb_user_name, current_user_info.smb_name); +} /******************************************************************* Given a pointer to a %$(NAME) expand it as an environment variable. @@ -384,7 +397,7 @@ void standard_sub_basic(const char *smb_name, char *str,size_t len) string_sub(p,"%m", get_remote_machine_name(),l); break; case 'v' : - string_sub(p,"%v", VERSION,l); + string_sub(p,"%v", SAMBA_VERSION_STRING,l); break; case '$' : p += expand_env_var(p,l); @@ -539,7 +552,7 @@ char *alloc_sub_basic(const char *smb_name, const char *str) t = realloc_string_sub(t, "%m", remote_machine); break; case 'v' : - t = realloc_string_sub(t, "%v", VERSION); + t = realloc_string_sub(t, "%v", SAMBA_VERSION_STRING); break; case '$' : t = realloc_expand_env_var(t, p); /* Expand environment variables */ diff --git a/source3/lib/system.c b/source3/lib/system.c index a7024c852d..b020a20373 100644 --- a/source3/lib/system.c +++ b/source3/lib/system.c @@ -1263,6 +1263,16 @@ ssize_t sys_getxattr (const char *path, const char *name, void *value, size_t si { #if defined(HAVE_GETXATTR) return getxattr(path, name, value, size); +#elif defined(HAVE_ATTR_GET) + int retval, flags = 0; + int valuelength = (int)size; + char *attrname = strchr(name,'.') +1; + + if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT; + + retval = attr_get(path, attrname, (char *)value, &valuelength, flags); + + return retval ? retval : valuelength; #else errno = ENOSYS; return -1; @@ -1273,6 +1283,16 @@ ssize_t sys_lgetxattr (const char *path, const char *name, void *value, size_t s { #if defined(HAVE_LGETXATTR) return lgetxattr(path, name, value, size); +#elif defined(HAVE_ATTR_GET) + int retval, flags = ATTR_DONTFOLLOW; + int valuelength = (int)size; + char *attrname = strchr(name,'.') +1; + + if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT; + + retval = attr_get(path, attrname, (char *)value, &valuelength, flags); + + return retval ? retval : valuelength; #else errno = ENOSYS; return -1; @@ -1283,16 +1303,96 @@ ssize_t sys_fgetxattr (int filedes, const char *name, void *value, size_t size) { #if defined(HAVE_FGETXATTR) return fgetxattr(filedes, name, value, size); +#elif defined(HAVE_ATTR_GETF) + int retval, flags = 0; + int valuelength = (int)size; + char *attrname = strchr(name,'.') +1; + + if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT; + + retval = attr_getf(filedes, attrname, (char *)value, &valuelength, flags); + + return retval ? retval : valuelength; #else errno = ENOSYS; return -1; #endif } +#if defined(HAVE_ATTR_LIST) +static char attr_buffer[ATTR_MAX_VALUELEN]; + +static ssize_t irix_attr_list(const char *path, int filedes, char *list, size_t size, int flags) +{ + int retval = 0, index; + attrlist_cursor_t *cursor = 0; + int total_size = 0; + attrlist_t * al = (attrlist_t *)attr_buffer; + attrlist_ent_t *ae; + size_t ent_size, left = size; + char *bp = list; + + while (True) { + if (filedes) + retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor); + else + retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor); + if (retval) break; + for (index = 0; index < al->al_count; index++) { + ae = ATTR_ENTRY(attr_buffer, index); + ent_size = strlen(ae->a_name) + sizeof("user."); + if (left >= ent_size) { + strncpy(bp, "user.", sizeof("user.")); + strncat(bp, ae->a_name, ent_size - sizeof("user.")); + bp += ent_size; + left -= ent_size; + } else if (size) { + errno = ERANGE; + retval = -1; + break; + } + total_size += ent_size; + } + if (al->al_more == 0) break; + } + if (retval == 0) { + flags |= ATTR_ROOT; + cursor = 0; + while (True) { + if (filedes) + retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor); + else + retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor); + if (retval) break; + for (index = 0; index < al->al_count; index++) { + ae = ATTR_ENTRY(attr_buffer, index); + ent_size = strlen(ae->a_name) + sizeof("system."); + if (left >= ent_size) { + strncpy(bp, "system.", sizeof("system.")); + strncat(bp, ae->a_name, ent_size - sizeof("system.")); + bp += ent_size; + left -= ent_size; + } else if (size) { + errno = ERANGE; + retval = -1; + break; + } + total_size += ent_size; + } + if (al->al_more == 0) break; + } + } + return (ssize_t)(retval ? retval : total_size); +} + +#endif + ssize_t sys_listxattr (const char *path, char *list, size_t size) { #if defined(HAVE_LISTXATTR) return listxattr(path, list, size); +#elif defined(HAVE_ATTR_LIST) + return irix_attr_list(path, 0, list, size, 0); #else errno = ENOSYS; return -1; @@ -1301,8 +1401,10 @@ ssize_t sys_listxattr (const char *path, char *list, size_t size) ssize_t sys_llistxattr (const char *path, char *list, size_t size) { -#if defined(HAVE_GETXATTR) +#if defined(HAVE_LLISTXATTR) return llistxattr(path, list, size); +#elif defined(HAVE_ATTR_LIST) + return irix_attr_list(path, 0, list, size, ATTR_DONTFOLLOW); #else errno = ENOSYS; return -1; @@ -1313,6 +1415,8 @@ ssize_t sys_flistxattr (int filedes, char *list, size_t size) { #if defined(HAVE_FLISTXATTR) return flistxattr(filedes, list, size); +#elif defined(HAVE_ATTR_LISTF) + return irix_attr_list(NULL, filedes, list, size, 0); #else errno = ENOSYS; return -1; @@ -1323,6 +1427,13 @@ int sys_removexattr (const char *path, const char *name) { #if defined(HAVE_REMOVEXATTR) return removexattr(path, name); +#elif defined(HAVE_ATTR_REMOVE) + int flags = 0; + char *attrname = strchr(name,'.') +1; + + if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT; + + return attr_remove(path, attrname, flags); #else errno = ENOSYS; return -1; @@ -1333,6 +1444,13 @@ int sys_lremovexattr (const char *path, const char *name) { #if defined(HAVE_LREMOVEXATTR) return lremovexattr(path, name); +#elif defined(HAVE_ATTR_REMOVE) + int flags = ATTR_DONTFOLLOW; + char *attrname = strchr(name,'.') +1; + + if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT; + + return attr_remove(path, attrname, flags); #else errno = ENOSYS; return -1; @@ -1343,16 +1461,37 @@ int sys_fremovexattr (int filedes, const char *name) { #if defined(HAVE_FREMOVEXATTR) return fremovexattr(filedes, name); +#elif defined(HAVE_ATTR_REMOVEF) + int flags = 0; + char *attrname = strchr(name,'.') +1; + + if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT; + + return attr_removef(filedes, attrname, flags); #else errno = ENOSYS; return -1; #endif } +#if !defined(HAVE_SETXATTR) +#define XATTR_CREATE 0x1 /* set value, fail if attr already exists */ +#define XATTR_REPLACE 0x2 /* set value, fail if attr does not exist */ +#endif + int sys_setxattr (const char *path, const char *name, const void *value, size_t size, int flags) { #if defined(HAVE_SETXATTR) return setxattr(path, name, value, size, flags); +#elif defined(HAVE_ATTR_SET) + int myflags = 0; + char *attrname = strchr(name,'.') +1; + + if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT; + if (flags & XATTR_CREATE) myflags |= ATTR_CREATE; + if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE; + + return attr_set(path, attrname, (const char *)value, size, myflags); #else errno = ENOSYS; return -1; @@ -1363,6 +1502,15 @@ int sys_lsetxattr (const char *path, const char *name, const void *value, size_t { #if defined(HAVE_LSETXATTR) return lsetxattr(path, name, value, size, flags); +#elif defined(HAVE_ATTR_SET) + int myflags = ATTR_DONTFOLLOW; + char *attrname = strchr(name,'.') +1; + + if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT; + if (flags & XATTR_CREATE) myflags |= ATTR_CREATE; + if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE; + + return attr_set(path, attrname, (const char *)value, size, myflags); #else errno = ENOSYS; return -1; @@ -1373,6 +1521,15 @@ int sys_fsetxattr (int filedes, const char *name, const void *value, size_t size { #if defined(HAVE_FSETXATTR) return fsetxattr(filedes, name, value, size, flags); +#elif defined(HAVE_ATTR_SETF) + int myflags = 0; + char *attrname = strchr(name,'.') +1; + + if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT; + if (flags & XATTR_CREATE) myflags |= ATTR_CREATE; + if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE; + + return attr_setf(filedes, attrname, (const char *)value, size, myflags); #else errno = ENOSYS; return -1; diff --git a/source3/lib/util.c b/source3/lib/util.c index eaa232a549..766c5041b4 100644 --- a/source3/lib/util.c +++ b/source3/lib/util.c @@ -261,7 +261,7 @@ BOOL init_names(void) } fstrcpy( local_machine, global_myname() ); - trim_string( local_machine, " ", " " ); + trim_char( local_machine, ' ', ' ' ); p = strchr( local_machine, ' ' ); if (p) *p = 0; @@ -311,7 +311,7 @@ BOOL in_group(gid_t group, gid_t current_gid, int ngroups, const gid_t *groups) static const char *Atoic(const char *p, int *n, const char *c) { - if (!isdigit((const int)*p)) { + if (!isdigit((int)*p)) { DEBUG(5, ("Atoic: malformed number\n")); return NULL; } @@ -605,68 +605,6 @@ void unix_clean_name(char *s) trim_string(s,NULL,"/.."); } -/******************************************************************* - Convert '\' to '/'. - Reduce a file name, removing or reducing /../ , /./ , // elements. - Remove also any trailing . and / - Return a new allocated string. -********************************************************************/ - -smb_ucs2_t *unix_clean_path(const smb_ucs2_t *s) -{ - smb_ucs2_t *ns; - smb_ucs2_t *p, *r, *t; - - DEBUG(3, ("unix_clean_path\n")); /* [%unicode]\n")); */ - if(!s) - return NULL; - - /* convert '\' to '/' */ - ns = strdup_w(s); - if (!ns) - return NULL; - unix_format_w(ns); - - /* remove all double slashes */ - p = ns; - ns = all_string_sub_wa(p, "//", "/"); - SAFE_FREE(p); - if (!ns) - return NULL; - - /* remove any /./ */ - p = ns; - ns = all_string_sub_wa(p, "/./", "/"); - SAFE_FREE(p); - if (!ns) - return NULL; - - /* reduce any /../ */ - t = ns; - while (*t && (r = strstr_wa(t, "/.."))) { - t = &(r[3]); - if (*t == UCS2_CHAR('/') || *t == 0) { - *r = 0; - p = strrchr_w(ns, UCS2_CHAR('/')); - if (!p) - p = ns; - if (*t == 0) - *p = 0; - else - memmove(p, t, (strlen_w(t) + 1) * sizeof(smb_ucs2_t)); - t = p; - } - } - - /* remove any leading ./ trailing /. */ - trim_string_wa(ns, "./", "/."); - - /* remove any leading and trailing / */ - trim_string_wa(ns, "/", "/"); - - return ns; -} - /**************************************************************************** Make a dir struct. ****************************************************************************/ @@ -2205,7 +2143,7 @@ char *lock_path(const char *name) static pstring fname; pstrcpy(fname,lp_lockdir()); - trim_string(fname,"","/"); + trim_char(fname,'\0','/'); if (!directory_exist(fname,NULL)) mkdir(fname,0755); @@ -2225,7 +2163,7 @@ char *pid_path(const char *name) static pstring fname; pstrcpy(fname,lp_piddir()); - trim_string(fname,"","/"); + trim_char(fname,'\0','/'); if (!directory_exist(fname,NULL)) mkdir(fname,0755); @@ -2335,21 +2273,12 @@ BOOL ms_has_wild_w(const smb_ucs2_t *s) BOOL mask_match(const char *string, char *pattern, BOOL is_case_sensitive) { - fstring p2, s2; - if (strcmp(string,"..") == 0) string = "."; if (strcmp(pattern,".") == 0) return False; - if (is_case_sensitive) - return ms_fnmatch(pattern, string, Protocol) == 0; - - fstrcpy(p2, pattern); - fstrcpy(s2, string); - strlower_m(p2); - strlower_m(s2); - return ms_fnmatch(p2, s2, Protocol) == 0; + return ms_fnmatch(pattern, string, Protocol, is_case_sensitive) == 0; } /********************************************************* diff --git a/source3/lib/util_file.c b/source3/lib/util_file.c index 638a6ca342..bd505ac921 100644 --- a/source3/lib/util_file.c +++ b/source3/lib/util_file.c @@ -20,6 +20,11 @@ #include "includes.h" +#ifndef MAP_FAILED +#define MAP_FAILED ((void *)-1) +#endif + + static int gotalarm; /*************************************************************** diff --git a/source3/lib/util_sid.c b/source3/lib/util_sid.c index 00f14d7d26..fbb393770d 100644 --- a/source3/lib/util_sid.c +++ b/source3/lib/util_sid.c @@ -93,7 +93,7 @@ static const struct { {SID_NAME_UNKNOWN, "UNKNOWN"}, {SID_NAME_COMPUTER, "Computer"}, - {0, NULL} + {(enum SID_NAME_USE)0, NULL} }; const char *sid_type_lookup(uint32 sid_type) diff --git a/source3/lib/util_str.c b/source3/lib/util_str.c index 7569a39e6a..82b312e241 100644 --- a/source3/lib/util_str.c +++ b/source3/lib/util_str.c @@ -37,7 +37,7 @@ **/ BOOL next_token(const char **ptr,char *buff, const char *sep, size_t bufsize) { - const char *s; + char *s; char *pbuf; BOOL quoted; size_t len=1; @@ -45,7 +45,7 @@ BOOL next_token(const char **ptr,char *buff, const char *sep, size_t bufsize) if (!ptr) return(False); - s = *ptr; + s = (char *)*ptr; /* default to simple separators */ if (!sep) @@ -88,7 +88,7 @@ BOOL next_token_nr(const char **ptr,char *buff, const char *sep, size_t bufsize) { BOOL ret; if (!ptr) - ptr = (const char **)&last_ptr; + ptr = &last_ptr; ret = next_token(ptr, buff, sep, bufsize); last_ptr = *ptr; @@ -109,7 +109,7 @@ void set_first_token(char *ptr) char **toktocliplist(int *ctok, const char *sep) { - char *s=last_ptr; + char *s=(char *)last_ptr; int ictok=0; char **ret, **iret; @@ -132,7 +132,7 @@ char **toktocliplist(int *ctok, const char *sep) } while(*s); *ctok=ictok; - s=last_ptr; + s=(char *)last_ptr; if (!(ret=iret=malloc(ictok*sizeof(char *)))) return NULL; @@ -364,9 +364,27 @@ BOOL strisnormal(const char *s) void string_replace(pstring s,char oldc,char newc) { - push_ucs2(NULL, tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE); + unsigned char *p; + + /* this is quite a common operation, so we want it to be + fast. We optimise for the ascii case, knowing that all our + supported multi-byte character sets are ascii-compatible + (ie. they match for the first 128 chars) */ + + for (p = (unsigned char *)s; *p; p++) { + if (*p & 0x80) /* mb string - slow path. */ + break; + if (*p == oldc) + *p = newc; + } + + if (!*p) + return; + + /* Slow (mb) path. */ + push_ucs2(NULL, tmpbuf, p, sizeof(tmpbuf), STR_TERMINATE); string_replace_w(tmpbuf, UCS2_CHAR(oldc), UCS2_CHAR(newc)); - pull_ucs2(NULL, s, tmpbuf, -1, sizeof(tmpbuf), STR_TERMINATE); + pull_ucs2(NULL, p, tmpbuf, -1, sizeof(tmpbuf), STR_TERMINATE); } /** @@ -406,6 +424,59 @@ size_t str_ascii_charnum(const char *s) return strlen(tmpbuf2); } +BOOL trim_char(char *s,char cfront,char cback) +{ + BOOL ret = False; + char *ep; + char *fp = s; + + /* Ignore null or empty strings. */ + if (!s || (s[0] == '\0')) + return False; + + if (cfront) { + while (*fp && *fp == cfront) + fp++; + if (!*fp) { + /* We ate the string. */ + s[0] = '\0'; + return True; + } + if (fp != s) + ret = True; + } + + ep = fp + strlen(fp) - 1; + if (cback) { + /* Attempt ascii only. Bail for mb strings. */ + while ((ep >= fp) && (*ep == cback)) { + ret = True; + if ((ep > fp) && (((unsigned char)ep[-1]) & 0x80)) { + /* Could be mb... bail back to tim_string. */ + char fs[2], bs[2]; + if (cfront) { + fs[0] = cfront; + fs[1] = '\0'; + } + bs[0] = cback; + bs[1] = '\0'; + return trim_string(s, cfront ? fs : NULL, bs); + } else { + ep--; + } + } + if (ep < fp) { + /* We ate the string. */ + s[0] = '\0'; + return True; + } + } + + ep[1] = '\0'; + memmove(s, fp, ep-fp+2); + return ret; +} + /** Trim the specified elements off the front and back of a string. **/ @@ -428,7 +499,9 @@ BOOL trim_string(char *s,const char *front,const char *back) if (front_len) { while (len && strncmp(s, front, front_len)==0) { - memcpy(s, s+front_len, (len-front_len)+1); + /* Must use memmove here as src & dest can + * easily overlap. Found by valgrind. JRA. */ + memmove(s, s+front_len, (len-front_len)+1); len -= front_len; ret=True; } @@ -501,7 +574,9 @@ char *safe_strcpy_fn(const char *fn, int line, char *dest,const char *src, size_ return NULL; } +#ifdef DEVELOPER clobber_region(fn,line,dest, maxlength+1); +#endif if (!src) { *dest = 0; @@ -540,7 +615,9 @@ char *safe_strcat_fn(const char *fn, int line, char *dest, const char *src, size src_len = strnlen(src, maxlength + 1); dest_len = strnlen(dest, maxlength + 1); +#ifdef DEVELOPER clobber_region(fn, line, dest + dest_len, maxlength + 1 - dest_len); +#endif if (src_len + dest_len > maxlength) { DEBUG(0,("ERROR: string overflow by %d in safe_strcat [%.50s]\n", @@ -567,7 +644,9 @@ char *alpha_strcpy_fn(const char *fn, int line, char *dest, const char *src, con { size_t len, i; +#ifdef DEVELOPER clobber_region(fn, line, dest, maxlength); +#endif if (!dest) { DEBUG(0,("ERROR: NULL dest in alpha_strcpy\n")); @@ -607,7 +686,9 @@ char *StrnCpy_fn(const char *fn, int line,char *dest,const char *src,size_t n) { char *d = dest; +#ifdef DEVELOPER clobber_region(fn, line, dest, n+1); +#endif if (!dest) return(NULL); @@ -637,8 +718,9 @@ static char *strncpyn(char *dest, const char *src, size_t n, char c) char *p; size_t str_len; +#ifdef DEVELOPER clobber_region(dest, n+1); - +#endif p = strchr_m(src, c); if (p == NULL) { DEBUG(5, ("strncpyn: separator character (%c) not found\n", c)); @@ -910,6 +992,7 @@ char *realloc_string_sub(char *string, const char *pattern, const char *insert) while ((p = strstr(s,pattern))) { if (ld > 0) { + int offset = PTR_DIFF(s,string); char *t = Realloc(string, ls + ld + 1); if (!t) { DEBUG(0, ("realloc_string_sub: out of memory!\n")); @@ -917,7 +1000,7 @@ char *realloc_string_sub(char *string, const char *pattern, const char *insert) return NULL; } string = t; - p = t + (p - s); + p = t + offset + (p - s); } if (li != lp) { memmove(p+li,p+lp,strlen(p+lp)+1); @@ -1098,6 +1181,19 @@ char *strchr_m(const char *s, char c) pstring s2; smb_ucs2_t *p; + /* this is quite a common operation, so we want it to be + fast. We optimise for the ascii case, knowing that all our + supported multi-byte character sets are ascii-compatible + (ie. they match for the first 128 chars) */ + + while (*s && (((unsigned char)s[0]) & 0x80)) { + if (*s == c) + return s; + } + + if (!*s) + return NULL; + push_ucs2(NULL, ws, s, sizeof(ws), STR_TERMINATE); p = strchr_w(ws, UCS2_CHAR(c)); if (!p) @@ -1109,17 +1205,53 @@ char *strchr_m(const char *s, char c) char *strrchr_m(const char *s, char c) { - wpstring ws; - pstring s2; - smb_ucs2_t *p; + /* this is quite a common operation, so we want it to be + fast. We optimise for the ascii case, knowing that all our + supported multi-byte character sets are ascii-compatible + (ie. they match for the first 128 chars). Also, in Samba + we only search for ascii characters in 'c' and that + in all mb character sets with a compound character + containing c, if 'c' is not a match at position + p, then p[-1] > 0x7f. JRA. */ - push_ucs2(NULL, ws, s, sizeof(ws), STR_TERMINATE); - p = strrchr_w(ws, UCS2_CHAR(c)); - if (!p) - return NULL; - *p = 0; - pull_ucs2_pstring(s2, ws); - return (char *)(s+strlen(s2)); + { + size_t len = strlen(s); + const char *cp = s; + BOOL got_mb = False; + + if (len == 0) + return NULL; + cp += (len - 1); + do { + if (c == *cp) { + /* Could be a match. Part of a multibyte ? */ + if ((cp > s) && (((unsigned char)cp[-1]) & 0x80)) { + /* Yep - go slow :-( */ + got_mb = True; + break; + } + /* No - we have a match ! */ + return cp; + } + } while (cp-- != s); + if (!got_mb) + return NULL; + } + + /* String contained a non-ascii char. Slow path. */ + { + wpstring ws; + pstring s2; + smb_ucs2_t *p; + + push_ucs2(NULL, ws, s, sizeof(ws), STR_TERMINATE); + p = strrchr_w(ws, UCS2_CHAR(c)); + if (!p) + return NULL; + *p = 0; + pull_ucs2_pstring(s2, ws); + return (char *)(s+strlen(s2)); + } } /*********************************************************************** @@ -1409,6 +1541,35 @@ void str_list_free(char ***list) SAFE_FREE(*list); } +/****************************************************************************** + version of standard_sub_basic() for string lists; uses alloc_sub_basic() + for the work + *****************************************************************************/ + +BOOL str_list_sub_basic( char **list, const char *smb_name ) +{ + char *s, *tmpstr; + + while ( *list ) { + s = *list; + tmpstr = alloc_sub_basic(smb_name, s); + if ( !tmpstr ) { + DEBUG(0,("str_list_sub_basic: alloc_sub_basic() return NULL!\n")); + return False; + } + + *list = tmpstr; + + list++; + } + + return True; +} + +/****************************************************************************** + substritute a specific pattern in a string list + *****************************************************************************/ + BOOL str_list_substitute(char **list, const char *pattern, const char *insert) { char *p, *s, *t; @@ -1464,6 +1625,7 @@ BOOL str_list_substitute(char **list, const char *pattern, const char *insert) } } + list++; } diff --git a/source3/lib/version.c b/source3/lib/version.c new file mode 100644 index 0000000000..99f836c2d5 --- /dev/null +++ b/source3/lib/version.c @@ -0,0 +1,42 @@ +/* + Unix SMB/CIFS implementation. + Samba Version functions + + Copyright (C) Stefan Metzmacher 2003 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +const char *samba_version_string(void) +{ +#ifndef SAMBA_VERSION_VENDOR_SUFFIX + return SAMBA_VERSION_OFFICIAL_STRING; +#else + static fstring samba_version; + static BOOL init_samba_version; + + if (init_samba_version) + return samba_version; + + snprintf(samba_version,sizeof(samba_version),"%s-%s", + SAMBA_VERSION_OFFICIAL_STRING, + SAMBA_VERSION_VENDOR_SUFFIX); + + init_samba_version = True; + return samba_version; +#endif +} diff --git a/source3/libads/ads_status.c b/source3/libads/ads_status.c index 80fdb99eac..11f9d66b92 100644 --- a/source3/libads/ads_status.c +++ b/source3/libads/ads_status.c @@ -87,7 +87,7 @@ NTSTATUS ads_ntstatus(ADS_STATUS status) */ const char *ads_errstr(ADS_STATUS status) { - int msg_ctx; + uint32 msg_ctx; static char *ret; SAFE_FREE(ret); diff --git a/source3/libads/authdata.c b/source3/libads/authdata.c index 50a9ef2718..29170af377 100644 --- a/source3/libads/authdata.c +++ b/source3/libads/authdata.c @@ -39,6 +39,7 @@ static DATA_BLOB unwrap_pac(DATA_BLOB *auth_data) asn1_end_tag(&data); asn1_end_tag(&data); asn1_end_tag(&data); + asn1_free(&data); return pac_contents; } @@ -422,7 +423,7 @@ static BOOL pac_io_pac_signature_data(const char *desc, if (!prs_uint32("type", ps, depth, &data->type)) return False; if (UNMARSHALLING(ps)) { - data->signature = prs_alloc_mem(ps, siglen); + data->signature = (unsigned char *)prs_alloc_mem(ps, siglen); if (!data->signature) { DEBUG(3, ("No memory available\n")); return False; @@ -600,9 +601,11 @@ PAC_DATA *decode_pac_data(DATA_BLOB *auth_data, TALLOC_CTX *ctx) DEBUG(5,("dump_pac_data\n")); prs_init(&ps, pac_data_blob.length, ctx, UNMARSHALL); - prs_copy_data_in(&ps, pac_data_blob.data, pac_data_blob.length); + prs_copy_data_in(&ps, (char *)pac_data_blob.data, pac_data_blob.length); prs_set_offset(&ps, 0); + data_blob_free(&pac_data_blob); + pac_data = (PAC_DATA *) talloc_zero(ctx, sizeof(PAC_DATA)); pac_io_pac_data("pac data", pac_data, &ps, 0); diff --git a/source3/libads/kerberos_verify.c b/source3/libads/kerberos_verify.c index 48b61cd1f2..4ae89aa01f 100644 --- a/source3/libads/kerberos_verify.c +++ b/source3/libads/kerberos_verify.c @@ -4,6 +4,8 @@ Copyright (C) Andrew Tridgell 2001 Copyright (C) Remus Koos 2001 Copyright (C) Luke Howard 2003 + Copyright (C) Guenther Deschner 2003 + Copyright (C) Jim McDonough (jmcd@us.ibm.com) 2003 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -24,11 +26,132 @@ #ifdef HAVE_KRB5 +static void free_keytab(krb5_context context, krb5_keytab keytab) +{ + int ret=0; + + if (keytab) + ret = krb5_kt_close(context, keytab); + if (ret) { + DEBUG(3, ("krb5_kt_close failed (%s)\n", + error_message(ret))); + } +} + +#ifdef HAVE_MEMORY_KEYTAB +static krb5_error_code create_keytab(krb5_context context, + krb5_principal host_princ, + char *host_princ_s, + krb5_data password, + krb5_enctype *enctypes, + krb5_keytab *keytab, + char *keytab_name) +{ + krb5_keytab_entry entry; + krb5_kvno kvno = 1; + krb5_error_code ret; + krb5_keyblock *key; + int i; + + DEBUG(10,("creating keytab: %s\n", keytab_name)); + ret = krb5_kt_resolve(context, keytab_name, keytab); + if (ret) + return ret; + + if (!(key = (krb5_keyblock *)malloc(sizeof(*key)))) { + return ENOMEM; + } + + /* add keytab entries for all encryption types */ + for ( i=0; enctypes[i]; i++ ) { + + if (create_kerberos_key_from_string(context, host_princ, &password, key, enctypes[i])) { + continue; + } + + entry.principal = host_princ; + entry.vno = kvno; + /* this will have to be detected in configure...heimdal + calls it keyblock, MIT calls it key, but it does not + matter we are creating keytabs with MIT */ + entry.keyblock = *key; + + DEBUG(10,("adding keytab-entry for (%s) with encryption type (%d)\n", + host_princ_s, enctypes[i])); + ret = krb5_kt_add_entry(context, *keytab, &entry); + if (ret) { + DEBUG(1,("adding entry to keytab failed (%s)\n", + error_message(ret))); + free_keytab(context, *keytab); + return ret; + } + } + krb5_free_keyblock(context, key); + + return 0; +} +#endif + +static BOOL setup_keytab(krb5_context context, + krb5_principal host_princ, + char *host_princ_s, + krb5_data password, + krb5_enctype *enctypes, + krb5_keytab *keytab) +{ + char *keytab_name = NULL; + krb5_error_code ret; + + /* check if we have to setup a keytab - not currently enabled + I've put this in so that the else block below functions + the same way that it will when this code is turned on */ + if (0 /* will later be *lp_keytab() */) { + + /* use a file-keytab */ + asprintf(&keytab_name, "%s:%s", + "" + /* KRB5_KT_FILE_PREFIX, "FILE" or + "WRFILE" depending on HEeimdal or MIT */, + "" /* will later be lp_keytab() */); + + DEBUG(10,("will use filebased keytab: %s\n", keytab_name)); + ret = krb5_kt_resolve(context, keytab_name, keytab); + if (ret) { + DEBUG(3,("cannot resolve keytab name %s (%s)\n", + keytab_name, + error_message(ret))); + SAFE_FREE(keytab_name); + return False; + } + + } + +#if defined(HAVE_MEMORY_KEYTAB) + else { + + /* setup a in-memory-keytab */ + asprintf(&keytab_name, "MEMORY:"); + + ret = create_keytab(context, host_princ, host_princ_s, password, enctypes, + keytab, keytab_name); + if (ret) { + DEBUG(3,("unable to create MEMORY: keytab (%s)\n", + error_message(ret))); + SAFE_FREE(keytab_name); + return False; + } + } +#endif + SAFE_FREE(keytab_name); + return True; +} + + /* verify an incoming ticket and parse out the principal name and authorization_data if available */ -NTSTATUS ads_verify_ticket(ADS_STRUCT *ads, const DATA_BLOB *ticket, +NTSTATUS ads_verify_ticket(const char *realm, const DATA_BLOB *ticket, char **principal, DATA_BLOB *auth_data, DATA_BLOB *ap_rep, uint8 session_key[16]) @@ -79,7 +202,7 @@ NTSTATUS ads_verify_ticket(ADS_STRUCT *ads, const DATA_BLOB *ticket, return NT_STATUS_LOGON_FAILURE; } - ret = krb5_set_default_realm(context, ads->auth.realm); + ret = krb5_set_default_realm(context, realm); if (ret) { DEBUG(1,("ads_verify_ticket: krb5_set_default_realm failed (%s)\n", error_message(ret))); sret = NT_STATUS_LOGON_FAILURE; @@ -128,11 +251,6 @@ NTSTATUS ads_verify_ticket(ADS_STRUCT *ads, const DATA_BLOB *ticket, /* CIFS doesn't use addresses in tickets. This would breat NAT. JRA */ - if (!(key = (krb5_keyblock *)malloc(sizeof(*key)))) { - sret = NT_STATUS_NO_MEMORY; - goto out; - } - if ((ret = get_kerberos_allowed_etypes(context, &enctypes))) { DEBUG(1,("ads_verify_ticket: krb5_get_permitted_enctypes failed (%s)\n", error_message(ret))); @@ -149,22 +267,40 @@ NTSTATUS ads_verify_ticket(ADS_STRUCT *ads, const DATA_BLOB *ticket, goto out; } + if (!setup_keytab(context, host_princ, host_princ_s, password, + enctypes, &keytab)) { + DEBUG(3,("ads_verify_ticket: unable to setup keytab\n")); + sret = NT_STATUS_LOGON_FAILURE; + goto out; + } + /* We need to setup a auth context with each possible encoding type in turn. */ for (i=0;enctypes[i];i++) { + if (!(key = (krb5_keyblock *)malloc(sizeof(*key)))) { + sret = NT_STATUS_NO_MEMORY; + goto out; + } + if (create_kerberos_key_from_string(context, host_princ, &password, key, enctypes[i])) { continue; } krb5_auth_con_setuseruserkey(context, auth_context, key); + krb5_free_keyblock(context, key); + packet.length = ticket->length; packet.data = (krb5_pointer)ticket->data; if (!(ret = krb5_rd_req(context, &auth_context, &packet, - NULL, keytab, NULL, &tkt))) { +#ifdef HAVE_MEMORY_KEYTAB + host_princ, +#else + NULL, +#endif + keytab, NULL, &tkt))) { DEBUG(10,("ads_verify_ticket: enc type [%u] decrypted message !\n", (unsigned int)enctypes[i] )); - free_kerberos_etypes(context, enctypes); auth_ok = True; break; } @@ -217,8 +353,13 @@ NTSTATUS ads_verify_ticket(ADS_STRUCT *ads, const DATA_BLOB *ticket, file_save("/tmp/authdata.dat", tkt->enc_part2->authorization_data[0]->contents, tkt->enc_part2->authorization_data[0]->length); + } #endif + + /* get rid of all resources associated with the keytab */ + if (keytab) free_keytab(context, keytab); + if ((ret = krb5_unparse_name(context, get_principal_from_tkt(tkt), principal))) { DEBUG(3,("ads_verify_ticket: krb5_unparse_name failed (%s)\n", @@ -237,8 +378,12 @@ NTSTATUS ads_verify_ticket(ADS_STRUCT *ads, const DATA_BLOB *ticket, if (!NT_STATUS_IS_OK(sret)) data_blob_free(ap_rep); - SAFE_FREE(host_princ_s); + krb5_free_principal(context, host_princ); + if (tkt != NULL) + krb5_free_ticket(context, tkt); + free_kerberos_etypes(context, enctypes); SAFE_FREE(password_s); + SAFE_FREE(host_princ_s); if (auth_context) krb5_auth_con_free(context, auth_context); diff --git a/source3/libads/krb5_setpw.c b/source3/libads/krb5_setpw.c index 80ef6cdf01..9cf15221a8 100644 --- a/source3/libads/krb5_setpw.c +++ b/source3/libads/krb5_setpw.c @@ -143,7 +143,7 @@ static krb5_error_code build_kpasswd_request(uint16 pversion, else return EINVAL; - encoded_setpw.data = setpw.data; + encoded_setpw.data = (char *)setpw.data; encoded_setpw.length = setpw.length; ret = krb5_mk_priv(context, auth_context, @@ -664,25 +664,22 @@ ADS_STATUS kerberos_set_password(const char *kpasswd_server, * @return status of password change **/ ADS_STATUS ads_set_machine_password(ADS_STRUCT *ads, - const char *hostname, + const char *machine_account, const char *password) { ADS_STATUS status; - char *host = strdup(hostname); - char *principal; - - strlower_m(host); + char *principal = NULL; /* - we need to use the '$' form of the name here, as otherwise the - server might end up setting the password for a user instead + we need to use the '$' form of the name here (the machine account name), + as otherwise the server might end up setting the password for a user + instead */ - asprintf(&principal, "%s$@%s", host, ads->config.realm); + asprintf(&principal, "%s@%s", machine_account, ads->config.realm); status = ads_krb5_set_password(ads->auth.kdc_server, principal, password, ads->auth.time_offset); - free(host); free(principal); return status; diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c index 5a12288b16..e925750e0a 100644 --- a/source3/libads/ldap.c +++ b/source3/libads/ldap.c @@ -1045,7 +1045,7 @@ static ADS_STATUS ads_add_machine_acct(ADS_STRUCT *ads, const char *hostname, ads_mod_str(ctx, &mods, "dNSHostName", hostname); ads_mod_str(ctx, &mods, "userAccountControl", controlstr); ads_mod_str(ctx, &mods, "operatingSystem", "Samba"); - ads_mod_str(ctx, &mods, "operatingSystemVersion", VERSION); + ads_mod_str(ctx, &mods, "operatingSystemVersion", SAMBA_VERSION_STRING); ret = ads_gen_add(ads, new_dn, mods); @@ -1777,7 +1777,7 @@ ADS_STATUS ads_USN(ADS_STRUCT *ads, uint32 *usn) ADS_STATUS status; void *res; - status = ads_do_search(ads, "", LDAP_SCOPE_BASE, "(objectclass=*)", attrs, &res); + status = ads_do_search_retry(ads, "", LDAP_SCOPE_BASE, "(objectclass=*)", attrs, &res); if (!ADS_ERR_OK(status)) return status; if (ads_count_replies(ads, res) != 1) { @@ -1900,7 +1900,7 @@ ADS_STATUS ads_domain_sid(ADS_STRUCT *ads, DOM_SID *sid) void *res; ADS_STATUS rc; - rc = ads_do_search(ads, ads->config.bind_path, LDAP_SCOPE_BASE, "(objectclass=*)", + rc = ads_do_search_retry(ads, ads->config.bind_path, LDAP_SCOPE_BASE, "(objectclass=*)", attrs, &res); if (!ADS_ERR_OK(rc)) return rc; if (!ads_pull_sid(ads, res, "objectSid", sid)) { diff --git a/source3/libads/ldap_utils.c b/source3/libads/ldap_utils.c index 6855600288..1fa9ebfc97 100644 --- a/source3/libads/ldap_utils.c +++ b/source3/libads/ldap_utils.c @@ -73,7 +73,10 @@ ADS_STATUS ads_do_search_retry(ADS_STRUCT *ads, const char *bind_path, int scope } free(bp); - DEBUG(1,("ads reopen failed after error %s\n", ads_errstr(status))); + if (!ADS_ERR_OK(status)) + DEBUG(1,("ads reopen failed after error %s\n", + ads_errstr(status))); + return status; } diff --git a/source3/libads/sasl.c b/source3/libads/sasl.c index 910ff3f4dc..5122803597 100644 --- a/source3/libads/sasl.c +++ b/source3/libads/sasl.c @@ -60,7 +60,7 @@ static ADS_STATUS ads_sasl_spnego_ntlmssp_bind(ADS_STRUCT *ads) msg1 = gen_negTokenTarg(mechs, blob); data_blob_free(&blob); - cred.bv_val = msg1.data; + cred.bv_val = (char *)msg1.data; cred.bv_len = msg1.length; rc = ldap_sasl_bind_s(ads->ld, NULL, "GSS-SPNEGO", &cred, NULL, NULL, &scred); @@ -106,7 +106,7 @@ static ADS_STATUS ads_sasl_spnego_ntlmssp_bind(ADS_STRUCT *ads) data_blob_free(&blob); /* now send the auth packet and we should be done */ - cred.bv_val = auth.data; + cred.bv_val = (char *)auth.data; cred.bv_len = auth.length; rc = ldap_sasl_bind_s(ads->ld, NULL, "GSS-SPNEGO", &cred, NULL, NULL, &scred); @@ -134,7 +134,7 @@ static ADS_STATUS ads_sasl_spnego_krb5_bind(ADS_STRUCT *ads, const char *princip } /* now send the auth packet and we should be done */ - cred.bv_val = blob.data; + cred.bv_val = (char *)blob.data; cred.bv_len = blob.length; rc = ldap_sasl_bind_s(ads->ld, NULL, "GSS-SPNEGO", &cred, NULL, NULL, &scred); @@ -227,13 +227,13 @@ failed: */ static ADS_STATUS ads_sasl_gssapi_bind(ADS_STRUCT *ads) { - int minor_status; + uint32 minor_status; gss_name_t serv_name; gss_buffer_desc input_name; gss_ctx_id_t context_handle; gss_OID mech_type = GSS_C_NULL_OID; gss_buffer_desc output_token, input_token; - OM_uint32 ret_flags, conf_state; + uint32 ret_flags, conf_state; struct berval cred; struct berval *scred; int i=0; @@ -328,7 +328,7 @@ static ADS_STATUS ads_sasl_gssapi_bind(ADS_STRUCT *ads) gss_release_name(&minor_status, &serv_name); gss_rc = gss_unwrap(&minor_status,context_handle,&input_token,&output_token, - &conf_state,NULL); + (int *)&conf_state,NULL); if (gss_rc) { status = ADS_ERROR_GSS(gss_rc, minor_status); goto failed; @@ -353,13 +353,13 @@ static ADS_STATUS ads_sasl_gssapi_bind(ADS_STRUCT *ads) *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(p); + snprintf((char *)p, strlen(ads->config.bind_path)+4, "dn:%s", ads->config.bind_path); + p += strlen((const char *)p); 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, + &output_token, (int *)&conf_state, &input_token); if (gss_rc) { status = ADS_ERROR_GSS(gss_rc, minor_status); diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c index 94fe04a480..48bcb61f92 100644 --- a/source3/libsmb/cliconnect.c +++ b/source3/libsmb/cliconnect.c @@ -190,7 +190,7 @@ static BOOL cli_session_setup_plaintext(struct cli_state *cli, const char *user, char *p; fstring lanman; - fstr_sprintf( lanman, "Samba %s", VERSION ); + fstr_sprintf( lanman, "Samba %s", SAMBA_VERSION_STRING); set_message(cli->outbuf,13,0,True); SCVAL(cli->outbuf,smb_com,SMBsesssetupX); @@ -247,7 +247,8 @@ static void set_cli_session_key (struct cli_state *cli, DATA_BLOB session_key) } /**************************************************************************** - do a NT1 NTLM/LM encrypted session setup + do a NT1 NTLM/LM encrypted session setup - for when extended security + is not negotiated. @param cli client state to create do session setup on @param user username @param pass *either* cleartext password (passlen !=24) or LM response. @@ -267,7 +268,9 @@ static BOOL cli_session_setup_nt1(struct cli_state *cli, const char *user, BOOL ret = False; char *p; - if (passlen != 24) { + if (passlen == 0) { + /* do nothing - guest login */ + } else if (passlen != 24) { if (lp_client_ntlmv2_auth()) { DATA_BLOB server_chal; DATA_BLOB names_blob; @@ -351,7 +354,7 @@ static BOOL cli_session_setup_nt1(struct cli_state *cli, const char *user, goto end; } - show_msg(cli->inbuf); + /* show_msg(cli->inbuf); */ if (cli_is_error(cli)) { ret = False; @@ -610,6 +613,7 @@ static BOOL cli_session_setup_ntlmssp(struct cli_state *cli, const char *user, } while (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)); if (NT_STATUS_IS_OK(nt_status)) { + fstrcpy(cli->server_domain, ntlmssp_state->server_domain); set_cli_session_key(cli, ntlmssp_state->session_key); } @@ -619,7 +623,7 @@ static BOOL cli_session_setup_ntlmssp(struct cli_state *cli, const char *user, if (!NT_STATUS_IS_OK(ntlmssp_client_end(&ntlmssp_state))) { return False; } - + return (NT_STATUS_IS_OK(nt_status)); } @@ -627,8 +631,8 @@ static BOOL cli_session_setup_ntlmssp(struct cli_state *cli, const char *user, Do a spnego encrypted session setup. ****************************************************************************/ -static BOOL cli_session_setup_spnego(struct cli_state *cli, const char *user, - const char *pass, const char *workgroup) +BOOL cli_session_setup_spnego(struct cli_state *cli, const char *user, + const char *pass, const char *workgroup) { char *principal; char *OIDs[ASN1_MAX_OIDS]; @@ -677,7 +681,7 @@ static BOOL cli_session_setup_spnego(struct cli_state *cli, const char *user, * and do not store results */ if (got_kerberos_mechanism && cli->use_kerberos) { - if (*pass) { + if (pass && *pass) { int ret; use_in_memory_ccache(); @@ -1024,22 +1028,27 @@ BOOL cli_negprot(struct cli_state *cli) smb_buflen(cli->inbuf)-8, STR_UNICODE|STR_NOALIGN); } - if ((cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED)) { - /* Fail if signing is mandatory and we don't want to support it. */ + /* + * As signing is slow we only turn it on if either the client or + * the server require it. JRA. + */ + + if (cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED) { + /* Fail if server says signing is mandatory and we don't want to support it. */ if (!cli->sign_info.allow_smb_signing) { DEBUG(1,("cli_negprot: SMB signing is mandatory and we have disabled it.\n")); return False; } cli->sign_info.negotiated_smb_signing = True; - } - - if ((cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) && cli->sign_info.allow_smb_signing) + cli->sign_info.mandatory_signing = True; + } else if (cli->sign_info.mandatory_signing && cli->sign_info.allow_smb_signing) { + /* Fail if client says signing is mandatory and the server doesn't support it. */ + if (!(cli->sec_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED)) { + DEBUG(1,("cli_negprot: SMB signing is mandatory and the server doesn't support it.\n")); + return False; + } cli->sign_info.negotiated_smb_signing = True; - - /* Fail if signing is mandatory and the server doesn't support it. */ - if (cli->sign_info.mandatory_signing && !(cli->sign_info.negotiated_smb_signing)) { - DEBUG(1,("cli_negprot: SMB signing is mandatory and the server doesn't support it.\n")); - return False; + cli->sign_info.mandatory_signing = True; } } else if (cli->protocol >= PROTOCOL_LANMAN1) { @@ -1223,7 +1232,7 @@ BOOL cli_connect(struct cli_state *cli, const char *host, struct in_addr *ip) Initialise client credentials for authenticated pipe access. ****************************************************************************/ -static void init_creds(struct ntuser_creds *creds, const char* username, +void init_creds(struct ntuser_creds *creds, const char* username, const char* domain, const char* password) { ZERO_STRUCTP(creds); @@ -1239,30 +1248,21 @@ static void init_creds(struct ntuser_creds *creds, const char* username, } /** - establishes a connection right up to doing tconX, password specified. + establishes a connection to after the negprot. @param output_cli A fully initialised cli structure, non-null only on success @param dest_host The netbios name of the remote host @param dest_ip (optional) The the destination IP, NULL for name based lookup @param port (optional) The destination port (0 for default) - @param service (optional) The share to make the connection to. Should be 'unqualified' in any way. - @param service_type The 'type' of serivice. - @param user Username, unix string - @param domain User's domain - @param password User's password, unencrypted unix string. @param retry BOOL. Did this connection fail with a retryable error ? -*/ -NTSTATUS cli_full_connection(struct cli_state **output_cli, - const char *my_name, - const char *dest_host, - struct in_addr *dest_ip, int port, - const char *service, const char *service_type, - const char *user, const char *domain, - const char *password, int flags, - int signing_state, - BOOL *retry) +*/ +NTSTATUS cli_start_connection(struct cli_state **output_cli, + const char *my_name, + const char *dest_host, + struct in_addr *dest_ip, int port, + int signing_state, int flags, + BOOL *retry) { - struct ntuser_creds creds; NTSTATUS nt_status; struct nmb_name calling; struct nmb_name called; @@ -1295,7 +1295,7 @@ NTSTATUS cli_full_connection(struct cli_state **output_cli, again: - DEBUG(3,("Connecting to host=%s share=%s\n", dest_host, service)); + DEBUG(3,("Connecting to host=%s\n", dest_host)); if (!cli_connect(cli, dest_host, &ip)) { DEBUG(1,("cli_full_connection: failed to connect to %s (%s)\n", @@ -1336,6 +1336,46 @@ again: return nt_status; } + *output_cli = cli; + return NT_STATUS_OK; +} + + +/** + establishes a connection right up to doing tconX, password specified. + @param output_cli A fully initialised cli structure, non-null only on success + @param dest_host The netbios name of the remote host + @param dest_ip (optional) The the destination IP, NULL for name based lookup + @param port (optional) The destination port (0 for default) + @param service (optional) The share to make the connection to. Should be 'unqualified' in any way. + @param service_type The 'type' of serivice. + @param user Username, unix string + @param domain User's domain + @param password User's password, unencrypted unix string. + @param retry BOOL. Did this connection fail with a retryable error ? +*/ + +NTSTATUS cli_full_connection(struct cli_state **output_cli, + const char *my_name, + const char *dest_host, + struct in_addr *dest_ip, int port, + const char *service, const char *service_type, + const char *user, const char *domain, + const char *password, int flags, + int signing_state, + BOOL *retry) +{ + struct ntuser_creds creds; + NTSTATUS nt_status; + struct cli_state *cli = NULL; + + nt_status = cli_start_connection(&cli, my_name, dest_host, + dest_ip, port, signing_state, flags, retry); + + if (!NT_STATUS_IS_OK(nt_status)) { + return nt_status; + } + if (!cli_session_setup(cli, user, password, strlen(password)+1, password, strlen(password)+1, domain)) { diff --git a/source3/libsmb/clientgen.c b/source3/libsmb/clientgen.c index bc5f1462cc..0a134f715d 100644 --- a/source3/libsmb/clientgen.c +++ b/source3/libsmb/clientgen.c @@ -299,9 +299,12 @@ struct cli_state *cli_initialise(struct cli_state *cli) memset(cli->outbuf, 0, cli->bufsize); memset(cli->inbuf, 0, cli->bufsize); + +#if defined(DEVELOPER) /* just because we over-allocate, doesn't mean it's right to use it */ clobber_region(FUNCTION_MACRO, __LINE__, cli->outbuf+cli->bufsize, SAFETY_MARGIN); clobber_region(FUNCTION_MACRO, __LINE__, cli->inbuf+cli->bufsize, SAFETY_MARGIN); +#endif /* initialise signing */ cli_null_set_signing(cli); @@ -339,7 +342,9 @@ void cli_nt_session_close(struct cli_state *cli) ntlmssp_client_end(&cli->ntlmssp_pipe_state); } - cli_close(cli, cli->nt_pipe_fnum); + if (cli->nt_pipe_fnum != 0) + cli_close(cli, cli->nt_pipe_fnum); + cli->nt_pipe_fnum = 0; cli->pipe_idx = -1; } diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c index f021076a46..c7f0cdb84b 100644 --- a/source3/libsmb/clifile.c +++ b/source3/libsmb/clifile.c @@ -951,8 +951,9 @@ BOOL cli_chkpath(struct cli_state *cli, const char *path) char *p; pstrcpy(path2,path); - trim_string(path2,NULL,"\\"); - if (!*path2) *path2 = '\\'; + trim_char(path2,'\0','\\'); + if (!*path2) + *path2 = '\\'; memset(cli->outbuf,'\0',smb_size); set_message(cli->outbuf,0,0,True); diff --git a/source3/libsmb/clikrb5.c b/source3/libsmb/clikrb5.c index beac8cb2c1..1fccc04a01 100644 --- a/source3/libsmb/clikrb5.c +++ b/source3/libsmb/clikrb5.c @@ -74,7 +74,7 @@ { pkaddr->addrtype = ADDRTYPE_INET; pkaddr->length = sizeof(((struct sockaddr_in *)paddr)->sin_addr); - pkaddr->contents = (char *)&(((struct sockaddr_in *)paddr)->sin_addr); + pkaddr->contents = (krb5_octet *)&(((struct sockaddr_in *)paddr)->sin_addr); } #else __ERROR__XX__UNKNOWN_ADDRTYPE @@ -97,7 +97,9 @@ return ret; } krb5_use_enctype(context, &eblock, enctype); - return krb5_string_to_key(context, &eblock, key, password, &salt); + ret = krb5_string_to_key(context, &eblock, key, password, &salt); + SAFE_FREE(salt.data); + return ret; } #elif defined(HAVE_KRB5_GET_PW_SALT) && defined(HAVE_KRB5_STRING_TO_KEY_SALT) int create_kerberos_key_from_string(krb5_context context, @@ -369,29 +371,27 @@ failed: BOOL get_krb5_smb_session_key(krb5_context context, krb5_auth_context auth_context, uint8 session_key[16], BOOL remote) { -#ifdef ENCTYPE_ARCFOUR_HMAC krb5_keyblock *skey; -#endif - BOOL ret = False; krb5_error_code err; + BOOL ret = False; memset(session_key, 0, 16); -#ifdef ENCTYPE_ARCFOUR_HMAC if (remote) err = krb5_auth_con_getremotesubkey(context, auth_context, &skey); else err = krb5_auth_con_getlocalsubkey(context, auth_context, &skey); if (err == 0 && skey != NULL) { - if (KRB5_KEY_TYPE(skey) == - ENCTYPE_ARCFOUR_HMAC - && KRB5_KEY_LENGTH(skey) == 16) { + DEBUG(10, ("Got KRB5 session key of length %d\n", KRB5_KEY_LENGTH(skey))); + if (KRB5_KEY_LENGTH(skey) == 16) { memcpy(session_key, KRB5_KEY_DATA(skey), KRB5_KEY_LENGTH(skey)); + dump_data_pw("KRB5 Session Key:\n", session_key, 16); ret = True; } krb5_free_keyblock(context, skey); + } else { + DEBUG(10, ("KRB5 error getting session key %d\n", err)); } -#endif /* ENCTYPE_ARCFOUR_HMAC */ return ret; } diff --git a/source3/libsmb/climessage.c b/source3/libsmb/climessage.c index 8ce8416487..035088212c 100644 --- a/source3/libsmb/climessage.c +++ b/source3/libsmb/climessage.c @@ -87,7 +87,7 @@ int cli_message_text_build(struct cli_state *cli, char *msg, int len, int grp) p = smb_buf(cli->outbuf); *p++ = 1; - if ((lendos = convert_string_allocate(CH_UNIX, CH_DOS, msg,len, (void **) &msgdos)) < 0 || !msgdos) { + if ((lendos = convert_string_allocate(NULL,CH_UNIX, CH_DOS, msg,len, (void **) &msgdos)) < 0 || !msgdos) { DEBUG(3,("Conversion failed, sending message in UNIX charset\n")); SSVAL(p, 0, len); p += 2; memcpy(p, msg, len); diff --git a/source3/libsmb/cliprint.c b/source3/libsmb/cliprint.c index f302c045a5..2fb0e59aca 100644 --- a/source3/libsmb/cliprint.c +++ b/source3/libsmb/cliprint.c @@ -55,7 +55,7 @@ int cli_print_queue(struct cli_state *cli, char *rparam = NULL; char *rdata = NULL; char *p; - int rdrcnt, rprcnt; + unsigned int rdrcnt, rprcnt; pstring param; int result_code=0; int i = -1; @@ -125,7 +125,8 @@ int cli_printjob_del(struct cli_state *cli, int job) char *rparam = NULL; char *rdata = NULL; char *p; - int rdrcnt,rprcnt, ret = -1; + unsigned int rdrcnt,rprcnt; + int ret = -1; pstring param; memset(param,'\0',sizeof(param)); diff --git a/source3/libsmb/clirap.c b/source3/libsmb/clirap.c index a307ac6ccf..79ad38fc8c 100644 --- a/source3/libsmb/clirap.c +++ b/source3/libsmb/clirap.c @@ -76,7 +76,7 @@ BOOL cli_NetWkstaUserLogon(struct cli_state *cli,char *user, char *workstation) char *rparam = NULL; char *rdata = NULL; char *p; - int rdrcnt,rprcnt; + unsigned int rdrcnt,rprcnt; pstring param; memset(param, 0, sizeof(param)); @@ -137,7 +137,7 @@ int cli_RNetShareEnum(struct cli_state *cli, void (*fn)(const char *, uint32, co char *rparam = NULL; char *rdata = NULL; char *p; - int rdrcnt,rprcnt; + unsigned int rdrcnt,rprcnt; pstring param; int count = -1; @@ -211,7 +211,7 @@ BOOL cli_NetServerEnum(struct cli_state *cli, char *workgroup, uint32 stype, { char *rparam = NULL; char *rdata = NULL; - int rdrcnt,rprcnt; + unsigned int rdrcnt,rprcnt; char *p; pstring param; int uLevel = 1; @@ -256,7 +256,7 @@ BOOL cli_NetServerEnum(struct cli_state *cli, char *workgroup, uint32 stype, const char *cmnt = comment_offset?(rdata+comment_offset):""; pstring s1, s2; - if (comment_offset < 0 || comment_offset > rdrcnt) continue; + if (comment_offset < 0 || comment_offset > (int)rdrcnt) continue; stype = IVAL(p,18) & ~SV_TYPE_LOCAL_LIST_ONLY; @@ -290,7 +290,7 @@ BOOL cli_oem_change_password(struct cli_state *cli, const char *user, const char unsigned int param_len = 0; char *rparam = NULL; char *rdata = NULL; - int rprcnt, rdrcnt; + unsigned int rprcnt, rdrcnt; pstring dos_new_password; if (strlen(user) >= sizeof(fstring)-1) { diff --git a/source3/libsmb/clirap2.c b/source3/libsmb/clirap2.c index 669b33860d..12a3d63aff 100644 --- a/source3/libsmb/clirap2.c +++ b/source3/libsmb/clirap2.c @@ -153,7 +153,8 @@ int cli_NetGroupDelete(struct cli_state *cli, const char *group_name ) char *rparam = NULL; char *rdata = NULL; char *p; - int rdrcnt,rprcnt, res; + unsigned int rdrcnt,rprcnt; + int res; char param[WORDSIZE /* api number */ +sizeof(RAP_NetGroupDel_REQ) /* parm string */ +1 /* no ret string */ @@ -204,7 +205,8 @@ int cli_NetGroupAdd(struct cli_state *cli, RAP_GROUP_INFO_1 * grinfo ) char *rparam = NULL; char *rdata = NULL; char *p; - int rdrcnt,rprcnt,res; + unsigned int rdrcnt,rprcnt; + int res; char param[WORDSIZE /* api number */ +sizeof(RAP_NetGroupAdd_REQ) /* req string */ +sizeof(RAP_GROUP_INFO_L1) /* return string */ @@ -272,7 +274,7 @@ int cli_RNetGroupEnum(struct cli_state *cli, void (*fn)(const char *, const char char *p; char *rparam = NULL; char *rdata = NULL; - int rprcnt, rdrcnt; + unsigned int rprcnt, rdrcnt; int res = -1; @@ -332,7 +334,8 @@ int cli_NetGroupDelUser(struct cli_state * cli, const char *group_name, const ch char *rparam = NULL; char *rdata = NULL; char *p; - int rdrcnt,rprcnt,res; + unsigned int rdrcnt,rprcnt; + int res; char param[WORDSIZE /* api number */ +sizeof(RAP_NetGroupDelUser_REQ) /* parm string */ +1 /* no ret string */ @@ -390,7 +393,8 @@ int cli_NetGroupAddUser(struct cli_state * cli, const char *group_name, const ch char *rparam = NULL; char *rdata = NULL; char *p; - int rdrcnt,rprcnt,res; + unsigned int rdrcnt,rprcnt; + int res; char param[WORDSIZE /* api number */ +sizeof(RAP_NetGroupAddUser_REQ) /* parm string */ +1 /* no ret string */ @@ -446,7 +450,7 @@ int cli_NetGroupGetUsers(struct cli_state * cli, const char *group_name, void (* char *rparam = NULL; char *rdata = NULL; char *p; - int rdrcnt,rprcnt; + unsigned int rdrcnt,rprcnt; int res = -1; char param[WORDSIZE /* api number */ +sizeof(RAP_NetGroupGetUsers_REQ)/* parm string */ @@ -501,7 +505,7 @@ int cli_NetUserGetGroups(struct cli_state * cli, const char *user_name, void (*f char *rparam = NULL; char *rdata = NULL; char *p; - int rdrcnt,rprcnt; + unsigned int rdrcnt,rprcnt; int res = -1; char param[WORDSIZE /* api number */ +sizeof(RAP_NetUserGetGroups_REQ)/* parm string */ @@ -560,7 +564,8 @@ int cli_NetUserDelete(struct cli_state *cli, const char * user_name ) char *rparam = NULL; char *rdata = NULL; char *p; - int rdrcnt,rprcnt, res; + unsigned int rdrcnt,rprcnt; + int res; char param[WORDSIZE /* api number */ +sizeof(RAP_NetGroupDel_REQ) /* parm string */ +1 /* no ret string */ @@ -614,7 +619,8 @@ int cli_NetUserAdd(struct cli_state *cli, RAP_USER_INFO_1 * userinfo ) char *rparam = NULL; char *rdata = NULL; char *p; - int rdrcnt,rprcnt,res; + unsigned int rdrcnt,rprcnt; + int res; char param[WORDSIZE /* api number */ +sizeof(RAP_NetUserAdd2_REQ) /* req string */ +sizeof(RAP_USER_INFO_L1) /* data string */ @@ -702,7 +708,7 @@ int cli_RNetUserEnum(struct cli_state *cli, void (*fn)(const char *, const char char *p; char *rparam = NULL; char *rdata = NULL; - int rprcnt, rdrcnt; + unsigned int rprcnt, rdrcnt; int res = -1; @@ -770,7 +776,7 @@ int cli_NetFileClose(struct cli_state *cli, uint32 file_id ) char *rparam = NULL; char *rdata = NULL; char *p; - int rdrcnt,rprcnt; + unsigned int rdrcnt,rprcnt; char param[WORDSIZE /* api number */ +sizeof(RAP_WFileClose2_REQ) /* req string */ +1 /* no ret string */ @@ -816,7 +822,8 @@ int cli_NetFileGetInfo(struct cli_state *cli, uint32 file_id, void (*fn)(const c char *rparam = NULL; char *rdata = NULL; char *p; - int rdrcnt,rprcnt, res; + unsigned int rdrcnt,rprcnt; + int res; char param[WORDSIZE /* api number */ +sizeof(RAP_WFileGetInfo2_REQ) /* req string */ +sizeof(RAP_FILE_INFO_L3) /* return string */ @@ -893,7 +900,7 @@ int cli_NetFileEnum(struct cli_state *cli, char * user, char * base_path, void ( char *rparam = NULL; char *rdata = NULL; char *p; - int rdrcnt,rprcnt; + unsigned int rdrcnt,rprcnt; char param[WORDSIZE /* api number */ +sizeof(RAP_WFileEnum2_REQ) /* req string */ +sizeof(RAP_FILE_INFO_L3) /* return string */ @@ -965,7 +972,8 @@ int cli_NetShareAdd(struct cli_state *cli, RAP_SHARE_INFO_2 * sinfo ) char *rparam = NULL; char *rdata = NULL; char *p; - int rdrcnt,rprcnt,res; + unsigned int rdrcnt,rprcnt; + int res; char param[WORDSIZE /* api number */ +sizeof(RAP_WShareAdd_REQ) /* req string */ +sizeof(RAP_SHARE_INFO_L2) /* return string */ @@ -1035,7 +1043,8 @@ int cli_NetShareDelete(struct cli_state *cli, const char * share_name ) char *rparam = NULL; char *rdata = NULL; char *p; - int rdrcnt,rprcnt, res; + unsigned int rdrcnt,rprcnt; + int res; char param[WORDSIZE /* api number */ +sizeof(RAP_WShareDel_REQ) /* req string */ +1 /* no ret string */ @@ -1097,7 +1106,7 @@ BOOL cli_get_pdc_name(struct cli_state *cli, char *workgroup, char *pdc_name) { char *rparam = NULL; char *rdata = NULL; - int rdrcnt,rprcnt; + unsigned int rdrcnt,rprcnt; char *p; char param[WORDSIZE /* api number */ +sizeof(RAP_NetServerEnum2_REQ) /* req string */ @@ -1177,7 +1186,7 @@ BOOL cli_get_server_domain(struct cli_state *cli) { char *rparam = NULL; char *rdata = NULL; - int rdrcnt,rprcnt; + unsigned int rdrcnt,rprcnt; char *p; char param[WORDSIZE /* api number */ +sizeof(RAP_WWkstaGetInfo_REQ) /* req string */ @@ -1242,7 +1251,7 @@ BOOL cli_get_server_type(struct cli_state *cli, uint32 *pstype) { char *rparam = NULL; char *rdata = NULL; - int rdrcnt,rprcnt; + unsigned int rdrcnt,rprcnt; char *p; char param[WORDSIZE /* api number */ +sizeof(RAP_WserverGetInfo_REQ) /* req string */ @@ -1309,7 +1318,7 @@ BOOL cli_ns_check_server_type(struct cli_state *cli, char *workgroup, uint32 sty { char *rparam = NULL; char *rdata = NULL; - int rdrcnt,rprcnt; + unsigned int rdrcnt,rprcnt; char *p; char param[WORDSIZE /* api number */ +sizeof(RAP_NetServerEnum2_REQ) /* req string */ @@ -1378,7 +1387,7 @@ BOOL cli_NetWkstaUserLogoff(struct cli_state *cli,char *user, char *workstation) char *rparam = NULL; char *rdata = NULL; char *p; - int rdrcnt,rprcnt; + unsigned int rdrcnt,rprcnt; char param[WORDSIZE /* api number */ +sizeof(RAP_NetWkstaUserLogoff_REQ) /* req string */ +sizeof(RAP_USER_LOGOFF_INFO_L1) /* return string */ @@ -1436,7 +1445,7 @@ int cli_NetPrintQEnum(struct cli_state *cli, char *p; char *rparam = NULL; char *rdata = NULL; - int rprcnt, rdrcnt; + unsigned int rprcnt, rdrcnt; int res = -1; @@ -1540,7 +1549,7 @@ int cli_NetPrintQGetInfo(struct cli_state *cli, const char *printer, char *p; char *rparam = NULL; char *rdata = NULL; - int rprcnt, rdrcnt; + unsigned int rprcnt, rdrcnt; int res = -1; @@ -1639,7 +1648,7 @@ int cli_RNetServiceEnum(struct cli_state *cli, void (*fn)(const char *, const ch char *p; char *rparam = NULL; char *rdata = NULL; - int rprcnt, rdrcnt; + unsigned int rprcnt, rdrcnt; int res = -1; @@ -1708,7 +1717,7 @@ int cli_NetSessionEnum(struct cli_state *cli, void (*fn)(char *, char *, uint16, char *p; char *rparam = NULL; char *rdata = NULL; - int rprcnt, rdrcnt; + unsigned int rprcnt, rdrcnt; int res = -1; memset(param, '\0', sizeof(param)); @@ -1784,7 +1793,7 @@ int cli_NetSessionGetInfo(struct cli_state *cli, const char *workstation, void ( char *p; char *rparam = NULL; char *rdata = NULL; - int rprcnt, rdrcnt; + unsigned int rprcnt, rdrcnt; int res = -1; @@ -1858,7 +1867,7 @@ int cli_NetSessionDel(struct cli_state *cli, const char *workstation) char *p; char *rparam = NULL; char *rdata = NULL; - int rprcnt, rdrcnt; + unsigned int rprcnt, rdrcnt; int res; memset(param, '\0', sizeof(param)); @@ -1903,7 +1912,7 @@ int cli_NetConnectionEnum(struct cli_state *cli, const char *qualifier, void (*f char *p; char *rparam = NULL; char *rdata = NULL; - int rprcnt, rdrcnt; + unsigned int rprcnt, rdrcnt; int res = -1; memset(param, '\0', sizeof(param)); diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index 0715aa7f1a..8eac7d07d8 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -326,7 +326,7 @@ ssize_t cli_write(struct cli_state *cli, int issued = 0; int received = 0; int mpx = MAX(cli->max_mux-1, 1); - int block = (cli->max_xmit - (smb_size+32)) & ~1023; + int block = cli->max_xmit - (smb_size+32); int blocks = (size + (block-1)) / block; while (received < blocks) { diff --git a/source3/libsmb/clisecdesc.c b/source3/libsmb/clisecdesc.c index d86a9022a6..548cd6ec18 100644 --- a/source3/libsmb/clisecdesc.c +++ b/source3/libsmb/clisecdesc.c @@ -28,7 +28,7 @@ SEC_DESC *cli_query_secdesc(struct cli_state *cli, int fnum, { char param[8]; char *rparam=NULL, *rdata=NULL; - int rparam_count=0, rdata_count=0; + unsigned int rparam_count=0, rdata_count=0; prs_struct pd; SEC_DESC *psd = NULL; @@ -78,7 +78,7 @@ BOOL cli_set_secdesc(struct cli_state *cli, int fnum, SEC_DESC *sd) { char param[8]; char *rparam=NULL, *rdata=NULL; - int rparam_count=0, rdata_count=0; + unsigned int rparam_count=0, rdata_count=0; uint32 sec_info = 0; TALLOC_CTX *mem_ctx; prs_struct pd; diff --git a/source3/libsmb/clispnego.c b/source3/libsmb/clispnego.c index b0570b09b6..63076a1a1c 100644 --- a/source3/libsmb/clispnego.c +++ b/source3/libsmb/clispnego.c @@ -331,6 +331,9 @@ DATA_BLOB spnego_gen_negTokenTarg(const char *principal, int time_offset, unsign /* get a kerberos ticket for the service and extract the session key */ tkt = cli_krb5_get_ticket(principal, time_offset, session_key_krb5); + if (tkt.data == NULL) + return tkt; + /* wrap that up in a nice GSS-API wrapping */ tkt_wrapped = spnego_gen_krb5_wrap(tkt, TOK_ID_KRB_AP_REQ); diff --git a/source3/libsmb/namequery.c b/source3/libsmb/namequery.c index 9875f77c72..1de7413711 100644 --- a/source3/libsmb/namequery.c +++ b/source3/libsmb/namequery.c @@ -61,7 +61,7 @@ static struct node_status *parse_node_status(char *p, int *num_names) p++; for (i=0;i< *num_names;i++) { StrnCpy(ret[i].name,p,15); - trim_string(ret[i].name,NULL," "); + trim_char(ret[i].name,'\0',' '); ret[i].type = CVAL(p,15); ret[i].flags = p[16]; p += 18; diff --git a/source3/libsmb/namequery_dc.c b/source3/libsmb/namequery_dc.c index c9d45a7acc..a596f00ddb 100644 --- a/source3/libsmb/namequery_dc.c +++ b/source3/libsmb/namequery_dc.c @@ -161,18 +161,28 @@ BOOL get_dc_name(const char *domain, fstring srv_name, struct in_addr *ip_out) { struct in_addr dc_ip; BOOL ret; + BOOL our_domain = False; zero_ip(&dc_ip); ret = False; - if (lp_security() == SEC_ADS) + + if ( strequal(lp_workgroup(), domain) || strequal(lp_realm(), domain) ) + our_domain = True; + + /* always try to obey what the admin specified in smb.conf. + If it is not our domain, assume that domain names with periods + in them are realm names */ + + if ( (our_domain && lp_security()==SEC_ADS) || strchr_m(domain, '.') ) { ret = ads_dc_name(domain, &dc_ip, srv_name); - + } + if (!ret) { /* fall back on rpc methods if the ADS methods fail */ ret = rpc_dc_name(domain, srv_name, &dc_ip); } - + *ip_out = dc_ip; return ret; diff --git a/source3/libsmb/nmblib.c b/source3/libsmb/nmblib.c index 6ee05f0104..ff38245435 100644 --- a/source3/libsmb/nmblib.c +++ b/source3/libsmb/nmblib.c @@ -310,21 +310,24 @@ static int put_nmb_name(char *buf,int offset,struct nmb_name *name) } /******************************************************************* - useful for debugging messages - ******************************************************************/ + Useful for debugging messages. +******************************************************************/ + char *nmb_namestr(struct nmb_name *n) { - static int i=0; - static fstring ret[4]; - char *p = ret[i]; - - if (!n->scope[0]) - slprintf(p,sizeof(fstring)-1, "%s<%02x>",n->name,n->name_type); - else - slprintf(p,sizeof(fstring)-1, "%s<%02x>.%s",n->name,n->name_type,n->scope); - - i = (i+1)%4; - return(p); + static int i=0; + static fstring ret[4]; + fstring name; + char *p = ret[i]; + + pull_ascii_fstring(name, n->name); + if (!n->scope[0]) + slprintf(p,sizeof(fstring)-1, "%s<%02x>",name,n->name_type); + else + slprintf(p,sizeof(fstring)-1, "%s<%02x>.%s",name,n->name_type,n->scope); + + i = (i+1)%4; + return(p); } /******************************************************************* @@ -820,10 +823,9 @@ static int build_dgram(char *buf,struct packet_struct *p) void make_nmb_name( struct nmb_name *n, const char *name, int type) { memset( (char *)n, '\0', sizeof(struct nmb_name) ); - push_ascii(n->name, name, 16, STR_TERMINATE|STR_UPPER); + push_ascii(n->name, name, sizeof(n->name), STR_TERMINATE|STR_UPPER); n->name_type = (unsigned int)type & 0xFF; - StrnCpy( n->scope, global_scope(), 63 ); - strupper_m( n->scope ); + push_ascii(n->scope, global_scope(), 64, STR_TERMINATE); } /******************************************************************* diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index a50ae9b70f..42bf18d1d2 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -140,7 +140,7 @@ static NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state, &cliname, &domname)) { DEBUG(1, ("ntlmssp_server_negotiate: failed to parse NTLMSSP:\n")); - dump_data(2, request.data, request.length); + dump_data(2, (const char *)request.data, request.length); return NT_STATUS_INVALID_PARAMETER; } @@ -172,6 +172,9 @@ static NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state, target_name = ntlmssp_target_name(ntlmssp_state, neg_flags, &chal_flags); + if (target_name == NULL) + return NT_STATUS_INVALID_PARAMETER; + /* This should be a 'netbios domain -> DNS domain' mapping */ dnsdomname[0] = '\0'; get_mydomname(dnsdomname); @@ -273,7 +276,7 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state, &sess_key, &neg_flags)) { DEBUG(1, ("ntlmssp_server_auth: failed to parse NTLMSSP:\n")); - dump_data(2, request.data, request.length); + dump_data(2, (const char *)request.data, request.length); return NT_STATUS_INVALID_PARAMETER; } @@ -412,6 +415,8 @@ static NTSTATUS ntlmssp_client_initial(struct ntlmssp_client_state *ntlmssp_stat if (ntlmssp_state->use_ntlmv2) { ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_NTLM2; } + + ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_NTLM2; /* generate the ntlmssp negotiate packet */ msrpc_gen(next_request, "CddAA", @@ -446,16 +451,7 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st DATA_BLOB lm_response = data_blob(NULL, 0); DATA_BLOB nt_response = data_blob(NULL, 0); DATA_BLOB session_key = data_blob(NULL, 0); - uint8 datagram_sess_key[16]; - size_t datagram_sess_key_len; - -#if 0 /* until we know what flag to tigger it on */ - generate_random_buffer(datagram_sess_key, sizeof(datagram_sess_key), False); - datagram_sess_key_len = sizeof(datagram_sess_key); -#else - ZERO_STRUCT(datagram_sess_key); - datagram_sess_key_len = 0; -#endif + DATA_BLOB encrypted_session_key = data_blob(NULL, 0); if (!msrpc_parse(&reply, "CdBd", "NTLMSSP", @@ -463,7 +459,7 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st &server_domain_blob, &chal_flags)) { DEBUG(1, ("Failed to parse the NTLMSSP Challenge: (#1)\n")); - dump_data(2, reply.data, reply.length); + dump_data(2, (const char *)reply.data, reply.length); return NT_STATUS_INVALID_PARAMETER; } @@ -489,7 +485,9 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st } else { chal_parse_string = "CdAdbdd"; } + auth_gen_string = "CdBBAAABd"; + ntlmssp_state->unicode = False; ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_UNICODE; ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_OEM; @@ -513,6 +511,10 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_128; } + if (!(chal_flags & NTLMSSP_NEGOTIATE_KEY_EXCH)) { + ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_KEY_EXCH; + } + DEBUG(3, ("NTLMSSP: Set final flags:\n")); debug_ntlmssp_flags(ntlmssp_state->neg_flags); @@ -525,17 +527,22 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st &unkn1, &unkn2, &struct_blob)) { DEBUG(1, ("Failed to parse the NTLMSSP Challenge: (#2)\n")); - dump_data(2, reply.data, reply.length); + dump_data(2, (const char *)reply.data, reply.length); return NT_STATUS_INVALID_PARAMETER; } + ntlmssp_state->server_domain = talloc_strdup(ntlmssp_state->mem_ctx, + server_domain); + SAFE_FREE(server_domain); if (challenge_blob.length != 8) { data_blob_free(&struct_blob); return NT_STATUS_INVALID_PARAMETER; } - if (ntlmssp_state->use_ntlmv2) { + if (!ntlmssp_state->password) { + /* do nothing - blobs are zero length */ + } else if (ntlmssp_state->use_ntlmv2) { if (!struct_blob.length) { /* be lazy, match win2k - we can't do NTLMv2 without it */ @@ -554,7 +561,38 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st data_blob_free(&struct_blob); return NT_STATUS_NO_MEMORY; } + } else if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) { + struct MD5Context md5_session_nonce_ctx; + uchar nt_hash[16]; + uchar session_nonce[16]; + uchar session_nonce_hash[16]; + uchar nt_session_key[16]; + E_md4hash(ntlmssp_state->password, nt_hash); + + lm_response = data_blob(NULL, 24); + generate_random_buffer(lm_response.data, 8, False); + memset(lm_response.data+8, 0, 16); + + memcpy(session_nonce, challenge_blob.data, 8); + memcpy(&session_nonce[8], lm_response.data, 8); + + MD5Init(&md5_session_nonce_ctx); + MD5Update(&md5_session_nonce_ctx, challenge_blob.data, 8); + MD5Update(&md5_session_nonce_ctx, lm_response.data, 8); + MD5Final(session_nonce_hash, &md5_session_nonce_ctx); + + nt_response = data_blob(NULL, 24); + SMBNTencrypt(ntlmssp_state->password, + session_nonce_hash, + nt_response.data); + + session_key = data_blob(NULL, 16); + + SMBsesskeygen_ntv1(nt_hash, NULL, nt_session_key); + hmac_md5(nt_session_key, session_nonce, sizeof(session_nonce), session_key.data); } else { + + uchar lm_hash[16]; uchar nt_hash[16]; E_deshash(ntlmssp_state->password, lm_hash); @@ -565,15 +603,15 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st lm_response = data_blob(NULL, 24); SMBencrypt(ntlmssp_state->password,challenge_blob.data, lm_response.data); - } + } nt_response = data_blob(NULL, 24); SMBNTencrypt(ntlmssp_state->password,challenge_blob.data, nt_response.data); - + session_key = data_blob(NULL, 16); if ((ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_LM_KEY) - && lp_client_lanman_auth()) { + && lp_client_lanman_auth()) { SMBsesskeygen_lmv1(lm_hash, lm_response.data, session_key.data); } else { @@ -582,6 +620,18 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st } data_blob_free(&struct_blob); + /* Key exchange encryptes a new client-generated session key with + the password-derived key */ + if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) { + uint8 client_session_key[16]; + + generate_random_buffer(client_session_key, sizeof(client_session_key), False); + encrypted_session_key = data_blob(client_session_key, sizeof(client_session_key)); + SamOEMhash(encrypted_session_key.data, session_key.data, encrypted_session_key.length); + data_blob_free(&session_key); + session_key = data_blob(client_session_key, sizeof(client_session_key)); + } + /* this generates the actual auth packet */ if (!msrpc_gen(next_request, auth_gen_string, "NTLMSSP", @@ -591,7 +641,7 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st ntlmssp_state->domain, ntlmssp_state->user, ntlmssp_state->get_global_myname(), - datagram_sess_key, datagram_sess_key_len, + encrypted_session_key.data, encrypted_session_key.length, ntlmssp_state->neg_flags)) { data_blob_free(&lm_response); @@ -600,6 +650,8 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_client_state *ntlmssp_st return NT_STATUS_NO_MEMORY; } + data_blob_free(&encrypted_session_key); + data_blob_free(&ntlmssp_state->chal); data_blob_free(&ntlmssp_state->lm_resp); data_blob_free(&ntlmssp_state->nt_resp); @@ -638,6 +690,8 @@ NTSTATUS ntlmssp_client_start(NTLMSSP_CLIENT_STATE **ntlmssp_state) (*ntlmssp_state)->neg_flags = NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_NTLM | + NTLMSSP_NEGOTIATE_NTLM2 | + NTLMSSP_NEGOTIATE_KEY_EXCH | NTLMSSP_REQUEST_TARGET; (*ntlmssp_state)->ref_count = 1; @@ -706,9 +760,13 @@ NTSTATUS ntlmssp_set_username(NTLMSSP_CLIENT_STATE *ntlmssp_state, const char *u NTSTATUS ntlmssp_set_password(NTLMSSP_CLIENT_STATE *ntlmssp_state, const char *password) { - ntlmssp_state->password = talloc_strdup(ntlmssp_state->mem_ctx, password); - if (!ntlmssp_state->password) { - return NT_STATUS_NO_MEMORY; + if (!password) { + ntlmssp_state->password = NULL; + } else { + ntlmssp_state->password = talloc_strdup(ntlmssp_state->mem_ctx, password); + if (!ntlmssp_state->password) { + return NT_STATUS_NO_MEMORY; + } } return NT_STATUS_OK; } diff --git a/source3/libsmb/ntlmssp_parse.c b/source3/libsmb/ntlmssp_parse.c index 3c6da349e4..60cb4ab04a 100644 --- a/source3/libsmb/ntlmssp_parse.c +++ b/source3/libsmb/ntlmssp_parse.c @@ -153,7 +153,8 @@ BOOL msrpc_gen(DATA_BLOB *blob, SSVAL(blob->data, head_ofs, n); head_ofs += 2; SSVAL(blob->data, head_ofs, n); head_ofs += 2; SIVAL(blob->data, head_ofs, data_ofs); head_ofs += 4; - memcpy(blob->data+data_ofs, b, n); + if (n && b) /* don't follow null pointers... */ + memcpy(blob->data+data_ofs, b, n); data_ofs += n; break; case 'd': diff --git a/source3/libsmb/ntlmssp_sign.c b/source3/libsmb/ntlmssp_sign.c index ecaef808c9..ff2f97c2e8 100644 --- a/source3/libsmb/ntlmssp_sign.c +++ b/source3/libsmb/ntlmssp_sign.c @@ -91,8 +91,8 @@ static void calc_ntlmv2_hash(unsigned char hash[16], char digest[16], MD5Init(&ctx3); MD5Update(&ctx3, session_key.data, session_key.length); - MD5Update(&ctx3, constant, strlen(constant)); - MD5Final(digest, &ctx3); + MD5Update(&ctx3, (const unsigned char *)constant, strlen(constant)); + MD5Final((unsigned char *)digest, &ctx3); calc_hash(hash, digest, 16); } @@ -113,8 +113,8 @@ static NTSTATUS ntlmssp_make_packet_signature(NTLMSSP_CLIENT_STATE *ntlmssp_stat uchar digest[16]; SIVAL(seq_num, 0, ntlmssp_state->ntlmssp_seq_num); - hmac_md5_init_limK_to_64(ntlmssp_state->cli_sign_const, 16, &ctx); - hmac_md5_update(seq_num, 4, &ctx); + hmac_md5_init_limK_to_64((const unsigned char *)(ntlmssp_state->cli_sign_const), 16, &ctx); + hmac_md5_update((const unsigned char *)seq_num, 4, &ctx); hmac_md5_update(data, length, &ctx); hmac_md5_final(digest, &ctx); @@ -132,7 +132,7 @@ static NTSTATUS ntlmssp_make_packet_signature(NTLMSSP_CLIENT_STATE *ntlmssp_stat } } else { uint32 crc; - crc = crc32_calc_buffer(data, length); + crc = crc32_calc_buffer((const char *)data, length); if (!msrpc_gen(sig, "dddd", NTLMSSP_SIGN_VERSION, 0, crc, ntlmssp_state->ntlmssp_seq_num)) { return NT_STATUS_NO_MEMORY; } @@ -183,10 +183,10 @@ NTSTATUS ntlmssp_client_check_packet(NTLMSSP_CLIENT_STATE *ntlmssp_state, if (memcmp(sig->data+sig->length - 8, local_sig.data+local_sig.length - 8, 8) != 0) { DEBUG(5, ("BAD SIG: wanted signature of\n")); - dump_data(5, local_sig.data, local_sig.length); + dump_data(5, (const char *)local_sig.data, local_sig.length); DEBUG(5, ("BAD SIG: got signature of\n")); - dump_data(5, sig->data, sig->length); + dump_data(5, (const char *)(sig->data), sig->length); DEBUG(0, ("NTLMSSP packet check failed due to invalid signature!\n")); return NT_STATUS_ACCESS_DENIED; @@ -216,8 +216,8 @@ NTSTATUS ntlmssp_client_seal_packet(NTLMSSP_CLIENT_STATE *ntlmssp_state, uchar digest[16]; SIVAL(seq_num, 0, ntlmssp_state->ntlmssp_seq_num); - hmac_md5_init_limK_to_64(ntlmssp_state->cli_sign_const, 16, &ctx); - hmac_md5_update(seq_num, 4, &ctx); + hmac_md5_init_limK_to_64((const unsigned char *)(ntlmssp_state->cli_sign_const), 16, &ctx); + hmac_md5_update((const unsigned char *)seq_num, 4, &ctx); hmac_md5_update(data, length, &ctx); hmac_md5_final(digest, &ctx); @@ -236,7 +236,7 @@ NTSTATUS ntlmssp_client_seal_packet(NTLMSSP_CLIENT_STATE *ntlmssp_state, NTLMSSPcalc_ap(ntlmssp_state->cli_sign_hash, sig->data+4, sig->length-4); } else { uint32 crc; - crc = crc32_calc_buffer(data, length); + crc = crc32_calc_buffer((const char *)data, length); if (!msrpc_gen(sig, "dddd", NTLMSSP_SIGN_VERSION, 0, crc, ntlmssp_state->ntlmssp_seq_num)) { return NT_STATUS_NO_MEMORY; } @@ -335,7 +335,7 @@ NTSTATUS ntlmssp_client_sign_init(NTLMSSP_CLIENT_STATE *ntlmssp_state) DEBUG(5, ("NTLMSSP Sign/Seal - using LM KEY\n")); - calc_hash(ntlmssp_state->ntlmssp_hash, ntlmssp_state->session_key.data, 8); + calc_hash(ntlmssp_state->ntlmssp_hash, (const char *)(ntlmssp_state->session_key.data), 8); dump_data_pw("NTLMSSP hash:\n", ntlmssp_state->ntlmssp_hash, sizeof(ntlmssp_state->ntlmssp_hash)); } else { @@ -347,7 +347,7 @@ NTSTATUS ntlmssp_client_sign_init(NTLMSSP_CLIENT_STATE *ntlmssp_state) DEBUG(5, ("NTLMSSP Sign/Seal - using NT KEY\n")); - calc_hash(ntlmssp_state->ntlmssp_hash, ntlmssp_state->session_key.data, 16); + calc_hash(ntlmssp_state->ntlmssp_hash, (const char *)(ntlmssp_state->session_key.data), 16); dump_data_pw("NTLMSSP hash:\n", ntlmssp_state->ntlmssp_hash, sizeof(ntlmssp_state->ntlmssp_hash)); } diff --git a/source3/libsmb/smb_signing.c b/source3/libsmb/smb_signing.c index 4167452953..08ff655a3f 100644 --- a/source3/libsmb/smb_signing.c +++ b/source3/libsmb/smb_signing.c @@ -25,6 +25,7 @@ struct outstanding_packet_lookup { uint16 mid; uint32 reply_seq_num; + BOOL deferred_packet; struct outstanding_packet_lookup *prev, *next; }; @@ -43,7 +44,7 @@ struct smb_basic_signing_context { }; static void store_sequence_for_reply(struct outstanding_packet_lookup **list, - uint16 mid, uint32 reply_seq_num) + uint16 mid, uint32 reply_seq_num, BOOL deferred_pkt) { struct outstanding_packet_lookup *t; struct outstanding_packet_lookup *tmp; @@ -54,19 +55,25 @@ static void store_sequence_for_reply(struct outstanding_packet_lookup **list, DLIST_ADD_END(*list, t, tmp); t->mid = mid; t->reply_seq_num = reply_seq_num; - DEBUG(10,("store_sequence_for_reply: stored seq = %u mid = %u\n", + t->deferred_packet = deferred_pkt; + + DEBUG(10,("store_sequence_for_reply: stored %sseq = %u mid = %u\n", + deferred_pkt ? "deferred " : "", (unsigned int)reply_seq_num, (unsigned int)mid )); } static BOOL get_sequence_for_reply(struct outstanding_packet_lookup **list, - uint16 mid, uint32 *reply_seq_num) + uint16 mid, uint32 *reply_seq_num, BOOL *def) { struct outstanding_packet_lookup *t; for (t = *list; t; t = t->next) { if (t->mid == mid) { *reply_seq_num = t->reply_seq_num; - DEBUG(10,("get_sequence_for_reply: found seq = %u mid = %u\n", + if (def) + *def = t->deferred_packet; + DEBUG(10,("get_sequence_for_reply: found %sseq = %u mid = %u\n", + (t->deferred_packet) ? "deferred " : "", (unsigned int)t->reply_seq_num, (unsigned int)t->mid )); DLIST_REMOVE(*list, t); SAFE_FREE(t); @@ -76,6 +83,22 @@ static BOOL get_sequence_for_reply(struct outstanding_packet_lookup **list, return False; } +/*********************************************************** + A reply is pending if there is a non-deferred packet on the queue. +************************************************************/ + +static BOOL is_reply_pending(struct outstanding_packet_lookup *list) +{ + for (; list; list = list->next) { + if (!list->deferred_packet) { + DEBUG(10,("is_reply_pending: True.\n")); + return True; + } + } + DEBUG(10,("is_reply_pending: False.\n")); + return False; +} + /*********************************************************** SMB signing - Common code before we set a new signing implementation ************************************************************/ @@ -188,7 +211,7 @@ static void free_signing_context(struct smb_sign_info *si) } -static BOOL signing_good(char *inbuf, struct smb_sign_info *si, BOOL good) +static BOOL signing_good(char *inbuf, struct smb_sign_info *si, BOOL good, uint32 seq) { if (good && !si->doing_signing) { si->doing_signing = True; @@ -200,7 +223,8 @@ static BOOL signing_good(char *inbuf, struct smb_sign_info *si, BOOL good) /* W2K sends a bad first signature but the sign engine is on.... JRA. */ if (data->send_seq_num > 1) - DEBUG(1, ("signing_good: SMB signature check failed!\n")); + DEBUG(1, ("signing_good: SMB signature check failed on seq %u!\n", + (unsigned int)seq )); return False; } else { @@ -290,10 +314,10 @@ static void client_sign_outgoing_message(char *outbuf, struct smb_sign_info *si) else send_seq_num = data->send_seq_num; - simple_packet_signature(data, outbuf, send_seq_num, calc_md5_mac); + simple_packet_signature(data, (const unsigned char *)outbuf, send_seq_num, calc_md5_mac); DEBUG(10, ("client_sign_outgoing_message: sent SMB signature of\n")); - dump_data(10, calc_md5_mac, 8); + dump_data(10, (const char *)calc_md5_mac, 8); memcpy(&outbuf[smb_ss_field], calc_md5_mac, 8); @@ -306,7 +330,7 @@ static void client_sign_outgoing_message(char *outbuf, struct smb_sign_info *si) data->send_seq_num++; store_sequence_for_reply(&data->outstanding_packet_list, SVAL(outbuf,smb_mid), - data->send_seq_num); + data->send_seq_num, False); data->send_seq_num++; } @@ -318,6 +342,7 @@ static BOOL client_check_incoming_message(char *inbuf, struct smb_sign_info *si) { BOOL good; uint32 reply_seq_number; + uint32 saved_seq; unsigned char calc_md5_mac[16]; unsigned char *server_sent_mac; @@ -335,29 +360,30 @@ static BOOL client_check_incoming_message(char *inbuf, struct smb_sign_info *si) reply_seq_number = data->trans_info->reply_seq_num; } else if (!get_sequence_for_reply(&data->outstanding_packet_list, SVAL(inbuf, smb_mid), - &reply_seq_number)) { + &reply_seq_number, NULL)) { DEBUG(1, ("client_check_incoming_message: failed to get sequence number %u for reply.\n", (unsigned int) SVAL(inbuf, smb_mid) )); return False; } - simple_packet_signature(data, inbuf, reply_seq_number, calc_md5_mac); + saved_seq = reply_seq_number; + simple_packet_signature(data, (const unsigned char *)inbuf, reply_seq_number, calc_md5_mac); - server_sent_mac = &inbuf[smb_ss_field]; + server_sent_mac = (unsigned char *)&inbuf[smb_ss_field]; good = (memcmp(server_sent_mac, calc_md5_mac, 8) == 0); if (!good) { DEBUG(5, ("client_check_incoming_message: BAD SIG: wanted SMB signature of\n")); - dump_data(5, calc_md5_mac, 8); + dump_data(5, (const char *)calc_md5_mac, 8); DEBUG(5, ("client_check_incoming_message: BAD SIG: got SMB signature of\n")); - dump_data(5, server_sent_mac, 8); + dump_data(5, (const char *)server_sent_mac, 8); #if 1 /* JRATEST */ { int i; reply_seq_number -= 5; for (i = 0; i < 10; i++, reply_seq_number++) { - simple_packet_signature(data, inbuf, reply_seq_number, calc_md5_mac); + simple_packet_signature(data, (const unsigned char *)inbuf, reply_seq_number, calc_md5_mac); if (memcmp(server_sent_mac, calc_md5_mac, 8) == 0) { DEBUG(0,("client_check_incoming_message: out of seq. seq num %u matches.\n", reply_seq_number )); @@ -369,9 +395,9 @@ static BOOL client_check_incoming_message(char *inbuf, struct smb_sign_info *si) } else { DEBUG(10, ("client_check_incoming_message:: seq %u: got good SMB signature of\n", (unsigned int)reply_seq_number)); - dump_data(10, server_sent_mac, 8); + dump_data(10, (const char *)server_sent_mac, 8); } - return signing_good(inbuf, si, good); + return signing_good(inbuf, si, good, saved_seq); } /*********************************************************** @@ -428,12 +454,12 @@ BOOL cli_simple_set_signing(struct cli_state *cli, const uchar user_session_key[ memcpy(&data->mac_key.data[0], user_session_key, 16); DEBUG(10, ("cli_simple_set_signing: user_session_key\n")); - dump_data(10, user_session_key, 16); + dump_data(10, (const char *)user_session_key, 16); if (response.length) { memcpy(&data->mac_key.data[16],response.data, response.length); DEBUG(10, ("cli_simple_set_signing: response_data\n")); - dump_data(10, response.data, response.length); + dump_data(10, (const char *)response.data, response.length); } else { DEBUG(10, ("cli_simple_set_signing: NULL response_data\n")); } @@ -584,17 +610,6 @@ BOOL cli_check_sign_mac(struct cli_state *cli) return True; } -static BOOL packet_is_oplock_break(char *buf) -{ - if (CVAL(buf,smb_com) != SMBlockingX) - return False; - - if (CVAL(buf,smb_vwv3) != LOCKING_ANDX_OPLOCK_RELEASE) - return False; - - return True; -} - /*********************************************************** SMB signing - Server implementation - send the MAC. ************************************************************/ @@ -608,25 +623,6 @@ static void srv_sign_outgoing_message(char *outbuf, struct smb_sign_info *si) uint16 mid; if (!si->doing_signing) { - if (si->allow_smb_signing && si->negotiated_smb_signing) { - mid = SVAL(outbuf, smb_mid); - - was_deferred_packet = get_sequence_for_reply(&data->outstanding_packet_list, - mid, &send_seq_number); - if (!was_deferred_packet) { - /* - * Is this an outgoing oplock break ? If so, store the - * mid in the outstanding list. - */ - - if (packet_is_oplock_break(outbuf)) { - store_sequence_for_reply(&data->outstanding_packet_list, - mid, data->send_seq_num); - } - - data->send_seq_num++; - } - } return; } @@ -643,7 +639,7 @@ static void srv_sign_outgoing_message(char *outbuf, struct smb_sign_info *si) mid = SVAL(outbuf, smb_mid); /* See if this is a reply for a deferred packet. */ - was_deferred_packet = get_sequence_for_reply(&data->outstanding_packet_list, mid, &send_seq_number); + get_sequence_for_reply(&data->outstanding_packet_list, mid, &send_seq_number, &was_deferred_packet); if (data->trans_info && (data->trans_info->mid == mid)) { /* This is a reply in a trans stream. Use the sequence @@ -651,10 +647,10 @@ static void srv_sign_outgoing_message(char *outbuf, struct smb_sign_info *si) send_seq_number = data->trans_info->send_seq_num; } - simple_packet_signature(data, outbuf, send_seq_number, calc_md5_mac); + simple_packet_signature(data, (const unsigned char *)outbuf, send_seq_number, calc_md5_mac); DEBUG(10, ("srv_sign_outgoing_message: seq %u: sent SMB signature of\n", (unsigned int)send_seq_number)); - dump_data(10, calc_md5_mac, 8); + dump_data(10, (const char *)calc_md5_mac, 8); memcpy(&outbuf[smb_ss_field], calc_md5_mac, 8); @@ -662,7 +658,7 @@ static void srv_sign_outgoing_message(char *outbuf, struct smb_sign_info *si) Uncomment this to test if the remote server actually verifies signatures...*/ if (!was_deferred_packet) { - if (!data->trans_info) { + if (!data->trans_info) { /* Always increment if not in a trans stream. */ data->send_seq_num++; } else if ((data->trans_info->send_seq_num == data->send_seq_num) || (data->trans_info->mid != mid)) { @@ -670,7 +666,23 @@ static void srv_sign_outgoing_message(char *outbuf, struct smb_sign_info *si) * packet that doesn't belong to this stream (different mid). */ data->send_seq_num++; } - } + } +} + +/*********************************************************** + Is an incoming packet an oplock break reply ? +************************************************************/ + +static BOOL is_oplock_break(char *inbuf) +{ + if (CVAL(inbuf,smb_com) != SMBlockingX) + return False; + + if (!(CVAL(inbuf,smb_vwv3) & LOCKING_ANDX_OPLOCK_RELEASE)) + return False; + + DEBUG(10,("is_oplock_break: Packet is oplock break\n")); + return True; } /*********************************************************** @@ -682,6 +694,7 @@ static BOOL srv_check_incoming_message(char *inbuf, struct smb_sign_info *si) BOOL good; struct smb_basic_signing_context *data = si->signing_context; uint32 reply_seq_number = data->send_seq_num; + uint32 saved_seq; unsigned char calc_md5_mac[16]; unsigned char *server_sent_mac; uint mid; @@ -703,30 +716,37 @@ static BOOL srv_check_incoming_message(char *inbuf, struct smb_sign_info *si) } else { /* We always increment the sequence number. */ data->send_seq_num++; - /* Oplock break requests store an outgoing mid in the packet list. */ - if (packet_is_oplock_break(inbuf)) - get_sequence_for_reply(&data->outstanding_packet_list, mid, &reply_seq_number); + + /* If we get an asynchronous oplock break reply and there + * isn't a reply pending we need to re-sync the sequence + * number. + */ + if (is_oplock_break(inbuf) && !is_reply_pending(data->outstanding_packet_list)) + data->send_seq_num++; } - simple_packet_signature(data, inbuf, reply_seq_number, calc_md5_mac); + saved_seq = reply_seq_number; + simple_packet_signature(data, (const unsigned char *)inbuf, reply_seq_number, calc_md5_mac); - server_sent_mac = &inbuf[smb_ss_field]; + server_sent_mac = (unsigned char *)&inbuf[smb_ss_field]; good = (memcmp(server_sent_mac, calc_md5_mac, 8) == 0); if (!good) { - DEBUG(5, ("srv_check_incoming_message: BAD SIG: wanted SMB signature of\n")); - dump_data(5, calc_md5_mac, 8); + DEBUG(5, ("srv_check_incoming_message: BAD SIG: seq %u wanted SMB signature of\n", + (unsigned int)saved_seq)); + dump_data(5, (const char *)calc_md5_mac, 8); - DEBUG(5, ("srv_check_incoming_message: BAD SIG: got SMB signature of\n")); - dump_data(5, server_sent_mac, 8); + DEBUG(5, ("srv_check_incoming_message: BAD SIG: seq %u got SMB signature of\n", + (unsigned int)saved_seq)); + dump_data(5, (const char *)server_sent_mac, 8); #if 1 /* JRATEST */ { int i; reply_seq_number -= 5; for (i = 0; i < 10; i++, reply_seq_number++) { - simple_packet_signature(data, inbuf, reply_seq_number, calc_md5_mac); + simple_packet_signature(data, (const unsigned char *)inbuf, reply_seq_number, calc_md5_mac); if (memcmp(server_sent_mac, calc_md5_mac, 8) == 0) { DEBUG(0,("srv_check_incoming_message: out of seq. seq num %u matches.\n", reply_seq_number )); @@ -737,10 +757,10 @@ static BOOL srv_check_incoming_message(char *inbuf, struct smb_sign_info *si) #endif /* JRATEST */ } else { - DEBUG(10, ("srv_check_incoming_message: seq %u: got good SMB signature of\n", (unsigned int)reply_seq_number)); - dump_data(10, server_sent_mac, 8); + DEBUG(10, ("srv_check_incoming_message: seq %u: (current is %u) got good SMB signature of\n", (unsigned int)reply_seq_number, (unsigned int)data->send_seq_num)); + dump_data(10, (const char *)server_sent_mac, 8); } - return signing_good(inbuf, si, good); + return signing_good(inbuf, si, good, saved_seq); } /*********************************************************** @@ -800,7 +820,7 @@ void srv_calculate_sign_mac(char *outbuf) Called by server to defer an outgoing packet. ************************************************************/ -void srv_defer_sign_response(uint16 mid) +void srv_defer_sign_response(uint16 mid, BOOL deferred_packet) { struct smb_basic_signing_context *data; @@ -813,7 +833,7 @@ void srv_defer_sign_response(uint16 mid) return; store_sequence_for_reply(&data->outstanding_packet_list, - mid, data->send_seq_num); + mid, data->send_seq_num, deferred_packet); data->send_seq_num++; } @@ -837,7 +857,7 @@ void srv_cancel_sign_response(uint16 mid) DEBUG(10,("srv_cancel_sign_response: for mid %u\n", (unsigned int)mid )); - while (get_sequence_for_reply(&data->outstanding_packet_list, mid, &dummy_seq)) + while (get_sequence_for_reply(&data->outstanding_packet_list, mid, &dummy_seq,NULL)) ; } diff --git a/source3/libsmb/smbencrypt.c b/source3/libsmb/smbencrypt.c index 7a1a2d7d18..ec31bb5dba 100644 --- a/source3/libsmb/smbencrypt.c +++ b/source3/libsmb/smbencrypt.c @@ -81,7 +81,7 @@ void E_deshash(const char *passwd, uchar p16[16]) push_ascii(dospwd, passwd, sizeof(dospwd), STR_UPPER|STR_TERMINATE); /* Only the fisrt 14 chars are considered, password need not be null terminated. */ - E_P16(dospwd, p16); + E_P16((const unsigned char *)dospwd, p16); ZERO_STRUCT(dospwd); } @@ -247,7 +247,7 @@ BOOL make_oem_passwd_hash(char data[516], const char *passwd, uchar old_pw_hash[ return True; } -/* Does the md5 encryption from the NT hash for NTLMv2. */ +/* Does the md5 encryption from the Key Response for NTLMv2. */ void SMBOWFencrypt_ntv2(const uchar kr[16], const DATA_BLOB *srv_chal, const DATA_BLOB *cli_chal, diff --git a/source3/libsmb/spnego.c b/source3/libsmb/spnego.c new file mode 100644 index 0000000000..50caf7b4c0 --- /dev/null +++ b/source3/libsmb/spnego.c @@ -0,0 +1,343 @@ +/* + Unix SMB/CIFS implementation. + + RFC2478 Compliant SPNEGO implementation + + Copyright (C) Jim McDonough 2003 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_AUTH + +static BOOL read_negTokenInit(ASN1_DATA *asn1, negTokenInit_t *token) +{ + ZERO_STRUCTP(token); + + asn1_start_tag(asn1, ASN1_CONTEXT(0)); + asn1_start_tag(asn1, ASN1_SEQUENCE(0)); + + while (!asn1->has_error && 0 < asn1_tag_remaining(asn1)) { + int i; + + switch (asn1->data[asn1->ofs]) { + /* Read mechTypes */ + case ASN1_CONTEXT(0): + asn1_start_tag(asn1, ASN1_CONTEXT(0)); + asn1_start_tag(asn1, ASN1_SEQUENCE(0)); + + token->mechTypes = malloc(sizeof(*token->mechTypes)); + for (i = 0; !asn1->has_error && + 0 < asn1_tag_remaining(asn1); i++) { + token->mechTypes = + realloc(token->mechTypes, (i + 2) * + sizeof(*token->mechTypes)); + asn1_read_OID(asn1, token->mechTypes + i); + } + token->mechTypes[i] = NULL; + + asn1_end_tag(asn1); + asn1_end_tag(asn1); + break; + /* Read reqFlags */ + case ASN1_CONTEXT(1): + asn1_start_tag(asn1, ASN1_CONTEXT(1)); + asn1_read_Integer(asn1, &token->reqFlags); + token->reqFlags |= SPNEGO_REQ_FLAG; + asn1_end_tag(asn1); + break; + /* Read mechToken */ + case ASN1_CONTEXT(2): + asn1_start_tag(asn1, ASN1_CONTEXT(2)); + asn1_read_OctetString(asn1, &token->mechToken); + asn1_end_tag(asn1); + break; + /* Read mecListMIC */ + case ASN1_CONTEXT(3): + asn1_start_tag(asn1, ASN1_CONTEXT(3)); + if (asn1->data[asn1->ofs] == ASN1_OCTET_STRING) { + asn1_read_OctetString(asn1, + &token->mechListMIC); + } else { + /* RFC 2478 says we have an Octet String here, + but W2k sends something different... */ + char *mechListMIC; + asn1_push_tag(asn1, ASN1_SEQUENCE(0)); + asn1_push_tag(asn1, ASN1_CONTEXT(0)); + asn1_read_GeneralString(asn1, &mechListMIC); + asn1_pop_tag(asn1); + asn1_pop_tag(asn1); + + token->mechListMIC = + data_blob(mechListMIC, strlen(mechListMIC)); + SAFE_FREE(mechListMIC); + } + asn1_end_tag(asn1); + break; + default: + asn1->has_error = True; + break; + } + } + + asn1_end_tag(asn1); + asn1_end_tag(asn1); + + return !asn1->has_error; +} + +static BOOL write_negTokenInit(ASN1_DATA *asn1, negTokenInit_t *token) +{ + asn1_push_tag(asn1, ASN1_CONTEXT(0)); + asn1_push_tag(asn1, ASN1_SEQUENCE(0)); + + /* Write mechTypes */ + if (token->mechTypes && *token->mechTypes) { + int i; + + asn1_push_tag(asn1, ASN1_CONTEXT(0)); + asn1_push_tag(asn1, ASN1_SEQUENCE(0)); + for (i = 0; token->mechTypes[i]; i++) { + asn1_write_OID(asn1, token->mechTypes[i]); + } + asn1_pop_tag(asn1); + asn1_pop_tag(asn1); + } + + /* write reqFlags */ + if (token->reqFlags & SPNEGO_REQ_FLAG) { + int flags = token->reqFlags & ~SPNEGO_REQ_FLAG; + + asn1_push_tag(asn1, ASN1_CONTEXT(1)); + asn1_write_Integer(asn1, flags); + asn1_pop_tag(asn1); + } + + /* write mechToken */ + if (token->mechToken.data) { + asn1_push_tag(asn1, ASN1_CONTEXT(2)); + asn1_write_OctetString(asn1, token->mechToken.data, + token->mechToken.length); + asn1_pop_tag(asn1); + } + + /* write mechListMIC */ + if (token->mechListMIC.data) { + asn1_push_tag(asn1, ASN1_CONTEXT(3)); +#if 0 + /* This is what RFC 2478 says ... */ + asn1_write_OctetString(asn1, token->mechListMIC.data, + token->mechListMIC.length); +#else + /* ... but unfortunately this is what Windows + sends/expects */ + asn1_push_tag(asn1, ASN1_SEQUENCE(0)); + asn1_push_tag(asn1, ASN1_CONTEXT(0)); + asn1_push_tag(asn1, ASN1_GENERAL_STRING); + asn1_write(asn1, token->mechListMIC.data, + token->mechListMIC.length); + asn1_pop_tag(asn1); + asn1_pop_tag(asn1); + asn1_pop_tag(asn1); +#endif + asn1_pop_tag(asn1); + } + + asn1_pop_tag(asn1); + asn1_pop_tag(asn1); + + return !asn1->has_error; +} + +static BOOL read_negTokenTarg(ASN1_DATA *asn1, negTokenTarg_t *token) +{ + ZERO_STRUCTP(token); + + asn1_start_tag(asn1, ASN1_CONTEXT(1)); + asn1_start_tag(asn1, ASN1_SEQUENCE(0)); + + while (!asn1->has_error && 0 < asn1_tag_remaining(asn1)) { + switch (asn1->data[asn1->ofs]) { + case ASN1_CONTEXT(0): + asn1_start_tag(asn1, ASN1_CONTEXT(0)); + asn1_start_tag(asn1, ASN1_ENUMERATED); + asn1_read_uint8(asn1, &token->negResult); + asn1_end_tag(asn1); + asn1_end_tag(asn1); + break; + case ASN1_CONTEXT(1): + asn1_start_tag(asn1, ASN1_CONTEXT(1)); + asn1_read_OID(asn1, &token->supportedMech); + asn1_end_tag(asn1); + break; + case ASN1_CONTEXT(2): + asn1_start_tag(asn1, ASN1_CONTEXT(2)); + asn1_read_OctetString(asn1, &token->responseToken); + asn1_end_tag(asn1); + break; + case ASN1_CONTEXT(3): + asn1_start_tag(asn1, ASN1_CONTEXT(3)); + asn1_read_OctetString(asn1, &token->mechListMIC); + asn1_end_tag(asn1); + break; + default: + asn1->has_error = True; + break; + } + } + + asn1_end_tag(asn1); + asn1_end_tag(asn1); + + return !asn1->has_error; +} + +static BOOL write_negTokenTarg(ASN1_DATA *asn1, negTokenTarg_t *token) +{ + asn1_push_tag(asn1, ASN1_CONTEXT(1)); + asn1_push_tag(asn1, ASN1_SEQUENCE(0)); + + asn1_push_tag(asn1, ASN1_CONTEXT(0)); + asn1_write_enumerated(asn1, token->negResult); + asn1_pop_tag(asn1); + + if (token->supportedMech) { + asn1_push_tag(asn1, ASN1_CONTEXT(1)); + asn1_write_OID(asn1, token->supportedMech); + asn1_pop_tag(asn1); + } + + if (token->responseToken.data) { + asn1_push_tag(asn1, ASN1_CONTEXT(2)); + asn1_write_OctetString(asn1, token->responseToken.data, + token->responseToken.length); + asn1_pop_tag(asn1); + } + + if (token->mechListMIC.data) { + asn1_push_tag(asn1, ASN1_CONTEXT(3)); + asn1_write_OctetString(asn1, token->mechListMIC.data, + token->mechListMIC.length); + asn1_pop_tag(asn1); + } + + asn1_pop_tag(asn1); + asn1_pop_tag(asn1); + + return !asn1->has_error; +} + +ssize_t read_spnego_data(DATA_BLOB data, SPNEGO_DATA *token) +{ + ASN1_DATA asn1; + ssize_t ret = -1; + + ZERO_STRUCTP(token); + ZERO_STRUCT(asn1); + asn1_load(&asn1, data); + + switch (asn1.data[asn1.ofs]) { + case ASN1_APPLICATION(0): + asn1_start_tag(&asn1, ASN1_APPLICATION(0)); + asn1_check_OID(&asn1, OID_SPNEGO); + if (read_negTokenInit(&asn1, &token->negTokenInit)) { + token->type = SPNEGO_NEG_TOKEN_INIT; + } + asn1_end_tag(&asn1); + break; + case ASN1_CONTEXT(1): + if (read_negTokenTarg(&asn1, &token->negTokenTarg)) { + token->type = SPNEGO_NEG_TOKEN_TARG; + } + break; + default: + break; + } + + if (!asn1.has_error) ret = asn1.ofs; + asn1_free(&asn1); + + return ret; +} + +ssize_t write_spnego_data(DATA_BLOB *blob, SPNEGO_DATA *spnego) +{ + ASN1_DATA asn1; + ssize_t ret = -1; + + ZERO_STRUCT(asn1); + + switch (spnego->type) { + case SPNEGO_NEG_TOKEN_INIT: + asn1_push_tag(&asn1, ASN1_APPLICATION(0)); + asn1_write_OID(&asn1, OID_SPNEGO); + write_negTokenInit(&asn1, &spnego->negTokenInit); + asn1_pop_tag(&asn1); + break; + case SPNEGO_NEG_TOKEN_TARG: + write_negTokenTarg(&asn1, &spnego->negTokenTarg); + break; + default: + asn1.has_error = True; + break; + } + + if (!asn1.has_error) { + *blob = data_blob(asn1.data, asn1.length); + ret = asn1.ofs; + } + asn1_free(&asn1); + + return ret; +} + +BOOL free_spnego_data(SPNEGO_DATA *spnego) +{ + BOOL ret = True; + + if (!spnego) goto out; + + switch(spnego->type) { + case SPNEGO_NEG_TOKEN_INIT: + if (spnego->negTokenInit.mechTypes) { + int i; + for (i = 0; spnego->negTokenInit.mechTypes[i]; i++) { + free(spnego->negTokenInit.mechTypes[i]); + } + free(spnego->negTokenInit.mechTypes); + } + data_blob_free(&spnego->negTokenInit.mechToken); + data_blob_free(&spnego->negTokenInit.mechListMIC); + break; + case SPNEGO_NEG_TOKEN_TARG: + if (spnego->negTokenTarg.supportedMech) { + free(spnego->negTokenTarg.supportedMech); + } + data_blob_free(&spnego->negTokenTarg.responseToken); + data_blob_free(&spnego->negTokenTarg.mechListMIC); + break; + default: + ret = False; + break; + } + ZERO_STRUCTP(spnego); +out: + return ret; +} + diff --git a/source3/libsmb/trusts_util.c b/source3/libsmb/trusts_util.c index 610f4b3c03..4e02b29f92 100644 --- a/source3/libsmb/trusts_util.c +++ b/source3/libsmb/trusts_util.c @@ -35,16 +35,15 @@ static NTSTATUS just_change_the_password(struct cli_state *cli, TALLOC_CTX *mem_ uint32 sec_channel_type) { NTSTATUS result; - uint32 neg_flags = 0x000001ff; - result = cli_nt_setup_creds(cli, sec_channel_type, orig_trust_passwd_hash, &neg_flags, 2); - - if (!NT_STATUS_IS_OK(result)) { + /* ensure that schannel uses the right domain */ + fstrcpy(cli->domain, lp_workgroup()); + if (! NT_STATUS_IS_OK(result = cli_nt_establish_netlogon(cli, sec_channel_type, orig_trust_passwd_hash))) { DEBUG(3,("just_change_the_password: unable to setup creds (%s)!\n", nt_errstr(result))); return result; } - + result = cli_net_srv_pwset(cli, mem_ctx, global_myname(), new_trust_passwd_hash); if (!NT_STATUS_IS_OK(result)) { diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 4475f1446f..91bc20af90 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -419,10 +419,10 @@ int get_share_modes(connection_struct *conn, struct locking_data *data; int num_share_modes; share_mode_entry *shares = NULL; - + TDB_DATA key = locking_key(dev, inode); *pp_shares = NULL; - dbuf = tdb_fetch(tdb, locking_key(dev, inode)); + dbuf = tdb_fetch(tdb, key); if (!dbuf.dptr) return 0; @@ -469,7 +469,7 @@ int get_share_modes(connection_struct *conn, /* The record has shrunk a bit */ dbuf.dsize -= del_count * sizeof(share_mode_entry); - if (tdb_store(tdb, locking_key(dev, inode), dbuf, TDB_REPLACE) == -1) { + if (tdb_store(tdb, key, dbuf, TDB_REPLACE) == -1) { SAFE_FREE(shares); SAFE_FREE(dbuf.dptr); return 0; @@ -544,12 +544,13 @@ ssize_t del_share_entry( SMB_DEV_T dev, SMB_INO_T inode, int i, del_count=0; share_mode_entry *shares; ssize_t count = 0; + TDB_DATA key = locking_key(dev, inode); if (ppse) *ppse = NULL; /* read in the existing share modes */ - dbuf = tdb_fetch(tdb, locking_key(dev, inode)); + dbuf = tdb_fetch(tdb, key); if (!dbuf.dptr) return -1; @@ -590,10 +591,10 @@ ssize_t del_share_entry( SMB_DEV_T dev, SMB_INO_T inode, /* store it back in the database */ if (data->u.num_share_mode_entries == 0) { - if (tdb_delete(tdb, locking_key(dev, inode)) == -1) + if (tdb_delete(tdb, key) == -1) count = -1; } else { - if (tdb_store(tdb, locking_key(dev, inode), dbuf, TDB_REPLACE) == -1) + if (tdb_store(tdb, key, dbuf, TDB_REPLACE) == -1) count = -1; } } @@ -630,10 +631,11 @@ BOOL set_share_mode(files_struct *fsp, uint16 port, uint16 op_type) struct locking_data *data; char *p=NULL; int size; + TDB_DATA key = locking_key_fsp(fsp); BOOL ret = True; /* read in the existing share modes if any */ - dbuf = tdb_fetch(tdb, locking_key_fsp(fsp)); + dbuf = tdb_fetch(tdb, key); if (!dbuf.dptr) { size_t offset; /* we'll need to create a new record */ @@ -658,7 +660,7 @@ BOOL set_share_mode(files_struct *fsp, uint16 port, uint16 op_type) fill_share_mode(p + sizeof(*data), fsp, port, op_type); dbuf.dptr = p; dbuf.dsize = size; - if (tdb_store(tdb, locking_key_fsp(fsp), dbuf, TDB_REPLACE) == -1) + if (tdb_store(tdb, key, dbuf, TDB_REPLACE) == -1) ret = False; print_share_mode_table((struct locking_data *)p); @@ -688,7 +690,7 @@ BOOL set_share_mode(files_struct *fsp, uint16 port, uint16 op_type) SAFE_FREE(dbuf.dptr); dbuf.dptr = p; dbuf.dsize = size; - if (tdb_store(tdb, locking_key_fsp(fsp), dbuf, TDB_REPLACE) == -1) + if (tdb_store(tdb, key, dbuf, TDB_REPLACE) == -1) ret = False; print_share_mode_table((struct locking_data *)p); SAFE_FREE(p); @@ -709,9 +711,10 @@ static BOOL mod_share_mode( SMB_DEV_T dev, SMB_INO_T inode, share_mode_entry *en share_mode_entry *shares; BOOL need_store=False; BOOL ret = True; + TDB_DATA key = locking_key(dev, inode); /* read in the existing share modes */ - dbuf = tdb_fetch(tdb, locking_key(dev, inode)); + dbuf = tdb_fetch(tdb, key); if (!dbuf.dptr) return False; @@ -729,10 +732,10 @@ static BOOL mod_share_mode( SMB_DEV_T dev, SMB_INO_T inode, share_mode_entry *en /* if the mod fn was called then store it back */ if (need_store) { if (data->u.num_share_mode_entries == 0) { - if (tdb_delete(tdb, locking_key(dev, inode)) == -1) + if (tdb_delete(tdb, key) == -1) ret = False; } else { - if (tdb_store(tdb, locking_key(dev, inode), dbuf, TDB_REPLACE) == -1) + if (tdb_store(tdb, key, dbuf, TDB_REPLACE) == -1) ret = False; } } @@ -808,9 +811,10 @@ BOOL modify_delete_flag( SMB_DEV_T dev, SMB_INO_T inode, BOOL delete_on_close) struct locking_data *data; int i; share_mode_entry *shares; + TDB_DATA key = locking_key(dev, inode); /* read in the existing share modes */ - dbuf = tdb_fetch(tdb, locking_key(dev, inode)); + dbuf = tdb_fetch(tdb, key); if (!dbuf.dptr) return False; @@ -826,7 +830,7 @@ BOOL modify_delete_flag( SMB_DEV_T dev, SMB_INO_T inode, BOOL delete_on_close) /* store it back */ if (data->u.num_share_mode_entries) { - if (tdb_store(tdb, locking_key(dev,inode), dbuf, TDB_REPLACE)==-1) { + if (tdb_store(tdb, key, dbuf, TDB_REPLACE)==-1) { SAFE_FREE(dbuf.dptr); return False; } diff --git a/source3/modules/CP437.c b/source3/modules/CP437.c new file mode 100644 index 0000000000..b7e7409746 --- /dev/null +++ b/source3/modules/CP437.c @@ -0,0 +1,136 @@ +/* + * Conversion table for CP437 charset also known as IBM437 + * + * Copyright (C) Alexander Bokovoy 2003 + * + * Conversion tables are generated using GNU libc 2.2.5's + * localedata/charmaps/IBM437 table and source/script/gen-8bit-gap.sh script + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "includes.h" + +static const uint16 to_ucs2[256] = { + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, + 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, + 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, + 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F, + 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, + 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, + 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, + 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F, + 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, + 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, + 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, + 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F, + 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, + 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, + 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, + 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F, + 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, + 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, + 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, + 0x00FF, 0x00D6, 0x00DC, 0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192, + 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, + 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, + 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, + 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, + 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, + 0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, + 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229, + 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, + 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0, +}; + +static const struct charset_gap_table from_idx[] = { + { 0x0000, 0x007f, 0 }, + { 0x00a0, 0x00c9, -32 }, + { 0x00d1, 0x00ff, -39 }, + { 0x0192, 0x0192, -185 }, + { 0x0393, 0x0398, -697 }, + { 0x03a3, 0x03a9, -707 }, + { 0x03b1, 0x03b5, -714 }, + { 0x03c0, 0x03c6, -724 }, + { 0x207f, 0x207f, -8076 }, + { 0x20a7, 0x20a7, -8115 }, + { 0x2219, 0x221e, -8484 }, + { 0x2229, 0x2229, -8494 }, + { 0x2248, 0x2248, -8524 }, + { 0x2261, 0x2265, -8548 }, + { 0x2310, 0x2310, -8718 }, + { 0x2320, 0x2321, -8733 }, + { 0x2500, 0x2502, -9211 }, + { 0x250c, 0x251c, -9220 }, + { 0x2524, 0x2524, -9227 }, + { 0x252c, 0x252c, -9234 }, + { 0x2534, 0x2534, -9241 }, + { 0x253c, 0x253c, -9248 }, + { 0x2550, 0x256c, -9267 }, + { 0x2580, 0x2593, -9286 }, + { 0x25a0, 0x25a0, -9298 }, + { 0xffff, 0xffff, 0 } +}; + +static const unsigned char from_ucs2[] = { + + '\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07', + '\x08', '\x09', '\x0a', '\x0b', '\x0c', '\x0d', '\x0e', '\x0f', + '\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17', + '\x18', '\x19', '\x1a', '\x1b', '\x1c', '\x1d', '\x1e', '\x1f', + '\x20', '\x21', '\x22', '\x23', '\x24', '\x25', '\x26', '\x27', + '\x28', '\x29', '\x2a', '\x2b', '\x2c', '\x2d', '\x2e', '\x2f', + '\x30', '\x31', '\x32', '\x33', '\x34', '\x35', '\x36', '\x37', + '\x38', '\x39', '\x3a', '\x3b', '\x3c', '\x3d', '\x3e', '\x3f', + '\x40', '\x41', '\x42', '\x43', '\x44', '\x45', '\x46', '\x47', + '\x48', '\x49', '\x4a', '\x4b', '\x4c', '\x4d', '\x4e', '\x4f', + '\x50', '\x51', '\x52', '\x53', '\x54', '\x55', '\x56', '\x57', + '\x58', '\x59', '\x5a', '\x5b', '\x5c', '\x5d', '\x5e', '\x5f', + '\x60', '\x61', '\x62', '\x63', '\x64', '\x65', '\x66', '\x67', + '\x68', '\x69', '\x6a', '\x6b', '\x6c', '\x6d', '\x6e', '\x6f', + '\x70', '\x71', '\x72', '\x73', '\x74', '\x75', '\x76', '\x77', + '\x78', '\x79', '\x7a', '\x7b', '\x7c', '\x7d', '\x7e', '\x7f', + '\xff', '\xad', '\x9b', '\x9c', '\x00', '\x9d', '\x00', '\x00', + '\x00', '\x00', '\xa6', '\xae', '\xaa', '\x00', '\x00', '\x00', + '\xf8', '\xf1', '\xfd', '\x00', '\x00', '\xe6', '\x00', '\xfa', + '\x00', '\x00', '\xa7', '\xaf', '\xac', '\xab', '\x00', '\xa8', + '\x00', '\x00', '\x00', '\x00', '\x8e', '\x8f', '\x92', '\x80', + '\x00', '\x90', '\xa5', '\x00', '\x00', '\x00', '\x00', '\x99', + '\x00', '\x00', '\x00', '\x00', '\x00', '\x9a', '\x00', '\x00', + '\xe1', '\x85', '\xa0', '\x83', '\x00', '\x84', '\x86', '\x91', + '\x87', '\x8a', '\x82', '\x88', '\x89', '\x8d', '\xa1', '\x8c', + '\x8b', '\x00', '\xa4', '\x95', '\xa2', '\x93', '\x00', '\x94', + '\xf6', '\x00', '\x97', '\xa3', '\x96', '\x81', '\x00', '\x00', + '\x98', '\x9f', '\xe2', '\x00', '\x00', '\x00', '\x00', '\xe9', + '\xe4', '\x00', '\x00', '\xe8', '\x00', '\x00', '\xea', '\xe0', + '\x00', '\x00', '\xeb', '\xee', '\xe3', '\x00', '\x00', '\xe5', + '\xe7', '\x00', '\xed', '\xfc', '\x9e', '\xf9', '\xfb', '\x00', + '\x00', '\x00', '\xec', '\xef', '\xf7', '\xf0', '\x00', '\x00', + '\xf3', '\xf2', '\xa9', '\xf4', '\xf5', '\xc4', '\x00', '\xb3', + '\xda', '\x00', '\x00', '\x00', '\xbf', '\x00', '\x00', '\x00', + '\xc0', '\x00', '\x00', '\x00', '\xd9', '\x00', '\x00', '\x00', + '\xc3', '\xb4', '\xc2', '\xc1', '\xc5', '\xcd', '\xba', '\xd5', + '\xd6', '\xc9', '\xb8', '\xb7', '\xbb', '\xd4', '\xd3', '\xc8', + '\xbe', '\xbd', '\xbc', '\xc6', '\xc7', '\xcc', '\xb5', '\xb6', + '\xb9', '\xd1', '\xd2', '\xcb', '\xcf', '\xd0', '\xca', '\xd8', + '\xd7', '\xce', '\xdf', '\x00', '\x00', '\x00', '\xdc', '\x00', + '\x00', '\x00', '\xdb', '\x00', '\x00', '\x00', '\xdd', '\x00', + '\x00', '\x00', '\xde', '\xb0', '\xb1', '\xb2', '\xfe', +}; + +SMB_GENERATE_CHARSET_MODULE_8_BIT_GAP(CP437) diff --git a/source3/modules/CP850.c b/source3/modules/CP850.c new file mode 100644 index 0000000000..311d651068 --- /dev/null +++ b/source3/modules/CP850.c @@ -0,0 +1,122 @@ +/* + * Conversion table for CP850 charset also known as IBM850. + * + * Copyright (C) Alexander Bokovoy 2003 + * + * Conversion tables are generated using GNU libc 2.2.5's + * localedata/charmaps/IBM850 table and source/script/gen-8bit-gap.sh script + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "includes.h" + +static const uint16 to_ucs2[256] = { + 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, + 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, + 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, + 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F, + 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, + 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, + 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, + 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F, + 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, + 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, + 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, + 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F, + 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, + 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, + 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, + 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F, + 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, + 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, + 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, + 0x00FF, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x0192, + 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, + 0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x00C0, + 0x00A9, 0x2563, 0x2551, 0x2557, 0x255D, 0x00A2, 0x00A5, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3, + 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4, + 0x00F0, 0x00D0, 0x00CA, 0x00CB, 0x00C8, 0x0131, 0x00CD, 0x00CE, + 0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00A6, 0x00CC, 0x2580, + 0x00D3, 0x00DF, 0x00D4, 0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x00FE, + 0x00DE, 0x00DA, 0x00DB, 0x00D9, 0x00FD, 0x00DD, 0x00AF, 0x00B4, + 0x00AD, 0x00B1, 0x2017, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x00B8, + 0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0, +}; + +static const struct charset_gap_table from_idx[] = { + /* start, end, idx */ + { 0x0000, 0x007f, 0 }, + { 0x00a0, 0x00ff, -32 }, + { 0x0131, 0x0131, -81 }, + { 0x0192, 0x0192, -177 }, + { 0x2017, 0x2017, -7989 }, + { 0x2500, 0x2502, -9245 }, + { 0x250c, 0x251c, -9254 }, + { 0x2524, 0x2524, -9261 }, + { 0x252c, 0x252c, -9268 }, + { 0x2534, 0x2534, -9275 }, + { 0x253c, 0x253c, -9282 }, + { 0x2550, 0x256c, -9301 }, + { 0x2580, 0x2588, -9320 }, + { 0x2591, 0x2593, -9328 }, + { 0x25a0, 0x25a0, -9340 }, + { 0xffff, 0xffff, 0 } +}; +static const unsigned char from_ucs2[] = { + + '\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07', + '\x08', '\x09', '\x0a', '\x0b', '\x0c', '\x0d', '\x0e', '\x0f', + '\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17', + '\x18', '\x19', '\x1a', '\x1b', '\x1c', '\x1d', '\x1e', '\x1f', + '\x20', '\x21', '\x22', '\x23', '\x24', '\x25', '\x26', '\x27', + '\x28', '\x29', '\x2a', '\x2b', '\x2c', '\x2d', '\x2e', '\x2f', + '\x30', '\x31', '\x32', '\x33', '\x34', '\x35', '\x36', '\x37', + '\x38', '\x39', '\x3a', '\x3b', '\x3c', '\x3d', '\x3e', '\x3f', + '\x40', '\x41', '\x42', '\x43', '\x44', '\x45', '\x46', '\x47', + '\x48', '\x49', '\x4a', '\x4b', '\x4c', '\x4d', '\x4e', '\x4f', + '\x50', '\x51', '\x52', '\x53', '\x54', '\x55', '\x56', '\x57', + '\x58', '\x59', '\x5a', '\x5b', '\x5c', '\x5d', '\x5e', '\x5f', + '\x60', '\x61', '\x62', '\x63', '\x64', '\x65', '\x66', '\x67', + '\x68', '\x69', '\x6a', '\x6b', '\x6c', '\x6d', '\x6e', '\x6f', + '\x70', '\x71', '\x72', '\x73', '\x74', '\x75', '\x76', '\x77', + '\x78', '\x79', '\x7a', '\x7b', '\x7c', '\x7d', '\x7e', '\x7f', + '\xff', '\xad', '\xbd', '\x9c', '\xcf', '\xbe', '\xdd', '\xf5', + '\xf9', '\xb8', '\xa6', '\xae', '\xaa', '\xf0', '\xa9', '\xee', + '\xf8', '\xf1', '\xfd', '\xfc', '\xef', '\xe6', '\xf4', '\xfa', + '\xf7', '\xfb', '\xa7', '\xaf', '\xac', '\xab', '\xf3', '\xa8', + '\xb7', '\xb5', '\xb6', '\xc7', '\x8e', '\x8f', '\x92', '\x80', + '\xd4', '\x90', '\xd2', '\xd3', '\xde', '\xd6', '\xd7', '\xd8', + '\xd1', '\xa5', '\xe3', '\xe0', '\xe2', '\xe5', '\x99', '\x9e', + '\x9d', '\xeb', '\xe9', '\xea', '\x9a', '\xed', '\xe8', '\xe1', + '\x85', '\xa0', '\x83', '\xc6', '\x84', '\x86', '\x91', '\x87', + '\x8a', '\x82', '\x88', '\x89', '\x8d', '\xa1', '\x8c', '\x8b', + '\xd0', '\xa4', '\x95', '\xa2', '\x93', '\xe4', '\x94', '\xf6', + '\x9b', '\x97', '\xa3', '\x96', '\x81', '\xec', '\xe7', '\x98', + '\xd5', '\x9f', '\xf2', '\xc4', '\x00', '\xb3', '\xda', '\x00', + '\x00', '\x00', '\xbf', '\x00', '\x00', '\x00', '\xc0', '\x00', + '\x00', '\x00', '\xd9', '\x00', '\x00', '\x00', '\xc3', '\xb4', + '\xc2', '\xc1', '\xc5', '\xcd', '\xba', '\x00', '\x00', '\xc9', + '\x00', '\x00', '\xbb', '\x00', '\x00', '\xc8', '\x00', '\x00', + '\xbc', '\x00', '\x00', '\xcc', '\x00', '\x00', '\xb9', '\x00', + '\x00', '\xcb', '\x00', '\x00', '\xca', '\x00', '\x00', '\xce', + '\xdf', '\x00', '\x00', '\x00', '\xdc', '\x00', '\x00', '\x00', + '\xdb', '\xb0', '\xb1', '\xb2', '\xfe', +}; + +SMB_GENERATE_CHARSET_MODULE_8_BIT_GAP(CP850) + diff --git a/source3/modules/getdate.c b/source3/modules/getdate.c new file mode 100644 index 0000000000..491c51294e --- /dev/null +++ b/source3/modules/getdate.c @@ -0,0 +1,2460 @@ +/* A Bison parser, made by GNU Bison 1.875a. */ + +/* Skeleton parser for Yacc-like parsing with Bison, + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. + + 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, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* As a special exception, when this file is copied by Bison into a + Bison output file, you may use that output file without restriction. + This special exception was added by the Free Software Foundation + in version 1.24 of Bison. */ + +/* Written by Richard Stallman by simplifying the original so called + ``semantic'' parser. */ + +/* All symbols defined below should begin with yy or YY, to avoid + infringing on user name space. This should be done even for local + variables, as they might otherwise be expanded by user macros. + There are some unavoidable exceptions within include files to + define necessary library symbols; they are noted "INFRINGES ON + USER NAME SPACE" below. */ + +/* Identify Bison output. */ +#define YYBISON 1 + +/* Skeleton name. */ +#define YYSKELETON_NAME "yacc.c" + +/* Pure parsers. */ +#define YYPURE 1 + +/* Using locations. */ +#define YYLSP_NEEDED 0 + + + +/* Tokens. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + /* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ + enum yytokentype { + tAGO = 258, + tDST = 259, + tDAY = 260, + tDAY_UNIT = 261, + tDAYZONE = 262, + tHOUR_UNIT = 263, + tLOCAL_ZONE = 264, + tMERIDIAN = 265, + tMINUTE_UNIT = 266, + tMONTH = 267, + tMONTH_UNIT = 268, + tSEC_UNIT = 269, + tYEAR_UNIT = 270, + tZONE = 271, + tSNUMBER = 272, + tUNUMBER = 273 + }; +#endif +#define tAGO 258 +#define tDST 259 +#define tDAY 260 +#define tDAY_UNIT 261 +#define tDAYZONE 262 +#define tHOUR_UNIT 263 +#define tLOCAL_ZONE 264 +#define tMERIDIAN 265 +#define tMINUTE_UNIT 266 +#define tMONTH 267 +#define tMONTH_UNIT 268 +#define tSEC_UNIT 269 +#define tYEAR_UNIT 270 +#define tZONE 271 +#define tSNUMBER 272 +#define tUNUMBER 273 + + + + +/* Copy the first part of user declarations. */ +#line 1 "getdate.y" + +/* Parse a string into an internal time stamp. + Copyright (C) 1999, 2000, 2002 Free Software Foundation, Inc. + + 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, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* Originally written by Steven M. Bellovin while + at the University of North Carolina at Chapel Hill. Later tweaked by + a couple of people on Usenet. Completely overhauled by Rich $alz + and Jim Berets in August, 1990. + + Modified by Paul Eggert in August 1999 to do + the right thing about local DST. Unlike previous versions, this + version is reentrant. */ + +#ifdef HAVE_CONFIG_H +# include +# ifdef HAVE_ALLOCA_H +# include +# endif +#endif + +/* Since the code of getdate.y is not included in the Emacs executable + itself, there is no need to #define static in this file. Even if + the code were included in the Emacs executable, it probably + wouldn't do any harm to #undef it here; this will only cause + problems if we try to write to a static variable, which I don't + think this code needs to do. */ +#ifdef emacs +# undef static +#endif + +#include + +#if HAVE_STDLIB_H +# include /* for `free'; used by Bison 1.27 */ +#endif + +#if STDC_HEADERS || (! defined isascii && ! HAVE_ISASCII) +# define IN_CTYPE_DOMAIN(c) 1 +#else +# define IN_CTYPE_DOMAIN(c) isascii (c) +#endif + +#define ISSPACE(c) (IN_CTYPE_DOMAIN (c) && isspace (c)) +#define ISALPHA(c) (IN_CTYPE_DOMAIN (c) && isalpha (c)) +#define ISLOWER(c) (IN_CTYPE_DOMAIN (c) && islower (c)) +#define ISDIGIT_LOCALE(c) (IN_CTYPE_DOMAIN (c) && isdigit (c)) + +/* ISDIGIT differs from ISDIGIT_LOCALE, as follows: + - Its arg may be any int or unsigned int; it need not be an unsigned char. + - It's guaranteed to evaluate its argument exactly once. + - It's typically faster. + POSIX says that only '0' through '9' are digits. Prefer ISDIGIT to + ISDIGIT_LOCALE unless it's important to use the locale's definition + of `digit' even when the host does not conform to POSIX. */ +#define ISDIGIT(c) ((unsigned) (c) - '0' <= 9) + +#if STDC_HEADERS || HAVE_STRING_H +# include +#endif + +#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8) || __STRICT_ANSI__ +# define __attribute__(x) +#endif + +#ifndef ATTRIBUTE_UNUSED +# define ATTRIBUTE_UNUSED __attribute__ ((__unused__)) +#endif + +#define EPOCH_YEAR 1970 +#define TM_YEAR_BASE 1900 + +#define HOUR(x) ((x) * 60) + +/* An integer value, and the number of digits in its textual + representation. */ +typedef struct +{ + int value; + int digits; +} textint; + +/* An entry in the lexical lookup table. */ +typedef struct +{ + char const *name; + int type; + int value; +} table; + +/* Meridian: am, pm, or 24-hour style. */ +enum { MERam, MERpm, MER24 }; + +/* Information passed to and from the parser. */ +typedef struct +{ + /* The input string remaining to be parsed. */ + const char *input; + + /* N, if this is the Nth Tuesday. */ + int day_ordinal; + + /* Day of week; Sunday is 0. */ + int day_number; + + /* tm_isdst flag for the local zone. */ + int local_isdst; + + /* Time zone, in minutes east of UTC. */ + int time_zone; + + /* Style used for time. */ + int meridian; + + /* Gregorian year, month, day, hour, minutes, and seconds. */ + textint year; + int month; + int day; + int hour; + int minutes; + int seconds; + + /* Relative year, month, day, hour, minutes, and seconds. */ + int rel_year; + int rel_month; + int rel_day; + int rel_hour; + int rel_minutes; + int rel_seconds; + + /* Counts of nonterminals of various flavors parsed so far. */ + int dates_seen; + int days_seen; + int local_zones_seen; + int rels_seen; + int times_seen; + int zones_seen; + + /* Table of local time zone abbrevations, terminated by a null entry. */ + table local_time_zone_table[3]; +} parser_control; + +#define PC (* (parser_control *) parm) +#define YYLEX_PARAM parm +#define YYPARSE_PARAM parm + +static int yyerror (); +static int yylex (); + + + +/* Enabling traces. */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif + +/* Enabling verbose error messages. */ +#ifdef YYERROR_VERBOSE +# undef YYERROR_VERBOSE +# define YYERROR_VERBOSE 1 +#else +# define YYERROR_VERBOSE 0 +#endif + +#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED) +#line 172 "getdate.y" +typedef union YYSTYPE { + int intval; + textint textintval; +} YYSTYPE; +/* Line 191 of yacc.c. */ +#line 281 "getdate.c" +# define yystype YYSTYPE /* obsolescent; will be withdrawn */ +# define YYSTYPE_IS_DECLARED 1 +# define YYSTYPE_IS_TRIVIAL 1 +#endif + + + +/* Copy the second part of user declarations. */ + + +/* Line 214 of yacc.c. */ +#line 293 "getdate.c" + +#if ! defined (yyoverflow) || YYERROR_VERBOSE + +/* The parser invokes alloca or malloc; define the necessary symbols. */ + +# if YYSTACK_USE_ALLOCA +# define YYSTACK_ALLOC alloca +# else +# ifndef YYSTACK_USE_ALLOCA +# if defined (alloca) || defined (_ALLOCA_H) +# define YYSTACK_ALLOC alloca +# else +# ifdef __GNUC__ +# define YYSTACK_ALLOC __builtin_alloca +# endif +# endif +# endif +# endif + +# ifdef YYSTACK_ALLOC + /* Pacify GCC's `empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) +# else +# if defined (__STDC__) || defined (__cplusplus) +# include /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# endif +# define YYSTACK_ALLOC malloc +# define YYSTACK_FREE free +# endif +#endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */ + + +#if (! defined (yyoverflow) \ + && (! defined (__cplusplus) \ + || (YYSTYPE_IS_TRIVIAL))) + +/* A type that is properly aligned for any stack member. */ +union yyalloc +{ + short yyss; + YYSTYPE yyvs; + }; + +/* The size of the maximum gap between one aligned stack and the next. */ +# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) + +/* The size of an array large to enough to hold all stacks, each with + N elements. */ +# define YYSTACK_BYTES(N) \ + ((N) * (sizeof (short) + sizeof (YYSTYPE)) \ + + YYSTACK_GAP_MAXIMUM) + +/* Copy COUNT objects from FROM to TO. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if 1 < __GNUC__ +# define YYCOPY(To, From, Count) \ + __builtin_memcpy (To, From, (Count) * sizeof (*(From))) +# else +# define YYCOPY(To, From, Count) \ + do \ + { \ + register YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (To)[yyi] = (From)[yyi]; \ + } \ + while (0) +# endif +# endif + +/* Relocate STACK from its old location to the new one. The + local variables YYSIZE and YYSTACKSIZE give the old and new number of + elements in the stack, and YYPTR gives the new location of the + stack. Advance YYPTR to a properly aligned location for the next + stack. */ +# define YYSTACK_RELOCATE(Stack) \ + do \ + { \ + YYSIZE_T yynewbytes; \ + YYCOPY (&yyptr->Stack, Stack, yysize); \ + Stack = &yyptr->Stack; \ + yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ + yyptr += yynewbytes / sizeof (*yyptr); \ + } \ + while (0) + +#endif + +#if defined (__STDC__) || defined (__cplusplus) + typedef signed char yysigned_char; +#else + typedef short yysigned_char; +#endif + +/* YYFINAL -- State number of the termination state. */ +#define YYFINAL 2 +/* YYLAST -- Last index in YYTABLE. */ +#define YYLAST 52 + +/* YYNTOKENS -- Number of terminals. */ +#define YYNTOKENS 22 +/* YYNNTS -- Number of nonterminals. */ +#define YYNNTS 12 +/* YYNRULES -- Number of rules. */ +#define YYNRULES 54 +/* YYNRULES -- Number of states. */ +#define YYNSTATES 64 + +/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ +#define YYUNDEFTOK 2 +#define YYMAXUTOK 273 + +#define YYTRANSLATE(YYX) \ + ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) + +/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ +static const unsigned char yytranslate[] = +{ + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 20, 2, 2, 21, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 19, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18 +}; + +#if YYDEBUG +/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in + YYRHS. */ +static const unsigned char yyprhs[] = +{ + 0, 0, 3, 4, 7, 9, 11, 13, 15, 17, + 19, 21, 24, 29, 34, 41, 48, 50, 53, 55, + 57, 60, 62, 65, 68, 72, 78, 82, 86, 89, + 94, 97, 101, 104, 106, 109, 112, 114, 117, 120, + 122, 125, 128, 130, 133, 136, 138, 141, 144, 146, + 149, 152, 154, 156, 157 +}; + +/* YYRHS -- A `-1'-separated list of the rules' RHS. */ +static const yysigned_char yyrhs[] = +{ + 23, 0, -1, -1, 23, 24, -1, 25, -1, 26, + -1, 27, -1, 29, -1, 28, -1, 30, -1, 32, + -1, 18, 10, -1, 18, 19, 18, 33, -1, 18, + 19, 18, 17, -1, 18, 19, 18, 19, 18, 33, + -1, 18, 19, 18, 19, 18, 17, -1, 9, -1, + 9, 4, -1, 16, -1, 7, -1, 16, 4, -1, + 5, -1, 5, 20, -1, 18, 5, -1, 18, 21, + 18, -1, 18, 21, 18, 21, 18, -1, 18, 17, + 17, -1, 18, 12, 17, -1, 12, 18, -1, 12, + 18, 20, 18, -1, 18, 12, -1, 18, 12, 18, + -1, 31, 3, -1, 31, -1, 18, 15, -1, 17, + 15, -1, 15, -1, 18, 13, -1, 17, 13, -1, + 13, -1, 18, 6, -1, 17, 6, -1, 6, -1, + 18, 8, -1, 17, 8, -1, 8, -1, 18, 11, + -1, 17, 11, -1, 11, -1, 18, 14, -1, 17, + 14, -1, 14, -1, 18, -1, -1, 10, -1 +}; + +/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ +static const unsigned short yyrline[] = +{ + 0, 188, 188, 190, 194, 196, 198, 200, 202, 204, + 206, 210, 217, 224, 232, 239, 251, 253, 258, 260, + 262, 267, 272, 277, 285, 290, 310, 317, 325, 330, + 336, 341, 350, 359, 363, 365, 367, 369, 371, 373, + 375, 377, 379, 381, 383, 385, 387, 389, 391, 393, + 395, 397, 402, 439, 440 +}; +#endif + +#if YYDEBUG || YYERROR_VERBOSE +/* YYTNME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. + First, the terminals, then, starting at YYNTOKENS, nonterminals. */ +static const char *const yytname[] = +{ + "$end", "error", "$undefined", "tAGO", "tDST", "tDAY", "tDAY_UNIT", + "tDAYZONE", "tHOUR_UNIT", "tLOCAL_ZONE", "tMERIDIAN", "tMINUTE_UNIT", + "tMONTH", "tMONTH_UNIT", "tSEC_UNIT", "tYEAR_UNIT", "tZONE", "tSNUMBER", + "tUNUMBER", "':'", "','", "'/'", "$accept", "spec", "item", "time", + "local_zone", "zone", "day", "date", "rel", "relunit", "number", + "o_merid", 0 +}; +#endif + +# ifdef YYPRINT +/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to + token YYLEX-NUM. */ +static const unsigned short yytoknum[] = +{ + 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, + 265, 266, 267, 268, 269, 270, 271, 272, 273, 58, + 44, 47 +}; +# endif + +/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +static const unsigned char yyr1[] = +{ + 0, 22, 23, 23, 24, 24, 24, 24, 24, 24, + 24, 25, 25, 25, 25, 25, 26, 26, 27, 27, + 27, 28, 28, 28, 29, 29, 29, 29, 29, 29, + 29, 29, 30, 30, 31, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, + 31, 31, 32, 33, 33 +}; + +/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ +static const unsigned char yyr2[] = +{ + 0, 2, 0, 2, 1, 1, 1, 1, 1, 1, + 1, 2, 4, 4, 6, 6, 1, 2, 1, 1, + 2, 1, 2, 2, 3, 5, 3, 3, 2, 4, + 2, 3, 2, 1, 2, 2, 1, 2, 2, 1, + 2, 2, 1, 2, 2, 1, 2, 2, 1, 2, + 2, 1, 1, 0, 1 +}; + +/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state + STATE-NUM when YYTABLE doesn't specify something else to do. Zero + means the default is an error. */ +static const unsigned char yydefact[] = +{ + 2, 0, 1, 21, 42, 19, 45, 16, 48, 0, + 39, 51, 36, 18, 0, 52, 3, 4, 5, 6, + 8, 7, 9, 33, 10, 22, 17, 28, 20, 41, + 44, 47, 38, 50, 35, 23, 40, 43, 11, 46, + 30, 37, 49, 34, 0, 0, 0, 32, 0, 27, + 31, 26, 53, 24, 29, 54, 13, 0, 12, 0, + 53, 25, 15, 14 +}; + +/* YYDEFGOTO[NTERM-NUM]. */ +static const yysigned_char yydefgoto[] = +{ + -1, 1, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 58 +}; + +/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ +#define YYPACT_NINF -17 +static const yysigned_char yypact[] = +{ + -17, 0, -17, 1, -17, -17, -17, 19, -17, -14, + -17, -17, -17, 32, 26, 14, -17, -17, -17, -17, + -17, -17, -17, 27, -17, -17, -17, 22, -17, -17, + -17, -17, -17, -17, -17, -17, -17, -17, -17, -17, + -16, -17, -17, -17, 29, 25, 30, -17, 31, -17, + -17, -17, 28, 23, -17, -17, -17, 33, -17, 34, + -7, -17, -17, -17 +}; + +/* YYPGOTO[NTERM-NUM]. */ +static const yysigned_char yypgoto[] = +{ + -17, -17, -17, -17, -17, -17, -17, -17, -17, -17, + -17, -10 +}; + +/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If + positive, shift that token. If negative, reduce the rule which + number is the opposite. If zero, do what YYDEFACT says. + If YYTABLE_NINF, syntax error. */ +#define YYTABLE_NINF -1 +static const unsigned char yytable[] = +{ + 2, 49, 50, 55, 27, 3, 4, 5, 6, 7, + 62, 8, 9, 10, 11, 12, 13, 14, 15, 35, + 36, 25, 37, 26, 38, 39, 40, 41, 42, 43, + 47, 44, 29, 45, 30, 46, 28, 31, 55, 32, + 33, 34, 48, 52, 59, 56, 51, 57, 53, 54, + 63, 60, 61 +}; + +static const unsigned char yycheck[] = +{ + 0, 17, 18, 10, 18, 5, 6, 7, 8, 9, + 17, 11, 12, 13, 14, 15, 16, 17, 18, 5, + 6, 20, 8, 4, 10, 11, 12, 13, 14, 15, + 3, 17, 6, 19, 8, 21, 4, 11, 10, 13, + 14, 15, 20, 18, 21, 17, 17, 19, 18, 18, + 60, 18, 18 +}; + +/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing + symbol of state STATE-NUM. */ +static const unsigned char yystos[] = +{ + 0, 23, 0, 5, 6, 7, 8, 9, 11, 12, + 13, 14, 15, 16, 17, 18, 24, 25, 26, 27, + 28, 29, 30, 31, 32, 20, 4, 18, 4, 6, + 8, 11, 13, 14, 15, 5, 6, 8, 10, 11, + 12, 13, 14, 15, 17, 19, 21, 3, 20, 17, + 18, 17, 18, 18, 18, 10, 17, 19, 33, 21, + 18, 18, 17, 33 +}; + +#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__) +# define YYSIZE_T __SIZE_TYPE__ +#endif +#if ! defined (YYSIZE_T) && defined (size_t) +# define YYSIZE_T size_t +#endif +#if ! defined (YYSIZE_T) +# if defined (__STDC__) || defined (__cplusplus) +# include /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# endif +#endif +#if ! defined (YYSIZE_T) +# define YYSIZE_T unsigned int +#endif + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY (-2) +#define YYEOF 0 + +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrlab1 + + +/* Like YYERROR except do call yyerror. This remains here temporarily + to ease the transition to the new meaning of YYERROR, for GCC. + Once GCC version 2 has supplanted version 1, this can go. */ + +#define YYFAIL goto yyerrlab + +#define YYRECOVERING() (!!yyerrstatus) + +#define YYBACKUP(Token, Value) \ +do \ + if (yychar == YYEMPTY && yylen == 1) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + yytoken = YYTRANSLATE (yychar); \ + YYPOPSTACK; \ + goto yybackup; \ + } \ + else \ + { \ + yyerror ("syntax error: cannot back up");\ + YYERROR; \ + } \ +while (0) + +#define YYTERROR 1 +#define YYERRCODE 256 + +/* YYLLOC_DEFAULT -- Compute the default location (before the actions + are run). */ + +#ifndef YYLLOC_DEFAULT +# define YYLLOC_DEFAULT(Current, Rhs, N) \ + Current.first_line = Rhs[1].first_line; \ + Current.first_column = Rhs[1].first_column; \ + Current.last_line = Rhs[N].last_line; \ + Current.last_column = Rhs[N].last_column; +#endif + +/* YYLEX -- calling `yylex' with the right arguments. */ + +#ifdef YYLEX_PARAM +# define YYLEX yylex (&yylval, YYLEX_PARAM) +#else +# define YYLEX yylex (&yylval) +#endif + +/* Enable debugging if requested. */ +#if YYDEBUG + +# ifndef YYFPRINTF +# include /* INFRINGES ON USER NAME SPACE */ +# define YYFPRINTF fprintf +# endif + +# define YYDPRINTF(Args) \ +do { \ + if (yydebug) \ + YYFPRINTF Args; \ +} while (0) + +# define YYDSYMPRINT(Args) \ +do { \ + if (yydebug) \ + yysymprint Args; \ +} while (0) + +# define YYDSYMPRINTF(Title, Token, Value, Location) \ +do { \ + if (yydebug) \ + { \ + YYFPRINTF (stderr, "%s ", Title); \ + yysymprint (stderr, \ + Token, Value); \ + YYFPRINTF (stderr, "\n"); \ + } \ +} while (0) + +/*------------------------------------------------------------------. +| yy_stack_print -- Print the state stack from its BOTTOM up to its | +| TOP (cinluded). | +`------------------------------------------------------------------*/ + +#if defined (__STDC__) || defined (__cplusplus) +static void +yy_stack_print (short *bottom, short *top) +#else +static void +yy_stack_print (bottom, top) + short *bottom; + short *top; +#endif +{ + YYFPRINTF (stderr, "Stack now"); + for (/* Nothing. */; bottom <= top; ++bottom) + YYFPRINTF (stderr, " %d", *bottom); + YYFPRINTF (stderr, "\n"); +} + +# define YY_STACK_PRINT(Bottom, Top) \ +do { \ + if (yydebug) \ + yy_stack_print ((Bottom), (Top)); \ +} while (0) + + +/*------------------------------------------------. +| Report that the YYRULE is going to be reduced. | +`------------------------------------------------*/ + +#if defined (__STDC__) || defined (__cplusplus) +static void +yy_reduce_print (int yyrule) +#else +static void +yy_reduce_print (yyrule) + int yyrule; +#endif +{ + int yyi; + unsigned int yylineno = yyrline[yyrule]; + YYFPRINTF (stderr, "Reducing stack by rule %d (line %u), ", + yyrule - 1, yylineno); + /* Print the symbols being reduced, and their result. */ + for (yyi = yyprhs[yyrule]; 0 <= yyrhs[yyi]; yyi++) + YYFPRINTF (stderr, "%s ", yytname [yyrhs[yyi]]); + YYFPRINTF (stderr, "-> %s\n", yytname [yyr1[yyrule]]); +} + +# define YY_REDUCE_PRINT(Rule) \ +do { \ + if (yydebug) \ + yy_reduce_print (Rule); \ +} while (0) + +/* Nonzero means print parse trace. It is left uninitialized so that + multiple parsers can coexist. */ +int yydebug; +#else /* !YYDEBUG */ +# define YYDPRINTF(Args) +# define YYDSYMPRINT(Args) +# define YYDSYMPRINTF(Title, Token, Value, Location) +# define YY_STACK_PRINT(Bottom, Top) +# define YY_REDUCE_PRINT(Rule) +#endif /* !YYDEBUG */ + + +/* YYINITDEPTH -- initial size of the parser's stacks. */ +#ifndef YYINITDEPTH +# define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only + if the built-in stack extension method is used). + + Do not make this value too large; the results are undefined if + SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH) + evaluated with infinite-precision integer arithmetic. */ + +#if YYMAXDEPTH == 0 +# undef YYMAXDEPTH +#endif + +#ifndef YYMAXDEPTH +# define YYMAXDEPTH 10000 +#endif + + + +#if YYERROR_VERBOSE + +# ifndef yystrlen +# if defined (__GLIBC__) && defined (_STRING_H) +# define yystrlen strlen +# else +/* Return the length of YYSTR. */ +static YYSIZE_T +# if defined (__STDC__) || defined (__cplusplus) +yystrlen (const char *yystr) +# else +yystrlen (yystr) + const char *yystr; +# endif +{ + register const char *yys = yystr; + + while (*yys++ != '\0') + continue; + + return yys - yystr - 1; +} +# endif +# endif + +# ifndef yystpcpy +# if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE) +# define yystpcpy stpcpy +# else +/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in + YYDEST. */ +static char * +# if defined (__STDC__) || defined (__cplusplus) +yystpcpy (char *yydest, const char *yysrc) +# else +yystpcpy (yydest, yysrc) + char *yydest; + const char *yysrc; +# endif +{ + register char *yyd = yydest; + register const char *yys = yysrc; + + while ((*yyd++ = *yys++) != '\0') + continue; + + return yyd - 1; +} +# endif +# endif + +#endif /* !YYERROR_VERBOSE */ + + + +#if YYDEBUG +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +#if defined (__STDC__) || defined (__cplusplus) +static void +yysymprint (FILE *yyoutput, int yytype, YYSTYPE *yyvaluep) +#else +static void +yysymprint (yyoutput, yytype, yyvaluep) + FILE *yyoutput; + int yytype; + YYSTYPE *yyvaluep; +#endif +{ + /* Pacify ``unused variable'' warnings. */ + (void) yyvaluep; + + if (yytype < YYNTOKENS) + { + YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); +# ifdef YYPRINT + YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); +# endif + } + else + YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); + + switch (yytype) + { + default: + break; + } + YYFPRINTF (yyoutput, ")"); +} + +#endif /* ! YYDEBUG */ +/*-----------------------------------------------. +| Release the memory associated to this symbol. | +`-----------------------------------------------*/ + +#if defined (__STDC__) || defined (__cplusplus) +static void +yydestruct (int yytype, YYSTYPE *yyvaluep) +#else +static void +yydestruct (yytype, yyvaluep) + int yytype; + YYSTYPE *yyvaluep; +#endif +{ + /* Pacify ``unused variable'' warnings. */ + (void) yyvaluep; + + switch (yytype) + { + + default: + break; + } +} + + +/* Prevent warnings from -Wmissing-prototypes. */ + +#ifdef YYPARSE_PARAM +# if defined (__STDC__) || defined (__cplusplus) +int yyparse (void *YYPARSE_PARAM); +# else +int yyparse (); +# endif +#else /* ! YYPARSE_PARAM */ +#if defined (__STDC__) || defined (__cplusplus) +int yyparse (void); +#else +int yyparse (); +#endif +#endif /* ! YYPARSE_PARAM */ + + + + + + +/*----------. +| yyparse. | +`----------*/ + +#ifdef YYPARSE_PARAM +# if defined (__STDC__) || defined (__cplusplus) +int yyparse (void *YYPARSE_PARAM) +# else +int yyparse (YYPARSE_PARAM) + void *YYPARSE_PARAM; +# endif +#else /* ! YYPARSE_PARAM */ +#if defined (__STDC__) || defined (__cplusplus) +int +yyparse (void) +#else +int +yyparse () + +#endif +#endif +{ + /* The lookahead symbol. */ +int yychar; + +/* The semantic value of the lookahead symbol. */ +YYSTYPE yylval; + +/* Number of syntax errors so far. */ +int yynerrs; + + register int yystate; + register int yyn; + int yyresult; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus; + /* Lookahead token as an internal (translated) token number. */ + int yytoken = 0; + + /* Three stacks and their tools: + `yyss': related to states, + `yyvs': related to semantic values, + `yyls': related to locations. + + Refer to the stacks thru separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + + /* The state stack. */ + short yyssa[YYINITDEPTH]; + short *yyss = yyssa; + register short *yyssp; + + /* The semantic value stack. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs = yyvsa; + register YYSTYPE *yyvsp; + + + +#define YYPOPSTACK (yyvsp--, yyssp--) + + YYSIZE_T yystacksize = YYINITDEPTH; + + /* The variables used to return semantic value and location from the + action routines. */ + YYSTYPE yyval; + + + /* When reducing, the number of symbols on the RHS of the reduced + rule. */ + int yylen; + + YYDPRINTF ((stderr, "Starting parse\n")); + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. + The wasted elements are never initialized. */ + + yyssp = yyss; + yyvsp = yyvs; + + goto yysetstate; + +/*------------------------------------------------------------. +| yynewstate -- Push a new state, which is found in yystate. | +`------------------------------------------------------------*/ + yynewstate: + /* In all cases, when you get here, the value and location stacks + have just been pushed. so pushing a state here evens the stacks. + */ + yyssp++; + + yysetstate: + *yyssp = yystate; + + if (yyss + yystacksize - 1 <= yyssp) + { + /* Get the current used size of the three stacks, in elements. */ + YYSIZE_T yysize = yyssp - yyss + 1; + +#ifdef yyoverflow + { + /* Give user a chance to reallocate the stack. Use copies of + these so that the &'s don't force the real ones into + memory. */ + YYSTYPE *yyvs1 = yyvs; + short *yyss1 = yyss; + + + /* Each stack pointer address is followed by the size of the + data in use in that stack, in bytes. This used to be a + conditional around just the two extra args, but that might + be undefined if yyoverflow is a macro. */ + yyoverflow ("parser stack overflow", + &yyss1, yysize * sizeof (*yyssp), + &yyvs1, yysize * sizeof (*yyvsp), + + &yystacksize); + + yyss = yyss1; + yyvs = yyvs1; + } +#else /* no yyoverflow */ +# ifndef YYSTACK_RELOCATE + goto yyoverflowlab; +# else + /* Extend the stack our own way. */ + if (YYMAXDEPTH <= yystacksize) + goto yyoverflowlab; + yystacksize *= 2; + if (YYMAXDEPTH < yystacksize) + yystacksize = YYMAXDEPTH; + + { + short *yyss1 = yyss; + union yyalloc *yyptr = + (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); + if (! yyptr) + goto yyoverflowlab; + YYSTACK_RELOCATE (yyss); + YYSTACK_RELOCATE (yyvs); + +# undef YYSTACK_RELOCATE + if (yyss1 != yyssa) + YYSTACK_FREE (yyss1); + } +# endif +#endif /* no yyoverflow */ + + yyssp = yyss + yysize - 1; + yyvsp = yyvs + yysize - 1; + + + YYDPRINTF ((stderr, "Stack size increased to %lu\n", + (unsigned long int) yystacksize)); + + if (yyss + yystacksize - 1 <= yyssp) + YYABORT; + } + + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + + goto yybackup; + +/*-----------. +| yybackup. | +`-----------*/ +yybackup: + +/* Do appropriate processing given the current state. */ +/* Read a lookahead token if we need one and don't already have one. */ +/* yyresume: */ + + /* First try to decide what to do without reference to lookahead token. */ + + yyn = yypact[yystate]; + if (yyn == YYPACT_NINF) + goto yydefault; + + /* Not known => get a lookahead token if don't already have one. */ + + /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ + if (yychar == YYEMPTY) + { + YYDPRINTF ((stderr, "Reading a token: ")); + yychar = YYLEX; + } + + if (yychar <= YYEOF) + { + yychar = yytoken = YYEOF; + YYDPRINTF ((stderr, "Now at end of input.\n")); + } + else + { + yytoken = YYTRANSLATE (yychar); + YYDSYMPRINTF ("Next token is", yytoken, &yylval, &yylloc); + } + + /* If the proper action on seeing token YYTOKEN is to reduce or to + detect an error, take that action. */ + yyn += yytoken; + if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) + goto yydefault; + yyn = yytable[yyn]; + if (yyn <= 0) + { + if (yyn == 0 || yyn == YYTABLE_NINF) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + + if (yyn == YYFINAL) + YYACCEPT; + + /* Shift the lookahead token. */ + YYDPRINTF ((stderr, "Shifting token %s, ", yytname[yytoken])); + + /* Discard the token being shifted unless it is eof. */ + if (yychar != YYEOF) + yychar = YYEMPTY; + + *++yyvsp = yylval; + + + /* Count tokens shifted since error; after three, turn off error + status. */ + if (yyerrstatus) + yyerrstatus--; + + yystate = yyn; + goto yynewstate; + + +/*-----------------------------------------------------------. +| yydefault -- do the default action for the current state. | +`-----------------------------------------------------------*/ +yydefault: + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + goto yyreduce; + + +/*-----------------------------. +| yyreduce -- Do a reduction. | +`-----------------------------*/ +yyreduce: + /* yyn is the number of a rule to reduce with. */ + yylen = yyr2[yyn]; + + /* If YYLEN is nonzero, implement the default value of the action: + `$$ = $1'. + + Otherwise, the following line sets YYVAL to garbage. + This behavior is undocumented and Bison + users should not rely upon it. Assigning to YYVAL + unconditionally makes the parser a bit smaller, and it avoids a + GCC warning that YYVAL may be used uninitialized. */ + yyval = yyvsp[1-yylen]; + + + YY_REDUCE_PRINT (yyn); + switch (yyn) + { + case 4: +#line 195 "getdate.y" + { PC.times_seen++; } + break; + + case 5: +#line 197 "getdate.y" + { PC.local_zones_seen++; } + break; + + case 6: +#line 199 "getdate.y" + { PC.zones_seen++; } + break; + + case 7: +#line 201 "getdate.y" + { PC.dates_seen++; } + break; + + case 8: +#line 203 "getdate.y" + { PC.days_seen++; } + break; + + case 9: +#line 205 "getdate.y" + { PC.rels_seen++; } + break; + + case 11: +#line 211 "getdate.y" + { + PC.hour = yyvsp[-1].textintval.value; + PC.minutes = 0; + PC.seconds = 0; + PC.meridian = yyvsp[0].intval; + } + break; + + case 12: +#line 218 "getdate.y" + { + PC.hour = yyvsp[-3].textintval.value; + PC.minutes = yyvsp[-1].textintval.value; + PC.seconds = 0; + PC.meridian = yyvsp[0].intval; + } + break; + + case 13: +#line 225 "getdate.y" + { + PC.hour = yyvsp[-3].textintval.value; + PC.minutes = yyvsp[-1].textintval.value; + PC.meridian = MER24; + PC.zones_seen++; + PC.time_zone = yyvsp[0].textintval.value % 100 + (yyvsp[0].textintval.value / 100) * 60; + } + break; + + case 14: +#line 233 "getdate.y" + { + PC.hour = yyvsp[-5].textintval.value; + PC.minutes = yyvsp[-3].textintval.value; + PC.seconds = yyvsp[-1].textintval.value; + PC.meridian = yyvsp[0].intval; + } + break; + + case 15: +#line 240 "getdate.y" + { + PC.hour = yyvsp[-5].textintval.value; + PC.minutes = yyvsp[-3].textintval.value; + PC.seconds = yyvsp[-1].textintval.value; + PC.meridian = MER24; + PC.zones_seen++; + PC.time_zone = yyvsp[0].textintval.value % 100 + (yyvsp[0].textintval.value / 100) * 60; + } + break; + + case 16: +#line 252 "getdate.y" + { PC.local_isdst = yyvsp[0].intval; } + break; + + case 17: +#line 254 "getdate.y" + { PC.local_isdst = yyvsp[-1].intval < 0 ? 1 : yyvsp[-1].intval + 1; } + break; + + case 18: +#line 259 "getdate.y" + { PC.time_zone = yyvsp[0].intval; } + break; + + case 19: +#line 261 "getdate.y" + { PC.time_zone = yyvsp[0].intval + 60; } + break; + + case 20: +#line 263 "getdate.y" + { PC.time_zone = yyvsp[-1].intval + 60; } + break; + + case 21: +#line 268 "getdate.y" + { + PC.day_ordinal = 1; + PC.day_number = yyvsp[0].intval; + } + break; + + case 22: +#line 273 "getdate.y" + { + PC.day_ordinal = 1; + PC.day_number = yyvsp[-1].intval; + } + break; + + case 23: +#line 278 "getdate.y" + { + PC.day_ordinal = yyvsp[-1].textintval.value; + PC.day_number = yyvsp[0].intval; + } + break; + + case 24: +#line 286 "getdate.y" + { + PC.month = yyvsp[-2].textintval.value; + PC.day = yyvsp[0].textintval.value; + } + break; + + case 25: +#line 291 "getdate.y" + { + /* Interpret as YYYY/MM/DD if the first value has 4 or more digits, + otherwise as MM/DD/YY. + The goal in recognizing YYYY/MM/DD is solely to support legacy + machine-generated dates like those in an RCS log listing. If + you want portability, use the ISO 8601 format. */ + if (4 <= yyvsp[-4].textintval.digits) + { + PC.year = yyvsp[-4].textintval; + PC.month = yyvsp[-2].textintval.value; + PC.day = yyvsp[0].textintval.value; + } + else + { + PC.month = yyvsp[-4].textintval.value; + PC.day = yyvsp[-2].textintval.value; + PC.year = yyvsp[0].textintval; + } + } + break; + + case 26: +#line 311 "getdate.y" + { + /* ISO 8601 format. YYYY-MM-DD. */ + PC.year = yyvsp[-2].textintval; + PC.month = -yyvsp[-1].textintval.value; + PC.day = -yyvsp[0].textintval.value; + } + break; + + case 27: +#line 318 "getdate.y" + { + /* e.g. 17-JUN-1992. */ + PC.day = yyvsp[-2].textintval.value; + PC.month = yyvsp[-1].intval; + PC.year.value = -yyvsp[0].textintval.value; + PC.year.digits = yyvsp[0].textintval.digits; + } + break; + + case 28: +#line 326 "getdate.y" + { + PC.month = yyvsp[-1].intval; + PC.day = yyvsp[0].textintval.value; + } + break; + + case 29: +#line 331 "getdate.y" + { + PC.month = yyvsp[-3].intval; + PC.day = yyvsp[-2].textintval.value; + PC.year = yyvsp[0].textintval; + } + break; + + case 30: +#line 337 "getdate.y" + { + PC.day = yyvsp[-1].textintval.value; + PC.month = yyvsp[0].intval; + } + break; + + case 31: +#line 342 "getdate.y" + { + PC.day = yyvsp[-2].textintval.value; + PC.month = yyvsp[-1].intval; + PC.year = yyvsp[0].textintval; + } + break; + + case 32: +#line 351 "getdate.y" + { + PC.rel_seconds = -PC.rel_seconds; + PC.rel_minutes = -PC.rel_minutes; + PC.rel_hour = -PC.rel_hour; + PC.rel_day = -PC.rel_day; + PC.rel_month = -PC.rel_month; + PC.rel_year = -PC.rel_year; + } + break; + + case 34: +#line 364 "getdate.y" + { PC.rel_year += yyvsp[-1].textintval.value * yyvsp[0].intval; } + break; + + case 35: +#line 366 "getdate.y" + { PC.rel_year += yyvsp[-1].textintval.value * yyvsp[0].intval; } + break; + + case 36: +#line 368 "getdate.y" + { PC.rel_year += yyvsp[0].intval; } + break; + + case 37: +#line 370 "getdate.y" + { PC.rel_month += yyvsp[-1].textintval.value * yyvsp[0].intval; } + break; + + case 38: +#line 372 "getdate.y" + { PC.rel_month += yyvsp[-1].textintval.value * yyvsp[0].intval; } + break; + + case 39: +#line 374 "getdate.y" + { PC.rel_month += yyvsp[0].intval; } + break; + + case 40: +#line 376 "getdate.y" + { PC.rel_day += yyvsp[-1].textintval.value * yyvsp[0].intval; } + break; + + case 41: +#line 378 "getdate.y" + { PC.rel_day += yyvsp[-1].textintval.value * yyvsp[0].intval; } + break; + + case 42: +#line 380 "getdate.y" + { PC.rel_day += yyvsp[0].intval; } + break; + + case 43: +#line 382 "getdate.y" + { PC.rel_hour += yyvsp[-1].textintval.value * yyvsp[0].intval; } + break; + + case 44: +#line 384 "getdate.y" + { PC.rel_hour += yyvsp[-1].textintval.value * yyvsp[0].intval; } + break; + + case 45: +#line 386 "getdate.y" + { PC.rel_hour += yyvsp[0].intval; } + break; + + case 46: +#line 388 "getdate.y" + { PC.rel_minutes += yyvsp[-1].textintval.value * yyvsp[0].intval; } + break; + + case 47: +#line 390 "getdate.y" + { PC.rel_minutes += yyvsp[-1].textintval.value * yyvsp[0].intval; } + break; + + case 48: +#line 392 "getdate.y" + { PC.rel_minutes += yyvsp[0].intval; } + break; + + case 49: +#line 394 "getdate.y" + { PC.rel_seconds += yyvsp[-1].textintval.value * yyvsp[0].intval; } + break; + + case 50: +#line 396 "getdate.y" + { PC.rel_seconds += yyvsp[-1].textintval.value * yyvsp[0].intval; } + break; + + case 51: +#line 398 "getdate.y" + { PC.rel_seconds += yyvsp[0].intval; } + break; + + case 52: +#line 403 "getdate.y" + { + if (PC.dates_seen + && ! PC.rels_seen && (PC.times_seen || 2 < yyvsp[0].textintval.digits)) + PC.year = yyvsp[0].textintval; + else + { + if (4 < yyvsp[0].textintval.digits) + { + PC.dates_seen++; + PC.day = yyvsp[0].textintval.value % 100; + PC.month = (yyvsp[0].textintval.value / 100) % 100; + PC.year.value = yyvsp[0].textintval.value / 10000; + PC.year.digits = yyvsp[0].textintval.digits - 4; + } + else + { + PC.times_seen++; + if (yyvsp[0].textintval.digits <= 2) + { + PC.hour = yyvsp[0].textintval.value; + PC.minutes = 0; + } + else + { + PC.hour = yyvsp[0].textintval.value / 100; + PC.minutes = yyvsp[0].textintval.value % 100; + } + PC.seconds = 0; + PC.meridian = MER24; + } + } + } + break; + + case 53: +#line 439 "getdate.y" + { yyval.intval = MER24; } + break; + + case 54: +#line 441 "getdate.y" + { yyval.intval = yyvsp[0].intval; } + break; + + + } + +/* Line 999 of yacc.c. */ +#line 1593 "getdate.c" + + yyvsp -= yylen; + yyssp -= yylen; + + + YY_STACK_PRINT (yyss, yyssp); + + *++yyvsp = yyval; + + + /* Now `shift' the result of the reduction. Determine what state + that goes to, based on the state we popped back to and the rule + number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; + if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTOKENS]; + + goto yynewstate; + + +/*------------------------------------. +| yyerrlab -- here on detecting error | +`------------------------------------*/ +yyerrlab: + /* If not already recovering from an error, report this error. */ + if (!yyerrstatus) + { + ++yynerrs; +#if YYERROR_VERBOSE + yyn = yypact[yystate]; + + if (YYPACT_NINF < yyn && yyn < YYLAST) + { + YYSIZE_T yysize = 0; + int yytype = YYTRANSLATE (yychar); + char *yymsg; + int yyx, yycount; + + yycount = 0; + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. */ + for (yyx = yyn < 0 ? -yyn : 0; + yyx < (int) (sizeof (yytname) / sizeof (char *)); yyx++) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) + yysize += yystrlen (yytname[yyx]) + 15, yycount++; + yysize += yystrlen ("syntax error, unexpected ") + 1; + yysize += yystrlen (yytname[yytype]); + yymsg = (char *) YYSTACK_ALLOC (yysize); + if (yymsg != 0) + { + char *yyp = yystpcpy (yymsg, "syntax error, unexpected "); + yyp = yystpcpy (yyp, yytname[yytype]); + + if (yycount < 5) + { + yycount = 0; + for (yyx = yyn < 0 ? -yyn : 0; + yyx < (int) (sizeof (yytname) / sizeof (char *)); + yyx++) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) + { + const char *yyq = ! yycount ? ", expecting " : " or "; + yyp = yystpcpy (yyp, yyq); + yyp = yystpcpy (yyp, yytname[yyx]); + yycount++; + } + } + yyerror (yymsg); + YYSTACK_FREE (yymsg); + } + else + yyerror ("syntax error; also virtual memory exhausted"); + } + else +#endif /* YYERROR_VERBOSE */ + yyerror ("syntax error"); + } + + + + if (yyerrstatus == 3) + { + /* If just tried and failed to reuse lookahead token after an + error, discard it. */ + + /* Return failure if at end of input. */ + if (yychar == YYEOF) + { + /* Pop the error token. */ + YYPOPSTACK; + /* Pop the rest of the stack. */ + while (yyss < yyssp) + { + YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp); + yydestruct (yystos[*yyssp], yyvsp); + YYPOPSTACK; + } + YYABORT; + } + + YYDSYMPRINTF ("Error: discarding", yytoken, &yylval, &yylloc); + yydestruct (yytoken, &yylval); + yychar = YYEMPTY; + + } + + /* Else will try to reuse lookahead token after shifting the error + token. */ + goto yyerrlab1; + + +/*----------------------------------------------------. +| yyerrlab1 -- error raised explicitly by an action. | +`----------------------------------------------------*/ +yyerrlab1: + yyerrstatus = 3; /* Each real token shifted decrements this. */ + + for (;;) + { + yyn = yypact[yystate]; + if (yyn != YYPACT_NINF) + { + yyn += YYTERROR; + if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) + { + yyn = yytable[yyn]; + if (0 < yyn) + break; + } + } + + /* Pop the current state because it cannot handle the error token. */ + if (yyssp == yyss) + YYABORT; + + YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp); + yydestruct (yystos[yystate], yyvsp); + yyvsp--; + yystate = *--yyssp; + + YY_STACK_PRINT (yyss, yyssp); + } + + if (yyn == YYFINAL) + YYACCEPT; + + YYDPRINTF ((stderr, "Shifting error token, ")); + + *++yyvsp = yylval; + + + yystate = yyn; + goto yynewstate; + + +/*-------------------------------------. +| yyacceptlab -- YYACCEPT comes here. | +`-------------------------------------*/ +yyacceptlab: + yyresult = 0; + goto yyreturn; + +/*-----------------------------------. +| yyabortlab -- YYABORT comes here. | +`-----------------------------------*/ +yyabortlab: + yyresult = 1; + goto yyreturn; + +#ifndef yyoverflow +/*----------------------------------------------. +| yyoverflowlab -- parser overflow comes here. | +`----------------------------------------------*/ +yyoverflowlab: + yyerror ("parser stack overflow"); + yyresult = 2; + /* Fall through. */ +#endif + +yyreturn: +#ifndef yyoverflow + if (yyss != yyssa) + YYSTACK_FREE (yyss); +#endif + return yyresult; +} + + +#line 444 "getdate.y" + + +/* Include this file down here because bison inserts code above which + may define-away `const'. We want the prototype for get_date to have + the same signature as the function definition. */ +#include "modules/getdate.h" + +#ifndef gmtime +struct tm *gmtime (); +#endif +#ifndef localtime +struct tm *localtime (); +#endif +#ifndef mktime +time_t mktime (); +#endif + +static table const meridian_table[] = +{ + { "AM", tMERIDIAN, MERam }, + { "A.M.", tMERIDIAN, MERam }, + { "PM", tMERIDIAN, MERpm }, + { "P.M.", tMERIDIAN, MERpm }, + { 0, 0, 0 } +}; + +static table const dst_table[] = +{ + { "DST", tDST, 0 } +}; + +static table const month_and_day_table[] = +{ + { "JANUARY", tMONTH, 1 }, + { "FEBRUARY", tMONTH, 2 }, + { "MARCH", tMONTH, 3 }, + { "APRIL", tMONTH, 4 }, + { "MAY", tMONTH, 5 }, + { "JUNE", tMONTH, 6 }, + { "JULY", tMONTH, 7 }, + { "AUGUST", tMONTH, 8 }, + { "SEPTEMBER",tMONTH, 9 }, + { "SEPT", tMONTH, 9 }, + { "OCTOBER", tMONTH, 10 }, + { "NOVEMBER", tMONTH, 11 }, + { "DECEMBER", tMONTH, 12 }, + { "SUNDAY", tDAY, 0 }, + { "MONDAY", tDAY, 1 }, + { "TUESDAY", tDAY, 2 }, + { "TUES", tDAY, 2 }, + { "WEDNESDAY",tDAY, 3 }, + { "WEDNES", tDAY, 3 }, + { "THURSDAY", tDAY, 4 }, + { "THUR", tDAY, 4 }, + { "THURS", tDAY, 4 }, + { "FRIDAY", tDAY, 5 }, + { "SATURDAY", tDAY, 6 }, + { 0, 0, 0 } +}; + +static table const time_units_table[] = +{ + { "YEAR", tYEAR_UNIT, 1 }, + { "MONTH", tMONTH_UNIT, 1 }, + { "FORTNIGHT",tDAY_UNIT, 14 }, + { "WEEK", tDAY_UNIT, 7 }, + { "DAY", tDAY_UNIT, 1 }, + { "HOUR", tHOUR_UNIT, 1 }, + { "MINUTE", tMINUTE_UNIT, 1 }, + { "MIN", tMINUTE_UNIT, 1 }, + { "SECOND", tSEC_UNIT, 1 }, + { "SEC", tSEC_UNIT, 1 }, + { 0, 0, 0 } +}; + +/* Assorted relative-time words. */ +static table const relative_time_table[] = +{ + { "TOMORROW", tMINUTE_UNIT, 24 * 60 }, + { "YESTERDAY",tMINUTE_UNIT, - (24 * 60) }, + { "TODAY", tMINUTE_UNIT, 0 }, + { "NOW", tMINUTE_UNIT, 0 }, + { "LAST", tUNUMBER, -1 }, + { "THIS", tUNUMBER, 0 }, + { "NEXT", tUNUMBER, 1 }, + { "FIRST", tUNUMBER, 1 }, +/*{ "SECOND", tUNUMBER, 2 }, */ + { "THIRD", tUNUMBER, 3 }, + { "FOURTH", tUNUMBER, 4 }, + { "FIFTH", tUNUMBER, 5 }, + { "SIXTH", tUNUMBER, 6 }, + { "SEVENTH", tUNUMBER, 7 }, + { "EIGHTH", tUNUMBER, 8 }, + { "NINTH", tUNUMBER, 9 }, + { "TENTH", tUNUMBER, 10 }, + { "ELEVENTH", tUNUMBER, 11 }, + { "TWELFTH", tUNUMBER, 12 }, + { "AGO", tAGO, 1 }, + { 0, 0, 0 } +}; + +/* The time zone table. This table is necessarily incomplete, as time + zone abbreviations are ambiguous; e.g. Australians interpret "EST" + as Eastern time in Australia, not as US Eastern Standard Time. + You cannot rely on getdate to handle arbitrary time zone + abbreviations; use numeric abbreviations like `-0500' instead. */ +static table const time_zone_table[] = +{ + { "GMT", tZONE, HOUR ( 0) }, /* Greenwich Mean */ + { "UT", tZONE, HOUR ( 0) }, /* Universal (Coordinated) */ + { "UTC", tZONE, HOUR ( 0) }, + { "WET", tZONE, HOUR ( 0) }, /* Western European */ + { "WEST", tDAYZONE, HOUR ( 0) }, /* Western European Summer */ + { "BST", tDAYZONE, HOUR ( 0) }, /* British Summer */ + { "ART", tZONE, -HOUR ( 3) }, /* Argentina */ + { "BRT", tZONE, -HOUR ( 3) }, /* Brazil */ + { "BRST", tDAYZONE, -HOUR ( 3) }, /* Brazil Summer */ + { "NST", tZONE, -(HOUR ( 3) + 30) }, /* Newfoundland Standard */ + { "NDT", tDAYZONE,-(HOUR ( 3) + 30) }, /* Newfoundland Daylight */ + { "AST", tZONE, -HOUR ( 4) }, /* Atlantic Standard */ + { "ADT", tDAYZONE, -HOUR ( 4) }, /* Atlantic Daylight */ + { "CLT", tZONE, -HOUR ( 4) }, /* Chile */ + { "CLST", tDAYZONE, -HOUR ( 4) }, /* Chile Summer */ + { "EST", tZONE, -HOUR ( 5) }, /* Eastern Standard */ + { "EDT", tDAYZONE, -HOUR ( 5) }, /* Eastern Daylight */ + { "CST", tZONE, -HOUR ( 6) }, /* Central Standard */ + { "CDT", tDAYZONE, -HOUR ( 6) }, /* Central Daylight */ + { "MST", tZONE, -HOUR ( 7) }, /* Mountain Standard */ + { "MDT", tDAYZONE, -HOUR ( 7) }, /* Mountain Daylight */ + { "PST", tZONE, -HOUR ( 8) }, /* Pacific Standard */ + { "PDT", tDAYZONE, -HOUR ( 8) }, /* Pacific Daylight */ + { "AKST", tZONE, -HOUR ( 9) }, /* Alaska Standard */ + { "AKDT", tDAYZONE, -HOUR ( 9) }, /* Alaska Daylight */ + { "HST", tZONE, -HOUR (10) }, /* Hawaii Standard */ + { "HAST", tZONE, -HOUR (10) }, /* Hawaii-Aleutian Standard */ + { "HADT", tDAYZONE, -HOUR (10) }, /* Hawaii-Aleutian Daylight */ + { "SST", tZONE, -HOUR (12) }, /* Samoa Standard */ + { "WAT", tZONE, HOUR ( 1) }, /* West Africa */ + { "CET", tZONE, HOUR ( 1) }, /* Central European */ + { "CEST", tDAYZONE, HOUR ( 1) }, /* Central European Summer */ + { "MET", tZONE, HOUR ( 1) }, /* Middle European */ + { "MEZ", tZONE, HOUR ( 1) }, /* Middle European */ + { "MEST", tDAYZONE, HOUR ( 1) }, /* Middle European Summer */ + { "MESZ", tDAYZONE, HOUR ( 1) }, /* Middle European Summer */ + { "EET", tZONE, HOUR ( 2) }, /* Eastern European */ + { "EEST", tDAYZONE, HOUR ( 2) }, /* Eastern European Summer */ + { "CAT", tZONE, HOUR ( 2) }, /* Central Africa */ + { "SAST", tZONE, HOUR ( 2) }, /* South Africa Standard */ + { "EAT", tZONE, HOUR ( 3) }, /* East Africa */ + { "MSK", tZONE, HOUR ( 3) }, /* Moscow */ + { "MSD", tDAYZONE, HOUR ( 3) }, /* Moscow Daylight */ + { "IST", tZONE, (HOUR ( 5) + 30) }, /* India Standard */ + { "SGT", tZONE, HOUR ( 8) }, /* Singapore */ + { "KST", tZONE, HOUR ( 9) }, /* Korea Standard */ + { "JST", tZONE, HOUR ( 9) }, /* Japan Standard */ + { "GST", tZONE, HOUR (10) }, /* Guam Standard */ + { "NZST", tZONE, HOUR (12) }, /* New Zealand Standard */ + { "NZDT", tDAYZONE, HOUR (12) }, /* New Zealand Daylight */ + { 0, 0, 0 } +}; + +/* Military time zone table. */ +static table const military_table[] = +{ + { "A", tZONE, -HOUR ( 1) }, + { "B", tZONE, -HOUR ( 2) }, + { "C", tZONE, -HOUR ( 3) }, + { "D", tZONE, -HOUR ( 4) }, + { "E", tZONE, -HOUR ( 5) }, + { "F", tZONE, -HOUR ( 6) }, + { "G", tZONE, -HOUR ( 7) }, + { "H", tZONE, -HOUR ( 8) }, + { "I", tZONE, -HOUR ( 9) }, + { "K", tZONE, -HOUR (10) }, + { "L", tZONE, -HOUR (11) }, + { "M", tZONE, -HOUR (12) }, + { "N", tZONE, HOUR ( 1) }, + { "O", tZONE, HOUR ( 2) }, + { "P", tZONE, HOUR ( 3) }, + { "Q", tZONE, HOUR ( 4) }, + { "R", tZONE, HOUR ( 5) }, + { "S", tZONE, HOUR ( 6) }, + { "T", tZONE, HOUR ( 7) }, + { "U", tZONE, HOUR ( 8) }, + { "V", tZONE, HOUR ( 9) }, + { "W", tZONE, HOUR (10) }, + { "X", tZONE, HOUR (11) }, + { "Y", tZONE, HOUR (12) }, + { "Z", tZONE, HOUR ( 0) }, + { 0, 0, 0 } +}; + + + +static int +to_hour (int hours, int meridian) +{ + switch (meridian) + { + case MER24: + return 0 <= hours && hours < 24 ? hours : -1; + case MERam: + return 0 < hours && hours < 12 ? hours : hours == 12 ? 0 : -1; + case MERpm: + return 0 < hours && hours < 12 ? hours + 12 : hours == 12 ? 12 : -1; + default: + abort (); + } + /* NOTREACHED */ + return 0; +} + +static int +to_year (textint textyear) +{ + int year = textyear.value; + + if (year < 0) + year = -year; + + /* XPG4 suggests that years 00-68 map to 2000-2068, and + years 69-99 map to 1969-1999. */ + if (textyear.digits == 2) + year += year < 69 ? 2000 : 1900; + + return year; +} + +static table const * +lookup_zone (parser_control const *pc, char const *name) +{ + table const *tp; + + /* Try local zone abbreviations first; they're more likely to be right. */ + for (tp = pc->local_time_zone_table; tp->name; tp++) + if (strcmp (name, tp->name) == 0) + return tp; + + for (tp = time_zone_table; tp->name; tp++) + if (strcmp (name, tp->name) == 0) + return tp; + + return 0; +} + +#if ! HAVE_TM_GMTOFF +/* Yield the difference between *A and *B, + measured in seconds, ignoring leap seconds. + The body of this function is taken directly from the GNU C Library; + see src/strftime.c. */ +static int +tm_diff (struct tm const *a, struct tm const *b) +{ + /* Compute intervening leap days correctly even if year is negative. + Take care to avoid int overflow in leap day calculations, + but it's OK to assume that A and B are close to each other. */ + int a4 = (a->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (a->tm_year & 3); + int b4 = (b->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (b->tm_year & 3); + int a100 = a4 / 25 - (a4 % 25 < 0); + int b100 = b4 / 25 - (b4 % 25 < 0); + int a400 = a100 >> 2; + int b400 = b100 >> 2; + int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400); + int years = a->tm_year - b->tm_year; + int days = (365 * years + intervening_leap_days + + (a->tm_yday - b->tm_yday)); + return (60 * (60 * (24 * days + (a->tm_hour - b->tm_hour)) + + (a->tm_min - b->tm_min)) + + (a->tm_sec - b->tm_sec)); +} +#endif /* ! HAVE_TM_GMTOFF */ + +static table const * +lookup_word (parser_control const *pc, char *word) +{ + char *p; + char *q; + size_t wordlen; + table const *tp; + int i; + int abbrev; + + /* Make it uppercase. */ + for (p = word; *p; p++) + if (ISLOWER ((unsigned char) *p)) + *p = toupper ((unsigned char) *p); + + for (tp = meridian_table; tp->name; tp++) + if (strcmp (word, tp->name) == 0) + return tp; + + /* See if we have an abbreviation for a month. */ + wordlen = strlen (word); + abbrev = wordlen == 3 || (wordlen == 4 && word[3] == '.'); + + for (tp = month_and_day_table; tp->name; tp++) + if ((abbrev ? strncmp (word, tp->name, 3) : strcmp (word, tp->name)) == 0) + return tp; + + if ((tp = lookup_zone (pc, word))) + return tp; + + if (strcmp (word, dst_table[0].name) == 0) + return dst_table; + + for (tp = time_units_table; tp->name; tp++) + if (strcmp (word, tp->name) == 0) + return tp; + + /* Strip off any plural and try the units table again. */ + if (word[wordlen - 1] == 'S') + { + word[wordlen - 1] = '\0'; + for (tp = time_units_table; tp->name; tp++) + if (strcmp (word, tp->name) == 0) + return tp; + word[wordlen - 1] = 'S'; /* For "this" in relative_time_table. */ + } + + for (tp = relative_time_table; tp->name; tp++) + if (strcmp (word, tp->name) == 0) + return tp; + + /* Military time zones. */ + if (wordlen == 1) + for (tp = military_table; tp->name; tp++) + if (word[0] == tp->name[0]) + return tp; + + /* Drop out any periods and try the time zone table again. */ + for (i = 0, p = q = word; (*p = *q); q++) + if (*q == '.') + i = 1; + else + p++; + if (i && (tp = lookup_zone (pc, word))) + return tp; + + return 0; +} + +static int +yylex (YYSTYPE *lvalp, parser_control *pc) +{ + unsigned char c; + int count; + + for (;;) + { + while (c = *pc->input, ISSPACE (c)) + pc->input++; + + if (ISDIGIT (c) || c == '-' || c == '+') + { + char const *p; + int sign; + int value; + if (c == '-' || c == '+') + { + sign = c == '-' ? -1 : 1; + c = *++pc->input; + if (! ISDIGIT (c)) + /* skip the '-' sign */ + continue; + } + else + sign = 0; + p = pc->input; + value = 0; + do + { + value = 10 * value + c - '0'; + c = *++p; + } + while (ISDIGIT (c)); + lvalp->textintval.value = sign < 0 ? -value : value; + lvalp->textintval.digits = p - pc->input; + pc->input = p; + return sign ? tSNUMBER : tUNUMBER; + } + + if (ISALPHA (c)) + { + char buff[20]; + char *p = buff; + table const *tp; + + do + { + if (p < buff + sizeof buff - 1) + *p++ = c; + c = *++pc->input; + } + while (ISALPHA (c) || c == '.'); + + *p = '\0'; + tp = lookup_word (pc, buff); + if (! tp) + return '?'; + lvalp->intval = tp->value; + return tp->type; + } + + if (c != '(') + return *pc->input++; + count = 0; + do + { + c = *pc->input++; + if (c == '\0') + return c; + if (c == '(') + count++; + else if (c == ')') + count--; + } + while (count > 0); + } +} + +/* Do nothing if the parser reports an error. */ +static int +yyerror (char *s ATTRIBUTE_UNUSED) +{ + return 0; +} + +/* Parse a date/time string P. Return the corresponding time_t value, + or (time_t) -1 if there is an error. P can be an incomplete or + relative time specification; if so, use *NOW as the basis for the + returned time. */ +time_t +get_date (const char *p, const time_t *now) +{ + time_t Start = now ? *now : time (0); + struct tm *tmp = localtime (&Start); + struct tm tm; + struct tm tm0; + parser_control pc; + + if (! tmp) + return -1; + + pc.input = p; + pc.year.value = tmp->tm_year + TM_YEAR_BASE; + pc.year.digits = 4; + pc.month = tmp->tm_mon + 1; + pc.day = tmp->tm_mday; + pc.hour = tmp->tm_hour; + pc.minutes = tmp->tm_min; + pc.seconds = tmp->tm_sec; + tm.tm_isdst = tmp->tm_isdst; + + pc.meridian = MER24; + pc.rel_seconds = 0; + pc.rel_minutes = 0; + pc.rel_hour = 0; + pc.rel_day = 0; + pc.rel_month = 0; + pc.rel_year = 0; + pc.dates_seen = 0; + pc.days_seen = 0; + pc.rels_seen = 0; + pc.times_seen = 0; + pc.local_zones_seen = 0; + pc.zones_seen = 0; + +#if HAVE_STRUCT_TM_TM_ZONE + pc.local_time_zone_table[0].name = tmp->tm_zone; + pc.local_time_zone_table[0].type = tLOCAL_ZONE; + pc.local_time_zone_table[0].value = tmp->tm_isdst; + pc.local_time_zone_table[1].name = 0; + + /* Probe the names used in the next three calendar quarters, looking + for a tm_isdst different from the one we already have. */ + { + int quarter; + for (quarter = 1; quarter <= 3; quarter++) + { + time_t probe = Start + quarter * (90 * 24 * 60 * 60); + struct tm *probe_tm = localtime (&probe); + if (probe_tm && probe_tm->tm_zone + && probe_tm->tm_isdst != pc.local_time_zone_table[0].value) + { + { + pc.local_time_zone_table[1].name = probe_tm->tm_zone; + pc.local_time_zone_table[1].type = tLOCAL_ZONE; + pc.local_time_zone_table[1].value = probe_tm->tm_isdst; + pc.local_time_zone_table[2].name = 0; + } + break; + } + } + } +#else +#if HAVE_TZNAME + { +# ifndef tzname + extern char *tzname[]; +# endif + int i; + for (i = 0; i < 2; i++) + { + pc.local_time_zone_table[i].name = tzname[i]; + pc.local_time_zone_table[i].type = tLOCAL_ZONE; + pc.local_time_zone_table[i].value = i; + } + pc.local_time_zone_table[i].name = 0; + } +#else + pc.local_time_zone_table[0].name = 0; +#endif +#endif + + if (pc.local_time_zone_table[0].name && pc.local_time_zone_table[1].name + && ! strcmp (pc.local_time_zone_table[0].name, + pc.local_time_zone_table[1].name)) + { + /* This locale uses the same abbrevation for standard and + daylight times. So if we see that abbreviation, we don't + know whether it's daylight time. */ + pc.local_time_zone_table[0].value = -1; + pc.local_time_zone_table[1].name = 0; + } + + if (yyparse (&pc) != 0 + || 1 < pc.times_seen || 1 < pc.dates_seen || 1 < pc.days_seen + || 1 < (pc.local_zones_seen + pc.zones_seen) + || (pc.local_zones_seen && 1 < pc.local_isdst)) + return -1; + + tm.tm_year = to_year (pc.year) - TM_YEAR_BASE + pc.rel_year; + tm.tm_mon = pc.month - 1 + pc.rel_month; + tm.tm_mday = pc.day + pc.rel_day; + if (pc.times_seen || (pc.rels_seen && ! pc.dates_seen && ! pc.days_seen)) + { + tm.tm_hour = to_hour (pc.hour, pc.meridian); + if (tm.tm_hour < 0) + return -1; + tm.tm_min = pc.minutes; + tm.tm_sec = pc.seconds; + } + else + { + tm.tm_hour = tm.tm_min = tm.tm_sec = 0; + } + + /* Let mktime deduce tm_isdst if we have an absolute time stamp, + or if the relative time stamp mentions days, months, or years. */ + if (pc.dates_seen | pc.days_seen | pc.times_seen | pc.rel_day + | pc.rel_month | pc.rel_year) + tm.tm_isdst = -1; + + /* But if the input explicitly specifies local time with or without + DST, give mktime that information. */ + if (pc.local_zones_seen) + tm.tm_isdst = pc.local_isdst; + + tm0 = tm; + + Start = mktime (&tm); + + if (Start == (time_t) -1) + { + + /* Guard against falsely reporting errors near the time_t boundaries + when parsing times in other time zones. For example, if the min + time_t value is 1970-01-01 00:00:00 UTC and we are 8 hours ahead + of UTC, then the min localtime value is 1970-01-01 08:00:00; if + we apply mktime to 1970-01-01 00:00:00 we will get an error, so + we apply mktime to 1970-01-02 08:00:00 instead and adjust the time + zone by 24 hours to compensate. This algorithm assumes that + there is no DST transition within a day of the time_t boundaries. */ + if (pc.zones_seen) + { + tm = tm0; + if (tm.tm_year <= EPOCH_YEAR - TM_YEAR_BASE) + { + tm.tm_mday++; + pc.time_zone += 24 * 60; + } + else + { + tm.tm_mday--; + pc.time_zone -= 24 * 60; + } + Start = mktime (&tm); + } + + if (Start == (time_t) -1) + return Start; + } + + if (pc.days_seen && ! pc.dates_seen) + { + tm.tm_mday += ((pc.day_number - tm.tm_wday + 7) % 7 + + 7 * (pc.day_ordinal - (0 < pc.day_ordinal))); + tm.tm_isdst = -1; + Start = mktime (&tm); + if (Start == (time_t) -1) + return Start; + } + + if (pc.zones_seen) + { + int delta = pc.time_zone * 60; +#ifdef HAVE_TM_GMTOFF + delta -= tm.tm_gmtoff; +#else + struct tm *gmt = gmtime (&Start); + if (! gmt) + return -1; + delta -= tm_diff (&tm, gmt); +#endif + if ((Start < Start - delta) != (delta < 0)) + return -1; /* time_t overflow */ + Start -= delta; + } + + /* Add relative hours, minutes, and seconds. Ignore leap seconds; + i.e. "+ 10 minutes" means 600 seconds, even if one of them is a + leap second. Typically this is not what the user wants, but it's + too hard to do it the other way, because the time zone indicator + must be applied before relative times, and if mktime is applied + again the time zone will be lost. */ + { + time_t t0 = Start; + long d1 = 60 * 60 * (long) pc.rel_hour; + time_t t1 = t0 + d1; + long d2 = 60 * (long) pc.rel_minutes; + time_t t2 = t1 + d2; + int d3 = pc.rel_seconds; + time_t t3 = t2 + d3; + if ((d1 / (60 * 60) ^ pc.rel_hour) + | (d2 / 60 ^ pc.rel_minutes) + | ((t0 + d1 < t0) ^ (d1 < 0)) + | ((t1 + d2 < t1) ^ (d2 < 0)) + | ((t2 + d3 < t2) ^ (d3 < 0))) + return -1; + Start = t3; + } + + return Start; +} + +#if TEST + +#include + +int +main (int ac, char **av) +{ + char buff[BUFSIZ]; + time_t d; + + printf ("Enter date, or blank line to exit.\n\t> "); + fflush (stdout); + + buff[BUFSIZ - 1] = 0; + while (fgets (buff, BUFSIZ - 1, stdin) && buff[0]) + { + d = get_date (buff, 0); + if (d == (time_t) -1) + printf ("Bad format - couldn't convert.\n"); + else + printf ("%s", ctime (&d)); + printf ("\t> "); + fflush (stdout); + } + return 0; +} +#endif /* defined TEST */ + + diff --git a/source3/modules/getdate.h b/source3/modules/getdate.h new file mode 100644 index 0000000000..674c474f11 --- /dev/null +++ b/source3/modules/getdate.h @@ -0,0 +1,46 @@ +/* Copyright (C) 1995, 1997, 1998 Free Software Foundation, Inc. + + 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, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#if HAVE_CONFIG_H +# include +#endif + +#ifndef PARAMS +# if defined PROTOTYPES || (defined __STDC__ && __STDC__) +# define PARAMS(Args) Args +# else +# define PARAMS(Args) () +# endif +#endif + +#ifdef vms +# include +# include +#else +# include +# if TIME_WITH_SYS_TIME +# include +# include +# else +# if HAVE_SYS_TIME_H +# include +# else +# include +# endif +# endif +#endif /* defined (vms) */ + +time_t get_date PARAMS ((const char *p, const time_t *now)); diff --git a/source3/modules/getdate.y b/source3/modules/getdate.y new file mode 100644 index 0000000000..aab37f4d23 --- /dev/null +++ b/source3/modules/getdate.y @@ -0,0 +1,1115 @@ +%{ +/* Parse a string into an internal time stamp. + Copyright (C) 1999, 2000, 2002 Free Software Foundation, Inc. + + 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, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* Originally written by Steven M. Bellovin while + at the University of North Carolina at Chapel Hill. Later tweaked by + a couple of people on Usenet. Completely overhauled by Rich $alz + and Jim Berets in August, 1990. + + Modified by Paul Eggert in August 1999 to do + the right thing about local DST. Unlike previous versions, this + version is reentrant. */ + +#ifdef HAVE_CONFIG_H +# include +# ifdef HAVE_ALLOCA_H +# include +# endif +#endif + +/* Since the code of getdate.y is not included in the Emacs executable + itself, there is no need to #define static in this file. Even if + the code were included in the Emacs executable, it probably + wouldn't do any harm to #undef it here; this will only cause + problems if we try to write to a static variable, which I don't + think this code needs to do. */ +#ifdef emacs +# undef static +#endif + +#include + +#if HAVE_STDLIB_H +# include /* for `free'; used by Bison 1.27 */ +#endif + +#if STDC_HEADERS || (! defined isascii && ! HAVE_ISASCII) +# define IN_CTYPE_DOMAIN(c) 1 +#else +# define IN_CTYPE_DOMAIN(c) isascii (c) +#endif + +#define ISSPACE(c) (IN_CTYPE_DOMAIN (c) && isspace (c)) +#define ISALPHA(c) (IN_CTYPE_DOMAIN (c) && isalpha (c)) +#define ISLOWER(c) (IN_CTYPE_DOMAIN (c) && islower (c)) +#define ISDIGIT_LOCALE(c) (IN_CTYPE_DOMAIN (c) && isdigit (c)) + +/* ISDIGIT differs from ISDIGIT_LOCALE, as follows: + - Its arg may be any int or unsigned int; it need not be an unsigned char. + - It's guaranteed to evaluate its argument exactly once. + - It's typically faster. + POSIX says that only '0' through '9' are digits. Prefer ISDIGIT to + ISDIGIT_LOCALE unless it's important to use the locale's definition + of `digit' even when the host does not conform to POSIX. */ +#define ISDIGIT(c) ((unsigned) (c) - '0' <= 9) + +#if STDC_HEADERS || HAVE_STRING_H +# include +#endif + +#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8) || __STRICT_ANSI__ +# define __attribute__(x) +#endif + +#ifndef ATTRIBUTE_UNUSED +# define ATTRIBUTE_UNUSED __attribute__ ((__unused__)) +#endif + +#define EPOCH_YEAR 1970 +#define TM_YEAR_BASE 1900 + +#define HOUR(x) ((x) * 60) + +/* An integer value, and the number of digits in its textual + representation. */ +typedef struct +{ + int value; + int digits; +} textint; + +/* An entry in the lexical lookup table. */ +typedef struct +{ + char const *name; + int type; + int value; +} table; + +/* Meridian: am, pm, or 24-hour style. */ +enum { MERam, MERpm, MER24 }; + +/* Information passed to and from the parser. */ +typedef struct +{ + /* The input string remaining to be parsed. */ + const char *input; + + /* N, if this is the Nth Tuesday. */ + int day_ordinal; + + /* Day of week; Sunday is 0. */ + int day_number; + + /* tm_isdst flag for the local zone. */ + int local_isdst; + + /* Time zone, in minutes east of UTC. */ + int time_zone; + + /* Style used for time. */ + int meridian; + + /* Gregorian year, month, day, hour, minutes, and seconds. */ + textint year; + int month; + int day; + int hour; + int minutes; + int seconds; + + /* Relative year, month, day, hour, minutes, and seconds. */ + int rel_year; + int rel_month; + int rel_day; + int rel_hour; + int rel_minutes; + int rel_seconds; + + /* Counts of nonterminals of various flavors parsed so far. */ + int dates_seen; + int days_seen; + int local_zones_seen; + int rels_seen; + int times_seen; + int zones_seen; + + /* Table of local time zone abbrevations, terminated by a null entry. */ + table local_time_zone_table[3]; +} parser_control; + +#define PC (* (parser_control *) parm) +#define YYLEX_PARAM parm +#define YYPARSE_PARAM parm + +static int yyerror (); +static int yylex (); + +%} + +/* We want a reentrant parser. */ +%pure_parser + +/* This grammar has 13 shift/reduce conflicts. */ +%expect 13 + +%union +{ + int intval; + textint textintval; +} + +%token tAGO tDST + +%token tDAY tDAY_UNIT tDAYZONE tHOUR_UNIT tLOCAL_ZONE tMERIDIAN +%token tMINUTE_UNIT tMONTH tMONTH_UNIT tSEC_UNIT tYEAR_UNIT tZONE + +%token tSNUMBER tUNUMBER + +%type o_merid + +%% + +spec: + /* empty */ + | spec item + ; + +item: + time + { PC.times_seen++; } + | local_zone + { PC.local_zones_seen++; } + | zone + { PC.zones_seen++; } + | date + { PC.dates_seen++; } + | day + { PC.days_seen++; } + | rel + { PC.rels_seen++; } + | number + ; + +time: + tUNUMBER tMERIDIAN + { + PC.hour = $1.value; + PC.minutes = 0; + PC.seconds = 0; + PC.meridian = $2; + } + | tUNUMBER ':' tUNUMBER o_merid + { + PC.hour = $1.value; + PC.minutes = $3.value; + PC.seconds = 0; + PC.meridian = $4; + } + | tUNUMBER ':' tUNUMBER tSNUMBER + { + PC.hour = $1.value; + PC.minutes = $3.value; + PC.meridian = MER24; + PC.zones_seen++; + PC.time_zone = $4.value % 100 + ($4.value / 100) * 60; + } + | tUNUMBER ':' tUNUMBER ':' tUNUMBER o_merid + { + PC.hour = $1.value; + PC.minutes = $3.value; + PC.seconds = $5.value; + PC.meridian = $6; + } + | tUNUMBER ':' tUNUMBER ':' tUNUMBER tSNUMBER + { + PC.hour = $1.value; + PC.minutes = $3.value; + PC.seconds = $5.value; + PC.meridian = MER24; + PC.zones_seen++; + PC.time_zone = $6.value % 100 + ($6.value / 100) * 60; + } + ; + +local_zone: + tLOCAL_ZONE + { PC.local_isdst = $1; } + | tLOCAL_ZONE tDST + { PC.local_isdst = $1 < 0 ? 1 : $1 + 1; } + ; + +zone: + tZONE + { PC.time_zone = $1; } + | tDAYZONE + { PC.time_zone = $1 + 60; } + | tZONE tDST + { PC.time_zone = $1 + 60; } + ; + +day: + tDAY + { + PC.day_ordinal = 1; + PC.day_number = $1; + } + | tDAY ',' + { + PC.day_ordinal = 1; + PC.day_number = $1; + } + | tUNUMBER tDAY + { + PC.day_ordinal = $1.value; + PC.day_number = $2; + } + ; + +date: + tUNUMBER '/' tUNUMBER + { + PC.month = $1.value; + PC.day = $3.value; + } + | tUNUMBER '/' tUNUMBER '/' tUNUMBER + { + /* Interpret as YYYY/MM/DD if the first value has 4 or more digits, + otherwise as MM/DD/YY. + The goal in recognizing YYYY/MM/DD is solely to support legacy + machine-generated dates like those in an RCS log listing. If + you want portability, use the ISO 8601 format. */ + if (4 <= $1.digits) + { + PC.year = $1; + PC.month = $3.value; + PC.day = $5.value; + } + else + { + PC.month = $1.value; + PC.day = $3.value; + PC.year = $5; + } + } + | tUNUMBER tSNUMBER tSNUMBER + { + /* ISO 8601 format. YYYY-MM-DD. */ + PC.year = $1; + PC.month = -$2.value; + PC.day = -$3.value; + } + | tUNUMBER tMONTH tSNUMBER + { + /* e.g. 17-JUN-1992. */ + PC.day = $1.value; + PC.month = $2; + PC.year.value = -$3.value; + PC.year.digits = $3.digits; + } + | tMONTH tUNUMBER + { + PC.month = $1; + PC.day = $2.value; + } + | tMONTH tUNUMBER ',' tUNUMBER + { + PC.month = $1; + PC.day = $2.value; + PC.year = $4; + } + | tUNUMBER tMONTH + { + PC.day = $1.value; + PC.month = $2; + } + | tUNUMBER tMONTH tUNUMBER + { + PC.day = $1.value; + PC.month = $2; + PC.year = $3; + } + ; + +rel: + relunit tAGO + { + PC.rel_seconds = -PC.rel_seconds; + PC.rel_minutes = -PC.rel_minutes; + PC.rel_hour = -PC.rel_hour; + PC.rel_day = -PC.rel_day; + PC.rel_month = -PC.rel_month; + PC.rel_year = -PC.rel_year; + } + | relunit + ; + +relunit: + tUNUMBER tYEAR_UNIT + { PC.rel_year += $1.value * $2; } + | tSNUMBER tYEAR_UNIT + { PC.rel_year += $1.value * $2; } + | tYEAR_UNIT + { PC.rel_year += $1; } + | tUNUMBER tMONTH_UNIT + { PC.rel_month += $1.value * $2; } + | tSNUMBER tMONTH_UNIT + { PC.rel_month += $1.value * $2; } + | tMONTH_UNIT + { PC.rel_month += $1; } + | tUNUMBER tDAY_UNIT + { PC.rel_day += $1.value * $2; } + | tSNUMBER tDAY_UNIT + { PC.rel_day += $1.value * $2; } + | tDAY_UNIT + { PC.rel_day += $1; } + | tUNUMBER tHOUR_UNIT + { PC.rel_hour += $1.value * $2; } + | tSNUMBER tHOUR_UNIT + { PC.rel_hour += $1.value * $2; } + | tHOUR_UNIT + { PC.rel_hour += $1; } + | tUNUMBER tMINUTE_UNIT + { PC.rel_minutes += $1.value * $2; } + | tSNUMBER tMINUTE_UNIT + { PC.rel_minutes += $1.value * $2; } + | tMINUTE_UNIT + { PC.rel_minutes += $1; } + | tUNUMBER tSEC_UNIT + { PC.rel_seconds += $1.value * $2; } + | tSNUMBER tSEC_UNIT + { PC.rel_seconds += $1.value * $2; } + | tSEC_UNIT + { PC.rel_seconds += $1; } + ; + +number: + tUNUMBER + { + if (PC.dates_seen + && ! PC.rels_seen && (PC.times_seen || 2 < $1.digits)) + PC.year = $1; + else + { + if (4 < $1.digits) + { + PC.dates_seen++; + PC.day = $1.value % 100; + PC.month = ($1.value / 100) % 100; + PC.year.value = $1.value / 10000; + PC.year.digits = $1.digits - 4; + } + else + { + PC.times_seen++; + if ($1.digits <= 2) + { + PC.hour = $1.value; + PC.minutes = 0; + } + else + { + PC.hour = $1.value / 100; + PC.minutes = $1.value % 100; + } + PC.seconds = 0; + PC.meridian = MER24; + } + } + } + ; + +o_merid: + /* empty */ + { $$ = MER24; } + | tMERIDIAN + { $$ = $1; } + ; + +%% + +/* Include this file down here because bison inserts code above which + may define-away `const'. We want the prototype for get_date to have + the same signature as the function definition. */ +#include "modules/getdate.h" + +#ifndef gmtime +struct tm *gmtime (); +#endif +#ifndef localtime +struct tm *localtime (); +#endif +#ifndef mktime +time_t mktime (); +#endif + +static table const meridian_table[] = +{ + { "AM", tMERIDIAN, MERam }, + { "A.M.", tMERIDIAN, MERam }, + { "PM", tMERIDIAN, MERpm }, + { "P.M.", tMERIDIAN, MERpm }, + { 0, 0, 0 } +}; + +static table const dst_table[] = +{ + { "DST", tDST, 0 } +}; + +static table const month_and_day_table[] = +{ + { "JANUARY", tMONTH, 1 }, + { "FEBRUARY", tMONTH, 2 }, + { "MARCH", tMONTH, 3 }, + { "APRIL", tMONTH, 4 }, + { "MAY", tMONTH, 5 }, + { "JUNE", tMONTH, 6 }, + { "JULY", tMONTH, 7 }, + { "AUGUST", tMONTH, 8 }, + { "SEPTEMBER",tMONTH, 9 }, + { "SEPT", tMONTH, 9 }, + { "OCTOBER", tMONTH, 10 }, + { "NOVEMBER", tMONTH, 11 }, + { "DECEMBER", tMONTH, 12 }, + { "SUNDAY", tDAY, 0 }, + { "MONDAY", tDAY, 1 }, + { "TUESDAY", tDAY, 2 }, + { "TUES", tDAY, 2 }, + { "WEDNESDAY",tDAY, 3 }, + { "WEDNES", tDAY, 3 }, + { "THURSDAY", tDAY, 4 }, + { "THUR", tDAY, 4 }, + { "THURS", tDAY, 4 }, + { "FRIDAY", tDAY, 5 }, + { "SATURDAY", tDAY, 6 }, + { 0, 0, 0 } +}; + +static table const time_units_table[] = +{ + { "YEAR", tYEAR_UNIT, 1 }, + { "MONTH", tMONTH_UNIT, 1 }, + { "FORTNIGHT",tDAY_UNIT, 14 }, + { "WEEK", tDAY_UNIT, 7 }, + { "DAY", tDAY_UNIT, 1 }, + { "HOUR", tHOUR_UNIT, 1 }, + { "MINUTE", tMINUTE_UNIT, 1 }, + { "MIN", tMINUTE_UNIT, 1 }, + { "SECOND", tSEC_UNIT, 1 }, + { "SEC", tSEC_UNIT, 1 }, + { 0, 0, 0 } +}; + +/* Assorted relative-time words. */ +static table const relative_time_table[] = +{ + { "TOMORROW", tMINUTE_UNIT, 24 * 60 }, + { "YESTERDAY",tMINUTE_UNIT, - (24 * 60) }, + { "TODAY", tMINUTE_UNIT, 0 }, + { "NOW", tMINUTE_UNIT, 0 }, + { "LAST", tUNUMBER, -1 }, + { "THIS", tUNUMBER, 0 }, + { "NEXT", tUNUMBER, 1 }, + { "FIRST", tUNUMBER, 1 }, +/*{ "SECOND", tUNUMBER, 2 }, */ + { "THIRD", tUNUMBER, 3 }, + { "FOURTH", tUNUMBER, 4 }, + { "FIFTH", tUNUMBER, 5 }, + { "SIXTH", tUNUMBER, 6 }, + { "SEVENTH", tUNUMBER, 7 }, + { "EIGHTH", tUNUMBER, 8 }, + { "NINTH", tUNUMBER, 9 }, + { "TENTH", tUNUMBER, 10 }, + { "ELEVENTH", tUNUMBER, 11 }, + { "TWELFTH", tUNUMBER, 12 }, + { "AGO", tAGO, 1 }, + { 0, 0, 0 } +}; + +/* The time zone table. This table is necessarily incomplete, as time + zone abbreviations are ambiguous; e.g. Australians interpret "EST" + as Eastern time in Australia, not as US Eastern Standard Time. + You cannot rely on getdate to handle arbitrary time zone + abbreviations; use numeric abbreviations like `-0500' instead. */ +static table const time_zone_table[] = +{ + { "GMT", tZONE, HOUR ( 0) }, /* Greenwich Mean */ + { "UT", tZONE, HOUR ( 0) }, /* Universal (Coordinated) */ + { "UTC", tZONE, HOUR ( 0) }, + { "WET", tZONE, HOUR ( 0) }, /* Western European */ + { "WEST", tDAYZONE, HOUR ( 0) }, /* Western European Summer */ + { "BST", tDAYZONE, HOUR ( 0) }, /* British Summer */ + { "ART", tZONE, -HOUR ( 3) }, /* Argentina */ + { "BRT", tZONE, -HOUR ( 3) }, /* Brazil */ + { "BRST", tDAYZONE, -HOUR ( 3) }, /* Brazil Summer */ + { "NST", tZONE, -(HOUR ( 3) + 30) }, /* Newfoundland Standard */ + { "NDT", tDAYZONE,-(HOUR ( 3) + 30) }, /* Newfoundland Daylight */ + { "AST", tZONE, -HOUR ( 4) }, /* Atlantic Standard */ + { "ADT", tDAYZONE, -HOUR ( 4) }, /* Atlantic Daylight */ + { "CLT", tZONE, -HOUR ( 4) }, /* Chile */ + { "CLST", tDAYZONE, -HOUR ( 4) }, /* Chile Summer */ + { "EST", tZONE, -HOUR ( 5) }, /* Eastern Standard */ + { "EDT", tDAYZONE, -HOUR ( 5) }, /* Eastern Daylight */ + { "CST", tZONE, -HOUR ( 6) }, /* Central Standard */ + { "CDT", tDAYZONE, -HOUR ( 6) }, /* Central Daylight */ + { "MST", tZONE, -HOUR ( 7) }, /* Mountain Standard */ + { "MDT", tDAYZONE, -HOUR ( 7) }, /* Mountain Daylight */ + { "PST", tZONE, -HOUR ( 8) }, /* Pacific Standard */ + { "PDT", tDAYZONE, -HOUR ( 8) }, /* Pacific Daylight */ + { "AKST", tZONE, -HOUR ( 9) }, /* Alaska Standard */ + { "AKDT", tDAYZONE, -HOUR ( 9) }, /* Alaska Daylight */ + { "HST", tZONE, -HOUR (10) }, /* Hawaii Standard */ + { "HAST", tZONE, -HOUR (10) }, /* Hawaii-Aleutian Standard */ + { "HADT", tDAYZONE, -HOUR (10) }, /* Hawaii-Aleutian Daylight */ + { "SST", tZONE, -HOUR (12) }, /* Samoa Standard */ + { "WAT", tZONE, HOUR ( 1) }, /* West Africa */ + { "CET", tZONE, HOUR ( 1) }, /* Central European */ + { "CEST", tDAYZONE, HOUR ( 1) }, /* Central European Summer */ + { "MET", tZONE, HOUR ( 1) }, /* Middle European */ + { "MEZ", tZONE, HOUR ( 1) }, /* Middle European */ + { "MEST", tDAYZONE, HOUR ( 1) }, /* Middle European Summer */ + { "MESZ", tDAYZONE, HOUR ( 1) }, /* Middle European Summer */ + { "EET", tZONE, HOUR ( 2) }, /* Eastern European */ + { "EEST", tDAYZONE, HOUR ( 2) }, /* Eastern European Summer */ + { "CAT", tZONE, HOUR ( 2) }, /* Central Africa */ + { "SAST", tZONE, HOUR ( 2) }, /* South Africa Standard */ + { "EAT", tZONE, HOUR ( 3) }, /* East Africa */ + { "MSK", tZONE, HOUR ( 3) }, /* Moscow */ + { "MSD", tDAYZONE, HOUR ( 3) }, /* Moscow Daylight */ + { "IST", tZONE, (HOUR ( 5) + 30) }, /* India Standard */ + { "SGT", tZONE, HOUR ( 8) }, /* Singapore */ + { "KST", tZONE, HOUR ( 9) }, /* Korea Standard */ + { "JST", tZONE, HOUR ( 9) }, /* Japan Standard */ + { "GST", tZONE, HOUR (10) }, /* Guam Standard */ + { "NZST", tZONE, HOUR (12) }, /* New Zealand Standard */ + { "NZDT", tDAYZONE, HOUR (12) }, /* New Zealand Daylight */ + { 0, 0, 0 } +}; + +/* Military time zone table. */ +static table const military_table[] = +{ + { "A", tZONE, -HOUR ( 1) }, + { "B", tZONE, -HOUR ( 2) }, + { "C", tZONE, -HOUR ( 3) }, + { "D", tZONE, -HOUR ( 4) }, + { "E", tZONE, -HOUR ( 5) }, + { "F", tZONE, -HOUR ( 6) }, + { "G", tZONE, -HOUR ( 7) }, + { "H", tZONE, -HOUR ( 8) }, + { "I", tZONE, -HOUR ( 9) }, + { "K", tZONE, -HOUR (10) }, + { "L", tZONE, -HOUR (11) }, + { "M", tZONE, -HOUR (12) }, + { "N", tZONE, HOUR ( 1) }, + { "O", tZONE, HOUR ( 2) }, + { "P", tZONE, HOUR ( 3) }, + { "Q", tZONE, HOUR ( 4) }, + { "R", tZONE, HOUR ( 5) }, + { "S", tZONE, HOUR ( 6) }, + { "T", tZONE, HOUR ( 7) }, + { "U", tZONE, HOUR ( 8) }, + { "V", tZONE, HOUR ( 9) }, + { "W", tZONE, HOUR (10) }, + { "X", tZONE, HOUR (11) }, + { "Y", tZONE, HOUR (12) }, + { "Z", tZONE, HOUR ( 0) }, + { 0, 0, 0 } +}; + + + +static int +to_hour (int hours, int meridian) +{ + switch (meridian) + { + case MER24: + return 0 <= hours && hours < 24 ? hours : -1; + case MERam: + return 0 < hours && hours < 12 ? hours : hours == 12 ? 0 : -1; + case MERpm: + return 0 < hours && hours < 12 ? hours + 12 : hours == 12 ? 12 : -1; + default: + abort (); + } + /* NOTREACHED */ + return 0; +} + +static int +to_year (textint textyear) +{ + int year = textyear.value; + + if (year < 0) + year = -year; + + /* XPG4 suggests that years 00-68 map to 2000-2068, and + years 69-99 map to 1969-1999. */ + if (textyear.digits == 2) + year += year < 69 ? 2000 : 1900; + + return year; +} + +static table const * +lookup_zone (parser_control const *pc, char const *name) +{ + table const *tp; + + /* Try local zone abbreviations first; they're more likely to be right. */ + for (tp = pc->local_time_zone_table; tp->name; tp++) + if (strcmp (name, tp->name) == 0) + return tp; + + for (tp = time_zone_table; tp->name; tp++) + if (strcmp (name, tp->name) == 0) + return tp; + + return 0; +} + +#if ! HAVE_TM_GMTOFF +/* Yield the difference between *A and *B, + measured in seconds, ignoring leap seconds. + The body of this function is taken directly from the GNU C Library; + see src/strftime.c. */ +static int +tm_diff (struct tm const *a, struct tm const *b) +{ + /* Compute intervening leap days correctly even if year is negative. + Take care to avoid int overflow in leap day calculations, + but it's OK to assume that A and B are close to each other. */ + int a4 = (a->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (a->tm_year & 3); + int b4 = (b->tm_year >> 2) + (TM_YEAR_BASE >> 2) - ! (b->tm_year & 3); + int a100 = a4 / 25 - (a4 % 25 < 0); + int b100 = b4 / 25 - (b4 % 25 < 0); + int a400 = a100 >> 2; + int b400 = b100 >> 2; + int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400); + int years = a->tm_year - b->tm_year; + int days = (365 * years + intervening_leap_days + + (a->tm_yday - b->tm_yday)); + return (60 * (60 * (24 * days + (a->tm_hour - b->tm_hour)) + + (a->tm_min - b->tm_min)) + + (a->tm_sec - b->tm_sec)); +} +#endif /* ! HAVE_TM_GMTOFF */ + +static table const * +lookup_word (parser_control const *pc, char *word) +{ + char *p; + char *q; + size_t wordlen; + table const *tp; + int i; + int abbrev; + + /* Make it uppercase. */ + for (p = word; *p; p++) + if (ISLOWER ((unsigned char) *p)) + *p = toupper ((unsigned char) *p); + + for (tp = meridian_table; tp->name; tp++) + if (strcmp (word, tp->name) == 0) + return tp; + + /* See if we have an abbreviation for a month. */ + wordlen = strlen (word); + abbrev = wordlen == 3 || (wordlen == 4 && word[3] == '.'); + + for (tp = month_and_day_table; tp->name; tp++) + if ((abbrev ? strncmp (word, tp->name, 3) : strcmp (word, tp->name)) == 0) + return tp; + + if ((tp = lookup_zone (pc, word))) + return tp; + + if (strcmp (word, dst_table[0].name) == 0) + return dst_table; + + for (tp = time_units_table; tp->name; tp++) + if (strcmp (word, tp->name) == 0) + return tp; + + /* Strip off any plural and try the units table again. */ + if (word[wordlen - 1] == 'S') + { + word[wordlen - 1] = '\0'; + for (tp = time_units_table; tp->name; tp++) + if (strcmp (word, tp->name) == 0) + return tp; + word[wordlen - 1] = 'S'; /* For "this" in relative_time_table. */ + } + + for (tp = relative_time_table; tp->name; tp++) + if (strcmp (word, tp->name) == 0) + return tp; + + /* Military time zones. */ + if (wordlen == 1) + for (tp = military_table; tp->name; tp++) + if (word[0] == tp->name[0]) + return tp; + + /* Drop out any periods and try the time zone table again. */ + for (i = 0, p = q = word; (*p = *q); q++) + if (*q == '.') + i = 1; + else + p++; + if (i && (tp = lookup_zone (pc, word))) + return tp; + + return 0; +} + +static int +yylex (YYSTYPE *lvalp, parser_control *pc) +{ + unsigned char c; + int count; + + for (;;) + { + while (c = *pc->input, ISSPACE (c)) + pc->input++; + + if (ISDIGIT (c) || c == '-' || c == '+') + { + char const *p; + int sign; + int value; + if (c == '-' || c == '+') + { + sign = c == '-' ? -1 : 1; + c = *++pc->input; + if (! ISDIGIT (c)) + /* skip the '-' sign */ + continue; + } + else + sign = 0; + p = pc->input; + value = 0; + do + { + value = 10 * value + c - '0'; + c = *++p; + } + while (ISDIGIT (c)); + lvalp->textintval.value = sign < 0 ? -value : value; + lvalp->textintval.digits = p - pc->input; + pc->input = p; + return sign ? tSNUMBER : tUNUMBER; + } + + if (ISALPHA (c)) + { + char buff[20]; + char *p = buff; + table const *tp; + + do + { + if (p < buff + sizeof buff - 1) + *p++ = c; + c = *++pc->input; + } + while (ISALPHA (c) || c == '.'); + + *p = '\0'; + tp = lookup_word (pc, buff); + if (! tp) + return '?'; + lvalp->intval = tp->value; + return tp->type; + } + + if (c != '(') + return *pc->input++; + count = 0; + do + { + c = *pc->input++; + if (c == '\0') + return c; + if (c == '(') + count++; + else if (c == ')') + count--; + } + while (count > 0); + } +} + +/* Do nothing if the parser reports an error. */ +static int +yyerror (char *s ATTRIBUTE_UNUSED) +{ + return 0; +} + +/* Parse a date/time string P. Return the corresponding time_t value, + or (time_t) -1 if there is an error. P can be an incomplete or + relative time specification; if so, use *NOW as the basis for the + returned time. */ +time_t +get_date (const char *p, const time_t *now) +{ + time_t Start = now ? *now : time (0); + struct tm *tmp = localtime (&Start); + struct tm tm; + struct tm tm0; + parser_control pc; + + if (! tmp) + return -1; + + pc.input = p; + pc.year.value = tmp->tm_year + TM_YEAR_BASE; + pc.year.digits = 4; + pc.month = tmp->tm_mon + 1; + pc.day = tmp->tm_mday; + pc.hour = tmp->tm_hour; + pc.minutes = tmp->tm_min; + pc.seconds = tmp->tm_sec; + tm.tm_isdst = tmp->tm_isdst; + + pc.meridian = MER24; + pc.rel_seconds = 0; + pc.rel_minutes = 0; + pc.rel_hour = 0; + pc.rel_day = 0; + pc.rel_month = 0; + pc.rel_year = 0; + pc.dates_seen = 0; + pc.days_seen = 0; + pc.rels_seen = 0; + pc.times_seen = 0; + pc.local_zones_seen = 0; + pc.zones_seen = 0; + +#if HAVE_STRUCT_TM_TM_ZONE + pc.local_time_zone_table[0].name = tmp->tm_zone; + pc.local_time_zone_table[0].type = tLOCAL_ZONE; + pc.local_time_zone_table[0].value = tmp->tm_isdst; + pc.local_time_zone_table[1].name = 0; + + /* Probe the names used in the next three calendar quarters, looking + for a tm_isdst different from the one we already have. */ + { + int quarter; + for (quarter = 1; quarter <= 3; quarter++) + { + time_t probe = Start + quarter * (90 * 24 * 60 * 60); + struct tm *probe_tm = localtime (&probe); + if (probe_tm && probe_tm->tm_zone + && probe_tm->tm_isdst != pc.local_time_zone_table[0].value) + { + { + pc.local_time_zone_table[1].name = probe_tm->tm_zone; + pc.local_time_zone_table[1].type = tLOCAL_ZONE; + pc.local_time_zone_table[1].value = probe_tm->tm_isdst; + pc.local_time_zone_table[2].name = 0; + } + break; + } + } + } +#else +#if HAVE_TZNAME + { +# ifndef tzname + extern char *tzname[]; +# endif + int i; + for (i = 0; i < 2; i++) + { + pc.local_time_zone_table[i].name = tzname[i]; + pc.local_time_zone_table[i].type = tLOCAL_ZONE; + pc.local_time_zone_table[i].value = i; + } + pc.local_time_zone_table[i].name = 0; + } +#else + pc.local_time_zone_table[0].name = 0; +#endif +#endif + + if (pc.local_time_zone_table[0].name && pc.local_time_zone_table[1].name + && ! strcmp (pc.local_time_zone_table[0].name, + pc.local_time_zone_table[1].name)) + { + /* This locale uses the same abbrevation for standard and + daylight times. So if we see that abbreviation, we don't + know whether it's daylight time. */ + pc.local_time_zone_table[0].value = -1; + pc.local_time_zone_table[1].name = 0; + } + + if (yyparse (&pc) != 0 + || 1 < pc.times_seen || 1 < pc.dates_seen || 1 < pc.days_seen + || 1 < (pc.local_zones_seen + pc.zones_seen) + || (pc.local_zones_seen && 1 < pc.local_isdst)) + return -1; + + tm.tm_year = to_year (pc.year) - TM_YEAR_BASE + pc.rel_year; + tm.tm_mon = pc.month - 1 + pc.rel_month; + tm.tm_mday = pc.day + pc.rel_day; + if (pc.times_seen || (pc.rels_seen && ! pc.dates_seen && ! pc.days_seen)) + { + tm.tm_hour = to_hour (pc.hour, pc.meridian); + if (tm.tm_hour < 0) + return -1; + tm.tm_min = pc.minutes; + tm.tm_sec = pc.seconds; + } + else + { + tm.tm_hour = tm.tm_min = tm.tm_sec = 0; + } + + /* Let mktime deduce tm_isdst if we have an absolute time stamp, + or if the relative time stamp mentions days, months, or years. */ + if (pc.dates_seen | pc.days_seen | pc.times_seen | pc.rel_day + | pc.rel_month | pc.rel_year) + tm.tm_isdst = -1; + + /* But if the input explicitly specifies local time with or without + DST, give mktime that information. */ + if (pc.local_zones_seen) + tm.tm_isdst = pc.local_isdst; + + tm0 = tm; + + Start = mktime (&tm); + + if (Start == (time_t) -1) + { + + /* Guard against falsely reporting errors near the time_t boundaries + when parsing times in other time zones. For example, if the min + time_t value is 1970-01-01 00:00:00 UTC and we are 8 hours ahead + of UTC, then the min localtime value is 1970-01-01 08:00:00; if + we apply mktime to 1970-01-01 00:00:00 we will get an error, so + we apply mktime to 1970-01-02 08:00:00 instead and adjust the time + zone by 24 hours to compensate. This algorithm assumes that + there is no DST transition within a day of the time_t boundaries. */ + if (pc.zones_seen) + { + tm = tm0; + if (tm.tm_year <= EPOCH_YEAR - TM_YEAR_BASE) + { + tm.tm_mday++; + pc.time_zone += 24 * 60; + } + else + { + tm.tm_mday--; + pc.time_zone -= 24 * 60; + } + Start = mktime (&tm); + } + + if (Start == (time_t) -1) + return Start; + } + + if (pc.days_seen && ! pc.dates_seen) + { + tm.tm_mday += ((pc.day_number - tm.tm_wday + 7) % 7 + + 7 * (pc.day_ordinal - (0 < pc.day_ordinal))); + tm.tm_isdst = -1; + Start = mktime (&tm); + if (Start == (time_t) -1) + return Start; + } + + if (pc.zones_seen) + { + int delta = pc.time_zone * 60; +#ifdef HAVE_TM_GMTOFF + delta -= tm.tm_gmtoff; +#else + struct tm *gmt = gmtime (&Start); + if (! gmt) + return -1; + delta -= tm_diff (&tm, gmt); +#endif + if ((Start < Start - delta) != (delta < 0)) + return -1; /* time_t overflow */ + Start -= delta; + } + + /* Add relative hours, minutes, and seconds. Ignore leap seconds; + i.e. "+ 10 minutes" means 600 seconds, even if one of them is a + leap second. Typically this is not what the user wants, but it's + too hard to do it the other way, because the time zone indicator + must be applied before relative times, and if mktime is applied + again the time zone will be lost. */ + { + time_t t0 = Start; + long d1 = 60 * 60 * (long) pc.rel_hour; + time_t t1 = t0 + d1; + long d2 = 60 * (long) pc.rel_minutes; + time_t t2 = t1 + d2; + int d3 = pc.rel_seconds; + time_t t3 = t2 + d3; + if ((d1 / (60 * 60) ^ pc.rel_hour) + | (d2 / 60 ^ pc.rel_minutes) + | ((t0 + d1 < t0) ^ (d1 < 0)) + | ((t1 + d2 < t1) ^ (d2 < 0)) + | ((t2 + d3 < t2) ^ (d3 < 0))) + return -1; + Start = t3; + } + + return Start; +} + +#if TEST + +#include + +int +main (int ac, char **av) +{ + char buff[BUFSIZ]; + time_t d; + + printf ("Enter date, or blank line to exit.\n\t> "); + fflush (stdout); + + buff[BUFSIZ - 1] = 0; + while (fgets (buff, BUFSIZ - 1, stdin) && buff[0]) + { + d = get_date (buff, 0); + if (d == (time_t) -1) + printf ("Bad format - couldn't convert.\n"); + else + printf ("%s", ctime (&d)); + printf ("\t> "); + fflush (stdout); + } + return 0; +} +#endif /* defined TEST */ diff --git a/source3/modules/vfs_cap.c b/source3/modules/vfs_cap.c new file mode 100644 index 0000000000..0526276acb --- /dev/null +++ b/source3/modules/vfs_cap.c @@ -0,0 +1,448 @@ +/* + * CAP VFS module for Samba 3.x Version 0.3 + * + * Copyright (C) Tim Potter, 1999-2000 + * Copyright (C) Alexander Bokovoy, 2002-2003 + * Copyright (C) Stefan (metze) Metzmacher, 2003 + * Copyright (C) TAKAHASHI Motonobu (monyo), 2003 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +#include "includes.h" + +/* cap functions */ +static char *capencode(char *to, const char *from); +static char *capdecode(char *to, const char *from); + +static SMB_BIG_UINT cap_disk_free(vfs_handle_struct *handle, connection_struct *conn, const char *path, + BOOL small_query, SMB_BIG_UINT *bsize, + SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize) +{ + pstring cappath; + capencode(cappath, path); + return SMB_VFS_NEXT_DISK_FREE(handle, conn, cappath, small_query, bsize, + dfree, dsize); +} + +static DIR *cap_opendir(vfs_handle_struct *handle, connection_struct *conn, const char *fname) +{ + pstring capname; + capencode(capname, fname); + return SMB_VFS_NEXT_OPENDIR(handle, conn, capname); +} + +static struct dirent *cap_readdir(vfs_handle_struct *handle, connection_struct *conn, DIR *dirp) +{ + struct dirent *result; + DEBUG(3,("cap: cap_readdir\n")); + result = SMB_VFS_NEXT_READDIR(handle, conn, dirp); + if (result) { + DEBUG(3,("cap: cap_readdir: %s\n", result->d_name)); + capdecode(result->d_name, result->d_name); + } + return result; +} + +static int cap_mkdir(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode) +{ + pstring cappath; + capencode(cappath, path); + return SMB_VFS_NEXT_MKDIR(handle, conn, cappath, mode); +} + +static int cap_rmdir(vfs_handle_struct *handle, connection_struct *conn, const char *path) +{ + pstring cappath; + capencode(cappath, path); + return SMB_VFS_NEXT_RMDIR(handle, conn, cappath); +} + +static int cap_open(vfs_handle_struct *handle, connection_struct *conn, const char *fname, int flags, mode_t mode) +{ + pstring capname; + DEBUG(3,("cap: cap_open for %s\n", fname)); + capencode(capname, fname); + return SMB_VFS_NEXT_OPEN(handle, conn, capname, flags, mode); +} + +static int cap_rename(vfs_handle_struct *handle, connection_struct *conn, const char *old, const char *new) +{ + pstring capold, capnew; + capencode(capold, old); + capencode(capnew, new); + + return SMB_VFS_NEXT_RENAME(handle, conn, capold, capnew); +} + +static int cap_stat(vfs_handle_struct *handle, connection_struct *conn, const char *fname, SMB_STRUCT_STAT *sbuf) +{ + pstring capname; + capencode(capname, fname); + return SMB_VFS_NEXT_STAT(handle, conn, capname, sbuf); +} + +static int cap_lstat(vfs_handle_struct *handle, connection_struct *conn, const char *path, SMB_STRUCT_STAT *sbuf) +{ + pstring cappath; + capencode(cappath, path); + return SMB_VFS_NEXT_LSTAT(handle, conn, cappath, sbuf); +} + +static int cap_unlink(vfs_handle_struct *handle, connection_struct *conn, const char *path) +{ + pstring cappath; + capencode(cappath, path); + return SMB_VFS_NEXT_UNLINK(handle, conn, cappath); +} + +static int cap_chmod(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode) +{ + pstring cappath; + capencode(cappath, path); + return SMB_VFS_NEXT_CHMOD(handle, conn, cappath, mode); +} + +static int cap_chown(vfs_handle_struct *handle, connection_struct *conn, const char *path, uid_t uid, gid_t gid) +{ + pstring cappath; + capencode(cappath, path); + return SMB_VFS_NEXT_CHOWN(handle, conn, cappath, uid, gid); +} + +static int cap_chdir(vfs_handle_struct *handle, connection_struct *conn, const char *path) +{ + pstring cappath; + DEBUG(3,("cap: cap_chdir for %s\n", path)); + capencode(cappath, path); + return SMB_VFS_NEXT_CHDIR(handle, conn, cappath); +} + +static int cap_utime(vfs_handle_struct *handle, connection_struct *conn, const char *path, struct utimbuf *times) +{ + pstring cappath; + capencode(cappath, path); + return SMB_VFS_NEXT_UTIME(handle, conn, cappath, times); +} + + +static BOOL cap_symlink(vfs_handle_struct *handle, connection_struct *conn, const char *oldpath, const char *newpath) +{ + pstring capoldpath, capnewpath; + capencode(capoldpath, oldpath); + capencode(capnewpath, newpath); + return SMB_VFS_NEXT_SYMLINK(handle, conn, capoldpath, capnewpath); +} + +static BOOL cap_readlink(vfs_handle_struct *handle, connection_struct *conn, const char *path, char *buf, size_t bufsiz) +{ + pstring cappath; + capencode(cappath, path); + return SMB_VFS_NEXT_READLINK(handle, conn, cappath, buf, bufsiz); +} + +static int cap_link(vfs_handle_struct *handle, connection_struct *conn, const char *oldpath, const char *newpath) +{ + pstring capoldpath, capnewpath; + capencode(capoldpath, oldpath); + capencode(capnewpath, newpath); + return SMB_VFS_NEXT_LINK(handle, conn, capoldpath, capnewpath); +} + +static int cap_mknod(vfs_handle_struct *handle, connection_struct *conn, const char *path, mode_t mode, SMB_DEV_T dev) +{ + pstring cappath; + capencode(cappath, path); + return SMB_VFS_NEXT_MKNOD(handle, conn, cappath, mode, dev); +} + +static char *cap_realpath(vfs_handle_struct *handle, connection_struct *conn, const char *path, char *resolved_path) +{ + /* monyo need capencode'ed and capdecode'ed? */ + pstring cappath; + capencode(cappath, path); + return SMB_VFS_NEXT_REALPATH(handle, conn, path, resolved_path); +} + +static BOOL cap_set_nt_acl(vfs_handle_struct *handle, files_struct *fsp, const char *name, uint32 security_info_sent, struct security_descriptor_info *psd) +{ + pstring capname; + capencode(capname, name); + return SMB_VFS_NEXT_SET_NT_ACL(handle, fsp, capname, security_info_sent, psd); +} + +static int cap_chmod_acl(vfs_handle_struct *handle, connection_struct *conn, const char *name, mode_t mode) +{ + pstring capname; + capencode(capname, name); + + /* If the underlying VFS doesn't have ACL support... */ + if (!handle->vfs_next.ops.chmod_acl) { + errno = ENOSYS; + return -1; + } + return SMB_VFS_NEXT_CHMOD_ACL(handle, conn, capname, mode); +} + +static SMB_ACL_T cap_sys_acl_get_file(vfs_handle_struct *handle, connection_struct *conn, const char *path_p, SMB_ACL_TYPE_T type) +{ + pstring cappath_p; + capencode(cappath_p, path_p); + return SMB_VFS_NEXT_SYS_ACL_GET_FILE(handle, conn, cappath_p, type); +} + +static int cap_sys_acl_set_file(vfs_handle_struct *handle, connection_struct *conn, const char *name, SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl) +{ + pstring capname; + capencode(capname, name); + return SMB_VFS_NEXT_SYS_ACL_SET_FILE(handle, conn, capname, acltype, theacl); +} + +static int cap_sys_acl_delete_def_file(vfs_handle_struct *handle, connection_struct *conn, const char *path) +{ + pstring cappath; + capencode(cappath, path); + return SMB_VFS_NEXT_SYS_ACL_DELETE_DEF_FILE(handle, conn, cappath); +} + +static ssize_t cap_getxattr(vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name, void *value, size_t size) +{ + pstring cappath, capname; + capencode(cappath, path); + capencode(capname, name); + return SMB_VFS_NEXT_GETXATTR(handle, conn, cappath, capname, value, size); +} + +static ssize_t cap_lgetxattr(vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name, void *value, size_t +size) +{ + pstring cappath, capname; + capencode(cappath, path); + capencode(capname, name); + return SMB_VFS_NEXT_LGETXATTR(handle, conn, cappath, capname, value, size); +} + +static ssize_t cap_fgetxattr(vfs_handle_struct *handle, struct files_struct *fsp,int fd, const char *name, void *value, size_t size) +{ + pstring capname; + capencode(capname, name); + return SMB_VFS_NEXT_FGETXATTR(handle, fsp, fd, capname, value, size); +} + +static ssize_t cap_listxattr(vfs_handle_struct *handle, struct connection_struct *conn,const char *path, char *list, size_t size) +{ + pstring cappath; + capencode(cappath, path); + return SMB_VFS_NEXT_LISTXATTR(handle, conn, cappath, list, size); +} + +static ssize_t cap_llistxattr(vfs_handle_struct *handle, struct connection_struct *conn,const char *path, char *list, size_t size) +{ + pstring cappath; + capencode(cappath, path); + return SMB_VFS_NEXT_LLISTXATTR(handle, conn, cappath, list, size); +} + +static int cap_removexattr(vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name) +{ + pstring cappath, capname; + capencode(cappath, path); + capencode(capname, name); + return SMB_VFS_NEXT_REMOVEXATTR(handle, conn, cappath, capname); +} + +static int cap_lremovexattr(vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name) +{ + pstring cappath, capname; + capencode(cappath, path); + capencode(capname, name); + return SMB_VFS_NEXT_LREMOVEXATTR(handle, conn, cappath, capname); +} + +static int cap_fremovexattr(vfs_handle_struct *handle, struct files_struct *fsp,int fd, const char *name) +{ + pstring capname; + capencode(capname, name); + return SMB_VFS_NEXT_FREMOVEXATTR(handle, fsp, fd, capname); +} + +static int cap_setxattr(vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name, const void *value, size_t size, int flags) +{ + pstring cappath, capname; + capencode(cappath, path); + capencode(capname, name); + return SMB_VFS_NEXT_SETXATTR(handle, conn, cappath, capname, value, size, flags); +} + +static int cap_lsetxattr(vfs_handle_struct *handle, struct connection_struct *conn,const char *path, const char *name, const void *value, size_t size, int flags) +{ + pstring cappath, capname; + capencode(cappath, path); + capencode(capname, name); + return SMB_VFS_NEXT_LSETXATTR(handle, conn, cappath, capname, value, size, flags); +} + +static int cap_fsetxattr(vfs_handle_struct *handle, struct files_struct *fsp,int fd, const char *name, const void *value, size_t size, int flags) +{ + pstring capname; + capencode(capname, name); + return SMB_VFS_NEXT_FSETXATTR(handle, fsp, fd, capname, value, size, flags); +} + +/* VFS operations structure */ + +static vfs_op_tuple cap_op_tuples[] = { + + /* Disk operations */ + + {SMB_VFS_OP(cap_disk_free), SMB_VFS_OP_DISK_FREE, SMB_VFS_LAYER_TRANSPARENT}, + + /* Directory operations */ + + {SMB_VFS_OP(cap_opendir), SMB_VFS_OP_OPENDIR, SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(cap_readdir), SMB_VFS_OP_READDIR, SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(cap_mkdir), SMB_VFS_OP_MKDIR, SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(cap_rmdir), SMB_VFS_OP_RMDIR, SMB_VFS_LAYER_TRANSPARENT}, + + /* File operations */ + + {SMB_VFS_OP(cap_open), SMB_VFS_OP_OPEN, SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(cap_rename), SMB_VFS_OP_RENAME, SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(cap_stat), SMB_VFS_OP_STAT, SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(cap_lstat), SMB_VFS_OP_LSTAT, SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(cap_unlink), SMB_VFS_OP_UNLINK, SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(cap_chmod), SMB_VFS_OP_CHMOD, SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(cap_chown), SMB_VFS_OP_CHOWN, SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(cap_chdir), SMB_VFS_OP_CHDIR, SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(cap_utime), SMB_VFS_OP_UTIME, SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(cap_symlink), SMB_VFS_OP_SYMLINK, SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(cap_readlink), SMB_VFS_OP_READLINK, SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(cap_link), SMB_VFS_OP_LINK, SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(cap_mknod), SMB_VFS_OP_MKNOD, SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(cap_realpath), SMB_VFS_OP_REALPATH, SMB_VFS_LAYER_TRANSPARENT}, + + /* NT File ACL operations */ + + {SMB_VFS_OP(cap_set_nt_acl), SMB_VFS_OP_SET_NT_ACL, SMB_VFS_LAYER_TRANSPARENT}, + + /* POSIX ACL operations */ + + {SMB_VFS_OP(cap_chmod_acl), SMB_VFS_OP_CHMOD_ACL, SMB_VFS_LAYER_TRANSPARENT}, + + {SMB_VFS_OP(cap_sys_acl_get_file), SMB_VFS_OP_SYS_ACL_GET_FILE, SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(cap_sys_acl_set_file), SMB_VFS_OP_SYS_ACL_SET_FILE, SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(cap_sys_acl_delete_def_file), SMB_VFS_OP_SYS_ACL_DELETE_DEF_FILE, SMB_VFS_LAYER_TRANSPARENT}, + + /* EA operations. */ + {SMB_VFS_OP(cap_getxattr), SMB_VFS_OP_GETXATTR, SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(cap_lgetxattr), SMB_VFS_OP_LGETXATTR, SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(cap_fgetxattr), SMB_VFS_OP_FGETXATTR, SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(cap_listxattr), SMB_VFS_OP_LISTXATTR, SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(cap_llistxattr), SMB_VFS_OP_LLISTXATTR, SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(cap_removexattr), SMB_VFS_OP_REMOVEXATTR, SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(cap_lremovexattr), SMB_VFS_OP_LREMOVEXATTR, SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(cap_fremovexattr), SMB_VFS_OP_FREMOVEXATTR, SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(cap_setxattr), SMB_VFS_OP_SETXATTR, SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(cap_lsetxattr), SMB_VFS_OP_LSETXATTR, SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(cap_fsetxattr), SMB_VFS_OP_FSETXATTR, SMB_VFS_LAYER_TRANSPARENT}, + + {NULL, SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP} +}; + +NTSTATUS vfs_cap_init(void) +{ + return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "cap", cap_op_tuples); +} + +/* For CAP functions */ +#define hex_tag ':' +#define hex2bin(c) hex2bin_table[(unsigned char)(c)] +#define bin2hex(c) bin2hex_table[(unsigned char)(c)] +#define is_hex(s) ((s)[0] == hex_tag) + +static unsigned char hex2bin_table[256] = { +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00 */ +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10 */ +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20 */ +0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, /* 0x30 */ +0000, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0000, /* 0x40 */ +0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x50 */ +0000, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0000, /* 0x60 */ +0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70 */ +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80 */ +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90 */ +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xa0 */ +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xb0 */ +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xc0 */ +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xd0 */ +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xe0 */ +0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 0xf0 */ +}; +static unsigned char bin2hex_table[256] = "0123456789abcdef"; + +/******************************************************************* + original code -> ":xx" - CAP format +********************************************************************/ +static char *capencode(char *to, const char *from) +{ + pstring cvtbuf; + char *out; + + if (to == from) { + from = pstrcpy ((char *) cvtbuf, from); + } + + for (out = to; *from && (out - to < sizeof(pstring)-7);) { + /* buffer husoku error */ + if ((unsigned char)*from >= 0x80) { + *out++ = hex_tag; + *out++ = bin2hex (((*from)>>4)&0x0f); + *out++ = bin2hex ((*from)&0x0f); + from++; + } + else { + *out++ = *from++; + } + } + *out = '\0'; + return to; +} + +/******************************************************************* + CAP -> original code +********************************************************************/ +/* ":xx" -> a byte */ +static char *capdecode(char *to, const char *from) +{ + pstring cvtbuf; + char *out; + + if (to == from) { + from = pstrcpy ((char *) cvtbuf, from); + } + for (out = to; *from && (out - to < sizeof(pstring)-3);) { + if (is_hex(from)) { + *out++ = (hex2bin (from[1])<<4) | (hex2bin (from[2])); + from += 3; + } else { + *out++ = *from++; + } + } + *out = '\0'; + return to; +} diff --git a/source3/modules/vfs_default_quota.c b/source3/modules/vfs_default_quota.c new file mode 100644 index 0000000000..1294a51533 --- /dev/null +++ b/source3/modules/vfs_default_quota.c @@ -0,0 +1,180 @@ +/* + * Store default Quotas in a specified quota record + * + * Copyright (C) Stefan (metze) Metzmacher 2003 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "includes.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_VFS + +#define DEFAULT_QUOTA_NAME "default_quota" + +#define DEFAULT_QUOTA_UID_DEFAULT 0 +#define DEFAULT_QUOTA_UID_NOLIMIT_DEFAULT True +#define DEFAULT_QUOTA_GID_DEFAULT 0 +#define DEFAULT_QUOTA_GID_NOLIMIT_DEFAULT True + +#define DEFAULT_QUOTA_UID(handle) \ + (uid_t)lp_parm_int(SNUM((handle)->conn),DEFAULT_QUOTA_NAME,"uid",DEFAULT_QUOTA_UID_DEFAULT) + +#define DEFAULT_QUOTA_UID_NOLIMIT(handle) \ + lp_parm_bool(SNUM((handle)->conn),DEFAULT_QUOTA_NAME,"uid nolimit",DEFAULT_QUOTA_UID_NOLIMIT_DEFAULT) + +#define DEFAULT_QUOTA_GID(handle) \ + (gid_t)lp_parm_int(SNUM((handle)->conn),DEFAULT_QUOTA_NAME,"gid",DEFAULT_QUOTA_GID_DEFAULT) + +#define DEFAULT_QUOTA_GID_NOLIMIT(handle) \ + lp_parm_bool(SNUM((handle)->conn),DEFAULT_QUOTA_NAME,"gid nolimit",DEFAULT_QUOTA_GID_NOLIMIT_DEFAULT) + +static int default_quota_get_quota(vfs_handle_struct *handle, connection_struct *conn, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dq) +{ + int ret = -1; + + if ((ret=SMB_VFS_NEXT_GET_QUOTA(handle, conn, qtype, id, dq))!=0) { + return ret; + } + + switch (qtype) { + case SMB_USER_QUOTA_TYPE: + /* we use id.uid == 0 for default quotas */ + if ((id.uid==DEFAULT_QUOTA_UID(handle)) && + DEFAULT_QUOTA_UID_NOLIMIT(handle)) { + SMB_QUOTAS_SET_NO_LIMIT(dq); + } + break; +#ifdef HAVE_GROUP_QUOTA + case SMB_GROUP_QUOTA_TYPE: + /* we use id.gid == 0 for default quotas */ + if ((id.gid==DEFAULT_QUOTA_GID(handle)) && + DEFAULT_QUOTA_GID_NOLIMIT(handle)) { + SMB_QUOTAS_SET_NO_LIMIT(dq); + } + break; +#endif /* HAVE_GROUP_QUOTA */ + case SMB_USER_FS_QUOTA_TYPE: + { + unid_t qid; + uint32 qflags = dq->qflags; + qid.uid = DEFAULT_QUOTA_UID(handle); + SMB_VFS_NEXT_GET_QUOTA(handle, conn, SMB_USER_QUOTA_TYPE, qid, dq); + dq->qflags = qflags; + } + break; +#ifdef HAVE_GROUP_QUOTA + case SMB_GROUP_FS_QUOTA_TYPE: + { + unid_t qid; + uint32 qflags = dq->qflags; + qid.gid = DEFAULT_QUOTA_GID(handle); + SMB_VFS_NEXT_GET_QUOTA(handle, conn, SMB_GROUP_QUOTA_TYPE, qid, dq); + dq->qflags = qflags; + } + break; +#endif /* HAVE_GROUP_QUOTA */ + default: + errno = ENOSYS; + return -1; + break; + } + + return ret; +} + +static int default_quota_set_quota(vfs_handle_struct *handle, connection_struct *conn, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dq) +{ + int ret = -1; + + switch (qtype) { + case SMB_USER_QUOTA_TYPE: + /* we use id.uid == 0 for default quotas */ + if ((id.uid==DEFAULT_QUOTA_UID(handle)) && + DEFAULT_QUOTA_UID_NOLIMIT(handle)) { + return -1; + } + break; +#ifdef HAVE_GROUP_QUOTA + case SMB_GROUP_QUOTA_TYPE: + /* we use id.gid == 0 for default quotas */ + if ((id.gid==DEFAULT_QUOTA_GID(handle)) && + DEFAULT_QUOTA_GID_NOLIMIT(handle)) { + return -1; + } + break; +#endif /* HAVE_GROUP_QUOTA */ + case SMB_USER_FS_QUOTA_TYPE: + break; +#ifdef HAVE_GROUP_QUOTA + case SMB_GROUP_FS_QUOTA_TYPE: + break; +#endif /* HAVE_GROUP_QUOTA */ + default: + errno = ENOSYS; + return -1; + break; + } + + if ((ret=SMB_VFS_NEXT_SET_QUOTA(handle, conn, qtype, id, dq))!=0) { + return ret; + } + + switch (qtype) { + case SMB_USER_QUOTA_TYPE: + break; +#ifdef HAVE_GROUP_QUOTA + case SMB_GROUP_QUOTA_TYPE: + break; +#endif /* HAVE_GROUP_QUOTA */ + case SMB_USER_FS_QUOTA_TYPE: + { + unid_t qid; + qid.uid = DEFAULT_QUOTA_UID(handle); + ret = SMB_VFS_NEXT_SET_QUOTA(handle, conn, SMB_USER_QUOTA_TYPE, qid, dq); + } + break; +#ifdef HAVE_GROUP_QUOTA + case SMB_GROUP_FS_QUOTA_TYPE: + { + unid_t qid; + qid.gid = DEFAULT_QUOTA_GID(handle); + ret = SMB_VFS_NEXT_SET_QUOTA(handle, conn, SMB_GROUP_QUOTA_TYPE, qid, dq); + } + break; +#endif /* HAVE_GROUP_QUOTA */ + default: + errno = ENOSYS; + return -1; + break; + } + + return ret; +} + +/* VFS operations structure */ + +static vfs_op_tuple default_quota_ops[] = { + {SMB_VFS_OP(default_quota_get_quota), SMB_VFS_OP_GET_QUOTA, SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(default_quota_set_quota), SMB_VFS_OP_SET_QUOTA, SMB_VFS_LAYER_TRANSPARENT}, + + {SMB_VFS_OP(NULL), SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP} +}; + +NTSTATUS vfs_default_quota_init(void) +{ + return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, DEFAULT_QUOTA_NAME, default_quota_ops); +} diff --git a/source3/modules/vfs_readonly.c b/source3/modules/vfs_readonly.c new file mode 100644 index 0000000000..ee9e40c2fc --- /dev/null +++ b/source3/modules/vfs_readonly.c @@ -0,0 +1,98 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + VFS module to perform read-only limitation based on a time period + Copyright (C) Alexander Bokovoy 2003 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + This work was sponsored by Optifacio Software Services, Inc. +*/ + +#include "includes.h" +#include "getdate.h" + +/* + This module performs a read-only limitation for specified share + (or all of them if it is loaded in a [global] section) based on period + definition in smb.conf. You can stack this module multiple times under + different names to get multiple limit intervals. + + The module uses get_date() function from coreutils' date utility to parse + specified dates according to date(1) rules. Look into info page for date(1) + to understand the syntax. + + The module accepts one parameter: + + readonly: period = "begin date","end date" + + where "begin date" and "end date" are mandatory and should comply with date(1) + syntax for date strings. + + Example: + + readonly: period = "today 14:00","today 15:00" + + Default: + + readonly: period = "today 0:0:0","tomorrow 0:0:0" + + The default covers whole day thus making the share readonly + + */ + +#define MODULE_NAME "readonly" +static int readonly_connect(vfs_handle_struct *handle, + connection_struct *conn, + const char *service, + const char *user) +{ + const char *period_def[] = {"today 0:0:0", "tomorrow 0:0:0"}; + + const char **period = lp_parm_string_list(SNUM(handle->conn), + (handle->param ? handle->param : MODULE_NAME), + "period", period_def); + + if (period && period[0] && period[1]) { + time_t current_time = time(NULL); + time_t begin_period = get_date(period[0], ¤t_time); + time_t end_period = get_date(period[1], ¤t_time); + + if ((current_time >= begin_period) && (current_time <= end_period)) { + conn->read_only = True; + } + + return SMB_VFS_NEXT_CONNECT(handle, conn, service, user); + + } else { + + return 1; + + } +} + + +/* VFS operations structure */ + +static vfs_op_tuple readonly_op_tuples[] = { + /* Disk operations */ + {SMB_VFS_OP(readonly_connect), SMB_VFS_OP_CONNECT, SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(NULL), SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP} +}; + +NTSTATUS vfs_readonly_init(void) +{ + return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, MODULE_NAME, readonly_op_tuples); +} diff --git a/source3/modules/vfs_recycle.c b/source3/modules/vfs_recycle.c index e725daedba..b1b2ac0353 100644 --- a/source3/modules/vfs_recycle.c +++ b/source3/modules/vfs_recycle.c @@ -336,7 +336,7 @@ static int recycle_unlink(vfs_handle_struct *handle, connection_struct *conn, co repository = alloc_sub_conn(conn, recycle_repository(handle)); ALLOC_CHECK(repository, done); /* shouldn't we allow absolute path names here? --metze */ - trim_string(repository, "/", "/"); + trim_char(repository, '/', '/'); if(!repository || *(repository) == '\0') { DEBUG(3, ("recycle: repository path not set, purging %s...\n", file_name)); @@ -455,7 +455,8 @@ static int recycle_unlink(vfs_handle_struct *handle, connection_struct *conn, co /* rename file we move to recycle bin */ i = 1; while (recycle_file_exist(handle, final_name)) { - snprintf(final_name, PATH_MAX -1, "%s/Copy #%d of %s", temp_name, i++, base); + SAFE_FREE(final_name); + asprintf(&final_name, "%s/Copy #%d of %s", temp_name, i++, base); } DEBUG(10, ("recycle: Moving %s to %s\n", file_name, final_name)); diff --git a/source3/msdfs/README b/source3/msdfs/README deleted file mode 100644 index 0e924b31dc..0000000000 --- a/source3/msdfs/README +++ /dev/null @@ -1,32 +0,0 @@ -Setting up MS Dfs in Samba -kalele@veritas.com March 2000 - -Currently, MS Dfs support is a configure time parameter (--with-msdfs). Can be changed later to always compile it in.. - -To have a server announce itself as a Dfs server, add a "host msdfs=yes" entry to smb.conf. - -To make a share a Dfs root, add a "msdfs root=yes" entry to the share definition -in the smb.conf file. -e.g. -[pub] - path = /export/publicsmb - msdfs root = yes - -To create dfs volumes/junctions in the share, create symbolic links of the -format msdfs:server1\share1,server2\share2 and so on. - -In the above example, create a dfs volume "dfsstorage" in the [pub] share as: -cd /export/publicsmb -ln -s msdfs:serverA\\share dfsstorage - -Clicking on dfsstorage from a dfs-aware client will show you the contents of -\\serverA\share - -Shares with "msdfs root = no" (which is the default) entries are served as normal -shares and the client stops talking Dfs with Samba after a tconX. - -NOTES: -* Windows clients need to be rebooted if a non-dfs root is made a dfs root or - vice versa. A better option is to introduce a new share and make it the dfs root. -* Currently there's a restriction that msdfs symlink names should be all - lowercase. diff --git a/source3/msdfs/msdfs.c b/source3/msdfs/msdfs.c index ce6e64d915..4c86cd0f94 100644 --- a/source3/msdfs/msdfs.c +++ b/source3/msdfs/msdfs.c @@ -40,7 +40,7 @@ static BOOL parse_dfs_path(char* pathname, struct dfs_path* pdp) ZERO_STRUCTP(pdp); - trim_string(temp,"\\","\\"); + trim_char(temp,'\\','\\'); DEBUG(10,("temp in parse_dfs_path: .%s. after trimming \\'s\n",temp)); /* now tokenize */ @@ -87,8 +87,16 @@ static BOOL create_conn_struct( connection_struct *conn, int snum, char *path) conn->connectpath = path; pstring_sub(conn->connectpath , "%S", lp_servicename(snum)); + /* needed for smbd_vfs_init() */ + + if ( (conn->mem_ctx=talloc_init("connection_struct")) == NULL ) { + DEBUG(0,("talloc_init(connection_struct) failed!\n")); + return False; + } + if (!smbd_vfs_init(conn)) { DEBUG(0,("create_conn_struct: smbd_vfs_init failed.\n")); + talloc_destroy( conn->mem_ctx ); return False; } return True; @@ -267,7 +275,7 @@ static BOOL resolve_dfs_path(char* dfspath, struct dfs_path* dp, char *q; pstring buf; pstrcpy(buf, dfspath); - trim_string(buf, NULL, "\\"); + trim_char(buf, '\0', '\\'); for (; consumed_level; consumed_level--) { q = strrchr(buf, '\\'); if (q) *q = 0; @@ -339,6 +347,7 @@ BOOL get_referred_path(char *pathname, struct junction_map* jn, struct connection_struct* conn = &conns; pstring conn_path; int snum; + BOOL ret = False; BOOL self_referral = False; @@ -381,16 +390,15 @@ BOOL get_referred_path(char *pathname, struct junction_map* jn, if (!lp_msdfs_root(SNUM(conn))) { DEBUG(3,("get_referred_path: .%s. in dfs path %s is not a dfs root.\n", dp.servicename, pathname)); - return False; + goto out; } if (*lp_msdfs_proxy(snum) != '\0') { struct referral* ref; jn->referral_count = 1; - if ((ref = (struct referral*) malloc(sizeof(struct referral))) - == NULL) { + if ((ref = (struct referral*) malloc(sizeof(struct referral))) == NULL) { DEBUG(0, ("malloc failed for referral\n")); - return False; + goto out; } pstrcpy(ref->alternate_path, lp_msdfs_proxy(snum)); @@ -401,7 +409,8 @@ BOOL get_referred_path(char *pathname, struct junction_map* jn, jn->referral_list = ref; if (consumedcntp) *consumedcntp = strlen(pathname); - return True; + ret = True; + goto out; } /* If not remote & not a self referral, return False */ @@ -410,7 +419,7 @@ BOOL get_referred_path(char *pathname, struct junction_map* jn, self_referralp, consumedcntp)) { if (!*self_referralp) { DEBUG(3,("get_referred_path: No valid referrals for path %s\n", pathname)); - return False; + goto out; } } @@ -418,10 +427,9 @@ BOOL get_referred_path(char *pathname, struct junction_map* jn, if (*self_referralp) { struct referral* ref; jn->referral_count = 1; - if((ref = (struct referral*) malloc(sizeof(struct referral))) - == NULL) { + if((ref = (struct referral*) malloc(sizeof(struct referral))) == NULL) { DEBUG(0,("malloc failed for referral\n")); - return False; + goto out; } pstrcpy(ref->alternate_path,pathname); @@ -431,8 +439,12 @@ BOOL get_referred_path(char *pathname, struct junction_map* jn, if (consumedcntp) *consumedcntp = strlen(pathname); } - - return True; + + ret = True; +out: + talloc_destroy( conn->mem_ctx ); + + return ret; } static int setup_ver2_dfs_referral(char* pathname, char** ppdata, @@ -758,6 +770,7 @@ BOOL create_msdfs_link(struct junction_map* jn, BOOL exists) connection_struct *conn = &conns; int i=0; BOOL insert_comma = False; + BOOL ret = False; if(!junction_to_local_path(jn, path, sizeof(path), conn)) return False; @@ -767,7 +780,7 @@ BOOL create_msdfs_link(struct junction_map* jn, BOOL exists) for(i=0; ireferral_count; i++) { char* refpath = jn->referral_list[i].alternate_path; - trim_string(refpath, "\\", "\\"); + trim_char(refpath, '\\', '\\'); if(*refpath == '\0') { if (i == 0) insert_comma = False; @@ -786,14 +799,20 @@ BOOL create_msdfs_link(struct junction_map* jn, BOOL exists) if(exists) if(SMB_VFS_UNLINK(conn,path)!=0) - return False; + goto out; if(SMB_VFS_SYMLINK(conn, msdfs_link, path) < 0) { DEBUG(1,("create_msdfs_link: symlink failed %s -> %s\nError: %s\n", path, msdfs_link, strerror(errno))); - return False; + goto out; } - return True; + + + ret = True; + +out: + talloc_destroy( conn->mem_ctx ); + return ret; } BOOL remove_msdfs_link(struct junction_map* jn) @@ -801,14 +820,16 @@ BOOL remove_msdfs_link(struct junction_map* jn) pstring path; connection_struct conns; connection_struct *conn = &conns; + BOOL ret = False; - if(!junction_to_local_path(jn, path, sizeof(path), conn)) - return False; - - if(SMB_VFS_UNLINK(conn, path)!=0) - return False; - - return True; + if( junction_to_local_path(jn, path, sizeof(path), conn) ) { + if( SMB_VFS_UNLINK(conn, path) == 0 ) + ret = True; + + talloc_destroy( conn->mem_ctx ); + } + + return ret; } static BOOL form_junctions(int snum, struct junction_map* jn, int* jn_count) @@ -821,6 +842,7 @@ static BOOL form_junctions(int snum, struct junction_map* jn, int* jn_count) connection_struct conns; connection_struct *conn = &conns; struct referral *ref = NULL; + BOOL ret = False; pstrcpy(connect_path,lp_pathname(snum)); @@ -846,7 +868,7 @@ static BOOL form_junctions(int snum, struct junction_map* jn, int* jn_count) = (struct referral*) malloc(sizeof(struct referral)); if (jn[cnt].referral_list == NULL) { DEBUG(0, ("Malloc failed!\n")); - return False; + goto out; } ref->proximity = 0; @@ -854,7 +876,8 @@ static BOOL form_junctions(int snum, struct junction_map* jn, int* jn_count) if (*lp_msdfs_proxy(snum) != '\0') { pstrcpy(ref->alternate_path, lp_msdfs_proxy(snum)); *jn_count = ++cnt; - return True; + ret = True; + goto out; } slprintf(ref->alternate_path, sizeof(pstring)-1, @@ -864,7 +887,7 @@ static BOOL form_junctions(int snum, struct junction_map* jn, int* jn_count) /* Now enumerate all dfs links */ dirp = SMB_VFS_OPENDIR(conn, connect_path); if(!dirp) - return False; + goto out; while((dname = vfs_readdirname(conn, dirp)) != NULL) { pstring pathreal; @@ -883,7 +906,9 @@ static BOOL form_junctions(int snum, struct junction_map* jn, int* jn_count) SMB_VFS_CLOSEDIR(conn,dirp); *jn_count = cnt; - return True; +out: + talloc_destroy(conn->mem_ctx); + return ret; } int enum_msdfs_links(struct junction_map* jn) @@ -892,9 +917,9 @@ int enum_msdfs_links(struct junction_map* jn) int jn_count = 0; if(!lp_host_msdfs()) - return -1; + return 0; - for(i=0;*lp_servicename(i);i++) { + for(i=0;i < lp_numservices();i++) { if(lp_msdfs_root(i)) form_junctions(i,jn,&jn_count); } diff --git a/source3/nmbd/asyncdns.c b/source3/nmbd/asyncdns.c index c86ee69a09..6d5d487b11 100644 --- a/source3/nmbd/asyncdns.c +++ b/source3/nmbd/asyncdns.c @@ -26,26 +26,25 @@ static struct name_record *add_dns_result(struct nmb_name *question, struct in_addr addr) { - int name_type = question->name_type; - char *qname = question->name; - + int name_type = question->name_type; + nstring qname; + + pull_ascii_nstring(qname, question->name); - if (!addr.s_addr) { - /* add the fail to WINS cache of names. give it 1 hour in the cache */ - DEBUG(3,("add_dns_result: Negative DNS answer for %s\n", qname)); - (void)add_name_to_subnet( wins_server_subnet, qname, name_type, - NB_ACTIVE, 60*60, DNSFAIL_NAME, 1, &addr ); - return( NULL ); - } - - /* add it to our WINS cache of names. give it 2 hours in the cache */ - DEBUG(3,("add_dns_result: DNS gave answer for %s of %s\n", qname, inet_ntoa(addr))); - - return( add_name_to_subnet( wins_server_subnet, qname, name_type, - NB_ACTIVE, 2*60*60, DNS_NAME, 1, &addr ) ); -} + if (!addr.s_addr) { + /* add the fail to WINS cache of names. give it 1 hour in the cache */ + DEBUG(3,("add_dns_result: Negative DNS answer for %s\n", qname)); + (void)add_name_to_subnet( wins_server_subnet, qname, name_type, + NB_ACTIVE, 60*60, DNSFAIL_NAME, 1, &addr ); + return( NULL ); + } + /* add it to our WINS cache of names. give it 2 hours in the cache */ + DEBUG(3,("add_dns_result: DNS gave answer for %s of %s\n", qname, inet_ntoa(addr))); + return( add_name_to_subnet( wins_server_subnet, qname, name_type, + NB_ACTIVE, 2*60*60, DNS_NAME, 1, &addr ) ); +} #ifndef SYNC_DNS @@ -70,6 +69,7 @@ static struct packet_struct *dns_current; return the fd used to gather async dns replies. This is added to the select loop ****************************************************************************/ + int asyncdns_fd(void) { return fd_in; @@ -110,7 +110,7 @@ static void asyncdns_process(void) static void sig_term(int sig) { - _exit(0); + _exit(0); } /*************************************************************************** @@ -224,10 +224,10 @@ void run_dns_queue(void) if (query_current(&r)) { DEBUG(3,("DNS calling send_wins_name_query_response\n")); in_dns = 1; - if(namerec == NULL) - send_wins_name_query_response(NAM_ERR, dns_current, NULL); - else - send_wins_name_query_response(0,dns_current,namerec); + if(namerec == NULL) + send_wins_name_query_response(NAM_ERR, dns_current, NULL); + else + send_wins_name_query_response(0,dns_current,namerec); in_dns = 0; } @@ -245,10 +245,10 @@ void run_dns_queue(void) if (nmb_name_equal(question, &r.name)) { DEBUG(3,("DNS calling send_wins_name_query_response\n")); in_dns = 1; - if(namerec == NULL) - send_wins_name_query_response(NAM_ERR, p, NULL); - else - send_wins_name_query_response(0,p,namerec); + if(namerec == NULL) + send_wins_name_query_response(NAM_ERR, p, NULL); + else + send_wins_name_query_response(0,p,namerec); in_dns = 0; p->locked = False; @@ -269,7 +269,8 @@ void run_dns_queue(void) if (dns_queue) { dns_current = dns_queue; dns_queue = dns_queue->next; - if (dns_queue) dns_queue->prev = NULL; + if (dns_queue) + dns_queue->prev = NULL; dns_current->next = NULL; if (!write_child(dns_current)) { @@ -277,12 +278,12 @@ void run_dns_queue(void) return; } } - } /*************************************************************************** queue a DNS query ****************************************************************************/ + BOOL queue_dns_query(struct packet_struct *p,struct nmb_name *question, struct name_record **n) { @@ -315,11 +316,14 @@ BOOL queue_dns_query(struct packet_struct *p,struct nmb_name *question, /*************************************************************************** we use this when we can't do async DNS lookups ****************************************************************************/ + BOOL queue_dns_query(struct packet_struct *p,struct nmb_name *question, struct name_record **n) { - char *qname = question->name; struct in_addr dns_ip; + nstring qname; + + pull_ascii_nstring(qname, question->name); DEBUG(3,("DNS search for %s - ", nmb_namestr(question))); @@ -332,18 +336,19 @@ BOOL queue_dns_query(struct packet_struct *p,struct nmb_name *question, BlockSignals(True, SIGTERM); *n = add_dns_result(question, dns_ip); - if(*n == NULL) - send_wins_name_query_response(NAM_ERR, p, NULL); - else - send_wins_name_query_response(0, p, *n); + if(*n == NULL) + send_wins_name_query_response(NAM_ERR, p, NULL); + else + send_wins_name_query_response(0, p, *n); return False; } /*************************************************************************** With sync dns there is no child to kill on SIGTERM. ****************************************************************************/ + void kill_async_dns_child(void) { - return; + return; } #endif diff --git a/source3/nmbd/nmbd.c b/source3/nmbd/nmbd.c index 2801e54551..25ba07c8a7 100644 --- a/source3/nmbd/nmbd.c +++ b/source3/nmbd/nmbd.c @@ -231,7 +231,8 @@ static BOOL reload_interfaces(time_t t) DEBUG(2,("Found new interface %s\n", inet_ntoa(iface->ip))); subrec = make_normal_subnet(iface); - if (subrec) register_my_workgroup_one_subnet(subrec); + if (subrec) + register_my_workgroup_one_subnet(subrec); } } @@ -303,6 +304,7 @@ static BOOL reload_nmbd_services(BOOL test) * We use buf here to return BOOL result to process() when reload_interfaces() * detects that there are no subnets. **************************************************************************** */ + static void msg_reload_nmbd_services(int msg_type, pid_t src, void *buf, size_t len) { write_browse_list( 0, True ); @@ -650,126 +652,120 @@ static BOOL open_sockets(BOOL isdaemon, int port) log_stdout = True; } - if ( log_stdout && Fork ) { - DEBUG(0,("ERROR: Can't log to stdout (-S) unless daemon is in foreground (-F) or interactive (-i)\n")); - exit(1); - } + if ( log_stdout && Fork ) { + DEBUG(0,("ERROR: Can't log to stdout (-S) unless daemon is in foreground (-F) or interactive (-i)\n")); + exit(1); + } - setup_logging( argv[0], log_stdout ); + setup_logging( argv[0], log_stdout ); - reopen_logs(); + reopen_logs(); - DEBUG( 0, ( "Netbios nameserver version %s started.\n", VERSION ) ); - DEBUGADD( 0, ( "Copyright Andrew Tridgell and the Samba Team 1994-2003\n" ) ); + DEBUG( 0, ( "Netbios nameserver version %s started.\n", SAMBA_VERSION_STRING) ); + DEBUGADD( 0, ( "Copyright Andrew Tridgell and the Samba Team 1994-2003\n" ) ); - if ( !reload_nmbd_services(False) ) - return(-1); + if ( !reload_nmbd_services(False) ) + return(-1); - if(!init_names()) - return -1; + if(!init_names()) + return -1; - reload_nmbd_services( True ); + reload_nmbd_services( True ); - if (strequal(lp_workgroup(),"*")) - { - DEBUG(0,("ERROR: a workgroup name of * is no longer supported\n")); - exit(1); - } + if (strequal(lp_workgroup(),"*")) { + DEBUG(0,("ERROR: a workgroup name of * is no longer supported\n")); + exit(1); + } - set_samba_nb_type(); + set_samba_nb_type(); - if (!is_daemon && !is_a_socket(0)) - { - DEBUG(0,("standard input is not a socket, assuming -D option\n")); - is_daemon = True; - } + if (!is_daemon && !is_a_socket(0)) { + DEBUG(0,("standard input is not a socket, assuming -D option\n")); + is_daemon = True; + } - if (is_daemon && !opt_interactive) - { - DEBUG( 2, ( "Becoming a daemon.\n" ) ); - become_daemon(Fork); - } + if (is_daemon && !opt_interactive) { + DEBUG( 2, ( "Becoming a daemon.\n" ) ); + become_daemon(Fork); + } #if HAVE_SETPGID - /* - * If we're interactive we want to set our own process group for - * signal management. - */ - if (opt_interactive) - setpgid( (pid_t)0, (pid_t)0 ); + /* + * If we're interactive we want to set our own process group for + * signal management. + */ + if (opt_interactive) + setpgid( (pid_t)0, (pid_t)0 ); #endif #ifndef SYNC_DNS - /* Setup the async dns. We do it here so it doesn't have all the other - stuff initialised and thus chewing memory and sockets */ - if(lp_we_are_a_wins_server() && lp_dns_proxy()) { - start_async_dns(); - } + /* Setup the async dns. We do it here so it doesn't have all the other + stuff initialised and thus chewing memory and sockets */ + if(lp_we_are_a_wins_server() && lp_dns_proxy()) { + start_async_dns(); + } #endif - if (!directory_exist(lp_lockdir(), NULL)) { - mkdir(lp_lockdir(), 0755); - } - - pidfile_create("nmbd"); - message_init(); - message_register(MSG_FORCE_ELECTION, nmbd_message_election); - message_register(MSG_WINS_NEW_ENTRY, nmbd_wins_new_entry); - message_register(MSG_SHUTDOWN, nmbd_terminate); - message_register(MSG_SMB_CONF_UPDATED, msg_reload_nmbd_services); - - DEBUG( 3, ( "Opening sockets %d\n", global_nmb_port ) ); - - if ( !open_sockets( is_daemon, global_nmb_port ) ) { - kill_async_dns_child(); - return 1; - } - - /* Determine all the IP addresses we have. */ - load_interfaces(); - - /* Create an nmbd subnet record for each of the above. */ - if( False == create_subnets() ) - { - DEBUG(0,("ERROR: Failed when creating subnet lists. Exiting.\n")); - kill_async_dns_child(); - exit(1); - } - - /* Load in any static local names. */ - load_lmhosts_file(dyn_LMHOSTSFILE); - DEBUG(3,("Loaded hosts file %s\n", dyn_LMHOSTSFILE)); - - /* If we are acting as a WINS server, initialise data structures. */ - if( !initialise_wins() ) - { - DEBUG( 0, ( "nmbd: Failed when initialising WINS server.\n" ) ); - kill_async_dns_child(); - exit(1); - } - - /* - * Register nmbd primary workgroup and nmbd names on all - * the broadcast subnets, and on the WINS server (if specified). - * Also initiate the startup of our primary workgroup (start - * elections if we are setup as being able to be a local - * master browser. - */ - - if( False == register_my_workgroup_and_names() ) - { - DEBUG(0,("ERROR: Failed when creating my my workgroup. Exiting.\n")); - kill_async_dns_child(); - exit(1); - } - - /* We can only take signals in the select. */ - BlockSignals( True, SIGTERM ); - - process(); - - if (dbf) - x_fclose(dbf); - kill_async_dns_child(); - return(0); + if (!directory_exist(lp_lockdir(), NULL)) { + mkdir(lp_lockdir(), 0755); + } + + pidfile_create("nmbd"); + message_init(); + message_register(MSG_FORCE_ELECTION, nmbd_message_election); + message_register(MSG_WINS_NEW_ENTRY, nmbd_wins_new_entry); + message_register(MSG_SHUTDOWN, nmbd_terminate); + message_register(MSG_SMB_CONF_UPDATED, msg_reload_nmbd_services); + + DEBUG( 3, ( "Opening sockets %d\n", global_nmb_port ) ); + + if ( !open_sockets( is_daemon, global_nmb_port ) ) { + kill_async_dns_child(); + return 1; + } + + /* Determine all the IP addresses we have. */ + load_interfaces(); + + /* Create an nmbd subnet record for each of the above. */ + if( False == create_subnets() ) { + DEBUG(0,("ERROR: Failed when creating subnet lists. Exiting.\n")); + kill_async_dns_child(); + exit(1); + } + + /* Load in any static local names. */ + load_lmhosts_file(dyn_LMHOSTSFILE); + DEBUG(3,("Loaded hosts file %s\n", dyn_LMHOSTSFILE)); + + /* If we are acting as a WINS server, initialise data structures. */ + if( !initialise_wins() ) { + DEBUG( 0, ( "nmbd: Failed when initialising WINS server.\n" ) ); + kill_async_dns_child(); + exit(1); + } + + /* + * Register nmbd primary workgroup and nmbd names on all + * the broadcast subnets, and on the WINS server (if specified). + * Also initiate the startup of our primary workgroup (start + * elections if we are setup as being able to be a local + * master browser. + */ + + if( False == register_my_workgroup_and_names() ) { + DEBUG(0,("ERROR: Failed when creating my my workgroup. Exiting.\n")); + kill_async_dns_child(); + exit(1); + } + + /* We can only take signals in the select. */ + BlockSignals( True, SIGTERM ); + + process(); + + if (dbf) + x_fclose(dbf); + kill_async_dns_child(); + return(0); } diff --git a/source3/nmbd/nmbd_become_dmb.c b/source3/nmbd/nmbd_become_dmb.c index 2e76e51f45..46d37fbb81 100644 --- a/source3/nmbd/nmbd_become_dmb.c +++ b/source3/nmbd/nmbd_become_dmb.c @@ -3,7 +3,7 @@ NBT netbios routines and daemon - version 2 Copyright (C) Andrew Tridgell 1994-1998 Copyright (C) Luke Kenneth Casson Leighton 1994-1998 - Copyright (C) Jeremy Allison 1994-1998 + Copyright (C) Jeremy Allison 1994-2003 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -37,36 +37,37 @@ static void become_domain_master_fail(struct subnet_record *subrec, struct response_record *rrec, struct nmb_name *fail_name) { - struct work_record *work = find_workgroup_on_subnet(subrec, fail_name->name); - struct server_record *servrec; - - if(!work) - { - DEBUG(0,("become_domain_master_fail: Error - cannot find \ -workgroup %s on subnet %s\n", fail_name->name, subrec->subnet_name)); - return; - } - - /* Set the state back to DOMAIN_NONE. */ - work->dom_state = DOMAIN_NONE; - - if((servrec = find_server_in_workgroup( work, global_myname())) == NULL) - { - DEBUG(0,("become_domain_master_fail: Error - cannot find server %s \ + nstring failname; + struct work_record *work; + struct server_record *servrec; + + pull_ascii_nstring(failname, fail_name->name); + work = find_workgroup_on_subnet(subrec, failname); + if(!work) { + DEBUG(0,("become_domain_master_fail: Error - cannot find \ +workgroup %s on subnet %s\n", failname, subrec->subnet_name)); + return; + } + + /* Set the state back to DOMAIN_NONE. */ + work->dom_state = DOMAIN_NONE; + + if((servrec = find_server_in_workgroup( work, global_myname())) == NULL) { + DEBUG(0,("become_domain_master_fail: Error - cannot find server %s \ in workgroup %s on subnet %s\n", - global_myname(), work->work_group, subrec->subnet_name)); - return; - } + global_myname(), work->work_group, subrec->subnet_name)); + return; + } - /* Update our server status. */ - servrec->serv.type &= ~SV_TYPE_DOMAIN_MASTER; + /* Update our server status. */ + servrec->serv.type &= ~SV_TYPE_DOMAIN_MASTER; - /* Tell the namelist writer to write out a change. */ - subrec->work_changed = True; + /* Tell the namelist writer to write out a change. */ + subrec->work_changed = True; - DEBUG(0,("become_domain_master_fail: Failed to become a domain master browser for \ + DEBUG(0,("become_domain_master_fail: Failed to become a domain master browser for \ workgroup %s on subnet %s. Couldn't register name %s.\n", - work->work_group, subrec->subnet_name, nmb_namestr(fail_name))); + work->work_group, subrec->subnet_name, nmb_namestr(fail_name))); } /**************************************************************************** @@ -79,115 +80,112 @@ static void become_domain_master_stage2(struct subnet_record *subrec, uint16 nb_flags, int ttl, struct in_addr registered_ip) { - struct work_record *work = find_workgroup_on_subnet( subrec, registered_name->name); - struct server_record *servrec; - - if(!work) - { - DEBUG(0,("become_domain_master_stage2: Error - cannot find \ -workgroup %s on subnet %s\n", registered_name->name, subrec->subnet_name)); - return; - } - - if((servrec = find_server_in_workgroup( work, global_myname())) == NULL) - { - DEBUG(0,("become_domain_master_stage2: Error - cannot find server %s \ + nstring regname; + struct work_record *work; + struct server_record *servrec; + + pull_ascii_nstring(regname, registered_name->name); + work = find_workgroup_on_subnet( subrec, regname); + + if(!work) { + DEBUG(0,("become_domain_master_stage2: Error - cannot find \ +workgroup %s on subnet %s\n", regname, subrec->subnet_name)); + return; + } + + if((servrec = find_server_in_workgroup( work, global_myname())) == NULL) { + DEBUG(0,("become_domain_master_stage2: Error - cannot find server %s \ in workgroup %s on subnet %s\n", - global_myname(), registered_name->name, subrec->subnet_name)); - work->dom_state = DOMAIN_NONE; - return; - } - - /* Set the state in the workgroup structure. */ - work->dom_state = DOMAIN_MST; /* Become domain master. */ - - /* Update our server status. */ - servrec->serv.type |= (SV_TYPE_NT|SV_TYPE_DOMAIN_MASTER); - - /* Tell the namelist writer to write out a change. */ - subrec->work_changed = True; - - if( DEBUGLVL( 0 ) ) - { - dbgtext( "*****\n\nSamba server %s ", global_myname() ); - dbgtext( "is now a domain master browser for " ); - dbgtext( "workgroup %s ", work->work_group ); - dbgtext( "on subnet %s\n\n*****\n", subrec->subnet_name ); - } - - if( subrec == unicast_subnet ) - { - struct nmb_name nmbname; - struct in_addr my_first_ip; - - /* Put our name and first IP address into the - workgroup struct as domain master browser. This - will stop us syncing with ourself if we are also - a local master browser. */ - - make_nmb_name(&nmbname, global_myname(), 0x20); - - work->dmb_name = nmbname; - /* Pick the first interface ip address as the domain master browser ip. */ - my_first_ip = *iface_n_ip(0); - - putip((char *)&work->dmb_addr, &my_first_ip); - - /* We successfully registered by unicast with the - WINS server. We now expect to become the domain - master on the local subnets. If this fails, it's - probably a 1.9.16p2 to 1.9.16p11 server's fault. - - This is a configuration issue that should be addressed - by the network administrator - you shouldn't have - several machines configured as a domain master browser - for the same WINS scope (except if they are 1.9.17 or - greater, and you know what you're doing. - - see docs/DOMAIN.txt. - - */ - become_domain_master_browser_bcast(work->work_group); - } - else - { - /* - * Now we are a domain master on a broadcast subnet, we need to add - * the WORKGROUP<1b> name to the unicast subnet so that we can answer - * unicast requests sent to this name. This bug wasn't found for a while - * as it is strange to have a DMB without using WINS. JRA. - */ - insert_permanent_name_into_unicast(subrec, registered_name, nb_flags); - } + global_myname(), regname, subrec->subnet_name)); + work->dom_state = DOMAIN_NONE; + return; + } + + /* Set the state in the workgroup structure. */ + work->dom_state = DOMAIN_MST; /* Become domain master. */ + + /* Update our server status. */ + servrec->serv.type |= (SV_TYPE_NT|SV_TYPE_DOMAIN_MASTER); + + /* Tell the namelist writer to write out a change. */ + subrec->work_changed = True; + + if( DEBUGLVL( 0 ) ) { + dbgtext( "*****\n\nSamba server %s ", global_myname() ); + dbgtext( "is now a domain master browser for " ); + dbgtext( "workgroup %s ", work->work_group ); + dbgtext( "on subnet %s\n\n*****\n", subrec->subnet_name ); + } + + if( subrec == unicast_subnet ) { + struct nmb_name nmbname; + struct in_addr my_first_ip; + + /* Put our name and first IP address into the + workgroup struct as domain master browser. This + will stop us syncing with ourself if we are also + a local master browser. */ + + make_nmb_name(&nmbname, global_myname(), 0x20); + + work->dmb_name = nmbname; + /* Pick the first interface ip address as the domain master browser ip. */ + my_first_ip = *iface_n_ip(0); + + putip((char *)&work->dmb_addr, &my_first_ip); + + /* We successfully registered by unicast with the + WINS server. We now expect to become the domain + master on the local subnets. If this fails, it's + probably a 1.9.16p2 to 1.9.16p11 server's fault. + + This is a configuration issue that should be addressed + by the network administrator - you shouldn't have + several machines configured as a domain master browser + for the same WINS scope (except if they are 1.9.17 or + greater, and you know what you're doing. + + see docs/DOMAIN.txt. + + */ + become_domain_master_browser_bcast(work->work_group); + } else { + /* + * Now we are a domain master on a broadcast subnet, we need to add + * the WORKGROUP<1b> name to the unicast subnet so that we can answer + * unicast requests sent to this name. This bug wasn't found for a while + * as it is strange to have a DMB without using WINS. JRA. + */ + insert_permanent_name_into_unicast(subrec, registered_name, nb_flags); + } } /**************************************************************************** Start the name registration process when becoming a Domain Master Browser on a subnet. - ****************************************************************************/ +****************************************************************************/ -static void become_domain_master_stage1(struct subnet_record *subrec, char *wg_name) +static void become_domain_master_stage1(struct subnet_record *subrec, const char *wg_name) { - struct work_record *work; + struct work_record *work; - DEBUG(2,("become_domain_master_stage1: Becoming domain master browser for \ + DEBUG(2,("become_domain_master_stage1: Becoming domain master browser for \ workgroup %s on subnet %s\n", wg_name, subrec->subnet_name)); - /* First, find the workgroup on the subnet. */ - if((work = find_workgroup_on_subnet( subrec, wg_name )) == NULL) - { - DEBUG(0,("become_domain_master_stage1: Error - unable to find workgroup %s on subnet %s.\n", - wg_name, subrec->subnet_name)); - return; - } - - DEBUG(3,("become_domain_master_stage1: go to first stage: register <1b> name\n")); - work->dom_state = DOMAIN_WAIT; - - /* WORKGROUP<1b> is the domain master browser name. */ - register_name(subrec, work->work_group,0x1b,samba_nb_type, - become_domain_master_stage2, - become_domain_master_fail, NULL); + /* First, find the workgroup on the subnet. */ + if((work = find_workgroup_on_subnet( subrec, wg_name )) == NULL) { + DEBUG(0,("become_domain_master_stage1: Error - unable to find workgroup %s on subnet %s.\n", + wg_name, subrec->subnet_name)); + return; + } + + DEBUG(3,("become_domain_master_stage1: go to first stage: register <1b> name\n")); + work->dom_state = DOMAIN_WAIT; + + /* WORKGROUP<1b> is the domain master browser name. */ + register_name(subrec, work->work_group,0x1b,samba_nb_type, + become_domain_master_stage2, + become_domain_master_fail, NULL); } /**************************************************************************** @@ -202,37 +200,35 @@ static void become_domain_master_query_success(struct subnet_record *subrec, struct nmb_name *nmbname, struct in_addr ip, struct res_rec *rrec) { - /* If the given ip is not ours, then we can't become a domain - controler as the name is already registered. - */ - - /* BUG note. Samba 1.9.16p11 servers seem to return the broadcast - address or zero ip for this query. Pretend this is ok. */ - - if(ismyip(ip) || ip_equal(allones_ip, ip) || is_zero_ip(ip)) - { - if( DEBUGLVL( 3 ) ) - { - dbgtext( "become_domain_master_query_success():\n" ); - dbgtext( "Our address (%s) ", inet_ntoa(ip) ); - dbgtext( "returned in query for name %s ", nmb_namestr(nmbname) ); - dbgtext( "(domain master browser name) " ); - dbgtext( "on subnet %s.\n", subrec->subnet_name ); - dbgtext( "Continuing with domain master code.\n" ); - } - - become_domain_master_stage1(subrec, nmbname->name); - } - else - { - if( DEBUGLVL( 0 ) ) - { - dbgtext( "become_domain_master_query_success:\n" ); - dbgtext( "There is already a domain master browser at " ); - dbgtext( "IP %s for workgroup %s ", inet_ntoa(ip), nmbname->name ); - dbgtext( "registered on subnet %s.\n", subrec->subnet_name ); - } - } + nstring name; + pull_ascii_nstring(name, nmbname->name); + + /* If the given ip is not ours, then we can't become a domain + controler as the name is already registered. + */ + + /* BUG note. Samba 1.9.16p11 servers seem to return the broadcast + address or zero ip for this query. Pretend this is ok. */ + + if(ismyip(ip) || ip_equal(allones_ip, ip) || is_zero_ip(ip)) { + if( DEBUGLVL( 3 ) ) { + dbgtext( "become_domain_master_query_success():\n" ); + dbgtext( "Our address (%s) ", inet_ntoa(ip) ); + dbgtext( "returned in query for name %s ", nmb_namestr(nmbname) ); + dbgtext( "(domain master browser name) " ); + dbgtext( "on subnet %s.\n", subrec->subnet_name ); + dbgtext( "Continuing with domain master code.\n" ); + } + + become_domain_master_stage1(subrec, name); + } else { + if( DEBUGLVL( 0 ) ) { + dbgtext( "become_domain_master_query_success:\n" ); + dbgtext( "There is already a domain master browser at " ); + dbgtext( "IP %s for workgroup %s ", inet_ntoa(ip), name ); + dbgtext( "registered on subnet %s.\n", subrec->subnet_name ); + } + } } /**************************************************************************** @@ -245,18 +241,21 @@ static void become_domain_master_query_fail(struct subnet_record *subrec, struct response_record *rrec, struct nmb_name *question_name, int fail_code) { - /* If the query was unicast, and the error is not NAM_ERR (name didn't exist), - then this is a failure. Otherwise, not finding the name is what we want. */ - if((subrec == unicast_subnet) && (fail_code != NAM_ERR)) - { - DEBUG(0,("become_domain_master_query_fail: Error %d returned when \ + nstring name; + + /* If the query was unicast, and the error is not NAM_ERR (name didn't exist), + then this is a failure. Otherwise, not finding the name is what we want. */ + + if((subrec == unicast_subnet) && (fail_code != NAM_ERR)) { + DEBUG(0,("become_domain_master_query_fail: Error %d returned when \ querying WINS server for name %s.\n", - fail_code, nmb_namestr(question_name))); - return; - } + fail_code, nmb_namestr(question_name))); + return; + } - /* Otherwise - not having the name allows us to register it. */ - become_domain_master_stage1(subrec, question_name->name); + /* Otherwise - not having the name allows us to register it. */ + pull_ascii_nstring(name, question_name->name); + become_domain_master_stage1(subrec, name); } /**************************************************************************** @@ -265,47 +264,43 @@ querying WINS server for name %s.\n", static void become_domain_master_browser_bcast(const char *workgroup_name) { - struct subnet_record *subrec; - - for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) - { - struct work_record *work = find_workgroup_on_subnet(subrec, workgroup_name); - - if (work && (work->dom_state == DOMAIN_NONE)) - { - struct nmb_name nmbname; - make_nmb_name(&nmbname,workgroup_name,0x1b); - - /* - * Check for our name on the given broadcast subnet first, only initiate - * further processing if we cannot find it. - */ - - if (find_name_on_subnet(subrec, &nmbname, FIND_SELF_NAME) == NULL) - { - if( DEBUGLVL( 0 ) ) - { - dbgtext( "become_domain_master_browser_bcast:\n" ); - dbgtext( "Attempting to become domain master browser on " ); - dbgtext( "workgroup %s on subnet %s\n", - workgroup_name, subrec->subnet_name ); - } - - /* Send out a query to establish whether there's a - domain controller on the local subnet. If not, - we can become a domain controller. - */ - - DEBUG(0,("become_domain_master_browser_bcast: querying subnet %s \ + struct subnet_record *subrec; + + for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) { + struct work_record *work = find_workgroup_on_subnet(subrec, workgroup_name); + + if (work && (work->dom_state == DOMAIN_NONE)) { + struct nmb_name nmbname; + make_nmb_name(&nmbname,workgroup_name,0x1b); + + /* + * Check for our name on the given broadcast subnet first, only initiate + * further processing if we cannot find it. + */ + + if (find_name_on_subnet(subrec, &nmbname, FIND_SELF_NAME) == NULL) { + if( DEBUGLVL( 0 ) ) { + dbgtext( "become_domain_master_browser_bcast:\n" ); + dbgtext( "Attempting to become domain master browser on " ); + dbgtext( "workgroup %s on subnet %s\n", + workgroup_name, subrec->subnet_name ); + } + + /* Send out a query to establish whether there's a + domain controller on the local subnet. If not, + we can become a domain controller. + */ + + DEBUG(0,("become_domain_master_browser_bcast: querying subnet %s \ for domain master browser on workgroup %s\n", subrec->subnet_name, workgroup_name)); - query_name(subrec, nmbname.name, nmbname.name_type, - become_domain_master_query_success, - become_domain_master_query_fail, - NULL); - } - } - } + query_name(subrec, workgroup_name, nmbname.name_type, + become_domain_master_query_success, + become_domain_master_query_fail, + NULL); + } + } + } } /**************************************************************************** @@ -314,46 +309,43 @@ for domain master browser on workgroup %s\n", subrec->subnet_name, workgroup_nam static void become_domain_master_browser_wins(const char *workgroup_name) { - struct work_record *work; + struct work_record *work; - work = find_workgroup_on_subnet(unicast_subnet, workgroup_name); + work = find_workgroup_on_subnet(unicast_subnet, workgroup_name); - if (work && (work->dom_state == DOMAIN_NONE)) - { - struct nmb_name nmbname; + if (work && (work->dom_state == DOMAIN_NONE)) { + struct nmb_name nmbname; - make_nmb_name(&nmbname,workgroup_name,0x1b); + make_nmb_name(&nmbname,workgroup_name,0x1b); - /* - * Check for our name on the unicast subnet first, only initiate - * further processing if we cannot find it. - */ + /* + * Check for our name on the unicast subnet first, only initiate + * further processing if we cannot find it. + */ - if (find_name_on_subnet(unicast_subnet, &nmbname, FIND_SELF_NAME) == NULL) - { - if( DEBUGLVL( 0 ) ) - { - dbgtext( "become_domain_master_browser_wins:\n" ); - dbgtext( "Attempting to become domain master browser " ); - dbgtext( "on workgroup %s, subnet %s.\n", - workgroup_name, unicast_subnet->subnet_name ); - } + if (find_name_on_subnet(unicast_subnet, &nmbname, FIND_SELF_NAME) == NULL) { + if( DEBUGLVL( 0 ) ) { + dbgtext( "become_domain_master_browser_wins:\n" ); + dbgtext( "Attempting to become domain master browser " ); + dbgtext( "on workgroup %s, subnet %s.\n", + workgroup_name, unicast_subnet->subnet_name ); + } - /* Send out a query to establish whether there's a - domain master broswer registered with WINS. If not, - we can become a domain master browser. - */ + /* Send out a query to establish whether there's a + domain master broswer registered with WINS. If not, + we can become a domain master browser. + */ - DEBUG(0,("become_domain_master_browser_wins: querying WINS server from IP %s \ + DEBUG(0,("become_domain_master_browser_wins: querying WINS server from IP %s \ for domain master browser name %s on workgroup %s\n", - inet_ntoa(unicast_subnet->myip), nmb_namestr(&nmbname), workgroup_name)); - - query_name(unicast_subnet, nmbname.name, nmbname.name_type, - become_domain_master_query_success, - become_domain_master_query_fail, - NULL); - } - } + inet_ntoa(unicast_subnet->myip), nmb_namestr(&nmbname), workgroup_name)); + + query_name(unicast_subnet, workgroup_name, nmbname.name_type, + become_domain_master_query_success, + become_domain_master_query_fail, + NULL); + } + } } /**************************************************************************** @@ -363,34 +355,32 @@ for domain master browser name %s on workgroup %s\n", void add_domain_names(time_t t) { - static time_t lastrun = 0; - - if ((lastrun != 0) && (t < lastrun + (CHECK_TIME_ADD_DOM_NAMES * 60))) - return; - - lastrun = t; - - /* Do the "internet group" - <1c> names. */ - if (lp_domain_logons()) - add_logon_names(); - - /* Do the domain master names. */ - if(lp_domain_master()) - { - if(we_are_a_wins_client()) - { - /* We register the WORKGROUP<1b> name with the WINS - server first, and call add_domain_master_bcast() - only if this is successful. - - This results in domain logon services being gracefully provided, - as opposed to the aggressive nature of 1.9.16p2 to 1.9.16p11. - 1.9.16p2 to 1.9.16p11 - due to a bug in namelogon.c, - cannot provide domain master / domain logon services. - */ - become_domain_master_browser_wins(lp_workgroup()); - } - else - become_domain_master_browser_bcast(lp_workgroup()); - } + static time_t lastrun = 0; + + if ((lastrun != 0) && (t < lastrun + (CHECK_TIME_ADD_DOM_NAMES * 60))) + return; + + lastrun = t; + + /* Do the "internet group" - <1c> names. */ + if (lp_domain_logons()) + add_logon_names(); + + /* Do the domain master names. */ + if(lp_domain_master()) { + if(we_are_a_wins_client()) { + /* We register the WORKGROUP<1b> name with the WINS + server first, and call add_domain_master_bcast() + only if this is successful. + + This results in domain logon services being gracefully provided, + as opposed to the aggressive nature of 1.9.16p2 to 1.9.16p11. + 1.9.16p2 to 1.9.16p11 - due to a bug in namelogon.c, + cannot provide domain master / domain logon services. + */ + become_domain_master_browser_wins(lp_workgroup()); + } else { + become_domain_master_browser_bcast(lp_workgroup()); + } + } } diff --git a/source3/nmbd/nmbd_become_lmb.c b/source3/nmbd/nmbd_become_lmb.c index d390bf72e9..2370c7ba36 100644 --- a/source3/nmbd/nmbd_become_lmb.c +++ b/source3/nmbd/nmbd_become_lmb.c @@ -3,7 +3,7 @@ NBT netbios routines and daemon - version 2 Copyright (C) Andrew Tridgell 1994-1998 Copyright (C) Luke Kenneth Casson Leighton 1994-1998 - Copyright (C) Jeremy Allison 1994-1998 + Copyright (C) Jeremy Allison 1994-2003 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -33,21 +33,20 @@ extern uint16 samba_nb_type; /* Samba's NetBIOS name type. */ void insert_permanent_name_into_unicast( struct subnet_record *subrec, struct nmb_name *nmbname, uint16 nb_type ) { - struct name_record *namerec; - - if((namerec = find_name_on_subnet(unicast_subnet, nmbname, FIND_SELF_NAME)) == NULL) - { - /* The name needs to be created on the unicast subnet. */ - (void)add_name_to_subnet( unicast_subnet, nmbname->name, - nmbname->name_type, nb_type, - PERMANENT_TTL, PERMANENT_NAME, 1, &subrec->myip); - } - else - { - /* The name already exists on the unicast subnet. Add our local - IP for the given broadcast subnet to the name. */ - add_ip_to_name_record( namerec, subrec->myip); - } + nstring name; + struct name_record *namerec; + + if((namerec = find_name_on_subnet(unicast_subnet, nmbname, FIND_SELF_NAME)) == NULL) { + pull_ascii_nstring(name, nmbname->name); + /* The name needs to be created on the unicast subnet. */ + (void)add_name_to_subnet( unicast_subnet, name, + nmbname->name_type, nb_type, + PERMANENT_TTL, PERMANENT_NAME, 1, &subrec->myip); + } else { + /* The name already exists on the unicast subnet. Add our local + IP for the given broadcast subnet to the name. */ + add_ip_to_name_record( namerec, subrec->myip); + } } /******************************************************************* @@ -57,15 +56,14 @@ void insert_permanent_name_into_unicast( struct subnet_record *subrec, static void remove_permanent_name_from_unicast( struct subnet_record *subrec, struct nmb_name *nmbname ) { - struct name_record *namerec; - - if((namerec = find_name_on_subnet(unicast_subnet, nmbname, FIND_SELF_NAME)) != NULL) - { - /* Remove this broadcast subnet IP address from the name. */ - remove_ip_from_name_record( namerec, subrec->myip); - if(namerec->data.num_ips == 0) - remove_name_from_namelist( unicast_subnet, namerec); - } + struct name_record *namerec; + + if((namerec = find_name_on_subnet(unicast_subnet, nmbname, FIND_SELF_NAME)) != NULL) { + /* Remove this broadcast subnet IP address from the name. */ + remove_ip_from_name_record( namerec, subrec->myip); + if(namerec->data.num_ips == 0) + remove_name_from_namelist( unicast_subnet, namerec); + } } /******************************************************************* @@ -73,60 +71,58 @@ static void remove_permanent_name_from_unicast( struct subnet_record *subrec, state back to potential browser, or none. ******************************************************************/ -static void reset_workgroup_state( struct subnet_record *subrec, char *workgroup_name, +static void reset_workgroup_state( struct subnet_record *subrec, const char *workgroup_name, BOOL force_new_election ) { - struct work_record *work; - struct server_record *servrec; - struct nmb_name nmbname; + struct work_record *work; + struct server_record *servrec; + struct nmb_name nmbname; - if((work = find_workgroup_on_subnet( subrec, workgroup_name)) == NULL) - { - DEBUG(0,("reset_workgroup_state: Error - cannot find workgroup %s on \ + if((work = find_workgroup_on_subnet( subrec, workgroup_name)) == NULL) { + DEBUG(0,("reset_workgroup_state: Error - cannot find workgroup %s on \ subnet %s.\n", workgroup_name, subrec->subnet_name )); - return; - } + return; + } - if((servrec = find_server_in_workgroup( work, global_myname())) == NULL) - { - DEBUG(0,("reset_workgroup_state: Error - cannot find server %s \ + if((servrec = find_server_in_workgroup( work, global_myname())) == NULL) { + DEBUG(0,("reset_workgroup_state: Error - cannot find server %s \ in workgroup %s on subnet %s\n", - global_myname(), work->work_group, subrec->subnet_name)); - work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE; - return; - } + global_myname(), work->work_group, subrec->subnet_name)); + work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE; + return; + } - /* Update our server status - remove any master flag and replace - it with the potential browser flag. */ - servrec->serv.type &= ~SV_TYPE_MASTER_BROWSER; - servrec->serv.type |= (lp_local_master() ? SV_TYPE_POTENTIAL_BROWSER : 0); + /* Update our server status - remove any master flag and replace + it with the potential browser flag. */ + servrec->serv.type &= ~SV_TYPE_MASTER_BROWSER; + servrec->serv.type |= (lp_local_master() ? SV_TYPE_POTENTIAL_BROWSER : 0); - /* Tell the namelist writer to write out a change. */ - subrec->work_changed = True; + /* Tell the namelist writer to write out a change. */ + subrec->work_changed = True; - /* Reset our election flags. */ - work->ElectionCriterion &= ~0x4; + /* Reset our election flags. */ + work->ElectionCriterion &= ~0x4; - work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE; + work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE; - /* Forget who the local master browser was for - this workgroup. */ + /* Forget who the local master browser was for + this workgroup. */ - set_workgroup_local_master_browser_name( work, ""); + set_workgroup_local_master_browser_name( work, ""); - /* - * Ensure the IP address of this subnet is not registered as one - * of the IP addresses of the WORKGROUP<1d> name on the unicast - * subnet. This undoes what we did below when we became a local - * master browser. - */ + /* + * Ensure the IP address of this subnet is not registered as one + * of the IP addresses of the WORKGROUP<1d> name on the unicast + * subnet. This undoes what we did below when we became a local + * master browser. + */ - make_nmb_name(&nmbname, work->work_group, 0x1d); + make_nmb_name(&nmbname, work->work_group, 0x1d); - remove_permanent_name_from_unicast( subrec, &nmbname); + remove_permanent_name_from_unicast( subrec, &nmbname); - if(force_new_election) - work->needelection = True; + if(force_new_election) + work->needelection = True; } /******************************************************************* @@ -138,24 +134,25 @@ static void unbecome_local_master_success(struct subnet_record *subrec, struct nmb_name *released_name, struct in_addr released_ip) { - BOOL force_new_election = False; + BOOL force_new_election = False; + nstring relname; - memcpy((char *)&force_new_election, userdata->data, sizeof(BOOL)); + memcpy((char *)&force_new_election, userdata->data, sizeof(BOOL)); - DEBUG(3,("unbecome_local_master_success: released name %s.\n", - nmb_namestr(released_name))); + DEBUG(3,("unbecome_local_master_success: released name %s.\n", + nmb_namestr(released_name))); - /* Now reset the workgroup and server state. */ - reset_workgroup_state( subrec, released_name->name, force_new_election ); + /* Now reset the workgroup and server state. */ + pull_ascii_nstring(relname, released_name->name); + reset_workgroup_state( subrec, relname, force_new_election ); - if( DEBUGLVL( 0 ) ) - { - dbgtext( "*****\n\n" ); - dbgtext( "Samba name server %s ", global_myname() ); - dbgtext( "has stopped being a local master browser " ); - dbgtext( "for workgroup %s ", released_name->name ); - dbgtext( "on subnet %s\n\n*****\n", subrec->subnet_name ); - } + if( DEBUGLVL( 0 ) ) { + dbgtext( "*****\n\n" ); + dbgtext( "Samba name server %s ", global_myname() ); + dbgtext( "has stopped being a local master browser " ); + dbgtext( "for workgroup %s ", relname ); + dbgtext( "on subnet %s\n\n*****\n", subrec->subnet_name ); + } } @@ -166,67 +163,66 @@ static void unbecome_local_master_success(struct subnet_record *subrec, static void unbecome_local_master_fail(struct subnet_record *subrec, struct response_record *rrec, struct nmb_name *fail_name) { - struct name_record *namerec; - struct userdata_struct *userdata = rrec->userdata; - BOOL force_new_election = False; + struct name_record *namerec; + struct userdata_struct *userdata = rrec->userdata; + BOOL force_new_election = False; + nstring failname; - memcpy((char *)&force_new_election, userdata->data, sizeof(BOOL)); + memcpy((char *)&force_new_election, userdata->data, sizeof(BOOL)); - DEBUG(0,("unbecome_local_master_fail: failed to release name %s. \ + DEBUG(0,("unbecome_local_master_fail: failed to release name %s. \ Removing from namelist anyway.\n", nmb_namestr(fail_name))); - /* Do it anyway. */ - namerec = find_name_on_subnet(subrec, fail_name, FIND_SELF_NAME); - if(namerec) - remove_name_from_namelist(subrec, namerec); - - /* Now reset the workgroup and server state. */ - reset_workgroup_state( subrec, fail_name->name, force_new_election ); - - if( DEBUGLVL( 0 ) ) - { - dbgtext( "*****\n\n" ); - dbgtext( "Samba name server %s ", global_myname() ); - dbgtext( "has stopped being a local master browser " ); - dbgtext( "for workgroup %s ", fail_name->name ); - dbgtext( "on subnet %s\n\n*****\n", subrec->subnet_name ); - } + /* Do it anyway. */ + namerec = find_name_on_subnet(subrec, fail_name, FIND_SELF_NAME); + if(namerec) + remove_name_from_namelist(subrec, namerec); + + /* Now reset the workgroup and server state. */ + pull_ascii_nstring(failname, fail_name->name); + reset_workgroup_state( subrec, failname, force_new_election ); + + if( DEBUGLVL( 0 ) ) { + dbgtext( "*****\n\n" ); + dbgtext( "Samba name server %s ", global_myname() ); + dbgtext( "has stopped being a local master browser " ); + dbgtext( "for workgroup %s ", failname ); + dbgtext( "on subnet %s\n\n*****\n", subrec->subnet_name ); + } } /******************************************************************* Utility function to remove the WORKGROUP<1d> name. ******************************************************************/ -static void release_1d_name( struct subnet_record *subrec, char *workgroup_name, +static void release_1d_name( struct subnet_record *subrec, const char *workgroup_name, BOOL force_new_election) { - struct nmb_name nmbname; - struct name_record *namerec; - - make_nmb_name(&nmbname, workgroup_name, 0x1d); - if((namerec = find_name_on_subnet( subrec, &nmbname, FIND_SELF_NAME))!=NULL) - { - struct userdata_struct *userdata; - size_t size = sizeof(struct userdata_struct) + sizeof(BOOL); - - if((userdata = (struct userdata_struct *)malloc(size)) == NULL) - { - DEBUG(0,("release_1d_name: malloc fail.\n")); - return; - } - - userdata->copy_fn = NULL; - userdata->free_fn = NULL; - userdata->userdata_len = sizeof(BOOL); - memcpy((char *)userdata->data, &force_new_election, sizeof(BOOL)); - - release_name(subrec, namerec, - unbecome_local_master_success, - unbecome_local_master_fail, - userdata); - - zero_free(userdata, size); - } + struct nmb_name nmbname; + struct name_record *namerec; + + make_nmb_name(&nmbname, workgroup_name, 0x1d); + if((namerec = find_name_on_subnet( subrec, &nmbname, FIND_SELF_NAME))!=NULL) { + struct userdata_struct *userdata; + size_t size = sizeof(struct userdata_struct) + sizeof(BOOL); + + if((userdata = (struct userdata_struct *)malloc(size)) == NULL) { + DEBUG(0,("release_1d_name: malloc fail.\n")); + return; + } + + userdata->copy_fn = NULL; + userdata->free_fn = NULL; + userdata->userdata_len = sizeof(BOOL); + memcpy((char *)userdata->data, &force_new_election, sizeof(BOOL)); + + release_name(subrec, namerec, + unbecome_local_master_success, + unbecome_local_master_fail, + userdata); + + zero_free(userdata, size); + } } /******************************************************************* @@ -238,11 +234,11 @@ static void release_msbrowse_name_success(struct subnet_record *subrec, struct nmb_name *released_name, struct in_addr released_ip) { - DEBUG(4,("release_msbrowse_name_success: Released name %s on subnet %s\n.", - nmb_namestr(released_name), subrec->subnet_name )); + DEBUG(4,("release_msbrowse_name_success: Released name %s on subnet %s\n.", + nmb_namestr(released_name), subrec->subnet_name )); - /* Remove the permanent MSBROWSE name added into the unicast subnet. */ - remove_permanent_name_from_unicast( subrec, released_name); + /* Remove the permanent MSBROWSE name added into the unicast subnet. */ + remove_permanent_name_from_unicast( subrec, released_name); } /******************************************************************* @@ -253,18 +249,18 @@ static void release_msbrowse_name_fail( struct subnet_record *subrec, struct response_record *rrec, struct nmb_name *fail_name) { - struct name_record *namerec; + struct name_record *namerec; - DEBUG(4,("release_msbrowse_name_fail: Failed to release name %s on subnet %s\n.", - nmb_namestr(fail_name), subrec->subnet_name )); + DEBUG(4,("release_msbrowse_name_fail: Failed to release name %s on subnet %s\n.", + nmb_namestr(fail_name), subrec->subnet_name )); - /* Release the name anyway. */ - namerec = find_name_on_subnet(subrec, fail_name, FIND_SELF_NAME); - if(namerec) - remove_name_from_namelist(subrec, namerec); + /* Release the name anyway. */ + namerec = find_name_on_subnet(subrec, fail_name, FIND_SELF_NAME); + if(namerec) + remove_name_from_namelist(subrec, namerec); - /* Remove the permanent MSBROWSE name added into the unicast subnet. */ - remove_permanent_name_from_unicast( subrec, fail_name); + /* Remove the permanent MSBROWSE name added into the unicast subnet. */ + remove_permanent_name_from_unicast( subrec, fail_name); } /******************************************************************* @@ -275,50 +271,48 @@ static void release_msbrowse_name_fail( struct subnet_record *subrec, void unbecome_local_master_browser(struct subnet_record *subrec, struct work_record *work, BOOL force_new_election) { - struct name_record *namerec; - struct nmb_name nmbname; + struct name_record *namerec; + struct nmb_name nmbname; /* Sanity check. */ - DEBUG(2,("unbecome_local_master_browser: unbecoming local master for workgroup %s \ + DEBUG(2,("unbecome_local_master_browser: unbecoming local master for workgroup %s \ on subnet %s\n",work->work_group, subrec->subnet_name)); - if(find_server_in_workgroup( work, global_myname()) == NULL) - { - DEBUG(0,("unbecome_local_master_browser: Error - cannot find server %s \ + if(find_server_in_workgroup( work, global_myname()) == NULL) { + DEBUG(0,("unbecome_local_master_browser: Error - cannot find server %s \ in workgroup %s on subnet %s\n", - global_myname(), work->work_group, subrec->subnet_name)); - work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE; - return; - } + global_myname(), work->work_group, subrec->subnet_name)); + work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE; + return; + } - /* Set the state to unbecoming. */ - work->mst_state = MST_UNBECOMING_MASTER; - - /* - * Release the WORKGROUP<1d> name asap to allow another machine to - * claim it. - */ - - release_1d_name( subrec, work->work_group, force_new_election); - - /* Deregister any browser names we may have. */ - make_nmb_name(&nmbname, MSBROWSE, 0x1); - if((namerec = find_name_on_subnet( subrec, &nmbname, FIND_SELF_NAME))!=NULL) - { - release_name(subrec, namerec, - release_msbrowse_name_success, - release_msbrowse_name_fail, - NULL); - } - - /* - * Ensure we have sent and processed these release packets - * before returning - we don't want to process any election - * packets before dealing with the 1d release. - */ - - retransmit_or_expire_response_records(time(NULL)); + /* Set the state to unbecoming. */ + work->mst_state = MST_UNBECOMING_MASTER; + + /* + * Release the WORKGROUP<1d> name asap to allow another machine to + * claim it. + */ + + release_1d_name( subrec, work->work_group, force_new_election); + + /* Deregister any browser names we may have. */ + make_nmb_name(&nmbname, MSBROWSE, 0x1); + if((namerec = find_name_on_subnet( subrec, &nmbname, FIND_SELF_NAME))!=NULL) { + release_name(subrec, namerec, + release_msbrowse_name_success, + release_msbrowse_name_fail, + NULL); + } + + /* + * Ensure we have sent and processed these release packets + * before returning - we don't want to process any election + * packets before dealing with the 1d release. + */ + + retransmit_or_expire_response_records(time(NULL)); } /**************************************************************************** @@ -332,104 +326,107 @@ static void become_local_master_stage2(struct subnet_record *subrec, uint16 nb_flags, int ttl, struct in_addr registered_ip) { - int i = 0; - struct server_record *sl; - struct work_record *work = find_workgroup_on_subnet( subrec, registered_name->name); - struct server_record *servrec; - - if(!work) - { - DEBUG(0,("become_local_master_stage2: Error - cannot find \ -workgroup %s on subnet %s\n", registered_name->name, subrec->subnet_name)); - return; - } - - if((servrec = find_server_in_workgroup( work, global_myname())) == NULL) - { - DEBUG(0,("become_local_master_stage2: Error - cannot find server %s \ + int i = 0; + struct server_record *sl; + struct work_record *work; + struct server_record *servrec; + nstring regname; + + pull_ascii_nstring(regname, registered_name->name); + work = find_workgroup_on_subnet( subrec, regname); + + if(!work) { + DEBUG(0,("become_local_master_stage2: Error - cannot find \ +workgroup %s on subnet %s\n", regname, subrec->subnet_name)); + return; + } + + if((servrec = find_server_in_workgroup( work, global_myname())) == NULL) { + DEBUG(0,("become_local_master_stage2: Error - cannot find server %s \ in workgroup %s on subnet %s\n", - global_myname(), registered_name->name, subrec->subnet_name)); - work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE; - return; - } + global_myname(), regname, subrec->subnet_name)); + work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE; + return; + } - DEBUG(3,("become_local_master_stage2: registered as master browser for workgroup %s \ + DEBUG(3,("become_local_master_stage2: registered as master browser for workgroup %s \ on subnet %s\n", work->work_group, subrec->subnet_name)); - work->mst_state = MST_BROWSER; /* registering WORKGROUP(1d) succeeded */ - - /* update our server status */ - servrec->serv.type |= SV_TYPE_MASTER_BROWSER; - servrec->serv.type &= ~SV_TYPE_POTENTIAL_BROWSER; - - /* Tell the namelist writer to write out a change. */ - subrec->work_changed = True; - - /* Add this name to the workgroup as local master browser. */ - set_workgroup_local_master_browser_name( work, global_myname()); - - /* Count the number of servers we have on our list. If it's - less than 10 (just a heuristic) request the servers - to announce themselves. - */ - for( sl = work->serverlist; sl != NULL; sl = sl->next) - i++; - - if (i < 10) - { - /* Ask all servers on our local net to announce to us. */ - broadcast_announce_request(subrec, work); - } - - /* - * Now we are a local master on a broadcast subnet, we need to add - * the WORKGROUP<1d> name to the unicast subnet so that we can answer - * unicast requests sent to this name. We can create this name directly on - * the unicast subnet as a WINS server always returns true when registering - * this name, and discards the registration. We use the number of IP - * addresses registered to this name as a reference count, as we - * remove this broadcast subnet IP address from it when we stop becoming a local - * master browser for this broadcast subnet. - */ - - insert_permanent_name_into_unicast( subrec, registered_name, nb_flags); - - /* Reset the announce master browser timer so that we try and tell a domain - master browser as soon as possible that we are a local master browser. */ - reset_announce_timer(); - - if( DEBUGLVL( 0 ) ) - { - dbgtext( "*****\n\n" ); - dbgtext( "Samba name server %s ", global_myname() ); - dbgtext( "is now a local master browser " ); - dbgtext( "for workgroup %s ", work->work_group ); - dbgtext( "on subnet %s\n\n*****\n", subrec->subnet_name ); - } - + work->mst_state = MST_BROWSER; /* registering WORKGROUP(1d) succeeded */ + + /* update our server status */ + servrec->serv.type |= SV_TYPE_MASTER_BROWSER; + servrec->serv.type &= ~SV_TYPE_POTENTIAL_BROWSER; + + /* Tell the namelist writer to write out a change. */ + subrec->work_changed = True; + + /* Add this name to the workgroup as local master browser. */ + set_workgroup_local_master_browser_name( work, global_myname()); + + /* Count the number of servers we have on our list. If it's + less than 10 (just a heuristic) request the servers + to announce themselves. + */ + for( sl = work->serverlist; sl != NULL; sl = sl->next) + i++; + + if (i < 10) { + /* Ask all servers on our local net to announce to us. */ + broadcast_announce_request(subrec, work); + } + + /* + * Now we are a local master on a broadcast subnet, we need to add + * the WORKGROUP<1d> name to the unicast subnet so that we can answer + * unicast requests sent to this name. We can create this name directly on + * the unicast subnet as a WINS server always returns true when registering + * this name, and discards the registration. We use the number of IP + * addresses registered to this name as a reference count, as we + * remove this broadcast subnet IP address from it when we stop becoming a local + * master browser for this broadcast subnet. + */ + + insert_permanent_name_into_unicast( subrec, registered_name, nb_flags); + + /* Reset the announce master browser timer so that we try and tell a domain + master browser as soon as possible that we are a local master browser. */ + reset_announce_timer(); + + if( DEBUGLVL( 0 ) ) { + dbgtext( "*****\n\n" ); + dbgtext( "Samba name server %s ", global_myname() ); + dbgtext( "is now a local master browser " ); + dbgtext( "for workgroup %s ", work->work_group ); + dbgtext( "on subnet %s\n\n*****\n", subrec->subnet_name ); + } } /**************************************************************************** Failed to register the WORKGROUP<1d> name. ****************************************************************************/ + static void become_local_master_fail2(struct subnet_record *subrec, struct response_record *rrec, struct nmb_name *fail_name) { - struct work_record *work = find_workgroup_on_subnet( subrec, fail_name->name); + nstring failname; + struct work_record *work; - DEBUG(0,("become_local_master_fail2: failed to register name %s on subnet %s. \ + DEBUG(0,("become_local_master_fail2: failed to register name %s on subnet %s. \ Failed to become a local master browser.\n", nmb_namestr(fail_name), subrec->subnet_name)); - if(!work) - { - DEBUG(0,("become_local_master_fail2: Error - cannot find \ -workgroup %s on subnet %s\n", fail_name->name, subrec->subnet_name)); - return; - } + pull_ascii_nstring(failname, fail_name->name); + work = find_workgroup_on_subnet( subrec, failname); - /* Roll back all the way by calling unbecome_local_master_browser(). */ - unbecome_local_master_browser(subrec, work, False); + if(!work) { + DEBUG(0,("become_local_master_fail2: Error - cannot find \ +workgroup %s on subnet %s\n", failname, subrec->subnet_name)); + return; + } + + /* Roll back all the way by calling unbecome_local_master_browser(). */ + unbecome_local_master_browser(subrec, work, False); } /**************************************************************************** @@ -442,35 +439,34 @@ static void become_local_master_stage1(struct subnet_record *subrec, uint16 nb_flags, int ttl, struct in_addr registered_ip) { - char *work_name = userdata->data; - struct work_record *work = find_workgroup_on_subnet( subrec, work_name); - - if(!work) - { - DEBUG(0,("become_local_master_stage1: Error - cannot find \ -workgroup %s on subnet %s\n", work_name, subrec->subnet_name)); - return; - } - - DEBUG(3,("become_local_master_stage1: go to stage 2: register the %s<1d> name.\n", - work->work_group)); - - work->mst_state = MST_MSB; /* Registering MSBROWSE was successful. */ - - /* - * We registered the MSBROWSE name on a broadcast subnet, now need to add - * the MSBROWSE name to the unicast subnet so that we can answer - * unicast requests sent to this name. We create this name directly on - * the unicast subnet. - */ - - insert_permanent_name_into_unicast( subrec, registered_name, nb_flags); - - /* Attempt to register the WORKGROUP<1d> name. */ - register_name(subrec, work->work_group,0x1d,samba_nb_type, - become_local_master_stage2, - become_local_master_fail2, - NULL); + char *work_name = userdata->data; + struct work_record *work = find_workgroup_on_subnet( subrec, work_name); + + if(!work) { + DEBUG(0,("become_local_master_stage1: Error - cannot find \ + %s on subnet %s\n", work_name, subrec->subnet_name)); + return; + } + + DEBUG(3,("become_local_master_stage1: go to stage 2: register the %s<1d> name.\n", + work->work_group)); + + work->mst_state = MST_MSB; /* Registering MSBROWSE was successful. */ + + /* + * We registered the MSBROWSE name on a broadcast subnet, now need to add + * the MSBROWSE name to the unicast subnet so that we can answer + * unicast requests sent to this name. We create this name directly on + * the unicast subnet. + */ + + insert_permanent_name_into_unicast( subrec, registered_name, nb_flags); + + /* Attempt to register the WORKGROUP<1d> name. */ + register_name(subrec, work->work_group,0x1d,samba_nb_type, + become_local_master_stage2, + become_local_master_fail2, + NULL); } /**************************************************************************** @@ -481,29 +477,27 @@ static void become_local_master_fail1(struct subnet_record *subrec, struct response_record *rrec, struct nmb_name *fail_name) { - char *work_name = rrec->userdata->data; - struct work_record *work = find_workgroup_on_subnet(subrec, work_name); + char *work_name = rrec->userdata->data; + struct work_record *work = find_workgroup_on_subnet(subrec, work_name); - if(!work) - { - DEBUG(0,("become_local_master_fail1: Error - cannot find \ + if(!work) { + DEBUG(0,("become_local_master_fail1: Error - cannot find \ workgroup %s on subnet %s\n", work_name, subrec->subnet_name)); - return; - } + return; + } - if(find_server_in_workgroup(work, global_myname()) == NULL) - { - DEBUG(0,("become_local_master_fail1: Error - cannot find server %s \ + if(find_server_in_workgroup(work, global_myname()) == NULL) { + DEBUG(0,("become_local_master_fail1: Error - cannot find server %s \ in workgroup %s on subnet %s\n", - global_myname(), work->work_group, subrec->subnet_name)); - return; - } + global_myname(), work->work_group, subrec->subnet_name)); + return; + } - reset_workgroup_state( subrec, work->work_group, False ); + reset_workgroup_state( subrec, work->work_group, False ); - DEBUG(0,("become_local_master_fail1: Failed to become a local master browser for \ + DEBUG(0,("become_local_master_fail1: Failed to become a local master browser for \ workgroup %s on subnet %s. Couldn't register name %s.\n", - work->work_group, subrec->subnet_name, nmb_namestr(fail_name))); + work->work_group, subrec->subnet_name, nmb_namestr(fail_name))); } /****************************************************************** @@ -517,61 +511,57 @@ workgroup %s on subnet %s. Couldn't register name %s.\n", void become_local_master_browser(struct subnet_record *subrec, struct work_record *work) { - struct userdata_struct *userdata; - size_t size = sizeof(struct userdata_struct) + sizeof(fstring) + 1; - - /* Sanity check. */ - if (!lp_local_master()) - { - DEBUG(0,("become_local_master_browser: Samba not configured as a local master browser.\n")); - return; - } - - if(!AM_POTENTIAL_MASTER_BROWSER(work)) - { - DEBUG(2,("become_local_master_browser: Awaiting potential browser state. Current state is %d\n", - work->mst_state )); - return; - } - - if(find_server_in_workgroup( work, global_myname()) == NULL) - { - DEBUG(0,("become_local_master_browser: Error - cannot find server %s \ + struct userdata_struct *userdata; + size_t size = sizeof(struct userdata_struct) + sizeof(fstring) + 1; + + /* Sanity check. */ + if (!lp_local_master()) { + DEBUG(0,("become_local_master_browser: Samba not configured as a local master browser.\n")); + return; + } + + if(!AM_POTENTIAL_MASTER_BROWSER(work)) { + DEBUG(2,("become_local_master_browser: Awaiting potential browser state. Current state is %d\n", + work->mst_state )); + return; + } + + if(find_server_in_workgroup( work, global_myname()) == NULL) { + DEBUG(0,("become_local_master_browser: Error - cannot find server %s \ in workgroup %s on subnet %s\n", - global_myname(), work->work_group, subrec->subnet_name)); - return; - } + global_myname(), work->work_group, subrec->subnet_name)); + return; + } - DEBUG(2,("become_local_master_browser: Starting to become a master browser for workgroup \ + DEBUG(2,("become_local_master_browser: Starting to become a master browser for workgroup \ %s on subnet %s\n", work->work_group, subrec->subnet_name)); - DEBUG(3,("become_local_master_browser: first stage - attempt to register ^1^2__MSBROWSE__^2^1\n")); - work->mst_state = MST_BACKUP; /* an election win was successful */ + DEBUG(3,("become_local_master_browser: first stage - attempt to register ^1^2__MSBROWSE__^2^1\n")); + work->mst_state = MST_BACKUP; /* an election win was successful */ - work->ElectionCriterion |= 0x5; + work->ElectionCriterion |= 0x5; - /* Tell the namelist writer to write out a change. */ - subrec->work_changed = True; + /* Tell the namelist writer to write out a change. */ + subrec->work_changed = True; - /* Setup the userdata_struct. */ - if((userdata = (struct userdata_struct *)malloc(size)) == NULL) - { - DEBUG(0,("become_local_master_browser: malloc fail.\n")); - return; - } + /* Setup the userdata_struct. */ + if((userdata = (struct userdata_struct *)malloc(size)) == NULL) { + DEBUG(0,("become_local_master_browser: malloc fail.\n")); + return; + } - userdata->copy_fn = NULL; - userdata->free_fn = NULL; - userdata->userdata_len = strlen(work->work_group)+1; - overmalloc_safe_strcpy(userdata->data, work->work_group, size - sizeof(*userdata) - 1); + userdata->copy_fn = NULL; + userdata->free_fn = NULL; + userdata->userdata_len = strlen(work->work_group)+1; + overmalloc_safe_strcpy(userdata->data, work->work_group, size - sizeof(*userdata) - 1); - /* Register the special browser group name. */ - register_name(subrec, MSBROWSE, 0x01, samba_nb_type|NB_GROUP, - become_local_master_stage1, - become_local_master_fail1, - userdata); + /* Register the special browser group name. */ + register_name(subrec, MSBROWSE, 0x01, samba_nb_type|NB_GROUP, + become_local_master_stage1, + become_local_master_fail1, + userdata); - zero_free(userdata, size); + zero_free(userdata, size); } /*************************************************************** @@ -583,7 +573,7 @@ in workgroup %s on subnet %s\n", void set_workgroup_local_master_browser_name( struct work_record *work, const char *newname) { - DEBUG(5,("set_workgroup_local_master_browser_name: setting local master name to '%s' \ + DEBUG(5,("set_workgroup_local_master_browser_name: setting local master name to '%s' \ for workgroup %s.\n", newname, work->work_group )); #if 0 @@ -600,5 +590,5 @@ local_master_browser_name for workgroup %s to workgroup name.\n", } #endif - fstrcpy(work->local_master_browser_name, newname); + nstrcpy(work->local_master_browser_name, newname); } diff --git a/source3/nmbd/nmbd_browserdb.c b/source3/nmbd/nmbd_browserdb.c index 4a302ddfd4..443edf599d 100644 --- a/source3/nmbd/nmbd_browserdb.c +++ b/source3/nmbd/nmbd_browserdb.c @@ -80,8 +80,8 @@ void update_browser_death_time( struct browse_cache_record *browc ) * * ************************************************************************** ** */ -struct browse_cache_record *create_browser_in_lmb_cache( char *work_name, - char *browser_name, +struct browse_cache_record *create_browser_in_lmb_cache( const char *work_name, + const char *browser_name, struct in_addr ip ) { struct browse_cache_record *browc; @@ -106,8 +106,8 @@ struct browse_cache_record *create_browser_in_lmb_cache( char *work_name, /* Allow the new lmb to miss an announce period before we remove it. */ browc->death_time = now + ( (CHECK_TIME_MST_ANNOUNCE + 2) * 60 ); - pstrcpy( browc->lmb_name, browser_name); - pstrcpy( browc->work_group, work_name); + nstrcpy( browc->lmb_name, browser_name); + nstrcpy( browc->work_group, work_name); strupper_m( browc->lmb_name ); strupper_m( browc->work_group ); @@ -134,7 +134,7 @@ struct browse_cache_record *create_browser_in_lmb_cache( char *work_name, * * ************************************************************************** ** */ -struct browse_cache_record *find_browser_in_lmb_cache( char *browser_name ) +struct browse_cache_record *find_browser_in_lmb_cache( const char *browser_name ) { struct browse_cache_record *browc; diff --git a/source3/nmbd/nmbd_browsesync.c b/source3/nmbd/nmbd_browsesync.c index 26d4735744..6cde88651f 100644 --- a/source3/nmbd/nmbd_browsesync.c +++ b/source3/nmbd/nmbd_browsesync.c @@ -3,7 +3,7 @@ NBT netbios routines and daemon - version 2 Copyright (C) Andrew Tridgell 1994-1998 Copyright (C) Luke Kenneth Casson Leighton 1994-1998 - Copyright (C) Jeremy Allison 1994-1998 + Copyright (C) Jeremy Allison 1994-2003 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -29,74 +29,70 @@ extern ubi_dlList lmb_browserlist[]; /**************************************************************************** As a domain master browser, do a sync with a local master browser. **************************************************************************/ + static void sync_with_lmb(struct browse_cache_record *browc) { - struct work_record *work; - - if( !(work = find_workgroup_on_subnet(unicast_subnet, browc->work_group)) ) - { - if( DEBUGLVL( 0 ) ) - { - dbgtext( "sync_with_lmb:\n" ); - dbgtext( "Failed to get a workgroup for a local master browser " ); - dbgtext( "cache entry workgroup " ); - dbgtext( "%s, server %s\n", browc->work_group, browc->lmb_name ); - } - return; - } + struct work_record *work; - /* We should only be doing this if we are a domain master browser for - the given workgroup. Ensure this is so. */ - - if(!AM_DOMAIN_MASTER_BROWSER(work)) - { - if( DEBUGLVL( 0 ) ) - { - dbgtext( "sync_with_lmb:\n" ); - dbgtext( "We are trying to sync with a local master browser " ); - dbgtext( "%s for workgroup %s\n", browc->lmb_name, browc->work_group ); - dbgtext( "and we are not a domain master browser on this workgroup.\n" ); - dbgtext( "Error!\n" ); - } - return; - } + if( !(work = find_workgroup_on_subnet(unicast_subnet, browc->work_group)) ) { + if( DEBUGLVL( 0 ) ) { + dbgtext( "sync_with_lmb:\n" ); + dbgtext( "Failed to get a workgroup for a local master browser " ); + dbgtext( "cache entry workgroup " ); + dbgtext( "%s, server %s\n", browc->work_group, browc->lmb_name ); + } + return; + } - if( DEBUGLVL( 2 ) ) - { - dbgtext( "sync_with_lmb:\n" ); - dbgtext( "Initiating sync with local master browser " ); - dbgtext( "%s<0x20> at IP %s ", browc->lmb_name, inet_ntoa(browc->ip) ); - dbgtext( "for workgroup %s\n", browc->work_group ); - } + /* We should only be doing this if we are a domain master browser for + the given workgroup. Ensure this is so. */ - sync_browse_lists(work, browc->lmb_name, 0x20, browc->ip, True, True); + if(!AM_DOMAIN_MASTER_BROWSER(work)) { + if( DEBUGLVL( 0 ) ) { + dbgtext( "sync_with_lmb:\n" ); + dbgtext( "We are trying to sync with a local master browser " ); + dbgtext( "%s for workgroup %s\n", browc->lmb_name, browc->work_group ); + dbgtext( "and we are not a domain master browser on this workgroup.\n" ); + dbgtext( "Error!\n" ); + } + return; + } + + if( DEBUGLVL( 2 ) ) { + dbgtext( "sync_with_lmb:\n" ); + dbgtext( "Initiating sync with local master browser " ); + dbgtext( "%s<0x20> at IP %s ", browc->lmb_name, inet_ntoa(browc->ip) ); + dbgtext( "for workgroup %s\n", browc->work_group ); + } + + sync_browse_lists(work, browc->lmb_name, 0x20, browc->ip, True, True); - browc->sync_time += (CHECK_TIME_DMB_TO_LMB_SYNC * 60); + browc->sync_time += (CHECK_TIME_DMB_TO_LMB_SYNC * 60); } /**************************************************************************** Sync or expire any local master browsers. **************************************************************************/ + void dmb_expire_and_sync_browser_lists(time_t t) { - static time_t last_run = 0; - struct browse_cache_record *browc; + static time_t last_run = 0; + struct browse_cache_record *browc; - /* Only do this every 20 seconds. */ - if (t - last_run < 20) - return; + /* Only do this every 20 seconds. */ + if (t - last_run < 20) + return; - last_run = t; + last_run = t; - expire_lmb_browsers(t); + expire_lmb_browsers(t); - for( browc = (struct browse_cache_record *)ubi_dlFirst( lmb_browserlist ); - browc; - browc = (struct browse_cache_record *)ubi_dlNext( browc ) ) - { - if (browc->sync_time < t) - sync_with_lmb(browc); - } + for( browc = (struct browse_cache_record *)ubi_dlFirst( lmb_browserlist ); + browc; + browc = (struct browse_cache_record *)ubi_dlNext( browc ) ) { + if (browc->sync_time < t) + sync_with_lmb(browc); + } } /**************************************************************************** @@ -105,46 +101,43 @@ As a local master browser, send an announce packet to the domain master browser. static void announce_local_master_browser_to_domain_master_browser( struct work_record *work) { - pstring outbuf; - fstring myname; - char *p; - - if(ismyip(work->dmb_addr)) - { - if( DEBUGLVL( 2 ) ) - { - dbgtext( "announce_local_master_browser_to_domain_master_browser:\n" ); - dbgtext( "We are both a domain and a local master browser for " ); - dbgtext( "workgroup %s. ", work->work_group ); - dbgtext( "Do not announce to ourselves.\n" ); - } - return; - } + pstring outbuf; + fstring myname; + char *p; + + if(ismyip(work->dmb_addr)) { + if( DEBUGLVL( 2 ) ) { + dbgtext( "announce_local_master_browser_to_domain_master_browser:\n" ); + dbgtext( "We are both a domain and a local master browser for " ); + dbgtext( "workgroup %s. ", work->work_group ); + dbgtext( "Do not announce to ourselves.\n" ); + } + return; + } - memset(outbuf,'\0',sizeof(outbuf)); - p = outbuf; - SCVAL(p,0,ANN_MasterAnnouncement); - p++; + memset(outbuf,'\0',sizeof(outbuf)); + p = outbuf; + SCVAL(p,0,ANN_MasterAnnouncement); + p++; - fstrcpy(myname, global_myname()); - strupper_m(myname); - myname[15]='\0'; - push_pstring_base(p, myname, outbuf); + fstrcpy(myname, global_myname()); + strupper_m(myname); + myname[15]='\0'; + /* The call below does CH_UNIX -> CH_DOS conversion. JRA */ + push_pstring_base(p, myname, outbuf); - p = skip_string(p,1); + p = skip_string(p,1); - if( DEBUGLVL( 4 ) ) - { - dbgtext( "announce_local_master_browser_to_domain_master_browser:\n" ); - dbgtext( "Sending local master announce to " ); - dbgtext( "%s for workgroup %s.\n", nmb_namestr(&work->dmb_name), - work->work_group ); - } + if( DEBUGLVL( 4 ) ) { + dbgtext( "announce_local_master_browser_to_domain_master_browser:\n" ); + dbgtext( "Sending local master announce to " ); + dbgtext( "%s for workgroup %s.\n", nmb_namestr(&work->dmb_name), + work->work_group ); + } - send_mailslot(True, BROWSE_MAILSLOT, outbuf,PTR_DIFF(p,outbuf), + send_mailslot(True, BROWSE_MAILSLOT, outbuf,PTR_DIFF(p,outbuf), global_myname(), 0x0, work->dmb_name.name, 0x0, work->dmb_addr, FIRST_SUBNET->myip, DGRAM_PORT); - } /**************************************************************************** @@ -153,17 +146,19 @@ As a local master browser, do a sync with a domain master browser. static void sync_with_dmb(struct work_record *work) { - if( DEBUGLVL( 2 ) ) - { - dbgtext( "sync_with_dmb:\n" ); - dbgtext( "Initiating sync with domain master browser " ); - dbgtext( "%s ", nmb_namestr(&work->dmb_name) ); - dbgtext( "at IP %s ", inet_ntoa(work->dmb_addr) ); - dbgtext( "for workgroup %s\n", work->work_group ); - } + nstring dmb_name; + + if( DEBUGLVL( 2 ) ) { + dbgtext( "sync_with_dmb:\n" ); + dbgtext( "Initiating sync with domain master browser " ); + dbgtext( "%s ", nmb_namestr(&work->dmb_name) ); + dbgtext( "at IP %s ", inet_ntoa(work->dmb_addr) ); + dbgtext( "for workgroup %s\n", work->work_group ); + } - sync_browse_lists(work, work->dmb_name.name, work->dmb_name.name_type, - work->dmb_addr, False, True); + pull_ascii_nstring(dmb_name, work->dmb_name.name); + sync_browse_lists(work, dmb_name, work->dmb_name.name_type, + work->dmb_addr, False, True); } /**************************************************************************** @@ -175,78 +170,69 @@ static void domain_master_node_status_success(struct subnet_record *subrec, struct res_rec *answers, struct in_addr from_ip) { - struct work_record *work = find_workgroup_on_subnet( subrec, userdata->data); - - if( work == NULL ) - { - if( DEBUGLVL( 0 ) ) - { - dbgtext( "domain_master_node_status_success:\n" ); - dbgtext( "Unable to find workgroup " ); - dbgtext( "%s on subnet %s.\n", userdata->data, subrec->subnet_name ); - } - return; - } + struct work_record *work = find_workgroup_on_subnet( subrec, userdata->data); - if( DEBUGLVL( 3 ) ) - { - dbgtext( "domain_master_node_status_success:\n" ); - dbgtext( "Success in node status for workgroup " ); - dbgtext( "%s from ip %s\n", work->work_group, inet_ntoa(from_ip) ); - } + if( work == NULL ) { + if( DEBUGLVL( 0 ) ) { + dbgtext( "domain_master_node_status_success:\n" ); + dbgtext( "Unable to find workgroup " ); + dbgtext( "%s on subnet %s.\n", userdata->data, subrec->subnet_name ); + } + return; + } + + if( DEBUGLVL( 3 ) ) { + dbgtext( "domain_master_node_status_success:\n" ); + dbgtext( "Success in node status for workgroup " ); + dbgtext( "%s from ip %s\n", work->work_group, inet_ntoa(from_ip) ); + } /* Go through the list of names found at answers->rdata and look for the first SERVER<0x20> name. */ - if(answers->rdata != NULL) - { - char *p = answers->rdata; - int numnames = CVAL(p, 0); + if(answers->rdata != NULL) { + char *p = answers->rdata; + int numnames = CVAL(p, 0); - p += 1; + p += 1; - while (numnames--) - { - char qname[17]; - uint16 nb_flags; - int name_type; + while (numnames--) { + nstring qname; + uint16 nb_flags; + int name_type; - StrnCpy(qname,p,15); - name_type = CVAL(p,15); - nb_flags = get_nb_flags(&p[16]); - trim_string(qname,NULL," "); + pull_ascii_nstring(qname, p); + name_type = CVAL(p,15); + nb_flags = get_nb_flags(&p[16]); + trim_char(qname,'\0',' '); - p += 18; + p += 18; - if(!(nb_flags & NB_GROUP) && (name_type == 0x20)) - { - struct nmb_name nmbname; + if(!(nb_flags & NB_GROUP) && (name_type == 0x20)) { + struct nmb_name nmbname; - make_nmb_name(&nmbname, qname, name_type); + make_nmb_name(&nmbname, qname, name_type); - /* Copy the dmb name and IP address - into the workgroup struct. */ + /* Copy the dmb name and IP address + into the workgroup struct. */ - work->dmb_name = nmbname; - putip((char *)&work->dmb_addr, &from_ip); + work->dmb_name = nmbname; + putip((char *)&work->dmb_addr, &from_ip); - /* Do the local master browser announcement to the domain - master browser name and IP. */ - announce_local_master_browser_to_domain_master_browser( work ); + /* Do the local master browser announcement to the domain + master browser name and IP. */ + announce_local_master_browser_to_domain_master_browser( work ); - /* Now synchronise lists with the domain master browser. */ - sync_with_dmb(work); - break; - } - } - } - else - if( DEBUGLVL( 0 ) ) - { - dbgtext( "domain_master_node_status_success:\n" ); - dbgtext( "Failed to find a SERVER<0x20> name in reply from IP " ); - dbgtext( "%s.\n", inet_ntoa(from_ip) ); - } + /* Now synchronise lists with the domain master browser. */ + sync_with_dmb(work); + break; + } + } + } else if( DEBUGLVL( 0 ) ) { + dbgtext( "domain_master_node_status_success:\n" ); + dbgtext( "Failed to find a SERVER<0x20> name in reply from IP " ); + dbgtext( "%s.\n", inet_ntoa(from_ip) ); + } } /**************************************************************************** @@ -256,16 +242,15 @@ static void domain_master_node_status_success(struct subnet_record *subrec, static void domain_master_node_status_fail(struct subnet_record *subrec, struct response_record *rrec) { - struct userdata_struct *userdata = rrec->userdata; - - if( DEBUGLVL( 0 ) ) - { - dbgtext( "domain_master_node_status_fail:\n" ); - dbgtext( "Doing a node status request to the domain master browser\n" ); - dbgtext( "for workgroup %s ", userdata ? userdata->data : "NULL" ); - dbgtext( "at IP %s failed.\n", inet_ntoa(rrec->packet->ip) ); - dbgtext( "Cannot sync browser lists.\n" ); - } + struct userdata_struct *userdata = rrec->userdata; + + if( DEBUGLVL( 0 ) ) { + dbgtext( "domain_master_node_status_fail:\n" ); + dbgtext( "Doing a node status request to the domain master browser\n" ); + dbgtext( "for workgroup %s ", userdata ? userdata->data : "NULL" ); + dbgtext( "at IP %s failed.\n", inet_ntoa(rrec->packet->ip) ); + dbgtext( "Cannot sync browser lists.\n" ); + } } /**************************************************************************** @@ -276,100 +261,99 @@ static void find_domain_master_name_query_success(struct subnet_record *subrec, struct userdata_struct *userdata_in, struct nmb_name *q_name, struct in_addr answer_ip, struct res_rec *rrec) { - /* - * Unfortunately, finding the IP address of the Domain Master Browser, - * as we have here, is not enough. We need to now do a sync to the - * SERVERNAME<0x20> NetBIOS name, as only recent NT servers will - * respond to the SMBSERVER name. To get this name from IP - * address we do a Node status request, and look for the first - * NAME<0x20> in the response, and take that as the server name. - * We also keep a cache of the Domain Master Browser name for this - * workgroup in the Workgroup struct, so that if the same IP addess - * is returned every time, we don't need to do the node status - * request. - */ - - struct work_record *work; - struct nmb_name nmbname; - struct userdata_struct *userdata; - size_t size = sizeof(struct userdata_struct) + sizeof(fstring)+1; - - if( !(work = find_workgroup_on_subnet(subrec, q_name->name)) ) - { - if( DEBUGLVL( 0 ) ) - { - dbgtext( "find_domain_master_name_query_success:\n" ); - dbgtext( "Failed to find workgroup %s\n", q_name->name ); - } - return; + /* + * Unfortunately, finding the IP address of the Domain Master Browser, + * as we have here, is not enough. We need to now do a sync to the + * SERVERNAME<0x20> NetBIOS name, as only recent NT servers will + * respond to the SMBSERVER name. To get this name from IP + * address we do a Node status request, and look for the first + * NAME<0x20> in the response, and take that as the server name. + * We also keep a cache of the Domain Master Browser name for this + * workgroup in the Workgroup struct, so that if the same IP addess + * is returned every time, we don't need to do the node status + * request. + */ + + struct work_record *work; + struct nmb_name nmbname; + struct userdata_struct *userdata; + size_t size = sizeof(struct userdata_struct) + sizeof(fstring)+1; + nstring qname; + + pull_ascii_nstring(qname, q_name->name); + if( !(work = find_workgroup_on_subnet(subrec, qname)) ) { + if( DEBUGLVL( 0 ) ) { + dbgtext( "find_domain_master_name_query_success:\n" ); + dbgtext( "Failed to find workgroup %s\n", qname); + } + return; } /* First check if we already have a dmb for this workgroup. */ - if(!is_zero_ip(work->dmb_addr) && ip_equal(work->dmb_addr, answer_ip)) - { - /* Do the local master browser announcement to the domain - master browser name and IP. */ - announce_local_master_browser_to_domain_master_browser( work ); + if(!is_zero_ip(work->dmb_addr) && ip_equal(work->dmb_addr, answer_ip)) { + /* Do the local master browser announcement to the domain + master browser name and IP. */ + announce_local_master_browser_to_domain_master_browser( work ); - /* Now synchronise lists with the domain master browser. */ - sync_with_dmb(work); - return; - } - else - zero_ip(&work->dmb_addr); - - /* Now initiate the node status request. */ - - /* We used to use the name "*",0x0 here, but some Windows - * servers don't answer that name. However we *know* they - * have the name workgroup#1b (as we just looked it up). - * So do the node status request on this name instead. - * Found at LBL labs. JRA. - */ - - make_nmb_name(&nmbname,work->work_group,0x1b); - - /* Put the workgroup name into the userdata so we know - what workgroup we're talking to when the reply comes - back. */ - - /* Setup the userdata_struct - this is copied so we can use - a stack variable for this. */ - if((userdata = (struct userdata_struct *)malloc(size)) == NULL) - { - DEBUG(0, ("find_domain_master_name_query_success: malloc fail.\n")); - return; - } + /* Now synchronise lists with the domain master browser. */ + sync_with_dmb(work); + return; + } else { + zero_ip(&work->dmb_addr); + } - userdata->copy_fn = NULL; - userdata->free_fn = NULL; - userdata->userdata_len = strlen(work->work_group)+1; - overmalloc_safe_strcpy(userdata->data, work->work_group, size - sizeof(*userdata) - 1); + /* Now initiate the node status request. */ - node_status( subrec, &nmbname, answer_ip, - domain_master_node_status_success, - domain_master_node_status_fail, - userdata); + /* We used to use the name "*",0x0 here, but some Windows + * servers don't answer that name. However we *know* they + * have the name workgroup#1b (as we just looked it up). + * So do the node status request on this name instead. + * Found at LBL labs. JRA. + */ - zero_free(userdata, size); + make_nmb_name(&nmbname,work->work_group,0x1b); + + /* Put the workgroup name into the userdata so we know + what workgroup we're talking to when the reply comes + back. */ + + /* Setup the userdata_struct - this is copied so we can use + a stack variable for this. */ + + if((userdata = (struct userdata_struct *)malloc(size)) == NULL) { + DEBUG(0, ("find_domain_master_name_query_success: malloc fail.\n")); + return; + } + + userdata->copy_fn = NULL; + userdata->free_fn = NULL; + userdata->userdata_len = strlen(work->work_group)+1; + overmalloc_safe_strcpy(userdata->data, work->work_group, size - sizeof(*userdata) - 1); + + node_status( subrec, &nmbname, answer_ip, + domain_master_node_status_success, + domain_master_node_status_fail, + userdata); + + zero_free(userdata, size); } /**************************************************************************** Function called when a query for a WORKGROUP<1b> name fails. ****************************************************************************/ + static void find_domain_master_name_query_fail(struct subnet_record *subrec, struct response_record *rrec, struct nmb_name *question_name, int fail_code) { - if( DEBUGLVL( 0 ) ) - { - dbgtext( "find_domain_master_name_query_fail:\n" ); - dbgtext( "Unable to find the Domain Master Browser name " ); - dbgtext( "%s for the workgroup %s.\n", - nmb_namestr(question_name), question_name->name ); - dbgtext( "Unable to sync browse lists in this workgroup.\n" ); - } + if( DEBUGLVL( 0 ) ) { + dbgtext( "find_domain_master_name_query_fail:\n" ); + dbgtext( "Unable to find the Domain Master Browser name " ); + dbgtext( "%s for the workgroup %s.\n", + nmb_namestr(question_name), question_name->name ); + dbgtext( "Unable to sync browse lists in this workgroup.\n" ); + } } /**************************************************************************** @@ -381,27 +365,20 @@ full domain browse lists from it onto the given subnet. void announce_and_sync_with_domain_master_browser( struct subnet_record *subrec, struct work_record *work) { - struct nmb_name nmbname; - - /* Only do this if we are using a WINS server. */ - if(we_are_a_wins_client() == False) - { - if( DEBUGLVL( 10 ) ) - { - dbgtext( "announce_and_sync_with_domain_master_browser:\n" ); - dbgtext( "Ignoring, as we are not a WINS client.\n" ); - } - return; - } - - make_nmb_name(&nmbname,work->work_group,0x1b); + /* Only do this if we are using a WINS server. */ + if(we_are_a_wins_client() == False) { + if( DEBUGLVL( 10 ) ) { + dbgtext( "announce_and_sync_with_domain_master_browser:\n" ); + dbgtext( "Ignoring, as we are not a WINS client.\n" ); + } + return; + } - /* First, query for the WORKGROUP<1b> name from the WINS server. */ - query_name(unicast_subnet, nmbname.name, nmbname.name_type, + /* First, query for the WORKGROUP<1b> name from the WINS server. */ + query_name(unicast_subnet, work->work_group, 0x1b, find_domain_master_name_query_success, find_domain_master_name_query_fail, NULL); - } /**************************************************************************** @@ -421,89 +398,81 @@ static void get_domain_master_name_node_status_success(struct subnet_record *sub struct res_rec *answers, struct in_addr from_ip) { - struct work_record *work; - fstring server_name; + struct work_record *work; + fstring server_name; - server_name[0] = 0; + server_name[0] = 0; - if( DEBUGLVL( 3 ) ) - { - dbgtext( "get_domain_master_name_node_status_success:\n" ); - dbgtext( "Success in node status from ip %s\n", inet_ntoa(from_ip) ); - } + if( DEBUGLVL( 3 ) ) { + dbgtext( "get_domain_master_name_node_status_success:\n" ); + dbgtext( "Success in node status from ip %s\n", inet_ntoa(from_ip) ); + } - /* - * Go through the list of names found at answers->rdata and look for - * the first WORKGROUP<0x1b> name. - */ - - if(answers->rdata != NULL) - { - char *p = answers->rdata; - int numnames = CVAL(p, 0); - - p += 1; - - while (numnames--) - { - char qname[17]; - uint16 nb_flags; - int name_type; - - StrnCpy(qname,p,15); - name_type = CVAL(p,15); - nb_flags = get_nb_flags(&p[16]); - trim_string(qname,NULL," "); - - p += 18; - - if(!(nb_flags & NB_GROUP) && (name_type == 0x00) && - server_name[0] == 0) { - /* this is almost certainly the server netbios name */ - fstrcpy(server_name, qname); - continue; - } - - if(!(nb_flags & NB_GROUP) && (name_type == 0x1b)) - { - if( DEBUGLVL( 5 ) ) - { - dbgtext( "get_domain_master_name_node_status_success:\n" ); - dbgtext( "%s(%s) ", server_name, inet_ntoa(from_ip) ); - dbgtext( "is a domain master browser for workgroup " ); - dbgtext( "%s. Adding this name.\n", qname ); - } - - /* - * If we don't already know about this workgroup, add it - * to the workgroup list on the unicast_subnet. - */ - if((work = find_workgroup_on_subnet( subrec, qname)) == NULL) - { - struct nmb_name nmbname; - /* - * Add it - with an hour in the cache. - */ - if(!(work= create_workgroup_on_subnet(subrec, qname, 60*60))) - return; - - /* remember who the master is */ - fstrcpy(work->local_master_browser_name, server_name); - make_nmb_name(&nmbname, server_name, 0x20); - work->dmb_name = nmbname; - work->dmb_addr = from_ip; - } - break; - } - } - } - else - if( DEBUGLVL( 0 ) ) - { - dbgtext( "get_domain_master_name_node_status_success:\n" ); - dbgtext( "Failed to find a WORKGROUP<0x1b> name in reply from IP " ); - dbgtext( "%s.\n", inet_ntoa(from_ip) ); - } + /* + * Go through the list of names found at answers->rdata and look for + * the first WORKGROUP<0x1b> name. + */ + + if(answers->rdata != NULL) { + char *p = answers->rdata; + int numnames = CVAL(p, 0); + + p += 1; + + while (numnames--) { + nstring qname; + uint16 nb_flags; + int name_type; + + pull_ascii_nstring(qname, p); + name_type = CVAL(p,15); + nb_flags = get_nb_flags(&p[16]); + trim_char(qname,'\0',' '); + + p += 18; + + if(!(nb_flags & NB_GROUP) && (name_type == 0x00) && + server_name[0] == 0) { + /* this is almost certainly the server netbios name */ + fstrcpy(server_name, qname); + continue; + } + + if(!(nb_flags & NB_GROUP) && (name_type == 0x1b)) { + if( DEBUGLVL( 5 ) ) { + dbgtext( "get_domain_master_name_node_status_success:\n" ); + dbgtext( "%s(%s) ", server_name, inet_ntoa(from_ip) ); + dbgtext( "is a domain master browser for workgroup " ); + dbgtext( "%s. Adding this name.\n", qname ); + } + + /* + * If we don't already know about this workgroup, add it + * to the workgroup list on the unicast_subnet. + */ + + if((work = find_workgroup_on_subnet( subrec, qname)) == NULL) { + struct nmb_name nmbname; + /* + * Add it - with an hour in the cache. + */ + if(!(work= create_workgroup_on_subnet(subrec, qname, 60*60))) + return; + + /* remember who the master is */ + nstrcpy(work->local_master_browser_name, server_name); + make_nmb_name(&nmbname, server_name, 0x20); + work->dmb_name = nmbname; + work->dmb_addr = from_ip; + } + break; + } + } + } else if( DEBUGLVL( 0 ) ) { + dbgtext( "get_domain_master_name_node_status_success:\n" ); + dbgtext( "Failed to find a WORKGROUP<0x1b> name in reply from IP " ); + dbgtext( "%s.\n", inet_ntoa(from_ip) ); + } } /**************************************************************************** @@ -513,13 +482,12 @@ static void get_domain_master_name_node_status_success(struct subnet_record *sub static void get_domain_master_name_node_status_fail(struct subnet_record *subrec, struct response_record *rrec) { - if( DEBUGLVL( 0 ) ) - { - dbgtext( "get_domain_master_name_node_status_fail:\n" ); - dbgtext( "Doing a node status request to the domain master browser " ); - dbgtext( "at IP %s failed.\n", inet_ntoa(rrec->packet->ip) ); - dbgtext( "Cannot get workgroup name.\n" ); - } + if( DEBUGLVL( 0 ) ) { + dbgtext( "get_domain_master_name_node_status_fail:\n" ); + dbgtext( "Doing a node status request to the domain master browser " ); + dbgtext( "at IP %s failed.\n", inet_ntoa(rrec->packet->ip) ); + dbgtext( "Cannot get workgroup name.\n" ); + } } /**************************************************************************** @@ -530,58 +498,53 @@ static void find_all_domain_master_names_query_success(struct subnet_record *sub struct userdata_struct *userdata_in, struct nmb_name *q_name, struct in_addr answer_ip, struct res_rec *rrec) { - /* - * We now have a list of all the domain master browsers for all workgroups - * that have registered with the WINS server. Now do a node status request - * to each one and look for the first 1b name in the reply. This will be - * the workgroup name that we will add to the unicast subnet as a 'non-local' - * workgroup. - */ - - struct nmb_name nmbname; - struct in_addr send_ip; - int i; - - if( DEBUGLVL( 5 ) ) - { - dbgtext( "find_all_domain_master_names_query_succes:\n" ); - dbgtext( "Got answer from WINS server of %d ", (rrec->rdlength / 6) ); - dbgtext( "IP addresses for Domain Master Browsers.\n" ); - } + /* + * We now have a list of all the domain master browsers for all workgroups + * that have registered with the WINS server. Now do a node status request + * to each one and look for the first 1b name in the reply. This will be + * the workgroup name that we will add to the unicast subnet as a 'non-local' + * workgroup. + */ + + struct nmb_name nmbname; + struct in_addr send_ip; + int i; + + if( DEBUGLVL( 5 ) ) { + dbgtext( "find_all_domain_master_names_query_succes:\n" ); + dbgtext( "Got answer from WINS server of %d ", (rrec->rdlength / 6) ); + dbgtext( "IP addresses for Domain Master Browsers.\n" ); + } - for(i = 0; i < rrec->rdlength / 6; i++) - { - /* Initiate the node status requests. */ - make_nmb_name(&nmbname, "*", 0); - - putip((char *)&send_ip, (char *)&rrec->rdata[(i*6) + 2]); - - /* - * Don't send node status requests to ourself. - */ - - if(ismyip( send_ip )) - { - if( DEBUGLVL( 5 ) ) - { - dbgtext( "find_all_domain_master_names_query_succes:\n" ); - dbgtext( "Not sending node status to our own IP " ); - dbgtext( "%s.\n", inet_ntoa(send_ip) ); - } - continue; - } - - if( DEBUGLVL( 5 ) ) - { - dbgtext( "find_all_domain_master_names_query_success:\n" ); - dbgtext( "Sending node status request to IP %s.\n", inet_ntoa(send_ip) ); - } - - node_status( subrec, &nmbname, send_ip, - get_domain_master_name_node_status_success, - get_domain_master_name_node_status_fail, - NULL); - } + for(i = 0; i < rrec->rdlength / 6; i++) { + /* Initiate the node status requests. */ + make_nmb_name(&nmbname, "*", 0); + + putip((char *)&send_ip, (char *)&rrec->rdata[(i*6) + 2]); + + /* + * Don't send node status requests to ourself. + */ + + if(ismyip( send_ip )) { + if( DEBUGLVL( 5 ) ) { + dbgtext( "find_all_domain_master_names_query_succes:\n" ); + dbgtext( "Not sending node status to our own IP " ); + dbgtext( "%s.\n", inet_ntoa(send_ip) ); + } + continue; + } + + if( DEBUGLVL( 5 ) ) { + dbgtext( "find_all_domain_master_names_query_success:\n" ); + dbgtext( "Sending node status request to IP %s.\n", inet_ntoa(send_ip) ); + } + + node_status( subrec, &nmbname, send_ip, + get_domain_master_name_node_status_success, + get_domain_master_name_node_status_fail, + NULL); + } } /**************************************************************************** @@ -591,13 +554,12 @@ static void find_all_domain_master_names_query_fail(struct subnet_record *subrec struct response_record *rrec, struct nmb_name *question_name, int fail_code) { - if( DEBUGLVL( 10 ) ) - { - dbgtext( "find_domain_master_name_query_fail:\n" ); - dbgtext( "WINS server did not reply to a query for name " ); - dbgtext( "%s.\nThis means it ", nmb_namestr(question_name) ); - dbgtext( "is probably not a Samba 1.9.18 or above WINS server.\n" ); - } + if( DEBUGLVL( 10 ) ) { + dbgtext( "find_domain_master_name_query_fail:\n" ); + dbgtext( "WINS server did not reply to a query for name " ); + dbgtext( "%s.\nThis means it ", nmb_namestr(question_name) ); + dbgtext( "is probably not a Samba 1.9.18 or above WINS server.\n" ); + } } /**************************************************************************** @@ -608,43 +570,39 @@ static void find_all_domain_master_names_query_fail(struct subnet_record *subrec <1b> name in the reply - this is the workgroup name. Add this to the unicast subnet. This is expensive, so we only do this every 15 minutes. **************************************************************************/ + void collect_all_workgroup_names_from_wins_server(time_t t) { - static time_t lastrun = 0; - struct work_record *work; - struct nmb_name nmbname; - - /* Only do this if we are using a WINS server. */ - if(we_are_a_wins_client() == False) - return; - - /* Check to see if we are a domain master browser on the unicast subnet. */ - if((work = find_workgroup_on_subnet( unicast_subnet, lp_workgroup())) == NULL) - { - if( DEBUGLVL( 0 ) ) - { - dbgtext( "collect_all_workgroup_names_from_wins_server:\n" ); - dbgtext( "Cannot find my workgroup %s ", lp_workgroup() ); - dbgtext( "on subnet %s.\n", unicast_subnet->subnet_name ); - } - return; - } + static time_t lastrun = 0; + struct work_record *work; - if(!AM_DOMAIN_MASTER_BROWSER(work)) - return; + /* Only do this if we are using a WINS server. */ + if(we_are_a_wins_client() == False) + return; - if ((lastrun != 0) && (t < lastrun + (15 * 60))) - return; - - lastrun = t; + /* Check to see if we are a domain master browser on the unicast subnet. */ + if((work = find_workgroup_on_subnet( unicast_subnet, lp_workgroup())) == NULL) { + if( DEBUGLVL( 0 ) ) { + dbgtext( "collect_all_workgroup_names_from_wins_server:\n" ); + dbgtext( "Cannot find my workgroup %s ", lp_workgroup() ); + dbgtext( "on subnet %s.\n", unicast_subnet->subnet_name ); + } + return; + } + + if(!AM_DOMAIN_MASTER_BROWSER(work)) + return; - make_nmb_name(&nmbname,"*",0x1b); + if ((lastrun != 0) && (t < lastrun + (15 * 60))) + return; + + lastrun = t; - /* First, query for the *<1b> name from the WINS server. */ - query_name(unicast_subnet, nmbname.name, nmbname.name_type, - find_all_domain_master_names_query_success, - find_all_domain_master_names_query_fail, - NULL); + /* First, query for the *<1b> name from the WINS server. */ + query_name(unicast_subnet, "*", 0x1b, + find_all_domain_master_names_query_success, + find_all_domain_master_names_query_fail, + NULL); } @@ -656,6 +614,7 @@ To prevent exponential network traffic with large numbers of workgroups we use a randomised system where sync probability is inversely proportional to the number of known workgroups **************************************************************************/ + void sync_all_dmbs(time_t t) { static time_t lastrun = 0; @@ -669,7 +628,8 @@ void sync_all_dmbs(time_t t) /* Check to see if we are a domain master browser on the unicast subnet. */ work = find_workgroup_on_subnet(unicast_subnet, lp_workgroup()); - if (!work) return; + if (!work) + return; if (!AM_DOMAIN_MASTER_BROWSER(work)) return; @@ -679,15 +639,18 @@ void sync_all_dmbs(time_t t) /* count how many syncs we might need to do */ for (work=unicast_subnet->workgrouplist; work; work = work->next) { - if (strcmp(lp_workgroup(), work->work_group)) { + if (strncmp(lp_workgroup(), work->work_group, sizeof(nstring))) { count++; } } /* sync with a probability of 1/count */ for (work=unicast_subnet->workgrouplist; work; work = work->next) { - if (strcmp(lp_workgroup(), work->work_group)) { - if (((unsigned)sys_random()) % count != 0) continue; + if (strncmp(lp_workgroup(), work->work_group, sizeof(nstring))) { + nstring dmb_name; + + if (((unsigned)sys_random()) % count != 0) + continue; lastrun = t; @@ -699,13 +662,15 @@ void sync_all_dmbs(time_t t) 0x20); } + pull_ascii_nstring(dmb_name, work->dmb_name.name); + DEBUG(3,("Initiating DMB<->DMB sync with %s(%s)\n", - work->dmb_name.name, - inet_ntoa(work->dmb_addr))); + dmb_name, inet_ntoa(work->dmb_addr))); + sync_browse_lists(work, - work->dmb_name.name, + dmb_name, work->dmb_name.name_type, work->dmb_addr, False, False); } } -} +} diff --git a/source3/nmbd/nmbd_elections.c b/source3/nmbd/nmbd_elections.c index b948eb9d04..fabc0eddca 100644 --- a/source3/nmbd/nmbd_elections.c +++ b/source3/nmbd/nmbd_elections.c @@ -3,7 +3,7 @@ NBT netbios routines and daemon - version 2 Copyright (C) Andrew Tridgell 1994-1998 Copyright (C) Luke Kenneth Casson Leighton 1994-1998 - Copyright (C) Jeremy Allison 1994-1998 + Copyright (C) Jeremy Allison 1994-2003 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -29,32 +29,36 @@ extern time_t StartupTime; /**************************************************************************** Send an election datagram packet. **************************************************************************/ + static void send_election_dgram(struct subnet_record *subrec, const char *workgroup_name, uint32 criterion, int timeup,const char *server_name) { - pstring outbuf; - char *p; - - DEBUG(2,("send_election_dgram: Sending election packet for workgroup %s on subnet %s\n", - workgroup_name, subrec->subnet_name )); - - memset(outbuf,'\0',sizeof(outbuf)); - p = outbuf; - SCVAL(p,0,ANN_Election); /* Election opcode. */ - p++; - - SCVAL(p,0,((criterion == 0 && timeup == 0) ? 0 : ELECTION_VERSION)); - SIVAL(p,1,criterion); - SIVAL(p,5,timeup*1000); /* ms - Despite what the spec says. */ - p += 13; - pstrcpy_base(p, server_name, outbuf); - strupper_m(p); - p = skip_string(p,1); + pstring outbuf; + fstring srv_name; + char *p; + + DEBUG(2,("send_election_dgram: Sending election packet for workgroup %s on subnet %s\n", + workgroup_name, subrec->subnet_name )); + + memset(outbuf,'\0',sizeof(outbuf)); + p = outbuf; + SCVAL(p,0,ANN_Election); /* Election opcode. */ + p++; + + SCVAL(p,0,((criterion == 0 && timeup == 0) ? 0 : ELECTION_VERSION)); + SIVAL(p,1,criterion); + SIVAL(p,5,timeup*1000); /* ms - Despite what the spec says. */ + p += 13; + fstrcpy(srv_name, server_name); + strupper_m(srv_name); + /* The following call does UNIX -> DOS charset conversion. */ + pstrcpy_base(p, srv_name, outbuf); + p = skip_string(p,1); - send_mailslot(False, BROWSE_MAILSLOT, outbuf, PTR_DIFF(p,outbuf), - global_myname(), 0, - workgroup_name, 0x1e, - subrec->bcast_ip, subrec->myip, DGRAM_PORT); + send_mailslot(False, BROWSE_MAILSLOT, outbuf, PTR_DIFF(p,outbuf), + global_myname(), 0, + workgroup_name, 0x1e, + subrec->bcast_ip, subrec->myip, DGRAM_PORT); } /******************************************************************* @@ -66,8 +70,10 @@ static void check_for_master_browser_success(struct subnet_record *subrec, struct nmb_name *answer_name, struct in_addr answer_ip, struct res_rec *rrec) { - DEBUG(3,("check_for_master_browser_success: Local master browser for workgroup %s exists at \ -IP %s (just checking).\n", answer_name->name, inet_ntoa(answer_ip) )); + nstring aname; + pull_ascii_nstring(aname, answer_name->name); + DEBUG(3,("check_for_master_browser_success: Local master browser for workgroup %s exists at \ +IP %s (just checking).\n", aname, inet_ntoa(answer_ip) )); } /******************************************************************* @@ -79,41 +85,39 @@ static void check_for_master_browser_fail( struct subnet_record *subrec, struct nmb_name *question_name, int fail_code) { - char *workgroup_name = question_name->name; - struct work_record *work = find_workgroup_on_subnet(subrec, workgroup_name); - - if(work == NULL) - { - DEBUG(0,("check_for_master_browser_fail: Unable to find workgroup %s on subnet %s.=\n", - workgroup_name, subrec->subnet_name )); - return; - } - - if (strequal(work->work_group, lp_workgroup())) - { - - if (lp_local_master()) - { - /* We have discovered that there is no local master - browser, and we are configured to initiate - an election that we will participate in. - */ - DEBUG(2,("check_for_master_browser_fail: Forcing election on workgroup %s subnet %s\n", - work->work_group, subrec->subnet_name )); - - /* Setting this means we will participate when the - election is run in run_elections(). */ - work->needelection = True; - } - else - { - /* We need to force an election, because we are configured - not to become the local master, but we still need one, - having detected that one doesn't exist. - */ - send_election_dgram(subrec, work->work_group, 0, 0, ""); - } - } + nstring workgroup_name; + struct work_record *work; + + pull_ascii_nstring(workgroup_name,question_name->name); + + work = find_workgroup_on_subnet(subrec, workgroup_name); + if(work == NULL) { + DEBUG(0,("check_for_master_browser_fail: Unable to find workgroup %s on subnet %s.=\n", + workgroup_name, subrec->subnet_name )); + return; + } + + if (strnequal(work->work_group, lp_workgroup(), sizeof(nstring)-1)) { + + if (lp_local_master()) { + /* We have discovered that there is no local master + browser, and we are configured to initiate + an election that we will participate in. + */ + DEBUG(2,("check_for_master_browser_fail: Forcing election on workgroup %s subnet %s\n", + work->work_group, subrec->subnet_name )); + + /* Setting this means we will participate when the + election is run in run_elections(). */ + work->needelection = True; + } else { + /* We need to force an election, because we are configured + not to become the local master, but we still need one, + having detected that one doesn't exist. + */ + send_election_dgram(subrec, work->work_group, 0, 0, ""); + } + } } /******************************************************************* @@ -123,36 +127,33 @@ static void check_for_master_browser_fail( struct subnet_record *subrec, void check_master_browser_exists(time_t t) { - static time_t lastrun=0; - struct subnet_record *subrec; - const char *workgroup_name = lp_workgroup(); - - if (!lastrun) - lastrun = t; - - if (t < (lastrun + (CHECK_TIME_MST_BROWSE * 60))) - return; - - lastrun = t; - - dump_workgroups(False); - - for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) - { - struct work_record *work; - - for (work = subrec->workgrouplist; work; work = work->next) - { - if (strequal(work->work_group, workgroup_name) && !AM_LOCAL_MASTER_BROWSER(work)) - { - /* Do a name query for the local master browser on this net. */ - query_name( subrec, work->work_group, 0x1d, - check_for_master_browser_success, - check_for_master_browser_fail, - NULL); - } - } - } + static time_t lastrun=0; + struct subnet_record *subrec; + const char *workgroup_name = lp_workgroup(); + + if (!lastrun) + lastrun = t; + + if (t < (lastrun + (CHECK_TIME_MST_BROWSE * 60))) + return; + + lastrun = t; + + dump_workgroups(False); + + for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) { + struct work_record *work; + + for (work = subrec->workgrouplist; work; work = work->next) { + if (strnequal(work->work_group, workgroup_name, sizeof(nstring)-1) && !AM_LOCAL_MASTER_BROWSER(work)) { + /* Do a name query for the local master browser on this net. */ + query_name( subrec, work->work_group, 0x1d, + check_for_master_browser_success, + check_for_master_browser_fail, + NULL); + } + } + } } /******************************************************************* @@ -161,56 +162,52 @@ void check_master_browser_exists(time_t t) void run_elections(time_t t) { - static time_t lastime = 0; + static time_t lastime = 0; - struct subnet_record *subrec; + struct subnet_record *subrec; - /* Send election packets once every 2 seconds - note */ - if (lastime && (t - lastime < 2)) - return; + /* Send election packets once every 2 seconds - note */ + if (lastime && (t - lastime < 2)) + return; - lastime = t; + lastime = t; - START_PROFILE(run_elections); - for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) - { - struct work_record *work; - - for (work = subrec->workgrouplist; work; work = work->next) - { - if (work->RunningElection) - { - /* - * We can only run an election for a workgroup if we have - * registered the WORKGROUP<1e> name, as that's the name - * we must listen to. - */ - struct nmb_name nmbname; - - make_nmb_name(&nmbname, work->work_group, 0x1e); - if(find_name_on_subnet( subrec, &nmbname, FIND_SELF_NAME)==NULL) { - DEBUG(8,("run_elections: Cannot send election packet yet as name %s not \ + START_PROFILE(run_elections); + for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) { + struct work_record *work; + + for (work = subrec->workgrouplist; work; work = work->next) { + if (work->RunningElection) { + /* + * We can only run an election for a workgroup if we have + * registered the WORKGROUP<1e> name, as that's the name + * we must listen to. + */ + struct nmb_name nmbname; + + make_nmb_name(&nmbname, work->work_group, 0x1e); + if(find_name_on_subnet( subrec, &nmbname, FIND_SELF_NAME)==NULL) { + DEBUG(8,("run_elections: Cannot send election packet yet as name %s not \ yet registered on subnet %s\n", nmb_namestr(&nmbname), subrec->subnet_name )); - continue; - } + continue; + } - send_election_dgram(subrec, work->work_group, work->ElectionCriterion, - t - StartupTime, global_myname()); + send_election_dgram(subrec, work->work_group, work->ElectionCriterion, + t - StartupTime, global_myname()); - if (work->ElectionCount++ >= 4) - { - /* Won election (4 packets were sent out uncontested. */ - DEBUG(2,("run_elections: >>> Won election for workgroup %s on subnet %s <<<\n", - work->work_group, subrec->subnet_name )); - - work->RunningElection = False; - - become_local_master_browser(subrec, work); - } - } - } - } - END_PROFILE(run_elections); + if (work->ElectionCount++ >= 4) { + /* Won election (4 packets were sent out uncontested. */ + DEBUG(2,("run_elections: >>> Won election for workgroup %s on subnet %s <<<\n", + work->work_group, subrec->subnet_name )); + + work->RunningElection = False; + + become_local_master_browser(subrec, work); + } + } + } + } + END_PROFILE(run_elections); } /******************************************************************* @@ -218,44 +215,42 @@ yet registered on subnet %s\n", nmb_namestr(&nmbname), subrec->subnet_name )); ******************************************************************/ static BOOL win_election(struct work_record *work, int version, - uint32 criterion, int timeup, char *server_name) + uint32 criterion, int timeup, const char *server_name) { - int mytimeup = time(NULL) - StartupTime; - uint32 mycriterion = work->ElectionCriterion; - - /* If local master is false then never win - in election broadcasts. */ - if(!lp_local_master()) - { - DEBUG(3,("win_election: Losing election as local master == False\n")); - return False; - } + int mytimeup = time(NULL) - StartupTime; + uint32 mycriterion = work->ElectionCriterion; + + /* If local master is false then never win in election broadcasts. */ + if(!lp_local_master()) { + DEBUG(3,("win_election: Losing election as local master == False\n")); + return False; + } - DEBUG(4,("win_election: election comparison: %x:%x %x:%x %d:%d %s:%s\n", - version, ELECTION_VERSION, - criterion, mycriterion, - timeup, mytimeup, - server_name, global_myname())); - - if (version > ELECTION_VERSION) - return(False); - if (version < ELECTION_VERSION) - return(True); + DEBUG(4,("win_election: election comparison: %x:%x %x:%x %d:%d %s:%s\n", + version, ELECTION_VERSION, + criterion, mycriterion, + timeup, mytimeup, + server_name, global_myname())); + + if (version > ELECTION_VERSION) + return(False); + if (version < ELECTION_VERSION) + return(True); - if (criterion > mycriterion) - return(False); - if (criterion < mycriterion) - return(True); - - if (timeup > mytimeup) - return(False); - if (timeup < mytimeup) - return(True); - - if (strcasecmp(global_myname(), server_name) > 0) - return(False); + if (criterion > mycriterion) + return(False); + if (criterion < mycriterion) + return(True); + + if (timeup > mytimeup) + return(False); + if (timeup < mytimeup) + return(True); + + if (strcasecmp(global_myname(), server_name) > 0) + return(False); - return(True); + return(True); } /******************************************************************* @@ -264,66 +259,63 @@ static BOOL win_election(struct work_record *work, int version, void process_election(struct subnet_record *subrec, struct packet_struct *p, char *buf) { - struct dgram_packet *dgram = &p->packet.dgram; - int version = CVAL(buf,0); - uint32 criterion = IVAL(buf,1); - int timeup = IVAL(buf,5)/1000; - char *server_name = buf+13; - struct work_record *work; - char *workgroup_name = dgram->dest_name.name; - - START_PROFILE(election); - server_name[15] = 0; - - DEBUG(3,("process_election: Election request from %s at IP %s on subnet %s for workgroup %s.\n", - server_name,inet_ntoa(p->ip), subrec->subnet_name, workgroup_name )); - - DEBUG(5,("process_election: vers=%d criterion=%08x timeup=%d\n", version,criterion,timeup)); - - if(( work = find_workgroup_on_subnet(subrec, workgroup_name)) == NULL) - { - DEBUG(0,("process_election: Cannot find workgroup %s on subnet %s.\n", - workgroup_name, subrec->subnet_name )); - goto done; - } - - if (!strequal(work->work_group, lp_workgroup())) - { - DEBUG(3,("process_election: ignoring election request for workgroup %s on subnet %s as this \ + struct dgram_packet *dgram = &p->packet.dgram; + int version = CVAL(buf,0); + uint32 criterion = IVAL(buf,1); + int timeup = IVAL(buf,5)/1000; + nstring server_name; + struct work_record *work; + nstring workgroup_name; + + pull_ascii_nstring(server_name, buf+13); + pull_ascii_nstring(workgroup_name, dgram->dest_name.name); + + START_PROFILE(election); + server_name[15] = 0; + + DEBUG(3,("process_election: Election request from %s at IP %s on subnet %s for workgroup %s.\n", + server_name,inet_ntoa(p->ip), subrec->subnet_name, workgroup_name )); + + DEBUG(5,("process_election: vers=%d criterion=%08x timeup=%d\n", version,criterion,timeup)); + + if(( work = find_workgroup_on_subnet(subrec, workgroup_name)) == NULL) { + DEBUG(0,("process_election: Cannot find workgroup %s on subnet %s.\n", + workgroup_name, subrec->subnet_name )); + goto done; + } + + if (!strnequal(work->work_group, lp_workgroup(), sizeof(nstring)-1)) { + DEBUG(3,("process_election: ignoring election request for workgroup %s on subnet %s as this \ is not my workgroup.\n", work->work_group, subrec->subnet_name )); - goto done; - } - - if (win_election(work, version,criterion,timeup,server_name)) - { - /* We take precedence over the requesting server. */ - if (!work->RunningElection) - { - /* We weren't running an election - start running one. */ - - work->needelection = True; - work->ElectionCount=0; - } - - /* Note that if we were running an election for this workgroup on this - subnet already, we just ignore the server we take precedence over. */ - } - else - { - /* We lost. Stop participating. */ - work->needelection = False; - - if (work->RunningElection || AM_LOCAL_MASTER_BROWSER(work)) - { - work->RunningElection = False; - DEBUG(3,("process_election: >>> Lost election for workgroup %s on subnet %s <<<\n", - work->work_group, subrec->subnet_name )); - if (AM_LOCAL_MASTER_BROWSER(work)) - unbecome_local_master_browser(subrec, work, False); - } - } + goto done; + } + + if (win_election(work, version,criterion,timeup,server_name)) { + /* We take precedence over the requesting server. */ + if (!work->RunningElection) { + /* We weren't running an election - start running one. */ + + work->needelection = True; + work->ElectionCount=0; + } + + /* Note that if we were running an election for this workgroup on this + subnet already, we just ignore the server we take precedence over. */ + } else { + /* We lost. Stop participating. */ + work->needelection = False; + + if (work->RunningElection || AM_LOCAL_MASTER_BROWSER(work)) { + work->RunningElection = False; + DEBUG(3,("process_election: >>> Lost election for workgroup %s on subnet %s <<<\n", + work->work_group, subrec->subnet_name )); + if (AM_LOCAL_MASTER_BROWSER(work)) + unbecome_local_master_browser(subrec, work, False); + } + } done: - END_PROFILE(election); + + END_PROFILE(election); } /**************************************************************************** @@ -335,57 +327,53 @@ done: BOOL check_elections(void) { - struct subnet_record *subrec; - BOOL run_any_election = False; - - for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) - { - struct work_record *work; - for (work = subrec->workgrouplist; work; work = work->next) - { - run_any_election |= work->RunningElection; - - /* - * Start an election if we have any chance of winning. - * Note this is a change to the previous code, that would - * only run an election if nmbd was in the potential browser - * state. We need to run elections in any state if we're told - * to. JRA. - */ - - if (work->needelection && !work->RunningElection && lp_local_master()) - { - /* - * We can only run an election for a workgroup if we have - * registered the WORKGROUP<1e> name, as that's the name - * we must listen to. - */ - struct nmb_name nmbname; - - make_nmb_name(&nmbname, work->work_group, 0x1e); - if(find_name_on_subnet( subrec, &nmbname, FIND_SELF_NAME)==NULL) { - DEBUG(8,("check_elections: Cannot send election packet yet as name %s not \ + struct subnet_record *subrec; + BOOL run_any_election = False; + + for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) { + struct work_record *work; + for (work = subrec->workgrouplist; work; work = work->next) { + run_any_election |= work->RunningElection; + + /* + * Start an election if we have any chance of winning. + * Note this is a change to the previous code, that would + * only run an election if nmbd was in the potential browser + * state. We need to run elections in any state if we're told + * to. JRA. + */ + + if (work->needelection && !work->RunningElection && lp_local_master()) { + /* + * We can only run an election for a workgroup if we have + * registered the WORKGROUP<1e> name, as that's the name + * we must listen to. + */ + struct nmb_name nmbname; + + make_nmb_name(&nmbname, work->work_group, 0x1e); + if(find_name_on_subnet( subrec, &nmbname, FIND_SELF_NAME)==NULL) { + DEBUG(8,("check_elections: Cannot send election packet yet as name %s not \ yet registered on subnet %s\n", nmb_namestr(&nmbname), subrec->subnet_name )); - continue; - } - - DEBUG(3,("check_elections: >>> Starting election for workgroup %s on subnet %s <<<\n", - work->work_group, subrec->subnet_name )); - - work->ElectionCount = 0; - work->RunningElection = True; - work->needelection = False; - } - } - } - return run_any_election; -} + continue; + } + DEBUG(3,("check_elections: >>> Starting election for workgroup %s on subnet %s <<<\n", + work->work_group, subrec->subnet_name )); + work->ElectionCount = 0; + work->RunningElection = True; + work->needelection = False; + } + } + } + return run_any_election; +} /**************************************************************************** -process a internal Samba message forcing an election + Process a internal Samba message forcing an election. ***************************************************************************/ + void nmbd_message_election(int msg_type, pid_t src, void *buf, size_t len) { struct subnet_record *subrec; @@ -393,7 +381,7 @@ void nmbd_message_election(int msg_type, pid_t src, void *buf, size_t len) for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) { struct work_record *work; for (work = subrec->workgrouplist; work; work = work->next) { - if (strequal(work->work_group, lp_workgroup())) { + if (strnequal(work->work_group, lp_workgroup(), sizeof(nstring)-1)) { work->needelection = True; work->ElectionCount=0; work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE; diff --git a/source3/nmbd/nmbd_incomingdgrams.c b/source3/nmbd/nmbd_incomingdgrams.c index 80465ada0d..f646e39716 100644 --- a/source3/nmbd/nmbd_incomingdgrams.c +++ b/source3/nmbd/nmbd_incomingdgrams.c @@ -95,102 +95,99 @@ void tell_become_backup(void) void process_host_announce(struct subnet_record *subrec, struct packet_struct *p, char *buf) { - struct dgram_packet *dgram = &p->packet.dgram; - int ttl = IVAL(buf,1)/1000; - char *announce_name = buf+5; - uint32 servertype = IVAL(buf,23); - char *comment = buf+31; - struct work_record *work; - struct server_record *servrec; - const char *work_name; - char *source_name = dgram->source_name.name; - - START_PROFILE(host_announce); - comment[43] = 0; + struct dgram_packet *dgram = &p->packet.dgram; + int ttl = IVAL(buf,1)/1000; + nstring announce_name; + uint32 servertype = IVAL(buf,23); + fstring comment; + struct work_record *work; + struct server_record *servrec; + nstring work_name; + nstring source_name; + + START_PROFILE(host_announce); + + pull_ascii_fstring(comment, buf+31); + comment[42] = 0; - DEBUG(3,("process_host_announce: from %s<%02x> IP %s to \ + pull_ascii_nstring(announce_name, buf+5); + pull_ascii_nstring(source_name, dgram->source_name.name); + + DEBUG(3,("process_host_announce: from %s<%02x> IP %s to \ %s for server %s.\n", source_name, source_name[15], inet_ntoa(p->ip), - nmb_namestr(&dgram->dest_name),announce_name)); + nmb_namestr(&dgram->dest_name),announce_name)); - DEBUG(5,("process_host_announce: ttl=%d server type=%08x comment=%s\n", - ttl, servertype,comment)); + DEBUG(5,("process_host_announce: ttl=%d server type=%08x comment=%s\n", + ttl, servertype,comment)); - /* Filter servertype to remove impossible bits. */ - servertype &= ~(SV_TYPE_LOCAL_LIST_ONLY|SV_TYPE_DOMAIN_ENUM); + /* Filter servertype to remove impossible bits. */ + servertype &= ~(SV_TYPE_LOCAL_LIST_ONLY|SV_TYPE_DOMAIN_ENUM); - /* A host announcement must be sent to the name WORKGROUP<1d>. */ - if(dgram->dest_name.name_type != 0x1d) - { - DEBUG(2,("process_host_announce: incorrect name type for destination from IP %s \ + /* A host announcement must be sent to the name WORKGROUP<1d>. */ + if(dgram->dest_name.name_type != 0x1d) { + DEBUG(2,("process_host_announce: incorrect name type for destination from IP %s \ (was %02x) should be 0x1d. Allowing packet anyway.\n", - inet_ntoa(p->ip), dgram->dest_name.name_type)); - /* Change it so it was. */ - dgram->dest_name.name_type = 0x1d; - } - - /* For a host announce the workgroup name is the destination name. */ - work_name = dgram->dest_name.name; - - /* - * Syntax servers version 5.1 send HostAnnounce packets to - * *THE WRONG NAME*. They send to LOCAL_MASTER_BROWSER_NAME<00> - * instead of WORKGROUP<1d> name. So to fix this we check if - * the workgroup name is our own name, and if so change it - * to be our primary workgroup name. - */ - - if(strequal(work_name, global_myname())) - work_name = lp_workgroup(); - - /* - * We are being very agressive here in adding a workgroup - * name on the basis of a host announcing itself as being - * in that workgroup. Maybe we should wait for the workgroup - * announce instead ? JRA. - */ - - work = find_workgroup_on_subnet(subrec, work_name); - - if(servertype != 0) - { - if (work ==NULL ) - { - /* We have no record of this workgroup. Add it. */ - if((work = create_workgroup_on_subnet(subrec, work_name, ttl))==NULL) - goto done; - } + inet_ntoa(p->ip), dgram->dest_name.name_type)); + /* Change it so it was. */ + dgram->dest_name.name_type = 0x1d; + } + + /* For a host announce the workgroup name is the destination name. */ + pull_ascii_nstring(work_name, dgram->dest_name.name); + + /* + * Syntax servers version 5.1 send HostAnnounce packets to + * *THE WRONG NAME*. They send to LOCAL_MASTER_BROWSER_NAME<00> + * instead of WORKGROUP<1d> name. So to fix this we check if + * the workgroup name is our own name, and if so change it + * to be our primary workgroup name. + */ + + if(strequal(work_name, global_myname())) + nstrcpy(work_name,lp_workgroup()); + + /* + * We are being very agressive here in adding a workgroup + * name on the basis of a host announcing itself as being + * in that workgroup. Maybe we should wait for the workgroup + * announce instead ? JRA. + */ + + work = find_workgroup_on_subnet(subrec, work_name); + + if(servertype != 0) { + if (work ==NULL ) { + /* We have no record of this workgroup. Add it. */ + if((work = create_workgroup_on_subnet(subrec, work_name, ttl))==NULL) + goto done; + } - if((servrec = find_server_in_workgroup( work, announce_name))==NULL) - { - /* If this server is not already in the workgroup, add it. */ - create_server_on_workgroup(work, announce_name, - servertype|SV_TYPE_LOCAL_LIST_ONLY, - ttl, comment); - } - else - { - /* Update the record. */ - servrec->serv.type = servertype|SV_TYPE_LOCAL_LIST_ONLY; - update_server_ttl( servrec, ttl); - fstrcpy(servrec->serv.comment,comment); - } - } - else - { - /* - * This server is announcing it is going down. Remove it from the - * workgroup. - */ - if(!is_myname(announce_name) && (work != NULL) && - ((servrec = find_server_in_workgroup( work, announce_name))!=NULL) - ) - { - remove_server_from_workgroup( work, servrec); - } - } - subrec->work_changed = True; + if((servrec = find_server_in_workgroup( work, announce_name))==NULL) { + /* If this server is not already in the workgroup, add it. */ + create_server_on_workgroup(work, announce_name, + servertype|SV_TYPE_LOCAL_LIST_ONLY, + ttl, comment); + } else { + /* Update the record. */ + servrec->serv.type = servertype|SV_TYPE_LOCAL_LIST_ONLY; + update_server_ttl( servrec, ttl); + fstrcpy(servrec->serv.comment,comment); + } + } else { + /* + * This server is announcing it is going down. Remove it from the + * workgroup. + */ + if(!is_myname(announce_name) && (work != NULL) && + ((servrec = find_server_in_workgroup( work, announce_name))!=NULL)) { + remove_server_from_workgroup( work, servrec); + } + } + + subrec->work_changed = True; done: - END_PROFILE(host_announce); + + END_PROFILE(host_announce); } /******************************************************************* @@ -199,53 +196,55 @@ done: void process_workgroup_announce(struct subnet_record *subrec, struct packet_struct *p, char *buf) { - struct dgram_packet *dgram = &p->packet.dgram; - int ttl = IVAL(buf,1)/1000; - char *workgroup_announce_name = buf+5; - uint32 servertype = IVAL(buf,23); - char *master_name = buf+31; - struct work_record *work; - char *source_name = dgram->source_name.name; - - START_PROFILE(workgroup_announce); - master_name[43] = 0; - - DEBUG(3,("process_workgroup_announce: from %s<%02x> IP %s to \ + struct dgram_packet *dgram = &p->packet.dgram; + int ttl = IVAL(buf,1)/1000; + nstring workgroup_announce_name; + nstring master_name; + uint32 servertype = IVAL(buf,23); + struct work_record *work; + nstring source_name; + nstring dest_name; + + START_PROFILE(workgroup_announce); + + pull_ascii_nstring(workgroup_announce_name,buf+5); + pull_ascii_nstring(master_name,buf+31); + pull_ascii_nstring(source_name,dgram->source_name.name); + pull_ascii_nstring(dest_name,dgram->dest_name.name); + + DEBUG(3,("process_workgroup_announce: from %s<%02x> IP %s to \ %s for workgroup %s.\n", source_name, source_name[15], inet_ntoa(p->ip), - nmb_namestr(&dgram->dest_name),workgroup_announce_name)); - - DEBUG(5,("process_workgroup_announce: ttl=%d server type=%08x master browser=%s\n", - ttl, servertype, master_name)); - - /* Workgroup announcements must only go to the MSBROWSE name. */ - if (!strequal(dgram->dest_name.name, MSBROWSE) || (dgram->dest_name.name_type != 0x1)) - { - DEBUG(0,("process_workgroup_announce: from IP %s should be to __MSBROWSE__<0x01> not %s\n", - inet_ntoa(p->ip), nmb_namestr(&dgram->dest_name))); - goto done; - } + nmb_namestr(&dgram->dest_name),workgroup_announce_name)); + + DEBUG(5,("process_workgroup_announce: ttl=%d server type=%08x master browser=%s\n", + ttl, servertype, master_name)); + + /* Workgroup announcements must only go to the MSBROWSE name. */ + if (!strequal(dest_name, MSBROWSE) || (dgram->dest_name.name_type != 0x1)) { + DEBUG(0,("process_workgroup_announce: from IP %s should be to __MSBROWSE__<0x01> not %s\n", + inet_ntoa(p->ip), nmb_namestr(&dgram->dest_name))); + goto done; + } + + if ((work = find_workgroup_on_subnet(subrec, workgroup_announce_name))==NULL) { + /* We have no record of this workgroup. Add it. */ + if((work = create_workgroup_on_subnet(subrec, workgroup_announce_name, ttl))==NULL) + goto done; + } else { + /* Update the workgroup death_time. */ + update_workgroup_ttl(work, ttl); + } + + if(*work->local_master_browser_name == '\0') { + /* Set the master browser name. */ + set_workgroup_local_master_browser_name( work, master_name ); + } + + subrec->work_changed = True; - if ((work = find_workgroup_on_subnet(subrec, workgroup_announce_name))==NULL) - { - /* We have no record of this workgroup. Add it. */ - if((work = create_workgroup_on_subnet(subrec, workgroup_announce_name, ttl))==NULL) - goto done; - } - else - { - /* Update the workgroup death_time. */ - update_workgroup_ttl(work, ttl); - } - - if(*work->local_master_browser_name == '\0') - { - /* Set the master browser name. */ - set_workgroup_local_master_browser_name( work, master_name ); - } - - subrec->work_changed = True; done: - END_PROFILE(workgroup_announce); + + END_PROFILE(workgroup_announce); } /******************************************************************* @@ -254,117 +253,110 @@ done: void process_local_master_announce(struct subnet_record *subrec, struct packet_struct *p, char *buf) { - struct dgram_packet *dgram = &p->packet.dgram; - int ttl = IVAL(buf,1)/1000; - char *server_name = buf+5; - uint32 servertype = IVAL(buf,23); - char *comment = buf+31; - char *work_name; - struct work_record *work; - struct server_record *servrec; - char *source_name = dgram->source_name.name; - - START_PROFILE(local_master_announce); - comment[43] = 0; - - DEBUG(3,("process_local_master_announce: from %s<%02x> IP %s to \ + struct dgram_packet *dgram = &p->packet.dgram; + int ttl = IVAL(buf,1)/1000; + nstring server_name; + uint32 servertype = IVAL(buf,23); + fstring comment; + nstring work_name; + struct work_record *work; + struct server_record *servrec; + nstring source_name; + + START_PROFILE(local_master_announce); + + pull_ascii_nstring(server_name,buf+5); + pull_ascii_fstring(comment, buf+31); + comment[42] = 0; + pull_ascii_nstring(source_name, dgram->source_name.name); + pull_ascii_nstring(work_name, dgram->dest_name.name); + + DEBUG(3,("process_local_master_announce: from %s<%02x> IP %s to \ %s for server %s.\n", source_name, source_name[15], inet_ntoa(p->ip), - nmb_namestr(&dgram->dest_name),server_name)); + nmb_namestr(&dgram->dest_name),server_name)); - DEBUG(5,("process_local_master_announce: ttl=%d server type=%08x comment=%s\n", - ttl, servertype, comment)); + DEBUG(5,("process_local_master_announce: ttl=%d server type=%08x comment=%s\n", + ttl, servertype, comment)); - /* A local master announcement must be sent to the name WORKGROUP<1e>. */ - if(dgram->dest_name.name_type != 0x1e) - { - DEBUG(0,("process_local_master_announce: incorrect name type for destination from IP %s \ + /* A local master announcement must be sent to the name WORKGROUP<1e>. */ + if(dgram->dest_name.name_type != 0x1e) { + DEBUG(0,("process_local_master_announce: incorrect name type for destination from IP %s \ (was %02x) should be 0x1e. Ignoring packet.\n", - inet_ntoa(p->ip), dgram->dest_name.name_type)); - goto done; - } - - /* Filter servertype to remove impossible bits. */ - servertype &= ~(SV_TYPE_LOCAL_LIST_ONLY|SV_TYPE_DOMAIN_ENUM); - - /* For a local master announce the workgroup name is the destination name. */ - work_name = dgram->dest_name.name; - - if ((work = find_workgroup_on_subnet(subrec, work_name))==NULL) - { - /* Don't bother adding if it's a local master release announce. */ - if(servertype == 0) - goto done; - - /* We have no record of this workgroup. Add it. */ - if((work = create_workgroup_on_subnet(subrec, work_name, ttl))==NULL) - goto done; - } - - /* If we think we're the local master browser for this workgroup, - we should never have got this packet. We don't see our own - packets. - */ - if(AM_LOCAL_MASTER_BROWSER(work)) - { - DEBUG(0,("process_local_master_announce: Server %s at IP %s is announcing itself as \ + inet_ntoa(p->ip), dgram->dest_name.name_type)); + goto done; + } + + /* Filter servertype to remove impossible bits. */ + servertype &= ~(SV_TYPE_LOCAL_LIST_ONLY|SV_TYPE_DOMAIN_ENUM); + + /* For a local master announce the workgroup name is the destination name. */ + + if ((work = find_workgroup_on_subnet(subrec, work_name))==NULL) { + /* Don't bother adding if it's a local master release announce. */ + if(servertype == 0) + goto done; + + /* We have no record of this workgroup. Add it. */ + if((work = create_workgroup_on_subnet(subrec, work_name, ttl))==NULL) + goto done; + } + + /* If we think we're the local master browser for this workgroup, + we should never have got this packet. We don't see our own + packets. + */ + if(AM_LOCAL_MASTER_BROWSER(work)) { + DEBUG(0,("process_local_master_announce: Server %s at IP %s is announcing itself as \ a local master browser for workgroup %s and we think we are master. Forcing election.\n", - server_name, inet_ntoa(p->ip), work_name)); + server_name, inet_ntoa(p->ip), work_name)); - /* Samba nmbd versions 1.9.17 to 1.9.17p4 have a bug in that when - they have become a local master browser once, they will never - stop sending local master announcements. To fix this we send - them a reset browser packet, with level 0x2 on the __SAMBA__ - name that only they should be listening to. */ + /* Samba nmbd versions 1.9.17 to 1.9.17p4 have a bug in that when + they have become a local master browser once, they will never + stop sending local master announcements. To fix this we send + them a reset browser packet, with level 0x2 on the __SAMBA__ + name that only they should be listening to. */ - send_browser_reset( 0x2, "__SAMBA__" , 0x20, p->ip); - - /* We should demote ourself and force an election. */ - - unbecome_local_master_browser( subrec, work, True); - - /* The actual election requests are handled in - nmbd_election.c */ - goto done; - } - - /* Find the server record on this workgroup. If it doesn't exist, add it. */ - - if(servertype != 0) - { - if((servrec = find_server_in_workgroup( work, server_name))==NULL) - { - /* If this server is not already in the workgroup, add it. */ - create_server_on_workgroup(work, server_name, - servertype|SV_TYPE_LOCAL_LIST_ONLY, - ttl, comment); - } - else - { - /* Update the record. */ - servrec->serv.type = servertype|SV_TYPE_LOCAL_LIST_ONLY; - update_server_ttl(servrec, ttl); - fstrcpy(servrec->serv.comment,comment); - } - - set_workgroup_local_master_browser_name( work, server_name ); - } - else - { - /* - * This server is announcing it is going down. Remove it from the - * workgroup. - */ - if(!is_myname(server_name) && (work != NULL) && - ((servrec = find_server_in_workgroup( work, server_name))!=NULL) - ) - { - remove_server_from_workgroup( work, servrec); - } - } - - subrec->work_changed = True; + send_browser_reset( 0x2, "__SAMBA__" , 0x20, p->ip); + + /* We should demote ourself and force an election. */ + + unbecome_local_master_browser( subrec, work, True); + + /* The actual election requests are handled in nmbd_election.c */ + goto done; + } + + /* Find the server record on this workgroup. If it doesn't exist, add it. */ + + if(servertype != 0) { + if((servrec = find_server_in_workgroup( work, server_name))==NULL) { + /* If this server is not already in the workgroup, add it. */ + create_server_on_workgroup(work, server_name, + servertype|SV_TYPE_LOCAL_LIST_ONLY, + ttl, comment); + } else { + /* Update the record. */ + servrec->serv.type = servertype|SV_TYPE_LOCAL_LIST_ONLY; + update_server_ttl(servrec, ttl); + fstrcpy(servrec->serv.comment,comment); + } + + set_workgroup_local_master_browser_name( work, server_name ); + } else { + /* + * This server is announcing it is going down. Remove it from the + * workgroup. + */ + if(!is_myname(server_name) && (work != NULL) && + ((servrec = find_server_in_workgroup( work, server_name))!=NULL)) { + remove_server_from_workgroup( work, servrec); + } + } + + subrec->work_changed = True; done: - END_PROFILE(local_master_announce); + + END_PROFILE(local_master_announce); } /******************************************************************* @@ -377,50 +369,49 @@ done: void process_master_browser_announce(struct subnet_record *subrec, struct packet_struct *p,char *buf) { - char *local_master_name = buf; - struct work_record *work; - struct browse_cache_record *browrec; + nstring local_master_name; + struct work_record *work; + struct browse_cache_record *browrec; - START_PROFILE(master_browser_announce); - local_master_name[15] = 0; + START_PROFILE(master_browser_announce); + + pull_ascii_nstring(local_master_name,buf); - DEBUG(3,("process_master_browser_announce: Local master announce from %s IP %s.\n", - local_master_name, inet_ntoa(p->ip))); + DEBUG(3,("process_master_browser_announce: Local master announce from %s IP %s.\n", + local_master_name, inet_ntoa(p->ip))); - if (!lp_domain_master()) - { - DEBUG(0,("process_master_browser_announce: Not configured as domain \ + if (!lp_domain_master()) { + DEBUG(0,("process_master_browser_announce: Not configured as domain \ master - ignoring master announce.\n")); - goto done; - } + goto done; + } - if((work = find_workgroup_on_subnet(subrec, lp_workgroup())) == NULL) - { - DEBUG(0,("process_master_browser_announce: Cannot find workgroup %s on subnet %s\n", - lp_workgroup(), subrec->subnet_name)); - goto done; - } - - if(!AM_DOMAIN_MASTER_BROWSER(work)) - { - DEBUG(0,("process_master_browser_announce: Local master announce made to us from \ + if((work = find_workgroup_on_subnet(subrec, lp_workgroup())) == NULL) { + DEBUG(0,("process_master_browser_announce: Cannot find workgroup %s on subnet %s\n", + lp_workgroup(), subrec->subnet_name)); + goto done; + } + + if(!AM_DOMAIN_MASTER_BROWSER(work)) { + DEBUG(0,("process_master_browser_announce: Local master announce made to us from \ %s IP %s and we are not a domain master browser.\n", local_master_name, inet_ntoa(p->ip))); - goto done; - } + goto done; + } - /* Add this host as a local master browser entry on the browse lists. - This causes a sync request to be made to it at a later date. - */ + /* Add this host as a local master browser entry on the browse lists. + This causes a sync request to be made to it at a later date. + */ + + if((browrec = find_browser_in_lmb_cache( local_master_name )) == NULL) { + /* Add it. */ + create_browser_in_lmb_cache( work->work_group, local_master_name, p->ip); + } else { + update_browser_death_time(browrec); + } - if((browrec = find_browser_in_lmb_cache( local_master_name )) == NULL) - { - /* Add it. */ - create_browser_in_lmb_cache( work->work_group, local_master_name, p->ip); - } - else - update_browser_death_time(browrec); done: - END_PROFILE(master_browser_announce); + + END_PROFILE(master_browser_announce); } /******************************************************************* @@ -429,123 +420,117 @@ done: void process_lm_host_announce(struct subnet_record *subrec, struct packet_struct *p, char *buf) { - struct dgram_packet *dgram = &p->packet.dgram; - uint32 servertype = IVAL(buf,1); - int osmajor=CVAL(buf,5); /* major version of node software */ - int osminor=CVAL(buf,6); /* minor version of node software */ - int ttl = SVAL(buf,7); - char *announce_name = buf+9; - struct work_record *work; - struct server_record *servrec; - const char *work_name; - char *source_name = dgram->source_name.name; - pstring comment; - char *s = buf+9; - - START_PROFILE(lm_host_announce); - s = skip_string(s,1); - StrnCpy(comment, s, 43); - - DEBUG(3,("process_lm_host_announce: LM Announcement from %s<%02x> IP %s to \ -%s for server %s.\n", source_name, source_name[15], inet_ntoa(p->ip), - nmb_namestr(&dgram->dest_name),announce_name)); - - DEBUG(5,("process_lm_host_announce: os=(%d,%d) ttl=%d server type=%08x comment=%s\n", - osmajor, osminor, ttl, servertype,comment)); - - if ((osmajor < 36) || (osmajor > 38) || (osminor !=0)) - { - DEBUG(5,("process_lm_host_announce: LM Announcement packet does not \ + struct dgram_packet *dgram = &p->packet.dgram; + uint32 servertype = IVAL(buf,1); + int osmajor=CVAL(buf,5); /* major version of node software */ + int osminor=CVAL(buf,6); /* minor version of node software */ + int ttl = SVAL(buf,7); + nstring announce_name; + struct work_record *work; + struct server_record *servrec; + nstring work_name; + nstring source_name; + fstring comment; + char *s = buf+9; + + START_PROFILE(lm_host_announce); + s = skip_string(s,1); + pull_ascii(comment, s, sizeof(fstring), 43, STR_TERMINATE); + + pull_ascii_nstring(announce_name,buf+9); + pull_ascii_nstring(source_name,dgram->source_name.name); + /* For a LanMan host announce the workgroup name is the destination name. */ + pull_ascii_nstring(work_name,dgram->dest_name.name); + + DEBUG(3,("process_lm_host_announce: LM Announcement from %s IP %s to \ +%s for server %s.\n", nmb_namestr(&dgram->source_name), inet_ntoa(p->ip), + nmb_namestr(&dgram->dest_name),announce_name)); + + DEBUG(5,("process_lm_host_announce: os=(%d,%d) ttl=%d server type=%08x comment=%s\n", + osmajor, osminor, ttl, servertype,comment)); + + if ((osmajor < 36) || (osmajor > 38) || (osminor !=0)) { + DEBUG(5,("process_lm_host_announce: LM Announcement packet does not \ originate from OS/2 Warp client. Ignoring packet.\n")); - /* Could have been from a Windows machine (with its LM Announce enabled), - or a Samba server. Then don't disrupt the current browse list. */ - goto done; - } + /* Could have been from a Windows machine (with its LM Announce enabled), + or a Samba server. Then don't disrupt the current browse list. */ + goto done; + } - /* Filter servertype to remove impossible bits. */ - servertype &= ~(SV_TYPE_LOCAL_LIST_ONLY|SV_TYPE_DOMAIN_ENUM); + /* Filter servertype to remove impossible bits. */ + servertype &= ~(SV_TYPE_LOCAL_LIST_ONLY|SV_TYPE_DOMAIN_ENUM); - /* A LanMan host announcement must be sent to the name WORKGROUP<00>. */ - if(dgram->dest_name.name_type != 0x00) - { - DEBUG(2,("process_lm_host_announce: incorrect name type for destination from IP %s \ + /* A LanMan host announcement must be sent to the name WORKGROUP<00>. */ + if(dgram->dest_name.name_type != 0x00) { + DEBUG(2,("process_lm_host_announce: incorrect name type for destination from IP %s \ (was %02x) should be 0x00. Allowing packet anyway.\n", - inet_ntoa(p->ip), dgram->dest_name.name_type)); - /* Change it so it was. */ - dgram->dest_name.name_type = 0x00; - } - - /* For a LanMan host announce the workgroup name is the destination name. */ - work_name = dgram->dest_name.name; - - /* - * Syntax servers version 5.1 send HostAnnounce packets to - * *THE WRONG NAME*. They send to LOCAL_MASTER_BROWSER_NAME<00> - * instead of WORKGROUP<1d> name. So to fix this we check if - * the workgroup name is our own name, and if so change it - * to be our primary workgroup name. This code is probably - * not needed in the LanMan announce code, but it won't hurt. - */ - - if(strequal(work_name, global_myname())) - work_name = lp_workgroup(); - - /* - * We are being very agressive here in adding a workgroup - * name on the basis of a host announcing itself as being - * in that workgroup. Maybe we should wait for the workgroup - * announce instead ? JRA. - */ + inet_ntoa(p->ip), dgram->dest_name.name_type)); + /* Change it so it was. */ + dgram->dest_name.name_type = 0x00; + } + + /* + * Syntax servers version 5.1 send HostAnnounce packets to + * *THE WRONG NAME*. They send to LOCAL_MASTER_BROWSER_NAME<00> + * instead of WORKGROUP<1d> name. So to fix this we check if + * the workgroup name is our own name, and if so change it + * to be our primary workgroup name. This code is probably + * not needed in the LanMan announce code, but it won't hurt. + */ + + if(strequal(work_name, global_myname())) + nstrcpy(work_name,lp_workgroup()); + + /* + * We are being very agressive here in adding a workgroup + * name on the basis of a host announcing itself as being + * in that workgroup. Maybe we should wait for the workgroup + * announce instead ? JRA. + */ + + work = find_workgroup_on_subnet(subrec, work_name); + + if(servertype != 0) { + if (work == NULL) { + /* We have no record of this workgroup. Add it. */ + if((work = create_workgroup_on_subnet(subrec, work_name, ttl))==NULL) + goto done; + } + + if((servrec = find_server_in_workgroup( work, announce_name))==NULL) { + /* If this server is not already in the workgroup, add it. */ + create_server_on_workgroup(work, announce_name, + servertype|SV_TYPE_LOCAL_LIST_ONLY, + ttl, comment); + } else { + /* Update the record. */ + servrec->serv.type = servertype|SV_TYPE_LOCAL_LIST_ONLY; + update_server_ttl( servrec, ttl); + fstrcpy(servrec->serv.comment,comment); + } + } else { + /* + * This server is announcing it is going down. Remove it from the + * workgroup. + */ + if(!is_myname(announce_name) && (work != NULL) && + ((servrec = find_server_in_workgroup( work, announce_name))!=NULL)) { + remove_server_from_workgroup( work, servrec); + } + } + + subrec->work_changed = True; + found_lm_clients = True; - work = find_workgroup_on_subnet(subrec, work_name); - - if(servertype != 0) - { - if (work == NULL) - { - /* We have no record of this workgroup. Add it. */ - if((work = create_workgroup_on_subnet(subrec, work_name, ttl))==NULL) - goto done; - } - - if((servrec = find_server_in_workgroup( work, announce_name))==NULL) - { - /* If this server is not already in the workgroup, add it. */ - create_server_on_workgroup(work, announce_name, - servertype|SV_TYPE_LOCAL_LIST_ONLY, - ttl, comment); - } - else - { - /* Update the record. */ - servrec->serv.type = servertype|SV_TYPE_LOCAL_LIST_ONLY; - update_server_ttl( servrec, ttl); - fstrcpy(servrec->serv.comment,comment); - } - } - else - { - /* - * This server is announcing it is going down. Remove it from the - * workgroup. - */ - if(!is_myname(announce_name) && (work != NULL) && - ((servrec = find_server_in_workgroup( work, announce_name))!=NULL) - ) - { - remove_server_from_workgroup( work, servrec); - } - } - - subrec->work_changed = True; - found_lm_clients = True; done: - END_PROFILE(lm_host_announce); + + END_PROFILE(lm_host_announce); } /**************************************************************************** Send a backup list response. *****************************************************************************/ + static void send_backup_list_response(struct subnet_record *subrec, struct work_record *work, struct nmb_name *send_to_name, @@ -553,40 +538,41 @@ static void send_backup_list_response(struct subnet_record *subrec, uint32 token, struct in_addr sendto_ip, int port) { - char outbuf[1024]; - char *p, *countptr; - unsigned int count = 0; + char outbuf[1024]; + char *p, *countptr; + unsigned int count = 0; + nstring send_to_namestr; #if 0 struct server_record *servrec; #endif - fstring myname; + fstring myname; - memset(outbuf,'\0',sizeof(outbuf)); + memset(outbuf,'\0',sizeof(outbuf)); - DEBUG(3,("send_backup_list_response: sending backup list for workgroup %s to %s IP %s\n", - work->work_group, nmb_namestr(send_to_name), inet_ntoa(sendto_ip))); + DEBUG(3,("send_backup_list_response: sending backup list for workgroup %s to %s IP %s\n", + work->work_group, nmb_namestr(send_to_name), inet_ntoa(sendto_ip))); - p = outbuf; + p = outbuf; - SCVAL(p,0,ANN_GetBackupListResp); /* Backup list response opcode. */ - p++; + SCVAL(p,0,ANN_GetBackupListResp); /* Backup list response opcode. */ + p++; - countptr = p; - p++; + countptr = p; + p++; - SIVAL(p,0,token); /* The sender's unique info. */ - p += 4; + SIVAL(p,0,token); /* The sender's unique info. */ + p += 4; - /* We always return at least one name - our own. */ - count = 1; - fstrcpy(myname, global_myname()); - strupper_m(myname); - myname[15]='\0'; - push_pstring_base(p, myname, outbuf); + /* We always return at least one name - our own. */ + count = 1; + fstrcpy(myname, global_myname()); + strupper_m(myname); + myname[15]='\0'; + push_pstring_base(p, myname, outbuf); - p = skip_string(p,1); + p = skip_string(p,1); - /* Look for backup browsers in this workgroup. */ + /* Look for backup browsers in this workgroup. */ #if 0 /* we don't currently send become_backup requests so we should never @@ -624,16 +610,18 @@ static void send_backup_list_response(struct subnet_record *subrec, } #endif - SCVAL(countptr, 0, count); + SCVAL(countptr, 0, count); + + pull_ascii_nstring(send_to_namestr, send_to_name->name); - DEBUG(4,("send_backup_list_response: sending response to %s<00> IP %s with %d servers.\n", - send_to_name->name, inet_ntoa(sendto_ip), count)); + DEBUG(4,("send_backup_list_response: sending response to %s<00> IP %s with %d servers.\n", + send_to_namestr, inet_ntoa(sendto_ip), count)); - send_mailslot(True, BROWSE_MAILSLOT, - outbuf,PTR_DIFF(p,outbuf), - global_myname(), 0, - send_to_name->name,0, - sendto_ip, subrec->myip, port); + send_mailslot(True, BROWSE_MAILSLOT, + outbuf,PTR_DIFF(p,outbuf), + global_myname(), 0, + send_to_namestr,0, + sendto_ip, subrec->myip, port); } /******************************************************************* @@ -649,80 +637,74 @@ static void send_backup_list_response(struct subnet_record *subrec, void process_get_backup_list_request(struct subnet_record *subrec, struct packet_struct *p,char *buf) { - struct dgram_packet *dgram = &p->packet.dgram; - struct work_record *work; - unsigned char max_number_requested = CVAL(buf,0); - uint32 token = IVAL(buf,1); /* Sender's key index for the workgroup. */ - int name_type = dgram->dest_name.name_type; - char *workgroup_name = dgram->dest_name.name; - struct subnet_record *search_subrec = subrec; - - START_PROFILE(get_backup_list); - DEBUG(3,("process_get_backup_list_request: request from %s IP %s to %s.\n", - nmb_namestr(&dgram->source_name), inet_ntoa(p->ip), - nmb_namestr(&dgram->dest_name))); + struct dgram_packet *dgram = &p->packet.dgram; + struct work_record *work; + unsigned char max_number_requested = CVAL(buf,0); + uint32 token = IVAL(buf,1); /* Sender's key index for the workgroup. */ + int name_type = dgram->dest_name.name_type; + nstring workgroup_name; + struct subnet_record *search_subrec = subrec; + + START_PROFILE(get_backup_list); + pull_ascii_nstring(workgroup_name, dgram->dest_name.name); + + DEBUG(3,("process_get_backup_list_request: request from %s IP %s to %s.\n", + nmb_namestr(&dgram->source_name), inet_ntoa(p->ip), + nmb_namestr(&dgram->dest_name))); - /* We have to be a master browser, or a domain master browser - for the requested workgroup. That means it must be our - workgroup. */ - - if(strequal(workgroup_name, lp_workgroup()) == False) - { - DEBUG(7,("process_get_backup_list_request: Ignoring announce request for workgroup %s.\n", - workgroup_name)); - goto done; - } - - if((work = find_workgroup_on_subnet(search_subrec, workgroup_name)) == NULL) - { - DEBUG(0,("process_get_backup_list_request: Cannot find workgroup %s on \ + /* We have to be a master browser, or a domain master browser + for the requested workgroup. That means it must be our + workgroup. */ + + if(strequal(workgroup_name, lp_workgroup()) == False) { + DEBUG(7,("process_get_backup_list_request: Ignoring announce request for workgroup %s.\n", + workgroup_name)); + goto done; + } + + if((work = find_workgroup_on_subnet(search_subrec, workgroup_name)) == NULL) { + DEBUG(0,("process_get_backup_list_request: Cannot find workgroup %s on \ subnet %s.\n", workgroup_name, search_subrec->subnet_name)); - goto done; - } + goto done; + } - /* - * If the packet was sent to WORKGROUP<1b> instead - * of WORKGROUP<1d> then it was unicast to us a domain master - * browser. Change search subrec to unicast. - */ + /* + * If the packet was sent to WORKGROUP<1b> instead + * of WORKGROUP<1d> then it was unicast to us a domain master + * browser. Change search subrec to unicast. + */ - if(name_type == 0x1b) - { - /* We must be a domain master browser in order to - process this packet. */ + if(name_type == 0x1b) { + /* We must be a domain master browser in order to + process this packet. */ - if(!AM_DOMAIN_MASTER_BROWSER(work)) - { - DEBUG(0,("process_get_backup_list_request: domain list requested for workgroup %s \ + if(!AM_DOMAIN_MASTER_BROWSER(work)) { + DEBUG(0,("process_get_backup_list_request: domain list requested for workgroup %s \ and I am not a domain master browser.\n", workgroup_name)); - goto done; - } + goto done; + } - search_subrec = unicast_subnet; - } - else if (name_type == 0x1d) - { - /* We must be a local master browser in order to - process this packet. */ + search_subrec = unicast_subnet; + } else if (name_type == 0x1d) { + /* We must be a local master browser in order to process this packet. */ - if(!AM_LOCAL_MASTER_BROWSER(work)) - { - DEBUG(0,("process_get_backup_list_request: domain list requested for workgroup %s \ + if(!AM_LOCAL_MASTER_BROWSER(work)) { + DEBUG(0,("process_get_backup_list_request: domain list requested for workgroup %s \ and I am not a local master browser.\n", workgroup_name)); - goto done; - } - } - else - { - DEBUG(0,("process_get_backup_list_request: Invalid name type %x - should be 0x1b or 0x1d.\n", - name_type)); - goto done; - } + goto done; + } + } else { + DEBUG(0,("process_get_backup_list_request: Invalid name type %x - should be 0x1b or 0x1d.\n", + name_type)); + goto done; + } + + send_backup_list_response(subrec, work, &dgram->source_name, + max_number_requested, token, p->ip, p->port); - send_backup_list_response(subrec, work, &dgram->source_name, - max_number_requested, token, p->ip, p->port); done: - END_PROFILE(get_backup_list); + + END_PROFILE(get_backup_list); } /******************************************************************* @@ -738,49 +720,46 @@ done: void process_reset_browser(struct subnet_record *subrec, struct packet_struct *p,char *buf) { - struct dgram_packet *dgram = &p->packet.dgram; - int state = CVAL(buf,0); - struct subnet_record *sr; + struct dgram_packet *dgram = &p->packet.dgram; + int state = CVAL(buf,0); + struct subnet_record *sr; - START_PROFILE(reset_browser); - DEBUG(1,("process_reset_browser: received diagnostic browser reset \ -request from %s IP %s state=0x%X\n", - nmb_namestr(&dgram->source_name), inet_ntoa(p->ip), state)); + START_PROFILE(reset_browser); - /* Stop being a local master browser on all our broadcast subnets. */ - if (state & 0x1) - { - for (sr = FIRST_SUBNET; sr; sr = NEXT_SUBNET_EXCLUDING_UNICAST(sr)) - { - struct work_record *work; - for (work = sr->workgrouplist; work; work = work->next) - { - if (AM_LOCAL_MASTER_BROWSER(work)) - unbecome_local_master_browser(sr, work, True); - } - } - } + DEBUG(1,("process_reset_browser: received diagnostic browser reset \ +request from %s IP %s state=0x%X\n", + nmb_namestr(&dgram->source_name), inet_ntoa(p->ip), state)); + + /* Stop being a local master browser on all our broadcast subnets. */ + if (state & 0x1) { + for (sr = FIRST_SUBNET; sr; sr = NEXT_SUBNET_EXCLUDING_UNICAST(sr)) { + struct work_record *work; + for (work = sr->workgrouplist; work; work = work->next) { + if (AM_LOCAL_MASTER_BROWSER(work)) + unbecome_local_master_browser(sr, work, True); + } + } + } - /* Discard our browse lists. */ - if (state & 0x2) - { - /* - * Calling expire_workgroups_and_servers with a -1 - * time causes all servers not marked with a PERMANENT_TTL - * on the workgroup lists to be discarded, and all - * workgroups with empty server lists to be discarded. - * This means we keep our own server names and workgroup - * as these have a PERMANENT_TTL. - */ - - expire_workgroups_and_servers(-1); - } + /* Discard our browse lists. */ + if (state & 0x2) { + /* + * Calling expire_workgroups_and_servers with a -1 + * time causes all servers not marked with a PERMANENT_TTL + * on the workgroup lists to be discarded, and all + * workgroups with empty server lists to be discarded. + * This means we keep our own server names and workgroup + * as these have a PERMANENT_TTL. + */ + + expire_workgroups_and_servers(-1); + } - /* Request to stop browsing altogether. */ - if (state & 0x4) - DEBUG(1,("process_reset_browser: ignoring request to stop being a browser.\n")); + /* Request to stop browsing altogether. */ + if (state & 0x4) + DEBUG(1,("process_reset_browser: ignoring request to stop being a browser.\n")); - END_PROFILE(reset_browser); + END_PROFILE(reset_browser); } /******************************************************************* @@ -793,33 +772,34 @@ request from %s IP %s state=0x%X\n", void process_announce_request(struct subnet_record *subrec, struct packet_struct *p, char *buf) { - struct dgram_packet *dgram = &p->packet.dgram; - struct work_record *work; - char *workgroup_name = dgram->dest_name.name; + struct dgram_packet *dgram = &p->packet.dgram; + struct work_record *work; + nstring workgroup_name; - START_PROFILE(announce_request); - DEBUG(3,("process_announce_request: Announce request from %s IP %s to %s.\n", - nmb_namestr(&dgram->source_name), inet_ntoa(p->ip), - nmb_namestr(&dgram->dest_name))); - - /* We only send announcement requests on our workgroup. */ - if(strequal(workgroup_name, lp_workgroup()) == False) - { - DEBUG(7,("process_announce_request: Ignoring announce request for workgroup %s.\n", - workgroup_name)); - goto done; - } - - if((work = find_workgroup_on_subnet(subrec, workgroup_name)) == NULL) - { - DEBUG(0,("process_announce_request: Unable to find workgroup %s on subnet !\n", - workgroup_name)); - goto done; - } + START_PROFILE(announce_request); - work->needannounce = True; + pull_ascii_nstring(workgroup_name, dgram->dest_name.name); + DEBUG(3,("process_announce_request: Announce request from %s IP %s to %s.\n", + nmb_namestr(&dgram->source_name), inet_ntoa(p->ip), + nmb_namestr(&dgram->dest_name))); + + /* We only send announcement requests on our workgroup. */ + if(strequal(workgroup_name, lp_workgroup()) == False) { + DEBUG(7,("process_announce_request: Ignoring announce request for workgroup %s.\n", + workgroup_name)); + goto done; + } + + if((work = find_workgroup_on_subnet(subrec, workgroup_name)) == NULL) { + DEBUG(0,("process_announce_request: Unable to find workgroup %s on subnet !\n", + workgroup_name)); + goto done; + } + + work->needannounce = True; done: - END_PROFILE(lm_host_announce); + + END_PROFILE(lm_host_announce); } /******************************************************************* @@ -833,30 +813,32 @@ done: void process_lm_announce_request(struct subnet_record *subrec, struct packet_struct *p, char *buf) { - struct dgram_packet *dgram = &p->packet.dgram; - char *workgroup_name = dgram->dest_name.name; + struct dgram_packet *dgram = &p->packet.dgram; + nstring workgroup_name; - START_PROFILE(lm_announce_request); - DEBUG(3,("process_lm_announce_request: Announce request from %s IP %s to %s.\n", - nmb_namestr(&dgram->source_name), inet_ntoa(p->ip), - nmb_namestr(&dgram->dest_name))); + START_PROFILE(lm_announce_request); - /* We only send announcement requests on our workgroup. */ - if(strequal(workgroup_name, lp_workgroup()) == False) - { - DEBUG(7,("process_lm_announce_request: Ignoring announce request for workgroup %s.\n", - workgroup_name)); - goto done; - } + pull_ascii_nstring(workgroup_name, dgram->dest_name.name); + DEBUG(3,("process_lm_announce_request: Announce request from %s IP %s to %s.\n", + nmb_namestr(&dgram->source_name), inet_ntoa(p->ip), + nmb_namestr(&dgram->dest_name))); - if(find_workgroup_on_subnet(subrec, workgroup_name) == NULL) - { - DEBUG(0,("process_announce_request: Unable to find workgroup %s on subnet !\n", - workgroup_name)); - goto done; - } + /* We only send announcement requests on our workgroup. */ + if(strequal(workgroup_name, lp_workgroup()) == False) { + DEBUG(7,("process_lm_announce_request: Ignoring announce request for workgroup %s.\n", + workgroup_name)); + goto done; + } + + if(find_workgroup_on_subnet(subrec, workgroup_name) == NULL) { + DEBUG(0,("process_announce_request: Unable to find workgroup %s on subnet !\n", + workgroup_name)); + goto done; + } + + found_lm_clients = True; - found_lm_clients = True; done: - END_PROFILE(lm_host_announce); + + END_PROFILE(lm_host_announce); } diff --git a/source3/nmbd/nmbd_incomingrequests.c b/source3/nmbd/nmbd_incomingrequests.c index a3faf5e104..dd999fbdf7 100644 --- a/source3/nmbd/nmbd_incomingrequests.c +++ b/source3/nmbd/nmbd_incomingrequests.c @@ -3,7 +3,7 @@ NBT netbios routines and daemon - version 2 Copyright (C) Andrew Tridgell 1994-1998 Copyright (C) Luke Kenneth Casson Leighton 1994-1998 - Copyright (C) Jeremy Allison 1994-1998 + Copyright (C) Jeremy Allison 1994-2003 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -33,18 +33,18 @@ Send a name release response. static void send_name_release_response(int rcode, struct packet_struct *p) { - struct nmb_packet *nmb = &p->packet.nmb; - char rdata[6]; + struct nmb_packet *nmb = &p->packet.nmb; + char rdata[6]; - memcpy(&rdata[0], &nmb->additional->rdata[0], 6); + memcpy(&rdata[0], &nmb->additional->rdata[0], 6); - reply_netbios_packet(p, /* Packet to reply to. */ - rcode, /* Result code. */ - NMB_REL, /* nmbd type code. */ - NMB_NAME_RELEASE_OPCODE, /* opcode. */ - 0, /* ttl. */ - rdata, /* data to send. */ - 6); /* data length. */ + reply_netbios_packet(p, /* Packet to reply to. */ + rcode, /* Result code. */ + NMB_REL, /* nmbd type code. */ + NMB_NAME_RELEASE_OPCODE, /* opcode. */ + 0, /* ttl. */ + rdata, /* data to send. */ + 6); /* data length. */ } /**************************************************************************** @@ -55,76 +55,74 @@ Ignore it if it's not one of our names. void process_name_release_request(struct subnet_record *subrec, struct packet_struct *p) { - struct nmb_packet *nmb = &p->packet.nmb; - struct in_addr owner_ip; - struct nmb_name *question = &nmb->question.question_name; - BOOL bcast = nmb->header.nm_flags.bcast; - uint16 nb_flags = get_nb_flags(nmb->additional->rdata); - BOOL group = (nb_flags & NB_GROUP) ? True : False; - struct name_record *namerec; - int rcode = 0; + struct nmb_packet *nmb = &p->packet.nmb; + struct in_addr owner_ip; + struct nmb_name *question = &nmb->question.question_name; + nstring qname; + BOOL bcast = nmb->header.nm_flags.bcast; + uint16 nb_flags = get_nb_flags(nmb->additional->rdata); + BOOL group = (nb_flags & NB_GROUP) ? True : False; + struct name_record *namerec; + int rcode = 0; - putip((char *)&owner_ip,&nmb->additional->rdata[2]); + putip((char *)&owner_ip,&nmb->additional->rdata[2]); - if(!bcast) - { - /* We should only get broadcast name release packets here. - Anyone trying to release unicast should be going to a WINS - server. If the code gets here, then either we are not a wins - server and they sent it anyway, or we are a WINS server and - the request was malformed. Either way, log an error here. - and send an error reply back. - */ - DEBUG(0,("process_name_release_request: unicast name release request \ + if(!bcast) { + /* We should only get broadcast name release packets here. + Anyone trying to release unicast should be going to a WINS + server. If the code gets here, then either we are not a wins + server and they sent it anyway, or we are a WINS server and + the request was malformed. Either way, log an error here. + and send an error reply back. + */ + DEBUG(0,("process_name_release_request: unicast name release request \ received for name %s from IP %s on subnet %s. Error - should be sent to WINS server\n", - nmb_namestr(question), inet_ntoa(owner_ip), subrec->subnet_name)); + nmb_namestr(question), inet_ntoa(owner_ip), subrec->subnet_name)); - send_name_release_response(FMT_ERR, p); - return; - } + send_name_release_response(FMT_ERR, p); + return; + } - DEBUG(3,("process_name_release_request: Name release on name %s, \ + DEBUG(3,("process_name_release_request: Name release on name %s, \ subnet %s from owner IP %s\n", - nmb_namestr(&nmb->question.question_name), - subrec->subnet_name, inet_ntoa(owner_ip))); + nmb_namestr(&nmb->question.question_name), + subrec->subnet_name, inet_ntoa(owner_ip))); - /* If someone is releasing a broadcast group name, just ignore it. */ - if( group && !ismyip(owner_ip) ) - return; - - /* - * Code to work around a bug in FTP OnNet software NBT implementation. - * They do a broadcast name release for WORKGROUP<0> and WORKGROUP<1e> - * names and *don't set the group bit* !!!!! - */ - - if( !group && !ismyip(owner_ip) && strequal(question->name, lp_workgroup()) && - ((question->name_type == 0x0) || (question->name_type == 0x1e))) - { - DEBUG(6,("process_name_release_request: FTP OnNet bug workaround. Ignoring \ + /* If someone is releasing a broadcast group name, just ignore it. */ + if( group && !ismyip(owner_ip) ) + return; + + /* + * Code to work around a bug in FTP OnNet software NBT implementation. + * They do a broadcast name release for WORKGROUP<0> and WORKGROUP<1e> + * names and *don't set the group bit* !!!!! + */ + + pull_ascii_nstring(qname, question->name); + if( !group && !ismyip(owner_ip) && strequal(qname, lp_workgroup()) && + ((question->name_type == 0x0) || (question->name_type == 0x1e))) { + DEBUG(6,("process_name_release_request: FTP OnNet bug workaround. Ignoring \ group release name %s from IP %s on subnet %s with no group bit set.\n", - nmb_namestr(question), inet_ntoa(owner_ip), subrec->subnet_name )); - return; - } - - namerec = find_name_on_subnet(subrec, &nmb->question.question_name, FIND_ANY_NAME); - - /* We only care about someone trying to release one of our names. */ - if( namerec - && ( (namerec->data.source == SELF_NAME) - || (namerec->data.source == PERMANENT_NAME) ) ) - { - rcode = ACT_ERR; - DEBUG(0, ("process_name_release_request: Attempt to release name %s from IP %s \ + nmb_namestr(question), inet_ntoa(owner_ip), subrec->subnet_name )); + return; + } + + namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME); + + /* We only care about someone trying to release one of our names. */ + if( namerec && ( (namerec->data.source == SELF_NAME) + || (namerec->data.source == PERMANENT_NAME) ) ) { + rcode = ACT_ERR; + DEBUG(0, ("process_name_release_request: Attempt to release name %s from IP %s \ on subnet %s being rejected as it is one of our names.\n", - nmb_namestr(&nmb->question.question_name), inet_ntoa(owner_ip), subrec->subnet_name)); - } + nmb_namestr(&nmb->question.question_name), inet_ntoa(owner_ip), subrec->subnet_name)); + } - if(rcode == 0) - return; + if(rcode == 0) + return; - /* Send a NAME RELEASE RESPONSE (pos/neg) see rfc1002.txt 4.2.10-11 */ - send_name_release_response(rcode, p); + /* Send a NAME RELEASE RESPONSE (pos/neg) see rfc1002.txt 4.2.10-11 */ + send_name_release_response(rcode, p); } /**************************************************************************** @@ -133,18 +131,18 @@ Send a name registration response. static void send_name_registration_response(int rcode, int ttl, struct packet_struct *p) { - struct nmb_packet *nmb = &p->packet.nmb; - char rdata[6]; + struct nmb_packet *nmb = &p->packet.nmb; + char rdata[6]; - memcpy(&rdata[0], &nmb->additional->rdata[0], 6); + memcpy(&rdata[0], &nmb->additional->rdata[0], 6); - reply_netbios_packet(p, /* Packet to reply to. */ - rcode, /* Result code. */ - NMB_REG, /* nmbd type code. */ - NMB_NAME_REG_OPCODE, /* opcode. */ - ttl, /* ttl. */ - rdata, /* data to send. */ - 6); /* data length. */ + reply_netbios_packet(p, /* Packet to reply to. */ + rcode, /* Result code. */ + NMB_REG, /* nmbd type code. */ + NMB_NAME_REG_OPCODE, /* opcode. */ + ttl, /* ttl. */ + rdata, /* data to send. */ + 6); /* data length. */ } /**************************************************************************** @@ -154,38 +152,34 @@ Process a name refresh request on a broadcast subnet. void process_name_refresh_request(struct subnet_record *subrec, struct packet_struct *p) { - - struct nmb_packet *nmb = &p->packet.nmb; - struct nmb_name *question = &nmb->question.question_name; - BOOL bcast = nmb->header.nm_flags.bcast; - struct in_addr from_ip; + struct nmb_packet *nmb = &p->packet.nmb; + struct nmb_name *question = &nmb->question.question_name; + BOOL bcast = nmb->header.nm_flags.bcast; + struct in_addr from_ip; - putip((char *)&from_ip,&nmb->additional->rdata[2]); - - if(!bcast) - { - /* We should only get broadcast name refresh packets here. - Anyone trying to refresh unicast should be going to a WINS - server. If the code gets here, then either we are not a wins - server and they sent it anyway, or we are a WINS server and - the request was malformed. Either way, log an error here. - and send an error reply back. - */ - DEBUG(0,("process_name_refresh_request: unicast name registration request \ + putip((char *)&from_ip,&nmb->additional->rdata[2]); + + if(!bcast) { + /* We should only get broadcast name refresh packets here. + Anyone trying to refresh unicast should be going to a WINS + server. If the code gets here, then either we are not a wins + server and they sent it anyway, or we are a WINS server and + the request was malformed. Either way, log an error here. + and send an error reply back. + */ + DEBUG(0,("process_name_refresh_request: unicast name registration request \ received for name %s from IP %s on subnet %s.\n", - nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name)); - DEBUG(0,("Error - should be sent to WINS server\n")); + nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name)); + DEBUG(0,("Error - should be sent to WINS server\n")); - send_name_registration_response(FMT_ERR, 0, p); - return; - } + send_name_registration_response(FMT_ERR, 0, p); + return; + } - /* Just log a message. We really don't care about broadcast name - refreshes. */ + /* Just log a message. We really don't care about broadcast name refreshes. */ - DEBUG(3,("process_name_refresh_request: Name refresh for name %s \ + DEBUG(3,("process_name_refresh_request: Name refresh for name %s \ IP %s on subnet %s\n", nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name)); - } /**************************************************************************** @@ -195,92 +189,83 @@ Process a name registration request on a broadcast subnet. void process_name_registration_request(struct subnet_record *subrec, struct packet_struct *p) { - struct nmb_packet *nmb = &p->packet.nmb; - struct nmb_name *question = &nmb->question.question_name; - BOOL bcast = nmb->header.nm_flags.bcast; - uint16 nb_flags = get_nb_flags(nmb->additional->rdata); - BOOL group = (nb_flags & NB_GROUP) ? True : False; - struct name_record *namerec = NULL; - int ttl = nmb->additional->ttl; - struct in_addr from_ip; + struct nmb_packet *nmb = &p->packet.nmb; + struct nmb_name *question = &nmb->question.question_name; + BOOL bcast = nmb->header.nm_flags.bcast; + uint16 nb_flags = get_nb_flags(nmb->additional->rdata); + BOOL group = (nb_flags & NB_GROUP) ? True : False; + struct name_record *namerec = NULL; + int ttl = nmb->additional->ttl; + struct in_addr from_ip; - putip((char *)&from_ip,&nmb->additional->rdata[2]); + putip((char *)&from_ip,&nmb->additional->rdata[2]); - if(!bcast) - { - /* We should only get broadcast name registration packets here. - Anyone trying to register unicast should be going to a WINS - server. If the code gets here, then either we are not a wins - server and they sent it anyway, or we are a WINS server and - the request was malformed. Either way, log an error here. - and send an error reply back. - */ - DEBUG(0,("process_name_registration_request: unicast name registration request \ + if(!bcast) { + /* We should only get broadcast name registration packets here. + Anyone trying to register unicast should be going to a WINS + server. If the code gets here, then either we are not a wins + server and they sent it anyway, or we are a WINS server and + the request was malformed. Either way, log an error here. + and send an error reply back. + */ + DEBUG(0,("process_name_registration_request: unicast name registration request \ received for name %s from IP %s on subnet %s. Error - should be sent to WINS server\n", - nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name)); + nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name)); - send_name_registration_response(FMT_ERR, 0, p); - return; - } + send_name_registration_response(FMT_ERR, 0, p); + return; + } - DEBUG(3,("process_name_registration_request: Name registration for name %s \ + DEBUG(3,("process_name_registration_request: Name registration for name %s \ IP %s on subnet %s\n", nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name)); - /* See if the name already exists. */ - namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME); + /* See if the name already exists. */ + namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME); - /* - * If the name being registered exists and is a WINS_PROXY_NAME - * then delete the WINS proxy name entry so we don't reply erroneously - * later to queries. - */ - - if((namerec != NULL) && (namerec->data.source == WINS_PROXY_NAME)) - { - remove_name_from_namelist( subrec, namerec ); - namerec = NULL; - } - - if (!group) - { - /* Unique name. */ - - if( (namerec != NULL) - && ( (namerec->data.source == SELF_NAME) - || (namerec->data.source == PERMANENT_NAME) - || NAME_GROUP(namerec) ) ) - { - /* No-one can register one of Samba's names, nor can they - register a name that's a group name as a unique name */ - - send_name_registration_response(ACT_ERR, 0, p); - return; - } - else if(namerec != NULL) - { - /* Update the namelist record with the new information. */ - namerec->data.ip[0] = from_ip; - update_name_ttl(namerec, ttl); - - DEBUG(3,("process_name_registration_request: Updated name record %s \ + /* + * If the name being registered exists and is a WINS_PROXY_NAME + * then delete the WINS proxy name entry so we don't reply erroneously + * later to queries. + */ + + if((namerec != NULL) && (namerec->data.source == WINS_PROXY_NAME)) { + remove_name_from_namelist( subrec, namerec ); + namerec = NULL; + } + + if (!group) { + /* Unique name. */ + + if( (namerec != NULL) + && ( (namerec->data.source == SELF_NAME) + || (namerec->data.source == PERMANENT_NAME) + || NAME_GROUP(namerec) ) ) { + /* No-one can register one of Samba's names, nor can they + register a name that's a group name as a unique name */ + + send_name_registration_response(ACT_ERR, 0, p); + return; + } else if(namerec != NULL) { + /* Update the namelist record with the new information. */ + namerec->data.ip[0] = from_ip; + update_name_ttl(namerec, ttl); + + DEBUG(3,("process_name_registration_request: Updated name record %s \ with IP %s on subnet %s\n",nmb_namestr(&namerec->name),inet_ntoa(from_ip), subrec->subnet_name)); - return; - } - } - else - { - /* Group name. */ - - if( (namerec != NULL) - && !NAME_GROUP(namerec) - && ( (namerec->data.source == SELF_NAME) - || (namerec->data.source == PERMANENT_NAME) ) ) - { - /* Disallow group names when we have a unique name. */ - send_name_registration_response(ACT_ERR, 0, p); - return; - } - } + return; + } + } else { + /* Group name. */ + + if( (namerec != NULL) + && !NAME_GROUP(namerec) + && ( (namerec->data.source == SELF_NAME) + || (namerec->data.source == PERMANENT_NAME) ) ) { + /* Disallow group names when we have a unique name. */ + send_name_registration_response(ACT_ERR, 0, p); + return; + } + } } /**************************************************************************** @@ -290,147 +275,150 @@ We put our own names first, then in alphabetical order. static int status_compare(char *n1,char *n2) { - int l1,l2,l3; - - /* It's a bit tricky because the names are space padded */ - for (l1=0;l1<15 && n1[l1] && n1[l1] != ' ';l1++) ; - for (l2=0;l2<15 && n2[l2] && n2[l2] != ' ';l2++) ; - l3 = strlen(global_myname()); - - if ((l1==l3) && strncmp(n1,global_myname(),l3) == 0 && - (l2!=l3 || strncmp(n2,global_myname(),l3) != 0)) - return -1; - - if ((l2==l3) && strncmp(n2,global_myname(),l3) == 0 && - (l1!=l3 || strncmp(n1,global_myname(),l3) != 0)) - return 1; - - return memcmp(n1,n2,18); + nstring name1, name2; + int l1,l2,l3; + + pull_ascii_nstring(name1, n1); + pull_ascii_nstring(name2, n2); + n1 = name1; + n2 = name2; + + /* It's a bit tricky because the names are space padded */ + for (l1=0;l1<15 && n1[l1] && n1[l1] != ' ';l1++) + ; + for (l2=0;l2<15 && n2[l2] && n2[l2] != ' ';l2++) + ; + l3 = strlen(global_myname()); + + if ((l1==l3) && strncmp(n1,global_myname(),l3) == 0 && + (l2!=l3 || strncmp(n2,global_myname(),l3) != 0)) + return -1; + + if ((l2==l3) && strncmp(n2,global_myname(),l3) == 0 && + (l1!=l3 || strncmp(n1,global_myname(),l3) != 0)) + return 1; + + return memcmp(n1,n2,sizeof(nstring)); } - /**************************************************************************** Process a node status query ****************************************************************************/ void process_node_status_request(struct subnet_record *subrec, struct packet_struct *p) { - struct nmb_packet *nmb = &p->packet.nmb; - char *qname = nmb->question.question_name.name; - int ques_type = nmb->question.question_name.name_type; - char rdata[MAX_DGRAM_SIZE]; - char *countptr, *buf, *bufend, *buf0; - int names_added,i; - struct name_record *namerec; - - DEBUG(3,("process_node_status_request: status request for name %s from IP %s on \ -subnet %s.\n", nmb_namestr(&nmb->question.question_name), inet_ntoa(p->ip), - subrec->subnet_name)); - - if((namerec = find_name_on_subnet(subrec, &nmb->question.question_name, - FIND_SELF_NAME)) == 0) - { - DEBUG(1,("process_node_status_request: status request for name %s from IP %s on \ + struct nmb_packet *nmb = &p->packet.nmb; + nstring qname; + int ques_type = nmb->question.question_name.name_type; + char rdata[MAX_DGRAM_SIZE]; + char *countptr, *buf, *bufend, *buf0; + int names_added,i; + struct name_record *namerec; + + pull_ascii_nstring(qname, nmb->question.question_name.name); + + DEBUG(3,("process_node_status_request: status request for name %s from IP %s on \ +subnet %s.\n", nmb_namestr(&nmb->question.question_name), inet_ntoa(p->ip), subrec->subnet_name)); + + if((namerec = find_name_on_subnet(subrec, &nmb->question.question_name, FIND_SELF_NAME)) == 0) { + DEBUG(1,("process_node_status_request: status request for name %s from IP %s on \ subnet %s - name not found.\n", nmb_namestr(&nmb->question.question_name), - inet_ntoa(p->ip), subrec->subnet_name)); + inet_ntoa(p->ip), subrec->subnet_name)); - return; - } + return; + } - /* this is not an exact calculation. the 46 is for the stats buffer - and the 60 is to leave room for the header etc */ - bufend = &rdata[MAX_DGRAM_SIZE] - (18 + 46 + 60); - countptr = buf = rdata; - buf += 1; - buf0 = buf; - - names_added = 0; - - namerec = (struct name_record *)ubi_trFirst( subrec->namelist ); - - while (buf < bufend) - { - if( (namerec->data.source == SELF_NAME) - || (namerec->data.source == PERMANENT_NAME) ) - { - int name_type = namerec->name.name_type; - - if (!strequal(namerec->name.name,"*") && - !strequal(namerec->name.name,"__SAMBA__") && - (name_type < 0x1b || name_type >= 0x20 || - ques_type < 0x1b || ques_type >= 0x20 || - strequal(qname, namerec->name.name))) - { - /* Start with the name. */ - memset(buf,'\0',18); - slprintf(buf, 17, "%-15.15s",namerec->name.name); - strupper_m(buf); - - /* Put the name type and netbios flags in the buffer. */ - buf[15] = name_type; - set_nb_flags( &buf[16],namerec->data.nb_flags ); - buf[16] |= NB_ACTIVE; /* all our names are active */ - - buf += 18; - - names_added++; - } - } - - /* Remove duplicate names. */ - if (names_added > 1) { - qsort( buf0, names_added, 18, QSORT_CAST status_compare ); - } - - for( i=1; i < names_added ; i++ ) - { - if (memcmp(buf0 + 18*i,buf0 + 18*(i-1),16) == 0) - { - names_added--; - if (names_added == i) - break; - memmove(buf0 + 18*i,buf0 + 18*(i+1),18*(names_added-i)); - i--; - } - } - - buf = buf0 + 18*names_added; - - namerec = (struct name_record *)ubi_trNext( namerec ); - - if (!namerec) - { - /* End of the subnet specific name list. Now - add the names on the unicast subnet . */ - struct subnet_record *uni_subrec = unicast_subnet; - - if (uni_subrec != subrec) - { - subrec = uni_subrec; - namerec = (struct name_record *)ubi_trFirst( subrec->namelist ); - } - } - if (!namerec) - break; - - } + /* this is not an exact calculation. the 46 is for the stats buffer + and the 60 is to leave room for the header etc */ + bufend = &rdata[MAX_DGRAM_SIZE] - (18 + 46 + 60); + countptr = buf = rdata; + buf += 1; + buf0 = buf; + + names_added = 0; + + namerec = (struct name_record *)ubi_trFirst( subrec->namelist ); + + while (buf < bufend) { + if( (namerec->data.source == SELF_NAME) || (namerec->data.source == PERMANENT_NAME) ) { + int name_type = namerec->name.name_type; + nstring name; + + pull_ascii_nstring(name, namerec->name.name); + strupper_m(name); + if (!strequal(name,"*") && + !strequal(name,"__SAMBA__") && + (name_type < 0x1b || name_type >= 0x20 || + ques_type < 0x1b || ques_type >= 0x20 || + strequal(qname, name))) { + /* Start with the name. */ + nstring tmp_name; + memset(tmp_name,'\0',sizeof(tmp_name)); + snprintf(tmp_name, sizeof(tmp_name), "%-15.15s",name); + push_ascii_nstring(buf, tmp_name); + + /* Put the name type and netbios flags in the buffer. */ + + buf[15] = name_type; + set_nb_flags( &buf[16],namerec->data.nb_flags ); + buf[16] |= NB_ACTIVE; /* all our names are active */ + + buf += 18; + + names_added++; + } + } + + /* Remove duplicate names. */ + if (names_added > 1) { + qsort( buf0, names_added, 18, QSORT_CAST status_compare ); + } + + for( i=1; i < names_added ; i++ ) { + if (memcmp(buf0 + 18*i,buf0 + 18*(i-1),16) == 0) { + names_added--; + if (names_added == i) + break; + memmove(buf0 + 18*i,buf0 + 18*(i+1),18*(names_added-i)); + i--; + } + } + + buf = buf0 + 18*names_added; + + namerec = (struct name_record *)ubi_trNext( namerec ); + + if (!namerec) { + /* End of the subnet specific name list. Now + add the names on the unicast subnet . */ + struct subnet_record *uni_subrec = unicast_subnet; + + if (uni_subrec != subrec) { + subrec = uni_subrec; + namerec = (struct name_record *)ubi_trFirst( subrec->namelist ); + } + } + if (!namerec) + break; + + } - SCVAL(countptr,0,names_added); + SCVAL(countptr,0,names_added); - /* We don't send any stats as they could be used to attack - the protocol. */ - memset(buf,'\0',46); + /* We don't send any stats as they could be used to attack + the protocol. */ + memset(buf,'\0',46); - buf += 46; + buf += 46; - /* Send a NODE STATUS RESPONSE */ - reply_netbios_packet(p, /* Packet to reply to. */ - 0, /* Result code. */ - NMB_STATUS, /* nmbd type code. */ - NMB_NAME_QUERY_OPCODE, /* opcode. */ - 0, /* ttl. */ - rdata, /* data to send. */ - PTR_DIFF(buf,rdata)); /* data length. */ + /* Send a NODE STATUS RESPONSE */ + reply_netbios_packet(p, /* Packet to reply to. */ + 0, /* Result code. */ + NMB_STATUS, /* nmbd type code. */ + NMB_NAME_QUERY_OPCODE, /* opcode. */ + 0, /* ttl. */ + rdata, /* data to send. */ + PTR_DIFF(buf,rdata)); /* data length. */ } diff --git a/source3/nmbd/nmbd_lmhosts.c b/source3/nmbd/nmbd_lmhosts.c index 3c067d8ed4..b14e13f3a4 100644 --- a/source3/nmbd/nmbd_lmhosts.c +++ b/source3/nmbd/nmbd_lmhosts.c @@ -28,50 +28,46 @@ /**************************************************************************** Load a lmhosts file. ****************************************************************************/ + void load_lmhosts_file(char *fname) { - pstring name; - int name_type; - struct in_addr ipaddr; - XFILE *fp = startlmhosts( fname ); - - if (!fp) { - DEBUG(2,("load_lmhosts_file: Can't open lmhosts file %s. Error was %s\n", - fname, strerror(errno))); - return; - } + pstring name; + int name_type; + struct in_addr ipaddr; + XFILE *fp = startlmhosts( fname ); + + if (!fp) { + DEBUG(2,("load_lmhosts_file: Can't open lmhosts file %s. Error was %s\n", + fname, strerror(errno))); + return; + } - while (getlmhostsent(fp, name, &name_type, &ipaddr) ) - { - struct subnet_record *subrec = NULL; - enum name_source source = LMHOSTS_NAME; - - /* We find a relevent subnet to put this entry on, then add it. */ - /* Go through all the broadcast subnets and see if the mask matches. */ - for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) - { - if(same_net(ipaddr, subrec->bcast_ip, subrec->mask_ip)) - break; - } + while (getlmhostsent(fp, name, &name_type, &ipaddr) ) { + struct subnet_record *subrec = NULL; + enum name_source source = LMHOSTS_NAME; + + /* We find a relevent subnet to put this entry on, then add it. */ + /* Go through all the broadcast subnets and see if the mask matches. */ + for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) { + if(same_net(ipaddr, subrec->bcast_ip, subrec->mask_ip)) + break; + } - /* If none match add the name to the remote_broadcast_subnet. */ - if(subrec == NULL) - subrec = remote_broadcast_subnet; - - if(name_type == -1) - { - /* Add the (0) and (0x20) names directly into the namelist for this subnet. */ - (void)add_name_to_subnet(subrec,name,0x00,(uint16)NB_ACTIVE,PERMANENT_TTL,source,1,&ipaddr); - (void)add_name_to_subnet(subrec,name,0x20,(uint16)NB_ACTIVE,PERMANENT_TTL,source,1,&ipaddr); - } - else - { - /* Add the given name type to the subnet namelist. */ - (void)add_name_to_subnet(subrec,name,name_type,(uint16)NB_ACTIVE,PERMANENT_TTL,source,1,&ipaddr); - } - } + /* If none match add the name to the remote_broadcast_subnet. */ + if(subrec == NULL) + subrec = remote_broadcast_subnet; + + if(name_type == -1) { + /* Add the (0) and (0x20) names directly into the namelist for this subnet. */ + (void)add_name_to_subnet(subrec,name,0x00,(uint16)NB_ACTIVE,PERMANENT_TTL,source,1,&ipaddr); + (void)add_name_to_subnet(subrec,name,0x20,(uint16)NB_ACTIVE,PERMANENT_TTL,source,1,&ipaddr); + } else { + /* Add the given name type to the subnet namelist. */ + (void)add_name_to_subnet(subrec,name,name_type,(uint16)NB_ACTIVE,PERMANENT_TTL,source,1,&ipaddr); + } + } - endlmhosts(fp); + endlmhosts(fp); } /**************************************************************************** @@ -82,17 +78,16 @@ void load_lmhosts_file(char *fname) BOOL find_name_in_lmhosts(struct nmb_name *nmbname, struct name_record **namerecp) { - struct name_record *namerec; + struct name_record *namerec; - *namerecp = NULL; + *namerecp = NULL; - if((namerec = find_name_on_subnet(remote_broadcast_subnet, nmbname, - FIND_ANY_NAME))==NULL) - return False; + if((namerec = find_name_on_subnet(remote_broadcast_subnet, nmbname, FIND_ANY_NAME))==NULL) + return False; - if(!NAME_IS_ACTIVE(namerec) || (namerec->data.source != LMHOSTS_NAME)) - return False; + if(!NAME_IS_ACTIVE(namerec) || (namerec->data.source != LMHOSTS_NAME)) + return False; - *namerecp = namerec; - return True; + *namerecp = namerec; + return True; } diff --git a/source3/nmbd/nmbd_logonnames.c b/source3/nmbd/nmbd_logonnames.c index b73586aa45..f79fc56f7b 100644 --- a/source3/nmbd/nmbd_logonnames.c +++ b/source3/nmbd/nmbd_logonnames.c @@ -3,7 +3,7 @@ NBT netbios routines and daemon - version 2 Copyright (C) Andrew Tridgell 1994-1998 Copyright (C) Luke Kenneth Casson Leighton 1994-1998 - Copyright (C) Jeremy Allison 1994-1998 + Copyright (C) Jeremy Allison 1994-2003 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -29,38 +29,40 @@ extern uint16 samba_nb_type; /* Samba's NetBIOS type. */ /**************************************************************************** Fail to become a Logon server on a subnet. - ****************************************************************************/ +****************************************************************************/ + static void become_logon_server_fail(struct subnet_record *subrec, struct response_record *rrec, struct nmb_name *fail_name) { - struct work_record *work = find_workgroup_on_subnet(subrec, fail_name->name); - struct server_record *servrec; - - if(!work) - { - DEBUG(0,("become_logon_server_fail: Error - cannot find \ -workgroup %s on subnet %s\n", fail_name->name, subrec->subnet_name)); - return; - } - - if((servrec = find_server_in_workgroup( work, global_myname())) == NULL) - { - DEBUG(0,("become_logon_server_fail: Error - cannot find server %s \ + nstring failname; + struct work_record *work; + struct server_record *servrec; + + pull_ascii_nstring(failname, fail_name->name); + work = find_workgroup_on_subnet(subrec, failname); + if(!work) { + DEBUG(0,("become_logon_server_fail: Error - cannot find \ +workgroup %s on subnet %s\n", failname, subrec->subnet_name)); + return; + } + + if((servrec = find_server_in_workgroup( work, global_myname())) == NULL) { + DEBUG(0,("become_logon_server_fail: Error - cannot find server %s \ in workgroup %s on subnet %s\n", - global_myname(), fail_name->name, subrec->subnet_name)); - work->log_state = LOGON_NONE; - return; - } + global_myname(), failname, subrec->subnet_name)); + work->log_state = LOGON_NONE; + return; + } - /* Set the state back to LOGON_NONE. */ - work->log_state = LOGON_NONE; + /* Set the state back to LOGON_NONE. */ + work->log_state = LOGON_NONE; - servrec->serv.type &= ~SV_TYPE_DOMAIN_CTRL; + servrec->serv.type &= ~SV_TYPE_DOMAIN_CTRL; - DEBUG(0,("become_logon_server_fail: Failed to become a domain master for \ + DEBUG(0,("become_logon_server_fail: Failed to become a domain master for \ workgroup %s on subnet %s. Couldn't register name %s.\n", - work->work_group, subrec->subnet_name, nmb_namestr(fail_name))); + work->work_group, subrec->subnet_name, nmb_namestr(fail_name))); } @@ -74,49 +76,51 @@ static void become_logon_server_success(struct subnet_record *subrec, uint16 nb_flags, int ttl, struct in_addr registered_ip) { - struct work_record *work = find_workgroup_on_subnet( subrec, registered_name->name); - struct server_record *servrec; - - if(!work) - { - DEBUG(0,("become_logon_server_success: Error - cannot find \ -workgroup %s on subnet %s\n", registered_name->name, subrec->subnet_name)); - return; - } - - if((servrec = find_server_in_workgroup( work, global_myname())) == NULL) - { - DEBUG(0,("become_logon_server_success: Error - cannot find server %s \ + nstring reg_name; + struct work_record *work; + struct server_record *servrec; + + pull_ascii_nstring(reg_name, registered_name->name); + work = find_workgroup_on_subnet( subrec, reg_name); + if(!work) { + DEBUG(0,("become_logon_server_success: Error - cannot find \ +workgroup %s on subnet %s\n", reg_name, subrec->subnet_name)); + return; + } + + if((servrec = find_server_in_workgroup( work, global_myname())) == NULL) { + DEBUG(0,("become_logon_server_success: Error - cannot find server %s \ in workgroup %s on subnet %s\n", - global_myname(), registered_name->name, subrec->subnet_name)); - work->log_state = LOGON_NONE; - return; - } - - /* Set the state in the workgroup structure. */ - work->log_state = LOGON_SRV; /* Become domain master. */ - - /* Update our server status. */ - servrec->serv.type |= (SV_TYPE_NT|SV_TYPE_DOMAIN_MEMBER); - /* To allow Win95 policies to load we need to set type domain - controller. - */ - servrec->serv.type |= SV_TYPE_DOMAIN_CTRL; - - /* Tell the namelist writer to write out a change. */ - subrec->work_changed = True; - - /* - * Add the WORKGROUP<1C> name to the UNICAST subnet with the IP address - * for this subnet so we will respond to queries on this name. - */ - { - struct nmb_name nmbname; - make_nmb_name(&nmbname,lp_workgroup(),0x1c); - insert_permanent_name_into_unicast(subrec, &nmbname, 0x1c); - } - - DEBUG(0,("become_logon_server_success: Samba is now a logon server \ + global_myname(), reg_name, subrec->subnet_name)); + work->log_state = LOGON_NONE; + return; + } + + /* Set the state in the workgroup structure. */ + work->log_state = LOGON_SRV; /* Become domain master. */ + + /* Update our server status. */ + servrec->serv.type |= (SV_TYPE_NT|SV_TYPE_DOMAIN_MEMBER); + /* To allow Win95 policies to load we need to set type domain + controller. + */ + servrec->serv.type |= SV_TYPE_DOMAIN_CTRL; + + /* Tell the namelist writer to write out a change. */ + subrec->work_changed = True; + + /* + * Add the WORKGROUP<1C> name to the UNICAST subnet with the IP address + * for this subnet so we will respond to queries on this name. + */ + + { + struct nmb_name nmbname; + make_nmb_name(&nmbname,lp_workgroup(),0x1c); + insert_permanent_name_into_unicast(subrec, &nmbname, 0x1c); + } + + DEBUG(0,("become_logon_server_success: Samba is now a logon server \ for workgroup %s on subnet %s\n", work->work_group, subrec->subnet_name)); } @@ -128,45 +132,42 @@ for workgroup %s on subnet %s\n", work->work_group, subrec->subnet_name)); static void become_logon_server(struct subnet_record *subrec, struct work_record *work) { - DEBUG(2,("become_logon_server: Atempting to become logon server for workgroup %s \ + DEBUG(2,("become_logon_server: Atempting to become logon server for workgroup %s \ on subnet %s\n", work->work_group,subrec->subnet_name)); - DEBUG(3,("become_logon_server: go to first stage: register %s<1c> name\n", - work->work_group)); - work->log_state = LOGON_WAIT; + DEBUG(3,("become_logon_server: go to first stage: register %s<1c> name\n", + work->work_group)); + work->log_state = LOGON_WAIT; - register_name(subrec, work->work_group,0x1c,samba_nb_type|NB_GROUP, - become_logon_server_success, - become_logon_server_fail, NULL); + register_name(subrec, work->work_group,0x1c,samba_nb_type|NB_GROUP, + become_logon_server_success, + become_logon_server_fail, NULL); } /***************************************************************************** Add the internet group <1c> logon names by unicast and broadcast. ****************************************************************************/ + void add_logon_names(void) { - struct subnet_record *subrec; - - for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec)) - { - struct work_record *work = find_workgroup_on_subnet(subrec, lp_workgroup()); - - if (work && (work->log_state == LOGON_NONE)) - { - struct nmb_name nmbname; - make_nmb_name(&nmbname,lp_workgroup(),0x1c); - - if (find_name_on_subnet(subrec, &nmbname, FIND_SELF_NAME) == NULL) - { - if( DEBUGLVL( 0 ) ) - { - dbgtext( "add_domain_logon_names:\n" ); - dbgtext( "Attempting to become logon server " ); - dbgtext( "for workgroup %s ", lp_workgroup() ); - dbgtext( "on subnet %s\n", subrec->subnet_name ); - } - become_logon_server(subrec, work); - } - } - } + struct subnet_record *subrec; + + for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec)) { + struct work_record *work = find_workgroup_on_subnet(subrec, lp_workgroup()); + + if (work && (work->log_state == LOGON_NONE)) { + struct nmb_name nmbname; + make_nmb_name(&nmbname,lp_workgroup(),0x1c); + + if (find_name_on_subnet(subrec, &nmbname, FIND_SELF_NAME) == NULL) { + if( DEBUGLVL( 0 ) ) { + dbgtext( "add_domain_logon_names:\n" ); + dbgtext( "Attempting to become logon server " ); + dbgtext( "for workgroup %s ", lp_workgroup() ); + dbgtext( "on subnet %s\n", subrec->subnet_name ); + } + become_logon_server(subrec, work); + } + } + } } diff --git a/source3/nmbd/nmbd_mynames.c b/source3/nmbd/nmbd_mynames.c index dd66821839..f02fbe1640 100644 --- a/source3/nmbd/nmbd_mynames.c +++ b/source3/nmbd/nmbd_mynames.c @@ -3,7 +3,7 @@ NBT netbios routines and daemon - version 2 Copyright (C) Andrew Tridgell 1994-1998 Copyright (C) Luke Kenneth Casson Leighton 1994-1998 - Copyright (C) Jeremy Allison 1994-1998 + Copyright (C) Jeremy Allison 1994-2003 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -27,20 +27,21 @@ extern uint16 samba_nb_type; /* Samba's NetBIOS type. */ /**************************************************************************** Fail funtion when registering my netbios names. - **************************************************************************/ +**************************************************************************/ static void my_name_register_failed(struct subnet_record *subrec, struct response_record *rrec, struct nmb_name *nmbname) { - DEBUG(0,("my_name_register_failed: Failed to register my name %s on subnet %s.\n", - nmb_namestr(nmbname), subrec->subnet_name)); + DEBUG(0,("my_name_register_failed: Failed to register my name %s on subnet %s.\n", + nmb_namestr(nmbname), subrec->subnet_name)); } /**************************************************************************** Add my workgroup and my given names to one subnet Also add the magic Samba names. - **************************************************************************/ +**************************************************************************/ + void register_my_workgroup_one_subnet(struct subnet_record *subrec) { int i; @@ -84,111 +85,104 @@ Exiting.\n", lp_workgroup(), subrec->subnet_name)); static void insert_refresh_name_into_unicast( struct subnet_record *subrec, struct nmb_name *nmbname, uint16 nb_type ) { - struct name_record *namerec; - - if (!we_are_a_wins_client()) { - insert_permanent_name_into_unicast(subrec, nmbname, nb_type); - return; - } - - if((namerec = find_name_on_subnet(unicast_subnet, nmbname, FIND_SELF_NAME)) == NULL) - { - /* The name needs to be created on the unicast subnet. */ - (void)add_name_to_subnet( unicast_subnet, nmbname->name, - nmbname->name_type, nb_type, - MIN(lp_max_ttl(), MAX_REFRESH_TIME), SELF_NAME, 1, &subrec->myip); - } - else - { - /* The name already exists on the unicast subnet. Add our local - IP for the given broadcast subnet to the name. */ - add_ip_to_name_record( namerec, subrec->myip); - } + struct name_record *namerec; + + if (!we_are_a_wins_client()) { + insert_permanent_name_into_unicast(subrec, nmbname, nb_type); + return; + } + + if((namerec = find_name_on_subnet(unicast_subnet, nmbname, FIND_SELF_NAME)) == NULL) { + nstring name; + pull_ascii_nstring(name, nmbname->name); + /* The name needs to be created on the unicast subnet. */ + (void)add_name_to_subnet( unicast_subnet, name, + nmbname->name_type, nb_type, + MIN(lp_max_ttl(), MAX_REFRESH_TIME), SELF_NAME, 1, &subrec->myip); + } else { + /* The name already exists on the unicast subnet. Add our local + IP for the given broadcast subnet to the name. */ + add_ip_to_name_record( namerec, subrec->myip); + } } /**************************************************************************** Add my workgroup and my given names to the subnet lists. Also add the magic Samba names. - **************************************************************************/ +**************************************************************************/ BOOL register_my_workgroup_and_names(void) { - struct subnet_record *subrec; - int i; - - for(subrec = FIRST_SUBNET; - subrec; - subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec)) - { - register_my_workgroup_one_subnet(subrec); - } - - /* We still need to add the magic Samba - names and the netbios names to the unicast subnet directly. This is - to allow unicast node status requests and queries to still work - in a broadcast only environment. */ - - add_samba_names_to_subnet(unicast_subnet); - - for (i=0; my_netbios_names(i); i++) - { - for(subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) - { - /* - * Ensure all the IP addresses are added if we are multihomed. - */ - struct nmb_name nmbname; - - make_nmb_name(&nmbname, my_netbios_names(i),0x20); - insert_refresh_name_into_unicast(subrec, &nmbname, samba_nb_type); - - make_nmb_name(&nmbname, my_netbios_names(i),0x3); - insert_refresh_name_into_unicast(subrec, &nmbname, samba_nb_type); - - make_nmb_name(&nmbname, my_netbios_names(i),0x0); - insert_refresh_name_into_unicast(subrec, &nmbname, samba_nb_type); - } - } - - /* - * Add the WORKGROUP<0> and WORKGROUP<1e> group names to the unicast subnet - * also for the same reasons. - */ - - for(subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) - { - /* - * Ensure all the IP addresses are added if we are multihomed. - */ - struct nmb_name nmbname; - - make_nmb_name(&nmbname, lp_workgroup(), 0x0); - insert_refresh_name_into_unicast(subrec, &nmbname, samba_nb_type|NB_GROUP); - - make_nmb_name(&nmbname, lp_workgroup(), 0x1e); - insert_refresh_name_into_unicast(subrec, &nmbname, samba_nb_type|NB_GROUP); - } - - /* - * We need to add the Samba names to the remote broadcast subnet, - * as NT 4.x does directed broadcast requests to the *<0x0> name. - */ - add_samba_names_to_subnet(remote_broadcast_subnet); - - return True; + struct subnet_record *subrec; + int i; + + for(subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec)) { + register_my_workgroup_one_subnet(subrec); + } + + /* We still need to add the magic Samba + names and the netbios names to the unicast subnet directly. This is + to allow unicast node status requests and queries to still work + in a broadcast only environment. */ + + add_samba_names_to_subnet(unicast_subnet); + + for (i=0; my_netbios_names(i); i++) { + for(subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) { + /* + * Ensure all the IP addresses are added if we are multihomed. + */ + struct nmb_name nmbname; + + make_nmb_name(&nmbname, my_netbios_names(i),0x20); + insert_refresh_name_into_unicast(subrec, &nmbname, samba_nb_type); + + make_nmb_name(&nmbname, my_netbios_names(i),0x3); + insert_refresh_name_into_unicast(subrec, &nmbname, samba_nb_type); + + make_nmb_name(&nmbname, my_netbios_names(i),0x0); + insert_refresh_name_into_unicast(subrec, &nmbname, samba_nb_type); + } + } + + /* + * Add the WORKGROUP<0> and WORKGROUP<1e> group names to the unicast subnet + * also for the same reasons. + */ + + for(subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) { + /* + * Ensure all the IP addresses are added if we are multihomed. + */ + struct nmb_name nmbname; + + make_nmb_name(&nmbname, lp_workgroup(), 0x0); + insert_refresh_name_into_unicast(subrec, &nmbname, samba_nb_type|NB_GROUP); + + make_nmb_name(&nmbname, lp_workgroup(), 0x1e); + insert_refresh_name_into_unicast(subrec, &nmbname, samba_nb_type|NB_GROUP); + } + + /* + * We need to add the Samba names to the remote broadcast subnet, + * as NT 4.x does directed broadcast requests to the *<0x0> name. + */ + + add_samba_names_to_subnet(remote_broadcast_subnet); + + return True; } /**************************************************************************** Remove all the names we registered. **************************************************************************/ + void release_wins_names(void) { struct subnet_record *subrec = unicast_subnet; struct name_record *namerec, *nextnamerec; - for (namerec = (struct name_record *)ubi_trFirst( subrec->namelist ); - namerec; - namerec = nextnamerec) { + for (namerec = (struct name_record *)ubi_trFirst( subrec->namelist ); namerec; namerec = nextnamerec) { nextnamerec = (struct name_record *)ubi_trNext( namerec ); if( (namerec->data.source == SELF_NAME) && !NAME_IS_DEREGISTERING(namerec) ) @@ -199,12 +193,14 @@ void release_wins_names(void) /******************************************************************* Refresh our registered names with WINS - ******************************************************************/ +******************************************************************/ + void refresh_my_names(time_t t) { struct name_record *namerec; - if (wins_srv_count() < 1) return; + if (wins_srv_count() < 1) + return; for (namerec = (struct name_record *)ubi_trFirst(unicast_subnet->namelist); namerec; diff --git a/source3/nmbd/nmbd_namelistdb.c b/source3/nmbd/nmbd_namelistdb.c index 3f6d2f3b64..d1c9afd608 100644 --- a/source3/nmbd/nmbd_namelistdb.c +++ b/source3/nmbd/nmbd_namelistdb.c @@ -3,7 +3,7 @@ NBT netbios routines and daemon - version 2 Copyright (C) Andrew Tridgell 1994-1998 Copyright (C) Luke Kenneth Casson Leighton 1994-1998 - Copyright (C) Jeremy Allison 1994-1998 + Copyright (C) Jeremy Allison 1994-2003 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -26,152 +26,149 @@ uint16 samba_nb_type = 0; /* samba's NetBIOS name type */ -/* ************************************************************************** ** - * Set Samba's NetBIOS name type. - * ************************************************************************** ** - */ +/************************************************************************** + Set Samba's NetBIOS name type. +***************************************************************************/ + void set_samba_nb_type(void) - { - if( lp_wins_support() || wins_srv_count() ) - samba_nb_type = NB_HFLAG; /* samba is a 'hybrid' node type. */ - else - samba_nb_type = NB_BFLAG; /* samba is broadcast-only node type. */ - } /* set_samba_nb_type */ - -/* ************************************************************************** ** - * Convert a NetBIOS name to upper case. - * ************************************************************************** ** - */ +{ + if( lp_wins_support() || wins_srv_count() ) + samba_nb_type = NB_HFLAG; /* samba is a 'hybrid' node type. */ + else + samba_nb_type = NB_BFLAG; /* samba is broadcast-only node type. */ +} + +/*************************************************************************** + Convert a NetBIOS name to upper case. +***************************************************************************/ + static void upcase_name( struct nmb_name *target, struct nmb_name *source ) - { - int i; - - if( NULL != source ) - (void)memcpy( target, source, sizeof( struct nmb_name ) ); - - strupper_m( target->name ); - strupper_m( target->scope ); - - /* fudge... We're using a byte-by-byte compare, so we must be sure that - * unused space doesn't have garbage in it. - */ - for( i = strlen( target->name ); i < sizeof( target->name ); i++ ) - target->name[i] = '\0'; - for( i = strlen( target->scope ); i < sizeof( target->scope ); i++ ) - target->scope[i] = '\0'; - } /* upcase_name */ - -/* ************************************************************************** ** - * Add a new or overwrite an existing namelist entry. - * ************************************************************************** ** - */ +{ + int i; + nstring targ; + fstring scope; + + if( NULL != source ) + memcpy( target, source, sizeof( struct nmb_name ) ); + + pull_ascii_nstring(targ, target->name); + strupper_m( targ ); + push_ascii_nstring( target->name, targ); + + pull_ascii(scope, target->scope, 64, -1, STR_TERMINATE); + strupper_m( scope ); + push_ascii(target->scope, scope, 64, STR_TERMINATE); + + /* fudge... We're using a byte-by-byte compare, so we must be sure that + * unused space doesn't have garbage in it. + */ + + for( i = strlen( target->name ); i < sizeof( target->name ); i++ ) + target->name[i] = '\0'; + for( i = strlen( target->scope ); i < sizeof( target->scope ); i++ ) + target->scope[i] = '\0'; +} + +/************************************************************************** + Add a new or overwrite an existing namelist entry. +***************************************************************************/ + static void update_name_in_namelist( struct subnet_record *subrec, struct name_record *namerec ) - { - struct name_record *oldrec = NULL; - - (void)ubi_trInsert( subrec->namelist, namerec, &(namerec->name), &oldrec ); - if( oldrec ) - { - SAFE_FREE( oldrec->data.ip ); - SAFE_FREE( oldrec ); - } - } /* update_name_in_namelist */ - -/* ************************************************************************** ** - * Remove a name from the namelist. - * ************************************************************************** ** - */ -void remove_name_from_namelist( struct subnet_record *subrec, - struct name_record *namerec ) - { - (void)ubi_trRemove( subrec->namelist, namerec ); +{ + struct name_record *oldrec = NULL; - SAFE_FREE(namerec->data.ip); + ubi_trInsert( subrec->namelist, namerec, &(namerec->name), &oldrec ); + if( oldrec ) { + SAFE_FREE( oldrec->data.ip ); + SAFE_FREE( oldrec ); + } +} - ZERO_STRUCTP(namerec); - SAFE_FREE(namerec); +/************************************************************************** + Remove a name from the namelist. +***************************************************************************/ + +void remove_name_from_namelist( struct subnet_record *subrec, + struct name_record *namerec ) +{ + ubi_trRemove( subrec->namelist, namerec ); + SAFE_FREE(namerec->data.ip); + ZERO_STRUCTP(namerec); + SAFE_FREE(namerec); + subrec->namelist_changed = True; +} - subrec->namelist_changed = True; - } /* remove_name_from_namelist */ +/************************************************************************** + Find a name in a subnet. +**************************************************************************/ -/* ************************************************************************** ** - * Find a name in a subnet. - * ************************************************************************** ** - */ struct name_record *find_name_on_subnet( struct subnet_record *subrec, struct nmb_name *nmbname, BOOL self_only ) - { - struct nmb_name uc_name[1]; - struct name_record *name_ret; - - upcase_name( uc_name, nmbname ); - name_ret = (struct name_record *)ubi_trFind( subrec->namelist, uc_name ); - if( name_ret ) - { - /* Self names only - these include permanent names. */ - if( self_only - && (name_ret->data.source != SELF_NAME) - && (name_ret->data.source != PERMANENT_NAME) ) - { - DEBUG( 9, - ( "find_name_on_subnet: on subnet %s - self name %s NOT FOUND\n", - subrec->subnet_name, nmb_namestr(nmbname) ) ); - return( NULL ); - } - DEBUG( 9, ("find_name_on_subnet: on subnet %s - found name %s source=%d\n", - subrec->subnet_name, nmb_namestr(nmbname), name_ret->data.source) ); - return( name_ret ); - } - DEBUG( 9, - ( "find_name_on_subnet: on subnet %s - name %s NOT FOUND\n", - subrec->subnet_name, nmb_namestr(nmbname) ) ); - return( NULL ); - } /* find_name_on_subnet */ - -/* ************************************************************************** ** - * Find a name over all known broadcast subnets. - * ************************************************************************** ** - */ +{ + struct nmb_name uc_name[1]; + struct name_record *name_ret; + + upcase_name( uc_name, nmbname ); + name_ret = (struct name_record *)ubi_trFind( subrec->namelist, uc_name ); + if( name_ret ) { + /* Self names only - these include permanent names. */ + if( self_only && (name_ret->data.source != SELF_NAME) && (name_ret->data.source != PERMANENT_NAME) ) { + DEBUG( 9, ( "find_name_on_subnet: on subnet %s - self name %s NOT FOUND\n", + subrec->subnet_name, nmb_namestr(nmbname) ) ); + return( NULL ); + } + + DEBUG( 9, ("find_name_on_subnet: on subnet %s - found name %s source=%d\n", + subrec->subnet_name, nmb_namestr(nmbname), name_ret->data.source) ); + return( name_ret ); + } + + DEBUG( 9, ( "find_name_on_subnet: on subnet %s - name %s NOT FOUND\n", + subrec->subnet_name, nmb_namestr(nmbname) ) ); + return( NULL ); +} + +/************************************************************************** + Find a name over all known broadcast subnets. +************************************************************************/ + struct name_record *find_name_for_remote_broadcast_subnet( struct nmb_name *nmbname, BOOL self_only ) - { - struct subnet_record *subrec; - struct name_record *namerec = NULL; - - for( subrec = FIRST_SUBNET; - subrec; - subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec) ) - { - if( NULL != (namerec = find_name_on_subnet(subrec, nmbname, self_only)) ) - break; - } - - return( namerec ); - } /* find_name_for_remote_broadcast_subnet */ +{ + struct subnet_record *subrec; + struct name_record *namerec = NULL; + + for( subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec) ) { + if( NULL != (namerec = find_name_on_subnet(subrec, nmbname, self_only)) ) + break; + } + + return( namerec ); +} -/* ************************************************************************** ** - * Update the ttl of an entry in a subnet name list. - * ************************************************************************** ** - */ +/************************************************************************** + Update the ttl of an entry in a subnet name list. +***************************************************************************/ + void update_name_ttl( struct name_record *namerec, int ttl ) { - time_t time_now = time(NULL); + time_t time_now = time(NULL); - if( namerec->data.death_time != PERMANENT_TTL ) - namerec->data.death_time = time_now + ttl; + if( namerec->data.death_time != PERMANENT_TTL ) + namerec->data.death_time = time_now + ttl; - namerec->data.refresh_time = time_now + MIN((ttl/2), MAX_REFRESH_TIME); + namerec->data.refresh_time = time_now + MIN((ttl/2), MAX_REFRESH_TIME); + + namerec->subnet->namelist_changed = True; +} - namerec->subnet->namelist_changed = True; -} /* update_name_ttl */ +/************************************************************************** + Add an entry to a subnet name list. +***********************************************************************/ -/* ************************************************************************** ** - * Add an entry to a subnet name list. - * ************************************************************************** ** - */ struct name_record *add_name_to_subnet( struct subnet_record *subrec, const char *name, int type, @@ -181,70 +178,66 @@ struct name_record *add_name_to_subnet( struct subnet_record *subrec, int num_ips, struct in_addr *iplist) { - struct name_record *namerec; - time_t time_now = time(NULL); + struct name_record *namerec; + time_t time_now = time(NULL); - namerec = (struct name_record *)malloc( sizeof(*namerec) ); - if( NULL == namerec ) - { - DEBUG( 0, ( "add_name_to_subnet: malloc fail.\n" ) ); - return( NULL ); - } + namerec = (struct name_record *)malloc( sizeof(*namerec) ); + if( NULL == namerec ) { + DEBUG( 0, ( "add_name_to_subnet: malloc fail.\n" ) ); + return( NULL ); + } - memset( (char *)namerec, '\0', sizeof(*namerec) ); - namerec->data.ip = (struct in_addr *)malloc( sizeof(struct in_addr) - * num_ips ); - if( NULL == namerec->data.ip ) - { - DEBUG( 0, ( "add_name_to_subnet: malloc fail when creating ip_flgs.\n" ) ); + memset( (char *)namerec, '\0', sizeof(*namerec) ); + namerec->data.ip = (struct in_addr *)malloc( sizeof(struct in_addr) * num_ips ); + if( NULL == namerec->data.ip ) { + DEBUG( 0, ( "add_name_to_subnet: malloc fail when creating ip_flgs.\n" ) ); + ZERO_STRUCTP(namerec); + SAFE_FREE(namerec); + return NULL; + } - ZERO_STRUCTP(namerec); - SAFE_FREE(namerec); - return NULL; - } + namerec->subnet = subrec; - namerec->subnet = subrec; + make_nmb_name(&namerec->name, name, type); + upcase_name(&namerec->name, NULL ); - make_nmb_name(&namerec->name, name, type); - upcase_name(&namerec->name, NULL ); + /* Enter the name as active. */ + namerec->data.nb_flags = nb_flags | NB_ACTIVE; + namerec->data.wins_flags = WINS_ACTIVE; - /* Enter the name as active. */ - namerec->data.nb_flags = nb_flags | NB_ACTIVE; - namerec->data.wins_flags = WINS_ACTIVE; + /* If it's our primary name, flag it as so. */ + if( strequal( my_netbios_names(0), name ) ) + namerec->data.nb_flags |= NB_PERM; - /* If it's our primary name, flag it as so. */ - if( strequal( my_netbios_names(0), name ) ) - namerec->data.nb_flags |= NB_PERM; + /* Copy the IPs. */ + namerec->data.num_ips = num_ips; + memcpy( (namerec->data.ip), iplist, num_ips * sizeof(struct in_addr) ); - /* Copy the IPs. */ - namerec->data.num_ips = num_ips; - memcpy( (namerec->data.ip), iplist, num_ips * sizeof(struct in_addr) ); + /* Data source. */ + namerec->data.source = source; - /* Data source. */ - namerec->data.source = source; + /* Setup the death_time and refresh_time. */ + if( ttl == PERMANENT_TTL ) + namerec->data.death_time = PERMANENT_TTL; + else + namerec->data.death_time = time_now + ttl; - /* Setup the death_time and refresh_time. */ - if( ttl == PERMANENT_TTL ) - namerec->data.death_time = PERMANENT_TTL; - else - namerec->data.death_time = time_now + ttl; + namerec->data.refresh_time = time_now + MIN((ttl/2), MAX_REFRESH_TIME); - namerec->data.refresh_time = time_now + MIN((ttl/2), MAX_REFRESH_TIME); + /* Now add the record to the name list. */ + update_name_in_namelist( subrec, namerec ); - /* Now add the record to the name list. */ - update_name_in_namelist( subrec, namerec ); - - DEBUG( 3, ( "add_name_to_subnet: Added netbios name %s with first IP %s \ + DEBUG( 3, ( "add_name_to_subnet: Added netbios name %s with first IP %s \ ttl=%d nb_flags=%2x to subnet %s\n", - nmb_namestr( &namerec->name ), - inet_ntoa( *iplist ), - ttl, - (unsigned int)nb_flags, - subrec->subnet_name ) ); + nmb_namestr( &namerec->name ), + inet_ntoa( *iplist ), + ttl, + (unsigned int)nb_flags, + subrec->subnet_name ) ); - subrec->namelist_changed = True; + subrec->namelist_changed = True; - return(namerec); + return(namerec); } /******************************************************************* @@ -258,14 +251,17 @@ void standard_success_register(struct subnet_record *subrec, struct nmb_name *nmbname, uint16 nb_flags, int ttl, struct in_addr registered_ip) { - struct name_record *namerec; - - namerec = find_name_on_subnet( subrec, nmbname, FIND_SELF_NAME ); - if( NULL == namerec ) - (void)add_name_to_subnet( subrec, nmbname->name, nmbname->name_type, - nb_flags, ttl, SELF_NAME, 1, ®istered_ip ); - else - update_name_ttl( namerec, ttl ); + struct name_record *namerec; + + namerec = find_name_on_subnet( subrec, nmbname, FIND_SELF_NAME ); + if( NULL == namerec ) { + nstring name; + pull_ascii_nstring(name, nmbname->name); + add_name_to_subnet( subrec, name, nmbname->name_type, + nb_flags, ttl, SELF_NAME, 1, ®istered_ip ); + } else { + update_name_ttl( namerec, ttl ); + } } /******************************************************************* @@ -279,17 +275,16 @@ void standard_fail_register( struct subnet_record *subrec, struct response_record *rrec, struct nmb_name *nmbname ) { - struct name_record *namerec; + struct name_record *namerec; - namerec = find_name_on_subnet( subrec, nmbname, FIND_SELF_NAME ); + namerec = find_name_on_subnet( subrec, nmbname, FIND_SELF_NAME ); - DEBUG( 0, ( "standard_fail_register: Failed to register/refresh name %s \ -on subnet %s\n", - nmb_namestr(nmbname), subrec->subnet_name) ); + DEBUG( 0, ( "standard_fail_register: Failed to register/refresh name %s \ +on subnet %s\n", nmb_namestr(nmbname), subrec->subnet_name) ); - /* Remove the name from the subnet. */ - if( namerec ) - remove_name_from_namelist(subrec, namerec); + /* Remove the name from the subnet. */ + if( namerec ) + remove_name_from_namelist(subrec, namerec); } /******************************************************************* @@ -298,13 +293,13 @@ on subnet %s\n", static void remove_nth_ip_in_record( struct name_record *namerec, int ind) { - if( ind != namerec->data.num_ips ) - memmove( (char *)(&namerec->data.ip[ind]), - (char *)(&namerec->data.ip[ind+1]), - ( namerec->data.num_ips - ind - 1) * sizeof(struct in_addr) ); + if( ind != namerec->data.num_ips ) + memmove( (char *)(&namerec->data.ip[ind]), + (char *)(&namerec->data.ip[ind+1]), + ( namerec->data.num_ips - ind - 1) * sizeof(struct in_addr) ); - namerec->data.num_ips--; - namerec->subnet->namelist_changed = True; + namerec->data.num_ips--; + namerec->subnet->namelist_changed = True; } /******************************************************************* @@ -313,13 +308,13 @@ static void remove_nth_ip_in_record( struct name_record *namerec, int ind) BOOL find_ip_in_name_record( struct name_record *namerec, struct in_addr ip ) { - int i; + int i; - for(i = 0; i < namerec->data.num_ips; i++) - if(ip_equal( namerec->data.ip[i], ip)) - return True; + for(i = 0; i < namerec->data.num_ips; i++) + if(ip_equal( namerec->data.ip[i], ip)) + return True; - return False; + return False; } /******************************************************************* @@ -328,30 +323,26 @@ BOOL find_ip_in_name_record( struct name_record *namerec, struct in_addr ip ) void add_ip_to_name_record( struct name_record *namerec, struct in_addr new_ip ) { - struct in_addr *new_list; + struct in_addr *new_list; - /* Don't add one we already have. */ - if( find_ip_in_name_record( namerec, new_ip ) ) - return; + /* Don't add one we already have. */ + if( find_ip_in_name_record( namerec, new_ip ) ) + return; - new_list = (struct in_addr *)malloc( (namerec->data.num_ips + 1) - * sizeof(struct in_addr) ); - if( NULL == new_list ) - { - DEBUG(0,("add_ip_to_name_record: Malloc fail !\n")); - return; - } - - memcpy( (char *)new_list, - (char *)namerec->data.ip, - namerec->data.num_ips * sizeof(struct in_addr) ); - new_list[namerec->data.num_ips] = new_ip; - - SAFE_FREE(namerec->data.ip); - namerec->data.ip = new_list; - namerec->data.num_ips += 1; - - namerec->subnet->namelist_changed = True; + new_list = (struct in_addr *)malloc( (namerec->data.num_ips + 1) * sizeof(struct in_addr) ); + if( NULL == new_list ) { + DEBUG(0,("add_ip_to_name_record: Malloc fail !\n")); + return; + } + + memcpy( (char *)new_list, (char *)namerec->data.ip, namerec->data.num_ips * sizeof(struct in_addr) ); + new_list[namerec->data.num_ips] = new_ip; + + SAFE_FREE(namerec->data.ip); + namerec->data.ip = new_list; + namerec->data.num_ips += 1; + + namerec->subnet->namelist_changed = True; } /******************************************************************* @@ -361,16 +352,16 @@ void add_ip_to_name_record( struct name_record *namerec, struct in_addr new_ip ) void remove_ip_from_name_record( struct name_record *namerec, struct in_addr remove_ip ) { - /* Try and find the requested ip address - remove it. */ - int i; - int orig_num = namerec->data.num_ips; - - for(i = 0; i < orig_num; i++) - if( ip_equal( remove_ip, namerec->data.ip[i]) ) - { - remove_nth_ip_in_record( namerec, i); - break; - } + /* Try and find the requested ip address - remove it. */ + int i; + int orig_num = namerec->data.num_ips; + + for(i = 0; i < orig_num; i++) { + if( ip_equal( remove_ip, namerec->data.ip[i]) ) { + remove_nth_ip_in_record( namerec, i); + break; + } + } } /******************************************************************* @@ -384,85 +375,67 @@ void standard_success_release( struct subnet_record *subrec, struct nmb_name *nmbname, struct in_addr released_ip ) { - struct name_record *namerec; - - namerec = find_name_on_subnet( subrec, nmbname, FIND_ANY_NAME ); - - if( namerec == NULL ) - { - DEBUG( 0, ( "standard_success_release: Name release for name %s IP %s \ -on subnet %s. Name was not found on subnet.\n", - nmb_namestr(nmbname), - inet_ntoa(released_ip), - subrec->subnet_name) ); - return; - } - else - { - int orig_num = namerec->data.num_ips; - - remove_ip_from_name_record( namerec, released_ip ); - - if( namerec->data.num_ips == orig_num ) - DEBUG( 0, ( "standard_success_release: Name release for name %s IP %s \ -on subnet %s. This ip is not known for this name.\n", - nmb_namestr(nmbname), - inet_ntoa(released_ip), - subrec->subnet_name ) ); - } - - if( namerec->data.num_ips == 0 ) - remove_name_from_namelist( subrec, namerec ); + struct name_record *namerec; + + namerec = find_name_on_subnet( subrec, nmbname, FIND_ANY_NAME ); + if( namerec == NULL ) { + DEBUG( 0, ( "standard_success_release: Name release for name %s IP %s \ +on subnet %s. Name was not found on subnet.\n", nmb_namestr(nmbname), inet_ntoa(released_ip), + subrec->subnet_name) ); + return; + } else { + int orig_num = namerec->data.num_ips; + + remove_ip_from_name_record( namerec, released_ip ); + + if( namerec->data.num_ips == orig_num ) + DEBUG( 0, ( "standard_success_release: Name release for name %s IP %s \ +on subnet %s. This ip is not known for this name.\n", nmb_namestr(nmbname), inet_ntoa(released_ip), subrec->subnet_name ) ); + } + + if( namerec->data.num_ips == 0 ) + remove_name_from_namelist( subrec, namerec ); } /******************************************************************* Expires old names in a subnet namelist. - ******************************************************************/ +******************************************************************/ void expire_names_on_subnet(struct subnet_record *subrec, time_t t) { - struct name_record *namerec; - struct name_record *next_namerec; - - for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist ); - namerec; - namerec = next_namerec ) - { - next_namerec = (struct name_record *)ubi_trNext( namerec ); - if( (namerec->data.death_time != PERMANENT_TTL) - && (namerec->data.death_time < t) ) - { - if( namerec->data.source == SELF_NAME ) - { - DEBUG( 3, ( "expire_names_on_subnet: Subnet %s not expiring SELF \ -name %s\n", - subrec->subnet_name, nmb_namestr(&namerec->name) ) ); - namerec->data.death_time += 300; - namerec->subnet->namelist_changed = True; - continue; - } - DEBUG(3,("expire_names_on_subnet: Subnet %s - removing expired name %s\n", - subrec->subnet_name, nmb_namestr(&namerec->name))); + struct name_record *namerec; + struct name_record *next_namerec; + + for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist ); namerec; namerec = next_namerec ) { + next_namerec = (struct name_record *)ubi_trNext( namerec ); + if( (namerec->data.death_time != PERMANENT_TTL) && (namerec->data.death_time < t) ) { + if( namerec->data.source == SELF_NAME ) { + DEBUG( 3, ( "expire_names_on_subnet: Subnet %s not expiring SELF \ +name %s\n", subrec->subnet_name, nmb_namestr(&namerec->name) ) ); + namerec->data.death_time += 300; + namerec->subnet->namelist_changed = True; + continue; + } + + DEBUG(3,("expire_names_on_subnet: Subnet %s - removing expired name %s\n", + subrec->subnet_name, nmb_namestr(&namerec->name))); - remove_name_from_namelist( subrec, namerec ); - } - } + remove_name_from_namelist( subrec, namerec ); + } + } } /******************************************************************* Expires old names in all subnet namelists. - ******************************************************************/ +******************************************************************/ void expire_names(time_t t) { - struct subnet_record *subrec; - - for( subrec = FIRST_SUBNET; - subrec; - subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec) ) - { - expire_names_on_subnet( subrec, t ); - } + struct subnet_record *subrec; + + for( subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec) ) { + expire_names_on_subnet( subrec, t ); + } } /**************************************************************************** @@ -475,46 +448,39 @@ void expire_names(time_t t) void add_samba_names_to_subnet( struct subnet_record *subrec ) { - struct in_addr *iplist = &subrec->myip; - int num_ips = 1; - - /* These names are added permanently (ttl of zero) and will NOT be - refreshed. */ - - if( (subrec == unicast_subnet) - || (subrec == wins_server_subnet) - || (subrec == remote_broadcast_subnet) ) - { - struct subnet_record *bcast_subrecs; - int i; - /* Create an IP list containing all our known subnets. */ - - num_ips = iface_count(); - iplist = (struct in_addr *)malloc( num_ips * sizeof(struct in_addr) ); - if( NULL == iplist ) - { - DEBUG(0,("add_samba_names_to_subnet: Malloc fail !\n")); - return; - } - - for( bcast_subrecs = FIRST_SUBNET, i = 0; - bcast_subrecs; - bcast_subrecs = NEXT_SUBNET_EXCLUDING_UNICAST(bcast_subrecs), i++ ) - iplist[i] = bcast_subrecs->myip; - - } - - (void)add_name_to_subnet(subrec,"*",0x0,samba_nb_type, PERMANENT_TTL, - PERMANENT_NAME, num_ips, iplist); - (void)add_name_to_subnet(subrec,"*",0x20,samba_nb_type,PERMANENT_TTL, - PERMANENT_NAME, num_ips, iplist); - (void)add_name_to_subnet(subrec,"__SAMBA__",0x20,samba_nb_type,PERMANENT_TTL, - PERMANENT_NAME, num_ips, iplist); - (void)add_name_to_subnet(subrec,"__SAMBA__",0x00,samba_nb_type,PERMANENT_TTL, - PERMANENT_NAME, num_ips, iplist); - - if(iplist != &subrec->myip) - SAFE_FREE(iplist); + struct in_addr *iplist = &subrec->myip; + int num_ips = 1; + + /* These names are added permanently (ttl of zero) and will NOT be refreshed. */ + + if( (subrec == unicast_subnet) || (subrec == wins_server_subnet) || (subrec == remote_broadcast_subnet) ) { + struct subnet_record *bcast_subrecs; + int i; + + /* Create an IP list containing all our known subnets. */ + + num_ips = iface_count(); + iplist = (struct in_addr *)malloc( num_ips * sizeof(struct in_addr) ); + if( NULL == iplist ) { + DEBUG(0,("add_samba_names_to_subnet: Malloc fail !\n")); + return; + } + + for( bcast_subrecs = FIRST_SUBNET, i = 0; bcast_subrecs; bcast_subrecs = NEXT_SUBNET_EXCLUDING_UNICAST(bcast_subrecs), i++ ) + iplist[i] = bcast_subrecs->myip; + } + + add_name_to_subnet(subrec,"*",0x0,samba_nb_type, PERMANENT_TTL, + PERMANENT_NAME, num_ips, iplist); + add_name_to_subnet(subrec,"*",0x20,samba_nb_type,PERMANENT_TTL, + PERMANENT_NAME, num_ips, iplist); + add_name_to_subnet(subrec,"__SAMBA__",0x20,samba_nb_type,PERMANENT_TTL, + PERMANENT_NAME, num_ips, iplist); + add_name_to_subnet(subrec,"__SAMBA__",0x00,samba_nb_type,PERMANENT_TTL, + PERMANENT_NAME, num_ips, iplist); + + if(iplist != &subrec->myip) + SAFE_FREE(iplist); } /**************************************************************************** @@ -524,68 +490,65 @@ void add_samba_names_to_subnet( struct subnet_record *subrec ) static void dump_subnet_namelist( struct subnet_record *subrec, XFILE *fp) { - struct name_record *namerec; - const char *src_type; - struct tm *tm; - int i; - - x_fprintf(fp, "Subnet %s\n----------------------\n", subrec->subnet_name); - for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist ); - namerec; - namerec = (struct name_record *)ubi_trNext( namerec ) ) - { - x_fprintf(fp,"\tName = %s\t", nmb_namestr(&namerec->name)); - switch(namerec->data.source) - { - case LMHOSTS_NAME: - src_type = "LMHOSTS_NAME"; - break; - case WINS_PROXY_NAME: - src_type = "WINS_PROXY_NAME"; - break; - case REGISTER_NAME: - src_type = "REGISTER_NAME"; - break; - case SELF_NAME: - src_type = "SELF_NAME"; - break; - case DNS_NAME: - src_type = "DNS_NAME"; - break; - case DNSFAIL_NAME: - src_type = "DNSFAIL_NAME"; - break; - case PERMANENT_NAME: - src_type = "PERMANENT_NAME"; - break; - default: - src_type = "unknown!"; - break; - } - x_fprintf(fp,"Source = %s\nb_flags = %x\t", src_type, namerec->data.nb_flags); - - if(namerec->data.death_time != PERMANENT_TTL) - { - tm = LocalTime(&namerec->data.death_time); - x_fprintf(fp, "death_time = %s\t", asctime(tm)); - } - else - x_fprintf(fp, "death_time = PERMANENT\t"); - - if(namerec->data.refresh_time != PERMANENT_TTL) - { - tm = LocalTime(&namerec->data.refresh_time); - x_fprintf(fp, "refresh_time = %s\n", asctime(tm)); - } - else - x_fprintf(fp, "refresh_time = PERMANENT\n"); - - x_fprintf(fp, "\t\tnumber of IPS = %d", namerec->data.num_ips); - for(i = 0; i < namerec->data.num_ips; i++) - x_fprintf(fp, "\t%s", inet_ntoa(namerec->data.ip[i])); - - x_fprintf(fp, "\n\n"); - } + struct name_record *namerec; + const char *src_type; + struct tm *tm; + int i; + + x_fprintf(fp, "Subnet %s\n----------------------\n", subrec->subnet_name); + for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist ); namerec; + namerec = (struct name_record *)ubi_trNext( namerec ) ) { + + x_fprintf(fp,"\tName = %s\t", nmb_namestr(&namerec->name)); + switch(namerec->data.source) { + case LMHOSTS_NAME: + src_type = "LMHOSTS_NAME"; + break; + case WINS_PROXY_NAME: + src_type = "WINS_PROXY_NAME"; + break; + case REGISTER_NAME: + src_type = "REGISTER_NAME"; + break; + case SELF_NAME: + src_type = "SELF_NAME"; + break; + case DNS_NAME: + src_type = "DNS_NAME"; + break; + case DNSFAIL_NAME: + src_type = "DNSFAIL_NAME"; + break; + case PERMANENT_NAME: + src_type = "PERMANENT_NAME"; + break; + default: + src_type = "unknown!"; + break; + } + + x_fprintf(fp,"Source = %s\nb_flags = %x\t", src_type, namerec->data.nb_flags); + + if(namerec->data.death_time != PERMANENT_TTL) { + tm = LocalTime(&namerec->data.death_time); + x_fprintf(fp, "death_time = %s\t", asctime(tm)); + } else { + x_fprintf(fp, "death_time = PERMANENT\t"); + } + + if(namerec->data.refresh_time != PERMANENT_TTL) { + tm = LocalTime(&namerec->data.refresh_time); + x_fprintf(fp, "refresh_time = %s\n", asctime(tm)); + } else { + x_fprintf(fp, "refresh_time = PERMANENT\n"); + } + + x_fprintf(fp, "\t\tnumber of IPS = %d", namerec->data.num_ips); + for(i = 0; i < namerec->data.num_ips; i++) + x_fprintf(fp, "\t%s", inet_ntoa(namerec->data.ip[i])); + + x_fprintf(fp, "\n\n"); + } } /**************************************************************************** @@ -595,30 +558,27 @@ static void dump_subnet_namelist( struct subnet_record *subrec, XFILE *fp) void dump_all_namelists(void) { - XFILE *fp; - struct subnet_record *subrec; + XFILE *fp; + struct subnet_record *subrec; - fp = x_fopen(lock_path("namelist.debug"),O_WRONLY|O_CREAT|O_TRUNC, 0644); + fp = x_fopen(lock_path("namelist.debug"),O_WRONLY|O_CREAT|O_TRUNC, 0644); - if (!fp) - { - DEBUG(0,("dump_all_namelists: Can't open file %s. Error was %s\n", - "namelist.debug",strerror(errno))); - return; - } + if (!fp) { + DEBUG(0,("dump_all_namelists: Can't open file %s. Error was %s\n", + "namelist.debug",strerror(errno))); + return; + } - for( subrec = FIRST_SUBNET; - subrec; - subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec) ) - dump_subnet_namelist( subrec, fp ); + for( subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec) ) + dump_subnet_namelist( subrec, fp ); - if( !we_are_a_wins_client() ) - dump_subnet_namelist( unicast_subnet, fp ); + if( !we_are_a_wins_client() ) + dump_subnet_namelist( unicast_subnet, fp ); - if( remote_broadcast_subnet->namelist != NULL ) - dump_subnet_namelist( remote_broadcast_subnet, fp ); + if( remote_broadcast_subnet->namelist != NULL ) + dump_subnet_namelist( remote_broadcast_subnet, fp ); - if( wins_server_subnet != NULL ) - dump_subnet_namelist( wins_server_subnet, fp ); - x_fclose( fp ); + if( wins_server_subnet != NULL ) + dump_subnet_namelist( wins_server_subnet, fp ); + x_fclose( fp ); } diff --git a/source3/nmbd/nmbd_namequery.c b/source3/nmbd/nmbd_namequery.c index 8995e9ac52..1b07852f11 100644 --- a/source3/nmbd/nmbd_namequery.c +++ b/source3/nmbd/nmbd_namequery.c @@ -3,7 +3,7 @@ NBT netbios routines and daemon - version 2 Copyright (C) Andrew Tridgell 1994-1998 Copyright (C) Luke Kenneth Casson Leighton 1994-1998 - Copyright (C) Jeremy Allison 1994-1998 + Copyright (C) Jeremy Allison 1994-2003 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -31,106 +31,95 @@ static void query_name_response( struct subnet_record *subrec, struct response_record *rrec, struct packet_struct *p) { - struct nmb_packet *nmb = &p->packet.nmb; - BOOL success = False; - struct nmb_name *question_name = - &rrec->packet->packet.nmb.question.question_name; - struct in_addr answer_ip; - - zero_ip(&answer_ip); - - /* Ensure we don't retry the query but leave the response record cleanup - to the timeout code. We may get more answer responses in which case - we should mark the name in conflict.. */ - rrec->repeat_count = 0; - - if(rrec->num_msgs == 1) - { - /* This is the first response. */ - - if(nmb->header.opcode == NMB_WACK_OPCODE) - { - /* WINS server is telling us to wait. Pretend we didn't get - the response but don't send out any more query requests. */ - - if( DEBUGLVL( 5 ) ) - { - dbgtext( "query_name_response: " ); - dbgtext( "WACK from WINS server %s ", inet_ntoa(p->ip) ); - dbgtext( "in querying name %s ", nmb_namestr(question_name) ); - dbgtext( "on subnet %s.\n", subrec->subnet_name ); - } + struct nmb_packet *nmb = &p->packet.nmb; + BOOL success = False; + struct nmb_name *question_name = &rrec->packet->packet.nmb.question.question_name; + struct in_addr answer_ip; + + zero_ip(&answer_ip); + + /* Ensure we don't retry the query but leave the response record cleanup + to the timeout code. We may get more answer responses in which case + we should mark the name in conflict.. */ + rrec->repeat_count = 0; + + if(rrec->num_msgs == 1) { + /* This is the first response. */ + + if(nmb->header.opcode == NMB_WACK_OPCODE) { + /* WINS server is telling us to wait. Pretend we didn't get + the response but don't send out any more query requests. */ + + if( DEBUGLVL( 5 ) ) { + dbgtext( "query_name_response: " ); + dbgtext( "WACK from WINS server %s ", inet_ntoa(p->ip) ); + dbgtext( "in querying name %s ", nmb_namestr(question_name) ); + dbgtext( "on subnet %s.\n", subrec->subnet_name ); + } - rrec->repeat_count = 0; - /* How long we should wait for. */ - rrec->repeat_time = p->timestamp + nmb->answers->ttl; - rrec->num_msgs--; - return; - } - else if(nmb->header.rcode != 0) - { - success = False; - - if( DEBUGLVL( 5 ) ) - { - dbgtext( "query_name_response: On subnet %s ", subrec->subnet_name ); - dbgtext( "- negative response from IP %s ", inet_ntoa(p->ip) ); - dbgtext( "for name %s. ", nmb_namestr(question_name) ); - dbgtext( "Error code was %d.\n", nmb->header.rcode ); - } - } - else - { - if (!nmb->answers) - { - dbgtext( "query_name_response: On subnet %s ", subrec->subnet_name ); - dbgtext( "IP %s ", inet_ntoa(p->ip) ); - dbgtext( "returned a success response with no answer\n" ); - return; - } - - success = True; - - putip((char *)&answer_ip,&nmb->answers->rdata[2]); - if( DEBUGLVL( 5 ) ) - { - dbgtext( "query_name_response: On subnet %s ", subrec->subnet_name ); - dbgtext( "- positive response from IP %s ", inet_ntoa(p->ip) ); - dbgtext( "for name %s. ", nmb_namestr(question_name) ); - dbgtext( "IP of that name is %s\n", inet_ntoa(answer_ip) ); - } - - /* Interestingly, we could add these names to our namelists, and - change nmbd to a model that checked its own name cache first, - before sending out a query. This is a task for another day, though. - */ - } - } - else if( rrec->num_msgs > 1) - { - if( DEBUGLVL( 0 ) ) - { - if (nmb->answers) - putip( (char *)&answer_ip, &nmb->answers->rdata[2] ); - dbgtext( "query_name_response: " ); - dbgtext( "Multiple (%d) responses ", rrec->num_msgs ); - dbgtext( "received for a query on subnet %s ", subrec->subnet_name ); - dbgtext( "for name %s.\nThis response ", nmb_namestr(question_name) ); - dbgtext( "was from IP %s, reporting ", inet_ntoa(p->ip) ); - dbgtext( "an IP address of %s.\n", inet_ntoa(answer_ip) ); - } - - /* We have already called the success or fail function, so we - don't call again here. Leave the response record around in - case we get more responses. */ - - return; - } + rrec->repeat_count = 0; + /* How long we should wait for. */ + rrec->repeat_time = p->timestamp + nmb->answers->ttl; + rrec->num_msgs--; + return; + } else if(nmb->header.rcode != 0) { + + success = False; + + if( DEBUGLVL( 5 ) ) { + dbgtext( "query_name_response: On subnet %s ", subrec->subnet_name ); + dbgtext( "- negative response from IP %s ", inet_ntoa(p->ip) ); + dbgtext( "for name %s. ", nmb_namestr(question_name) ); + dbgtext( "Error code was %d.\n", nmb->header.rcode ); + } + } else { + if (!nmb->answers) { + dbgtext( "query_name_response: On subnet %s ", subrec->subnet_name ); + dbgtext( "IP %s ", inet_ntoa(p->ip) ); + dbgtext( "returned a success response with no answer\n" ); + return; + } + + success = True; + + putip((char *)&answer_ip,&nmb->answers->rdata[2]); + + if( DEBUGLVL( 5 ) ) { + dbgtext( "query_name_response: On subnet %s ", subrec->subnet_name ); + dbgtext( "- positive response from IP %s ", inet_ntoa(p->ip) ); + dbgtext( "for name %s. ", nmb_namestr(question_name) ); + dbgtext( "IP of that name is %s\n", inet_ntoa(answer_ip) ); + } + + /* Interestingly, we could add these names to our namelists, and + change nmbd to a model that checked its own name cache first, + before sending out a query. This is a task for another day, though. + */ + } + } else if( rrec->num_msgs > 1) { + + if( DEBUGLVL( 0 ) ) { + if (nmb->answers) + putip( (char *)&answer_ip, &nmb->answers->rdata[2] ); + dbgtext( "query_name_response: " ); + dbgtext( "Multiple (%d) responses ", rrec->num_msgs ); + dbgtext( "received for a query on subnet %s ", subrec->subnet_name ); + dbgtext( "for name %s.\nThis response ", nmb_namestr(question_name) ); + dbgtext( "was from IP %s, reporting ", inet_ntoa(p->ip) ); + dbgtext( "an IP address of %s.\n", inet_ntoa(answer_ip) ); + } + + /* We have already called the success or fail function, so we + don't call again here. Leave the response record around in + case we get more responses. */ + + return; + } - if(success && rrec->success_fn) - (*(query_name_success_function)rrec->success_fn)(subrec, rrec->userdata, question_name, answer_ip, nmb->answers); - else if( rrec->fail_fn) - (*(query_name_fail_function)rrec->fail_fn)(subrec, rrec, question_name, nmb->header.rcode); + if(success && rrec->success_fn) + (*(query_name_success_function)rrec->success_fn)(subrec, rrec->userdata, question_name, answer_ip, nmb->answers); + else if( rrec->fail_fn) + (*(query_name_fail_function)rrec->fail_fn)(subrec, rrec, question_name, nmb->header.rcode); } @@ -141,32 +130,30 @@ static void query_name_response( struct subnet_record *subrec, static void query_name_timeout_response(struct subnet_record *subrec, struct response_record *rrec) { - struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb; - /* We can only fail here, never succeed. */ - BOOL failed = True; - struct nmb_name *question_name = &sent_nmb->question.question_name; - - if(rrec->num_msgs != 0) - { - /* We got at least one response, and have called the success/fail - function already. */ - - failed = False; - } - - if(failed) - { - if( DEBUGLVL( 5 ) ) - { - dbgtext( "query_name_timeout_response: No response to " ); - dbgtext( "query for name %s ", nmb_namestr(question_name) ); - dbgtext( "on subnet %s.\n", subrec->subnet_name ); - } - if(rrec->fail_fn) - (*(query_name_fail_function)rrec->fail_fn)(subrec, rrec, question_name, 0); - } - - remove_response_record(subrec, rrec); + struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb; + /* We can only fail here, never succeed. */ + BOOL failed = True; + struct nmb_name *question_name = &sent_nmb->question.question_name; + + if(rrec->num_msgs != 0) { + /* We got at least one response, and have called the success/fail + function already. */ + + failed = False; + } + + if(failed) { + if( DEBUGLVL( 5 ) ) { + dbgtext( "query_name_timeout_response: No response to " ); + dbgtext( "query for name %s ", nmb_namestr(question_name) ); + dbgtext( "on subnet %s.\n", subrec->subnet_name ); + } + + if(rrec->fail_fn) + (*(query_name_fail_function)rrec->fail_fn)(subrec, rrec, question_name, 0); + } + + remove_response_record(subrec, rrec); } /**************************************************************************** @@ -177,98 +164,83 @@ static void query_name_timeout_response(struct subnet_record *subrec, static BOOL query_local_namelists(struct subnet_record *subrec, struct nmb_name *nmbname, struct name_record **namerecp) { - struct name_record *namerec; + struct name_record *namerec; - *namerecp = NULL; + *namerecp = NULL; - if(find_name_in_lmhosts(nmbname, namerecp)) - return True; + if(find_name_in_lmhosts(nmbname, namerecp)) + return True; - if((namerec = find_name_on_subnet(subrec, nmbname, FIND_ANY_NAME))==NULL) - return False; - - if( NAME_IS_ACTIVE(namerec) - && ( (namerec->data.source == SELF_NAME) - || (namerec->data.source == LMHOSTS_NAME) ) ) - { - *namerecp = namerec; - return True; - } - return False; + if((namerec = find_name_on_subnet(subrec, nmbname, FIND_ANY_NAME))==NULL) + return False; + + if( NAME_IS_ACTIVE(namerec) && ( (namerec->data.source == SELF_NAME) || (namerec->data.source == LMHOSTS_NAME) ) ) { + *namerecp = namerec; + return True; + } + return False; } /**************************************************************************** Try and query for a name. ****************************************************************************/ -BOOL query_name(struct subnet_record *subrec, char *name, int type, +BOOL query_name(struct subnet_record *subrec, const char *name, int type, query_name_success_function success_fn, query_name_fail_function fail_fn, struct userdata_struct *userdata) { - struct nmb_name nmbname; - struct name_record *namerec; - - make_nmb_name(&nmbname, name, type); - - /* - * We need to check our local namelists first. - * It may be an magic name, lmhosts name or just - * a name we have registered. - */ - - if(query_local_namelists(subrec, &nmbname, &namerec) == True) - { - struct res_rec rrec; - int i; - - memset((char *)&rrec, '\0', sizeof(struct res_rec)); - - /* Fake up the needed res_rec just in case it's used. */ - rrec.rr_name = nmbname; - rrec.rr_type = RR_TYPE_NB; - rrec.rr_class = RR_CLASS_IN; - rrec.ttl = PERMANENT_TTL; - rrec.rdlength = namerec->data.num_ips * 6; - if(rrec.rdlength > MAX_DGRAM_SIZE) - { - if( DEBUGLVL( 0 ) ) - { - dbgtext( "query_name: nmbd internal error - " ); - dbgtext( "there are %d ip addresses ", namerec->data.num_ips ); - dbgtext( "for name %s.\n", nmb_namestr(&nmbname) ); - } - return False; - } - - for( i = 0; i < namerec->data.num_ips; i++) - { - set_nb_flags( &rrec.rdata[i*6], namerec->data.nb_flags ); - putip( &rrec.rdata[(i*6) + 2], (char *)&namerec->data.ip[i]); - } - - /* Call the success function directly. */ - if(success_fn) - (*(query_name_success_function)success_fn)(subrec, userdata, &nmbname, namerec->data.ip[0], &rrec); - return False; - } - - if(queue_query_name( subrec, - query_name_response, - query_name_timeout_response, - success_fn, - fail_fn, - userdata, - &nmbname) == NULL) - { - if( DEBUGLVL( 0 ) ) - { - dbgtext( "query_name: Failed to send packet " ); - dbgtext( "trying to query name %s\n", nmb_namestr(&nmbname) ); - } - return True; - } - return False; + struct nmb_name nmbname; + struct name_record *namerec; + + make_nmb_name(&nmbname, name, type); + + /* + * We need to check our local namelists first. + * It may be an magic name, lmhosts name or just + * a name we have registered. + */ + + if(query_local_namelists(subrec, &nmbname, &namerec) == True) { + struct res_rec rrec; + int i; + + memset((char *)&rrec, '\0', sizeof(struct res_rec)); + + /* Fake up the needed res_rec just in case it's used. */ + rrec.rr_name = nmbname; + rrec.rr_type = RR_TYPE_NB; + rrec.rr_class = RR_CLASS_IN; + rrec.ttl = PERMANENT_TTL; + rrec.rdlength = namerec->data.num_ips * 6; + if(rrec.rdlength > MAX_DGRAM_SIZE) { + if( DEBUGLVL( 0 ) ) { + dbgtext( "query_name: nmbd internal error - " ); + dbgtext( "there are %d ip addresses ", namerec->data.num_ips ); + dbgtext( "for name %s.\n", nmb_namestr(&nmbname) ); + } + return False; + } + + for( i = 0; i < namerec->data.num_ips; i++) { + set_nb_flags( &rrec.rdata[i*6], namerec->data.nb_flags ); + putip( &rrec.rdata[(i*6) + 2], (char *)&namerec->data.ip[i]); + } + + /* Call the success function directly. */ + if(success_fn) + (*(query_name_success_function)success_fn)(subrec, userdata, &nmbname, namerec->data.ip[0], &rrec); + return False; + } + + if(queue_query_name( subrec, query_name_response, query_name_timeout_response, success_fn, fail_fn, userdata, &nmbname) == NULL) { + if( DEBUGLVL( 0 ) ) { + dbgtext( "query_name: Failed to send packet " ); + dbgtext( "trying to query name %s\n", nmb_namestr(&nmbname) ); + } + return True; + } + return False; } /**************************************************************************** @@ -276,29 +248,21 @@ BOOL query_name(struct subnet_record *subrec, char *name, int type, ****************************************************************************/ BOOL query_name_from_wins_server(struct in_addr ip_to, - char *name, int type, + const char *name, int type, query_name_success_function success_fn, query_name_fail_function fail_fn, struct userdata_struct *userdata) { - struct nmb_name nmbname; - - make_nmb_name(&nmbname, name, type); - - if(queue_query_name_from_wins_server( ip_to, - query_name_response, - query_name_timeout_response, - success_fn, - fail_fn, - userdata, - &nmbname) == NULL) - { - if( DEBUGLVL( 0 ) ) - { - dbgtext( "query_name_from_wins_server: Failed to send packet " ); - dbgtext( "trying to query name %s\n", nmb_namestr(&nmbname) ); - } - return True; - } - return False; + struct nmb_name nmbname; + + make_nmb_name(&nmbname, name, type); + + if(queue_query_name_from_wins_server( ip_to, query_name_response, query_name_timeout_response, success_fn, fail_fn, userdata, &nmbname) == NULL) { + if( DEBUGLVL( 0 ) ) { + dbgtext( "query_name_from_wins_server: Failed to send packet " ); + dbgtext( "trying to query name %s\n", nmb_namestr(&nmbname) ); + } + return True; + } + return False; } diff --git a/source3/nmbd/nmbd_nameregister.c b/source3/nmbd/nmbd_nameregister.c index 7bf2584053..0397f56512 100644 --- a/source3/nmbd/nmbd_nameregister.c +++ b/source3/nmbd/nmbd_nameregister.c @@ -3,7 +3,7 @@ NBT netbios routines and daemon - version 2 Copyright (C) Andrew Tridgell 1994-1998 Copyright (C) Luke Kenneth Casson Leighton 1994-1998 - Copyright (C) Jeremy Allison 1994-1998 + Copyright (C) Jeremy Allison 1994-2003 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -85,7 +85,9 @@ static void register_name_response(struct subnet_record *subrec, */ #if 1 /* OLD_SAMBA_SERVER_HACK */ - if((nmb->header.rcode == ACT_ERR) && strequal(lp_workgroup(), answer_name->name) && + nstring ans_name; + pull_ascii_nstring(ans_name, answer_name->name); + if((nmb->header.rcode == ACT_ERR) && strequal(lp_workgroup(), ans_name) && (answer_name->name_type == 0x1b)) { /* Pretend we did not get this. */ rrec->num_msgs--; @@ -161,10 +163,10 @@ static void register_name_response(struct subnet_record *subrec, remove_response_record(subrec, rrec); } - /**************************************************************************** Deal with a timeout of a WINS registration request ****************************************************************************/ + static void wins_registration_timeout(struct subnet_record *subrec, struct response_record *rrec) { @@ -233,7 +235,6 @@ static void wins_registration_timeout(struct subnet_record *subrec, us trying to register with each of our failover wins servers */ } - /**************************************************************************** Deal with a timeout when registering one of our names. ****************************************************************************/ @@ -290,10 +291,10 @@ static void register_name_timeout_response(struct subnet_record *subrec, remove_response_record(subrec, rrec); } - /**************************************************************************** -initiate one multi-homed name registration packet + Initiate one multi-homed name registration packet. ****************************************************************************/ + static void multihomed_register_one(struct nmb_name *nmbname, uint16 nb_flags, register_name_success_function success_fn, @@ -336,11 +337,11 @@ static void multihomed_register_one(struct nmb_name *nmbname, free(userdata); } - /**************************************************************************** -we have finished the registration of one IP and need to see if we have -any more IPs left to register with this group of wins server for this name + We have finished the registration of one IP and need to see if we have + any more IPs left to register with this group of wins server for this name. ****************************************************************************/ + static void wins_next_registration(struct response_record *rrec) { struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb; @@ -388,6 +389,7 @@ static void wins_next_registration(struct response_record *rrec) /**************************************************************************** Try and register one of our names on the unicast subnet - multihomed. ****************************************************************************/ + static void multihomed_register_name(struct nmb_name *nmbname, uint16 nb_flags, register_name_success_function success_fn, register_name_fail_function fail_fn) @@ -416,6 +418,7 @@ static void multihomed_register_name(struct nmb_name *nmbname, uint16 nb_flags, struct subnet_record *subrec; char **wins_tags; struct in_addr *ip_list; + nstring name; for(subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec) ) num_ips++; @@ -431,7 +434,8 @@ static void multihomed_register_name(struct nmb_name *nmbname, uint16 nb_flags, ip_list[i] = subrec->myip; } - add_name_to_subnet(unicast_subnet, nmbname->name, nmbname->name_type, + pull_ascii_nstring(name, nmbname->name); + add_name_to_subnet(unicast_subnet, name, nmbname->name_type, nb_flags, lp_max_ttl(), SELF_NAME, num_ips, ip_list); @@ -456,10 +460,10 @@ static void multihomed_register_name(struct nmb_name *nmbname, uint16 nb_flags, SAFE_FREE(ip_list); } - /**************************************************************************** Try and register one of our names. ****************************************************************************/ + void register_name(struct subnet_record *subrec, const char *name, int type, uint16 nb_flags, register_name_success_function success_fn, @@ -467,8 +471,18 @@ void register_name(struct subnet_record *subrec, struct userdata_struct *userdata) { struct nmb_name nmbname; - - make_nmb_name(&nmbname, name, type); + nstring nname; + + if (strlen(name)+1 > sizeof(nstring)) { + memcpy(nname, name,sizeof(nstring)-1); + nname[sizeof(nstring)-1] = '\0'; + DEBUG(0,("register_name: NetBIOS name %s is too long. Truncating to %s\n", + name, nname)); + } else { + nstrcpy(nname,name); + } + + make_nmb_name(&nmbname, nname, type); /* Always set the NB_ACTIVE flag on the name we are registering. Doesn't make sense without it. @@ -498,10 +512,10 @@ void register_name(struct subnet_record *subrec, } } - /**************************************************************************** Try and refresh one of our names. This is *only* called for WINS refresh ****************************************************************************/ + void wins_refresh_name(struct name_record *namerec) { int t; diff --git a/source3/nmbd/nmbd_nodestatus.c b/source3/nmbd/nmbd_nodestatus.c index 993e4d9d17..0ea5d6a818 100644 --- a/source3/nmbd/nmbd_nodestatus.c +++ b/source3/nmbd/nmbd_nodestatus.c @@ -3,7 +3,7 @@ NBT netbios routines and daemon - version 2 Copyright (C) Andrew Tridgell 1994-1998 Copyright (C) Luke Kenneth Casson Leighton 1994-1998 - Copyright (C) Jeremy Allison 1994-1998 + Copyright (C) Jeremy Allison 1994-2003 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -26,52 +26,52 @@ /**************************************************************************** Deal with a successful node status response. ****************************************************************************/ + static void node_status_response(struct subnet_record *subrec, struct response_record *rrec, struct packet_struct *p) { - struct nmb_packet *nmb = &p->packet.nmb; - struct nmb_name *question_name = &rrec->packet->packet.nmb.question.question_name; - struct nmb_name *answer_name = &nmb->answers->rr_name; + struct nmb_packet *nmb = &p->packet.nmb; + struct nmb_name *question_name = &rrec->packet->packet.nmb.question.question_name; + struct nmb_name *answer_name = &nmb->answers->rr_name; - /* Sanity check. Ensure that the answer name in the incoming packet is the - same as the requested name in the outgoing packet. */ + /* Sanity check. Ensure that the answer name in the incoming packet is the + same as the requested name in the outgoing packet. */ - if(!nmb_name_equal(question_name, answer_name)) - { - DEBUG(0,("node_status_response: Answer name %s differs from question \ + if(!nmb_name_equal(question_name, answer_name)) { + DEBUG(0,("node_status_response: Answer name %s differs from question \ name %s.\n", nmb_namestr(answer_name), nmb_namestr(question_name))); - return; - } + return; + } - DEBUG(5,("node_status_response: response from name %s on subnet %s.\n", - nmb_namestr(answer_name), subrec->subnet_name)); + DEBUG(5,("node_status_response: response from name %s on subnet %s.\n", + nmb_namestr(answer_name), subrec->subnet_name)); - /* Just send the whole answer resource record for the success function - to parse. */ - if(rrec->success_fn) - (*(node_status_success_function)rrec->success_fn)(subrec, rrec->userdata, nmb->answers, p->ip); + /* Just send the whole answer resource record for the success function to parse. */ + if(rrec->success_fn) + (*(node_status_success_function)rrec->success_fn)(subrec, rrec->userdata, nmb->answers, p->ip); - /* Ensure we don't retry. */ - remove_response_record(subrec, rrec); + /* Ensure we don't retry. */ + remove_response_record(subrec, rrec); } /**************************************************************************** Deal with a timeout when requesting a node status. ****************************************************************************/ + static void node_status_timeout_response(struct subnet_record *subrec, struct response_record *rrec) { - struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb; - struct nmb_name *question_name = &sent_nmb->question.question_name; + struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb; + struct nmb_name *question_name = &sent_nmb->question.question_name; - DEBUG(5,("node_status_timeout_response: failed to get node status from name %s on subnet %s\n", - nmb_namestr(question_name), subrec->subnet_name)); + DEBUG(5,("node_status_timeout_response: failed to get node status from name %s on subnet %s\n", + nmb_namestr(question_name), subrec->subnet_name)); - if( rrec->fail_fn) - (*rrec->fail_fn)(subrec, rrec); + if( rrec->fail_fn) + (*rrec->fail_fn)(subrec, rrec); - /* Ensure we don't retry. */ - remove_response_record(subrec, rrec); + /* Ensure we don't retry. */ + remove_response_record(subrec, rrec); } /**************************************************************************** @@ -82,13 +82,11 @@ BOOL node_status(struct subnet_record *subrec, struct nmb_name *nmbname, struct in_addr send_ip, node_status_success_function success_fn, node_status_fail_function fail_fn, struct userdata_struct *userdata) { - if(queue_node_status( subrec, - node_status_response, node_status_timeout_response, - success_fn, fail_fn, userdata, nmbname, send_ip)==NULL) - { - DEBUG(0,("node_status: Failed to send packet trying to get node status for \ + if(queue_node_status( subrec, node_status_response, node_status_timeout_response, + success_fn, fail_fn, userdata, nmbname, send_ip)==NULL) { + DEBUG(0,("node_status: Failed to send packet trying to get node status for \ name %s, IP address %s\n", nmb_namestr(nmbname), inet_ntoa(send_ip))); - return True; - } - return False; + return True; + } + return False; } diff --git a/source3/nmbd/nmbd_packets.c b/source3/nmbd/nmbd_packets.c index 6c3446d6c8..72eb1b5019 100644 --- a/source3/nmbd/nmbd_packets.c +++ b/source3/nmbd/nmbd_packets.c @@ -3,7 +3,7 @@ NBT netbios routines and daemon - version 2 Copyright (C) Andrew Tridgell 1994-1998 Copyright (C) Luke Kenneth Casson Leighton 1994-1998 - Copyright (C) Jeremy Allison 1994-1998 + Copyright (C) Jeremy Allison 1994-2003 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -50,13 +50,13 @@ Utility function to find the specific fd to send a packet out on. static int find_subnet_fd_for_address( struct in_addr local_ip ) { - struct subnet_record *subrec; + struct subnet_record *subrec; - for( subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) - if(ip_equal(local_ip, subrec->myip)) - return subrec->nmb_sock; + for( subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) + if(ip_equal(local_ip, subrec->myip)) + return subrec->nmb_sock; - return ClientNMB; + return ClientNMB; } /*************************************************************************** @@ -65,13 +65,13 @@ Utility function to find the specific fd to send a mailslot packet out on. static int find_subnet_mailslot_fd_for_address( struct in_addr local_ip ) { - struct subnet_record *subrec; + struct subnet_record *subrec; - for( subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) - if(ip_equal(local_ip, subrec->myip)) - return subrec->dgram_sock; + for( subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) + if(ip_equal(local_ip, subrec->myip)) + return subrec->dgram_sock; - return ClientDGRAM; + return ClientDGRAM; } /*************************************************************************** @@ -80,13 +80,13 @@ Get/Set problematic nb_flags as network byte order 16 bit int. uint16 get_nb_flags(char *buf) { - return ((((uint16)*buf)&0xFFFF) & NB_FLGMSK); + return ((((uint16)*buf)&0xFFFF) & NB_FLGMSK); } void set_nb_flags(char *buf, uint16 nb_flags) { - *buf++ = ((nb_flags & NB_FLGMSK) & 0xFF); - *buf = '\0'; + *buf++ = ((nb_flags & NB_FLGMSK) & 0xFF); + *buf = '\0'; } /*************************************************************************** @@ -95,37 +95,34 @@ Dumps out the browse packet data. static void debug_browse_data(char *outbuf, int len) { - int i,j; - - DEBUG( 4, ( "debug_browse_data():\n" ) ); - for (i = 0; i < len; i+= 16) - { - DEBUGADD( 4, ( "%3x char ", i ) ); - - for (j = 0; j < 16; j++) - { - unsigned char x; - if (i+j >= len) - break; - - x = outbuf[i+j]; - if (x < 32 || x > 127) - x = '.'; + int i,j; + + DEBUG( 4, ( "debug_browse_data():\n" ) ); + for (i = 0; i < len; i+= 16) { + DEBUGADD( 4, ( "%3x char ", i ) ); + + for (j = 0; j < 16; j++) { + unsigned char x; + if (i+j >= len) + break; + + x = outbuf[i+j]; + if (x < 32 || x > 127) + x = '.'; - DEBUGADD( 4, ( "%c", x ) ); - } + DEBUGADD( 4, ( "%c", x ) ); + } - DEBUGADD( 4, ( "%*s hex", 16-j, "" ) ); + DEBUGADD( 4, ( "%*s hex", 16-j, "" ) ); - for (j = 0; j < 16; j++) - { - if (i+j >= len) - break; - DEBUGADD( 4, ( " %02x", (unsigned char)outbuf[i+j] ) ); - } + for (j = 0; j < 16; j++) { + if (i+j >= len) + break; + DEBUGADD( 4, ( " %02x", (unsigned char)outbuf[i+j] ) ); + } - DEBUGADD( 4, ("\n") ); - } + DEBUGADD( 4, ("\n") ); + } } /*************************************************************************** @@ -136,13 +133,11 @@ static uint16 name_trn_id=0; static uint16 generate_name_trn_id(void) { - - if (!name_trn_id) - { - name_trn_id = ((unsigned)time(NULL)%(unsigned)0x7FFF) + ((unsigned)sys_getpid()%(unsigned)100); - } - name_trn_id = (name_trn_id+1) % (unsigned)0x7FFF; - return name_trn_id; + if (!name_trn_id) { + name_trn_id = ((unsigned)time(NULL)%(unsigned)0x7FFF) + ((unsigned)sys_getpid()%(unsigned)100); + } + name_trn_id = (name_trn_id+1) % (unsigned)0x7FFF; + return name_trn_id; } /*************************************************************************** @@ -151,28 +146,25 @@ static uint16 generate_name_trn_id(void) static BOOL send_netbios_packet(struct packet_struct *p) { - BOOL loopback_this_packet = False; - - /* Check if we are sending to or from ourselves as a WINS server. */ - if(ismyip(p->ip) && (p->port == global_nmb_port)) - loopback_this_packet = True; - - if(loopback_this_packet) - { - struct packet_struct *lo_packet = NULL; - DEBUG(5,("send_netbios_packet: sending packet to ourselves.\n")); - if((lo_packet = copy_packet(p)) == NULL) - return False; - queue_packet(lo_packet); - } - else if (!send_packet(p)) - { - DEBUG(0,("send_netbios_packet: send_packet() to IP %s port %d failed\n", - inet_ntoa(p->ip),p->port)); - return False; - } + BOOL loopback_this_packet = False; + + /* Check if we are sending to or from ourselves as a WINS server. */ + if(ismyip(p->ip) && (p->port == global_nmb_port)) + loopback_this_packet = True; + + if(loopback_this_packet) { + struct packet_struct *lo_packet = NULL; + DEBUG(5,("send_netbios_packet: sending packet to ourselves.\n")); + if((lo_packet = copy_packet(p)) == NULL) + return False; + queue_packet(lo_packet); + } else if (!send_packet(p)) { + DEBUG(0,("send_netbios_packet: send_packet() to IP %s port %d failed\n", + inet_ntoa(p->ip),p->port)); + return False; + } - return True; + return True; } /*************************************************************************** @@ -188,45 +180,44 @@ static struct packet_struct *create_and_init_netbios_packet(struct nmb_name *nmb BOOL bcast, BOOL rec_des, struct in_addr to_ip) { - struct packet_struct *packet = NULL; - struct nmb_packet *nmb = NULL; - - /* Allocate the packet_struct we will return. */ - if((packet = (struct packet_struct *)malloc(sizeof(*packet))) == NULL) - { - DEBUG(0,("create_and_init_netbios_packet: malloc fail (1) for packet struct.\n")); - return NULL; - } + struct packet_struct *packet = NULL; + struct nmb_packet *nmb = NULL; + + /* Allocate the packet_struct we will return. */ + if((packet = (struct packet_struct *)malloc(sizeof(*packet))) == NULL) { + DEBUG(0,("create_and_init_netbios_packet: malloc fail (1) for packet struct.\n")); + return NULL; + } - memset((char *)packet,'\0',sizeof(*packet)); + memset((char *)packet,'\0',sizeof(*packet)); - nmb = &packet->packet.nmb; + nmb = &packet->packet.nmb; - nmb->header.name_trn_id = generate_name_trn_id(); - nmb->header.response = False; - nmb->header.nm_flags.recursion_desired = rec_des; - nmb->header.nm_flags.recursion_available = False; - nmb->header.nm_flags.trunc = False; - nmb->header.nm_flags.authoritative = False; - nmb->header.nm_flags.bcast = bcast; + nmb->header.name_trn_id = generate_name_trn_id(); + nmb->header.response = False; + nmb->header.nm_flags.recursion_desired = rec_des; + nmb->header.nm_flags.recursion_available = False; + nmb->header.nm_flags.trunc = False; + nmb->header.nm_flags.authoritative = False; + nmb->header.nm_flags.bcast = bcast; - nmb->header.rcode = 0; - nmb->header.qdcount = 1; - nmb->header.ancount = 0; - nmb->header.nscount = 0; - - nmb->question.question_name = *nmbname; - nmb->question.question_type = QUESTION_TYPE_NB_QUERY; - nmb->question.question_class = QUESTION_CLASS_IN; - - packet->ip = to_ip; - packet->port = NMB_PORT; - packet->fd = ClientNMB; - packet->timestamp = time(NULL); - packet->packet_type = NMB_PACKET; - packet->locked = False; + nmb->header.rcode = 0; + nmb->header.qdcount = 1; + nmb->header.ancount = 0; + nmb->header.nscount = 0; + + nmb->question.question_name = *nmbname; + nmb->question.question_type = QUESTION_TYPE_NB_QUERY; + nmb->question.question_class = QUESTION_CLASS_IN; + + packet->ip = to_ip; + packet->port = NMB_PORT; + packet->fd = ClientNMB; + packet->timestamp = time(NULL); + packet->packet_type = NMB_PACKET; + packet->locked = False; - return packet; /* Caller must free. */ + return packet; /* Caller must free. */ } /*************************************************************************** @@ -283,20 +274,20 @@ static BOOL create_and_init_additional_record(struct packet_struct *packet, static BOOL initiate_name_query_packet( struct packet_struct *packet) { - struct nmb_packet *nmb = NULL; + struct nmb_packet *nmb = NULL; - nmb = &packet->packet.nmb; + nmb = &packet->packet.nmb; - nmb->header.opcode = NMB_NAME_QUERY_OPCODE; - nmb->header.arcount = 0; + nmb->header.opcode = NMB_NAME_QUERY_OPCODE; + nmb->header.arcount = 0; - nmb->header.nm_flags.recursion_desired = True; + nmb->header.nm_flags.recursion_desired = True; - DEBUG(4,("initiate_name_query_packet: sending query for name %s (bcast=%s) to IP %s\n", - nmb_namestr(&nmb->question.question_name), - BOOLSTR(nmb->header.nm_flags.bcast), inet_ntoa(packet->ip))); + DEBUG(4,("initiate_name_query_packet: sending query for name %s (bcast=%s) to IP %s\n", + nmb_namestr(&nmb->question.question_name), + BOOLSTR(nmb->header.nm_flags.bcast), inet_ntoa(packet->ip))); - return send_netbios_packet( packet ); + return send_netbios_packet( packet ); } /*************************************************************************** @@ -305,20 +296,20 @@ static BOOL initiate_name_query_packet( struct packet_struct *packet) static BOOL initiate_name_query_packet_from_wins_server( struct packet_struct *packet) { - struct nmb_packet *nmb = NULL; + struct nmb_packet *nmb = NULL; - nmb = &packet->packet.nmb; + nmb = &packet->packet.nmb; - nmb->header.opcode = NMB_NAME_QUERY_OPCODE; - nmb->header.arcount = 0; + nmb->header.opcode = NMB_NAME_QUERY_OPCODE; + nmb->header.arcount = 0; - nmb->header.nm_flags.recursion_desired = False; + nmb->header.nm_flags.recursion_desired = False; - DEBUG(4,("initiate_name_query_packet_from_wins_server: sending query for name %s (bcast=%s) to IP %s\n", - nmb_namestr(&nmb->question.question_name), - BOOLSTR(nmb->header.nm_flags.bcast), inet_ntoa(packet->ip))); + DEBUG(4,("initiate_name_query_packet_from_wins_server: sending query for name %s (bcast=%s) to IP %s\n", + nmb_namestr(&nmb->question.question_name), + BOOLSTR(nmb->header.nm_flags.bcast), inet_ntoa(packet->ip))); - return send_netbios_packet( packet ); + return send_netbios_packet( packet ); } /*************************************************************************** @@ -328,21 +319,21 @@ static BOOL initiate_name_query_packet_from_wins_server( struct packet_struct *p static BOOL initiate_name_register_packet( struct packet_struct *packet, uint16 nb_flags, struct in_addr *register_ip) { - struct nmb_packet *nmb = &packet->packet.nmb; + struct nmb_packet *nmb = &packet->packet.nmb; - nmb->header.opcode = NMB_NAME_REG_OPCODE; - nmb->header.arcount = 1; + nmb->header.opcode = NMB_NAME_REG_OPCODE; + nmb->header.arcount = 1; - nmb->header.nm_flags.recursion_desired = True; + nmb->header.nm_flags.recursion_desired = True; - if(create_and_init_additional_record(packet, nb_flags, register_ip) == False) - return False; + if(create_and_init_additional_record(packet, nb_flags, register_ip) == False) + return False; - DEBUG(4,("initiate_name_register_packet: sending registration for name %s (bcast=%s) to IP %s\n", - nmb_namestr(&nmb->additional->rr_name), - BOOLSTR(nmb->header.nm_flags.bcast), inet_ntoa(packet->ip))); + DEBUG(4,("initiate_name_register_packet: sending registration for name %s (bcast=%s) to IP %s\n", + nmb_namestr(&nmb->additional->rr_name), + BOOLSTR(nmb->header.nm_flags.bcast), inet_ntoa(packet->ip))); - return send_netbios_packet( packet ); + return send_netbios_packet( packet ); } /*************************************************************************** @@ -380,21 +371,21 @@ for name %s IP %s (bcast=%s) to IP %s\n", static BOOL initiate_name_refresh_packet( struct packet_struct *packet, uint16 nb_flags, struct in_addr *refresh_ip) { - struct nmb_packet *nmb = &packet->packet.nmb; + struct nmb_packet *nmb = &packet->packet.nmb; - nmb->header.opcode = NMB_NAME_REFRESH_OPCODE_8; - nmb->header.arcount = 1; + nmb->header.opcode = NMB_NAME_REFRESH_OPCODE_8; + nmb->header.arcount = 1; - nmb->header.nm_flags.recursion_desired = False; + nmb->header.nm_flags.recursion_desired = False; - if(create_and_init_additional_record(packet, nb_flags, refresh_ip) == False) - return False; + if(create_and_init_additional_record(packet, nb_flags, refresh_ip) == False) + return False; - DEBUG(4,("initiate_name_refresh_packet: sending refresh for name %s (bcast=%s) to IP %s\n", - nmb_namestr(&nmb->additional->rr_name), - BOOLSTR(nmb->header.nm_flags.bcast), inet_ntoa(packet->ip))); + DEBUG(4,("initiate_name_refresh_packet: sending refresh for name %s (bcast=%s) to IP %s\n", + nmb_namestr(&nmb->additional->rr_name), + BOOLSTR(nmb->header.nm_flags.bcast), inet_ntoa(packet->ip))); - return send_netbios_packet( packet ); + return send_netbios_packet( packet ); } /*************************************************************************** @@ -404,21 +395,21 @@ static BOOL initiate_name_refresh_packet( struct packet_struct *packet, static BOOL initiate_name_release_packet( struct packet_struct *packet, uint16 nb_flags, struct in_addr *release_ip) { - struct nmb_packet *nmb = &packet->packet.nmb; + struct nmb_packet *nmb = &packet->packet.nmb; - nmb->header.opcode = NMB_NAME_RELEASE_OPCODE; - nmb->header.arcount = 1; + nmb->header.opcode = NMB_NAME_RELEASE_OPCODE; + nmb->header.arcount = 1; - nmb->header.nm_flags.recursion_desired = False; + nmb->header.nm_flags.recursion_desired = False; - if(create_and_init_additional_record(packet, nb_flags, release_ip) == False) - return False; + if(create_and_init_additional_record(packet, nb_flags, release_ip) == False) + return False; - DEBUG(4,("initiate_name_release_packet: sending release for name %s (bcast=%s) to IP %s\n", - nmb_namestr(&nmb->additional->rr_name), - BOOLSTR(nmb->header.nm_flags.bcast), inet_ntoa(packet->ip))); + DEBUG(4,("initiate_name_release_packet: sending release for name %s (bcast=%s) to IP %s\n", + nmb_namestr(&nmb->additional->rr_name), + BOOLSTR(nmb->header.nm_flags.bcast), inet_ntoa(packet->ip))); - return send_netbios_packet( packet ); + return send_netbios_packet( packet ); } /*************************************************************************** @@ -427,20 +418,20 @@ static BOOL initiate_name_release_packet( struct packet_struct *packet, static BOOL initiate_node_status_packet( struct packet_struct *packet ) { - struct nmb_packet *nmb = &packet->packet.nmb; + struct nmb_packet *nmb = &packet->packet.nmb; - nmb->header.opcode = NMB_NAME_QUERY_OPCODE; - nmb->header.arcount = 0; + nmb->header.opcode = NMB_NAME_QUERY_OPCODE; + nmb->header.arcount = 0; - nmb->header.nm_flags.recursion_desired = False; + nmb->header.nm_flags.recursion_desired = False; - nmb->question.question_type = QUESTION_TYPE_NB_STATUS; + nmb->question.question_type = QUESTION_TYPE_NB_STATUS; - DEBUG(4,("initiate_node_status_packet: sending node status request for name %s to IP %s\n", - nmb_namestr(&nmb->question.question_name), - inet_ntoa(packet->ip))); + DEBUG(4,("initiate_node_status_packet: sending node status request for name %s to IP %s\n", + nmb_namestr(&nmb->question.question_name), + inet_ntoa(packet->ip))); - return send_netbios_packet( packet ); + return send_netbios_packet( packet ); } /**************************************************************************** @@ -456,13 +447,12 @@ static BOOL initiate_node_status_packet( struct packet_struct *packet ) static BOOL assert_check_subnet(struct subnet_record *subrec) { - if( subrec == remote_broadcast_subnet) - { - DEBUG(0,("assert_check_subnet: Attempt to send packet on remote broadcast subnet. \ + if( subrec == remote_broadcast_subnet) { + DEBUG(0,("assert_check_subnet: Attempt to send packet on remote broadcast subnet. \ This is a bug.\n")); - return True; - } - return False; + return True; + } + return False; } /**************************************************************************** @@ -478,46 +468,42 @@ struct response_record *queue_register_name( struct subnet_record *subrec, struct nmb_name *nmbname, uint16 nb_flags) { - struct packet_struct *p; - struct response_record *rrec; - - if(assert_check_subnet(subrec)) - return NULL; - - /* note that all name registration requests have RD set (rfc1002 - - section 4.2.2 */ - if ((p = create_and_init_netbios_packet(nmbname, (subrec != unicast_subnet), True, - subrec->bcast_ip)) == NULL) - return NULL; - - if(initiate_name_register_packet( p, nb_flags, - iface_ip(subrec->bcast_ip)) == False) - { - p->locked = False; - free_packet(p); - return NULL; - } - - if((rrec = make_response_record(subrec, /* subnet record. */ - p, /* packet we sent. */ - resp_fn, /* function to call on response. */ - timeout_fn, /* function to call on timeout. */ - (success_function)success_fn, /* function to call on operation success. */ - (fail_function)fail_fn, /* function to call on operation fail. */ - userdata)) == NULL) - { - p->locked = False; - free_packet(p); - return NULL; - } - - return rrec; -} + struct packet_struct *p; + struct response_record *rrec; + + if(assert_check_subnet(subrec)) + return NULL; + + /* note that all name registration requests have RD set (rfc1002 - section 4.2.2 */ + if ((p = create_and_init_netbios_packet(nmbname, (subrec != unicast_subnet), True, + subrec->bcast_ip)) == NULL) + return NULL; + + if(initiate_name_register_packet( p, nb_flags, iface_ip(subrec->bcast_ip)) == False) { + p->locked = False; + free_packet(p); + return NULL; + } + + if((rrec = make_response_record(subrec, /* subnet record. */ + p, /* packet we sent. */ + resp_fn, /* function to call on response. */ + timeout_fn, /* function to call on timeout. */ + (success_function)success_fn, /* function to call on operation success. */ + (fail_function)fail_fn, /* function to call on operation fail. */ + userdata)) == NULL) { + p->locked = False; + free_packet(p); + return NULL; + } + return rrec; +} /**************************************************************************** Queue a refresh name packet to the broadcast address of a subnet. ****************************************************************************/ + void queue_wins_refresh(struct nmb_name *nmbname, response_function resp_fn, timeout_response_function timeout_fn, @@ -648,47 +634,44 @@ struct response_record *queue_release_name( struct subnet_record *subrec, struct in_addr release_ip, struct in_addr dest_ip) { - struct packet_struct *p; - struct response_record *rrec; - - if(assert_check_subnet(subrec)) - return NULL; - - if ((p = create_and_init_netbios_packet(nmbname, (subrec != unicast_subnet), False, - dest_ip)) == NULL) - return NULL; - - if(initiate_name_release_packet( p, nb_flags, &release_ip) == False) - { - p->locked = False; - free_packet(p); - return NULL; - } - - if((rrec = make_response_record(subrec, /* subnet record. */ - p, /* packet we sent. */ - resp_fn, /* function to call on response. */ - timeout_fn, /* function to call on timeout. */ - (success_function)success_fn, /* function to call on operation success. */ - (fail_function)fail_fn, /* function to call on operation fail. */ - userdata)) == NULL) - { - p->locked = False; - free_packet(p); - return NULL; - } - - /* - * For a broadcast release packet, only send once. - * This will cause us to remove the name asap. JRA. - */ - - if (subrec != unicast_subnet) { - rrec->repeat_count = 0; - rrec->repeat_time = 0; - } - - return rrec; + struct packet_struct *p; + struct response_record *rrec; + + if(assert_check_subnet(subrec)) + return NULL; + + if ((p = create_and_init_netbios_packet(nmbname, (subrec != unicast_subnet), False, dest_ip)) == NULL) + return NULL; + + if(initiate_name_release_packet( p, nb_flags, &release_ip) == False) { + p->locked = False; + free_packet(p); + return NULL; + } + + if((rrec = make_response_record(subrec, /* subnet record. */ + p, /* packet we sent. */ + resp_fn, /* function to call on response. */ + timeout_fn, /* function to call on timeout. */ + (success_function)success_fn, /* function to call on operation success. */ + (fail_function)fail_fn, /* function to call on operation fail. */ + userdata)) == NULL) { + p->locked = False; + free_packet(p); + return NULL; + } + + /* + * For a broadcast release packet, only send once. + * This will cause us to remove the name asap. JRA. + */ + + if (subrec != unicast_subnet) { + rrec->repeat_count = 0; + rrec->repeat_time = 0; + } + + return rrec; } /**************************************************************************** @@ -703,80 +686,80 @@ struct response_record *queue_query_name( struct subnet_record *subrec, struct userdata_struct *userdata, struct nmb_name *nmbname) { - struct packet_struct *p; - struct response_record *rrec; - struct in_addr to_ip; + struct packet_struct *p; + struct response_record *rrec; + struct in_addr to_ip; - if(assert_check_subnet(subrec)) - return NULL; + if(assert_check_subnet(subrec)) + return NULL; - to_ip = subrec->bcast_ip; + to_ip = subrec->bcast_ip; - /* queries to the WINS server turn up here as queries to IP 0.0.0.0 - These need to be handled a bit differently */ - if (subrec->type == UNICAST_SUBNET && is_zero_ip(to_ip)) { - /* what we really need to do is loop over each of our wins - * servers and wins server tags here, but that just doesn't - * fit our architecture at the moment (userdata may already - * be used when we get here). For now we just query the first - * active wins server on the first tag. */ - char **tags = wins_srv_tags(); - if (!tags) { - return NULL; - } - to_ip = wins_srv_ip_tag(tags[0], to_ip); - wins_srv_tags_free(tags); - } - - if(( p = create_and_init_netbios_packet(nmbname, - (subrec != unicast_subnet), - (subrec == unicast_subnet), - to_ip)) == NULL) - return NULL; - - if(lp_bind_interfaces_only()) { - int i; - - DEBUG(10,("queue_query_name: bind_interfaces_only is set, looking for suitable source IP\n")); - for(i = 0; i < iface_count(); i++) { - struct in_addr *ifip = iface_n_ip(i); - - if(ifip == NULL) { - DEBUG(0,("queue_query_name: interface %d has NULL IP address !\n", i)); - continue; - } - - if (ip_equal(*ifip,loopback_ip)) { - DEBUG(5,("queue_query_name: ignoring loopback interface (%d)\n", i)); - continue; - } - - DEBUG(10,("queue_query_name: using source IP %s\n",inet_ntoa(*ifip))); - p->fd = find_subnet_fd_for_address( *ifip ); - break; - } - } - - if(initiate_name_query_packet( p ) == False) { - p->locked = False; - free_packet(p); - return NULL; - } - - if((rrec = make_response_record(subrec, /* subnet record. */ - p, /* packet we sent. */ - resp_fn, /* function to call on response. */ - timeout_fn, /* function to call on timeout. */ - (success_function)success_fn, /* function to call on operation success. */ - (fail_function)fail_fn, /* function to call on operation fail. */ - userdata)) == NULL) - { - p->locked = False; - free_packet(p); - return NULL; - } - - return rrec; + /* queries to the WINS server turn up here as queries to IP 0.0.0.0 + These need to be handled a bit differently */ + if (subrec->type == UNICAST_SUBNET && is_zero_ip(to_ip)) { + /* What we really need to do is loop over each of our wins + * servers and wins server tags here, but that just doesn't + * fit our architecture at the moment (userdata may already + * be used when we get here). For now we just query the first + * active wins server on the first tag. + */ + char **tags = wins_srv_tags(); + if (!tags) { + return NULL; + } + to_ip = wins_srv_ip_tag(tags[0], to_ip); + wins_srv_tags_free(tags); + } + + if(( p = create_and_init_netbios_packet(nmbname, + (subrec != unicast_subnet), + (subrec == unicast_subnet), + to_ip)) == NULL) + return NULL; + + if(lp_bind_interfaces_only()) { + int i; + + DEBUG(10,("queue_query_name: bind_interfaces_only is set, looking for suitable source IP\n")); + for(i = 0; i < iface_count(); i++) { + struct in_addr *ifip = iface_n_ip(i); + + if(ifip == NULL) { + DEBUG(0,("queue_query_name: interface %d has NULL IP address !\n", i)); + continue; + } + + if (ip_equal(*ifip,loopback_ip)) { + DEBUG(5,("queue_query_name: ignoring loopback interface (%d)\n", i)); + continue; + } + + DEBUG(10,("queue_query_name: using source IP %s\n",inet_ntoa(*ifip))); + p->fd = find_subnet_fd_for_address( *ifip ); + break; + } + } + + if(initiate_name_query_packet( p ) == False) { + p->locked = False; + free_packet(p); + return NULL; + } + + if((rrec = make_response_record(subrec, /* subnet record. */ + p, /* packet we sent. */ + resp_fn, /* function to call on response. */ + timeout_fn, /* function to call on timeout. */ + (success_function)success_fn, /* function to call on operation success. */ + (fail_function)fail_fn, /* function to call on operation fail. */ + userdata)) == NULL) { + p->locked = False; + free_packet(p); + return NULL; + } + + return rrec; } /**************************************************************************** @@ -791,33 +774,31 @@ struct response_record *queue_query_name_from_wins_server( struct in_addr to_ip, struct userdata_struct *userdata, struct nmb_name *nmbname) { - struct packet_struct *p; - struct response_record *rrec; - - if ((p = create_and_init_netbios_packet(nmbname, False, False, to_ip)) == NULL) - return NULL; - - if(initiate_name_query_packet_from_wins_server( p ) == False) - { - p->locked = False; - free_packet(p); - return NULL; - } - - if((rrec = make_response_record(wins_server_subnet, /* subnet record. */ - p, /* packet we sent. */ - resp_fn, /* function to call on response. */ - timeout_fn, /* function to call on timeout. */ - (success_function)success_fn, /* function to call on operation success. */ - (fail_function)fail_fn, /* function to call on operation fail. */ - userdata)) == NULL) - { - p->locked = False; - free_packet(p); - return NULL; - } - - return rrec; + struct packet_struct *p; + struct response_record *rrec; + + if ((p = create_and_init_netbios_packet(nmbname, False, False, to_ip)) == NULL) + return NULL; + + if(initiate_name_query_packet_from_wins_server( p ) == False) { + p->locked = False; + free_packet(p); + return NULL; + } + + if((rrec = make_response_record(wins_server_subnet, /* subnet record. */ + p, /* packet we sent. */ + resp_fn, /* function to call on response. */ + timeout_fn, /* function to call on timeout. */ + (success_function)success_fn, /* function to call on operation success. */ + (fail_function)fail_fn, /* function to call on operation fail. */ + userdata)) == NULL) { + p->locked = False; + free_packet(p); + return NULL; + } + + return rrec; } /**************************************************************************** @@ -833,45 +814,41 @@ struct response_record *queue_node_status( struct subnet_record *subrec, struct nmb_name *nmbname, struct in_addr send_ip) { - struct packet_struct *p; - struct response_record *rrec; + struct packet_struct *p; + struct response_record *rrec; - /* Sanity check. */ - if(subrec != unicast_subnet) - { - DEBUG(0,("queue_register_multihomed_name: should only be done on \ + /* Sanity check. */ + if(subrec != unicast_subnet) { + DEBUG(0,("queue_register_multihomed_name: should only be done on \ unicast subnet. subnet is %s\n.", subrec->subnet_name )); - return NULL; - } - - if(assert_check_subnet(subrec)) - return NULL; - - if(( p = create_and_init_netbios_packet(nmbname, False, False, - send_ip)) == NULL) - return NULL; - - if(initiate_node_status_packet(p) == False) - { - p->locked = False; - free_packet(p); - return NULL; - } - - if((rrec = make_response_record(subrec, /* subnet record. */ - p, /* packet we sent. */ - resp_fn, /* function to call on response. */ - timeout_fn, /* function to call on timeout. */ - (success_function)success_fn, /* function to call on operation success. */ - (fail_function)fail_fn, /* function to call on operation fail. */ - userdata)) == NULL) - { - p->locked = False; - free_packet(p); - return NULL; - } - - return rrec; + return NULL; + } + + if(assert_check_subnet(subrec)) + return NULL; + + if(( p = create_and_init_netbios_packet(nmbname, False, False, send_ip)) == NULL) + return NULL; + + if(initiate_node_status_packet(p) == False) { + p->locked = False; + free_packet(p); + return NULL; + } + + if((rrec = make_response_record(subrec, /* subnet record. */ + p, /* packet we sent. */ + resp_fn, /* function to call on response. */ + timeout_fn, /* function to call on timeout. */ + (success_function)success_fn, /* function to call on operation success. */ + (fail_function)fail_fn, /* function to call on operation fail. */ + userdata)) == NULL) { + p->locked = False; + free_packet(p); + return NULL; + } + + return rrec; } /**************************************************************************** @@ -882,169 +859,145 @@ void reply_netbios_packet(struct packet_struct *orig_packet, int rcode, enum netbios_reply_type_code rcv_code, int opcode, int ttl, char *data,int len) { - struct packet_struct packet; - struct nmb_packet *nmb = NULL; - struct res_rec answers; - struct nmb_packet *orig_nmb = &orig_packet->packet.nmb; - BOOL loopback_this_packet = False; - const char *packet_type = "unknown"; + struct packet_struct packet; + struct nmb_packet *nmb = NULL; + struct res_rec answers; + struct nmb_packet *orig_nmb = &orig_packet->packet.nmb; + BOOL loopback_this_packet = False; + const char *packet_type = "unknown"; - /* Check if we are sending to or from ourselves. */ - if(ismyip(orig_packet->ip) && (orig_packet->port == global_nmb_port)) - loopback_this_packet = True; + /* Check if we are sending to or from ourselves. */ + if(ismyip(orig_packet->ip) && (orig_packet->port == global_nmb_port)) + loopback_this_packet = True; - nmb = &packet.packet.nmb; - - /* Do a partial copy of the packet. We clear the locked flag and - the resource record pointers. */ - packet = *orig_packet; /* Full structure copy. */ - packet.locked = False; - nmb->answers = NULL; - nmb->nsrecs = NULL; - nmb->additional = NULL; - - switch (rcv_code) - { - case NMB_STATUS: - { - packet_type = "nmb_status"; - nmb->header.nm_flags.recursion_desired = False; - nmb->header.nm_flags.recursion_available = False; - break; - } - case NMB_QUERY: - { - packet_type = "nmb_query"; - nmb->header.nm_flags.recursion_desired = True; - nmb->header.nm_flags.recursion_available = True; - break; - } - case NMB_REG: - case NMB_REG_REFRESH: - { - packet_type = "nmb_reg"; - nmb->header.nm_flags.recursion_desired = True; - nmb->header.nm_flags.recursion_available = True; - break; - } - case NMB_REL: - { - packet_type = "nmb_rel"; - nmb->header.nm_flags.recursion_desired = False; - nmb->header.nm_flags.recursion_available = False; - break; - } - case NMB_WAIT_ACK: - { - packet_type = "nmb_wack"; - nmb->header.nm_flags.recursion_desired = False; - nmb->header.nm_flags.recursion_available = False; - break; - } - case WINS_REG: - { - packet_type = "wins_reg"; - nmb->header.nm_flags.recursion_desired = True; - nmb->header.nm_flags.recursion_available = True; - break; - } - case WINS_QUERY: - { - packet_type = "wins_query"; - nmb->header.nm_flags.recursion_desired = True; - nmb->header.nm_flags.recursion_available = True; - break; - } - - default: - { - DEBUG(0,("reply_netbios_packet: Unknown packet type: %s %s to ip %s\n", - packet_type, nmb_namestr(&orig_nmb->question.question_name), - inet_ntoa(packet.ip))); - - return; - } - } - - DEBUG(4,("reply_netbios_packet: sending a reply of packet type: %s %s to ip %s \ -for id %hu\n", - packet_type, nmb_namestr(&orig_nmb->question.question_name), - inet_ntoa(packet.ip), orig_nmb->header.name_trn_id)); - - nmb->header.name_trn_id = orig_nmb->header.name_trn_id; - nmb->header.opcode = opcode; - nmb->header.response = True; - nmb->header.nm_flags.bcast = False; - nmb->header.nm_flags.trunc = False; - nmb->header.nm_flags.authoritative = True; + nmb = &packet.packet.nmb; + + /* Do a partial copy of the packet. We clear the locked flag and + the resource record pointers. */ + packet = *orig_packet; /* Full structure copy. */ + packet.locked = False; + nmb->answers = NULL; + nmb->nsrecs = NULL; + nmb->additional = NULL; + + switch (rcv_code) { + case NMB_STATUS: + packet_type = "nmb_status"; + nmb->header.nm_flags.recursion_desired = False; + nmb->header.nm_flags.recursion_available = False; + break; + case NMB_QUERY: + packet_type = "nmb_query"; + nmb->header.nm_flags.recursion_desired = True; + nmb->header.nm_flags.recursion_available = True; + break; + case NMB_REG: + case NMB_REG_REFRESH: + packet_type = "nmb_reg"; + nmb->header.nm_flags.recursion_desired = True; + nmb->header.nm_flags.recursion_available = True; + break; + case NMB_REL: + packet_type = "nmb_rel"; + nmb->header.nm_flags.recursion_desired = False; + nmb->header.nm_flags.recursion_available = False; + break; + case NMB_WAIT_ACK: + packet_type = "nmb_wack"; + nmb->header.nm_flags.recursion_desired = False; + nmb->header.nm_flags.recursion_available = False; + break; + case WINS_REG: + packet_type = "wins_reg"; + nmb->header.nm_flags.recursion_desired = True; + nmb->header.nm_flags.recursion_available = True; + break; + case WINS_QUERY: + packet_type = "wins_query"; + nmb->header.nm_flags.recursion_desired = True; + nmb->header.nm_flags.recursion_available = True; + break; + default: + DEBUG(0,("reply_netbios_packet: Unknown packet type: %s %s to ip %s\n", + packet_type, nmb_namestr(&orig_nmb->question.question_name), + inet_ntoa(packet.ip))); + return; + } + + DEBUG(4,("reply_netbios_packet: sending a reply of packet type: %s %s to ip %s \ +for id %hu\n", packet_type, nmb_namestr(&orig_nmb->question.question_name), + inet_ntoa(packet.ip), orig_nmb->header.name_trn_id)); + + nmb->header.name_trn_id = orig_nmb->header.name_trn_id; + nmb->header.opcode = opcode; + nmb->header.response = True; + nmb->header.nm_flags.bcast = False; + nmb->header.nm_flags.trunc = False; + nmb->header.nm_flags.authoritative = True; - nmb->header.rcode = rcode; - nmb->header.qdcount = 0; - nmb->header.ancount = 1; - nmb->header.nscount = 0; - nmb->header.arcount = 0; + nmb->header.rcode = rcode; + nmb->header.qdcount = 0; + nmb->header.ancount = 1; + nmb->header.nscount = 0; + nmb->header.arcount = 0; - memset((char*)&nmb->question,'\0',sizeof(nmb->question)); + memset((char*)&nmb->question,'\0',sizeof(nmb->question)); - nmb->answers = &answers; - memset((char*)nmb->answers,'\0',sizeof(*nmb->answers)); + nmb->answers = &answers; + memset((char*)nmb->answers,'\0',sizeof(*nmb->answers)); - nmb->answers->rr_name = orig_nmb->question.question_name; - nmb->answers->rr_type = orig_nmb->question.question_type; - nmb->answers->rr_class = orig_nmb->question.question_class; - nmb->answers->ttl = ttl; + nmb->answers->rr_name = orig_nmb->question.question_name; + nmb->answers->rr_type = orig_nmb->question.question_type; + nmb->answers->rr_class = orig_nmb->question.question_class; + nmb->answers->ttl = ttl; - if (data && len) - { - nmb->answers->rdlength = len; - memcpy(nmb->answers->rdata, data, len); - } + if (data && len) { + nmb->answers->rdlength = len; + memcpy(nmb->answers->rdata, data, len); + } - packet.packet_type = NMB_PACKET; - /* Ensure we send out on the same fd that the original - packet came in on to give the correct source IP address. */ - packet.fd = orig_packet->fd; - packet.timestamp = time(NULL); + packet.packet_type = NMB_PACKET; + /* Ensure we send out on the same fd that the original + packet came in on to give the correct source IP address. */ + packet.fd = orig_packet->fd; + packet.timestamp = time(NULL); - debug_nmb_packet(&packet); + debug_nmb_packet(&packet); - if(loopback_this_packet) - { - struct packet_struct *lo_packet; - DEBUG(5,("reply_netbios_packet: sending packet to ourselves.\n")); - if((lo_packet = copy_packet(&packet)) == NULL) - return; - queue_packet(lo_packet); - } - else if (!send_packet(&packet)) - { - DEBUG(0,("reply_netbios_packet: send_packet to IP %s port %d failed\n", - inet_ntoa(packet.ip),packet.port)); - } + if(loopback_this_packet) { + struct packet_struct *lo_packet; + DEBUG(5,("reply_netbios_packet: sending packet to ourselves.\n")); + if((lo_packet = copy_packet(&packet)) == NULL) + return; + queue_packet(lo_packet); + } else if (!send_packet(&packet)) { + DEBUG(0,("reply_netbios_packet: send_packet to IP %s port %d failed\n", + inet_ntoa(packet.ip),packet.port)); + } } /******************************************************************* Queue a packet into a packet queue ******************************************************************/ + static void queue_packet(struct packet_struct *packet) { - struct packet_struct *p; - - if (!packet_queue) - { - packet->prev = NULL; - packet->next = NULL; - packet_queue = packet; - return; - } + struct packet_struct *p; + + if (!packet_queue) { + packet->prev = NULL; + packet->next = NULL; + packet_queue = packet; + return; + } - /* find the bottom */ - for (p=packet_queue;p->next;p=p->next) - ; + /* find the bottom */ + for (p=packet_queue;p->next;p=p->next) + ; - p->next = packet; - packet->next = NULL; - packet->prev = p; + p->next = packet; + packet->next = NULL; + packet->prev = p; } /**************************************************************************** @@ -1053,184 +1006,153 @@ static void queue_packet(struct packet_struct *packet) static struct subnet_record *find_subnet_for_dgram_browse_packet(struct packet_struct *p) { - struct subnet_record *subrec; - - /* Go through all the broadcast subnets and see if the mask matches. */ - for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) - { - if(same_net(p->ip, subrec->bcast_ip, subrec->mask_ip)) - return subrec; - } - - /* If the subnet record is the remote announce broadcast subnet, - hack it here to be the first subnet. This is really gross and - is needed due to people turning on port 137/138 broadcast - forwarding on their routers. May fire and brimstone rain - down upon them... - */ - - return FIRST_SUBNET; + struct subnet_record *subrec; + + /* Go through all the broadcast subnets and see if the mask matches. */ + for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) { + if(same_net(p->ip, subrec->bcast_ip, subrec->mask_ip)) + return subrec; + } + + /* If the subnet record is the remote announce broadcast subnet, + hack it here to be the first subnet. This is really gross and + is needed due to people turning on port 137/138 broadcast + forwarding on their routers. May fire and brimstone rain + down upon them... + */ + + return FIRST_SUBNET; } /**************************************************************************** Dispatch a browse frame from port 138 to the correct processing function. ****************************************************************************/ + static void process_browse_packet(struct packet_struct *p, char *buf,int len) { - struct dgram_packet *dgram = &p->packet.dgram; - int command = CVAL(buf,0); - struct subnet_record *subrec = find_subnet_for_dgram_browse_packet(p); - - /* Drop the packet if it's a different NetBIOS scope, or - the source is from one of our names. */ - - if (!strequal(dgram->dest_name.scope, global_scope())) - { - DEBUG(7,("process_browse_packet: Discarding datagram from IP %s. Scope (%s) \ -mismatch with our scope (%s).\n", inet_ntoa(p->ip), dgram->dest_name.scope, global_scope())); - return; - } - - if (is_myname(dgram->source_name.name)) - { - DEBUG(0,("process_browse_packet: Discarding datagram from IP %s. Source name \ + struct dgram_packet *dgram = &p->packet.dgram; + int command = CVAL(buf,0); + struct subnet_record *subrec = find_subnet_for_dgram_browse_packet(p); + char scope[64]; + nstring src_name; + + /* Drop the packet if it's a different NetBIOS scope, or the source is from one of our names. */ + pull_ascii(scope, dgram->dest_name.scope, 64, 64, STR_TERMINATE); + if (!strequal(scope, global_scope())) { + DEBUG(7,("process_browse_packet: Discarding datagram from IP %s. Scope (%s) \ +mismatch with our scope (%s).\n", inet_ntoa(p->ip), scope, global_scope())); + return; + } + + pull_ascii_nstring(src_name, dgram->source_name.name); + if (is_myname(src_name)) { + DEBUG(0,("process_browse_packet: Discarding datagram from IP %s. Source name \ %s is one of our names !\n", inet_ntoa(p->ip), nmb_namestr(&dgram->source_name))); - return; - } - - switch (command) - { - case ANN_HostAnnouncement: - { - debug_browse_data(buf, len); - process_host_announce(subrec, p, buf+1); - break; - } - case ANN_DomainAnnouncement: - { - debug_browse_data(buf, len); - process_workgroup_announce(subrec, p, buf+1); - break; - } - case ANN_LocalMasterAnnouncement: - { - debug_browse_data(buf, len); - process_local_master_announce(subrec, p, buf+1); - break; - } - case ANN_AnnouncementRequest: - { - debug_browse_data(buf, len); - process_announce_request(subrec, p, buf+1); - break; - } - case ANN_Election: - { - debug_browse_data(buf, len); - process_election(subrec, p, buf+1); - break; - } - case ANN_GetBackupListReq: - { - debug_browse_data(buf, len); - process_get_backup_list_request(subrec, p, buf+1); - break; - } - case ANN_GetBackupListResp: - { - debug_browse_data(buf, len); - /* We never send ANN_GetBackupListReq so we - should never get these. */ - DEBUG(0,("process_browse_packet: Discarding GetBackupListResponse \ + return; + } + + switch (command) { + case ANN_HostAnnouncement: + debug_browse_data(buf, len); + process_host_announce(subrec, p, buf+1); + break; + case ANN_DomainAnnouncement: + debug_browse_data(buf, len); + process_workgroup_announce(subrec, p, buf+1); + break; + case ANN_LocalMasterAnnouncement: + debug_browse_data(buf, len); + process_local_master_announce(subrec, p, buf+1); + break; + case ANN_AnnouncementRequest: + debug_browse_data(buf, len); + process_announce_request(subrec, p, buf+1); + break; + case ANN_Election: + debug_browse_data(buf, len); + process_election(subrec, p, buf+1); + break; + case ANN_GetBackupListReq: + debug_browse_data(buf, len); + process_get_backup_list_request(subrec, p, buf+1); + break; + case ANN_GetBackupListResp: + debug_browse_data(buf, len); + /* We never send ANN_GetBackupListReq so we should never get these. */ + DEBUG(0,("process_browse_packet: Discarding GetBackupListResponse \ packet from %s IP %s\n", nmb_namestr(&dgram->source_name), inet_ntoa(p->ip))); - break; - } - case ANN_ResetBrowserState: - { - debug_browse_data(buf, len); - process_reset_browser(subrec, p, buf+1); - break; - } - case ANN_MasterAnnouncement: - { - /* Master browser datagrams must be processed - on the unicast subnet. */ - subrec = unicast_subnet; - - debug_browse_data(buf, len); - process_master_browser_announce(subrec, p, buf+1); - break; - } - case ANN_BecomeBackup: - { - /* - * We don't currently implement this. Log it just in case. - */ - debug_browse_data(buf, len); - DEBUG(10,("process_browse_packet: On subnet %s ignoring browse packet \ -command ANN_BecomeBackup from %s IP %s to %s\n", - subrec->subnet_name, nmb_namestr(&dgram->source_name), - inet_ntoa(p->ip), nmb_namestr(&dgram->dest_name))); - break; - } - default: - { - debug_browse_data(buf, len); - DEBUG(0,("process_browse_packet: On subnet %s ignoring browse packet \ -command code %d from %s IP %s to %s\n", - subrec->subnet_name, command, nmb_namestr(&dgram->source_name), - inet_ntoa(p->ip), nmb_namestr(&dgram->dest_name))); - } - } + break; + case ANN_ResetBrowserState: + debug_browse_data(buf, len); + process_reset_browser(subrec, p, buf+1); + break; + case ANN_MasterAnnouncement: + /* Master browser datagrams must be processed on the unicast subnet. */ + subrec = unicast_subnet; + + debug_browse_data(buf, len); + process_master_browser_announce(subrec, p, buf+1); + break; + case ANN_BecomeBackup: + /* + * We don't currently implement this. Log it just in case. + */ + debug_browse_data(buf, len); + DEBUG(10,("process_browse_packet: On subnet %s ignoring browse packet \ +command ANN_BecomeBackup from %s IP %s to %s\n", subrec->subnet_name, nmb_namestr(&dgram->source_name), + inet_ntoa(p->ip), nmb_namestr(&dgram->dest_name))); + break; + default: + debug_browse_data(buf, len); + DEBUG(0,("process_browse_packet: On subnet %s ignoring browse packet \ +command code %d from %s IP %s to %s\n", subrec->subnet_name, command, nmb_namestr(&dgram->source_name), + inet_ntoa(p->ip), nmb_namestr(&dgram->dest_name))); + break; + } } /**************************************************************************** Dispatch a LanMan browse frame from port 138 to the correct processing function. ****************************************************************************/ + static void process_lanman_packet(struct packet_struct *p, char *buf,int len) { - struct dgram_packet *dgram = &p->packet.dgram; - int command = SVAL(buf,0); - struct subnet_record *subrec = find_subnet_for_dgram_browse_packet(p); - - /* Drop the packet if it's a different NetBIOS scope, or - the source is from one of our names. */ - - if (!strequal(dgram->dest_name.scope, global_scope())) - { - DEBUG(7,("process_lanman_packet: Discarding datagram from IP %s. Scope (%s) \ -mismatch with our scope (%s).\n", inet_ntoa(p->ip), dgram->dest_name.scope, global_scope())); - return; - } - - if (is_myname(dgram->source_name.name)) - { - DEBUG(0,("process_lanman_packet: Discarding datagram from IP %s. Source name \ + struct dgram_packet *dgram = &p->packet.dgram; + int command = SVAL(buf,0); + struct subnet_record *subrec = find_subnet_for_dgram_browse_packet(p); + char scope[64]; + nstring src_name; + + /* Drop the packet if it's a different NetBIOS scope, or the source is from one of our names. */ + + pull_ascii(scope, dgram->dest_name.scope, 64, 64, STR_TERMINATE); + if (!strequal(scope, global_scope())) { + DEBUG(7,("process_lanman_packet: Discarding datagram from IP %s. Scope (%s) \ +mismatch with our scope (%s).\n", inet_ntoa(p->ip), scope, global_scope())); + return; + } + + pull_ascii_nstring(src_name, dgram->source_name.name); + if (is_myname(src_name)) { + DEBUG(0,("process_lanman_packet: Discarding datagram from IP %s. Source name \ %s is one of our names !\n", inet_ntoa(p->ip), nmb_namestr(&dgram->source_name))); - return; - } - - switch (command) - { - case ANN_HostAnnouncement: - { - debug_browse_data(buf, len); - process_lm_host_announce(subrec, p, buf+1); - break; - } - case ANN_AnnouncementRequest: - { - process_lm_announce_request(subrec, p, buf+1); - break; - } - default: - { - DEBUG(0,("process_lanman_packet: On subnet %s ignoring browse packet \ -command code %d from %s IP %s to %s\n", - subrec->subnet_name, command, nmb_namestr(&dgram->source_name), - inet_ntoa(p->ip), nmb_namestr(&dgram->dest_name))); - } - } + return; + } + + switch (command) { + case ANN_HostAnnouncement: + debug_browse_data(buf, len); + process_lm_host_announce(subrec, p, buf+1); + break; + case ANN_AnnouncementRequest: + process_lm_announce_request(subrec, p, buf+1); + break; + default: + DEBUG(0,("process_lanman_packet: On subnet %s ignoring browse packet \ +command code %d from %s IP %s to %s\n", subrec->subnet_name, command, nmb_namestr(&dgram->source_name), + inet_ntoa(p->ip), nmb_namestr(&dgram->dest_name))); + break; + } } /**************************************************************************** @@ -1241,104 +1163,94 @@ command code %d from %s IP %s to %s\n", static BOOL listening(struct packet_struct *p,struct nmb_name *nbname) { - struct subnet_record *subrec = NULL; + struct subnet_record *subrec = NULL; - for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) - { - if(same_net(p->ip, subrec->bcast_ip, subrec->mask_ip)) - break; - } + for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) { + if(same_net(p->ip, subrec->bcast_ip, subrec->mask_ip)) + break; + } - if(subrec == NULL) - subrec = unicast_subnet; + if(subrec == NULL) + subrec = unicast_subnet; - return (find_name_on_subnet(subrec, nbname, FIND_SELF_NAME) != NULL); + return (find_name_on_subnet(subrec, nbname, FIND_SELF_NAME) != NULL); } /**************************************************************************** Process udp 138 datagrams ****************************************************************************/ + static void process_dgram(struct packet_struct *p) { - char *buf; - char *buf2; - int len; - struct dgram_packet *dgram = &p->packet.dgram; - - /* If we aren't listening to the destination name then ignore the packet */ - if (!listening(p,&dgram->dest_name)) - { - unexpected_packet(p); - DEBUG(5,("process_dgram: ignoring dgram packet sent to name %s from %s\n", - nmb_namestr(&dgram->dest_name), inet_ntoa(p->ip))); - return; - } - - if (dgram->header.msg_type != 0x10 && - dgram->header.msg_type != 0x11 && - dgram->header.msg_type != 0x12) - { - unexpected_packet(p); - /* Don't process error packets etc yet */ - DEBUG(5,("process_dgram: ignoring dgram packet sent to name %s from IP %s as it is \ -an error packet of type %x\n", - nmb_namestr(&dgram->dest_name), inet_ntoa(p->ip), dgram->header.msg_type)); - return; - } - - buf = &dgram->data[0]; - buf -= 4; /* XXXX for the pseudo tcp length - - someday I need to get rid of this */ - - if (CVAL(buf,smb_com) != SMBtrans) - return; - - len = SVAL(buf,smb_vwv11); - buf2 = smb_base(buf) + SVAL(buf,smb_vwv12); - - if (len <= 0) - return; - - if (buf2 + len > buf + sizeof(dgram->data)) { - DEBUG(2,("process_dgram: datagram from %s to %s IP %s for %s len=%d too long.\n", + char *buf; + char *buf2; + int len; + struct dgram_packet *dgram = &p->packet.dgram; + + /* If we aren't listening to the destination name then ignore the packet */ + if (!listening(p,&dgram->dest_name)) { + unexpected_packet(p); + DEBUG(5,("process_dgram: ignoring dgram packet sent to name %s from %s\n", + nmb_namestr(&dgram->dest_name), inet_ntoa(p->ip))); + return; + } + + if (dgram->header.msg_type != 0x10 && dgram->header.msg_type != 0x11 && dgram->header.msg_type != 0x12) { + unexpected_packet(p); + /* Don't process error packets etc yet */ + DEBUG(5,("process_dgram: ignoring dgram packet sent to name %s from IP %s as it is \ +an error packet of type %x\n", nmb_namestr(&dgram->dest_name), inet_ntoa(p->ip), dgram->header.msg_type)); + return; + } + + buf = &dgram->data[0]; + buf -= 4; /* XXXX for the pseudo tcp length - someday I need to get rid of this */ + + if (CVAL(buf,smb_com) != SMBtrans) + return; + + len = SVAL(buf,smb_vwv11); + buf2 = smb_base(buf) + SVAL(buf,smb_vwv12); + + if (len <= 0) + return; + + if (buf2 + len > buf + sizeof(dgram->data)) { + DEBUG(2,("process_dgram: datagram from %s to %s IP %s for %s len=%d too long.\n", + nmb_namestr(&dgram->source_name),nmb_namestr(&dgram->dest_name), + inet_ntoa(p->ip), smb_buf(buf),len)); + len = (buf + sizeof(dgram->data)) - buf; + } + + DEBUG(4,("process_dgram: datagram from %s to %s IP %s for %s of type %d len=%d\n", nmb_namestr(&dgram->source_name),nmb_namestr(&dgram->dest_name), - inet_ntoa(p->ip), smb_buf(buf),len)); - len = (buf + sizeof(dgram->data)) - buf; - } + inet_ntoa(p->ip), smb_buf(buf),CVAL(buf2,0),len)); - DEBUG(4,("process_dgram: datagram from %s to %s IP %s for %s of type %d len=%d\n", - nmb_namestr(&dgram->source_name),nmb_namestr(&dgram->dest_name), - inet_ntoa(p->ip), smb_buf(buf),CVAL(buf2,0),len)); + /* Datagram packet received for the browser mailslot */ + if (strequal(smb_buf(buf),BROWSE_MAILSLOT)) { + process_browse_packet(p,buf2,len); + return; + } - - /* Datagram packet received for the browser mailslot */ - if (strequal(smb_buf(buf),BROWSE_MAILSLOT)) - { - process_browse_packet(p,buf2,len); - return; - } - - /* Datagram packet received for the LAN Manager mailslot */ - if (strequal(smb_buf(buf),LANMAN_MAILSLOT)) { - process_lanman_packet(p,buf2,len); - return; - } - - /* Datagram packet received for the domain logon mailslot */ - if (strequal(smb_buf(buf),NET_LOGON_MAILSLOT)) - { - process_logon_packet(p,buf2,len,NET_LOGON_MAILSLOT); - return; - } - - /* Datagram packet received for the NT domain logon mailslot */ - if (strequal(smb_buf(buf),NT_LOGON_MAILSLOT)) - { - process_logon_packet(p,buf2,len,NT_LOGON_MAILSLOT); - return; - } - - unexpected_packet(p); + /* Datagram packet received for the LAN Manager mailslot */ + if (strequal(smb_buf(buf),LANMAN_MAILSLOT)) { + process_lanman_packet(p,buf2,len); + return; + } + + /* Datagram packet received for the domain logon mailslot */ + if (strequal(smb_buf(buf),NET_LOGON_MAILSLOT)) { + process_logon_packet(p,buf2,len,NET_LOGON_MAILSLOT); + return; + } + + /* Datagram packet received for the NT domain logon mailslot */ + if (strequal(smb_buf(buf),NT_LOGON_MAILSLOT)) { + process_logon_packet(p,buf2,len,NT_LOGON_MAILSLOT); + return; + } + + unexpected_packet(p); } /**************************************************************************** @@ -1347,52 +1259,49 @@ an error packet of type %x\n", static BOOL validate_nmb_response_packet( struct nmb_packet *nmb ) { - BOOL ignore = False; - - switch (nmb->header.opcode) - { - case NMB_NAME_REG_OPCODE: - case NMB_NAME_REFRESH_OPCODE_8: /* ambiguity in rfc1002 about which is correct. */ - case NMB_NAME_REFRESH_OPCODE_9: /* WinNT uses 8 by default. */ - if (nmb->header.ancount == 0) - { - DEBUG(0,("validate_nmb_response_packet: Bad REG/REFRESH Packet. ")); - ignore = True; - } - break; - - case NMB_NAME_QUERY_OPCODE: - if ((nmb->header.ancount != 0) && (nmb->header.ancount != 1)) - { - DEBUG(0,("validate_nmb_response_packet: Bad QUERY Packet. ")); - ignore = True; - } - break; - case NMB_NAME_RELEASE_OPCODE: - if (nmb->header.ancount == 0) - { - DEBUG(0,("validate_nmb_response_packet: Bad RELEASE Packet. ")); - ignore = True; - } - break; - case NMB_WACK_OPCODE: - /* Check WACK response here. */ - if (nmb->header.ancount != 1) - { - DEBUG(0,("validate_nmb_response_packet: Bad WACK Packet. ")); - ignore = True; - } - break; - default: - DEBUG(0,("validate_nmb_response_packet: Ignoring packet with unknown opcode %d.\n", - nmb->header.opcode)); - return True; - } - - if(ignore) - DEBUG(0,("Ignoring response packet with opcode %d.\n", nmb->header.opcode)); - - return ignore; + BOOL ignore = False; + + switch (nmb->header.opcode) { + case NMB_NAME_REG_OPCODE: + case NMB_NAME_REFRESH_OPCODE_8: /* ambiguity in rfc1002 about which is correct. */ + case NMB_NAME_REFRESH_OPCODE_9: /* WinNT uses 8 by default. */ + if (nmb->header.ancount == 0) { + DEBUG(0,("validate_nmb_response_packet: Bad REG/REFRESH Packet. ")); + ignore = True; + } + break; + + case NMB_NAME_QUERY_OPCODE: + if ((nmb->header.ancount != 0) && (nmb->header.ancount != 1)) { + DEBUG(0,("validate_nmb_response_packet: Bad QUERY Packet. ")); + ignore = True; + } + break; + + case NMB_NAME_RELEASE_OPCODE: + if (nmb->header.ancount == 0) { + DEBUG(0,("validate_nmb_response_packet: Bad RELEASE Packet. ")); + ignore = True; + } + break; + + case NMB_WACK_OPCODE: + /* Check WACK response here. */ + if (nmb->header.ancount != 1) { + DEBUG(0,("validate_nmb_response_packet: Bad WACK Packet. ")); + ignore = True; + } + break; + default: + DEBUG(0,("validate_nmb_response_packet: Ignoring packet with unknown opcode %d.\n", + nmb->header.opcode)); + return True; + } + + if(ignore) + DEBUG(0,("Ignoring response packet with opcode %d.\n", nmb->header.opcode)); + + return ignore; } /**************************************************************************** @@ -1401,48 +1310,43 @@ static BOOL validate_nmb_response_packet( struct nmb_packet *nmb ) static BOOL validate_nmb_packet( struct nmb_packet *nmb ) { - BOOL ignore = False; - - switch (nmb->header.opcode) - { - case NMB_NAME_REG_OPCODE: - case NMB_NAME_REFRESH_OPCODE_8: /* ambiguity in rfc1002 about which is correct. */ - case NMB_NAME_REFRESH_OPCODE_9: /* WinNT uses 8 by default. */ - case NMB_NAME_MULTIHOMED_REG_OPCODE: - if (nmb->header.qdcount==0 || nmb->header.arcount==0) - { - DEBUG(0,("validate_nmb_packet: Bad REG/REFRESH Packet. ")); - ignore = True; - } - break; - - case NMB_NAME_QUERY_OPCODE: - if ((nmb->header.qdcount == 0) || - ((nmb->question.question_type != QUESTION_TYPE_NB_QUERY) && - (nmb->question.question_type != QUESTION_TYPE_NB_STATUS))) - { - DEBUG(0,("validate_nmb_packet: Bad QUERY Packet. ")); - ignore = True; - } - break; - - case NMB_NAME_RELEASE_OPCODE: - if (nmb->header.qdcount==0 || nmb->header.arcount==0) - { - DEBUG(0,("validate_nmb_packet: Bad RELEASE Packet. ")); - ignore = True; - } - break; - default: - DEBUG(0,("validate_nmb_packet: Ignoring packet with unknown opcode %d.\n", - nmb->header.opcode)); - return True; - } - - if(ignore) - DEBUG(0,("validate_nmb_packet: Ignoring request packet with opcode %d.\n", nmb->header.opcode)); - - return ignore; + BOOL ignore = False; + + switch (nmb->header.opcode) { + case NMB_NAME_REG_OPCODE: + case NMB_NAME_REFRESH_OPCODE_8: /* ambiguity in rfc1002 about which is correct. */ + case NMB_NAME_REFRESH_OPCODE_9: /* WinNT uses 8 by default. */ + case NMB_NAME_MULTIHOMED_REG_OPCODE: + if (nmb->header.qdcount==0 || nmb->header.arcount==0) { + DEBUG(0,("validate_nmb_packet: Bad REG/REFRESH Packet. ")); + ignore = True; + } + break; + + case NMB_NAME_QUERY_OPCODE: + if ((nmb->header.qdcount == 0) || ((nmb->question.question_type != QUESTION_TYPE_NB_QUERY) && + (nmb->question.question_type != QUESTION_TYPE_NB_STATUS))) { + DEBUG(0,("validate_nmb_packet: Bad QUERY Packet. ")); + ignore = True; + } + break; + + case NMB_NAME_RELEASE_OPCODE: + if (nmb->header.qdcount==0 || nmb->header.arcount==0) { + DEBUG(0,("validate_nmb_packet: Bad RELEASE Packet. ")); + ignore = True; + } + break; + default: + DEBUG(0,("validate_nmb_packet: Ignoring packet with unknown opcode %d.\n", + nmb->header.opcode)); + return True; + } + + if(ignore) + DEBUG(0,("validate_nmb_packet: Ignoring request packet with opcode %d.\n", nmb->header.opcode)); + + return ignore; } /**************************************************************************** @@ -1452,58 +1356,53 @@ static BOOL validate_nmb_packet( struct nmb_packet *nmb ) static struct subnet_record *find_subnet_for_nmb_packet( struct packet_struct *p, struct response_record **pprrec) { - struct nmb_packet *nmb = &p->packet.nmb; - struct response_record *rrec = NULL; - struct subnet_record *subrec = NULL; - - if(pprrec != NULL) - *pprrec = NULL; - - if(nmb->header.response) - { - /* It's a response packet. Find a record for it or it's an error. */ - - rrec = find_response_record( &subrec, nmb->header.name_trn_id); - if(rrec == NULL) - { - DEBUG(3,("find_subnet_for_nmb_packet: response record not found for response id %hu\n", - nmb->header.name_trn_id)); - unexpected_packet(p); - return NULL; - } - - if(subrec == NULL) - { - DEBUG(0,("find_subnet_for_nmb_packet: subnet record not found for response id %hu\n", - nmb->header.name_trn_id)); - return NULL; - } - - if(pprrec != NULL) - *pprrec = rrec; - return subrec; - } - - /* Try and see what subnet this packet belongs to. */ - - /* WINS server ? */ - if(packet_is_for_wins_server(p)) - return wins_server_subnet; - - /* If it wasn't a broadcast packet then send to the UNICAST subnet. */ - if(nmb->header.nm_flags.bcast == False) - return unicast_subnet; - - /* Go through all the broadcast subnets and see if the mask matches. */ - for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) - { - if(same_net(p->ip, subrec->bcast_ip, subrec->mask_ip)) - return subrec; - } - - /* If none match it must have been a directed broadcast - assign - the remote_broadcast_subnet. */ - return remote_broadcast_subnet; + struct nmb_packet *nmb = &p->packet.nmb; + struct response_record *rrec = NULL; + struct subnet_record *subrec = NULL; + + if(pprrec != NULL) + *pprrec = NULL; + + if(nmb->header.response) { + /* It's a response packet. Find a record for it or it's an error. */ + + rrec = find_response_record( &subrec, nmb->header.name_trn_id); + if(rrec == NULL) { + DEBUG(3,("find_subnet_for_nmb_packet: response record not found for response id %hu\n", + nmb->header.name_trn_id)); + unexpected_packet(p); + return NULL; + } + + if(subrec == NULL) { + DEBUG(0,("find_subnet_for_nmb_packet: subnet record not found for response id %hu\n", + nmb->header.name_trn_id)); + return NULL; + } + + if(pprrec != NULL) + *pprrec = rrec; + return subrec; + } + + /* Try and see what subnet this packet belongs to. */ + + /* WINS server ? */ + if(packet_is_for_wins_server(p)) + return wins_server_subnet; + + /* If it wasn't a broadcast packet then send to the UNICAST subnet. */ + if(nmb->header.nm_flags.bcast == False) + return unicast_subnet; + + /* Go through all the broadcast subnets and see if the mask matches. */ + for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) { + if(same_net(p->ip, subrec->bcast_ip, subrec->mask_ip)) + return subrec; + } + + /* If none match it must have been a directed broadcast - assign the remote_broadcast_subnet. */ + return remote_broadcast_subnet; } /**************************************************************************** @@ -1512,79 +1411,71 @@ static struct subnet_record *find_subnet_for_nmb_packet( struct packet_struct *p static void process_nmb_request(struct packet_struct *p) { - struct nmb_packet *nmb = &p->packet.nmb; - struct subnet_record *subrec = NULL; - - debug_nmb_packet(p); - - /* Ensure we have a good packet. */ - if(validate_nmb_packet(nmb)) - return; - - /* Allocate a subnet to this packet - if we cannot - fail. */ - if((subrec = find_subnet_for_nmb_packet(p, NULL))==NULL) - return; - - switch (nmb->header.opcode) - { - case NMB_NAME_REG_OPCODE: - if(subrec == wins_server_subnet) - wins_process_name_registration_request(subrec, p); - else - process_name_registration_request(subrec, p); - break; - - case NMB_NAME_REFRESH_OPCODE_8: /* ambiguity in rfc1002 about which is correct. */ - case NMB_NAME_REFRESH_OPCODE_9: - if(subrec == wins_server_subnet) - wins_process_name_refresh_request(subrec, p); - else - process_name_refresh_request(subrec, p); - break; - - case NMB_NAME_MULTIHOMED_REG_OPCODE: - if(subrec == wins_server_subnet) - wins_process_multihomed_name_registration_request(subrec, p); - else - { - DEBUG(0,("process_nmb_request: Multihomed registration request must be \ + struct nmb_packet *nmb = &p->packet.nmb; + struct subnet_record *subrec = NULL; + + debug_nmb_packet(p); + + /* Ensure we have a good packet. */ + if(validate_nmb_packet(nmb)) + return; + + /* Allocate a subnet to this packet - if we cannot - fail. */ + if((subrec = find_subnet_for_nmb_packet(p, NULL))==NULL) + return; + + switch (nmb->header.opcode) { + case NMB_NAME_REG_OPCODE: + if(subrec == wins_server_subnet) + wins_process_name_registration_request(subrec, p); + else + process_name_registration_request(subrec, p); + break; + + case NMB_NAME_REFRESH_OPCODE_8: /* ambiguity in rfc1002 about which is correct. */ + case NMB_NAME_REFRESH_OPCODE_9: + if(subrec == wins_server_subnet) + wins_process_name_refresh_request(subrec, p); + else + process_name_refresh_request(subrec, p); + break; + + case NMB_NAME_MULTIHOMED_REG_OPCODE: + if(subrec == wins_server_subnet) { + wins_process_multihomed_name_registration_request(subrec, p); + } else { + DEBUG(0,("process_nmb_request: Multihomed registration request must be \ directed at a WINS server.\n")); - } - break; - - case NMB_NAME_QUERY_OPCODE: - switch (nmb->question.question_type) - { - case QUESTION_TYPE_NB_QUERY: - { - if(subrec == wins_server_subnet) - wins_process_name_query_request(subrec, p); - else - process_name_query_request(subrec, p); - break; - } - case QUESTION_TYPE_NB_STATUS: - { - if(subrec == wins_server_subnet) - { - DEBUG(0,("process_nmb_request: NB_STATUS request directed at WINS server is \ + } + break; + + case NMB_NAME_QUERY_OPCODE: + switch (nmb->question.question_type) { + case QUESTION_TYPE_NB_QUERY: + if(subrec == wins_server_subnet) + wins_process_name_query_request(subrec, p); + else + process_name_query_request(subrec, p); + break; + case QUESTION_TYPE_NB_STATUS: + if(subrec == wins_server_subnet) { + DEBUG(0,("process_nmb_request: NB_STATUS request directed at WINS server is \ not allowed.\n")); - break; - } - else - process_node_status_request(subrec, p); - break; - } - } - break; + break; + } else { + process_node_status_request(subrec, p); + } + break; + } + break; - case NMB_NAME_RELEASE_OPCODE: - if(subrec == wins_server_subnet) - wins_process_name_release_request(subrec, p); - else - process_name_release_request(subrec, p); - break; - } + case NMB_NAME_RELEASE_OPCODE: + if(subrec == wins_server_subnet) + wins_process_name_release_request(subrec, p); + else + process_name_release_request(subrec, p); + break; + } } /**************************************************************************** @@ -1594,65 +1485,61 @@ not allowed.\n")); static void process_nmb_response(struct packet_struct *p) { - struct nmb_packet *nmb = &p->packet.nmb; - struct subnet_record *subrec = NULL; - struct response_record *rrec = NULL; + struct nmb_packet *nmb = &p->packet.nmb; + struct subnet_record *subrec = NULL; + struct response_record *rrec = NULL; - debug_nmb_packet(p); + debug_nmb_packet(p); - if(validate_nmb_response_packet(nmb)) - return; + if(validate_nmb_response_packet(nmb)) + return; - if((subrec = find_subnet_for_nmb_packet(p, &rrec))==NULL) - return; + if((subrec = find_subnet_for_nmb_packet(p, &rrec))==NULL) + return; - if(rrec == NULL) - { - DEBUG(0,("process_nmb_response: response packet received but no response record \ + if(rrec == NULL) { + DEBUG(0,("process_nmb_response: response packet received but no response record \ found for id = %hu. Ignoring packet.\n", nmb->header.name_trn_id)); - return; - } + return; + } - /* Increment the number of responses received for this record. */ - rrec->num_msgs++; - /* Ensure we don't re-send the request. */ - rrec->repeat_count = 0; + /* Increment the number of responses received for this record. */ + rrec->num_msgs++; + /* Ensure we don't re-send the request. */ + rrec->repeat_count = 0; - /* Call the response received function for this packet. */ - (*rrec->resp_fn)(subrec, rrec, p); + /* Call the response received function for this packet. */ + (*rrec->resp_fn)(subrec, rrec, p); } - /******************************************************************* Run elements off the packet queue till its empty ******************************************************************/ void run_packet_queue(void) { - struct packet_struct *p; - - while ((p = packet_queue)) - { - packet_queue = p->next; - if (packet_queue) - packet_queue->prev = NULL; - p->next = p->prev = NULL; - - switch (p->packet_type) - { - case NMB_PACKET: - if(p->packet.nmb.header.response) - process_nmb_response(p); - else - process_nmb_request(p); - break; - - case DGRAM_PACKET: - process_dgram(p); - break; - } - free_packet(p); - } + struct packet_struct *p; + + while ((p = packet_queue)) { + packet_queue = p->next; + if (packet_queue) + packet_queue->prev = NULL; + p->next = p->prev = NULL; + + switch (p->packet_type) { + case NMB_PACKET: + if(p->packet.nmb.header.response) + process_nmb_response(p); + else + process_nmb_request(p); + break; + + case DGRAM_PACKET: + process_dgram(p); + break; + } + free_packet(p); + } } /******************************************************************* @@ -1665,66 +1552,54 @@ void run_packet_queue(void) void retransmit_or_expire_response_records(time_t t) { - struct subnet_record *subrec; + struct subnet_record *subrec; - for (subrec = FIRST_SUBNET; subrec; - subrec = get_next_subnet_maybe_unicast_or_wins_server(subrec)) - { - struct response_record *rrec, *nextrrec; + for (subrec = FIRST_SUBNET; subrec; subrec = get_next_subnet_maybe_unicast_or_wins_server(subrec)) { + struct response_record *rrec, *nextrrec; - for (rrec = subrec->responselist; rrec; rrec = nextrrec) - { - nextrrec = rrec->next; + for (rrec = subrec->responselist; rrec; rrec = nextrrec) { + nextrrec = rrec->next; - if (rrec->repeat_time <= t) - { - if (rrec->repeat_count > 0) - { - /* Resend while we have a non-zero repeat_count. */ - if(!send_packet(rrec->packet)) - { - DEBUG(0,("retransmit_or_expire_response_records: Failed to resend packet id %hu \ -to IP %s on subnet %s\n", rrec->response_id, inet_ntoa(rrec->packet->ip), - subrec->subnet_name)); - } - rrec->repeat_time = t + rrec->repeat_interval; - rrec->repeat_count--; - } - else - { - DEBUG(4,("retransmit_or_expire_response_records: timeout for packet id %hu to IP %s \ -on subnet %s\n", rrec->response_id, inet_ntoa(rrec->packet->ip), - subrec->subnet_name)); - - /* - * Check the flag in this record to prevent recursion if we end - * up in this function again via the timeout function call. - */ - - if(!rrec->in_expiration_processing) - { - - /* - * Set the recursion protection flag in this record. - */ - - rrec->in_expiration_processing = True; - - /* Call the timeout function. This will deal with removing the - timed out packet. */ - if(rrec->timeout_fn) - (*rrec->timeout_fn)(subrec, rrec); - else - { - /* We must remove the record ourself if there is - no timeout function. */ - remove_response_record(subrec, rrec); - } - } /* !rrec->in_expitation_processing */ - } /* rrec->repeat_count > 0 */ - } /* rrec->repeat_time <= t */ - } /* end for rrec */ - } /* end for subnet */ + if (rrec->repeat_time <= t) { + if (rrec->repeat_count > 0) { + /* Resend while we have a non-zero repeat_count. */ + if(!send_packet(rrec->packet)) { + DEBUG(0,("retransmit_or_expire_response_records: Failed to resend packet id %hu \ +to IP %s on subnet %s\n", rrec->response_id, inet_ntoa(rrec->packet->ip), subrec->subnet_name)); + } + rrec->repeat_time = t + rrec->repeat_interval; + rrec->repeat_count--; + } else { + DEBUG(4,("retransmit_or_expire_response_records: timeout for packet id %hu to IP %s \ +on subnet %s\n", rrec->response_id, inet_ntoa(rrec->packet->ip), subrec->subnet_name)); + + /* + * Check the flag in this record to prevent recursion if we end + * up in this function again via the timeout function call. + */ + + if(!rrec->in_expiration_processing) { + + /* + * Set the recursion protection flag in this record. + */ + + rrec->in_expiration_processing = True; + + /* Call the timeout function. This will deal with removing the + timed out packet. */ + if(rrec->timeout_fn) { + (*rrec->timeout_fn)(subrec, rrec); + } else { + /* We must remove the record ourself if there is + no timeout function. */ + remove_response_record(subrec, rrec); + } + } /* !rrec->in_expitation_processing */ + } /* rrec->repeat_count > 0 */ + } /* rrec->repeat_time <= t */ + } /* end for rrec */ + } /* end for subnet */ } /**************************************************************************** @@ -1734,68 +1609,63 @@ on subnet %s\n", rrec->response_id, inet_ntoa(rrec->packet->ip), static BOOL create_listen_fdset(fd_set **ppset, int **psock_array, int *listen_number) { - int *sock_array = NULL; - struct subnet_record *subrec = NULL; - int count = 0; - int num = 0; - fd_set *pset = (fd_set *)malloc(sizeof(fd_set)); - - if(pset == NULL) - { - DEBUG(0,("create_listen_fdset: malloc fail !\n")); - return True; - } - - /* Check that we can add all the fd's we need. */ - for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) - count++; - - if((count*2) + 2 > FD_SETSIZE) - { - DEBUG(0,("create_listen_fdset: Too many file descriptors needed (%d). We can \ + int *sock_array = NULL; + struct subnet_record *subrec = NULL; + int count = 0; + int num = 0; + fd_set *pset = (fd_set *)malloc(sizeof(fd_set)); + + if(pset == NULL) { + DEBUG(0,("create_listen_fdset: malloc fail !\n")); + return True; + } + + /* Check that we can add all the fd's we need. */ + for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) + count++; + + if((count*2) + 2 > FD_SETSIZE) { + DEBUG(0,("create_listen_fdset: Too many file descriptors needed (%d). We can \ only use %d.\n", (count*2) + 2, FD_SETSIZE)); - return True; - } - - if((sock_array = (int *)malloc(((count*2) + 2)*sizeof(int))) == NULL) - { - DEBUG(0,("create_listen_fdset: malloc fail for socket array.\n")); - return True; - } - - FD_ZERO(pset); - - /* Add in the broadcast socket on 137. */ - FD_SET(ClientNMB,pset); - sock_array[num++] = ClientNMB; - - /* Add in the 137 sockets on all the interfaces. */ - for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) - { - FD_SET(subrec->nmb_sock,pset); - sock_array[num++] = subrec->nmb_sock; - } - - /* Add in the broadcast socket on 138. */ - FD_SET(ClientDGRAM,pset); - sock_array[num++] = ClientDGRAM; - - /* Add in the 138 sockets on all the interfaces. */ - for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) - { - FD_SET(subrec->dgram_sock,pset); - sock_array[num++] = subrec->dgram_sock; - } - - *listen_number = (count*2) + 2; - - SAFE_FREE(*ppset); - SAFE_FREE(*psock_array); - - *ppset = pset; - *psock_array = sock_array; + return True; + } + + if((sock_array = (int *)malloc(((count*2) + 2)*sizeof(int))) == NULL) { + DEBUG(0,("create_listen_fdset: malloc fail for socket array.\n")); + return True; + } + + FD_ZERO(pset); + + /* Add in the broadcast socket on 137. */ + FD_SET(ClientNMB,pset); + sock_array[num++] = ClientNMB; + + /* Add in the 137 sockets on all the interfaces. */ + for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) { + FD_SET(subrec->nmb_sock,pset); + sock_array[num++] = subrec->nmb_sock; + } + + /* Add in the broadcast socket on 138. */ + FD_SET(ClientDGRAM,pset); + sock_array[num++] = ClientDGRAM; + + /* Add in the 138 sockets on all the interfaces. */ + for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) { + FD_SET(subrec->dgram_sock,pset); + sock_array[num++] = subrec->dgram_sock; + } + + *listen_number = (count*2) + 2; + + SAFE_FREE(*ppset); + SAFE_FREE(*psock_array); + + *ppset = pset; + *psock_array = sock_array; - return False; + return False; } /**************************************************************************** @@ -1805,214 +1675,211 @@ only use %d.\n", (count*2) + 2, FD_SETSIZE)); BOOL listen_for_packets(BOOL run_election) { - static fd_set *listen_set = NULL; - static int listen_number = 0; - static int *sock_array = NULL; - int i; - - fd_set fds; - int selrtn; - struct timeval timeout; + static fd_set *listen_set = NULL; + static int listen_number = 0; + static int *sock_array = NULL; + int i; + + fd_set fds; + int selrtn; + struct timeval timeout; #ifndef SYNC_DNS - int dns_fd; + int dns_fd; #endif - if(listen_set == NULL || rescan_listen_set) - { - if(create_listen_fdset(&listen_set, &sock_array, &listen_number)) - { - DEBUG(0,("listen_for_packets: Fatal error. unable to create listen set. Exiting.\n")); - return True; - } - rescan_listen_set = False; - } + if(listen_set == NULL || rescan_listen_set) { + if(create_listen_fdset(&listen_set, &sock_array, &listen_number)) { + DEBUG(0,("listen_for_packets: Fatal error. unable to create listen set. Exiting.\n")); + return True; + } + rescan_listen_set = False; + } - memcpy((char *)&fds, (char *)listen_set, sizeof(fd_set)); + memcpy((char *)&fds, (char *)listen_set, sizeof(fd_set)); #ifndef SYNC_DNS - dns_fd = asyncdns_fd(); - if (dns_fd != -1) { - FD_SET(dns_fd, &fds); - } + dns_fd = asyncdns_fd(); + if (dns_fd != -1) { + FD_SET(dns_fd, &fds); + } #endif + /* + * During elections and when expecting a netbios response packet we + * need to send election packets at tighter intervals. + * Ideally it needs to be the interval (in ms) between time now and + * the time we are expecting the next netbios packet. + */ - /* - * During elections and when expecting a netbios response packet we - * need to send election packets at tighter intervals. - * Ideally it needs to be the interval (in ms) between time now and - * the time we are expecting the next netbios packet. - */ - - timeout.tv_sec = (run_election||num_response_packets) ? 1 : NMBD_SELECT_LOOP; - timeout.tv_usec = 0; + timeout.tv_sec = (run_election||num_response_packets) ? 1 : NMBD_SELECT_LOOP; + timeout.tv_usec = 0; - /* Prepare for the select - allow certain signals. */ + /* Prepare for the select - allow certain signals. */ - BlockSignals(False, SIGTERM); + BlockSignals(False, SIGTERM); - selrtn = sys_select(FD_SETSIZE,&fds,NULL,NULL,&timeout); + selrtn = sys_select(FD_SETSIZE,&fds,NULL,NULL,&timeout); - /* We can only take signals when we are in the select - block them again here. */ + /* We can only take signals when we are in the select - block them again here. */ - BlockSignals(True, SIGTERM); + BlockSignals(True, SIGTERM); - if(selrtn == -1) { - return False; - } + if(selrtn == -1) { + return False; + } #ifndef SYNC_DNS - if (dns_fd != -1 && FD_ISSET(dns_fd,&fds)) { - run_dns_queue(); - } + if (dns_fd != -1 && FD_ISSET(dns_fd,&fds)) { + run_dns_queue(); + } #endif - for(i = 0; i < listen_number; i++) { - if (i < (listen_number/2)) { - /* Processing a 137 socket. */ - if (FD_ISSET(sock_array[i],&fds)) { - struct packet_struct *packet = read_packet(sock_array[i], NMB_PACKET); - if (packet) { - /* - * If we got a packet on the broadcast socket and interfaces - * only is set then check it came from one of our local nets. - */ - if(lp_bind_interfaces_only() && (sock_array[i] == ClientNMB) && - (!is_local_net(packet->ip))) { - DEBUG(7,("discarding nmb packet sent to broadcast socket from %s:%d\n", - inet_ntoa(packet->ip),packet->port)); - free_packet(packet); - } else if ((ip_equal(loopback_ip, packet->ip) || - ismyip(packet->ip)) && packet->port == global_nmb_port && - packet->packet.nmb.header.nm_flags.bcast) { - DEBUG(7,("discarding own bcast packet from %s:%d\n", - inet_ntoa(packet->ip),packet->port)); - free_packet(packet); - } else { - /* Save the file descriptor this packet came in on. */ - packet->fd = sock_array[i]; - queue_packet(packet); - } - } - } - } else { - /* Processing a 138 socket. */ - if (FD_ISSET(sock_array[i],&fds)) { - struct packet_struct *packet = read_packet(sock_array[i], DGRAM_PACKET); - if (packet) { - /* - * If we got a packet on the broadcast socket and interfaces - * only is set then check it came from one of our local nets. - */ - if(lp_bind_interfaces_only() && (sock_array[i] == ClientDGRAM) && - (!is_local_net(packet->ip))) { - DEBUG(7,("discarding dgram packet sent to broadcast socket from %s:%d\n", - inet_ntoa(packet->ip),packet->port)); - free_packet(packet); - } else if ((ip_equal(loopback_ip, packet->ip) || - ismyip(packet->ip)) && packet->port == DGRAM_PORT) { - DEBUG(7,("discarding own dgram packet from %s:%d\n", - inet_ntoa(packet->ip),packet->port)); - free_packet(packet); - } else { - /* Save the file descriptor this packet came in on. */ - packet->fd = sock_array[i]; - queue_packet(packet); - } - } - } - } /* end processing 138 socket. */ - } /* end for */ - return False; + for(i = 0; i < listen_number; i++) { + if (i < (listen_number/2)) { + /* Processing a 137 socket. */ + if (FD_ISSET(sock_array[i],&fds)) { + struct packet_struct *packet = read_packet(sock_array[i], NMB_PACKET); + if (packet) { + /* + * If we got a packet on the broadcast socket and interfaces + * only is set then check it came from one of our local nets. + */ + if(lp_bind_interfaces_only() && (sock_array[i] == ClientNMB) && + (!is_local_net(packet->ip))) { + DEBUG(7,("discarding nmb packet sent to broadcast socket from %s:%d\n", + inet_ntoa(packet->ip),packet->port)); + free_packet(packet); + } else if ((ip_equal(loopback_ip, packet->ip) || + ismyip(packet->ip)) && packet->port == global_nmb_port && + packet->packet.nmb.header.nm_flags.bcast) { + DEBUG(7,("discarding own bcast packet from %s:%d\n", + inet_ntoa(packet->ip),packet->port)); + free_packet(packet); + } else { + /* Save the file descriptor this packet came in on. */ + packet->fd = sock_array[i]; + queue_packet(packet); + } + } + } + } else { + /* Processing a 138 socket. */ + if (FD_ISSET(sock_array[i],&fds)) { + struct packet_struct *packet = read_packet(sock_array[i], DGRAM_PACKET); + if (packet) { + /* + * If we got a packet on the broadcast socket and interfaces + * only is set then check it came from one of our local nets. + */ + if(lp_bind_interfaces_only() && (sock_array[i] == ClientDGRAM) && + (!is_local_net(packet->ip))) { + DEBUG(7,("discarding dgram packet sent to broadcast socket from %s:%d\n", + inet_ntoa(packet->ip),packet->port)); + free_packet(packet); + } else if ((ip_equal(loopback_ip, packet->ip) || + ismyip(packet->ip)) && packet->port == DGRAM_PORT) { + DEBUG(7,("discarding own dgram packet from %s:%d\n", + inet_ntoa(packet->ip),packet->port)); + free_packet(packet); + } else { + /* Save the file descriptor this packet came in on. */ + packet->fd = sock_array[i]; + queue_packet(packet); + } + } + } + } /* end processing 138 socket. */ + } /* end for */ + return False; } /**************************************************************************** Construct and send a netbios DGRAM. **************************************************************************/ + BOOL send_mailslot(BOOL unique, const char *mailslot,char *buf, size_t len, const char *srcname, int src_type, const char *dstname, int dest_type, struct in_addr dest_ip,struct in_addr src_ip, int dest_port) { - BOOL loopback_this_packet = False; - struct packet_struct p; - struct dgram_packet *dgram = &p.packet.dgram; - char *ptr,*p2; - char tmp[4]; - - memset((char *)&p,'\0',sizeof(p)); - - if(ismyip(dest_ip) && (dest_port == DGRAM_PORT)) /* Only if to DGRAM_PORT */ - loopback_this_packet = True; - - /* generate_name_trn_id(); */ /* Not used, so gone, RJS */ - - /* DIRECT GROUP or UNIQUE datagram. */ - dgram->header.msg_type = unique ? 0x10 : 0x11; - dgram->header.flags.node_type = M_NODE; - dgram->header.flags.first = True; - dgram->header.flags.more = False; - dgram->header.dgm_id = generate_name_trn_id(); - dgram->header.source_ip = src_ip; - dgram->header.source_port = DGRAM_PORT; - dgram->header.dgm_length = 0; /* Let build_dgram() handle this. */ - dgram->header.packet_offset = 0; + BOOL loopback_this_packet = False; + struct packet_struct p; + struct dgram_packet *dgram = &p.packet.dgram; + char *ptr,*p2; + char tmp[4]; + + memset((char *)&p,'\0',sizeof(p)); + + if(ismyip(dest_ip) && (dest_port == DGRAM_PORT)) /* Only if to DGRAM_PORT */ + loopback_this_packet = True; + + /* generate_name_trn_id(); */ /* Not used, so gone, RJS */ + + /* DIRECT GROUP or UNIQUE datagram. */ + dgram->header.msg_type = unique ? 0x10 : 0x11; + dgram->header.flags.node_type = M_NODE; + dgram->header.flags.first = True; + dgram->header.flags.more = False; + dgram->header.dgm_id = generate_name_trn_id(); + dgram->header.source_ip = src_ip; + dgram->header.source_port = DGRAM_PORT; + dgram->header.dgm_length = 0; /* Let build_dgram() handle this. */ + dgram->header.packet_offset = 0; - make_nmb_name(&dgram->source_name,srcname,src_type); - make_nmb_name(&dgram->dest_name,dstname,dest_type); - - ptr = &dgram->data[0]; - - /* Setup the smb part. */ - ptr -= 4; /* XXX Ugliness because of handling of tcp SMB length. */ - memcpy(tmp,ptr,4); - set_message(ptr,17,23 + len,True); - memcpy(ptr,tmp,4); - - SCVAL(ptr,smb_com,SMBtrans); - SSVAL(ptr,smb_vwv1,len); - SSVAL(ptr,smb_vwv11,len); - SSVAL(ptr,smb_vwv12,70 + strlen(mailslot)); - SSVAL(ptr,smb_vwv13,3); - SSVAL(ptr,smb_vwv14,1); - SSVAL(ptr,smb_vwv15,1); - SSVAL(ptr,smb_vwv16,2); - p2 = smb_buf(ptr); - safe_strcpy_base(p2, mailslot, dgram->data, sizeof(dgram->data)); - p2 = skip_string(p2,1); + make_nmb_name(&dgram->source_name,srcname,src_type); + make_nmb_name(&dgram->dest_name,dstname,dest_type); + + ptr = &dgram->data[0]; + + /* Setup the smb part. */ + ptr -= 4; /* XXX Ugliness because of handling of tcp SMB length. */ + memcpy(tmp,ptr,4); + set_message(ptr,17,23 + len,True); + memcpy(ptr,tmp,4); + + SCVAL(ptr,smb_com,SMBtrans); + SSVAL(ptr,smb_vwv1,len); + SSVAL(ptr,smb_vwv11,len); + SSVAL(ptr,smb_vwv12,70 + strlen(mailslot)); + SSVAL(ptr,smb_vwv13,3); + SSVAL(ptr,smb_vwv14,1); + SSVAL(ptr,smb_vwv15,1); + SSVAL(ptr,smb_vwv16,2); + p2 = smb_buf(ptr); + safe_strcpy_base(p2, mailslot, dgram->data, sizeof(dgram->data)); + p2 = skip_string(p2,1); - if (((p2+len) > dgram->data+sizeof(dgram->data)) || ((p2+len) < p2)) { - DEBUG(0, ("send_mailslot: Cannot write beyond end of packet\n")); - return False; - } else { - memcpy(p2,buf,len); - p2 += len; - } - - dgram->datasize = PTR_DIFF(p2,ptr+4); /* +4 for tcp length. */ - - p.ip = dest_ip; - p.port = dest_port; - p.fd = find_subnet_mailslot_fd_for_address( src_ip ); - p.timestamp = time(NULL); - p.packet_type = DGRAM_PACKET; - - DEBUG(4,("send_mailslot: Sending to mailslot %s from %s IP %s ", mailslot, - nmb_namestr(&dgram->source_name), inet_ntoa(src_ip))); - DEBUG(4,("to %s IP %s\n", nmb_namestr(&dgram->dest_name), inet_ntoa(dest_ip))); - - debug_browse_data(buf, len); - - if(loopback_this_packet) - { - struct packet_struct *lo_packet = NULL; - DEBUG(5,("send_mailslot: sending packet to ourselves.\n")); - if((lo_packet = copy_packet(&p)) == NULL) - return False; - queue_packet(lo_packet); - return True; - } - else - return(send_packet(&p)); + if (((p2+len) > dgram->data+sizeof(dgram->data)) || ((p2+len) < p2)) { + DEBUG(0, ("send_mailslot: Cannot write beyond end of packet\n")); + return False; + } else { + memcpy(p2,buf,len); + p2 += len; + } + + dgram->datasize = PTR_DIFF(p2,ptr+4); /* +4 for tcp length. */ + + p.ip = dest_ip; + p.port = dest_port; + p.fd = find_subnet_mailslot_fd_for_address( src_ip ); + p.timestamp = time(NULL); + p.packet_type = DGRAM_PACKET; + + DEBUG(4,("send_mailslot: Sending to mailslot %s from %s IP %s ", mailslot, + nmb_namestr(&dgram->source_name), inet_ntoa(src_ip))); + DEBUG(4,("to %s IP %s\n", nmb_namestr(&dgram->dest_name), inet_ntoa(dest_ip))); + + debug_browse_data(buf, len); + + if(loopback_this_packet) { + struct packet_struct *lo_packet = NULL; + DEBUG(5,("send_mailslot: sending packet to ourselves.\n")); + if((lo_packet = copy_packet(&p)) == NULL) + return False; + queue_packet(lo_packet); + return True; + } else { + return(send_packet(&p)); + } } diff --git a/source3/nmbd/nmbd_processlogon.c b/source3/nmbd/nmbd_processlogon.c index bc3540af70..2a6a6b66d1 100644 --- a/source3/nmbd/nmbd_processlogon.c +++ b/source3/nmbd/nmbd_processlogon.c @@ -3,7 +3,7 @@ NBT netbios routines and daemon - version 2 Copyright (C) Andrew Tridgell 1994-1998 Copyright (C) Luke Kenneth Casson Leighton 1994-1998 - Copyright (C) Jeremy Allison 1994-1998 + Copyright (C) Jeremy Allison 1994-2003 Copyright (C) Jim McDonough 2002 This program is free software; you can redistribute it and/or modify @@ -35,6 +35,7 @@ struct sam_database_info { /**************************************************************************** Send a message to smbd to do a sam delta sync **************************************************************************/ + static void send_repl_message(uint32 low_serial) { TDB_CONTEXT *tdb; @@ -64,432 +65,452 @@ Process a domain logon packet void process_logon_packet(struct packet_struct *p, char *buf,int len, const char *mailslot) { - struct dgram_packet *dgram = &p->packet.dgram; - pstring my_name; - fstring reply_name; - pstring outbuf; - int code; - uint16 token = 0; - uint32 ntversion = 0; - uint16 lmnttoken = 0; - uint16 lm20token = 0; - uint32 domainsidsize; - BOOL short_request = False; - char *getdc; - char *uniuser; /* Unicode user name. */ - pstring ascuser; - char *unicomp; /* Unicode computer name. */ - - memset(outbuf, 0, sizeof(outbuf)); - - if (!lp_domain_logons()) - { - DEBUG(3,("process_logon_packet: Logon packet received from IP %s and domain \ + struct dgram_packet *dgram = &p->packet.dgram; + pstring my_name; + fstring reply_name; + pstring outbuf; + int code; + uint16 token = 0; + uint32 ntversion = 0; + uint16 lmnttoken = 0; + uint16 lm20token = 0; + uint32 domainsidsize; + BOOL short_request = False; + char *getdc; + char *uniuser; /* Unicode user name. */ + pstring ascuser; + char *unicomp; /* Unicode computer name. */ + + memset(outbuf, 0, sizeof(outbuf)); + + if (!lp_domain_logons()) { + DEBUG(3,("process_logon_packet: Logon packet received from IP %s and domain \ logons are not enabled.\n", inet_ntoa(p->ip) )); - return; - } - - pstrcpy(my_name, global_myname()); - - code = SVAL(buf,0); - DEBUG(1,("process_logon_packet: Logon from %s: code = 0x%x\n", inet_ntoa(p->ip), code)); - - switch (code) - { - case 0: - { - char *q = buf + 2; - char *machine = q; - char *user = skip_string(machine,1); - - getdc = skip_string(user,1); - q = skip_string(getdc,1); - token = SVAL(q,3); - - fstrcpy(reply_name,my_name); - - DEBUG(3,("process_logon_packet: Domain login request from %s at IP %s user=%s token=%x\n", - machine,inet_ntoa(p->ip),user,token)); - - q = outbuf; - SSVAL(q, 0, 6); - q += 2; - - fstrcpy(reply_name, "\\\\"); - fstrcat(reply_name, my_name); - fstrcpy(q, reply_name); q = skip_string(q, 1); /* PDC name */ - - SSVAL(q, 0, token); - q += 2; - - dump_data(4, outbuf, PTR_DIFF(q, outbuf)); - - send_mailslot(True, getdc, - outbuf,PTR_DIFF(q,outbuf), - global_myname(), 0x0, - machine, - dgram->source_name.name_type, - p->ip, *iface_ip(p->ip), p->port); - break; - } - - case QUERYFORPDC: - { - char *q = buf + 2; - char *machine = q; - - if (!lp_domain_master()) - { - /* We're not Primary Domain Controller -- ignore this */ - return; - } - - getdc = skip_string(machine,1); - q = skip_string(getdc,1); - q = ALIGN2(q, buf); - - /* at this point we can work out if this is a W9X or NT style - request. Experiments show that the difference is wether the - packet ends here. For a W9X request we now end with a pair of - bytes (usually 0xFE 0xFF) whereas with NT we have two further - strings - the following is a simple way of detecting this */ - if (len - PTR_DIFF(q, buf) <= 3) { - short_request = True; - } else { - unicomp = q; - - /* A full length (NT style) request */ - q = skip_unibuf(unicomp, PTR_DIFF(buf + len, unicomp)); - - if (len - PTR_DIFF(q, buf) > 8) { + return; + } + + pstrcpy(my_name, global_myname()); + + code = SVAL(buf,0); + DEBUG(1,("process_logon_packet: Logon from %s: code = 0x%x\n", inet_ntoa(p->ip), code)); + + switch (code) { + case 0: + { + fstring mach_str, user_str, getdc_str; + char *q = buf + 2; + char *machine = q; + char *user = skip_string(machine,1); + + getdc = skip_string(user,1); + q = skip_string(getdc,1); + token = SVAL(q,3); + + fstrcpy(reply_name,my_name); + + pull_ascii_fstring(mach_str, machine); + pull_ascii_fstring(user_str, user); + pull_ascii_fstring(getdc_str, getdc); + + DEBUG(3,("process_logon_packet: Domain login request from %s at IP %s user=%s token=%x\n", + mach_str,inet_ntoa(p->ip),user_str,token)); + + q = outbuf; + SSVAL(q, 0, 6); + q += 2; + + fstrcpy(reply_name, "\\\\"); + fstrcat(reply_name, my_name); + push_ascii_fstring(q, reply_name); + q = skip_string(q, 1); /* PDC name */ + + SSVAL(q, 0, token); + q += 2; + + dump_data(4, outbuf, PTR_DIFF(q, outbuf)); + + send_mailslot(True, getdc_str, + outbuf,PTR_DIFF(q,outbuf), + global_myname(), 0x0, + mach_str, + dgram->source_name.name_type, + p->ip, *iface_ip(p->ip), p->port); + break; + } + + case QUERYFORPDC: + { + fstring mach_str, getdc_str; + nstring source_name; + char *q = buf + 2; + char *machine = q; + + if (!lp_domain_master()) { + /* We're not Primary Domain Controller -- ignore this */ + return; + } + + getdc = skip_string(machine,1); + q = skip_string(getdc,1); + q = ALIGN2(q, buf); + + /* At this point we can work out if this is a W9X or NT style + request. Experiments show that the difference is wether the + packet ends here. For a W9X request we now end with a pair of + bytes (usually 0xFE 0xFF) whereas with NT we have two further + strings - the following is a simple way of detecting this */ + + if (len - PTR_DIFF(q, buf) <= 3) { + short_request = True; + } else { + unicomp = q; + + /* A full length (NT style) request */ + q = skip_unibuf(unicomp, PTR_DIFF(buf + len, unicomp)); + + if (len - PTR_DIFF(q, buf) > 8) { + /* with NT5 clients we can sometimes + get additional data - a length specificed string + containing the domain name, then 16 bytes of + data (no idea what it is) */ + int dom_len = CVAL(q, 0); + q++; + if (dom_len != 0) { + q += dom_len + 1; + } + q += 16; + } + ntversion = IVAL(q, 0); + lmnttoken = SVAL(q, 4); + lm20token = SVAL(q, 6); + } + + /* Construct reply. */ + q = outbuf; + SSVAL(q, 0, QUERYFORPDC_R); + q += 2; + + fstrcpy(reply_name,my_name); + push_ascii_fstring(q, reply_name); + q = skip_string(q, 1); /* PDC name */ + + /* PDC and domain name */ + if (!short_request) { + /* Make a full reply */ + q = ALIGN2(q, outbuf); + + q += dos_PutUniCode(q, my_name, sizeof(pstring), True); /* PDC name */ + q += dos_PutUniCode(q, lp_workgroup(),sizeof(pstring), True); /* Domain name*/ + SIVAL(q, 0, 1); /* our nt version */ + SSVAL(q, 4, 0xffff); /* our lmnttoken */ + SSVAL(q, 6, 0xffff); /* our lm20token */ + q += 8; + } + + /* RJS, 21-Feb-2000, we send a short reply if the request was short */ + + pull_ascii_fstring(mach_str, machine); + + DEBUG(3,("process_logon_packet: GETDC request from %s at IP %s, \ +reporting %s domain %s 0x%x ntversion=%x lm_nt token=%x lm_20 token=%x\n", + mach_str,inet_ntoa(p->ip), reply_name, lp_workgroup(), + QUERYFORPDC_R, (uint32)ntversion, (uint32)lmnttoken, + (uint32)lm20token )); + + dump_data(4, outbuf, PTR_DIFF(q, outbuf)); + + pull_ascii_fstring(getdc_str, getdc); + pull_ascii_nstring(source_name, dgram->source_name.name); + + send_mailslot(True, getdc_str, + outbuf,PTR_DIFF(q,outbuf), + global_myname(), 0x0, + source_name, + dgram->source_name.name_type, + p->ip, *iface_ip(p->ip), p->port); + return; + } + + case SAMLOGON: + + { + fstring getdc_str; + nstring source_name; + char *q = buf + 2; + fstring asccomp; + + q += 2; + unicomp = q; + uniuser = skip_unibuf(unicomp, PTR_DIFF(buf+len, unicomp)); + getdc = skip_unibuf(uniuser,PTR_DIFF(buf+len, uniuser)); + q = skip_string(getdc,1); + q += 4; /* Account Control Bits - indicating username type */ + domainsidsize = IVAL(q, 0); + q += 4; + + DEBUG(3,("process_logon_packet: SAMLOGON sidsize %d, len = %d\n", domainsidsize, len)); + + if (domainsidsize < (len - PTR_DIFF(q, buf)) && (domainsidsize != 0)) { + q += domainsidsize; + q = ALIGN4(q, buf); + } + + DEBUG(3,("process_logon_packet: len = %d PTR_DIFF(q, buf) = %d\n", len, PTR_DIFF(q, buf) )); + + if (len - PTR_DIFF(q, buf) > 8) { /* with NT5 clients we can sometimes - get additional data - a length specificed string - containing the domain name, then 16 bytes of - data (no idea what it is) */ + get additional data - a length specificed string + containing the domain name, then 16 bytes of + data (no idea what it is) */ int dom_len = CVAL(q, 0); q++; - if (dom_len != 0) { + if (dom_len < (len - PTR_DIFF(q, buf)) && (dom_len != 0)) { q += dom_len + 1; } q += 16; - } - ntversion = IVAL(q, 0); - lmnttoken = SVAL(q, 4); - lm20token = SVAL(q, 6); - } - - /* Construct reply. */ - q = outbuf; - SSVAL(q, 0, QUERYFORPDC_R); - q += 2; - - fstrcpy(reply_name,my_name); - fstrcpy(q, reply_name); - q = skip_string(q, 1); /* PDC name */ - - /* PDC and domain name */ - if (!short_request) /* Make a full reply */ - { - q = ALIGN2(q, outbuf); - - q += dos_PutUniCode(q, my_name, sizeof(pstring), True); /* PDC name */ - q += dos_PutUniCode(q, lp_workgroup(),sizeof(pstring), True); /* Domain name*/ - SIVAL(q, 0, 1); /* our nt version */ - SSVAL(q, 4, 0xffff); /* our lmnttoken */ - SSVAL(q, 6, 0xffff); /* our lm20token */ - q += 8; - } - - /* RJS, 21-Feb-2000, we send a short reply if the request was short */ - - DEBUG(3,("process_logon_packet: GETDC request from %s at IP %s, \ -reporting %s domain %s 0x%x ntversion=%x lm_nt token=%x lm_20 token=%x\n", - machine,inet_ntoa(p->ip), reply_name, lp_workgroup(), - QUERYFORPDC_R, (uint32)ntversion, (uint32)lmnttoken, - (uint32)lm20token )); - - dump_data(4, outbuf, PTR_DIFF(q, outbuf)); - - send_mailslot(True, getdc, - outbuf,PTR_DIFF(q,outbuf), - global_myname(), 0x0, - dgram->source_name.name, - dgram->source_name.name_type, - p->ip, *iface_ip(p->ip), p->port); - return; - } - - case SAMLOGON: - { - char *q = buf + 2; - fstring asccomp; - - q += 2; - unicomp = q; - uniuser = skip_unibuf(unicomp, PTR_DIFF(buf+len, unicomp)); - getdc = skip_unibuf(uniuser,PTR_DIFF(buf+len, uniuser)); - q = skip_string(getdc,1); - q += 4; /* Account Control Bits - indicating username type */ - domainsidsize = IVAL(q, 0); - q += 4; - - DEBUG(3,("process_logon_packet: SAMLOGON sidsize %d, len = %d\n", domainsidsize, len)); - - if (domainsidsize < (len - PTR_DIFF(q, buf)) && (domainsidsize != 0)) { - q += domainsidsize; - q = ALIGN4(q, buf); - } - - DEBUG(3,("process_logon_packet: len = %d PTR_DIFF(q, buf) = %d\n", len, PTR_DIFF(q, buf) )); - - if (len - PTR_DIFF(q, buf) > 8) { - /* with NT5 clients we can sometimes - get additional data - a length specificed string - containing the domain name, then 16 bytes of - data (no idea what it is) */ - int dom_len = CVAL(q, 0); - q++; - if (dom_len < (len - PTR_DIFF(q, buf)) && (dom_len != 0)) { - q += dom_len + 1; - } - q += 16; - } - - ntversion = IVAL(q, 0); - lmnttoken = SVAL(q, 4); - lm20token = SVAL(q, 6); - q += 8; - - DEBUG(3,("process_logon_packet: SAMLOGON sidsize %d ntv %d\n", domainsidsize, ntversion)); - - /* - * we respond regadless of whether the machine is in our password - * database. If it isn't then we let smbd send an appropriate error. - * Let's ignore the SID. - */ - pull_ucs2_pstring(ascuser, uniuser); - pull_ucs2_fstring(asccomp, unicomp); - DEBUG(3,("process_logon_packet: SAMLOGON user %s\n", ascuser)); - - fstrcpy(reply_name, "\\\\"); /* Here it wants \\LOGONSERVER. */ - fstrcat(reply_name, my_name); - - DEBUG(3,("process_logon_packet: SAMLOGON request from %s(%s) for %s, returning logon svr %s domain %s code %x token=%x\n", - asccomp,inet_ntoa(p->ip), ascuser, reply_name, lp_workgroup(), - SAMLOGON_R ,lmnttoken)); - - /* Construct reply. */ - - q = outbuf; - /* we want the simple version unless we are an ADS PDC..which means */ - /* never, at least for now */ - if ((ntversion < 11) || (SEC_ADS != lp_security()) || (ROLE_DOMAIN_PDC != lp_server_role())) { - if (SVAL(uniuser, 0) == 0) { - SSVAL(q, 0, SAMLOGON_UNK_R); /* user unknown */ - } else { - SSVAL(q, 0, SAMLOGON_R); - } + } + + ntversion = IVAL(q, 0); + lmnttoken = SVAL(q, 4); + lm20token = SVAL(q, 6); + q += 8; + + DEBUG(3,("process_logon_packet: SAMLOGON sidsize %d ntv %d\n", domainsidsize, ntversion)); + + /* + * we respond regadless of whether the machine is in our password + * database. If it isn't then we let smbd send an appropriate error. + * Let's ignore the SID. + */ + pull_ucs2_pstring(ascuser, uniuser); + pull_ucs2_fstring(asccomp, unicomp); + DEBUG(3,("process_logon_packet: SAMLOGON user %s\n", ascuser)); + + fstrcpy(reply_name, "\\\\"); /* Here it wants \\LOGONSERVER. */ + fstrcat(reply_name, my_name); + + DEBUG(3,("process_logon_packet: SAMLOGON request from %s(%s) for %s, returning logon svr %s domain %s code %x token=%x\n", + asccomp,inet_ntoa(p->ip), ascuser, reply_name, lp_workgroup(), + SAMLOGON_R ,lmnttoken)); + + /* Construct reply. */ + + q = outbuf; + /* we want the simple version unless we are an ADS PDC..which means */ + /* never, at least for now */ + if ((ntversion < 11) || (SEC_ADS != lp_security()) || (ROLE_DOMAIN_PDC != lp_server_role())) { + if (SVAL(uniuser, 0) == 0) { + SSVAL(q, 0, SAMLOGON_UNK_R); /* user unknown */ + } else { + SSVAL(q, 0, SAMLOGON_R); + } - q += 2; + q += 2; - q += dos_PutUniCode(q, reply_name,sizeof(pstring), True); - q += dos_PutUniCode(q, ascuser, sizeof(pstring), True); - q += dos_PutUniCode(q, lp_workgroup(),sizeof(pstring), True); - } + q += dos_PutUniCode(q, reply_name,sizeof(pstring), True); + q += dos_PutUniCode(q, ascuser, sizeof(pstring), True); + q += dos_PutUniCode(q, lp_workgroup(),sizeof(pstring), True); + } #ifdef HAVE_ADS - else { - GUID domain_guid; - pstring domain; - pstring hostname; - char *component, *dc, *q1; - uint8 size; - char *q_orig = q; - int str_offset; - - get_mydomname(domain); - get_myname(hostname); + else { + GUID domain_guid; + pstring domain; + pstring hostname; + char *component, *dc, *q1; + uint8 size; + char *q_orig = q; + int str_offset; + + get_mydomname(domain); + get_myname(hostname); - if (SVAL(uniuser, 0) == 0) { - SIVAL(q, 0, SAMLOGON_AD_UNK_R); /* user unknown */ - } else { - SIVAL(q, 0, SAMLOGON_AD_R); - } - q += 4; + if (SVAL(uniuser, 0) == 0) { + SIVAL(q, 0, SAMLOGON_AD_UNK_R); /* user unknown */ + } else { + SIVAL(q, 0, SAMLOGON_AD_R); + } + q += 4; - SIVAL(q, 0, ADS_PDC|ADS_GC|ADS_LDAP|ADS_DS| - ADS_KDC|ADS_TIMESERV|ADS_CLOSEST|ADS_WRITABLE); - q += 4; + SIVAL(q, 0, ADS_PDC|ADS_GC|ADS_LDAP|ADS_DS| + ADS_KDC|ADS_TIMESERV|ADS_CLOSEST|ADS_WRITABLE); + q += 4; - /* Push Domain GUID */ - if (False == secrets_fetch_domain_guid(domain, &domain_guid)) { - DEBUG(2, ("Could not fetch DomainGUID for %s\n", domain)); - return; - } - memcpy(q, &domain_guid, sizeof(domain_guid)); - q += sizeof(domain_guid); - - /* Forest */ - str_offset = q - q_orig; - dc = domain; - q1 = q; - while ((component = strtok(dc, "."))) { - dc = NULL; - size = push_ascii(&q[1], component, -1, 0); - SCVAL(q, 0, size); - q += (size + 1); - } + /* Push Domain GUID */ + if (False == secrets_fetch_domain_guid(domain, &domain_guid)) { + DEBUG(2, ("Could not fetch DomainGUID for %s\n", domain)); + return; + } + memcpy(q, &domain_guid, sizeof(domain_guid)); + q += sizeof(domain_guid); + + /* Forest */ + str_offset = q - q_orig; + dc = domain; + q1 = q; + while ((component = strtok(dc, "."))) { + dc = NULL; + size = push_ascii(&q[1], component, -1, 0); + SCVAL(q, 0, size); + q += (size + 1); + } - /* Unk0 */ - SCVAL(q, 0, 0); q++; - - /* Domain */ - SCVAL(q, 0, 0xc0 | ((str_offset >> 8) & 0x3F)); - SCVAL(q, 1, str_offset & 0xFF); - q += 2; - - /* Hostname */ - size = push_ascii(&q[1], hostname, -1, 0); - SCVAL(q, 0, size); - q += (size + 1); - SCVAL(q, 0, 0xc0 | ((str_offset >> 8) & 0x3F)); - SCVAL(q, 1, str_offset & 0xFF); - q += 2; - - /* NETBIOS of domain */ - size = push_ascii(&q[1], lp_workgroup(), -1, STR_UPPER); - SCVAL(q, 0, size); - q += (size + 1); - - /* Unk1 */ - SCVAL(q, 0, 0); q++; - - /* NETBIOS of hostname */ - size = push_ascii(&q[1], my_name, -1, 0); - SCVAL(q, 0, size); - q += (size + 1); - - /* Unk2 */ - SCVAL(q, 0, 0); q++; - - /* User name */ - if (SVAL(uniuser, 0) != 0) { - size = push_ascii(&q[1], ascuser, -1, 0); - SCVAL(q, 0, size); - q += (size + 1); - } + /* Unk0 */ + SCVAL(q, 0, 0); + q++; - q_orig = q; - /* Site name */ - size = push_ascii(&q[1], "Default-First-Site-Name", -1, 0); - SCVAL(q, 0, size); - q += (size + 1); - - /* Site name (2) */ - str_offset = q - q_orig; - SCVAL(q, 0, 0xc0 | ((str_offset >> 8) & 0x3F)); - SCVAL(q, 1, str_offset & 0xFF); - q += 2; - - SCVAL(q, 0, PTR_DIFF(q,q1)); - SCVAL(q, 1, 0x10); /* unknown */ - - SIVAL(q, 0, 0x00000002); q += 4; /* unknown */ - SIVAL(q, 0, (iface_ip(p->ip))->s_addr); q += 4; - SIVAL(q, 0, 0x00000000); q += 4; /* unknown */ - SIVAL(q, 0, 0x00000000); q += 4; /* unknown */ - } + /* Domain */ + SCVAL(q, 0, 0xc0 | ((str_offset >> 8) & 0x3F)); + SCVAL(q, 1, str_offset & 0xFF); + q += 2; + + /* Hostname */ + size = push_ascii(&q[1], hostname, -1, 0); + SCVAL(q, 0, size); + q += (size + 1); + SCVAL(q, 0, 0xc0 | ((str_offset >> 8) & 0x3F)); + SCVAL(q, 1, str_offset & 0xFF); + q += 2; + + /* NETBIOS of domain */ + size = push_ascii(&q[1], lp_workgroup(), -1, STR_UPPER); + SCVAL(q, 0, size); + q += (size + 1); + + /* Unk1 */ + SCVAL(q, 0, 0); + q++; + + /* NETBIOS of hostname */ + size = push_ascii(&q[1], my_name, -1, 0); + SCVAL(q, 0, size); + q += (size + 1); + + /* Unk2 */ + SCVAL(q, 0, 0); + q++; + + /* User name */ + if (SVAL(uniuser, 0) != 0) { + size = push_ascii(&q[1], ascuser, -1, 0); + SCVAL(q, 0, size); + q += (size + 1); + } + + q_orig = q; + /* Site name */ + size = push_ascii(&q[1], "Default-First-Site-Name", -1, 0); + SCVAL(q, 0, size); + q += (size + 1); + + /* Site name (2) */ + str_offset = q - q_orig; + SCVAL(q, 0, 0xc0 | ((str_offset >> 8) & 0x3F)); + SCVAL(q, 1, str_offset & 0xFF); + q += 2; + + SCVAL(q, 0, PTR_DIFF(q,q1)); + SCVAL(q, 1, 0x10); /* unknown */ + + SIVAL(q, 0, 0x00000002); + q += 4; /* unknown */ + SIVAL(q, 0, (iface_ip(p->ip))->s_addr); + q += 4; + SIVAL(q, 0, 0x00000000); + q += 4; /* unknown */ + SIVAL(q, 0, 0x00000000); + q += 4; /* unknown */ + } #endif - /* tell the client what version we are */ - SIVAL(q, 0, ((ntversion < 11) || (SEC_ADS != lp_security())) ? 1 : 13); - /* our ntversion */ - SSVAL(q, 4, 0xffff); /* our lmnttoken */ - SSVAL(q, 6, 0xffff); /* our lm20token */ - q += 8; - - dump_data(4, outbuf, PTR_DIFF(q, outbuf)); - - send_mailslot(True, getdc, - outbuf,PTR_DIFF(q,outbuf), - global_myname(), 0x0, - dgram->source_name.name, - dgram->source_name.name_type, - p->ip, *iface_ip(p->ip), p->port); - break; - } - - /* Announce change to UAS or SAM. Send by the domain controller when a - replication event is required. */ - - case SAM_UAS_CHANGE: { - struct sam_database_info *db_info; - char *q = buf + 2; - int i, db_count; - uint32 low_serial; + /* tell the client what version we are */ + SIVAL(q, 0, ((ntversion < 11) || (SEC_ADS != lp_security())) ? 1 : 13); + /* our ntversion */ + SSVAL(q, 4, 0xffff); /* our lmnttoken */ + SSVAL(q, 6, 0xffff); /* our lm20token */ + q += 8; + + dump_data(4, outbuf, PTR_DIFF(q, outbuf)); + + pull_ascii_fstring(getdc_str, getdc); + pull_ascii_nstring(source_name, dgram->source_name.name); + + send_mailslot(True, getdc, + outbuf,PTR_DIFF(q,outbuf), + global_myname(), 0x0, + dgram->source_name.name, + dgram->source_name.name_type, + p->ip, *iface_ip(p->ip), p->port); + break; + } + + /* Announce change to UAS or SAM. Send by the domain controller when a + replication event is required. */ + + case SAM_UAS_CHANGE: + { + struct sam_database_info *db_info; + char *q = buf + 2; + int i, db_count; + uint32 low_serial; - /* Header */ + /* Header */ - low_serial = IVAL(q, 0); q += 4; /* Low serial number */ + low_serial = IVAL(q, 0); q += 4; /* Low serial number */ - q += 4; /* Date/time */ - q += 4; /* Pulse */ - q += 4; /* Random */ + q += 4; /* Date/time */ + q += 4; /* Pulse */ + q += 4; /* Random */ - /* Domain info */ + /* Domain info */ - q = skip_string(q, 1); /* PDC name */ - q = skip_string(q, 1); /* Domain name */ - q = skip_unibuf(q, PTR_DIFF(buf + len, q)); /* Unicode PDC name */ - q = skip_unibuf(q, PTR_DIFF(buf + len, q)); /* Unicode domain name */ + q = skip_string(q, 1); /* PDC name */ + q = skip_string(q, 1); /* Domain name */ + q = skip_unibuf(q, PTR_DIFF(buf + len, q)); /* Unicode PDC name */ + q = skip_unibuf(q, PTR_DIFF(buf + len, q)); /* Unicode domain name */ - /* Database info */ + /* Database info */ - db_count = SVAL(q, 0); q += 2; + db_count = SVAL(q, 0); q += 2; - db_info = (struct sam_database_info *) - malloc(sizeof(struct sam_database_info) * db_count); - - if (db_info == NULL) { - DEBUG(3, ("out of memory allocating info for %d databases\n", - db_count)); - return; - } + db_info = (struct sam_database_info *) + malloc(sizeof(struct sam_database_info) * db_count); + + if (db_info == NULL) { + DEBUG(3, ("out of memory allocating info for %d databases\n", db_count)); + return; + } - for (i = 0; i < db_count; i++) { - db_info[i].index = IVAL(q, 0); - db_info[i].serial_lo = IVAL(q, 4); - db_info[i].serial_hi = IVAL(q, 8); - db_info[i].date_lo = IVAL(q, 12); - db_info[i].date_hi = IVAL(q, 16); - q += 20; - } - - /* Domain SID */ - - q += IVAL(q, 0) + 4; /* 4 byte length plus data */ + for (i = 0; i < db_count; i++) { + db_info[i].index = IVAL(q, 0); + db_info[i].serial_lo = IVAL(q, 4); + db_info[i].serial_hi = IVAL(q, 8); + db_info[i].date_lo = IVAL(q, 12); + db_info[i].date_hi = IVAL(q, 16); + q += 20; + } + + /* Domain SID */ + + q += IVAL(q, 0) + 4; /* 4 byte length plus data */ - q += 2; /* Alignment? */ - - /* Misc other info */ + q += 2; /* Alignment? */ - q += 4; /* NT version (0x1) */ - q += 2; /* LMNT token (0xff) */ - q += 2; /* LM20 token (0xff) */ + /* Misc other info */ - SAFE_FREE(db_info); /* Not sure whether we need to do anything - useful with these */ + q += 4; /* NT version (0x1) */ + q += 2; /* LMNT token (0xff) */ + q += 2; /* LM20 token (0xff) */ - /* Send message to smbd */ + SAFE_FREE(db_info); /* Not sure whether we need to do anything useful with these */ - send_repl_message(low_serial); + /* Send message to smbd */ - break; - } + send_repl_message(low_serial); + break; + } - default: - { - DEBUG(3,("process_logon_packet: Unknown domain request %d\n",code)); - return; - } - } + default: + DEBUG(3,("process_logon_packet: Unknown domain request %d\n",code)); + return; + } } diff --git a/source3/nmbd/nmbd_responserecordsdb.c b/source3/nmbd/nmbd_responserecordsdb.c index 7e8c8025ae..30c0c12950 100644 --- a/source3/nmbd/nmbd_responserecordsdb.c +++ b/source3/nmbd/nmbd_responserecordsdb.c @@ -34,27 +34,26 @@ int num_response_packets = 0; static void add_response_record(struct subnet_record *subrec, struct response_record *rrec) { - struct response_record *rrec2; + struct response_record *rrec2; - num_response_packets++; /* count of total number of packets still around */ + num_response_packets++; /* count of total number of packets still around */ - DEBUG(4,("add_response_record: adding response record id:%hu to subnet %s. num_records:%d\n", - rrec->response_id, subrec->subnet_name, num_response_packets)); + DEBUG(4,("add_response_record: adding response record id:%hu to subnet %s. num_records:%d\n", + rrec->response_id, subrec->subnet_name, num_response_packets)); - if (!subrec->responselist) - { - subrec->responselist = rrec; - rrec->prev = NULL; - rrec->next = NULL; - return; - } + if (!subrec->responselist) { + subrec->responselist = rrec; + rrec->prev = NULL; + rrec->next = NULL; + return; + } - for (rrec2 = subrec->responselist; rrec2->next; rrec2 = rrec2->next) - ; + for (rrec2 = subrec->responselist; rrec2->next; rrec2 = rrec2->next) + ; - rrec2->next = rrec; - rrec->next = NULL; - rrec->prev = rrec2; + rrec2->next = rrec; + rrec->next = NULL; + rrec->prev = rrec2; } /*************************************************************************** @@ -64,32 +63,31 @@ static void add_response_record(struct subnet_record *subrec, void remove_response_record(struct subnet_record *subrec, struct response_record *rrec) { - if (rrec->prev) - rrec->prev->next = rrec->next; - if (rrec->next) - rrec->next->prev = rrec->prev; - - if (subrec->responselist == rrec) - subrec->responselist = rrec->next; - - if(rrec->userdata) - { - if(rrec->userdata->free_fn) { - (*rrec->userdata->free_fn)(rrec->userdata); - } else { - ZERO_STRUCTP(rrec->userdata); - SAFE_FREE(rrec->userdata); - } - } - - /* Ensure we can delete. */ - rrec->packet->locked = False; - free_packet(rrec->packet); - - ZERO_STRUCTP(rrec); - SAFE_FREE(rrec); - - num_response_packets--; /* count of total number of packets still around */ + if (rrec->prev) + rrec->prev->next = rrec->next; + if (rrec->next) + rrec->next->prev = rrec->prev; + + if (subrec->responselist == rrec) + subrec->responselist = rrec->next; + + if(rrec->userdata) { + if(rrec->userdata->free_fn) { + (*rrec->userdata->free_fn)(rrec->userdata); + } else { + ZERO_STRUCTP(rrec->userdata); + SAFE_FREE(rrec->userdata); + } + } + + /* Ensure we can delete. */ + rrec->packet->locked = False; + free_packet(rrec->packet); + + ZERO_STRUCTP(rrec); + SAFE_FREE(rrec); + + num_response_packets--; /* count of total number of packets still around */ } /**************************************************************************** @@ -104,77 +102,70 @@ struct response_record *make_response_record( struct subnet_record *subrec, fail_function fail_fn, struct userdata_struct *userdata) { - struct response_record *rrec; - struct nmb_packet *nmb = &p->packet.nmb; - - if (!(rrec = (struct response_record *)malloc(sizeof(*rrec)))) - { - DEBUG(0,("make_response_queue_record: malloc fail for response_record.\n")); - return NULL; - } - - memset((char *)rrec, '\0', sizeof(*rrec)); - - rrec->response_id = nmb->header.name_trn_id; - - rrec->resp_fn = resp_fn; - rrec->timeout_fn = timeout_fn; - rrec->success_fn = success_fn; - rrec->fail_fn = fail_fn; - - rrec->packet = p; - - if(userdata) - { - /* Intelligent userdata. */ - if(userdata->copy_fn) - { - if((rrec->userdata = (*userdata->copy_fn)(userdata)) == NULL) - { - DEBUG(0,("make_response_queue_record: copy fail for userdata.\n")); - ZERO_STRUCTP(rrec); - SAFE_FREE(rrec); - return NULL; - } - } - else - { - /* Primitive userdata, do a memcpy. */ - if((rrec->userdata = (struct userdata_struct *) - malloc(sizeof(struct userdata_struct)+userdata->userdata_len)) == NULL) - { - DEBUG(0,("make_response_queue_record: malloc fail for userdata.\n")); - ZERO_STRUCTP(rrec); - SAFE_FREE(rrec); - return NULL; - } - rrec->userdata->copy_fn = userdata->copy_fn; - rrec->userdata->free_fn = userdata->free_fn; - rrec->userdata->userdata_len = userdata->userdata_len; - memcpy(rrec->userdata->data, userdata->data, userdata->userdata_len); - } - } - else - rrec->userdata = NULL; - - rrec->num_msgs = 0; - - if(!nmb->header.nm_flags.bcast) - rrec->repeat_interval = 5; /* 5 seconds for unicast packets. */ - else - rrec->repeat_interval = 1; /* XXXX should be in ms */ - rrec->repeat_count = 3; /* 3 retries */ - rrec->repeat_time = time(NULL) + rrec->repeat_interval; /* initial retry time */ - - /* This packet is not being processed. */ - rrec->in_expiration_processing = False; - - /* Lock the packet so we won't lose it while it's on the list. */ - p->locked = True; - - add_response_record(subrec, rrec); - - return rrec; + struct response_record *rrec; + struct nmb_packet *nmb = &p->packet.nmb; + + if (!(rrec = (struct response_record *)malloc(sizeof(*rrec)))) { + DEBUG(0,("make_response_queue_record: malloc fail for response_record.\n")); + return NULL; + } + + memset((char *)rrec, '\0', sizeof(*rrec)); + + rrec->response_id = nmb->header.name_trn_id; + + rrec->resp_fn = resp_fn; + rrec->timeout_fn = timeout_fn; + rrec->success_fn = success_fn; + rrec->fail_fn = fail_fn; + + rrec->packet = p; + + if(userdata) { + /* Intelligent userdata. */ + if(userdata->copy_fn) { + if((rrec->userdata = (*userdata->copy_fn)(userdata)) == NULL) { + DEBUG(0,("make_response_queue_record: copy fail for userdata.\n")); + ZERO_STRUCTP(rrec); + SAFE_FREE(rrec); + return NULL; + } + } else { + /* Primitive userdata, do a memcpy. */ + if((rrec->userdata = (struct userdata_struct *) + malloc(sizeof(struct userdata_struct)+userdata->userdata_len)) == NULL) { + DEBUG(0,("make_response_queue_record: malloc fail for userdata.\n")); + ZERO_STRUCTP(rrec); + SAFE_FREE(rrec); + return NULL; + } + rrec->userdata->copy_fn = userdata->copy_fn; + rrec->userdata->free_fn = userdata->free_fn; + rrec->userdata->userdata_len = userdata->userdata_len; + memcpy(rrec->userdata->data, userdata->data, userdata->userdata_len); + } + } else { + rrec->userdata = NULL; + } + + rrec->num_msgs = 0; + + if(!nmb->header.nm_flags.bcast) + rrec->repeat_interval = 5; /* 5 seconds for unicast packets. */ + else + rrec->repeat_interval = 1; /* XXXX should be in ms */ + rrec->repeat_count = 3; /* 3 retries */ + rrec->repeat_time = time(NULL) + rrec->repeat_interval; /* initial retry time */ + + /* This packet is not being processed. */ + rrec->in_expiration_processing = False; + + /* Lock the packet so we won't lose it while it's on the list. */ + p->locked = True; + + add_response_record(subrec, rrec); + + return rrec; } /**************************************************************************** @@ -184,18 +175,16 @@ struct response_record *make_response_record( struct subnet_record *subrec, static struct response_record *find_response_record_on_subnet( struct subnet_record *subrec, uint16 id) { - struct response_record *rrec = NULL; - - for (rrec = subrec->responselist; rrec; rrec = rrec->next) - { - if (rrec->response_id == id) - { - DEBUG(4, ("find_response_record: found response record id = %hu on subnet %s\n", - id, subrec->subnet_name)); - break; - } - } - return rrec; + struct response_record *rrec = NULL; + + for (rrec = subrec->responselist; rrec; rrec = rrec->next) { + if (rrec->response_id == id) { + DEBUG(4, ("find_response_record: found response record id = %hu on subnet %s\n", + id, subrec->subnet_name)); + break; + } + } + return rrec; } /**************************************************************************** @@ -205,37 +194,34 @@ static struct response_record *find_response_record_on_subnet( struct response_record *find_response_record(struct subnet_record **ppsubrec, uint16 id) { - struct response_record *rrec = NULL; - - for ((*ppsubrec) = FIRST_SUBNET; (*ppsubrec); - (*ppsubrec) = NEXT_SUBNET_INCLUDING_UNICAST(*ppsubrec)) - { - if((rrec = find_response_record_on_subnet(*ppsubrec, id)) != NULL) - return rrec; - } - - /* There should never be response records on the remote_broadcast subnet. - Sanity check to ensure this is so. */ - if(remote_broadcast_subnet->responselist != NULL) - { - DEBUG(0,("find_response_record: response record found on subnet %s. This should \ + struct response_record *rrec = NULL; + + for ((*ppsubrec) = FIRST_SUBNET; (*ppsubrec); + (*ppsubrec) = NEXT_SUBNET_INCLUDING_UNICAST(*ppsubrec)) { + if((rrec = find_response_record_on_subnet(*ppsubrec, id)) != NULL) + return rrec; + } + + /* There should never be response records on the remote_broadcast subnet. + Sanity check to ensure this is so. */ + if(remote_broadcast_subnet->responselist != NULL) { + DEBUG(0,("find_response_record: response record found on subnet %s. This should \ never happen !\n", remote_broadcast_subnet->subnet_name)); - } + } - /* Now check the WINS server subnet if it exists. */ - if(wins_server_subnet != NULL) - { - *ppsubrec = wins_server_subnet; - if((rrec = find_response_record_on_subnet(*ppsubrec, id))!= NULL) - return rrec; - } + /* Now check the WINS server subnet if it exists. */ + if(wins_server_subnet != NULL) { + *ppsubrec = wins_server_subnet; + if((rrec = find_response_record_on_subnet(*ppsubrec, id))!= NULL) + return rrec; + } - DEBUG(0,("find_response_record: response packet id %hu received with no \ + DEBUG(0,("find_response_record: response packet id %hu received with no \ matching record.\n", id)); - *ppsubrec = NULL; + *ppsubrec = NULL; - return NULL; + return NULL; } /**************************************************************************** @@ -244,21 +230,19 @@ matching record.\n", id)); BOOL is_refresh_already_queued(struct subnet_record *subrec, struct name_record *namerec) { - struct response_record *rrec = NULL; + struct response_record *rrec = NULL; - for (rrec = subrec->responselist; rrec; rrec = rrec->next) - { - struct packet_struct *p = rrec->packet; - struct nmb_packet *nmb = &p->packet.nmb; - - if((nmb->header.opcode == NMB_NAME_REFRESH_OPCODE_8) || - (nmb->header.opcode == NMB_NAME_REFRESH_OPCODE_9)) - { - /* Yes it's a queued refresh - check if the name is correct. */ - if(nmb_name_equal(&nmb->question.question_name, &namerec->name)) - return True; - } - } - - return False; -} + for (rrec = subrec->responselist; rrec; rrec = rrec->next) { + struct packet_struct *p = rrec->packet; + struct nmb_packet *nmb = &p->packet.nmb; + + if((nmb->header.opcode == NMB_NAME_REFRESH_OPCODE_8) || + (nmb->header.opcode == NMB_NAME_REFRESH_OPCODE_9)) { + /* Yes it's a queued refresh - check if the name is correct. */ + if(nmb_name_equal(&nmb->question.question_name, &namerec->name)) + return True; + } + } + + return False; +} diff --git a/source3/nmbd/nmbd_sendannounce.c b/source3/nmbd/nmbd_sendannounce.c index 353717ee62..87908e352c 100644 --- a/source3/nmbd/nmbd_sendannounce.c +++ b/source3/nmbd/nmbd_sendannounce.c @@ -35,21 +35,21 @@ extern BOOL found_lm_clients; void send_browser_reset(int reset_type, const char *to_name, int to_type, struct in_addr to_ip) { - pstring outbuf; - char *p; + pstring outbuf; + char *p; - DEBUG(3,("send_browser_reset: sending reset request type %d to %s<%02x> IP %s.\n", - reset_type, to_name, to_type, inet_ntoa(to_ip) )); + DEBUG(3,("send_browser_reset: sending reset request type %d to %s<%02x> IP %s.\n", + reset_type, to_name, to_type, inet_ntoa(to_ip) )); - memset(outbuf,'\0',sizeof(outbuf)); - p = outbuf; - SCVAL(p,0,ANN_ResetBrowserState); - p++; - SCVAL(p,0,reset_type); - p++; + memset(outbuf,'\0',sizeof(outbuf)); + p = outbuf; + SCVAL(p,0,ANN_ResetBrowserState); + p++; + SCVAL(p,0,reset_type); + p++; - send_mailslot(True, BROWSE_MAILSLOT, outbuf,PTR_DIFF(p,outbuf), - global_myname(), 0x0, to_name, to_type, to_ip, + send_mailslot(True, BROWSE_MAILSLOT, outbuf,PTR_DIFF(p,outbuf), + global_myname(), 0x0, to_name, to_type, to_ip, FIRST_SUBNET->myip, DGRAM_PORT); } @@ -60,25 +60,25 @@ void send_browser_reset(int reset_type, const char *to_name, int to_type, struct void broadcast_announce_request(struct subnet_record *subrec, struct work_record *work) { - pstring outbuf; - char *p; + pstring outbuf; + char *p; - work->needannounce = True; + work->needannounce = True; - DEBUG(3,("broadcast_announce_request: sending announce request for workgroup %s \ + DEBUG(3,("broadcast_announce_request: sending announce request for workgroup %s \ to subnet %s\n", work->work_group, subrec->subnet_name)); - memset(outbuf,'\0',sizeof(outbuf)); - p = outbuf; - SCVAL(p,0,ANN_AnnouncementRequest); - p++; + memset(outbuf,'\0',sizeof(outbuf)); + p = outbuf; + SCVAL(p,0,ANN_AnnouncementRequest); + p++; - SCVAL(p,0,work->token); /* (local) Unique workgroup token id. */ - p++; - p += push_string(NULL, p+1, global_myname(), 15, STR_ASCII|STR_UPPER|STR_TERMINATE); + SCVAL(p,0,work->token); /* (local) Unique workgroup token id. */ + p++; + p += push_string(NULL, p+1, global_myname(), 15, STR_ASCII|STR_UPPER|STR_TERMINATE); - send_mailslot(False, BROWSE_MAILSLOT, outbuf,PTR_DIFF(p,outbuf), - global_myname(), 0x0, work->work_group,0x1e, subrec->bcast_ip, + send_mailslot(False, BROWSE_MAILSLOT, outbuf,PTR_DIFF(p,outbuf), + global_myname(), 0x0, work->work_group,0x1e, subrec->bcast_ip, subrec->myip, DGRAM_PORT); } @@ -91,33 +91,33 @@ static void send_announcement(struct subnet_record *subrec, int announce_type, time_t announce_interval, const char *server_name, int server_type, const char *server_comment) { - pstring outbuf; - char *p; + pstring outbuf; + char *p; - memset(outbuf,'\0',sizeof(outbuf)); - p = outbuf+1; + memset(outbuf,'\0',sizeof(outbuf)); + p = outbuf+1; - SCVAL(outbuf,0,announce_type); + SCVAL(outbuf,0,announce_type); - /* Announcement parameters. */ - SCVAL(p,0,updatecount); - SIVAL(p,1,announce_interval*1000); /* Milliseconds - despite the spec. */ + /* Announcement parameters. */ + SCVAL(p,0,updatecount); + SIVAL(p,1,announce_interval*1000); /* Milliseconds - despite the spec. */ - push_string(NULL, p+5, server_name, 15, STR_ASCII|STR_UPPER|STR_TERMINATE); + push_string(NULL, p+5, server_name, 15, STR_ASCII|STR_UPPER|STR_TERMINATE); - SCVAL(p,21,lp_major_announce_version()); /* Major version. */ - SCVAL(p,22,lp_minor_announce_version()); /* Minor version. */ + SCVAL(p,21,lp_major_announce_version()); /* Major version. */ + SCVAL(p,22,lp_minor_announce_version()); /* Minor version. */ - SIVAL(p,23,server_type & ~SV_TYPE_LOCAL_LIST_ONLY); - /* Browse version: got from NT/AS 4.00 - Value defined in smb.h (JHT). */ - SSVAL(p,27,BROWSER_ELECTION_VERSION); - SSVAL(p,29,BROWSER_CONSTANT); /* Browse signature. */ + SIVAL(p,23,server_type & ~SV_TYPE_LOCAL_LIST_ONLY); + /* Browse version: got from NT/AS 4.00 - Value defined in smb.h (JHT). */ + SSVAL(p,27,BROWSER_ELECTION_VERSION); + SSVAL(p,29,BROWSER_CONSTANT); /* Browse signature. */ - p += 31 + push_string(NULL, p+31, server_comment, -1, STR_ASCII|STR_TERMINATE); + p += 31 + push_string(NULL, p+31, server_comment, -1, STR_ASCII|STR_TERMINATE); - send_mailslot(False,BROWSE_MAILSLOT, outbuf, PTR_DIFF(p,outbuf), - from_name, 0x0, to_name, to_type, to_ip, subrec->myip, - DGRAM_PORT); + send_mailslot(False,BROWSE_MAILSLOT, outbuf, PTR_DIFF(p,outbuf), + from_name, 0x0, to_name, to_type, to_ip, subrec->myip, + DGRAM_PORT); } /**************************************************************************** @@ -129,28 +129,23 @@ static void send_lm_announcement(struct subnet_record *subrec, int announce_type time_t announce_interval, char *server_name, int server_type, char *server_comment) { - pstring outbuf; - char *p=outbuf; - - memset(outbuf,'\0',sizeof(outbuf)); - - SSVAL(p,0,announce_type); - SIVAL(p,2,server_type & ~SV_TYPE_LOCAL_LIST_ONLY); - SCVAL(p,6,lp_major_announce_version()); /* Major version. */ - SCVAL(p,7,lp_minor_announce_version()); /* Minor version. */ - SSVAL(p,8,announce_interval); /* In seconds - according to spec. */ - - p += 10; - /*StrnCpy(p,server_name,15); - strupper_m(p); - p = skip_string(p,1); - pstrcpy(p,server_comment); - p = skip_string(p,1);*/ - p += push_string(NULL, p, server_name, 15, STR_ASCII|STR_UPPER|STR_TERMINATE); - p += push_string(NULL, p, server_comment, sizeof(pstring)-15, STR_ASCII|STR_UPPER|STR_TERMINATE); - - send_mailslot(False,LANMAN_MAILSLOT, outbuf, PTR_DIFF(p,outbuf), - from_name, 0x0, to_name, to_type, to_ip, subrec->myip, + pstring outbuf; + char *p=outbuf; + + memset(outbuf,'\0',sizeof(outbuf)); + + SSVAL(p,0,announce_type); + SIVAL(p,2,server_type & ~SV_TYPE_LOCAL_LIST_ONLY); + SCVAL(p,6,lp_major_announce_version()); /* Major version. */ + SCVAL(p,7,lp_minor_announce_version()); /* Minor version. */ + SSVAL(p,8,announce_interval); /* In seconds - according to spec. */ + + p += 10; + p += push_string(NULL, p, server_name, 15, STR_ASCII|STR_UPPER|STR_TERMINATE); + p += push_string(NULL, p, server_comment, sizeof(pstring)-15, STR_ASCII|STR_UPPER|STR_TERMINATE); + + send_mailslot(False,LANMAN_MAILSLOT, outbuf, PTR_DIFF(p,outbuf), + from_name, 0x0, to_name, to_type, to_ip, subrec->myip, DGRAM_PORT); } @@ -161,20 +156,20 @@ static void send_lm_announcement(struct subnet_record *subrec, int announce_type static void send_local_master_announcement(struct subnet_record *subrec, struct work_record *work, struct server_record *servrec) { - /* Ensure we don't have the prohibited bit set. */ - uint32 type = servrec->serv.type & ~SV_TYPE_LOCAL_LIST_ONLY; - - DEBUG(3,("send_local_master_announcement: type %x for name %s on subnet %s for workgroup %s\n", - type, global_myname(), subrec->subnet_name, work->work_group)); - - send_announcement(subrec, ANN_LocalMasterAnnouncement, - global_myname(), /* From nbt name. */ - work->work_group, 0x1e, /* To nbt name. */ - subrec->bcast_ip, /* To ip. */ - work->announce_interval, /* Time until next announce. */ - global_myname(), /* Name to announce. */ - type, /* Type field. */ - servrec->serv.comment); + /* Ensure we don't have the prohibited bit set. */ + uint32 type = servrec->serv.type & ~SV_TYPE_LOCAL_LIST_ONLY; + + DEBUG(3,("send_local_master_announcement: type %x for name %s on subnet %s for workgroup %s\n", + type, global_myname(), subrec->subnet_name, work->work_group)); + + send_announcement(subrec, ANN_LocalMasterAnnouncement, + global_myname(), /* From nbt name. */ + work->work_group, 0x1e, /* To nbt name. */ + subrec->bcast_ip, /* To ip. */ + work->announce_interval, /* Time until next announce. */ + global_myname(), /* Name to announce. */ + type, /* Type field. */ + servrec->serv.comment); } /**************************************************************************** @@ -183,17 +178,17 @@ static void send_local_master_announcement(struct subnet_record *subrec, struct static void send_workgroup_announcement(struct subnet_record *subrec, struct work_record *work) { - DEBUG(3,("send_workgroup_announcement: on subnet %s for workgroup %s\n", - subrec->subnet_name, work->work_group)); - - send_announcement(subrec, ANN_DomainAnnouncement, - global_myname(), /* From nbt name. */ - MSBROWSE, 0x1, /* To nbt name. */ - subrec->bcast_ip, /* To ip. */ - work->announce_interval, /* Time until next announce. */ - work->work_group, /* Name to announce. */ - SV_TYPE_DOMAIN_ENUM|SV_TYPE_NT, /* workgroup announce flags. */ - global_myname()); /* From name as comment. */ + DEBUG(3,("send_workgroup_announcement: on subnet %s for workgroup %s\n", + subrec->subnet_name, work->work_group)); + + send_announcement(subrec, ANN_DomainAnnouncement, + global_myname(), /* From nbt name. */ + MSBROWSE, 0x1, /* To nbt name. */ + subrec->bcast_ip, /* To ip. */ + work->announce_interval, /* Time until next announce. */ + work->work_group, /* Name to announce. */ + SV_TYPE_DOMAIN_ENUM|SV_TYPE_NT, /* workgroup announce flags. */ + global_myname()); /* From name as comment. */ } /**************************************************************************** @@ -203,20 +198,20 @@ static void send_workgroup_announcement(struct subnet_record *subrec, struct wor static void send_host_announcement(struct subnet_record *subrec, struct work_record *work, struct server_record *servrec) { - /* Ensure we don't have the prohibited bits set. */ - uint32 type = servrec->serv.type & ~SV_TYPE_LOCAL_LIST_ONLY; - - DEBUG(3,("send_host_announcement: type %x for host %s on subnet %s for workgroup %s\n", - type, servrec->serv.name, subrec->subnet_name, work->work_group)); - - send_announcement(subrec, ANN_HostAnnouncement, - servrec->serv.name, /* From nbt name. */ - work->work_group, 0x1d, /* To nbt name. */ - subrec->bcast_ip, /* To ip. */ - work->announce_interval, /* Time until next announce. */ - servrec->serv.name, /* Name to announce. */ - type, /* Type field. */ - servrec->serv.comment); + /* Ensure we don't have the prohibited bits set. */ + uint32 type = servrec->serv.type & ~SV_TYPE_LOCAL_LIST_ONLY; + + DEBUG(3,("send_host_announcement: type %x for host %s on subnet %s for workgroup %s\n", + type, servrec->serv.name, subrec->subnet_name, work->work_group)); + + send_announcement(subrec, ANN_HostAnnouncement, + servrec->serv.name, /* From nbt name. */ + work->work_group, 0x1d, /* To nbt name. */ + subrec->bcast_ip, /* To ip. */ + work->announce_interval, /* Time until next announce. */ + servrec->serv.name, /* Name to announce. */ + type, /* Type field. */ + servrec->serv.comment); } /**************************************************************************** @@ -226,20 +221,20 @@ static void send_host_announcement(struct subnet_record *subrec, struct work_rec static void send_lm_host_announcement(struct subnet_record *subrec, struct work_record *work, struct server_record *servrec, int lm_interval) { - /* Ensure we don't have the prohibited bits set. */ - uint32 type = servrec->serv.type & ~SV_TYPE_LOCAL_LIST_ONLY; - - DEBUG(3,("send_lm_host_announcement: type %x for host %s on subnet %s for workgroup %s, ttl: %d\n", - type, servrec->serv.name, subrec->subnet_name, work->work_group, lm_interval)); - - send_lm_announcement(subrec, ANN_HostAnnouncement, - servrec->serv.name, /* From nbt name. */ - work->work_group, 0x00, /* To nbt name. */ - subrec->bcast_ip, /* To ip. */ - lm_interval, /* Time until next announce. */ - servrec->serv.name, /* Name to announce. */ - type, /* Type field. */ - servrec->serv.comment); + /* Ensure we don't have the prohibited bits set. */ + uint32 type = servrec->serv.type & ~SV_TYPE_LOCAL_LIST_ONLY; + + DEBUG(3,("send_lm_host_announcement: type %x for host %s on subnet %s for workgroup %s, ttl: %d\n", + type, servrec->serv.name, subrec->subnet_name, work->work_group, lm_interval)); + + send_lm_announcement(subrec, ANN_HostAnnouncement, + servrec->serv.name, /* From nbt name. */ + work->work_group, 0x00, /* To nbt name. */ + subrec->bcast_ip, /* To ip. */ + lm_interval, /* Time until next announce. */ + servrec->serv.name, /* Name to announce (fstring not netbios name struct). */ + type, /* Type field. */ + servrec->serv.comment); } /**************************************************************************** @@ -249,18 +244,15 @@ static void send_lm_host_announcement(struct subnet_record *subrec, struct work_ static void announce_server(struct subnet_record *subrec, struct work_record *work, struct server_record *servrec) { - /* Only do domain announcements if we are a master and it's - our primary name we're being asked to announce. */ - - if (AM_LOCAL_MASTER_BROWSER(work) && strequal(global_myname(),servrec->serv.name)) - { - send_local_master_announcement(subrec, work, servrec); - send_workgroup_announcement(subrec, work); - } - else - { - send_host_announcement(subrec, work, servrec); - } + /* Only do domain announcements if we are a master and it's + our primary name we're being asked to announce. */ + + if (AM_LOCAL_MASTER_BROWSER(work) && strequal(global_myname(),servrec->serv.name)) { + send_local_master_announcement(subrec, work, servrec); + send_workgroup_announcement(subrec, work); + } else { + send_host_announcement(subrec, work, servrec); + } } /**************************************************************************** @@ -270,43 +262,39 @@ static void announce_server(struct subnet_record *subrec, struct work_record *wo void announce_my_server_names(time_t t) { - struct subnet_record *subrec; - - for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) - { - struct work_record *work = find_workgroup_on_subnet(subrec, lp_workgroup()); - - if(work) - { - struct server_record *servrec; - - if (work->needannounce) - { - /* Drop back to a max 3 minute announce. This is to prevent a - single lost packet from breaking things for too long. */ - - work->announce_interval = MIN(work->announce_interval, - CHECK_TIME_MIN_HOST_ANNCE*60); - work->lastannounce_time = t - (work->announce_interval+1); - work->needannounce = False; - } - - /* Announce every minute at first then progress to every 12 mins */ - if ((t - work->lastannounce_time) < work->announce_interval) - continue; - - if (work->announce_interval < (CHECK_TIME_MAX_HOST_ANNCE * 60)) - work->announce_interval += 60; - - work->lastannounce_time = t; - - for (servrec = work->serverlist; servrec; servrec = servrec->next) - { - if (is_myname(servrec->serv.name)) - announce_server(subrec, work, servrec); - } - } /* if work */ - } /* for subrec */ + struct subnet_record *subrec; + + for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) { + struct work_record *work = find_workgroup_on_subnet(subrec, lp_workgroup()); + + if(work) { + struct server_record *servrec; + + if (work->needannounce) { + /* Drop back to a max 3 minute announce. This is to prevent a + single lost packet from breaking things for too long. */ + + work->announce_interval = MIN(work->announce_interval, + CHECK_TIME_MIN_HOST_ANNCE*60); + work->lastannounce_time = t - (work->announce_interval+1); + work->needannounce = False; + } + + /* Announce every minute at first then progress to every 12 mins */ + if ((t - work->lastannounce_time) < work->announce_interval) + continue; + + if (work->announce_interval < (CHECK_TIME_MAX_HOST_ANNCE * 60)) + work->announce_interval += 60; + + work->lastannounce_time = t; + + for (servrec = work->serverlist; servrec; servrec = servrec->next) { + if (is_myname(servrec->serv.name)) + announce_server(subrec, work, servrec); + } + } /* if work */ + } /* for subrec */ } /**************************************************************************** @@ -316,47 +304,42 @@ void announce_my_server_names(time_t t) void announce_my_lm_server_names(time_t t) { - struct subnet_record *subrec; - static time_t last_lm_announce_time=0; - int announce_interval = lp_lm_interval(); - int lm_announce = lp_lm_announce(); - - if ((announce_interval <= 0) || (lm_announce <= 0)) - { - /* user absolutely does not want LM announcements to be sent. */ - return; - } - - if ((lm_announce >= 2) && (!found_lm_clients)) - { - /* has been set to 2 (Auto) but no LM clients detected (yet). */ - return; - } - - /* Otherwise: must have been set to 1 (Yes), or LM clients *have* - been detected. */ - - for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) - { - struct work_record *work = find_workgroup_on_subnet(subrec, lp_workgroup()); - - if(work) - { - struct server_record *servrec; - - if (last_lm_announce_time && ((t - last_lm_announce_time) < announce_interval )) - continue; - - last_lm_announce_time = t; - - for (servrec = work->serverlist; servrec; servrec = servrec->next) - { - if (is_myname(servrec->serv.name)) - /* skipping equivalent of announce_server() */ - send_lm_host_announcement(subrec, work, servrec, announce_interval); - } - } /* if work */ - } /* for subrec */ + struct subnet_record *subrec; + static time_t last_lm_announce_time=0; + int announce_interval = lp_lm_interval(); + int lm_announce = lp_lm_announce(); + + if ((announce_interval <= 0) || (lm_announce <= 0)) { + /* user absolutely does not want LM announcements to be sent. */ + return; + } + + if ((lm_announce >= 2) && (!found_lm_clients)) { + /* has been set to 2 (Auto) but no LM clients detected (yet). */ + return; + } + + /* Otherwise: must have been set to 1 (Yes), or LM clients *have* + been detected. */ + + for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) { + struct work_record *work = find_workgroup_on_subnet(subrec, lp_workgroup()); + + if(work) { + struct server_record *servrec; + + if (last_lm_announce_time && ((t - last_lm_announce_time) < announce_interval )) + continue; + + last_lm_announce_time = t; + + for (servrec = work->serverlist; servrec; servrec = servrec->next) { + if (is_myname(servrec->serv.name)) + /* skipping equivalent of announce_server() */ + send_lm_host_announcement(subrec, work, servrec, announce_interval); + } + } /* if work */ + } /* for subrec */ } /* Announce timer. Moved into global static so it can be reset @@ -370,7 +353,7 @@ static time_t announce_timer_last=0; void reset_announce_timer(void) { - announce_timer_last = time(NULL) - (CHECK_TIME_MST_ANNOUNCE * 60); + announce_timer_last = time(NULL) - (CHECK_TIME_MST_ANNOUNCE * 60); } /**************************************************************************** @@ -379,45 +362,40 @@ void reset_announce_timer(void) void announce_myself_to_domain_master_browser(time_t t) { - struct subnet_record *subrec; - struct work_record *work; - - if(!we_are_a_wins_client()) - { - DEBUG(10,("announce_myself_to_domain_master_browser: no unicast subnet, ignoring.\n")); - return; - } - - if (!announce_timer_last) - announce_timer_last = t; - - if ((t-announce_timer_last) < (CHECK_TIME_MST_ANNOUNCE * 60)) - { - DEBUG(10,("announce_myself_to_domain_master_browser: t (%d) - last(%d) < %d\n", - (int)t, (int)announce_timer_last, - CHECK_TIME_MST_ANNOUNCE * 60 )); - return; - } - - announce_timer_last = t; - - /* Look over all our broadcast subnets to see if any of them - has the state set as local master browser. */ - - for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) - { - for (work = subrec->workgrouplist; work; work = work->next) - { - if (AM_LOCAL_MASTER_BROWSER(work)) - { - DEBUG(4,( "announce_myself_to_domain_master_browser: I am a local master browser for \ + struct subnet_record *subrec; + struct work_record *work; + + if(!we_are_a_wins_client()) { + DEBUG(10,("announce_myself_to_domain_master_browser: no unicast subnet, ignoring.\n")); + return; + } + + if (!announce_timer_last) + announce_timer_last = t; + + if ((t-announce_timer_last) < (CHECK_TIME_MST_ANNOUNCE * 60)) { + DEBUG(10,("announce_myself_to_domain_master_browser: t (%d) - last(%d) < %d\n", + (int)t, (int)announce_timer_last, + CHECK_TIME_MST_ANNOUNCE * 60 )); + return; + } + + announce_timer_last = t; + + /* Look over all our broadcast subnets to see if any of them + has the state set as local master browser. */ + + for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) { + for (work = subrec->workgrouplist; work; work = work->next) { + if (AM_LOCAL_MASTER_BROWSER(work)) { + DEBUG(4,( "announce_myself_to_domain_master_browser: I am a local master browser for \ workgroup %s on subnet %s\n", work->work_group, subrec->subnet_name)); - /* Look in nmbd_browsersync.c for the rest of this code. */ - announce_and_sync_with_domain_master_browser(subrec, work); - } - } - } + /* Look in nmbd_browsersync.c for the rest of this code. */ + announce_and_sync_with_domain_master_browser(subrec, work); + } + } + } } /**************************************************************************** @@ -427,49 +405,43 @@ This must *only* be called on shutdown. void announce_my_servers_removed(void) { - int announce_interval = lp_lm_interval(); - int lm_announce = lp_lm_announce(); - struct subnet_record *subrec; - - for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) - { - struct work_record *work; - for (work = subrec->workgrouplist; work; work = work->next) - { - struct server_record *servrec; - - work->announce_interval = 0; - for (servrec = work->serverlist; servrec; servrec = servrec->next) - { - if (!is_myname(servrec->serv.name)) - continue; - servrec->serv.type = 0; - if(AM_LOCAL_MASTER_BROWSER(work)) - send_local_master_announcement(subrec, work, servrec); - send_host_announcement(subrec, work, servrec); - - - if ((announce_interval <= 0) || (lm_announce <= 0)) - { - /* user absolutely does not want LM announcements to be sent. */ - continue; - } - - if ((lm_announce >= 2) && (!found_lm_clients)) - { - /* has been set to 2 (Auto) but no LM clients detected (yet). */ - continue; - } - - /* - * lm announce was set or we have seen lm announcements, so do - * a lm announcement of host removed. - */ - - send_lm_host_announcement(subrec, work, servrec, 0); - } - } - } + int announce_interval = lp_lm_interval(); + int lm_announce = lp_lm_announce(); + struct subnet_record *subrec; + + for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) { + struct work_record *work; + for (work = subrec->workgrouplist; work; work = work->next) { + struct server_record *servrec; + + work->announce_interval = 0; + for (servrec = work->serverlist; servrec; servrec = servrec->next) { + if (!is_myname(servrec->serv.name)) + continue; + servrec->serv.type = 0; + if(AM_LOCAL_MASTER_BROWSER(work)) + send_local_master_announcement(subrec, work, servrec); + send_host_announcement(subrec, work, servrec); + + if ((announce_interval <= 0) || (lm_announce <= 0)) { + /* user absolutely does not want LM announcements to be sent. */ + continue; + } + + if ((lm_announce >= 2) && (!found_lm_clients)) { + /* has been set to 2 (Auto) but no LM clients detected (yet). */ + continue; + } + + /* + * lm announce was set or we have seen lm announcements, so do + * a lm announcement of host removed. + */ + + send_lm_host_announcement(subrec, work, servrec, 0); + } + } + } } /**************************************************************************** @@ -480,132 +452,127 @@ void announce_my_servers_removed(void) void announce_remote(time_t t) { - char *s; - const char *ptr; - static time_t last_time = 0; - pstring s2; - struct in_addr addr; - char *comment; - int stype = lp_default_server_announce(); - - if (last_time && (t < (last_time + REMOTE_ANNOUNCE_INTERVAL))) - return; - - last_time = t; - - s = lp_remote_announce(); - if (!*s) - return; - - comment = string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH); - - for (ptr=s; next_token(&ptr,s2,NULL,sizeof(s2)); ) - { - /* The entries are of the form a.b.c.d/WORKGROUP with - WORKGROUP being optional */ - const char *wgroup; - char *pwgroup; - int i; - - pwgroup = strchr_m(s2,'/'); - if (pwgroup) - *pwgroup++ = 0; - if (!pwgroup || !*pwgroup) - wgroup = lp_workgroup(); - else - wgroup = pwgroup; - - addr = *interpret_addr2(s2); + char *s; + const char *ptr; + static time_t last_time = 0; + pstring s2; + struct in_addr addr; + char *comment; + int stype = lp_default_server_announce(); + + if (last_time && (t < (last_time + REMOTE_ANNOUNCE_INTERVAL))) + return; + + last_time = t; + + s = lp_remote_announce(); + if (!*s) + return; + + comment = string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH); + + for (ptr=s; next_token(&ptr,s2,NULL,sizeof(s2)); ) { + /* The entries are of the form a.b.c.d/WORKGROUP with + WORKGROUP being optional */ + const char *wgroup; + char *pwgroup; + int i; + + pwgroup = strchr_m(s2,'/'); + if (pwgroup) + *pwgroup++ = 0; + if (!pwgroup || !*pwgroup) + wgroup = lp_workgroup(); + else + wgroup = pwgroup; + + addr = *interpret_addr2(s2); - /* Announce all our names including aliases */ - /* Give the ip address as the address of our first - broadcast subnet. */ - - for(i=0; my_netbios_names(i); i++) - { - const char *name = my_netbios_names(i); - - DEBUG(5,("announce_remote: Doing remote announce for server %s to IP %s.\n", - name, inet_ntoa(addr) )); - - send_announcement(FIRST_SUBNET, ANN_HostAnnouncement, - name, /* From nbt name. */ - wgroup, 0x1d, /* To nbt name. */ - addr, /* To ip. */ - REMOTE_ANNOUNCE_INTERVAL, /* Time until next announce. */ - name, /* Name to announce. */ - stype, /* Type field. */ - comment); - } - } + /* Announce all our names including aliases */ + /* Give the ip address as the address of our first + broadcast subnet. */ + + for(i=0; my_netbios_names(i); i++) { + const char *name = my_netbios_names(i); + + DEBUG(5,("announce_remote: Doing remote announce for server %s to IP %s.\n", + name, inet_ntoa(addr) )); + + send_announcement(FIRST_SUBNET, ANN_HostAnnouncement, + name, /* From nbt name. */ + wgroup, 0x1d, /* To nbt name. */ + addr, /* To ip. */ + REMOTE_ANNOUNCE_INTERVAL, /* Time until next announce. */ + name, /* Name to announce. */ + stype, /* Type field. */ + comment); + } + } } /**************************************************************************** Implement the 'remote browse sync' feature Andrew added. These are used to put our browse lists into remote browse lists. - **************************************************************************/ +**************************************************************************/ void browse_sync_remote(time_t t) { - char *s; - const char *ptr; - static time_t last_time = 0; - pstring s2; - struct in_addr addr; - struct work_record *work; - pstring outbuf; - char *p; - fstring myname; + char *s; + const char *ptr; + static time_t last_time = 0; + pstring s2; + struct in_addr addr; + struct work_record *work; + pstring outbuf; + char *p; + fstring myname; - if (last_time && (t < (last_time + REMOTE_ANNOUNCE_INTERVAL))) - return; + if (last_time && (t < (last_time + REMOTE_ANNOUNCE_INTERVAL))) + return; - last_time = t; - - s = lp_remote_browse_sync(); - if (!*s) - return; - - /* - * We only do this if we are the local master browser - * for our workgroup on the firsst subnet. - */ - - if((work = find_workgroup_on_subnet(FIRST_SUBNET, lp_workgroup())) == NULL) - { - DEBUG(0,("browse_sync_remote: Cannot find workgroup %s on subnet %s\n", - lp_workgroup(), FIRST_SUBNET->subnet_name )); - return; - } + last_time = t; + + s = lp_remote_browse_sync(); + if (!*s) + return; + + /* + * We only do this if we are the local master browser + * for our workgroup on the firsst subnet. + */ + + if((work = find_workgroup_on_subnet(FIRST_SUBNET, lp_workgroup())) == NULL) { + DEBUG(0,("browse_sync_remote: Cannot find workgroup %s on subnet %s\n", + lp_workgroup(), FIRST_SUBNET->subnet_name )); + return; + } - if(!AM_LOCAL_MASTER_BROWSER(work)) - { - DEBUG(5,("browse_sync_remote: We can only do this if we are a local master browser \ + if(!AM_LOCAL_MASTER_BROWSER(work)) { + DEBUG(5,("browse_sync_remote: We can only do this if we are a local master browser \ for workgroup %s on subnet %s.\n", lp_workgroup(), FIRST_SUBNET->subnet_name )); - return; - } + return; + } - memset(outbuf,'\0',sizeof(outbuf)); - p = outbuf; - SCVAL(p,0,ANN_MasterAnnouncement); - p++; + memset(outbuf,'\0',sizeof(outbuf)); + p = outbuf; + SCVAL(p,0,ANN_MasterAnnouncement); + p++; - fstrcpy(myname, global_myname()); - strupper_m(myname); - myname[15]='\0'; - push_pstring_base(p, myname, outbuf); + fstrcpy(myname, global_myname()); + strupper_m(myname); + myname[15]='\0'; + push_pstring_base(p, myname, outbuf); - p = skip_string(p,1); + p = skip_string(p,1); - for (ptr=s; next_token(&ptr,s2,NULL,sizeof(s2)); ) - { - /* The entries are of the form a.b.c.d */ - addr = *interpret_addr2(s2); + for (ptr=s; next_token(&ptr,s2,NULL,sizeof(s2)); ) { + /* The entries are of the form a.b.c.d */ + addr = *interpret_addr2(s2); - DEBUG(5,("announce_remote: Doing remote browse sync announce for server %s to IP %s.\n", - global_myname(), inet_ntoa(addr) )); + DEBUG(5,("announce_remote: Doing remote browse sync announce for server %s to IP %s.\n", + global_myname(), inet_ntoa(addr) )); - send_mailslot(True, BROWSE_MAILSLOT, outbuf,PTR_DIFF(p,outbuf), - global_myname(), 0x0, "*", 0x0, addr, FIRST_SUBNET->myip, DGRAM_PORT); - } + send_mailslot(True, BROWSE_MAILSLOT, outbuf,PTR_DIFF(p,outbuf), + global_myname(), 0x0, "*", 0x0, addr, FIRST_SUBNET->myip, DGRAM_PORT); + } } diff --git a/source3/nmbd/nmbd_serverlistdb.c b/source3/nmbd/nmbd_serverlistdb.c index 2484a7f830..cdb1089a54 100644 --- a/source3/nmbd/nmbd_serverlistdb.c +++ b/source3/nmbd/nmbd_serverlistdb.c @@ -33,28 +33,26 @@ int updatecount = 0; void remove_all_servers(struct work_record *work) { - struct server_record *servrec; - struct server_record *nexts; + struct server_record *servrec; + struct server_record *nexts; - for (servrec = work->serverlist; servrec; servrec = nexts) - { - DEBUG(7,("remove_all_servers: Removing server %s\n",servrec->serv.name)); - nexts = servrec->next; + for (servrec = work->serverlist; servrec; servrec = nexts) { + DEBUG(7,("remove_all_servers: Removing server %s\n",servrec->serv.name)); + nexts = servrec->next; - if (servrec->prev) - servrec->prev->next = servrec->next; - if (servrec->next) - servrec->next->prev = servrec->prev; + if (servrec->prev) + servrec->prev->next = servrec->next; + if (servrec->next) + servrec->next->prev = servrec->prev; - if (work->serverlist == servrec) - work->serverlist = servrec->next; + if (work->serverlist == servrec) + work->serverlist = servrec->next; - ZERO_STRUCTP(servrec); - SAFE_FREE(servrec); + ZERO_STRUCTP(servrec); + SAFE_FREE(servrec); + } - } - - work->subnet->work_changed = True; + work->subnet->work_changed = True; } /*************************************************************************** @@ -64,23 +62,22 @@ void remove_all_servers(struct work_record *work) static void add_server_to_workgroup(struct work_record *work, struct server_record *servrec) { - struct server_record *servrec2; - - if (!work->serverlist) - { - work->serverlist = servrec; - servrec->prev = NULL; - servrec->next = NULL; - return; - } - - for (servrec2 = work->serverlist; servrec2->next; servrec2 = servrec2->next) - ; - - servrec2->next = servrec; - servrec->next = NULL; - servrec->prev = servrec2; - work->subnet->work_changed = True; + struct server_record *servrec2; + + if (!work->serverlist) { + work->serverlist = servrec; + servrec->prev = NULL; + servrec->next = NULL; + return; + } + + for (servrec2 = work->serverlist; servrec2->next; servrec2 = servrec2->next) + ; + + servrec2->next = servrec; + servrec->next = NULL; + servrec->prev = servrec2; + work->subnet->work_changed = True; } /**************************************************************************** @@ -89,14 +86,13 @@ static void add_server_to_workgroup(struct work_record *work, struct server_record *find_server_in_workgroup(struct work_record *work, const char *name) { - struct server_record *ret; + struct server_record *ret; - for (ret = work->serverlist; ret; ret = ret->next) - { - if (strequal(ret->serv.name,name)) - return ret; - } - return NULL; + for (ret = work->serverlist; ret; ret = ret->next) { + if (strequal(ret->serv.name,name)) + return ret; + } + return NULL; } @@ -106,17 +102,17 @@ struct server_record *find_server_in_workgroup(struct work_record *work, const c void remove_server_from_workgroup(struct work_record *work, struct server_record *servrec) { - if (servrec->prev) - servrec->prev->next = servrec->next; - if (servrec->next) - servrec->next->prev = servrec->prev; + if (servrec->prev) + servrec->prev->next = servrec->next; + if (servrec->next) + servrec->next->prev = servrec->prev; - if (work->serverlist == servrec) - work->serverlist = servrec->next; + if (work->serverlist == servrec) + work->serverlist = servrec->next; - ZERO_STRUCTP(servrec); - SAFE_FREE(servrec); - work->subnet->work_changed = True; + ZERO_STRUCTP(servrec); + SAFE_FREE(servrec); + work->subnet->work_changed = True; } /**************************************************************************** @@ -127,47 +123,44 @@ struct server_record *create_server_on_workgroup(struct work_record *work, const char *name,int servertype, int ttl, const char *comment) { - struct server_record *servrec; + struct server_record *servrec; - if (name[0] == '*') - { - DEBUG(7,("create_server_on_workgroup: not adding name starting with '*' (%s)\n", - name)); - return (NULL); - } + if (name[0] == '*') { + DEBUG(7,("create_server_on_workgroup: not adding name starting with '*' (%s)\n", + name)); + return (NULL); + } - if((servrec = find_server_in_workgroup(work, name)) != NULL) - { - DEBUG(0,("create_server_on_workgroup: Server %s already exists on \ + if((servrec = find_server_in_workgroup(work, name)) != NULL) { + DEBUG(0,("create_server_on_workgroup: Server %s already exists on \ workgroup %s. This is a bug.\n", name, work->work_group)); - return NULL; - } + return NULL; + } - if((servrec = (struct server_record *)malloc(sizeof(*servrec))) == NULL) - { - DEBUG(0,("create_server_entry_on_workgroup: malloc fail !\n")); - return NULL; - } + if((servrec = (struct server_record *)malloc(sizeof(*servrec))) == NULL) { + DEBUG(0,("create_server_entry_on_workgroup: malloc fail !\n")); + return NULL; + } - memset((char *)servrec,'\0',sizeof(*servrec)); + memset((char *)servrec,'\0',sizeof(*servrec)); - servrec->subnet = work->subnet; + servrec->subnet = work->subnet; - fstrcpy(servrec->serv.name,name); - fstrcpy(servrec->serv.comment,comment); - strupper_m(servrec->serv.name); - servrec->serv.type = servertype; + fstrcpy(servrec->serv.name,name); + fstrcpy(servrec->serv.comment,comment); + strupper_m(servrec->serv.name); + servrec->serv.type = servertype; - update_server_ttl(servrec, ttl); + update_server_ttl(servrec, ttl); - add_server_to_workgroup(work, servrec); + add_server_to_workgroup(work, servrec); - DEBUG(3,("create_server_on_workgroup: Created server entry %s of type %x (%s) on \ + DEBUG(3,("create_server_on_workgroup: Created server entry %s of type %x (%s) on \ workgroup %s.\n", name,servertype,comment, work->work_group)); - work->subnet->work_changed = True; + work->subnet->work_changed = True; - return(servrec); + return(servrec); } /******************************************************************* @@ -176,15 +169,15 @@ workgroup %s.\n", name,servertype,comment, work->work_group)); void update_server_ttl(struct server_record *servrec, int ttl) { - if(ttl > lp_max_ttl()) - ttl = lp_max_ttl(); + if(ttl > lp_max_ttl()) + ttl = lp_max_ttl(); - if(is_myname(servrec->serv.name)) - servrec->death_time = PERMANENT_TTL; - else - servrec->death_time = (ttl != PERMANENT_TTL) ? time(NULL)+(ttl*3) : PERMANENT_TTL; + if(is_myname(servrec->serv.name)) + servrec->death_time = PERMANENT_TTL; + else + servrec->death_time = (ttl != PERMANENT_TTL) ? time(NULL)+(ttl*3) : PERMANENT_TTL; - servrec->subnet->work_changed = True; + servrec->subnet->work_changed = True; } /******************************************************************* @@ -195,20 +188,18 @@ void update_server_ttl(struct server_record *servrec, int ttl) void expire_servers(struct work_record *work, time_t t) { - struct server_record *servrec; - struct server_record *nexts; + struct server_record *servrec; + struct server_record *nexts; - for (servrec = work->serverlist; servrec; servrec = nexts) - { - nexts = servrec->next; - - if ((servrec->death_time != PERMANENT_TTL) && ((t == -1) || (servrec->death_time < t))) - { - DEBUG(3,("expire_old_servers: Removing timed out server %s\n",servrec->serv.name)); - remove_server_from_workgroup(work, servrec); - work->subnet->work_changed = True; - } - } + for (servrec = work->serverlist; servrec; servrec = nexts) { + nexts = servrec->next; + + if ((servrec->death_time != PERMANENT_TTL) && ((t == -1) || (servrec->death_time < t))) { + DEBUG(3,("expire_old_servers: Removing timed out server %s\n",servrec->serv.name)); + remove_server_from_workgroup(work, servrec); + work->subnet->work_changed = True; + } + } } /******************************************************************* @@ -221,33 +212,30 @@ static uint32 write_this_server_name( struct subnet_record *subrec, struct work_record *work, struct server_record *servrec) { - struct subnet_record *ssub; - struct work_record *iwork; - - /* Go through all the subnets we have already seen. */ - for (ssub = FIRST_SUBNET; ssub != subrec; ssub = NEXT_SUBNET_INCLUDING_UNICAST(ssub)) - { - for(iwork = ssub->workgrouplist; iwork; iwork = iwork->next) - { - if(find_server_in_workgroup( iwork, servrec->serv.name) != NULL) - { - /* - * We have already written out this server record, don't - * do it again. This gives precedence to servers we have seen - * on the broadcast subnets over servers that may have been - * added via a sync on the unicast_subet. - * - * The correct way to do this is to have a serverlist file - * per subnet - this means changes to smbd as well. I may - * add this at a later date (JRA). - */ - - return 0; - } - } - } - - return servrec->serv.type; + struct subnet_record *ssub; + struct work_record *iwork; + + /* Go through all the subnets we have already seen. */ + for (ssub = FIRST_SUBNET; ssub != subrec; ssub = NEXT_SUBNET_INCLUDING_UNICAST(ssub)) { + for(iwork = ssub->workgrouplist; iwork; iwork = iwork->next) { + if(find_server_in_workgroup( iwork, servrec->serv.name) != NULL) { + /* + * We have already written out this server record, don't + * do it again. This gives precedence to servers we have seen + * on the broadcast subnets over servers that may have been + * added via a sync on the unicast_subet. + * + * The correct way to do this is to have a serverlist file + * per subnet - this means changes to smbd as well. I may + * add this at a later date (JRA). + */ + + return 0; + } + } + } + + return servrec->serv.type; } /******************************************************************* @@ -261,30 +249,29 @@ static uint32 write_this_server_name( struct subnet_record *subrec, static uint32 write_this_workgroup_name( struct subnet_record *subrec, struct work_record *work) { - struct subnet_record *ssub; + struct subnet_record *ssub; - if(strequal(lp_workgroup(), work->work_group)) - return 0; + if(strnequal(lp_workgroup(), work->work_group, sizeof(nstring)-1)) + return 0; - /* This is a workgroup we have seen on a broadcast subnet. All - these have the same type. */ + /* This is a workgroup we have seen on a broadcast subnet. All + these have the same type. */ - if(subrec != unicast_subnet) - return (SV_TYPE_DOMAIN_ENUM|SV_TYPE_NT|SV_TYPE_LOCAL_LIST_ONLY); + if(subrec != unicast_subnet) + return (SV_TYPE_DOMAIN_ENUM|SV_TYPE_NT|SV_TYPE_LOCAL_LIST_ONLY); - for(ssub = FIRST_SUBNET; ssub; ssub = NEXT_SUBNET_EXCLUDING_UNICAST(ssub)) - { - /* This is the unicast subnet so check if we've already written out - this subnet when we passed over the broadcast subnets. */ + for(ssub = FIRST_SUBNET; ssub; ssub = NEXT_SUBNET_EXCLUDING_UNICAST(ssub)) { + /* This is the unicast subnet so check if we've already written out + this subnet when we passed over the broadcast subnets. */ - if(find_workgroup_on_subnet( ssub, work->work_group) != NULL) - return 0; - } + if(find_workgroup_on_subnet( ssub, work->work_group) != NULL) + return 0; + } - /* All workgroups on the unicast subnet (except our own, which we - have already written out) cannot be local. */ + /* All workgroups on the unicast subnet (except our own, which we + have already written out) cannot be local. */ - return (SV_TYPE_DOMAIN_ENUM|SV_TYPE_NT); + return (SV_TYPE_DOMAIN_ENUM|SV_TYPE_NT); } /******************************************************************* @@ -306,143 +293,130 @@ void write_browse_list_entry(XFILE *fp, const char *name, uint32 rec_type, void write_browse_list(time_t t, BOOL force_write) { - struct subnet_record *subrec; - struct work_record *work; - struct server_record *servrec; - pstring fname,fnamenew; - uint32 stype; - int i; - XFILE *fp; - BOOL list_changed = force_write; - static time_t lasttime = 0; + struct subnet_record *subrec; + struct work_record *work; + struct server_record *servrec; + pstring fname,fnamenew; + uint32 stype; + int i; + XFILE *fp; + BOOL list_changed = force_write; + static time_t lasttime = 0; - /* Always dump if we're being told to by a signal. */ - if(force_write == False) - { - if (!lasttime) - lasttime = t; - if (t - lasttime < 5) - return; - } - - lasttime = t; - - dump_workgroups(force_write); + /* Always dump if we're being told to by a signal. */ + if(force_write == False) { + if (!lasttime) + lasttime = t; + if (t - lasttime < 5) + return; + } + + lasttime = t; + + dump_workgroups(force_write); - for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec)) - { - if(subrec->work_changed) - { - list_changed = True; - break; - } - } - - if(!list_changed) - return; - - updatecount++; + for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec)) { + if(subrec->work_changed) { + list_changed = True; + break; + } + } + + if(!list_changed) + return; + + updatecount++; - pstrcpy(fname,lp_lockdir()); - trim_string(fname,NULL,"/"); - pstrcat(fname,"/"); - pstrcat(fname,SERVER_LIST); - pstrcpy(fnamenew,fname); - pstrcat(fnamenew,"."); + pstrcpy(fname,lp_lockdir()); + trim_char(fname,'\0' ,'/'); + pstrcat(fname,"/"); + pstrcat(fname,SERVER_LIST); + pstrcpy(fnamenew,fname); + pstrcat(fnamenew,"."); - fp = x_fopen(fnamenew,O_WRONLY|O_CREAT|O_TRUNC, 0644); + fp = x_fopen(fnamenew,O_WRONLY|O_CREAT|O_TRUNC, 0644); - if (!fp) - { - DEBUG(0,("write_browse_list: Can't open file %s. Error was %s\n", - fnamenew,strerror(errno))); - return; - } + if (!fp) { + DEBUG(0,("write_browse_list: Can't open file %s. Error was %s\n", + fnamenew,strerror(errno))); + return; + } - /* - * Write out a record for our workgroup. Use the record from the first - * subnet. - */ - - if((work = find_workgroup_on_subnet(FIRST_SUBNET, lp_workgroup())) == NULL) - { - DEBUG(0,("write_browse_list: Fatal error - cannot find my workgroup %s\n", - lp_workgroup())); - x_fclose(fp); - return; - } - - write_browse_list_entry(fp, work->work_group, - SV_TYPE_DOMAIN_ENUM|SV_TYPE_NT|SV_TYPE_LOCAL_LIST_ONLY, - work->local_master_browser_name, work->work_group); - - /* - * We need to do something special for our own names. - * This is due to the fact that we may be a local master browser on - * one of our broadcast subnets, and a domain master on the unicast - * subnet. We iterate over the subnets and only write out the name - * once. - */ - - for (i=0; my_netbios_names(i); i++) - { - stype = 0; - for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec)) - { - if((work = find_workgroup_on_subnet( subrec, lp_workgroup() )) == NULL) - continue; - if((servrec = find_server_in_workgroup( work, my_netbios_names(i))) == NULL) - continue; - - stype |= servrec->serv.type; - } - - /* Output server details, plus what workgroup they're in. */ - write_browse_list_entry(fp, my_netbios_names(i), stype, - string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH), lp_workgroup()); - } + /* + * Write out a record for our workgroup. Use the record from the first + * subnet. + */ + + if((work = find_workgroup_on_subnet(FIRST_SUBNET, lp_workgroup())) == NULL) { + DEBUG(0,("write_browse_list: Fatal error - cannot find my workgroup %s\n", + lp_workgroup())); + x_fclose(fp); + return; + } + + write_browse_list_entry(fp, work->work_group, + SV_TYPE_DOMAIN_ENUM|SV_TYPE_NT|SV_TYPE_LOCAL_LIST_ONLY, + work->local_master_browser_name, work->work_group); + + /* + * We need to do something special for our own names. + * This is due to the fact that we may be a local master browser on + * one of our broadcast subnets, and a domain master on the unicast + * subnet. We iterate over the subnets and only write out the name + * once. + */ + + for (i=0; my_netbios_names(i); i++) { + stype = 0; + for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec)) { + if((work = find_workgroup_on_subnet( subrec, lp_workgroup() )) == NULL) + continue; + if((servrec = find_server_in_workgroup( work, my_netbios_names(i))) == NULL) + continue; + + stype |= servrec->serv.type; + } + + /* Output server details, plus what workgroup they're in. */ + write_browse_list_entry(fp, my_netbios_names(i), stype, + string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH), lp_workgroup()); + } - for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec)) - { - subrec->work_changed = False; - - for (work = subrec->workgrouplist; work ; work = work->next) - { - /* Write out a workgroup record for a workgroup. */ - uint32 wg_type = write_this_workgroup_name( subrec, work); - - if(wg_type) - { - write_browse_list_entry(fp, work->work_group, wg_type, - work->local_master_browser_name, - work->work_group); - } - - /* Now write out any server records a workgroup may have. */ - - for (servrec = work->serverlist; servrec ; servrec = servrec->next) - { - uint32 serv_type; - - /* We have already written our names here. */ - if(is_myname(servrec->serv.name)) - continue; - - serv_type = write_this_server_name(subrec, work, servrec); - - if(serv_type) - { - /* Output server details, plus what workgroup they're in. */ - write_browse_list_entry(fp, servrec->serv.name, serv_type, - servrec->serv.comment, work->work_group); - } - } - } - } + for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec)) { + subrec->work_changed = False; + + for (work = subrec->workgrouplist; work ; work = work->next) { + /* Write out a workgroup record for a workgroup. */ + uint32 wg_type = write_this_workgroup_name( subrec, work); + + if(wg_type) { + write_browse_list_entry(fp, work->work_group, wg_type, + work->local_master_browser_name, + work->work_group); + } + + /* Now write out any server records a workgroup may have. */ + + for (servrec = work->serverlist; servrec ; servrec = servrec->next) { + uint32 serv_type; + + /* We have already written our names here. */ + if(is_myname(servrec->serv.name)) + continue; + + serv_type = write_this_server_name(subrec, work, servrec); + if(serv_type) { + /* Output server details, plus what workgroup they're in. */ + write_browse_list_entry(fp, servrec->serv.name, serv_type, + servrec->serv.comment, work->work_group); + } + } + } + } - x_fclose(fp); - unlink(fname); - chmod(fnamenew,0644); - rename(fnamenew,fname); - DEBUG(3,("write_browse_list: Wrote browse list into file %s\n",fname)); + x_fclose(fp); + unlink(fname); + chmod(fnamenew,0644); + rename(fnamenew,fname); + DEBUG(3,("write_browse_list: Wrote browse list into file %s\n",fname)); } diff --git a/source3/nmbd/nmbd_subnetdb.c b/source3/nmbd/nmbd_subnetdb.c index 6296826425..02a91f2760 100644 --- a/source3/nmbd/nmbd_subnetdb.c +++ b/source3/nmbd/nmbd_subnetdb.c @@ -63,28 +63,27 @@ static void add_subnet(struct subnet_record *subrec) * ************************************************************************** ** */ static int namelist_entry_compare( ubi_trItemPtr Item, ubi_trNodePtr Node ) - { - struct name_record *NR = (struct name_record *)Node; - - if( DEBUGLVL( 10 ) ) - { - struct nmb_name *Iname = (struct nmb_name *)Item; +{ + struct name_record *NR = (struct name_record *)Node; - Debug1( "nmbd_subnetdb:namelist_entry_compare()\n" ); - Debug1( "%d == memcmp( \"%s\", \"%s\", %d )\n", - memcmp( Item, &(NR->name), sizeof(struct nmb_name) ), - nmb_namestr(Iname), nmb_namestr(&NR->name), (int)sizeof(struct nmb_name) ); - } + if( DEBUGLVL( 10 ) ) { + struct nmb_name *Iname = (struct nmb_name *)Item; - return( memcmp( Item, &(NR->name), sizeof(struct nmb_name) ) ); - } /* namelist_entry_compare */ + Debug1( "nmbd_subnetdb:namelist_entry_compare()\n" ); + Debug1( "%d == memcmp( \"%s\", \"%s\", %d )\n", + memcmp( Item, &(NR->name), sizeof(struct nmb_name) ), + nmb_namestr(Iname), nmb_namestr(&NR->name), (int)sizeof(struct nmb_name) ); + } + return( memcmp( Item, &(NR->name), sizeof(struct nmb_name) ) ); +} /**************************************************************************** stop listening on a subnet we don't free the record as we don't have proper reference counting for it yet and it may be in use by a response record ****************************************************************************/ + void close_subnet(struct subnet_record *subrec) { DLIST_REMOVE(subnetlist, subrec); @@ -99,8 +98,6 @@ void close_subnet(struct subnet_record *subrec) } } - - /**************************************************************************** Create a subnet entry. ****************************************************************************/ @@ -109,102 +106,90 @@ static struct subnet_record *make_subnet(const char *name, enum subnet_type type struct in_addr myip, struct in_addr bcast_ip, struct in_addr mask_ip) { - struct subnet_record *subrec = NULL; - int nmb_sock, dgram_sock; - - /* Check if we are creating a non broadcast subnet - if so don't create - sockets. - */ - - if(type != NORMAL_SUBNET) - { - nmb_sock = -1; - dgram_sock = -1; - } - else - { - /* - * Attempt to open the sockets on port 137/138 for this interface - * and bind them. - * Fail the subnet creation if this fails. - */ - - if((nmb_sock = open_socket_in(SOCK_DGRAM, global_nmb_port,0, myip.s_addr,True)) == -1) - { - if( DEBUGLVL( 0 ) ) - { - Debug1( "nmbd_subnetdb:make_subnet()\n" ); - Debug1( " Failed to open nmb socket on interface %s ", inet_ntoa(myip) ); - Debug1( "for port %d. ", global_nmb_port ); - Debug1( "Error was %s\n", strerror(errno) ); - } - return NULL; - } - - if((dgram_sock = open_socket_in(SOCK_DGRAM,DGRAM_PORT,3, myip.s_addr,True)) == -1) - { - if( DEBUGLVL( 0 ) ) - { - Debug1( "nmbd_subnetdb:make_subnet()\n" ); - Debug1( " Failed to open dgram socket on interface %s ", inet_ntoa(myip) ); - Debug1( "for port %d. ", DGRAM_PORT ); - Debug1( "Error was %s\n", strerror(errno) ); - } - return NULL; - } - - /* Make sure we can broadcast from these sockets. */ - set_socket_options(nmb_sock,"SO_BROADCAST"); - set_socket_options(dgram_sock,"SO_BROADCAST"); - - } - - subrec = (struct subnet_record *)malloc(sizeof(*subrec)); - - if (!subrec) - { - DEBUG(0,("make_subnet: malloc fail !\n")); - close(nmb_sock); - close(dgram_sock); - return(NULL); - } + struct subnet_record *subrec = NULL; + int nmb_sock, dgram_sock; + + /* Check if we are creating a non broadcast subnet - if so don't create + sockets. */ + + if(type != NORMAL_SUBNET) { + nmb_sock = -1; + dgram_sock = -1; + } else { + /* + * Attempt to open the sockets on port 137/138 for this interface + * and bind them. + * Fail the subnet creation if this fails. + */ + + if((nmb_sock = open_socket_in(SOCK_DGRAM, global_nmb_port,0, myip.s_addr,True)) == -1) { + if( DEBUGLVL( 0 ) ) { + Debug1( "nmbd_subnetdb:make_subnet()\n" ); + Debug1( " Failed to open nmb socket on interface %s ", inet_ntoa(myip) ); + Debug1( "for port %d. ", global_nmb_port ); + Debug1( "Error was %s\n", strerror(errno) ); + } + return NULL; + } + + if((dgram_sock = open_socket_in(SOCK_DGRAM,DGRAM_PORT,3, myip.s_addr,True)) == -1) { + if( DEBUGLVL( 0 ) ) { + Debug1( "nmbd_subnetdb:make_subnet()\n" ); + Debug1( " Failed to open dgram socket on interface %s ", inet_ntoa(myip) ); + Debug1( "for port %d. ", DGRAM_PORT ); + Debug1( "Error was %s\n", strerror(errno) ); + } + return NULL; + } + + /* Make sure we can broadcast from these sockets. */ + set_socket_options(nmb_sock,"SO_BROADCAST"); + set_socket_options(dgram_sock,"SO_BROADCAST"); + } + + subrec = (struct subnet_record *)malloc(sizeof(*subrec)); + if (!subrec) { + DEBUG(0,("make_subnet: malloc fail !\n")); + close(nmb_sock); + close(dgram_sock); + return(NULL); + } - memset( (char *)subrec, '\0', sizeof(*subrec) ); - (void)ubi_trInitTree( subrec->namelist, - namelist_entry_compare, - ubi_trOVERWRITE ); - - if((subrec->subnet_name = strdup(name)) == NULL) - { - DEBUG(0,("make_subnet: malloc fail for subnet name !\n")); - close(nmb_sock); - close(dgram_sock); - ZERO_STRUCTP(subrec); - SAFE_FREE(subrec); - return(NULL); - } - - DEBUG(2, ("making subnet name:%s ", name )); - DEBUG(2, ("Broadcast address:%s ", inet_ntoa(bcast_ip))); - DEBUG(2, ("Subnet mask:%s\n", inet_ntoa(mask_ip))); + memset( (char *)subrec, '\0', sizeof(*subrec) ); + (void)ubi_trInitTree( subrec->namelist, + namelist_entry_compare, + ubi_trOVERWRITE ); + + if((subrec->subnet_name = strdup(name)) == NULL) { + DEBUG(0,("make_subnet: malloc fail for subnet name !\n")); + close(nmb_sock); + close(dgram_sock); + ZERO_STRUCTP(subrec); + SAFE_FREE(subrec); + return(NULL); + } + + DEBUG(2, ("making subnet name:%s ", name )); + DEBUG(2, ("Broadcast address:%s ", inet_ntoa(bcast_ip))); + DEBUG(2, ("Subnet mask:%s\n", inet_ntoa(mask_ip))); - subrec->namelist_changed = False; - subrec->work_changed = False; + subrec->namelist_changed = False; + subrec->work_changed = False; - subrec->bcast_ip = bcast_ip; - subrec->mask_ip = mask_ip; - subrec->myip = myip; - subrec->type = type; - subrec->nmb_sock = nmb_sock; - subrec->dgram_sock = dgram_sock; + subrec->bcast_ip = bcast_ip; + subrec->mask_ip = mask_ip; + subrec->myip = myip; + subrec->type = type; + subrec->nmb_sock = nmb_sock; + subrec->dgram_sock = dgram_sock; - return subrec; + return subrec; } - /**************************************************************************** Create a normal subnet **************************************************************************/ + struct subnet_record *make_normal_subnet(struct interface *iface) { struct subnet_record *subrec; @@ -217,100 +202,99 @@ struct subnet_record *make_normal_subnet(struct interface *iface) return subrec; } - /**************************************************************************** Create subnet entries. **************************************************************************/ BOOL create_subnets(void) { - int num_interfaces = iface_count(); - int i; - struct in_addr unicast_ip, ipzero; - extern struct in_addr loopback_ip; - - if(num_interfaces == 0) { - DEBUG(0,("create_subnets: No local interfaces !\n")); - DEBUG(0,("create_subnets: Waiting for an interface to appear ...\n")); - while (iface_count() == 0) { - sleep(5); - load_interfaces(); - } - } - - num_interfaces = iface_count(); - - /* - * Create subnets from all the local interfaces and thread them onto - * the linked list. - */ - - for (i = 0 ; i < num_interfaces; i++) - { - struct interface *iface = get_interface(i); - - /* - * We don't want to add a loopback interface, in case - * someone has added 127.0.0.1 for smbd, nmbd needs to - * ignore it here. JRA. - */ - - if (ip_equal(iface->ip, loopback_ip)) { - DEBUG(2,("create_subnets: Ignoring loopback interface.\n" )); - continue; - } - - if (!make_normal_subnet(iface)) return False; - } - - if (lp_we_are_a_wins_server()) { - /* Pick the first interface ip address as the WINS server ip. */ - unicast_ip = *iface_n_ip(0); - } else { - /* note that we do not set the wins server IP here. We just - set it at zero and let the wins registration code cope - with getting the IPs right for each packet */ - zero_ip(&unicast_ip); - } - - /* - * Create the unicast and remote broadcast subnets. - * Don't put these onto the linked list. - * The ip address of the unicast subnet is set to be - * the WINS server address, if it exists, or ipzero if not. - */ - - unicast_subnet = make_subnet( "UNICAST_SUBNET", UNICAST_SUBNET, - unicast_ip, unicast_ip, unicast_ip); - - zero_ip(&ipzero); - - remote_broadcast_subnet = make_subnet( "REMOTE_BROADCAST_SUBNET", - REMOTE_BROADCAST_SUBNET, - ipzero, ipzero, ipzero); - - if((unicast_subnet == NULL) || (remote_broadcast_subnet == NULL)) - return False; - - /* - * If we are WINS server, create the WINS_SERVER_SUBNET - don't put on - * the linked list. - */ - - if (lp_we_are_a_wins_server()) - { - if( (wins_server_subnet = make_subnet( "WINS_SERVER_SUBNET", - WINS_SERVER_SUBNET, - ipzero, ipzero, ipzero )) == NULL ) - return False; - } - - return True; + int num_interfaces = iface_count(); + int i; + struct in_addr unicast_ip, ipzero; + extern struct in_addr loopback_ip; + + if(num_interfaces == 0) { + DEBUG(0,("create_subnets: No local interfaces !\n")); + DEBUG(0,("create_subnets: Waiting for an interface to appear ...\n")); + while (iface_count() == 0) { + sleep(5); + load_interfaces(); + } + } + + num_interfaces = iface_count(); + + /* + * Create subnets from all the local interfaces and thread them onto + * the linked list. + */ + + for (i = 0 ; i < num_interfaces; i++) { + struct interface *iface = get_interface(i); + + /* + * We don't want to add a loopback interface, in case + * someone has added 127.0.0.1 for smbd, nmbd needs to + * ignore it here. JRA. + */ + + if (ip_equal(iface->ip, loopback_ip)) { + DEBUG(2,("create_subnets: Ignoring loopback interface.\n" )); + continue; + } + + if (!make_normal_subnet(iface)) + return False; + } + + if (lp_we_are_a_wins_server()) { + /* Pick the first interface ip address as the WINS server ip. */ + unicast_ip = *iface_n_ip(0); + } else { + /* note that we do not set the wins server IP here. We just + set it at zero and let the wins registration code cope + with getting the IPs right for each packet */ + zero_ip(&unicast_ip); + } + + /* + * Create the unicast and remote broadcast subnets. + * Don't put these onto the linked list. + * The ip address of the unicast subnet is set to be + * the WINS server address, if it exists, or ipzero if not. + */ + + unicast_subnet = make_subnet( "UNICAST_SUBNET", UNICAST_SUBNET, + unicast_ip, unicast_ip, unicast_ip); + + zero_ip(&ipzero); + + remote_broadcast_subnet = make_subnet( "REMOTE_BROADCAST_SUBNET", + REMOTE_BROADCAST_SUBNET, + ipzero, ipzero, ipzero); + + if((unicast_subnet == NULL) || (remote_broadcast_subnet == NULL)) + return False; + + /* + * If we are WINS server, create the WINS_SERVER_SUBNET - don't put on + * the linked list. + */ + + if (lp_we_are_a_wins_server()) { + if( (wins_server_subnet = make_subnet( "WINS_SERVER_SUBNET", + WINS_SERVER_SUBNET, + ipzero, ipzero, ipzero )) == NULL ) + return False; + } + + return True; } /******************************************************************* Function to tell us if we can use the unicast subnet. ******************************************************************/ + BOOL we_are_a_wins_client(void) { if (wins_srv_count() > 0) { @@ -326,12 +310,12 @@ Access function used by NEXT_SUBNET_INCLUDING_UNICAST struct subnet_record *get_next_subnet_maybe_unicast(struct subnet_record *subrec) { - if(subrec == unicast_subnet) - return NULL; - else if((subrec->next == NULL) && we_are_a_wins_client()) - return unicast_subnet; - else - return subrec->next; + if(subrec == unicast_subnet) + return NULL; + else if((subrec->next == NULL) && we_are_a_wins_client()) + return unicast_subnet; + else + return subrec->next; } /******************************************************************* @@ -343,19 +327,18 @@ struct subnet_record *get_next_subnet_maybe_unicast(struct subnet_record *subrec struct subnet_record *get_next_subnet_maybe_unicast_or_wins_server(struct subnet_record *subrec) { - if(subrec == unicast_subnet) - { - if(wins_server_subnet) - return wins_server_subnet; - else - return NULL; - } - - if(wins_server_subnet && subrec == wins_server_subnet) - return NULL; - - if((subrec->next == NULL) && we_are_a_wins_client()) - return unicast_subnet; - else - return subrec->next; + if(subrec == unicast_subnet) { + if(wins_server_subnet) + return wins_server_subnet; + else + return NULL; + } + + if(wins_server_subnet && subrec == wins_server_subnet) + return NULL; + + if((subrec->next == NULL) && we_are_a_wins_client()) + return unicast_subnet; + else + return subrec->next; } diff --git a/source3/nmbd/nmbd_synclists.c b/source3/nmbd/nmbd_synclists.c index b9952fb446..6a0576a5a4 100644 --- a/source3/nmbd/nmbd_synclists.c +++ b/source3/nmbd/nmbd_synclists.c @@ -31,8 +31,8 @@ struct sync_record { struct sync_record *next, *prev; - fstring workgroup; - fstring server; + nstring workgroup; + nstring server; pstring fname; struct in_addr ip; pid_t pid; @@ -47,6 +47,7 @@ static XFILE *fp; This is the NetServerEnum callback. Note sname and comment are in UNIX codepage format. ******************************************************************/ + static void callback(const char *sname, uint32 stype, const char *comment, void *state) { @@ -58,6 +59,7 @@ static void callback(const char *sname, uint32 stype, Log in on the remote server's SMB port to their IPC$ service, do a NetServerEnum and record the results in fname ******************************************************************/ + static void sync_child(char *name, int nm_type, char *workgroup, struct in_addr ip, BOOL local, BOOL servers, @@ -78,10 +80,9 @@ static void sync_child(char *name, int nm_type, } make_nmb_name(&calling, local_machine, 0x0); - make_nmb_name(&called , name , nm_type); + make_nmb_name(&called , name, nm_type); - if (!cli_session_request(&cli, &calling, &called)) - { + if (!cli_session_request(&cli, &calling, &called)) { cli_shutdown(&cli); return; } @@ -120,12 +121,12 @@ static void sync_child(char *name, int nm_type, cli_shutdown(&cli); } - /******************************************************************* initialise a browse sync with another browse server. Log in on the remote server's SMB port to their IPC$ service, do a NetServerEnum and record the results ******************************************************************/ + void sync_browse_lists(struct work_record *work, char *name, int nm_type, struct in_addr ip, BOOL local, BOOL servers) @@ -147,8 +148,8 @@ done: ZERO_STRUCTP(s); - fstrcpy(s->workgroup, work->work_group); - fstrcpy(s->server, name); + nstrcpy(s->workgroup, work->work_group); + nstrcpy(s->server, name); s->ip = ip; slprintf(s->fname, sizeof(pstring)-1, @@ -182,8 +183,9 @@ done: } /********************************************************************** -handle one line from a completed sync file + Handle one line from a completed sync file. **********************************************************************/ + static void complete_one(struct sync_record *s, char *sname, uint32 stype, char *comment) { @@ -204,8 +206,7 @@ static void complete_one(struct sync_record *s, sname, lp_max_ttl()); if (work) { /* remember who the master is */ - fstrcpy(work->local_master_browser_name, - comment); + nstrcpy(work->local_master_browser_name, comment); } } return; @@ -235,10 +236,10 @@ static void complete_one(struct sync_record *s, create_server_on_workgroup(work, sname,stype, lp_max_ttl(), comment); } - /********************************************************************** -read the completed sync info - **********************************************************************/ + Read the completed sync info. +**********************************************************************/ + static void complete_sync(struct sync_record *s) { XFILE *f; @@ -251,11 +252,13 @@ static void complete_sync(struct sync_record *s) f = x_fopen(s->fname,O_RDONLY, 0); - if (!f) return; + if (!f) + return; while (!x_feof(f)) { - if (!fgets_slash(line,sizeof(pstring),f)) continue; + if (!fgets_slash(line,sizeof(pstring),f)) + continue; ptr = line; @@ -281,8 +284,9 @@ static void complete_sync(struct sync_record *s) } /********************************************************************** -check for completion of any of the child processes - **********************************************************************/ + Check for completion of any of the child processes. +**********************************************************************/ + void sync_check_completion(void) { struct sync_record *s, *next; diff --git a/source3/nmbd/nmbd_winsproxy.c b/source3/nmbd/nmbd_winsproxy.c index 2e65ebb612..bace112752 100644 --- a/source3/nmbd/nmbd_winsproxy.c +++ b/source3/nmbd/nmbd_winsproxy.c @@ -30,92 +30,85 @@ static void wins_proxy_name_query_request_success( struct subnet_record *subrec, struct userdata_struct *userdata, struct nmb_name *nmbname, struct in_addr ip, struct res_rec *rrec) { - struct packet_struct *original_packet; - struct subnet_record *orig_broadcast_subnet; - struct name_record *namerec; - uint16 nb_flags; - int num_ips; - int i; - int ttl = 3600; /* By default one hour in the cache. */ - struct in_addr *iplist; - - /* Extract the original packet and the original broadcast subnet from - the userdata. */ - - memcpy( (char *)&orig_broadcast_subnet, userdata->data, sizeof(struct subnet_record *) ); - memcpy( (char *)&original_packet, &userdata->data[sizeof(struct subnet_record *)], - sizeof(struct packet_struct *) ); - - nb_flags = get_nb_flags( rrec->rdata ); - - num_ips = rrec->rdlength / 6; - if(num_ips == 0) - { - DEBUG(0,("wins_proxy_name_query_request_success: Invalid number of IP records (0) \ + nstring name; + struct packet_struct *original_packet; + struct subnet_record *orig_broadcast_subnet; + struct name_record *namerec; + uint16 nb_flags; + int num_ips; + int i; + int ttl = 3600; /* By default one hour in the cache. */ + struct in_addr *iplist; + + /* Extract the original packet and the original broadcast subnet from + the userdata. */ + + memcpy( (char *)&orig_broadcast_subnet, userdata->data, sizeof(struct subnet_record *) ); + memcpy( (char *)&original_packet, &userdata->data[sizeof(struct subnet_record *)], + sizeof(struct packet_struct *) ); + + nb_flags = get_nb_flags( rrec->rdata ); + + num_ips = rrec->rdlength / 6; + if(num_ips == 0) { + DEBUG(0,("wins_proxy_name_query_request_success: Invalid number of IP records (0) \ returned for name %s.\n", nmb_namestr(nmbname) )); - return; - } - - if(num_ips == 1) - iplist = &ip; - else - { - if((iplist = (struct in_addr *)malloc( num_ips * sizeof(struct in_addr) )) == NULL) - { - DEBUG(0,("wins_proxy_name_query_request_success: malloc fail !\n")); - return; - } - - for(i = 0; i < num_ips; i++) - putip( (char *)&iplist[i], (char *)&rrec->rdata[ (i*6) + 2]); - } - - /* Add the queried name to the original subnet as a WINS_PROXY_NAME. */ - - if(rrec == PERMANENT_TTL) - ttl = lp_max_ttl(); - - namerec = add_name_to_subnet( orig_broadcast_subnet, nmbname->name, - nmbname->name_type, nb_flags, ttl, - WINS_PROXY_NAME, num_ips, iplist ); - - if(iplist != &ip) - SAFE_FREE(iplist); - - /* - * Check that none of the IP addresses we are returning is on the - * same broadcast subnet as the original requesting packet. If it - * is then don't reply (although we still need to add the name - * to the cache) as the actual machine will be replying also - * and we don't want two replies to a broadcast query. - */ - - if(namerec && original_packet->packet.nmb.header.nm_flags.bcast) - { - for( i = 0; i < namerec->data.num_ips; i++) - { - if( same_net( namerec->data.ip[i], - orig_broadcast_subnet->myip, - orig_broadcast_subnet->mask_ip ) ) - { - DEBUG( 5, ( "wins_proxy_name_query_request_success: name %s is a WINS \ + return; + } + + if(num_ips == 1) { + iplist = &ip; + } else { + if((iplist = (struct in_addr *)malloc( num_ips * sizeof(struct in_addr) )) == NULL) { + DEBUG(0,("wins_proxy_name_query_request_success: malloc fail !\n")); + return; + } + + for(i = 0; i < num_ips; i++) + putip( (char *)&iplist[i], (char *)&rrec->rdata[ (i*6) + 2]); + } + + /* Add the queried name to the original subnet as a WINS_PROXY_NAME. */ + + if(rrec == PERMANENT_TTL) + ttl = lp_max_ttl(); + + pull_ascii_nstring(name, nmbname->name); + namerec = add_name_to_subnet( orig_broadcast_subnet, name, + nmbname->name_type, nb_flags, ttl, + WINS_PROXY_NAME, num_ips, iplist ); + + if(iplist != &ip) + SAFE_FREE(iplist); + + /* + * Check that none of the IP addresses we are returning is on the + * same broadcast subnet as the original requesting packet. If it + * is then don't reply (although we still need to add the name + * to the cache) as the actual machine will be replying also + * and we don't want two replies to a broadcast query. + */ + + if(namerec && original_packet->packet.nmb.header.nm_flags.bcast) { + for( i = 0; i < namerec->data.num_ips; i++) { + if( same_net( namerec->data.ip[i], orig_broadcast_subnet->myip, + orig_broadcast_subnet->mask_ip ) ) { + DEBUG( 5, ( "wins_proxy_name_query_request_success: name %s is a WINS \ proxy name and is also on the same subnet (%s) as the requestor. \ -Not replying.\n", - nmb_namestr(&namerec->name), - orig_broadcast_subnet->subnet_name ) ); - return; - } - } - } - - /* Finally reply to the original name query. */ - reply_netbios_packet(original_packet, /* Packet to reply to. */ - 0, /* Result code. */ - NMB_QUERY, /* nmbd type code. */ - NMB_NAME_QUERY_OPCODE, /* opcode. */ - ttl, /* ttl. */ - rrec->rdata, /* data to send. */ - rrec->rdlength); /* data length. */ +Not replying.\n", nmb_namestr(&namerec->name), orig_broadcast_subnet->subnet_name ) ); + return; + } + } + } + + /* Finally reply to the original name query. */ + reply_netbios_packet(original_packet, /* Packet to reply to. */ + 0, /* Result code. */ + NMB_QUERY, /* nmbd type code. */ + NMB_NAME_QUERY_OPCODE, /* opcode. */ + ttl, /* ttl. */ + rrec->rdata, /* data to send. */ + rrec->rdlength); /* data length. */ } /**************************************************************************** @@ -126,7 +119,7 @@ static void wins_proxy_name_query_request_fail(struct subnet_record *subrec, struct response_record *rrec, struct nmb_name *question_name, int fail_code) { - DEBUG(4,("wins_proxy_name_query_request_fail: WINS server returned error code %d for lookup \ + DEBUG(4,("wins_proxy_name_query_request_fail: WINS server returned error code %d for lookup \ of name %s.\n", fail_code, nmb_namestr(question_name) )); } @@ -137,38 +130,35 @@ proxy query returns. static struct userdata_struct *wins_proxy_userdata_copy_fn(struct userdata_struct *userdata) { - struct packet_struct *p, *copy_of_p; - struct userdata_struct *new_userdata = - (struct userdata_struct *)malloc( userdata->userdata_len ); + struct packet_struct *p, *copy_of_p; + struct userdata_struct *new_userdata = (struct userdata_struct *)malloc( userdata->userdata_len ); - if(new_userdata == NULL) - return NULL; + if(new_userdata == NULL) + return NULL; - new_userdata->copy_fn = userdata->copy_fn; - new_userdata->free_fn = userdata->free_fn; - new_userdata->userdata_len = userdata->userdata_len; + new_userdata->copy_fn = userdata->copy_fn; + new_userdata->free_fn = userdata->free_fn; + new_userdata->userdata_len = userdata->userdata_len; - /* Copy the subnet_record pointer. */ - memcpy( new_userdata->data, userdata->data, sizeof(struct subnet_record *) ); + /* Copy the subnet_record pointer. */ + memcpy( new_userdata->data, userdata->data, sizeof(struct subnet_record *) ); - /* Extract the pointer to the packet struct */ - memcpy((char *)&p, &userdata->data[sizeof(struct subnet_record *)], - sizeof(struct packet_struct *) ); + /* Extract the pointer to the packet struct */ + memcpy((char *)&p, &userdata->data[sizeof(struct subnet_record *)], sizeof(struct packet_struct *) ); - /* Do a deep copy of the packet. */ - if((copy_of_p = copy_packet(p)) == NULL) - { - SAFE_FREE(new_userdata); - return NULL; - } + /* Do a deep copy of the packet. */ + if((copy_of_p = copy_packet(p)) == NULL) { + SAFE_FREE(new_userdata); + return NULL; + } - /* Lock the copy. */ - copy_of_p->locked = True; + /* Lock the copy. */ + copy_of_p->locked = True; - memcpy( &new_userdata->data[sizeof(struct subnet_record *)], (char *)©_of_p, - sizeof(struct packet_struct *) ); + memcpy( &new_userdata->data[sizeof(struct subnet_record *)], (char *)©_of_p, + sizeof(struct packet_struct *) ); - return new_userdata; + return new_userdata; } /**************************************************************************** @@ -178,18 +168,18 @@ proxy query returned. static void wins_proxy_userdata_free_fn(struct userdata_struct *userdata) { - struct packet_struct *p; + struct packet_struct *p; - /* Extract the pointer to the packet struct */ - memcpy((char *)&p, &userdata->data[sizeof(struct subnet_record *)], - sizeof(struct packet_struct *)); + /* Extract the pointer to the packet struct */ + memcpy((char *)&p, &userdata->data[sizeof(struct subnet_record *)], + sizeof(struct packet_struct *)); - /* Unlock the packet. */ - p->locked = False; + /* Unlock the packet. */ + p->locked = False; - free_packet(p); - ZERO_STRUCTP(userdata); - SAFE_FREE(userdata); + free_packet(p); + ZERO_STRUCTP(userdata); + SAFE_FREE(userdata); } /**************************************************************************** @@ -200,22 +190,24 @@ void make_wins_proxy_name_query_request( struct subnet_record *subrec, struct packet_struct *incoming_packet, struct nmb_name *question_name) { - long *ud[(sizeof(struct userdata_struct) + sizeof(struct subrec *) + - sizeof(struct packet_struct *))/sizeof(long *) + 1]; - struct userdata_struct *userdata = (struct userdata_struct *)ud; + long *ud[(sizeof(struct userdata_struct) + sizeof(struct subrec *) + + sizeof(struct packet_struct *))/sizeof(long *) + 1]; + struct userdata_struct *userdata = (struct userdata_struct *)ud; + nstring qname; - memset(ud, '\0', sizeof(ud)); + memset(ud, '\0', sizeof(ud)); - userdata->copy_fn = wins_proxy_userdata_copy_fn; - userdata->free_fn = wins_proxy_userdata_free_fn; - userdata->userdata_len = sizeof(ud); - memcpy( userdata->data, (char *)&subrec, sizeof(struct subnet_record *)); - memcpy( &userdata->data[sizeof(struct subnet_record *)], (char *)&incoming_packet, - sizeof(struct packet_struct *)); - - /* Now use the unicast subnet to query the name with the WINS server. */ - query_name( unicast_subnet, question_name->name, question_name->name_type, - wins_proxy_name_query_request_success, - wins_proxy_name_query_request_fail, - userdata); + userdata->copy_fn = wins_proxy_userdata_copy_fn; + userdata->free_fn = wins_proxy_userdata_free_fn; + userdata->userdata_len = sizeof(ud); + memcpy( userdata->data, (char *)&subrec, sizeof(struct subnet_record *)); + memcpy( &userdata->data[sizeof(struct subnet_record *)], (char *)&incoming_packet, + sizeof(struct packet_struct *)); + + /* Now use the unicast subnet to query the name with the WINS server. */ + pull_ascii_nstring(qname, question_name->name); + query_name( unicast_subnet, qname, question_name->name_type, + wins_proxy_name_query_request_success, + wins_proxy_name_query_request_fail, + userdata); } diff --git a/source3/nmbd/nmbd_winsserver.c b/source3/nmbd/nmbd_winsserver.c index eafff03b76..484588c662 100644 --- a/source3/nmbd/nmbd_winsserver.c +++ b/source3/nmbd/nmbd_winsserver.c @@ -2,7 +2,7 @@ Unix SMB/CIFS implementation. NBT netbios routines and daemon - version 2 - Copyright (C) Jeremy Allison 1994-1998 + Copyright (C) Jeremy Allison 1994-2003 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -26,8 +26,9 @@ #define WINS_VERSION 1 /**************************************************************************** -change the wins owner address in the record. + Change the wins owner address in the record. *****************************************************************************/ + static void update_wins_owner(struct name_record *namerec, struct in_addr wins_ip) { if (namerec==NULL) @@ -36,8 +37,9 @@ static void update_wins_owner(struct name_record *namerec, struct in_addr wins_i } /**************************************************************************** -create the wins flags based on the nb flags and the input value. + Create the wins flags based on the nb flags and the input value. *****************************************************************************/ + static void update_wins_flag(struct name_record *namerec, int flags) { if (namerec==NULL) @@ -74,12 +76,12 @@ static void update_wins_flag(struct name_record *namerec, int flags) DEBUG(8,("update_wins_flag: nbflags: 0x%x, ttl: 0x%d, flags: 0x%x, winsflags: 0x%x\n", namerec->data.nb_flags, (int)namerec->data.death_time, flags, namerec->data.wins_flags)); - } /**************************************************************************** -return the general ID value and increase it if requested + Return the general ID value and increase it if requested. *****************************************************************************/ + static void get_global_id_and_update(SMB_BIG_UINT *current_id, BOOL update) { /* @@ -98,8 +100,9 @@ static void get_global_id_and_update(SMB_BIG_UINT *current_id, BOOL update) } /**************************************************************************** -possibly call the WINS hook external program when a WINS change is made + Possibly call the WINS hook external program when a WINS change is made. *****************************************************************************/ + static void wins_hook(const char *operation, struct name_record *namerec, int ttl) { pstring command; @@ -120,7 +123,7 @@ static void wins_hook(const char *operation, struct name_record *namerec, int tt p += slprintf(p, sizeof(command)-1, "%s %s %s %02x %d", cmd, operation, - namerec->name.name, + nmb_namestr(&namerec->name), namerec->name.name_type, ttl); @@ -139,63 +142,58 @@ Determine if this packet should be allocated to the WINS server. BOOL packet_is_for_wins_server(struct packet_struct *packet) { - struct nmb_packet *nmb = &packet->packet.nmb; - - /* Only unicast packets go to a WINS server. */ - if((wins_server_subnet == NULL) || (nmb->header.nm_flags.bcast == True)) - { - DEBUG(10, ("packet_is_for_wins_server: failing WINS test #1.\n")); - return False; - } - - /* Check for node status requests. */ - if (nmb->question.question_type != QUESTION_TYPE_NB_QUERY) - return False; - - switch(nmb->header.opcode) - { - /* - * A WINS server issues WACKS, not receives them. - */ - case NMB_WACK_OPCODE: - DEBUG(10, ("packet_is_for_wins_server: failing WINS test #2 (WACK).\n")); - return False; - /* - * A WINS server only processes registration and - * release requests, not responses. - */ - case NMB_NAME_REG_OPCODE: - case NMB_NAME_MULTIHOMED_REG_OPCODE: - case NMB_NAME_REFRESH_OPCODE_8: /* ambiguity in rfc1002 about which is correct. */ - case NMB_NAME_REFRESH_OPCODE_9: /* WinNT uses 8 by default. */ - if(nmb->header.response) - { - DEBUG(10, ("packet_is_for_wins_server: failing WINS test #3 (response = 1).\n")); - return False; - } - break; - - case NMB_NAME_RELEASE_OPCODE: - if(nmb->header.response) - { - DEBUG(10, ("packet_is_for_wins_server: failing WINS test #4 (response = 1).\n")); - return False; - } - break; - - /* - * Only process unicast name queries with rd = 1. - */ - case NMB_NAME_QUERY_OPCODE: - if(!nmb->header.response && !nmb->header.nm_flags.recursion_desired) - { - DEBUG(10, ("packet_is_for_wins_server: failing WINS test #5 (response = 1).\n")); - return False; - } - break; - } - - return True; + struct nmb_packet *nmb = &packet->packet.nmb; + + /* Only unicast packets go to a WINS server. */ + if((wins_server_subnet == NULL) || (nmb->header.nm_flags.bcast == True)) { + DEBUG(10, ("packet_is_for_wins_server: failing WINS test #1.\n")); + return False; + } + + /* Check for node status requests. */ + if (nmb->question.question_type != QUESTION_TYPE_NB_QUERY) + return False; + + switch(nmb->header.opcode) { + /* + * A WINS server issues WACKS, not receives them. + */ + case NMB_WACK_OPCODE: + DEBUG(10, ("packet_is_for_wins_server: failing WINS test #2 (WACK).\n")); + return False; + /* + * A WINS server only processes registration and + * release requests, not responses. + */ + case NMB_NAME_REG_OPCODE: + case NMB_NAME_MULTIHOMED_REG_OPCODE: + case NMB_NAME_REFRESH_OPCODE_8: /* ambiguity in rfc1002 about which is correct. */ + case NMB_NAME_REFRESH_OPCODE_9: /* WinNT uses 8 by default. */ + if(nmb->header.response) { + DEBUG(10, ("packet_is_for_wins_server: failing WINS test #3 (response = 1).\n")); + return False; + } + break; + + case NMB_NAME_RELEASE_OPCODE: + if(nmb->header.response) { + DEBUG(10, ("packet_is_for_wins_server: failing WINS test #4 (response = 1).\n")); + return False; + } + break; + + /* + * Only process unicast name queries with rd = 1. + */ + case NMB_NAME_QUERY_OPCODE: + if(!nmb->header.response && !nmb->header.nm_flags.recursion_desired) { + DEBUG(10, ("packet_is_for_wins_server: failing WINS test #5 (response = 1).\n")); + return False; + } + break; + } + + return True; } /**************************************************************************** @@ -204,15 +202,15 @@ Utility function to decide what ttl to give a register/refresh request. static int get_ttl_from_packet(struct nmb_packet *nmb) { - int ttl = nmb->additional->ttl; + int ttl = nmb->additional->ttl; - if(ttl < lp_min_wins_ttl() ) - ttl = lp_min_wins_ttl(); + if(ttl < lp_min_wins_ttl() ) + ttl = lp_min_wins_ttl(); - if(ttl > lp_max_wins_ttl() ) - ttl = lp_max_wins_ttl(); + if(ttl > lp_max_wins_ttl() ) + ttl = lp_max_wins_ttl(); - return ttl; + return ttl; } /**************************************************************************** @@ -221,177 +219,160 @@ Load or create the WINS database. BOOL initialise_wins(void) { - time_t time_now = time(NULL); - XFILE *fp; - pstring line; - - if(!lp_we_are_a_wins_server()) - return True; - - add_samba_names_to_subnet(wins_server_subnet); - - if((fp = x_fopen(lock_path(WINS_LIST),O_RDONLY,0)) == NULL) - { - DEBUG(2,("initialise_wins: Can't open wins database file %s. Error was %s\n", - WINS_LIST, strerror(errno) )); - return True; - } - - while (!x_feof(fp)) - { - pstring name_str, ip_str, ttl_str, nb_flags_str; - unsigned int num_ips; - pstring name; - struct in_addr *ip_list; - int type = 0; - int nb_flags; - int ttl; - const char *ptr; - char *p; - BOOL got_token; - BOOL was_ip; - int i; - unsigned hash; - int version; - - /* Read a line from the wins.dat file. Strips whitespace - from the beginning and end of the line. - */ - if (!fgets_slash(line,sizeof(pstring),fp)) - continue; + time_t time_now = time(NULL); + XFILE *fp; + pstring line; + + if(!lp_we_are_a_wins_server()) + return True; + + add_samba_names_to_subnet(wins_server_subnet); + + if((fp = x_fopen(lock_path(WINS_LIST),O_RDONLY,0)) == NULL) { + DEBUG(2,("initialise_wins: Can't open wins database file %s. Error was %s\n", + WINS_LIST, strerror(errno) )); + return True; + } + + while (!x_feof(fp)) { + pstring name_str, ip_str, ttl_str, nb_flags_str; + unsigned int num_ips; + pstring name; + struct in_addr *ip_list; + int type = 0; + int nb_flags; + int ttl; + const char *ptr; + char *p; + BOOL got_token; + BOOL was_ip; + int i; + unsigned int hash; + int version; + + /* Read a line from the wins.dat file. Strips whitespace + from the beginning and end of the line. */ + if (!fgets_slash(line,sizeof(pstring),fp)) + continue; - if (*line == '#') - continue; - - if (strncmp(line,"VERSION ", 8) == 0) { - if (sscanf(line,"VERSION %d %u", &version, &hash) != 2 || - version != WINS_VERSION) { - DEBUG(0,("Discarding invalid wins.dat file [%s]\n",line)); - x_fclose(fp); - return True; - } - continue; - } - - ptr = line; - - /* - * Now we handle multiple IP addresses per name we need - * to iterate over the line twice. The first time to - * determine how many IP addresses there are, the second - * time to actually parse them into the ip_list array. - */ - - if (!next_token(&ptr,name_str,NULL,sizeof(name_str))) - { - DEBUG(0,("initialise_wins: Failed to parse name when parsing line %s\n", line )); - continue; - } - - if (!next_token(&ptr,ttl_str,NULL,sizeof(ttl_str))) - { - DEBUG(0,("initialise_wins: Failed to parse time to live when parsing line %s\n", line )); - continue; - } - - /* - * Determine the number of IP addresses per line. - */ - num_ips = 0; - do - { - got_token = next_token(&ptr,ip_str,NULL,sizeof(ip_str)); - was_ip = False; - - if(got_token && strchr(ip_str, '.')) - { - num_ips++; - was_ip = True; - } - } while( got_token && was_ip); - - if(num_ips == 0) - { - DEBUG(0,("initialise_wins: Missing IP address when parsing line %s\n", line )); - continue; - } - - if(!got_token) - { - DEBUG(0,("initialise_wins: Missing nb_flags when parsing line %s\n", line )); - continue; - } - - /* Allocate the space for the ip_list. */ - if((ip_list = (struct in_addr *)malloc( num_ips * sizeof(struct in_addr))) == NULL) - { - DEBUG(0,("initialise_wins: Malloc fail !\n")); - return False; - } + if (*line == '#') + continue; + + if (strncmp(line,"VERSION ", 8) == 0) { + if (sscanf(line,"VERSION %d %u", &version, &hash) != 2 || + version != WINS_VERSION) { + DEBUG(0,("Discarding invalid wins.dat file [%s]\n",line)); + x_fclose(fp); + return True; + } + continue; + } + + ptr = line; + + /* + * Now we handle multiple IP addresses per name we need + * to iterate over the line twice. The first time to + * determine how many IP addresses there are, the second + * time to actually parse them into the ip_list array. + */ + + if (!next_token(&ptr,name_str,NULL,sizeof(name_str))) { + DEBUG(0,("initialise_wins: Failed to parse name when parsing line %s\n", line )); + continue; + } + + if (!next_token(&ptr,ttl_str,NULL,sizeof(ttl_str))) { + DEBUG(0,("initialise_wins: Failed to parse time to live when parsing line %s\n", line )); + continue; + } + + /* + * Determine the number of IP addresses per line. + */ + num_ips = 0; + do { + got_token = next_token(&ptr,ip_str,NULL,sizeof(ip_str)); + was_ip = False; + + if(got_token && strchr(ip_str, '.')) { + num_ips++; + was_ip = True; + } + } while( got_token && was_ip); + + if(num_ips == 0) { + DEBUG(0,("initialise_wins: Missing IP address when parsing line %s\n", line )); + continue; + } + + if(!got_token) { + DEBUG(0,("initialise_wins: Missing nb_flags when parsing line %s\n", line )); + continue; + } + + /* Allocate the space for the ip_list. */ + if((ip_list = (struct in_addr *)malloc( num_ips * sizeof(struct in_addr))) == NULL) { + DEBUG(0,("initialise_wins: Malloc fail !\n")); + return False; + } - /* Reset and re-parse the line. */ - ptr = line; - next_token(&ptr,name_str,NULL,sizeof(name_str)); - next_token(&ptr,ttl_str,NULL,sizeof(ttl_str)); - for(i = 0; i < num_ips; i++) - { - next_token(&ptr, ip_str, NULL, sizeof(ip_str)); - ip_list[i] = *interpret_addr2(ip_str); - } - next_token(&ptr,nb_flags_str,NULL, sizeof(nb_flags_str)); - - /* - * Deal with SELF or REGISTER name encoding. Default is REGISTER - * for compatibility with old nmbds. - */ - - if(nb_flags_str[strlen(nb_flags_str)-1] == 'S') - { - DEBUG(5,("initialise_wins: Ignoring SELF name %s\n", line)); - SAFE_FREE(ip_list); - continue; - } + /* Reset and re-parse the line. */ + ptr = line; + next_token(&ptr,name_str,NULL,sizeof(name_str)); + next_token(&ptr,ttl_str,NULL,sizeof(ttl_str)); + for(i = 0; i < num_ips; i++) { + next_token(&ptr, ip_str, NULL, sizeof(ip_str)); + ip_list[i] = *interpret_addr2(ip_str); + } + next_token(&ptr,nb_flags_str,NULL, sizeof(nb_flags_str)); + + /* + * Deal with SELF or REGISTER name encoding. Default is REGISTER + * for compatibility with old nmbds. + */ + + if(nb_flags_str[strlen(nb_flags_str)-1] == 'S') { + DEBUG(5,("initialise_wins: Ignoring SELF name %s\n", line)); + SAFE_FREE(ip_list); + continue; + } - if(nb_flags_str[strlen(nb_flags_str)-1] == 'R') - nb_flags_str[strlen(nb_flags_str)-1] = '\0'; + if(nb_flags_str[strlen(nb_flags_str)-1] == 'R') + nb_flags_str[strlen(nb_flags_str)-1] = '\0'; - /* Netbios name. # divides the name from the type (hex): netbios#xx */ - pstrcpy(name,name_str); + /* Netbios name. # divides the name from the type (hex): netbios#xx */ + pstrcpy(name,name_str); - if((p = strchr(name,'#')) != NULL) - { - *p = 0; - sscanf(p+1,"%x",&type); - } + if((p = strchr(name,'#')) != NULL) { + *p = 0; + sscanf(p+1,"%x",&type); + } - /* Decode the netbios flags (hex) and the time-to-live (in seconds). */ - sscanf(nb_flags_str,"%x",&nb_flags); - sscanf(ttl_str,"%d",&ttl); - - /* add all entries that have 60 seconds or more to live */ - if ((ttl - 60) > time_now || ttl == PERMANENT_TTL) - { - if(ttl != PERMANENT_TTL) - ttl -= time_now; + /* Decode the netbios flags (hex) and the time-to-live (in seconds). */ + sscanf(nb_flags_str,"%x",&nb_flags); + sscanf(ttl_str,"%d",&ttl); + + /* add all entries that have 60 seconds or more to live */ + if ((ttl - 60) > time_now || ttl == PERMANENT_TTL) { + if(ttl != PERMANENT_TTL) + ttl -= time_now; - DEBUG( 4, ("initialise_wins: add name: %s#%02x ttl = %d first IP %s flags = %2x\n", - name, type, ttl, inet_ntoa(ip_list[0]), nb_flags)); - - (void)add_name_to_subnet( wins_server_subnet, name, type, nb_flags, - ttl, REGISTER_NAME, num_ips, ip_list ); - - } - else - { - DEBUG(4, ("initialise_wins: not adding name (ttl problem) %s#%02x ttl = %d first IP %s flags = %2x\n", - name, type, ttl, inet_ntoa(ip_list[0]), nb_flags)); - } + DEBUG( 4, ("initialise_wins: add name: %s#%02x ttl = %d first IP %s flags = %2x\n", + name, type, ttl, inet_ntoa(ip_list[0]), nb_flags)); + + (void)add_name_to_subnet( wins_server_subnet, name, type, nb_flags, + ttl, REGISTER_NAME, num_ips, ip_list ); + } else { + DEBUG(4, ("initialise_wins: not adding name (ttl problem) %s#%02x ttl = %d first IP %s flags = %2x\n", + name, type, ttl, inet_ntoa(ip_list[0]), nb_flags)); + } - SAFE_FREE(ip_list); - } + SAFE_FREE(ip_list); + } - x_fclose(fp); - return True; + x_fclose(fp); + return True; } /**************************************************************************** @@ -400,30 +381,33 @@ Send a WINS WACK (Wait ACKnowledgement) response. static void send_wins_wack_response(int ttl, struct packet_struct *p) { - struct nmb_packet *nmb = &p->packet.nmb; - unsigned char rdata[2]; - - rdata[0] = rdata[1] = 0; - - /* Taken from nmblib.c - we need to send back almost - identical bytes from the requesting packet header. */ - - rdata[0] = (nmb->header.opcode & 0xF) << 3; - if (nmb->header.nm_flags.authoritative && - nmb->header.response) rdata[0] |= 0x4; - if (nmb->header.nm_flags.trunc) rdata[0] |= 0x2; - if (nmb->header.nm_flags.recursion_desired) rdata[0] |= 0x1; - if (nmb->header.nm_flags.recursion_available && - nmb->header.response) rdata[1] |= 0x80; - if (nmb->header.nm_flags.bcast) rdata[1] |= 0x10; - - reply_netbios_packet(p, /* Packet to reply to. */ - 0, /* Result code. */ - NMB_WAIT_ACK, /* nmbd type code. */ - NMB_WACK_OPCODE, /* opcode. */ - ttl, /* ttl. */ - (char *)rdata, /* data to send. */ - 2); /* data length. */ + struct nmb_packet *nmb = &p->packet.nmb; + unsigned char rdata[2]; + + rdata[0] = rdata[1] = 0; + + /* Taken from nmblib.c - we need to send back almost + identical bytes from the requesting packet header. */ + + rdata[0] = (nmb->header.opcode & 0xF) << 3; + if (nmb->header.nm_flags.authoritative && nmb->header.response) + rdata[0] |= 0x4; + if (nmb->header.nm_flags.trunc) + rdata[0] |= 0x2; + if (nmb->header.nm_flags.recursion_desired) + rdata[0] |= 0x1; + if (nmb->header.nm_flags.recursion_available && nmb->header.response) + rdata[1] |= 0x80; + if (nmb->header.nm_flags.bcast) + rdata[1] |= 0x10; + + reply_netbios_packet(p, /* Packet to reply to. */ + 0, /* Result code. */ + NMB_WAIT_ACK, /* nmbd type code. */ + NMB_WACK_OPCODE, /* opcode. */ + ttl, /* ttl. */ + (char *)rdata, /* data to send. */ + 2); /* data length. */ } /**************************************************************************** @@ -432,18 +416,18 @@ Send a WINS name registration response. static void send_wins_name_registration_response(int rcode, int ttl, struct packet_struct *p) { - struct nmb_packet *nmb = &p->packet.nmb; - char rdata[6]; - - memcpy(&rdata[0], &nmb->additional->rdata[0], 6); - - reply_netbios_packet(p, /* Packet to reply to. */ - rcode, /* Result code. */ - WINS_REG, /* nmbd type code. */ - NMB_NAME_REG_OPCODE, /* opcode. */ - ttl, /* ttl. */ - rdata, /* data to send. */ - 6); /* data length. */ + struct nmb_packet *nmb = &p->packet.nmb; + char rdata[6]; + + memcpy(&rdata[0], &nmb->additional->rdata[0], 6); + + reply_netbios_packet(p, /* Packet to reply to. */ + rcode, /* Result code. */ + WINS_REG, /* nmbd type code. */ + NMB_NAME_REG_OPCODE, /* opcode. */ + ttl, /* ttl. */ + rdata, /* data to send. */ + 6); /* data length. */ } /*********************************************************************** @@ -453,139 +437,128 @@ static void send_wins_name_registration_response(int rcode, int ttl, struct pack void wins_process_name_refresh_request(struct subnet_record *subrec, struct packet_struct *p) { - struct nmb_packet *nmb = &p->packet.nmb; - struct nmb_name *question = &nmb->question.question_name; - BOOL bcast = nmb->header.nm_flags.bcast; - uint16 nb_flags = get_nb_flags(nmb->additional->rdata); - BOOL group = (nb_flags & NB_GROUP) ? True : False; - struct name_record *namerec = NULL; - int ttl = get_ttl_from_packet(nmb); - struct in_addr from_ip; - struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0"); - - putip((char *)&from_ip,&nmb->additional->rdata[2]); - - if(bcast) - { - /* - * We should only get unicast name refresh packets here. - * Anyone trying to refresh broadcast should not be going to a WINS - * server. Log an error here. - */ - - DEBUG(0,("wins_process_name_refresh_request: broadcast name refresh request \ + struct nmb_packet *nmb = &p->packet.nmb; + struct nmb_name *question = &nmb->question.question_name; + BOOL bcast = nmb->header.nm_flags.bcast; + uint16 nb_flags = get_nb_flags(nmb->additional->rdata); + BOOL group = (nb_flags & NB_GROUP) ? True : False; + struct name_record *namerec = NULL; + int ttl = get_ttl_from_packet(nmb); + struct in_addr from_ip; + struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0"); + + putip((char *)&from_ip,&nmb->additional->rdata[2]); + + if(bcast) { + /* + * We should only get unicast name refresh packets here. + * Anyone trying to refresh broadcast should not be going to a WINS + * server. Log an error here. + */ + + DEBUG(0,("wins_process_name_refresh_request: broadcast name refresh request \ received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n", - nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name)); - return; - } + nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name)); + return; + } - DEBUG(3,("wins_process_name_refresh_request: Name refresh for name %s \ + DEBUG(3,("wins_process_name_refresh_request: Name refresh for name %s \ IP %s\n", nmb_namestr(question), inet_ntoa(from_ip) )); - /* - * See if the name already exists. - */ + /* + * See if the name already exists. + */ - namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME); + namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME); - /* - * If this is a refresh request and the name doesn't exist then - * treat it like a registration request. This allows us to recover - * from errors (tridge) - */ + /* + * If this is a refresh request and the name doesn't exist then + * treat it like a registration request. This allows us to recover + * from errors (tridge) + */ - if(namerec == NULL) - { - DEBUG(3,("wins_process_name_refresh_request: Name refresh for name %s and \ + if(namerec == NULL) { + DEBUG(3,("wins_process_name_refresh_request: Name refresh for name %s and \ the name does not exist. Treating as registration.\n", nmb_namestr(question) )); - wins_process_name_registration_request(subrec,p); - return; - } - - /* - * if the name is present but not active, - * simply remove it and treat the request - * as a registration - */ - if (namerec != NULL && !WINS_STATE_ACTIVE(namerec)) - { - DEBUG(5,("wins_process_name_refresh_request: Name (%s) in WINS was \ + wins_process_name_registration_request(subrec,p); + return; + } + + /* + * if the name is present but not active, + * simply remove it and treat the request + * as a registration + */ + if (namerec != NULL && !WINS_STATE_ACTIVE(namerec)) { + DEBUG(5,("wins_process_name_refresh_request: Name (%s) in WINS was \ not active - removing it.\n", nmb_namestr(question) )); - remove_name_from_namelist( subrec, namerec ); - namerec = NULL; - wins_process_name_registration_request(subrec,p); - return; - } - - /* - * Check that the group bits for the refreshing name and the - * name in our database match. - */ - - if((namerec != NULL) && ((group && !NAME_GROUP(namerec)) || (!group && NAME_GROUP(namerec))) ) - { - DEBUG(3,("wins_process_name_refresh_request: Name %s group bit = %s \ + remove_name_from_namelist( subrec, namerec ); + namerec = NULL; + wins_process_name_registration_request(subrec,p); + return; + } + + /* + * Check that the group bits for the refreshing name and the + * name in our database match. + */ + + if((namerec != NULL) && ((group && !NAME_GROUP(namerec)) || (!group && NAME_GROUP(namerec))) ) { + DEBUG(3,("wins_process_name_refresh_request: Name %s group bit = %s \ does not match group bit in WINS for this name.\n", nmb_namestr(question), group ? "True" : "False" )); - send_wins_name_registration_response(RFS_ERR, 0, p); - return; - } - - /* - * For a unique name check that the person refreshing the name is one of the registered IP - * addresses. If not - fail the refresh. Do the same for group names with a type of 0x1c. - * Just return success for unique 0x1d refreshes. For normal group names update the ttl - * and return success. - */ - - if((!group || (group && (question->name_type == 0x1c))) && find_ip_in_name_record(namerec, from_ip )) - { - /* - * Update the ttl. - */ - update_name_ttl(namerec, ttl); - - /* - * if the record is a replica: - * we take ownership and update the version ID. - */ - if (!ip_equal(namerec->data.wins_ip, our_fake_ip)) { - update_wins_owner(namerec, our_fake_ip); - get_global_id_and_update(&namerec->data.id, True); - } - - send_wins_name_registration_response(0, ttl, p); - wins_hook("refresh", namerec, ttl); - return; - } - else if(group) - { - /* - * Normal groups are all registered with an IP address of 255.255.255.255 - * so we can't search for the IP address. - */ - update_name_ttl(namerec, ttl); - send_wins_name_registration_response(0, ttl, p); - return; - } - else if(!group && (question->name_type == 0x1d)) - { - /* - * Special name type - just pretend the refresh succeeded. - */ - send_wins_name_registration_response(0, ttl, p); - return; - } - else - { - /* - * Fail the refresh. - */ - - DEBUG(3,("wins_process_name_refresh_request: Name refresh for name %s with IP %s and \ + send_wins_name_registration_response(RFS_ERR, 0, p); + return; + } + + /* + * For a unique name check that the person refreshing the name is one of the registered IP + * addresses. If not - fail the refresh. Do the same for group names with a type of 0x1c. + * Just return success for unique 0x1d refreshes. For normal group names update the ttl + * and return success. + */ + + if((!group || (group && (question->name_type == 0x1c))) && find_ip_in_name_record(namerec, from_ip )) { + /* + * Update the ttl. + */ + update_name_ttl(namerec, ttl); + + /* + * if the record is a replica: + * we take ownership and update the version ID. + */ + if (!ip_equal(namerec->data.wins_ip, our_fake_ip)) { + update_wins_owner(namerec, our_fake_ip); + get_global_id_and_update(&namerec->data.id, True); + } + + send_wins_name_registration_response(0, ttl, p); + wins_hook("refresh", namerec, ttl); + return; + } else if(group) { + /* + * Normal groups are all registered with an IP address of 255.255.255.255 + * so we can't search for the IP address. + */ + update_name_ttl(namerec, ttl); + send_wins_name_registration_response(0, ttl, p); + return; + } else if(!group && (question->name_type == 0x1d)) { + /* + * Special name type - just pretend the refresh succeeded. + */ + send_wins_name_registration_response(0, ttl, p); + return; + } else { + /* + * Fail the refresh. + */ + + DEBUG(3,("wins_process_name_refresh_request: Name refresh for name %s with IP %s and \ is IP is not known to the name.\n", nmb_namestr(question), inet_ntoa(from_ip) )); - send_wins_name_registration_response(RFS_ERR, 0, p); - return; - } + send_wins_name_registration_response(RFS_ERR, 0, p); + return; + } } /*********************************************************************** @@ -604,17 +577,17 @@ static void wins_register_query_success(struct subnet_record *subrec, struct in_addr ip, struct res_rec *answers) { - struct packet_struct *orig_reg_packet; + struct packet_struct *orig_reg_packet; - memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *)); + memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *)); - DEBUG(3,("wins_register_query_success: Original client at IP %s still wants the \ + DEBUG(3,("wins_register_query_success: Original client at IP %s still wants the \ name %s. Rejecting registration request.\n", inet_ntoa(ip), nmb_namestr(question_name) )); - send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet); + send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet); - orig_reg_packet->locked = False; - free_packet(orig_reg_packet); + orig_reg_packet->locked = False; + free_packet(orig_reg_packet); } /*********************************************************************** @@ -632,40 +605,37 @@ static void wins_register_query_fail(struct subnet_record *subrec, struct nmb_name *question_name, int rcode) { - struct userdata_struct *userdata = rrec->userdata; - struct packet_struct *orig_reg_packet; - struct name_record *namerec = NULL; - - memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *)); - - /* - * We want to just add the name, as we now know the original owner - * didn't want it. But we can't just do that as an arbitary - * amount of time may have taken place between the name query - * request and this timeout/error response. So we check that - * the name still exists and is in the same state - if so - * we remove it and call wins_process_name_registration_request() - * as we know it will do the right thing now. - */ - - namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME); - - if( (namerec != NULL) - && (namerec->data.source == REGISTER_NAME) - && ip_equal(rrec->packet->ip, *namerec->data.ip) ) - { - remove_name_from_namelist( subrec, namerec); - namerec = NULL; - } - - if(namerec == NULL) - wins_process_name_registration_request(subrec, orig_reg_packet); - else - DEBUG(2,("wins_register_query_fail: The state of the WINS database changed between \ + struct userdata_struct *userdata = rrec->userdata; + struct packet_struct *orig_reg_packet; + struct name_record *namerec = NULL; + + memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *)); + + /* + * We want to just add the name, as we now know the original owner + * didn't want it. But we can't just do that as an arbitary + * amount of time may have taken place between the name query + * request and this timeout/error response. So we check that + * the name still exists and is in the same state - if so + * we remove it and call wins_process_name_registration_request() + * as we know it will do the right thing now. + */ + + namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME); + + if( (namerec != NULL) && (namerec->data.source == REGISTER_NAME) && ip_equal(rrec->packet->ip, *namerec->data.ip) ) { + remove_name_from_namelist( subrec, namerec); + namerec = NULL; + } + + if(namerec == NULL) + wins_process_name_registration_request(subrec, orig_reg_packet); + else + DEBUG(2,("wins_register_query_fail: The state of the WINS database changed between \ querying for name %s in order to replace it and this reply.\n", nmb_namestr(question_name) )); - orig_reg_packet->locked = False; - free_packet(orig_reg_packet); + orig_reg_packet->locked = False; + free_packet(orig_reg_packet); } /*********************************************************************** @@ -728,279 +698,271 @@ querying for name %s in order to replace it and this reply.\n", nmb_namestr(ques void wins_process_name_registration_request(struct subnet_record *subrec, struct packet_struct *p) { - struct nmb_packet *nmb = &p->packet.nmb; - struct nmb_name *question = &nmb->question.question_name; - BOOL bcast = nmb->header.nm_flags.bcast; - uint16 nb_flags = get_nb_flags(nmb->additional->rdata); - int ttl = get_ttl_from_packet(nmb); - struct name_record *namerec = NULL; - struct in_addr from_ip; - BOOL registering_group_name = (nb_flags & NB_GROUP) ? True : False; - struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0"); - - putip((char *)&from_ip,&nmb->additional->rdata[2]); - - if(bcast) - { - /* - * We should only get unicast name registration packets here. - * Anyone trying to register broadcast should not be going to a WINS - * server. Log an error here. - */ - - DEBUG(0,("wins_process_name_registration_request: broadcast name registration request \ + nstring name; + struct nmb_packet *nmb = &p->packet.nmb; + struct nmb_name *question = &nmb->question.question_name; + BOOL bcast = nmb->header.nm_flags.bcast; + uint16 nb_flags = get_nb_flags(nmb->additional->rdata); + int ttl = get_ttl_from_packet(nmb); + struct name_record *namerec = NULL; + struct in_addr from_ip; + BOOL registering_group_name = (nb_flags & NB_GROUP) ? True : False; + struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0"); + + putip((char *)&from_ip,&nmb->additional->rdata[2]); + + if(bcast) { + /* + * We should only get unicast name registration packets here. + * Anyone trying to register broadcast should not be going to a WINS + * server. Log an error here. + */ + + DEBUG(0,("wins_process_name_registration_request: broadcast name registration request \ received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n", - nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name)); - return; - } + nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name)); + return; + } - DEBUG(3,("wins_process_name_registration_request: %s name registration for name %s \ + DEBUG(3,("wins_process_name_registration_request: %s name registration for name %s \ IP %s\n", registering_group_name ? "Group" : "Unique", nmb_namestr(question), inet_ntoa(from_ip) )); - /* - * See if the name already exists. - */ + /* + * See if the name already exists. + */ - namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME); + namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME); - /* - * if the record exists but NOT in active state, - * consider it dead. - */ - if ( (namerec != NULL) && !WINS_STATE_ACTIVE(namerec)) - { - DEBUG(5,("wins_process_name_registration_request: Name (%s) in WINS was \ + /* + * if the record exists but NOT in active state, + * consider it dead. + */ + if ( (namerec != NULL) && !WINS_STATE_ACTIVE(namerec)) { + DEBUG(5,("wins_process_name_registration_request: Name (%s) in WINS was \ not active - removing it.\n", nmb_namestr(question) )); - remove_name_from_namelist( subrec, namerec ); - namerec = NULL; - } - - /* - * Deal with the case where the name found was a dns entry. - * Remove it as we now have a NetBIOS client registering the - * name. - */ - - if( (namerec != NULL) - && ( (namerec->data.source == DNS_NAME) - || (namerec->data.source == DNSFAIL_NAME) ) ) - { - DEBUG(5,("wins_process_name_registration_request: Name (%s) in WINS was \ + remove_name_from_namelist( subrec, namerec ); + namerec = NULL; + } + + /* + * Deal with the case where the name found was a dns entry. + * Remove it as we now have a NetBIOS client registering the + * name. + */ + + if( (namerec != NULL) && ( (namerec->data.source == DNS_NAME) || (namerec->data.source == DNSFAIL_NAME) ) ) { + DEBUG(5,("wins_process_name_registration_request: Name (%s) in WINS was \ a dns lookup - removing it.\n", nmb_namestr(question) )); - remove_name_from_namelist( subrec, namerec ); - namerec = NULL; - } - - /* - * Reject if the name exists and is not a REGISTER_NAME. - * (ie. Don't allow any static names to be overwritten. - */ - - if((namerec != NULL) && (namerec->data.source != REGISTER_NAME)) - { - DEBUG( 3, ( "wins_process_name_registration_request: Attempt \ + remove_name_from_namelist( subrec, namerec ); + namerec = NULL; + } + + /* + * Reject if the name exists and is not a REGISTER_NAME. + * (ie. Don't allow any static names to be overwritten. + */ + + if((namerec != NULL) && (namerec->data.source != REGISTER_NAME)) { + DEBUG( 3, ( "wins_process_name_registration_request: Attempt \ to register name %s. Name already exists in WINS with source type %d.\n", - nmb_namestr(question), namerec->data.source )); - send_wins_name_registration_response(RFS_ERR, 0, p); - return; - } - - /* - * Special policy decisions based on MS documentation. - * 1). All group names (except names ending in 0x1c) are added as 255.255.255.255. - * 2). All unique names ending in 0x1d are ignored, although a positive response is sent. - */ - - /* - * A group name is always added as the local broadcast address, except - * for group names ending in 0x1c. - * Group names with type 0x1c are registered with individual IP addresses. - */ - - if(registering_group_name && (question->name_type != 0x1c)) - from_ip = *interpret_addr2("255.255.255.255"); - - /* - * Ignore all attempts to register a unique 0x1d name, although return success. - */ - - if(!registering_group_name && (question->name_type == 0x1d)) - { - DEBUG(3,("wins_process_name_registration_request: Ignoring request \ + nmb_namestr(question), namerec->data.source )); + send_wins_name_registration_response(RFS_ERR, 0, p); + return; + } + + /* + * Special policy decisions based on MS documentation. + * 1). All group names (except names ending in 0x1c) are added as 255.255.255.255. + * 2). All unique names ending in 0x1d are ignored, although a positive response is sent. + */ + + /* + * A group name is always added as the local broadcast address, except + * for group names ending in 0x1c. + * Group names with type 0x1c are registered with individual IP addresses. + */ + + if(registering_group_name && (question->name_type != 0x1c)) + from_ip = *interpret_addr2("255.255.255.255"); + + /* + * Ignore all attempts to register a unique 0x1d name, although return success. + */ + + if(!registering_group_name && (question->name_type == 0x1d)) { + DEBUG(3,("wins_process_name_registration_request: Ignoring request \ to register name %s from IP %s.\n", nmb_namestr(question), inet_ntoa(p->ip) )); - send_wins_name_registration_response(0, ttl, p); - return; - } - - /* - * Next two cases are the 'if statement' mentioned above. - */ - - if((namerec != NULL) && NAME_GROUP(namerec)) - { - if(registering_group_name) - { - /* - * If we are adding a group name, the name exists and is also a group entry just add this - * IP address to it and update the ttl. - */ - - DEBUG(3,("wins_process_name_registration_request: Adding IP %s to group name %s.\n", - inet_ntoa(from_ip), nmb_namestr(question) )); - /* - * Check the ip address is not already in the group. - */ - if(!find_ip_in_name_record(namerec, from_ip)) { - add_ip_to_name_record(namerec, from_ip); - /* we need to update the record for replication */ - get_global_id_and_update(&namerec->data.id, True); + send_wins_name_registration_response(0, ttl, p); + return; + } /* - * if the record is a replica, we must change - * the wins owner to us to make the replication updates - * it on the other wins servers. - * And when the partner will receive this record, - * it will update its own record. + * Next two cases are the 'if statement' mentioned above. */ - update_wins_owner(namerec, our_fake_ip); + if((namerec != NULL) && NAME_GROUP(namerec)) { + if(registering_group_name) { + /* + * If we are adding a group name, the name exists and is also a group entry just add this + * IP address to it and update the ttl. + */ + + DEBUG(3,("wins_process_name_registration_request: Adding IP %s to group name %s.\n", + inet_ntoa(from_ip), nmb_namestr(question) )); + + /* + * Check the ip address is not already in the group. + */ + + if(!find_ip_in_name_record(namerec, from_ip)) { + add_ip_to_name_record(namerec, from_ip); + /* we need to update the record for replication */ + get_global_id_and_update(&namerec->data.id, True); + + /* + * if the record is a replica, we must change + * the wins owner to us to make the replication updates + * it on the other wins servers. + * And when the partner will receive this record, + * it will update its own record. + */ + + update_wins_owner(namerec, our_fake_ip); + } + update_name_ttl(namerec, ttl); + send_wins_name_registration_response(0, ttl, p); + return; + } else { - } - update_name_ttl(namerec, ttl); - send_wins_name_registration_response(0, ttl, p); - return; - } - else - { - /* - * If we are adding a unique name, the name exists in the WINS db - * and is a group name then reject the registration. - * - * explanation: groups have a higher priority than unique names. - */ - - DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \ + /* + * If we are adding a unique name, the name exists in the WINS db + * and is a group name then reject the registration. + * + * explanation: groups have a higher priority than unique names. + */ + + DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \ already exists in WINS as a GROUP name.\n", nmb_namestr(question) )); - send_wins_name_registration_response(RFS_ERR, 0, p); - return; - } - } - - /* - * From here on down we know that if the name exists in the WINS db it is - * a unique name, not a group name. - */ - - /* - * If the name exists and is one of our names then check the - * registering IP address. If it's not one of ours then automatically - * reject without doing the query - we know we will reject it. - */ - - if((namerec != NULL) && (is_myname(namerec->name.name)) ) - { - if(!ismyip(from_ip)) - { - DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \ + send_wins_name_registration_response(RFS_ERR, 0, p); + return; + } + } + + /* + * From here on down we know that if the name exists in the WINS db it is + * a unique name, not a group name. + */ + + /* + * If the name exists and is one of our names then check the + * registering IP address. If it's not one of ours then automatically + * reject without doing the query - we know we will reject it. + */ + + if ( namerec != NULL ) + pull_ascii_nstring(name, namerec->name.name); + + if( is_myname(name) ) { + if(!ismyip(from_ip)) { + DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \ is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question) )); - send_wins_name_registration_response(RFS_ERR, 0, p); - return; - } - else - { - /* - * It's one of our names and one of our IP's - update the ttl. - */ - update_name_ttl(namerec, ttl); - send_wins_name_registration_response(0, ttl, p); - wins_hook("refresh", namerec, ttl); - return; - } - } - - /* - * If the name exists and it is a unique registration and the registering IP - * is the same as the (single) already registered IP then just update the ttl. - * - * But not if the record is an active replica. IF it's a replica, it means it can be - * the same client which has moved and not yet expired. So we don't update - * the ttl in this case and go beyond to do a WACK and query the old client - */ - - if( !registering_group_name - && (namerec != NULL) - && (namerec->data.num_ips == 1) - && ip_equal( namerec->data.ip[0], from_ip ) - && ip_equal(namerec->data.wins_ip, our_fake_ip) ) - { - update_name_ttl( namerec, ttl ); - send_wins_name_registration_response( 0, ttl, p ); - wins_hook("refresh", namerec, ttl); - return; - } - - /* - * Finally if the name exists do a query to the registering machine - * to see if they still claim to have the name. - */ - - if( namerec != NULL ) - { - long *ud[(sizeof(struct userdata_struct) + sizeof(struct packet_struct *))/sizeof(long *) + 1]; - struct userdata_struct *userdata = (struct userdata_struct *)ud; - - /* - * First send a WACK to the registering machine. - */ - - send_wins_wack_response(60, p); - - /* - * When the reply comes back we need the original packet. - * Lock this so it won't be freed and then put it into - * the userdata structure. - */ - - p->locked = True; - - userdata = (struct userdata_struct *)ud; - - userdata->copy_fn = NULL; - userdata->free_fn = NULL; - userdata->userdata_len = sizeof(struct packet_struct *); - memcpy(userdata->data, (char *)&p, sizeof(struct packet_struct *) ); - - /* - * Use the new call to send a query directly to an IP address. - * This sends the query directly to the IP address, and ensures - * the recursion desired flag is not set (you were right Luke :-). - * This function should *only* be called from the WINS server - * code. JRA. - */ - - query_name_from_wins_server( *namerec->data.ip, - question->name, - question->name_type, - wins_register_query_success, - wins_register_query_fail, - userdata ); - return; - } - - /* - * Name did not exist - add it. - */ - - (void)add_name_to_subnet( subrec, question->name, question->name_type, - nb_flags, ttl, REGISTER_NAME, 1, &from_ip); - if ((namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME))) { - get_global_id_and_update(&namerec->data.id, True); - update_wins_owner(namerec, our_fake_ip); - update_wins_flag(namerec, WINS_ACTIVE); - wins_hook("add", namerec, ttl); - } + send_wins_name_registration_response(RFS_ERR, 0, p); + return; + } else { + /* + * It's one of our names and one of our IP's - update the ttl. + */ + update_name_ttl(namerec, ttl); + send_wins_name_registration_response(0, ttl, p); + wins_hook("refresh", namerec, ttl); + return; + } + } + + /* + * If the name exists and it is a unique registration and the registering IP + * is the same as the (single) already registered IP then just update the ttl. + * + * But not if the record is an active replica. IF it's a replica, it means it can be + * the same client which has moved and not yet expired. So we don't update + * the ttl in this case and go beyond to do a WACK and query the old client + */ - send_wins_name_registration_response(0, ttl, p); + if( !registering_group_name + && (namerec != NULL) + && (namerec->data.num_ips == 1) + && ip_equal( namerec->data.ip[0], from_ip ) + && ip_equal(namerec->data.wins_ip, our_fake_ip) ) { + update_name_ttl( namerec, ttl ); + send_wins_name_registration_response( 0, ttl, p ); + wins_hook("refresh", namerec, ttl); + return; + } + + /* + * Finally if the name exists do a query to the registering machine + * to see if they still claim to have the name. + */ + + if( namerec != NULL ) { + long *ud[(sizeof(struct userdata_struct) + sizeof(struct packet_struct *))/sizeof(long *) + 1]; + struct userdata_struct *userdata = (struct userdata_struct *)ud; + + /* + * First send a WACK to the registering machine. + */ + + send_wins_wack_response(60, p); + + /* + * When the reply comes back we need the original packet. + * Lock this so it won't be freed and then put it into + * the userdata structure. + */ + + p->locked = True; + + userdata = (struct userdata_struct *)ud; + + userdata->copy_fn = NULL; + userdata->free_fn = NULL; + userdata->userdata_len = sizeof(struct packet_struct *); + memcpy(userdata->data, (char *)&p, sizeof(struct packet_struct *) ); + + /* + * Use the new call to send a query directly to an IP address. + * This sends the query directly to the IP address, and ensures + * the recursion desired flag is not set (you were right Luke :-). + * This function should *only* be called from the WINS server + * code. JRA. + */ + + pull_ascii_nstring(name, question->name); + query_name_from_wins_server( *namerec->data.ip, + name, + question->name_type, + wins_register_query_success, + wins_register_query_fail, + userdata ); + return; + } + + /* + * Name did not exist - add it. + */ + + pull_ascii_nstring(name, question->name); + add_name_to_subnet( subrec, name, question->name_type, + nb_flags, ttl, REGISTER_NAME, 1, &from_ip); + + if ((namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME))) { + get_global_id_and_update(&namerec->data.id, True); + update_wins_owner(namerec, our_fake_ip); + update_wins_flag(namerec, WINS_ACTIVE); + wins_hook("add", namerec, ttl); + } + + send_wins_name_registration_response(0, ttl, p); } /*********************************************************************** @@ -1017,55 +979,54 @@ static void wins_multihomed_register_query_success(struct subnet_record *subrec, struct in_addr ip, struct res_rec *answers) { - struct packet_struct *orig_reg_packet; - struct nmb_packet *nmb; - struct name_record *namerec = NULL; - struct in_addr from_ip; - int ttl; - struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0"); - - memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *)); - - nmb = &orig_reg_packet->packet.nmb; - - putip((char *)&from_ip,&nmb->additional->rdata[2]); - ttl = get_ttl_from_packet(nmb); - - /* - * We want to just add the new IP, as we now know the requesting - * machine claims to own it. But we can't just do that as an arbitary - * amount of time may have taken place between the name query - * request and this response. So we check that - * the name still exists and is in the same state - if so - * we just add the extra IP and update the ttl. - */ - - namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME); - - if( (namerec == NULL) || (namerec->data.source != REGISTER_NAME) || !WINS_STATE_ACTIVE(namerec) ) - { - DEBUG(3,("wins_multihomed_register_query_success: name %s is not in the correct state to add \ + struct packet_struct *orig_reg_packet; + struct nmb_packet *nmb; + struct name_record *namerec = NULL; + struct in_addr from_ip; + int ttl; + struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0"); + + memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *)); + + nmb = &orig_reg_packet->packet.nmb; + + putip((char *)&from_ip,&nmb->additional->rdata[2]); + ttl = get_ttl_from_packet(nmb); + + /* + * We want to just add the new IP, as we now know the requesting + * machine claims to own it. But we can't just do that as an arbitary + * amount of time may have taken place between the name query + * request and this response. So we check that + * the name still exists and is in the same state - if so + * we just add the extra IP and update the ttl. + */ + + namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME); + + if( (namerec == NULL) || (namerec->data.source != REGISTER_NAME) || !WINS_STATE_ACTIVE(namerec) ) { + DEBUG(3,("wins_multihomed_register_query_success: name %s is not in the correct state to add \ a subsequent IP address.\n", nmb_namestr(question_name) )); - send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet); + send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet); - orig_reg_packet->locked = False; - free_packet(orig_reg_packet); + orig_reg_packet->locked = False; + free_packet(orig_reg_packet); - return; - } + return; + } - if(!find_ip_in_name_record(namerec, from_ip)) - add_ip_to_name_record(namerec, from_ip); + if(!find_ip_in_name_record(namerec, from_ip)) + add_ip_to_name_record(namerec, from_ip); - get_global_id_and_update(&namerec->data.id, True); - update_wins_owner(namerec, our_fake_ip); - update_wins_flag(namerec, WINS_ACTIVE); - update_name_ttl(namerec, ttl); - send_wins_name_registration_response(0, ttl, orig_reg_packet); - wins_hook("add", namerec, ttl); + get_global_id_and_update(&namerec->data.id, True); + update_wins_owner(namerec, our_fake_ip); + update_wins_flag(namerec, WINS_ACTIVE); + update_name_ttl(namerec, ttl); + send_wins_name_registration_response(0, ttl, orig_reg_packet); + wins_hook("add", namerec, ttl); - orig_reg_packet->locked = False; - free_packet(orig_reg_packet); + orig_reg_packet->locked = False; + free_packet(orig_reg_packet); } /*********************************************************************** @@ -1081,18 +1042,18 @@ static void wins_multihomed_register_query_fail(struct subnet_record *subrec, struct nmb_name *question_name, int rcode) { - struct userdata_struct *userdata = rrec->userdata; - struct packet_struct *orig_reg_packet; + struct userdata_struct *userdata = rrec->userdata; + struct packet_struct *orig_reg_packet; - memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *)); + memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *)); - DEBUG(3,("wins_multihomed_register_query_fail: Registering machine at IP %s failed to answer \ + DEBUG(3,("wins_multihomed_register_query_fail: Registering machine at IP %s failed to answer \ query successfully for name %s.\n", inet_ntoa(orig_reg_packet->ip), nmb_namestr(question_name) )); - send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet); + send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet); - orig_reg_packet->locked = False; - free_packet(orig_reg_packet); - return; + orig_reg_packet->locked = False; + free_packet(orig_reg_packet); + return; } /*********************************************************************** @@ -1103,250 +1064,241 @@ query successfully for name %s.\n", inet_ntoa(orig_reg_packet->ip), nmb_namestr( void wins_process_multihomed_name_registration_request( struct subnet_record *subrec, struct packet_struct *p) { - struct nmb_packet *nmb = &p->packet.nmb; - struct nmb_name *question = &nmb->question.question_name; - BOOL bcast = nmb->header.nm_flags.bcast; - uint16 nb_flags = get_nb_flags(nmb->additional->rdata); - int ttl = get_ttl_from_packet(nmb); - struct name_record *namerec = NULL; - struct in_addr from_ip; - BOOL group = (nb_flags & NB_GROUP) ? True : False; - struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0"); - - putip((char *)&from_ip,&nmb->additional->rdata[2]); - - if(bcast) - { - /* - * We should only get unicast name registration packets here. - * Anyone trying to register broadcast should not be going to a WINS - * server. Log an error here. - */ - - DEBUG(0,("wins_process_multihomed_name_registration_request: broadcast name registration request \ + struct nmb_packet *nmb = &p->packet.nmb; + struct nmb_name *question = &nmb->question.question_name; + BOOL bcast = nmb->header.nm_flags.bcast; + uint16 nb_flags = get_nb_flags(nmb->additional->rdata); + int ttl = get_ttl_from_packet(nmb); + struct name_record *namerec = NULL; + struct in_addr from_ip; + BOOL group = (nb_flags & NB_GROUP) ? True : False; + struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0"); + nstring qname; + + putip((char *)&from_ip,&nmb->additional->rdata[2]); + + if(bcast) { + /* + * We should only get unicast name registration packets here. + * Anyone trying to register broadcast should not be going to a WINS + * server. Log an error here. + */ + + DEBUG(0,("wins_process_multihomed_name_registration_request: broadcast name registration request \ received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n", - nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name)); - return; - } + nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name)); + return; + } - /* - * Only unique names should be registered multihomed. - */ + /* + * Only unique names should be registered multihomed. + */ - if(group) - { - DEBUG(0,("wins_process_multihomed_name_registration_request: group name registration request \ + if(group) { + DEBUG(0,("wins_process_multihomed_name_registration_request: group name registration request \ received for name %s from IP %s on subnet %s. Errror - group names should not be multihomed.\n", - nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name)); - return; - } + nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name)); + return; + } - DEBUG(3,("wins_process_multihomed_name_registration_request: name registration for name %s \ + DEBUG(3,("wins_process_multihomed_name_registration_request: name registration for name %s \ IP %s\n", nmb_namestr(question), inet_ntoa(from_ip) )); - /* - * Deal with policy regarding 0x1d names. - */ + /* + * Deal with policy regarding 0x1d names. + */ - if(question->name_type == 0x1d) - { - DEBUG(3,("wins_process_multihomed_name_registration_request: Ignoring request \ + if(question->name_type == 0x1d) { + DEBUG(3,("wins_process_multihomed_name_registration_request: Ignoring request \ to register name %s from IP %s.", nmb_namestr(question), inet_ntoa(p->ip) )); - send_wins_name_registration_response(0, ttl, p); - return; - } - - /* - * See if the name already exists. - */ - - namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME); - - /* - * if the record exists but NOT in active state, - * consider it dead. - */ - if ((namerec != NULL) && !WINS_STATE_ACTIVE(namerec)) { - DEBUG(5,("wins_process_multihomed_name_registration_request: Name (%s) in WINS was not active - removing it.\n", nmb_namestr(question))); - remove_name_from_namelist(subrec, namerec); - namerec = NULL; - } + send_wins_name_registration_response(0, ttl, p); + return; + } + + /* + * See if the name already exists. + */ + + namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME); + + /* + * if the record exists but NOT in active state, + * consider it dead. + */ + + if ((namerec != NULL) && !WINS_STATE_ACTIVE(namerec)) { + DEBUG(5,("wins_process_multihomed_name_registration_request: Name (%s) in WINS was not active - removing it.\n", nmb_namestr(question))); + remove_name_from_namelist(subrec, namerec); + namerec = NULL; + } - /* - * Deal with the case where the name found was a dns entry. - * Remove it as we now have a NetBIOS client registering the - * name. - */ - - if( (namerec != NULL) - && ( (namerec->data.source == DNS_NAME) - || (namerec->data.source == DNSFAIL_NAME) ) ) - { - DEBUG(5,("wins_process_multihomed_name_registration_request: Name (%s) in WINS was a dns lookup \ + /* + * Deal with the case where the name found was a dns entry. + * Remove it as we now have a NetBIOS client registering the + * name. + */ + + if( (namerec != NULL) && ( (namerec->data.source == DNS_NAME) || (namerec->data.source == DNSFAIL_NAME) ) ) { + DEBUG(5,("wins_process_multihomed_name_registration_request: Name (%s) in WINS was a dns lookup \ - removing it.\n", nmb_namestr(question) )); - remove_name_from_namelist( subrec, namerec); - namerec = NULL; - } - - /* - * Reject if the name exists and is not a REGISTER_NAME. - * (ie. Don't allow any static names to be overwritten. - */ - - if( (namerec != NULL) && (namerec->data.source != REGISTER_NAME) ) - { - DEBUG( 3, ( "wins_process_multihomed_name_registration_request: Attempt \ + remove_name_from_namelist( subrec, namerec); + namerec = NULL; + } + + /* + * Reject if the name exists and is not a REGISTER_NAME. + * (ie. Don't allow any static names to be overwritten. + */ + + if( (namerec != NULL) && (namerec->data.source != REGISTER_NAME) ) { + DEBUG( 3, ( "wins_process_multihomed_name_registration_request: Attempt \ to register name %s. Name already exists in WINS with source type %d.\n", - nmb_namestr(question), namerec->data.source )); - send_wins_name_registration_response(RFS_ERR, 0, p); - return; - } - - /* - * Reject if the name exists and is a GROUP name and is active. - */ - - if((namerec != NULL) && NAME_GROUP(namerec) && WINS_STATE_ACTIVE(namerec)) - { - DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \ + nmb_namestr(question), namerec->data.source )); + send_wins_name_registration_response(RFS_ERR, 0, p); + return; + } + + /* + * Reject if the name exists and is a GROUP name and is active. + */ + + if((namerec != NULL) && NAME_GROUP(namerec) && WINS_STATE_ACTIVE(namerec)) { + DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \ already exists in WINS as a GROUP name.\n", nmb_namestr(question) )); - send_wins_name_registration_response(RFS_ERR, 0, p); - return; - } - - /* - * From here on down we know that if the name exists in the WINS db it is - * a unique name, not a group name. - */ - - /* - * If the name exists and is one of our names then check the - * registering IP address. If it's not one of ours then automatically - * reject without doing the query - we know we will reject it. - */ - - if((namerec != NULL) && (is_myname(namerec->name.name)) ) - { - if(!ismyip(from_ip)) - { - DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \ + send_wins_name_registration_response(RFS_ERR, 0, p); + return; + } + + /* + * From here on down we know that if the name exists in the WINS db it is + * a unique name, not a group name. + */ + + /* + * If the name exists and is one of our names then check the + * registering IP address. If it's not one of ours then automatically + * reject without doing the query - we know we will reject it. + */ + + if((namerec != NULL) && (is_myname(namerec->name.name)) ) { + if(!ismyip(from_ip)) { + DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \ is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question) )); - send_wins_name_registration_response(RFS_ERR, 0, p); - return; - } - else - { - /* - * It's one of our names and one of our IP's. Ensure the IP is in the record and - * update the ttl. Update the version ID to force replication. - */ - if(!find_ip_in_name_record(namerec, from_ip)) { - get_global_id_and_update(&namerec->data.id, True); - update_wins_owner(namerec, our_fake_ip); - update_wins_flag(namerec, WINS_ACTIVE); - - add_ip_to_name_record(namerec, from_ip); - wins_hook("add", namerec, ttl); - } else { - wins_hook("refresh", namerec, ttl); - } - - update_name_ttl(namerec, ttl); - send_wins_name_registration_response(0, ttl, p); - return; - } - } - - /* - * If the name exists and is active, check if the IP address is already registered - * to that name. If so then update the ttl and reply success. - */ - - if((namerec != NULL) && find_ip_in_name_record(namerec, from_ip) && WINS_STATE_ACTIVE(namerec)) - { - update_name_ttl(namerec, ttl); - /* - * If it's a replica, we need to become the wins owner - * to force the replication - */ - if (!ip_equal(namerec->data.wins_ip, our_fake_ip)) { - get_global_id_and_update(&namerec->data.id, True); - update_wins_owner(namerec, our_fake_ip); - update_wins_flag(namerec, WINS_ACTIVE); - } + send_wins_name_registration_response(RFS_ERR, 0, p); + return; + } else { + /* + * It's one of our names and one of our IP's. Ensure the IP is in the record and + * update the ttl. Update the version ID to force replication. + */ + if(!find_ip_in_name_record(namerec, from_ip)) { + get_global_id_and_update(&namerec->data.id, True); + update_wins_owner(namerec, our_fake_ip); + update_wins_flag(namerec, WINS_ACTIVE); + + add_ip_to_name_record(namerec, from_ip); + wins_hook("add", namerec, ttl); + } else { + wins_hook("refresh", namerec, ttl); + } + + update_name_ttl(namerec, ttl); + send_wins_name_registration_response(0, ttl, p); + return; + } + } + + /* + * If the name exists and is active, check if the IP address is already registered + * to that name. If so then update the ttl and reply success. + */ + + if((namerec != NULL) && find_ip_in_name_record(namerec, from_ip) && WINS_STATE_ACTIVE(namerec)) { + update_name_ttl(namerec, ttl); + + /* + * If it's a replica, we need to become the wins owner + * to force the replication + */ + if (!ip_equal(namerec->data.wins_ip, our_fake_ip)) { + get_global_id_and_update(&namerec->data.id, True); + update_wins_owner(namerec, our_fake_ip); + update_wins_flag(namerec, WINS_ACTIVE); + } - send_wins_name_registration_response(0, ttl, p); - wins_hook("refresh", namerec, ttl); - return; - } - - /* - * If the name exists do a query to the owner - * to see if they still want the name. - */ - - if(namerec != NULL) - { - long *ud[(sizeof(struct userdata_struct) + sizeof(struct packet_struct *))/sizeof(long *) + 1]; - struct userdata_struct *userdata = (struct userdata_struct *)ud; - - /* - * First send a WACK to the registering machine. - */ - - send_wins_wack_response(60, p); - - /* - * When the reply comes back we need the original packet. - * Lock this so it won't be freed and then put it into - * the userdata structure. - */ - - p->locked = True; - - userdata = (struct userdata_struct *)ud; - - userdata->copy_fn = NULL; - userdata->free_fn = NULL; - userdata->userdata_len = sizeof(struct packet_struct *); - memcpy(userdata->data, (char *)&p, sizeof(struct packet_struct *) ); - - /* - * Use the new call to send a query directly to an IP address. - * This sends the query directly to the IP address, and ensures - * the recursion desired flag is not set (you were right Luke :-). - * This function should *only* be called from the WINS server - * code. JRA. - * - * Note that this packet is sent to the current owner of the name, - * not the person who sent the packet - */ - - query_name_from_wins_server( namerec->data.ip[0], - question->name, - question->name_type, - wins_multihomed_register_query_success, - wins_multihomed_register_query_fail, - userdata ); - - return; - } - - /* - * Name did not exist - add it. - */ - - (void)add_name_to_subnet( subrec, question->name, question->name_type, - nb_flags, ttl, REGISTER_NAME, 1, &from_ip); - - if ((namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME))) { - get_global_id_and_update(&namerec->data.id, True); - update_wins_owner(namerec, our_fake_ip); - update_wins_flag(namerec, WINS_ACTIVE); - wins_hook("add", namerec, ttl); - } - - send_wins_name_registration_response(0, ttl, p); + send_wins_name_registration_response(0, ttl, p); + wins_hook("refresh", namerec, ttl); + return; + } + + /* + * If the name exists do a query to the owner + * to see if they still want the name. + */ + + if(namerec != NULL) { + long *ud[(sizeof(struct userdata_struct) + sizeof(struct packet_struct *))/sizeof(long *) + 1]; + struct userdata_struct *userdata = (struct userdata_struct *)ud; + + /* + * First send a WACK to the registering machine. + */ + + send_wins_wack_response(60, p); + + /* + * When the reply comes back we need the original packet. + * Lock this so it won't be freed and then put it into + * the userdata structure. + */ + + p->locked = True; + + userdata = (struct userdata_struct *)ud; + + userdata->copy_fn = NULL; + userdata->free_fn = NULL; + userdata->userdata_len = sizeof(struct packet_struct *); + memcpy(userdata->data, (char *)&p, sizeof(struct packet_struct *) ); + + /* + * Use the new call to send a query directly to an IP address. + * This sends the query directly to the IP address, and ensures + * the recursion desired flag is not set (you were right Luke :-). + * This function should *only* be called from the WINS server + * code. JRA. + * + * Note that this packet is sent to the current owner of the name, + * not the person who sent the packet + */ + + pull_ascii_nstring( qname, question->name); + query_name_from_wins_server( namerec->data.ip[0], + qname, + question->name_type, + wins_multihomed_register_query_success, + wins_multihomed_register_query_fail, + userdata ); + + return; + } + + /* + * Name did not exist - add it. + */ + + pull_ascii_nstring( qname, question->name); + add_name_to_subnet( subrec, qname, question->name_type, + nb_flags, ttl, REGISTER_NAME, 1, &from_ip); + + if ((namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME))) { + get_global_id_and_update(&namerec->data.id, True); + update_wins_owner(namerec, our_fake_ip); + update_wins_flag(namerec, WINS_ACTIVE); + wins_hook("add", namerec, ttl); + } + + send_wins_name_registration_response(0, ttl, p); } /*********************************************************************** @@ -1356,76 +1308,68 @@ is one of our (WINS server) names. Denying registration.\n", nmb_namestr(questio static void process_wins_dmb_query_request(struct subnet_record *subrec, struct packet_struct *p) { - struct name_record *namerec = NULL; - char *prdata; - int num_ips; - - /* - * Go through all the ACTIVE names in the WINS db looking for those - * ending in <1b>. Use this to calculate the number of IP - * addresses we need to return. - */ - - num_ips = 0; - for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist ); - namerec; - namerec = (struct name_record *)ubi_trNext( namerec ) ) - { - if(WINS_STATE_ACTIVE(namerec) && namerec->name.name_type == 0x1b ) - num_ips += namerec->data.num_ips; - } - - if(num_ips == 0) - { - /* - * There are no 0x1b names registered. Return name query fail. - */ - send_wins_name_query_response(NAM_ERR, p, NULL); - return; - } - - if((prdata = (char *)malloc( num_ips * 6 )) == NULL) - { - DEBUG(0,("process_wins_dmb_query_request: Malloc fail !.\n")); - return; - } - - /* - * Go through all the names again in the WINS db looking for those - * ending in <1b>. Add their IP addresses into the list we will - * return. - */ - - num_ips = 0; - for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist ); - namerec; - namerec = (struct name_record *)ubi_trNext( namerec ) ) - { - if(WINS_STATE_ACTIVE(namerec) && namerec->name.name_type == 0x1b) - { - int i; - for(i = 0; i < namerec->data.num_ips; i++) - { - set_nb_flags(&prdata[num_ips * 6],namerec->data.nb_flags); - putip((char *)&prdata[(num_ips * 6) + 2], &namerec->data.ip[i]); - num_ips++; - } - } - } - - /* - * Send back the reply containing the IP list. - */ - - reply_netbios_packet(p, /* Packet to reply to. */ - 0, /* Result code. */ - WINS_QUERY, /* nmbd type code. */ - NMB_NAME_QUERY_OPCODE, /* opcode. */ - lp_min_wins_ttl(), /* ttl. */ - prdata, /* data to send. */ - num_ips*6); /* data length. */ - - SAFE_FREE(prdata); + struct name_record *namerec = NULL; + char *prdata; + int num_ips; + + /* + * Go through all the ACTIVE names in the WINS db looking for those + * ending in <1b>. Use this to calculate the number of IP + * addresses we need to return. + */ + + num_ips = 0; + for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist ); + namerec; namerec = (struct name_record *)ubi_trNext( namerec ) ) { + if(WINS_STATE_ACTIVE(namerec) && namerec->name.name_type == 0x1b ) + num_ips += namerec->data.num_ips; + } + + if(num_ips == 0) { + /* + * There are no 0x1b names registered. Return name query fail. + */ + send_wins_name_query_response(NAM_ERR, p, NULL); + return; + } + + if((prdata = (char *)malloc( num_ips * 6 )) == NULL) { + DEBUG(0,("process_wins_dmb_query_request: Malloc fail !.\n")); + return; + } + + /* + * Go through all the names again in the WINS db looking for those + * ending in <1b>. Add their IP addresses into the list we will + * return. + */ + + num_ips = 0; + for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist ); + namerec; namerec = (struct name_record *)ubi_trNext( namerec ) ) { + if(WINS_STATE_ACTIVE(namerec) && namerec->name.name_type == 0x1b) { + int i; + for(i = 0; i < namerec->data.num_ips; i++) { + set_nb_flags(&prdata[num_ips * 6],namerec->data.nb_flags); + putip((char *)&prdata[(num_ips * 6) + 2], &namerec->data.ip[i]); + num_ips++; + } + } + } + + /* + * Send back the reply containing the IP list. + */ + + reply_netbios_packet(p, /* Packet to reply to. */ + 0, /* Result code. */ + WINS_QUERY, /* nmbd type code. */ + NMB_NAME_QUERY_OPCODE, /* opcode. */ + lp_min_wins_ttl(), /* ttl. */ + prdata, /* data to send. */ + num_ips*6); /* data length. */ + + SAFE_FREE(prdata); } /**************************************************************************** @@ -1435,55 +1379,48 @@ Send a WINS name query response. void send_wins_name_query_response(int rcode, struct packet_struct *p, struct name_record *namerec) { - char rdata[6]; - char *prdata = rdata; - int reply_data_len = 0; - int ttl = 0; - int i; - - memset(rdata,'\0',6); - - if(rcode == 0) - { - ttl = (namerec->data.death_time != PERMANENT_TTL) ? - namerec->data.death_time - p->timestamp : lp_max_wins_ttl(); - - /* Copy all known ip addresses into the return data. */ - /* Optimise for the common case of one IP address so - we don't need a malloc. */ - - if( namerec->data.num_ips == 1 ) - prdata = rdata; - else - { - if((prdata = (char *)malloc( namerec->data.num_ips * 6 )) == NULL) - { - DEBUG(0,("send_wins_name_query_response: malloc fail !\n")); - return; - } - } - - for(i = 0; i < namerec->data.num_ips; i++) - { - set_nb_flags(&prdata[i*6],namerec->data.nb_flags); - putip((char *)&prdata[2+(i*6)], &namerec->data.ip[i]); - } - - sort_query_replies(prdata, i, p->ip); - - reply_data_len = namerec->data.num_ips * 6; - } - - reply_netbios_packet(p, /* Packet to reply to. */ - rcode, /* Result code. */ - WINS_QUERY, /* nmbd type code. */ - NMB_NAME_QUERY_OPCODE, /* opcode. */ - ttl, /* ttl. */ - prdata, /* data to send. */ - reply_data_len); /* data length. */ - - if(prdata != rdata) - SAFE_FREE(prdata); + char rdata[6]; + char *prdata = rdata; + int reply_data_len = 0; + int ttl = 0; + int i; + + memset(rdata,'\0',6); + + if(rcode == 0) { + ttl = (namerec->data.death_time != PERMANENT_TTL) ? namerec->data.death_time - p->timestamp : lp_max_wins_ttl(); + + /* Copy all known ip addresses into the return data. */ + /* Optimise for the common case of one IP address so we don't need a malloc. */ + + if( namerec->data.num_ips == 1 ) { + prdata = rdata; + } else { + if((prdata = (char *)malloc( namerec->data.num_ips * 6 )) == NULL) { + DEBUG(0,("send_wins_name_query_response: malloc fail !\n")); + return; + } + } + + for(i = 0; i < namerec->data.num_ips; i++) { + set_nb_flags(&prdata[i*6],namerec->data.nb_flags); + putip((char *)&prdata[2+(i*6)], &namerec->data.ip[i]); + } + + sort_query_replies(prdata, i, p->ip); + reply_data_len = namerec->data.num_ips * 6; + } + + reply_netbios_packet(p, /* Packet to reply to. */ + rcode, /* Result code. */ + WINS_QUERY, /* nmbd type code. */ + NMB_NAME_QUERY_OPCODE, /* opcode. */ + ttl, /* ttl. */ + prdata, /* data to send. */ + reply_data_len); /* data length. */ + + if(prdata != rdata) + SAFE_FREE(prdata); } /*********************************************************************** @@ -1493,93 +1430,87 @@ void send_wins_name_query_response(int rcode, struct packet_struct *p, void wins_process_name_query_request(struct subnet_record *subrec, struct packet_struct *p) { - struct nmb_packet *nmb = &p->packet.nmb; - struct nmb_name *question = &nmb->question.question_name; - struct name_record *namerec = NULL; - - DEBUG(3,("wins_process_name_query: name query for name %s from IP %s\n", - nmb_namestr(question), inet_ntoa(p->ip) )); - - /* - * Special name code. If the queried name is *<1b> then search - * the entire WINS database and return a list of all the IP addresses - * registered to any <1b> name. This is to allow domain master browsers - * to discover other domains that may not have a presence on their subnet. - */ - - if(strequal( question->name, "*") && (question->name_type == 0x1b)) - { - process_wins_dmb_query_request( subrec, p); - return; - } - - namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME); - - if(namerec != NULL) - { - /* - * If the name is not anymore in active state then reply not found. - * it's fair even if we keep it in the cache for days. - */ - if (!WINS_STATE_ACTIVE(namerec)) - { - DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n", - nmb_namestr(question) )); - send_wins_name_query_response(NAM_ERR, p, namerec); - return; - } - /* - * If it's a DNSFAIL_NAME then reply name not found. - */ - - if( namerec->data.source == DNSFAIL_NAME ) - { - DEBUG(3,("wins_process_name_query: name query for name %s returning DNS fail.\n", - nmb_namestr(question) )); - send_wins_name_query_response(NAM_ERR, p, namerec); - return; - } - - /* - * If the name has expired then reply name not found. - */ - - if( (namerec->data.death_time != PERMANENT_TTL) - && (namerec->data.death_time < p->timestamp) ) - { - DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n", - nmb_namestr(question) )); - send_wins_name_query_response(NAM_ERR, p, namerec); - return; - } - - DEBUG(3,("wins_process_name_query: name query for name %s returning first IP %s.\n", - nmb_namestr(question), inet_ntoa(namerec->data.ip[0]) )); - - send_wins_name_query_response(0, p, namerec); - return; - } - - /* - * Name not found in WINS - try a dns query if it's a 0x20 name. - */ - - if(lp_dns_proxy() && - ((question->name_type == 0x20) || question->name_type == 0)) - { - - DEBUG(3,("wins_process_name_query: name query for name %s not found - doing dns lookup.\n", - nmb_namestr(question) )); - - queue_dns_query(p, question, &namerec); - return; - } - - /* - * Name not found - return error. - */ - - send_wins_name_query_response(NAM_ERR, p, NULL); + struct nmb_packet *nmb = &p->packet.nmb; + struct nmb_name *question = &nmb->question.question_name; + struct name_record *namerec = NULL; + nstring qname; + + DEBUG(3,("wins_process_name_query: name query for name %s from IP %s\n", + nmb_namestr(question), inet_ntoa(p->ip) )); + + /* + * Special name code. If the queried name is *<1b> then search + * the entire WINS database and return a list of all the IP addresses + * registered to any <1b> name. This is to allow domain master browsers + * to discover other domains that may not have a presence on their subnet. + */ + + pull_ascii_nstring(qname, question->name); + if(strequal( qname, "*") && (question->name_type == 0x1b)) { + process_wins_dmb_query_request( subrec, p); + return; + } + + namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME); + + if(namerec != NULL) { + /* + * If the name is not anymore in active state then reply not found. + * it's fair even if we keep it in the cache for days. + */ + if (!WINS_STATE_ACTIVE(namerec)) { + DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n", + nmb_namestr(question) )); + send_wins_name_query_response(NAM_ERR, p, namerec); + return; + } + + /* + * If it's a DNSFAIL_NAME then reply name not found. + */ + + if( namerec->data.source == DNSFAIL_NAME ) { + DEBUG(3,("wins_process_name_query: name query for name %s returning DNS fail.\n", + nmb_namestr(question) )); + send_wins_name_query_response(NAM_ERR, p, namerec); + return; + } + + /* + * If the name has expired then reply name not found. + */ + + if( (namerec->data.death_time != PERMANENT_TTL) && (namerec->data.death_time < p->timestamp) ) { + DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n", + nmb_namestr(question) )); + send_wins_name_query_response(NAM_ERR, p, namerec); + return; + } + + DEBUG(3,("wins_process_name_query: name query for name %s returning first IP %s.\n", + nmb_namestr(question), inet_ntoa(namerec->data.ip[0]) )); + + send_wins_name_query_response(0, p, namerec); + return; + } + + /* + * Name not found in WINS - try a dns query if it's a 0x20 name. + */ + + if(lp_dns_proxy() && ((question->name_type == 0x20) || question->name_type == 0)) { + DEBUG(3,("wins_process_name_query: name query for name %s not found - doing dns lookup.\n", + nmb_namestr(question) )); + + queue_dns_query(p, question, &namerec); + return; + } + + /* + * Name not found - return error. + */ + + send_wins_name_query_response(NAM_ERR, p, NULL); } /**************************************************************************** @@ -1588,18 +1519,18 @@ Send a WINS name release response. static void send_wins_name_release_response(int rcode, struct packet_struct *p) { - struct nmb_packet *nmb = &p->packet.nmb; - char rdata[6]; - - memcpy(&rdata[0], &nmb->additional->rdata[0], 6); - - reply_netbios_packet(p, /* Packet to reply to. */ - rcode, /* Result code. */ - NMB_REL, /* nmbd type code. */ - NMB_NAME_RELEASE_OPCODE, /* opcode. */ - 0, /* ttl. */ - rdata, /* data to send. */ - 6); /* data length. */ + struct nmb_packet *nmb = &p->packet.nmb; + char rdata[6]; + + memcpy(&rdata[0], &nmb->additional->rdata[0], 6); + + reply_netbios_packet(p, /* Packet to reply to. */ + rcode, /* Result code. */ + NMB_REL, /* nmbd type code. */ + NMB_NAME_RELEASE_OPCODE, /* opcode. */ + 0, /* ttl. */ + rdata, /* data to send. */ + 6); /* data length. */ } /*********************************************************************** @@ -1609,123 +1540,115 @@ static void send_wins_name_release_response(int rcode, struct packet_struct *p) void wins_process_name_release_request(struct subnet_record *subrec, struct packet_struct *p) { - struct nmb_packet *nmb = &p->packet.nmb; - struct nmb_name *question = &nmb->question.question_name; - BOOL bcast = nmb->header.nm_flags.bcast; - uint16 nb_flags = get_nb_flags(nmb->additional->rdata); - struct name_record *namerec = NULL; - struct in_addr from_ip; - BOOL releasing_group_name = (nb_flags & NB_GROUP) ? True : False;; - - putip((char *)&from_ip,&nmb->additional->rdata[2]); - - if(bcast) - { - /* - * We should only get unicast name registration packets here. - * Anyone trying to register broadcast should not be going to a WINS - * server. Log an error here. - */ - - DEBUG(0,("wins_process_name_release_request: broadcast name registration request \ + struct nmb_packet *nmb = &p->packet.nmb; + struct nmb_name *question = &nmb->question.question_name; + BOOL bcast = nmb->header.nm_flags.bcast; + uint16 nb_flags = get_nb_flags(nmb->additional->rdata); + struct name_record *namerec = NULL; + struct in_addr from_ip; + BOOL releasing_group_name = (nb_flags & NB_GROUP) ? True : False;; + + putip((char *)&from_ip,&nmb->additional->rdata[2]); + + if(bcast) { + /* + * We should only get unicast name registration packets here. + * Anyone trying to register broadcast should not be going to a WINS + * server. Log an error here. + */ + + DEBUG(0,("wins_process_name_release_request: broadcast name registration request \ received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n", - nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name)); - return; - } + nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name)); + return; + } - DEBUG(3,("wins_process_name_release_request: %s name release for name %s \ + DEBUG(3,("wins_process_name_release_request: %s name release for name %s \ IP %s\n", releasing_group_name ? "Group" : "Unique", nmb_namestr(question), inet_ntoa(from_ip) )); - /* - * Deal with policy regarding 0x1d names. - */ + /* + * Deal with policy regarding 0x1d names. + */ - if(!releasing_group_name && (question->name_type == 0x1d)) - { - DEBUG(3,("wins_process_name_release_request: Ignoring request \ + if(!releasing_group_name && (question->name_type == 0x1d)) { + DEBUG(3,("wins_process_name_release_request: Ignoring request \ to release name %s from IP %s.", nmb_namestr(question), inet_ntoa(p->ip) )); - send_wins_name_release_response(0, p); - return; - } + send_wins_name_release_response(0, p); + return; + } - /* - * See if the name already exists. - */ + /* + * See if the name already exists. + */ - namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME); - - if( (namerec == NULL) - || ((namerec != NULL) && (namerec->data.source != REGISTER_NAME)) ) - { - send_wins_name_release_response(NAM_ERR, p); - return; - } - - /* - * Check that the sending machine has permission to release this name. - * If it's a group name not ending in 0x1c then just say yes and let - * the group time out. - */ - - if(releasing_group_name && (question->name_type != 0x1c)) - { - send_wins_name_release_response(0, p); - return; - } - - /* - * Check that the releasing node is on the list of IP addresses - * for this name. Disallow the release if not. - */ - - if(!find_ip_in_name_record(namerec, from_ip)) - { - DEBUG(3,("wins_process_name_release_request: Refusing request to \ + namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME); + + if( (namerec == NULL) || ((namerec != NULL) && (namerec->data.source != REGISTER_NAME)) ) { + send_wins_name_release_response(NAM_ERR, p); + return; + } + + /* + * Check that the sending machine has permission to release this name. + * If it's a group name not ending in 0x1c then just say yes and let + * the group time out. + */ + + if(releasing_group_name && (question->name_type != 0x1c)) { + send_wins_name_release_response(0, p); + return; + } + + /* + * Check that the releasing node is on the list of IP addresses + * for this name. Disallow the release if not. + */ + + if(!find_ip_in_name_record(namerec, from_ip)) { + DEBUG(3,("wins_process_name_release_request: Refusing request to \ release name %s as IP %s is not one of the known IP's for this name.\n", - nmb_namestr(question), inet_ntoa(from_ip) )); - send_wins_name_release_response(NAM_ERR, p); - return; - } - - /* - * Check if the record is active. IF it's already released - * or tombstoned, refuse the release. - */ - if (!WINS_STATE_ACTIVE(namerec)) { - DEBUG(3,("wins_process_name_release_request: Refusing request to \ -release name %s as this record is not anymore active.\n", - nmb_namestr(question) )); - send_wins_name_release_response(NAM_ERR, p); - return; - } - - /* - * Check if the record is a 0x1c group - * and has more then one ip - * remove only this address. - */ - - if(releasing_group_name && - (question->name_type == 0x1c) && - (namerec->data.num_ips > 1)) { - remove_ip_from_name_record(namerec, from_ip); - DEBUG(3,("wins_process_name_release_request: Remove IP %s from NAME: %s\n", - inet_ntoa(from_ip),nmb_namestr(question))); - send_wins_name_release_response(0, p); - return; - } + nmb_namestr(question), inet_ntoa(from_ip) )); + send_wins_name_release_response(NAM_ERR, p); + return; + } + + /* + * Check if the record is active. IF it's already released + * or tombstoned, refuse the release. + */ - /* - * Send a release response. - * Flag the name as released and update the ttl - */ + if (!WINS_STATE_ACTIVE(namerec)) { + DEBUG(3,("wins_process_name_release_request: Refusing request to \ +release name %s as this record is not active anymore.\n", nmb_namestr(question) )); + send_wins_name_release_response(NAM_ERR, p); + return; + } + + /* + * Check if the record is a 0x1c group + * and has more then one ip + * remove only this address. + */ + + if(releasing_group_name && (question->name_type == 0x1c) && (namerec->data.num_ips > 1)) { + remove_ip_from_name_record(namerec, from_ip); + DEBUG(3,("wins_process_name_release_request: Remove IP %s from NAME: %s\n", + inet_ntoa(from_ip),nmb_namestr(question))); + send_wins_name_release_response(0, p); + return; + } + + /* + * Send a release response. + * Flag the name as released and update the ttl + */ - send_wins_name_release_response(0, p); + send_wins_name_release_response(0, p); - namerec->data.wins_flags |= WINS_RELEASED; - update_name_ttl(namerec, EXTINCTION_INTERVAL); + namerec->data.wins_flags |= WINS_RELEASED; + update_name_ttl(namerec, EXTINCTION_INTERVAL); - wins_hook("delete", namerec, 0); + wins_hook("delete", namerec, 0); } /******************************************************************* @@ -1817,94 +1740,89 @@ we are not the wins owner !\n", nmb_namestr(&namerec->name))); /******************************************************************* Write out the current WINS database. ******************************************************************/ + void wins_write_database(BOOL background) { - struct name_record *namerec; - pstring fname, fnamenew; + struct name_record *namerec; + pstring fname, fnamenew; - XFILE *fp; + XFILE *fp; - if(!lp_we_are_a_wins_server()) - return; - - /* we will do the writing in a child process to ensure that the parent - doesn't block while this is done */ - if (background) { - CatchChild(); - if (sys_fork()) { - return; - } - } - - slprintf(fname,sizeof(fname)-1,"%s/%s", lp_lockdir(), WINS_LIST); - all_string_sub(fname,"//", "/", 0); - slprintf(fnamenew,sizeof(fnamenew)-1,"%s.%u", fname, (unsigned int)sys_getpid()); - - if((fp = x_fopen(fnamenew,O_WRONLY|O_CREAT,0644)) == NULL) - { - DEBUG(0,("wins_write_database: Can't open %s. Error was %s\n", fnamenew, strerror(errno))); - if (background) { - _exit(0); - } - return; - } - - DEBUG(4,("wins_write_database: Dump of WINS name list.\n")); - - x_fprintf(fp,"VERSION %d %u\n", WINS_VERSION, 0); + if(!lp_we_are_a_wins_server()) + return; + + /* We will do the writing in a child process to ensure that the parent doesn't block while this is done */ + if (background) { + CatchChild(); + if (sys_fork()) { + return; + } + } + + slprintf(fname,sizeof(fname)-1,"%s/%s", lp_lockdir(), WINS_LIST); + all_string_sub(fname,"//", "/", 0); + slprintf(fnamenew,sizeof(fnamenew)-1,"%s.%u", fname, (unsigned int)sys_getpid()); + + if((fp = x_fopen(fnamenew,O_WRONLY|O_CREAT,0644)) == NULL) { + DEBUG(0,("wins_write_database: Can't open %s. Error was %s\n", fnamenew, strerror(errno))); + if (background) { + _exit(0); + } + return; + } + + DEBUG(4,("wins_write_database: Dump of WINS name list.\n")); + + x_fprintf(fp,"VERSION %d %u\n", WINS_VERSION, 0); - for( namerec - = (struct name_record *)ubi_trFirst( wins_server_subnet->namelist ); - namerec; - namerec = (struct name_record *)ubi_trNext( namerec ) ) - { - int i; - struct tm *tm; - - DEBUGADD(4,("%-19s ", nmb_namestr(&namerec->name) )); - - if( namerec->data.death_time != PERMANENT_TTL ) - { - char *ts, *nl; - - tm = LocalTime(&namerec->data.death_time); - ts = asctime(tm); - nl = strrchr( ts, '\n' ); - if( NULL != nl ) - *nl = '\0'; - DEBUGADD(4,("TTL = %s ", ts )); - } - else - DEBUGADD(4,("TTL = PERMANENT ")); - - for (i = 0; i < namerec->data.num_ips; i++) - DEBUGADD(4,("%15s ", inet_ntoa(namerec->data.ip[i]) )); - DEBUGADD(4,("%2x\n", namerec->data.nb_flags )); - - if( namerec->data.source == REGISTER_NAME ) - { - x_fprintf(fp, "\"%s#%02x\" %d ", - namerec->name.name,namerec->name.name_type, /* Ignore scope. */ - (int)namerec->data.death_time); - - for (i = 0; i < namerec->data.num_ips; i++) - x_fprintf( fp, "%s ", inet_ntoa( namerec->data.ip[i] ) ); - x_fprintf( fp, "%2xR\n", namerec->data.nb_flags ); - } - } + for( namerec = (struct name_record *)ubi_trFirst( wins_server_subnet->namelist ); namerec; namerec = (struct name_record *)ubi_trNext( namerec ) ) { + int i; + struct tm *tm; + + DEBUGADD(4,("%-19s ", nmb_namestr(&namerec->name) )); + + if( namerec->data.death_time != PERMANENT_TTL ) { + char *ts, *nl; + + tm = LocalTime(&namerec->data.death_time); + ts = asctime(tm); + nl = strrchr( ts, '\n' ); + if( NULL != nl ) + *nl = '\0'; + DEBUGADD(4,("TTL = %s ", ts )); + } else { + DEBUGADD(4,("TTL = PERMANENT ")); + } + + for (i = 0; i < namerec->data.num_ips; i++) + DEBUGADD(4,("%15s ", inet_ntoa(namerec->data.ip[i]) )); + DEBUGADD(4,("%2x\n", namerec->data.nb_flags )); + + if( namerec->data.source == REGISTER_NAME ) { + nstring name; + pull_ascii_nstring(name, namerec->name.name); + x_fprintf(fp, "\"%s#%02x\" %d ", name,namerec->name.name_type, /* Ignore scope. */ + (int)namerec->data.death_time); + + for (i = 0; i < namerec->data.num_ips; i++) + x_fprintf( fp, "%s ", inet_ntoa( namerec->data.ip[i] ) ); + x_fprintf( fp, "%2xR\n", namerec->data.nb_flags ); + } + } - x_fclose(fp); - chmod(fnamenew,0644); - unlink(fname); - rename(fnamenew,fname); - if (background) { - _exit(0); - } + x_fclose(fp); + chmod(fnamenew,0644); + unlink(fname); + rename(fnamenew,fname); + if (background) { + _exit(0); + } } /**************************************************************************** -process a internal Samba message receiving a wins record + Process a internal Samba message receiving a wins record. ***************************************************************************/ + void nmbd_wins_new_entry(int msg_type, pid_t src, void *buf, size_t len) { WINS_RECORD *record; @@ -1918,11 +1836,10 @@ void nmbd_wins_new_entry(int msg_type, pid_t src, void *buf, size_t len) if (buf==NULL) return; + /* Record should use UNIX codepage. Ensure this is so in the wrepld code. JRA. */ record=(WINS_RECORD *)buf; - ZERO_STRUCT(question); - memcpy(question.name, record->name, 16); - question.name_type=record->type; + make_nmb_name(&question, record->name, record->type); namerec = find_name_on_subnet(wins_server_subnet, &question, FIND_ANY_NAME); @@ -1994,9 +1911,9 @@ void nmbd_wins_new_entry(int msg_type, pid_t src, void *buf, size_t len) for (i=0; inum_ips; i++) if(!find_ip_in_name_record(namerec, record->ip[i])) add_ip_to_name_record(namerec, record->ip[i]); - } - else + } else { overwrite=True; + } } /* the replica is a multihomed host */ @@ -2050,11 +1967,3 @@ void nmbd_wins_new_entry(int msg_type, pid_t src, void *buf, size_t len) } } - - - - - - - - diff --git a/source3/nmbd/nmbd_workgroupdb.c b/source3/nmbd/nmbd_workgroupdb.c index 2357fd637b..b9fab4b278 100644 --- a/source3/nmbd/nmbd_workgroupdb.c +++ b/source3/nmbd/nmbd_workgroupdb.c @@ -31,7 +31,7 @@ int workgroup_count = 0; /* unique index key: one for each workgroup */ /**************************************************************************** Add a workgroup into the list. - **************************************************************************/ +**************************************************************************/ static void add_workgroup(struct subnet_record *subrec, struct work_record *work) { @@ -42,164 +42,160 @@ static void add_workgroup(struct subnet_record *subrec, struct work_record *work /**************************************************************************** Create an empty workgroup. - **************************************************************************/ +**************************************************************************/ static struct work_record *create_workgroup(const char *name, int ttl) { - struct work_record *work; - struct subnet_record *subrec; - int t = -1; + struct work_record *work; + struct subnet_record *subrec; + int t = -1; - if((work = (struct work_record *)malloc(sizeof(*work))) == NULL) - { - DEBUG(0,("create_workgroup: malloc fail !\n")); - return NULL; - } - memset((char *)work, '\0', sizeof(*work)); + if((work = (struct work_record *)malloc(sizeof(*work))) == NULL) { + DEBUG(0,("create_workgroup: malloc fail !\n")); + return NULL; + } + memset((char *)work, '\0', sizeof(*work)); - fstrcpy(work->work_group,name); - work->serverlist = NULL; + if (strlen(name)+1 > sizeof(nstring)) { + memcpy(work->work_group,name,sizeof(nstring)-1); + work->work_group[sizeof(nstring)-1] = '\0'; + DEBUG(0,("create_workgroup: workgroup name %s is too long. Truncating to %s\n", + name, work->work_group )); + } else { + nstrcpy(work->work_group,name); + } + work->serverlist = NULL; - work->RunningElection = False; - work->ElectionCount = 0; - work->announce_interval = 0; - work->needelection = False; - work->needannounce = True; - work->lastannounce_time = time(NULL); - work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE; - work->dom_state = DOMAIN_NONE; - work->log_state = LOGON_NONE; + work->RunningElection = False; + work->ElectionCount = 0; + work->announce_interval = 0; + work->needelection = False; + work->needannounce = True; + work->lastannounce_time = time(NULL); + work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE; + work->dom_state = DOMAIN_NONE; + work->log_state = LOGON_NONE; - work->death_time = (ttl != PERMANENT_TTL) ? time(NULL)+(ttl*3) : PERMANENT_TTL; + work->death_time = (ttl != PERMANENT_TTL) ? time(NULL)+(ttl*3) : PERMANENT_TTL; - /* Make sure all token representations of workgroups are unique. */ + /* Make sure all token representations of workgroups are unique. */ - for (subrec = FIRST_SUBNET; subrec && (t == -1); - subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec)) - { - struct work_record *w; - for (w = subrec->workgrouplist; w && t == -1; w = w->next) - { - if (strequal(w->work_group, work->work_group)) - t = w->token; - } - } + for (subrec = FIRST_SUBNET; subrec && (t == -1); subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec)) { + struct work_record *w; + for (w = subrec->workgrouplist; w && t == -1; w = w->next) { + if (strnequal(w->work_group, work->work_group, sizeof(nstring)-1)) + t = w->token; + } + } - if (t == -1) - work->token = ++workgroup_count; - else - work->token = t; + if (t == -1) + work->token = ++workgroup_count; + else + work->token = t; - /* No known local master browser as yet. */ - *work->local_master_browser_name = '\0'; - - /* No known domain master browser as yet. */ - *work->dmb_name.name = '\0'; - zero_ip(&work->dmb_addr); - - /* WfWg uses 01040b01 */ - /* Win95 uses 01041501 */ - /* NTAS uses ???????? */ - work->ElectionCriterion = (MAINTAIN_LIST)|(BROWSER_ELECTION_VERSION<<8); - work->ElectionCriterion |= (lp_os_level() << 24); - if (lp_domain_master()) - work->ElectionCriterion |= 0x80; + /* No known local master browser as yet. */ + *work->local_master_browser_name = '\0'; + + /* No known domain master browser as yet. */ + *work->dmb_name.name = '\0'; + zero_ip(&work->dmb_addr); + + /* WfWg uses 01040b01 */ + /* Win95 uses 01041501 */ + /* NTAS uses ???????? */ + work->ElectionCriterion = (MAINTAIN_LIST)|(BROWSER_ELECTION_VERSION<<8); + work->ElectionCriterion |= (lp_os_level() << 24); + if (lp_domain_master()) + work->ElectionCriterion |= 0x80; - return work; + return work; } /******************************************************************* Remove a workgroup. - ******************************************************************/ +******************************************************************/ static struct work_record *remove_workgroup_from_subnet(struct subnet_record *subrec, struct work_record *work) { - struct work_record *ret_work = NULL; + struct work_record *ret_work = NULL; - DEBUG(3,("remove_workgroup: Removing workgroup %s\n", work->work_group)); + DEBUG(3,("remove_workgroup: Removing workgroup %s\n", work->work_group)); - ret_work = work->next; + ret_work = work->next; - remove_all_servers(work); + remove_all_servers(work); - if (!work->serverlist) - { - if (work->prev) - work->prev->next = work->next; - if (work->next) - work->next->prev = work->prev; + if (!work->serverlist) { + if (work->prev) + work->prev->next = work->next; + if (work->next) + work->next->prev = work->prev; - if (subrec->workgrouplist == work) - subrec->workgrouplist = work->next; + if (subrec->workgrouplist == work) + subrec->workgrouplist = work->next; - ZERO_STRUCTP(work); - SAFE_FREE(work); - } + ZERO_STRUCTP(work); + SAFE_FREE(work); + } - subrec->work_changed = True; + subrec->work_changed = True; - return ret_work; + return ret_work; } - /**************************************************************************** Find a workgroup in the workgroup list of a subnet. - **************************************************************************/ +**************************************************************************/ struct work_record *find_workgroup_on_subnet(struct subnet_record *subrec, const char *name) { - struct work_record *ret; + struct work_record *ret; - DEBUG(4, ("find_workgroup_on_subnet: workgroup search for %s on subnet %s: ", - name, subrec->subnet_name)); + DEBUG(4, ("find_workgroup_on_subnet: workgroup search for %s on subnet %s: ", + name, subrec->subnet_name)); - for (ret = subrec->workgrouplist; ret; ret = ret->next) - { - if (!strcmp(ret->work_group,name)) - { - DEBUGADD(4, ("found.\n")); - return(ret); - } - } - DEBUGADD(4, ("not found.\n")); - return NULL; + for (ret = subrec->workgrouplist; ret; ret = ret->next) { + if (strnequal(ret->work_group,name,sizeof(nstring)-1)) { + DEBUGADD(4, ("found.\n")); + return(ret); + } + } + DEBUGADD(4, ("not found.\n")); + return NULL; } /**************************************************************************** Create a workgroup in the workgroup list of the subnet. - **************************************************************************/ +**************************************************************************/ struct work_record *create_workgroup_on_subnet(struct subnet_record *subrec, const char *name, int ttl) { - struct work_record *work = NULL; + struct work_record *work = NULL; - DEBUG(4,("create_workgroup_on_subnet: creating group %s on subnet %s\n", - name, subrec->subnet_name)); + DEBUG(4,("create_workgroup_on_subnet: creating group %s on subnet %s\n", + name, subrec->subnet_name)); - if ((work = create_workgroup(name, ttl))) - { - add_workgroup(subrec, work); - - subrec->work_changed = True; + if ((work = create_workgroup(name, ttl))) { + add_workgroup(subrec, work); + subrec->work_changed = True; + return(work); + } - return(work); - } - - return NULL; + return NULL; } /**************************************************************************** Update a workgroup ttl. - **************************************************************************/ +**************************************************************************/ void update_workgroup_ttl(struct work_record *work, int ttl) { - if(work->death_time != PERMANENT_TTL) - work->death_time = time(NULL)+(ttl*3); - work->subnet->work_changed = True; + if(work->death_time != PERMANENT_TTL) + work->death_time = time(NULL)+(ttl*3); + work->subnet->work_changed = True; } /**************************************************************************** @@ -210,8 +206,8 @@ void update_workgroup_ttl(struct work_record *work, int ttl) static void fail_register(struct subnet_record *subrec, struct response_record *rrec, struct nmb_name *nmbname) { - DEBUG(0,("fail_register: Failed to register name %s on subnet %s.\n", - nmb_namestr(nmbname), subrec->subnet_name)); + DEBUG(0,("fail_register: Failed to register name %s on subnet %s.\n", + nmb_namestr(nmbname), subrec->subnet_name)); } /**************************************************************************** @@ -220,50 +216,38 @@ static void fail_register(struct subnet_record *subrec, struct response_record * void initiate_myworkgroup_startup(struct subnet_record *subrec, struct work_record *work) { - int i; + int i; - if(!strequal(lp_workgroup(), work->work_group)) - return; + if(!strnequal(lp_workgroup(), work->work_group,sizeof(nstring)-1)) + return; - /* If this is a broadcast subnet then start elections on it - if we are so configured. */ + /* If this is a broadcast subnet then start elections on it if we are so configured. */ - if ((subrec != unicast_subnet) && (subrec != remote_broadcast_subnet) && - (subrec != wins_server_subnet) && lp_preferred_master() && - lp_local_master()) - { - DEBUG(3, ("initiate_myworkgroup_startup: preferred master startup for \ + if ((subrec != unicast_subnet) && (subrec != remote_broadcast_subnet) && + (subrec != wins_server_subnet) && lp_preferred_master() && lp_local_master()) { + DEBUG(3, ("initiate_myworkgroup_startup: preferred master startup for \ workgroup %s on subnet %s\n", work->work_group, subrec->subnet_name)); - work->needelection = True; - work->ElectionCriterion |= (1<<3); - } + work->needelection = True; + work->ElectionCriterion |= (1<<3); + } - /* Register the WORKGROUP<0> and WORKGROUP<1e> names on the network. */ + /* Register the WORKGROUP<0> and WORKGROUP<1e> names on the network. */ - register_name(subrec,lp_workgroup(),0x0,samba_nb_type|NB_GROUP, - NULL, - fail_register,NULL); - - register_name(subrec,lp_workgroup(),0x1e,samba_nb_type|NB_GROUP, - NULL, - fail_register,NULL); - - for( i = 0; my_netbios_names(i); i++) - { - const char *name = my_netbios_names(i); - int stype = lp_default_server_announce() | (lp_local_master() ? - SV_TYPE_POTENTIAL_BROWSER : 0 ); + register_name(subrec,lp_workgroup(),0x0,samba_nb_type|NB_GROUP, NULL, fail_register,NULL); + register_name(subrec,lp_workgroup(),0x1e,samba_nb_type|NB_GROUP, NULL, fail_register,NULL); + + for( i = 0; my_netbios_names(i); i++) { + const char *name = my_netbios_names(i); + int stype = lp_default_server_announce() | (lp_local_master() ? SV_TYPE_POTENTIAL_BROWSER : 0 ); - if(!strequal(global_myname(), name)) - stype &= ~(SV_TYPE_MASTER_BROWSER|SV_TYPE_POTENTIAL_BROWSER| - SV_TYPE_DOMAIN_MASTER|SV_TYPE_DOMAIN_MEMBER); + if(!strequal(global_myname(), name)) + stype &= ~(SV_TYPE_MASTER_BROWSER|SV_TYPE_POTENTIAL_BROWSER|SV_TYPE_DOMAIN_MASTER|SV_TYPE_DOMAIN_MEMBER); - create_server_on_workgroup(work,name,stype|SV_TYPE_LOCAL_LIST_ONLY, - PERMANENT_TTL, - string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH)); - DEBUG(3,("initiate_myworkgroup_startup: Added server name entry %s \ + create_server_on_workgroup(work,name,stype|SV_TYPE_LOCAL_LIST_ONLY, PERMANENT_TTL, + string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH)); + DEBUG(3,("initiate_myworkgroup_startup: Added server name entry %s \ on subnet %s\n", name, subrec->subnet_name)); - } + } } /**************************************************************************** @@ -272,43 +256,34 @@ on subnet %s\n", name, subrec->subnet_name)); void dump_workgroups(BOOL force_write) { - struct subnet_record *subrec; - int debuglevel = force_write ? 0 : 4; + struct subnet_record *subrec; + int debuglevel = force_write ? 0 : 4; - for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec)) - { - if (subrec->workgrouplist) - { - struct work_record *work; - - if( DEBUGLVL( debuglevel ) ) - { - dbgtext( "dump_workgroups()\n " ); - dbgtext( "dump workgroup on subnet %15s: ", subrec->subnet_name ); - dbgtext( "netmask=%15s:\n", inet_ntoa(subrec->mask_ip) ); - } - - for (work = subrec->workgrouplist; work; work = work->next) - { - DEBUGADD( debuglevel, ( "\t%s(%d) current master browser = %s\n", - work->work_group, - work->token, - *work->local_master_browser_name - ? work->local_master_browser_name : "UNKNOWN" ) ); - if (work->serverlist) - { - struct server_record *servrec; - for (servrec = work->serverlist; servrec; servrec = servrec->next) - { - DEBUGADD( debuglevel, ( "\t\t%s %8x (%s)\n", - servrec->serv.name, - servrec->serv.type, - servrec->serv.comment ) ); - } - } - } - } - } + for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec)) { + if (subrec->workgrouplist) { + struct work_record *work; + + if( DEBUGLVL( debuglevel ) ) { + dbgtext( "dump_workgroups()\n " ); + dbgtext( "dump workgroup on subnet %15s: ", subrec->subnet_name ); + dbgtext( "netmask=%15s:\n", inet_ntoa(subrec->mask_ip) ); + } + + for (work = subrec->workgrouplist; work; work = work->next) { + DEBUGADD( debuglevel, ( "\t%s(%d) current master browser = %s\n", work->work_group, + work->token, *work->local_master_browser_name ? work->local_master_browser_name : "UNKNOWN" ) ); + if (work->serverlist) { + struct server_record *servrec; + for (servrec = work->serverlist; servrec; servrec = servrec->next) { + DEBUGADD( debuglevel, ( "\t\t%s %8x (%s)\n", + servrec->serv.name, + servrec->serv.type, + servrec->serv.comment ) ); + } + } + } + } + } } /**************************************************************************** @@ -318,25 +293,22 @@ void dump_workgroups(BOOL force_write) void expire_workgroups_and_servers(time_t t) { - struct subnet_record *subrec; + struct subnet_record *subrec; - for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec)) - { - struct work_record *work; - struct work_record *nextwork; - - for (work = subrec->workgrouplist; work; work = nextwork) - { - nextwork = work->next; - expire_servers(work, t); - - if ((work->serverlist == NULL) && (work->death_time != PERMANENT_TTL) && - ((t == -1) || (work->death_time < t))) - { - DEBUG(3,("expire_workgroups_and_servers: Removing timed out workgroup %s\n", - work->work_group)); - remove_workgroup_from_subnet(subrec, work); - } - } - } + for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec)) { + struct work_record *work; + struct work_record *nextwork; + + for (work = subrec->workgrouplist; work; work = nextwork) { + nextwork = work->next; + expire_servers(work, t); + + if ((work->serverlist == NULL) && (work->death_time != PERMANENT_TTL) && + ((t == -1) || (work->death_time < t))) { + DEBUG(3,("expire_workgroups_and_servers: Removing timed out workgroup %s\n", + work->work_group)); + remove_workgroup_from_subnet(subrec, work); + } + } + } } diff --git a/source3/nsswitch/pam_winbind.h b/source3/nsswitch/pam_winbind.h index fae635d806..0afcceb6aa 100644 --- a/source3/nsswitch/pam_winbind.h +++ b/source3/nsswitch/pam_winbind.h @@ -25,15 +25,18 @@ #define PAM_SM_ACCOUNT #define PAM_SM_PASSWORD -#if defined(SUNOS5) || defined(SUNOS4) || defined(HPUX) +#if defined(SUNOS5) || defined(SUNOS4) || defined(HPUX) || defined(FREEBSD) /* Solaris always uses dynamic pam modules */ #define PAM_EXTERN extern #include +#ifndef PAM_AUTHTOK_RECOVER_ERR #define PAM_AUTHTOK_RECOVER_ERR PAM_AUTHTOK_RECOVERY_ERR #endif +#endif + #ifdef HAVE_SECURITY_PAM_MODULES_H #include #endif diff --git a/source3/nsswitch/wb_client.c b/source3/nsswitch/wb_client.c index 7c5a8dd054..0c6644e9d0 100644 --- a/source3/nsswitch/wb_client.c +++ b/source3/nsswitch/wb_client.c @@ -264,6 +264,80 @@ static int wb_getgroups(const char *user, gid_t **groups) return -1; } +/* Call winbindd to initialise group membership. This is necessary for + some systems (i.e RH5.2) that do not have an initgroups function as part + of the nss extension. In RH5.2 this is implemented using getgrent() + which can be amazingly inefficient as well as having problems with + username case. */ + +int winbind_initgroups(char *user, gid_t gid) +{ + gid_t *tgr, *groups = NULL; + int result; + + /* Call normal initgroups if we are a local user */ + + if (!strchr(user, *lp_winbind_separator())) { + return initgroups(user, gid); + } + + result = wb_getgroups(user, &groups); + + DEBUG(10,("winbind_getgroups: %s: result = %s\n", user, + result == -1 ? "FAIL" : "SUCCESS")); + + if (result != -1) { + int ngroups = result, i; + BOOL is_member = False; + + /* Check to see if the passed gid is already in the list */ + + for (i = 0; i < ngroups; i++) { + if (groups[i] == gid) { + is_member = True; + } + } + + /* Add group to list if necessary */ + + if (!is_member) { + tgr = (gid_t *)Realloc(groups, sizeof(gid_t) * ngroups + 1); + + if (!tgr) { + errno = ENOMEM; + result = -1; + goto done; + } + else groups = tgr; + + groups[ngroups] = gid; + ngroups++; + } + + /* Set the groups */ + + if (sys_setgroups(ngroups, groups) == -1) { + errno = EPERM; + result = -1; + goto done; + } + + } else { + + /* The call failed. Set errno to something so we don't get + a bogus value from the last failed system call. */ + + errno = EIO; + } + + /* Free response data if necessary */ + + done: + SAFE_FREE(groups); + + return result; +} + /* Return a list of groups the user is a member of. This function is useful for large systems where inverting the group database would be too time consuming. If size is zero, list is not modified and the total diff --git a/source3/nsswitch/wbinfo.c b/source3/nsswitch/wbinfo.c index fcd7d2d508..0018e99f60 100644 --- a/source3/nsswitch/wbinfo.c +++ b/source3/nsswitch/wbinfo.c @@ -3,7 +3,7 @@ Winbind status program. - Copyright (C) Tim Potter 2000-2002 + Copyright (C) Tim Potter 2000-2003 Copyright (C) Andrew Bartlett 2002 This program is free software; you can redistribute it and/or modify @@ -219,15 +219,20 @@ static BOOL wbinfo_list_domains(void) /* show sequence numbers */ -static BOOL wbinfo_show_sequence(void) +static BOOL wbinfo_show_sequence(const char *domain) { + struct winbindd_request request; struct winbindd_response response; ZERO_STRUCT(response); + ZERO_STRUCT(request); + + if ( domain ) + fstrcpy( request.domain_name, domain ); /* Send request */ - if (winbindd_request(WINBINDD_SHOW_SEQUENCE, NULL, &response) != + if (winbindd_request(WINBINDD_SHOW_SEQUENCE, &request, &response) != NSS_STATUS_SUCCESS) return False; @@ -481,9 +486,18 @@ static BOOL wbinfo_auth_crap(char *username) parse_wbinfo_domain_user(username, name_domain, name_user); - fstrcpy(request.data.auth_crap.user, name_user); + if (push_utf8_fstring(request.data.auth_crap.user, name_user) == -1) { + d_printf("unable to create utf8 string for '%s'\n", + name_user); + return False; + } - fstrcpy(request.data.auth_crap.domain, name_domain); + if (push_utf8_fstring(request.data.auth_crap.domain, + name_domain) == -1) { + d_printf("unable to create utf8 string for '%s'\n", + name_domain); + return False; + } generate_random_buffer(request.data.auth_crap.chal, 8, False); @@ -682,17 +696,27 @@ static BOOL wbinfo_remove_user_from_group(char *string) /* Print domain users */ -static BOOL print_domain_users(void) +static BOOL print_domain_users(const char *domain) { + struct winbindd_request request; struct winbindd_response response; const char *extra_data; fstring name; /* Send request to winbind daemon */ + ZERO_STRUCT(request); ZERO_STRUCT(response); + + if (domain) { + /* '.' is the special sign for our own domwin */ + if ( strequal(domain, ".") ) + fstrcpy( request.domain_name, lp_workgroup() ); + else + fstrcpy( request.domain_name, domain ); + } - if (winbindd_request(WINBINDD_LIST_USERS, NULL, &response) != + if (winbindd_request(WINBINDD_LIST_USERS, &request, &response) != NSS_STATUS_SUCCESS) return False; @@ -713,15 +737,24 @@ static BOOL print_domain_users(void) /* Print domain groups */ -static BOOL print_domain_groups(void) +static BOOL print_domain_groups(const char *domain) { + struct winbindd_request request; struct winbindd_response response; const char *extra_data; fstring name; + ZERO_STRUCT(request); ZERO_STRUCT(response); - if (winbindd_request(WINBINDD_LIST_GROUPS, NULL, &response) != + if (domain) { + if ( strequal(domain, ".") ) + fstrcpy( request.domain_name, lp_workgroup() ); + else + fstrcpy( request.domain_name, domain ); + } + + if (winbindd_request(WINBINDD_LIST_GROUPS, &request, &response) != NSS_STATUS_SUCCESS) return False; @@ -845,6 +878,7 @@ static BOOL wbinfo_ping(void) enum { OPT_SET_AUTH_USER = 1000, OPT_GET_AUTH_USER, + OPT_DOMAIN_NAME, OPT_SEQUENCE }; @@ -854,8 +888,8 @@ int main(int argc, char **argv) poptContext pc; static char *string_arg; + static char *opt_domain_name; static int int_arg; - BOOL got_command = False; int result = 1; struct poptOption long_options[] = { @@ -864,8 +898,8 @@ int main(int argc, char **argv) /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */ - { "domain-users", 'u', POPT_ARG_NONE, 0, 'u', "Lists all domain users"}, - { "domain-groups", 'g', POPT_ARG_NONE, 0, 'g', "Lists all domain groups" }, + { "domain-users", 'u', POPT_ARG_NONE, 0, 'u', "Lists all domain users", "domain"}, + { "domain-groups", 'g', POPT_ARG_NONE, 0, 'g', "Lists all domain groups", "domain" }, { "WINS-by-name", 'N', POPT_ARG_STRING, &string_arg, 'N', "Converts NetBIOS name to IP", "NETBIOS-NAME" }, { "WINS-by-ip", 'I', POPT_ARG_STRING, &string_arg, 'I', "Converts IP address to NetBIOS name", "IP" }, { "name-to-sid", 'n', POPT_ARG_STRING, &string_arg, 'n', "Converts name to sid", "NAME" }, @@ -888,6 +922,7 @@ int main(int argc, char **argv) { "set-auth-user", 0, POPT_ARG_STRING, &string_arg, OPT_SET_AUTH_USER, "Store user and password used by winbindd (root only)", "user%password" }, { "get-auth-user", 0, POPT_ARG_NONE, NULL, OPT_GET_AUTH_USER, "Retrieve user and password used by winbindd (root only)", NULL }, { "ping", 'p', POPT_ARG_NONE, 0, 'p', "Ping winbindd to see if it is alive" }, + { "domain", 0, POPT_ARG_STRING, &opt_domain_name, OPT_DOMAIN_NAME, "Define to the domain to restrict operatio", "domain" }, POPT_COMMON_VERSION POPT_TABLEEND }; @@ -917,11 +952,7 @@ int main(int argc, char **argv) } while((opt = poptGetNextOpt(pc)) != -1) { - if (got_command) { - d_fprintf(stderr, "No more than one command may be specified at once.\n"); - exit(1); - } - got_command = True; + /* get the generic configuration parameters like --domain */ } poptFreeContext(pc); @@ -932,13 +963,13 @@ int main(int argc, char **argv) while((opt = poptGetNextOpt(pc)) != -1) { switch (opt) { case 'u': - if (!print_domain_users()) { + if (!print_domain_users(opt_domain_name)) { d_printf("Error looking up domain users\n"); goto done; } break; case 'g': - if (!print_domain_groups()) { + if (!print_domain_groups(opt_domain_name)) { d_printf("Error looking up domain groups\n"); goto done; } @@ -1007,7 +1038,7 @@ int main(int argc, char **argv) } break; case OPT_SEQUENCE: - if (!wbinfo_show_sequence()) { + if (!wbinfo_show_sequence(opt_domain_name)) { d_printf("Could not show sequence numbers\n"); goto done; } @@ -1086,6 +1117,9 @@ int main(int argc, char **argv) case OPT_GET_AUTH_USER: wbinfo_get_auth_user(); break; + /* generic configuration options */ + case OPT_DOMAIN_NAME: + break; default: d_fprintf(stderr, "Invalid option\n"); poptPrintHelp(pc, stderr, 0); diff --git a/source3/nsswitch/winbindd.c b/source3/nsswitch/winbindd.c index 8345fa11d0..6a0056f917 100644 --- a/source3/nsswitch/winbindd.c +++ b/source3/nsswitch/winbindd.c @@ -570,9 +570,9 @@ static void process_loop(void) message_dispatch(); - /* rescan the trusted domains list. This must be done - regularly to cope with transitive trusts */ - rescan_trusted_domains(False); + /* refresh the trusted domain cache */ + + rescan_trusted_domains(); /* Free up temporary memory */ @@ -829,7 +829,7 @@ int main(int argc, char **argv) setup_logging("winbindd", log_stdout); reopen_logs(); - DEBUG(1, ("winbindd version %s started.\n", VERSION ) ); + DEBUG(1, ("winbindd version %s started.\n", SAMBA_VERSION_STRING) ); DEBUGADD( 1, ( "Copyright The Samba Team 2000-2003\n" ) ); if (!reload_services_file(False)) { diff --git a/source3/nsswitch/winbindd_acct.c b/source3/nsswitch/winbindd_acct.c index 8abfd17110..0c06df7fdd 100644 --- a/source3/nsswitch/winbindd_acct.c +++ b/source3/nsswitch/winbindd_acct.c @@ -70,18 +70,13 @@ static BOOL winbindd_accountdb_init(void) if ( account_tdb ) return True; - - /* Nope. Try to open it */ - if (!(account_tdb = tdb_open_log(lock_path("winbindd_idmap.tdb"), 0, - TDB_DEFAULT, O_RDWR | O_CREAT, 0600))) - { - /* last chance -- maybe idmap has already opened it */ - if ( !(account_tdb = idmap_tdb_handle()) ) { + /* winbindd_idmap.tdb should always be opened by the idmap_init() + code first */ - DEBUG(0, ("winbindd_idmap_init: Unable to open idmap database\n")); - return False; - } + if ( !(account_tdb = idmap_tdb_handle()) ) { + DEBUG(0, ("winbindd_accountdb_init: Unable to retreive handle for database\n")); + return False; } /* yeah! */ diff --git a/source3/nsswitch/winbindd_ads.c b/source3/nsswitch/winbindd_ads.c index 7140dc35a0..c64359a224 100644 --- a/source3/nsswitch/winbindd_ads.c +++ b/source3/nsswitch/winbindd_ads.c @@ -28,10 +28,6 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_WINBIND -/* the realm of our primary LDAP server */ -static char *primary_realm; - - /* return our ads connections structure for a domain. We keep the connection open to make things faster @@ -58,10 +54,8 @@ static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain) SAFE_FREE(ads->auth.password); ads->auth.password = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL); - if (primary_realm) { - SAFE_FREE(ads->auth.realm); - ads->auth.realm = strdup(primary_realm); - } + SAFE_FREE(ads->auth.realm); + ads->auth.realm = strdup(lp_realm()); status = ads_connect(ads); if (!ADS_ERR_OK(status) || !ads->config.realm) { @@ -84,11 +78,6 @@ static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain) return NULL; } - /* remember our primary realm for trusted domain support */ - if (!primary_realm) { - primary_realm = strdup(ads->config.realm); - } - domain->private = (void *)ads; return ads; } @@ -123,7 +112,7 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain, } rc = ads_search_retry(ads, &res, "(objectCategory=user)", attrs); - if (!ADS_ERR_OK(rc)) { + if (!ADS_ERR_OK(rc) || !res) { DEBUG(1,("query_user_list ads_search: %s\n", ads_errstr(rc))); goto done; } @@ -190,7 +179,8 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain, DEBUG(3,("ads query_user_list gave %d entries\n", (*num_entries))); done: - if (res) ads_msgfree(ads, res); + if (res) + ads_msgfree(ads, res); return status; } @@ -224,7 +214,7 @@ static NTSTATUS enum_dom_groups(struct winbindd_domain *domain, } rc = ads_search_retry(ads, &res, "(objectCategory=group)", attrs); - if (!ADS_ERR_OK(rc)) { + if (!ADS_ERR_OK(rc) || !res) { DEBUG(1,("enum_dom_groups ads_search: %s\n", ads_errstr(rc))); goto done; } @@ -283,7 +273,8 @@ static NTSTATUS enum_dom_groups(struct winbindd_domain *domain, DEBUG(3,("ads enum_dom_groups gave %d entries\n", (*num_entries))); done: - if (res) ads_msgfree(ads, res); + if (res) + ads_msgfree(ads, res); return status; } @@ -378,7 +369,7 @@ static BOOL dn_lookup(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, SAFE_FREE(ldap_exp); SAFE_FREE(escaped_dn); - if (!ADS_ERR_OK(rc)) { + if (!ADS_ERR_OK(rc) || !res) { goto failed; } @@ -393,11 +384,15 @@ static BOOL dn_lookup(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, goto failed; } - if (res) ads_msgfree(ads, res); + if (res) + ads_msgfree(ads, res); + return True; failed: - if (res) ads_msgfree(ads, res); + if (res) + ads_msgfree(ads, res); + return False; } @@ -436,7 +431,7 @@ static NTSTATUS query_user(struct winbindd_domain *domain, rc = ads_search_retry(ads, &msg, ldap_exp, attrs); free(ldap_exp); free(sidstr); - if (!ADS_ERR_OK(rc)) { + if (!ADS_ERR_OK(rc) || !msg) { DEBUG(1,("query_user(sid=%s) ads_search: %s\n", sid_to_string(sid_string, sid), ads_errstr(rc))); goto done; } @@ -470,7 +465,8 @@ static NTSTATUS query_user(struct winbindd_domain *domain, DEBUG(3,("ads query_user gave %s\n", info->acct_name)); done: - if (msg) ads_msgfree(ads, msg); + if (msg) + ads_msgfree(ads, msg); return status; } @@ -511,7 +507,7 @@ static NTSTATUS lookup_usergroups_alt(struct winbindd_domain *domain, rc = ads_search_retry(ads, &res, ldap_exp, group_attrs); free(ldap_exp); - if (!ADS_ERR_OK(rc)) { + if (!ADS_ERR_OK(rc) || !res) { DEBUG(1,("lookup_usergroups ads_search member=%s: %s\n", user_dn, ads_errstr(rc))); return ads_ntstatus(rc); } @@ -555,8 +551,10 @@ static NTSTATUS lookup_usergroups_alt(struct winbindd_domain *domain, DEBUG(3,("ads lookup_usergroups (alt) for dn=%s\n", user_dn)); done: - if (res) ads_msgfree(ads, res); - if (msg) ads_msgfree(ads, msg); + if (res) + ads_msgfree(ads, res); + if (msg) + ads_msgfree(ads, msg); return status; } @@ -609,7 +607,7 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, free(ldap_exp); free(sidstr); - if (!ADS_ERR_OK(rc)) { + if (!ADS_ERR_OK(rc) || !msg) { DEBUG(1,("lookup_usergroups(sid=%s) ads_search: %s\n", sid_to_string(sid_string, sid), ads_errstr(rc))); goto done; } @@ -617,14 +615,16 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, user_dn = ads_pull_string(ads, mem_ctx, msg, "distinguishedName"); if (!user_dn) { DEBUG(1,("lookup_usergroups(sid=%s) ads_search did not return a a distinguishedName!\n", sid_to_string(sid_string, sid))); - if (msg) ads_msgfree(ads, msg); + if (msg) + ads_msgfree(ads, msg); goto done; } - if (msg) ads_msgfree(ads, msg); + if (msg) + ads_msgfree(ads, msg); rc = ads_search_retry_dn(ads, &msg, user_dn, attrs2); - if (!ADS_ERR_OK(rc)) { + if (!ADS_ERR_OK(rc) || !msg) { DEBUG(1,("lookup_usergroups(sid=%s) ads_search tokenGroups: %s\n", sid_to_string(sid_string, sid), ads_errstr(rc))); goto done; } @@ -638,7 +638,8 @@ static NTSTATUS lookup_usergroups(struct winbindd_domain *domain, count = ads_pull_sids(ads, mem_ctx, msg, "tokenGroups", &sids); - if (msg) ads_msgfree(ads, msg); + if (msg) + ads_msgfree(ads, msg); /* there must always be at least one group in the token, unless we are talking to a buggy Win2k server */ @@ -712,7 +713,7 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, free(ldap_exp); free(sidstr); - if (!ADS_ERR_OK(rc)) { + if (!ADS_ERR_OK(rc) || !res) { DEBUG(1,("query_user_list ads_search: %s\n", ads_errstr(rc))); goto done; } @@ -761,7 +762,8 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, status = NT_STATUS_OK; DEBUG(3,("ads lookup_groupmem for sid=%s\n", sid_to_string(sid_string, group_sid))); done: - if (res) ads_msgfree(ads, res); + if (res) + ads_msgfree(ads, res); return status; } @@ -808,6 +810,7 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain, struct cli_state *cli = NULL; /* i think we only need our forest and downlevel trusted domains */ uint32 flags = DS_DOMAIN_IN_FOREST | DS_DOMAIN_DIRECT_OUTBOUND; + char *contact_domain_name; DEBUG(3,("ads: trusted_domains\n")); @@ -816,14 +819,15 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain, *names = NULL; *dom_sids = NULL; - if ( !NT_STATUS_IS_OK(result = cm_fresh_connection(domain->name, PI_NETLOGON, &cli)) ) { + contact_domain_name = *domain->alt_name ? domain->alt_name : domain->name; + if ( !NT_STATUS_IS_OK(result = cm_fresh_connection(contact_domain_name, PI_NETLOGON, &cli)) ) { DEBUG(5, ("trusted_domains: Could not open a connection to %s for PIPE_NETLOGON (%s)\n", - domain->name, nt_errstr(result))); + contact_domain_name, nt_errstr(result))); return NT_STATUS_UNSUCCESSFUL; } if ( NT_STATUS_IS_OK(result) ) - result = cli_ds_enum_domain_trusts( cli, mem_ctx, cli->desthost, flags, &domains, &count ); + result = cli_ds_enum_domain_trusts( cli, mem_ctx, cli->desthost, flags, &domains, (unsigned int *)&count ); if ( NT_STATUS_IS_OK(result) && count) { diff --git a/source3/nsswitch/winbindd_cache.c b/source3/nsswitch/winbindd_cache.c index 2891a4fa68..bc6967dee1 100644 --- a/source3/nsswitch/winbindd_cache.c +++ b/source3/nsswitch/winbindd_cache.c @@ -432,7 +432,7 @@ static struct cache_entry *wcache_fetch(struct winbind_cache *cache, } centry = smb_xmalloc(sizeof(*centry)); - centry->data = data.dptr; + centry->data = (unsigned char *)data.dptr; centry->len = data.dsize; centry->ofs = 0; @@ -576,7 +576,7 @@ static void centry_end(struct cache_entry *centry, const char *format, ...) key.dptr = kstr; key.dsize = strlen(kstr); - data.dptr = centry->data; + data.dptr = (char *)centry->data; data.dsize = centry->ofs; tdb_store(wcache->tdb, key, data, TDB_REPLACE); @@ -924,7 +924,7 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain, centry = wcache_fetch(cache, domain, "NS/%s/%s", domain->name, uname); if (!centry) goto do_query; - *type = centry_uint32(centry); + *type = (enum SID_NAME_USE)centry_uint32(centry); sid2 = centry_sid(centry, mem_ctx); if (!sid2) { ZERO_STRUCTP(sid); @@ -988,7 +988,7 @@ static NTSTATUS sid_to_name(struct winbindd_domain *domain, if (!centry) goto do_query; if (NT_STATUS_IS_OK(centry->status)) { - *type = centry_uint32(centry); + *type = (enum SID_NAME_USE)centry_uint32(centry); *name = centry_string(centry, mem_ctx); } status = centry->status; diff --git a/source3/nsswitch/winbindd_cm.c b/source3/nsswitch/winbindd_cm.c index f07117b5ab..8513a46f8f 100644 --- a/source3/nsswitch/winbindd_cm.c +++ b/source3/nsswitch/winbindd_cm.c @@ -116,7 +116,8 @@ static NTSTATUS cm_open_connection(const char *domain, const int pipe_index, struct winbindd_cm_conn *new_conn) { NTSTATUS result; - char *ipc_username, *ipc_domain, *ipc_password; + char *machine_password; + char *machine_krb5_principal, *ipc_username, *ipc_domain, *ipc_password; struct in_addr dc_ip; int i; BOOL retry = True; @@ -137,10 +138,15 @@ static NTSTATUS cm_open_connection(const char *domain, const int pipe_index, /* Initialise SMB connection */ - cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password); + /* grab stored passwords */ + machine_password = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL); + + if (asprintf(&machine_krb5_principal, "%s$@%s", global_myname(), lp_realm()) == -1) { + SAFE_FREE(machine_password); + return NT_STATUS_NO_MEMORY; + } - DEBUG(5, ("connecting to %s from %s with username [%s]\\[%s]\n", - new_conn->controller, global_myname(), ipc_domain, ipc_username)); + cm_get_ipc_userpass(&ipc_username, &ipc_domain, &ipc_password); for (i = 0; retry && (i < 3); i++) { BOOL got_mutex; @@ -150,12 +156,99 @@ static NTSTATUS cm_open_connection(const char *domain, const int pipe_index, continue; } - result = cli_full_connection(&new_conn->cli, global_myname(), new_conn->controller, - &dc_ip, 0, "IPC$", "IPC", ipc_username, ipc_domain, - ipc_password, CLI_FULL_CONNECTION_ANNONYMOUS_FALLBACK, - Undefined, &retry); - - secrets_named_mutex_release(new_conn->controller); + new_conn->cli = NULL; + result = cli_start_connection(&new_conn->cli, global_myname(), + new_conn->controller, + &dc_ip, 0, Undefined, + CLI_FULL_CONNECTION_USE_KERBEROS, + &retry); + + if (NT_STATUS_IS_OK(result)) { + + /* reset the error code */ + result = NT_STATUS_UNSUCCESSFUL; + + /* Krb5 session */ + + if ((lp_security() == SEC_ADS) + && (new_conn->cli->protocol >= PROTOCOL_NT1 && new_conn->cli->capabilities & CAP_EXTENDED_SECURITY)) { + new_conn->cli->use_kerberos = True; + DEBUG(5, ("connecting to %s from %s with kerberos principal [%s]\n", + new_conn->controller, global_myname(), machine_krb5_principal)); + + result = NT_STATUS_OK; + + if (!cli_session_setup_spnego(new_conn->cli, machine_krb5_principal, + machine_password, + domain)) { + result = cli_nt_error(new_conn->cli); + DEBUG(4,("failed kerberos session setup with %s\n", nt_errstr(result))); + if (NT_STATUS_IS_OK(result)) + result = NT_STATUS_UNSUCCESSFUL; + } + } + new_conn->cli->use_kerberos = False; + + /* only do this is we have a username/password for thr IPC$ connection */ + + if ( !NT_STATUS_IS_OK(result) + && new_conn->cli->sec_mode & NEGOTIATE_SECURITY_CHALLENGE_RESPONSE + && strlen(ipc_username) ) + { + DEBUG(5, ("connecting to %s from %s with username [%s]\\[%s]\n", + new_conn->controller, global_myname(), ipc_domain, ipc_username)); + + result = NT_STATUS_OK; + + if (!cli_session_setup(new_conn->cli, ipc_username, + ipc_password, strlen(ipc_password)+1, + ipc_password, strlen(ipc_password)+1, + domain)) { + result = cli_nt_error(new_conn->cli); + DEBUG(4,("failed authenticated session setup with %s\n", nt_errstr(result))); + if (NT_STATUS_IS_OK(result)) + result = NT_STATUS_UNSUCCESSFUL; + } + } + + /* anonymous is all that is left if we get to here */ + + if (!NT_STATUS_IS_OK(result)) { + + DEBUG(5, ("anonymous connection attempt to %s from %s\n", + new_conn->controller, global_myname())); + + result = NT_STATUS_OK; + + if (!cli_session_setup(new_conn->cli, "", NULL, 0, NULL, 0, "")) + { + result = cli_nt_error(new_conn->cli); + DEBUG(4,("failed anonymous session setup with %s\n", nt_errstr(result))); + if (NT_STATUS_IS_OK(result)) + result = NT_STATUS_UNSUCCESSFUL; + } + + } + + if (NT_STATUS_IS_OK(result) && !cli_send_tconX(new_conn->cli, "IPC$", "IPC", + "", 0)) { + result = cli_nt_error(new_conn->cli); + DEBUG(1,("failed tcon_X with %s\n", nt_errstr(result))); + cli_shutdown(new_conn->cli); + if (NT_STATUS_IS_OK(result)) { + result = NT_STATUS_UNSUCCESSFUL; + } + } + } + + if (NT_STATUS_IS_OK(result)) { + struct ntuser_creds creds; + init_creds(&creds, ipc_username, ipc_domain, ipc_password); + cli_init_creds(new_conn->cli, &creds); + } + + if (got_mutex) + secrets_named_mutex_release(new_conn->controller); if (NT_STATUS_IS_OK(result)) break; @@ -164,6 +257,7 @@ static NTSTATUS cm_open_connection(const char *domain, const int pipe_index, SAFE_FREE(ipc_username); SAFE_FREE(ipc_domain); SAFE_FREE(ipc_password); + SAFE_FREE(machine_password); if (!NT_STATUS_IS_OK(result)) { add_failed_connection_entry(domain, new_conn->controller, result); @@ -479,6 +573,7 @@ NTSTATUS cm_get_netlogon_cli(const char *domain, struct winbindd_cm_conn *conn; fstring lock_name; BOOL got_mutex; + struct winbindd_domain *wb_domain = NULL; if (!cli) return NT_STATUS_INVALID_PARAMETER; @@ -520,6 +615,17 @@ NTSTATUS cm_get_netlogon_cli(const char *domain, if ( sec_channel_type == SEC_CHAN_DOMAIN ) fstr_sprintf(conn->cli->mach_acct, "%s$", lp_workgroup()); + /* we need the short form of the domain name for the schanel + rpc bind. What if we fail? I don't think we should ever get + a request for a domain name not in our list but I'm not bailing + out if we do since I'm not 10% certain about this --jerry */ + + if ( (wb_domain = find_domain_from_name( domain )) != NULL ) { + DEBUG(5,("cm_get_netlogon_cli: Using short for of domain name [%s] for netlogon rpc bind\n", + wb_domain->name)); + fstrcpy( conn->cli->domain, wb_domain->name); + } + result = cli_nt_establish_netlogon(conn->cli, sec_channel_type, trust_passwd); if (got_mutex) diff --git a/source3/nsswitch/winbindd_group.c b/source3/nsswitch/winbindd_group.c index 96c121685a..fba427536c 100644 --- a/source3/nsswitch/winbindd_group.c +++ b/source3/nsswitch/winbindd_group.c @@ -821,17 +821,29 @@ enum winbindd_result winbindd_list_groups(struct winbindd_cli_state *state) { uint32 total_entries = 0; struct winbindd_domain *domain; + const char *which_domain; char *extra_data = NULL; char *ted = NULL; unsigned int extra_data_len = 0, i; DEBUG(3, ("[%5lu]: list groups\n", (unsigned long)state->pid)); + /* Ensure null termination */ + state->request.domain_name[sizeof(state->request.domain_name)-1]='\0'; + which_domain = state->request.domain_name; + /* Enumerate over trusted domains */ for (domain = domain_list(); domain; domain = domain->next) { struct getent_state groups; + /* if we have a domain name restricting the request and this + one in the list doesn't match, then just bypass the remainder + of the loop */ + + if ( *which_domain && !strequal(which_domain, domain->name) ) + continue; + ZERO_STRUCT(groups); /* Get list of sam groups */ diff --git a/source3/nsswitch/winbindd_misc.c b/source3/nsswitch/winbindd_misc.c index 740b760b93..88fbb5ee00 100644 --- a/source3/nsswitch/winbindd_misc.c +++ b/source3/nsswitch/winbindd_misc.c @@ -35,6 +35,8 @@ enum winbindd_result winbindd_check_machine_acct(struct winbindd_cli_state *stat int num_retries = 0; struct cli_state *cli; uint32 sec_channel_type; + const char *contact_domain_name = NULL; + DEBUG(3, ("[%5lu]: check machine account\n", (unsigned long)state->pid)); /* Get trust account password */ @@ -46,11 +48,21 @@ enum winbindd_result winbindd_check_machine_acct(struct winbindd_cli_state *stat goto done; } + + /* use the realm name if appropriate and possible */ + + if ( lp_security() == SEC_ADS ) + contact_domain_name = lp_realm(); + + if ( !contact_domain_name || !*contact_domain_name ) + contact_domain_name = lp_workgroup(); + /* This call does a cli_nt_setup_creds() which implicitly checks the trust account password. */ - /* Don't shut this down - it belongs to the connection cache code */ - result = cm_get_netlogon_cli(lp_workgroup(), trust_passwd, sec_channel_type, True, &cli); + + result = cm_get_netlogon_cli(contact_domain_name, + trust_passwd, sec_channel_type, True, &cli); if (!NT_STATUS_IS_OK(result)) { DEBUG(3, ("could not open handle to NETLOGON pipe\n")); @@ -148,9 +160,14 @@ enum winbindd_result winbindd_show_sequence(struct winbindd_cli_state *state) { struct winbindd_domain *domain; char *extra_data = NULL; + const char *which_domain; DEBUG(3, ("[%5lu]: show sequence\n", (unsigned long)state->pid)); + /* Ensure null termination */ + state->request.domain_name[sizeof(state->request.domain_name)-1]='\0'; + which_domain = state->request.domain_name; + extra_data = strdup(""); /* this makes for a very simple data format, and is easily parsable as well @@ -158,6 +175,13 @@ enum winbindd_result winbindd_show_sequence(struct winbindd_cli_state *state) for (domain = domain_list(); domain; domain = domain->next) { char *s; + /* if we have a domain name restricting the request and this + one in the list doesn't match, then just bypass the remainder + of the loop */ + + if ( *which_domain && !strequal(which_domain, domain->name) ) + continue; + domain->methods->sequence_number(domain, &domain->sequence_number); if (DOM_SEQUENCE_NONE == (unsigned)domain->sequence_number) { @@ -194,7 +218,7 @@ enum winbindd_result winbindd_info(struct winbindd_cli_state *state) DEBUG(3, ("[%5lu]: request misc info\n", (unsigned long)state->pid)); state->response.data.info.winbind_separator = *lp_winbind_separator(); - fstrcpy(state->response.data.info.samba_version, VERSION); + fstrcpy(state->response.data.info.samba_version, SAMBA_VERSION_STRING); return WINBINDD_OK; } diff --git a/source3/nsswitch/winbindd_nss.h b/source3/nsswitch/winbindd_nss.h index c4407bbe31..41fecd2816 100644 --- a/source3/nsswitch/winbindd_nss.h +++ b/source3/nsswitch/winbindd_nss.h @@ -157,6 +157,7 @@ struct winbindd_request { enum winbindd_cmd cmd; /* Winbindd command to execute */ pid_t pid; /* pid of calling process */ uint32 flags; /* flags relavant to a given request */ + fstring domain_name; /* name of domain for which the request applies */ union { fstring winsreq; /* WINS request */ diff --git a/source3/nsswitch/winbindd_pam.c b/source3/nsswitch/winbindd_pam.c index a8908487c1..21ae6478de 100644 --- a/source3/nsswitch/winbindd_pam.c +++ b/source3/nsswitch/winbindd_pam.c @@ -65,7 +65,7 @@ enum winbindd_result winbindd_pam_auth(struct winbindd_cli_state *state) time_t last_change_time; uint32 sec_channel_type; NET_USER_INFO_3 info3; - struct cli_state *cli = NULL; + struct cli_state *cli; uchar chal[8]; TALLOC_CTX *mem_ctx = NULL; DATA_BLOB lm_resp; @@ -75,6 +75,7 @@ enum winbindd_result winbindd_pam_auth(struct winbindd_cli_state *state) unsigned char local_lm_response[24]; unsigned char local_nt_response[24]; const char *contact_domain; + BOOL retry; /* Ensure null termination */ state->request.data.auth.user[sizeof(state->request.data.auth.user)-1]='\0'; @@ -127,6 +128,8 @@ enum winbindd_result winbindd_pam_auth(struct winbindd_cli_state *state) do { ZERO_STRUCT(info3); ZERO_STRUCT(ret_creds); + cli = NULL; + retry = False; /* Don't shut this down - it belongs to the connection cache code */ result = cm_get_netlogon_cli(contact_domain, trust_passwd, @@ -154,15 +157,14 @@ enum winbindd_result winbindd_pam_auth(struct winbindd_cli_state *state) "password was changed and we didn't know it. Killing connections to domain %s\n", name_domain)); winbindd_cm_flush(); - cli->fd = -1; + retry = True; } /* We have to try a second time as cm_get_netlogon_cli might not yet have noticed that the DC has killed our connection. */ - } while ( (attempts < 2) && (cli->fd == -1) ); - + } while ( (attempts < 2) && retry ); clnt_deal_with_creds(cli->sess_key, &(cli->clnt_cred), &ret_creds); @@ -170,10 +172,8 @@ enum winbindd_result winbindd_pam_auth(struct winbindd_cli_state *state) netsamlogon_cache_store( cli->mem_ctx, &info3 ); wcache_invalidate_samlogon(find_domain_from_name(name_domain), &info3); } - - + done: - /* give us a more useful (more correct?) error code */ if ((NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND) || (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)))) { result = NT_STATUS_NO_LOGON_SERVERS; @@ -206,7 +206,7 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state) time_t last_change_time; uint32 sec_channel_type; NET_USER_INFO_3 info3; - struct cli_state *cli = NULL; + struct cli_state *cli; TALLOC_CTX *mem_ctx = NULL; char *user = NULL; const char *domain = NULL; @@ -214,6 +214,7 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state) const char *contact_domain; DOM_CRED ret_creds; int attempts = 0; + BOOL retry; DATA_BLOB lm_resp, nt_resp; @@ -226,10 +227,8 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state) } /* Ensure null termination */ - state->request.data.auth_crap.user[sizeof(state->request.data.auth_crap.user)-1]='\0'; - - /* Ensure null termination */ - state->request.data.auth_crap.domain[sizeof(state->request.data.auth_crap.domain)-1]='\0'; + state->request.data.auth_crap.user[sizeof(state->request.data.auth_crap.user)-1]=0; + state->request.data.auth_crap.domain[sizeof(state->request.data.auth_crap.domain)-1]=0; if (!(mem_ctx = talloc_init("winbind pam auth crap for (utf8) %s", state->request.data.auth_crap.user))) { DEBUG(0, ("winbindd_pam_auth_crap: could not talloc_init()!\n")); @@ -239,12 +238,16 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state) if (pull_utf8_talloc(mem_ctx, &user, state->request.data.auth_crap.user) == (size_t)-1) { DEBUG(0, ("winbindd_pam_auth_crap: pull_utf8_talloc failed!\n")); + result = NT_STATUS_UNSUCCESSFUL; + goto done; } if (*state->request.data.auth_crap.domain) { char *dom = NULL; if (pull_utf8_talloc(mem_ctx, &dom, state->request.data.auth_crap.domain) == (size_t)-1) { DEBUG(0, ("winbindd_pam_auth_crap: pull_utf8_talloc failed!\n")); + result = NT_STATUS_UNSUCCESSFUL; + goto done; } domain = dom; } else if (lp_winbind_use_default_domain()) { @@ -268,6 +271,8 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state) char *wrk = NULL; if (pull_utf8_talloc(mem_ctx, &wrk, state->request.data.auth_crap.workstation) == (size_t)-1) { DEBUG(0, ("winbindd_pam_auth_crap: pull_utf8_talloc failed!\n")); + result = NT_STATUS_UNSUCCESSFUL; + goto done; } workstation = wrk; } else { @@ -296,6 +301,8 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state) do { ZERO_STRUCT(info3); ZERO_STRUCT(ret_creds); + cli = NULL; + retry = False; /* Don't shut this down - it belongs to the connection cache code */ result = cm_get_netlogon_cli(contact_domain, trust_passwd, sec_channel_type, False, &cli); @@ -325,14 +332,14 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state) "password was changed and we didn't know it. Killing connections to domain %s\n", domain)); winbindd_cm_flush(); - cli->fd = -1; + retry = True; } /* We have to try a second time as cm_get_netlogon_cli might not yet have noticed that the DC has killed our connection. */ - } while ( (attempts < 2) && (cli->fd == -1) ); + } while ( (attempts < 2) && retry ); clnt_deal_with_creds(cli->sess_key, &(cli->clnt_cred), &ret_creds); @@ -353,7 +360,6 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state) } done: - /* give us a more useful (more correct?) error code */ if ((NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND) || (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)))) { result = NT_STATUS_NO_LOGON_SERVERS; diff --git a/source3/nsswitch/winbindd_rpc.c b/source3/nsswitch/winbindd_rpc.c index 33339d7ca0..8bd2c66511 100644 --- a/source3/nsswitch/winbindd_rpc.c +++ b/source3/nsswitch/winbindd_rpc.c @@ -295,7 +295,7 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain, if (NT_STATUS_IS_OK(result)) { sid_copy(sid, &sids[0]); - *type = types[0]; + *type = (enum SID_NAME_USE)types[0]; } return result; @@ -331,7 +331,7 @@ static NTSTATUS sid_to_name(struct winbindd_domain *domain, hnd && hnd->cli && hnd->cli->fd == -1); if (NT_STATUS_IS_OK(result)) { - *type = types[0]; + *type = (enum SID_NAME_USE)types[0]; *name = names[0]; DEBUG(5,("Mapped sid to [%s]\\[%s]\n", domains[0], *name)); diff --git a/source3/nsswitch/winbindd_sid.c b/source3/nsswitch/winbindd_sid.c index 98a6fce24b..ac1ee11555 100644 --- a/source3/nsswitch/winbindd_sid.c +++ b/source3/nsswitch/winbindd_sid.c @@ -185,12 +185,17 @@ enum winbindd_result winbindd_uid_to_sid(struct winbindd_cli_state *state) { DOM_SID sid; - /* Bug out if the uid isn't in the winbind range */ - +#if 0 /* JERRY */ + /* we cannot do this check this anymore since a domain member of + a Samba domain may share unix accounts via NIS or LDAP. In this + case the uid/gid will be out of winbindd's range but still might + be resolved to a SID via an ldap idmap backend */ + if ((state->request.data.uid < server_state.uid_low ) || (state->request.data.uid > server_state.uid_high)) { return WINBINDD_ERROR; } +#endif DEBUG(3, ("[%5lu]: uid to sid %lu\n", (unsigned long)state->pid, (unsigned long)state->request.data.uid)); @@ -214,12 +219,17 @@ enum winbindd_result winbindd_gid_to_sid(struct winbindd_cli_state *state) { DOM_SID sid; - /* Bug out if the gid isn't in the winbind range */ - +#if 0 /* JERRY */ + /* we cannot do this check this anymore since a domain member of + a Samba domain may share unix accounts via NIS or LDAP. In this + case the uid/gid will be out of winbindd's range but still might + be resolved to a SID via an ldap idmap backend */ + if ((state->request.data.gid < server_state.gid_low) || (state->request.data.gid > server_state.gid_high)) { return WINBINDD_ERROR; } +#endif DEBUG(3, ("[%5lu]: gid to sid %lu\n", (unsigned long)state->pid, (unsigned long)state->request.data.gid)); diff --git a/source3/nsswitch/winbindd_user.c b/source3/nsswitch/winbindd_user.c index c0b0d94167..eab88c842e 100644 --- a/source3/nsswitch/winbindd_user.c +++ b/source3/nsswitch/winbindd_user.c @@ -575,6 +575,7 @@ enum winbindd_result winbindd_list_users(struct winbindd_cli_state *state) { struct winbindd_domain *domain; WINBIND_USERINFO *info; + const char *which_domain; uint32 num_entries = 0, total_entries = 0; char *ted, *extra_data = NULL; int extra_data_len = 0; @@ -586,13 +587,24 @@ enum winbindd_result winbindd_list_users(struct winbindd_cli_state *state) if (!(mem_ctx = talloc_init("winbindd_list_users"))) return WINBINDD_ERROR; + /* Ensure null termination */ + state->request.domain_name[sizeof(state->request.domain_name)-1]='\0'; + which_domain = state->request.domain_name; + /* Enumerate over trusted domains */ for (domain = domain_list(); domain; domain = domain->next) { NTSTATUS status; struct winbindd_methods *methods; unsigned int i; - + + /* if we have a domain name restricting the request and this + one in the list doesn't match, then just bypass the remainder + of the loop */ + + if ( *which_domain && !strequal(which_domain, domain->name) ) + continue; + methods = domain->methods; /* Query display info */ diff --git a/source3/nsswitch/winbindd_util.c b/source3/nsswitch/winbindd_util.c index a810e503a0..25de4eff71 100644 --- a/source3/nsswitch/winbindd_util.c +++ b/source3/nsswitch/winbindd_util.c @@ -80,6 +80,14 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const DOM_SID *sid) { struct winbindd_domain *domain; + char *contact_name; + const char *alternative_name = NULL; + + /* ignore alt_name if we are not in an AD domain */ + + if ( (lp_security() == SEC_ADS) && alt_name && *alt_name) { + alternative_name = alt_name; + } /* We can't call domain_list() as this function is called from init_domain_list() and we'll get stuck in a loop. */ @@ -88,9 +96,9 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const 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) { + if (alternative_name && *alternative_name) { + if (strcasecmp(alternative_name, domain->name) == 0 || + strcasecmp(alternative_name, domain->alt_name) == 0) { return domain; } } @@ -107,13 +115,13 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const ZERO_STRUCTP(domain); /* prioritise the short name */ - if (strchr_m(domain_name, '.') && alt_name && *alt_name) { - fstrcpy(domain->name, alt_name); + if (strchr_m(domain_name, '.') && alternative_name && *alternative_name) { + fstrcpy(domain->name, alternative_name); fstrcpy(domain->alt_name, domain_name); } else { fstrcpy(domain->name, domain_name); - if (alt_name) { - fstrcpy(domain->alt_name, alt_name); + if (alternative_name) { + fstrcpy(domain->alt_name, alternative_name); } } @@ -125,10 +133,12 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const sid_copy(&domain->sid, sid); } - /* see if this is a native mode win2k domain */ + /* see if this is a native mode win2k domain (use realm name if possible) */ - domain->native_mode = cm_check_for_native_mode_win2k( domain_name ); - DEBUG(3,("add_trusted_domain: %s is a %s mode domain\n", domain_name, + contact_name = *domain->alt_name ? domain->alt_name : domain->name; + domain->native_mode = cm_check_for_native_mode_win2k( contact_name ); + + DEBUG(3,("add_trusted_domain: %s is a %s mode domain\n", contact_name, domain->native_mode ? "native" : "mixed (or NT4)" )); /* Link to domain list */ @@ -141,57 +151,80 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const return domain; } +/******************************************************************** + Periodically we need to refresh the trusted domain cache for smbd +********************************************************************/ -/* +void rescan_trusted_domains( void ) +{ + static time_t last_scan; + time_t now = time(NULL); + struct winbindd_domain *mydomain = NULL; + + /* see if the time has come... */ + + if ( (now > last_scan) && ((now-last_scan) < WINBINDD_RESCAN_FREQ) ) + return; + + /* get the handle for our domain */ + + if ( (mydomain = find_domain_from_name(lp_workgroup())) == NULL ) { + DEBUG(0,("rescan_trusted_domains: Can't find my own domain!\n")); + return; + } + + /* this will only add new domains we didn't already know about */ + + add_trusted_domains( mydomain ); + + last_scan = now; + + return; +} + +/******************************************************************** rescan our domains looking for new trusted domains - */ -void rescan_trusted_domains(BOOL force) +********************************************************************/ + +void add_trusted_domains( struct winbindd_domain *domain ) { - struct winbindd_domain *domain; TALLOC_CTX *mem_ctx; - static time_t last_scan; - time_t t = time(NULL); + NTSTATUS result; + time_t t; + char **names; + char **alt_names; + int num_domains = 0; + DOM_SID *dom_sids, null_sid; + int i; + struct winbindd_domain *new_domain; /* trusted domains might be disabled */ if (!lp_allow_trusted_domains()) { return; } - /* Only rescan every few minutes but force if necessary */ - - if (((unsigned)(t - last_scan) < WINBINDD_RESCAN_FREQ) && !force) - return; - - last_scan = t; - DEBUG(1, ("scanning trusted domain list\n")); if (!(mem_ctx = talloc_init("init_domain_list"))) return; + + ZERO_STRUCTP(&null_sid); - for (domain = _domain_list; domain; domain = domain->next) { - NTSTATUS result; - char **names; - char **alt_names; - int num_domains = 0; - DOM_SID *dom_sids, null_sid; - int i; - struct winbindd_domain *new_domain; + t = time(NULL); + + /* ask the DC what domains it trusts */ + + result = domain->methods->trusted_domains(domain, mem_ctx, (unsigned int *)&num_domains, + &names, &alt_names, &dom_sids); - ZERO_STRUCTP(&null_sid); - - result = domain->methods->trusted_domains(domain, mem_ctx, &num_domains, - &names, &alt_names, &dom_sids); - if (!NT_STATUS_IS_OK(result)) { - continue; - } + if ( NT_STATUS_IS_OK(result) ) { /* Add each domain to the trusted domain list */ for(i = 0; i < num_domains; i++) { DEBUG(10,("Found domain %s\n", names[i])); add_trusted_domain(names[i], alt_names?alt_names[i]:NULL, - domain->methods, &dom_sids[i]); + domain->methods, &dom_sids[i]); /* if the SID was empty, we better set it now */ @@ -212,7 +245,7 @@ void rescan_trusted_domains(BOOL force) result = domain->methods->domain_sid( new_domain, &new_domain->sid ); if ( NT_STATUS_IS_OK(result) ) - sid_copy( &dom_sids[i], &domain->sid ); + sid_copy( &dom_sids[i], &new_domain->sid ); } /* store trusted domain in the cache */ @@ -234,18 +267,26 @@ BOOL init_domain_list(void) free_domain_list(); /* Add ourselves as the first entry */ - domain = add_trusted_domain( lp_workgroup(), NULL, &cache_methods, NULL); + + domain = add_trusted_domain( lp_workgroup(), lp_realm(), &cache_methods, NULL); + + /* get any alternate name for the primary domain */ + + cache_methods.alternate_name(domain); + + /* now we have the correct netbios (short) domain name */ + + if ( *domain->name ) + set_global_myworkgroup( domain->name ); + if (!secrets_fetch_domain_sid(domain->name, &domain->sid)) { DEBUG(1, ("Could not fetch sid for our domain %s\n", domain->name)); return False; } - /* get any alternate name for the primary domain */ - cache_methods.alternate_name(domain); - /* do an initial scan for trusted domains */ - rescan_trusted_domains(True); + add_trusted_domains(domain); return True; } diff --git a/source3/nsswitch/wins.c b/source3/nsswitch/wins.c index 87dac60192..0fc4e46cdb 100644 --- a/source3/nsswitch/wins.c +++ b/source3/nsswitch/wins.c @@ -260,54 +260,105 @@ int lookup(nsd_file_t *rq) } #else + +/* Allocate some space from the nss static buffer. The buffer and buflen + are the pointers passed in by the C library to the _nss_*_* + functions. */ + +static char *get_static(char **buffer, int *buflen, int len) +{ + char *result; + + /* Error check. We return false if things aren't set up right, or + there isn't enough buffer space left. */ + + if ((buffer == NULL) || (buflen == NULL) || (*buflen < len)) { + return NULL; + } + + /* Return an index into the static buffer */ + + result = *buffer; + *buffer += len; + *buflen -= len; + + return result; +} + /**************************************************************************** gethostbyname() - we ignore any domain portion of the name and only handle names that are at most 15 characters long **************************************************************************/ NSS_STATUS -_nss_wins_gethostbyname_r(const char *name, struct hostent *he, - char *buffer, size_t buflen, int *errnop, - int *h_errnop) +_nss_wins_gethostbyname_r(const char *hostname, struct hostent *he, + char *buffer, size_t buflen, int *h_errnop) { - char **host_addresses; struct in_addr *ip_list; int i, count; - size_t namelen = strlen(name) + 1; + fstring name; + size_t namelen; memset(he, '\0', sizeof(*he)); + fstrcpy(name, hostname); + + /* Do lookup */ ip_list = lookup_byname_backend(name, &count); - if (!ip_list) { - return NSS_STATUS_NOTFOUND; - } - if (buflen < namelen + (2*count+1)*INADDRSZ) { - /* no ENOMEM error type?! */ + if (!ip_list) return NSS_STATUS_NOTFOUND; - } + /* Copy h_name */ - host_addresses = (char **)buffer; - he->h_addr_list = host_addresses; - host_addresses[count] = NULL; - buffer += (count + 1) * INADDRSZ; - buflen += (count + 1) * INADDRSZ; - he->h_addrtype = AF_INET; - he->h_length = INADDRSZ; + namelen = strlen(name) + 1; + + if ((he->h_name = get_static(&buffer, &buflen, namelen)) == NULL) + return NSS_STATUS_TRYAGAIN; + + memcpy(he->h_name, name, namelen); + + /* Copy h_addr_list, align to pointer boundary first */ - for (i=0;ih_addr_list = (char **)get_static( + &buffer, &buflen, (count + 1) * sizeof(char *))) == NULL) + return NSS_STATUS_TRYAGAIN; + + for (i = 0; i < count; i++) { + if ((he->h_addr_list[i] = get_static(&buffer, &buflen, + INADDRSZ)) == NULL) + return NSS_STATUS_TRYAGAIN; + memcpy(he->h_addr_list[i], &ip_list[i], INADDRSZ); } + he->h_addr_list[count] = NULL; + if (ip_list) free(ip_list); - memcpy(buffer, name, namelen); - he->h_name = buffer; + /* Set h_addr_type and h_length */ + + he->h_addrtype = AF_INET; + he->h_length = INADDRSZ; + + /* Set h_aliases */ + + if ((i = (unsigned long)(buffer) % sizeof(char*)) != 0) + i = sizeof(char*) - i; + + if (get_static(&buffer, &buflen, i) == NULL) + return NSS_STATUS_TRYAGAIN; + + if ((he->h_aliases = (char **)get_static( + &buffer, &buflen, sizeof(char *))) == NULL) + return NSS_STATUS_TRYAGAIN; + + he->h_aliases[0] = NULL; return NSS_STATUS_SUCCESS; } @@ -315,15 +366,14 @@ _nss_wins_gethostbyname_r(const char *name, struct hostent *he, NSS_STATUS _nss_wins_gethostbyname2_r(const char *name, int af, struct hostent *he, - char *buffer, size_t buflen, int *errnop, - int *h_errnop) + char *buffer, size_t buflen, int *h_errnop) { if(af!=AF_INET) { *h_errnop = NO_DATA; - *errnop = EAFNOSUPPORT; return NSS_STATUS_UNAVAIL; } - return _nss_wins_gethostbyname_r(name,he,buffer,buflen,errnop,h_errnop); + return _nss_wins_gethostbyname_r( + name, he, buffer, buflen, h_errnop); } #endif diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index 8bd50f35de..41b32cef10 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -231,7 +231,6 @@ typedef struct char *szLdapSuffix; char *szLdapFilter; char *szLdapAdminDn; - BOOL ldap_trust_ids; char *szAclCompat; int ldap_passwd_sync; BOOL ldap_delete_dn; @@ -563,6 +562,7 @@ static BOOL handle_debug_list( const char *pszParmValue, char **ptr ); static BOOL handle_workgroup( const char *pszParmValue, char **ptr ); static BOOL handle_netbios_aliases( const char *pszParmValue, char **ptr ); static BOOL handle_netbios_scope( const char *pszParmValue, char **ptr ); +static BOOL handle_charset( const char *pszParmValue, char **ptr ); static BOOL handle_ldap_suffix ( const char *pszParmValue, char **ptr ); static BOOL handle_ldap_sub_suffix ( const char *pszParmValue, char **ptr ); @@ -700,6 +700,7 @@ static const struct enum_list enum_smb_signing_vals[] = { {True, "1"}, {True, "On"}, {True, "enabled"}, + {Auto, "auto"}, {Required, "required"}, {Required, "mandatory"}, {Required, "force"}, @@ -752,9 +753,9 @@ static const struct enum_list enum_map_to_guest[] = { static struct parm_struct parm_table[] = { {"Base Options", P_SEP, P_SEPARATOR}, - {"dos charset", P_STRING, P_GLOBAL, &Globals.dos_charset, NULL, NULL, FLAG_ADVANCED}, - {"unix charset", P_STRING, P_GLOBAL, &Globals.unix_charset, NULL, NULL, FLAG_ADVANCED}, - {"display charset", P_STRING, P_GLOBAL, &Globals.display_charset, NULL, NULL, FLAG_ADVANCED}, + {"dos charset", P_STRING, P_GLOBAL, &Globals.dos_charset, handle_charset, NULL, FLAG_ADVANCED}, + {"unix charset", P_STRING, P_GLOBAL, &Globals.unix_charset, handle_charset, NULL, FLAG_ADVANCED}, + {"display charset", P_STRING, P_GLOBAL, &Globals.display_charset, handle_charset, NULL, FLAG_ADVANCED}, {"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT}, {"path", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT}, {"directory", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL, FLAG_HIDE}, @@ -1071,7 +1072,6 @@ static struct parm_struct parm_table[] = { {"ldap admin dn", P_STRING, P_GLOBAL, &Globals.szLdapAdminDn, NULL, NULL, FLAG_ADVANCED}, {"ldap ssl", P_ENUM, P_GLOBAL, &Globals.ldap_ssl, NULL, enum_ldap_ssl, FLAG_ADVANCED}, {"ldap passwd sync", P_ENUM, P_GLOBAL, &Globals.ldap_passwd_sync, NULL, enum_ldap_passwd_sync, FLAG_ADVANCED}, - {"ldap trust ids", P_BOOL, P_GLOBAL, &Globals.ldap_trust_ids, NULL, NULL, FLAG_ADVANCED}, {"ldap delete dn", P_BOOL, P_GLOBAL, &Globals.ldap_delete_dn, NULL, NULL, FLAG_ADVANCED}, {"Miscellaneous Options", P_SEP, P_SEPARATOR}, @@ -1309,18 +1309,18 @@ static void init_globals(void) string_set(&Globals.szGuestaccount, GUEST_ACCOUNT); /* using UTF8 by default allows us to support all chars */ - string_set(&Globals.unix_charset, "UTF8"); + string_set(&Globals.unix_charset, DEFAULT_UNIX_CHARSET); #if defined(HAVE_NL_LANGINFO) && defined(CODESET) /* If the system supports nl_langinfo(), try to grab the value from the user's locale */ string_set(&Globals.display_charset, "LOCALE"); #else - string_set(&Globals.display_charset, "ASCII"); + string_set(&Globals.display_charset, DEFAULT_DISPLAY_CHARSET); #endif /* Use codepage 850 as a default for the dos character set */ - string_set(&Globals.dos_charset, "CP850"); + string_set(&Globals.dos_charset, DEFAULT_DOS_CHARSET); /* * Allow the default PASSWD_CHAT to be overridden in local.h. @@ -1339,7 +1339,7 @@ static void init_globals(void) string_set(&Globals.szLockDir, dyn_LOCKDIR); string_set(&Globals.szSocketAddress, "0.0.0.0"); pstrcpy(s, "Samba "); - pstrcat(s, VERSION); + pstrcat(s, SAMBA_VERSION_STRING); string_set(&Globals.szServerString, s); slprintf(s, sizeof(s) - 1, "%d.%d", DEFAULT_MAJOR_VERSION, DEFAULT_MINOR_VERSION); @@ -1427,19 +1427,21 @@ static void init_globals(void) Globals.bClientPlaintextAuth = True; /* Do use a plaintext password if is requested by the server */ Globals.bLanmanAuth = True; /* Do use the LanMan hash if it is available */ Globals.bNTLMAuth = True; /* Do use NTLMv1 if it is available (otherwise NTLMv2) */ - + Globals.bClientNTLMv2Auth = False; /* Client should not use NTLMv2, as we can't tell that the server supports it. */ + /* Note, that we will use NTLM2 session security (which is different), if it is available */ + Globals.map_to_guest = 0; /* By Default, "Never" */ Globals.min_passwd_length = MINPASSWDLENGTH; /* By Default, 5. */ Globals.oplock_break_wait_time = 0; /* By Default, 0 msecs. */ Globals.enhanced_browsing = True; - Globals.iLockSpinCount = 3; /* Try 2 times. */ + Globals.iLockSpinCount = 3; /* Try 3 times. */ Globals.iLockSpinTime = 10; /* usec. */ #ifdef MMAP_BLACKLIST Globals.bUseMmap = False; #else Globals.bUseMmap = True; #endif - Globals.bUnixExtensions = False; + Globals.bUnixExtensions = True; /* hostname lookups can be very expensive and are broken on a large number of sites (tridge) */ @@ -1514,6 +1516,9 @@ static void init_globals(void) Globals.bUseSpnego = True; Globals.bClientUseSpnego = True; + Globals.client_signing = Auto; + Globals.server_signing = False; + string_set(&Globals.smb_ports, SMB_PORTS); } @@ -1554,8 +1559,8 @@ static char *lp_string(const char *s) lp_talloc = talloc_init("lp_talloc"); tmpstr = alloc_sub_basic(current_user_info.smb_name, s); - if (trim_string(tmpstr, "\"", "\"")) { - if (strchr(tmpstr,'"') != NULL) { + if (trim_char(tmpstr, '\"', '\"')) { + if (strchr(tmpstr,'\"') != NULL) { SAFE_FREE(tmpstr); tmpstr = alloc_sub_basic(current_user_info.smb_name,s); } @@ -1692,7 +1697,6 @@ 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_BOOL(lp_ldap_trust_ids, &Globals.ldap_trust_ids) FN_GLOBAL_BOOL(lp_ldap_delete_dn, &Globals.ldap_delete_dn) FN_GLOBAL_STRING(lp_add_share_cmd, &Globals.szAddShareCommand) FN_GLOBAL_STRING(lp_change_share_cmd, &Globals.szChangeShareCommand) @@ -2293,13 +2297,8 @@ BOOL lp_add_home(const char *pszHomename, int iDefaultService, if (!(*(ServicePtrs[iDefaultService]->szPath)) || strequal(ServicePtrs[iDefaultService]->szPath, lp_pathname(GLOBAL_SECTION_SNUM))) { pstrcpy(newHomedir, pszHomedir); - } else { - pstrcpy(newHomedir, lp_pathname(iDefaultService)); - string_sub(newHomedir,"%H", pszHomedir, sizeof(newHomedir)); - string_sub(newHomedir,"%S", pszHomename, sizeof(newHomedir)); - } - - string_set(&ServicePtrs[i]->szPath, newHomedir); + string_set(&ServicePtrs[i]->szPath, newHomedir); + } if (!(*(ServicePtrs[i]->comment))) { pstring comment; @@ -2307,7 +2306,9 @@ BOOL lp_add_home(const char *pszHomename, int iDefaultService, "Home directory of %s", user); string_set(&ServicePtrs[i]->comment, comment); } - ServicePtrs[i]->bAvailable = sDefault.bAvailable; + + /* set the browseable flag from the gloabl default */ + ServicePtrs[i]->bBrowseable = sDefault.bBrowseable; DEBUG(3, ("adding home's share [%s] for user '%s' at '%s'\n", pszHomename, @@ -2377,7 +2378,10 @@ BOOL lp_add_printer(const char *pszPrintername, int iDefaultService) /* the printer name is set to the service name. */ string_set(&ServicePtrs[i]->szPrintername, pszPrintername); string_set(&ServicePtrs[i]->comment, comment); + + /* set the browseable flag from the gloabl default */ ServicePtrs[i]->bBrowseable = sDefault.bBrowseable; + /* Printers cannot be read_only. */ ServicePtrs[i]->bRead_only = False; /* No share modes on printer services. */ @@ -2698,7 +2702,6 @@ static BOOL handle_netbios_name(const char *pszParmValue, char **ptr) standard_sub_basic(current_user_info.smb_name, netbios_name,sizeof(netbios_name)); - ret = set_global_myname(netbios_name); string_set(&Globals.szNetbiosName,global_myname()); @@ -2708,6 +2711,15 @@ static BOOL handle_netbios_name(const char *pszParmValue, char **ptr) return ret; } +static BOOL handle_charset(const char *pszParmValue, char **ptr) +{ + if (strcmp(*ptr, pszParmValue) != 0) { + string_set(ptr, pszParmValue); + init_iconv(); + } + return True; +} + static BOOL handle_workgroup(const char *pszParmValue, char **ptr) { BOOL ret; @@ -3101,7 +3113,7 @@ BOOL lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue pstr_sprintf(param_key, "%s:", pszParmName); slen = strlen(param_key); pstrcat(param_key, sep+1); - trim_string(param_key+slen, " ", " "); + trim_char(param_key+slen, ' ', ' '); not_added = True; data = (snum < 0) ? Globals.param_opt : ServicePtrs[snum]->param_opt; @@ -4158,12 +4170,11 @@ void lp_remove_service(int snum) void lp_copy_service(int snum, const char *new_name) { - char *oldname = lp_servicename(snum); do_section(new_name); if (snum >= 0) { snum = lp_servicenumber(new_name); if (snum >= 0) - lp_do_parameter(snum, "copy", oldname); + lp_do_parameter(snum, "copy", lp_servicename(snum)); } } diff --git a/source3/passdb/lookup_sid.c b/source3/passdb/lookup_sid.c new file mode 100644 index 0000000000..f84ff28db9 --- /dev/null +++ b/source3/passdb/lookup_sid.c @@ -0,0 +1,488 @@ +/* + Unix SMB/CIFS implementation. + uid/user handling + Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Gerald (Jerry) Carter 2003 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +/***************************************************************** + *THE CANONICAL* convert name to SID function. + Tries local lookup first - for local domains - then uses winbind. +*****************************************************************/ + +BOOL lookup_name(const char *domain, const char *name, DOM_SID *psid, enum SID_NAME_USE *name_type) +{ + fstring sid; + BOOL local_lookup = False; + + *name_type = SID_NAME_UNKNOWN; + + /* If we are looking up a domain user, make sure it is + for the local machine only */ + + if (strequal(global_myname(), domain)) { + local_lookup = True; + } else if (lp_server_role() == ROLE_DOMAIN_PDC || + lp_server_role() == ROLE_DOMAIN_BDC) { + if (strequal(domain, lp_workgroup())) { + local_lookup = True; + } + } + + if (local_lookup) { + if (local_lookup_name(name, psid, name_type)) { + DEBUG(10, + ("lookup_name: (local) [%s]\\[%s] -> SID %s (type %s: %u)\n", + domain, name, sid_to_string(sid,psid), + sid_type_lookup(*name_type), (unsigned int)*name_type)); + return True; + } + } else { + /* Remote */ + if (winbind_lookup_name(domain, name, psid, name_type)) { + + DEBUG(10,("lookup_name (winbindd): [%s]\\[%s] -> SID %s (type %u)\n", + domain, name, sid_to_string(sid, psid), + (unsigned int)*name_type)); + return True; + } + } + + DEBUG(10, ("lookup_name: %s lookup for [%s]\\[%s] failed\n", + local_lookup ? "local" : "winbind", domain, name)); + + return False; +} + +/***************************************************************** + *THE CANONICAL* convert SID to name function. + Tries local lookup first - for local sids, then tries winbind. +*****************************************************************/ + +BOOL lookup_sid(DOM_SID *sid, fstring dom_name, fstring name, enum SID_NAME_USE *name_type) +{ + if (!name_type) + return False; + + *name_type = SID_NAME_UNKNOWN; + + /* Check if this is our own sid. This should perhaps be done by + winbind? For the moment handle it here. */ + + if (sid->num_auths == 5) { + DOM_SID tmp_sid; + uint32 rid; + + sid_copy(&tmp_sid, sid); + sid_split_rid(&tmp_sid, &rid); + + if (sid_equal(get_global_sam_sid(), &tmp_sid)) { + + return map_domain_sid_to_name(&tmp_sid, dom_name) && + local_lookup_sid(sid, name, name_type); + } + } + + if (!winbind_lookup_sid(sid, dom_name, name, name_type)) { + fstring sid_str; + DOM_SID tmp_sid; + uint32 rid; + + DEBUG(10,("lookup_sid: winbind lookup for SID %s failed - trying local.\n", sid_to_string(sid_str, sid) )); + + sid_copy(&tmp_sid, sid); + sid_split_rid(&tmp_sid, &rid); + return map_domain_sid_to_name(&tmp_sid, dom_name) && + lookup_known_rid(&tmp_sid, rid, name, name_type); + } + return True; +} + + +/***************************************************************** + Id mapping cache. This is to avoid Winbind mappings already + seen by smbd to be queried too frequently, keeping winbindd + busy, and blocking smbd while winbindd is busy with other + stuff. Written by Michael Steffens , + modified to use linked lists by jra. +*****************************************************************/ + +#define MAX_UID_SID_CACHE_SIZE 100 +#define TURNOVER_UID_SID_CACHE_SIZE 10 +#define MAX_GID_SID_CACHE_SIZE 100 +#define TURNOVER_GID_SID_CACHE_SIZE 10 + +static size_t n_uid_sid_cache = 0; +static size_t n_gid_sid_cache = 0; + +static struct uid_sid_cache { + struct uid_sid_cache *next, *prev; + uid_t uid; + DOM_SID sid; + enum SID_NAME_USE sidtype; +} *uid_sid_cache_head; + +static struct gid_sid_cache { + struct gid_sid_cache *next, *prev; + gid_t gid; + DOM_SID sid; + enum SID_NAME_USE sidtype; +} *gid_sid_cache_head; + +/***************************************************************** + Find a SID given a uid. +*****************************************************************/ + +static BOOL fetch_sid_from_uid_cache(DOM_SID *psid, uid_t uid) +{ + struct uid_sid_cache *pc; + + for (pc = uid_sid_cache_head; pc; pc = pc->next) { + if (pc->uid == uid) { + fstring sid; + *psid = pc->sid; + DEBUG(3,("fetch sid from uid cache %u -> %s\n", + (unsigned int)uid, sid_to_string(sid, psid))); + DLIST_PROMOTE(uid_sid_cache_head, pc); + return True; + } + } + return False; +} + +/***************************************************************** + Find a uid given a SID. +*****************************************************************/ + +static BOOL fetch_uid_from_cache( uid_t *puid, const DOM_SID *psid ) +{ + struct uid_sid_cache *pc; + + for (pc = uid_sid_cache_head; pc; pc = pc->next) { + if (sid_compare(&pc->sid, psid) == 0) { + fstring sid; + *puid = pc->uid; + DEBUG(3,("fetch uid from cache %u -> %s\n", + (unsigned int)*puid, sid_to_string(sid, psid))); + DLIST_PROMOTE(uid_sid_cache_head, pc); + return True; + } + } + return False; +} + +/***************************************************************** + Store uid to SID mapping in cache. +*****************************************************************/ + +static void store_uid_sid_cache(const DOM_SID *psid, uid_t uid) +{ + struct uid_sid_cache *pc; + + if (n_uid_sid_cache >= MAX_UID_SID_CACHE_SIZE && n_uid_sid_cache > TURNOVER_UID_SID_CACHE_SIZE) { + /* Delete the last TURNOVER_UID_SID_CACHE_SIZE entries. */ + struct uid_sid_cache *pc_next; + size_t i; + + for (i = 0, pc = uid_sid_cache_head; i < (n_uid_sid_cache - TURNOVER_UID_SID_CACHE_SIZE); i++, pc = pc->next) + ; + for(; pc; pc = pc_next) { + pc_next = pc->next; + DLIST_REMOVE(uid_sid_cache_head,pc); + SAFE_FREE(pc); + n_uid_sid_cache--; + } + } + + pc = (struct uid_sid_cache *)malloc(sizeof(struct uid_sid_cache)); + if (!pc) + return; + pc->uid = uid; + sid_copy(&pc->sid, psid); + DLIST_ADD(uid_sid_cache_head, pc); + n_uid_sid_cache++; +} + +/***************************************************************** + Find a SID given a gid. +*****************************************************************/ + +static BOOL fetch_sid_from_gid_cache(DOM_SID *psid, gid_t gid) +{ + struct gid_sid_cache *pc; + + for (pc = gid_sid_cache_head; pc; pc = pc->next) { + if (pc->gid == gid) { + fstring sid; + *psid = pc->sid; + DEBUG(3,("fetch sid from gid cache %u -> %s\n", + (unsigned int)gid, sid_to_string(sid, psid))); + DLIST_PROMOTE(gid_sid_cache_head, pc); + return True; + } + } + return False; +} + +/***************************************************************** + Find a gid given a SID. +*****************************************************************/ + +static BOOL fetch_gid_from_cache(gid_t *pgid, const DOM_SID *psid) +{ + struct gid_sid_cache *pc; + + for (pc = gid_sid_cache_head; pc; pc = pc->next) { + if (sid_compare(&pc->sid, psid) == 0) { + fstring sid; + *pgid = pc->gid; + DEBUG(3,("fetch uid from cache %u -> %s\n", + (unsigned int)*pgid, sid_to_string(sid, psid))); + DLIST_PROMOTE(gid_sid_cache_head, pc); + return True; + } + } + return False; +} + +/***************************************************************** + Store gid to SID mapping in cache. +*****************************************************************/ + +static void store_gid_sid_cache(const DOM_SID *psid, gid_t gid) +{ + struct gid_sid_cache *pc; + + if (n_gid_sid_cache >= MAX_GID_SID_CACHE_SIZE && n_gid_sid_cache > TURNOVER_GID_SID_CACHE_SIZE) { + /* Delete the last TURNOVER_GID_SID_CACHE_SIZE entries. */ + struct gid_sid_cache *pc_next; + size_t i; + + for (i = 0, pc = gid_sid_cache_head; i < (n_gid_sid_cache - TURNOVER_GID_SID_CACHE_SIZE); i++, pc = pc->next) + ; + for(; pc; pc = pc_next) { + pc_next = pc->next; + DLIST_REMOVE(gid_sid_cache_head,pc); + SAFE_FREE(pc); + n_gid_sid_cache--; + } + } + + pc = (struct gid_sid_cache *)malloc(sizeof(struct gid_sid_cache)); + if (!pc) + return; + pc->gid = gid; + sid_copy(&pc->sid, psid); + DLIST_ADD(gid_sid_cache_head, pc); + n_gid_sid_cache++; +} + +/***************************************************************** + *THE CANONICAL* convert uid_t to SID function. +*****************************************************************/ + +NTSTATUS uid_to_sid(DOM_SID *psid, uid_t uid) +{ + uid_t low, high; + fstring sid; + + ZERO_STRUCTP(psid); + + if (fetch_sid_from_uid_cache(psid, uid)) + return ( psid ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL ); + + if (lp_idmap_uid(&low, &high) && uid >= low && uid <= high) { + if (winbind_uid_to_sid(psid, uid)) { + + DEBUG(10,("uid_to_sid: winbindd %u -> %s\n", + (unsigned int)uid, sid_to_string(sid, psid))); + + if (psid) + store_uid_sid_cache(psid, uid); + return ( psid ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL ); + } + } + + if (!local_uid_to_sid(psid, uid)) { + DEBUG(10,("uid_to_sid: local %u failed to map to sid\n", (unsigned int)uid )); + return NT_STATUS_UNSUCCESSFUL; + } + + DEBUG(10,("uid_to_sid: local %u -> %s\n", (unsigned int)uid, sid_to_string(sid, psid))); + + store_uid_sid_cache(psid, uid); + return NT_STATUS_OK; +} + +/***************************************************************** + *THE CANONICAL* convert gid_t to SID function. +*****************************************************************/ + +NTSTATUS gid_to_sid(DOM_SID *psid, gid_t gid) +{ + gid_t low, high; + fstring sid; + + ZERO_STRUCTP(psid); + + if (fetch_sid_from_gid_cache(psid, gid)) + return ( psid ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL ); + + if (lp_idmap_gid(&low, &high) && gid >= low && gid <= high) { + if (winbind_gid_to_sid(psid, gid)) { + + DEBUG(10,("gid_to_sid: winbindd %u -> %s\n", + (unsigned int)gid, sid_to_string(sid, psid))); + + if (psid) + store_gid_sid_cache(psid, gid); + return ( psid ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL ); + } + } + + if (!local_gid_to_sid(psid, gid)) { + DEBUG(10,("gid_to_sid: local %u failed to map to sid\n", (unsigned int)gid )); + return NT_STATUS_UNSUCCESSFUL; + } + + DEBUG(10,("gid_to_sid: local %u -> %s\n", (unsigned int)gid, sid_to_string(sid, psid))); + + store_gid_sid_cache(psid, gid); + return NT_STATUS_OK; +} + +/***************************************************************** + *THE CANONICAL* convert SID to uid function. +*****************************************************************/ + +NTSTATUS sid_to_uid(const DOM_SID *psid, uid_t *puid) +{ + fstring dom_name, name, sid_str; + enum SID_NAME_USE name_type; + + if (fetch_uid_from_cache(puid, psid)) + return NT_STATUS_OK; + + /* if this is our SID then go straight to a local lookup */ + + if ( sid_compare_domain(get_global_sam_sid(), psid) == 0 ) { + DEBUG(10,("sid_to_uid: my domain (%s) - trying local.\n", + sid_string_static(psid) )); + + if ( local_sid_to_uid(puid, psid, &name_type) ) + goto success; + + DEBUG(10,("sid_to_uid: local lookup failed\n")); + + return NT_STATUS_UNSUCCESSFUL; + } + + /* If it is not our local domain, only hope is winbindd */ + + if ( !winbind_lookup_sid(psid, dom_name, name, &name_type) ) { + DEBUG(10,("sid_to_uid: winbind lookup for non-local sid %s failed\n", + sid_string_static(psid) )); + + return NT_STATUS_UNSUCCESSFUL; + } + + /* If winbindd does know the SID, ensure this is a user */ + + if (name_type != SID_NAME_USER) { + DEBUG(10,("sid_to_uid: winbind lookup succeeded but SID is not a user (%u)\n", + (unsigned int)name_type )); + return NT_STATUS_INVALID_PARAMETER; + } + + /* get the uid. Has to work or else we are dead in the water */ + + if ( !winbind_sid_to_uid(puid, psid) ) { + DEBUG(10,("sid_to_uid: winbind failed to allocate a new uid for sid %s\n", + sid_to_string(sid_str, psid) )); + return NT_STATUS_UNSUCCESSFUL; + } + +success: + DEBUG(10,("sid_to_uid: %s -> %u\n", sid_to_string(sid_str, psid), + (unsigned int)*puid )); + + store_uid_sid_cache(psid, *puid); + + return NT_STATUS_OK; +} +/***************************************************************** + *THE CANONICAL* convert SID to gid function. + Group mapping is used for gids that maps to Wellknown SIDs +*****************************************************************/ + +NTSTATUS sid_to_gid(const DOM_SID *psid, gid_t *pgid) +{ + fstring dom_name, name, sid_str; + enum SID_NAME_USE name_type; + + if (fetch_gid_from_cache(pgid, psid)) + return NT_STATUS_OK; + + /* + * First we must look up the name and decide if this is a group sid. + * Group mapping can deal with foreign SIDs + */ + + if (!winbind_lookup_sid(psid, dom_name, name, &name_type)) { + DEBUG(10,("sid_to_gid: winbind lookup for sid %s failed - trying local.\n", + sid_to_string(sid_str, psid) )); + + if ( local_sid_to_gid(pgid, psid, &name_type) ) + goto success; + + DEBUG(10,("sid_to_gid: no one knows this SID\n")); + + return NT_STATUS_UNSUCCESSFUL; + } + + /* winbindd knows it; Ensure this is a group sid */ + + if ((name_type != SID_NAME_DOM_GRP) && (name_type != SID_NAME_ALIAS) && (name_type != SID_NAME_WKN_GRP)) { + DEBUG(10,("sid_to_gid: winbind lookup succeeded but SID is not a known group (%u)\n", + (unsigned int)name_type )); + + /* winbindd is running and knows about this SID. Just the wrong type. + Don't fallback to a local lookup here */ + + return NT_STATUS_INVALID_PARAMETER; + } + + /* winbindd knows it and it is a type of group; sid_to_gid must succeed + or we are dead in the water */ + + if ( !winbind_sid_to_gid(pgid, psid) ) { + DEBUG(10,("sid_to_uid: winbind failed to allocate a new gid for sid %s\n", + sid_to_string(sid_str, psid) )); + return NT_STATUS_UNSUCCESSFUL; + } + +success: + DEBUG(10,("sid_to_gid: %s -> %u\n", sid_to_string(sid_str, psid), + (unsigned int)*pgid )); + + store_gid_sid_cache(psid, *pgid); + + return NT_STATUS_OK; +} + diff --git a/source3/passdb/passdb.c b/source3/passdb/passdb.c index e440e064ef..76745be3f0 100644 --- a/source3/passdb/passdb.c +++ b/source3/passdb/passdb.c @@ -758,13 +758,27 @@ BOOL local_lookup_sid(DOM_SID *sid, char *name, enum SID_NAME_USE *psid_name_use if (fallback_pdb_rid_is_user(rid)) { uid_t uid; + struct passwd *pw = NULL; DEBUG(5, ("assuming RID %u is a user\n", (unsigned)rid)); uid = fallback_pdb_user_rid_to_uid(rid); - slprintf(name, sizeof(fstring)-1, "unix_user.%u", (unsigned int)uid); - - return False; /* Indicates that this user was 'not mapped' */ + pw = sys_getpwuid( uid ); + + DEBUG(5,("local_lookup_sid: looking up uid %u %s\n", (unsigned int)uid, + pw ? "succeeded" : "failed" )); + + if ( !pw ) + fstr_sprintf(name, "unix_user.%u", (unsigned int)uid); + else + fstrcpy( name, pw->pw_name ); + + DEBUG(5,("local_lookup_sid: found user %s for rid %u\n", name, + (unsigned int)rid )); + + *psid_name_use = SID_NAME_USER; + + return ( pw != NULL ); } else { gid_t gid; struct group *gr; @@ -779,16 +793,19 @@ BOOL local_lookup_sid(DOM_SID *sid, char *name, enum SID_NAME_USE *psid_name_use DEBUG(5,("local_lookup_sid: looking up gid %u %s\n", (unsigned int)gid, gr ? "succeeded" : "failed" )); - if(!gr) { - slprintf(name, sizeof(fstring)-1, "unix_group.%u", (unsigned int)gid); - return False; /* Indicates that this group was 'not mapped' */ - } - - fstrcpy( name, gr->gr_name); + if( !gr ) + fstr_sprintf(name, "unix_group.%u", (unsigned int)gid); + else + fstrcpy( name, gr->gr_name); DEBUG(5,("local_lookup_sid: found group %s for rid %u\n", name, (unsigned int)rid )); - return True; + + /* assume fallback groups aer domain global groups */ + + *psid_name_use = SID_NAME_DOM_GRP; + + return ( gr != NULL ); } } @@ -1156,11 +1173,18 @@ BOOL local_sid_to_uid(uid_t *puid, const DOM_SID *psid, enum SID_NAME_USE *name_ DOM_SID *local_gid_to_sid(DOM_SID *psid, gid_t gid) { GROUP_MAP group; + BOOL ret; /* we don't need to disable winbindd since the gid is stored in the GROUP_MAP object */ + + /* done as root since ldap backend requires root to open a connection */ - if ( !pdb_getgrgid( &group, gid ) ) { + become_root(); + ret = pdb_getgrgid( &group, gid ); + unbecome_root(); + + if ( !ret ) { /* fallback to rid mapping if enabled */ @@ -1289,6 +1313,7 @@ BOOL init_sam_from_buffer(SAM_ACCOUNT *sampass, uint8 *buf, uint32 buflen) BOOL ret = True; uid_t uid = -1; gid_t gid = -1; + struct passwd *pw = NULL; if(sampass == NULL || buf == NULL) { DEBUG(0, ("init_sam_from_buffer: NULL parameters found!\n")); @@ -1296,7 +1321,7 @@ BOOL init_sam_from_buffer(SAM_ACCOUNT *sampass, uint8 *buf, uint32 buflen) } /* unpack the buffer into variables */ - len = tdb_unpack (buf, buflen, TDB_FORMAT_STRING, + len = tdb_unpack ((char *)buf, buflen, TDB_FORMAT_STRING, &logon_time, &logoff_time, &kickoff_time, @@ -1344,6 +1369,12 @@ BOOL init_sam_from_buffer(SAM_ACCOUNT *sampass, uint8 *buf, uint32 buflen) pdb_set_nt_username(sampass, nt_username, PDB_SET); pdb_set_fullname(sampass, fullname, PDB_SET); + + if ( (pw=Get_Pwnam(username)) != NULL ) { + uid = pw->pw_uid; + gid = pw->pw_gid; + } + if (homedir) { pdb_set_homedir(sampass, homedir, PDB_SET); } @@ -1633,7 +1664,7 @@ uint32 init_buffer_from_sam (uint8 **buf, const SAM_ACCOUNT *sampass, BOOL size_ } /* now for the real call to tdb_pack() */ - buflen = tdb_pack(*buf, len, TDB_FORMAT_STRING, + buflen = tdb_pack((char *)*buf, len, TDB_FORMAT_STRING, logon_time, logoff_time, kickoff_time, @@ -1676,3 +1707,51 @@ uint32 init_buffer_from_sam (uint8 **buf, const SAM_ACCOUNT *sampass, BOOL size_ return (buflen); } + + +/********************************************************************** +**********************************************************************/ + +static BOOL get_free_ugid_range(uint32 *low, uint32 *high) +{ + uid_t u_low, u_high; + gid_t g_low, g_high; + + if (!lp_idmap_uid(&u_low, &u_high) || !lp_idmap_gid(&g_low, &g_high)) { + return False; + } + + *low = (u_low < g_low) ? u_low : g_low; + *high = (u_high < g_high) ? u_high : g_high; + + return True; +} + +/****************************************************************** + Get the the non-algorithmic RID range if idmap range are defined +******************************************************************/ + +BOOL get_free_rid_range(uint32 *low, uint32 *high) +{ + uint32 id_low, id_high; + + if (!lp_enable_rid_algorithm()) { + *low = BASE_RID; + *high = (uint32)-1; + } + + if (!get_free_ugid_range(&id_low, &id_high)) { + return False; + } + + *low = fallback_pdb_uid_to_user_rid(id_low); + if (fallback_pdb_user_rid_to_uid((uint32)-1) < id_high) { + *high = (uint32)-1; + } else { + *high = fallback_pdb_uid_to_user_rid(id_high); + } + + return True; +} + + diff --git a/source3/passdb/pdb_interface.c b/source3/passdb/pdb_interface.c index 5ebc14030f..d548081e78 100644 --- a/source3/passdb/pdb_interface.c +++ b/source3/passdb/pdb_interface.c @@ -422,10 +422,10 @@ static NTSTATUS make_pdb_methods_name(struct pdb_methods **methods, struct pdb_c if (p) { *p = 0; module_location = p+1; - trim_string(module_location, " ", " "); + trim_char(module_location, ' ', ' '); } - trim_string(module_name, " ", " "); + trim_char(module_name, ' ', ' '); DEBUG(5,("Attempting to find an passdb backend to match %s (%s)\n", selected, module_name)); diff --git a/source3/passdb/pdb_ldap.c b/source3/passdb/pdb_ldap.c index aee6495759..009425c5f6 100644 --- a/source3/passdb/pdb_ldap.c +++ b/source3/passdb/pdb_ldap.c @@ -333,6 +333,8 @@ static NTSTATUS ldapsam_delete_entry(struct ldapsam_privates *ldap_state, /* New Interface is being implemented here */ +#if 0 /* JERRY - not uesed anymore */ + /********************************************************************** Initialize SAM_ACCOUNT from an LDAP query (unix attributes only) *********************************************************************/ @@ -385,6 +387,7 @@ static BOOL get_unix_attributes (struct ldapsam_privates *ldap_state, return True; } +#endif /********************************************************************** Initialize SAM_ACCOUNT from an LDAP query @@ -419,8 +422,9 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, uint32 hours_len; uint8 hours[MAX_HOURS_LEN]; pstring temp; + struct passwd *pw = NULL; uid_t uid = -1; - gid_t gid = getegid(); + gid_t gid = -1; /* * do a little initialization @@ -455,6 +459,14 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, DEBUG(2, ("Entry found for user: %s\n", username)); + /* I'm not going to fail here, since there are checks + higher up the cal stack to do this --jerry */ + + if ( (pw=Get_Pwnam(username)) != NULL ) { + uid = pw->pw_uid; + gid = pw->pw_gid; + } + pstrcpy(nt_username, username); pstrcpy(domain, ldap_state->domain_name); @@ -523,6 +535,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, } +#if 0 /* JERRY -- not used anymore */ /* * If so configured, try and get the values from LDAP */ @@ -541,6 +554,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, } } } +#endif if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_LAST_SET), temp)) @@ -1685,7 +1699,7 @@ static BOOL init_group_from_ldap(struct ldapsam_privates *ldap_state, get_attr_key2string( groupmap_attr_list, LDAP_ATTR_GROUP_TYPE))); return False; } - map->sid_name_use = (uint32)atol(temp); + map->sid_name_use = (enum SID_NAME_USE)atol(temp); if ((map->sid_name_use < SID_NAME_USER) || (map->sid_name_use > SID_NAME_UNKNOWN)) { @@ -2128,7 +2142,6 @@ static NTSTATUS ldapsam_enum_group_mapping(struct pdb_methods *methods, GROUP_MAP map; GROUP_MAP *mapt; int entries = 0; - NTSTATUS nt_status; *num_entries = 0; *rmap = NULL; @@ -2138,7 +2151,7 @@ static NTSTATUS ldapsam_enum_group_mapping(struct pdb_methods *methods, return NT_STATUS_ACCESS_DENIED; } - while (NT_STATUS_IS_OK(nt_status = ldapsam_getsamgrent(methods, &map))) { + while (NT_STATUS_IS_OK(ldapsam_getsamgrent(methods, &map))) { if (sid_name_use != SID_NAME_UNKNOWN && sid_name_use != map.sid_name_use) { DEBUG(11,("enum_group_mapping: group %s is not of the requested type\n", map.nt_name)); diff --git a/source3/passdb/pdb_mysql.c b/source3/passdb/pdb_mysql.c index d3eb7cb975..6c200be504 100644 --- a/source3/passdb/pdb_mysql.c +++ b/source3/passdb/pdb_mysql.c @@ -240,9 +240,9 @@ static NTSTATUS row_to_sam_account(MYSQL_RES * r, SAM_ACCOUNT * u) pdb_set_unknown_str(u, row[16], PDB_SET); pdb_set_munged_dial(u, row[17], PDB_SET); - string_to_sid(&sid, row[18]); + if(row[18])string_to_sid(&sid, row[18]); pdb_set_user_sid(u, &sid, PDB_SET); - string_to_sid(&sid, row[19]); + if(row[19])string_to_sid(&sid, row[19]); pdb_set_group_sid(u, &sid, PDB_SET); if (pdb_gethexpwd(row[20], temp), PDB_SET) diff --git a/source3/passdb/pdb_plugin.c b/source3/passdb/pdb_plugin.c index ea67da23a5..027cd0b5d3 100644 --- a/source3/passdb/pdb_plugin.c +++ b/source3/passdb/pdb_plugin.c @@ -41,9 +41,11 @@ NTSTATUS pdb_init_plugin(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, con if (p) { *p = 0; plugin_location = p+1; - trim_string(plugin_location, " ", " "); - } else plugin_location = NULL; - trim_string(plugin_name, " ", " "); + trim_char(plugin_location, ' ', ' '); + } else { + plugin_location = NULL; + } + trim_char(plugin_name, ' ', ' '); DEBUG(5, ("Trying to load sam plugin %s\n", plugin_name)); dl_handle = sys_dlopen(plugin_name, RTLD_NOW ); diff --git a/source3/passdb/pdb_tdb.c b/source3/passdb/pdb_tdb.c index 7c2156455a..c9a84f3242 100644 --- a/source3/passdb/pdb_tdb.c +++ b/source3/passdb/pdb_tdb.c @@ -133,7 +133,7 @@ static NTSTATUS tdbsam_getsampwent(struct pdb_methods *my_methods, SAM_ACCOUNT * } /* unpack the buffer */ - if (!init_sam_from_buffer(user, data.dptr, data.dsize)) { + if (!init_sam_from_buffer(user, (unsigned char *)data.dptr, data.dsize)) { DEBUG(0,("pdb_getsampwent: Bad SAM_ACCOUNT entry returned from TDB!\n")); SAFE_FREE(data.dptr); return nt_status; @@ -213,7 +213,7 @@ static NTSTATUS tdbsam_getsampwnam (struct pdb_methods *my_methods, SAM_ACCOUNT } /* unpack the buffer */ - if (!init_sam_from_buffer(user, data.dptr, data.dsize)) { + if (!init_sam_from_buffer(user, (unsigned char *)data.dptr, data.dsize)) { DEBUG(0,("pdb_getsampwent: Bad SAM_ACCOUNT entry returned from TDB!\n")); SAFE_FREE(data.dptr); tdb_close(pwd_tdb); @@ -390,7 +390,7 @@ static BOOL tdb_update_sam(struct pdb_methods *my_methods, SAM_ACCOUNT* newpwd, ret = False; goto done; } - data.dptr = buf; + data.dptr = (char *)buf; fstrcpy(name, pdb_get_username(newpwd)); strlower_m(name); diff --git a/source3/passdb/secrets.c b/source3/passdb/secrets.c index 23413e4026..8a146f0d68 100644 --- a/source3/passdb/secrets.c +++ b/source3/passdb/secrets.c @@ -58,7 +58,7 @@ void *secrets_fetch(const char *key, size_t *size) secrets_init(); if (!tdb) return NULL; - kbuf.dptr = key; + kbuf.dptr = (char *)key; kbuf.dsize = strlen(key); dbuf = tdb_fetch(tdb, kbuf); if (size) @@ -74,9 +74,9 @@ BOOL secrets_store(const char *key, const void *data, size_t size) secrets_init(); if (!tdb) return False; - kbuf.dptr = key; + kbuf.dptr = (char *)key; kbuf.dsize = strlen(key); - dbuf.dptr = data; + dbuf.dptr = (char *)data; dbuf.dsize = size; return tdb_store(tdb, kbuf, dbuf, TDB_REPLACE) == 0; } @@ -90,7 +90,7 @@ BOOL secrets_delete(const char *key) secrets_init(); if (!tdb) return False; - kbuf.dptr = key; + kbuf.dptr = (char *)key; kbuf.dsize = strlen(key); return tdb_delete(tdb, kbuf) == 0; } @@ -738,3 +738,56 @@ BOOL must_use_pdc( const char *domain ) } +/******************************************************************************* + Store a complete AFS keyfile into secrets.tdb. +*******************************************************************************/ + +BOOL secrets_store_afs_keyfile(const char *cell, const struct afs_keyfile *keyfile) +{ + fstring key; + + if ((cell == NULL) || (keyfile == NULL)) + return False; + + if (ntohl(keyfile->nkeys) > SECRETS_AFS_MAXKEYS) + return False; + + slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_AFS_KEYFILE, cell); + return secrets_store(key, keyfile, sizeof(struct afs_keyfile)); +} + +/******************************************************************************* + Fetch the current (highest) AFS key from secrets.tdb +*******************************************************************************/ +BOOL secrets_fetch_afs_key(const char *cell, struct afs_key *result) +{ + fstring key; + struct afs_keyfile *keyfile; + size_t size; + uint32 i; + + slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_AFS_KEYFILE, cell); + + keyfile = (struct afs_keyfile *)secrets_fetch(key, &size); + + if (keyfile == NULL) + return False; + + if (size != sizeof(struct afs_keyfile)) { + SAFE_FREE(keyfile); + return False; + } + + i = ntohl(keyfile->nkeys); + + if (i > SECRETS_AFS_MAXKEYS) { + SAFE_FREE(keyfile); + return False; + } + + *result = keyfile->entry[i-1]; + + result->kvno = ntohl(result->kvno); + + return True; +} diff --git a/source3/printing/lpq_parse.c b/source3/printing/lpq_parse.c index 0acca67b70..111617e3ae 100644 --- a/source3/printing/lpq_parse.c +++ b/source3/printing/lpq_parse.c @@ -766,14 +766,14 @@ static BOOL parse_lpq_nt(char *line,print_queue_struct *buf,BOOL first) /* Make sure the status is valid */ parse_line.space2 = '\0'; - trim_string(parse_line.status, NULL, " "); + trim_char(parse_line.status, '\0', ' '); if (!strequal(parse_line.status, LPRNT_PRINTING) && !strequal(parse_line.status, LPRNT_PAUSED) && !strequal(parse_line.status, LPRNT_WAITING)) return(False); parse_line.space3 = '\0'; - trim_string(parse_line.jobname, NULL, " "); + trim_char(parse_line.jobname, '\0', ' '); buf->job = atoi(parse_line.jobid); buf->priority = 0; @@ -837,7 +837,7 @@ static BOOL parse_lpq_os2(char *line,print_queue_struct *buf,BOOL first) /* Get the job name */ parse_line.space2[0] = '\0'; - trim_string(parse_line.jobname, NULL, " "); + trim_char(parse_line.jobname, '\0', ' '); fstrcpy(buf->fs_file, parse_line.jobname); buf->priority = 0; @@ -850,7 +850,7 @@ static BOOL parse_lpq_os2(char *line,print_queue_struct *buf,BOOL first) /* Make sure we have a valid status */ parse_line.space4[0] = '\0'; - trim_string(parse_line.status, NULL, " "); + trim_char(parse_line.status, '\0', ' '); if (!strequal(parse_line.status, LPROS2_PRINTING) && !strequal(parse_line.status, LPROS2_PAUSED) && !strequal(parse_line.status, LPROS2_WAITING)) diff --git a/source3/printing/nt_printing.c b/source3/printing/nt_printing.c index 5e6e95ff7e..4859d785be 100644 --- a/source3/printing/nt_printing.c +++ b/source3/printing/nt_printing.c @@ -204,13 +204,19 @@ struct table_node { int version; }; +#define SPL_ARCH_WIN40 "WIN40" +#define SPL_ARCH_W32X86 "W32X86" +#define SPL_ARCH_W32MIPS "W32MIPS" +#define SPL_ARCH_W32ALPHA "W32ALPHA" +#define SPL_ARCH_W32PPC "W32PPC" + static const struct table_node archi_table[]= { - {"Windows 4.0", "WIN40", 0 }, - {"Windows NT x86", "W32X86", 2 }, - {"Windows NT R4000", "W32MIPS", 2 }, - {"Windows NT Alpha_AXP", "W32ALPHA", 2 }, - {"Windows NT PowerPC", "W32PPC", 2 }, + {"Windows 4.0", SPL_ARCH_WIN40, 0 }, + {"Windows NT x86", SPL_ARCH_W32X86, 2 }, + {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 }, + {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 }, + {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 }, {NULL, "", -1 } }; @@ -1755,6 +1761,11 @@ static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, ZERO_STRUCT(driver); architecture = get_short_archi(arch); + + /* Windows 4.0 (i.e. win9x) should always use a version of 0 */ + + if ( strcmp( architecture, SPL_ARCH_WIN40 ) == 0 ) + version = 0; DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, drivername)); @@ -2015,7 +2026,7 @@ static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info) if (info->servername[0]!='\0') { trim_string(info->printername, info->servername, NULL); - trim_string(info->printername, "\\", NULL); + trim_char(info->printername, '\\', '\0'); info->servername[0]='\0'; } @@ -2245,7 +2256,7 @@ int unpack_devicemode(NT_DEVICEMODE **nt_devmode, char *buf, int buflen) int len = 0; int extra_len = 0; NT_DEVICEMODE devmode; - + ZERO_STRUCT(devmode); len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode); @@ -2886,6 +2897,11 @@ WERROR delete_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const key_index = lookup_printerkey( &p2->data, key ); if ( key_index == -1 ) return WERR_OK; + + /* make sure the value exists so we can return the correct error code */ + + if ( !regval_ctr_getvalue( &p2->data.keys[key_index].values, value ) ) + return WERR_BADFILE; regval_ctr_delvalue( &p2->data.keys[key_index].values, value ); @@ -2919,7 +2935,7 @@ WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const cha return WERR_NOMEM; regval_ctr_addvalue( &p2->data.keys[key_index].values, value, - type, data, real_len ); + type, (const char *)data, real_len ); DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n", key, value, type, real_len )); @@ -3012,7 +3028,7 @@ static int unpack_values(NT_PRINTER_DATA *printer_data, char *buf, int buflen) /* add the new value */ - regval_ctr_addvalue( &printer_data->keys[key_index].values, valuename, type, data_p, size ); + regval_ctr_addvalue( &printer_data->keys[key_index].values, valuename, type, (const char *)data_p, size ); SAFE_FREE(data_p); /* 'B' option to tdbpack does a malloc() */ @@ -3195,6 +3211,7 @@ static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, const char *sh int len = 0; TDB_DATA kbuf, dbuf; fstring printername; + char adevice[MAXDEVICENAME]; ZERO_STRUCT(info); @@ -3255,6 +3272,10 @@ static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **info_ptr, const char *sh printername)); info.devmode = construct_nt_devicemode(printername); } + + safe_strcpy(adevice, info.printername, sizeof(adevice)-1); + fstrcpy(info.devmode->devicename, adevice); + len += unpack_values( &info.data, dbuf.dptr+len, dbuf.dsize-len ); diff --git a/source3/python/py_lsa.c b/source3/python/py_lsa.c index 4204f43f7b..07191be868 100644 --- a/source3/python/py_lsa.c +++ b/source3/python/py_lsa.c @@ -104,8 +104,7 @@ done: if (cli) cli_shutdown(cli); - if (mem_ctx) - talloc_destroy(mem_ctx); + talloc_destroy(mem_ctx); } return result; @@ -141,12 +140,13 @@ static PyObject *lsa_close(PyObject *self, PyObject *args, PyObject *kw) static PyObject *lsa_lookup_names(PyObject *self, PyObject *args) { - PyObject *py_names, *result; + PyObject *py_names, *result = NULL; NTSTATUS ntstatus; lsa_policy_hnd_object *hnd = (lsa_policy_hnd_object *)self; int num_names, i; const char **names; DOM_SID *sids; + TALLOC_CTX *mem_ctx = NULL; uint32 *name_types; if (!PyArg_ParseTuple(args, "O", &py_names)) @@ -157,18 +157,22 @@ static PyObject *lsa_lookup_names(PyObject *self, PyObject *args) return NULL; } + if (!(mem_ctx = talloc_init("lsa_lookup_names"))) { + PyErr_SetString(lsa_error, "unable to init talloc context\n"); + goto done; + } + if (PyList_Check(py_names)) { /* Convert list to char ** array */ num_names = PyList_Size(py_names); - names = (const char **)talloc( - hnd->mem_ctx, num_names * sizeof(char *)); + names = (const char **)talloc(mem_ctx, num_names * sizeof(char *)); for (i = 0; i < num_names; i++) { PyObject *obj = PyList_GetItem(py_names, i); - names[i] = talloc_strdup(hnd->mem_ctx, PyString_AsString(obj)); + names[i] = talloc_strdup(mem_ctx, PyString_AsString(obj)); } } else { @@ -176,17 +180,17 @@ static PyObject *lsa_lookup_names(PyObject *self, PyObject *args) /* Just a single element */ num_names = 1; - names = (const char **)talloc(hnd->mem_ctx, sizeof(char *)); + names = (const char **)talloc(mem_ctx, sizeof(char *)); names[0] = PyString_AsString(py_names); } - ntstatus = cli_lsa_lookup_names(hnd->cli, hnd->mem_ctx, &hnd->pol, + ntstatus = cli_lsa_lookup_names(hnd->cli, mem_ctx, &hnd->pol, num_names, names, &sids, &name_types); if (!NT_STATUS_IS_OK(ntstatus) && NT_STATUS_V(ntstatus) != 0x107) { PyErr_SetObject(lsa_ntstatus, py_ntstatus_tuple(ntstatus)); - return NULL; + goto done; } result = PyList_New(num_names); @@ -196,10 +200,13 @@ static PyObject *lsa_lookup_names(PyObject *self, PyObject *args) py_from_SID(&sid_obj, &sids[i]); - obj = Py_BuildValue("(Oi)", sid_obj, name_types[i]); + obj = Py_BuildValue("(Ni)", sid_obj, name_types[i]); PyList_SetItem(result, i, obj); } + + done: + talloc_destroy(mem_ctx); return result; } @@ -207,7 +214,7 @@ static PyObject *lsa_lookup_names(PyObject *self, PyObject *args) static PyObject *lsa_lookup_sids(PyObject *self, PyObject *args, PyObject *kw) { - PyObject *py_sids, *result; + PyObject *py_sids, *result = NULL; NTSTATUS ntstatus; int num_sids, i; char **domains, **names; @@ -224,7 +231,7 @@ static PyObject *lsa_lookup_sids(PyObject *self, PyObject *args, return NULL; } - if (!(mem_ctx = talloc_init("lsa_open_policy"))) { + if (!(mem_ctx = talloc_init("lsa_lookup_sids"))) { PyErr_SetString(lsa_error, "unable to init talloc context\n"); goto done; } @@ -243,7 +250,6 @@ static PyObject *lsa_lookup_sids(PyObject *self, PyObject *args, if (!string_to_sid(&sids[i], PyString_AsString(obj))) { PyErr_SetString(PyExc_ValueError, "string_to_sid failed"); - result = NULL; goto done; } } @@ -257,7 +263,6 @@ static PyObject *lsa_lookup_sids(PyObject *self, PyObject *args, if (!string_to_sid(&sids[0], PyString_AsString(py_sids))) { PyErr_SetString(PyExc_ValueError, "string_to_sid failed"); - result = NULL; goto done; } } @@ -268,7 +273,6 @@ static PyObject *lsa_lookup_sids(PyObject *self, PyObject *args, if (!NT_STATUS_IS_OK(ntstatus)) { PyErr_SetObject(lsa_ntstatus, py_ntstatus_tuple(ntstatus)); - result = NULL; goto done; } @@ -285,8 +289,7 @@ static PyObject *lsa_lookup_sids(PyObject *self, PyObject *args, } done: - if (mem_ctx) - talloc_destroy(mem_ctx); + talloc_destroy(mem_ctx); return result; } @@ -404,7 +407,7 @@ static PyMethodDef lsa_methods[] = { "\n" "Example:\n" "\n" -">>> spoolss.setup_logging(interactive = 1)" }, +">>> lsa.setup_logging(interactive = 1)" }, { "get_debuglevel", (PyCFunction)get_debuglevel, METH_VARARGS, @@ -412,7 +415,7 @@ static PyMethodDef lsa_methods[] = { "\n" "Example:\n" "\n" -">>> spoolss.get_debuglevel()\n" +">>> lsa.get_debuglevel()\n" "0" }, { "set_debuglevel", (PyCFunction)set_debuglevel, @@ -421,7 +424,7 @@ static PyMethodDef lsa_methods[] = { "\n" "Example:\n" "\n" -">>> spoolss.set_debuglevel(10)" }, +">>> lsa.set_debuglevel(10)" }, { NULL } }; diff --git a/source3/python/py_smb.c b/source3/python/py_smb.c index bb84a337c9..e5e6506196 100644 --- a/source3/python/py_smb.c +++ b/source3/python/py_smb.c @@ -221,10 +221,10 @@ static PyObject *py_smb_query_secdesc(PyObject *self, PyObject *args, { cli_state_object *cli = (cli_state_object *)self; static char *kwlist[] = { "fnum", NULL }; - PyObject *result; + PyObject *result = NULL; SEC_DESC *secdesc = NULL; int fnum; - TALLOC_CTX *mem_ctx; + TALLOC_CTX *mem_ctx = NULL; /* Parse parameters */ @@ -238,7 +238,6 @@ static PyObject *py_smb_query_secdesc(PyObject *self, PyObject *args, if (cli_is_error(cli->cli)) { PyErr_SetString(PyExc_RuntimeError, "query_secdesc failed"); - result = NULL; goto done; } @@ -252,7 +251,6 @@ static PyObject *py_smb_query_secdesc(PyObject *self, PyObject *args, PyErr_SetString( PyExc_TypeError, "Invalid security descriptor returned"); - result = NULL; goto done; } @@ -268,11 +266,12 @@ static PyObject *py_smb_set_secdesc(PyObject *self, PyObject *args, { cli_state_object *cli = (cli_state_object *)self; static char *kwlist[] = { "fnum", "security_descriptor", NULL }; + PyObject *result = NULL; PyObject *py_secdesc; SEC_DESC *secdesc; - TALLOC_CTX *mem_ctx = talloc_init("py_smb_set_secdesc"); + TALLOC_CTX *mem_ctx = NULL; int fnum; - BOOL result; + BOOL err; /* Parse parameters */ @@ -280,20 +279,26 @@ static PyObject *py_smb_set_secdesc(PyObject *self, PyObject *args, args, kw, "iO", kwlist, &fnum, &py_secdesc)) return NULL; + mem_ctx = talloc_init("py_smb_set_secdesc"); + if (!py_to_SECDESC(&secdesc, py_secdesc, mem_ctx)) { PyErr_SetString(PyExc_TypeError, "Invalid security descriptor"); - return NULL; + goto done; } - result = cli_set_secdesc(cli->cli, fnum, secdesc); + err = cli_set_secdesc(cli->cli, fnum, secdesc); if (cli_is_error(cli->cli)) { PyErr_SetString(PyExc_RuntimeError, "set_secdesc failed"); - return NULL; + goto done; } - return PyInt_FromLong(result); + result = PyInt_FromLong(err); + done: + talloc_destroy(mem_ctx); + + return result; } static PyMethodDef smb_hnd_methods[] = { diff --git a/source3/python/py_spoolss_drivers.c b/source3/python/py_spoolss_drivers.c index a072ac0d5c..12190519ec 100644 --- a/source3/python/py_spoolss_drivers.c +++ b/source3/python/py_spoolss_drivers.c @@ -177,6 +177,7 @@ PyObject *spoolss_hnd_getprinterdriver(PyObject *self, PyObject *args, int level = 1; uint32 needed; char *arch = "Windows NT x86"; + int version = 2; static char *kwlist[] = {"level", "arch", NULL}; /* Parse parameters */ @@ -189,12 +190,12 @@ PyObject *spoolss_hnd_getprinterdriver(PyObject *self, PyObject *args, werror = cli_spoolss_getprinterdriver( hnd->cli, hnd->mem_ctx, 0, &needed, &hnd->pol, level, - arch, &ctr); + version, arch, &ctr); if (W_ERROR_V(werror) == ERRinsufficientbuffer) werror = cli_spoolss_getprinterdriver( hnd->cli, hnd->mem_ctx, needed, NULL, &hnd->pol, - level, arch, &ctr); + level, version, arch, &ctr); if (!W_ERROR_IS_OK(werror)) { PyErr_SetObject(spoolss_werror, py_werror_tuple(werror)); diff --git a/source3/python/py_winbind.c b/source3/python/py_winbind.c index ebceb95d71..130f78d7e1 100644 --- a/source3/python/py_winbind.c +++ b/source3/python/py_winbind.c @@ -427,7 +427,10 @@ static PyObject *py_auth_crap(PyObject *self, PyObject *args, PyObject *kw) ZERO_STRUCT(request); ZERO_STRUCT(response); - fstrcpy(request.data.auth_crap.user, username); + if (push_utf8_fstring(request.data.auth_crap.user, username) == -1) { + PyErr_SetString(winbind_error, "unable to create utf8 string"); + return NULL; + } generate_random_buffer(request.data.auth_crap.chal, 8, False); @@ -473,7 +476,10 @@ static PyObject *py_auth_smbd(PyObject *self, PyObject *args, PyObject *kw) ZERO_STRUCT(request); ZERO_STRUCT(response); - fstrcpy(request.data.smbd_auth_crap.user, username); + if (push_utf8_fstring(request.data.auth_crap.user, username) == -1) { + PyErr_SetString("unable to create utf8 string"); + return NULL; + } generate_random_buffer(request.data.smbd_auth_crap.chal, 8, False); diff --git a/source3/rpc_client/cli_netlogon.c b/source3/rpc_client/cli_netlogon.c index 7b8cd19174..97bc4c65b7 100644 --- a/source3/rpc_client/cli_netlogon.c +++ b/source3/rpc_client/cli_netlogon.c @@ -514,7 +514,7 @@ NTSTATUS cli_netlogon_sam_logon(struct cli_state *cli, TALLOC_CTX *mem_ctx, 0, /* param_ctrl */ 0xdead, 0xbeef, /* LUID? */ username, cli->clnt_name_slash, - cli->sess_key, lm_owf_user_pwd, + (const char *)cli->sess_key, lm_owf_user_pwd, nt_owf_user_pwd); break; @@ -685,31 +685,20 @@ NTSTATUS cli_net_srv_pwset(struct cli_state *cli, TALLOC_CTX *mem_ctx, NET_Q_SRV_PWSET q_s; uint16 sec_chan_type = 2; NTSTATUS nt_status; - char *mach_acct; gen_next_creds( cli, &new_clnt_cred); prs_init(&qbuf , 1024, mem_ctx, MARSHALL); prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* create and send a MSRPC command with api NET_SRV_PWSET */ - - mach_acct = talloc_asprintf(mem_ctx, "%s$", machine_name); - - if (!mach_acct) { - DEBUG(0,("talloc_asprintf failed!\n")); - nt_status = NT_STATUS_NO_MEMORY; - goto done; - } - DEBUG(4,("cli_net_srv_pwset: srv:%s acct:%s sc: %d mc: %s clnt %s %x\n", - cli->srv_name_slash, mach_acct, sec_chan_type, machine_name, + cli->srv_name_slash, cli->mach_acct, sec_chan_type, machine_name, credstr(new_clnt_cred.challenge.data), new_clnt_cred.timestamp.time)); /* store the parameters */ - init_q_srv_pwset(&q_s, cli->srv_name_slash, cli->sess_key, - mach_acct, sec_chan_type, machine_name, - &new_clnt_cred, (char *)hashed_mach_pwd); + init_q_srv_pwset(&q_s, cli->srv_name_slash, (const char *)cli->sess_key, + cli->mach_acct, sec_chan_type, machine_name, + &new_clnt_cred, hashed_mach_pwd); /* turn parameters into data stream */ if(!net_io_q_srv_pwset("", &q_s, &qbuf, 0)) { diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index ebe54c2c06..dedbf017a9 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -264,7 +264,7 @@ static BOOL rpc_auth_pipe(struct cli_state *cli, prs_struct *rdata, DATA_BLOB ntlmssp_verf = data_blob(NULL, auth_len); /* save the reply away, for use a little later */ - prs_copy_data_out(ntlmssp_verf.data, &auth_verf, auth_len); + prs_copy_data_out((char *)ntlmssp_verf.data, &auth_verf, auth_len); return (NT_STATUS_IS_OK(ntlmssp_client_store_response(cli->ntlmssp_pipe_state, @@ -287,7 +287,7 @@ static BOOL rpc_auth_pipe(struct cli_state *cli, prs_struct *rdata, return False; } sig = data_blob(NULL, auth_len); - prs_copy_data_out(sig.data, &auth_verf, auth_len); + prs_copy_data_out((char *)sig.data, &auth_verf, auth_len); } /* @@ -306,12 +306,12 @@ static BOOL rpc_auth_pipe(struct cli_state *cli, prs_struct *rdata, return False; } nt_status = ntlmssp_client_unseal_packet(cli->ntlmssp_pipe_state, - reply_data, data_len, + (unsigned char *)reply_data, data_len, &sig); } else if (cli->pipe_auth_flags & AUTH_PIPE_SIGN) { nt_status = ntlmssp_client_check_packet(cli->ntlmssp_pipe_state, - reply_data, data_len, + (const unsigned char *)reply_data, data_len, &sig); } @@ -684,10 +684,10 @@ static NTSTATUS create_rpc_bind_req(struct cli_state *cli, prs_struct *rpc_out, /* Auth len in the rpc header doesn't include auth_header. */ auth_len = request.length; - prs_copy_data_in(&auth_info, request.data, request.length); + prs_copy_data_in(&auth_info, (char *)request.data, request.length); DEBUG(5, ("NTLMSSP Negotiate:\n")); - dump_data(5, request.data, request.length); + dump_data(5, (const char *)request.data, request.length); data_blob_free(&request); @@ -751,6 +751,7 @@ static NTSTATUS create_rpc_bind_req(struct cli_state *cli, prs_struct *rpc_out, return NT_STATUS_NO_MEMORY; } } + prs_mem_free(&auth_info); return NT_STATUS_OK; } @@ -810,7 +811,7 @@ static NTSTATUS create_rpc_bind_resp(struct cli_state *cli, * Append the auth data to the outgoing buffer. */ - if(!prs_copy_data_in(rpc_out, ntlmssp_reply.data, ntlmssp_reply.length)) { + if(!prs_copy_data_in(rpc_out, (char *)ntlmssp_reply.data, ntlmssp_reply.length)) { DEBUG(0,("create_rpc_bind_req: failed to grow parse struct to add auth.\n")); data_blob_free(&ntlmssp_reply); return NT_STATUS_NO_MEMORY; @@ -1016,7 +1017,7 @@ BOOL rpc_api_pipe_req(struct cli_state *cli, uint8 op_num, /* write auth footer onto the packet */ real_auth_len = sign_blob.length; - prs_copy_data_in(&sec_blob, sign_blob.data, sign_blob.length); + prs_copy_data_in(&sec_blob, (char *)sign_blob.data, sign_blob.length); data_blob_free(&sign_blob); } @@ -1492,7 +1493,9 @@ NTSTATUS cli_nt_establish_netlogon(struct cli_state *cli, int sec_chan, const uchar trust_password[16]) { NTSTATUS result; - uint32 neg_flags = 0x000001ff; + /* The 7 here seems to be required to get Win2k not to downgrade us + to NT4. Actually, anything other than 1ff would seem to do... */ + uint32 neg_flags = 0x000701ff; int fnum; cli_nt_netlogon_netsec_session_close(cli); @@ -1585,7 +1588,9 @@ NTSTATUS cli_nt_setup_netsec(struct cli_state *cli, int sec_chan, const uchar trust_password[16]) { NTSTATUS result; - uint32 neg_flags = 0x000001ff; + /* The 7 here seems to be required to get Win2k not to downgrade us + to NT4. Actually, anything other than 1ff would seem to do... */ + uint32 neg_flags = 0x000701ff; cli->pipe_auth_flags = 0; if (lp_client_schannel() == False) { diff --git a/source3/rpc_client/cli_spoolss.c b/source3/rpc_client/cli_spoolss.c index 6392620497..8f5f2413de 100644 --- a/source3/rpc_client/cli_spoolss.c +++ b/source3/rpc_client/cli_spoolss.c @@ -720,7 +720,7 @@ WERROR cli_spoolss_getprinterdriver(struct cli_state *cli, TALLOC_CTX *mem_ctx, uint32 offered, uint32 *needed, POLICY_HND *pol, uint32 level, - const char *env, PRINTER_DRIVER_CTR *ctr) + const char *env, int version, PRINTER_DRIVER_CTR *ctr) { prs_struct qbuf, rbuf; SPOOL_Q_GETPRINTERDRIVER2 q; @@ -742,7 +742,7 @@ WERROR cli_spoolss_getprinterdriver(struct cli_state *cli, prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - make_spoolss_q_getprinterdriver2(&q, pol, env, level, 2, 2, + make_spoolss_q_getprinterdriver2(&q, pol, env, level, version, 2, &buffer, offered); /* Marshall data and send request */ @@ -2027,7 +2027,7 @@ WERROR cli_spoolss_setprinterdata(struct cli_state *cli, TALLOC_CTX *mem_ctx, /* Initialise input parameters */ make_spoolss_q_setprinterdata( - &q, hnd, value->valuename, value->type, value->data_p, value->size); + &q, hnd, value->valuename, value->type, (char *)value->data_p, value->size); /* Marshall data and send request */ @@ -2072,7 +2072,7 @@ WERROR cli_spoolss_setprinterdataex(struct cli_state *cli, TALLOC_CTX *mem_ctx, /* Initialise input parameters */ make_spoolss_q_setprinterdataex( - &q, hnd, keyname, value->valuename, value->type, value->data_p, + &q, hnd, keyname, value->valuename, value->type, (char *)value->data_p, value->size); /* Marshall data and send request */ @@ -2215,7 +2215,7 @@ WERROR cli_spoolss_enumprinterdataex(struct cli_state *cli, TALLOC_CTX *mem_ctx, rpcstr_pull(name, v->valuename.buffer, sizeof(name), -1, STR_TERMINATE); - regval_ctr_addvalue(ctr, name, v->type, v->data, v->data_len); + regval_ctr_addvalue(ctr, name, v->type, (const char *)v->data, v->data_len); } done: diff --git a/source3/rpc_parse/parse_echo.c b/source3/rpc_parse/parse_echo.c index 67f9ad772e..4b1ff1f4d5 100644 --- a/source3/rpc_parse/parse_echo.c +++ b/source3/rpc_parse/parse_echo.c @@ -73,7 +73,7 @@ BOOL echo_io_q_echo_data(const char *desc, ECHO_Q_ECHO_DATA *q_d, return False; } - if (!prs_uint8s(False, "data", ps, depth, q_d->data, q_d->size)) + if (!prs_uint8s(False, "data", ps, depth, (unsigned char *)q_d->data, q_d->size)) return False; return True; @@ -92,7 +92,7 @@ BOOL echo_io_r_echo_data(const char *desc, ECHO_R_ECHO_DATA *q_d, return False; } - if (!prs_uint8s(False, "data", ps, depth, q_d->data, q_d->size)) + if (!prs_uint8s(False, "data", ps, depth, (unsigned char *)q_d->data, q_d->size)) return False; return True; @@ -120,7 +120,7 @@ BOOL echo_io_q_sink_data(const char *desc, ECHO_Q_SINK_DATA *q_d, return False; } - if (!prs_uint8s(False, "data", ps, depth, q_d->data, q_d->size)) + if (!prs_uint8s(False, "data", ps, depth, (unsigned char *)q_d->data, q_d->size)) return False; return True; @@ -159,7 +159,7 @@ BOOL echo_io_r_source_data(const char *desc, ECHO_R_SOURCE_DATA *q_d, return False; } - if (!prs_uint8s(False, "data", ps, depth, q_d->data, q_d->size)) + if (!prs_uint8s(False, "data", ps, depth, (unsigned char *)q_d->data, q_d->size)) return False; return True; diff --git a/source3/rpc_parse/parse_net.c b/source3/rpc_parse/parse_net.c index 804da707de..dd319df5a0 100644 --- a/source3/rpc_parse/parse_net.c +++ b/source3/rpc_parse/parse_net.c @@ -801,7 +801,7 @@ void init_q_srv_pwset(NET_Q_SRV_PWSET *q_s, DEBUG(5,("init_q_srv_pwset\n")); /* Process the new password. */ - cred_hash3( nt_cypher, hashed_mach_pwd, sess_key, 1); + cred_hash3( nt_cypher, hashed_mach_pwd, (const unsigned char *)sess_key, 1); init_clnt_info(&q_s->clnt_id, logon_srv, acct_name, sec_chan, comp_name, cred); @@ -2447,6 +2447,10 @@ static BOOL net_io_sam_policy_info(const char *desc, SAM_DELTA_POLICY *info, return True; } +#if 0 + +/* This function is pretty broken - see bug #334 */ + /******************************************************************* reads or writes a structure. ********************************************************************/ @@ -2495,6 +2499,12 @@ static BOOL net_io_sam_trustdoms_info(const char *desc, SAM_DELTA_TRUSTDOMS *inf return True; } +#endif + +#if 0 + +/* This function doesn't work - see bug #334 */ + /******************************************************************* reads or writes a structure. ********************************************************************/ @@ -2582,6 +2592,8 @@ static BOOL net_io_sam_secret_info(const char *desc, SAM_DELTA_SECRET *info, return True; } +#endif + /******************************************************************* reads or writes a structure. ********************************************************************/ @@ -2726,14 +2738,10 @@ static BOOL net_io_sam_delta_ctr(const char *desc, uint8 sess_key[16], return False; break; - case SAM_DELTA_TRUST_DOMS: - if (!net_io_sam_trustdoms_info("", &delta->trustdoms_info, ps, depth)) - return False; - break; + /* These guys are implemented but broken */ + case SAM_DELTA_TRUST_DOMS: 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 */ diff --git a/source3/rpc_parse/parse_prs.c b/source3/rpc_parse/parse_prs.c index 11d8658b15..81a9573077 100644 --- a/source3/rpc_parse/parse_prs.c +++ b/source3/rpc_parse/parse_prs.c @@ -1402,7 +1402,7 @@ static void netsec_digest(struct netsec_auth_struct *a, if (auth_flags & AUTH_PIPE_SEAL) { MD5Update(&ctx3, verf->data8, sizeof(verf->data8)); } - MD5Update(&ctx3, data, data_len); + MD5Update(&ctx3, (const unsigned char *)data, data_len); MD5Final(whole_packet_digest, &ctx3); dump_data_pw("whole_packet_digest:\n", whole_packet_digest, sizeof(whole_packet_digest)); @@ -1429,7 +1429,7 @@ static void netsec_get_sealing_key(struct netsec_auth_struct *a, dump_data_pw("sess_kf0:\n", sess_kf0, sizeof(sess_kf0)); - /* MD5 of sess_kf0 and the high bytes of the sequence number */ + /* MD5 of sess_kf0 and 4 zero bytes */ hmac_md5(sess_kf0, zeros, 0x4, digest2); dump_data_pw("digest2:\n", digest2, sizeof(digest2)); @@ -1506,9 +1506,9 @@ void netsec_encode(struct netsec_auth_struct *a, int auth_flags, dump_data_pw("verf->data8_enc:\n", verf->data8, sizeof(verf->data8)); /* encode the packet payload */ - dump_data_pw("data:\n", data, data_len); - netsechash(sealing_key, data, data_len); - dump_data_pw("data_enc:\n", data, data_len); + dump_data_pw("data:\n", (const unsigned char *)data, data_len); + netsechash(sealing_key, (unsigned char *)data, data_len); + dump_data_pw("data_enc:\n", (const unsigned char *)data, data_len); } /* encode the sequence number (key based on packet digest) */ @@ -1578,9 +1578,9 @@ BOOL netsec_decode(struct netsec_auth_struct *a, int auth_flags, sizeof(verf->data8)); /* extract the packet payload */ - dump_data_pw("data :\n", data, data_len); - netsechash(sealing_key, data, data_len); - dump_data_pw("datadec:\n", data, data_len); + dump_data_pw("data :\n", (const unsigned char *)data, data_len); + netsechash(sealing_key, (unsigned char *)data, data_len); + dump_data_pw("datadec:\n", (const unsigned char *)data, data_len); } /* digest includes 'data' after unsealing */ diff --git a/source3/rpc_parse/parse_reg.c b/source3/rpc_parse/parse_reg.c index b4d20bf2ba..bbf6e6a8e3 100644 --- a/source3/rpc_parse/parse_reg.c +++ b/source3/rpc_parse/parse_reg.c @@ -40,7 +40,7 @@ static uint32 reg_init_buffer2( BUFFER2 *buf2, REGISTRY_VALUE *val ) return 0; real_size = regval_size(val); - init_buffer2( buf2, (char*)regval_data_p(val), real_size ); + init_buffer2( buf2, (unsigned char*)regval_data_p(val), real_size ); return real_size; } diff --git a/source3/rpc_parse/parse_samr.c b/source3/rpc_parse/parse_samr.c index fce3195225..1fe9b3231f 100644 --- a/source3/rpc_parse/parse_samr.c +++ b/source3/rpc_parse/parse_samr.c @@ -183,9 +183,9 @@ BOOL samr_io_r_lookup_domain(const char *desc, SAMR_R_LOOKUP_DOMAIN * r_u, reads or writes a structure. ********************************************************************/ -void init_samr_q_unknown_2d(SAMR_Q_UNKNOWN_2D * q_u, POLICY_HND *dom_pol, DOM_SID *sid) +void init_samr_q_remove_user_foreign_domain(SAMR_Q_REMOVE_USER_FOREIGN_DOMAIN * q_u, POLICY_HND *dom_pol, DOM_SID *sid) { - DEBUG(5, ("samr_init_samr_q_unknown_2d\n")); + DEBUG(5, ("samr_init_samr_q_remove_user_foreign_domain\n")); q_u->dom_pol = *dom_pol; init_dom_sid2(&q_u->sid, sid); @@ -195,13 +195,13 @@ void init_samr_q_unknown_2d(SAMR_Q_UNKNOWN_2D * q_u, POLICY_HND *dom_pol, DOM_SI reads or writes a structure. ********************************************************************/ -BOOL samr_io_q_unknown_2d(const char *desc, SAMR_Q_UNKNOWN_2D * q_u, +BOOL samr_io_q_remove_user_foreign_domain(const char *desc, SAMR_Q_REMOVE_USER_FOREIGN_DOMAIN * q_u, prs_struct *ps, int depth) { if (q_u == NULL) return False; - prs_debug(ps, depth, desc, "samr_io_q_unknown_2d"); + prs_debug(ps, depth, desc, "samr_io_q_remove_user_foreign_domain"); depth++; if(!prs_align(ps)) @@ -223,13 +223,13 @@ BOOL samr_io_q_unknown_2d(const char *desc, SAMR_Q_UNKNOWN_2D * q_u, reads or writes a structure. ********************************************************************/ -BOOL samr_io_r_unknown_2d(const char *desc, SAMR_R_UNKNOWN_2D * r_u, +BOOL samr_io_r_remove_user_foreign_domain(const char *desc, SAMR_R_REMOVE_USER_FOREIGN_DOMAIN * r_u, prs_struct *ps, int depth) { if (r_u == NULL) return False; - prs_debug(ps, depth, desc, "samr_io_r_unknown_2d"); + prs_debug(ps, depth, desc, "samr_io_r_remove_user_foreign_domain"); depth++; if(!prs_align(ps)) diff --git a/source3/rpc_parse/parse_spoolss.c b/source3/rpc_parse/parse_spoolss.c index 1a380c64d5..7ca9bccab4 100644 --- a/source3/rpc_parse/parse_spoolss.c +++ b/source3/rpc_parse/parse_spoolss.c @@ -1368,7 +1368,7 @@ BOOL spoolss_io_r_getprinterdata(const char *desc, SPOOL_R_GETPRINTERDATA *r_u, return False; if (UNMARSHALLING(ps) && r_u->size) { - r_u->data = prs_alloc_mem(ps, r_u->size); + r_u->data = (unsigned char *)prs_alloc_mem(ps, r_u->size); if(!r_u->data) return False; } @@ -6178,7 +6178,7 @@ BOOL make_spoolss_q_setprinterdata(SPOOL_Q_SETPRINTERDATA *q_u, const POLICY_HND init_unistr2(&q_u->value, value, strlen(value)+1); q_u->max_len = q_u->real_len = data_size; - q_u->data = data; + q_u->data = (unsigned char *)data; return True; } @@ -6195,7 +6195,7 @@ BOOL make_spoolss_q_setprinterdataex(SPOOL_Q_SETPRINTERDATAEX *q_u, const POLICY init_unistr2(&q_u->key, key, strlen(key)+1); q_u->max_len = q_u->real_len = data_size; - q_u->data = data; + q_u->data = (unsigned char *)data; return True; } @@ -6990,7 +6990,7 @@ BOOL spoolss_io_r_getprinterdataex(const char *desc, SPOOL_R_GETPRINTERDATAEX *r return False; if (UNMARSHALLING(ps) && r_u->size) { - r_u->data = prs_alloc_mem(ps, r_u->size); + r_u->data = (unsigned char *)prs_alloc_mem(ps, r_u->size); if(!r_u->data) return False; } @@ -7689,7 +7689,7 @@ BOOL make_spoolss_q_writeprinter(SPOOL_Q_WRITEPRINTER *q_u, { memcpy(&q_u->handle, handle, sizeof(POLICY_HND)); q_u->buffer_size = q_u->buffer_size2 = data_size; - q_u->buffer = data; + q_u->buffer = (unsigned char *)data; return True; } diff --git a/source3/rpc_server/srv_dfs.c b/source3/rpc_server/srv_dfs.c index 27bb0732b4..6c35917e61 100644 --- a/source3/rpc_server/srv_dfs.c +++ b/source3/rpc_server/srv_dfs.c @@ -157,17 +157,23 @@ static BOOL api_dfs_enum(pipes_struct *p) /******************************************************************* \pipe\netdfs commands ********************************************************************/ - -NTSTATUS rpc_dfs_init(void) +static struct api_struct api_netdfs_cmds[] = { - struct api_struct api_netdfs_cmds[] = - { {"DFS_EXIST", DFS_EXIST, api_dfs_exist }, {"DFS_ADD", DFS_ADD, api_dfs_add }, {"DFS_REMOVE", DFS_REMOVE, api_dfs_remove }, {"DFS_GET_INFO", DFS_GET_INFO, api_dfs_get_info }, {"DFS_ENUM", DFS_ENUM, api_dfs_enum } - }; +}; + +void netdfs_get_pipe_fns( struct api_struct **fns, int *n_fns ) +{ + *fns = api_netdfs_cmds; + *n_fns = sizeof(api_netdfs_cmds) / sizeof(struct api_struct); +} + +NTSTATUS rpc_dfs_init(void) +{ return rpc_pipe_register_commands(SMB_RPC_INTERFACE_VERSION, "netdfs", "netdfs", api_netdfs_cmds, sizeof(api_netdfs_cmds) / sizeof(struct api_struct)); } diff --git a/source3/rpc_server/srv_dfs_nt.c b/source3/rpc_server/srv_dfs_nt.c index eba4eaec75..3470ad99b4 100644 --- a/source3/rpc_server/srv_dfs_nt.c +++ b/source3/rpc_server/srv_dfs_nt.c @@ -159,7 +159,7 @@ WERROR _dfs_remove(pipes_struct *p, DFS_Q_DFS_REMOVE *q_u, { pstring refpath; pstrcpy(refpath,jn.referral_list[i].alternate_path); - trim_string(refpath, "\\", "\\"); + trim_char(refpath, '\\', '\\'); DEBUG(10,("_dfs_remove: refpath: .%s.\n", refpath)); if(strequal(refpath, altpath)) { @@ -257,7 +257,7 @@ static BOOL init_reply_dfs_info_3(TALLOC_CTX *ctx, struct junction_map* j, DFS_I struct referral* ref = &(j[i].referral_list[ii]); pstrcpy(path, ref->alternate_path); - trim_string(path,"\\",""); + trim_char(path,'\\','\0'); p = strrchr_m(path,'\\'); if(p==NULL) { diff --git a/source3/rpc_server/srv_echo.c b/source3/rpc_server/srv_echo.c index 166b6e939d..c6cfde07c1 100644 --- a/source3/rpc_server/srv_echo.c +++ b/source3/rpc_server/srv_echo.c @@ -120,18 +120,31 @@ static BOOL api_sink_data(pipes_struct *p) \pipe\rpcecho commands ********************************************************************/ -NTSTATUS rpc_echo_init(void) +struct api_struct api_echo_cmds[] = { + {"ADD_ONE", ECHO_ADD_ONE, api_add_one }, + {"ECHO_DATA", ECHO_DATA, api_echo_data }, + {"SOURCE_DATA", ECHO_SOURCE_DATA, api_source_data }, + {"SINK_DATA", ECHO_SINK_DATA, api_sink_data }, +}; + + +void echo_get_pipe_fns( struct api_struct **fns, int *n_fns ) { - struct api_struct api_echo_cmds[] = { - {"ADD_ONE", ECHO_ADD_ONE, api_add_one }, - {"ECHO_DATA", ECHO_DATA, api_echo_data }, - {"SOURCE_DATA", ECHO_SOURCE_DATA, api_source_data }, - {"SINK_DATA", ECHO_SINK_DATA, api_sink_data }, - }; + *fns = api_echo_cmds; + *n_fns = sizeof(api_echo_cmds) / sizeof(struct api_struct); +} +NTSTATUS rpc_echo_init(void) +{ return rpc_pipe_register_commands(SMB_RPC_INTERFACE_VERSION, "rpcecho", "rpcecho", api_echo_cmds, sizeof(api_echo_cmds) / sizeof(struct api_struct)); } +#else /* DEVELOPER */ + +NTSTATUS rpc_echo_init(void) +{ + return NT_STATUS_OK; +} #endif /* DEVELOPER */ diff --git a/source3/rpc_server/srv_lsa.c b/source3/rpc_server/srv_lsa.c index 34812b15d9..138fb1d7ef 100644 --- a/source3/rpc_server/srv_lsa.c +++ b/source3/rpc_server/srv_lsa.c @@ -644,9 +644,8 @@ static BOOL api_lsa_query_info2(pipes_struct *p) /*************************************************************************** \PIPE\ntlsa commands ***************************************************************************/ -NTSTATUS rpc_lsa_init(void) -{ -static const struct api_struct api_lsa_cmds[] = + +static struct api_struct api_lsa_cmds[] = { { "LSA_OPENPOLICY2" , LSA_OPENPOLICY2 , api_lsa_open_policy2 }, { "LSA_OPENPOLICY" , LSA_OPENPOLICY , api_lsa_open_policy }, @@ -671,17 +670,33 @@ static const struct api_struct api_lsa_cmds[] = ADS DC capabilities */ { "LSA_QUERYINFO2" , LSA_QUERYINFO2 , api_lsa_query_info2 } }; -/* - * NOTE: Certain calls can not be enabled if we aren't an ADS DC. Make sure - * these calls are always last and that you decrement by the amount of calls - * to disable. - */ - int funcs = sizeof(api_lsa_cmds) / sizeof(struct api_struct); - if (!(SEC_ADS == lp_security() && ROLE_DOMAIN_PDC == lp_server_role())) { - funcs -= 1; - } +static int count_fns(void) +{ + int funcs = sizeof(api_lsa_cmds) / sizeof(struct api_struct); + + /* + * NOTE: Certain calls can not be enabled if we aren't an ADS DC. Make sure + * these calls are always last and that you decrement by the amount of calls + * to disable. + */ + if (!(SEC_ADS == lp_security() && ROLE_DOMAIN_PDC == lp_server_role())) { + funcs -= 1; + } + + return funcs; +} +void lsa_get_pipe_fns( struct api_struct **fns, int *n_fns ) +{ + *fns = api_lsa_cmds; + *n_fns = count_fns(); +} + + +NTSTATUS rpc_lsa_init(void) +{ + int funcs = count_fns(); - return rpc_pipe_register_commands(SMB_RPC_INTERFACE_VERSION, "lsarpc", "lsass", api_lsa_cmds, - funcs); + return rpc_pipe_register_commands(SMB_RPC_INTERFACE_VERSION, "lsarpc", "lsass", api_lsa_cmds, + funcs); } diff --git a/source3/rpc_server/srv_lsa_ds.c b/source3/rpc_server/srv_lsa_ds.c new file mode 100644 index 0000000000..1e75175c2c --- /dev/null +++ b/source3/rpc_server/srv_lsa_ds.c @@ -0,0 +1,93 @@ +/* + * Unix SMB/CIFS implementation. + * RPC Pipe client / server routines + * Copyright (C) Gerald Carter 2003 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* This is the interface for the registry functions. */ + +#include "includes.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_RPC_SRV + +#if 0 /* disabled */ +/******************************************************************* + api_reg_open_entry + ********************************************************************/ + +static BOOL api_dsrole_get_primary_dominfo(pipes_struct *p) +{ + DS_Q_GETPRIMDOMINFO q_u; + DS_R_GETPRIMDOMINFO r_u; + prs_struct *data = &p->in_data.data; + prs_struct *rdata = &p->out_data.rdata; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + /* grab the request */ + if ( !ds_io_q_getprimdominfo("", data, 0, &q_u) ) + return False; + + /* construct reply. */ + r_u.status = _dsrole_get_primary_dominfo( p, &q_u, &r_u ); + + if ( !ds_io_r_getprimdominfo("", rdata, 0, &r_u) ) + return False; + + return True; +} +#endif + +/******************************************************************* + stub functions for unimplemented RPC +*******************************************************************/ + +static BOOL api_dsrole_stub( pipes_struct *p ) +{ + DEBUG(0,("api_dsrole_stub: Hmmm....didn't know this RPC existed...\n")); + + return False; +} + + +/******************************************************************* + array of \PIPE\lsass (new windows 2000 UUID) operations +********************************************************************/ +static struct api_struct api_lsa_ds_cmds[] = { + { "DS_NOP", DS_NOP, api_dsrole_stub } + +#if 0 /* disabled due to breakage with viewing domain users and groups + on a Samba PDC from win2k clients --jerry CIFS 2003 */ + { "DS_GETPRIMDOMINFO", DS_GETPRIMDOMINFO, api_dsrole_get_primary_dominfo } +#endif + +}; + +void lsa_ds_get_pipe_fns( struct api_struct **fns, int *n_fns ) +{ + *fns = api_lsa_ds_cmds; + *n_fns = sizeof(api_lsa_ds_cmds) / sizeof(struct api_struct); +} + + +NTSTATUS rpc_lsa_ds_init(void) +{ + return rpc_pipe_register_commands(SMB_RPC_INTERFACE_VERSION, "lsa_ds", "lsa_ds", api_lsa_ds_cmds, + sizeof(api_lsa_ds_cmds) / sizeof(struct api_struct)); +} diff --git a/source3/rpc_server/srv_lsa_ds_nt.c b/source3/rpc_server/srv_lsa_ds_nt.c new file mode 100644 index 0000000000..37540a9668 --- /dev/null +++ b/source3/rpc_server/srv_lsa_ds_nt.c @@ -0,0 +1,127 @@ +/* + * Unix SMB/CIFS implementation. + * RPC Pipe client / server routines + * Copyright (C) Andrew Tridgell 1992-1997. + * Copyright (C) Luke Kenneth Casson Leighton 1996-1997. + * Copyright (C) Paul Ashton 1997. + * Copyright (C) Jeremy Allison 2001. + * Copyright (C) Gerald Carter 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 + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* Implementation of registry functions. */ + +#include "includes.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_RPC_SRV + +/******************************************************************** + Fill in a DS_DOMINFO_CTR structure + ********************************************************************/ + +static NTSTATUS fill_dsrole_dominfo_basic(TALLOC_CTX *ctx, DSROLE_PRIMARY_DOMAIN_INFO_BASIC **info) +{ + DSROLE_PRIMARY_DOMAIN_INFO_BASIC *basic; + const char *netbios_domain; + fstring dnsdomain; + + DEBUG(10,("fill_dsrole_dominfo_basic: enter\n")); + + if ( !(basic = talloc_zero(ctx, sizeof(DSROLE_PRIMARY_DOMAIN_INFO_BASIC))) ) { + DEBUG(0,("fill_dsrole_dominfo_basic: FATAL error! talloc_xero() failed\n")); + return NT_STATUS_NO_MEMORY; + } + + switch ( lp_server_role() ) { + case ROLE_STANDALONE: + basic->machine_role = DSROLE_STANDALONE_SRV; + break; + case ROLE_DOMAIN_MEMBER: + basic->machine_role = DSROLE_DOMAIN_MEMBER_SRV; + break; + case ROLE_DOMAIN_BDC: + basic->machine_role = DSROLE_BDC; + basic->flags = DSROLE_PRIMARY_DS_RUNNING|DSROLE_PRIMARY_DS_MIXED_MODE; + if ( secrets_fetch_domain_guid( lp_workgroup(), &basic->domain_guid ) ) + basic->flags |= DSROLE_PRIMARY_DOMAIN_GUID_PRESENT; + get_mydomname(dnsdomain); + strlower_m(dnsdomain); + break; + case ROLE_DOMAIN_PDC: + basic->machine_role = DSROLE_PDC; + basic->flags = DSROLE_PRIMARY_DS_RUNNING|DSROLE_PRIMARY_DS_MIXED_MODE; + if ( secrets_fetch_domain_guid( lp_workgroup(), &basic->domain_guid ) ) + basic->flags |= DSROLE_PRIMARY_DOMAIN_GUID_PRESENT; + get_mydomname(dnsdomain); + strlower_m(dnsdomain); + break; + } + + basic->unknown = 0x6173; /* seen on the wire; maybe padding */ + + /* always set netbios name */ + + basic->netbios_ptr = 1; + netbios_domain = get_global_sam_name(); + init_unistr2( &basic->netbios_domain, netbios_domain, strlen(netbios_domain) ); + + basic->dnsname_ptr = 1; + init_unistr2( &basic->dns_domain, dnsdomain, strlen(dnsdomain) ); + basic->forestname_ptr = 1; + init_unistr2( &basic->forest_domain, dnsdomain, strlen(dnsdomain) ); + + + /* fill in some additional fields if we are a member of an AD domain */ + + if ( lp_security() == SEC_ADS ) { + /* TODO */ + ;; + } + + *info = basic; + + return NT_STATUS_OK; +} + +/******************************************************************** + Implement the DsroleGetPrimaryDomainInfo() call + ********************************************************************/ + +NTSTATUS _dsrole_get_primary_dominfo(pipes_struct *p, DS_Q_GETPRIMDOMINFO *q_u, DS_R_GETPRIMDOMINFO *r_u) +{ + NTSTATUS result = NT_STATUS_OK; + uint32 level = q_u->level; + + switch ( level ) { + + case DsRolePrimaryDomainInfoBasic: + r_u->level = DsRolePrimaryDomainInfoBasic; + r_u->ptr = 1; + result = fill_dsrole_dominfo_basic( p->mem_ctx, &r_u->info.basic ); + break; + + default: + DEBUG(0,("_dsrole_get_primary_dominfo: Unsupported info level [%d]!\n", + level)); + result = NT_STATUS_INVALID_LEVEL; + } + + return result; +} + + + diff --git a/source3/rpc_server/srv_lsa_nt.c b/source3/rpc_server/srv_lsa_nt.c index 9eafcb8dc3..330dd727ef 100644 --- a/source3/rpc_server/srv_lsa_nt.c +++ b/source3/rpc_server/srv_lsa_nt.c @@ -502,7 +502,7 @@ NTSTATUS _lsa_enum_trust_dom(pipes_struct *p, LSA_Q_ENUM_TRUST_DOM *q_u, LSA_R_E if (!(info->access & POLICY_VIEW_LOCAL_INFORMATION)) return NT_STATUS_ACCESS_DENIED; - nt_status = secrets_get_trusted_domains(p->mem_ctx, &enum_context, max_num_domains, &num_domains, &trust_doms); + nt_status = secrets_get_trusted_domains(p->mem_ctx, (int *)&enum_context, max_num_domains, (int *)&num_domains, &trust_doms); if (!NT_STATUS_IS_OK(nt_status) && !NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES) && diff --git a/source3/rpc_server/srv_netlog.c b/source3/rpc_server/srv_netlog.c index d1be2f3723..9c10d86379 100644 --- a/source3/rpc_server/srv_netlog.c +++ b/source3/rpc_server/srv_netlog.c @@ -320,10 +320,7 @@ static BOOL api_net_logon_ctrl(pipes_struct *p) /******************************************************************* array of \PIPE\NETLOGON operations ********************************************************************/ - -NTSTATUS rpc_net_init(void) -{ - static struct api_struct api_net_cmds [] = +static struct api_struct api_net_cmds [] = { { "NET_REQCHAL" , NET_REQCHAL , api_net_req_chal }, { "NET_AUTH" , NET_AUTH , api_net_auth }, @@ -336,6 +333,14 @@ NTSTATUS rpc_net_init(void) { "NET_LOGON_CTRL" , NET_LOGON_CTRL , api_net_logon_ctrl } }; +void netlog_get_pipe_fns( struct api_struct **fns, int *n_fns ) +{ + *fns = api_net_cmds; + *n_fns = sizeof(api_net_cmds) / sizeof(struct api_struct); +} + +NTSTATUS rpc_net_init(void) +{ return rpc_pipe_register_commands(SMB_RPC_INTERFACE_VERSION, "NETLOGON", "lsass", api_net_cmds, sizeof(api_net_cmds) / sizeof(struct api_struct)); } diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c index 594cb3a9ae..d1fb587d74 100644 --- a/source3/rpc_server/srv_pipe.c +++ b/source3/rpc_server/srv_pipe.c @@ -713,26 +713,19 @@ BOOL setup_fault_pdu(pipes_struct *p, NTSTATUS status) Used to reject unknown binds from Win2k. *******************************************************************/ -BOOL check_bind_req(char* pipe_name, RPC_IFACE* abstract, - RPC_IFACE* transfer) +BOOL check_bind_req(struct pipes_struct *p, RPC_IFACE* abstract, + RPC_IFACE* transfer, uint32 context_id) { extern struct pipe_id_info pipe_names[]; + char *pipe_name = p->name; int i=0; fstring pname; + fstrcpy(pname,"\\PIPE\\"); fstrcat(pname,pipe_name); DEBUG(3,("check_bind_req for %s\n", pname)); -#ifndef SUPPORT_NEW_LSARPC_UUID - - /* check for the first pipe matching the name */ - - for ( i=0; pipe_names[i].client_pipe; i++ ) { - if ( strequal(pipe_names[i].client_pipe, pname) ) - break; - } -#else /* we have to check all now since win2k introduced a new UUID on the lsaprpc pipe */ for ( i=0; pipe_names[i].client_pipe; i++ ) @@ -743,29 +736,34 @@ BOOL check_bind_req(char* pipe_name, RPC_IFACE* abstract, && (transfer->version == pipe_names[i].trans_syntax.version) && (memcmp(&transfer->uuid, &pipe_names[i].trans_syntax.uuid, sizeof(RPC_UUID)) == 0) ) { + struct api_struct *fns = NULL; + int n_fns = 0; + PIPE_RPC_FNS *context_fns; + + if ( !(context_fns = malloc(sizeof(PIPE_RPC_FNS))) ) { + DEBUG(0,("check_bind_req: malloc() failed!\n")); + return False; + } + + /* save the RPC function table associated with this bind */ + + get_pipe_fns(i, &fns, &n_fns); + + context_fns->cmds = fns; + context_fns->n_cmds = n_fns; + context_fns->context_id = context_id; + + /* add to the list of open contexts */ + + DLIST_ADD( p->contexts, context_fns ); + break; } } -#endif if(pipe_names[i].client_pipe == NULL) return False; -#ifndef SUPPORT_NEW_LSARPC_UUID - /* check the abstract interface */ - if ( (abstract->version != pipe_names[i].abstr_syntax.version) - || (memcmp(&abstract->uuid, &pipe_names[i].abstr_syntax.uuid, sizeof(RPC_UUID)) != 0) ) - { - return False; - } - - /* check the transfer interface */ - if ( (transfer->version != pipe_names[i].trans_syntax.version) - || (memcmp(&transfer->uuid, &pipe_names[i].trans_syntax.uuid, sizeof(RPC_UUID)) != 0) ) - { - return False; - } -#endif return True; } @@ -861,7 +859,7 @@ BOOL api_pipe_bind_req(pipes_struct *p, prs_struct *rpc_in_p) } if (i == rpc_lookup_size) { - if (NT_STATUS_IS_ERR(smb_probe_module("rpc", p->name))) { + if (NT_STATUS_IS_ERR(smb_probe_module("rpc", p->name))) { DEBUG(3,("api_pipe_bind_req: Unknown pipe name %s in bind request.\n", p->name )); if(!setup_bind_nak(p)) @@ -878,10 +876,10 @@ BOOL api_pipe_bind_req(pipes_struct *p, prs_struct *rpc_in_p) } } - if (i == rpc_lookup_size) { - DEBUG(0, ("module %s doesn't provide functions for pipe %s!\n", p->name, p->name)); - return False; - } + if (i == rpc_lookup_size) { + DEBUG(0, ("module %s doesn't provide functions for pipe %s!\n", p->name, p->name)); + return False; + } } /* decode the bind request */ @@ -1028,7 +1026,8 @@ BOOL api_pipe_bind_req(pipes_struct *p, prs_struct *rpc_in_p) unknown to NT4) Needed when adding entries to a DACL from NT5 - SK */ - if(check_bind_req(p->name, &hdr_rb.abstract, &hdr_rb.transfer)) { + if(check_bind_req(p, &hdr_rb.abstract, &hdr_rb.transfer, hdr_rb.context_id )) + { init_rpc_hdr_ba(&hdr_ba, MAX_PDU_FRAG_LEN, MAX_PDU_FRAG_LEN, @@ -1227,10 +1226,10 @@ BOOL api_pipe_auth_process(pipes_struct *p, prs_struct *rpc_in) sizeof(p->ntlmssp_hash)); dump_data_pw("Incoming RPC PDU (NTLMSSP sealed)\n", - data, data_len); + (const unsigned char *)data, data_len); NTLMSSPcalc_p(p, (uchar*)data, data_len); dump_data_pw("Incoming RPC PDU (NTLMSSP unsealed)\n", - data, data_len); + (const unsigned char *)data, data_len); crc32 = crc32_calc_buffer(data, data_len); } @@ -1391,6 +1390,48 @@ struct current_user *get_current_user(struct current_user *user, pipes_struct *p return user; } +/**************************************************************************** + Find the set of RPC functions associated with this context_id +****************************************************************************/ + +static PIPE_RPC_FNS* find_pipe_fns_by_context( PIPE_RPC_FNS *list, uint32 context_id ) +{ + PIPE_RPC_FNS *fns = NULL; + PIPE_RPC_FNS *tmp = NULL; + + if ( !list ) { + DEBUG(0,("find_pipe_fns_by_context: ERROR! No context list for pipe!\n")); + return NULL; + } + + for (tmp=list; tmp; tmp=tmp->next ) { + if ( tmp->context_id == context_id ) + break; + } + + fns = tmp; + + return fns; +} + +/**************************************************************************** + memory cleanup +****************************************************************************/ + +void free_pipe_rpc_context( PIPE_RPC_FNS *list ) +{ + PIPE_RPC_FNS *tmp = list; + PIPE_RPC_FNS *tmp2; + + while (tmp) { + tmp2 = tmp->next; + SAFE_FREE(tmp); + tmp = tmp2; + } + + return; +} + /**************************************************************************** Find the correct RPC function to call for this request. If the pipe is authenticated then become the correct UNIX user @@ -1399,9 +1440,9 @@ struct current_user *get_current_user(struct current_user *user, pipes_struct *p BOOL api_pipe_request(pipes_struct *p) { - int i = 0; BOOL ret = False; - + PIPE_RPC_FNS *pipe_fns; + if (p->ntlmssp_auth_validated) { if(!become_authenticated_pipe_user(p)) { @@ -1411,36 +1452,19 @@ BOOL api_pipe_request(pipes_struct *p) } DEBUG(5, ("Requested \\PIPE\\%s\n", p->name)); - - for (i = 0; i < rpc_lookup_size; i++) { - if (strequal(rpc_lookup[i].pipe.clnt, p->name)) { - DEBUG(3,("Doing \\PIPE\\%s\n", - rpc_lookup[i].pipe.clnt)); - set_current_rpc_talloc(p->mem_ctx); - ret = api_rpcTNP(p, rpc_lookup[i].pipe.clnt, - rpc_lookup[i].cmds, - rpc_lookup[i].n_cmds); - set_current_rpc_talloc(NULL); - break; - } + + /* get the set of RPC functions for this context */ + + pipe_fns = find_pipe_fns_by_context(p->contexts, p->hdr_req.context_id); + + if ( pipe_fns ) { + set_current_rpc_talloc(p->mem_ctx); + ret = api_rpcTNP(p, p->name, pipe_fns->cmds, pipe_fns->n_cmds); + set_current_rpc_talloc(NULL); } - - - if (i == rpc_lookup_size) { - smb_probe_module("rpc", p->name); - - for (i = 0; i < rpc_lookup_size; i++) { - if (strequal(rpc_lookup[i].pipe.clnt, p->name)) { - DEBUG(3,("Doing \\PIPE\\%s\n", - rpc_lookup[i].pipe.clnt)); - set_current_rpc_talloc(p->mem_ctx); - ret = api_rpcTNP(p, rpc_lookup[i].pipe.clnt, - rpc_lookup[i].cmds, - rpc_lookup[i].n_cmds); - set_current_rpc_talloc(NULL); - break; - } - } + else { + DEBUG(0,("api_pipe_request: No rpc function table associated with context [%d] on pipe [%s]\n", + p->hdr_req.context_id, p->name)); } if(p->ntlmssp_auth_validated) @@ -1529,3 +1553,56 @@ BOOL api_rpcTNP(pipes_struct *p, const char *rpc_name, return True; } + +/******************************************************************* +*******************************************************************/ + +void get_pipe_fns( int idx, struct api_struct **fns, int *n_fns ) +{ + struct api_struct *cmds = NULL; + int n_cmds = 0; + + switch ( idx ) { + case PI_LSARPC: + lsa_get_pipe_fns( &cmds, &n_cmds ); + break; + case PI_LSARPC_DS: + lsa_ds_get_pipe_fns( &cmds, &n_cmds ); + break; + case PI_SAMR: + samr_get_pipe_fns( &cmds, &n_cmds ); + break; + case PI_NETLOGON: + netlog_get_pipe_fns( &cmds, &n_cmds ); + break; + case PI_SRVSVC: + srvsvc_get_pipe_fns( &cmds, &n_cmds ); + break; + case PI_WKSSVC: + wkssvc_get_pipe_fns( &cmds, &n_cmds ); + break; + case PI_WINREG: + reg_get_pipe_fns( &cmds, &n_cmds ); + break; + case PI_SPOOLSS: + spoolss_get_pipe_fns( &cmds, &n_cmds ); + break; + case PI_NETDFS: + netdfs_get_pipe_fns( &cmds, &n_cmds ); + break; +#ifdef DEVELOPER + case PI_ECHO: + echo_get_pipe_fns( &cmds, &n_cmds ); + break; +#endif + default: + DEBUG(0,("get_pipe_fns: Unknown pipe index! [%d]\n", idx)); + } + + *fns = cmds; + *n_fns = n_cmds; + + return; +} + + diff --git a/source3/rpc_server/srv_pipe_hnd.c b/source3/rpc_server/srv_pipe_hnd.c index 125f603771..55def97673 100644 --- a/source3/rpc_server/srv_pipe_hnd.c +++ b/source3/rpc_server/srv_pipe_hnd.c @@ -1106,6 +1106,8 @@ static BOOL close_internal_rpc_pipe_hnd(void *np_conn) if (p->mem_ctx) talloc_destroy(p->mem_ctx); + + free_pipe_rpc_context( p->contexts ); /* Free the handles database. */ close_policy_by_pipe(p); diff --git a/source3/rpc_server/srv_reg.c b/source3/rpc_server/srv_reg.c index e1a02103f7..b780be0aff 100644 --- a/source3/rpc_server/srv_reg.c +++ b/source3/rpc_server/srv_reg.c @@ -367,16 +367,12 @@ static BOOL api_reg_save_key(pipes_struct *p) return True; } - - /******************************************************************* array of \PIPE\reg operations ********************************************************************/ -NTSTATUS rpc_reg_init(void) +static struct api_struct api_reg_cmds[] = { - static struct api_struct api_reg_cmds[] = - { { "REG_CLOSE" , REG_CLOSE , api_reg_close }, { "REG_OPEN_ENTRY" , REG_OPEN_ENTRY , api_reg_open_entry }, { "REG_OPEN_HKCR" , REG_OPEN_HKCR , api_reg_open_hkcr }, @@ -390,7 +386,17 @@ NTSTATUS rpc_reg_init(void) { "REG_ABORT_SHUTDOWN" , REG_ABORT_SHUTDOWN , api_reg_abort_shutdown }, { "REG_UNKNOWN_1A" , REG_UNKNOWN_1A , api_reg_unknown_1a }, { "REG_SAVE_KEY" , REG_SAVE_KEY , api_reg_save_key } - }; +}; + +void reg_get_pipe_fns( struct api_struct **fns, int *n_fns ) +{ + *fns = api_reg_cmds; + *n_fns = sizeof(api_reg_cmds) / sizeof(struct api_struct); +} + +NTSTATUS rpc_reg_init(void) +{ + return rpc_pipe_register_commands(SMB_RPC_INTERFACE_VERSION, "winreg", "winreg", api_reg_cmds, sizeof(api_reg_cmds) / sizeof(struct api_struct)); } diff --git a/source3/rpc_server/srv_samr.c b/source3/rpc_server/srv_samr.c index 86ff039683..a0f62c20fc 100644 --- a/source3/rpc_server/srv_samr.c +++ b/source3/rpc_server/srv_samr.c @@ -386,7 +386,7 @@ static BOOL api_samr_chgpasswd_user(pipes_struct *p) ZERO_STRUCT(q_u); ZERO_STRUCT(r_u); - /* unknown 38 command */ + /* change password request */ if (!samr_io_q_chgpasswd_user("", &q_u, data, 0)) { DEBUG(0,("api_samr_chgpasswd_user: Failed to unmarshall SAMR_Q_CHGPASSWD_USER.\n")); return False; @@ -448,13 +448,12 @@ static BOOL api_samr_open_user(pipes_struct *p) ZERO_STRUCT(q_u); ZERO_STRUCT(r_u); - /* grab the samr unknown 22 */ if(!samr_io_q_open_user("", &q_u, data, 0)) { DEBUG(0,("api_samr_open_user: unable to unmarshall SAMR_Q_OPEN_USER.\n")); return False; } - r_u.status = _api_samr_open_user(p, &q_u, &r_u); + r_u.status = _samr_open_user(p, &q_u, &r_u); /* store the response in the SMB stream */ if(!samr_io_r_open_user("", &r_u, rdata, 0)) { @@ -479,7 +478,6 @@ static BOOL api_samr_query_userinfo(pipes_struct *p) ZERO_STRUCT(q_u); ZERO_STRUCT(r_u); - /* grab the samr unknown 24 */ if(!samr_io_q_query_userinfo("", &q_u, data, 0)){ DEBUG(0,("api_samr_query_userinfo: unable to unmarshall SAMR_Q_QUERY_USERINFO.\n")); return False; @@ -510,7 +508,6 @@ static BOOL api_samr_query_usergroups(pipes_struct *p) ZERO_STRUCT(q_u); ZERO_STRUCT(r_u); - /* grab the samr unknown 32 */ if(!samr_io_q_query_usergroups("", &q_u, data, 0)) { DEBUG(0,("api_samr_query_usergroups: unable to unmarshall SAMR_Q_QUERY_USERGROUPS.\n")); return False; @@ -541,7 +538,6 @@ static BOOL api_samr_query_dom_info(pipes_struct *p) ZERO_STRUCT(q_u); ZERO_STRUCT(r_u); - /* grab the samr unknown 8 command */ if(!samr_io_q_query_dom_info("", &q_u, data, 0)) { DEBUG(0,("api_samr_query_dom_info: unable to unmarshall SAMR_Q_QUERY_DOMAIN_INFO.\n")); return False; @@ -579,7 +575,7 @@ static BOOL api_samr_create_user(pipes_struct *p) return False; } - r_u.status=_api_samr_create_user(p, &q_u, &r_u); + r_u.status=_samr_create_user(p, &q_u, &r_u); /* store the response in the SMB stream */ if(!samr_io_r_create_user("", &r_u, rdata, 0)) { @@ -761,7 +757,7 @@ static BOOL api_samr_open_alias(pipes_struct *p) return False; } - r_u.status=_api_samr_open_alias(p, &q_u, &r_u); + r_u.status=_samr_open_alias(p, &q_u, &r_u); /* store the response in the SMB stream */ if(!samr_io_r_open_alias("", &r_u, rdata, 0)) { @@ -1347,13 +1343,13 @@ static BOOL api_samr_open_group(pipes_struct *p) } /******************************************************************* - api_samr_unknown_2d + api_samr_remove_user_foreign_domain ********************************************************************/ -static BOOL api_samr_unknown_2d(pipes_struct *p) +static BOOL api_samr_remove_user_foreign_domain(pipes_struct *p) { - SAMR_Q_UNKNOWN_2D q_u; - SAMR_R_UNKNOWN_2D r_u; + SAMR_Q_REMOVE_USER_FOREIGN_DOMAIN q_u; + SAMR_R_REMOVE_USER_FOREIGN_DOMAIN r_u; prs_struct *data = &p->in_data.data; prs_struct *rdata = &p->out_data.rdata; @@ -1361,15 +1357,15 @@ static BOOL api_samr_unknown_2d(pipes_struct *p) ZERO_STRUCT(q_u); ZERO_STRUCT(r_u); - if (!samr_io_q_unknown_2d("", &q_u, data, 0)) { - DEBUG(0,("api_samr_unknown_2d: unable to unmarshall SAMR_Q_UNKNOWN_2D.\n")); + if (!samr_io_q_remove_user_foreign_domain("", &q_u, data, 0)) { + DEBUG(0,("api_samr_remove_user_foreign_domain: unable to unmarshall SAMR_Q_REMOVE_USER_FOREIGN_DOMAIN.\n")); return False; } - r_u.status = _samr_unknown_2d(p, &q_u, &r_u); + r_u.status = _samr_remove_user_foreign_domain(p, &q_u, &r_u); - if (!samr_io_r_unknown_2d("", &r_u, rdata, 0)) { - DEBUG(0,("api_samr_unknown_2d: unable to marshall SAMR_R_UNKNOWN_2D.\n")); + if (!samr_io_r_remove_user_foreign_domain("", &r_u, rdata, 0)) { + DEBUG(0,("api_samr_remove_user_foreign_domain: unable to marshall SAMR_R_REMOVE_USER_FOREIGN_DOMAIN.\n")); return False; } @@ -1421,7 +1417,6 @@ static BOOL api_samr_set_dom_info(pipes_struct *p) ZERO_STRUCT(q_u); ZERO_STRUCT(r_u); - /* grab the samr unknown 8 command */ if(!samr_io_q_set_domain_info("", &q_u, data, 0)) { DEBUG(0,("api_samr_set_dom_info: unable to unmarshall SAMR_Q_SET_DOMAIN_INFO.\n")); return False; @@ -1442,10 +1437,8 @@ static BOOL api_samr_set_dom_info(pipes_struct *p) array of \PIPE\samr operations ********************************************************************/ -NTSTATUS rpc_samr_init(void) +static struct api_struct api_samr_cmds [] = { - static struct api_struct api_samr_cmds [] = - { {"SAMR_CLOSE_HND" , SAMR_CLOSE_HND , api_samr_close_hnd }, {"SAMR_CONNECT" , SAMR_CONNECT , api_samr_connect }, {"SAMR_CONNECT_ANON" , SAMR_CONNECT_ANON , api_samr_connect_anon }, @@ -1490,7 +1483,7 @@ NTSTATUS rpc_samr_init(void) {"SAMR_OPEN_ALIAS" , SAMR_OPEN_ALIAS , api_samr_open_alias }, {"SAMR_OPEN_GROUP" , SAMR_OPEN_GROUP , api_samr_open_group }, {"SAMR_OPEN_DOMAIN" , SAMR_OPEN_DOMAIN , api_samr_open_domain }, - {"SAMR_UNKNOWN_2D" , SAMR_UNKNOWN_2D , api_samr_unknown_2d }, + {"SAMR_REMOVE_USER_FOREIGN_DOMAIN" , SAMR_REMOVE_USER_FOREIGN_DOMAIN , api_samr_remove_user_foreign_domain }, {"SAMR_LOOKUP_DOMAIN" , SAMR_LOOKUP_DOMAIN , api_samr_lookup_domain }, {"SAMR_QUERY_SEC_OBJECT" , SAMR_QUERY_SEC_OBJECT , api_samr_query_sec_obj }, @@ -1499,7 +1492,17 @@ NTSTATUS rpc_samr_init(void) {"SAMR_UNKNOWN_2E" , SAMR_UNKNOWN_2E , api_samr_unknown_2e }, {"SAMR_SET_DOMAIN_INFO" , SAMR_SET_DOMAIN_INFO , api_samr_set_dom_info }, {"SAMR_CONNECT4" , SAMR_CONNECT4 , api_samr_connect4 } - }; +}; + +void samr_get_pipe_fns( struct api_struct **fns, int *n_fns ) +{ + *fns = api_samr_cmds; + *n_fns = sizeof(api_samr_cmds) / sizeof(struct api_struct); +} + + +NTSTATUS rpc_samr_init(void) +{ return rpc_pipe_register_commands(SMB_RPC_INTERFACE_VERSION, "samr", "lsass", api_samr_cmds, sizeof(api_samr_cmds) / sizeof(struct api_struct)); } diff --git a/source3/rpc_server/srv_samr_nt.c b/source3/rpc_server/srv_samr_nt.c index 14aad5d6f8..7f7b5e8d5e 100644 --- a/source3/rpc_server/srv_samr_nt.c +++ b/source3/rpc_server/srv_samr_nt.c @@ -8,6 +8,7 @@ * Copyright (C) Jeremy Allison 2001-2002, * Copyright (C) Jean François Micouleau 1998-2001, * Copyright (C) Jim McDonough 2002. + * Copyright (C) Gerald (Jerry) Carter 2003. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -913,7 +914,6 @@ static NTSTATUS get_group_alias_entries(TALLOC_CTX *ctx, DOMAIN_GRP **d_grp, DOM } else if (sid_equal(sid, get_global_sam_sid()) && !lp_hide_local_users()) { struct sys_grent *glist; struct sys_grent *grp; - struct passwd *pw; gid_t winbind_gid_low, winbind_gid_high; BOOL winbind_groups_exist = lp_idmap_gid(&winbind_gid_low, &winbind_gid_high); @@ -952,7 +952,7 @@ static NTSTATUS get_group_alias_entries(TALLOC_CTX *ctx, DOMAIN_GRP **d_grp, DOM /* Don't return user private groups... */ - if ((pw = Get_Pwnam(smap.nt_name)) != 0) { + if (Get_Pwnam(smap.nt_name) != 0) { DEBUG(10,("get_group_alias_entries: not returing %s, clashes with user.\n", smap.nt_name )); continue; } @@ -1013,8 +1013,13 @@ static NTSTATUS get_group_domain_entries(TALLOC_CTX *ctx, DOMAIN_GRP **d_grp, DO *p_num_entries = 0; + /* access checks for the users were performed higher up. become/unbecome_root() + needed for some passdb backends to enumerate groups */ + + become_root(); pdb_enum_group_mapping(SID_NAME_DOM_GRP, &map, (int *)&group_entries, ENUM_ONLY_MAPPED); - + unbecome_root(); + num_entries=group_entries-start_idx; /* limit the number of entries */ @@ -1659,10 +1664,10 @@ NTSTATUS _samr_lookup_rids(pipes_struct *p, SAMR_Q_LOOKUP_RIDS *q_u, SAMR_R_LOOK } /******************************************************************* - _api_samr_open_user. Safe - gives out no passwd info. + _samr_open_user. Safe - gives out no passwd info. ********************************************************************/ -NTSTATUS _api_samr_open_user(pipes_struct *p, SAMR_Q_OPEN_USER *q_u, SAMR_R_OPEN_USER *r_u) +NTSTATUS _samr_open_user(pipes_struct *p, SAMR_Q_OPEN_USER *q_u, SAMR_R_OPEN_USER *r_u) { SAM_ACCOUNT *sampass=NULL; DOM_SID sid; @@ -2140,7 +2145,7 @@ NTSTATUS _samr_query_dom_info(pipes_struct *p, SAMR_Q_QUERY_DOMAIN_INFO *q_u, SA num_users, num_groups, num_aliases); break; case 0x03: - account_policy_get(AP_TIME_TO_LOGOUT, (int *)&u_logout); + account_policy_get(AP_TIME_TO_LOGOUT, (unsigned int *)&u_logout); unix_to_nt_time_abs(&nt_logout, u_logout); init_unk_info3(&ctr->info.inf3, nt_logout); @@ -2181,12 +2186,12 @@ NTSTATUS _samr_query_dom_info(pipes_struct *p, SAMR_Q_QUERY_DOMAIN_INFO *q_u, SA } /******************************************************************* - _api_samr_create_user + _samr_create_user Create an account, can be either a normal user or a machine. This funcion will need to be updated for bdc/domain trusts. ********************************************************************/ -NTSTATUS _api_samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_CREATE_USER *r_u) +NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_CREATE_USER *r_u) { SAM_ACCOUNT *sam_pass=NULL; fstring account; @@ -2300,12 +2305,12 @@ NTSTATUS _api_samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_ int add_ret; all_string_sub(add_script, "%u", account, sizeof(account)); add_ret = smbrun(add_script,NULL); - DEBUG(3,("_api_samr_create_user: Running the command `%s' gave %d\n", add_script, add_ret)); + DEBUG(3,("_samr_create_user: Running the command `%s' gave %d\n", add_script, add_ret)); } else /* no add user script -- ask winbindd to do it */ { if ( !winbind_create_user( account, &new_rid ) ) { - DEBUG(3,("_api_samr_create_user: winbind_create_user(%s) failed\n", + DEBUG(3,("_samr_create_user: winbind_create_user(%s) failed\n", account)); } } @@ -2369,6 +2374,7 @@ NTSTATUS _api_samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_ NTSTATUS _samr_connect_anon(pipes_struct *p, SAMR_Q_CONNECT_ANON *q_u, SAMR_R_CONNECT_ANON *r_u) { struct samr_info *info = NULL; + uint32 des_access = q_u->access_mask; /* Access check */ @@ -2386,6 +2392,13 @@ NTSTATUS _samr_connect_anon(pipes_struct *p, SAMR_Q_CONNECT_ANON *q_u, SAMR_R_CO if ((info = get_samr_info_by_sid(NULL)) == NULL) return NT_STATUS_NO_MEMORY; + /* don't give away the farm but this is probably ok. The SA_RIGHT_SAM_ENUM_DOMAINS + was observed from a win98 client trying to enumerate users (when configured + user level access control on shares) --jerry */ + + se_map_generic( &des_access, &sam_generic_mapping ); + info->acc_granted = des_access & (SA_RIGHT_SAM_ENUM_DOMAINS|SA_RIGHT_SAM_OPEN_DOMAIN); + info->status = q_u->unknown_0; /* get a (unique) handle. open a policy on it. */ @@ -2510,7 +2523,9 @@ NTSTATUS _samr_lookup_domain(pipes_struct *p, SAMR_Q_LOOKUP_DOMAIN *q_u, SAMR_R_ if (!find_policy_by_hnd(p, &q_u->connect_pol, (void**)&info)) return NT_STATUS_INVALID_HANDLE; - if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(info->acc_granted, SA_RIGHT_SAM_OPEN_DOMAIN, "_samr_lookup_domain"))) { + if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(info->acc_granted, + SA_RIGHT_SAM_ENUM_DOMAINS, "_samr_lookup_domain"))) + { return r_u->status; } @@ -2605,7 +2620,7 @@ NTSTATUS _samr_enum_domains(pipes_struct *p, SAMR_Q_ENUM_DOMAINS *q_u, SAMR_R_EN api_samr_open_alias ********************************************************************/ -NTSTATUS _api_samr_open_alias(pipes_struct *p, SAMR_Q_OPEN_ALIAS *q_u, SAMR_R_OPEN_ALIAS *r_u) +NTSTATUS _samr_open_alias(pipes_struct *p, SAMR_Q_OPEN_ALIAS *q_u, SAMR_R_OPEN_ALIAS *r_u) { DOM_SID sid; POLICY_HND domain_pol = q_u->dom_pol; @@ -3773,7 +3788,8 @@ NTSTATUS _samr_delete_dom_user(pipes_struct *p, SAMR_Q_DELETE_DOM_USER *q_u, SAM /* check if the user exists before trying to delete */ pdb_init_sam(&sam_pass); if(!pdb_getsampwsid(sam_pass, &user_sid)) { - DEBUG(5,("_samr_delete_dom_user:User %s doesn't exist.\n", pdb_get_username(sam_pass))); + DEBUG(5,("_samr_delete_dom_user:User %s doesn't exist.\n", + sid_string_static(&user_sid))); pdb_free_sam(&sam_pass); return NT_STATUS_NO_SUCH_USER; } @@ -4269,13 +4285,75 @@ NTSTATUS _samr_open_group(pipes_struct *p, SAMR_Q_OPEN_GROUP *q_u, SAMR_R_OPEN_G } /********************************************************************* - _samr_unknown_2d + _samr_remove_user_foreign_domain *********************************************************************/ -NTSTATUS _samr_unknown_2d(pipes_struct *p, SAMR_Q_UNKNOWN_2D *q_u, SAMR_R_UNKNOWN_2D *r_u) +NTSTATUS _samr_remove_user_foreign_domain(pipes_struct *p, + SAMR_Q_REMOVE_USER_FOREIGN_DOMAIN *q_u, + SAMR_R_REMOVE_USER_FOREIGN_DOMAIN *r_u) { - DEBUG(0,("_samr_unknown_2d: Not yet implemented.\n")); - return NT_STATUS_NOT_IMPLEMENTED; + DOM_SID user_sid, dom_sid; + SAM_ACCOUNT *sam_pass=NULL; + uint32 acc_granted; + + sid_copy( &user_sid, &q_u->sid.sid ); + + DEBUG(5,("_samr_remove_user_foreign_domain: removing user [%s]\n", + sid_string_static(&user_sid))); + + /* Find the policy handle. Open a policy on it. */ + + if (!get_lsa_policy_samr_sid(p, &q_u->dom_pol, &dom_sid, &acc_granted)) + return NT_STATUS_INVALID_HANDLE; + + if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, + STD_RIGHT_DELETE_ACCESS, "_samr_remove_user_foreign_domain"))) + { + return r_u->status; + } + + if ( !sid_check_is_in_our_domain(&user_sid) ) { + DEBUG(5,("_samr_remove_user_foreign_domain: user not is our domain!\n")); + return NT_STATUS_NO_SUCH_USER; + } + + /* check if the user exists before trying to delete */ + + pdb_init_sam(&sam_pass); + + if ( !pdb_getsampwsid(sam_pass, &user_sid) ) { + + DEBUG(5,("_samr_remove_user_foreign_domain:User %s doesn't exist.\n", + sid_string_static(&user_sid))); + + pdb_free_sam(&sam_pass); + + return NT_STATUS_NO_SUCH_USER; + } + + /* + * delete the unix side + * + * note: we don't check if the delete really happened + * as the script is not necessary present + * and maybe the sysadmin doesn't want to delete the unix side + */ + + smb_delete_user(pdb_get_username(sam_pass)); + + /* and delete the samba side */ + + if ( !pdb_delete_sam_account(sam_pass) ) { + + DEBUG(5,("_samr_delete_dom_user:Failed to delete entry for user %s.\n", pdb_get_username(sam_pass))); + pdb_free_sam(&sam_pass); + + return NT_STATUS_CANNOT_DELETE; + } + + pdb_free_sam(&sam_pass); + + return NT_STATUS_OK; } /******************************************************************* diff --git a/source3/rpc_server/srv_spoolss.c b/source3/rpc_server/srv_spoolss.c index fa0ca8478c..f846813a40 100755 --- a/source3/rpc_server/srv_spoolss.c +++ b/source3/rpc_server/srv_spoolss.c @@ -141,7 +141,7 @@ static BOOL api_spoolss_deleteprinterdata(pipes_struct *p) return False; } - r_u.status = _spoolss_deleteprinterdata( p, &q_u, &r_u); + r_u.status = _spoolss_deleteprinterdata( p, &q_u, &r_u ); if (!spoolss_io_r_deleteprinterdata("", &r_u, rdata, 0)) { DEBUG(0,("spoolss_io_r_deleteprinterdata: unable to marshall SPOOL_R_DELETEPRINTERDATA.\n")); @@ -1580,8 +1580,6 @@ static BOOL api_spoolss_replycloseprinter(pipes_struct *p) \pipe\spoolss commands ********************************************************************/ -NTSTATUS rpc_spoolss_init(void) -{ struct api_struct api_spoolss_cmds[] = { {"SPOOLSS_OPENPRINTER", SPOOLSS_OPENPRINTER, api_spoolss_open_printer }, @@ -1640,6 +1638,15 @@ NTSTATUS rpc_spoolss_init(void) {"SPOOLSS_REPLYCLOSEPRINTER", SPOOLSS_REPLYCLOSEPRINTER, api_spoolss_replycloseprinter } #endif }; + +void spoolss_get_pipe_fns( struct api_struct **fns, int *n_fns ) +{ + *fns = api_spoolss_cmds; + *n_fns = sizeof(api_spoolss_cmds) / sizeof(struct api_struct); +} + +NTSTATUS rpc_spoolss_init(void) +{ return rpc_pipe_register_commands(SMB_RPC_INTERFACE_VERSION, "spoolss", "spoolss", api_spoolss_cmds, sizeof(api_spoolss_cmds) / sizeof(struct api_struct)); } diff --git a/source3/rpc_server/srv_spoolss_nt.c b/source3/rpc_server/srv_spoolss_nt.c index 8237298ebb..7159527a7d 100644 --- a/source3/rpc_server/srv_spoolss_nt.c +++ b/source3/rpc_server/srv_spoolss_nt.c @@ -387,7 +387,6 @@ static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd) char *cmd = lp_deleteprinter_cmd(); pstring command; int ret; - int i; /* Printer->dev.handlename equals portname equals sharename */ slprintf(command, sizeof(command)-1, "%s \"%s\"", cmd, @@ -406,7 +405,7 @@ static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd) /* go ahead and re-read the services immediately */ reload_services( False ); - if ( ( i = lp_servicenumber( Printer->dev.handlename ) ) < 0 ) + if ( lp_servicenumber( Printer->dev.handlename ) < 0 ) return WERR_ACCESS_DENIED; } @@ -957,7 +956,7 @@ static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx ) SPOOL_NOTIFY_INFO_DATA *data; uint32 data_len = 0; uint32 id; - int i, event_index; + int i; /* Is there notification on this handle? */ @@ -980,8 +979,6 @@ static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx ) data = talloc( mem_ctx, msg_group->num_msgs*sizeof(SPOOL_NOTIFY_INFO_DATA) ); ZERO_STRUCTP(data); - event_index = 0; - /* build the array of change notifications */ sending_msg_count = 0; @@ -2671,6 +2668,8 @@ static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer, fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */ + ZERO_STRUCT(notify_cli); + if(!spoolss_connect_to_client(¬ify_cli, client_ip, unix_printer)) return False; @@ -3753,7 +3752,6 @@ static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd, Printer_entry *Printer=find_printer_index_by_hnd(p, hnd); int n_services=lp_numservices(); int i; - uint32 id; SPOOL_NOTIFY_OPTION *option; SPOOL_NOTIFY_OPTION_TYPE *option_type; @@ -3763,7 +3761,6 @@ static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd, return WERR_BADFID; option=Printer->notify.option; - id=1; info->version=2; info->data=NULL; info->count=0; @@ -6192,12 +6189,9 @@ static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle, SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7; int snum; Printer_entry *Printer = find_printer_index_by_hnd(p, handle); - WERROR result; DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action)); - result = WERR_OK; - if (!Printer) return WERR_BADFID; @@ -7100,7 +7094,6 @@ static void fill_port_2(PORT_INFO_2 *port, const char *name) init_unistr(&port->port_name, name); init_unistr(&port->monitor_name, "Local Monitor"); init_unistr(&port->description, "Local Port"); -#define PORT_TYPE_WRITE 1 port->port_type=PORT_TYPE_WRITE; port->reserved=0x0; } @@ -7723,7 +7716,6 @@ WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, S NT_PRINTER_INFO_LEVEL *printer = NULL; - uint32 param_index; uint32 biggest_valuesize; uint32 biggest_datasize; uint32 data_len; @@ -7772,7 +7764,6 @@ WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, S { DEBUGADD(6,("Activating NT mega-hack to find sizes\n")); - param_index = 0; biggest_valuesize = 0; biggest_datasize = 0; @@ -8032,6 +8023,9 @@ WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_ unistr2_to_ascii( valuename, value, sizeof(valuename)-1 ); status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename ); + + if ( W_ERROR_IS_OK(status) ) + mod_a_printer( *printer, 2 ); free_a_printer(&printer, 2); @@ -8895,6 +8889,9 @@ WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX status = delete_printer_dataex( printer, keyname, valuename ); + if ( W_ERROR_IS_OK(status) ) + mod_a_printer( *printer, 2 ); + free_a_printer(&printer, 2); return status; @@ -9186,12 +9183,11 @@ static WERROR getprintprocessordirectory_level_1(UNISTR2 *name, { pstring path; pstring long_archi; - const char *short_archi; PRINTPROCESSOR_DIRECTORY_1 *info=NULL; unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1); - if (!(short_archi = get_short_archi(long_archi))) + if (!get_short_archi(long_archi)) return WERR_INVALID_ENVIRONMENT; if((info=(PRINTPROCESSOR_DIRECTORY_1 *)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1))) == NULL) diff --git a/source3/rpc_server/srv_srvsvc.c b/source3/rpc_server/srv_srvsvc.c index 0da3cf70dd..9d85088e56 100644 --- a/source3/rpc_server/srv_srvsvc.c +++ b/source3/rpc_server/srv_srvsvc.c @@ -526,10 +526,8 @@ static BOOL api_srv_net_file_set_secdesc(pipes_struct *p) \PIPE\srvsvc commands ********************************************************************/ -NTSTATUS rpc_srv_init(void) +static struct api_struct api_srv_cmds[] = { - static const struct api_struct api_srv_cmds[] = - { { "SRV_NET_CONN_ENUM" , SRV_NET_CONN_ENUM , api_srv_net_conn_enum }, { "SRV_NET_SESS_ENUM" , SRV_NET_SESS_ENUM , api_srv_net_sess_enum }, { "SRV_NET_SHARE_ENUM_ALL" , SRV_NET_SHARE_ENUM_ALL , api_srv_net_share_enum_all }, @@ -547,7 +545,17 @@ NTSTATUS rpc_srv_init(void) { "SRV_NET_NAME_VALIDATE" , SRV_NET_NAME_VALIDATE , api_srv_net_name_validate }, { "SRV_NET_FILE_QUERY_SECDESC", SRV_NET_FILE_QUERY_SECDESC, api_srv_net_file_query_secdesc }, { "SRV_NET_FILE_SET_SECDESC" , SRV_NET_FILE_SET_SECDESC , api_srv_net_file_set_secdesc } - }; +}; + +void srvsvc_get_pipe_fns( struct api_struct **fns, int *n_fns ) +{ + *fns = api_srv_cmds; + *n_fns = sizeof(api_srv_cmds) / sizeof(struct api_struct); +} + + +NTSTATUS rpc_srv_init(void) +{ return rpc_pipe_register_commands(SMB_RPC_INTERFACE_VERSION, "srvsvc", "ntsvcs", api_srv_cmds, sizeof(api_srv_cmds) / sizeof(struct api_struct)); } diff --git a/source3/rpc_server/srv_util.c b/source3/rpc_server/srv_util.c index 03e53118a8..632d381503 100644 --- a/source3/rpc_server/srv_util.c +++ b/source3/rpc_server/srv_util.c @@ -307,8 +307,17 @@ BOOL get_domain_user_groups(TALLOC_CTX *ctx, int *numgroups, DOM_GID **pgids, SA */ gids = (DOM_GID *)talloc(ctx, sizeof(DOM_GID) * num_entries); - /* for each group, check if the user is a member of*/ + /* for each group, check if the user is a member of. Only include groups + from this domain */ + for(i=0; idesthost, flags, &trusts, &num_domains ); diff --git a/source3/rpcclient/cmd_netlogon.c b/source3/rpcclient/cmd_netlogon.c index 0ec78a0673..a48b59bf6a 100644 --- a/source3/rpcclient/cmd_netlogon.c +++ b/source3/rpcclient/cmd_netlogon.c @@ -146,13 +146,10 @@ static NTSTATUS cmd_netlogon_sam_sync(struct cli_state *cli, const char **argv) { NTSTATUS result = NT_STATUS_UNSUCCESSFUL; - unsigned char trust_passwd[16]; uint32 database_id = 0, num_deltas; SAM_DELTA_HDR *hdr_deltas; SAM_DELTA_CTR *deltas; DOM_CRED ret_creds; - uint32 neg_flags = 0x000001ff; - uint32 sec_channel_type = 0; if (argc > 2) { fprintf(stderr, "Usage: %s [database_id]\n", argv[0]); @@ -162,26 +159,6 @@ static NTSTATUS cmd_netlogon_sam_sync(struct cli_state *cli, if (argc == 2) database_id = atoi(argv[1]); - if (!secrets_init()) { - fprintf(stderr, "Unable to initialise secrets database\n"); - return result; - } - - /* Initialise session credentials */ - - if (!secrets_fetch_trust_account_password(lp_workgroup(), trust_passwd, - NULL, &sec_channel_type)) { - fprintf(stderr, "could not fetch trust account password\n"); - goto done; - } - - result = cli_nt_setup_creds(cli, sec_channel_type, trust_passwd, &neg_flags, 2); - - if (!NT_STATUS_IS_OK(result)) { - fprintf(stderr, "Error initialising session creds\n"); - goto done; - } - /* on first call the returnAuthenticator is empty */ memset(&ret_creds, 0, sizeof(ret_creds)); @@ -208,13 +185,10 @@ static NTSTATUS cmd_netlogon_sam_deltas(struct cli_state *cli, const char **argv) { NTSTATUS result = NT_STATUS_UNSUCCESSFUL; - unsigned char trust_passwd[16]; uint32 database_id, num_deltas, tmp; SAM_DELTA_HDR *hdr_deltas; SAM_DELTA_CTR *deltas; UINT64_S seqnum; - uint32 neg_flags = 0x000001ff; - uint32 sec_channel_type = 0; if (argc != 3) { fprintf(stderr, "Usage: %s database_id seqnum\n", argv[0]); @@ -227,28 +201,6 @@ static NTSTATUS cmd_netlogon_sam_deltas(struct cli_state *cli, seqnum.low = tmp & 0xffff; seqnum.high = 0; - if (!secrets_init()) { - fprintf(stderr, "Unable to initialise secrets database\n"); - goto done; - } - - /* Initialise session credentials */ - - if (!secrets_fetch_trust_account_password(lp_workgroup(), trust_passwd, - NULL, &sec_channel_type)) { - fprintf(stderr, "could not fetch trust account password\n"); - goto done; - } - - result = cli_nt_setup_creds(cli, sec_channel_type, trust_passwd, &neg_flags, 2); - - if (!NT_STATUS_IS_OK(result)) { - fprintf(stderr, "Error initialising session creds\n"); - goto done; - } - - /* Synchronise sam database */ - result = cli_netlogon_sam_deltas(cli, mem_ctx, database_id, seqnum, &num_deltas, &hdr_deltas, &deltas); @@ -308,6 +260,8 @@ static NTSTATUS cmd_netlogon_sam_logon(struct cli_state *cli, result = cli_netlogon_sam_logon(cli, mem_ctx, &ret_creds, username, password, logon_type); + clnt_deal_with_creds(cli->sess_key, &(cli->clnt_cred), &ret_creds); + if (!NT_STATUS_IS_OK(result)) goto done; @@ -315,6 +269,39 @@ static NTSTATUS cmd_netlogon_sam_logon(struct cli_state *cli, return result; } +/* Change the trust account password */ + +static NTSTATUS cmd_netlogon_change_trust_pw(struct cli_state *cli, + TALLOC_CTX *mem_ctx, int argc, + const char **argv) +{ + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + DOM_CRED ret_creds; + + /* Check arguments */ + + if (argc > 1) { + fprintf(stderr, "Usage: change_trust_pw"); + return NT_STATUS_OK; + } + + /* Perform the sam logon */ + + ZERO_STRUCT(ret_creds); + + result = trust_pw_find_change_and_store_it(cli, mem_ctx, + lp_workgroup()); + + clnt_deal_with_creds(cli->sess_key, &(cli->clnt_cred), &ret_creds); + + if (!NT_STATUS_IS_OK(result)) + goto done; + + done: + return result; +} + + /* List of commands exported by this module */ struct cmd_set netlogon_commands[] = { @@ -325,7 +312,8 @@ struct cmd_set netlogon_commands[] = { { "logonctrl", RPC_RTYPE_NTSTATUS, cmd_netlogon_logon_ctrl, NULL, PI_NETLOGON, "Logon Control", "" }, { "samsync", RPC_RTYPE_NTSTATUS, cmd_netlogon_sam_sync, NULL, PI_NETLOGON, "Sam Synchronisation", "" }, { "samdeltas", RPC_RTYPE_NTSTATUS, cmd_netlogon_sam_deltas, NULL, PI_NETLOGON, "Query Sam Deltas", "" }, - { "samlogon", RPC_RTYPE_NTSTATUS, cmd_netlogon_sam_logon, NULL, PI_NETLOGON, "Sam Logon", "" }, + { "samlogon", RPC_RTYPE_NTSTATUS, cmd_netlogon_sam_logon, NULL, PI_NETLOGON, "Sam Logon", "" }, + { "samlogon", RPC_RTYPE_NTSTATUS, cmd_netlogon_change_trust_pw, NULL, PI_NETLOGON, "Change Trust Account Password", "" }, { NULL } }; diff --git a/source3/rpcclient/cmd_spoolss.c b/source3/rpcclient/cmd_spoolss.c index b2fa802e9a..61e100c03b 100644 --- a/source3/rpcclient/cmd_spoolss.c +++ b/source3/rpcclient/cmd_spoolss.c @@ -35,6 +35,7 @@ static const struct table_node archi_table[]= { {"Windows 4.0", "WIN40", 0 }, {"Windows NT x86", "W32X86", 2 }, + {"Windows NT x86", "W32X86", 3 }, {"Windows NT R4000", "W32MIPS", 2 }, {"Windows NT Alpha_AXP", "W32ALPHA", 2 }, {"Windows NT PowerPC", "W32PPC", 2 }, @@ -395,7 +396,31 @@ static void display_port_info_2(PORT_INFO_2 *i2) rpcstr_pull(buffer, i2->description.buffer, sizeof(buffer), -1, STR_TERMINATE); printf("\tDescription:\t[%s]\n", buffer); - printf("\tPort Type:\t[%d]\n", i2->port_type); + printf("\tPort Type:\t" ); + if ( i2->port_type ) { + int comma = 0; /* hack */ + printf( "[" ); + if ( i2->port_type & PORT_TYPE_READ ) { + printf( "Read" ); + comma = 1; + } + if ( i2->port_type & PORT_TYPE_WRITE ) { + printf( "%sWrite", comma ? ", " : "" ); + comma = 1; + } + /* These two have slightly different interpretations + on 95/98/ME but I'm disregarding that for now */ + if ( i2->port_type & PORT_TYPE_REDIRECTED ) { + printf( "%sRedirected", comma ? ", " : "" ); + comma = 1; + } + if ( i2->port_type & PORT_TYPE_NET_ATTACHED ) { + printf( "%sNet-Attached", comma ? ", " : "" ); + } + printf( "]\n" ); + } else { + printf( "[Unset]\n" ); + } printf("\tReserved:\t[%d]\n", i2->reserved); printf("\n"); } @@ -912,6 +937,7 @@ static WERROR cmd_spoolss_getdriver(struct cli_state *cli, servername, user; uint32 i; + BOOL success = False; if ((argc == 1) || (argc > 3)) { @@ -947,15 +973,22 @@ static WERROR cmd_spoolss_getdriver(struct cli_state *cli, werror = cli_spoolss_getprinterdriver( cli, mem_ctx, 0, &needed, &pol, info_level, - archi_table[i].long_archi, &ctr); + archi_table[i].long_archi, archi_table[i].version, + &ctr); - if (W_ERROR_V(werror) == ERRinsufficientbuffer) + if (W_ERROR_V(werror) == ERRinsufficientbuffer) { werror = cli_spoolss_getprinterdriver( cli, mem_ctx, needed, NULL, &pol, info_level, - archi_table[i].long_archi, &ctr); + archi_table[i].long_archi, archi_table[i].version, + &ctr); + } if (!W_ERROR_IS_OK(werror)) continue; + + /* need at least one success */ + + success = True; printf ("\n[%s]\n", archi_table[i].long_archi); @@ -980,6 +1013,9 @@ static WERROR cmd_spoolss_getdriver(struct cli_state *cli, if (opened_hnd) cli_spoolss_close_printer (cli, mem_ctx, &pol); + if ( success ) + werror = WERR_OK; + return werror; } diff --git a/source3/rpcclient/rpcclient.c b/source3/rpcclient/rpcclient.c index 831d2beaa4..515489292b 100644 --- a/source3/rpcclient/rpcclient.c +++ b/source3/rpcclient/rpcclient.c @@ -40,7 +40,7 @@ static struct cmd_list { /**************************************************************************** handle completion of commands for readline ****************************************************************************/ -static char **completion_fn(char *text, int start, int end) +static char **completion_fn(const char *text, int start, int end) { #define MAX_COMPLETIONS 100 char **matches; @@ -361,7 +361,7 @@ static NTSTATUS cmd_schannel(struct cli_state *cli, TALLOC_CTX *mem_ctx, static uchar zeros[16]; if (argc == 2) { - strhex_to_str(cli->auth_info.sess_key, + strhex_to_str((char *)cli->auth_info.sess_key, strlen(argv[1]), argv[1]); memcpy(cli->sess_key, cli->auth_info.sess_key, sizeof(cli->sess_key)); @@ -522,6 +522,8 @@ static NTSTATUS do_cmd(struct cli_state *cli, /* some of the DsXXX commands use the netlogon pipe */ if (lp_client_schannel() && (cmd_entry->pipe_idx == PI_NETLOGON) && !(cli->pipe_auth_flags & AUTH_PIPE_NETSEC)) { + /* The 7 here seems to be required to get Win2k not to downgrade us + to NT4. Actually, anything other than 1ff would seem to do... */ uint32 neg_flags = 0x000001ff; uint32 sec_channel_type; @@ -725,8 +727,10 @@ out_free: nt_status = cli_full_connection(&cli, global_myname(), server, opt_ipaddr ? &server_ip : NULL, 0, "IPC$", "IPC", - cmdline_auth_info.username, lp_workgroup(), - cmdline_auth_info.password, 0, + cmdline_auth_info.username, + lp_workgroup(), + cmdline_auth_info.password, + cmdline_auth_info.use_kerberos ? CLI_FULL_CONNECTION_USE_KERBEROS : 0, cmdline_auth_info.signing_state,NULL); if (!NT_STATUS_IS_OK(nt_status)) { diff --git a/source3/sam/idmap_ldap.c b/source3/sam/idmap_ldap.c index 9a1ee039d0..6122641718 100644 --- a/source3/sam/idmap_ldap.c +++ b/source3/sam/idmap_ldap.c @@ -4,7 +4,7 @@ idmap LDAP backend Copyright (C) Tim Potter 2000 - Copyright (C) Anthony Liguori 2003 + Copyright (C) Jim McDonough 2003 Copyright (C) Simo Sorce 2003 Copyright (C) Gerald Carter 2003 @@ -41,12 +41,6 @@ struct ldap_idmap_state { struct smbldap_state *smbldap_state; TALLOC_CTX *mem_ctx; - - uint32 low_allocated_user_rid; - uint32 high_allocated_user_rid; - uint32 low_allocated_group_rid; - uint32 high_allocated_group_rid; - }; #define LDAP_MAX_ALLOC_ID 128 /* number tries while allocating @@ -203,11 +197,7 @@ static NTSTATUS ldap_next_rid(struct ldap_idmap_state *state, uint32 *rid, get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_USERRID), old_rid_string)) { - - *rid = (uint32)atol(old_rid_string); - - } else { - *rid = state->low_allocated_user_rid; + *rid = (uint32)atol(old_rid_string); } break; case GROUP_RID_TYPE: @@ -216,8 +206,6 @@ static NTSTATUS ldap_next_rid(struct ldap_idmap_state *state, uint32 *rid, old_rid_string)) { *rid = (uint32)atol(old_rid_string); - } else { - *rid = state->low_allocated_group_rid; } break; } @@ -231,10 +219,6 @@ static NTSTATUS ldap_next_rid(struct ldap_idmap_state *state, uint32 *rid, switch (rid_type) { case USER_RID_TYPE: - if (next_rid > state->high_allocated_user_rid) { - return NT_STATUS_UNSUCCESSFUL; - } - /* Try to make the modification atomically by enforcing the old value in the delete mod. */ smbldap_make_mod(state->smbldap_state->ldap_struct, entry, &mods, @@ -243,10 +227,6 @@ static NTSTATUS ldap_next_rid(struct ldap_idmap_state *state, uint32 *rid, break; case GROUP_RID_TYPE: - if (next_rid > state->high_allocated_group_rid) { - return NT_STATUS_UNSUCCESSFUL; - } - /* Try to make the modification atomically by enforcing the old value in the delete mod. */ smbldap_make_mod(state->smbldap_state->ldap_struct, entry, &mods, @@ -361,7 +341,7 @@ static NTSTATUS ldap_allocate_id(unid_t *id, int id_type) get_attr_key2string( idpool_attr_list, LDAP_ATTR_UIDNUMBER ) : get_attr_key2string( idpool_attr_list, LDAP_ATTR_GIDNUMBER ); - snprintf(filter, sizeof(filter)-1, "(objectClass=%s)", LDAP_OBJ_IDPOOL); + pstr_sprintf(filter, "(objectClass=%s)", LDAP_OBJ_IDPOOL); attr_list = get_attr_list( idpool_attr_list ); @@ -400,20 +380,23 @@ static NTSTATUS ldap_allocate_id(unid_t *id, int id_type) if (id_type & ID_USERID) { id->uid = strtoul(id_str, NULL, 10); if (id->uid > huid ) { - DEBUG(0,("ldap_allocate_id: Cannot allocate uid above %d!\n", huid)); + DEBUG(0,("ldap_allocate_id: Cannot allocate uid above %lu!\n", + (unsigned long)huid)); goto out; } } else { id->gid = strtoul(id_str, NULL, 10); if (id->gid > hgid ) { - DEBUG(0,("ldap_allocate_id: Cannot allocate gid above %d!\n", hgid)); + DEBUG(0,("ldap_allocate_id: Cannot allocate gid above %lu!\n", + (unsigned long)hgid)); goto out; } } - snprintf(new_id_str, sizeof(new_id_str), "%u", - ((id_type & ID_USERID) ? id->uid : id->gid) + 1); + pstr_sprintf(new_id_str, "%lu", + ((id_type & ID_USERID) ? (unsigned long)id->uid : + (unsigned long)id->gid) + 1); smbldap_set_mod( &mods, LDAP_MOD_DELETE, type, id_str ); smbldap_set_mod( &mods, LDAP_MOD_ADD, type, new_id_str ); @@ -458,27 +441,38 @@ static NTSTATUS ldap_get_sid_from_id(DOM_SID *sid, unid_t id, int id_type) if ( id_type & ID_USERID ) { type = get_attr_key2string( idpool_attr_list, LDAP_ATTR_UIDNUMBER ); obj_class = LDAP_OBJ_SAMBASAMACCOUNT; - snprintf(id_str, sizeof(id_str), "%u", id.uid ); + fstr_sprintf(id_str, "%lu", (unsigned long)id.uid ); pstrcpy( suffix, lp_ldap_suffix()); } else { type = get_attr_key2string( idpool_attr_list, LDAP_ATTR_GIDNUMBER ); obj_class = LDAP_OBJ_GROUPMAP; - snprintf(id_str, sizeof(id_str), "%u", id.gid ); + fstr_sprintf(id_str, "%lu", (unsigned long)id.gid ); pstrcpy( suffix, lp_ldap_group_suffix() ); } + + DEBUG(5,("ldap_get_sid_from_id: Searching \"%s\"\n", filter )); attr_list = get_attr_list( sidmap_attr_list ); - snprintf(filter, sizeof(filter), "(&(|(objectClass=%s)(objectClass=%s))(%s=%s))", + pstr_sprintf(filter, "(&(|(objectClass=%s)(objectClass=%s))(%s=%s))", LDAP_OBJ_IDMAP_ENTRY, obj_class, type, id_str); rc = smbldap_search(ldap_state.smbldap_state, suffix, LDAP_SCOPE_SUBTREE, filter, attr_list, 0, &result); - if (rc != LDAP_SUCCESS) + if (rc != LDAP_SUCCESS) { + DEBUG(3,("ldap_get_isd_from_id: Failure looking up entry (%s)\n", + ldap_err2string(rc) )); goto out; - + } + count = ldap_count_entries(ldap_state.smbldap_state->ldap_struct, result); + + if (count > 1) { + DEBUG(0,("ldap_get_sid_from_id: mapping returned [%d] entries!\n", + count)); + goto out; + } /* fall back to looking up an idmap entry if we didn't find and actual user or group */ @@ -487,24 +481,30 @@ static NTSTATUS ldap_get_sid_from_id(DOM_SID *sid, unid_t id, int id_type) ldap_msgfree(result); result = NULL; - snprintf(filter, sizeof(filter), "(&(objectClass=%s)(%s=%u))", - LDAP_OBJ_IDMAP_ENTRY, type, ((id_type & ID_USERID) ? id.uid : id.gid)); + pstr_sprintf(filter, "(&(objectClass=%s)(%s=%lu))", + LDAP_OBJ_IDMAP_ENTRY, type, + ((id_type & ID_USERID) ? (unsigned long)id.uid : + (unsigned long)id.gid)); pstrcpy( suffix, lp_ldap_idmap_suffix() ); rc = smbldap_search(ldap_state.smbldap_state, suffix, LDAP_SCOPE_SUBTREE, filter, attr_list, 0, &result); - if (rc != LDAP_SUCCESS) - goto out; + if (rc != LDAP_SUCCESS) { + DEBUG(3,("ldap_get_isd_from_id: Failure looking up entry (%s)\n", + ldap_err2string(rc) )); + goto out; + } count = ldap_count_entries(ldap_state.smbldap_state->ldap_struct, result); - } - - if (count != 1) { - DEBUG(0,("ldap_get_sid_from_id: mapping not found for %s: %u\n", - type, ((id_type & ID_USERID) ? id.uid : id.gid))); - goto out; + + if (count != 1) { + DEBUG(0,("ldap_get_sid_from_id: mapping not found for %s: %lu\n", + type, ((id_type & ID_USERID) ? (unsigned long)id.uid : + (unsigned long)id.gid))); + goto out; + } } entry = ldap_first_entry(ldap_state.smbldap_state->ldap_struct, result); @@ -538,117 +538,146 @@ static NTSTATUS ldap_get_id_from_sid(unid_t *id, int *id_type, const DOM_SID *si pstring id_str; const char *suffix; const char *type; - const char *obj_class; - const char *posix_obj_class; int rc; int count; char **attr_list; char *dn = NULL; NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; - /* first try getting the mapping from a samba user or group */ - sid_to_string(sid_str, sid); - if ( *id_type & ID_USERID ) { - type = get_attr_key2string( sidmap_attr_list, LDAP_ATTR_UIDNUMBER ); - obj_class = LDAP_OBJ_SAMBASAMACCOUNT; - posix_obj_class = LDAP_OBJ_POSIXACCOUNT; - suffix = lp_ldap_suffix(); - snprintf(filter, sizeof(filter), - "(&(|(&(objectClass=%s)(objectClass=%s))(objectClass=%s))(%s=%s))", - obj_class, posix_obj_class, LDAP_OBJ_IDMAP_ENTRY, - get_attr_key2string( sidmap_attr_list, LDAP_ATTR_SID ), - sid_str); - } - else { + + DEBUG(8,("ldap_get_id_from_sid: %s (%s)\n", sid_str, + (*id_type & ID_GROUPID ? "group" : "user") )); + + /* ahhh.... ok. We have to check users and groups in places other + than idmap (hint: we're a domain member of a Samba domain) */ + + if ( *id_type & ID_GROUPID ) { + type = get_attr_key2string( sidmap_attr_list, LDAP_ATTR_GIDNUMBER ); - obj_class = LDAP_OBJ_GROUPMAP; - posix_obj_class = LDAP_OBJ_POSIXGROUP; suffix = lp_ldap_group_suffix(); - snprintf(filter, sizeof(filter), - "(&(|(objectClass=%s)(objectClass=%s))(%s=%s))", - obj_class, LDAP_OBJ_IDMAP_ENTRY, + pstr_sprintf(filter, "(&(|(objectClass=%s)(objectClass=%s))(%s=%s))", + LDAP_OBJ_GROUPMAP, LDAP_OBJ_IDMAP_ENTRY, + get_attr_key2string( sidmap_attr_list, LDAP_ATTR_SID ), + sid_str); + + } + else { + + type = get_attr_key2string( sidmap_attr_list, LDAP_ATTR_UIDNUMBER ); + suffix = lp_ldap_suffix(); + pstr_sprintf(filter, "(&(|(&(objectClass=%s)(objectClass=%s))(objectClass=%s))(%s=%s))", + LDAP_OBJ_SAMBASAMACCOUNT, LDAP_OBJ_POSIXACCOUNT, LDAP_OBJ_IDMAP_ENTRY, get_attr_key2string( sidmap_attr_list, LDAP_ATTR_SID ), sid_str); + } - + + DEBUG(10,("ldap_get_id_from_sid: Searching for \"%s\"\n", filter)); + + /* do the search and check for errors */ + attr_list = get_attr_list( sidmap_attr_list ); rc = smbldap_search(ldap_state.smbldap_state, suffix, LDAP_SCOPE_SUBTREE, - filter, attr_list, 0, &result); - - if (rc != LDAP_SUCCESS) + filter, attr_list, 0, &result); + + if ( rc != LDAP_SUCCESS ) { + DEBUG(3,("ldap_get_id_from_sid: Failure looking up group mapping (%s)\n", + ldap_err2string(rc) )); goto out; + } count = ldap_count_entries(ldap_state.smbldap_state->ldap_struct, result); - - /* fall back to looking up an idmap entry if we didn't find anything under the idmap - user or group suffix */ - if (count == 0) { - ldap_msgfree(result); - - snprintf(filter, sizeof(filter), "(&(objectClass=%s)(%s=%s))", - LDAP_OBJ_IDMAP_ENTRY, LDAP_ATTRIBUTE_SID, sid_str); + if ( count > 1 ) { + DEBUG(3,("ldap_get_id_from_sid: search \"%s\" returned [%d] entries. Bailing...\n", + filter, count)); + goto out; + } + + /* see if we need to do a search here */ + + if ( count == 0 ) { + + if ( result ) { + ldap_msgfree(result); + result = NULL; + } + + /* look in idmap suffix */ suffix = lp_ldap_idmap_suffix(); + pstr_sprintf(filter, "(&(objectClass=%s)(%s=%s))", + LDAP_OBJ_IDMAP_ENTRY, LDAP_ATTRIBUTE_SID, sid_str); rc = smbldap_search(ldap_state.smbldap_state, suffix, LDAP_SCOPE_SUBTREE, filter, attr_list, 0, &result); - if (rc != LDAP_SUCCESS) + if (rc != LDAP_SUCCESS) { + DEBUG(3,("ldap_get_id_from_sid: Failure looking up idmap entry (%s)\n", + ldap_err2string(rc) )); goto out; + } + /* check for the number of entries returned */ + count = ldap_count_entries(ldap_state.smbldap_state->ldap_struct, result); - } - if ( count > 1 ) { - DEBUG(0, ("ldap_get_id_from_sid: search %s returned more than on entry!\n", - filter)); - goto out; - } - - /* we might have an existing entry to work with so pull out the requested information */ - - if ( count ) { - entry = ldap_first_entry(ldap_state.smbldap_state->ldap_struct, result); - - dn = ldap_get_dn(ldap_state.smbldap_state->ldap_struct, result); - DEBUG(10, ("Found mapping entry at dn=%s, looking for %s\n", dn, type)); - - if ( smbldap_get_single_attribute(ldap_state.smbldap_state->ldap_struct, entry, type, id_str) ) - { - if ( (*id_type & ID_USERID) ) - id->uid = strtoul(id_str, NULL, 10); - else - id->gid = strtoul(id_str, NULL, 10); - - ret = NT_STATUS_OK; + if ( count > 1 ) { + DEBUG(0, ("ldap_get_id_from_sid: (2nd) search %s returned [%d] entries!\n", + filter, count)); goto out; } - } - if (!(*id_type & ID_QUERY_ONLY)) { - /* if entry == NULL, and we are asked to - allocate a new id */ - int i; + + /* try to allocate a new id if we still haven't found one */ + + if ( (count==0) && !(*id_type & ID_QUERY_ONLY) ) { + int i; + + DEBUG(8,("ldap_get_id_from_sid: Allocating new id\n")); - for (i = 0; i < LDAP_MAX_ALLOC_ID; i++) - { - ret = ldap_allocate_id(id, *id_type); - if ( NT_STATUS_IS_OK(ret) ) - break; - } + for (i = 0; i < LDAP_MAX_ALLOC_ID; i++) { + ret = ldap_allocate_id(id, *id_type); + if ( NT_STATUS_IS_OK(ret) ) + break; + } - if ( !NT_STATUS_IS_OK(ret) ) { - DEBUG(0,("ldap_allocate_id: cannot acquire id lock!\n")); + if ( !NT_STATUS_IS_OK(ret) ) { + DEBUG(0,("ldap_allocate_id: cannot acquire id lock!\n")); + goto out; + } + + DEBUG(10,("ldap_get_id_from_sid: Allocated new %cid [%ul]\n", + (*id_type & ID_GROUPID ? 'g' : 'u'), (uint32)id->uid )); + + ret = ldap_set_mapping(sid, *id, *id_type); + + /* all done */ + goto out; } - - ret = ldap_set_mapping(sid, *id, *id_type); - } else { - /* no match, and not adding one */ - ret = NT_STATUS_UNSUCCESSFUL; } + DEBUG(10,("ldap_get_id_from_sid: success\n")); + + entry = ldap_first_entry(ldap_state.smbldap_state->ldap_struct, result); + + dn = ldap_get_dn(ldap_state.smbldap_state->ldap_struct, result); + + DEBUG(10, ("Found mapping entry at dn=%s, looking for %s\n", dn, type)); + + if ( smbldap_get_single_attribute(ldap_state.smbldap_state->ldap_struct, entry, type, id_str) ) + { + if ( (*id_type & ID_USERID) ) + id->uid = strtoul(id_str, NULL, 10); + else + id->gid = strtoul(id_str, NULL, 10); + + ret = NT_STATUS_OK; + goto out; + } + out: free_attr_list( attr_list ); if (result) @@ -670,7 +699,7 @@ static NTSTATUS ldap_set_mapping_internals(const DOM_SID *sid, unid_t id, int id_type, const char *ldap_dn, LDAPMessage *entry) { - char *dn = NULL; + pstring dn; pstring id_str; fstring type; LDAPMod **mods = NULL; @@ -685,24 +714,20 @@ static NTSTATUS ldap_set_mapping_internals(const DOM_SID *sid, unid_t id, if (ldap_dn) { DEBUG(10, ("Adding new IDMAP mapping on DN: %s", ldap_dn)); ldap_op = LDAP_MOD_REPLACE; - dn = strdup(ldap_dn); + pstrcpy( dn, ldap_dn ); } else { ldap_op = LDAP_MOD_ADD; - asprintf(&dn, "%s=%s,%s", get_attr_key2string( sidmap_attr_list, LDAP_ATTR_SID), + pstr_sprintf(dn, "%s=%s,%s", get_attr_key2string( sidmap_attr_list, LDAP_ATTR_SID), sid_string, lp_ldap_idmap_suffix()); } - if (!dn) { - DEBUG(0, ("ldap_set_mapping_internals: out of memory allocating DN!\n")); - return NT_STATUS_NO_MEMORY; - } - if ( id_type & ID_USERID ) fstrcpy( type, get_attr_key2string( sidmap_attr_list, LDAP_ATTR_UIDNUMBER ) ); else fstrcpy( type, get_attr_key2string( sidmap_attr_list, LDAP_ATTR_GIDNUMBER ) ); - snprintf(id_str, sizeof(id_str), "%u", ((id_type & ID_USERID) ? id.uid : id.gid)); + pstr_sprintf(id_str, "%lu", ((id_type & ID_USERID) ? (unsigned long)id.uid : + (unsigned long)id.gid)); if (entry) values = ldap_get_values(ldap_state.smbldap_state->ldap_struct, entry, "objectClass"); @@ -754,15 +779,16 @@ static NTSTATUS ldap_set_mapping_internals(const DOM_SID *sid, unid_t id, char *ld_error = NULL; ldap_get_option(ldap_state.smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error); - DEBUG(0,("ldap_set_mapping_internals: Failed to %s mapping from %s to %u [%s]\n", + DEBUG(0,("ldap_set_mapping_internals: Failed to %s mapping from %s to %lu [%s]\n", (ldap_op == LDAP_MOD_ADD) ? "add" : "replace", - sid_string, (unsigned int)((id_type & ID_USERID) ? id.uid : id.gid), type)); + sid_string, (unsigned long)((id_type & ID_USERID) ? id.uid : id.gid), type)); DEBUG(0, ("ldap_set_mapping_internals: Error was: %s (%s)\n", ld_error ? ld_error : "(NULL)", ldap_err2string (rc))); return NT_STATUS_UNSUCCESSFUL; } - DEBUG(10,("ldap_set_mapping: Successfully created mapping from %s to %d [%s]\n", - sid_string, ((id_type & ID_USERID) ? id.uid : id.gid), type)); + DEBUG(10,("ldap_set_mapping: Successfully created mapping from %s to %lu [%s]\n", + sid_string, ((id_type & ID_USERID) ? (unsigned long)id.uid : + (unsigned long)id.gid), type)); return NT_STATUS_OK; } @@ -794,18 +820,18 @@ static NTSTATUS ldap_set_mapping(const DOM_SID *sid, unid_t id, int id_type) suffix = lp_ldap_suffix(); type = get_attr_key2string( idpool_attr_list, LDAP_ATTR_UIDNUMBER ); posix_obj_class = LDAP_OBJ_POSIXACCOUNT; - snprintf(id_str, sizeof(id_str), "%u", id.uid ); + fstr_sprintf(id_str, "%lu", (unsigned long)id.uid ); } else { obj_class = LDAP_OBJ_GROUPMAP; suffix = lp_ldap_group_suffix(); type = get_attr_key2string( idpool_attr_list, LDAP_ATTR_GIDNUMBER ); posix_obj_class = LDAP_OBJ_POSIXGROUP; - snprintf(id_str, sizeof(id_str), "%u", id.gid ); + fstr_sprintf(id_str, "%lu", (unsigned long)id.gid ); } sid_to_string(sid_str, sid); - snprintf(filter, sizeof(filter), + pstr_sprintf(filter, "(|" "(&(|(objectClass=%s)(|(objectClass=%s)(objectClass=%s)))(%s=%s))" "(&(objectClass=%s)(%s=%s))" @@ -859,10 +885,13 @@ out: return ret; } -/***************************************************************************** - Initialise idmap database. -*****************************************************************************/ -static NTSTATUS ldap_idmap_init( char *params ) + + +/********************************************************************** + Verify the sambaUnixIdPool entry in the directiry. +**********************************************************************/ + +static NTSTATUS verify_idpool( void ) { fstring filter; int rc; @@ -870,24 +899,8 @@ static NTSTATUS ldap_idmap_init( char *params ) LDAPMessage *result = NULL; LDAPMod **mods = NULL; int count; - NTSTATUS nt_status; - - ldap_state.mem_ctx = talloc_init("idmap_ldap"); - if (!ldap_state.mem_ctx) { - return NT_STATUS_NO_MEMORY; - } - - /* assume location is the only parameter */ - if (!NT_STATUS_IS_OK(nt_status = - smbldap_init(ldap_state.mem_ctx, params, - &ldap_state.smbldap_state))) { - talloc_destroy(ldap_state.mem_ctx); - return nt_status; - } - - /* see if the idmap suffix and sub entries exists */ - snprintf( filter, sizeof(filter), "(objectclass=%s)", LDAP_OBJ_IDPOOL ); + fstr_sprintf( filter, "(objectclass=%s)", LDAP_OBJ_IDPOOL ); attr_list = get_attr_list( idpool_attr_list ); rc = smbldap_search(ldap_state.smbldap_state, lp_ldap_idmap_suffix(), @@ -914,8 +927,8 @@ static NTSTATUS ldap_idmap_init( char *params ) return NT_STATUS_UNSUCCESSFUL; } - snprintf( uid_str, sizeof(uid_str), "%d", luid ); - snprintf( gid_str, sizeof(gid_str), "%d", lgid ); + fstr_sprintf( uid_str, "%lu", (unsigned long)luid ); + fstr_sprintf( gid_str, "%lu", (unsigned long)lgid ); smbldap_set_mod( &mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_IDPOOL ); smbldap_set_mod( &mods, LDAP_MOD_ADD, @@ -925,7 +938,36 @@ static NTSTATUS ldap_idmap_init( char *params ) rc = smbldap_modify(ldap_state.smbldap_state, lp_ldap_idmap_suffix(), mods); } + + return ( rc==LDAP_SUCCESS ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL ); +} + +/***************************************************************************** + Initialise idmap database. +*****************************************************************************/ +static NTSTATUS ldap_idmap_init( char *params ) +{ + NTSTATUS nt_status; + + ldap_state.mem_ctx = talloc_init("idmap_ldap"); + if (!ldap_state.mem_ctx) { + return NT_STATUS_NO_MEMORY; + } + + /* assume location is the only parameter */ + if (!NT_STATUS_IS_OK(nt_status = + smbldap_init(ldap_state.mem_ctx, params, + &ldap_state.smbldap_state))) { + talloc_destroy(ldap_state.mem_ctx); + return nt_status; + } + + /* see if the idmap suffix and sub entries exists */ + nt_status = verify_idpool(); + if ( !NT_STATUS_IS_OK(nt_status) ) + return nt_status; + return NT_STATUS_OK; } diff --git a/source3/sam/idmap_tdb.c b/source3/sam/idmap_tdb.c index 2055103898..8ab8ec8477 100644 --- a/source3/sam/idmap_tdb.c +++ b/source3/sam/idmap_tdb.c @@ -45,20 +45,6 @@ static struct idmap_state { gid_t gid_low, gid_high; /* Range of gids to allocate */ } idmap_state; -/********************************************************************** - Return the TDB_CONTEXT* for winbindd_idmap. I **really** feel - dirty doing this, but not so dirty that I want to create another - tdb -***********************************************************************/ - -TDB_CONTEXT *idmap_tdb_handle( void ) -{ - if ( idmap_tdb ) - return idmap_tdb; - - return NULL; -} - /********************************************************************** allocate a new RID; We don't care if is a user or group **********************************************************************/ @@ -75,7 +61,7 @@ static NTSTATUS db_allocate_rid(uint32 *rid, int rid_type) /* cannot fail since idmap is only called winbindd */ - idmap_get_free_rid_range( &lowrid, &highrid ); + get_free_rid_range( &lowrid, &highrid ); tmp_rid = lowrid; @@ -122,7 +108,7 @@ static NTSTATUS db_allocate_id(unid_t *id, int id_type) } /* fetch a new id and increment it */ - ret = tdb_change_uint32_atomic(idmap_tdb, HWM_USER, &hwm, 1); + ret = tdb_change_uint32_atomic(idmap_tdb, HWM_USER, (unsigned int *)&hwm, 1); if (!ret) { DEBUG(0, ("idmap_tdb: Fatal error while fetching a new id\n!")); return NT_STATUS_UNSUCCESSFUL; @@ -152,7 +138,7 @@ static NTSTATUS db_allocate_id(unid_t *id, int id_type) } /* fetch a new id and increment it */ - ret = tdb_change_uint32_atomic(idmap_tdb, HWM_GROUP, &hwm, 1); + ret = tdb_change_uint32_atomic(idmap_tdb, HWM_GROUP, (unsigned int *)&hwm, 1); if (!ret) { DEBUG(0, ("idmap_tdb: Fatal error while fetching a new id\n!")); @@ -650,6 +636,27 @@ static void db_idmap_status(void) /* Display complete mapping of users and groups to rids */ } +/********************************************************************** + Return the TDB_CONTEXT* for winbindd_idmap. I **really** feel + dirty doing this, but not so dirty that I want to create another + tdb +***********************************************************************/ + +TDB_CONTEXT *idmap_tdb_handle( void ) +{ + if ( idmap_tdb ) + return idmap_tdb; + + /* go ahead an open it; db_idmap_init() doesn't use any params + right now */ + + db_idmap_init( NULL ); + if ( idmap_tdb ) + return idmap_tdb; + + return NULL; +} + static struct idmap_methods db_methods = { db_idmap_init, diff --git a/source3/sam/idmap_util.c b/source3/sam/idmap_util.c index f794ea5173..f28e11cde7 100644 --- a/source3/sam/idmap_util.c +++ b/source3/sam/idmap_util.c @@ -22,50 +22,7 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_IDMAP -/********************************************************************** -**********************************************************************/ - -BOOL idmap_get_free_ugid_range(uint32 *low, uint32 *high) -{ - uid_t u_low, u_high; - gid_t g_low, g_high; - - if (!lp_idmap_uid(&u_low, &u_high) || !lp_idmap_gid(&g_low, &g_high)) { - return False; - } - - *low = (u_low < g_low) ? u_low : g_low; - *high = (u_high < g_high) ? u_high : g_high; - - return True; -} - -/****************************************************************** - Get the the non-algorithmic RID range if idmap range are defined -******************************************************************/ - -BOOL idmap_get_free_rid_range(uint32 *low, uint32 *high) -{ - uint32 id_low, id_high; - - if (!lp_enable_rid_algorithm()) { - *low = BASE_RID; - *high = (uint32)-1; - } - - if (!idmap_get_free_ugid_range(&id_low, &id_high)) { - return False; - } - - *low = fallback_pdb_uid_to_user_rid(id_low); - if (fallback_pdb_user_rid_to_uid((uint32)-1) < id_high) { - *high = (uint32)-1; - } else { - *high = fallback_pdb_uid_to_user_rid(id_high); - } - - return True; -} +#if 0 /* NOT USED */ /********************************************************************** Get the free RID base if idmap is configured, otherwise return 0 @@ -137,6 +94,8 @@ BOOL idmap_check_sid_is_in_free_range(const DOM_SID *sid) return True; } +#endif /* NOT USED */ + /***************************************************************** Returns SID pointer. *****************************************************************/ @@ -192,7 +151,7 @@ NTSTATUS idmap_sid_to_uid(const DOM_SID *sid, uid_t *uid, uint32 flags) flags |= ID_USERID; - ret = idmap_get_id_from_sid(&id, &flags, sid); + ret = idmap_get_id_from_sid(&id, (int *)&flags, sid); if ( NT_STATUS_IS_OK(ret) ) { DEBUG(10,("idmap_sid_to_uid: uid = [%lu]\n", (unsigned long)id.uid)); @@ -221,7 +180,7 @@ NTSTATUS idmap_sid_to_gid(const DOM_SID *sid, gid_t *gid, uint32 flags) flags |= ID_GROUPID; - ret = idmap_get_id_from_sid(&id, &flags, sid); + ret = idmap_get_id_from_sid(&id, (int *)&flags, sid); if ( NT_STATUS_IS_OK(ret) ) { diff --git a/source3/script/.cvsignore b/source3/script/.cvsignore index 7a8114ecd7..0464ca2335 100644 --- a/source3/script/.cvsignore +++ b/source3/script/.cvsignore @@ -1 +1,2 @@ findsmb +gen-8bit-gap.sh diff --git a/source3/script/find_missing_doc.pl b/source3/script/find_missing_doc.pl deleted file mode 100755 index b27a405e4d..0000000000 --- a/source3/script/find_missing_doc.pl +++ /dev/null @@ -1,90 +0,0 @@ -#!/usr/bin/perl - -my $doc_file = "/docs/docbook/manpages/smb.conf.5.sgml"; -my $source_file = "/source/param/loadparm.c"; - -my %link,%doc,%param; - -# This one shouldn't be documented at all -$doc{-valid} = "FOUND"; - -$topdir = (shift @ARGV) or $topdir = "."; - -################################################## -# Reading links from manpage - -open(IN,$topdir.$doc_file); - -while() { - if( /([^<]*)<\/parameter><\/link><\/para><\/listitem>/g ){ - $link{$2} = $1; - $ref{$1} = $2; - } -} - -close(IN); - -################################################## -# Reading documentation from manpage - -open(IN,$topdir.$doc_file) || die("Can't open $topdir$doc_file"); - -while() { - if( /([^<]*?)([ ]*)\(.\)([ ]*)<\/term>/g ) { - $key = $1; - $value = $2; - $doc{$value} = $key; - - # There is a reference to this entry - if($ref{$key} eq $value){ - $ref{$key} = "FOUND"; - } else { - if($ref{$key}) { - print "$key should refer to $value, but refers to " . $ref{$key} . "\n"; - } else { - print "$key should refer to $value, but has no reference!\n"; - } - $ref{$key} = $value; - } - } -} - -close(IN); - -################################################# -# Reading entries from source code - -open(SOURCE,$topdir.$source_file) || die("Can't open $topdir$source_file"); - -while ($ln = ) { - last if $ln =~ m/^static\ struct\ parm_struct\ parm_table.*/; -} #burn through the preceding lines - -while ($ln = ) { - last if $ln =~ m/^\s*\}\;\s*$/; - #pull in the param names only - next if $ln =~ m/.*P_SEPARATOR.*/; - next unless $ln =~ /.*\"(.*)\".*/; - - if($doc{lc($1)}) { - $doc{lc($1)} = "FOUND"; - } else { - print "$1 is not documented!\n"; - } -} -close SOURCE; - -################################################## -# Trying to find missing references - -foreach (keys %ref) { - if($ref{$_} cmp "FOUND") { - print "$_ references to " . $ref{$_} . ", but " . $ref{$_} . " isn't an anchor!\n"; - } -} - -foreach (keys %doc) { - if($doc{$_} cmp "FOUND") { - print "$_ is documented but is not a configuration option!\n"; - } -} diff --git a/source3/script/findsmb.in b/source3/script/findsmb.in index 6276bd3f39..fb06018fe5 100755 --- a/source3/script/findsmb.in +++ b/source3/script/findsmb.in @@ -23,29 +23,33 @@ $SAMBABIN = "@prefix@/bin"; for ($i = 0; $i < 2; $i++) { # test for -d and -r options - $_ = shift; - if (m/-d|-D/) { - $DEBUG = 1; - } elsif (m/-r/) { - $R_OPTION = "-r"; - } + $_ = shift; + if (m/-d|-D/) { + $DEBUG = 1; + } elsif (m/-r/) { + $R_OPTION = "-r"; + } } if ($_) { # set broadcast address if it was specified - $BCAST = "-B $_"; + $BCAST = "-B $_"; } -sub ipsort # do numeric sort on last field of IP address + +###################################################################### +# do numeric sort on last field of IP address +sub ipsort { - @t1 = split(/\./,$a); - @t2 = split(/\./,$b); - @t1[3] <=> @t2[3]; + @t1 = split(/\./,$a); + @t2 = split(/\./,$b); + @t1[3] <=> @t2[3]; } +###################################################################### # look for all machines that respond to a name lookup -open(NMBLOOKUP,"$SAMBABIN/nmblookup $BCAST '*'|") || - die("Can't run nmblookup '*'.\n"); +open(NMBLOOKUP,"$SAMBABIN/nmblookup $BCAST '*' --debuglevel=0|") || + die("Can't run nmblookup '*'.\n"); # get rid of all lines that are not a response IP address, # strip everything but IP address and sort by last field in address @@ -59,94 +63,98 @@ print "---------------------------------------------------------------------\n"; foreach $ip (@ipaddrs) # loop through each IP address found { - $ip =~ s/\n//; # strip newline from IP address - -# find the netbios names registered by each machine - - open(NMBLOOKUP,"$SAMBABIN/nmblookup $R_OPTION -A $ip|") || - die("Can't get nmb name list.\n"); - @nmblookup = ; - close NMBLOOKUP; - -# get the first <00> name - - @name = grep(/<00>/,@nmblookup); - $_ = @name[0]; - if ($_) { # we have a netbios name - if (/GROUP/) { # is it a group name - ($name, $aliases, $type, $length, @addresses) = - gethostbyaddr(pack('C4',split('\.',$ip)),2); - if (! $name) { # could not get name - $name = "unknown nis name"; + $ip =~ s/\n//; # strip newline from IP address + + # find the netbios names registered by each machine + + open(NMBLOOKUP,"$SAMBABIN/nmblookup $R_OPTION -A $ip --debuglevel=0|") || + die("Can't get nmb name list.\n"); + @nmblookup = ; + close NMBLOOKUP; + + # get the first <00> name + + @name = grep(/<00>/,@nmblookup); + $_ = @name[0]; + + if ($_) { # we have a netbios name + if (/GROUP/) { # is it a group name + ($name, $aliases, $type, $length, @addresses) = + gethostbyaddr(pack('C4',split('\.',$ip)),2); + if (! $name) { # could not get name + $name = "unknown nis name"; + } + } else { + # The Netbios name can contain lot of characters also '<' '>' + # and spaces. The follwing cure inside name space but not + # names starting or ending with spaces + /(.{1,15})\s+<00>\s+/; + $name = $1; + $name =~ s/^\s+//g; + } + + # do an smbclient command on the netbios name. + + if ( "$name" ) { + open(SMB,"$SAMBABIN/smbclient -L $name -I $ip -N --debuglevel=1 2>&1 |") || + die("Can't do smbclient command.\n"); + @smb = ; + close SMB; + + if ($DEBUG) { # if -d flag print results of nmblookup and smbclient + print "===============================================================\n"; + print @nmblookup; + print @smb; + } + + # look for the OS= string + + @info = grep(/OS=/,@smb); + $_ = @info[0]; + if ($_) { # we found response + s/Domain=|OS=|Server=|\n//g; # strip out descriptions to make line shorter + + } else { # no OS= string in response (WIN95 client) + + # for WIN95 clients get workgroup name from nmblookup response + @name = grep(/<00> - /,@nmblookup); + $_ = @name[0]; + if ($_) { + # Same as before for space and characters + /(.{1,15})\s+<00>\s+/; + $_ = "[$1]"; + } else { + $_ = "Unknown Workgroup"; + } + } + } + + # see if machine registered a local master browser name + if (grep(/<1d>/,@nmblookup)) { + $master = '+'; # indicate local master browser + if (grep(/<1b>/,@nmblookup)) { # how about domain master browser? + $master = '*'; # indicate domain master browser + } + } else { + $master = ' '; # not a browse master + } + + # line up info in 3 columns + + print "$ip".' 'x(16-length($ip))."$name".' 'x(14-length($name))."$master"."$_\n"; + + } else { # no netbios name found + # try getting the host name + ($name, $aliases, $type, $length, @addresses) = + gethostbyaddr(pack('C4',split('\.',$ip)),2); + if (! $name) { # could not get name + $name = "unknown nis name"; + } + if ($DEBUG) { # if -d flag print results of nmblookup + print "===============================================================\n"; + print @nmblookup; + } + print "$ip".' 'x(16-length($ip))."$name\n"; } - } else { -# The Netbios name can contain lot of characters also '<' '>' -# and spaces. The follwing cure inside name space but not -# names starting or ending with spaces - /(.{1,15})\s+<00>\s+/; - $name = $1; - } - -# do an smbclient command on the netbios name. - - open(SMB,"$SAMBABIN/smbclient -N -L $name -I $ip -U% |") || - die("Can't do smbclient command.\n"); - @smb = ; - close SMB; - - if ($DEBUG) { # if -d flag print results of nmblookup and smbclient - print "===============================================================\n"; - print @nmblookup; - print @smb; - } - -# look for the OS= string - - @info = grep(/OS=/,@smb); - $_ = @info[0]; - if ($_) { # we found response - s/Domain=|OS=|Server=|\n//g; # strip out descriptions to make line shorter - - } else { # no OS= string in response (WIN95 client) - -# for WIN95 clients get workgroup name from nmblookup response - @name = grep(/<00> - /,@nmblookup); - $_ = @name[0]; - if ($_) { -# Same as before for space and characters - /(.{1,15})\s+<00>\s+/; - $_ = "[$1]"; - } else { - $_ = "Unknown Workgroup"; - } - } - -# see if machine registered a local master browser name - if (grep(/<1d>/,@nmblookup)) { - $master = '+'; # indicate local master browser - if (grep(/<1b>/,@nmblookup)) { # how about domain master browser? - $master = '*'; # indicate domain master browser - } - } else { - $master = ' '; # not a browse master - } - -# line up info in 3 columns - - print "$ip".' 'x(16-length($ip))."$name".' 'x(14-length($name))."$master"."$_\n"; - - } else { # no netbios name found -# try getting the host name - ($name, $aliases, $type, $length, @addresses) = - gethostbyaddr(pack('C4',split('\.',$ip)),2); - if (! $name) { # could not get name - $name = "unknown nis name"; - } - if ($DEBUG) { # if -d flag print results of nmblookup - print "===============================================================\n"; - print @nmblookup; - } - print "$ip".' 'x(16-length($ip))."$name\n"; - } } diff --git a/source3/script/gap.awk b/source3/script/gap.awk new file mode 100644 index 0000000000..11680d10f9 --- /dev/null +++ b/source3/script/gap.awk @@ -0,0 +1,39 @@ +BEGIN { hv["0"] = 0; hv["1"] = 1; hv["2"] = 2; hv["3"] = 3; + hv["4"] = 4; hv["5"] = 5; hv["6"] = 6; hv["7"] = 7; + hv["8"] = 8; hv["9"] = 9; hv["A"] = 10; hv["B"] = 11; + hv["C"] = 12; hv["D"] = 13; hv["E"] = 14; hv["F"] = 15; + hv["a"] = 10; hv["b"] = 11; hv["c"] = 12; hv["d"] = 13; + hv["e"] = 14; hv["f"] = 15; + + first = 0; last = 0; idx = 0; +} + +function tonum(str) +{ + num=0; + cnt=1; + while (cnt <= length(str)) { + num *= 16; + num += hv[substr(str,cnt,1)]; + ++cnt; + } + return num; +} + +{ + u = tonum($1); + if (u - last > 6) + { + if (last) + { + printf (" { 0x%04x, 0x%04x, %5d },\n", + first, last, idx); + idx -= u - last - 1; + } + first = u; + } + last = u; +} + +END { printf (" { 0x%04x, 0x%04x, %5d },\n", + first, last, idx); } diff --git a/source3/script/gaptab.awk b/source3/script/gaptab.awk new file mode 100644 index 0000000000..f9d1526361 --- /dev/null +++ b/source3/script/gaptab.awk @@ -0,0 +1,48 @@ +BEGIN { hv["0"] = 0; hv["1"] = 1; hv["2"] = 2; hv["3"] = 3; + hv["4"] = 4; hv["5"] = 5; hv["6"] = 6; hv["7"] = 7; + hv["8"] = 8; hv["9"] = 9; hv["A"] = 10; hv["B"] = 11; + hv["C"] = 12; hv["D"] = 13; hv["E"] = 14; hv["F"] = 15; + hv["a"] = 10; hv["b"] = 11; hv["c"] = 12; hv["d"] = 13; + hv["e"] = 14; hv["f"] = 15; + + first = 0; last = 0; idx = 0; f = 0; +} + +function tonum(str) +{ + num=0; + cnt=1; + while (cnt <= length(str)) { + num *= 16; + num += hv[substr(str,cnt,1)]; + ++cnt; + } + return num; +} + +function fmt(val) +{ + if (f++ % 8 == 0) + { printf ("\n '\\x%02x',", val); } + else + { printf (" '\\x%02x',", val); } +} + +{ + u = tonum($1); c = tonum($2); + + if (u - last > 6) + { + if (last) { idx += last - first + 1; } + first = u; + } + else + { + for (m = last+1; m < u; m++) { fmt(0); } + } + + fmt(c); + last = u; +} + +END { print "" } diff --git a/source3/script/gen-8bit-gap.awk b/source3/script/gen-8bit-gap.awk new file mode 100644 index 0000000000..59a1a23be0 --- /dev/null +++ b/source3/script/gen-8bit-gap.awk @@ -0,0 +1,18 @@ +BEGIN { + for (i=0; i<256; i++) { + tbl[sprintf("%02x",i)] = "0x0000"; + } +} + +/^[[:space:]]*.x([[:xdigit:]][[:xdigit:]])[:space:]*.*$/ { + tbl[substr($2,3,2)]=sprintf("0x%s",substr($1,3,4)); +} + +END { + for(i=0; i<32; i++) { + for(j=0; j<8; j++) { + printf(" %s,", tbl[sprintf("%02x",i*8+j)]); + } + printf "\n" + } +} \ No newline at end of file diff --git a/source3/script/gen-8bit-gap.sh.in b/source3/script/gen-8bit-gap.sh.in new file mode 100755 index 0000000000..bcf64a4464 --- /dev/null +++ b/source3/script/gen-8bit-gap.sh.in @@ -0,0 +1,49 @@ +#!/bin/sh +if test $# -ne 2 ; then + echo "Usage: $0 " + exit 1 +fi + +CHARMAP=$1 +CHARSETNAME=$2 + +echo "/* " +echo " * Conversion table for $CHARSETNAME charset " +echo " * " +echo " * Conversion tables are generated using $CHARMAP table " +echo " * and source/script/gen-8bit-gap.sh script " +echo " * " +echo " * This program is free software; you can redistribute it and/or modify " +echo " * it under the terms of the GNU General Public License as published by " +echo " * the Free Software Foundation; either version 2 of the License, or " +echo " * (at your option) any later version. " +echo " * " +echo " * This program is distributed in the hope that it will be useful," +echo " * but WITHOUT ANY WARRANTY; without even the implied warranty of " +echo " * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the " +echo " * GNU General Public License for more details. " +echo " * " +echo " * You should have received a copy of the GNU General Public License " +echo " * along with this program; if not, write to the Free Software " +echo " * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. " +echo " */" + +echo '#include "includes.h"' +echo +echo "static const uint16 to_ucs2[256] = {" +cat "$CHARMAP" | @AWK@ -f @srcdir@/script/gen-8bit-gap.awk +echo "};" +echo +echo "static const struct charset_gap_table from_idx[] = {" +sed -ne 's/^[[:space:]]*.x\(..\).*/\1 \2/p' \ + "$CHARMAP" | sort -u | @AWK@ -f @srcdir@/script/gaptab.awk +echo "};" +echo +echo "SMB_GENERATE_CHARSET_MODULE_8_BIT_GAP($CHARSETNAME)" +echo diff --git a/source3/script/installmodules.sh b/source3/script/installmodules.sh index ec5691992d..c80da76368 100755 --- a/source3/script/installmodules.sh +++ b/source3/script/installmodules.sh @@ -24,13 +24,4 @@ for p in $*; do chmod $INSTALLPERMS $LIBDIR/$p2 done - -cat << EOF -====================================================================== -The modules are installed. You may uninstall the modules using the -command "make uninstallmodules" or "make uninstall" to uninstall -binaries, man pages, shell scripts and modules. -====================================================================== -EOF - exit 0 diff --git a/source3/script/installswat.sh b/source3/script/installswat.sh index d1f8ea191d..bd2f8da234 100755 --- a/source3/script/installswat.sh +++ b/source3/script/installswat.sh @@ -71,13 +71,13 @@ done done -# Install Using Samba book +# Install Using Samba book (but only if it is there) -if [ "x$BOOKDIR" != "x" ]; then +if [ "x$BOOKDIR" != "x" -a -f $SRCDIR../docs/htmldocs/using_samba/toc.html ]; then # Create directories - for d in $BOOKDIR $BOOKDIR/figs $BOOKDIR/gifs; do + for d in $BOOKDIR $BOOKDIR/figs ; do if [ ! -d $d ]; then mkdir $d if [ ! -d $d ]; then @@ -96,19 +96,17 @@ if [ "x$BOOKDIR" != "x" ]; then chmod 0644 $FNAME done - # Figures - - for f in $SRCDIR../docs/htmldocs/using_samba/figs/*.gif; do - FNAME=$BOOKDIR/figs/`basename $f` + for f in $SRCDIR../docs/htmldocs/using_samba/*.gif; do + FNAME=$BOOKDIR/`basename $f` echo $FNAME cp $f $FNAME || echo Cannot install $FNAME. Does $USER have privileges? chmod 0644 $FNAME done - # Gifs + # Figures - for f in $SRCDIR../docs/htmldocs/using_samba/gifs/*.gif; do - FNAME=$BOOKDIR/gifs/`basename $f` + for f in $SRCDIR../docs/htmldocs/using_samba/figs/*.gif; do + FNAME=$BOOKDIR/figs/`basename $f` echo $FNAME cp $f $FNAME || echo Cannot install $FNAME. Does $USER have privileges? chmod 0644 $FNAME diff --git a/source3/script/linkmodules.sh b/source3/script/linkmodules.sh new file mode 100755 index 0000000000..16a04cc064 --- /dev/null +++ b/source3/script/linkmodules.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +cd "$1" +test -f "$2" || exit 0 + +for I in $3 $4 $5 $6 $7 $8 +do + echo "Linking $I to $2" + ln -s $2 $I +done + +exit 0 diff --git a/source3/script/mkproto.awk b/source3/script/mkproto.awk index 6a45a70cc3..b6e911699e 100644 --- a/source3/script/mkproto.awk +++ b/source3/script/mkproto.awk @@ -41,20 +41,6 @@ END { } } -# special handling for code merge of TNG to head -/^#define OLD_NTDOMAIN 1/ { - printf "#if OLD_NTDOMAIN\n" -} -/^#undef OLD_NTDOMAIN/ { - printf "#endif\n" -} -/^#define NEW_NTDOMAIN 1/ { - printf "#if NEW_NTDOMAIN\n" -} -/^#undef NEW_NTDOMAIN/ { - printf "#endif\n" -} - # we handle the loadparm.c fns separately /^FN_LOCAL_BOOL/ { diff --git a/source3/script/mkproto.sh b/source3/script/mkproto.sh index 2bf96c9b41..62041c7e33 100755 --- a/source3/script/mkproto.sh +++ b/source3/script/mkproto.sh @@ -25,7 +25,7 @@ header="$1" shift headertmp="$header.$$.tmp~" -proto_src="`echo $@ | tr ' ' '\n' | sed -e 's/\.o/\.c/g' | sort | uniq | egrep -v 'ubiqx/|wrapped'`" +proto_src="`echo $@ | tr ' ' '\n' | sed -e 's/\.o/\.c/g' | sort | uniq | egrep -v 'ubiqx/|wrapped|modules/getdate'`" echo creating $header diff --git a/source3/script/mkversion.sh b/source3/script/mkversion.sh new file mode 100755 index 0000000000..ca39297940 --- /dev/null +++ b/source3/script/mkversion.sh @@ -0,0 +1,87 @@ +#!/bin/sh +# + +VERSION_FILE=$1 +OUTPUT_FILE=$2 + +if test -z "$VERSION_FILE";then + VERSION_FILE="VERSION" +fi + +if test -z "$OUTPUT_FILE";then + OUTPUT_FILE="include/version.h" +fi + +SOURCE_DIR=$3 + +SAMBA_VERSION_MAJOR=`sed -n 's/^SAMBA_VERSION_MAJOR=//p' $SOURCE_DIR$VERSION_FILE` +SAMBA_VERSION_MINOR=`sed -n 's/^SAMBA_VERSION_MINOR=//p' $SOURCE_DIR$VERSION_FILE` +SAMBA_VERSION_RELEASE=`sed -n 's/^SAMBA_VERSION_RELEASE=//p' $SOURCE_DIR$VERSION_FILE` + +SAMBA_VERSION_REVISION=`sed -n 's/^SAMBA_VERSION_REVISION=//p' $SOURCE_DIR$VERSION_FILE` + +SAMBA_VERSION_PRE_RELEASE=`sed -n 's/^SAMBA_VERSION_PRE_RELEASE=//p' $SOURCE_DIR$VERSION_FILE` + +SAMBA_VERSION_RC_RELEASE=`sed -n 's/^SAMBA_VERSION_RC_RELEASE=//p' $SOURCE_DIR$VERSION_FILE` + +SAMBA_VERSION_BETA_RELEASE=`sed -n 's/^SAMBA_VERSION_BETA_RELEASE=//p' $SOURCE_DIR$VERSION_FILE` + +SAMBA_VERSION_ALPHA_RELEASE=`sed -n 's/^SAMBA_VERSION_ALPHA_RELEASE=//p' $SOURCE_DIR$VERSION_FILE` + +SAMBA_VERSION_TEST_RELEASE=`sed -n 's/^SAMBA_VERSION_TEST_RELEASE=//p' $SOURCE_DIR$VERSION_FILE` + +SAMBA_VERSION_IS_CVS_SNAPSHOT=`sed -n 's/^SAMBA_VERSION_IS_CVS_SNAPSHOT=//p' $SOURCE_DIR$VERSION_FILE` + +SAMBA_VERSION_VENDOR_SUFFIX=`sed -n 's/^SAMBA_VERSION_VENDOR_SUFFIX=//p' $SOURCE_DIR$VERSION_FILE` + +echo "/* Autogenerated by script/mkversion.sh */" > $OUTPUT_FILE + +echo "#define SAMBA_VERSION_MAJOR ${SAMBA_VERSION_MAJOR}" >> $OUTPUT_FILE +echo "#define SAMBA_VERSION_MINOR ${SAMBA_VERSION_MINOR}" >> $OUTPUT_FILE +echo "#define SAMBA_VERSION_RELEASE ${SAMBA_VERSION_RELEASE}" >> $OUTPUT_FILE + + +SAMBA_VERSION_STRING="${SAMBA_VERSION_MAJOR}.${SAMBA_VERSION_MINOR}.${SAMBA_VERSION_RELEASE}" + + +if test -n "${SAMBA_VERSION_REVISION}";then + SAMBA_VERSION_STRING="${SAMBA_VERSION_STRING}${SAMBA_VERSION_REVISION}" + echo "#define SAMBA_VERSION_REVISION \"${SAMBA_VERSION_REVISION}\"" >> $OUTPUT_FILE +elif test -n "${SAMBA_VERSION_PRE_RELEASE}";then + SAMBA_VERSION_STRING="${SAMBA_VERSION_STRING}pre${SAMBA_VERSION_PRE_RELEASE}" + echo "#define SAMBA_VERSION_PRE_RELEASE ${SAMBA_VERSION_PRE_RELEASE}" >> $OUTPUT_FILE +elif test -n "${SAMBA_VERSION_RC_RELEASE}";then + SAMBA_VERSION_STRING="${SAMBA_VERSION_STRING}rc${SAMBA_VERSION_RC_RELEASE}" + echo "#define SAMBA_VERSION_RC_RELEASE ${SAMBA_VERSION_RC_RELEASE}" >> $OUTPUT_FILE +elif test -n "${SAMBA_VERSION_BETA_RELEASE}";then + SAMBA_VERSION_STRING="${SAMBA_VERSION_STRING}beta${SAMBA_VERSION_BETA_RELEASE}" + echo "#define SAMBA_VERSION_BETA_RELEASE ${SAMBA_VERSION_BETA_RELEASE}" >> $OUTPUT_FILE +elif test -n "${SAMBA_VERSION_ALPHA_RELEASE}";then + SAMBA_VERSION_STRING="${SAMBA_VERSION_STRING}alpha${SAMBA_VERSION_ALPHA_RELEASE}" + echo "#define SAMBA_VERSION_ALPHA_RELEASE ${SAMBA_VERSION_ALPHA_RELEASE}" >> $OUTPUT_FILE +elif test -n "${SAMBA_VERSION_TEST_RELEASE}";then + SAMBA_VERSION_STRING="${SAMBA_VERSION_STRING}test${SAMBA_VERSION_TEST_RELEASE}" + echo "#define SAMBA_VERSION_TEST_RELEASE ${SAMBA_VERSION_TEST_RELEASE}" >> $OUTPUT_FILE +fi + + +if test x"${SAMBA_VERSION_IS_CVS_SNAPSHOT}" = x"yes";then + SAMBA_VERSION_STRING="CVS ${SAMBA_VERSION_STRING}" + echo "#define SAMBA_VERSION_IS_CVS_SNAPSHOT 1" >> $OUTPUT_FILE +fi + +if test -n "${SAMBA_VERSION_VENDOR_SUFFIX}";then + echo "#define SAMBA_VERSION_VENDOR_SUFFIX ${SAMBA_VERSION_VENDOR_SUFFIX}" >> $OUTPUT_FILE +fi + +echo "#define SAMBA_VERSION_OFFICIAL_STRING \"${SAMBA_VERSION_STRING}\"" >> $OUTPUT_FILE + +echo "#define SAMBA_VERSION_STRING samba_version_string()" >> $OUTPUT_FILE + +echo "$0: 'include/version.h' created for Samba(\"${SAMBA_VERSION_STRING}\")" + +if test -n "${SAMBA_VERSION_VENDOR_SUFFIX}";then + echo "$0: with VENDOR_SUFFIX = ${SAMBA_VERSION_VENDOR_SUFFIX}" +fi + +exit 0 diff --git a/source3/smbadduser b/source3/smbadduser index 9837413aeb..35f6dbab14 100755 --- a/source3/smbadduser +++ b/source3/smbadduser @@ -2,13 +2,19 @@ # # smbadduser - Written by Mike Zakharoff # + +prefix=/usr/local/samba +exec_prefix=${prefix} +LIBDIR=${exec_prefix}/lib +PRIVATEDIR=${prefix}/private +CONFIGDIR=${LIBDIR} + unalias * set path = ($path /usr/local/samba/bin) -set smbpasswd = /usr/local/samba/private/smbpasswd -#set smbpasswd = /etc/samba/smbpasswd -set user_map = /usr/local/samba/lib/users.map -#set user_map = /etc/samba/smbusers +set smbpasswd = $PRIVATEDIR/smbpasswd +set user_map = $CONFIGDIR/users.map + # # Set to site specific passwd command # diff --git a/source3/smbadduser.in b/source3/smbadduser.in new file mode 100644 index 0000000000..05da7de08e --- /dev/null +++ b/source3/smbadduser.in @@ -0,0 +1,79 @@ +#!/bin/csh +# +# smbadduser - Written by Mike Zakharoff +# + +prefix=@prefix@ +exec_prefix=@exec_prefix@ +LIBDIR=@libdir@ +PRIVATEDIR=@privatedir@ +CONFIGDIR=@configdir@ + +unalias * +set path = ($path /usr/local/samba/bin) + +set smbpasswd = $PRIVATEDIR/smbpasswd +set user_map = $CONFIGDIR/users.map + +# +# Set to site specific passwd command +# +set passwd = "cat /etc/passwd" +#set passwd = "niscat passwd.org_dir" +#set passwd = "ypcat passwd" + +set line = "----------------------------------------------------------" +if ($#argv == 0) then + echo $line + echo "Written: Mike Zakharoff email: michael.j.zakharoff@boeing.com" + echo "" + echo " 1) Updates $smbpasswd" + echo " 2) Updates $user_map" + echo " 3) Executes smbpasswd for each new user" + echo "" + echo "smbadduser unixid:ntid unixid:ntid ..." + echo "" + echo "Example: smbadduser zak:zakharoffm johns:smithj" + echo $line + exit 1 +endif + +touch $smbpasswd $user_map +set new = () +foreach one ($argv) + echo $one | grep ':' >& /dev/null + if ($status != 0) then + echo "ERROR: Must use unixid:ntid like -> zak:zakharoffm" + continue + endif + set unix = `echo $one | awk -F: '{print $1}'` + set ntid = `echo $one | awk -F: '{print $2}'` + + set usr = `eval $passwd | awk -F: '$1==USR {print $1}' USR=$unix` + if ($#usr != 1) then + echo "ERROR: $unix Not in passwd database SKIPPING..." + continue + endif + set tmp = `cat $smbpasswd | awk -F: '$1==USR {print $1}' USR=$unix` + if ($#tmp != 0) then + echo "ERROR: $unix is already in $smbpasswd SKIPPING..." + continue + endif + + echo "Adding: $unix to $smbpasswd" + /usr/bin/smbpasswd -a -n $unix + if ($unix != $ntid) then + echo "Adding: {$unix = $ntid} to $user_map" + echo "$unix = $ntid" >> $user_map + endif + set new = ($new $unix) +end + +# +# Enter password for new users +# +foreach one ($new) + echo $line + echo "ENTER password for $one" + smbpasswd $one +end diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index fed3a51b88..8fa2a6494e 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -148,7 +148,7 @@ for fnum = %d, name = %s\n", length, (int)blr->expire_time, lock_timeout, blr->fsp->fnum, blr->fsp->fsp_name )); /* Push the MID of this packet on the signing queue. */ - srv_defer_sign_response(SVAL(inbuf,smb_mid)); + srv_defer_sign_response(SVAL(inbuf,smb_mid), True); return True; } diff --git a/source3/smbd/change_trust_pw.c b/source3/smbd/change_trust_pw.c index 2eff77b1f7..80c9fcb258 100644 --- a/source3/smbd/change_trust_pw.c +++ b/source3/smbd/change_trust_pw.c @@ -35,6 +35,9 @@ NTSTATUS change_trust_account_password( const char *domain, const char *remote_m fstring dc_name; struct cli_state *cli; + DEBUG(5,("change_trust_account_password: Attempting to change trust account password in domain %s....\n", + domain)); + if (remote_machine == NULL || !strcmp(remote_machine, "*")) { /* Use the PDC *only* for this */ @@ -92,6 +95,8 @@ failed: DEBUG(0,("%s : change_trust_account_password: Failed to change password for domain %s.\n", timestring(False), domain)); } + else + DEBUG(5,("change_trust_account_password: sucess!\n")); return nt_status; } diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 6bc8626d81..d99570ff7c 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -259,7 +259,7 @@ static int expect(int master, char *issue, char *expected) /* Eat leading/trailing whitespace before match. */ pstring str; pstrcpy( str, buffer); - trim_string( str, " ", " "); + trim_char( str, ' ', ' '); if ((match = (unix_wild_match(expected, str) == 0))) timeout = 200; @@ -333,19 +333,14 @@ static BOOL chat_with_program(char *passwordprogram, struct passwd *pass, int wstat; BOOL chstat = False; - if (pass == NULL) - { - DEBUG(0, - ("chat_with_program: user doesn't exist in the UNIX password database.\n")); + if (pass == NULL) { + DEBUG(0, ("chat_with_program: user doesn't exist in the UNIX password database.\n")); return False; } /* allocate a pseudo-terminal device */ - if ((master = findpty(&slavedev)) < 0) - { - DEBUG(3, - ("Cannot Allocate pty for password change: %s\n", - pass->pw_name)); + if ((master = findpty(&slavedev)) < 0) { + DEBUG(3, ("Cannot Allocate pty for password change: %s\n", pass->pw_name)); return (False); } @@ -356,39 +351,29 @@ static BOOL chat_with_program(char *passwordprogram, struct passwd *pass, CatchChildLeaveStatus(); - if ((pid = sys_fork()) < 0) - { - DEBUG(3, - ("Cannot fork() child for password change: %s\n", - pass->pw_name)); + if ((pid = sys_fork()) < 0) { + DEBUG(3, ("Cannot fork() child for password change: %s\n", pass->pw_name)); close(master); CatchChild(); return (False); } /* we now have a pty */ - if (pid > 0) - { /* This is the parent process */ - if ((chstat = talktochild(master, chatsequence)) == False) - { - DEBUG(3, - ("Child failed to change password: %s\n", - pass->pw_name)); + if (pid > 0) { /* This is the parent process */ + if ((chstat = talktochild(master, chatsequence)) == False) { + DEBUG(3, ("Child failed to change password: %s\n", pass->pw_name)); kill(pid, SIGKILL); /* be sure to end this process */ } - while ((wpid = sys_waitpid(pid, &wstat, 0)) < 0) - { - if (errno == EINTR) - { + while ((wpid = sys_waitpid(pid, &wstat, 0)) < 0) { + if (errno == EINTR) { errno = 0; continue; } break; } - if (wpid < 0) - { + if (wpid < 0) { DEBUG(3, ("The process is no longer waiting!\n\n")); close(master); CatchChild(); @@ -402,29 +387,21 @@ static BOOL chat_with_program(char *passwordprogram, struct passwd *pass, close(master); - if (pid != wpid) - { - DEBUG(3, - ("We were waiting for the wrong process ID\n")); + if (pid != wpid) { + DEBUG(3, ("We were waiting for the wrong process ID\n")); return (False); } - if (WIFEXITED(wstat) == 0) - { - DEBUG(3, - ("The process exited while we were waiting\n")); + if (WIFEXITED(wstat) == 0) { + DEBUG(3, ("The process exited while we were waiting\n")); return (False); } - if (WEXITSTATUS(wstat) != 0) - { - DEBUG(3, - ("The status of the process exiting was %d\n", + if (WEXITSTATUS(wstat) != 0) { + DEBUG(3, ("The status of the process exiting was %d\n", wstat)); return (False); } - } - else - { + } else { /* CHILD */ /* @@ -438,12 +415,9 @@ static BOOL chat_with_program(char *passwordprogram, struct passwd *pass, if (as_root) become_root(); - DEBUG(3, - ("Dochild for user %s (uid=%d,gid=%d)\n", pass->pw_name, - (int)getuid(), (int)getgid())); - chstat = - dochild(master, slavedev, pass, passwordprogram, - as_root); + DEBUG(3, ("Dochild for user %s (uid=%d,gid=%d) (as_root = %s)\n", pass->pw_name, + (int)getuid(), (int)getgid(), BOOLSTR(as_root) )); + chstat = dochild(master, slavedev, pass, passwordprogram, as_root); if (as_root) unbecome_root(); @@ -452,20 +426,16 @@ static BOOL chat_with_program(char *passwordprogram, struct passwd *pass, * The child should never return from dochild() .... */ - DEBUG(0, - ("chat_with_program: Error: dochild() returned %d\n", - chstat)); + DEBUG(0, ("chat_with_program: Error: dochild() returned %d\n", chstat)); exit(1); } if (chstat) - DEBUG(3, - ("Password change %ssuccessful for user %s\n", + DEBUG(3, ("Password change %ssuccessful for user %s\n", (chstat ? "" : "un"), pass->pw_name)); return (chstat); } - BOOL chgpasswd(const char *name, const char *oldpass, const char *newpass, BOOL as_root) { pstring passwordprogram; @@ -489,7 +459,7 @@ BOOL chgpasswd(const char *name, const char *oldpass, const char *newpass, BOOL oldpass = ""; } - DEBUG(3, ("Password change for user: %s\n", name)); + DEBUG(3, ("Password change (as_root=%s) for user: %s\n", BOOLSTR(as_root), name)); #if DEBUG_PASSWORD DEBUG(100, ("Passwords: old=%s new=%s\n", oldpass, newpass)); @@ -519,8 +489,7 @@ BOOL chgpasswd(const char *name, const char *oldpass, const char *newpass, BOOL len = strlen(oldpass); for (i = 0; i < len; i++) { if (iscntrl((int)oldpass[i])) { - DEBUG(0, - ("chat_with_program: oldpass contains control characters (disallowed).\n")); + DEBUG(0, ("chat_with_program: oldpass contains control characters (disallowed).\n")); return False; } } @@ -528,8 +497,7 @@ BOOL chgpasswd(const char *name, const char *oldpass, const char *newpass, BOOL len = strlen(newpass); for (i = 0; i < len; i++) { if (iscntrl((int)newpass[i])) { - DEBUG(0, - ("chat_with_program: newpass contains control characters (disallowed).\n")); + DEBUG(0, ("chat_with_program: newpass contains control characters (disallowed).\n")); return False; } } @@ -556,11 +524,8 @@ BOOL chgpasswd(const char *name, const char *oldpass, const char *newpass, BOOL /* A non-PAM password change just doen't make sense without a valid local user */ - if (pass == NULL) - { - DEBUG(0, - ("chgpasswd: user %s doesn't exist in the UNIX password database.\n", - name)); + if (pass == NULL) { + DEBUG(0, ("chgpasswd: user %s doesn't exist in the UNIX password database.\n", name)); return False; } @@ -746,7 +711,6 @@ NTSTATUS pass_oem_change(char *user, uchar * ntdata, uchar * nthash) { fstring new_passwd; - const char *unix_user; SAM_ACCOUNT *sampass = NULL; NTSTATUS nt_status = check_oem_password(user, lmdata, lmhash, ntdata, nthash, &sampass, new_passwd, sizeof(new_passwd)); @@ -754,20 +718,9 @@ NTSTATUS pass_oem_change(char *user, if (!NT_STATUS_IS_OK(nt_status)) return nt_status; - /* - * At this point we have the new case-sensitive plaintext - * password in the fstring new_passwd. If we wanted to synchronise - * with UNIX passwords we would call a UNIX password changing - * function here. However it would have to be done as root - * as the plaintext of the old users password is not - * available. JRA. - */ - - unix_user = pdb_get_username(sampass); - /* We've already checked the old password here.... */ become_root(); - nt_status = change_oem_password(sampass, NULL, new_passwd); + nt_status = change_oem_password(sampass, NULL, new_passwd, True); unbecome_root(); memset(new_passwd, 0, sizeof(new_passwd)); @@ -949,7 +902,7 @@ static NTSTATUS check_oem_password(const char *user, is correct before calling. JRA. ************************************************************/ -NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passwd) +NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passwd, BOOL as_root) { BOOL ret; uint32 min_len; @@ -993,7 +946,7 @@ NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passw */ if(lp_unix_password_sync() && - !chgpasswd(pdb_get_username(hnd), old_passwd, new_passwd, False)) { + !chgpasswd(pdb_get_username(hnd), old_passwd, new_passwd, as_root)) { return NT_STATUS_ACCESS_DENIED; } diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index 6be5f6af7d..6cf7014846 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -87,8 +87,11 @@ ssize_t read_file(files_struct *fsp,char *data,SMB_OFF_T pos,size_t n) * Serve from write cache if we can. */ - if(read_from_write_cache(fsp, data, pos, n)) + if(read_from_write_cache(fsp, data, pos, n)) { + fsp->pos = pos + n; + fsp->position_information = fsp->pos; return n; + } flush_write_cache(fsp, READ_FLUSH); @@ -123,6 +126,9 @@ tryagain: DEBUG(10,("read_file (%s): pos = %.0f, size = %lu, returned %lu\n", fsp->fsp_name, (double)pos, (unsigned long)n, (long)ret )); + fsp->pos += ret; + fsp->position_information = fsp->pos; + return(ret); } @@ -145,6 +151,16 @@ static ssize_t real_write_file(files_struct *fsp,char *data,SMB_OFF_T pos, size_ DEBUG(10,("real_write_file (%s): pos = %.0f, size = %lu, returned %ld\n", fsp->fsp_name, (double)pos, (unsigned long)n, (long)ret )); + if (ret != -1) { + fsp->pos += ret; + +/* Yes - this is correct - writes don't update this. JRA. */ +/* Found by Samba4 tests. */ +#if 0 + fsp->position_information = fsp->pos; +#endif + } + return ret; } @@ -244,7 +260,7 @@ nonop=%u allocated=%u active=%u direct=%u perfect=%u readhits=%u\n", if(!wcp) { DO_PROFILE_INC(writecache_direct_writes); total_written = real_write_file(fsp, data, pos, n); - if ((total_written != -1) && (pos + total_written > (SMB_OFF_T)fsp->size)) + if ((total_written != -1) && (pos + total_written > (SMB_OFF_T)fsp->size)) fsp->size = (SMB_BIG_UINT)(pos + total_written); return total_written; } @@ -252,6 +268,8 @@ nonop=%u allocated=%u active=%u direct=%u perfect=%u readhits=%u\n", DEBUG(9,("write_file (%s)(fd=%d pos=%.0f size=%u) wcp->offset=%.0f wcp->data_size=%u\n", fsp->fsp_name, fsp->fd, (double)pos, (unsigned int)n, (double)wcp->offset, (unsigned int)wcp->data_size)); + fsp->pos = pos + n; + /* * If we have active cache and it isn't contiguous then we flush. * NOTE: There is a small problem with running out of disk .... diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index ad107f9c3e..643e315c06 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -125,7 +125,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen * also trim trailing /'s. */ - trim_string(name,"/","/"); + trim_char(name,'/','/'); /* * If we trimmed down to a single '\0' character @@ -164,7 +164,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen return(True); start = name; - while (strncmp(start,"./",2) == 0) + while (start[0] == '.' && start[1] == '/') start += 2; pstrcpy(orig_path, name); diff --git a/source3/smbd/files.c b/source3/smbd/files.c index f0fd6b7a73..1fe6f250e5 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -142,6 +142,22 @@ void file_close_conn(connection_struct *conn) } } +/**************************************************************************** + Close all open files for a pid. +****************************************************************************/ + +void file_close_pid(uint16 smbpid) +{ + files_struct *fsp, *next; + + for (fsp=Files;fsp;fsp=next) { + next = fsp->next; + if (fsp->file_pid == smbpid) { + close_file(fsp,False); + } + } +} + /**************************************************************************** Initialise file structures. ****************************************************************************/ @@ -200,6 +216,18 @@ void file_close_user(int vuid) } } +void file_dump_open_table(void) +{ + int count=0; + files_struct *fsp; + + for (fsp=Files;fsp;fsp=fsp->next,count++) { + DEBUG(10,("Files[%d], fnum = %d, name %s, fd = %d, fileid = %lu, dev = %x, inode = %.0f\n", + count, fsp->fnum, fsp->fsp_name, fsp->fd, (unsigned long)fsp->file_id, + (unsigned int)fsp->dev, (double)fsp->inode )); + } +} + /**************************************************************************** Find a fsp given a file descriptor. ****************************************************************************/ diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index a5f7a7b2ea..b27ccc23ef 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -1706,13 +1706,24 @@ static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *para int uLevel = SVAL(p,0); const char *level_string; int count=0; + SAM_ACCOUNT *sampw = NULL; + BOOL ret = False; + DOM_GID *gids = NULL; + int num_groups = 0; + int i; + fstring grp_domain; + fstring grp_name; + enum SID_NAME_USE grp_type; + DOM_SID sid, dom_sid; *rparam_len = 8; *rparam = REALLOC(*rparam,*rparam_len); /* check it's a supported varient */ - if (!strcmp(str1,"zWrLeh")) + + if ( strcmp(str1,"zWrLeh") != 0 ) return False; + switch( uLevel ) { case 0: level_string = "B21"; @@ -1732,18 +1743,59 @@ static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *para p = *rdata; - /* XXXX we need a real SAM database some day */ - pstrcpy(p,"Users"); p += 21; count++; - pstrcpy(p,"Domain Users"); p += 21; count++; - pstrcpy(p,"Guests"); p += 21; count++; - pstrcpy(p,"Domain Guests"); p += 21; count++; + /* Lookup the user information; This should only be one of + our accounts (not remote domains) */ + + pdb_init_sam( &sampw ); + + become_root(); /* ROOT BLOCK */ + + if ( !pdb_getsampwnam(sampw, UserName) ) + goto out; + + /* this next set of code is horribly inefficient, but since + it is rarely called, I'm going to leave it like this since + it easier to follow --jerry */ + + /* get the list of group SIDs */ + + if ( !get_domain_user_groups(conn->mem_ctx, &num_groups, &gids, sampw) ) { + DEBUG(1,("api_NetUserGetGroups: get_domain_user_groups() failed!\n")); + goto out; + } + /* convert to names (we don't support universal groups so the domain + can only be ours) */ + + sid_copy( &dom_sid, get_global_sam_sid() ); + for (i=0; isam_account, pass1, pass2))) { + if (NT_STATUS_IS_OK(change_oem_password(server_info->sam_account, pass1, pass2, False))) { SSVAL(*rparam,0,NERR_Success); } unbecome_root(); @@ -1957,7 +2009,7 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param if (check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &hnd)) { become_root(); - if (change_lanman_password(hnd,pass2)) { + if (change_lanman_password(hnd,(uchar *)pass2)) { SSVAL(*rparam,0,NERR_Success); } unbecome_root(); @@ -1980,47 +2032,46 @@ static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char * char **rdata,char **rparam, int *rdata_len,int *rparam_len) { - fstring user; - char *p = param + 2; - *rparam_len = 2; - *rparam = REALLOC(*rparam,*rparam_len); + fstring user; + char *p = param + 2; + *rparam_len = 2; + *rparam = REALLOC(*rparam,*rparam_len); - *rdata_len = 0; + *rdata_len = 0; - SSVAL(*rparam,0,NERR_badpass); + SSVAL(*rparam,0,NERR_badpass); - /* - * Check the parameter definition is correct. - */ - if(!strequal(param + 2, "zsT")) { - DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", param + 2)); - return False; - } - p = skip_string(p, 1); + /* + * Check the parameter definition is correct. + */ - if(!strequal(p, "B516B16")) { - DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p)); - return False; - } - p = skip_string(p,1); + if(!strequal(param + 2, "zsT")) { + DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", param + 2)); + return False; + } + p = skip_string(p, 1); - p += pull_ascii_fstring(user,p); + if(!strequal(p, "B516B16")) { + DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p)); + return False; + } + p = skip_string(p,1); + p += pull_ascii_fstring(user,p); - DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user)); + DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user)); - /* - * Pass the user through the NT -> unix user mapping - * function. - */ + /* + * Pass the user through the NT -> unix user mapping + * function. + */ - (void)map_username(user); + (void)map_username(user); - if (NT_STATUS_IS_OK(pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL))) - { - SSVAL(*rparam,0,NERR_Success); - } + if (NT_STATUS_IS_OK(pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL))) { + SSVAL(*rparam,0,NERR_Success); + } - return(True); + return(True); } /**************************************************************************** diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index cdce28e1bd..9cd0438d51 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -201,22 +201,24 @@ static const char *cache_lookup(u32 hash) In this algorithm, mangled names use only pure ascii characters (no multi-byte) so we can avoid doing a UCS2 conversion */ -static BOOL is_mangled_component(const char *name) +static BOOL is_mangled_component(const char *name, size_t len) { - unsigned int len, i; + unsigned int i; - M_DEBUG(10,("is_mangled_component %s ?\n", name)); + M_DEBUG(10,("is_mangled_component %s (len %u) ?\n", name, (unsigned int)len)); /* check the length */ - len = strlen(name); - if (len > 12 || len < 8) return False; + if (len > 12 || len < 8) + return False; /* the best distinguishing characteristic is the ~ */ - if (name[6] != '~') return False; + if (name[6] != '~') + return False; /* check extension */ if (len > 8) { - if (name[8] != '.') return False; + if (name[8] != '.') + return False; for (i=9; name[i]; i++) { if (! FLAG_CHECK(name[i], FLAG_ASCII)) { return False; @@ -241,7 +243,7 @@ static BOOL is_mangled_component(const char *name) } } - M_DEBUG(10,("is_mangled %s -> yes\n", name)); + M_DEBUG(10,("is_mangled_component %s (len %u) -> yes\n", name, (unsigned int)len)); return True; } @@ -267,16 +269,13 @@ static BOOL is_mangled(const char *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)); - if (is_mangled_component(component)) { - free(component); + if (is_mangled_component(s, PTR_DIFF(p, s))) { return True; } - free(component); } /* and the last part ... */ - return is_mangled_component(s); + return is_mangled_component(s,strlen(s)); } @@ -305,7 +304,8 @@ static BOOL is_8_3(const char *name, BOOL check_case, BOOL allow_wildcards) the result we need in this case. Using strlen_m would not only be slower, it would be incorrect */ len = strlen(name); - if (len > 12) return False; + if (len > 12) + return False; /* find the '.'. Note that once again we use the non-multibyte function */ @@ -449,6 +449,27 @@ static BOOL is_legal_name(const char *name) size_t numdots = 0; while (*name) { + if (((unsigned int)name[0]) > 128 && (name[1] != 0)) { + /* Possible start of mb character. */ + char mbc[2]; + /* + * We know the following will return 2 bytes. What + * we need to know was if errno was set. + * Note that if CH_UNIX is utf8 a string may be 3 + * bytes, but this is ok as mb utf8 characters don't + * contain embedded ascii bytes. We are really checking + * for mb UNIX asian characters like Japanese (SJIS) here. + * JRA. + */ + errno = 0; + convert_string(CH_UNIX, CH_UCS2, name, 2, mbc, 2); + if (!errno) { + /* Was a good mb string. */ + name += 2; + continue; + } + } + if (FLAG_CHECK(name[0], FLAG_ILLEGAL)) { return False; } diff --git a/source3/smbd/message.c b/source3/smbd/message.c index 233848d2d6..88f833e468 100644 --- a/source3/smbd/message.c +++ b/source3/smbd/message.c @@ -64,7 +64,7 @@ static void msg_deliver(void) * Incoming message is in DOS codepage format. Convert to UNIX. */ - if ((len = convert_string_allocate(CH_DOS, CH_UNIX, msgbuf, msgpos, (void **) &msg)) < 0 || !msg) { + if ((len = convert_string_allocate(NULL,CH_DOS, CH_UNIX, msgbuf, msgpos, (void **) &msg)) < 0 || !msg) { DEBUG(3,("Conversion failed, delivering message in DOS codepage format\n")); for (i = 0; i < msgpos;) { if (msgbuf[i] == '\r' && i < (msgpos-1) && msgbuf[i+1] == '\n') { diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 9adf827c79..ca6f2b783f 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -199,7 +199,7 @@ BOOL change_notify_set(char *inbuf, files_struct *fsp, connection_struct *conn, DLIST_ADD(change_notify_list, cnbp); /* Push the MID of this packet on the signing queue. */ - srv_defer_sign_response(SVAL(inbuf,smb_mid)); + srv_defer_sign_response(SVAL(inbuf,smb_mid), True); return True; } diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 3ffa6efa77..f8bd3ae15f 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -762,9 +762,8 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib restore_case_semantics(file_attributes); if(!fsp) { - set_bad_path_error(errno, bad_path); END_PROFILE(SMBntcreateX); - return(UNIXERROR(ERRDOS,ERRnoaccess)); + return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess); } } else { /* @@ -838,16 +837,14 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib if(!fsp) { restore_case_semantics(file_attributes); - set_bad_path_error(errno, bad_path); END_PROFILE(SMBntcreateX); - return(UNIXERROR(ERRDOS,ERRnoaccess)); + return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess); } } else { restore_case_semantics(file_attributes); - set_bad_path_error(errno, bad_path); END_PROFILE(SMBntcreateX); - return(UNIXERROR(ERRDOS,ERRnoaccess)); + return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess); } } } @@ -1279,8 +1276,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o if(!fsp) { restore_case_semantics(file_attributes); - set_bad_path_error(errno, bad_path); - return(UNIXERROR(ERRDOS,ERRnoaccess)); + return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess); } } else { @@ -1312,13 +1308,11 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o if(!fsp) { restore_case_semantics(file_attributes); - set_bad_path_error(errno, bad_path); - return(UNIXERROR(ERRDOS,ERRnoaccess)); + return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess); } } else { restore_case_semantics(file_attributes); - set_bad_path_error(errno, bad_path); - return(UNIXERROR(ERRDOS,ERRnoaccess)); + return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess); } } @@ -1724,7 +1718,11 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou char **ppparams, uint32 parameter_count, char **ppdata, uint32 data_count) { - unsigned fnum, control; + uint32 function; + uint16 fidnum; + files_struct *fsp; + uint8 isFSctl; + uint8 compfilter; static BOOL logged_message; char *pdata = *ppdata; @@ -1733,19 +1731,26 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou return ERROR_NT(NT_STATUS_NOT_SUPPORTED); } - fnum = SVAL(*ppsetup, 4); - control = IVAL(*ppsetup, 0); + function = IVAL(*ppsetup, 0); + fidnum = SVAL(*ppsetup, 4); + isFSctl = CVAL(*ppsetup, 6); + compfilter = CVAL(*ppsetup, 7); + + DEBUG(10,("call_nt_transact_ioctl: function[0x%08X] FID[0x%04X] isFSctl[0x%02X] compfilter[0x%02X]\n", + function, fidnum, isFSctl, compfilter)); - DEBUG(10,("call_nt_transact_ioctl: fnum=%d control=0x%08x\n", - fnum, control)); + fsp=file_fsp(*ppsetup, 4); + /* this check is done in each implemented function case for now + because I don't want to break anything... --metze + FSP_BELONGS_CONN(fsp,conn);*/ - switch (control) { + switch (function) { case FSCTL_SET_SPARSE: /* pretend this succeeded - tho strictly we should mark the file sparse (if the local fs supports it) so we can know if we need to pre-allocate or not */ - DEBUG(10,("FSCTL_SET_SPARSE: fnum=%d control=0x%08x\n",fnum,control)); + DEBUG(10,("FSCTL_SET_SPARSE: called on FID[0x%04X](but not implemented)\n", fidnum)); send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL, 0); return -1; @@ -1754,7 +1759,7 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou but works ok like this --metze */ - DEBUG(10,("FSCTL_GET_REPARSE_POINT: fnum=%d control=0x%08x\n",fnum,control)); + DEBUG(10,("FSCTL_0x000900C0: called on FID[0x%04X](but not implemented)\n",fidnum)); send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL, 0); return -1; @@ -1763,7 +1768,7 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou * --metze */ - DEBUG(10,("FSCTL_GET_REPARSE_POINT: fnum=%d control=0x%08x\n",fnum,control)); + DEBUG(10,("FSCTL_GET_REPARSE_POINT: called on FID[0x%04X](but not implemented)\n",fidnum)); send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_NOT_A_REPARSE_POINT, NULL, 0, NULL, 0); return -1; @@ -1772,10 +1777,125 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou * --metze */ - DEBUG(10,("FSCTL_SET_REPARSE_POINT: fnum=%d control=0x%08x\n",fnum,control)); + DEBUG(10,("FSCTL_SET_REPARSE_POINT: called on FID[0x%04X](but not implemented)\n",fidnum)); send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_NOT_A_REPARSE_POINT, NULL, 0, NULL, 0); return -1; + case FSCTL_GET_SHADOW_COPY_DATA: /* don't know if this name is right...*/ + { + /* + * This is called to retrieve the number of Shadow Copies (a.k.a. snapshots) + * and return their volume names. If max_data_count is 16, then it is just + * asking for the number of volumes and length of the combined names. + * + * pdata is the data allocated by our caller, but that uses + * total_data_count (which is 0 in our case) rather than max_data_count. + * Allocate the correct amount and return the pointer to let + * it be deallocated when we return. + */ + uint32 max_data_count = IVAL(inbuf,smb_nt_MaxDataCount); + SHADOW_COPY_DATA *shadow_data = NULL; + TALLOC_CTX *shadow_mem_ctx = NULL; + BOOL labels = False; + uint32 labels_data_count = 0; + uint32 i; + char *cur_pdata; + + FSP_BELONGS_CONN(fsp,conn); + + if (max_data_count < 16) { + DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid!\n", + max_data_count)); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + + if (max_data_count > 16) { + labels = True; + } + + shadow_mem_ctx = talloc_init("SHADOW_COPY_DATA"); + if (shadow_mem_ctx == NULL) { + DEBUG(0,("talloc_init(SHADOW_COPY_DATA) failed!\n")); + return ERROR_NT(NT_STATUS_NO_MEMORY); + } + + shadow_data = (SHADOW_COPY_DATA *)talloc_zero(shadow_mem_ctx,sizeof(SHADOW_COPY_DATA)); + if (shadow_data == NULL) { + DEBUG(0,("talloc_zero() failed!\n")); + return ERROR_NT(NT_STATUS_NO_MEMORY); + } + + shadow_data->mem_ctx = shadow_mem_ctx; + + /* + * Call the VFS routine to actually do the work. + */ + if (SMB_VFS_GET_SHADOW_COPY_DATA(fsp, shadow_data, labels)!=0) { + talloc_destroy(shadow_data->mem_ctx); + if (errno == ENOSYS) { + DEBUG(5,("FSCTL_GET_SHADOW_COPY_DATA: connectpath %s, not supported.\n", + conn->connectpath)); + return ERROR_NT(NT_STATUS_NOT_SUPPORTED); + } else { + DEBUG(0,("FSCTL_GET_SHADOW_COPY_DATA: connectpath %s, failed.\n", + conn->connectpath)); + return ERROR_NT(NT_STATUS_UNSUCCESSFUL); + } + } + + labels_data_count = (shadow_data->num_volumes*2*sizeof(SHADOW_COPY_LABEL))+2; + + if (!labels) { + data_count = 16; + } else { + data_count = 12+labels_data_count+4; + } + + if (max_data_countmem_ctx); + return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL); + } + + pdata = nttrans_realloc(ppdata, data_count); + if (pdata == NULL) { + talloc_destroy(shadow_data->mem_ctx); + return ERROR_NT(NT_STATUS_NO_MEMORY); + } + + cur_pdata = pdata; + + /* num_volumes 4 bytes */ + SIVAL(pdata,0,shadow_data->num_volumes); + + if (labels) { + /* num_labels 4 bytes */ + SIVAL(pdata,4,shadow_data->num_volumes); + } + + /* needed_data_count 4 bytes */ + SIVAL(pdata,8,labels_data_count); + + cur_pdata+=12; + + DEBUG(10,("FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s].\n", + shadow_data->num_volumes,fsp->fsp_name)); + if (labels && shadow_data->labels) { + for (i=0;inum_volumes;i++) { + srvstr_push(outbuf, cur_pdata, shadow_data->labels[i], 2*sizeof(SHADOW_COPY_LABEL), STR_UNICODE|STR_TERMINATE); + cur_pdata+=2*sizeof(SHADOW_COPY_LABEL); + DEBUGADD(10,("Label[%u]: '%s'\n",i,shadow_data->labels[i])); + } + } + + talloc_destroy(shadow_data->mem_ctx); + + send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0, pdata, data_count); + + return -1; + } + case FSCTL_FIND_FILES_BY_SID: /* I hope this name is right */ { /* pretend this succeeded - @@ -1783,24 +1903,24 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou * we have to send back a list with all files owned by this SID * * but I have to check that --metze - */ - + */ DOM_SID sid; uid_t uid; - size_t sid_len=SID_MAX_SIZE; - - DEBUG(10,("FSCTL_FIND_FILES_BY_SID: fnum=%d control=0x%08x\n",fnum,control)); + size_t sid_len = MIN(data_count-4,SID_MAX_SIZE); - /* this is not the length of the sid :-( so unknown 4 bytes */ - /*sid_len = IVAL(pdata,0); - DEBUGADD(0,("sid_len: (%u)\n",sid_len));*/ + DEBUG(10,("FSCTL_FIND_FILES_BY_SID: called on FID[0x%04X]\n",fidnum)); + + FSP_BELONGS_CONN(fsp,conn); + + /* unknown 4 bytes: this is not the length of the sid :-( */ + /*unknown = IVAL(pdata,0);*/ sid_parse(pdata+4,sid_len,&sid); - DEBUGADD(10,("SID: %s\n",sid_string_static(&sid))); + DEBUGADD(10,("for SID: %s\n",sid_string_static(&sid))); if (!NT_STATUS_IS_OK(sid_to_uid(&sid, &uid))) { - DEBUG(0,("sid_to_uid: failed, sid[%s]\n", - sid_string_static(&sid))); + DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%u]\n", + sid_string_static(&sid),sid_len)); uid = (-1); } @@ -1813,6 +1933,7 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou * for each file * * but I don't know how to deal with the paged results + * (maybe we can hang the result anywhere in the fsp struct) * * we don't send all files at once * and at the next we should *not* start from the beginning, @@ -1829,7 +1950,7 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou if (!logged_message) { logged_message = True; /* Only print this once... */ DEBUG(0,("call_nt_transact_ioctl(0x%x): Currently not implemented.\n", - control)); + function)); } } diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 5f49640aa4..71af23aaf9 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -23,6 +23,7 @@ extern userdom_struct current_user_info; extern uint16 global_oplock_port; +extern uint16 global_smbpid; extern BOOL global_client_failed_oplock_break; /**************************************************************************** @@ -226,8 +227,8 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, fsp->inode = psbuf->st_ino; fsp->dev = psbuf->st_dev; fsp->vuid = current_user.vuid; + fsp->file_pid = global_smbpid; fsp->size = psbuf->st_size; - fsp->pos = -1; fsp->can_lock = True; fsp->can_read = ((flags & O_WRONLY)==0); fsp->can_write = ((flags & (O_WRONLY|O_RDWR))!=0); @@ -626,6 +627,12 @@ static int open_mode_check(connection_struct *conn, const char *fname, SMB_DEV_T DEBUG(5,("open_mode_check: oplock_request = %d, breaking oplock (%x) on file %s, \ dev = %x, inode = %.0f\n", *p_oplock_request, share_entry->op_type, fname, (unsigned int)dev, (double)inode)); + /* Ensure the reply for the open uses the correct sequence number. */ + /* This isn't a real deferred packet as it's response will also increment + * the sequence. + */ + srv_defer_sign_response(get_current_mid(), False); + /* Oplock break - unlock to request it. */ unlock_share_entry(conn, dev, inode); @@ -1356,7 +1363,7 @@ files_struct *open_directory(connection_struct *conn, char *fname, SMB_STRUCT_ST fsp->dev = psbuf->st_dev; fsp->size = psbuf->st_size; fsp->vuid = current_user.vuid; - fsp->pos = -1; + fsp->file_pid = global_smbpid; fsp->can_lock = True; fsp->can_read = False; fsp->can_write = False; @@ -1419,7 +1426,7 @@ files_struct *open_file_stat(connection_struct *conn, char *fname, SMB_STRUCT_ST fsp->dev = (SMB_DEV_T)0; fsp->size = psbuf->st_size; fsp->vuid = current_user.vuid; - fsp->pos = -1; + fsp->file_pid = global_smbpid; fsp->can_lock = False; fsp->can_read = False; fsp->can_write = False; diff --git a/source3/smbd/password.c b/source3/smbd/password.c index b988f2ec74..32c24b3d67 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -28,6 +28,9 @@ static user_struct *validated_users; static int next_vuid = VUID_OFFSET; static int num_validated_vuids; +extern userdom_struct current_user_info; + + /**************************************************************************** Check if a uid has been validated, and return an pointer to the user_struct if it has. NULL if not. vuid is biased by an offset. This allows us to @@ -296,7 +299,7 @@ BOOL user_ok(const char *user,int snum, gid_t *groups, size_t n_groups) if (ret && lp_valid_users(snum)) { str_list_copy(&valid, lp_valid_users(snum)); - if (valid && str_list_substitute(valid, "%S", lp_servicename(snum))) { + if ( valid && str_list_sub_basic(valid, current_user_info.smb_name) ) { ret = user_in_list(user, (const char **)valid, groups, n_groups); } } diff --git a/source3/smbd/process.c b/source3/smbd/process.c index dce1c4bc03..3c15cd1833 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -47,6 +47,15 @@ SIG_ATOMIC_T got_sig_term = 0; BOOL global_machine_password_needs_changing = False; extern int max_send; +/**************************************************************************** + Function to return the current request mid from Inbuffer. +****************************************************************************/ + +uint16 get_current_mid(void) +{ + return SVAL(InBuffer,smb_mid); +} + /**************************************************************************** structure to hold a linked list of queued messages. for processing. @@ -88,7 +97,7 @@ static BOOL push_message(ubi_slList *list_head, char *buf, int msg_len) ubi_slAddTail( list_head, msg); /* Push the MID of this packet on the signing queue. */ - srv_defer_sign_response(SVAL(buf,smb_mid)); + srv_defer_sign_response(SVAL(buf,smb_mid), True); return True; } @@ -710,7 +719,7 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize if(session_tag != UID_FIELD_INVALID) vuser = get_valid_user_struct(session_tag); if(vuser != NULL) - current_user_info = vuser->user; + set_current_user_info(&vuser->user); } /* does this protocol need to be run as root? */ @@ -1256,8 +1265,10 @@ void smbd_process(void) if ((InBuffer == NULL) || (OutBuffer == NULL)) return; +#if defined(DEVELOPER) clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, InBuffer, total_buffer_size); clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, OutBuffer, total_buffer_size); +#endif max_recv = MIN(lp_maxxmit(),BUFFER_SIZE); @@ -1286,7 +1297,9 @@ void smbd_process(void) num_smbs = 0; /* Reset smb counter. */ } +#if defined(DEVELOPER) clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, InBuffer, total_buffer_size); +#endif while (!receive_message_or_smb(InBuffer,BUFFER_SIZE+LARGE_WRITEX_HDR_SIZE,select_timeout)) { if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time)) diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 71312295f4..6ac4cffddb 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -38,6 +38,21 @@ unsigned int smb_echo_count = 0; extern BOOL global_encrypted_passwords_negotiated; +/**************************************************************************** + Ensure we check the path in the same way as W2K. +****************************************************************************/ + +static NTSTATUS check_path_syntax(const char *name) +{ + while (*name == '\\') + name++; + if (strequal(name, ".")) + return NT_STATUS_OBJECT_NAME_INVALID; + else if (strequal(name, "..")) + return NT_STATUS_OBJECT_PATH_SYNTAX_BAD; + return NT_STATUS_OK; +} + /**************************************************************************** Reply to a special message. ****************************************************************************/ @@ -333,7 +348,6 @@ int reply_ioctl(connection_struct *conn, uint32 ioctl_code = (device << 16) + function; int replysize, outsize; char *p; - files_struct *fsp = file_fsp(inbuf,smb_vwv0); START_PROFILE(SMBioctl); DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code)); @@ -356,6 +370,11 @@ int reply_ioctl(connection_struct *conn, switch (ioctl_code) { case IOCTL_QUERY_JOB_INFO: { + files_struct *fsp = file_fsp(inbuf,smb_vwv0); + if (!fsp) { + END_PROFILE(SMBioctl); + return(UNIXERROR(ERRDOS,ERRbadfid)); + } SSVAL(p,0,fsp->rap_print_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); @@ -379,10 +398,16 @@ int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size BOOL ok = False; BOOL bad_path = False; SMB_STRUCT_STAT sbuf; + NTSTATUS status; + START_PROFILE(SMBchkpth); srvstr_pull_buf(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), STR_TERMINATE); + status = check_path_syntax(name); + if (!NT_STATUS_IS_OK(status)) + return ERROR_NT(status); + RESOLVE_DFSPATH(name, conn, inbuf, outbuf); unix_convert(name,conn,0,&bad_path,&sbuf); @@ -401,8 +426,21 @@ int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size 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(errno == ENOENT) { + /* + * Windows returns different error codes if + * the parent directory is valid but not the + * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND + * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND + * if the path is invalid. + */ + if (bad_path) { + return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); + } else { + return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND); + } + } else if (errno == ENOTDIR) + return ERROR_NT(NT_STATUS_NOT_A_DIRECTORY); return(UNIXERROR(ERRDOS,ERRbadpath)); } @@ -463,9 +501,8 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size } if (!ok) { - set_bad_path_error(errno, bad_path); END_PROFILE(SMBgetatr); - return(UNIXERROR(ERRDOS,ERRbadfile)); + return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadfile); } outsize = set_message(outbuf,10,0,True); @@ -510,20 +547,24 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size mode = SVAL(inbuf,smb_vwv0); mtime = make_unix_date3(inbuf+smb_vwv1); - if (VALID_STAT_OF_DIR(sbuf)) - mode |= aDIR; - else - mode &= ~aDIR; + if (mode != FILE_ATTRIBUTE_NORMAL) { + if (VALID_STAT_OF_DIR(sbuf)) + mode |= aDIR; + else + mode &= ~aDIR; + + if (check_name(fname,conn)) + ok = (file_chmod(conn,fname,mode,NULL) == 0); + } else { + ok = True; + } - if (check_name(fname,conn)) - ok = (file_chmod(conn,fname,mode,NULL) == 0); if (ok) ok = set_filetime(conn,fname,mtime); if (!ok) { - set_bad_path_error(errno, bad_path); END_PROFILE(SMBsetatr); - return(UNIXERROR(ERRDOS,ERRnoaccess)); + return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess); } outsize = set_message(outbuf,0,0,True); @@ -684,9 +725,8 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid)); if (dptr_num < 0) { if(dptr_num == -2) { - set_bad_path_error(errno, bad_path); END_PROFILE(SMBsearch); - return (UNIXERROR(ERRDOS,ERRnofids)); + return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnofids); } END_PROFILE(SMBsearch); return ERROR_DOS(ERRDOS,ERRnofids); @@ -732,21 +772,23 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size SearchEmpty: - if (numentries == 0 || !ok) { - SCVAL(outbuf,smb_rcls,ERRDOS); - SSVAL(outbuf,smb_err,ERRnofiles); - dptr_close(&dptr_num); - } - /* If we were called as SMBffirst with smb_search_id == NULL and no entries were found then return error and close dirptr (X/Open spec) */ if(ok && expect_close && numentries == 0 && status_len == 0) { - SCVAL(outbuf,smb_rcls,ERRDOS); - SSVAL(outbuf,smb_err,ERRnofiles); + if (Protocol < PROTOCOL_NT1) { + SCVAL(outbuf,smb_rcls,ERRDOS); + SSVAL(outbuf,smb_err,ERRnofiles); + } /* Also close the dptr - we know it's gone */ dptr_close(&dptr_num); + } else if (numentries == 0 || !ok) { + if (Protocol < PROTOCOL_NT1) { + SCVAL(outbuf,smb_rcls,ERRDOS); + SSVAL(outbuf,smb_err,ERRnofiles); + } + dptr_close(&dptr_num); } /* If we were called as SMBfunique, then we can close the dirptr now ! */ @@ -851,9 +893,8 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, unixmode, oplock_request,&rmode,NULL); if (!fsp) { - set_bad_path_error(errno, bad_path); END_PROFILE(SMBopen); - return(UNIXERROR(ERRDOS,ERRnoaccess)); + return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess); } size = sbuf.st_size; @@ -939,9 +980,8 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt oplock_request, &rmode,&smb_action); if (!fsp) { - set_bad_path_error(errno, bad_path); END_PROFILE(SMBopenX); - return(UNIXERROR(ERRDOS,ERRnoaccess)); + return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess); } size = sbuf.st_size; @@ -1063,9 +1103,8 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, ofun, unixmode, oplock_request, NULL, NULL); if (!fsp) { - set_bad_path_error(errno, bad_path); END_PROFILE(SMBcreate); - return(UNIXERROR(ERRDOS,ERRnoaccess)); + return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess); } outsize = set_message(outbuf,1,0,True); @@ -1132,9 +1171,8 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, close(tmpfd); if (!fsp) { - set_bad_path_error(errno, bad_path); END_PROFILE(SMBctemp); - return(UNIXERROR(ERRDOS,ERRnoaccess)); + return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess); } outsize = set_message(outbuf,1,0,True); @@ -1215,6 +1253,9 @@ static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype) int access_mode; files_struct *fsp; + DEBUG(10,("can_delete: %s, dirtype = %d\n", + fname, dirtype )); + if (!CAN_WRITE(conn)) return NT_STATUS_MEDIA_WRITE_PROTECTED; @@ -1222,14 +1263,21 @@ static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype) return NT_STATUS_OBJECT_NAME_NOT_FOUND; fmode = dos_mode(conn,fname,&sbuf); + + /* Can't delete a directory. */ if (fmode & aDIR) return NT_STATUS_FILE_IS_A_DIRECTORY; +#if 0 /* JRATEST */ + else if (dirtype & aDIR) /* Asked for a directory and it isn't. */ + return NT_STATUS_OBJECT_NAME_INVALID; +#endif /* JRATEST */ + if (!lp_delete_readonly(SNUM(conn))) { if (fmode & aRONLY) return NT_STATUS_CANNOT_DELETE; } if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) - return NT_STATUS_CANNOT_DELETE; + return NT_STATUS_NO_SUCH_FILE; /* We need a better way to return NT status codes from open... */ unix_ERR_class = 0; @@ -1329,7 +1377,7 @@ NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name) */ if (dirptr) { - error = NT_STATUS_OBJECT_NAME_NOT_FOUND; + error = NT_STATUS_NO_SUCH_FILE; if (strequal(mask,"????????.???")) pstrcpy(mask,"*"); @@ -1377,6 +1425,10 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size srvstr_pull_buf(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), STR_TERMINATE); + status = check_path_syntax(name); + if (!NT_STATUS_IS_OK(status)) + return ERROR_NT(status); + RESOLVE_DFSPATH(name, conn, inbuf, outbuf); DEBUG(3,("reply_unlink : %s\n",name)); @@ -2262,39 +2314,25 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int switch (mode) { case 0: umode = SEEK_SET; + res = startpos; break; case 1: umode = SEEK_CUR; + res = fsp->pos + startpos; break; case 2: umode = SEEK_END; break; default: umode = SEEK_SET; + res = startpos; break; } - if((res = SMB_VFS_LSEEK(fsp,fsp->fd,startpos,umode)) == -1) { - /* - * Check for the special case where a seek before the start - * of the file sets the offset to zero. Added in the CIFS spec, - * section 4.2.7. - */ - - if(errno == EINVAL) { - SMB_OFF_T current_pos = startpos; - - if(umode == SEEK_CUR) { - - if((current_pos = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_CUR)) == -1) { - END_PROFILE(SMBlseek); - return(UNIXERROR(ERRDOS,ERRnoaccess)); - } - - current_pos += startpos; - - } else if (umode == SEEK_END) { - + if (umode == SEEK_END) { + if((res = SMB_VFS_LSEEK(fsp,fsp->fd,startpos,umode)) == -1) { + if(errno == EINVAL) { + SMB_OFF_T current_pos = startpos; SMB_STRUCT_STAT sbuf; if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1) { @@ -2303,10 +2341,9 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int } current_pos += sbuf.st_size; + if(current_pos < 0) + res = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_SET); } - - if(current_pos < 0) - res = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_SET); } if(res == -1) { @@ -2334,10 +2371,12 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize) { int outsize = set_message(outbuf,0,0,True); + uint16 fnum = SVAL(inbuf,smb_vwv0); files_struct *fsp = file_fsp(inbuf,smb_vwv0); START_PROFILE(SMBflush); - CHECK_FSP(fsp,conn); + if (fnum != 0xFFFF) + CHECK_FSP(fsp,conn); if (!fsp) { file_sync_all(conn); @@ -2359,6 +2398,9 @@ int reply_exit(connection_struct *conn, { int outsize; START_PROFILE(SMBexit); + + file_close_pid(SVAL(inbuf,smb_pid)); + outsize = set_message(outbuf,0,0,True); DEBUG(3,("exit\n")); @@ -2704,7 +2746,7 @@ int reply_printclose(connection_struct *conn, if (!CAN_PRINT(conn)) { END_PROFILE(SMBsplclose); - return ERROR_DOS(ERRDOS,ERRnoaccess); + return ERROR_NT(NT_STATUS_UNSUCCESSFUL); } DEBUG(3,("printclose fd=%d fnum=%d\n", @@ -2849,7 +2891,17 @@ NTSTATUS mkdir_internal(connection_struct *conn, pstring directory) ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory)); if (ret == -1) { - NTSTATUS nterr = set_bad_path_error(errno, bad_path); + NTSTATUS nterr = NT_STATUS_OK; + if(errno == ENOENT) { + unix_ERR_class = ERRDOS; + if (bad_path) { + unix_ERR_code = ERRbadpath; + nterr = NT_STATUS_OBJECT_PATH_NOT_FOUND; + } else { + unix_ERR_code = ERRbadfile; + nterr = NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + } if (!NT_STATUS_IS_OK(nterr)) return nterr; return map_nt_error_from_unix(errno); @@ -3044,9 +3096,8 @@ int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, } if (!ok) { - set_bad_path_error(errno, bad_path); END_PROFILE(SMBrmdir); - return(UNIXERROR(ERRDOS,ERRbadpath)); + return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRbadpath); } outsize = set_message(outbuf,0,0,True); @@ -3129,6 +3180,130 @@ static BOOL resolve_wildcards(const char *name1, char *name2) return(True); } +/**************************************************************************** + Ensure open files have their names updates. +****************************************************************************/ + +static void rename_open_files(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode, char *newname) +{ + files_struct *fsp; + BOOL did_rename = False; + + for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) { + DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n", + fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode, + fsp->fsp_name, newname )); + string_set(&fsp->fsp_name, newname); + did_rename = True; + } + + if (!did_rename) + DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n", + (unsigned int)dev, (double)inode, newname )); +} + +/**************************************************************************** + Rename an open file - given an fsp. +****************************************************************************/ + +NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, BOOL replace_if_exists) +{ + SMB_STRUCT_STAT sbuf; + BOOL bad_path = False; + pstring newname_last_component; + NTSTATUS error = NT_STATUS_OK; + BOOL dest_exists; + + ZERO_STRUCT(sbuf); + unix_convert(newname,conn,newname_last_component,&bad_path,&sbuf); + + /* Ensure newname contains a '/' */ + if(strrchr_m(newname,'/') == 0) { + pstring tmpstr; + + pstrcpy(tmpstr, "./"); + pstrcat(tmpstr, newname); + pstrcpy(newname, tmpstr); + } + + /* + * Check for special case with case preserving and not + * case sensitive. If the old last component differs from the original + * last component only by case, then we should allow + * the rename (user is trying to change the case of the + * filename). + */ + + if((case_sensitive == False) && (case_preserve == True) && + strequal(newname, fsp->fsp_name)) { + char *p; + pstring newname_modified_last_component; + + /* + * Get the last component of the modified name. + * Note that we guarantee that newname contains a '/' + * character above. + */ + p = strrchr_m(newname,'/'); + pstrcpy(newname_modified_last_component,p+1); + + if(strcsequal(newname_modified_last_component, + newname_last_component) == False) { + /* + * Replace the modified last component with + * the original. + */ + pstrcpy(p+1, newname_last_component); + } + } + + /* + * If the src and dest names are identical - including case, + * don't do the rename, just return success. + */ + + if (strcsequal(fsp->fsp_name, newname)) { + DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n", + newname)); + return NT_STATUS_OK; + } + + dest_exists = vfs_object_exist(conn,newname,NULL); + + if(!replace_if_exists && dest_exists) { + DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n", + fsp->fsp_name,newname)); + return NT_STATUS_OBJECT_NAME_COLLISION; + } + + error = can_rename(newname,conn,&sbuf); + + if (dest_exists && !NT_STATUS_IS_OK(error)) { + DEBUG(3,("rename_internals: Error %s rename %s -> %s\n", + nt_errstr(error), fsp->fsp_name,newname)); + if (NT_STATUS_EQUAL(error,NT_STATUS_SHARING_VIOLATION)) + error = NT_STATUS_ACCESS_DENIED; + return error; + } + + if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) { + DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n", + fsp->fsp_name,newname)); + rename_open_files(conn, fsp->dev, fsp->inode, newname); + return NT_STATUS_OK; + } + + if (errno == ENOTDIR || errno == EISDIR) + error = NT_STATUS_OBJECT_NAME_COLLISION; + else + error = map_nt_error_from_unix(errno); + + DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n", + nt_errstr(error), fsp->fsp_name,newname)); + + return error; +} + /**************************************************************************** The guts of the rename command, split out so it may be called by the NT SMB code. @@ -3150,6 +3325,8 @@ NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, BO *directory = *mask = 0; + ZERO_STRUCT(sbuf1); + ZERO_STRUCT(sbuf2); rc = unix_convert(name,conn,0,&bad_path1,&sbuf1); unix_convert(newname,conn,newname_last_component,&bad_path2,&sbuf2); @@ -3290,6 +3467,7 @@ directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n", */ if (strcsequal(directory, newname)) { + rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname); DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory)); return NT_STATUS_OK; } @@ -3303,6 +3481,7 @@ directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n", if(SMB_VFS_RENAME(conn,directory, newname) == 0) { DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n", directory,newname)); + rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname); return NT_STATUS_OK; } @@ -3367,8 +3546,10 @@ directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n", continue; } - if (!SMB_VFS_RENAME(conn,fname,destname)) + if (!SMB_VFS_RENAME(conn,fname,destname)) { + rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname); count++; + } DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname)); } CloseDir(dirptr); diff --git a/source3/smbd/sec_ctx.c b/source3/smbd/sec_ctx.c index 411ece5249..8a85792ead 100644 --- a/source3/smbd/sec_ctx.c +++ b/source3/smbd/sec_ctx.c @@ -199,7 +199,7 @@ BOOL initialise_groups(char *user, uid_t uid, gid_t gid) /* Call initgroups() to get user groups */ - if (initgroups(user,gid) == -1) { + if (winbind_initgroups(user,gid) == -1) { DEBUG(0,("Unable to initgroups. Error was %s\n", strerror(errno) )); if (getuid() == 0) { if (gid < 0 || gid > 32767 || uid < 0 || uid > 32767) { diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 453ff54e4b..8b890549ea 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -744,7 +744,7 @@ void build_options(BOOL screen); reopen_logs(); - DEBUG(0,( "smbd version %s started.\n", VERSION)); + DEBUG(0,( "smbd version %s started.\n", SAMBA_VERSION_STRING)); DEBUGADD(0,( "Copyright Andrew Tridgell and the Samba Team 1992-2003\n")); DEBUG(2,("uid=%d gid=%d euid=%d egid=%d\n", diff --git a/source3/smbd/service.c b/source3/smbd/service.c index c2855487a5..70126b9e7f 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -273,7 +273,7 @@ static void set_read_only(connection_struct *conn, gid_t *groups, size_t n_group str_list_copy(&list, lp_readlist(conn->service)); if (list) { - if (!str_list_substitute(list, "%S", service)) { + if ( !str_list_sub_basic(list, current_user_info.smb_name) ) { DEBUG(0, ("ERROR: read list substitution failed\n")); } if (user_in_list(conn->user, (const char **)list, groups, n_groups)) @@ -283,7 +283,7 @@ static void set_read_only(connection_struct *conn, gid_t *groups, size_t n_group str_list_copy(&list, lp_writelist(conn->service)); if (list) { - if (!str_list_substitute(list, "%S", service)) { + if ( !str_list_sub_basic(list, current_user_info.smb_name) ) { DEBUG(0, ("ERROR: write list substitution failed\n")); } if (user_in_list(conn->user, (const char **)list, groups, n_groups)) @@ -642,6 +642,10 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, return NULL; } } + +#ifdef WITH_FAKE_KASERVER + afs_login(user); +#endif #if CHECK_PATH_ON_TCONX /* win2000 does not check the permissions on the directory @@ -691,6 +695,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, if( DEBUGLVL( IS_IPC(conn) ? 3 : 1 ) ) { dbgtext( "%s (%s) ", get_remote_machine_name(), conn->client_address ); + dbgtext( "%s", srv_is_signing_active() ? "signed " : ""); dbgtext( "connect to service %s ", lp_servicename(SNUM(conn)) ); dbgtext( "initially as user %s ", user ); dbgtext( "(uid=%d, gid=%d) ", (int)geteuid(), (int)getegid() ); diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 88b442215d..427caa3ba1 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -62,7 +62,7 @@ static int add_signature(char *outbuf, char *p) char *start = p; fstring lanman; - fstr_sprintf( lanman, "Samba %s", VERSION ); + fstr_sprintf( lanman, "Samba %s", SAMBA_VERSION_STRING); p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE); p += srvstr_push(outbuf, p, lanman, -1, STR_TERMINATE); @@ -149,7 +149,6 @@ static int reply_spnego_kerberos(connection_struct *conn, DATA_BLOB auth_data; DATA_BLOB ap_rep, ap_rep_wrapped, response; auth_serversupplied_info *server_info = NULL; - ADS_STRUCT *ads; uint8 session_key[16]; uint8 tok_id[2]; BOOL foreign = False; @@ -165,18 +164,12 @@ static int reply_spnego_kerberos(connection_struct *conn, return ERROR_NT(NT_STATUS_LOGON_FAILURE); } - ads = ads_init_simple(); + ret = ads_verify_ticket(lp_realm(), &ticket, &client, &auth_data, &ap_rep, session_key); - if (!ads) { - return ERROR_NT(NT_STATUS_LOGON_FAILURE); - } + data_blob_free(&ticket); - ads->auth.realm = strdup(lp_realm()); - - ret = ads_verify_ticket(ads, &ticket, &client, &auth_data, &ap_rep, session_key); if (!NT_STATUS_IS_OK(ret)) { DEBUG(1,("Failed to verify incoming ticket!\n")); - ads_destroy(&ads); return ERROR_NT(NT_STATUS_LOGON_FAILURE); } @@ -187,16 +180,17 @@ static int reply_spnego_kerberos(connection_struct *conn, p = strchr_m(client, '@'); if (!p) { DEBUG(3,("Doesn't look like a valid principal\n")); - ads_destroy(&ads); data_blob_free(&ap_rep); + SAFE_FREE(client); return ERROR_NT(NT_STATUS_LOGON_FAILURE); } *p = 0; - if (strcasecmp(p+1, ads->auth.realm) != 0) { + if (strcasecmp(p+1, lp_realm()) != 0) { DEBUG(3,("Ticket for foreign realm %s@%s\n", client, p+1)); if (!lp_allow_trusted_domains()) { data_blob_free(&ap_rep); + SAFE_FREE(client); return ERROR_NT(NT_STATUS_LOGON_FAILURE); } foreign = True; @@ -213,7 +207,7 @@ static int reply_spnego_kerberos(connection_struct *conn, user = smb_xstrdup(client); } - ads_destroy(&ads); + SAFE_FREE(client); /* setup the string used by %U */ sub_set_smb_name(user); @@ -223,7 +217,7 @@ static int reply_spnego_kerberos(connection_struct *conn, if (!pw) { DEBUG(1,("Username %s is invalid on this system\n",user)); data_blob_free(&ap_rep); - return ERROR_NT(NT_STATUS_NO_SUCH_USER); + return ERROR_NT(NT_STATUS_LOGON_FAILURE); } if (!NT_STATUS_IS_OK(ret = make_server_info_pw(&server_info,pw))) { diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index fbebdb240f..948173687d 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -66,11 +66,12 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat return; /* - * Don't cache trivial valid directory entries. + * Don't cache trivial valid directory entries such as . and .. */ - if((*full_orig_name == '\0') || (strcmp(full_orig_name, ".") == 0) || - (strcmp(full_orig_name, "..") == 0)) + if((*full_orig_name == '\0') || (full_orig_name[0] == '.' && + ((full_orig_name[1] == '\0') || + (full_orig_name[1] == '.' && full_orig_name[1] == '\0')))) return; /* @@ -216,10 +217,10 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, /* * Don't lookup trivial valid directory entries. */ - if((*name == '\0') || (strcmp(name, ".") == 0) || (strcmp(name, "..") == 0)) { - DO_PROFILE_INC(statcache_misses); + if((*name == '\0') || (name[0] == '.' && + ((name[1] == '\0') || + (name[1] == '.' && name[1] == '\0')))) return False; - } if (case_sensitive) { chk_name = strdup(name); @@ -247,6 +248,7 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, while (1) { hash_elem = hash_lookup(&stat_cache, chk_name); if(hash_elem == NULL) { + DEBUG(10,("stat_cache_lookup: lookup failed for name [%s]\n", chk_name )); /* * Didn't find it - remove last component for next try. */ @@ -276,6 +278,7 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath, } } else { scp = (stat_cache_entry *)(hash_elem->value); + DEBUG(10,("stat_cache_lookup: lookup succeeded for name [%s] -> [%s]\n", chk_name, scp->translated_path )); DO_PROFILE_INC(statcache_hits); if(SMB_VFS_STAT(conn,scp->translated_path, pst) != 0) { /* Discard this entry - it doesn't exist in the filesystem. */ diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 86906fa5be..033e76a33e 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1,7 +1,7 @@ /* Unix SMB/CIFS implementation. SMB transaction2 handling - Copyright (C) Jeremy Allison 1994-2001 + Copyright (C) Jeremy Allison 1994-2003 Copyright (C) Stefan (metze) Metzmacher 2003 Extensively modified by Andrew Tridgell, 1995 @@ -261,8 +261,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i unix_convert(fname,conn,0,&bad_path,&sbuf); if (!check_name(fname,conn)) { - set_bad_path_error(errno, bad_path); - return(UNIXERROR(ERRDOS,ERRnoaccess)); + return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess); } unixmode = unix_mode(conn,open_attr | aARCH, fname); @@ -271,8 +270,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i oplock_request, &rmode,&smb_action); if (!fsp) { - set_bad_path_error(errno, bad_path); - return(UNIXERROR(ERRDOS,ERRnoaccess)); + return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess); } size = get_file_size(sbuf); @@ -441,9 +439,9 @@ static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *ps } /**************************************************************************** -checks for SMB_TIME_NO_CHANGE and if not found -calls interpret_long_date + Checks for SMB_TIME_NO_CHANGE and if not found calls interpret_long_date. ****************************************************************************/ + time_t interpret_long_unix_date(char *p) { DEBUG(1,("interpret_long_unix_date\n")); @@ -763,6 +761,70 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, p = pdata + len; break; + case SMB_FIND_FILE_LEVEL_261: + p += 4; + SIVAL(p,0,reskey); p += 4; + put_long_date(p,cdate); p += 8; + put_long_date(p,adate); p += 8; + put_long_date(p,mdate); p += 8; + put_long_date(p,mdate); p += 8; + SOFF_T(p,0,file_size); + SOFF_T(p,8,allocation_size); + p += 16; + SIVAL(p,0,nt_extmode); + p += 4; + len = srvstr_push(outbuf, p + 20, fname, -1, STR_TERMINATE_ASCII); + SIVAL(p, 0, len); + memset(p+4,'\0',16); /* EA size. Unknown 0 1 2 */ + p += 20 + len; /* Strlen, EA size. Unknown 0 1 2, string itself */ + len = PTR_DIFF(p, pdata); + len = (len + 3) & ~3; + SIVAL(pdata,0,len); + p = pdata + len; + break; + + case SMB_FIND_FILE_LEVEL_262: + was_8_3 = mangle_is_8_3(fname, True); + p += 4; + SIVAL(p,0,reskey); p += 4; + put_long_date(p,cdate); p += 8; + put_long_date(p,adate); p += 8; + put_long_date(p,mdate); p += 8; + put_long_date(p,mdate); p += 8; + SOFF_T(p,0,file_size); + SOFF_T(p,8,allocation_size); + p += 16; + 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); + mangle_map(mangled_name,True,True,SNUM(conn)); + mangled_name[12] = 0; + len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE); + SSVAL(p, 0, len); + } else { + SSVAL(p,0,0); + *(p+2) = 0; + } + p += 2 + 24; + memset(p, '\0', 10); /* 2 4 byte unknowns plus a zero reserved. */ + p += 10; + len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII); + SIVAL(q,0,len); + p += len; + len = PTR_DIFF(p, pdata); + len = (len + 3) & ~3; + SIVAL(pdata,0,len); + p = pdata + len; + break; + /* CIFS UNIX Extension. */ case SMB_FIND_FILE_UNIX: @@ -895,6 +957,8 @@ close_if_end = %d requires_resume_key = %d level = %d, max_data_bytes = %d\n", case SMB_FIND_FILE_FULL_DIRECTORY_INFO: case SMB_FIND_FILE_NAMES_INFO: case SMB_FIND_FILE_BOTH_DIRECTORY_INFO: + case SMB_FIND_FILE_LEVEL_261: + case SMB_FIND_FILE_LEVEL_262: break; case SMB_FIND_FILE_UNIX: if (!lp_unix_extensions()) @@ -910,8 +974,7 @@ close_if_end = %d requires_resume_key = %d level = %d, max_data_bytes = %d\n", unix_convert(directory,conn,0,&bad_path,&sbuf); if(!check_name(directory,conn)) { - set_bad_path_error(errno, bad_path); - return(UNIXERROR(ERRDOS,ERRbadpath)); + return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath); } p = strrchr_m(directory,'/'); @@ -1365,7 +1428,7 @@ static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf * the called hostname and the service name. */ SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(local_machine)<<16) ); - len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, 0); + len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN); SCVAL(pdata,l2_vol_cch,len); data_len = l2_vol_szVolLabel + len; DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n", @@ -1716,14 +1779,22 @@ static int call_trans2setfsinfo(connection_struct *conn, * Utility function to set bad path error. ****************************************************************************/ -NTSTATUS set_bad_path_error(int err, BOOL bad_path) +int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint32 def_code) { - if((err == ENOENT) && bad_path) { + DEBUG(10,("set_bad_path_error: err = %d bad_path = %d\n", + err, (int)bad_path )); + + if(err == ENOENT) { unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; - return NT_STATUS_OBJECT_PATH_NOT_FOUND; + if (bad_path) { + unix_ERR_code = ERRbadpath; + return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); + } else { + unix_ERR_code = ERRbadfile; + return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND); + } } - return NT_STATUS_OK; + return UNIXERROR(def_class,def_code); } /**************************************************************************** @@ -1778,8 +1849,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, unix_convert(fname,conn,0,&bad_path,&sbuf); if (!check_name(fname,conn)) { DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed for fake_file(%s)\n",fname,strerror(errno))); - set_bad_path_error(errno, bad_path); - return(UNIXERROR(ERRDOS,ERRbadpath)); + return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath); } } else if(fsp && (fsp->is_directory || fsp->fd == -1)) { @@ -1792,21 +1862,18 @@ static int call_trans2qfilepathinfo(connection_struct *conn, unix_convert(fname,conn,0,&bad_path,&sbuf); if (!check_name(fname,conn)) { DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno))); - set_bad_path_error(errno, bad_path); - return(UNIXERROR(ERRDOS,ERRbadpath)); + return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath); } if (INFO_LEVEL_IS_UNIX(info_level)) { /* Always do lstat for UNIX calls. */ if (SMB_VFS_LSTAT(conn,fname,&sbuf)) { DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno))); - set_bad_path_error(errno, bad_path); - return(UNIXERROR(ERRDOS,ERRbadpath)); + return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath); } } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) { DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno))); - set_bad_path_error(errno, bad_path); - return(UNIXERROR(ERRDOS,ERRbadpath)); + return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath); } delete_pending = fsp->directory_delete_on_close; @@ -1821,9 +1888,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno))); return(UNIXERROR(ERRDOS,ERRbadfid)); } - if((pos = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_CUR)) == -1) - return(UNIXERROR(ERRDOS,ERRnoaccess)); - + pos = fsp->position_information; delete_pending = fsp->delete_on_close; } } else { @@ -1842,29 +1907,26 @@ static int call_trans2qfilepathinfo(connection_struct *conn, unix_convert(fname,conn,0,&bad_path,&sbuf); if (!check_name(fname,conn)) { DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno))); - set_bad_path_error(errno, bad_path); - return(UNIXERROR(ERRDOS,ERRbadpath)); + return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath); } if (INFO_LEVEL_IS_UNIX(info_level)) { /* Always do lstat for UNIX calls. */ if (SMB_VFS_LSTAT(conn,fname,&sbuf)) { DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno))); - set_bad_path_error(errno, bad_path); - return(UNIXERROR(ERRDOS,ERRbadpath)); + return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath); } } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) { DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno))); - set_bad_path_error(errno, bad_path); - return(UNIXERROR(ERRDOS,ERRbadpath)); + return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath); } } if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) return ERROR_DOS(ERRDOS,ERRunknownlevel); - DEBUG(3,("call_trans2qfilepathinfo %s level=%d call=%d total_data=%d\n", - fname,info_level,tran_call,total_data)); + DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n", + fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data)); p = strrchr_m(fname,'/'); if (!p) @@ -1873,6 +1935,9 @@ static int call_trans2qfilepathinfo(connection_struct *conn, base_name = p+1; mode = dos_mode(conn,fname,&sbuf); + if (!mode) + mode = FILE_ATTRIBUTE_NORMAL; + fullpathname = fname; file_size = get_file_size(sbuf); allocation_size = get_allocation_size(fsp,&sbuf); @@ -1985,7 +2050,10 @@ static int call_trans2qfilepathinfo(connection_struct *conn, data_size = 24; SOFF_T(pdata,0,allocation_size); SOFF_T(pdata,8,file_size); - SIVAL(pdata,16,sbuf.st_nlink); + if (delete_pending & sbuf.st_nlink) + SIVAL(pdata,16,sbuf.st_nlink - 1); + else + SIVAL(pdata,16,sbuf.st_nlink); SCVAL(pdata,20,0); SCVAL(pdata,21,(mode&aDIR)?1:0); break; @@ -2043,7 +2111,10 @@ static int call_trans2qfilepathinfo(connection_struct *conn, pdata += 40; SOFF_T(pdata,0,allocation_size); SOFF_T(pdata,8,file_size); - SIVAL(pdata,16,sbuf.st_nlink); + if (delete_pending && sbuf.st_nlink) + SIVAL(pdata,16,sbuf.st_nlink - 1); + else + SIVAL(pdata,16,sbuf.st_nlink); SCVAL(pdata,20,delete_pending); SCVAL(pdata,21,(mode&aDIR)?1:0); pdata += 24; @@ -2415,8 +2486,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, unix_convert(fname,conn,0,&bad_path,&sbuf); if (!check_name(fname,conn) || (!VALID_STAT(sbuf))) { DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno))); - set_bad_path_error(errno, bad_path); - return(UNIXERROR(ERRDOS,ERRbadpath)); + return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath); } } else if (fsp && fsp->print_file) { /* @@ -2455,8 +2525,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, srvstr_pull(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE); unix_convert(fname,conn,0,&bad_path,&sbuf); if(!check_name(fname, conn)) { - set_bad_path_error(errno, bad_path); - return(UNIXERROR(ERRDOS,ERRbadpath)); + return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath); } /* @@ -2465,8 +2534,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn, if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) { DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno))); - set_bad_path_error(errno, bad_path); - return(UNIXERROR(ERRDOS,ERRbadpath)); + return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND); } } @@ -2479,8 +2547,8 @@ static int call_trans2setfilepathinfo(connection_struct *conn, if (VALID_STAT(sbuf)) unixmode = sbuf.st_mode; - DEBUG(3,("call_trans2setfilepathinfo(%d) %s info_level=%d totdata=%d\n", - tran_call,fname,info_level,total_data)); + DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n", + tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data)); /* Realloc the parameter and data sizes */ params = Realloc(*pparams,2); @@ -2507,18 +2575,13 @@ static int call_trans2setfilepathinfo(connection_struct *conn, switch (info_level) { case SMB_INFO_STANDARD: { - if (total_data < l1_cbFile+4) + if (total_data < 12) return(ERROR_DOS(ERRDOS,ERRinvalidparam)); /* access time */ tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess); - /* write time */ tvs.modtime = make_unix_date2(pdata+l1_fdateLastWrite); - - dosmode = SVAL(pdata,l1_attrFile); - size = IVAL(pdata,l1_cbFile); - break; } @@ -2677,14 +2740,17 @@ static int call_trans2setfilepathinfo(connection_struct *conn, case SMB_FILE_DISPOSITION_INFORMATION: case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */ { - BOOL delete_on_close = (CVAL(pdata,0) ? True : False); + BOOL delete_on_close; NTSTATUS status; if (total_data < 1) return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + delete_on_close = (CVAL(pdata,0) ? True : False); + + /* Just ignore this set on a path. */ if (tran_call != TRANSACT2_SETFILEINFO) - return ERROR_DOS(ERRDOS,ERRunknownlevel); + break; if (fsp == NULL) return(UNIXERROR(ERRDOS,ERRbadfid)); @@ -2702,6 +2768,27 @@ static int call_trans2setfilepathinfo(connection_struct *conn, break; } + case SMB_FILE_POSITION_INFORMATION: + { + SMB_BIG_UINT position_information; + + if (total_data < 8) + return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + + position_information = (SMB_BIG_UINT)IVAL(pdata,0); +#ifdef LARGE_SMB_OFF_T + position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32); +#else /* LARGE_SMB_OFF_T */ + if (IVAL(pdata,4) != 0) /* more than 32 bits? */ + return ERROR_DOS(ERRDOS,ERRunknownlevel); +#endif /* LARGE_SMB_OFF_T */ + DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n", + fname, (double)position_information )); + if (fsp) + fsp->position_information = position_information; + break; + } + /* * CIFS UNIX extensions. */ @@ -2881,6 +2968,55 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", return(-1); } + case SMB_FILE_RENAME_INFORMATION: + { + BOOL overwrite; + uint32 root_fid; + uint32 len; + pstring newname; + pstring base_name; + char *p; + NTSTATUS status; + + if (total_data < 12) + return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + + overwrite = (CVAL(pdata,0) ? True : False); + root_fid = IVAL(pdata,4); + len = IVAL(pdata,8); + srvstr_pull(inbuf, newname, &pdata[12], sizeof(newname), len, 0); + + /* Check the new name has no '\' characters. */ + if (strchr_m(newname, '\\') || strchr_m(newname, '/')) + return ERROR_NT(NT_STATUS_NOT_SUPPORTED); + + RESOLVE_DFSPATH(newname, conn, inbuf, outbuf); + + /* Create the base directory. */ + pstrcpy(base_name, fname); + p = strrchr_m(base_name, '/'); + if (p) + *p = '\0'; + /* Append the new name. */ + pstrcat(base_name, "/"); + pstrcat(base_name, newname); + + if (fsp) { + DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n", + fsp->fnum, fsp->fsp_name, base_name )); + status = rename_internals_fsp(conn, fsp, base_name, overwrite); + } else { + DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n", + fname, newname )); + status = rename_internals(conn, fname, base_name, overwrite); + } + if (!NT_STATUS_IS_OK(status)) + return ERROR_NT(status); + process_pending_change_notify_queue((time_t)0); + SSVAL(params,0,0); + send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); + return(-1); + } default: return ERROR_DOS(ERRDOS,ERRunknownlevel); } @@ -2896,10 +3032,12 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", DEBUG(6,("modtime: %s ", ctime(&tvs.modtime))); DEBUG(6,("size: %.0f ", (double)size)); - if (S_ISDIR(sbuf.st_mode)) - dosmode |= aDIR; - else - dosmode &= ~aDIR; + if (dosmode) { + if (S_ISDIR(sbuf.st_mode)) + dosmode |= aDIR; + else + dosmode &= ~aDIR; + } DEBUG(6,("dosmode: %x\n" , dosmode)); @@ -3030,8 +3168,7 @@ static int call_trans2mkdir(connection_struct *conn, if(ret < 0) { DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno))); - set_bad_path_error(errno, bad_path); - return(UNIXERROR(ERRDOS,ERRnoaccess)); + return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess); } /* Realloc the parameter and data sizes */ diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 8d3e7cd9be..7979ffe854 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -370,7 +370,7 @@ BOOL unbecome_user(void) } /***************************************************************** - Convert the suplimentary SIDs returned in a netlogon into UNIX + Convert the supplementary SIDs returned in a netlogon into UNIX group gid_t's. Add to the total group array. *****************************************************************/ @@ -437,467 +437,4 @@ void add_supplementary_nt_login_groups(int *n_groups, gid_t **pp_groups, NT_USER *pptok = new_tok; } -/***************************************************************** - *THE CANONICAL* convert name to SID function. - Tries local lookup first - for local domains - then uses winbind. -*****************************************************************/ - -BOOL lookup_name(const char *domain, const char *name, DOM_SID *psid, enum SID_NAME_USE *name_type) -{ - fstring sid; - BOOL local_lookup = False; - - *name_type = SID_NAME_UNKNOWN; - - /* If we are looking up a domain user, make sure it is - for the local machine only */ - - if (strequal(global_myname(), domain)) { - local_lookup = True; - } else if (lp_server_role() == ROLE_DOMAIN_PDC || - lp_server_role() == ROLE_DOMAIN_BDC) { - if (strequal(domain, lp_workgroup())) { - local_lookup = True; - } - } - - if (local_lookup) { - if (local_lookup_name(name, psid, name_type)) { - DEBUG(10, - ("lookup_name: (local) [%s]\\[%s] -> SID %s (type %s: %u)\n", - domain, name, sid_to_string(sid,psid), - sid_type_lookup(*name_type), (unsigned int)*name_type)); - return True; - } - } else { - /* Remote */ - if (winbind_lookup_name(domain, name, psid, name_type)) { - - DEBUG(10,("lookup_name (winbindd): [%s]\\[%s] -> SID %s (type %u)\n", - domain, name, sid_to_string(sid, psid), - (unsigned int)*name_type)); - return True; - } - } - - DEBUG(10, ("lookup_name: %s lookup for [%s]\\[%s] failed\n", - local_lookup ? "local" : "winbind", domain, name)); - - return False; -} - -/***************************************************************** - *THE CANONICAL* convert SID to name function. - Tries local lookup first - for local sids, then tries winbind. -*****************************************************************/ - -BOOL lookup_sid(DOM_SID *sid, fstring dom_name, fstring name, enum SID_NAME_USE *name_type) -{ - if (!name_type) - return False; - - *name_type = SID_NAME_UNKNOWN; - - /* Check if this is our own sid. This should perhaps be done by - winbind? For the moment handle it here. */ - - if (sid->num_auths == 5) { - DOM_SID tmp_sid; - uint32 rid; - - sid_copy(&tmp_sid, sid); - sid_split_rid(&tmp_sid, &rid); - - if (sid_equal(get_global_sam_sid(), &tmp_sid)) { - - return map_domain_sid_to_name(&tmp_sid, dom_name) && - local_lookup_sid(sid, name, name_type); - } - } - - if (!winbind_lookup_sid(sid, dom_name, name, name_type)) { - fstring sid_str; - DOM_SID tmp_sid; - uint32 rid; - - DEBUG(10,("lookup_sid: winbind lookup for SID %s failed - trying local.\n", sid_to_string(sid_str, sid) )); - - sid_copy(&tmp_sid, sid); - sid_split_rid(&tmp_sid, &rid); - return map_domain_sid_to_name(&tmp_sid, dom_name) && - lookup_known_rid(&tmp_sid, rid, name, name_type); - } - return True; -} - - -/***************************************************************** - Id mapping cache. This is to avoid Winbind mappings already - seen by smbd to be queried too frequently, keeping winbindd - busy, and blocking smbd while winbindd is busy with other - stuff. Written by Michael Steffens , - modified to use linked lists by jra. -*****************************************************************/ - -#define MAX_UID_SID_CACHE_SIZE 100 -#define TURNOVER_UID_SID_CACHE_SIZE 10 -#define MAX_GID_SID_CACHE_SIZE 100 -#define TURNOVER_GID_SID_CACHE_SIZE 10 - -static size_t n_uid_sid_cache = 0; -static size_t n_gid_sid_cache = 0; - -static struct uid_sid_cache { - struct uid_sid_cache *next, *prev; - uid_t uid; - DOM_SID sid; - enum SID_NAME_USE sidtype; -} *uid_sid_cache_head; - -static struct gid_sid_cache { - struct gid_sid_cache *next, *prev; - gid_t gid; - DOM_SID sid; - enum SID_NAME_USE sidtype; -} *gid_sid_cache_head; - -/***************************************************************** - Find a SID given a uid. -*****************************************************************/ - -static BOOL fetch_sid_from_uid_cache(DOM_SID *psid, uid_t uid) -{ - struct uid_sid_cache *pc; - - for (pc = uid_sid_cache_head; pc; pc = pc->next) { - if (pc->uid == uid) { - fstring sid; - *psid = pc->sid; - DEBUG(3,("fetch sid from uid cache %u -> %s\n", - (unsigned int)uid, sid_to_string(sid, psid))); - DLIST_PROMOTE(uid_sid_cache_head, pc); - return True; - } - } - return False; -} - -/***************************************************************** - Find a uid given a SID. -*****************************************************************/ - -static BOOL fetch_uid_from_cache( uid_t *puid, const DOM_SID *psid ) -{ - struct uid_sid_cache *pc; - - for (pc = uid_sid_cache_head; pc; pc = pc->next) { - if (sid_compare(&pc->sid, psid) == 0) { - fstring sid; - *puid = pc->uid; - DEBUG(3,("fetch uid from cache %u -> %s\n", - (unsigned int)*puid, sid_to_string(sid, psid))); - DLIST_PROMOTE(uid_sid_cache_head, pc); - return True; - } - } - return False; -} - -/***************************************************************** - Store uid to SID mapping in cache. -*****************************************************************/ - -static void store_uid_sid_cache(const DOM_SID *psid, uid_t uid) -{ - struct uid_sid_cache *pc; - - if (n_uid_sid_cache >= MAX_UID_SID_CACHE_SIZE && n_uid_sid_cache > TURNOVER_UID_SID_CACHE_SIZE) { - /* Delete the last TURNOVER_UID_SID_CACHE_SIZE entries. */ - struct uid_sid_cache *pc_next; - size_t i; - - for (i = 0, pc = uid_sid_cache_head; i < (n_uid_sid_cache - TURNOVER_UID_SID_CACHE_SIZE); i++, pc = pc->next) - ; - for(; pc; pc = pc_next) { - pc_next = pc->next; - DLIST_REMOVE(uid_sid_cache_head,pc); - SAFE_FREE(pc); - n_uid_sid_cache--; - } - } - - pc = (struct uid_sid_cache *)malloc(sizeof(struct uid_sid_cache)); - if (!pc) - return; - pc->uid = uid; - sid_copy(&pc->sid, psid); - DLIST_ADD(uid_sid_cache_head, pc); - n_uid_sid_cache++; -} - -/***************************************************************** - Find a SID given a gid. -*****************************************************************/ - -static BOOL fetch_sid_from_gid_cache(DOM_SID *psid, gid_t gid) -{ - struct gid_sid_cache *pc; - - for (pc = gid_sid_cache_head; pc; pc = pc->next) { - if (pc->gid == gid) { - fstring sid; - *psid = pc->sid; - DEBUG(3,("fetch sid from gid cache %u -> %s\n", - (unsigned int)gid, sid_to_string(sid, psid))); - DLIST_PROMOTE(gid_sid_cache_head, pc); - return True; - } - } - return False; -} - -/***************************************************************** - Find a gid given a SID. -*****************************************************************/ - -static BOOL fetch_gid_from_cache(gid_t *pgid, const DOM_SID *psid) -{ - struct gid_sid_cache *pc; - - for (pc = gid_sid_cache_head; pc; pc = pc->next) { - if (sid_compare(&pc->sid, psid) == 0) { - fstring sid; - *pgid = pc->gid; - DEBUG(3,("fetch uid from cache %u -> %s\n", - (unsigned int)*pgid, sid_to_string(sid, psid))); - DLIST_PROMOTE(gid_sid_cache_head, pc); - return True; - } - } - return False; -} - -/***************************************************************** - Store gid to SID mapping in cache. -*****************************************************************/ -static void store_gid_sid_cache(const DOM_SID *psid, gid_t gid) -{ - struct gid_sid_cache *pc; - - if (n_gid_sid_cache >= MAX_GID_SID_CACHE_SIZE && n_gid_sid_cache > TURNOVER_GID_SID_CACHE_SIZE) { - /* Delete the last TURNOVER_GID_SID_CACHE_SIZE entries. */ - struct gid_sid_cache *pc_next; - size_t i; - - for (i = 0, pc = gid_sid_cache_head; i < (n_gid_sid_cache - TURNOVER_GID_SID_CACHE_SIZE); i++, pc = pc->next) - ; - for(; pc; pc = pc_next) { - pc_next = pc->next; - DLIST_REMOVE(gid_sid_cache_head,pc); - SAFE_FREE(pc); - n_gid_sid_cache--; - } - } - - pc = (struct gid_sid_cache *)malloc(sizeof(struct gid_sid_cache)); - if (!pc) - return; - pc->gid = gid; - sid_copy(&pc->sid, psid); - DLIST_ADD(gid_sid_cache_head, pc); - n_gid_sid_cache++; -} - -/***************************************************************** - *THE CANONICAL* convert uid_t to SID function. -*****************************************************************/ - -NTSTATUS uid_to_sid(DOM_SID *psid, uid_t uid) -{ - uid_t low, high; - fstring sid; - - ZERO_STRUCTP(psid); - - if (fetch_sid_from_uid_cache(psid, uid)) - return ( psid ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL ); - - if (lp_idmap_uid(&low, &high) && uid >= low && uid <= high) { - if (winbind_uid_to_sid(psid, uid)) { - - DEBUG(10,("uid_to_sid: winbindd %u -> %s\n", - (unsigned int)uid, sid_to_string(sid, psid))); - - if (psid) - store_uid_sid_cache(psid, uid); - return ( psid ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL ); - } - } - - if (!local_uid_to_sid(psid, uid)) { - DEBUG(10,("uid_to_sid: local %u failed to map to sid\n", (unsigned int)uid )); - return NT_STATUS_UNSUCCESSFUL; - } - - DEBUG(10,("uid_to_sid: local %u -> %s\n", (unsigned int)uid, sid_to_string(sid, psid))); - - store_uid_sid_cache(psid, uid); - return NT_STATUS_OK; -} - -/***************************************************************** - *THE CANONICAL* convert gid_t to SID function. -*****************************************************************/ - -NTSTATUS gid_to_sid(DOM_SID *psid, gid_t gid) -{ - gid_t low, high; - fstring sid; - - ZERO_STRUCTP(psid); - - if (fetch_sid_from_gid_cache(psid, gid)) - return ( psid ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL ); - - if (lp_idmap_gid(&low, &high) && gid >= low && gid <= high) { - if (winbind_gid_to_sid(psid, gid)) { - - DEBUG(10,("gid_to_sid: winbindd %u -> %s\n", - (unsigned int)gid, sid_to_string(sid, psid))); - - if (psid) - store_gid_sid_cache(psid, gid); - return ( psid ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL ); - } - } - - if (!local_gid_to_sid(psid, gid)) { - DEBUG(10,("gid_to_sid: local %u failed to map to sid\n", (unsigned int)gid )); - return NT_STATUS_UNSUCCESSFUL; - } - - DEBUG(10,("gid_to_sid: local %u -> %s\n", (unsigned int)gid, sid_to_string(sid, psid))); - - store_gid_sid_cache(psid, gid); - return NT_STATUS_OK; -} - -/***************************************************************** - *THE CANONICAL* convert SID to uid function. -*****************************************************************/ - -NTSTATUS sid_to_uid(const DOM_SID *psid, uid_t *puid) -{ - fstring dom_name, name, sid_str; - enum SID_NAME_USE name_type; - - if (fetch_uid_from_cache(puid, psid)) - return NT_STATUS_OK; - - /* if this is our SID then go straight to a local lookup */ - - if ( sid_compare_domain(get_global_sam_sid(), psid) == 0 ) { - DEBUG(10,("sid_to_uid: my domain (%s) - trying local.\n", - sid_string_static(psid) )); - - if ( local_sid_to_uid(puid, psid, &name_type) ) - goto success; - - DEBUG(10,("sid_to_uid: local lookup failed\n")); - - return NT_STATUS_UNSUCCESSFUL; - } - - /* If it is not our local domain, only hope is winbindd */ - - if ( !winbind_lookup_sid(psid, dom_name, name, &name_type) ) { - DEBUG(10,("sid_to_uid: winbind lookup for non-local sid %s failed\n", - sid_string_static(psid) )); - - return NT_STATUS_UNSUCCESSFUL; - } - - /* If winbindd does know the SID, ensure this is a user */ - - if (name_type != SID_NAME_USER) { - DEBUG(10,("sid_to_uid: winbind lookup succeeded but SID is not a user (%u)\n", - (unsigned int)name_type )); - return NT_STATUS_INVALID_PARAMETER; - } - - /* get the uid. Has to work or else we are dead in the water */ - - if ( !winbind_sid_to_uid(puid, psid) ) { - DEBUG(10,("sid_to_uid: winbind failed to allocate a new uid for sid %s\n", - sid_to_string(sid_str, psid) )); - return NT_STATUS_UNSUCCESSFUL; - } - -success: - DEBUG(10,("sid_to_uid: %s -> %u\n", sid_to_string(sid_str, psid), - (unsigned int)*puid )); - - store_uid_sid_cache(psid, *puid); - - return NT_STATUS_OK; -} -/***************************************************************** - *THE CANONICAL* convert SID to gid function. - Group mapping is used for gids that maps to Wellknown SIDs -*****************************************************************/ - -NTSTATUS sid_to_gid(const DOM_SID *psid, gid_t *pgid) -{ - fstring dom_name, name, sid_str; - enum SID_NAME_USE name_type; - - if (fetch_gid_from_cache(pgid, psid)) - return NT_STATUS_OK; - - /* - * First we must look up the name and decide if this is a group sid. - * Group mapping can deal with foreign SIDs - */ - - if (!winbind_lookup_sid(psid, dom_name, name, &name_type)) { - DEBUG(10,("sid_to_gid: winbind lookup for sid %s failed - trying local.\n", - sid_to_string(sid_str, psid) )); - - if ( local_sid_to_gid(pgid, psid, &name_type) ) - goto success; - - DEBUG(10,("sid_to_gid: no one knows this SID\n")); - - return NT_STATUS_UNSUCCESSFUL; - } - - /* winbindd knows it; Ensure this is a group sid */ - - if ((name_type != SID_NAME_DOM_GRP) && (name_type != SID_NAME_ALIAS) && (name_type != SID_NAME_WKN_GRP)) { - DEBUG(10,("sid_to_gid: winbind lookup succeeded but SID is not a known group (%u)\n", - (unsigned int)name_type )); - - /* winbindd is running and knows about this SID. Just the wrong type. - Don't fallback to a local lookup here */ - - return NT_STATUS_INVALID_PARAMETER; - } - - /* winbindd knows it and it is a type of group; sid_to_gid must succeed - or we are dead in the water */ - - if ( !winbind_sid_to_gid(pgid, psid) ) { - DEBUG(10,("sid_to_uid: winbind failed to allocate a new gid for sid %s\n", - sid_to_string(sid_str, psid) )); - return NT_STATUS_UNSUCCESSFUL; - } - -success: - DEBUG(10,("sid_to_gid: %s -> %u\n", sid_to_string(sid_str, psid), - (unsigned int)*pgid )); - - store_gid_sid_cache(psid, *pgid); - - return NT_STATUS_OK; -} diff --git a/source3/smbd/utmp.c b/source3/smbd/utmp.c index 6ff2f586ba..a521d0113d 100644 --- a/source3/smbd/utmp.c +++ b/source3/smbd/utmp.c @@ -217,13 +217,13 @@ static void uw_pathname(pstring fname, const char *uw_name, const char *uw_defau /* For w-files, first look for explicit "wtmp dir" */ if (uw_name[0] == 'w') { pstrcpy(dirname,lp_wtmpdir()); - trim_string(dirname,"","/"); + trim_char(dirname,'\0','/'); } /* For u-files and non-explicit w-dir, look for "utmp dir" */ if (dirname == 0 || strlen(dirname) == 0) { pstrcpy(dirname,lp_utmpdir()); - trim_string(dirname,"","/"); + trim_char(dirname,'\0','/'); } /* If explicit directory above, use it */ @@ -283,8 +283,12 @@ static void updwtmp_my(pstring wname, struct utmp *u, BOOL claim) * man page appears not to specify (hints non-NULL) * A correspondent suggest at least ut_name should be NULL */ +#if defined(HAVE_UT_UT_NAME) memset((char *)&u->ut_name, '\0', sizeof(u->ut_name)); +#endif +#if defined(HAVE_UT_UT_HOST) memset((char *)&u->ut_host, '\0', sizeof(u->ut_host)); +#endif } /* Stolen from logwtmp function in libutil. * May be more locking/blocking is needed? @@ -406,7 +410,9 @@ static void sys_utmp_update(struct utmp *u, const char *hostname, BOOL claim) else ux.ut_syslen = 0; #endif +#if defined(HAVE_UT_UT_HOST) utmp_strcpy(ux.ut_host, hostname, sizeof(ux.ut_host)); +#endif uw_pathname(uname, "utmpx", ux_pathname); uw_pathname(wname, "wtmpx", wx_pathname); diff --git a/source3/smbd/vfs-wrap.c b/source3/smbd/vfs-wrap.c index 8d44a1a0fa..a76a7a6abd 100644 --- a/source3/smbd/vfs-wrap.c +++ b/source3/smbd/vfs-wrap.c @@ -49,6 +49,42 @@ SMB_BIG_UINT vfswrap_disk_free(vfs_handle_struct *handle, connection_struct *con result = sys_disk_free(path, small_query, bsize, dfree, dsize); return result; } + +int vfswrap_get_quota(struct vfs_handle_struct *handle, struct connection_struct *conn, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt) +{ +#ifdef HAVE_SYS_QUOTAS + int result; + + START_PROFILE(syscall_get_quota); + result = sys_get_quota(conn->connectpath, qtype, id, qt); + END_PROFILE(syscall_get_quota); + return result; +#else + errno = ENOSYS; + return -1; +#endif +} + +int vfswrap_set_quota(struct vfs_handle_struct *handle, struct connection_struct *conn, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt) +{ +#ifdef HAVE_SYS_QUOTAS + int result; + + START_PROFILE(syscall_set_quota); + result = sys_set_quota(conn->connectpath, qtype, id, qt); + END_PROFILE(syscall_set_quota); + return result; +#else + errno = ENOSYS; + return -1; +#endif +} + +int vfswrap_get_shadow_copy_data(struct vfs_handle_struct *handle, struct files_struct *fsp, SHADOW_COPY_DATA *shadow_copy_data, BOOL labels) +{ + errno = ENOSYS; + return -1; /* Not implemented. */ +} /* Directory operations */ @@ -756,36 +792,6 @@ int vfswrap_sys_acl_free_qualifier(vfs_handle_struct *handle, connection_struct return sys_acl_free_qualifier(qualifier, tagtype); } -int vfswrap_get_quota(struct vfs_handle_struct *handle, struct connection_struct *conn, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt) -{ -#ifdef HAVE_SYS_QUOTAS - int result; - - START_PROFILE(syscall_get_quota); - result = sys_get_quota(conn->connectpath, qtype, id, qt); - END_PROFILE(syscall_get_quota); - return result; -#else - errno = ENOSYS; - return -1; -#endif -} - -int vfswrap_set_quota(struct vfs_handle_struct *handle, struct connection_struct *conn, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *qt) -{ -#ifdef HAVE_SYS_QUOTAS - int result; - - START_PROFILE(syscall_set_quota); - result = sys_set_quota(conn->connectpath, qtype, id, qt); - END_PROFILE(syscall_set_quota); - return result; -#else - errno = ENOSYS; - return -1; -#endif -} - /**************************************************************** Extended attribute operations. *****************************************************************/ diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 5f3abe7efe..753db4cece 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -56,6 +56,7 @@ static struct vfs_ops default_vfs = { vfswrap_disk_free, vfswrap_get_quota, vfswrap_set_quota, + vfswrap_get_shadow_copy_data, /* Directory operations */ @@ -140,7 +141,6 @@ static struct vfs_ops default_vfs = { vfswrap_setxattr, vfswrap_lsetxattr, vfswrap_fsetxattr - } }; @@ -233,10 +233,10 @@ BOOL vfs_init_custom(connection_struct *conn, const char *vfs_object) if (p) { *p = 0; module_param = p+1; - trim_string(module_param, " ", " "); + trim_char(module_param, ' ', ' '); } - trim_string(module_name, " ", " "); + trim_char(module_name, ' ', ' '); /* First, try to load the module with the new module system */ if((entry = vfs_find_backend_entry(module_name)) || diff --git a/source3/tdb/tdb.c b/source3/tdb/tdb.c index 34681ea78f..f5809ef63a 100644 --- a/source3/tdb/tdb.c +++ b/source3/tdb/tdb.c @@ -1015,12 +1015,11 @@ static int tdb_keylocked(TDB_CONTEXT *tdb, u32 hash) } /* As tdb_find, but if you succeed, keep the lock */ -static tdb_off tdb_find_lock(TDB_CONTEXT *tdb, TDB_DATA key, int locktype, +static tdb_off tdb_find_lock_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash, int locktype, struct list_struct *rec) { - u32 hash, rec_ptr; + u32 rec_ptr; - hash = tdb_hash(&key); if (!tdb_keylocked(tdb, hash)) return 0; if (tdb_lock(tdb, BUCKET(hash), locktype) == -1) @@ -1061,13 +1060,13 @@ const char *tdb_errorstr(TDB_CONTEXT *tdb) on failure return -1. */ -static int tdb_update(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf) +static int tdb_update_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash, TDB_DATA dbuf) { struct list_struct rec; tdb_off rec_ptr; /* find entry */ - if (!(rec_ptr = tdb_find(tdb, key, tdb_hash(&key), &rec))) + if (!(rec_ptr = tdb_find(tdb, key, hash, &rec))) return -1; /* must be long enough key, data and tailer */ @@ -1101,9 +1100,11 @@ TDB_DATA tdb_fetch(TDB_CONTEXT *tdb, TDB_DATA key) tdb_off rec_ptr; struct list_struct rec; TDB_DATA ret; + u32 hash; /* find which hash bucket it is in */ - if (!(rec_ptr = tdb_find_lock(tdb,key,F_RDLCK,&rec))) + hash = tdb_hash(&key); + if (!(rec_ptr = tdb_find_lock_hash(tdb,key,hash,F_RDLCK,&rec))) return tdb_null; if (rec.data_len) @@ -1122,16 +1123,22 @@ TDB_DATA tdb_fetch(TDB_CONTEXT *tdb, TDB_DATA key) this doesn't match the conventions in the rest of this module, but is compatible with gdbm */ -int tdb_exists(TDB_CONTEXT *tdb, TDB_DATA key) +static int tdb_exists_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash) { struct list_struct rec; - if (tdb_find_lock(tdb, key, F_RDLCK, &rec) == 0) + if (tdb_find_lock_hash(tdb, key, hash, F_RDLCK, &rec) == 0) return 0; tdb_unlock(tdb, BUCKET(rec.full_hash), F_RDLCK); return 1; } +int tdb_exists(TDB_CONTEXT *tdb, TDB_DATA key) +{ + u32 hash = tdb_hash(&key); + return tdb_exists_hash(tdb, key, hash); +} + /* record lock stops delete underneath */ static int lock_record(TDB_CONTEXT *tdb, tdb_off off) { @@ -1388,7 +1395,7 @@ TDB_DATA tdb_nextkey(TDB_CONTEXT *tdb, TDB_DATA oldkey) if (!tdb->travlocks.off) { /* No previous element: do normal find, and lock record */ - tdb->travlocks.off = tdb_find_lock(tdb, oldkey, F_WRLCK, &rec); + tdb->travlocks.off = tdb_find_lock_hash(tdb, oldkey, tdb_hash(&oldkey), F_WRLCK, &rec); if (!tdb->travlocks.off) return tdb_null; tdb->travlocks.hash = BUCKET(rec.full_hash); @@ -1416,13 +1423,13 @@ TDB_DATA tdb_nextkey(TDB_CONTEXT *tdb, TDB_DATA oldkey) } /* delete an entry in the database given a key */ -int tdb_delete(TDB_CONTEXT *tdb, TDB_DATA key) +static int tdb_delete_hash(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash) { tdb_off rec_ptr; struct list_struct rec; int ret; - if (!(rec_ptr = tdb_find_lock(tdb, key, F_WRLCK, &rec))) + if (!(rec_ptr = tdb_find_lock_hash(tdb, key, hash, F_WRLCK, &rec))) return -1; ret = do_delete(tdb, rec_ptr, &rec); if (tdb_unlock(tdb, BUCKET(rec.full_hash), F_WRLCK) != 0) @@ -1430,6 +1437,12 @@ int tdb_delete(TDB_CONTEXT *tdb, TDB_DATA key) return ret; } +int tdb_delete(TDB_CONTEXT *tdb, TDB_DATA key) +{ + u32 hash = tdb_hash(&key); + return tdb_delete_hash(tdb, key, hash); +} + /* store an element in the database, replacing any existing element with the same key @@ -1452,13 +1465,13 @@ int tdb_store(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, int flag) /* check for it existing, on insert. */ if (flag == TDB_INSERT) { - if (tdb_exists(tdb, key)) { + if (tdb_exists_hash(tdb, key, hash)) { tdb->ecode = TDB_ERR_EXISTS; goto fail; } } else { /* first try in-place update, on modify or replace. */ - if (tdb_update(tdb, key, dbuf) == 0) + if (tdb_update_hash(tdb, key, hash, dbuf) == 0) goto out; if (flag == TDB_MODIFY && tdb->ecode == TDB_ERR_NOEXIST) goto fail; @@ -1470,7 +1483,7 @@ int tdb_store(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, int flag) care. Doing this first reduces fragmentation, and avoids coalescing with `allocated' block before it's updated. */ if (flag != TDB_INSERT) - tdb_delete(tdb, key); + tdb_delete_hash(tdb, key, hash); /* Copy key+value *before* allocating free space in case malloc fails and we are left with a dead spot in the tdb. */ @@ -1519,13 +1532,13 @@ fail: is <= the old data size and the key exists. on failure return -1. Record must be locked before calling. */ -static int tdb_append_inplace(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA new_dbuf) +static int tdb_append_inplace(TDB_CONTEXT *tdb, TDB_DATA key, u32 hash, TDB_DATA new_dbuf) { struct list_struct rec; tdb_off rec_ptr; /* find entry */ - if (!(rec_ptr = tdb_find(tdb, key, tdb_hash(&key), &rec))) + if (!(rec_ptr = tdb_find(tdb, key, hash, &rec))) return -1; /* Append of 0 is always ok. */ @@ -1567,7 +1580,7 @@ int tdb_append(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA new_dbuf) return -1; /* first try in-place. */ - if (tdb_append_inplace(tdb, key, new_dbuf) == 0) + if (tdb_append_inplace(tdb, key, hash, new_dbuf) == 0) goto out; /* reset the error code potentially set by the tdb_append_inplace() */ @@ -1610,7 +1623,7 @@ int tdb_append(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA new_dbuf) care. Doing this first reduces fragmentation, and avoids coalescing with `allocated' block before it's updated. */ - tdb_delete(tdb, key); + tdb_delete_hash(tdb, key, hash); if (!(rec_ptr = tdb_allocate(tdb, key.dsize + new_data_size, &rec))) goto fail; diff --git a/source3/torture/cmd_vfs.c b/source3/torture/cmd_vfs.c index d91dbf50e0..8317a57a20 100644 --- a/source3/torture/cmd_vfs.c +++ b/source3/torture/cmd_vfs.c @@ -490,8 +490,8 @@ static NTSTATUS cmd_stat(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, c int ret; const char *user; const char *group; - struct passwd *pwd; - struct group *grp; + struct passwd *pwd = NULL; + struct group *grp = NULL; SMB_STRUCT_STAT st; if (argc != 2) { @@ -533,6 +533,7 @@ static NTSTATUS cmd_stat(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, c printf(" Access: %s", ctime(&(st.st_atime))); printf(" Modify: %s", ctime(&(st.st_mtime))); printf(" Change: %s", ctime(&(st.st_ctime))); + SAFE_FREE(pwd); SAFE_FREE(grp); return NT_STATUS_OK; @@ -544,8 +545,8 @@ static NTSTATUS cmd_fstat(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, int fd; const char *user; const char *group; - struct passwd *pwd; - struct group *grp; + struct passwd *pwd = NULL; + struct group *grp = NULL; SMB_STRUCT_STAT st; if (argc != 2) { @@ -596,6 +597,7 @@ static NTSTATUS cmd_fstat(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, printf(" Access: %s", ctime(&(st.st_atime))); printf(" Modify: %s", ctime(&(st.st_mtime))); printf(" Change: %s", ctime(&(st.st_ctime))); + SAFE_FREE(pwd); SAFE_FREE(grp); return NT_STATUS_OK; @@ -606,8 +608,8 @@ static NTSTATUS cmd_lstat(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, { const char *user; const char *group; - struct passwd *pwd; - struct group *grp; + struct passwd *pwd = NULL; + struct group *grp = NULL; SMB_STRUCT_STAT st; if (argc != 2) { @@ -647,6 +649,7 @@ static NTSTATUS cmd_lstat(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc, printf(" Access: %s", ctime(&(st.st_atime))); printf(" Modify: %s", ctime(&(st.st_mtime))); printf(" Change: %s", ctime(&(st.st_ctime))); + SAFE_FREE(pwd); SAFE_FREE(grp); return NT_STATUS_OK; diff --git a/source3/torture/masktest.c b/source3/torture/masktest.c index fa901e3d63..8c44f35f95 100644 --- a/source3/torture/masktest.c +++ b/source3/torture/masktest.c @@ -140,7 +140,7 @@ static BOOL reg_match_one(struct cli_state *cli, const char *pattern, const char if (strcmp(file,"..") == 0) file = "."; - return ms_fnmatch(pattern, file, cli->protocol)==0; + return ms_fnmatch(pattern, file, cli->protocol, False /* not case sensitive */)==0; } static char *reg_test(struct cli_state *cli, char *pattern, char *long_name, char *short_name) diff --git a/source3/torture/rpctorture.c b/source3/torture/rpctorture.c index 8dfaebd64f..d95c0cee0f 100644 --- a/source3/torture/rpctorture.c +++ b/source3/torture/rpctorture.c @@ -193,7 +193,7 @@ static void usage(char *pname) fprintf(out_hnd, "Usage: %s service [-d debuglevel] [-l log] ", pname); - fprintf(out_hnd, "\nVersion %s\n",VERSION); + fprintf(out_hnd, "\nVersion %s\n",SAMBA_VERSION_STRING); fprintf(out_hnd, "\t-d debuglevel set the debuglevel\n"); fprintf(out_hnd, "\t-l log basename. Basename for log/debug files\n"); fprintf(out_hnd, "\t-n netbios name. Use this name as my netbios name\n"); @@ -489,7 +489,7 @@ enum client_action strupper_m(global_myname); fstrcpy(cli_info.myhostname, global_myname); - DEBUG(3,("%s client started (version %s)\n",timestring(False),VERSION)); + DEBUG(3,("%s client started (version %s)\n",timestring(False),SAMBA_VERSION_STRING)); if (*smb_cli->domain == 0) { diff --git a/source3/torture/smbiconv.c b/source3/torture/smbiconv.c index 3524136fb1..1dd168b0bb 100644 --- a/source3/torture/smbiconv.c +++ b/source3/torture/smbiconv.c @@ -24,7 +24,7 @@ #include "includes.h" static int -process_block (smb_iconv_t cd, char *addr, size_t len, FILE *output) +process_block (smb_iconv_t cd, const char *addr, size_t len, FILE *output) { #define OUTBUF_SIZE 32768 const char *start = addr; @@ -37,7 +37,7 @@ process_block (smb_iconv_t cd, char *addr, size_t len, FILE *output) { outptr = outbuf; outlen = OUTBUF_SIZE; - n = smb_iconv (cd, &addr, &len, &outptr, &outlen); + n = smb_iconv (cd, &addr, &len, &outptr, &outlen); if (outptr != outbuf) { @@ -171,7 +171,7 @@ int main(int argc, char *argv[]) char *from = ""; char *to = ""; char *output = NULL; - char *preload = NULL; + const char *preload_modules[] = {NULL, NULL}; FILE *out = stdout; int fd; smb_iconv_t cd; @@ -184,7 +184,7 @@ int main(int argc, char *argv[]) { "from-code", 'f', POPT_ARG_STRING, &from, 0, "Encoding of original text" }, { "to-code", 't', POPT_ARG_STRING, &to, 0, "Encoding for output" }, { "output", 'o', POPT_ARG_STRING, &output, 0, "Write output to this file" }, - { "preload-modules", 'p', POPT_ARG_STRING, &preload, 0, "Modules to load" }, + { "preload-modules", 'p', POPT_ARG_STRING, &preload_modules[0], 0, "Modules to load" }, POPT_COMMON_SAMBA POPT_TABLEEND }; @@ -202,12 +202,12 @@ int main(int argc, char *argv[]) facilities. See lib/debug.c */ setup_logging("smbiconv", True); - if(preload)smb_load_modules(str_list_make(preload, NULL)); + if (preload_modules[0]) smb_load_modules(preload_modules); if(output) { - output = fopen(output, "w"); + out = fopen(output, "w"); - if(!output) { + if(!out) { DEBUG(0, ("Can't open output file '%s': %s, exiting...\n", output, strerror(errno))); return 1; } @@ -231,7 +231,7 @@ int main(int argc, char *argv[]) } /* Loop thru all arguments */ - process_fd(cd, fd, stdout); + process_fd(cd, fd, out); close(fd); } diff --git a/source3/utils/log2pcaphex.c b/source3/utils/log2pcaphex.c new file mode 100644 index 0000000000..4804b99338 --- /dev/null +++ b/source3/utils/log2pcaphex.c @@ -0,0 +1,294 @@ +/* + Unix SMB/CIFS implementation. + Utility to extract pcap files from samba (log level 10) log files + + Copyright (C) Jelmer Vernooij 2003 + Thanks to Tim Potter for the genial idea + + Portions (from capconvert.c) (C) Andrew Tridgell 1997 + Portions (from text2pcap.c) (C) Ashok Narayanan 2001 + + Example use with -h parameter: + log2pcaphex < samba-log-file | text2pcap -T 139,139 - foo.pcap + + TODO: Have correct IP and TCP checksums. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" +#include + +int quiet = 0; +int hexformat = 0; + +#define itoa(a) ((a) < 0xa?'0'+(a):'A' + (a-0xa)) + +#include +#include +#include +#include +#include + +#define TCPDUMP_MAGIC 0xa1b2c3d4 + +/* tcpdump file format */ +struct tcpdump_file_header { + uint32 magic; + uint16 major; + uint16 minor; + int32 zone; + uint32 sigfigs; + uint32 snaplen; + uint32 linktype; +}; + +struct tcpdump_packet { + struct timeval ts; + uint32 caplen; + uint32 len; +}; + +typedef struct { + uint8 ver_hdrlen; + uint8 dscp; + uint16 packet_length; + uint16 identification; + uint8 flags; + uint8 fragment; + uint8 ttl; + uint8 protocol; + uint16 hdr_checksum; + uint32 src_addr; + uint32 dest_addr; +} hdr_ip_t; + +static hdr_ip_t HDR_IP = {0x45, 0, 0, 0x3412, 0, 0, 0xff, 6, 0, 0x01010101, 0x02020202}; + +typedef struct { + uint16 source_port; + uint16 dest_port; + uint32 seq_num; + uint32 ack_num; + uint8 hdr_length; + uint8 flags; + uint16 window; + uint16 checksum; + uint16 urg; +} hdr_tcp_t; + +static hdr_tcp_t HDR_TCP = {139, 139, 0, 0, 0x50, 0, 0, 0, 0}; + +void print_pcap_header(FILE *out) +{ + struct tcpdump_file_header h; + h.magic = TCPDUMP_MAGIC; + h.major = 2; + h.minor = 4; + h.zone = 0; + h.sigfigs = 0; + h.snaplen = 102400; /* As long packets as possible */ + h.linktype = 101; /* Raw IP */ + fwrite(&h, sizeof(struct tcpdump_file_header), 1, out); +} + +void print_pcap_packet(FILE *out, unsigned char *data, long length, long caplen) +{ + static int i = 0; + struct tcpdump_packet p; + i++; + p.ts.tv_usec = 0; + p.ts.tv_sec = 0; + p.caplen = caplen; + p.len = length; + fwrite(&p, sizeof(struct tcpdump_packet), 1, out); + fwrite(data, sizeof(unsigned char), caplen, out); +} + +void print_hex_packet(FILE *out, unsigned char *data, long length) +{ + long i,cur = 0; + while(cur < length) { + fprintf(out, "%06lX ", cur); + for(i = cur; i < length && i < cur + 16; i++) { + fprintf(out, "%02x ", data[i]); + } + + cur = i; + fprintf(out, "\n"); + } +} + +void print_netbios_packet(FILE *out, unsigned char *data, long length, long actual_length) +{ + unsigned char *newdata; long offset = 0; + long newlen; + + newlen = length+sizeof(HDR_IP)+sizeof(HDR_TCP); + newdata = malloc(newlen); + + HDR_IP.packet_length = htons(newlen); + HDR_TCP.window = htons(0x2000); + HDR_TCP.source_port = HDR_TCP.dest_port = htons(139); + + memcpy(newdata+offset, &HDR_IP, sizeof(HDR_IP));offset+=sizeof(HDR_IP); + memcpy(newdata+offset, &HDR_TCP, sizeof(HDR_TCP));offset+=sizeof(HDR_TCP); + memcpy(newdata+offset,data,length); + + print_pcap_packet(out, newdata, newlen, actual_length+offset); + free(newdata); +} + +unsigned char *curpacket = NULL; +long curpacket_len = 0; + +void read_log_msg(FILE *in, unsigned char **_buffer, long *buffersize, long *data_offset, long *data_length) +{ + unsigned char *buffer; + int tmp; long i; + assert(fscanf(in, " size=%ld\n", buffersize)); + *buffersize+=4; /* for netbios */ + buffer = malloc(*buffersize); + memset(buffer, 0, *buffersize); + /* NetBIOS */ + buffer[0] = 0x00; + buffer[1] = 0x00; + memcpy(buffer+2, &buffersize, 2); + buffer[4] = 0xFF; + buffer[5] = 'S'; + buffer[6] = 'M'; + buffer[7] = 'B'; + assert(fscanf(in, " smb_com=0x%x\n", &tmp)); buffer[smb_com] = tmp; + assert(fscanf(in, " smb_rcls=%d\n", &tmp)); buffer[smb_rcls] = tmp; + assert(fscanf(in, " smb_reh=%d\n", &tmp)); buffer[smb_reh] = tmp; + assert(fscanf(in, " smb_err=%d\n", &tmp)); memcpy(buffer+smb_err, &tmp, 2); + assert(fscanf(in, " smb_flg=%d\n", &tmp)); buffer[smb_flg] = tmp; + assert(fscanf(in, " smb_flg2=%d\n", &tmp)); memcpy(buffer+smb_flg2, &tmp, 2); + assert(fscanf(in, " smb_tid=%d\n", &tmp)); memcpy(buffer+smb_tid, &tmp, 2); + assert(fscanf(in, " smb_pid=%d\n", &tmp)); memcpy(buffer+smb_pid, &tmp, 2); + assert(fscanf(in, " smb_uid=%d\n", &tmp)); memcpy(buffer+smb_uid, &tmp, 2); + assert(fscanf(in, " smb_mid=%d\n", &tmp)); memcpy(buffer+smb_mid, &tmp, 2); + assert(fscanf(in, " smt_wct=%d\n", &tmp)); buffer[smb_wct] = tmp; + for(i = 0; i < buffer[smb_wct]; i++) { + assert(fscanf(in, " smb_vwv[%*2d]=%*5d (0x%X)\n", &tmp)); + memcpy(buffer+smb_vwv+i*2, &tmp, 2); + } + + *data_offset = smb_vwv+buffer[smb_wct]*2; + assert(fscanf(in, " smb_bcc=%ld\n", data_length)); buffer[(*data_offset)] = *data_length; + (*data_offset)+=2; + *_buffer = buffer; +} + +long read_log_data(FILE *in, unsigned char *buffer, long data_length) +{ + long i, addr; char real[2][16]; int ret; + unsigned char tmp; + for(i = 0; i < data_length; i++) { + if(i % 16 == 0){ + if(i != 0) { /* Read data after each line */ + assert(fscanf(in, "%8s %8s", real[0], real[1]) == 2); + } + ret = fscanf(in, " [%03lX]", &addr); + if(!ret) { + if(!quiet)fprintf(stderr, "Only first %ld bytes are logged, packet trace will be incomplete\nTry a higher log level\n", i); + return i-1; + } + assert(addr == i); + } + if(!fscanf(in, "%02lX", &tmp)) { + if(!quiet)fprintf(stderr, "Only first %ld bytes are logged, packet trace will be incomplete\nTry a higher log level\n", i-1); + return i-1; + } + buffer[i] = tmp; + } + return data_length; +} + +int main (int argc, char **argv) +{ + const char *infile, *outfile; + FILE *out, *in; + int opt; + poptContext pc; + char buffer[4096]; + long data_offset, data_length; + long data_bytes_read; + int in_packet = 0; + struct poptOption long_options[] = { + POPT_AUTOHELP + { "quiet", 'q', POPT_ARG_NONE, &quiet, 0, "Be quiet, don't output warnings" }, + { "hex", 'h', POPT_ARG_NONE, &hexformat, 0, "Output format readable by text2pcap" }, + POPT_TABLEEND + }; + + pc = poptGetContext(NULL, argc, (const char **) argv, long_options, + POPT_CONTEXT_KEEP_FIRST); + poptSetOtherOptionHelp(pc, "[ []]"); + + + while((opt = poptGetNextOpt(pc)) != -1) { + switch (opt) { + } + } + + poptGetArg(pc); /* Drop argv[0], the program name */ + + infile = poptGetArg(pc); + + if(infile) { + in = fopen(infile, "r"); + if(!in) { + perror("fopen"); + return 1; + } + } else in = stdin; + + outfile = poptGetArg(pc); + + if(outfile) { + out = fopen(outfile, "w+"); + if(!out) { + perror("fopen"); + fprintf(stderr, "Can't find %s, using stdout...\n", outfile); + } + } + + if(!outfile) out = stdout; + + if(!hexformat)print_pcap_header(out); + + while(!feof(in)) { + fgets(buffer, sizeof(buffer), in); + if(buffer[0] == '[') { /* Header */ + if(strstr(buffer, "show_msg")) { + in_packet++; + if(in_packet == 1)continue; + read_log_msg(in, &curpacket, &curpacket_len, &data_offset, &data_length); + } else if(in_packet && strstr(buffer, "dump_data")) { + data_bytes_read = read_log_data(in, curpacket+data_offset, data_length); + } else { + if(in_packet){ + if(hexformat) print_hex_packet(out, curpacket, curpacket_len); + else print_netbios_packet(out, curpacket, curpacket_len, data_bytes_read+data_offset); + free(curpacket); + } + in_packet = 0; + } + } + } + + return 0; +} diff --git a/source3/utils/net.c b/source3/utils/net.c index 8f6b09a3fa..e5c078da29 100644 --- a/source3/utils/net.c +++ b/source3/utils/net.c @@ -181,6 +181,27 @@ NTSTATUS connect_to_ipc_anonymous(struct cli_state **c, } } +/**************************************************************************** + Use the local machine's password for this session +****************************************************************************/ +int net_use_machine_password(void) +{ + char *user_name = NULL; + + if (!secrets_init()) { + d_printf("ERROR: Unable to open secrets database\n"); + exit(1); + } + + user_name = NULL; + opt_password = secrets_fetch_machine_password(opt_target_workgroup, NULL, NULL); + if (asprintf(&user_name, "%s$@%s", global_myname(), lp_realm()) == -1) { + return -1; + } + opt_user_name = user_name; + return 0; +} + BOOL net_find_server(unsigned flags, struct in_addr *server_ip, char **server_name) { @@ -321,7 +342,7 @@ static int net_join(int argc, const char **argv) if (net_ads_join(argc, argv) == 0) return 0; else - d_printf("ADS join did not work, trying RPC...\n"); + d_printf("ADS join did not work, falling back to RPC...\n"); } return net_rpc_join(argc, argv); } @@ -334,6 +355,31 @@ static int net_changetrustpw(int argc, const char **argv) return net_rpc_changetrustpw(argc, argv); } +static int net_changesecretpw(int argc, const char **argv) +{ + char *trust_pw; + uint32 sec_channel_type = SEC_CHAN_WKSTA; + + if(opt_force) { + trust_pw = getpass("Enter machine password: "); + + if (!secrets_store_machine_password(trust_pw, lp_workgroup(), sec_channel_type)) { + d_printf("Unable to write the machine account password in the secrets database"); + return 1; + } + else { + d_printf("Modified trust account password in secrets database\n"); + } + } + else { + d_printf("Machine account password change requires the -f flag.\n"); + d_printf("Do NOT use this function unless you know what it does!\n"); + d_printf("This function will change the ADS Domain member machine account password in the secrets.tdb file!\n"); + } + + return 0; +} + static int net_share(int argc, const char **argv) { if (net_rpc_check(0)) @@ -416,6 +462,50 @@ static int net_getdomainsid(int argc, const char **argv) return 0; } +#ifdef WITH_FAKE_KASERVER + +int net_afskey_usage(int argc, const char **argv) +{ + d_printf(" net afskey filename\n" + "\tImports a OpenAFS KeyFile into our secrets.tdb\n\n"); + return -1; +} + +static int net_afskey(int argc, const char **argv) +{ + int fd; + struct afs_keyfile keyfile; + + if (argc != 1) { + d_printf("usage: 'net afskey '\n"); + return -1; + } + + if (!secrets_init()) { + d_printf("Could not open secrets.tdb\n"); + return -1; + } + + if ((fd = open(argv[0], O_RDONLY, 0)) < 0) { + d_printf("Could not open %s\n", argv[0]); + return -1; + } + + if (read(fd, &keyfile, sizeof(keyfile)) != sizeof(keyfile)) { + d_printf("Could not read keyfile\n"); + return -1; + } + + if (!secrets_store_afs_keyfile(afs_cell(), &keyfile)) { + d_printf("Could not write keyfile to secrets.tdb\n"); + return -1; + } + + return 0; +} + +#endif /* WITH_FAKE_KASERVER */ + static uint32 get_maxrid(void) { SAM_ACCOUNT *pwd = NULL; @@ -516,6 +606,7 @@ static struct functable net_func[] = { {"SERVICE", net_rap_service}, {"PASSWORD", net_rap_password}, {"CHANGETRUSTPW", net_changetrustpw}, + {"CHANGESECRETPW", net_changesecretpw}, {"TIME", net_time}, {"LOOKUP", net_lookup}, {"JOIN", net_join}, @@ -525,6 +616,9 @@ static struct functable net_func[] = { {"GETDOMAINSID", net_getdomainsid}, {"MAXRID", net_maxrid}, {"IDMAP", net_idmap}, +#ifdef WITH_FAKE_KASERVER + {"AFSKEY", net_afskey}, +#endif {"HELP", net_help}, {NULL, NULL} @@ -649,23 +743,10 @@ static struct functable net_func[] = { sec_init(); if (opt_machine_pass) { - char *user = NULL; /* it is very useful to be able to make ads queries as the machine account for testing purposes and for domain leave */ - if (!secrets_init()) { - d_printf("ERROR: Unable to open secrets database\n"); - exit(1); - } - - opt_password = secrets_fetch_machine_password(opt_workgroup, NULL, NULL); - - asprintf(&user,"%s$", global_myname()); - opt_user_name = user; - if (!opt_password) { - d_printf("ERROR: Unable to fetch machine password\n"); - exit(1); - } + net_use_machine_password(); } if (!opt_password) { diff --git a/source3/utils/net_ads.c b/source3/utils/net_ads.c index 631e235127..3b955742d8 100644 --- a/source3/utils/net_ads.c +++ b/source3/utils/net_ads.c @@ -127,9 +127,14 @@ static ADS_STRUCT *ads_startup(void) ADS_STATUS status; BOOL need_password = False; BOOL second_time = False; - char *cp; + char *cp; - ads = ads_init(NULL, opt_target_workgroup, opt_host); + /* lp_realm() should be handled by a command line param, + However, the join requires that realm be set in smb.conf + and compares our realm with the remote server's so this is + ok until someone needs more flexibility */ + + ads = ads_init(lp_realm(), opt_target_workgroup, opt_host); if (!opt_user_name) { opt_user_name = "administrator"; @@ -579,10 +584,7 @@ static int net_ads_leave(int argc, const char **argv) } if (!opt_password) { - char *user_name; - asprintf(&user_name, "%s$", global_myname()); - opt_password = secrets_fetch_machine_password(opt_target_workgroup, NULL, NULL); - opt_user_name = user_name; + net_use_machine_password(); } if (!(ads = ads_startup())) { @@ -603,7 +605,6 @@ static int net_ads_leave(int argc, const char **argv) static int net_ads_join_ok(void) { - char *user_name; ADS_STRUCT *ads = NULL; if (!secrets_init()) { @@ -611,9 +612,7 @@ static int net_ads_join_ok(void) return -1; } - asprintf(&user_name, "%s$", global_myname()); - opt_user_name = user_name; - opt_password = secrets_fetch_machine_password(opt_target_workgroup, NULL, NULL); + net_use_machine_password(); if (!(ads = ads_startup())) { return -1; @@ -648,6 +647,7 @@ int net_ads_join(int argc, const char **argv) ADS_STRUCT *ads; ADS_STATUS rc; char *password; + char *machine_account = NULL; char *tmp_password; const char *org_unit = "Computers"; char *dn; @@ -656,6 +656,8 @@ int net_ads_join(int argc, const char **argv) char *ou_str; uint32 sec_channel_type = SEC_CHAN_WKSTA; uint32 account_type = UF_WORKSTATION_TRUST_ACCOUNT; + char *short_domain_name = NULL; + TALLOC_CTX *ctx = NULL; if (argc > 0) org_unit = argv[0]; @@ -669,6 +671,16 @@ int net_ads_join(int argc, const char **argv) if (!(ads = ads_startup())) return -1; + if (!*lp_realm()) { + d_printf("realm must be set in in smb.conf for ADS join to succeed.\n"); + return -1; + } + + if (strcmp(ads->config.realm, lp_realm()) != 0) { + d_printf("realm of remote server (%s) and realm in smb.conf (%s) DO NOT match. Aborting join\n", ads->config.realm, lp_realm()); + return -1; + } + ou_str = ads_ou_string(org_unit); asprintf(&dn, "%s,%s", ou_str, ads->config.bind_path); free(ou_str); @@ -696,16 +708,47 @@ int net_ads_join(int argc, const char **argv) rc = ads_domain_sid(ads, &dom_sid); if (!ADS_ERR_OK(rc)) { - d_printf("ads_domain_sid: %s\n", ads_errstr(rc)); + d_printf("ads_domain_sid: %s\n", ads_errstr(rc)); + return -1; + } + + if (asprintf(&machine_account, "%s$", global_myname()) == -1) { + d_printf("asprintf failed\n"); return -1; } - rc = ads_set_machine_password(ads, global_myname(), password); + rc = ads_set_machine_password(ads, machine_account, password); if (!ADS_ERR_OK(rc)) { d_printf("ads_set_machine_password: %s\n", ads_errstr(rc)); return -1; } - + + /* make sure we get the right workgroup */ + + if ( !(ctx = talloc_init("net ads join")) ) { + d_printf("talloc_init() failed!\n"); + return -1; + } + + rc = ads_workgroup_name(ads, ctx, &short_domain_name); + if ( ADS_ERR_OK(rc) ) { + if ( !strequal(lp_workgroup(), short_domain_name) ) { + d_printf("The workgroup in smb.conf does not match the short\n"); + d_printf("domain name obtained from the server.\n"); + d_printf("Using the name [%s] from the server.\n", short_domain_name); + d_printf("You should set \"workgroup = %s\" in smb.conf.\n", short_domain_name); + } + } + else + short_domain_name = lp_workgroup(); + + d_printf("Using short domain name -- %s\n", short_domain_name); + + /* HACK ALRET! Store the sid and password under bother the lp_workgroup() + value from smb.conf and the string returned from the server. The former is + neede to bootstrap winbindd's first connection to the DC to get the real + short domain name --jerry */ + if (!secrets_store_domain_sid(lp_workgroup(), &dom_sid)) { DEBUG(1,("Failed to save domain sid\n")); return -1; @@ -716,10 +759,22 @@ int net_ads_join(int argc, const char **argv) return -1; } - d_printf("Joined '%s' to realm '%s'\n", global_myname(), ads->config.realm); + if (!secrets_store_domain_sid(short_domain_name, &dom_sid)) { + DEBUG(1,("Failed to save domain sid\n")); + return -1; + } - free(password); + if (!secrets_store_machine_password(password, short_domain_name, sec_channel_type)) { + DEBUG(1,("Failed to save machine password\n")); + return -1; + } + + d_printf("Joined '%s' to realm '%s'\n", global_myname(), ads->config.realm); + SAFE_FREE(password); + SAFE_FREE(machine_account); + if ( ctx ) + talloc_destroy(ctx); return 0; } @@ -1020,17 +1075,13 @@ int net_ads_changetrustpw(int argc, const char **argv) char *host_principal; char *hostname; ADS_STATUS ret; - char *user_name; if (!secrets_init()) { DEBUG(1,("Failed to initialise secrets database\n")); return -1; } - asprintf(&user_name, "%s$", global_myname()); - opt_user_name = user_name; - - opt_password = secrets_fetch_machine_password(opt_target_workgroup, NULL, NULL); + net_use_machine_password(); use_in_memory_ccache(); diff --git a/source3/utils/net_ads_cldap.c b/source3/utils/net_ads_cldap.c index e74e4b5a4c..595e6e9434 100644 --- a/source3/utils/net_ads_cldap.c +++ b/source3/utils/net_ads_cldap.c @@ -240,7 +240,7 @@ static int recv_cldap_netlogon(int sock, struct cldap_netlogon_reply *reply) return -1; } - p = os3.data; + p = (char *)os3.data; reply->type = IVAL(p, 0); p += 4; reply->flags = IVAL(p, 0); p += 4; @@ -248,25 +248,25 @@ static int recv_cldap_netlogon(int sock, struct cldap_netlogon_reply *reply) memcpy(&reply->guid.info, p, GUID_SIZE); p += GUID_SIZE; - p += pull_netlogon_string(reply->forest, p, os3.data); - p += pull_netlogon_string(reply->unk0, p, os3.data); - p += pull_netlogon_string(reply->domain, p, os3.data); - p += pull_netlogon_string(reply->hostname, p, os3.data); - p += pull_netlogon_string(reply->netbios_domain, p, os3.data); - p += pull_netlogon_string(reply->unk1, p, os3.data); - p += pull_netlogon_string(reply->netbios_hostname, p, os3.data); - p += pull_netlogon_string(reply->unk2, p, os3.data); + p += pull_netlogon_string(reply->forest, p, (const char *)os3.data); + p += pull_netlogon_string(reply->unk0, p, (const char *)os3.data); + p += pull_netlogon_string(reply->domain, p, (const char *)os3.data); + p += pull_netlogon_string(reply->hostname, p, (const char *)os3.data); + p += pull_netlogon_string(reply->netbios_domain, p, (const char *)os3.data); + p += pull_netlogon_string(reply->unk1, p, (const char *)os3.data); + p += pull_netlogon_string(reply->netbios_hostname, p, (const char *)os3.data); + p += pull_netlogon_string(reply->unk2, p, (const char *)os3.data); if (reply->type == SAMLOGON_AD_R) { - p += pull_netlogon_string(reply->user_name, p, os3.data); + p += pull_netlogon_string(reply->user_name, p, (const char *)os3.data); } else { *reply->user_name = 0; } - p += pull_netlogon_string(reply->unk3, p, os3.data); - p += pull_netlogon_string(reply->site_name, p, os3.data); - p += pull_netlogon_string(reply->unk4, p, os3.data); - p += pull_netlogon_string(reply->site_name_2, p, os3.data); + p += pull_netlogon_string(reply->unk3, p, (const char *)os3.data); + p += pull_netlogon_string(reply->site_name, p, (const char *)os3.data); + p += pull_netlogon_string(reply->unk4, p, (const char *)os3.data); + p += pull_netlogon_string(reply->site_name_2, p, (const char *)os3.data); reply->version = IVAL(p, 0); reply->lmnt_token = SVAL(p, 4); diff --git a/source3/utils/net_groupmap.c b/source3/utils/net_groupmap.c index 8831839e4e..9937145230 100644 --- a/source3/utils/net_groupmap.c +++ b/source3/utils/net_groupmap.c @@ -252,11 +252,21 @@ static int net_groupmap_add(int argc, const char **argv) } } - if ( !unixgrp[0] || (!rid && !string_sid[0]) ) { + if ( !unixgrp[0] ) { d_printf("Usage: net groupmap add {rid=|sid=} unixgroup= [type=] [ntgroup=] [comment=]\n"); return -1; } + if ( (gid = nametogid(unixgrp)) == (gid_t)-1 ) { + d_printf("Can't lookup UNIX group %s\n", ntgroup); + return -1; + } + + if ( (rid == 0) && (string_sid[0] == '\0') ) { + d_printf("No rid or sid specified, choosing algorithmic mapping\n"); + rid = pdb_gid_to_group_rid(gid); + } + /* append the rid to our own domain/machine SID if we don't have a full SID */ if ( !string_sid[0] ) { sid_copy(&sid, get_global_sam_sid()); @@ -267,11 +277,6 @@ static int net_groupmap_add(int argc, const char **argv) if (ntcomment[0]) fstrcpy(ntcomment, "Local Unix group"); - if ( (gid = nametogid(unixgrp)) == (gid_t)-1 ) { - d_printf("Can't lookup UNIX group %s\n", ntgroup); - return -1; - } - if ( !ntgroup[0] ) fstrcpy( ntgroup, unixgrp ); diff --git a/source3/utils/net_help.c b/source3/utils/net_help.c index 1f3afb1690..95116a4d2a 100644 --- a/source3/utils/net_help.c +++ b/source3/utils/net_help.c @@ -47,7 +47,7 @@ int net_common_flags_usage(int argc, const char **argv) d_printf("\t-U or --user=\t\tuser name\n"); d_printf("\t-s or --configfile=\t\tpathname of smb.conf file\n"); d_printf("\t-l or --long\t\t\tDisplay full information\n"); - d_printf("\t-V or --version\t\tPrint samba version information\n"); + d_printf("\t-V or --version\t\t\tPrint samba version information\n"); d_printf("\t-P or --machine-pass\t\tAuthenticate as machine account\n"); return -1; } @@ -60,7 +60,8 @@ 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 GETLOCALSID SETLOCALSID\n"); +" GROUPMEMBER ADMIN SERVICE PASSWORD TIME LOOKUP GETLOCALSID SETLOCALSID\n"\ +" CHANGESCRETPW\n"); return -1; } @@ -156,6 +157,8 @@ static int net_usage(int argc, const char **argv) " 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"\ + " net changesecretpw\tto change the machine password in the local secrets database only\n"\ + " \tthis requires the -f flag as a safety barrier\n"\ "\n"\ " net ads \tto run ADS commands\n"\ " net rap \tto run RAP (pre-RPC) commands\n"\ @@ -193,6 +196,9 @@ int net_help(int argc, const char **argv) {"PASSWORD", net_rap_password_usage}, {"TIME", net_time_usage}, {"LOOKUP", net_lookup_usage}, +#ifdef WITH_FAKE_KASERVER + {"AFSKEY", net_afskey_usage}, +#endif {"HELP", help_usage}, {NULL, NULL}}; diff --git a/source3/utils/net_lookup.c b/source3/utils/net_lookup.c index 8456da4e0c..cef0ea5fbe 100644 --- a/source3/utils/net_lookup.c +++ b/source3/utils/net_lookup.c @@ -23,7 +23,7 @@ int net_lookup_usage(int argc, const char **argv) { d_printf( -" net lookup host HOSTNAME \n\tgives IP for a hostname\n\n" +" net lookup [host] HOSTNAME[#]\n\tgives IP for a hostname\n\n" " net lookup ldap [domain]\n\tgives IP of domain's ldap server\n\n" " net lookup kdc [realm]\n\tgives IP of realm's kerberos KDC\n\n" " net lookup dc [domain]\n\tgives IP of domains Domain Controllers\n\n" @@ -37,14 +37,22 @@ static int net_lookup_host(int argc, const char **argv) { struct in_addr ip; int name_type = 0x20; + const char *name = argv[0]; + char *p; - if (argc == 0) return net_lookup_usage(argc, argv); - if (argc > 1) name_type = strtol(argv[1], NULL, 0); + if (argc == 0) + return net_lookup_usage(argc, argv); - if (!resolve_name(argv[0], &ip, name_type)) { + p = strchr_m(name,'#'); + if (p) { + *p = '\0'; + sscanf(++p,"%x",&name_type); + } + + if (!resolve_name(name, &ip, name_type)) { /* we deliberately use DEBUG() here to send it to stderr so scripts aren't mucked up */ - DEBUG(0,("Didn't find %s#%02x\n", argv[0], name_type)); + DEBUG(0,("Didn't find %s#%02x\n", name, name_type)); return -1; } @@ -221,7 +229,9 @@ static int net_lookup_kdc(int argc, const char **argv) /* lookup hosts or IP addresses using internal samba lookup fns */ int net_lookup(int argc, const char **argv) { - struct functable func[] = { + int i; + + struct functable table[] = { {"HOST", net_lookup_host}, {"LDAP", net_lookup_ldap}, {"DC", net_lookup_dc}, @@ -230,5 +240,19 @@ int net_lookup(int argc, const char **argv) {NULL, NULL} }; - return net_run_function(argc, argv, func, net_lookup_usage); + if (argc < 1) { + d_printf("\nUsage: \n"); + return net_lookup_usage(argc, argv); + } + for (i=0; table[i].funcname; i++) { + if (StrCaseCmp(argv[0], table[i].funcname) == 0) + return table[i].fn(argc-1, argv+1); + } + + /* Default to lookup a hostname so 'net lookup foo#1b' can be + used instead of 'net lookup host foo#1b'. The host syntax + is a bit confusing as non #00 names can't really be + considered hosts as such. */ + + return net_lookup_host(argc, argv); } diff --git a/source3/utils/net_rpc.c b/source3/utils/net_rpc.c index 890d4a012b..fefc5af365 100644 --- a/source3/utils/net_rpc.c +++ b/source3/utils/net_rpc.c @@ -84,7 +84,14 @@ static DOM_SID *net_get_remote_domain_sid(struct cli_state *cli) result = cli_lsa_query_info_policy(cli, mem_ctx, &pol, info_class, domain_name, domain_sid); if (!NT_STATUS_IS_OK(result)) { - goto error; + error: + fprintf(stderr, "could not obtain sid for domain %s\n", cli->domain); + + if (!NT_STATUS_IS_OK(result)) { + fprintf(stderr, "error: %s\n", nt_errstr(result)); + } + + exit(1); } cli_lsa_close(cli, mem_ctx, &pol); @@ -92,15 +99,6 @@ static DOM_SID *net_get_remote_domain_sid(struct cli_state *cli) talloc_destroy(mem_ctx); return domain_sid; - - error: - fprintf(stderr, "could not obtain sid for domain %s\n", cli->domain); - - if (!NT_STATUS_IS_OK(result)) { - fprintf(stderr, "error: %s\n", nt_errstr(result)); - } - - exit(1); } /** @@ -1709,8 +1707,13 @@ static NTSTATUS rpc_trustdom_add_internals(const DOM_SID *domain_sid, struct cli static int rpc_trustdom_add(int argc, const char **argv) { - return run_rpc_command(NULL, PI_SAMR, 0, rpc_trustdom_add_internals, - argc, argv); + if (argc > 0) { + return run_rpc_command(NULL, PI_SAMR, 0, rpc_trustdom_add_internals, + argc, argv); + } else { + d_printf("Usage: net rpc trustdom add \n"); + return -1; + } } @@ -1726,6 +1729,7 @@ static int rpc_trustdom_add(int argc, const char **argv) static int rpc_trustdom_del(int argc, const char **argv) { d_printf("Sorry, not yet implemented.\n"); + d_printf("Use 'smbpasswd -x -i' instead.\n"); return -1; } @@ -1782,7 +1786,7 @@ static int rpc_trustdom_establish(int argc, const char **argv) /* find the domain controller */ if (!net_find_pdc(&server_ip, pdc_name, domain_name)) { - DEBUG(0, ("Coulnd find domain controller for domain %s\n", domain_name)); + DEBUG(0, ("Couldn't find domain controller for domain %s\n", domain_name)); return -1; } @@ -1988,8 +1992,8 @@ static int rpc_trustdom_list(int argc, const char **argv) POLICY_HND connect_hnd; /* trusted domains listing variables */ - int enum_ctx = 0; - int num_domains, i, pad_len, col_len = 20; + unsigned int num_domains, enum_ctx = 0; + int i, pad_len, col_len = 20; DOM_SID *domain_sids; char **trusted_dom_names; fstring pdc_name, dummy; diff --git a/source3/utils/net_rpc_samsync.c b/source3/utils/net_rpc_samsync.c index 9eadbbbade..ed69f8a326 100644 --- a/source3/utils/net_rpc_samsync.c +++ b/source3/utils/net_rpc_samsync.c @@ -550,7 +550,11 @@ fetch_group_info(uint32 rid, SAM_GROUP_INFO *delta) map.sid = group_sid; map.sid_name_use = SID_NAME_DOM_GRP; fstrcpy(map.nt_name, name); - fstrcpy(map.comment, comment); + if (delta->hdr_grp_desc.buffer) { + fstrcpy(map.comment, comment); + } else { + fstrcpy(map.comment, ""); + } if (insert) pdb_add_group_mapping_entry(&map); @@ -911,9 +915,40 @@ fetch_sam_entry(SAM_DELTA_HDR *hdr_delta, SAM_DELTA_CTR *delta, fetch_alias_mem(hdr_delta->target_rid, &delta->als_mem_info, dom_sid); break; + /* The following types are recognised but not handled */ case SAM_DELTA_DOMAIN_INFO: d_printf("SAM_DELTA_DOMAIN_INFO not handled\n"); break; + case SAM_DELTA_RENAME_GROUP: + d_printf("SAM_DELTA_RENAME_GROUP not handled\n"); + break; + case SAM_DELTA_RENAME_USER: + d_printf("SAM_DELTA_RENAME_USER not handled\n"); + break; + case SAM_DELTA_RENAME_ALIAS: + d_printf("SAM_DELTA_RENAME_ALIAS not handled\n"); + break; + case SAM_DELTA_POLICY_INFO: + d_printf("SAM_DELTA_POLICY_INFO not handled\n"); + break; + case SAM_DELTA_TRUST_DOMS: + d_printf("SAM_DELTA_TRUST_DOMS not handled\n"); + break; + case SAM_DELTA_PRIVS_INFO: + d_printf("SAM_DELTA_PRIVS_INFO not handled\n"); + break; + case SAM_DELTA_SECRET_INFO: + d_printf("SAM_DELTA_SECRET_INFO not handled\n"); + break; + case SAM_DELTA_DELETE_GROUP: + d_printf("SAM_DELTA_DELETE_GROUP not handled\n"); + break; + case SAM_DELTA_DELETE_USER: + d_printf("SAM_DELTA_DELETE_USER not handled\n"); + break; + case SAM_DELTA_MODIFIED_COUNT: + d_printf("SAM_DELTA_MODIFIED_COUNT not handled\n"); + break; default: d_printf("Unknown delta record type %d\n", hdr_delta->type); break; diff --git a/source3/utils/nmblookup.c b/source3/utils/nmblookup.c index d2c5cbc00e..3c5a22841e 100644 --- a/source3/utils/nmblookup.c +++ b/source3/utils/nmblookup.c @@ -109,7 +109,7 @@ static void do_node_status(int fd, const char *name, int type, struct in_addr ip status = node_status_query(fd,&nname,ip, &count); if (status) { for (i=0;idata, MIN(challenge->length, 8)); @@ -296,7 +310,7 @@ static void manage_squid_ntlmssp_request(enum squid_mode squid_mode, } DEBUG(10, ("got NTLMSSP packet:\n")); - dump_data(10, request.data, request.length); + dump_data(10, (const char *)request.data, request.length); nt_status = ntlmssp_server_update(ntlmssp_state, request, &reply); @@ -347,27 +361,35 @@ static void manage_squid_basic_request(enum squid_mode squid_mode, static void offer_gss_spnego_mechs(void) { DATA_BLOB token; - ASN1_DATA asn1; SPNEGO_DATA spnego; ssize_t len; char *reply_base64; + pstring principal; + pstring myname_lower; + ZERO_STRUCT(spnego); + pstrcpy(myname_lower, global_myname()); + strlower_m(myname_lower); + + pstr_sprintf(principal, "%s$@%s", myname_lower, lp_realm()); + /* Server negTokenInit (mech offerings) */ spnego.type = SPNEGO_NEG_TOKEN_INIT; - spnego.negTokenInit.mechTypes = smb_xmalloc(sizeof(char *) * 2); + spnego.negTokenInit.mechTypes = smb_xmalloc(sizeof(char *) * 3); +#ifdef HAVE_KRB5 + spnego.negTokenInit.mechTypes[0] = smb_xstrdup(OID_KERBEROS5_OLD); + spnego.negTokenInit.mechTypes[1] = smb_xstrdup(OID_NTLMSSP); + spnego.negTokenInit.mechTypes[2] = NULL; +#else spnego.negTokenInit.mechTypes[0] = smb_xstrdup(OID_NTLMSSP); spnego.negTokenInit.mechTypes[1] = NULL; +#endif + - ZERO_STRUCT(asn1); - asn1_push_tag(&asn1, ASN1_SEQUENCE(0)); - asn1_push_tag(&asn1, ASN1_CONTEXT(0)); - asn1_write_GeneralString(&asn1, "NONE"); - asn1_pop_tag(&asn1); - asn1_pop_tag(&asn1); - spnego.negTokenInit.mechListMIC = data_blob(asn1.data, asn1.length); - asn1_free(&asn1); + spnego.negTokenInit.mechListMIC = data_blob(principal, + strlen(principal)); len = write_spnego_data(&token, &spnego); free_spnego_data(&spnego); @@ -391,11 +413,14 @@ static void manage_gss_spnego_request(enum squid_mode squid_mode, char *buf, int length) { static NTLMSSP_STATE *ntlmssp_state = NULL; - SPNEGO_DATA spnego; - DATA_BLOB request, token; + SPNEGO_DATA request, response; + DATA_BLOB token; NTSTATUS status; ssize_t len; + char *user = NULL; + char *domain = NULL; + const char *reply_code; char *reply_base64; pstring reply_argument; @@ -432,9 +457,9 @@ static void manage_gss_spnego_request(enum squid_mode squid_mode, return; } - request = base64_decode_data_blob(buf + 3); - len = read_spnego_data(request, &spnego); - data_blob_free(&request); + token = base64_decode_data_blob(buf + 3); + len = read_spnego_data(token, &request); + data_blob_free(&token); if (len == -1) { DEBUG(1, ("GSS-SPNEGO query [%s] invalid", buf)); @@ -442,100 +467,159 @@ static void manage_gss_spnego_request(enum squid_mode squid_mode, return; } - if (spnego.type == SPNEGO_NEG_TOKEN_INIT) { + if (request.type == SPNEGO_NEG_TOKEN_INIT) { /* Second request from Client. This is where the client offers its mechanism to use. We currently only support NTLMSSP, the decision for Kerberos would be taken here. */ - if ( (spnego.negTokenInit.mechTypes == NULL) || - (spnego.negTokenInit.mechTypes[0] == NULL) ) { + if ( (request.negTokenInit.mechTypes == NULL) || + (request.negTokenInit.mechTypes[0] == NULL) ) { DEBUG(1, ("Client did not offer any mechanism")); x_fprintf(x_stdout, "BH\n"); return; } - if ( strcmp(spnego.negTokenInit.mechTypes[0], OID_NTLMSSP) != 0 ) { - DEBUG(1, ("Client did not choose NTLMSSP but %s\n", - spnego.negTokenInit.mechTypes[0])); - x_fprintf(x_stdout, "BH\n"); - return; - } + if (strcmp(request.negTokenInit.mechTypes[0], OID_NTLMSSP) == 0) { - if ( spnego.negTokenInit.mechToken.data == NULL ) { - DEBUG(1, ("Client did not provide NTLMSSP data\n")); - x_fprintf(x_stdout, "BH\n"); - return; - } + if ( request.negTokenInit.mechToken.data == NULL ) { + DEBUG(1, ("Client did not provide NTLMSSP data\n")); + x_fprintf(x_stdout, "BH\n"); + return; + } - if ( ntlmssp_state != NULL ) { - DEBUG(1, ("Client wants a new NTLMSSP challenge, but " - "already got one\n")); - x_fprintf(x_stdout, "BH\n"); - ntlmssp_server_end(&ntlmssp_state); - return; + if ( ntlmssp_state != NULL ) { + DEBUG(1, ("Client wants a new NTLMSSP challenge, but " + "already got one\n")); + x_fprintf(x_stdout, "BH\n"); + ntlmssp_server_end(&ntlmssp_state); + return; + } + + ntlmssp_server_start(&ntlmssp_state); + ntlmssp_state->check_password = winbind_pw_check; + ntlmssp_state->get_domain = get_winbind_domain; + ntlmssp_state->get_global_myname = get_winbind_netbios_name; + + DEBUG(10, ("got NTLMSSP packet:\n")); + dump_data(10, (const char *)request.negTokenInit.mechToken.data, + request.negTokenInit.mechToken.length); + + response.type = SPNEGO_NEG_TOKEN_TARG; + response.negTokenTarg.supportedMech = strdup(OID_NTLMSSP); + response.negTokenTarg.mechListMIC = data_blob(NULL, 0); + + status = ntlmssp_server_update(ntlmssp_state, + request.negTokenInit.mechToken, + &response.negTokenTarg.responseToken); } - ntlmssp_server_start(&ntlmssp_state); - ntlmssp_state->check_password = winbind_pw_check; - ntlmssp_state->get_domain = get_winbind_domain; - ntlmssp_state->get_global_myname = get_winbind_netbios_name; +#ifdef HAVE_KRB5 + if (strcmp(request.negTokenInit.mechTypes[0], OID_KERBEROS5_OLD) == 0) { - DEBUG(10, ("got NTLMSSP packet:\n")); - dump_data(10, spnego.negTokenInit.mechToken.data, - spnego.negTokenInit.mechToken.length); + char *principal; + DATA_BLOB auth_data; + DATA_BLOB ap_rep; + uint8 session_key[16]; - free_spnego_data(&spnego); + if ( request.negTokenInit.mechToken.data == NULL ) { + DEBUG(1, ("Client did not provide Kerberos data\n")); + x_fprintf(x_stdout, "BH\n"); + return; + } - spnego.type = SPNEGO_NEG_TOKEN_TARG; - spnego.negTokenTarg.negResult = SPNEGO_ACCEPT_INCOMPLETE; - spnego.negTokenTarg.supportedMech = strdup(OID_NTLMSSP); + response.type = SPNEGO_NEG_TOKEN_TARG; + response.negTokenTarg.supportedMech = strdup(OID_KERBEROS5_OLD); + response.negTokenTarg.mechListMIC = data_blob(NULL, 0); + response.negTokenTarg.responseToken = data_blob(NULL, 0); - status = ntlmssp_server_update(ntlmssp_state, - spnego.negTokenInit.mechToken, - &spnego.negTokenTarg.responseToken); + status = ads_verify_ticket(lp_realm(), + &request.negTokenInit.mechToken, + &principal, &auth_data, &ap_rep, + session_key); - } else { + /* Now in "principal" we have the name we are + authenticated as. */ + + if (NT_STATUS_IS_OK(status)) { + + domain = strchr(principal, '@'); - /* spnego.type == SPNEGO_NEG_TOKEN_TARG */ + if (domain == NULL) { + DEBUG(1, ("Did not get a valid principal " + "from ads_verify_ticket\n")); + x_fprintf(x_stdout, "BH\n"); + return; + } - DATA_BLOB response; + *domain++ = '\0'; + domain = strdup(domain); + user = strdup(principal); - if (spnego.negTokenTarg.responseToken.data == NULL) { - DEBUG(1, ("Got a negTokenArg without a responseToken!\n")); + data_blob_free(&ap_rep); + data_blob_free(&auth_data); + + SAFE_FREE(principal); + } + } +#endif + + } else { + + if ( (request.negTokenTarg.supportedMech == NULL) || + ( strcmp(request.negTokenTarg.supportedMech, OID_NTLMSSP) != 0 ) ) { + /* Kerberos should never send a negTokenTarg, OID_NTLMSSP + is the only one we support that sends this stuff */ + DEBUG(1, ("Got a negTokenTarg for something non-NTLMSSP: %s\n", + request.negTokenTarg.supportedMech)); x_fprintf(x_stdout, "BH\n"); return; } - status = ntlmssp_server_update(ntlmssp_state, - spnego.negTokenTarg.responseToken, - &response); + if (request.negTokenTarg.responseToken.data == NULL) { + DEBUG(1, ("Got a negTokenTarg without a responseToken!\n")); + x_fprintf(x_stdout, "BH\n"); + return; + } - data_blob_free(&spnego.negTokenTarg.responseToken); + status = ntlmssp_server_update(ntlmssp_state, + request.negTokenTarg.responseToken, + &response.negTokenTarg.responseToken); - spnego.negTokenTarg.responseToken = response; + response.type = SPNEGO_NEG_TOKEN_TARG; + response.negTokenTarg.supportedMech = strdup(OID_NTLMSSP); + response.negTokenTarg.mechListMIC = data_blob(NULL, 0); + if (NT_STATUS_IS_OK(status)) { + user = strdup(ntlmssp_state->user); + domain = strdup(ntlmssp_state->domain); + ntlmssp_server_end(&ntlmssp_state); + } } + free_spnego_data(&request); + if (NT_STATUS_IS_OK(status)) { - spnego.negTokenTarg.negResult = SPNEGO_ACCEPT_COMPLETED; + response.negTokenTarg.negResult = SPNEGO_ACCEPT_COMPLETED; reply_code = "AF"; - pstr_sprintf(reply_argument, "%s\\%s", - ntlmssp_state->domain, ntlmssp_state->user); + pstr_sprintf(reply_argument, "%s\\%s", domain, user); } else if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { - spnego.negTokenTarg.negResult = SPNEGO_ACCEPT_INCOMPLETE; + response.negTokenTarg.negResult = SPNEGO_ACCEPT_INCOMPLETE; reply_code = "TT"; pstr_sprintf(reply_argument, "*"); } else { - spnego.negTokenTarg.negResult = SPNEGO_REJECT; + response.negTokenTarg.negResult = SPNEGO_REJECT; reply_code = "NA"; pstrcpy(reply_argument, nt_errstr(status)); } - len = write_spnego_data(&token, &spnego); - free_spnego_data(&spnego); + SAFE_FREE(user); + SAFE_FREE(domain); + + len = write_spnego_data(&token, &response); + free_spnego_data(&response); if (len == -1) { DEBUG(1, ("Could not write SPNEGO data blob\n")); @@ -551,16 +635,12 @@ static void manage_gss_spnego_request(enum squid_mode squid_mode, SAFE_FREE(reply_base64); data_blob_free(&token); - if (NT_STATUS_IS_OK(status)) { - ntlmssp_server_end(&ntlmssp_state); - } - return; } static NTLMSSP_CLIENT_STATE *client_ntlmssp_state = NULL; -static void manage_client_ntlmssp_init(SPNEGO_DATA spnego) +static BOOL manage_client_ntlmssp_init(SPNEGO_DATA spnego) { NTSTATUS status; DATA_BLOB null_blob = data_blob(NULL, 0); @@ -573,14 +653,12 @@ static void manage_client_ntlmssp_init(SPNEGO_DATA spnego) if (client_ntlmssp_state != NULL) { DEBUG(1, ("Request for initial SPNEGO request where " "we already have a state\n")); - x_fprintf(x_stdout, "BH\n"); - return; + return False; } if ( (opt_username == NULL) || (opt_domain == NULL) ) { DEBUG(1, ("Need username and domain for NTLMSSP\n")); - x_fprintf(x_stdout, "BH\n"); - return; + return False; } if (opt_password == NULL) { @@ -591,7 +669,7 @@ static void manage_client_ntlmssp_init(SPNEGO_DATA spnego) DEBUG(10, ("Requesting password\n")); x_fprintf(x_stdout, "PW\n"); - return; + return True; } status = ntlmssp_client_start(&client_ntlmssp_state); @@ -599,9 +677,8 @@ static void manage_client_ntlmssp_init(SPNEGO_DATA spnego) if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("Could not start NTLMSSP client: %s\n", nt_errstr(status))); - x_fprintf(x_stdout, "BH\n"); ntlmssp_client_end(&client_ntlmssp_state); - return; + return False; } status = ntlmssp_set_username(client_ntlmssp_state, opt_username); @@ -609,9 +686,8 @@ static void manage_client_ntlmssp_init(SPNEGO_DATA spnego) if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("Could not set username: %s\n", nt_errstr(status))); - x_fprintf(x_stdout, "BH\n"); ntlmssp_client_end(&client_ntlmssp_state); - return; + return False; } status = ntlmssp_set_domain(client_ntlmssp_state, opt_domain); @@ -619,9 +695,8 @@ static void manage_client_ntlmssp_init(SPNEGO_DATA spnego) if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("Could not set domain: %s\n", nt_errstr(status))); - x_fprintf(x_stdout, "BH\n"); ntlmssp_client_end(&client_ntlmssp_state); - return; + return False; } status = ntlmssp_set_password(client_ntlmssp_state, opt_password); @@ -629,9 +704,8 @@ static void manage_client_ntlmssp_init(SPNEGO_DATA spnego) if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("Could not set password: %s\n", nt_errstr(status))); - x_fprintf(x_stdout, "BH\n"); ntlmssp_client_end(&client_ntlmssp_state); - return; + return False; } spnego.type = SPNEGO_NEG_TOKEN_INIT; @@ -645,9 +719,8 @@ static void manage_client_ntlmssp_init(SPNEGO_DATA spnego) if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { DEBUG(1, ("Expected MORE_PROCESSING_REQUIRED, got: %s\n", nt_errstr(status))); - x_fprintf(x_stdout, "BH\n"); ntlmssp_client_end(&client_ntlmssp_state); - return; + return False; } write_spnego_data(&to_server, &spnego); @@ -657,7 +730,7 @@ static void manage_client_ntlmssp_init(SPNEGO_DATA spnego) data_blob_free(&to_server); x_fprintf(x_stdout, "KK %s\n", to_server_base64); SAFE_FREE(to_server_base64); - return; + return True; } static void manage_client_ntlmssp_targ(SPNEGO_DATA spnego) @@ -719,21 +792,110 @@ static void manage_client_ntlmssp_targ(SPNEGO_DATA spnego) return; } -static void manage_client_krb5_init(SPNEGO_DATA spnego) +#ifdef HAVE_KRB5 + +static BOOL manage_client_krb5_init(SPNEGO_DATA spnego) { - DEBUG(1, ("to be done ... \n")); - x_fprintf(x_stdout, "BH\n"); - return; + char *principal; + DATA_BLOB tkt, to_server; + unsigned char session_key_krb5[16]; + SPNEGO_DATA reply; + char *reply_base64; + + const char *my_mechs[] = {OID_KERBEROS5_OLD, NULL}; + ssize_t len; + + if ( (spnego.negTokenInit.mechListMIC.data == NULL) || + (spnego.negTokenInit.mechListMIC.length == 0) ) { + DEBUG(1, ("Did not get a principal for krb5\n")); + return False; + } + + principal = malloc(spnego.negTokenInit.mechListMIC.length+1); + + if (principal == NULL) { + DEBUG(1, ("Could not malloc principal\n")); + return False; + } + + memcpy(principal, spnego.negTokenInit.mechListMIC.data, + spnego.negTokenInit.mechListMIC.length); + principal[spnego.negTokenInit.mechListMIC.length] = '\0'; + + tkt = cli_krb5_get_ticket(principal, 0, session_key_krb5); + + if (tkt.data == NULL) { + + pstring user; + + /* Let's try to first get the TGT, for that we need a + password. */ + + if (opt_password == NULL) { + DEBUG(10, ("Requesting password\n")); + x_fprintf(x_stdout, "PW\n"); + return True; + } + + pstr_sprintf(user, "%s@%s", opt_username, opt_domain); + + if (kerberos_kinit_password(user, opt_password, 0) != 0) { + DEBUG(10, ("Requesting TGT failed\n")); + x_fprintf(x_stdout, "NA\n"); + return True; + } + + tkt = cli_krb5_get_ticket(principal, 0, session_key_krb5); + } + + ZERO_STRUCT(reply); + + reply.type = SPNEGO_NEG_TOKEN_INIT; + reply.negTokenInit.mechTypes = my_mechs; + reply.negTokenInit.reqFlags = 0; + reply.negTokenInit.mechToken = tkt; + reply.negTokenInit.mechListMIC = data_blob(NULL, 0); + + len = write_spnego_data(&to_server, &reply); + data_blob_free(&tkt); + + if (len == -1) { + DEBUG(1, ("Could not write SPNEGO data blob\n")); + return False; + } + + reply_base64 = base64_encode_data_blob(to_server); + x_fprintf(x_stdout, "KK %s *\n", reply_base64); + + SAFE_FREE(reply_base64); + data_blob_free(&to_server); + DEBUG(10, ("sent GSS-SPNEGO KERBEROS5 negTokenInit\n")); + return True; } static void manage_client_krb5_targ(SPNEGO_DATA spnego) { - DEBUG(1, ("Got a negTokenTarg with a Kerberos token. This should not " - "happen!\n")); - x_fprintf(x_stdout, "BH\n"); - return; + switch (spnego.negTokenTarg.negResult) { + case SPNEGO_ACCEPT_INCOMPLETE: + DEBUG(1, ("Got a Kerberos negTokenTarg with ACCEPT_INCOMPLETE\n")); + x_fprintf(x_stdout, "BH\n"); + break; + case SPNEGO_ACCEPT_COMPLETED: + DEBUG(10, ("Accept completed\n")); + x_fprintf(x_stdout, "AF\n"); + break; + case SPNEGO_REJECT: + DEBUG(10, ("Rejected\n")); + x_fprintf(x_stdout, "NA\n"); + break; + default: + DEBUG(1, ("Got an invalid negTokenTarg\n")); + x_fprintf(x_stdout, "AF\n"); + } } +#endif + static void manage_gss_spnego_client_request(enum squid_mode squid_mode, char *buf, int length) { @@ -753,7 +915,7 @@ static void manage_gss_spnego_client_request(enum squid_mode squid_mode, /* We asked for a password and obviously got it :-) */ - opt_password = strndup(request.data, request.length); + opt_password = strndup((const char *)request.data, request.length); if (opt_password == NULL) { DEBUG(1, ("Out of memory\n")); @@ -796,14 +958,17 @@ static void manage_gss_spnego_client_request(enum squid_mode squid_mode, while (*mechType != NULL) { - if (strcmp(*mechType, OID_NTLMSSP) == 0) { - manage_client_ntlmssp_init(spnego); - goto out; +#ifdef HAVE_KRB5 + if ( (strcmp(*mechType, OID_KERBEROS5_OLD) == 0) || + (strcmp(*mechType, OID_KERBEROS5) == 0) ) { + if (manage_client_krb5_init(spnego)) + goto out; } +#endif - if (strcmp(*mechType, OID_KERBEROS5_OLD) == 0) { - manage_client_krb5_init(spnego); - goto out; + if (strcmp(*mechType, OID_NTLMSSP) == 0) { + if (manage_client_ntlmssp_init(spnego)) + goto out; } mechType++; @@ -816,17 +981,42 @@ static void manage_gss_spnego_client_request(enum squid_mode squid_mode, if (spnego.type == SPNEGO_NEG_TOKEN_TARG) { + if (spnego.negTokenTarg.supportedMech == NULL) { + /* On accept/reject Windows does not send the + mechanism anymore. Handle that here and + shut down the mechanisms. */ + + switch (spnego.negTokenTarg.negResult) { + case SPNEGO_ACCEPT_COMPLETED: + x_fprintf(x_stdout, "AF\n"); + break; + case SPNEGO_REJECT: + x_fprintf(x_stdout, "NA\n"); + break; + default: + DEBUG(1, ("Got a negTokenTarg with no mech and an " + "unknown negResult: %d\n", + spnego.negTokenTarg.negResult)); + x_fprintf(x_stdout, "BH\n"); + } + + ntlmssp_client_end(&client_ntlmssp_state); + goto out; + } + if (strcmp(spnego.negTokenTarg.supportedMech, OID_NTLMSSP) == 0) { manage_client_ntlmssp_targ(spnego); goto out; } +#if HAVE_KRB5 if (strcmp(spnego.negTokenTarg.supportedMech, OID_KERBEROS5_OLD) == 0) { manage_client_krb5_targ(spnego); goto out; } +#endif } @@ -925,8 +1115,8 @@ static BOOL check_auth_crap(void) &opt_lm_response, &opt_nt_response, flags, - lm_key, - nt_key, + (unsigned char *)lm_key, + (unsigned char *)nt_key, &error_string); if (!NT_STATUS_IS_OK(nt_status)) { @@ -940,7 +1130,7 @@ static BOOL check_auth_crap(void) if (request_lm_key && (memcmp(zeros, lm_key, sizeof(lm_key)) != 0)) { - hex_encode(lm_key, + hex_encode((const unsigned char *)lm_key, sizeof(lm_key), &hex_lm_key); x_fprintf(x_stdout, "LM_KEY: %s\n", hex_lm_key); @@ -949,7 +1139,7 @@ static BOOL check_auth_crap(void) if (request_nt_key && (memcmp(zeros, nt_key, sizeof(nt_key)) != 0)) { - hex_encode(nt_key, + hex_encode((const unsigned char *)nt_key, sizeof(nt_key), &hex_nt_key); x_fprintf(x_stdout, "NT_KEY: %s\n", hex_nt_key); @@ -1023,16 +1213,16 @@ static BOOL test_lm(void) sizeof(lm_key)) != 0) { DEBUG(1, ("LM Key does not match expectations!\n")); DEBUG(1, ("lm_key:\n")); - dump_data(1, lm_key, 8); + dump_data(1, (const char *)lm_key, 8); DEBUG(1, ("expected:\n")); - dump_data(1, lm_hash, 8); + dump_data(1, (const char *)lm_hash, 8); } if (memcmp(lm_hash, nt_key, 8) != 0) { DEBUG(1, ("Session Key (first 8, lm hash) does not match expectations!\n")); DEBUG(1, ("nt_key:\n")); - dump_data(1, nt_key, 8); + dump_data(1, (const char *)nt_key, 8); DEBUG(1, ("expected:\n")); - dump_data(1, lm_hash, 8); + dump_data(1, (const char *)lm_hash, 8); } return True; } @@ -1095,18 +1285,18 @@ static BOOL test_lm_ntlm(void) sizeof(lm_key)) != 0) { DEBUG(1, ("LM Key does not match expectations!\n")); DEBUG(1, ("lm_key:\n")); - dump_data(1, lm_key, 8); + dump_data(1, (const char *)lm_key, 8); DEBUG(1, ("expected:\n")); - dump_data(1, lm_hash, 8); + dump_data(1, (const char *)lm_hash, 8); pass = False; } if (memcmp(session_key.data, nt_key, sizeof(nt_key)) != 0) { DEBUG(1, ("NT Session Key does not match expectations!\n")); DEBUG(1, ("nt_key:\n")); - dump_data(1, nt_key, 16); + dump_data(1, (const char *)nt_key, 16); DEBUG(1, ("expected:\n")); - dump_data(1, session_key.data, session_key.length); + dump_data(1, (const char *)session_key.data, session_key.length); pass = False; } return pass; @@ -1138,10 +1328,10 @@ static BOOL test_ntlm(void) flags |= WBFLAG_PAM_NTKEY; SMBNTencrypt(opt_password,chall.data,nt_response.data); - E_md4hash(opt_password, nt_hash); - SMBsesskeygen_ntv1(nt_hash, NULL, session_key.data); + E_md4hash(opt_password, (unsigned char *)nt_hash); + SMBsesskeygen_ntv1((const unsigned char *)nt_hash, NULL, session_key.data); - E_deshash(opt_password, lm_hash); + E_deshash(opt_password, (unsigned char *)lm_hash); nt_status = contact_winbind_auth_crap(opt_username, opt_domain, opt_workstation, @@ -1149,8 +1339,8 @@ static BOOL test_ntlm(void) NULL, &nt_response, flags, - lm_key, - nt_key, + (unsigned char *)lm_key, + (unsigned char *)nt_key, &error_string); data_blob_free(&nt_response); @@ -1178,7 +1368,7 @@ static BOOL test_ntlm(void) DEBUG(1, ("nt_key:\n")); dump_data(1, nt_key, 16); DEBUG(1, ("expected:\n")); - dump_data(1, session_key.data, session_key.length); + dump_data(1, (const char *)session_key.data, session_key.length); pass = False; } return pass; @@ -1234,17 +1424,17 @@ static BOOL test_ntlm_in_lm(void) sizeof(lm_key)) != 0) { DEBUG(1, ("LM Key does not match expectations!\n")); DEBUG(1, ("lm_key:\n")); - dump_data(1, lm_key, 8); + dump_data(1, (const char *)lm_key, 8); DEBUG(1, ("expected:\n")); - dump_data(1, lm_hash, 8); + dump_data(1, (const char *)lm_hash, 8); pass = False; } if (memcmp(lm_hash, nt_key, 8) != 0) { DEBUG(1, ("Session Key (first 8 lm hash) does not match expectations!\n")); DEBUG(1, ("nt_key:\n")); - dump_data(1, nt_key, 16); + dump_data(1, (const char *)nt_key, 16); DEBUG(1, ("expected:\n")); - dump_data(1, lm_hash, 8); + dump_data(1, (const char *)lm_hash, 8); pass = False; } return pass; @@ -1276,10 +1466,10 @@ static BOOL test_ntlm_in_both(void) flags |= WBFLAG_PAM_NTKEY; SMBNTencrypt(opt_password,chall.data,nt_response.data); - E_md4hash(opt_password, nt_hash); - SMBsesskeygen_ntv1(nt_hash, NULL, session_key.data); + E_md4hash(opt_password, (unsigned char *)nt_hash); + SMBsesskeygen_ntv1((const unsigned char *)nt_hash, NULL, session_key.data); - E_deshash(opt_password, lm_hash); + E_deshash(opt_password, (unsigned char *)lm_hash); nt_status = contact_winbind_auth_crap(opt_username, opt_domain, opt_workstation, @@ -1287,8 +1477,8 @@ static BOOL test_ntlm_in_both(void) &nt_response, &nt_response, flags, - lm_key, - nt_key, + (unsigned char *)lm_key, + (unsigned char *)nt_key, &error_string); data_blob_free(&nt_response); @@ -1316,7 +1506,7 @@ static BOOL test_ntlm_in_both(void) DEBUG(1, ("nt_key:\n")); dump_data(1, nt_key, 16); DEBUG(1, ("expected:\n")); - dump_data(1, session_key.data, session_key.length); + dump_data(1, (const char *)session_key.data, session_key.length); pass = False; } @@ -1378,9 +1568,9 @@ static BOOL test_ntlmv2(void) sizeof(nt_key)) != 0) { DEBUG(1, ("NT Session Key does not match expectations!\n")); DEBUG(1, ("nt_key:\n")); - dump_data(1, nt_key, 16); + dump_data(1, (const char *)nt_key, 16); DEBUG(1, ("expected:\n")); - dump_data(1, nt_session_key.data, nt_session_key.length); + dump_data(1, (const char *)nt_session_key.data, nt_session_key.length); pass = False; } return pass; @@ -1442,9 +1632,9 @@ static BOOL test_lmv2_ntlmv2(void) sizeof(nt_key)) != 0) { DEBUG(1, ("NT Session Key does not match expectations!\n")); DEBUG(1, ("nt_key:\n")); - dump_data(1, nt_key, 16); + dump_data(1, (const char *)nt_key, 16); DEBUG(1, ("expected:\n")); - dump_data(1, nt_session_key.data, nt_session_key.length); + dump_data(1, (const char *)nt_session_key.data, nt_session_key.length); pass = False; } return pass; @@ -1557,18 +1747,18 @@ static BOOL test_ntlm_broken(BOOL break_lm) sizeof(lm_key)) != 0) { DEBUG(1, ("LM Key does not match expectations!\n")); DEBUG(1, ("lm_key:\n")); - dump_data(1, lm_key, 8); + dump_data(1, (const char *)lm_key, 8); DEBUG(1, ("expected:\n")); - dump_data(1, lm_hash, 8); + dump_data(1, (const char *)lm_hash, 8); pass = False; } if (memcmp(session_key.data, nt_key, sizeof(nt_key)) != 0) { DEBUG(1, ("NT Session Key does not match expectations!\n")); DEBUG(1, ("nt_key:\n")); - dump_data(1, nt_key, 16); + dump_data(1, (const char *)nt_key, 16); DEBUG(1, ("expected:\n")); - dump_data(1, session_key.data, session_key.length); + dump_data(1, (const char *)session_key.data, session_key.length); pass = False; } return pass; diff --git a/source3/utils/profiles.c b/source3/utils/profiles.c index 23df26d150..3230eb21fc 100644 --- a/source3/utils/profiles.c +++ b/source3/utils/profiles.c @@ -448,7 +448,7 @@ static int get_sid(DOM_SID *sid, const unsigned char *sid_str) SIVAL(&sid->sub_auths[i], 0, auth); i++; - lstr = strchr(lstr + 1, '-'); + lstr = (const unsigned char *)strchr(lstr + 1, '-'); } return 1; diff --git a/source3/utils/smbcacls.c b/source3/utils/smbcacls.c index c90c042106..58ee57b5dd 100644 --- a/source3/utils/smbcacls.c +++ b/source3/utils/smbcacls.c @@ -751,7 +751,7 @@ static struct cli_state *connect_one(const char *share) POPT_AUTOHELP { "delete", 'D', POPT_ARG_STRING, NULL, 'D', "Delete an acl", "ACL" }, { "modify", 'M', POPT_ARG_STRING, NULL, 'M', "Modify an acl", "ACL" }, - { "add", 'A', POPT_ARG_STRING, NULL, 'A', "Add an acl", "ACL" }, + { "add", 'a', POPT_ARG_STRING, NULL, 'a', "Add an acl", "ACL" }, { "set", 'S', POPT_ARG_STRING, NULL, 'S', "Set acls", "ACLS" }, { "chown", 'C', POPT_ARG_STRING, NULL, 'C', "Change ownership of a file", "USERNAME" }, { "chgrp", 'G', POPT_ARG_STRING, NULL, 'G', "Change group ownership of a file", "GROUPNAME" }, @@ -796,7 +796,7 @@ static struct cli_state *connect_one(const char *share) mode = SMB_ACL_MODIFY; break; - case 'A': + case 'a': the_acl = smb_xstrdup(poptGetOptArg(pc)); mode = SMB_ACL_ADD; break; diff --git a/source3/utils/smbgroupedit.c b/source3/utils/smbgroupedit.c deleted file mode 100644 index 0faa0513ed..0000000000 --- a/source3/utils/smbgroupedit.c +++ /dev/null @@ -1,405 +0,0 @@ -/* - * Unix SMB/CIFS implementation. - * RPC Pipe client / server routines - * Copyright (C) Andrew Tridgell 1992-2000, - * Copyright (C) Jean François Micouleau 1998-2001. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include "includes.h" - -/* - * Next two lines needed for SunOS and don't - * hurt anything else... - */ -extern char *optarg; -extern int optind; - -/********************************************************* - Print command usage on stderr and die. -**********************************************************/ -static void usage(void) -{ - if (getuid() == 0) { - printf("smbgroupedit options\n"); - } else { - printf("You need to be root to use this tool!\n"); - } - printf("options:\n"); - printf(" -a group create new group\n"); - printf(" -n group NT group name\n"); - printf(" -p privilege only local\n"); - printf(" -d description group description\n"); - printf(" -v list groups\n"); - printf(" -l long list (include details)\n"); - printf(" -s short list (default)\n"); - printf(" -c SID change group\n"); - printf(" -u unix group\n"); - printf(" -d description group description\n"); - printf(" -r rid RID of new group\n"); - printf(" -x group delete this group\n"); - printf("\n"); - printf(" -t[b|d|l] type: builtin, domain, local \n"); - exit(1); -} - -/********************************************************* - Figure out if the input was an NT group or a SID string. - Return the SID. -**********************************************************/ -static BOOL get_sid_from_input(DOM_SID *sid, char *input) -{ - GROUP_MAP map; - - if (StrnCaseCmp( input, "S-", 2)) { - /* Perhaps its the NT group name? */ - if (!pdb_getgrnam(&map, input, MAPPING_WITHOUT_PRIV)) { - printf("NT Group %s doesn't exist in mapping DB\n", input); - return False; - } else { - *sid = map.sid; - } - } else { - if (!string_to_sid(sid, input)) { - printf("converting sid %s from a string failed!\n", input); - return False; - } - } - return True; -} - -/********************************************************* - add a group. -**********************************************************/ -static int addgroup(gid_t gid, enum SID_NAME_USE sid_type, char *ntgroup, char *ntcomment, char *privilege, uint32 rid) -{ - PRIVILEGE_SET se_priv; - DOM_SID sid; - fstring string_sid; - fstring comment; - - sid_copy(&sid, get_global_sam_sid()); - sid_append_rid(&sid, rid); - - sid_to_string(string_sid, &sid); - - if (ntcomment==NULL) - fstrcpy(comment, "Local Unix group"); - else - fstrcpy(comment, ntcomment); - - init_privilege(&se_priv); - if (privilege!=NULL) - convert_priv_from_text(&se_priv, privilege); - - if(!add_initial_entry(gid, string_sid, sid_type, ntgroup, - comment, se_priv, PR_ACCESS_FROM_NETWORK)) { - printf("adding entry for group %s failed!\n", ntgroup); - free_privilege(&se_priv); - return -1; - } - - free_privilege(&se_priv); - return 0; -} - -/********************************************************* - Change a group. -**********************************************************/ -static int changegroup(char *sid_string, char *group, enum SID_NAME_USE sid_type, char *ntgroup, char *groupdesc, char *privilege) -{ - DOM_SID sid; - GROUP_MAP map; - gid_t gid; - - if (!get_sid_from_input(&sid, sid_string)) { - return -1; - } - - /* Get the current mapping from the database */ - if(!pdb_getgrsid(&map, sid, MAPPING_WITH_PRIV)) { - printf("This SID does not exist in the database\n"); - return -1; - } - - /* If a new Unix group is specified, check and change */ - if (group!=NULL) { - gid=nametogid(group); - if (gid==-1) { - printf("The UNIX group does not exist\n"); - return -1; - } else - map.gid=gid; - } - - /* - * Allow changing of group type only between domain and local - * We disallow changing Builtin groups !!! (SID problem) - */ - if (sid_type==SID_NAME_ALIAS - || sid_type==SID_NAME_DOM_GRP - || sid_type==SID_NAME_UNKNOWN) { - if (map.sid_name_use==SID_NAME_ALIAS - || map.sid_name_use==SID_NAME_DOM_GRP - || map.sid_name_use==SID_NAME_UNKNOWN) { - map.sid_name_use=sid_type; - } else { - printf("cannot change group type to builtin\n"); - }; - } else { - printf("cannot change group type from builtin\n"); - } - - if (ntgroup!=NULL) - fstrcpy(map.nt_name, ntgroup); - - /* Change comment if new one */ - if (groupdesc!=NULL) - fstrcpy(map.comment, groupdesc); - - /* Change the privilege if new one */ - if (privilege!=NULL) - convert_priv_from_text(&map.priv_set, privilege); - - if (!pdb_update_group_mapping_entry(&map)) { - printf("Could not update group database\n"); - free_privilege(&map.priv_set); - return -1; - } - - free_privilege(&map.priv_set); - return 0; -} - -/********************************************************* - Delete the group. -**********************************************************/ -static int deletegroup(char *group) -{ - DOM_SID sid; - - if (!get_sid_from_input(&sid, group)) { - return -1; - } - - if(!pdb_delete_group_mapping_entry(sid)) { - printf("removing group %s from the mapping db failed!\n", group); - return -1; - } - - return 0; -} - -/********************************************************* - List the groups. -**********************************************************/ -static int listgroup(enum SID_NAME_USE sid_type, BOOL long_list) -{ - int entries,i; - GROUP_MAP *map=NULL; - fstring string_sid; - fstring group_type; - fstring priv_text; - - if (!long_list) - printf("NT group (SID) -> Unix group\n"); - - if (!pdb_enum_group_mapping(sid_type, &map, &entries, ENUM_ALL_MAPPED, MAPPING_WITH_PRIV)) - return -1; - - for (i=0; i %s\n", map[i].nt_name, string_sid, gidtoname(map[i].gid)); - else { - printf("%s\n", map[i].nt_name); - printf("\tSID : %s\n", string_sid); - printf("\tUnix group: %s\n", gidtoname(map[i].gid)); - printf("\tGroup type: %s\n", group_type); - printf("\tComment : %s\n", map[i].comment); - printf("\tPrivilege : %s\n\n", priv_text); - } - } - - return 0; -} - -/********************************************************* - Start here. -**********************************************************/ -int main (int argc, char **argv) -{ - int ch; - BOOL add_group = False; - BOOL view_group = False; - BOOL change_group = False; - BOOL delete_group = False; - BOOL nt_group = False; - BOOL priv = False; - BOOL group_type = False; - BOOL long_list = False; - - char *group = NULL; - char *sid = NULL; - char *ntgroup = NULL; - char *privilege = NULL; - char *groupt = NULL; - char *group_desc = NULL; - - enum SID_NAME_USE sid_type; - uint32 rid = -1; - - setup_logging("groupedit", True); - - if (argc < 2) { - usage(); - return 0; - } - - if (!lp_load(dyn_CONFIGFILE,True,False,False)) { - fprintf(stderr, "Can't load %s - run testparm to debug it\n", - dyn_CONFIGFILE); - exit(1); - } - - if (!init_names()) - exit(1); - - if(!initialize_password_db(True)) { - fprintf(stderr, "Can't setup password database vectors.\n"); - exit(1); - } - - if(get_global_sam_sid()==False) { - fprintf(stderr, "Can not read machine SID\n"); - return 0; - } - - while ((ch = getopt(argc, argv, "a:c:d:ln:p:r:st:u:vx:")) != EOF) { - switch(ch) { - case 'a': - add_group = True; - group=optarg; - break; - case 'c': - change_group = True; - sid=optarg; - break; - case 'd': - group_desc=optarg; - break; - case 'l': - long_list = True; - break; - case 'n': - nt_group = True; - ntgroup=optarg; - break; - case 'p': - priv = True; - privilege=optarg; - break; - case 'r': - rid = atoi(optarg); - break; - case 's': - long_list = False; - break; - case 't': - group_type = True; - groupt=optarg; - break; - case 'u': - group=optarg; - break; - case 'v': - view_group = True; - break; - case 'x': - delete_group = True; - group=optarg; - break; - /*default: - usage();*/ - } - } - - - if (((add_group?1:0) + (view_group?1:0) + (change_group?1:0) + (delete_group?1:0)) > 1) { - fprintf (stderr, "Incompatible options on command line!\n"); - usage(); - exit(1); - } - - /* no option on command line -> list groups */ - if (((add_group?1:0) + (view_group?1:0) + (change_group?1:0) + (delete_group?1:0)) == 0) - view_group = True; - - - if (group_type==False) - sid_type=SID_NAME_UNKNOWN; - else { - switch (groupt[0]) { - case 'l': - case 'L': - sid_type=SID_NAME_ALIAS; - break; - case 'd': - case 'D': - sid_type=SID_NAME_DOM_GRP; - break; - case 'b': - case 'B': - sid_type=SID_NAME_WKN_GRP; - break; - default: - sid_type=SID_NAME_UNKNOWN; - break; - } - } - - if (add_group) { - gid_t gid=nametogid(group); - if (gid==-1) { - printf("unix group %s doesn't exist!\n", group); - return -1; - } - - if (rid == -1) { - rid = pdb_gid_to_group_rid(gid); - } - return addgroup(gid, sid_type, ntgroup?ntgroup:group, - group_desc, privilege, rid); - } - - if (view_group) - return listgroup(sid_type, long_list); - - if (delete_group) - return deletegroup(group); - - if (change_group) { - return changegroup(sid, group, sid_type, ntgroup, group_desc, privilege); - } - - usage(); - - return 0; -} diff --git a/source3/utils/status.c b/source3/utils/status.c index 8bf67fc4d6..c17e080b6b 100644 --- a/source3/utils/status.c +++ b/source3/utils/status.c @@ -597,7 +597,7 @@ static int traverse_sessionid(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, vo } else { if (locks_only) goto locks; - d_printf("\nSamba version %s\n",VERSION); + d_printf("\nSamba version %s\n",SAMBA_VERSION_STRING); d_printf("PID Username Group Machine \n"); d_printf("-------------------------------------------------------------------\n"); diff --git a/source3/utils/testparm.c b/source3/utils/testparm.c index 16918ecd4a..0a87b4bc1e 100644 --- a/source3/utils/testparm.c +++ b/source3/utils/testparm.c @@ -287,6 +287,27 @@ via the %%o substitution. With encrypted passwords this is not possible.\n", lp_ Level II oplocks can only be set if oplocks are also set.\n", lp_servicename(s) ); } + + if (lp_map_hidden(s) && !(lp_create_mask(s) & S_IXOTH)) { + printf("Invalid combination of parameters for service %s. \ + Map hidden can only work if create mask includes octal 01 (S_IXOTH).\n", + lp_servicename(s) ); + } + if (lp_map_hidden(s) && (lp_force_create_mode(s) & S_IXOTH)) { + printf("Invalid combination of parameters for service %s. \ + Map hidden can only work if force create mode excludes octal 01 (S_IXOTH).\n", + lp_servicename(s) ); + } + if (lp_map_system(s) && !(lp_create_mask(s) & S_IXGRP)) { + printf("Invalid combination of parameters for service %s. \ + Map system can only work if create mask includes octal 010 (S_IXGRP).\n", + lp_servicename(s) ); + } + if (lp_map_system(s) && (lp_force_create_mode(s) & S_IXGRP)) { + printf("Invalid combination of parameters for service %s. \ + Map system can only work if force create mode excludes octal 010 (S_IXGRP).\n", + lp_servicename(s) ); + } } } diff --git a/source3/web/statuspage.c b/source3/web/statuspage.c index c579e8f112..21d7e45738 100644 --- a/source3/web/statuspage.c +++ b/source3/web/statuspage.c @@ -327,7 +327,7 @@ void status_page(void) d_printf("
\n"); - d_printf("", _("version:"), VERSION); + d_printf("", _("version:"), SAMBA_VERSION_STRING); fflush(stdout); d_printf("\n", _("smbd:"), smbd_running()?_("running"):_("not running")); diff --git a/source3/web/swat.c b/source3/web/swat.c index a1c132a088..1c892559dd 100644 --- a/source3/web/swat.c +++ b/source3/web/swat.c @@ -737,7 +737,16 @@ static void wizard_page(void) d_printf("", (winstype == 0) ? "checked" : ""); d_printf("", (winstype == 1) ? "checked" : ""); d_printf("", (winstype == 2) ? "checked" : ""); - d_printf("",lp_wins_server_list()); + d_printf(""); if (winstype == 3) { d_printf(""); d_printf(""); diff --git a/source3/wrepld/server.c b/source3/wrepld/server.c index 504818b8d5..25de680982 100644 --- a/source3/wrepld/server.c +++ b/source3/wrepld/server.c @@ -586,7 +586,7 @@ static void process(void) reopen_logs(); - DEBUG(1,( "wrepld version %s started.\n", VERSION)); + DEBUG(1,( "wrepld version %s started.\n", SAMBA_VERSION_STRING)); DEBUGADD(1,( "Copyright Andrew Tridgell and the Samba Team 1992-2002\n")); DEBUG(2,("uid=%d gid=%d euid=%d egid=%d\n", -- cgit From 7f438c3b9e8913a7836b4851ef7c40a7b97a986d Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Tue, 9 Sep 2003 04:14:19 +0000 Subject: removing unused files (This used to be commit 1a9145015d4b2ee7e7399099760cda13d619e740) --- source3/include/smb_ldap.h | 59 -- source3/libsmb/netlogon_unigrp.c | 172 ----- source3/passdb/pdb_nisplus.c | 1519 -------------------------------------- source3/passdb/pdb_unix.c | 131 ---- source3/script/cvslog.pl | 102 --- 5 files changed, 1983 deletions(-) delete mode 100644 source3/include/smb_ldap.h delete mode 100644 source3/libsmb/netlogon_unigrp.c delete mode 100644 source3/passdb/pdb_nisplus.c delete mode 100644 source3/passdb/pdb_unix.c delete mode 100755 source3/script/cvslog.pl (limited to 'source3') diff --git a/source3/include/smb_ldap.h b/source3/include/smb_ldap.h deleted file mode 100644 index 1a30b853e7..0000000000 --- a/source3/include/smb_ldap.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - 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) Jim McDonough 2003 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#ifndef SMB_LDAP_H -#define SMB_LDAP_H - -#ifdef HAVE_LDAP - -#include -#include - -struct smb_ldap_privates { - - /* Former statics */ - LDAP *ldap_struct; - LDAPMessage *result; - LDAPMessage *entry; - int index; - - time_t last_ping; - /* retrive-once info */ - const char *uri; - - BOOL permit_non_unix_accounts; - - uint32 low_nua_rid; - uint32 high_nua_rid; - - char *bind_dn; - char *bind_secret; - - struct smb_ldap_privates *next; -}; - -#endif -#endif diff --git a/source3/libsmb/netlogon_unigrp.c b/source3/libsmb/netlogon_unigrp.c deleted file mode 100644 index 466410d800..0000000000 --- a/source3/libsmb/netlogon_unigrp.c +++ /dev/null @@ -1,172 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Universal groups helpers - Copyright (C) Alexander Bokovoy 2002. - Copyright (C) Andrew Bartlett 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 - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - This work was sponsored by Optifacio Software Services, Inc. -*/ - -#include "includes.h" -#define UNIGROUP_PREFIX "UNIGROUP" - -/* - Handle for netlogon_unigrp.tdb database. It is used internally - in cli_store_uni_groups_*() and cli_fetch_uni_groups() - and is initialized on first call to cli_store_uni_groups_*() -*/ -static TDB_CONTEXT *netlogon_unigrp_tdb = NULL; - -/* - Store universal groups info into netlogon_unigrp.tdb for - later usage. We use 'domain_SID/user_rid' as key and - array of uint32 where array[0] is number of elements - and elements are array[1] ... array[array[0]] -*/ - -BOOL uni_group_cache_init(void) -{ - if (!netlogon_unigrp_tdb) { - netlogon_unigrp_tdb = tdb_open_log(lock_path("netlogon_unigrp.tdb"), 0, - TDB_DEFAULT, O_RDWR | O_CREAT, 0644); - } - - return (netlogon_unigrp_tdb != NULL); -} - -BOOL uni_group_cache_store_netlogon(TALLOC_CTX *mem_ctx, NET_USER_INFO_3 *user) -{ - TDB_DATA key,data; - fstring keystr, sid_string; - DOM_SID user_sid; - unsigned int i; - - if (!uni_group_cache_init()) { - DEBUG(0,("uni_group_cache_store_netlogon: cannot open netlogon_unigrp.tdb for write!\n")); - return False; - } - - sid_copy(&user_sid, &user->dom_sid.sid); - sid_append_rid(&user_sid, user->user_rid); - - /* Prepare key as USER-SID string */ - slprintf(keystr, sizeof(keystr), "%s/%s", - UNIGROUP_PREFIX, - sid_to_string(sid_string, &user_sid)); - key.dptr = keystr; - key.dsize = strlen(keystr) + 1; - - /* Prepare data */ - data.dsize = (user->num_groups2+1)*sizeof(uint32); - data.dptr = talloc(mem_ctx, data.dsize); - if(!data.dptr) { - DEBUG(0,("uni_group_cache_store_netlogon: cannot allocate memory!\n")); - talloc_destroy(mem_ctx); - return False; - } - - /* Store data in byteorder-independent format */ - SIVAL(&((uint32*)data.dptr)[0],0,user->num_groups2); - for(i=1; i<=user->num_groups2; i++) { - SIVAL(&((uint32*)data.dptr)[i],0,user->gids[i-1].g_rid); - } - if (tdb_store(netlogon_unigrp_tdb, key, data, TDB_REPLACE) == -1) - return False; - return True; -} - -/* - Fetch universal groups info from netlogon_unigrp.tdb for given - domain sid and user rid and allocate it using given mem_ctx. - Universal groups are returned as array of uint32 elements - and elements are array[0] ... array[num_elements-1] - -*/ -DOM_SID **uni_group_cache_fetch(DOM_SID *domain, DOM_SID *user_sid, - TALLOC_CTX *mem_ctx, uint32 *num_groups) -{ - TDB_DATA key,data; - fstring keystr; - DOM_SID **groups; - uint32 i; - uint32 group_count; - fstring sid_string; - - if (!domain) { - DEBUG(1,("uni_group_cache_fetch: expected non-null domain sid\n")); - return NULL; - } - if (!mem_ctx) { - DEBUG(1,("uni_group_cache_fetch: expected non-null memory context\n")); - return NULL; - } - if (!num_groups) { - DEBUG(1,("uni_group_cache_fetch: expected non-null num_groups\n")); - return NULL; - } - if (!netlogon_unigrp_tdb) { - netlogon_unigrp_tdb = tdb_open_log(lock_path("netlogon_unigrp.tdb"), 0, - TDB_DEFAULT, O_RDWR, 0644); - } - if (!netlogon_unigrp_tdb) { - DEBUG(5,("uni_group_cache_fetch: cannot open netlogon_unigrp.tdb for read - normal if not created yet\n")); - return NULL; - } - - *num_groups = 0; - - /* Fetch universal groups */ - slprintf(keystr, sizeof(keystr), "%s/%s", - UNIGROUP_PREFIX, - sid_to_string(sid_string, user_sid)); - key.dptr = keystr; - key.dsize = strlen(keystr) + 1; - data = tdb_fetch(netlogon_unigrp_tdb, key); - - /* There is no cached universal groups in netlogon_unigrp.tdb */ - /* for this user. */ - if (!data.dptr) - return NULL; - - /* Transfer data to receiver's memory context */ - group_count = IVAL(&((uint32*)data.dptr)[0],0); - groups = talloc(mem_ctx, (group_count)*sizeof(*groups)); - if (groups) { - for(i=0; i - * Copyright (C) Luke Kenneth Casson Leighton 1996-1998. - * Copyright (C) Toomas Soome 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 - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 675 - * Mass Ave, Cambridge, MA 02139, USA. - */ - -#include "includes.h" - -#ifdef BROKEN_NISPLUS_INCLUDE_FILES - -/* - * The following lines are needed due to buggy include files - * in Solaris 2.6 which define GROUP in both /usr/include/sys/acl.h and - * also in /usr/include/rpcsvc/nis.h. The definitions conflict. JRA. - * Also GROUP_OBJ is defined as 0x4 in /usr/include/sys/acl.h and as - * an enum in /usr/include/rpcsvc/nis.h. - */ - - -#if defined(GROUP) -#undef GROUP -#endif - -#if defined(GROUP_OBJ) -#undef GROUP_OBJ -#endif - -#endif - -#include - -/*************************************************************** - - the fields for the NIS+ table, generated from mknissmbpwtbl.sh, are: - - 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 - - logon_t=,nw+r - logoff_t=,nw+r - kick_t=,nw+r - pwdlset_t=,nw+r - pwdlchg_t=,nw+r - pwdmchg_t=,nw+r - - full_name=,nw+r - home_dir=,nw+r - dir_drive=,nw+r - logon_script=,nw+r - profile_path=,nw+r - acct_desc=,nw+r - workstations=,nw+r - - hours=,nw+r - -****************************************************************/ - -#define NPF_NAME 0 -#define NPF_UID 1 -#define NPF_USER_RID 2 -#define NPF_SMB_GRPID 3 -#define NPF_GROUP_RID 4 -#define NPF_ACB 5 -#define NPF_LMPWD 6 -#define NPF_NTPWD 7 -#define NPF_LOGON_T 8 -#define NPF_LOGOFF_T 9 -#define NPF_KICK_T 10 -#define NPF_PWDLSET_T 11 -#define NPF_PWDCCHG_T 12 -#define NPF_PWDMCHG_T 13 -#define NPF_FULL_NAME 14 -#define NPF_HOME_DIR 15 -#define NPF_DIR_DRIVE 16 -#define NPF_LOGON_SCRIPT 17 -#define NPF_PROFILE_PATH 18 -#define NPF_ACCT_DESC 19 -#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); - -/*************************************************************** - Start enumeration of the passwd list. -****************************************************************/ - -static NTSTATUS nisplussam_setsampwent (struct pdb_methods *methods, BOOL update) -{ - struct nisplus_private_info *private = - (struct nisplus_private_info *) methods->private_data; - - char *sp; - pstring pfiletmp; - - 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; - if (global_nisp_ent->result != NULL) - return NT_STATUS_UNSUCCESSFUL; - else - return NT_STATUS_OK; -} - -/*************************************************************** - End enumeration of the passwd list. -****************************************************************/ - -static void nisplussam_endsampwent (struct pdb_methods *methods) -{ - 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; -} - -/***************************************************************** - Get one SAM_ACCOUNT from the list (next in line) -*****************************************************************/ - -static NTSTATUS nisplussam_getsampwent (struct pdb_methods *methods, - SAM_ACCOUNT * user) -{ - NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; - 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; - - if (user == NULL) { - DEBUG (0, ("SAM_ACCOUNT is NULL.\n")); - return nt_status; - } - - if (result == NULL || enum_entry < 0 || enum_entry >= (NIS_RES_NUMOBJ (result) - 1)) { - return nt_status; - } - - if (!make_sam_from_nisp_object(user, &NIS_RES_OBJECT (result)[enum_entry])) { - DEBUG (0, ("Bad SAM_ACCOUNT entry returned from NIS+!\n")); - return nt_status; - } - (int) (global_nisp_ent->enum_entry)++; - - return nt_status; -} - -/****************************************************************** - Lookup a name in the SAM database -******************************************************************/ - -static NTSTATUS nisplussam_getsampwnam (struct pdb_methods *methods, - SAM_ACCOUNT * user, const char *sname) -{ - /* Static buffers we will return. */ - NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; - 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 nt_status; - } - 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 nt_status; - } - - ret = make_sam_from_nisresult (user, result); - nis_freeresult (result); - - if (ret) nt_status = NT_STATUS_OK; - - return nt_status; -} - -/*************************************************************************** - Search by sid - **************************************************************************/ - -static NTSTATUS nisplussam_getsampwrid (struct pdb_methods *methods, - SAM_ACCOUNT * user, uint32 rid) -{ - NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; - 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 nt_status; - } - - 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 nt_status; - } - - ret = make_sam_from_nisresult (user, result); - nis_freeresult (result); - - if (ret) nt_status = NT_STATUS_OK; - - return nt_status; -} - -static NTSTATUS 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 NT_STATUS_UNSUCCESSFUL; - return nisplussam_getsampwrid (methods, user, rid); -} - - - -/*************************************************************************** - Delete a SAM_ACCOUNT -****************************************************************************/ - -static NTSTATUS nisplussam_delete_sam_account (struct pdb_methods *methods, - SAM_ACCOUNT * user) -{ - NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; - 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 nt_status; - } - - sname = pdb_get_username (user); - - if (!private->location || !(*private->location)) { - DEBUG (0, ("no SMB password file set\n")); - return nt_status; - } - - 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 nt_status; - } - - 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 nt_status; - } - - 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 nt_status; - } - nis_freeresult (delresult); - - return NT_STATUS_OK; -} - -/*************************************************************************** - Modifies an existing SAM_ACCOUNT -****************************************************************************/ - -static NTSTATUS nisplussam_update_sam_account (struct pdb_methods *methods, - SAM_ACCOUNT * newpwd) -{ - NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; - 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 nt_status; - } - 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 ne_status; - } - - 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 nt_status; - } - - 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 nt_status; - } - - 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 nt_status; - } - - DEBUG (6, ("password changed\n")); - nis_freeresult (addresult); - } else { - DEBUG (6, ("nothing to change!\n")); - } - - free (ecol); - nis_freeresult (result); - - return NT_STATUS_OK; -} - -/*************************************************************************** - Adds an existing SAM_ACCOUNT -****************************************************************************/ - -static NTSTATUS nisplussam_add_sam_account (struct pdb_methods *methods, - SAM_ACCOUNT * newpwd) -{ - NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; - 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 nt_status; - } - - if (! - (result = - nisp_get_nis_list (nisname, - MASTER_ONLY | FOLLOW_LINKS | FOLLOW_PATH | - EXPAND_NAME | HARD_LOOKUP))) { - return nt_status; - } - 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 nt_status; - } - - 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 nt_status; - } - - 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 nt_status; - } - 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 nt_status; - } - /* 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 nt_status; - } - - 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 nt_status; - } - - nis_freeresult (tblresult); - nis_freeresult (result); - - return NT_STATUS_OK; -} - -/*************************************************************** - make_nisname_from_user_rid - ****************************************************************/ -static char *make_nisname_from_user_rid (uint32 rid, char *pfile) -{ - 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); - - return nisname; -} - -/*************************************************************** - make_nisname_from_name - ****************************************************************/ -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); - - return nisname; -} - -/************************************************************************* - gets a NIS+ attribute - *************************************************************************/ -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) { - len = entry_len; - } - - 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) -{ - 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, PDB_DEFAULT); - 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), - PDB_SET); - } - } - - pdb_set_logoff_time (pw_buf, get_time_t_max (), PDB_DEFAULT); - 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), - PDB_SET); - } - } - - pdb_set_kickoff_time (pw_buf, get_time_t_max (), PDB_DEFAULT); - 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), - PDB_SET); - } - } - - pdb_set_pass_last_set_time (pw_buf, (time_t) 0, PDB_DEFAULT); - 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); - } - } - - pdb_set_pass_can_change_time (pw_buf, (time_t) 0, PDB_DEFAULT); - 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), - PDB_SET); - } - } - - pdb_set_pass_must_change_time (pw_buf, get_time_t_max (), PDB_DEFAULT); /* 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), - PDB_SET); - } - } - - /* string values */ - pdb_set_username (pw_buf, ENTRY_VAL (obj, NPF_NAME), PDB_SET); - pdb_set_domain (pw_buf, lp_workgroup (), PDB_DEFAULT); - /* 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); -#endif - pdb_set_fullname (pw_buf, full_name, PDB_SET); - - pdb_set_acct_ctrl (pw_buf, pdb_decode_acct_ctrl (ENTRY_VAL (obj, - NPF_ACB), PDB_SET)); - - get_single_attribute (obj, NPF_ACCT_DESC, acct_desc, - sizeof (pstring)); -#if 0 - unix_to_dos (acct_desc, True); -#endif - pdb_set_acct_desc (pw_buf, acct_desc, PDB_SET); - - pdb_set_workstations (pw_buf, ENTRY_VAL (obj, NPF_WORKSTATIONS), PDB_SET); - pdb_set_munged_dial (pw_buf, NULL, PDB_DEFAULT); - - pdb_set_user_sid_from_rid (pw_buf, - atoi (ENTRY_VAL (obj, NPF_USER_RID)), PDB_SET); - pdb_set_group_sid_from_rid (pw_buf, - atoi (ENTRY_VAL (obj, NPF_GROUP_RID)), PDB_SET); - - /* 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, PDB_DEFAULT); - } else - pdb_set_homedir (pw_buf, home_dir, PDB_SET); - - 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, PDB_DEFAULT); - } else - pdb_set_dir_drive (pw_buf, home_drive, PDB_SET); - - get_single_attribute (obj, NPF_LOGON_SCRIPT, logon_script, - sizeof (pstring)); - if (!(logon_script && *logon_script)) { - pstrcpy (logon_script, lp_logon_script ()); - pdb_set_logon_script (pw_buf, logon_script, PDB_DEFAULT); - } else - pdb_set_logon_script (pw_buf, logon_script, PDB_SET); - - 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, PDB_DEFAULT); - } else - pdb_set_profile_path (pw_buf, profile_path, PDB_SET); - - } else { - /* lkclXXXX this is OBSERVED behaviour by NT PDCs, enforced here. */ - pdb_set_group_sid_from_rid (pw_buf, DOMAIN_GROUP_RID_USERS, PDB_DEFAULT); - } - - /* Check the lanman password column. */ - ptr = (char *) ENTRY_VAL (obj, NPF_LMPWD); - if (!pdb_set_lanman_passwd (pw_buf, NULL, PDB_DEFAULT)) - return False; - - if (!strncasecmp (ptr, "NO PASSWORD", 11)) { - pdb_set_acct_ctrl (pw_buf, - pdb_get_acct_ctrl (pw_buf) | ACB_PWNOTREQ, PDB_SET); - } 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, PDB_SET)) - return False; - } - - /* Check the NT password column. */ - ptr = ENTRY_VAL (obj, NPF_NTPWD); - if (!pdb_set_nt_passwd (pw_buf, NULL, PDB_DEFAULT)) - 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:\ %s.\n", - pdb_get_username (pw_buf))); - return False; - } - if (!pdb_set_nt_passwd (pw_buf, smbntpwd, PDB_SET)) - return False; - } - - pdb_set_unknown_3 (pw_buf, 0xffffff, PDB_DEFAULT); /* don't know */ - pdb_set_logon_divs (pw_buf, 168, PDB_DEFAULT); /* 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); - pdb_set_hours (pw_buf, hours, PDB_SET); - - pdb_set_unknown_5 (pw_buf, 0x00020000, PDB_DEFAULT); /* don't know */ - pdb_set_unknown_6 (pw_buf, 0x000004ec, PDB_DEFAULT); /* 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) -{ - 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))); - return False; - } - - /* User not found. */ - 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")); - } - - /* Grab the first hit. */ - 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) -{ - if (new_obj == NULL) - return; - - ENTRY_VAL (new_obj, col) = val; - ENTRY_LEN (new_obj, col) = len + 1; - - if (flags != 0) { - new_obj->EN_data.en_cols.en_cols_val[col].ec_flags = flags; - } -} - -/*************************************************************** - 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) -{ - /* - * 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 */ - - uint32 u_rid; - uint32 g_rid; - /* 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 */ - - if (!(u_rid = pdb_get_user_rid (sampass))) - return False; - if (!(g_rid = pdb_get_group_rid (sampass))) - return False; - - slprintf (uid, sizeof (uid) - 1, "%u", fallback_pdb_user_rid_to_uid (u_rid)); - slprintf (user_rid, sizeof (user_rid) - 1, "%u", u_rid); - slprintf (gid, sizeof (gid) - 1, "%u", fallback_pdb_group_rid_to_uid (g_rid)); - slprintf (group_rid, sizeof (group_rid) - 1, "%u", g_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); - -#if 0 - - /* Not sure what to do with these guys. -tpot */ - - 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); - } - - - /* uid */ - 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 (!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 (!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 (!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; -} - -/*************************************************************** - calls nis_list, returns results. - ****************************************************************/ -static nis_result *nisp_get_nis_list (const char *nisname, unsigned int flags) -{ - nis_result *result; - int i; - - 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; -} - -static void free_private_data(void **vp) -{ - struct nisplus_private_info **private = (struct nisplus_private_info **)vp; - - if ((*private)->result) { - nis_freeresult ((*private)->result); - } - - free(*private); - - /* No need to free any further, as it is talloc()ed */ -} - -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)); - - ZERO_STRUCT(private); - p->location = talloc_strdup(pdb_context->mem_ctx, location); - - if (!NT_STATUS_IS_OK - (nt_status = - make_pdb_methods (pdb_context->mem_ctx, pdb_method))) { - return nt_status; - } - - (*pdb_method)->name = "nisplussam"; - - /* Functions your pdb module doesn't provide should be set - * to NULL */ - - (*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)->free_private_data = free_private_data; - (*pdb_method)->private_data = private; - - return NT_STATUS_OK; -} - -NTSTATUS pdb_nisplus_init(void) -{ - return smb_register_passdb(PASSDB_INTERFACE_VERSION, "nisplussam", pdb_init_nisplussam); -} diff --git a/source3/passdb/pdb_unix.c b/source3/passdb/pdb_unix.c deleted file mode 100644 index 395795758f..0000000000 --- a/source3/passdb/pdb_unix.c +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Unix password backend for samba - * 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 - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 675 - * Mass Ave, Cambridge, MA 02139, USA. - */ - -#include "includes.h" - -/****************************************************************** - Lookup a name in the SAM database - ******************************************************************/ - -static NTSTATUS unixsam_getsampwnam (struct pdb_methods *methods, SAM_ACCOUNT *user, const char *sname) -{ - struct passwd *pass; - if (!methods) { - DEBUG(0,("invalid methods\n")); - return NT_STATUS_UNSUCCESSFUL; - } - if (!sname) { - DEBUG(0,("invalid name specified")); - return NT_STATUS_UNSUCCESSFUL; - } - pass = Get_Pwnam(sname); - - return pdb_fill_sam_pw(user, pass); -} - - -/*************************************************************************** - Search by rid - **************************************************************************/ - -static NTSTATUS unixsam_getsampwrid (struct pdb_methods *methods, - SAM_ACCOUNT *user, uint32 rid) -{ - NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; - struct passwd *pass = NULL; - const char *guest_account = lp_guestaccount(); - if (!(guest_account && *guest_account)) { - DEBUG(1, ("NULL guest account!?!?\n")); - return nt_status; - } - - if (!methods) { - DEBUG(0,("invalid methods\n")); - return nt_status; - } - - if (rid == DOMAIN_USER_RID_GUEST) { - pass = getpwnam_alloc(guest_account); - if (!pass) { - DEBUG(1, ("guest account %s does not seem to exist...\n", guest_account)); - return nt_status; - } - } else if (fallback_pdb_rid_is_user(rid)) { - pass = getpwuid_alloc(fallback_pdb_user_rid_to_uid (rid)); - } - - if (pass == NULL) { - return nt_status; - } - - nt_status = pdb_fill_sam_pw(user, pass); - passwd_free(&pass); - - return nt_status; -} - -static NTSTATUS unixsam_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUNT * user, const DOM_SID *sid) -{ - uint32 rid; - if (!sid_peek_check_rid(get_global_sam_sid(), sid, &rid)) - return NT_STATUS_UNSUCCESSFUL; - return unixsam_getsampwrid(my_methods, user, rid); -} - -/*************************************************************************** - Updates a SAM_ACCOUNT - - This isn't a particulary practical option for pdb_unix. We certainly don't - want to twidde the filesystem, so what should we do? - - Current plan is to transparently add the account. It should appear - as if the pdb_unix version was modified, but its actually stored somehwere. - ****************************************************************************/ - -static NTSTATUS unixsam_update_sam_account (struct pdb_methods *methods, SAM_ACCOUNT *newpwd) -{ - return methods->parent->pdb_add_sam_account(methods->parent, newpwd); -} - -NTSTATUS pdb_init_unixsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location) -{ - NTSTATUS nt_status; - - if (!pdb_context) { - DEBUG(0, ("invalid pdb_context specified\n")); - return NT_STATUS_UNSUCCESSFUL; - } - - if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) { - return nt_status; - } - - (*pdb_method)->name = "unixsam"; - (*pdb_method)->update_sam_account = unixsam_update_sam_account; - (*pdb_method)->getsampwnam = unixsam_getsampwnam; - (*pdb_method)->getsampwsid = unixsam_getsampwsid; - - /* There's not very much to initialise here */ - return NT_STATUS_OK; -} - -NTSTATUS pdb_unix_init(void) -{ - return smb_register_passdb(PASSDB_INTERFACE_VERSION, "unixsam", pdb_init_unixsam); -} diff --git a/source3/script/cvslog.pl b/source3/script/cvslog.pl deleted file mode 100755 index f3d020aa72..0000000000 --- a/source3/script/cvslog.pl +++ /dev/null @@ -1,102 +0,0 @@ -#!/usr/bin/perl -w - -my ( $tag, $filename, $date ); -my ( $tmp, $change_flag ); - -if ( $#ARGV != 2 ) { - - print "Usage: ", $0, " cvstag date file\n"; - exit 1; -} - -$tag = $ARGV[0]; -$date = $ARGV[1]; -$filename = $ARGV[2]; - -print STDERR "$filename\n"; - -open ( CVSLOG, "cvs log -d\"$date\" $filename |" ) || die $!; - -## -## First get the branch revision number -## -undef $revision; -while ( !defined($revision) ) { - if ( eof( \*CVSLOG ) ) { - print STDERR "Premature end of cvs log output!\n"; - exit (1); - } - - $string = ; - chomp( $string ); - - if ( $string =~ /$tag:/ ) { - ( $tmp, $revision ) = split( /:/, $string ); - $revision =~ s/\s+//g; - $revision =~ s/\.0\./\./g; - } -} - -## -## Setup the beginning of the first record -## -$string = ""; -while ( $string !~ /^-+/ ) { - $string = ; - exit(0) if ( eof(\*CVSLOG) ); -} - -## -## Loop starting at the revision number for the entry -## - -while ( $string = ) { - - ($tmp, $entry_rev) = split( /\s+/, $string ); - if ( equal_revision( $revision, $entry_rev ) ) { - if ( ! defined($change_flag) ) { - print "++++++++++++++++++++++++++++++++++++++++++++++++++\n"; - print "## $filename\n"; - print "++\n"; - $change_flag = 1; - } - - while ( $string !~ /^-+/ && !eof(CVSLOG) ) { - print "$string"; - $string = ; - } - } - else { - while ( ($string !~ /^-+/) && !eof(CVSLOG) ) { - $string = ; - } - } -} - -close( CVSLOG ); -exit 0; - -############################################################## -## -sub equal_revision { - my ( $branch, $newfile ) = @_; - my ( $indx ); - my ( @branch_rev, @file_rev ); - - @branch_rev = split( /\./, $branch ); - @file_rev = split( /\./, $newfile ); - - return 0 if ( $#branch_rev != ($#file_rev - 1) ); - - $indx = 0; - while( $indx <= $#branch_rev ) { - if ( $branch_rev[$indx] != $file_rev[$indx] ) { - return 0; - } - $indx++; - } - - return 1; -} - - -- cgit From fd5b572f556bcd56ffa04013b8ce731dcf79dcf0 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Tue, 9 Sep 2003 18:29:33 +0000 Subject: version.h is autogenerated now (This used to be commit 04f8cbbca66024ffdcd2ebc0f4db7849d02ca99b) --- source3/include/version.h | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 source3/include/version.h (limited to 'source3') diff --git a/source3/include/version.h b/source3/include/version.h deleted file mode 100644 index 51e8c408e6..0000000000 --- a/source3/include/version.h +++ /dev/null @@ -1,8 +0,0 @@ -/* Autogenerated by script/mkversion.sh */ -#define SAMBA_VERSION_MAJOR 3 -#define SAMBA_VERSION_MINOR 0 -#define SAMBA_VERSION_RELEASE 1 -#define SAMBA_VERSION_PRE_RELEASE 1 -#define SAMBA_VERSION_IS_CVS_SNAPSHOT 1 -#define SAMBA_VERSION_OFFICIAL_STRING "CVS 3.0.1pre1" -#define SAMBA_VERSION_STRING samba_version_string() -- cgit From 9a9031ec729f1ce6bd18e95bd726d4200dfd9500 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Wed, 10 Sep 2003 00:43:00 +0000 Subject: remove references to 'strip dot' (This used to be commit b5c5a9dc76c7584047e6ad8e7063b2da348e67d7) --- source3/param/loadparm.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'source3') diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index 41b32cef10..b370b6b049 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -246,7 +246,6 @@ typedef struct BOOL bUpdateEncrypt; int clientSchannel; int serverSchannel; - BOOL bStripDot; BOOL bNullPasswords; BOOL bObeyPamRestrictions; BOOL bLoadPrinters; @@ -965,7 +964,6 @@ static struct parm_struct parm_table[] = { {"default devmode", P_BOOL, P_LOCAL, &sDefault.bDefaultDevmode, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT}, {"Filename Handling", P_SEP, P_SEPARATOR}, - {"strip dot", P_BOOL, P_GLOBAL, &Globals.bStripDot, NULL, NULL, FLAG_ADVANCED}, {"mangling method", P_STRING, P_GLOBAL, &Globals.szManglingMethod, NULL, NULL, FLAG_ADVANCED}, {"mangle prefix", P_INTEGER, P_GLOBAL, &Globals.mangle_prefix, NULL, NULL, FLAG_ADVANCED}, @@ -1387,7 +1385,6 @@ static void init_globals(void) Globals.bReadbmpx = False; Globals.bNullPasswords = False; Globals.bObeyPamRestrictions = False; - Globals.bStripDot = False; Globals.syslog = 1; Globals.bSyslogOnly = False; Globals.bTimestampLogs = True; @@ -1718,7 +1715,6 @@ FN_GLOBAL_BOOL(lp_large_readwrite, &Globals.bLargeReadwrite) FN_GLOBAL_BOOL(lp_writeraw, &Globals.bWriteRaw) FN_GLOBAL_BOOL(lp_null_passwords, &Globals.bNullPasswords) FN_GLOBAL_BOOL(lp_obey_pam_restrictions, &Globals.bObeyPamRestrictions) -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_INTEGER(lp_client_schannel, &Globals.clientSchannel) -- cgit From ca4dabf12c8f23977c4ed190a5e32e16e7d56d6b Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Wed, 10 Sep 2003 03:34:21 +0000 Subject: Removed accidentally re-added file. (This used to be commit a7bffe2095e4bb591dfa97ea4d786483fd44053b) --- source3/intl/libgettext.h | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 source3/intl/libgettext.h (limited to 'source3') diff --git a/source3/intl/libgettext.h b/source3/intl/libgettext.h deleted file mode 100644 index e69de29bb2..0000000000 -- cgit From f59a010674418f3e82774a8680fa108d02eb8460 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Wed, 10 Sep 2003 03:47:10 +0000 Subject: Remove autogenerated file. (This used to be commit 275bdc3ff550fd14a11c9f3919a82d4af35dc6fa) --- source3/smbadduser | 79 ------------------------------------------------------ 1 file changed, 79 deletions(-) delete mode 100755 source3/smbadduser (limited to 'source3') diff --git a/source3/smbadduser b/source3/smbadduser deleted file mode 100755 index 35f6dbab14..0000000000 --- a/source3/smbadduser +++ /dev/null @@ -1,79 +0,0 @@ -#!/bin/csh -# -# smbadduser - Written by Mike Zakharoff -# - -prefix=/usr/local/samba -exec_prefix=${prefix} -LIBDIR=${exec_prefix}/lib -PRIVATEDIR=${prefix}/private -CONFIGDIR=${LIBDIR} - -unalias * -set path = ($path /usr/local/samba/bin) - -set smbpasswd = $PRIVATEDIR/smbpasswd -set user_map = $CONFIGDIR/users.map - -# -# Set to site specific passwd command -# -set passwd = "cat /etc/passwd" -#set passwd = "niscat passwd.org_dir" -#set passwd = "ypcat passwd" - -set line = "----------------------------------------------------------" -if ($#argv == 0) then - echo $line - echo "Written: Mike Zakharoff email: michael.j.zakharoff@boeing.com" - echo "" - echo " 1) Updates $smbpasswd" - echo " 2) Updates $user_map" - echo " 3) Executes smbpasswd for each new user" - echo "" - echo "smbadduser unixid:ntid unixid:ntid ..." - echo "" - echo "Example: smbadduser zak:zakharoffm johns:smithj" - echo $line - exit 1 -endif - -touch $smbpasswd $user_map -set new = () -foreach one ($argv) - echo $one | grep ':' >& /dev/null - if ($status != 0) then - echo "ERROR: Must use unixid:ntid like -> zak:zakharoffm" - continue - endif - set unix = `echo $one | awk -F: '{print $1}'` - set ntid = `echo $one | awk -F: '{print $2}'` - - set usr = `eval $passwd | awk -F: '$1==USR {print $1}' USR=$unix` - if ($#usr != 1) then - echo "ERROR: $unix Not in passwd database SKIPPING..." - continue - endif - set tmp = `cat $smbpasswd | awk -F: '$1==USR {print $1}' USR=$unix` - if ($#tmp != 0) then - echo "ERROR: $unix is already in $smbpasswd SKIPPING..." - continue - endif - - echo "Adding: $unix to $smbpasswd" - /usr/bin/smbpasswd -a -n $unix - if ($unix != $ntid) then - echo "Adding: {$unix = $ntid} to $user_map" - echo "$unix = $ntid" >> $user_map - endif - set new = ($new $unix) -end - -# -# Enter password for new users -# -foreach one ($new) - echo $line - echo "ENTER password for $one" - smbpasswd $one -end -- cgit From 80a11b868d402174ad3afab37c8f461c3c6eeb1c Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Wed, 10 Sep 2003 03:49:43 +0000 Subject: Remove another dead file. (This used to be commit a5656a5756b3c1061d683d664a7f087182b39b47) --- source3/lib/ldap.c | 719 ------------------------------------------------- source3/python/mkpatch | 6 - 2 files changed, 725 deletions(-) delete mode 100644 source3/lib/ldap.c delete mode 100755 source3/python/mkpatch (limited to 'source3') diff --git a/source3/lib/ldap.c b/source3/lib/ldap.c deleted file mode 100644 index 917e03a871..0000000000 --- a/source3/lib/ldap.c +++ /dev/null @@ -1,719 +0,0 @@ -/* - 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) Jim McDonough 2003 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#include "includes.h" - -#ifdef HAVE_LDAP -/* TODO: -* persistent connections: if using NSS LDAP, many connections are made -* however, using only one within Samba would be nice -* -* Clean up SSL stuff, compile on OpenLDAP 1.x, 2.x, and Netscape SDK -* -* Other LDAP based login attributes: accountExpires, etc. -* (should be the domain of Samba proper, but the sam_password/SAM_ACCOUNT -* structures don't have fields for some of these attributes) -* -* SSL is done, but can't get the certificate based authentication to work -* against on my test platform (Linux 2.4, OpenLDAP 2.x) -*/ - -/* NOTE: this will NOT work against an Active Directory server -* due to the fact that the two password fields cannot be retrieved -* from a server; recommend using security = domain in this situation -* and/or winbind -*/ - -#include "smb_ldap.h" - -/* We need an internal mapping of LDAP * -> smb_ldap_privates so we implement - it in terms of a VK list. It's a little backwards but its quite efficent */ -static struct smb_ldap_privates *head; - -static struct smb_ldap_privates *get_internal(LDAP *ldap_struct) -{ - struct smb_ldap_privates *ret = head; - - while (NULL != ret && ret->ldap_struct != ldap_struct) { - ret = ret->next; - } - - return ret; -} - -#define SMB_LDAP_DONT_PING_TIME 10 /* ping only all 10 seconds */ - -/******************************************************************* - find the ldap password -******************************************************************/ -static BOOL smb_ldap_fetch_pw(char **dn, char** pw) -{ - char *key = NULL; - size_t size; - - *dn = smb_xstrdup(lp_ldap_admin_dn()); - - if (asprintf(&key, "%s/%s", SECRETS_LDAP_BIND_PW, *dn) < 0) { - SAFE_FREE(*dn); - DEBUG(0, ("smb_ldap_fetch_pw: asprintf failed!\n")); - } - - *pw=secrets_fetch(key, &size); - SAFE_FREE(key); - if (!size) { - /* Upgrade 2.2 style entry */ - char *p; - char* old_style_key = strdup(*dn); - char *data; - fstring old_style_pw; - - if (!old_style_key) { - DEBUG(0, ("smb_ldap_fetch_pw: strdup failed!\n")); - return False; - } - - for (p=old_style_key; *p; p++) - if (*p == ',') *p = '/'; - - data=secrets_fetch(old_style_key, &size); - if (!size && size < sizeof(old_style_pw)) { - DEBUG(0,("fetch_ldap_pw: neither ldap secret retrieved!\n")); - SAFE_FREE(old_style_key); - SAFE_FREE(*dn); - return False; - } - - strncpy(old_style_pw, data, size); - old_style_pw[size] = 0; - - SAFE_FREE(data); - - if (!secrets_store_ldap_pw(*dn, old_style_pw)) { - DEBUG(0,("fetch_ldap_pw: ldap secret could not be upgraded!\n")); - SAFE_FREE(old_style_key); - SAFE_FREE(*dn); - return False; - } - if (!secrets_delete(old_style_key)) { - DEBUG(0,("fetch_ldap_pw: old ldap secret could not be deleted!\n")); - } - - SAFE_FREE(old_style_key); - - *pw = smb_xstrdup(old_style_pw); - } - - return True; -} - -/******************************************************************* - open a connection to the ldap server. -******************************************************************/ -int smb_ldap_open_connection (struct smb_ldap_privates *ldap_state, - LDAP ** ldap_struct) -{ - int rc = LDAP_SUCCESS; - int version; - BOOL ldap_v3 = False; - -#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000) - DEBUG(10, ("smb_ldap_open_connection: %s\n", ldap_state->uri)); - - if ((rc = ldap_initialize(ldap_struct, ldap_state->uri)) != LDAP_SUCCESS) { - DEBUG(0, ("ldap_initialize: %s\n", ldap_err2string(rc))); - return rc; - } - -#else - - /* Parse the string manually */ - - { - int port = 0; - fstring protocol; - fstring host; - const char *p = ldap_state->uri; - SMB_ASSERT(sizeof(protocol)>10 && sizeof(host)>254); - - /* skip leading "URL:" (if any) */ - if ( strncasecmp( p, "URL:", 4 ) == 0 ) { - p += 4; - } - - sscanf(p, "%10[^:]://%254s[^:]:%d", protocol, host, &port); - - if (port == 0) { - if (strequal(protocol, "ldap")) { - port = LDAP_PORT; - } else if (strequal(protocol, "ldaps")) { - port = LDAPS_PORT; - } else { - DEBUG(0, ("unrecognised protocol (%s)!\n", protocol)); - } - } - - if ((*ldap_struct = ldap_init(host, port)) == NULL) { - DEBUG(0, ("ldap_init failed !\n")); - return LDAP_OPERATIONS_ERROR; - } - - if (strequal(protocol, "ldaps")) { -#ifdef LDAP_OPT_X_TLS - int tls = LDAP_OPT_X_TLS_HARD; - if (ldap_set_option (*ldap_struct, LDAP_OPT_X_TLS, &tls) != LDAP_SUCCESS) - { - DEBUG(0, ("Failed to setup a TLS session\n")); - } - - DEBUG(3,("LDAPS option set...!\n")); -#else - DEBUG(0,("smb_ldap_open_connection: Secure connection not supported by LDAP client libraries!\n")); - return LDAP_OPERATIONS_ERROR; -#endif - } - } -#endif - - if (ldap_get_option(*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version) == LDAP_OPT_SUCCESS) - { - if (version != LDAP_VERSION3) - { - version = LDAP_VERSION3; - if (ldap_set_option (*ldap_struct, LDAP_OPT_PROTOCOL_VERSION, &version) == LDAP_OPT_SUCCESS) { - ldap_v3 = True; - } - } else { - ldap_v3 = True; - } - } - - if (lp_ldap_ssl() == LDAP_SSL_START_TLS) { -#ifdef LDAP_OPT_X_TLS - if (ldap_v3) { - if ((rc = ldap_start_tls_s (*ldap_struct, NULL, NULL)) != LDAP_SUCCESS) - { - DEBUG(0,("Failed to issue the StartTLS instruction: %s\n", - ldap_err2string(rc))); - return rc; - } - DEBUG (3, ("StartTLS issued: using a TLS connection\n")); - } else { - - DEBUG(0, ("Need LDAPv3 for Start TLS\n")); - return LDAP_OPERATIONS_ERROR; - } -#else - DEBUG(0,("smb_ldap_open_connection: StartTLS not supported by LDAP client libraries!\n")); - return LDAP_OPERATIONS_ERROR; -#endif - } - - DEBUG(2, ("smb_ldap_open_connection: connection opened\n")); - return rc; -} - - -/******************************************************************* - 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) -{ - struct smb_ldap_privates *ldap_state = arg; - - /** @TODO Should we be doing something to check what servers we rebind to? - Could we get a referral to a machine that we don't want to give our - username and password to? */ - - if (freeit) { - SAFE_FREE(*whop); - memset(*credp, '\0', strlen(*credp)); - SAFE_FREE(*credp); - } else { - DEBUG(5,("rebind_proc_with_state: Rebinding as \"%s\"\n", - ldap_state->bind_dn)); - - *whop = strdup(ldap_state->bind_dn); - if (!*whop) { - return LDAP_NO_MEMORY; - } - *credp = strdup(ldap_state->bind_secret); - if (!*credp) { - SAFE_FREE(*whop); - return LDAP_NO_MEMORY; - } - *methodp = LDAP_AUTH_SIMPLE; - } - 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, - ber_int_t msgid, void *arg) -{ - struct smb_ldap_privates *ldap_state = arg; - int rc; - DEBUG(5,("rebindproc_connect_with_state: Rebinding as \"%s\"\n", - ldap_state->bind_dn)); - - /** @TODO Should we be doing something to check what servers we rebind to? - Could we get a referral to a machine that we don't want to give our - username and password to? */ - - rc = ldap_simple_bind_s(ldap_struct, ldap_state->bind_dn, ldap_state->bind_secret); - - 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 ) -{ - return rebindproc_with_state(ldap_struct, whop, credp, - method, freeit, get_internal(ldap_struct)); - -} -# 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, - get_internal(ld)); -} -# 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. -******************************************************************/ -int smb_ldap_connect_system(struct smb_ldap_privates *ldap_state, - LDAP * ldap_struct) -{ - int rc; - char *ldap_dn; - char *ldap_secret; - - if (NULL == get_internal(ldap_struct)) { - ldap_state->next = head; - } - - /* get the password */ - if (!smb_ldap_fetch_pw(&ldap_dn, &ldap_secret)) - { - DEBUG(0, ("ldap_connect_system: Failed to retrieve password from secrets.tdb\n")); - return LDAP_INVALID_CREDENTIALS; - } - - ldap_state->bind_dn = ldap_dn; - ldap_state->bind_secret = ldap_secret; - - /* removed the sasl_bind_s "EXTERNAL" stuff, as my testsuite - (OpenLDAP) doesnt' seem to support it */ - - DEBUG(10,("ldap_connect_system: Binding to ldap server %s as \"%s\"\n", - ldap_state->uri, ldap_dn)); - -#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000) -# if LDAP_SET_REBIND_PROC_ARGS == 2 - ldap_set_rebind_proc(ldap_struct, &rebindproc_connect); -# endif -# if LDAP_SET_REBIND_PROC_ARGS == 3 - ldap_set_rebind_proc(ldap_struct, &rebindproc_connect_with_state, (void *)ldap_state); -# endif -#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 /*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) { - char *ld_error; - ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, - &ld_error); - DEBUG(0, - ("failed to bind to server with dn= %s Error: %s\n\t%s\n", - ldap_dn, ldap_err2string(rc), - ld_error)); - free(ld_error); - return rc; - } - - DEBUG(2, ("ldap_connect_system: succesful connection to the LDAP server\n")); - return rc; -} - -/********************************************************************** -Connect to LDAP server -*********************************************************************/ -int smb_ldap_open(struct smb_ldap_privates *ldap_state) -{ - int rc; - SMB_ASSERT(ldap_state); - -#ifndef NO_LDAP_SECURITY - if (geteuid() != 0) { - DEBUG(0, ("smb_ldap_open: cannot access LDAP when not root..\n")); - return LDAP_INSUFFICIENT_ACCESS; - } -#endif - - if ((ldap_state->ldap_struct != NULL) && ((ldap_state->last_ping + SMB_LDAP_DONT_PING_TIME) < time(NULL))) { - struct sockaddr_un addr; - socklen_t len; - int sd; - if (ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_DESC, &sd) == 0 && - getpeername(sd, (struct sockaddr *) &addr, &len) < 0) { - /* the other end has died. reopen. */ - ldap_unbind_ext(ldap_state->ldap_struct, NULL, NULL); - ldap_state->ldap_struct = NULL; - ldap_state->last_ping = (time_t)0; - } else { - ldap_state->last_ping = time(NULL); - } - } - - if (ldap_state->ldap_struct != NULL) { - DEBUG(5,("smb_ldap_open: allready connected to the LDAP server\n")); - return LDAP_SUCCESS; - } - - if ((rc = smb_ldap_open_connection(ldap_state, &ldap_state->ldap_struct))) { - return rc; - } - - if ((rc = smb_ldap_connect_system(ldap_state, ldap_state->ldap_struct))) { - ldap_unbind_ext(ldap_state->ldap_struct, NULL, NULL); - ldap_state->ldap_struct = NULL; - return rc; - } - - - ldap_state->last_ping = time(NULL); - DEBUG(4,("The LDAP server is succesful connected\n")); - - return LDAP_SUCCESS; -} - -/********************************************************************** -Disconnect from LDAP server -*********************************************************************/ -NTSTATUS smb_ldap_close(struct smb_ldap_privates *ldap_state) -{ - if (!ldap_state) - return NT_STATUS_INVALID_PARAMETER; - - if (ldap_state->ldap_struct != NULL) { - ldap_unbind_ext(ldap_state->ldap_struct, NULL, NULL); - ldap_state->ldap_struct = NULL; - } - - DEBUG(5,("The connection to the LDAP server was closed\n")); - /* maybe free the results here --metze */ - - return NT_STATUS_OK; -} - -static int smb_ldap_retry_open(struct smb_ldap_privates *ldap_state, int *attempts) -{ - int rc; - - SMB_ASSERT(ldap_state && attempts); - - if (*attempts != 0) { - /* we retry after 0.5, 2, 4.5, 8, 12.5, 18, 24.5 seconds */ - msleep((((*attempts)*(*attempts))/2)*1000); - } - (*attempts)++; - - if ((rc = smb_ldap_open(ldap_state))) { - DEBUG(0,("Connection to LDAP Server failed for the %d try!\n",*attempts)); - return rc; - } - - return LDAP_SUCCESS; -} - - -int smb_ldap_search(struct smb_ldap_privates *ldap_state, - const char *base, int scope, const char *filter, - const char *attrs[], int attrsonly, - LDAPMessage **res) -{ - int rc = LDAP_SERVER_DOWN; - int attempts = 0; - - SMB_ASSERT(ldap_state); - - while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) { - - if ((rc = smb_ldap_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS) - continue; - - rc = ldap_search_s(ldap_state->ldap_struct, base, scope, - filter, (char **)attrs, attrsonly, res); - } - - if (rc == LDAP_SERVER_DOWN) { - DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO)); - smb_ldap_close(ldap_state); - } - - return rc; -} - -int smb_ldap_modify(struct smb_ldap_privates *ldap_state, char *dn, - LDAPMod *attrs[]) -{ - int rc = LDAP_SERVER_DOWN; - int attempts = 0; - - if (!ldap_state) - return (-1); - - while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) { - - if ((rc = smb_ldap_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS) - continue; - - rc = ldap_modify_s(ldap_state->ldap_struct, dn, attrs); - } - - if (rc == LDAP_SERVER_DOWN) { - DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO)); - smb_ldap_close(ldap_state); - } - - return rc; -} - -int smb_ldap_add(struct smb_ldap_privates *ldap_state, const char *dn, - LDAPMod *attrs[]) -{ - int rc = LDAP_SERVER_DOWN; - int attempts = 0; - - if (!ldap_state) - return (-1); - - while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) { - - if ((rc = smb_ldap_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS) - continue; - - rc = ldap_add_s(ldap_state->ldap_struct, dn, attrs); - } - - if (rc == LDAP_SERVER_DOWN) { - DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO)); - smb_ldap_close(ldap_state); - } - - return rc; -} - -int smb_ldap_delete(struct smb_ldap_privates *ldap_state, char *dn) -{ - int rc = LDAP_SERVER_DOWN; - int attempts = 0; - - if (!ldap_state) - return (-1); - - while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) { - - if ((rc = smb_ldap_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS) - continue; - - rc = ldap_delete_s(ldap_state->ldap_struct, dn); - } - - if (rc == LDAP_SERVER_DOWN) { - DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO)); - smb_ldap_close(ldap_state); - } - - return rc; -} - -int smb_ldap_extended_operation(struct smb_ldap_privates *ldap_state, - LDAP_CONST char *reqoid, - struct berval *reqdata, - LDAPControl **serverctrls, - LDAPControl **clientctrls, char **retoidp, - struct berval **retdatap) -{ - int rc = LDAP_SERVER_DOWN; - int attempts = 0; - - if (!ldap_state) - return (-1); - - while ((rc == LDAP_SERVER_DOWN) && (attempts < 8)) { - - if ((rc = smb_ldap_retry_open(ldap_state,&attempts)) != LDAP_SUCCESS) - continue; - - rc = ldap_extended_operation_s(ldap_state->ldap_struct, reqoid, reqdata, serverctrls, clientctrls, retoidp, retdatap); - } - - if (rc == LDAP_SERVER_DOWN) { - DEBUG(0,("%s: LDAP server is down!\n",FUNCTION_MACRO)); - smb_ldap_close(ldap_state); - } - - return rc; -} - -/******************************************************************* -search an attribute and return the first value found. -******************************************************************/ -BOOL smb_ldap_get_single_attribute (LDAP * ldap_struct, LDAPMessage * entry, - const char *attribute, pstring value) -{ - char **values; - - if ((values = ldap_get_values (ldap_struct, entry, attribute)) == NULL) { - value = NULL; - DEBUG (10, ("smb_ldap_get_single_attribute: [%s] = []\n", attribute)); - - return False; - } - - pstrcpy(value, values[0]); - ldap_value_free(values); -#ifdef DEBUG_PASSWORDS - DEBUG (100, ("smb_ldap_get_single_attribute: [%s] = [%s]\n", attribute, value)); -#endif - return True; -} - - -/************************************************************************ -Routine to manage the LDAPMod structure array -manage memory used by the array, by each struct, and values - -************************************************************************/ -void smb_ldap_make_a_mod (LDAPMod *** modlist, int modop, - const char *attribute, const char *value) -{ - LDAPMod **mods; - int i; - int j; - - mods = *modlist; - - if (attribute == NULL || *attribute == '\0') - return; - - if (value == NULL || *value == '\0') - return; - - if (mods == NULL) - { - mods = (LDAPMod **) malloc(sizeof(LDAPMod *)); - if (mods == NULL) - { - DEBUG(0, ("smb_ldap_make_a_mod: out of memory!\n")); - return; - } - mods[0] = NULL; - } - - for (i = 0; mods[i] != NULL; ++i) { - if (mods[i]->mod_op == modop && !strcasecmp(mods[i]->mod_type, attribute)) - break; - } - - if (mods[i] == NULL) - { - mods = (LDAPMod **) Realloc (mods, (i + 2) * sizeof (LDAPMod *)); - if (mods == NULL) - { - DEBUG(0, ("smb_ldap_make_a_mod: out of memory!\n")); - return; - } - mods[i] = (LDAPMod *) malloc(sizeof(LDAPMod)); - if (mods[i] == NULL) - { - DEBUG(0, ("smb_ldap_make_a_mod: out of memory!\n")); - return; - } - mods[i]->mod_op = modop; - mods[i]->mod_values = NULL; - mods[i]->mod_type = strdup(attribute); - mods[i + 1] = NULL; - } - - if (value != NULL) - { - j = 0; - if (mods[i]->mod_values != NULL) { - for (; mods[i]->mod_values[j] != NULL; j++); - } - mods[i]->mod_values = (char **)Realloc(mods[i]->mod_values, - (j + 2) * sizeof (char *)); - - if (mods[i]->mod_values == NULL) { - DEBUG (0, ("smb_ldap_make_a_mod: Memory allocation failure!\n")); - return; - } - mods[i]->mod_values[j] = strdup(value); - mods[i]->mod_values[j + 1] = NULL; - } - *modlist = mods; -} - -#endif diff --git a/source3/python/mkpatch b/source3/python/mkpatch deleted file mode 100755 index ab5be1b6a2..0000000000 --- a/source3/python/mkpatch +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh -# -# Make samba-head.patch. Must be run from samba source directory. -# - -cvs -z3 diff -u Makefile.in configure.in > python/samba-head.patch -- cgit From 623a46b7e4a56f0f9552a6b394409136d0c050cd Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Wed, 10 Sep 2003 03:59:35 +0000 Subject: Remove tags file for distclean. (This used to be commit 2ac5ac495025f6c673216c1922ff51b913a0aeac) --- source3/Makefile.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3') diff --git a/source3/Makefile.in b/source3/Makefile.in index f7ec500d06..a2c4a360d4 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -1377,7 +1377,7 @@ distclean: realclean -rm -f include/stamp-h -rm -f include/config.h Makefile -rm -f config.status config.cache so_locations - -rm -rf .deps + -rm -rf .deps TAGS realdistclean: distclean -rm -f include/config.h.in -- cgit From 37737023a8dccbaa546d1b88999c4d4f8257e436 Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Wed, 10 Sep 2003 14:03:08 +0000 Subject: Support for CAN-2003-0689 port from SAMBA_3_0 (This used to be commit 69b30ec0776b06c62810a3eb1d7be1df3db9e169) --- source3/configure.in | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) (limited to 'source3') diff --git a/source3/configure.in b/source3/configure.in index a2e04b5d48..151411feb8 100644 --- a/source3/configure.in +++ b/source3/configure.in @@ -883,8 +883,23 @@ AC_CHECK_FUNCS(open64 _open64 __open64 creat64) # case "$host_os" in *linux*) - # glibc <= 2.3.2 has a broken getgrouplist - AC_TRY_RUN([ + # test if user trusts its own glibc version w.r.t. CAN-2003-0689 + # Some vendors already provided glibc builds with this fix so getgrouplist() is usable + # on those platforms. Unfortunately, we can't get this information from compiling yet. + AC_MSG_CHECKING([whether GNU libc has good getgrouplist w.r.t. CAN-2003-0689]) + AC_ARG_WITH(good-getgrouplist, + [ --with-good-getgrouplist[=no] whether GNU libc has good getgrouplist w.r.t. CAN-2003-0689 ], + [ case "$with_good_getgrouplist" in + yes) + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_GETGROUPLIST, 1, [Have good getgrouplist]) + ;; + *) + AC_MSG_RESULT(no) + ;; + esac], +# glibc <= 2.3.2 has a broken getgrouplist +AC_TRY_RUN([ #include #include main() { @@ -902,8 +917,12 @@ main() { } ], [linux_getgrouplist_ok=yes], [linux_getgrouplist_ok=no]) if test x"$linux_getgrouplist_ok" = x"yes"; then + AC_MSG_RESULT(yes) AC_DEFINE(HAVE_GETGROUPLIST, 1, [Have good getgrouplist]) + else + AC_MSG_RESULT(no) fi +) ;; *) AC_CHECK_FUNCS(getgrouplist) -- cgit From 1c138c61818c5641ce5bd556d44245db5d4b45ca Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Wed, 10 Sep 2003 15:41:07 +0000 Subject: Back out --with-good-getgrouplist patch (This used to be commit d2fdc3955fb6859e865e805d32ca405ab44d0505) --- source3/configure.in | 23 ++--------------------- 1 file changed, 2 insertions(+), 21 deletions(-) (limited to 'source3') diff --git a/source3/configure.in b/source3/configure.in index 151411feb8..a2e04b5d48 100644 --- a/source3/configure.in +++ b/source3/configure.in @@ -883,23 +883,8 @@ AC_CHECK_FUNCS(open64 _open64 __open64 creat64) # case "$host_os" in *linux*) - # test if user trusts its own glibc version w.r.t. CAN-2003-0689 - # Some vendors already provided glibc builds with this fix so getgrouplist() is usable - # on those platforms. Unfortunately, we can't get this information from compiling yet. - AC_MSG_CHECKING([whether GNU libc has good getgrouplist w.r.t. CAN-2003-0689]) - AC_ARG_WITH(good-getgrouplist, - [ --with-good-getgrouplist[=no] whether GNU libc has good getgrouplist w.r.t. CAN-2003-0689 ], - [ case "$with_good_getgrouplist" in - yes) - AC_MSG_RESULT(yes) - AC_DEFINE(HAVE_GETGROUPLIST, 1, [Have good getgrouplist]) - ;; - *) - AC_MSG_RESULT(no) - ;; - esac], -# glibc <= 2.3.2 has a broken getgrouplist -AC_TRY_RUN([ + # glibc <= 2.3.2 has a broken getgrouplist + AC_TRY_RUN([ #include #include main() { @@ -917,12 +902,8 @@ main() { } ], [linux_getgrouplist_ok=yes], [linux_getgrouplist_ok=no]) if test x"$linux_getgrouplist_ok" = x"yes"; then - AC_MSG_RESULT(yes) AC_DEFINE(HAVE_GETGROUPLIST, 1, [Have good getgrouplist]) - else - AC_MSG_RESULT(no) fi -) ;; *) AC_CHECK_FUNCS(getgrouplist) -- cgit From ff166384c84acb24fad4abe54e2ec43a7f4fdfc3 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Wed, 10 Sep 2003 19:47:13 +0000 Subject: Remove obsolete files. (This used to be commit 3d71340e5c1bf3397e69897bbc8434bbaa503a75) --- source3/include/sam.h | 238 ------ source3/sam/SAM-interface_handles.txt | 123 --- source3/sam/get_set_account.c | 845 -------------------- source3/sam/get_set_domain.c | 263 ------- source3/sam/get_set_group.c | 106 --- source3/sam/sam_ads.c | 1378 --------------------------------- source3/sam/sam_plugin.c | 79 -- source3/sam/sam_skel.c | 251 ------ source3/torture/cmd_sam.c | 514 ------------ source3/torture/samtest.c | 445 ----------- 10 files changed, 4242 deletions(-) delete mode 100644 source3/include/sam.h delete mode 100644 source3/sam/SAM-interface_handles.txt delete mode 100644 source3/sam/get_set_account.c delete mode 100644 source3/sam/get_set_domain.c delete mode 100644 source3/sam/get_set_group.c delete mode 100755 source3/sam/sam_ads.c delete mode 100644 source3/sam/sam_plugin.c delete mode 100644 source3/sam/sam_skel.c delete mode 100644 source3/torture/cmd_sam.c delete mode 100644 source3/torture/samtest.c (limited to 'source3') diff --git a/source3/include/sam.h b/source3/include/sam.h deleted file mode 100644 index f46a6e7bcb..0000000000 --- a/source3/include/sam.h +++ /dev/null @@ -1,238 +0,0 @@ -/* - Unix SMB/CIFS implementation. - SAM structures - Copyright (C) Kai Krueger 2002 - Copyright (C) Stefan (metze) Metzmacher 2002 - Copyright (C) Simo Sorce 2002 - Copyright (C) Andrew Bartlett 2002 - 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 Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#ifndef _SAM_H -#define _SAM_H - -/* We want to track down bugs early */ -#if 1 -#define SAM_ASSERT(x) SMB_ASSERT(x) -#else -#define SAM_ASSERT(x) while (0) { \ - if (!(x)) { - DEBUG(0, ("SAM_ASSERT failed!\n")) - return NT_STATUS_FAIL_CHECK;\ - } \ - } -#endif - - -/* let it be 0 until we have a stable interface --metze */ -#define SAM_INTERFACE_VERSION 0 - -/* use this inside a passdb module */ -#define SAM_MODULE_VERSIONING_MAGIC \ -int sam_version(void)\ -{\ - return SAM_INTERFACE_VERSION;\ -} - -/* Backend to use by default when no backend was specified */ -#define SAM_DEFAULT_BACKEND "plugin" - -typedef struct sam_domain_handle { - TALLOC_CTX *mem_ctx; - uint32 access_granted; - const struct sam_methods *current_sam_methods; /* sam_methods creating this handle */ - void (*free_fn)(struct sam_domain_handle **); - struct domain_data { - DOM_SID sid; /*SID of the domain. Should not be changed */ - char *name; /* Name of the domain */ - char *servername; /* */ - NTTIME max_passwordage; /* time till next password expiration */ - NTTIME min_passwordage; /* time till password can be changed again */ - NTTIME lockout_duration; /* time till login is allowed again after lockout*/ - NTTIME reset_count; /* time till bad login counter is reset */ - uint16 min_passwordlength; /* minimum number of characters for a password */ - uint16 password_history; /* number of passwords stored in history */ - uint16 lockout_count; /* number of bad login attempts before lockout */ - BOOL force_logoff; /* force logoff after logon hours have expired */ - BOOL login_pwdchange; /* Users need to logon to change their password */ - uint32 num_accounts; /* number of accounts in the domain */ - uint32 num_groups; /* number of global groups */ - uint32 num_aliases; /* number of local groups */ - uint32 sam_sequence_number; /* global sequence number */ - } private; -} SAM_DOMAIN_HANDLE; - -typedef struct sam_account_handle { - TALLOC_CTX *mem_ctx; - uint32 access_granted; - const struct sam_methods *current_sam_methods; /* sam_methods creating this handle */ - void (*free_fn)(struct sam_account_handle **); - struct sam_account_data { - uint32 init_flag; - NTTIME logon_time; /* logon time */ - NTTIME logoff_time; /* logoff time */ - NTTIME kickoff_time; /* kickoff time */ - NTTIME pass_last_set_time; /* password last set time */ - NTTIME pass_can_change_time; /* password can change time */ - NTTIME pass_must_change_time; /* password must change time */ - char * account_name; /* account_name string */ - SAM_DOMAIN_HANDLE * domain; /* domain of account */ - char *full_name; /* account's full name string */ - char *unix_home_dir; /* UNIX home directory string */ - char *home_dir; /* home directory string */ - char *dir_drive; /* home directory drive string */ - char *logon_script; /* logon script string */ - char *profile_path; /* profile path string */ - char *acct_desc; /* account description string */ - char *workstations; /* login from workstations string */ - char *unknown_str; /* don't know what this is, yet. */ - char *munged_dial; /* munged path name and dial-back tel number */ - DOM_SID account_sid; /* Primary Account SID */ - DOM_SID group_sid; /* Primary Group SID */ - DATA_BLOB lm_pw; /* .data is Null if no password */ - DATA_BLOB nt_pw; /* .data is Null if no password */ - char *plaintext_pw; /* if Null not available */ - uint16 acct_ctrl; /* account info (ACB_xxxx bit-mask) */ - uint32 unknown_1; /* 0x00ff ffff */ - uint16 logon_divs; /* 168 - number of hours in a week */ - uint32 hours_len; /* normally 21 bytes */ - uint8 hours[MAX_HOURS_LEN]; - uint32 unknown_2; /* 0x0002 0000 */ - uint32 unknown_3; /* 0x0000 04ec */ - } private; -} SAM_ACCOUNT_HANDLE; - -typedef struct sam_group_handle { - TALLOC_CTX *mem_ctx; - uint32 access_granted; - const struct sam_methods *current_sam_methods; /* sam_methods creating this handle */ - void (*free_fn)(struct sam_group_handle **); - struct sam_group_data { - char *group_name; - char *group_desc; - DOM_SID sid; - uint16 group_ctrl; /* specifies if the group is a local group or a global group */ - uint32 num_members; - } private; -} SAM_GROUP_HANDLE; - - -typedef struct sam_group_member { - DOM_SID sid; - BOOL group; /* specifies if it is a group or a account */ -} SAM_GROUP_MEMBER; - -typedef struct sam_account_enum { - DOM_SID sid; - char *account_name; - char *full_name; - char *account_desc; - uint16 acct_ctrl; -} SAM_ACCOUNT_ENUM; - -typedef struct sam_group_enum { - DOM_SID sid; - char *group_name; - char *group_desc; - uint16 group_ctrl; -} SAM_GROUP_ENUM; - - -/* bits for group_ctrl: to spezify if the group is global group or alias */ -#define GCB_LOCAL_GROUP 0x0001 -#define GCB_ALIAS_GROUP (GCB_LOCAL_GROUP |GCB_BUILTIN) -#define GCB_GLOBAL_GROUP 0x0002 -#define GCB_BUILTIN 0x1000 - -typedef struct sam_context -{ - struct sam_methods *methods; - TALLOC_CTX *mem_ctx; - - void (*free_fn)(struct sam_context **); -} SAM_CONTEXT; - -typedef struct sam_methods -{ - struct sam_context *parent; - struct sam_methods *next; - struct sam_methods *prev; - const char *backendname; - const char *domain_name; - DOM_SID domain_sid; - void *private_data; - - /* General API */ - - NTSTATUS (*sam_get_sec_desc) (const struct sam_methods *, const NT_USER_TOKEN *access_token, const DOM_SID *sid, SEC_DESC **sd); - NTSTATUS (*sam_set_sec_desc) (const struct sam_methods *, const NT_USER_TOKEN *access_token, const DOM_SID *sid, const SEC_DESC *sd); - - NTSTATUS (*sam_lookup_sid) (const struct sam_methods *, const NT_USER_TOKEN *access_token, TALLOC_CTX *mem_ctx, const DOM_SID *sid, char **name, uint32 *type); - NTSTATUS (*sam_lookup_name) (const struct sam_methods *, const NT_USER_TOKEN *access_token, const char *name, DOM_SID *sid, uint32 *type); - - /* Domain API */ - - NTSTATUS (*sam_update_domain) (const struct sam_methods *, const SAM_DOMAIN_HANDLE *domain); - NTSTATUS (*sam_get_domain_handle) (const struct sam_methods *, const NT_USER_TOKEN *access_token, uint32 access_desired, SAM_DOMAIN_HANDLE **domain); - - /* Account API */ - - NTSTATUS (*sam_create_account) (const struct sam_methods *, const NT_USER_TOKEN *access_token, uint32 access_desired, const char *account_name, uint16 acct_ctrl, SAM_ACCOUNT_HANDLE **account); - NTSTATUS (*sam_add_account) (const struct sam_methods *, const SAM_ACCOUNT_HANDLE *account); - NTSTATUS (*sam_update_account) (const struct sam_methods *, const SAM_ACCOUNT_HANDLE *account); - NTSTATUS (*sam_delete_account) (const struct sam_methods *, const SAM_ACCOUNT_HANDLE *account); - NTSTATUS (*sam_enum_accounts) (const struct sam_methods *, const NT_USER_TOKEN *access_token, uint16 acct_ctrl, uint32 *account_count, SAM_ACCOUNT_ENUM **accounts); - - NTSTATUS (*sam_get_account_by_sid) (const struct sam_methods *, const NT_USER_TOKEN *access_token, uint32 access_desired, const DOM_SID *accountsid, SAM_ACCOUNT_HANDLE **account); - NTSTATUS (*sam_get_account_by_name) (const struct sam_methods *, const NT_USER_TOKEN *access_token, uint32 access_desired, const char *name, SAM_ACCOUNT_HANDLE **account); - - /* Group API */ - - NTSTATUS (*sam_create_group) (const struct sam_methods *, const NT_USER_TOKEN *access_token, uint32 access_desired, const char *group_name, uint16 group_ctrl, SAM_GROUP_HANDLE **group); - NTSTATUS (*sam_add_group) (const struct sam_methods *, const SAM_GROUP_HANDLE *group); - NTSTATUS (*sam_update_group) (const struct sam_methods *, const SAM_GROUP_HANDLE *group); - NTSTATUS (*sam_delete_group) (const struct sam_methods *, const SAM_GROUP_HANDLE *group); - NTSTATUS (*sam_enum_groups) (const struct sam_methods *, const NT_USER_TOKEN *access_token, uint16 group_ctrl, uint32 *groups_count, SAM_GROUP_ENUM **groups); - NTSTATUS (*sam_get_group_by_sid) (const struct sam_methods *, const NT_USER_TOKEN *access_token, uint32 access_desired, const DOM_SID *groupsid, SAM_GROUP_HANDLE **group); - NTSTATUS (*sam_get_group_by_name) (const struct sam_methods *, const NT_USER_TOKEN *access_token, uint32 access_desired, const char *name, SAM_GROUP_HANDLE **group); - - NTSTATUS (*sam_add_member_to_group) (const struct sam_methods *, const SAM_GROUP_HANDLE *group, const SAM_GROUP_MEMBER *member); - NTSTATUS (*sam_delete_member_from_group) (const struct sam_methods *, const SAM_GROUP_HANDLE *group, const SAM_GROUP_MEMBER *member); - NTSTATUS (*sam_enum_groupmembers) (const struct sam_methods *, const SAM_GROUP_HANDLE *group, uint32 *members_count, SAM_GROUP_MEMBER **members); - - NTSTATUS (*sam_get_groups_of_sid) (const struct sam_methods *, const NT_USER_TOKEN *access_token, const DOM_SID **sids, uint16 group_ctrl, uint32 *group_count, SAM_GROUP_ENUM **groups); - - void (*free_private_data)(void **); -} SAM_METHODS; - -typedef NTSTATUS (*sam_init_function)(SAM_METHODS *, const char *); - -struct sam_init_function_entry { - char *module_name; - /* Function to create a member of the sam_methods list */ - sam_init_function init; -}; - -typedef struct sam_backend_entry { - char *module_name; - char *module_params; - char *domain_name; - DOM_SID *domain_sid; -} SAM_BACKEND_ENTRY; - - -#endif /* _SAM_H */ diff --git a/source3/sam/SAM-interface_handles.txt b/source3/sam/SAM-interface_handles.txt deleted file mode 100644 index 1c164bd198..0000000000 --- a/source3/sam/SAM-interface_handles.txt +++ /dev/null @@ -1,123 +0,0 @@ -SAM API - -NTSTATUS sam_get_sec_obj(NT_USER_TOKEN *access, DOM_SID *sid, SEC_DESC **sd) -NTSTATUS sam_set_sec_obj(NT_USER_TOKEN *access, DOM_SID *sid, SEC_DESC *sd) - -NTSTATUS sam_lookup_name(NT_USER_TOKEN *access, DOM_SID *domain, char *name, DOM_SID **sid, uint32 *type) -NTSTATUS sam_lookup_sid(NT_USER_TOKEN *access, DOM_SID *sid, char **name, uint32 *type) - - -Domain API - -NTSTATUS sam_update_domain(SAM_DOMAIN_HANDLE *domain) - -NTSTATUS sam_enum_domains(NT_USER_TOKEN *access, int32 *domain_count, DOM_SID **domains, char **domain_names) -NTSTATUS sam_lookup_domain(NT_USER_TOKEN *access, char *domain, DOM_SID **domainsid) - -NTSTATUS sam_get_domain_by_sid(NT_USER_TOKEN *access, uint32 access_desired, DOM_SID *domainsid, SAM_DOMAIN_HANDLE **domain) - - -User API - -NTSTATUS sam_create_user(NT_USER_TOKEN *access, uint32 access_desired, SAM_USER_HANDLE **user) -NTSTATUS sam_add_user(SAM_USER_HANDLE *user) -NTSTATUS sam_update_user(SAM_USER_HANDLE *user) -NTSTATUS sam_delete_user(SAM_USER_HANDLE * user) - -NTSTATUS sam_enum_users(NT_USER_TOKEN *access, DOM_SID *domain, int32 *user_count, SAM_USER_ENUM **users) - -NTSTATUS sam_get_user_by_sid(NT_USER_TOKEN *access, uint32 access_desired, DOM_SID *usersid, SAM_USER_HANDLE **user) -NTSTATUS sam_get_user_by_name(NT_USER_TOKEN *access, uint32 access_desired, char *domain, char *name, SAM_USER_HANDLE **user) - - -Group API - -NTSTATUS sam_create_group(NT_USER_TOKEN *access, uint32 access_desired, uint32 typ, SAM_GROUP_HANDLE **group) -NTSTATUS sam_add_group(SAM_GROUP_HANDLE *samgroup) -NTSTATUS sam_update_group(SAM_GROUP_HANDLE *samgroup) -NTSTATUS sam_delete_group(SAM_GROUP_HANDLE *groupsid) - -NTSTATUS sam_enum_groups(NT_USER_TOKEN *access, DOM_SID *domainsid, uint32 typ, uint32 *groups_count, SAM_GROUP_ENUM **groups) - -NTSTATUS sam_get_group_by_sid(NT_USER_TOKEN *access, uint32 access_desired, DOM_SID *groupsid, SAM_GROUP_HANDLE **group) -NTSTATUS sam_get_group_by_name(NT_USER_TOKEN *access, uint32 access_desired, char *domain, char *name, SAM_GROUP_HANDLE **group) - -NTSTATUS sam_add_member_to_group(SAM_GROUP_HANDLE *group, SAM_GROUP_MEMBER *member) -NTSTATUS sam_delete_member_from_group(SAM_GROUP_HANDLE *group, SAM_GROUP_MEMBER *member) -NTSTATUS sam_enum_groupmembers(SAM_GROUP_HANLDE *group, uint32 *members_count, SAM_GROUP_MEMBER **members) - -NTSTATUS sam_get_groups_of_user(SAM_USER_HANDLE *user, uint32 typ, uint32 *group_count, SAM_GROUP_ENUM **groups) - - - -structures - -typedef _SAM_GROUP_MEMBER { - DOM_SID sid; - BOOL group; /* specifies if it is a group or a user */ - -} SAM_GROUP_MEMBER - -typedef struct sam_user_enum { - DOM_SID sid; - char *username; - char *full_name; - char *user_desc; - uint16 acc_ctrl; -} SAM_USER_ENUM; - -typedef struct sam_group_enum { - DOM_SID sid; - char *groupname; - char *comment; -} SAM_GROUP_ENUM - -NTSTATUS sam_get_domain_sid(SAM_DOMAIN_HANDLE *domain, DOM_SID **sid) -NTSTATUS sam_get_domain_num_users(SAM_DOMAIN_HANDLE *domain, uint32 *num_users) -NTSTATUS sam_get_domain_num_groups(SAM_DOMAIN_HANDLE *domain, uint32 *num_groups) -NTSTATUS sam_get_domain_num_aliases(SAM_DOMAIN_HANDLE *domain, uint32 *num_aliases) -NTSTATUS sam_{get,set}_domain_name(SAM_DOMAIN_HANDLE *domain, char **domain_name) -NTSTATUS sam_{get,set}_domain_server(SAM_DOMAIN_HANDLE *domain, char **server_name) -NTSTATUS sam_{get,set}_domain_max_pwdage(SAM_DOMAIN_HANDLE *domain, NTTIME *max_passwordage) -NTSTATUS sam_{get,set}_domain_min_pwdage(SAM_DOMAIN_HANDLE *domain, NTTIME *min_passwordage) -NTSTATUS sam_{get,set}_domain_lockout_duration(SAM_DOMAIN_HANDLE *domain, NTTIME *lockout_duration) -NTSTATUS sam_{get,set}_domain_reset_count(SAM_DOMAIN_HANDLE *domain, NTTIME *reset_lockout_count) -NTSTATUS sam_{get,set}_domain_min_pwdlength(SAM_DOMAIN_HANDLE *domain, uint16 *min_passwordlength) -NTSTATUS sam_{get,set}_domain_pwd_history(SAM_DOMAIN_HANDLE *domain, uin16 *password_history) -NTSTATUS sam_{get,set}_domain_lockout_count(SAM_DOMAIN_HANDLE *domain, uint16 *lockout_count) -NTSTATUS sam_{get,set}_domain_force_logoff(SAM_DOMAIN_HANDLE *domain, BOOL *force_logoff) -NTSTATUS sam_{get,set}_domain_login_pwdchange(SAM_DOMAIN_HANDLE *domain, BOOL *login_pwdchange) - -NTSTATUS sam_get_user_sid(SAM_USER_HANDLE *user, DOM_SID **sid) -NTSTATUS sam_{get,set}_user_pgroup(SAM_USER_HANDLE *user, DOM_SID **pgroup) -NTSTATUS sam_{get,set}_user_name(SAM_USER_HANDLE *user, char **username) -NTSTATUS sam_{get,set}_user_fullname(SAM_USER_HANDLE *user, char** fullname) -NTSTATUS sam_{get,set}_user_description(SAM_USER_HANDLE *user, char **description) -NTSTATUS sam_{get,set}_user_home_dir(SAM_USER_HANDLE *user, char **home_dir) -NTSTATUS sam_{get,set}_user_dir_drive(SAM_USER_HANDLE *user, char **dir_drive) -NTSTATUS sam_{get,set}_user_logon_script(SAM_USER_HANDLE *user, char **logon_script) -NTSTATUS sam_{get,set}_user_profile_path(SAM_USER_HANDLE *user, char **profile_path) -NTSTATUS sam_{get,set}_user_workstations(SAM_USER_HANDLE *user, char **workstations) -NTSTATUS sam_{get,set}_user_munged_dial(SAM_USER_HANDLE *user, char **munged_dial) -NTSTATUS sam_{get,set}_user_lm_pwd(SAM_USER_HANDLE *user, DATA_BLOB *lm_pwd) -NTSTATUS sam_{get,set}_user_nt_pwd(SAM_USER_HANDLE *user, DATA_BLOB *nt_pwd) -NTSTATUS sam_{get,set}_user_plain_pwd(SAM_USER_HANDLE *user, DATA_BLOB *plaintext_pwd) -NTSTATUS sam_{get,set}_user_acct_ctrl(SAM_USER_HANDLE *user, uint16 *acct_ctrl) -NTSTATUS sam_{get,set}_user_logon_divs(SAM_USER_HANDLE *user, uint16 *logon_divs) -NTSTATUS sam_{get,set}_user_hours(SAM_USER_HANDLE *user, uint32 *hours_len, uint8 **hours) -NTSTATUS sam_{get,set}_user_logon_time(SAM_USER_HANDLE *user, NTTIME *logon_time) -NTSTATUS sam_{get,set}_user_logoff_time(SAM_USER_HANDLE *user, NTTIME *logoff_time) -NTSTATUS sam_{get,set}_user_kickoff_time(SAM_USER_HANDLE *user, NTTIME kickoff_time) -NTSTATUS sam_{get,set}_user_pwd_last_set(SAM_USER_HANDLE *user, NTTIME pwd_last_set) -NTSTATUS sam_{get,set}_user_pwd_can_change(SAM_USER_HANDLE *user, NTTIME pwd_can_change) -NTSTATUS sam_{get,set}_user_pwd_must_change(SAM_USER_HANDLE *user, NTTIME pwd_must_change) -NTSTATUS sam_{get,set}_user_unknown_1(SAM_USER_HANDLE *user, char **unknown_1) -NTSTATUS sam_{get,set}_user_unknown_2(SAM_USER_HANDLE *user, uint32 *unknown_2) -NTSTATUS sam_{get,set}_user_unknown_3(SAM_USER_HANDLE *user, uint32 *unknown_3) -NTSTATUS sam_{get,set}_user_unknown_4(SAM_USER_HANDLE *user, uint32 *unknown_4) - -NTSTATUS sam_get_group_sid(SAM_GROUP_HANDLE *group, DOM_SID **sid) -NTSTATUS sam_get_group_typ(SAM_GROUP_HANDLE *group, uint32 *typ) -NTSTATUS sam_{get,set}_group_name(SAM_GROUP_HANDLE *group, char **group_name) -NTSTATUS sam_{get,set}_group_comment(SAM_GROUP_HANDLE *group, char **comment) -NTSTATUS sam_{get,set}_group_priv_set(SAM_GROUP_HANDLE *group, PRIVILEGE_SET *priv_set) \ No newline at end of file diff --git a/source3/sam/get_set_account.c b/source3/sam/get_set_account.c deleted file mode 100644 index acac281d21..0000000000 --- a/source3/sam/get_set_account.c +++ /dev/null @@ -1,845 +0,0 @@ -/* - Unix SMB/CIFS implementation. - SAM_ACCOUNT_HANDLE access routines - Copyright (C) Andrew Bartlett 2002 - Copyright (C) Stefan (metze) Metzmacher 2002 - 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 Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_SAM - -NTSTATUS sam_get_account_domain_sid(const SAM_ACCOUNT_HANDLE *sampass, const DOM_SID **sid) -{ - NTSTATUS status; - SAM_DOMAIN_HANDLE *domain; - SAM_ASSERT(!sampass || !sid); - - if (!NT_STATUS_IS_OK(status = sam_get_account_domain(sampass, &domain))){ - DEBUG(0, ("sam_get_account_domain_sid: Can't get domain for account\n")); - return status; - } - - return sam_get_domain_sid(domain, sid); -} - -NTSTATUS sam_get_account_domain_name(const SAM_ACCOUNT_HANDLE *sampass, const char **domain_name) -{ - NTSTATUS status; - SAM_DOMAIN_HANDLE *domain; - SAM_ASSERT(sampass && domain_name); - - if (!NT_STATUS_IS_OK(status = sam_get_account_domain(sampass, &domain))){ - DEBUG(0, ("sam_get_account_domain_name: Can't get domain for account\n")); - return status; - } - - return sam_get_domain_name(domain, domain_name); -} - -NTSTATUS sam_get_account_acct_ctrl(const SAM_ACCOUNT_HANDLE *sampass, uint16 *acct_ctrl) -{ - SAM_ASSERT(sampass && acct_ctrl); - - *acct_ctrl = sampass->private.acct_ctrl; - - return NT_STATUS_OK; -} - -NTSTATUS sam_get_account_logon_time(const SAM_ACCOUNT_HANDLE *sampass, NTTIME *logon_time) -{ - SAM_ASSERT(sampass && logon_time) ; - - *logon_time = sampass->private.logon_time; - - return NT_STATUS_OK; -} - -NTSTATUS sam_get_account_logoff_time(const SAM_ACCOUNT_HANDLE *sampass, NTTIME *logoff_time) -{ - SAM_ASSERT(sampass && logoff_time) ; - - *logoff_time = sampass->private.logoff_time; - - return NT_STATUS_OK; -} - -NTSTATUS sam_get_account_kickoff_time(const SAM_ACCOUNT_HANDLE *sampass, NTTIME *kickoff_time) -{ - SAM_ASSERT(sampass && kickoff_time); - - *kickoff_time = sampass->private.kickoff_time; - - return NT_STATUS_OK; -} - -NTSTATUS sam_get_account_pass_last_set_time(const SAM_ACCOUNT_HANDLE *sampass, NTTIME *pass_last_set_time) -{ - SAM_ASSERT(sampass && pass_last_set_time); - - *pass_last_set_time = sampass->private.pass_last_set_time; - - return NT_STATUS_OK; -} - -NTSTATUS sam_get_account_pass_can_change_time(const SAM_ACCOUNT_HANDLE *sampass, NTTIME *pass_can_change_time) -{ - SAM_ASSERT(sampass && pass_can_change_time); - - *pass_can_change_time = sampass->private.pass_can_change_time; - - return NT_STATUS_OK; -} - -NTSTATUS sam_get_account_pass_must_change_time(const SAM_ACCOUNT_HANDLE *sampass, NTTIME *pass_must_change_time) -{ - SAM_ASSERT(sampass && pass_must_change_time); - - *pass_must_change_time = sampass->private.pass_must_change_time; - - return NT_STATUS_OK; -} - -NTSTATUS sam_get_account_logon_divs(const SAM_ACCOUNT_HANDLE *sampass, uint16 *logon_divs) -{ - SAM_ASSERT(sampass && logon_divs); - - *logon_divs = sampass->private.logon_divs; - - return NT_STATUS_OK; -} - -NTSTATUS sam_get_account_hours_len(const SAM_ACCOUNT_HANDLE *sampass, uint32 *hours_len) -{ - SAM_ASSERT(sampass && hours_len); - - *hours_len = sampass->private.hours_len; - - return NT_STATUS_OK; -} - -NTSTATUS sam_get_account_hours(const SAM_ACCOUNT_HANDLE *sampass, const uint8 **hours) -{ - SAM_ASSERT(sampass && hours); - - *hours = sampass->private.hours; - - return NT_STATUS_OK; -} - -NTSTATUS sam_get_account_nt_pwd(const SAM_ACCOUNT_HANDLE *sampass, DATA_BLOB *nt_pwd) -{ - SAM_ASSERT(sampass); - - SMB_ASSERT((!sampass->private.nt_pw.data) - || sampass->private.nt_pw.length == NT_HASH_LEN); - - *nt_pwd = sampass->private.nt_pw; - - return NT_STATUS_OK; -} - -NTSTATUS sam_get_account_lm_pwd(const SAM_ACCOUNT_HANDLE *sampass, DATA_BLOB *lm_pwd) -{ - SAM_ASSERT(sampass); - - SMB_ASSERT((!sampass->private.lm_pw.data) - || sampass->private.lm_pw.length == LM_HASH_LEN); - - *lm_pwd = sampass->private.lm_pw; - - return NT_STATUS_OK; -} - -/* Return the plaintext password if known. Most of the time - it isn't, so don't assume anything magic about this function. - - Used to pass the plaintext to sam backends that might - want to store more than just the NTLM hashes. -*/ - -NTSTATUS sam_get_account_plaintext_pwd(const SAM_ACCOUNT_HANDLE *sampass, char **plain_pwd) -{ - SAM_ASSERT(sampass && plain_pwd); - - *plain_pwd = sampass->private.plaintext_pw; - - return NT_STATUS_OK; -} - -NTSTATUS sam_get_account_sid(const SAM_ACCOUNT_HANDLE *sampass, const DOM_SID **sid) -{ - SAM_ASSERT(sampass); - - *sid = &(sampass->private.account_sid); - - return NT_STATUS_OK; -} - -NTSTATUS sam_get_account_pgroup(const SAM_ACCOUNT_HANDLE *sampass, const DOM_SID **sid) -{ - SAM_ASSERT(sampass); - - *sid = &(sampass->private.group_sid); - - return NT_STATUS_OK; -} - -/** - * Get flags showing what is initalised in the SAM_ACCOUNT_HANDLE - * @param sampass the SAM_ACCOUNT_HANDLE in question - * @return the flags indicating the members initialised in the struct. - **/ - -NTSTATUS sam_get_account_init_flag(const SAM_ACCOUNT_HANDLE *sampass, uint32 *initflag) -{ - SAM_ASSERT(sampass); - - *initflag = sampass->private.init_flag; - - return NT_STATUS_OK; -} - -NTSTATUS sam_get_account_name(const SAM_ACCOUNT_HANDLE *sampass, char **account_name) -{ - SAM_ASSERT(sampass); - - *account_name = sampass->private.account_name; - - return NT_STATUS_OK; -} - -NTSTATUS sam_get_account_domain(const SAM_ACCOUNT_HANDLE *sampass, SAM_DOMAIN_HANDLE **domain) -{ - SAM_ASSERT(sampass); - - *domain = sampass->private.domain; - - return NT_STATUS_OK; -} - -NTSTATUS sam_get_account_fullname(const SAM_ACCOUNT_HANDLE *sampass, char **fullname) -{ - SAM_ASSERT(sampass); - - *fullname = sampass->private.full_name; - - return NT_STATUS_OK; -} - -NTSTATUS sam_get_account_homedir(const SAM_ACCOUNT_HANDLE *sampass, char **homedir) -{ - SAM_ASSERT(sampass); - - *homedir = sampass->private.home_dir; - - return NT_STATUS_OK; -} - -NTSTATUS sam_get_account_unix_home_dir(const SAM_ACCOUNT_HANDLE *sampass, char **uhomedir) -{ - SAM_ASSERT(sampass); - - *uhomedir = sampass->private.unix_home_dir; - - return NT_STATUS_OK; -} - -NTSTATUS sam_get_account_dir_drive(const SAM_ACCOUNT_HANDLE *sampass, char **dirdrive) -{ - SAM_ASSERT(sampass); - - *dirdrive = sampass->private.dir_drive; - - return NT_STATUS_OK; -} - -NTSTATUS sam_get_account_logon_script(const SAM_ACCOUNT_HANDLE *sampass, char **logon_script) -{ - SAM_ASSERT(sampass); - - *logon_script = sampass->private.logon_script; - - return NT_STATUS_OK; -} - -NTSTATUS sam_get_account_profile_path(const SAM_ACCOUNT_HANDLE *sampass, char **profile_path) -{ - SAM_ASSERT(sampass); - - *profile_path = sampass->private.profile_path; - - return NT_STATUS_OK; -} - -NTSTATUS sam_get_account_description(const SAM_ACCOUNT_HANDLE *sampass, char **description) -{ - SAM_ASSERT(sampass); - - *description = sampass->private.acct_desc; - - return NT_STATUS_OK; -} - -NTSTATUS sam_get_account_workstations(const SAM_ACCOUNT_HANDLE *sampass, char **workstations) -{ - SAM_ASSERT(sampass); - - *workstations = sampass->private.workstations; - - return NT_STATUS_OK; -} - -NTSTATUS sam_get_account_unknown_str(const SAM_ACCOUNT_HANDLE *sampass, char **unknown_str) -{ - SAM_ASSERT(sampass); - - *unknown_str = sampass->private.unknown_str; - - return NT_STATUS_OK; -} - -NTSTATUS sam_get_account_munged_dial(const SAM_ACCOUNT_HANDLE *sampass, char **munged_dial) -{ - SAM_ASSERT(sampass); - - *munged_dial = sampass->private.munged_dial; - - return NT_STATUS_OK; -} - -NTSTATUS sam_get_account_unknown_1(const SAM_ACCOUNT_HANDLE *sampass, uint32 *unknown1) -{ - SAM_ASSERT(sampass && unknown1); - - *unknown1 = sampass->private.unknown_1; - - return NT_STATUS_OK; -} - -NTSTATUS sam_get_account_unknown_2(const SAM_ACCOUNT_HANDLE *sampass, uint32 *unknown2) -{ - SAM_ASSERT(sampass && unknown2); - - *unknown2 = sampass->private.unknown_2; - - return NT_STATUS_OK; -} - -NTSTATUS sam_get_account_unknown_3(const SAM_ACCOUNT_HANDLE *sampass, uint32 *unknown3) -{ - SAM_ASSERT(sampass && unknown3); - - *unknown3 = sampass->private.unknown_3; - - return NT_STATUS_OK; -} - -/********************************************************************* - Collection of set...() functions for SAM_ACCOUNT_HANDLE_INFO. - ********************************************************************/ - -NTSTATUS sam_set_account_acct_ctrl(SAM_ACCOUNT_HANDLE *sampass, uint16 acct_ctrl) -{ - SAM_ASSERT(sampass); - - sampass->private.acct_ctrl = acct_ctrl; - - return NT_STATUS_OK; -} - -NTSTATUS sam_set_account_logon_time(SAM_ACCOUNT_HANDLE *sampass, NTTIME mytime, BOOL store) -{ - SAM_ASSERT(sampass); - - sampass->private.logon_time = mytime; - - - return NT_STATUS_UNSUCCESSFUL; -} - -NTSTATUS sam_set_account_logoff_time(SAM_ACCOUNT_HANDLE *sampass, NTTIME mytime, BOOL store) -{ - SAM_ASSERT(sampass); - - sampass->private.logoff_time = mytime; - - return NT_STATUS_OK; -} - -NTSTATUS sam_set_account_kickoff_time(SAM_ACCOUNT_HANDLE *sampass, NTTIME mytime, BOOL store) -{ - SAM_ASSERT(sampass); - - sampass->private.kickoff_time = mytime; - - - return NT_STATUS_OK; -} - -NTSTATUS sam_set_account_pass_can_change_time(SAM_ACCOUNT_HANDLE *sampass, NTTIME mytime, BOOL store) -{ - SAM_ASSERT(sampass); - - sampass->private.pass_can_change_time = mytime; - - - return NT_STATUS_OK; -} - -NTSTATUS sam_set_account_pass_must_change_time(SAM_ACCOUNT_HANDLE *sampass, NTTIME mytime, BOOL store) -{ - SAM_ASSERT(sampass); - - sampass->private.pass_must_change_time = mytime; - - return NT_STATUS_OK; -} - -NTSTATUS sam_set_account_pass_last_set_time(SAM_ACCOUNT_HANDLE *sampass, NTTIME mytime) -{ - SAM_ASSERT(sampass); - - sampass->private.pass_last_set_time = mytime; - - return NT_STATUS_OK; -} - -NTSTATUS sam_set_account_hours_len(SAM_ACCOUNT_HANDLE *sampass, uint32 len) -{ - SAM_ASSERT(sampass); - - sampass->private.hours_len = len; - return NT_STATUS_OK; -} - -NTSTATUS sam_set_account_logon_divs(SAM_ACCOUNT_HANDLE *sampass, uint16 hours) -{ - SAM_ASSERT(sampass); - - sampass->private.logon_divs = hours; - return NT_STATUS_OK; -} - -/** - * Set flags showing what is initalised in the SAM_ACCOUNT_HANDLE - * @param sampass the SAM_ACCOUNT_HANDLE in question - * @param flag The *new* flag to be set. Old flags preserved - * this flag is only added. - **/ - -NTSTATUS sam_set_account_init_flag(SAM_ACCOUNT_HANDLE *sampass, uint32 flag) -{ - SAM_ASSERT(sampass); - - sampass->private.init_flag |= flag; - - return NT_STATUS_OK; -} - -NTSTATUS sam_set_account_sid(SAM_ACCOUNT_HANDLE *sampass, const DOM_SID *u_sid) -{ - SAM_ASSERT(sampass && u_sid); - - sid_copy(&sampass->private.account_sid, u_sid); - - DEBUG(10, ("sam_set_account_sid: setting account sid %s\n", - sid_string_static(&sampass->private.account_sid))); - - return NT_STATUS_OK; -} - -NTSTATUS sam_set_account_sid_from_string(SAM_ACCOUNT_HANDLE *sampass, const char *u_sid) -{ - DOM_SID new_sid; - SAM_ASSERT(sampass && u_sid); - - DEBUG(10, ("sam_set_account_sid_from_string: setting account sid %s\n", - u_sid)); - - if (!string_to_sid(&new_sid, u_sid)) { - DEBUG(1, ("sam_set_account_sid_from_string: %s isn't a valid SID!\n", u_sid)); - return NT_STATUS_UNSUCCESSFUL; - } - - if (!NT_STATUS_IS_OK(sam_set_account_sid(sampass, &new_sid))) { - DEBUG(1, ("sam_set_account_sid_from_string: could not set sid %s on SAM_ACCOUNT_HANDLE!\n", u_sid)); - return NT_STATUS_UNSUCCESSFUL; - } - - return NT_STATUS_OK; -} - -NTSTATUS sam_set_account_pgroup_sid(SAM_ACCOUNT_HANDLE *sampass, const DOM_SID *g_sid) -{ - SAM_ASSERT(sampass && g_sid); - - sid_copy(&sampass->private.group_sid, g_sid); - - DEBUG(10, ("sam_set_group_sid: setting group sid %s\n", - sid_string_static(&sampass->private.group_sid))); - - return NT_STATUS_OK; -} - -NTSTATUS sam_set_account_pgroup_string(SAM_ACCOUNT_HANDLE *sampass, const char *g_sid) -{ - DOM_SID new_sid; - SAM_ASSERT(sampass && g_sid); - - DEBUG(10, ("sam_set_group_sid_from_string: setting group sid %s\n", - g_sid)); - - if (!string_to_sid(&new_sid, g_sid)) { - DEBUG(1, ("sam_set_group_sid_from_string: %s isn't a valid SID!\n", g_sid)); - return NT_STATUS_UNSUCCESSFUL; - } - - if (!NT_STATUS_IS_OK(sam_set_account_pgroup_sid(sampass, &new_sid))) { - DEBUG(1, ("sam_set_group_sid_from_string: could not set sid %s on SAM_ACCOUNT_HANDLE!\n", g_sid)); - return NT_STATUS_UNSUCCESSFUL; - } - return NT_STATUS_OK; -} - -/********************************************************************* - Set the domain name. - ********************************************************************/ - -NTSTATUS sam_set_account_domain(SAM_ACCOUNT_HANDLE *sampass, SAM_DOMAIN_HANDLE *domain) -{ - SAM_ASSERT(sampass); - - sampass->private.domain = domain; - - return NT_STATUS_OK; -} - -/********************************************************************* - Set the account's NT name. - ********************************************************************/ - -NTSTATUS sam_set_account_name(SAM_ACCOUNT_HANDLE *sampass, const char *account_name) -{ - SAM_ASSERT(sampass); - - DEBUG(10, ("sam_set_account_name: setting nt account_name %s, was %s\n", account_name, sampass->private.account_name)); - - sampass->private.account_name = talloc_strdup(sampass->mem_ctx, account_name); - - return NT_STATUS_OK; -} - -/********************************************************************* - Set the account's full name. - ********************************************************************/ - -NTSTATUS sam_set_account_fullname(SAM_ACCOUNT_HANDLE *sampass, const char *full_name) -{ - SAM_ASSERT(sampass); - - DEBUG(10, ("sam_set_account_fullname: setting full name %s, was %s\n", full_name, sampass->private.full_name)); - - sampass->private.full_name = talloc_strdup(sampass->mem_ctx, full_name); - - return NT_STATUS_OK; -} - -/********************************************************************* - Set the account's logon script. - ********************************************************************/ - -NTSTATUS sam_set_account_logon_script(SAM_ACCOUNT_HANDLE *sampass, const char *logon_script, BOOL store) -{ - SAM_ASSERT(sampass); - - DEBUG(10, ("sam_set_logon_script: from %s to %s\n", logon_script, sampass->private.logon_script)); - - sampass->private.logon_script = talloc_strdup(sampass->mem_ctx, logon_script); - - - return NT_STATUS_OK; -} - -/********************************************************************* - Set the account's profile path. - ********************************************************************/ - -NTSTATUS sam_set_account_profile_path(SAM_ACCOUNT_HANDLE *sampass, const char *profile_path, BOOL store) -{ - SAM_ASSERT(sampass); - - DEBUG(10, ("sam_set_profile_path: setting profile path %s, was %s\n", profile_path, sampass->private.profile_path)); - - sampass->private.profile_path = talloc_strdup(sampass->mem_ctx, profile_path); - - return NT_STATUS_OK; -} - -/********************************************************************* - Set the account's directory drive. - ********************************************************************/ - -NTSTATUS sam_set_account_dir_drive(SAM_ACCOUNT_HANDLE *sampass, const char *dir_drive, BOOL store) -{ - SAM_ASSERT(sampass); - - DEBUG(10, ("sam_set_dir_drive: setting dir drive %s, was %s\n", dir_drive, - sampass->private.dir_drive)); - - sampass->private.dir_drive = talloc_strdup(sampass->mem_ctx, dir_drive); - - return NT_STATUS_OK; -} - -/********************************************************************* - Set the account's home directory. - ********************************************************************/ - -NTSTATUS sam_set_account_homedir(SAM_ACCOUNT_HANDLE *sampass, const char *home_dir, BOOL store) -{ - SAM_ASSERT(sampass); - - DEBUG(10, ("sam_set_homedir: setting home dir %s, was %s\n", home_dir, - sampass->private.home_dir)); - - sampass->private.home_dir = talloc_strdup(sampass->mem_ctx, home_dir); - - return NT_STATUS_OK; -} - -/********************************************************************* - Set the account's unix home directory. - ********************************************************************/ - -NTSTATUS sam_set_account_unix_homedir(SAM_ACCOUNT_HANDLE *sampass, const char *unix_home_dir) -{ - SAM_ASSERT(sampass); - - DEBUG(10, ("sam_set_unix_homedir: setting home dir %s, was %s\n", unix_home_dir, - sampass->private.unix_home_dir)); - - sampass->private.unix_home_dir = talloc_strdup(sampass->mem_ctx, unix_home_dir); - - return NT_STATUS_OK; -} - -/********************************************************************* - Set the account's account description. - ********************************************************************/ - -NTSTATUS sam_set_account_acct_desc(SAM_ACCOUNT_HANDLE *sampass, const char *acct_desc) -{ - SAM_ASSERT(sampass); - - sampass->private.acct_desc = talloc_strdup(sampass->mem_ctx, acct_desc); - - return NT_STATUS_OK; -} - -/********************************************************************* - Set the account's workstation allowed list. - ********************************************************************/ - -NTSTATUS sam_set_account_workstations(SAM_ACCOUNT_HANDLE *sampass, const char *workstations) -{ - SAM_ASSERT(sampass); - - DEBUG(10, ("sam_set_workstations: setting workstations %s, was %s\n", workstations, - sampass->private.workstations)); - - sampass->private.workstations = talloc_strdup(sampass->mem_ctx, workstations); - - return NT_STATUS_OK; -} - -/********************************************************************* - Set the account's 'unknown_str', whatever the heck this actually is... - ********************************************************************/ - -NTSTATUS sam_set_account_unknown_str(SAM_ACCOUNT_HANDLE *sampass, const char *unknown_str) -{ - SAM_ASSERT(sampass); - - sampass->private.unknown_str = talloc_strdup(sampass->mem_ctx, unknown_str); - - return NT_STATUS_OK; -} - -/********************************************************************* - Set the account's dial string. - ********************************************************************/ - -NTSTATUS sam_set_account_munged_dial(SAM_ACCOUNT_HANDLE *sampass, const char *munged_dial) -{ - SAM_ASSERT(sampass); - - sampass->private.munged_dial = talloc_strdup(sampass->mem_ctx, munged_dial); - - return NT_STATUS_OK; -} - -/********************************************************************* - Set the account's NT hash. - ********************************************************************/ - -NTSTATUS sam_set_account_nt_pwd(SAM_ACCOUNT_HANDLE *sampass, const DATA_BLOB data) -{ - SAM_ASSERT(sampass); - - sampass->private.nt_pw = data; - - return NT_STATUS_OK; -} - -/********************************************************************* - Set the account's LM hash. - ********************************************************************/ - -NTSTATUS sam_set_account_lm_pwd(SAM_ACCOUNT_HANDLE *sampass, const DATA_BLOB data) -{ - SAM_ASSERT(sampass); - - sampass->private.lm_pw = data; - - return NT_STATUS_OK; -} - -/********************************************************************* - Set the account's plaintext password only (base procedure, see helper - below) - ********************************************************************/ - -NTSTATUS sam_set_account_plaintext_pwd(SAM_ACCOUNT_HANDLE *sampass, const char *plain_pwd) -{ - SAM_ASSERT(sampass); - - sampass->private.plaintext_pw = talloc_strdup(sampass->mem_ctx, plain_pwd); - - return NT_STATUS_OK; -} - -NTSTATUS sam_set_account_unknown_1(SAM_ACCOUNT_HANDLE *sampass, uint32 unkn) -{ - SAM_ASSERT(sampass); - - sampass->private.unknown_1 = unkn; - - return NT_STATUS_OK; -} - -NTSTATUS sam_set_account_unknown_2(SAM_ACCOUNT_HANDLE *sampass, uint32 unkn) -{ - SAM_ASSERT(sampass); - - sampass->private.unknown_2 = unkn; - - return NT_STATUS_OK; -} - -NTSTATUS sam_set_account_unknown_3(SAM_ACCOUNT_HANDLE *sampass, uint32 unkn) -{ - SAM_ASSERT(sampass); - - sampass->private.unknown_3 = unkn; - return NT_STATUS_OK; -} - -NTSTATUS sam_set_account_hours(SAM_ACCOUNT_HANDLE *sampass, const uint8 *hours) -{ - SAM_ASSERT(sampass); - - if (!hours) { - memset ((char *)sampass->private.hours, 0, MAX_HOURS_LEN); - return NT_STATUS_OK; - } - - memcpy(sampass->private.hours, hours, MAX_HOURS_LEN); - - return NT_STATUS_OK; -} - -/* Helpful interfaces to the above */ - -/********************************************************************* - Sets the last changed times and must change times for a normal - password change. - ********************************************************************/ - -NTSTATUS sam_set_account_pass_changed_now(SAM_ACCOUNT_HANDLE *sampass) -{ - uint32 expire; - NTTIME temptime; - - SAM_ASSERT(sampass); - - unix_to_nt_time(&temptime, time(NULL)); - if (!NT_STATUS_IS_OK(sam_set_account_pass_last_set_time(sampass, temptime))) - return NT_STATUS_UNSUCCESSFUL; - - if (!account_policy_get(AP_MAX_PASSWORD_AGE, &expire) - || (expire==(uint32)-1)) { - - get_nttime_max(&temptime); - if (!NT_STATUS_IS_OK(sam_set_account_pass_must_change_time(sampass, temptime, False))) - return NT_STATUS_UNSUCCESSFUL; - - } else { - /* FIXME: Add expire to temptime */ - - if (!NT_STATUS_IS_OK(sam_get_account_pass_last_set_time(sampass,&temptime)) || !NT_STATUS_IS_OK(sam_set_account_pass_must_change_time(sampass, temptime,True))) - return NT_STATUS_UNSUCCESSFUL; - } - - return NT_STATUS_OK; -} - -/********************************************************************* - Set the account's PLAINTEXT password. Used as an interface to the above. - Also sets the last change time to NOW. - ********************************************************************/ - -NTSTATUS sam_set_account_passwd(SAM_ACCOUNT_HANDLE *sampass, const char *plaintext) -{ - DATA_BLOB data; - uchar new_lanman_p16[16]; - uchar new_nt_p16[16]; - - SAM_ASSERT(sampass && plaintext); - - nt_lm_owf_gen(plaintext, new_nt_p16, new_lanman_p16); - - data = data_blob(new_nt_p16, 16); - if (!NT_STATUS_IS_OK(sam_set_account_nt_pwd(sampass, data))) - return NT_STATUS_UNSUCCESSFUL; - - data = data_blob(new_lanman_p16, 16); - - if (!NT_STATUS_IS_OK(sam_set_account_lm_pwd(sampass, data))) - return NT_STATUS_UNSUCCESSFUL; - - if (!NT_STATUS_IS_OK(sam_set_account_plaintext_pwd(sampass, plaintext))) - return NT_STATUS_UNSUCCESSFUL; - - if (!NT_STATUS_IS_OK(sam_set_account_pass_changed_now(sampass))) - return NT_STATUS_UNSUCCESSFUL; - - return NT_STATUS_OK; -} - diff --git a/source3/sam/get_set_domain.c b/source3/sam/get_set_domain.c deleted file mode 100644 index c70a4a3f09..0000000000 --- a/source3/sam/get_set_domain.c +++ /dev/null @@ -1,263 +0,0 @@ -/* - Unix SMB/CIFS implementation. - SAM_DOMAIN access routines - Copyright (C) Andrew Bartlett 2002 - Copyright (C) Stefan (metze) Metzmacher 2002 - 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 Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_SAM - -NTSTATUS sam_get_domain_sid(SAM_DOMAIN_HANDLE *domain, const DOM_SID **sid) -{ - SAM_ASSERT(domain &&sid); - - *sid = &(domain->private.sid); - - return NT_STATUS_OK; -} - -NTSTATUS sam_get_domain_num_accounts(SAM_DOMAIN_HANDLE *domain, uint32 *num_accounts) -{ - SAM_ASSERT(domain &&num_accounts); - - *num_accounts = domain->private.num_accounts; - - return NT_STATUS_OK; -} - -NTSTATUS sam_get_domain_num_groups(SAM_DOMAIN_HANDLE *domain, uint32 *num_groups) -{ - SAM_ASSERT(domain &&num_groups); - - *num_groups = domain->private.num_groups; - - return NT_STATUS_OK; -} - -NTSTATUS sam_get_domain_num_aliases(SAM_DOMAIN_HANDLE *domain, uint32 *num_aliases) -{ - SAM_ASSERT(domain &&num_aliases); - - *num_aliases = domain->private.num_aliases; - - return NT_STATUS_OK; -} - -NTSTATUS sam_get_domain_name(SAM_DOMAIN_HANDLE *domain, const char **domain_name) -{ - SAM_ASSERT(domain &&domain_name); - - *domain_name = domain->private.name; - - return NT_STATUS_OK; -} - -NTSTATUS sam_get_domain_server(SAM_DOMAIN_HANDLE *domain, const char **server_name) -{ - SAM_ASSERT(domain &&server_name); - - *server_name = domain->private.servername; - - return NT_STATUS_OK; -} - -NTSTATUS sam_get_domain_max_pwdage(SAM_DOMAIN_HANDLE *domain, NTTIME *max_passwordage) -{ - SAM_ASSERT(domain &&max_passwordage); - - *max_passwordage = domain->private.max_passwordage; - - return NT_STATUS_OK; -} - -NTSTATUS sam_get_domain_min_pwdage(SAM_DOMAIN_HANDLE *domain, NTTIME *min_passwordage) -{ - SAM_ASSERT(domain &&min_passwordage); - - *min_passwordage = domain->private.min_passwordage; - - return NT_STATUS_OK; -} - -NTSTATUS sam_get_domain_lockout_duration(SAM_DOMAIN_HANDLE *domain, NTTIME *lockout_duration) -{ - SAM_ASSERT(domain &&lockout_duration); - - *lockout_duration = domain->private.lockout_duration; - - return NT_STATUS_OK; -} - -NTSTATUS sam_get_domain_reset_count(SAM_DOMAIN_HANDLE *domain, NTTIME *reset_lockout_count) -{ - SAM_ASSERT(domain &&reset_lockout_count); - - *reset_lockout_count = domain->private.reset_count; - - return NT_STATUS_OK; -} - -NTSTATUS sam_get_domain_min_pwdlength(SAM_DOMAIN_HANDLE *domain, uint16 *min_passwordlength) -{ - SAM_ASSERT(domain &&min_passwordlength); - - *min_passwordlength = domain->private.min_passwordlength; - - return NT_STATUS_OK; -} - -NTSTATUS sam_get_domain_pwd_history(SAM_DOMAIN_HANDLE *domain, uint16 *password_history) -{ - SAM_ASSERT(domain &&password_history); - - *password_history = domain->private.password_history; - - return NT_STATUS_OK; -} - -NTSTATUS sam_get_domain_lockout_count(SAM_DOMAIN_HANDLE *domain, uint16 *lockout_count) -{ - SAM_ASSERT(domain &&lockout_count); - - *lockout_count = domain->private.lockout_count; - - return NT_STATUS_OK; -} - -NTSTATUS sam_get_domain_force_logoff(SAM_DOMAIN_HANDLE *domain, BOOL *force_logoff) -{ - SAM_ASSERT(domain &&force_logoff); - - *force_logoff = domain->private.force_logoff; - - return NT_STATUS_OK; -} - - -NTSTATUS sam_get_domain_login_pwdchange(SAM_DOMAIN_HANDLE *domain, BOOL *login_pwdchange) -{ - SAM_ASSERT(domain && login_pwdchange); - - *login_pwdchange = domain->private.login_pwdchange; - - return NT_STATUS_OK; -} - -/* Set */ - -NTSTATUS sam_set_domain_name(SAM_DOMAIN_HANDLE *domain, const char *domain_name) -{ - SAM_ASSERT(domain); - - domain->private.name = talloc_strdup(domain->mem_ctx, domain_name); - - return NT_STATUS_OK; -} - - -NTSTATUS sam_set_domain_max_pwdage(SAM_DOMAIN_HANDLE *domain, NTTIME max_passwordage) -{ - SAM_ASSERT(domain); - - domain->private.max_passwordage = max_passwordage; - - return NT_STATUS_OK; -} - -NTSTATUS sam_set_domain_min_pwdage(SAM_DOMAIN_HANDLE *domain, NTTIME min_passwordage) -{ - SAM_ASSERT(domain); - - domain->private.min_passwordage = min_passwordage; - - return NT_STATUS_OK; -} - -NTSTATUS sam_set_domain_lockout_duration(SAM_DOMAIN_HANDLE *domain, NTTIME lockout_duration) -{ - SAM_ASSERT(domain); - - domain->private.lockout_duration = lockout_duration; - - return NT_STATUS_OK; -} -NTSTATUS sam_set_domain_reset_count(SAM_DOMAIN_HANDLE *domain, NTTIME reset_lockout_count) -{ - SAM_ASSERT(domain); - - domain->private.reset_count = reset_lockout_count; - - return NT_STATUS_OK; -} - -NTSTATUS sam_set_domain_min_pwdlength(SAM_DOMAIN_HANDLE *domain, uint16 min_passwordlength) -{ - SAM_ASSERT(domain); - - domain->private.min_passwordlength = min_passwordlength; - - return NT_STATUS_OK; -} - -NTSTATUS sam_set_domain_pwd_history(SAM_DOMAIN_HANDLE *domain, uint16 password_history) -{ - SAM_ASSERT(domain); - - domain->private.password_history = password_history; - - return NT_STATUS_OK; -} - -NTSTATUS sam_set_domain_lockout_count(SAM_DOMAIN_HANDLE *domain, uint16 lockout_count) -{ - SAM_ASSERT(domain); - - domain->private.lockout_count = lockout_count; - - return NT_STATUS_OK; -} - -NTSTATUS sam_set_domain_force_logoff(SAM_DOMAIN_HANDLE *domain, BOOL force_logoff) -{ - SAM_ASSERT(domain); - - domain->private.force_logoff = force_logoff; - - return NT_STATUS_OK; -} - -NTSTATUS sam_set_domain_login_pwdchange(SAM_DOMAIN_HANDLE *domain, BOOL login_pwdchange) -{ - SAM_ASSERT(domain); - - domain->private.login_pwdchange = login_pwdchange; - - return NT_STATUS_OK; -} - -NTSTATUS sam_set_domain_server(SAM_DOMAIN_HANDLE *domain, const char *server_name) -{ - SAM_ASSERT(domain); - - domain->private.servername = talloc_strdup(domain->mem_ctx, server_name); - - return NT_STATUS_OK; -} diff --git a/source3/sam/get_set_group.c b/source3/sam/get_set_group.c deleted file mode 100644 index 11ea9258a7..0000000000 --- a/source3/sam/get_set_group.c +++ /dev/null @@ -1,106 +0,0 @@ -/* - Unix SMB/CIFS implementation. - SAM_USER_HANDLE access routines - Copyright (C) Andrew Bartlett 2002 - Copyright (C) Stefan (metze) Metzmacher 2002 - 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 Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_SAM - -/* sam group get functions */ - -NTSTATUS sam_get_group_sid(const SAM_GROUP_HANDLE *group, const DOM_SID **sid) -{ - SAM_ASSERT(group && sid); - - *sid = &(group->private.sid); - - return NT_STATUS_OK; -} - -NTSTATUS sam_get_group_ctrl(const SAM_GROUP_HANDLE *group, uint32 *group_ctrl) -{ - SAM_ASSERT(group && group_ctrl); - - *group_ctrl = group->private.group_ctrl; - - return NT_STATUS_OK; -} - -NTSTATUS sam_get_group_name(const SAM_GROUP_HANDLE *group, const char **group_name) -{ - SAM_ASSERT(group); - - *group_name = group->private.group_name; - - return NT_STATUS_OK; - -} -NTSTATUS sam_get_group_comment(const SAM_GROUP_HANDLE *group, const char **group_desc) -{ - SAM_ASSERT(group); - - *group_desc = group->private.group_desc; - - return NT_STATUS_OK; -} - -/* sam group set functions */ - -NTSTATUS sam_set_group_sid(SAM_GROUP_HANDLE *group, const DOM_SID *sid) -{ - SAM_ASSERT(group); - - if (!sid) - ZERO_STRUCT(group->private.sid); - else - sid_copy(&(group->private.sid), sid); - - return NT_STATUS_OK; -} - -NTSTATUS sam_set_group_group_ctrl(SAM_GROUP_HANDLE *group, uint32 group_ctrl) -{ - SAM_ASSERT(group); - - group->private.group_ctrl = group_ctrl; - - return NT_STATUS_OK; -} - -NTSTATUS sam_set_group_name(SAM_GROUP_HANDLE *group, const char *group_name) -{ - SAM_ASSERT(group); - - group->private.group_name = talloc_strdup(group->mem_ctx, group_name); - - return NT_STATUS_OK; -} - -NTSTATUS sam_set_group_description(SAM_GROUP_HANDLE *group, const char *group_desc) -{ - SAM_ASSERT(group); - - group->private.group_desc = talloc_strdup(group->mem_ctx, group_desc); - - return NT_STATUS_OK; - -} diff --git a/source3/sam/sam_ads.c b/source3/sam/sam_ads.c deleted file mode 100755 index 79b107e417..0000000000 --- a/source3/sam/sam_ads.c +++ /dev/null @@ -1,1378 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Active Directory SAM backend, for simulate a W2K DC in mixed mode. - - Copyright (C) Stefan (metze) Metzmacher 2002 - Copyright (C) Andrew Bartlett 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 - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" - - -#ifdef HAVE_LDAP - -static int sam_ads_debug_level = DBGC_SAM; - -#undef DBGC_CLASS -#define DBGC_CLASS sam_ads_debug_level - -#ifndef FIXME -#define FIXME( body ) { DEBUG(0,("FIXME: "));\ - DEBUGADD(0,(body));} -#endif - -#define ADS_STATUS_OK ADS_ERROR(0) -#define ADS_STATUS_UNSUCCESSFUL ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL) -#define ADS_STATUS_NOT_IMPLEMENTED ADS_ERROR_NT(NT_STATUS_NOT_IMPLEMENTED) - - -#define ADS_SUBTREE_BUILTIN "CN=Builtin," -#define ADS_SUBTREE_COMPUTERS "CN=Computers," -#define ADS_SUBTREE_DC "CN=Domain Controllers," -#define ADS_SUBTREE_USERS "CN=Users," -#define ADS_ROOT_TREE "" -/* Here are private module structs and functions */ - -typedef struct sam_ads_privates { - ADS_STRUCT *ads_struct; - TALLOC_CTX *mem_ctx; - BOOL bind_plaintext; - char *ads_bind_dn; - char *ads_bind_pw; - char *ldap_uri; - /* did we need something more? */ -}SAM_ADS_PRIVATES; - - -/* get only these LDAP attributes, witch we really need for an account */ -const char *account_attrs[] = { "objectSid", - "objectGUID", - "sAMAccountType", - "sAMAcountName", - "userPrincipalName", - "accountExpires", - "badPasswordTime", - "badPwdCount", - "lastLogoff", - "lastLogon", - "userWorkstations", - "dBCSPwd", - "unicodePwd", - "pwdLastSet", - "userAccountControl", - "profilePath", - "homeDrive", - "scriptPath", - "homeDirectory", - "cn", - "primaryGroupID",/* 513 */ - "nsNPAllowDialIn",/* TRUE */ - "userParameters",/* Dial Back number ...*/ - "codePage",/* 0 */ - "countryCode",/* 0 */ - "adminCount",/* 1 or 0 */ - "logonCount",/* 0 */ - "managedObjects", - "memberOf",/* dn */ - "instanceType",/* 4 */ - "name", /* sync with cn */ - "description", - /* "nTSecurityDescriptor", */ - NULL}; - -/* get only these LDAP attributes, witch we really need for a group */ -const char *group_attrs[] = {"objectSid", - /* "objectGUID", */ - "sAMAccountType", - "sAMAcountName", - "groupType", - /* "member", */ - "description", - "name", /* sync with cn */ - /* "nTSecurityDescriptor", */ - NULL}; - - -/*************************************************** - return our ads connection. We keep the connection - open to make things faster -****************************************************/ -static ADS_STATUS sam_ads_cached_connection(SAM_ADS_PRIVATES *privates) -{ - ADS_STRUCT *ads_struct; - ADS_STATUS ads_status; - - if (!privates->ads_struct) { - privates->ads_struct = ads_init_simple(); - ads_struct = privates->ads_struct; - ads_struct->server.ldap_uri = smb_xstrdup(privates->ldap_uri); - if ((!privates->ads_bind_dn) || (!*privates->ads_bind_dn)) { - ads_struct->auth.flags |= ADS_AUTH_ANON_BIND; - } else { - ads_struct->auth.user_name - = smb_xstrdup(privates->ads_bind_dn); - if (privates->ads_bind_pw) { - ads_struct->auth.password - = smb_xstrdup(privates->ads_bind_pw); - } - } - if (privates->bind_plaintext) { - ads_struct->auth.flags |= ADS_AUTH_SIMPLE_BIND; - } - } else { - ads_struct = privates->ads_struct; - } - - if (ads_struct->ld != NULL) { - /* connection has been opened. ping server. */ - struct sockaddr_un addr; - socklen_t len; - int sd; - if (ldap_get_option(ads_struct->ld, LDAP_OPT_DESC, &sd) == 0 && - getpeername(sd, (struct sockaddr *) &addr, &len) < 0) { - /* the other end has died. reopen. */ - ldap_unbind_ext(ads_struct->ld, NULL, NULL); - ads_struct->ld = NULL; - } - } - - if (ads_struct->ld != NULL) { - DEBUG(5,("sam_ads_cached_connection: allready connected to the LDAP server\n")); - return ADS_SUCCESS; - } - - ads_status = ads_connect(ads_struct); - - ads_status = ads_server_info(ads_struct); - if (!ADS_ERR_OK(ads_status)) { - DEBUG(0,("Can't set server info: %s\n",ads_errstr(ads_status))); - /* return ads_status; */ FIXME("for now we only warn!\n"); - } - - DEBUG(2, ("sam_ads_cached_connection: succesful connection to the LDAP server\n")); - return ADS_SUCCESS; -} - -static ADS_STATUS sam_ads_do_search(SAM_ADS_PRIVATES *privates, const char *bind_path, int scope, const char *exp, const char **attrs, void **res) -{ - ADS_STATUS ads_status = ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL); - - ads_status = sam_ads_cached_connection(privates); - if (!ADS_ERR_OK(ads_status)) - return ads_status; - - return ads_do_search_retry(privates->ads_struct, bind_path, scope, exp, attrs, res); -} - - -/********************************************* -here we have to check the update serial number - - this is the core of the ldap cache -*********************************************/ -static ADS_STATUS sam_ads_usn_is_valid(SAM_ADS_PRIVATES *privates, uint32 usn_in, uint32 *usn_out) -{ - ADS_STATUS ads_status = ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL); - - SAM_ASSERT(privates && privates->ads_struct && usn_out); - - ads_status = ads_USN(privates->ads_struct, usn_out); - if (!ADS_ERR_OK(ads_status)) - return ads_status; - - if (*usn_out == usn_in) - return ADS_SUCCESS; - - return ads_status; -} - -/*********************************************** -Initialize SAM_ACCOUNT_HANDLE from an ADS query -************************************************/ -/* not ready :-( */ -static ADS_STATUS ads_entry2sam_account_handle(SAM_ADS_PRIVATES *privates, SAM_ACCOUNT_HANDLE *account ,void *msg) -{ - ADS_STATUS ads_status = ADS_ERROR_NT(NT_STATUS_NO_SUCH_USER); - NTSTATUS nt_status = NT_STATUS_NO_SUCH_USER; - ADS_STRUCT *ads_struct = privates->ads_struct; - TALLOC_CTX *mem_ctx = account->mem_ctx; - char *tmp_str = NULL; - - SAM_ASSERT(privates && ads_struct && account && mem_ctx && msg); - - FIXME("should we really use ads_pull_username()(or ads_pull_string())?\n"); - if ((account->private.account_name = ads_pull_username(ads_struct, mem_ctx, msg))==NULL) { - DEBUG(0,("ads_pull_username failed\n")); - return ADS_ERROR_NT(NT_STATUS_NO_SUCH_USER); - } - - if ((account->private.full_name = ads_pull_string(ads_struct, mem_ctx, msg,"name"))==NULL) { - DEBUG(3,("ads_pull_string for 'name' failed - skip\n")); - } - - if ((account->private.acct_desc = ads_pull_string(ads_struct, mem_ctx, msg,"description"))!=NULL) { - DEBUG(3,("ads_pull_string for 'acct_desc' failed - skip\n")); - } - - if ((account->private.home_dir = ads_pull_string(ads_struct, mem_ctx, msg,"homeDirectory"))!=NULL) { - DEBUG(3,("ads_pull_string for 'homeDirectory' failed - skip\n")); - } - - if ((account->private.dir_drive = ads_pull_string(ads_struct, mem_ctx, msg,"homeDrive"))!=NULL) { - DEBUG(3,("ads_pull_string for 'homeDrive' failed - skip\n")); - } - - if ((account->private.profile_path = ads_pull_string(ads_struct, mem_ctx, msg,"profilePath"))!=NULL) { - DEBUG(3,("ads_pull_string for 'profilePath' failed - skip\n")); - } - - if ((account->private.logon_script = ads_pull_string(ads_struct, mem_ctx, msg,"scriptPath"))!=NULL) { - DEBUG(3,("ads_pull_string for 'scriptPath' failed - skip\n")); - } - - FIXME("check 'nsNPAllowDialIn' for munged_dial!\n"); - if ((account->private.munged_dial = ads_pull_string(ads_struct, mem_ctx, msg,"userParameters"))!=NULL) { - DEBUG(3,("ads_pull_string for 'userParameters' failed - skip\n")); - } - - if ((account->private.unix_home_dir = ads_pull_string(ads_struct, mem_ctx, msg,"msSFUHomeDrirectory"))!=NULL) { - DEBUG(3,("ads_pull_string for 'msSFUHomeDrirectory' failed - skip\n")); - } - -#if 0 - FIXME("use function intern mem_ctx for pwdLastSet\n"); - if ((tmp_str = ads_pull_string(ads_struct, mem_ctx, msg,"pwdLastSet"))!=NULL) { - DEBUG(3,("ads_pull_string for 'pwdLastSet' failed - skip\n")); - } else { - account->private.pass_last_set_time = ads_parse_nttime(tmp_str); - tmp_str = NULL; - - } -#endif - -#if 0 -typedef struct sam_account_handle { - TALLOC_CTX *mem_ctx; - uint32 access_granted; - const struct sam_methods *current_sam_methods; /* sam_methods creating this handle */ - void (*free_fn)(struct sam_account_handle **); - struct sam_account_data { - uint32 init_flag; - NTTIME logon_time; /* logon time */ - NTTIME logoff_time; /* logoff time */ - NTTIME kickoff_time; /* kickoff time */ - NTTIME pass_last_set_time; /* password last set time */ - NTTIME pass_can_change_time; /* password can change time */ - NTTIME pass_must_change_time; /* password must change time */ - char * account_name; /* account_name string */ - SAM_DOMAIN_HANDLE * domain; /* domain of account */ - char *full_name; /* account's full name string */ - char *unix_home_dir; /* UNIX home directory string */ - char *home_dir; /* home directory string */ - char *dir_drive; /* home directory drive string */ - char *logon_script; /* logon script string */ - char *profile_path; /* profile path string */ - char *acct_desc; /* account description string */ - char *workstations; /* login from workstations string */ - char *unknown_str; /* don't know what this is, yet. */ - char *munged_dial; /* munged path name and dial-back tel number */ - DOM_SID account_sid; /* Primary Account SID */ - DOM_SID group_sid; /* Primary Group SID */ - DATA_BLOB lm_pw; /* .data is Null if no password */ - DATA_BLOB nt_pw; /* .data is Null if no password */ - char *plaintext_pw; /* if Null not available */ - uint16 acct_ctrl; /* account info (ACB_xxxx bit-mask) */ - uint32 unknown_1; /* 0x00ff ffff */ - uint16 logon_divs; /* 168 - number of hours in a week */ - uint32 hours_len; /* normally 21 bytes */ - uint8 hours[MAX_HOURS_LEN]; - uint32 unknown_2; /* 0x0002 0000 */ - uint32 unknown_3; /* 0x0000 04ec */ - } private; -} SAM_ACCOUNT_HANDLE; -#endif - - return ads_status; -} - - -/*********************************************** -Initialize SAM_GROUP_ENUM from an ads entry -************************************************/ -/* not ready :-( */ -static ADS_STATUS ads_entry2sam_group_enum(SAM_ADS_PRIVATES *privates, TALLOC_CTX *mem_ctx, SAM_GROUP_ENUM **group_enum,const void *entry) -{ - ADS_STATUS ads_status = ADS_STATUS_UNSUCCESSFUL; - ADS_STRUCT *ads_struct = privates->ads_struct; - SAM_GROUP_ENUM __group_enum; - SAM_GROUP_ENUM *_group_enum = &__group_enum; - - SAM_ASSERT(privates && ads_struct && mem_ctx && group_enum && entry); - - *group_enum = _group_enum; - - DEBUG(3,("sam_ads: ads_entry2sam_account_handle\n")); - - if (!ads_pull_sid(ads_struct, &entry, "objectSid", &(_group_enum->sid))) { - DEBUG(0,("No sid for!?\n")); - return ADS_STATUS_UNSUCCESSFUL; - } - - if (!(_group_enum->group_name = ads_pull_string(ads_struct, mem_ctx, &entry, "sAMAccountName"))) { - DEBUG(0,("No groupname found")); - return ADS_STATUS_UNSUCCESSFUL; - } - - if (!(_group_enum->group_desc = ads_pull_string(ads_struct, mem_ctx, &entry, "desciption"))) { - DEBUG(0,("No description found")); - return ADS_STATUS_UNSUCCESSFUL; - } - - DEBUG(0,("sAMAccountName: %s\ndescription: %s\nobjectSid: %s\n", - _group_enum->group_name, - _group_enum->group_desc, - sid_string_static(&(_group_enum->sid)) - )); - - return ads_status; -} - -static ADS_STATUS sam_ads_access_check(SAM_ADS_PRIVATES *privates, const SEC_DESC *sd, const NT_USER_TOKEN *access_token, uint32 access_desired, uint32 *acc_granted) -{ - ADS_STATUS ads_status = ADS_ERROR_NT(NT_STATUS_ACCESS_DENIED); - NTSTATUS nt_status; - uint32 my_acc_granted; - - SAM_ASSERT(privates && sd && access_token); - /* acc_granted can be set to NULL */ - - /* the steps you need are: - 1. get_sec_desc for sid - 2. se_map_generic(accessdesired, generic_mapping) - 3. se_access_check() */ - - if (!se_access_check(sd, access_token, access_desired, (acc_granted)?acc_granted:&my_acc_granted, &nt_status)) { - DEBUG(3,("sam_ads_access_check: ACCESS DENIED\n")); - ads_status = ADS_ERROR_NT(nt_status); - return ads_status; - } - ads_status = ADS_ERROR_NT(nt_status); - return ads_status; -} - -static ADS_STATUS sam_ads_get_tree_sec_desc(SAM_ADS_PRIVATES *privates, const char *subtree, SEC_DESC **sd) -{ - ADS_STATUS ads_status = ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER); - ADS_STRUCT *ads_struct = privates->ads_struct; - TALLOC_CTX *mem_ctx = privates->mem_ctx; - char *search_path; - void *sec_desc_res; - void *sec_desc_msg; - const char *sec_desc_attrs[] = {"nTSecurityDescriptor",NULL}; - - SAM_ASSERT(privates && ads_struct && mem_ctx && sd); - *sd = NULL; - - if (subtree) { - asprintf(&search_path, "%s%s",subtree,ads_struct->config.bind_path); - } else { - asprintf(&search_path, "%s",""); - } - ads_status = sam_ads_do_search(privates, search_path, LDAP_SCOPE_BASE, "(objectClass=*)", sec_desc_attrs, &sec_desc_res); - SAFE_FREE(search_path); - if (!ADS_ERR_OK(ads_status)) - return ads_status; - - if ((sec_desc_msg = ads_first_entry(ads_struct, sec_desc_res))==NULL) { - ads_status = ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER); - return ads_status; - } - - if (!ads_pull_sd(ads_struct, mem_ctx, sec_desc_msg, sec_desc_attrs[0], sd)) { - *sd = NULL; - ads_status = ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER); - return ads_status; - } - - return ads_status; -} - -static ADS_STATUS sam_ads_account_policy_get(SAM_ADS_PRIVATES *privates, int field, uint32 *value) -{ - ADS_STATUS ads_status = ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER); - ADS_STRUCT *ads_struct = privates->ads_struct; - void *ap_res; - void *ap_msg; - const char *ap_attrs[] = {"minPwdLength",/* AP_MIN_PASSWORD_LEN */ - "pwdHistoryLength",/* AP_PASSWORD_HISTORY */ - "AP_USER_MUST_LOGON_TO_CHG_PASS",/* AP_USER_MUST_LOGON_TO_CHG_PASS */ - "maxPwdAge",/* AP_MAX_PASSWORD_AGE */ - "minPwdAge",/* AP_MIN_PASSWORD_AGE */ - "lockoutDuration",/* AP_LOCK_ACCOUNT_DURATION */ - "AP_RESET_COUNT_TIME",/* AP_RESET_COUNT_TIME */ - "AP_BAD_ATTEMPT_LOCKOUT",/* AP_BAD_ATTEMPT_LOCKOUT */ - "AP_TIME_TO_LOGOUT",/* AP_TIME_TO_LOGOUT */ - NULL}; - /*lockOutObservationWindow - lockoutThreshold $ pwdProperties*/ - static uint32 ap[9]; - static uint32 ap_usn = 0; - uint32 tmp_usn = 0; - - SAM_ASSERT(privates && ads_struct && value); - - FIXME("We need to decode all account_policy attributes!\n"); - - ads_status = sam_ads_usn_is_valid(privates,ap_usn,&tmp_usn); - if (!ADS_ERR_OK(ads_status)) { - ads_status = sam_ads_do_search(privates, ads_struct->config.bind_path, LDAP_SCOPE_BASE, "(objectClass=*)", ap_attrs, &ap_res); - if (!ADS_ERR_OK(ads_status)) - return ads_status; - - if (ads_count_replies(ads_struct, ap_res) != 1) { - ads_msgfree(ads_struct, ap_res); - return ADS_ERROR(LDAP_NO_RESULTS_RETURNED); - } - - if (!(ap_msg = ads_first_entry(ads_struct, ap_res))) { - ads_msgfree(ads_struct, ap_res); - return ADS_ERROR(LDAP_NO_RESULTS_RETURNED); - } - - if (!ads_pull_uint32(ads_struct, ap_msg, ap_attrs[0], &ap[0])) { - /* AP_MIN_PASSWORD_LEN */ - ap[0] = MINPASSWDLENGTH;/* 5 chars minimum */ - } - if (!ads_pull_uint32(ads_struct, ap_msg, ap_attrs[1], &ap[1])) { - /* AP_PASSWORD_HISTORY */ - ap[1] = 0;/* don't keep any old password */ - } - if (!ads_pull_uint32(ads_struct, ap_msg, ap_attrs[2], &ap[2])) { - /* AP_USER_MUST_LOGON_TO_CHG_PASS */ - ap[2] = 0;/* don't force user to logon */ - } - if (!ads_pull_uint32(ads_struct, ap_msg, ap_attrs[3], &ap[3])) { - /* AP_MAX_PASSWORD_AGE */ - ap[3] = MAX_PASSWORD_AGE;/* 21 days */ - } - if (!ads_pull_uint32(ads_struct, ap_msg, ap_attrs[4], &ap[4])) { - /* AP_MIN_PASSWORD_AGE */ - ap[4] = 0;/* 0 days */ - } - if (!ads_pull_uint32(ads_struct, ap_msg, ap_attrs[5], &ap[5])) { - /* AP_LOCK_ACCOUNT_DURATION */ - ap[5] = 0;/* lockout for 0 minutes */ - } - if (!ads_pull_uint32(ads_struct, ap_msg, ap_attrs[6], &ap[6])) { - /* AP_RESET_COUNT_TIME */ - ap[6] = 0;/* reset immediatly */ - } - if (!ads_pull_uint32(ads_struct, ap_msg, ap_attrs[7], &ap[7])) { - /* AP_BAD_ATTEMPT_LOCKOUT */ - ap[7] = 0;/* don't lockout */ - } - if (!ads_pull_uint32(ads_struct, ap_msg, ap_attrs[8], &ap[8])) { - /* AP_TIME_TO_LOGOUT */ - ap[8] = -1;/* don't force logout */ - } - - ads_msgfree(ads_struct, ap_res); - ap_usn = tmp_usn; - } - - switch(field) { - case AP_MIN_PASSWORD_LEN: - *value = ap[0]; - ads_status = ADS_ERROR_NT(NT_STATUS_OK); - break; - case AP_PASSWORD_HISTORY: - *value = ap[1]; - ads_status = ADS_ERROR_NT(NT_STATUS_OK); - break; - case AP_USER_MUST_LOGON_TO_CHG_PASS: - *value = ap[2]; - ads_status = ADS_ERROR_NT(NT_STATUS_OK); - break; - case AP_MAX_PASSWORD_AGE: - *value = ap[3]; - ads_status = ADS_ERROR_NT(NT_STATUS_OK); - break; - case AP_MIN_PASSWORD_AGE: - *value = ap[4]; - ads_status = ADS_ERROR_NT(NT_STATUS_OK); - break; - case AP_LOCK_ACCOUNT_DURATION: - *value = ap[5]; - ads_status = ADS_ERROR_NT(NT_STATUS_OK); - break; - case AP_RESET_COUNT_TIME: - *value = ap[6]; - ads_status = ADS_ERROR_NT(NT_STATUS_OK); - break; - case AP_BAD_ATTEMPT_LOCKOUT: - *value = ap[7]; - ads_status = ADS_ERROR_NT(NT_STATUS_OK); - break; - case AP_TIME_TO_LOGOUT: - *value = ap[8]; - ads_status = ADS_ERROR_NT(NT_STATUS_OK); - break; - default: *value = 0; break; - } - - return ads_status; -} - - -/********************************** -Now the functions off the SAM API -***********************************/ - -/* General API */ -static NTSTATUS sam_ads_get_sec_desc(const SAM_METHODS *sam_method, const NT_USER_TOKEN *access_token, - const DOM_SID *sid, SEC_DESC **sd) -{ - ADS_STATUS ads_status = ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL); - SAM_ADS_PRIVATES *privates = (struct sam_ads_privates *)sam_method->private_data; - ADS_STRUCT *ads_struct = privates->ads_struct; - TALLOC_CTX *mem_ctx; - char *sidstr,*filter; - void *sec_desc_res; - void *sec_desc_msg; - const char *sec_desc_attrs[] = {"nTSecurityDescriptor",NULL}; - fstring sid_str; - SEC_DESC *my_sd; - - SAM_ASSERT(sam_method && access_token && sid && sd); - - ads_status = sam_ads_get_tree_sec_desc(privates, ADS_ROOT_TREE, &my_sd); - if (!ADS_ERR_OK(ads_status)) - return ads_ntstatus(ads_status); - - ads_status = sam_ads_access_check(privates, my_sd, access_token, GENERIC_RIGHTS_DOMAIN_READ, NULL); - - if (!ADS_ERR_OK(ads_status)) - return ads_ntstatus(ads_status); - - sidstr = sid_binstring(sid); - if (asprintf(&filter, "(objectSid=%s)", sidstr) == -1) { - SAFE_FREE(sidstr); - return NT_STATUS_NO_MEMORY; - } - - SAFE_FREE(sidstr); - - ads_status = sam_ads_do_search(privates,ads_struct->config.bind_path, - LDAP_SCOPE_SUBTREE, filter, sec_desc_attrs, - &sec_desc_res); - SAFE_FREE(filter); - - if (!ADS_ERR_OK(ads_status)) { - return ads_ntstatus(ads_status); - } - - if (!(mem_ctx = talloc_init("sec_desc parse in sam_ads"))) { - DEBUG(1, ("talloc_init() failed for sec_desc parse context in sam_ads")); - ads_msgfree(ads_struct, sec_desc_res); - return NT_STATUS_NO_MEMORY; - } - - if (ads_count_replies(ads_struct, sec_desc_res) != 1) { - DEBUG(1,("sam_ads_get_sec_desc: duplicate or 0 results for sid %s\n", - sid_to_string(sid_str, sid))); - talloc_destroy(mem_ctx); - ads_msgfree(ads_struct, sec_desc_res); - return NT_STATUS_UNSUCCESSFUL; - } - - if (!(sec_desc_msg = ads_first_entry(ads_struct, sec_desc_res))) { - talloc_destroy(mem_ctx); - ads_msgfree(ads_struct, sec_desc_res); - return NT_STATUS_INVALID_PARAMETER; - } - - if (!ads_pull_sd(ads_struct, mem_ctx, sec_desc_msg, sec_desc_attrs[0], sd)) { - ads_status = ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER); - talloc_destroy(mem_ctx); - ads_msgfree(ads_struct, sec_desc_res); - return ads_ntstatus(ads_status); - } - - /* now, were we allowed to see the SD we just got? */ - - ads_msgfree(ads_struct, sec_desc_res); - talloc_destroy(mem_ctx); - return ads_ntstatus(ads_status); -} - -static NTSTATUS sam_ads_set_sec_desc(const SAM_METHODS *sam_method, const NT_USER_TOKEN *access_token, - const DOM_SID *sid, const SEC_DESC *sd) -{ - ADS_STATUS ads_status = ADS_STATUS_NOT_IMPLEMENTED; - DEBUG(0,("sam_ads: %s was called!\n",FUNCTION_MACRO)); - SAM_ASSERT(sam_method); - return ads_ntstatus(ads_status); -} - - -static NTSTATUS sam_ads_lookup_sid(const SAM_METHODS *sam_method, const NT_USER_TOKEN *access_token, - TALLOC_CTX *mem_ctx, const DOM_SID *sid, char **name, - enum SID_NAME_USE *type) -{ - ADS_STATUS ads_status = ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL); - SAM_ADS_PRIVATES *privates = (struct sam_ads_privates *)sam_method->private_data; - ADS_STRUCT *ads_struct = privates->ads_struct; - SEC_DESC *my_sd; - - SAM_ASSERT(sam_method && access_token && mem_ctx && sid && name && type); - - ads_status = sam_ads_get_tree_sec_desc(privates, ADS_ROOT_TREE, &my_sd); - if (!ADS_ERR_OK(ads_status)) - return ads_ntstatus(ads_status); - - ads_status = sam_ads_access_check(privates, my_sd, access_token, GENERIC_RIGHTS_DOMAIN_READ, NULL); - if (!ADS_ERR_OK(ads_status)) - return ads_ntstatus(ads_status); - - return ads_sid_to_name(ads_struct, mem_ctx, sid, name, type); -} - -static NTSTATUS sam_ads_lookup_name(const SAM_METHODS *sam_method, const NT_USER_TOKEN *access_token, - const char *name, DOM_SID *sid, enum SID_NAME_USE *type) -{ - ADS_STATUS ads_status = ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL); - SAM_ADS_PRIVATES *privates = (struct sam_ads_privates *)sam_method->private_data; - ADS_STRUCT *ads_struct = privates->ads_struct; - SEC_DESC *my_sd; - - SAM_ASSERT(sam_method && access_token && name && sid && type); - - ads_status = sam_ads_get_tree_sec_desc(privates, ADS_ROOT_TREE, &my_sd); - if (!ADS_ERR_OK(ads_status)) - return ads_ntstatus(ads_status); - - ads_status = sam_ads_access_check(privates, my_sd, access_token, GENERIC_RIGHTS_DOMAIN_READ, NULL); - if (!ADS_ERR_OK(ads_status)) - return ads_ntstatus(ads_status); - - return ads_name_to_sid(ads_struct, name, sid, type); -} - - -/* Domain API */ - -static NTSTATUS sam_ads_update_domain(const SAM_METHODS *sam_method, const SAM_DOMAIN_HANDLE *domain) -{ - ADS_STATUS ads_status = ADS_STATUS_NOT_IMPLEMENTED; - DEBUG(0,("sam_ads: %s was called!\n",FUNCTION_MACRO)); - SAM_ASSERT(sam_method); - return ads_ntstatus(ads_status); -} - -static NTSTATUS sam_ads_get_domain_handle(const SAM_METHODS *sam_method, const NT_USER_TOKEN *access_token, - const uint32 access_desired, SAM_DOMAIN_HANDLE **domain) -{ - ADS_STATUS ads_status = ADS_STATUS_NOT_IMPLEMENTED; - SAM_ADS_PRIVATES *privates = (struct sam_ads_privates *)sam_method->private_data; - TALLOC_CTX *mem_ctx = privates->mem_ctx; /*Fix me is this right??? */ - SAM_DOMAIN_HANDLE *dom_handle = NULL; - SEC_DESC *sd; - uint32 acc_granted; - uint32 tmp_value; - - DEBUG(5,("sam_ads_get_domain_handle: %d\n",__LINE__)); - - SAM_ASSERT(sam_method && access_token && domain); - - (*domain) = NULL; - - if ((dom_handle = talloc(mem_ctx, sizeof(SAM_DOMAIN_HANDLE))) == NULL) { - DEBUG(0,("failed to talloc dom_handle\n")); - ads_status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY); - return ads_ntstatus(ads_status); - } - - ZERO_STRUCTP(dom_handle); - - dom_handle->mem_ctx = mem_ctx; /*Fix me is this right??? */ - dom_handle->free_fn = NULL; - dom_handle->current_sam_methods = sam_method; - - /* check if access can be granted as requested */ - - ads_status = sam_ads_get_tree_sec_desc(privates, ADS_ROOT_TREE, &sd); - if (!ADS_ERR_OK(ads_status)) - return ads_ntstatus(ads_status); - - ads_status = sam_ads_access_check(privates, sd, access_token, access_desired, &acc_granted); - if (!ADS_ERR_OK(ads_status)) - return ads_ntstatus(ads_status); - - dom_handle->access_granted = acc_granted; - - /* fill all the values of dom_handle */ - sid_copy(&dom_handle->private.sid, &sam_method->domain_sid); - dom_handle->private.name = smb_xstrdup(sam_method->domain_name); - dom_handle->private.servername = "WHOKNOWS"; /* what is the servername */ - - /*Fix me: sam_ads_account_policy_get() return ADS_STATUS! */ - ads_status = sam_ads_account_policy_get(privates, AP_MAX_PASSWORD_AGE, &tmp_value); - if (!ADS_ERR_OK(ads_status)) { - DEBUG(4,("sam_ads_account_policy_get failed for max password age. Useing default\n")); - tmp_value = MAX_PASSWORD_AGE; - } - unix_to_nt_time_abs(&dom_handle->private.max_passwordage,tmp_value); - - ads_status = sam_ads_account_policy_get(privates, AP_MIN_PASSWORD_AGE, &tmp_value); - if (!ADS_ERR_OK(ads_status)) { - DEBUG(4,("sam_ads_account_policy_get failed for min password age. Useing default\n")); - tmp_value = 0; - } - unix_to_nt_time_abs(&dom_handle->private.min_passwordage, tmp_value); - - ads_status = sam_ads_account_policy_get(privates, AP_LOCK_ACCOUNT_DURATION, &tmp_value); - if (!ADS_ERR_OK(ads_status)) { - DEBUG(4,("sam_ads_account_policy_get failed for lockout duration. Useing default\n")); - tmp_value = 0; - } - unix_to_nt_time_abs(&dom_handle->private.lockout_duration, tmp_value); - - ads_status = sam_ads_account_policy_get(privates, AP_RESET_COUNT_TIME, &tmp_value); - if (!ADS_ERR_OK(ads_status)) { - DEBUG(4,("sam_ads_account_policy_get failed for time till locout count is reset. Useing default\n")); - tmp_value = 0; - } - unix_to_nt_time_abs(&dom_handle->private.reset_count, tmp_value); - - ads_status = sam_ads_account_policy_get(privates, AP_MIN_PASSWORD_LEN, &tmp_value); - if (!ADS_ERR_OK(ads_status)) { - DEBUG(4,("sam_ads_account_policy_get failed for min password length. Useing default\n")); - tmp_value = 0; - } - dom_handle->private.min_passwordlength = (uint16)tmp_value; - - ads_status = sam_ads_account_policy_get(privates, AP_PASSWORD_HISTORY, &tmp_value); - if (!ADS_ERR_OK(ads_status)) { - DEBUG(4,("sam_ads_account_policy_get failed password history. Useing default\n")); - tmp_value = 0; - } - dom_handle->private.password_history = (uint16)tmp_value; - - ads_status = sam_ads_account_policy_get(privates, AP_BAD_ATTEMPT_LOCKOUT, &tmp_value); - if (!ADS_ERR_OK(ads_status)) { - DEBUG(4,("sam_ads_account_policy_get failed for bad attempts till lockout. Useing default\n")); - tmp_value = 0; - } - dom_handle->private.lockout_count = (uint16)tmp_value; - - ads_status = sam_ads_account_policy_get(privates, AP_TIME_TO_LOGOUT, &tmp_value); - if (!ADS_ERR_OK(ads_status)) { - DEBUG(4,("sam_ads_account_policy_get failed for force logout. Useing default\n")); - tmp_value = -1; - } - - ads_status = sam_ads_account_policy_get(privates, AP_USER_MUST_LOGON_TO_CHG_PASS, &tmp_value); - if (!ADS_ERR_OK(ads_status)) { - DEBUG(4,("sam_ads_account_policy_get failed for user must login to change password. Useing default\n")); - tmp_value = 0; - } - - /* should the real values of num_accounts, num_groups and num_aliases be retreved? - * I think it is to expensive to bother - */ - dom_handle->private.num_accounts = 3; - dom_handle->private.num_groups = 4; - dom_handle->private.num_aliases = 5; - - *domain = dom_handle; - - ads_status = ADS_ERROR_NT(NT_STATUS_OK); - return ads_ntstatus(ads_status); -} - -/* Account API */ -static NTSTATUS sam_ads_create_account(const SAM_METHODS *sam_method, - const NT_USER_TOKEN *access_token, uint32 access_desired, - const char *account_name, uint16 acct_ctrl, SAM_ACCOUNT_HANDLE **account) -{ - ADS_STATUS ads_status = ADS_STATUS_NOT_IMPLEMENTED; - SAM_ADS_PRIVATES *privates = (struct sam_ads_privates *)sam_method->private_data; - SEC_DESC *sd = NULL; - uint32 acc_granted; - - SAM_ASSERT(sam_method && privates && access_token && account_name && account); - - ads_status = sam_ads_get_tree_sec_desc(privates, ADS_SUBTREE_USERS, &sd); - if (!ADS_ERR_OK(ads_status)) - return ads_ntstatus(ads_status); - - ads_status = sam_ads_access_check(privates, sd, access_token, access_desired, &acc_granted); - if (!ADS_ERR_OK(ads_status)) - return ads_ntstatus(ads_status); - - ads_status = ADS_ERROR_NT(sam_init_account(account)); - if (!ADS_ERR_OK(ads_status)) - return ads_ntstatus(ads_status); - - (*account)->access_granted = acc_granted; - - return ads_ntstatus(ads_status); -} - -static NTSTATUS sam_ads_add_account(const SAM_METHODS *sam_method, const SAM_ACCOUNT_HANDLE *account) -{ - ADS_STATUS ads_status = ADS_ERROR(LDAP_NO_MEMORY); - SAM_ADS_PRIVATES *privates = (struct sam_ads_privates *)sam_method->private_data; - ADS_STRUCT *ads_struct = privates->ads_struct; - TALLOC_CTX *mem_ctx = privates->mem_ctx; - ADS_MODLIST mods; - uint16 acct_ctrl; - char *new_dn; - SEC_DESC *sd; - uint32 acc_granted; - - SAM_ASSERT(sam_method && account); - - ads_status = ADS_ERROR_NT(sam_get_account_acct_ctrl(account,&acct_ctrl)); - if (!ADS_ERR_OK(ads_status)) - goto done; - - if ((acct_ctrl & ACB_WSTRUST)||(acct_ctrl & ACB_SVRTRUST)) { - /* Computer account */ - char *name,*controlstr; - char *hostname,*host_upn,*host_spn; - const char *objectClass[] = {"top", "person", "organizationalPerson", - "user", "computer", NULL}; - - ads_status = ADS_ERROR_NT(sam_get_account_name(account,&name)); - if (!ADS_ERR_OK(ads_status)) - goto done; - - if (!(host_upn = talloc_asprintf(mem_ctx, "%s@%s", name, ads_struct->config.realm))) { - ads_status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY); - goto done; - } - - if (!(new_dn = talloc_asprintf(mem_ctx, "CN=%s,CN=Computers,%s", hostname, - ads_struct->config.bind_path))) { - ads_status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY); - goto done; - } - - if (!(controlstr = talloc_asprintf(mem_ctx, "%u", ads_acb2uf(acct_ctrl)))) { - ads_status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY); - goto done; - } - - if (!(mods = ads_init_mods(mem_ctx))) { - ads_status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY); - goto done; - } - - ads_status = ads_mod_str(mem_ctx, &mods, "cn", hostname); - if (!ADS_ERR_OK(ads_status)) - goto done; - ads_status = ads_mod_strlist(mem_ctx, &mods, "objectClass", objectClass); - if (!ADS_ERR_OK(ads_status)) - goto done; - ads_status = ads_mod_str(mem_ctx, &mods, "userPrincipalName", host_upn); - if (!ADS_ERR_OK(ads_status)) - goto done; - ads_status = ads_mod_str(mem_ctx, &mods, "displayName", hostname); - if (!ADS_ERR_OK(ads_status)) - goto done; - ads_status = ads_mod_str(mem_ctx, &mods, "sAMAccountName", name); - if (!ADS_ERR_OK(ads_status)) - goto done; - ads_status = ads_mod_str(mem_ctx, &mods, "userAccountControl", controlstr); - if (!ADS_ERR_OK(ads_status)) - goto done; - - ads_status = ads_mod_str(mem_ctx, &mods, "servicePrincipalName", host_spn); - if (!ADS_ERR_OK(ads_status)) - goto done; - ads_status = ads_mod_str(mem_ctx, &mods, "dNSHostName", hostname); - if (!ADS_ERR_OK(ads_status)) - goto done; - ads_status = ads_mod_str(mem_ctx, &mods, "userAccountControl", controlstr); - if (!ADS_ERR_OK(ads_status)) - goto done; - /* ads_status = ads_mod_str(mem_ctx, &mods, "operatingSystem", "Samba"); - if (!ADS_ERR_OK(ads_status)) - goto done; - *//* ads_status = ads_mod_str(mem_ctx, &mods, "operatingSystemVersion", VERSION); - if (!ADS_ERR_OK(ads_status)) - goto done; - */ - /* End Computer account */ - } else { - /* User account*/ - char *upn, *controlstr; - char *name, *fullname; - const char *objectClass[] = {"top", "person", "organizationalPerson", - "user", NULL}; - - ads_status = ADS_ERROR_NT(sam_get_account_name(account,&name)); - if (!ADS_ERR_OK(ads_status)) - goto done; - - ads_status = ADS_ERROR_NT(sam_get_account_fullname(account,&fullname)); - if (!ADS_ERR_OK(ads_status)) - goto done; - - if (!(upn = talloc_asprintf(mem_ctx, "%s@%s", name, ads_struct->config.realm))) { - ads_status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY); - goto done; - } - - if (!(new_dn = talloc_asprintf(mem_ctx, "CN=%s,CN=Users,%s", fullname, - ads_struct->config.bind_path))) { - ads_status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY); - goto done; - } - - if (!(controlstr = talloc_asprintf(mem_ctx, "%u", ads_acb2uf(acct_ctrl)))) { - ads_status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY); - goto done; - } - - if (!(mods = ads_init_mods(mem_ctx))) { - ads_status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY); - goto done; - } - - ads_status = ads_mod_str(mem_ctx, &mods, "cn", fullname); - if (!ADS_ERR_OK(ads_status)) - goto done; - ads_status = ads_mod_strlist(mem_ctx, &mods, "objectClass", objectClass); - if (!ADS_ERR_OK(ads_status)) - goto done; - ads_status = ads_mod_str(mem_ctx, &mods, "userPrincipalName", upn); - if (!ADS_ERR_OK(ads_status)) - goto done; - ads_status = ads_mod_str(mem_ctx, &mods, "displayName", fullname); - if (!ADS_ERR_OK(ads_status)) - goto done; - ads_status = ads_mod_str(mem_ctx, &mods, "sAMAccountName", name); - if (!ADS_ERR_OK(ads_status)) - goto done; - ads_status = ads_mod_str(mem_ctx, &mods, "userAccountControl", controlstr); - if (!ADS_ERR_OK(ads_status)) - goto done; - }/* End User account */ - - /* Finally at the account */ - ads_status = ads_gen_add(ads_struct, new_dn, mods); - -done: - return ads_ntstatus(ads_status); -} - -static NTSTATUS sam_ads_update_account(const SAM_METHODS *sam_method, const SAM_ACCOUNT_HANDLE *account) -{ - ADS_STATUS ads_status = ADS_STATUS_NOT_IMPLEMENTED; - DEBUG(0,("sam_ads: %s was called!\n",FUNCTION_MACRO)); - SAM_ASSERT(sam_method); - return ads_ntstatus(ads_status); -} - -static NTSTATUS sam_ads_delete_account(const SAM_METHODS *sam_method, const SAM_ACCOUNT_HANDLE *account) -{ - ADS_STATUS ads_status = ADS_STATUS_NOT_IMPLEMENTED; - DEBUG(0,("sam_ads: %s was called!\n",FUNCTION_MACRO)); - SAM_ASSERT(sam_method); - - - - return ads_ntstatus(ads_status); -} - -static NTSTATUS sam_ads_enum_accounts(const SAM_METHODS *sam_method, const NT_USER_TOKEN *access_token, uint16 acct_ctrl, uint32 *account_count, SAM_ACCOUNT_ENUM **accounts) -{ - ADS_STATUS ads_status = ADS_STATUS_NOT_IMPLEMENTED; - DEBUG(0,("sam_ads: %s was called!\n",FUNCTION_MACRO)); - SAM_ASSERT(sam_method); - return ads_ntstatus(ads_status); -} - -#if 0 -static NTSTATUS sam_ads_get_account_by_sid(const SAM_METHODS *sam_method, const NT_USER_TOKEN *access_token, const uint32 access_desired, const DOM_SID *account_sid, SAM_ACCOUNT_HANDLE **account) -{ - ADS_STATUS ads_status = ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL); - SAM_ADS_PRIVATES *privates = (struct sam_ads_privates *)sam_method->private_data; - ADS_STRUCT *ads_struct = privates->ads_struct; - TALLOC_CTX *mem_ctx = privates->mem_ctx; - SEC_DESC *sd = NULL; - uint32 acc_granted; - - SAM_ASSERT(sam_method && privates && ads_struct && access_token && account_sid && account); - - ads_status = ADS_ERROR_NT(sam_ads_get_sec_desc(sam_method, access_token, account_sid, &my_sd)); - if (!ADS_ERR_OK(ads_status)) - return ads_ntstatus(ads_status); - - ads_status = sam_ads_access_check(privates, sd, access_token, access_desired, &acc_granted); - if (!ADS_ERR_OK(ads_status)) - return ads_ntstatus(ads_status); - - ads_status = ADS_ERROR_NT(sam_init_account(account)); - if (!ADS_ERR_OK(ads_status)) - return ads_ntstatus(ads_status); - - (*account)->access_granted = acc_granted; - - return ads_ntstatus(ads_status); -} -#else -static NTSTATUS sam_ads_get_account_by_sid(const SAM_METHODS *sam_method, const NT_USER_TOKEN *access_token, const uint32 access_desired, const DOM_SID *account_sid, SAM_ACCOUNT_HANDLE **account) -{ - ADS_STATUS ads_status = ADS_STATUS_NOT_IMPLEMENTED; - DEBUG(0,("sam_ads: %s was called!\n",FUNCTION_MACRO)); - SAM_ASSERT(sam_method); - return ads_ntstatus(ads_status); -} -#endif - -#if 0 -static NTSTATUS sam_ads_get_account_by_name(const SAM_METHODS *sam_method, const NT_USER_TOKEN *access_token, const uint32 access_desired, const char *account_name, SAM_ACCOUNT_HANDLE **account) -{ - ADS_STATUS ads_status = ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL); - SAM_ADS_PRIVATES *privates = (struct sam_ads_privates *)sam_method->private_data; - ADS_STRUCT *ads_struct = privates->ads_struct; - TALLOC_CTX *mem_ctx = privates->mem_ctx; - SEC_DESC *sd = NULL; - uint32 acc_granted; - - SAM_ASSERT(sam_method && privates && ads_struct && access_token && account_name && account); - - ads_status = sam_ads_get_tree_sec_desc(privates, ADS_ROOT_TREE, &sd); - if (!ADS_ERR_OK(ads_status)) - return ads_ntstatus(ads_status); - - ads_status = sam_ads_access_check(privates, sd, access_token, access_desired, &acc_granted); - if (!ADS_ERR_OK(ads_status)) - return ads_ntstatus(ads_status); - - ads_status = ADS_ERROR_NT(sam_init_account(account)); - if (!ADS_ERR_OK(ads_status)) - return ads_ntstatus(ads_status); - - (*account)->access_granted = acc_granted; - - return ads_ntstatus(ads_status); -} -#else -static NTSTATUS sam_ads_get_account_by_name(const SAM_METHODS *sam_method, const NT_USER_TOKEN *access_token, const uint32 access_desired, const char *account_name, SAM_ACCOUNT_HANDLE **account) -{ - ADS_STATUS ads_status = ADS_STATUS_NOT_IMPLEMENTED; - DEBUG(0,("sam_ads: %s was called!\n",FUNCTION_MACRO)); - SAM_ASSERT(sam_method); - return ads_ntstatus(ads_status); -} -#endif - -/* Group API */ -static NTSTATUS sam_ads_create_group(const SAM_METHODS *sam_method, const NT_USER_TOKEN *access_token, uint32 access_desired, const char *group_name, uint16 group_ctrl, SAM_GROUP_HANDLE **group) -{ - ADS_STATUS ads_status = ADS_STATUS_NOT_IMPLEMENTED; - DEBUG(0,("sam_ads: %s was called!\n",FUNCTION_MACRO)); - SAM_ASSERT(sam_method); - return ads_ntstatus(ads_status); -} - -static NTSTATUS sam_ads_add_group(const SAM_METHODS *sam_method, const SAM_GROUP_HANDLE *group) -{ - ADS_STATUS ads_status = ADS_STATUS_NOT_IMPLEMENTED; - DEBUG(0,("sam_ads: %s was called!\n",FUNCTION_MACRO)); - SAM_ASSERT(sam_method); - return ads_ntstatus(ads_status); -} - -static NTSTATUS sam_ads_update_group(const SAM_METHODS *sam_method, const SAM_GROUP_HANDLE *group) -{ - ADS_STATUS ads_status = ADS_STATUS_NOT_IMPLEMENTED; - DEBUG(0,("sam_ads: %s was called!\n",FUNCTION_MACRO)); - SAM_ASSERT(sam_method); - return ads_ntstatus(ads_status); -} - -static NTSTATUS sam_ads_delete_group(const SAM_METHODS *sam_method, const SAM_GROUP_HANDLE *group) -{ - ADS_STATUS ads_status = ADS_STATUS_NOT_IMPLEMENTED; - DEBUG(0,("sam_ads: %s was called!\n",FUNCTION_MACRO)); - SAM_ASSERT(sam_method); - return ads_ntstatus(ads_status); -} - -static NTSTATUS sam_ads_enum_groups(const SAM_METHODS *sam_method, const NT_USER_TOKEN *access_token, const uint16 group_ctrl, uint32 *groups_count, SAM_GROUP_ENUM **groups) -{ - ADS_STATUS ads_status = ADS_STATUS_NOT_IMPLEMENTED; - SAM_ADS_PRIVATES *privates = (struct sam_ads_privates *)sam_method->private_data; - ADS_STRUCT *ads_struct = privates->ads_struct; - TALLOC_CTX *mem_ctx = privates->mem_ctx; - void *res = NULL; - void *msg = NULL; - char *filter = NULL; - int i = 0; - - /* get only these LDAP attributes, witch we really need for a group */ - const char *group_enum_attrs[] = {"objectSid", - "description", - "sAMAcountName", - NULL}; - - SAM_ASSERT(sam_method && access_token && groups_count && groups); - - *groups_count = 0; - - DEBUG(3,("ads: enum_dom_groups\n")); - - FIXME("get only group from the wanted Type!\n"); - asprintf(&filter, "(&(objectClass=group)(groupType=%s))", "*"); - ads_status = sam_ads_do_search(privates, ads_struct->config.bind_path, LDAP_SCOPE_SUBTREE, filter, group_enum_attrs, &res); - if (!ADS_ERR_OK(ads_status)) { - DEBUG(1,("enum_groups ads_search: %s\n", ads_errstr(ads_status))); - } - - *groups_count = ads_count_replies(ads_struct, res); - if (*groups_count == 0) { - DEBUG(1,("enum_groups: No groups found\n")); - } - - (*groups) = talloc_zero(mem_ctx, (*groups_count) * sizeof(**groups)); - if (!*groups) { - ads_status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY); - } - - for (msg = ads_first_entry(ads_struct, res); msg; msg = ads_next_entry(ads_struct, msg)) { - uint32 grouptype; - - if (!ads_pull_uint32(ads_struct, msg, "groupType", &grouptype)) { - ; - } else { - (*groups)->group_ctrl = ads_gtype2gcb(grouptype); - } - - if (!((*groups)->group_name = ads_pull_string(ads_struct, mem_ctx, msg, "sAMAccountName"))) { - ; - } - - if (!((*groups)->group_desc = ads_pull_string(ads_struct, mem_ctx, msg, "description"))) { - ; - } - - if (!ads_pull_sid(ads_struct, msg, "objectSid", &((*groups)->sid))) { - DEBUG(1,("No sid for group %s !?\n", (*groups)->group_name)); - continue; - } - - i++; - } - - (*groups_count) = i; - - ads_status = ADS_ERROR_NT(NT_STATUS_OK); - - DEBUG(3,("ads enum_dom_groups gave %d entries\n", (*groups_count))); - - if (res) ads_msgfree(ads_struct, res); - - return ads_ntstatus(ads_status); -} - -static NTSTATUS sam_ads_get_group_by_sid(const SAM_METHODS *sam_method, const NT_USER_TOKEN *access_token, const uint32 access_desired, const DOM_SID *groupsid, SAM_GROUP_HANDLE **group) -{ - ADS_STATUS ads_status = ADS_STATUS_NOT_IMPLEMENTED; - DEBUG(0,("sam_ads: %s was called!\n",FUNCTION_MACRO)); - SAM_ASSERT(sam_method); - return ads_ntstatus(ads_status); -} - -static NTSTATUS sam_ads_get_group_by_name(const SAM_METHODS *sam_method, const NT_USER_TOKEN *access_token, const uint32 access_desired, const char *name, SAM_GROUP_HANDLE **group) -{ - ADS_STATUS ads_status = ADS_STATUS_NOT_IMPLEMENTED; - DEBUG(0,("sam_ads: %s was called!\n",FUNCTION_MACRO)); - SAM_ASSERT(sam_method); - return ads_ntstatus(ads_status); -} - -static NTSTATUS sam_ads_add_member_to_group(const SAM_METHODS *sam_method, const SAM_GROUP_HANDLE *group, const SAM_GROUP_MEMBER *member) -{ - ADS_STATUS ads_status = ADS_STATUS_NOT_IMPLEMENTED; - DEBUG(0,("sam_ads: %s was called!\n",FUNCTION_MACRO)); - SAM_ASSERT(sam_method); - return ads_ntstatus(ads_status); -} - -static NTSTATUS sam_ads_delete_member_from_group(const SAM_METHODS *sam_method, const SAM_GROUP_HANDLE *group, const SAM_GROUP_MEMBER *member) -{ - ADS_STATUS ads_status = ADS_STATUS_NOT_IMPLEMENTED; - DEBUG(0,("sam_ads: %s was called!\n",FUNCTION_MACRO)); - SAM_ASSERT(sam_method); - return ads_ntstatus(ads_status); -} - -static NTSTATUS sam_ads_enum_groupmembers(const SAM_METHODS *sam_method, const SAM_GROUP_HANDLE *group, uint32 *members_count, SAM_GROUP_MEMBER **members) -{ - ADS_STATUS ads_status = ADS_STATUS_NOT_IMPLEMENTED; - DEBUG(0,("sam_ads: %s was called!\n",FUNCTION_MACRO)); - SAM_ASSERT(sam_method); - return ads_ntstatus(ads_status); -} - -static NTSTATUS sam_ads_get_groups_of_sid(const SAM_METHODS *sam_method, const NT_USER_TOKEN *access_token, const DOM_SID **sids, const uint16 group_ctrl, uint32 *group_count, SAM_GROUP_ENUM **groups) -{ - ADS_STATUS ads_status = ADS_STATUS_NOT_IMPLEMENTED; - DEBUG(0,("sam_ads: %s was called!\n",FUNCTION_MACRO)); - SAM_ASSERT(sam_method); - return ads_ntstatus(ads_status); -} - -/********************************** -Free our private data -***********************************/ -static void sam_ads_free_private_data(void **vp) -{ - SAM_ADS_PRIVATES **sam_ads_state = (SAM_ADS_PRIVATES **)vp; - - if ((*sam_ads_state)->ads_struct->ld) { - ldap_unbind((*sam_ads_state)->ads_struct->ld); - } - - ads_destroy(&((*sam_ads_state)->ads_struct)); - - talloc_destroy((*sam_ads_state)->mem_ctx); - FIXME("maybe we must free some other stuff here\n"); - - *sam_ads_state = NULL; -} - - - -/***************************************************** -Init the ADS SAM backend -******************************************************/ -NTSTATUS sam_init_ads(SAM_METHODS *sam_method, const char *module_params) -{ - ADS_STATUS ads_status; - SAM_ADS_PRIVATES *sam_ads_state; - TALLOC_CTX *mem_ctx; - - SAM_ASSERT(sam_method && sam_method->parent); - - mem_ctx = sam_method->parent->mem_ctx; - - /* Here the SAM API functions of the sam_ads module */ - - /* General API */ - - sam_method->sam_get_sec_desc = sam_ads_get_sec_desc; - sam_method->sam_set_sec_desc = sam_ads_set_sec_desc; - - sam_method->sam_lookup_sid = sam_ads_lookup_sid; - sam_method->sam_lookup_name = sam_ads_lookup_name; - - /* Domain API */ - - sam_method->sam_update_domain = sam_ads_update_domain; - sam_method->sam_get_domain_handle = sam_ads_get_domain_handle; - - /* Account API */ - - sam_method->sam_create_account = sam_ads_create_account; - sam_method->sam_add_account = sam_ads_add_account; - sam_method->sam_update_account = sam_ads_update_account; - sam_method->sam_delete_account = sam_ads_delete_account; - sam_method->sam_enum_accounts = sam_ads_enum_accounts; - - sam_method->sam_get_account_by_sid = sam_ads_get_account_by_sid; - sam_method->sam_get_account_by_name = sam_ads_get_account_by_name; - - /* Group API */ - - sam_method->sam_create_group = sam_ads_create_group; - sam_method->sam_add_group = sam_ads_add_group; - sam_method->sam_update_group = sam_ads_update_group; - sam_method->sam_delete_group = sam_ads_delete_group; - sam_method->sam_enum_groups = sam_ads_enum_groups; - sam_method->sam_get_group_by_sid = sam_ads_get_group_by_sid; - sam_method->sam_get_group_by_name = sam_ads_get_group_by_name; - - sam_method->sam_add_member_to_group = sam_ads_add_member_to_group; - sam_method->sam_delete_member_from_group = sam_ads_delete_member_from_group; - sam_method->sam_enum_groupmembers = sam_ads_enum_groupmembers; - - sam_method->sam_get_groups_of_sid = sam_ads_get_groups_of_sid; - - sam_ads_state = talloc_zero(mem_ctx, sizeof(SAM_ADS_PRIVATES)); - if (!sam_ads_state) { - DEBUG(0, ("talloc() failed for sam_ads private_data!\n")); - return NT_STATUS_NO_MEMORY; - } - - if (!(sam_ads_state->mem_ctx = talloc_init("sam_ads_method"))) { - DEBUG(0, ("talloc_init() failed for sam_ads_state->mem_ctx\n")); - return NT_STATUS_NO_MEMORY; - } - - sam_ads_state->ads_bind_dn = talloc_strdup(sam_ads_state->mem_ctx, lp_parm_const_string(GLOBAL_SECTION_SNUM,"sam_ads","bind as", "")); - sam_ads_state->ads_bind_pw = talloc_strdup(sam_ads_state->mem_ctx, lp_parm_const_string(GLOBAL_SECTION_SNUM,"sam_ads","bind pw", "")); - - sam_ads_state->bind_plaintext = lp_parm_bool(GLOBAL_SECTION_SNUM, "sam_ads", "plaintext bind" , True); - - if (!sam_ads_state->ads_bind_dn || !sam_ads_state->ads_bind_pw) { - DEBUG(0, ("talloc_strdup() failed for bind dn or password\n")); - return NT_STATUS_NO_MEMORY; - } - - /* Maybe we should not check the result here? Server down on startup? */ - - if (module_params && *module_params) { - sam_ads_state->ldap_uri = talloc_strdup(sam_ads_state->mem_ctx, module_params); - if (!sam_ads_state->ldap_uri) { - DEBUG(0, ("talloc_strdup() failed for bind dn or password\n")); - return NT_STATUS_NO_MEMORY; - } - } else { - sam_ads_state->ldap_uri = "ldapi://"; - } - - ads_status = sam_ads_cached_connection(sam_ads_state); - if (!ADS_ERR_OK(ads_status)) { - return ads_ntstatus(ads_status); - } - - sam_method->private_data = sam_ads_state; - sam_method->free_private_data = sam_ads_free_private_data; - - sam_ads_debug_level = debug_add_class("sam_ads"); - if (sam_ads_debug_level == -1) { - sam_ads_debug_level = DBGC_ALL; - DEBUG(0, ("sam_ads: Couldn't register custom debugging class!\n")); - } else DEBUG(2, ("sam_ads: Debug class number of 'sam_ads': %d\n", sam_ads_debug_level)); - - DEBUG(5, ("Initializing sam_ads\n")); - if (module_params) - DEBUG(10, ("Module Parameters for Domain %s[%s]: %s\n", sam_method->domain_name, sam_method->domain_name, module_params)); - return NT_STATUS_OK; -} - -#else /* HAVE_LDAP */ -void sam_ads_dummy(void) -{ - DEBUG(0,("sam_ads: not supported!\n")); -} -#endif /* HAVE_LDAP */ diff --git a/source3/sam/sam_plugin.c b/source3/sam/sam_plugin.c deleted file mode 100644 index fd26c4b8d3..0000000000 --- a/source3/sam/sam_plugin.c +++ /dev/null @@ -1,79 +0,0 @@ -/* - Unix SMB/CIFS implementation. - Loadable san module interface. - Copyright (C) Jelmer Vernooij 2002 - 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 - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" - -#undef DBGC_CLASS -#define DBGC_CLASS DBGC_SAM - -NTSTATUS sam_init_plugin(SAM_METHODS *sam_methods, const char *module_params) -{ - void *dl_handle; - char *plugin_params, *plugin_name, *p; - sam_init_function plugin_init; - int (*plugin_version)(void); - - if (module_params == NULL) { - DEBUG(0, ("The plugin module needs an argument!\n")); - return NT_STATUS_UNSUCCESSFUL; - } - - plugin_name = smb_xstrdup(module_params); - p = strchr(plugin_name, ':'); - if (p) { - *p = 0; - plugin_params = p+1; - trim_string(plugin_params, " ", " "); - } else plugin_params = NULL; - trim_string(plugin_name, " ", " "); - - DEBUG(5, ("Trying to load sam plugin %s\n", plugin_name)); - 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; - } - - plugin_version = sys_dlsym(dl_handle, "sam_version"); - if (!plugin_version) { - sys_dlclose(dl_handle); - DEBUG(0, ("Failed to find function 'sam_version' using sys_dlsym in sam plugin %s (%s)\n", plugin_name, sys_dlerror())); - return NT_STATUS_UNSUCCESSFUL; - } - - if (plugin_version()!=SAM_INTERFACE_VERSION) { - sys_dlclose(dl_handle); - DEBUG(0, ("Wrong SAM_INTERFACE_VERSION! sam plugin has version %d and version %d is needed! Please update!\n", - plugin_version(),SAM_INTERFACE_VERSION)); - return NT_STATUS_UNSUCCESSFUL; - } - - plugin_init = sys_dlsym(dl_handle, "sam_init"); - if (!plugin_init) { - sys_dlclose(dl_handle); - DEBUG(0, ("Failed to find function 'sam_init' using sys_dlsym in sam plugin %s (%s)\n", plugin_name, sys_dlerror())); - return NT_STATUS_UNSUCCESSFUL; - } - - DEBUG(5, ("Starting sam plugin %s with parameters %s for domain %s\n", plugin_name, plugin_params, sam_methods->domain_name)); - return plugin_init(sam_methods, plugin_params); -} diff --git a/source3/sam/sam_skel.c b/source3/sam/sam_skel.c deleted file mode 100644 index b4d64bb6da..0000000000 --- a/source3/sam/sam_skel.c +++ /dev/null @@ -1,251 +0,0 @@ -/* - Unix SMB/CIFS implementation. - this is a skeleton for SAM backend modules. - - Copyright (C) Stefan (metze) Metzmacher 2002 - Copyright (C) Jelmer Vernooij 2002 - Copyright (C) Andrew Bartlett 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 - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" - -static int sam_skel_debug_level = DBGC_SAM; - -#undef DBGC_CLASS -#define DBGC_CLASS sam_skel_debug_level - -/* define the version of the SAM interface */ -SAM_MODULE_VERSIONING_MAGIC - -/* General API */ - -static NTSTATUS sam_skel_get_sec_desc(const SAM_METHODS *sam_methods, const NT_USER_TOKEN *access_token, const DOM_SID *sid, SEC_DESC **sd) -{ - DEBUG(0,("sam_skel: %s was called!\n",FUNCTION_MACRO)); - return NT_STATUS_NOT_IMPLEMENTED; -} - -static NTSTATUS sam_skel_set_sec_desc(const SAM_METHODS *sam_methods, const NT_USER_TOKEN *access_token, const DOM_SID *sid, const SEC_DESC *sd) -{ - DEBUG(0,("sam_skel: %s was called!\n",FUNCTION_MACRO)); - return NT_STATUS_NOT_IMPLEMENTED; -} - - -static NTSTATUS sam_skel_lookup_sid(const SAM_METHODS *sam_methods, const NT_USER_TOKEN *access_token, TALLOC_CTX *mem_ctx, const DOM_SID *sid, char **name, uint32 *type) -{ - DEBUG(0,("sam_skel: %s was called!\n",FUNCTION_MACRO)); - return NT_STATUS_NOT_IMPLEMENTED; -} - -static NTSTATUS sam_skel_lookup_name(const SAM_METHODS *sam_methods, const NT_USER_TOKEN *access_token, const char *name, DOM_SID *sid, uint32 *type) -{ - DEBUG(0,("sam_skel: %s was called!\n",FUNCTION_MACRO)); - return NT_STATUS_NOT_IMPLEMENTED; -} - - -/* Domain API */ - -static NTSTATUS sam_skel_update_domain(const SAM_METHODS *sam_methods, const SAM_DOMAIN_HANDLE *domain) -{ - DEBUG(0,("sam_skel: %s was called!\n",FUNCTION_MACRO)); - return NT_STATUS_NOT_IMPLEMENTED; -} - -static NTSTATUS sam_skel_get_domain_handle(const SAM_METHODS *sam_methods, const NT_USER_TOKEN *access_token, uint32 access_desired, SAM_DOMAIN_HANDLE **domain) -{ - DEBUG(0,("sam_skel: %s was called!\n",FUNCTION_MACRO)); - return NT_STATUS_NOT_IMPLEMENTED; -} - - -/* Account API */ - -static NTSTATUS sam_skel_create_account(const SAM_METHODS *sam_methods, const NT_USER_TOKEN *access_token, uint32 access_desired, const char *account_name, uint16 acct_ctrl, SAM_ACCOUNT_HANDLE **account) -{ - DEBUG(0,("sam_skel: %s was called!\n",FUNCTION_MACRO)); - return NT_STATUS_NOT_IMPLEMENTED; -} - -static NTSTATUS sam_skel_add_account(const SAM_METHODS *sam_methods, const SAM_ACCOUNT_HANDLE *account) -{ - DEBUG(0,("sam_skel: %s was called!\n",FUNCTION_MACRO)); - return NT_STATUS_NOT_IMPLEMENTED; -} - -static NTSTATUS sam_skel_update_account(const SAM_METHODS *sam_methods, const SAM_ACCOUNT_HANDLE *account) -{ - DEBUG(0,("sam_skel: %s was called!\n",FUNCTION_MACRO)); - return NT_STATUS_NOT_IMPLEMENTED; -} - -static NTSTATUS sam_skel_delete_account(const SAM_METHODS *sam_methods, const SAM_ACCOUNT_HANDLE *account) -{ - DEBUG(0,("sam_skel: %s was called!\n",FUNCTION_MACRO)); - return NT_STATUS_NOT_IMPLEMENTED; -} - -static NTSTATUS sam_skel_enum_accounts(const SAM_METHODS *sam_methods, const NT_USER_TOKEN *access_token, uint16 acct_ctrl, uint32 *account_count, SAM_ACCOUNT_ENUM **accounts) -{ - DEBUG(0,("sam_skel: %s was called!\n",FUNCTION_MACRO)); - return NT_STATUS_NOT_IMPLEMENTED; -} - - -static NTSTATUS sam_skel_get_account_by_sid(const SAM_METHODS *sam_methods, const NT_USER_TOKEN *access_token, uint32 access_desired, const DOM_SID *accountsid, SAM_ACCOUNT_HANDLE **account) -{ - DEBUG(0,("sam_skel: %s was called!\n",FUNCTION_MACRO)); - return NT_STATUS_NOT_IMPLEMENTED; -} - -static NTSTATUS sam_skel_get_account_by_name(const SAM_METHODS *sam_methods, const NT_USER_TOKEN *access_token, uint32 access_desired, const char *name, SAM_ACCOUNT_HANDLE **account) -{ - DEBUG(0,("sam_skel: %s was called!\n",FUNCTION_MACRO)); - return NT_STATUS_NOT_IMPLEMENTED; -} - - -/* Group API */ - -static NTSTATUS sam_skel_create_group(const SAM_METHODS *sam_methods, const NT_USER_TOKEN *access_token, uint32 access_desired, const char *account_name, uint16 group_ctrl, SAM_GROUP_HANDLE **group) -{ - DEBUG(0,("sam_skel: %s was called!\n",FUNCTION_MACRO)); - return NT_STATUS_NOT_IMPLEMENTED; -} - -static NTSTATUS sam_skel_add_group(const SAM_METHODS *sam_methods, const SAM_GROUP_HANDLE *group) -{ - DEBUG(0,("sam_skel: %s was called!\n",FUNCTION_MACRO)); - return NT_STATUS_NOT_IMPLEMENTED; -} - -static NTSTATUS sam_skel_update_group(const SAM_METHODS *sam_methods, const SAM_GROUP_HANDLE *group) -{ - DEBUG(0,("sam_skel: %s was called!\n",FUNCTION_MACRO)); - return NT_STATUS_NOT_IMPLEMENTED; -} - -static NTSTATUS sam_skel_delete_group(const SAM_METHODS *sam_methods, const SAM_GROUP_HANDLE *group) -{ - DEBUG(0,("sam_skel: %s was called!\n",FUNCTION_MACRO)); - return NT_STATUS_NOT_IMPLEMENTED; -} - -static NTSTATUS sam_skel_enum_groups(const SAM_METHODS *sam_methods, const NT_USER_TOKEN *access_token, uint16 group_ctrl, uint32 *groups_count, SAM_GROUP_ENUM **groups) -{ - DEBUG(0,("sam_skel: %s was called!\n",FUNCTION_MACRO)); - return NT_STATUS_NOT_IMPLEMENTED; -} - -static NTSTATUS sam_skel_get_group_by_sid(const SAM_METHODS *sam_methods, const NT_USER_TOKEN *access_token, uint32 access_desired, const DOM_SID *groupsid, SAM_GROUP_HANDLE **group) -{ - DEBUG(0,("sam_skel: %s was called!\n",FUNCTION_MACRO)); - return NT_STATUS_NOT_IMPLEMENTED; -} - -static NTSTATUS sam_skel_get_group_by_name(const SAM_METHODS *sam_methods, const NT_USER_TOKEN *access_token, uint32 access_desired, const char *name, SAM_GROUP_HANDLE **group) -{ - DEBUG(0,("sam_skel: %s was called!\n",FUNCTION_MACRO)); - return NT_STATUS_NOT_IMPLEMENTED; -} - - -static NTSTATUS sam_skel_add_member_to_group(const SAM_METHODS *sam_methods, const SAM_GROUP_HANDLE *group, const SAM_GROUP_MEMBER *member) -{ - DEBUG(0,("sam_skel: %s was called!\n",FUNCTION_MACRO)); - return NT_STATUS_NOT_IMPLEMENTED; -} - -static NTSTATUS sam_skel_delete_member_from_group(const SAM_METHODS *sam_methods, const SAM_GROUP_HANDLE *group, const SAM_GROUP_MEMBER *member) -{ - DEBUG(0,("sam_skel: %s was called!\n",FUNCTION_MACRO)); - return NT_STATUS_NOT_IMPLEMENTED; -} - -static NTSTATUS sam_skel_enum_groupmembers(const SAM_METHODS *sam_methods, const SAM_GROUP_HANDLE *group, uint32 *members_count, SAM_GROUP_MEMBER **members) -{ - DEBUG(0,("sam_skel: %s was called!\n",FUNCTION_MACRO)); - return NT_STATUS_NOT_IMPLEMENTED; -} - - -static NTSTATUS sam_skel_get_groups_of_sid(const SAM_METHODS *sam_methods, const NT_USER_TOKEN *access_token, const DOM_SID **sids, uint16 group_ctrl, uint32 *group_count, SAM_GROUP_ENUM **groups) -{ - DEBUG(0,("sam_skel: %s was called!\n",FUNCTION_MACRO)); - return NT_STATUS_NOT_IMPLEMENTED; -} - -NTSTATUS sam_init_skel(SAM_METHODS *sam_methods, const char *module_params) -{ - /* Functions your SAM module doesn't provide should be set - * to NULL */ - - sam_methods->sam_get_sec_desc = sam_skel_get_sec_desc; - sam_methods->sam_set_sec_desc = sam_skel_set_sec_desc; - - sam_methods->sam_lookup_sid = sam_skel_lookup_sid; - sam_methods->sam_lookup_name = sam_skel_lookup_name; - - /* Domain API */ - - sam_methods->sam_update_domain = sam_skel_update_domain; - sam_methods->sam_get_domain_handle = sam_skel_get_domain_handle; - - /* Account API */ - - sam_methods->sam_create_account = sam_skel_create_account; - sam_methods->sam_add_account = sam_skel_add_account; - sam_methods->sam_update_account = sam_skel_update_account; - sam_methods->sam_delete_account = sam_skel_delete_account; - sam_methods->sam_enum_accounts = sam_skel_enum_accounts; - - sam_methods->sam_get_account_by_sid = sam_skel_get_account_by_sid; - sam_methods->sam_get_account_by_name = sam_skel_get_account_by_name; - - /* Group API */ - - sam_methods->sam_create_group = sam_skel_create_group; - sam_methods->sam_add_group = sam_skel_add_group; - sam_methods->sam_update_group = sam_skel_update_group; - sam_methods->sam_delete_group = sam_skel_delete_group; - sam_methods->sam_enum_groups = sam_skel_enum_groups; - sam_methods->sam_get_group_by_sid = sam_skel_get_group_by_sid; - sam_methods->sam_get_group_by_name = sam_skel_get_group_by_name; - - sam_methods->sam_add_member_to_group = sam_skel_add_member_to_group; - sam_methods->sam_delete_member_from_group = sam_skel_delete_member_from_group; - sam_methods->sam_enum_groupmembers = sam_skel_enum_groupmembers; - - sam_methods->sam_get_groups_of_sid = sam_skel_get_groups_of_sid; - - sam_methods->free_private_data = NULL; - - - sam_skel_debug_level = debug_add_class("sam_skel"); - if (sam_skel_debug_level == -1) { - sam_skel_debug_level = DBGC_SAM; - DEBUG(0, ("sam_skel: Couldn't register custom debugging class!\n")); - } else DEBUG(2, ("sam_skel: Debug class number of 'sam_skel': %d\n", sam_skel_debug_level)); - - if(module_params) - DEBUG(0, ("Starting 'sam_skel' with parameters '%s' for domain %s\n", module_params, sam_methods->domain_name)); - else - DEBUG(0, ("Starting 'sam_skel' for domain %s without paramters\n", sam_methods->domain_name)); - - return NT_STATUS_OK; -} diff --git a/source3/torture/cmd_sam.c b/source3/torture/cmd_sam.c deleted file mode 100644 index 3f7f7dfe27..0000000000 --- a/source3/torture/cmd_sam.c +++ /dev/null @@ -1,514 +0,0 @@ -/* - Unix SMB/CIFS implementation. - SAM module functions - - 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 Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" -#include "samtest.h" - -static void print_account(SAM_ACCOUNT_HANDLE *a) -{ - /* FIXME */ -} - -static NTSTATUS cmd_context(struct samtest_state *st, TALLOC_CTX *mem_ctx, int argc, char **argv) -{ - NTSTATUS status; - char **plugins; - int i; - - plugins = malloc(argc * sizeof(char *)); - - for(i = 1; i < argc; i++) - plugins[i-1] = argv[i]; - - plugins[argc-1] = NULL; - - if(!NT_STATUS_IS_OK(status = make_sam_context_list(&st->context, plugins))) { - printf("make_sam_context_list failed: %s\n", nt_errstr(status)); - SAFE_FREE(plugins); - return status; - } - - SAFE_FREE(plugins); - - return NT_STATUS_OK; -} - -static NTSTATUS cmd_load_module(struct samtest_state *st, TALLOC_CTX *mem_ctx, int argc, char **argv) -{ - char *plugin_arg[2]; - NTSTATUS status; - if (argc != 2 && argc != 3) { - printf("Usage: load [domain-name]\n"); - return NT_STATUS_OK; - } - - if (argc == 3) - asprintf(&plugin_arg[0], "plugin:%s|%s", argv[1], argv[2]); - else - asprintf(&plugin_arg[0], "plugin:%s", argv[1]); - - plugin_arg[1] = NULL; - - if(!NT_STATUS_IS_OK(status = make_sam_context_list(&st->context, plugin_arg))) { - free(plugin_arg[0]); - return status; - } - - free(plugin_arg[0]); - - printf("load: ok\n"); - return NT_STATUS_OK; -} - -static NTSTATUS cmd_get_sec_desc(struct samtest_state *st, TALLOC_CTX *mem_ctx, int argc, char **argv) -{ - return NT_STATUS_NOT_IMPLEMENTED; -} - -static NTSTATUS cmd_set_sec_desc(struct samtest_state *st, TALLOC_CTX *mem_ctx, int argc, char **argv) -{ - return NT_STATUS_NOT_IMPLEMENTED; -} - -static NTSTATUS cmd_lookup_sid(struct samtest_state *st, TALLOC_CTX *mem_ctx, int argc, char **argv) -{ - char *name; - uint32 type; - NTSTATUS status; - DOM_SID sid; - if (argc != 2) { - printf("Usage: lookup_sid \n"); - return NT_STATUS_INVALID_PARAMETER; - } - - if (!string_to_sid(&sid, argv[1])){ - printf("Unparseable SID specified!\n"); - return NT_STATUS_INVALID_PARAMETER; - } - - if (!NT_STATUS_IS_OK(status = sam_lookup_sid(st->context, st->token, mem_ctx, &sid, &name, &type))) { - printf("sam_lookup_sid failed!\n"); - return status; - } - - printf("Name: %s\n", name); - printf("Type: %d\n", type); /* FIXME: What kind of an integer is type ? */ - - return NT_STATUS_OK; -} - -static NTSTATUS cmd_lookup_name(struct samtest_state *st, TALLOC_CTX *mem_ctx, int argc, char **argv) -{ - DOM_SID sid; - uint32 type; - NTSTATUS status; - if (argc != 3) { - printf("Usage: lookup_name \n"); - return NT_STATUS_INVALID_PARAMETER; - } - - if (!NT_STATUS_IS_OK(status = sam_lookup_name(st->context, st->token, argv[1], argv[2], &sid, &type))) { - printf("sam_lookup_name failed!\n"); - return status; - } - - printf("SID: %s\n", sid_string_static(&sid)); - printf("Type: %d\n", type); - - return NT_STATUS_OK; -} - -static NTSTATUS cmd_lookup_account(struct samtest_state *st, TALLOC_CTX *mem_ctx, int argc, char **argv) -{ - return NT_STATUS_NOT_IMPLEMENTED; -} - -static NTSTATUS cmd_lookup_group(struct samtest_state *st, TALLOC_CTX *mem_ctx, int argc, char **argv) -{ - return NT_STATUS_NOT_IMPLEMENTED; -} - -static NTSTATUS cmd_lookup_domain(struct samtest_state *st, TALLOC_CTX *mem_ctx, int argc, char **argv) -{ - DOM_SID *sid; - NTSTATUS status; - if (argc != 2) { - printf("Usage: lookup_domain \n"); - return NT_STATUS_INVALID_PARAMETER; - } - - if (!NT_STATUS_IS_OK(status = sam_lookup_domain(st->context, st->token, argv[1], &sid))) { - printf("sam_lookup_name failed!\n"); - return status; - } - - printf("SID: %s\n", sid_string_static(sid)); - - return NT_STATUS_OK; -} - -static NTSTATUS cmd_enum_domains(struct samtest_state *st, TALLOC_CTX *mem_ctx, int argc, char **argv) -{ - int32 domain_count, i; - DOM_SID *domain_sids; - char **domain_names; - NTSTATUS status; - - if (!NT_STATUS_IS_OK(status = sam_enum_domains(st->context, st->token, &domain_count, &domain_sids, &domain_names))) { - printf("sam_enum_domains failed!\n"); - return status; - } - - if (domain_count == 0) { - printf("No domains found!\n"); - return NT_STATUS_OK; - } - - for (i = 0; i < domain_count; i++) { - printf("%s %s\n", domain_names[i], sid_string_static(&domain_sids[i])); - } - - SAFE_FREE(domain_sids); - SAFE_FREE(domain_names); - - return NT_STATUS_OK; -} - -static NTSTATUS cmd_update_domain(struct samtest_state *st, TALLOC_CTX *mem_ctx, int argc, char **argv) -{ - return NT_STATUS_NOT_IMPLEMENTED; -} - -static NTSTATUS cmd_show_domain(struct samtest_state *st, TALLOC_CTX *mem_ctx, int argc, char **argv) -{ - NTSTATUS status; - DOM_SID sid; - SAM_DOMAIN_HANDLE *domain; - uint32 tmp_uint32; - uint16 tmp_uint16; - NTTIME tmp_nttime; - BOOL tmp_bool; - const char *tmp_string; - - if (argc != 2) { - printf("Usage: show_domain \n"); - return status; - } - - if (!string_to_sid(&sid, argv[1])){ - printf("Unparseable SID specified!\n"); - return NT_STATUS_INVALID_PARAMETER; - } - - if (!NT_STATUS_IS_OK(status = sam_get_domain_by_sid(st->context, st->token, GENERIC_RIGHTS_DOMAIN_ALL_ACCESS, &sid, &domain))) { - printf("sam_get_domain_by_sid failed\n"); - return status; - } - - if (!NT_STATUS_IS_OK(status = sam_get_domain_num_accounts(domain, &tmp_uint32))) { - printf("sam_get_domain_num_accounts failed: %s\n", nt_errstr(status)); - } else { - printf("Number of accounts: %d\n", tmp_uint32); - } - - if (!NT_STATUS_IS_OK(status = sam_get_domain_num_groups(domain, &tmp_uint32))) { - printf("sam_get_domain_num_groups failed: %s\n", nt_errstr(status)); - } else { - printf("Number of groups: %u\n", tmp_uint32); - } - - if (!NT_STATUS_IS_OK(status = sam_get_domain_num_aliases(domain, &tmp_uint32))) { - printf("sam_get_domain_num_aliases failed: %s\n", nt_errstr(status)); - } else { - printf("Number of aliases: %u\n", tmp_uint32); - } - - if (!NT_STATUS_IS_OK(status = sam_get_domain_name(domain, &tmp_string))) { - printf("sam_get_domain_name failed: %s\n", nt_errstr(status)); - } else { - printf("Domain Name: %s\n", tmp_string); - } - - if (!NT_STATUS_IS_OK(status = sam_get_domain_lockout_count(domain, &tmp_uint16))) { - printf("sam_get_domain_lockout_count failed: %s\n", nt_errstr(status)); - } else { - printf("Lockout Count: %u\n", tmp_uint16); - } - - if (!NT_STATUS_IS_OK(status = sam_get_domain_force_logoff(domain, &tmp_bool))) { - printf("sam_get_domain_force_logoff failed: %s\n", nt_errstr(status)); - } else { - printf("Force Logoff: %s\n", (tmp_bool?"Yes":"No")); - } - - if (!NT_STATUS_IS_OK(status = sam_get_domain_lockout_duration(domain, &tmp_nttime))) { - printf("sam_get_domain_lockout_duration failed: %s\n", nt_errstr(status)); - } else { - printf("Lockout duration: %u\n", tmp_nttime.low); - } - - if (!NT_STATUS_IS_OK(status = sam_get_domain_login_pwdchange(domain, &tmp_bool))) { - printf("sam_get_domain_login_pwdchange failed: %s\n", nt_errstr(status)); - } else { - printf("Password changing allowed: %s\n", (tmp_bool?"Yes":"No")); - } - - if (!NT_STATUS_IS_OK(status = sam_get_domain_max_pwdage(domain, &tmp_nttime))) { - printf("sam_get_domain_max_pwdage failed: %s\n", nt_errstr(status)); - } else { - printf("Maximum password age: %u\n", tmp_nttime.low); - } - - if (!NT_STATUS_IS_OK(status = sam_get_domain_min_pwdage(domain, &tmp_nttime))) { - printf("sam_get_domain_min_pwdage failed: %s\n", nt_errstr(status)); - } else { - printf("Minimal password age: %u\n", tmp_nttime.low); - } - - if (!NT_STATUS_IS_OK(status = sam_get_domain_min_pwdlength(domain, &tmp_uint16))) { - printf("sam_get_domain_min_pwdlength: %s\n", nt_errstr(status)); - } else { - printf("Minimal Password Length: %u\n", tmp_uint16); - } - - if (!NT_STATUS_IS_OK(status = sam_get_domain_pwd_history(domain, &tmp_uint16))) { - printf("sam_get_domain_pwd_history failed: %s\n", nt_errstr(status)); - } else { - printf("Password history: %u\n", tmp_uint16); - } - - if (!NT_STATUS_IS_OK(status = sam_get_domain_reset_count(domain, &tmp_nttime))) { - printf("sam_get_domain_reset_count failed: %s\n", nt_errstr(status)); - } else { - printf("Reset count: %u\n", tmp_nttime.low); - } - - if (!NT_STATUS_IS_OK(status = sam_get_domain_server(domain, &tmp_string))) { - printf("sam_get_domain_server failed: %s\n", nt_errstr(status)); - } else { - printf("Server: %s\n", tmp_string); - } - - return NT_STATUS_OK; -} - -static NTSTATUS cmd_create_account(struct samtest_state *st, TALLOC_CTX *mem_ctx, int argc, char **argv) -{ - return NT_STATUS_NOT_IMPLEMENTED; -} - -static NTSTATUS cmd_update_account(struct samtest_state *st, TALLOC_CTX *mem_ctx, int argc, char **argv) -{ - return NT_STATUS_NOT_IMPLEMENTED; -} - -static NTSTATUS cmd_delete_account(struct samtest_state *st, TALLOC_CTX *mem_ctx, int argc, char **argv) -{ - return NT_STATUS_NOT_IMPLEMENTED; -} - -static NTSTATUS cmd_enum_accounts(struct samtest_state *st, TALLOC_CTX *mem_ctx, int argc, char **argv) -{ - NTSTATUS status; - DOM_SID sid; - int32 account_count, i; - SAM_ACCOUNT_ENUM *accounts; - - if (argc != 2) { - printf("Usage: enum_accounts \n"); - return NT_STATUS_INVALID_PARAMETER; - } - - if (!string_to_sid(&sid, argv[1])){ - printf("Unparseable SID specified!\n"); - return NT_STATUS_INVALID_PARAMETER; - } - - if (!NT_STATUS_IS_OK(status = sam_enum_accounts(st->context, st->token, &sid, 0, &account_count, &accounts))) { - printf("sam_enum_accounts failed: %s\n", nt_errstr(status)); - return status; - } - - if (account_count == 0) { - printf("No accounts found!\n"); - return NT_STATUS_OK; - } - - for (i = 0; i < account_count; i++) - printf("SID: %s\nName: %s\nFullname: %s\nDescription: %s\nACB_BITS: %08X\n\n", - sid_string_static(&accounts[i].sid), accounts[i].account_name, - accounts[i].full_name, accounts[i].account_desc, - accounts[i].acct_ctrl); - - SAFE_FREE(accounts); - - return NT_STATUS_OK; -} - -static NTSTATUS cmd_lookup_account_sid(struct samtest_state *st, TALLOC_CTX *mem_ctx, int argc, char **argv) -{ - NTSTATUS status; - DOM_SID sid; - SAM_ACCOUNT_HANDLE *account; - - if (argc != 2) { - printf("Usage: lookup_account_sid \n"); - return NT_STATUS_INVALID_PARAMETER; - } - - if (!string_to_sid(&sid, argv[1])){ - printf("Unparseable SID specified!\n"); - return NT_STATUS_INVALID_PARAMETER; - } - - if (!NT_STATUS_IS_OK(status = sam_get_account_by_sid(st->context, st->token, GENERIC_RIGHTS_USER_ALL_ACCESS, &sid, &account))) { - printf("context_sam_get_account_by_sid failed: %s\n", nt_errstr(status)); - return status; - } - - print_account(account); - - return NT_STATUS_OK; -} - -static NTSTATUS cmd_lookup_account_name(struct samtest_state *st, TALLOC_CTX *mem_ctx, int argc, char **argv) -{ - NTSTATUS status; - SAM_ACCOUNT_HANDLE *account; - - if (argc != 3) { - printf("Usage: lookup_account_name \n"); - return NT_STATUS_INVALID_PARAMETER; - } - - - if (!NT_STATUS_IS_OK(status = sam_get_account_by_name(st->context, st->token, GENERIC_RIGHTS_USER_ALL_ACCESS, argv[1], argv[2], &account))) { - printf("context_sam_get_account_by_sid failed: %s\n", nt_errstr(status)); - return status; - } - - print_account(account); - - return NT_STATUS_OK; -} - -static NTSTATUS cmd_create_group(struct samtest_state *st, TALLOC_CTX *mem_ctx, int argc, char **argv) -{ - return NT_STATUS_NOT_IMPLEMENTED; -} - -static NTSTATUS cmd_update_group(struct samtest_state *st, TALLOC_CTX *mem_ctx, int argc, char **argv) -{ - return NT_STATUS_NOT_IMPLEMENTED; -} - -static NTSTATUS cmd_delete_group(struct samtest_state *st, TALLOC_CTX *mem_ctx, int argc, char **argv) -{ - return NT_STATUS_NOT_IMPLEMENTED; -} - -static NTSTATUS cmd_enum_groups(struct samtest_state *st, TALLOC_CTX *mem_ctx, int argc, char **argv) -{ - return NT_STATUS_NOT_IMPLEMENTED; -} - -static NTSTATUS cmd_lookup_group_sid(struct samtest_state *st, TALLOC_CTX *mem_ctx, int argc, char **argv) -{ - return NT_STATUS_NOT_IMPLEMENTED; -} - -static NTSTATUS cmd_lookup_group_name(struct samtest_state *st, TALLOC_CTX *mem_ctx, int argc, char **argv) -{ - return NT_STATUS_NOT_IMPLEMENTED; -} - -static NTSTATUS cmd_group_add_member(struct samtest_state *st, TALLOC_CTX *mem_ctx, int argc, char **argv) -{ - return NT_STATUS_NOT_IMPLEMENTED; -} - -static NTSTATUS cmd_group_del_member(struct samtest_state *st, TALLOC_CTX *mem_ctx, int argc, char **argv) -{ - return NT_STATUS_NOT_IMPLEMENTED; -} - - -static NTSTATUS cmd_group_enum(struct samtest_state *st, TALLOC_CTX *mem_ctx, int argc, char **argv) -{ - return NT_STATUS_NOT_IMPLEMENTED; -} - - -static NTSTATUS cmd_get_sid_groups(struct samtest_state *st, TALLOC_CTX *mem_ctx, int argc, char **argv) -{ - return NT_STATUS_NOT_IMPLEMENTED; -} - -struct cmd_set sam_general_commands[] = { - - { "General SAM Commands" }, - - { "load", cmd_load_module, "Load a module", "load [domain-sid]" }, - { "context", cmd_context, "Load specified context", "context [DOMAIN|]backend1[:options] [DOMAIN|]backend2[:options]" }, - { "get_sec_desc", cmd_get_sec_desc, "Get security descriptor info", "get_sec_desc " }, - { "set_sec_desc", cmd_set_sec_desc, "Set security descriptor info", "set_sec_desc " }, - { "lookup_sid", cmd_lookup_sid, "Lookup type of specified SID", "lookup_sid " }, - { "lookup_name", cmd_lookup_name, "Lookup type of specified name", "lookup_name " }, - { NULL } -}; - -struct cmd_set sam_domain_commands[] = { - { "Domain Commands" }, - { "update_domain", cmd_update_domain, "Update domain information", "update_domain [domain-options] domain-name | domain-sid" }, - { "show_domain", cmd_show_domain, "Show domain information", "show_domain domain-sid | domain-name" }, - { "enum_domains", cmd_enum_domains, "Enumerate all domains", "enum_domains " }, - { "lookup_domain", cmd_lookup_domain, "Lookup a domain by name", "lookup_domain domain-name" }, - { NULL } -}; - -struct cmd_set sam_account_commands[] = { - { "Account Commands" }, - { "create_account", cmd_create_account, "Create a new account with specified properties", "create_account [account-options]" }, - { "update_account", cmd_update_account, "Update an existing account", "update_account [account-options] account-sid | account-name" }, - { "delete_account", cmd_delete_account, "Delete an account", "delete_account account-sid | account-name" }, - { "enum_accounts", cmd_enum_accounts, "Enumerate all accounts", "enum_accounts " }, - { "lookup_account", cmd_lookup_account, "Lookup an account by either sid or name", "lookup_account account-sid | account-name" }, - { "lookup_account_sid", cmd_lookup_account_sid, "Lookup an account by sid", "lookup_account_sid account-sid" }, - { "lookup_account_name", cmd_lookup_account_name, "Lookup an account by name", "lookup_account_name account-name" }, - { NULL } -}; - -struct cmd_set sam_group_commands[] = { - { "Group Commands" }, - { "create_group", cmd_create_group, "Create a new group", "create_group [group-opts]" }, - { "update_group", cmd_update_group, "Update an existing group", "update_group [group-opts] group-name | group-sid" }, - { "delete_group", cmd_delete_group, "Delete an existing group", "delete_group group-name | group-sid" }, - { "enum_groups", cmd_enum_groups, "Enumerate all groups", "enum_groups " }, - { "lookup_group", cmd_lookup_group, "Lookup a group by SID or name", "lookup_group group-sid | group-name" }, - { "lookup_group_sid", cmd_lookup_group_sid, "Lookup a group by SID", "lookup_group_sid " }, - { "lookup_group_name", cmd_lookup_group_name, "Lookup a group by name", "lookup_group_name " }, - { "group_add_member", cmd_group_add_member, "Add group member to group", "group_add_member " }, - { "group_del_member", cmd_group_del_member, "Delete group member from group", "group_del_member " }, - { "group_enum", cmd_group_enum, "Enumerate all members of specified group", "group_enum group-sid | group-name" }, - - { "get_sid_groups", cmd_get_sid_groups, "Get a list of groups specified sid is a member of", "group_enum " }, - { NULL } -}; diff --git a/source3/torture/samtest.c b/source3/torture/samtest.c deleted file mode 100644 index fd5f75a664..0000000000 --- a/source3/torture/samtest.c +++ /dev/null @@ -1,445 +0,0 @@ -/* - Unix SMB/CIFS implementation. - SAM module tester - - Copyright (C) 2002 Jelmer Vernooij - - Parts of the code stolen from vfstest by Simo Sorce and Eric Lorimer - Parts of the code stolen from rpcclient by Tim Potter - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include "includes.h" -#include "samtest.h" - -struct func_entry { - char *name; - int (*fn)(struct connection_struct *conn, const char *path); -}; - -/* List to hold groups of commands */ -static struct cmd_list { - struct cmd_list *prev, *next; - struct cmd_set *cmd_set; -} *cmd_list; - -static char* next_command (char** cmdstr) -{ - static pstring command; - char *p; - - if (!cmdstr || !(*cmdstr)) - return NULL; - - p = strchr_m(*cmdstr, ';'); - if (p) - *p = '\0'; - pstrcpy(command, *cmdstr); - *cmdstr = p; - - return command; -} - -/* Load specified configuration file */ -static NTSTATUS cmd_conf(struct samtest_state *sam, TALLOC_CTX *mem_ctx, - int argc, char **argv) -{ - if (argc != 2) { - printf("Usage: %s \n", argv[0]); - return NT_STATUS_OK; - } - - if (!lp_load(argv[1], False, True, False)) { - printf("Error loading \"%s\"\n", argv[1]); - return NT_STATUS_OK; - } - - printf("\"%s\" successfully loaded\n", argv[1]); - return NT_STATUS_OK; -} - -/* Display help on commands */ -static NTSTATUS cmd_help(struct samtest_state *st, TALLOC_CTX *mem_ctx, - int argc, const char **argv) -{ - struct cmd_list *tmp; - struct cmd_set *tmp_set; - - /* Usage */ - if (argc > 2) { - printf("Usage: %s [command]\n", argv[0]); - return NT_STATUS_OK; - } - - /* Help on one command */ - - if (argc == 2) { - for (tmp = cmd_list; tmp; tmp = tmp->next) { - - tmp_set = tmp->cmd_set; - - while(tmp_set->name) { - if (strequal(argv[1], tmp_set->name)) { - if (tmp_set->usage && - tmp_set->usage[0]) - printf("%s\n", tmp_set->usage); - else - printf("No help for %s\n", tmp_set->name); - - return NT_STATUS_OK; - } - - tmp_set++; - } - } - - printf("No such command: %s\n", argv[1]); - return NT_STATUS_OK; - } - - /* List all commands */ - - for (tmp = cmd_list; tmp; tmp = tmp->next) { - - tmp_set = tmp->cmd_set; - - while(tmp_set->name) { - - printf("%20s\t%s\n", tmp_set->name, - tmp_set->description ? tmp_set->description: - ""); - - tmp_set++; - } - } - - return NT_STATUS_OK; -} - -/* Change the debug level */ -static NTSTATUS cmd_debuglevel(struct samtest_state *st, TALLOC_CTX *mem_ctx, int argc, char **argv) -{ - if (argc > 2) { - printf("Usage: %s [debuglevel]\n", argv[0]); - return NT_STATUS_OK; - } - - if (argc == 2) { - DEBUGLEVEL = atoi(argv[1]); - } - - printf("debuglevel is %d\n", DEBUGLEVEL); - - return NT_STATUS_OK; -} - -static NTSTATUS cmd_quit(struct samtest_state *st, TALLOC_CTX *mem_ctx, int argc, char **argv) -{ - /* Cleanup */ - talloc_destroy(mem_ctx); - - exit(0); - return NT_STATUS_OK; /* NOTREACHED */ -} - -static struct cmd_set samtest_commands[] = { - - { "GENERAL OPTIONS" }, - - { "help", cmd_help, "Get help on commands", "" }, - { "?", cmd_help, "Get help on commands", "" }, - { "conf", cmd_conf, "Load smb configuration file", "conf " }, - { "debuglevel", cmd_debuglevel, "Set debug level", "" }, - { "exit", cmd_quit, "Exit program", "" }, - { "quit", cmd_quit, "Exit program", "" }, - - { NULL } -}; - -static struct cmd_set separator_command[] = { - { "---------------", NULL, "----------------------" }, - { NULL } -}; - - -/*extern struct cmd_set sam_commands[];*/ -extern struct cmd_set sam_general_commands[]; -extern struct cmd_set sam_domain_commands[]; -extern struct cmd_set sam_account_commands[]; -extern struct cmd_set sam_group_commands[]; -static struct cmd_set *samtest_command_list[] = { - samtest_commands, - sam_general_commands, - sam_domain_commands, - sam_account_commands, - sam_group_commands, - NULL -}; - -static void add_command_set(struct cmd_set *cmd_set) -{ - struct cmd_list *entry; - - if (!(entry = (struct cmd_list *)malloc(sizeof(struct cmd_list)))) { - DEBUG(0, ("out of memory\n")); - return; - } - - ZERO_STRUCTP(entry); - - entry->cmd_set = cmd_set; - DLIST_ADD(cmd_list, entry); -} - -static NTSTATUS do_cmd(struct samtest_state *st, struct cmd_set *cmd_entry, char *cmd) -{ - char *p = cmd, **argv = NULL; - NTSTATUS result = NT_STATUS_UNSUCCESSFUL; - TALLOC_CTX *mem_ctx = NULL; - pstring buf; - int argc = 0, i; - - /* Count number of arguments first time through the loop then - allocate memory and strdup them. */ - - again: - while(next_token(&p, buf, " ", sizeof(buf))) { - if (argv) { - argv[argc] = strdup(buf); - } - - argc++; - } - - if (!argv) { - - /* Create argument list */ - - argv = (char **)malloc(sizeof(char *) * argc); - memset(argv, 0, sizeof(char *) * argc); - - if (!argv) { - fprintf(stderr, "out of memory\n"); - result = NT_STATUS_NO_MEMORY; - goto done; - } - - p = cmd; - argc = 0; - - goto again; - } - - /* Call the function */ - - if (cmd_entry->fn) { - - if (mem_ctx == NULL) { - /* Create mem_ctx */ - if (!(mem_ctx = talloc_init("do_cmd"))) { - DEBUG(0, ("talloc_init() failed\n")); - goto done; - } - } - - /* Run command */ - result = cmd_entry->fn(st, mem_ctx, argc, argv); - - } else { - fprintf (stderr, "Invalid command\n"); - goto done; - } - - done: - - /* Cleanup */ - - if (argv) { - for (i = 0; i < argc; i++) - SAFE_FREE(argv[i]); - - SAFE_FREE(argv); - } - - return result; -} - -/* Process a command entered at the prompt or as part of -c */ -static NTSTATUS process_cmd(struct samtest_state *st, char *cmd) -{ - struct cmd_list *temp_list; - BOOL found = False; - pstring buf; - char *p = cmd; - NTSTATUS result = NT_STATUS_OK; - int len = 0; - - if (cmd[strlen(cmd) - 1] == '\n') - cmd[strlen(cmd) - 1] = '\0'; - - if (!next_token(&p, buf, " ", sizeof(buf))) { - return NT_STATUS_OK; - } - - /* strip the trainly \n if it exsists */ - len = strlen(buf); - if (buf[len-1] == '\n') - buf[len-1] = '\0'; - - /* Search for matching commands */ - - for (temp_list = cmd_list; temp_list; temp_list = temp_list->next) { - struct cmd_set *temp_set = temp_list->cmd_set; - - while(temp_set->name) { - if (strequal(buf, temp_set->name)) { - found = True; - result = do_cmd(st, temp_set, cmd); - - goto done; - } - temp_set++; - } - } - - done: - if (!found && buf[0]) { - printf("command not found: %s\n", buf); - return NT_STATUS_OK; - } - - if (!NT_STATUS_IS_OK(result)) { - printf("result was %s\n", nt_errstr(result)); - } - - return result; -} - -void exit_server(char *reason) -{ - DEBUG(3,("Server exit (%s)\n", (reason ? reason : ""))); - exit(0); -} - -static int server_fd = -1; -int last_message = -1; - -int smbd_server_fd(void) -{ - return server_fd; -} - -BOOL reload_services(BOOL test) -{ - return True; -} - -/* Main function */ - -int main(int argc, char *argv[]) -{ - BOOL interactive = True; - int opt; - static char *cmdstr = NULL; - struct cmd_set **cmd_set; - struct samtest_state st; - - /* make sure the vars that get altered (4th field) are in - a fixed location or certain compilers complain */ - poptContext pc; - struct poptOption long_options[] = { - POPT_AUTOHELP - {"command", 'e', POPT_ARG_STRING, &cmdstr, 'e', "Execute semicolon seperated cmds"}, - POPT_COMMON_SAMBA - POPT_TABLEEND - }; - - ZERO_STRUCT(st); - - st.token = get_system_token(); - - setlinebuf(stdout); - - DEBUGLEVEL = 1; - - pc = poptGetContext("samtest", argc, (const char **) argv, - long_options, 0); - - while((opt = poptGetNextOpt(pc)) != -1) { - switch (opt) { - case 'l': - slprintf(logfile, sizeof(logfile) - 1, "%s.client", - opt_logfile); - lp_set_logfile(logfile); - interactive = False; - break; - } - } - - if (!lp_load(config_file,True,False,False)) { - fprintf(stderr, "Can't load %s - run testparm to debug it\n", config_file); - exit(1); - } - - poptFreeContext(pc); - - /* the following functions are part of the Samba debugging - facilities. See lib/debug.c */ - setup_logging("samtest", interactive); - if (!interactive) - reopen_logs(); - - /* Load command lists */ - - cmd_set = samtest_command_list; - - while(*cmd_set) { - add_command_set(*cmd_set); - add_command_set(separator_command); - cmd_set++; - } - - /* Do anything specified with -c */ - if (cmdstr && cmdstr[0]) { - char *cmd; - char *p = cmdstr; - - while((cmd=next_command(&p)) != NULL) { - process_cmd(&st, cmd); - } - - return 0; - } - - /* Loop around accepting commands */ - - while(1) { - pstring prompt; - char *line; - - slprintf(prompt, sizeof(prompt) - 1, "samtest $> "); - - line = smb_readline(prompt, NULL, NULL); - - if (line == NULL) - break; - - if (line[0] != '\n') - process_cmd(&st, line); - } - - return 0; -} -- cgit From 7c6b4a1d18cf3b72569fe491b33be190f65c49a7 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Thu, 11 Sep 2003 07:31:39 +0000 Subject: Merge from samba-3.0: >Fix error message when calling namedtogid() fails adding a group map >entry. Bug #431. (This used to be commit 1befe1758351f43558808a3c91543752e7ff7823) --- source3/utils/net_groupmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3') diff --git a/source3/utils/net_groupmap.c b/source3/utils/net_groupmap.c index 9937145230..f99876bbd8 100644 --- a/source3/utils/net_groupmap.c +++ b/source3/utils/net_groupmap.c @@ -258,7 +258,7 @@ static int net_groupmap_add(int argc, const char **argv) } if ( (gid = nametogid(unixgrp)) == (gid_t)-1 ) { - d_printf("Can't lookup UNIX group %s\n", ntgroup); + d_printf("Can't lookup UNIX group %s\n", unixgrp); return -1; } -- cgit From 0788e30fe18901df92a497a9ceddb898cd3d07b9 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Thu, 11 Sep 2003 07:32:04 +0000 Subject: Merge from samba-3.0: >Formatting fixups for help output. (This used to be commit fe7c8e39688f0966563c67dd61a9ad8ae2b98f99) --- source3/utils/net_help.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3') diff --git a/source3/utils/net_help.c b/source3/utils/net_help.c index 95116a4d2a..c688beef72 100644 --- a/source3/utils/net_help.c +++ b/source3/utils/net_help.c @@ -42,10 +42,10 @@ int net_common_flags_usage(int argc, const char **argv) d_printf("Valid miscellaneous options are:\n"); /* misc options */ d_printf("\t-p or --port=\t\tconnection port on target\n"); d_printf("\t-W or --myworkgroup=\tclient workgroup\n"); - d_printf("\t-d or --debuglevel=\t\tdebug level (0-10)\n"); + d_printf("\t-d or --debuglevel=\tdebug level (0-10)\n"); d_printf("\t-n or --myname=\t\tclient name\n"); d_printf("\t-U or --user=\t\tuser name\n"); - d_printf("\t-s or --configfile=\t\tpathname of smb.conf file\n"); + d_printf("\t-s or --configfile=\tpathname of smb.conf file\n"); d_printf("\t-l or --long\t\t\tDisplay full information\n"); d_printf("\t-V or --version\t\t\tPrint samba version information\n"); d_printf("\t-P or --machine-pass\t\tAuthenticate as machine account\n"); -- cgit From 5cb04291390ccc369855449806778508d0c62ed9 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Thu, 11 Sep 2003 07:33:05 +0000 Subject: Merge from samba-3.0: >Revision 1.8.2.33 >Fix error return path memory leaks in vampire code for creating users. > >Display an error if we can't create a posix account for the user >(e.g no add user/machine script was specified; bug #323). >Revision 1.8.2.32: >Use opt_target_workgroup instead of lp_workgroup() in vampire code so >we can override the value in smb.conf with the -w option. > >Migrating accounts from another domain can now be done like: > ># bin/net join bdc -w nt4dom -Uadministrator%password ># bin/net rpc vampire -w nt4dom -U administrator%password (This used to be commit 36f7d88edd15bff1b7dfa78f3908dae272b96215) --- source3/utils/net_rpc_samsync.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'source3') diff --git a/source3/utils/net_rpc_samsync.c b/source3/utils/net_rpc_samsync.c index ed69f8a326..64f2d3f68f 100644 --- a/source3/utils/net_rpc_samsync.c +++ b/source3/utils/net_rpc_samsync.c @@ -428,9 +428,10 @@ static NTSTATUS fetch_account_info(uint32 rid, SAM_ACCOUNT_INFO *delta) (delta->acb_info & ACB_DOMTRUST) ) { pstrcpy(add_script, lp_addmachine_script()); } else { - *add_script = '\0'; DEBUG(1, ("Unknown user type: %s\n", smbpasswd_encode_acb_info(delta->acb_info))); + nt_ret = NT_STATUS_UNSUCCESSFUL; + goto done; } if (*add_script) { int add_ret; @@ -448,8 +449,11 @@ static NTSTATUS fetch_account_info(uint32 rid, SAM_ACCOUNT_INFO *delta) } /* try and find the possible unix account again */ - if ( !(passwd = Get_Pwnam(account)) ) - return NT_STATUS_NO_SUCH_USER; + if ( !(passwd = Get_Pwnam(account)) ) { + d_printf("Could not create posix account info for '%s'\n", account); + nt_ret = NT_STATUS_NO_SUCH_USER; + goto done; + } } @@ -499,6 +503,7 @@ static NTSTATUS fetch_account_info(uint32 rid, SAM_ACCOUNT_INFO *delta) pdb_get_username(sam_account))); } + done: pdb_free_sam(&sam_account); return nt_ret; } @@ -1034,7 +1039,7 @@ int rpc_vampire(int argc, const char **argv) goto fail; } - if (!secrets_fetch_trust_account_password(lp_workgroup(), + if (!secrets_fetch_trust_account_password(opt_target_workgroup, trust_password, NULL, &sec_channel)) { d_printf("Could not retrieve domain trust secret\n"); @@ -1056,7 +1061,7 @@ int rpc_vampire(int argc, const char **argv) nt_errstr(result)); if (NT_STATUS_EQUAL(result, NT_STATUS_NOT_SUPPORTED)) d_printf("Perhaps %s is a Windows 2000 native mode " - "domain?\n", lp_workgroup()); + "domain?\n", opt_target_workgroup); goto fail; } -- cgit From 95bfe31c1f4fda39195fcc2fea0648c277a0e49d Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Thu, 11 Sep 2003 07:34:44 +0000 Subject: Merge from samba-3.0: >Fix for bug #273 - smbd crash on machine account change. >Someone only half changed the code to use dc_name >instead of remote machine... Found via back trace from Dariush Forouher >. >Jeremy. (This used to be commit 1956478ddece5899ebdf627969136603e1c21637) --- source3/smbd/change_trust_pw.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) (limited to 'source3') diff --git a/source3/smbd/change_trust_pw.c b/source3/smbd/change_trust_pw.c index 80c9fcb258..1178400e4d 100644 --- a/source3/smbd/change_trust_pw.c +++ b/source3/smbd/change_trust_pw.c @@ -48,22 +48,20 @@ NTSTATUS change_trust_account_password( const char *domain, const char *remote_m if ( !name_status_find( domain, 0x1b, 0x20, pdc_ip, dc_name) ) goto failed; - } - /* supoport old deprecated "smbpasswd -j DOMAIN -r MACHINE" behavior */ - else { + } else { + /* supoport old deprecated "smbpasswd -j DOMAIN -r MACHINE" behavior */ fstrcpy( dc_name, remote_machine ); } /* if this next call fails, then give up. We can't do password changes on BDC's --jerry */ - if (!NT_STATUS_IS_OK(cli_full_connection(&cli, global_myname(), remote_machine, + if (!NT_STATUS_IS_OK(cli_full_connection(&cli, global_myname(), dc_name, NULL, 0, "IPC$", "IPC", "", "", - "", 0, Undefined, NULL))) - { - DEBUG(0,("modify_trust_password: Connection to %s failed!\n", remote_machine)); + "", 0, Undefined, NULL))) { + DEBUG(0,("modify_trust_password: Connection to %s failed!\n", dc_name)); nt_status = NT_STATUS_UNSUCCESSFUL; goto failed; } @@ -75,7 +73,7 @@ NTSTATUS change_trust_account_password( const char *domain, const char *remote_m if(cli_nt_session_open(cli, PI_NETLOGON) == False) { DEBUG(0,("modify_trust_password: unable to open the domain client session to machine %s. Error was : %s.\n", - remote_machine, cli_errstr(cli))); + dc_name, cli_errstr(cli))); cli_nt_session_close(cli); cli_ulogoff(cli); cli_shutdown(cli); @@ -83,8 +81,7 @@ NTSTATUS change_trust_account_password( const char *domain, const char *remote_m goto failed; } - nt_status = trust_pw_find_change_and_store_it(cli, cli->mem_ctx, - domain); + nt_status = trust_pw_find_change_and_store_it(cli, cli->mem_ctx, domain); cli_nt_session_close(cli); cli_ulogoff(cli); -- cgit From a0fb605c2519bd3a9e3730fcb372977a52c7d25b Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Fri, 12 Sep 2003 02:03:28 +0000 Subject: Fix another crash bug in samsync. (This used to be commit 675707c33e8447b9cb9fc2ae451663a56a14d792) --- source3/utils/net_rpc_samsync.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source3') diff --git a/source3/utils/net_rpc_samsync.c b/source3/utils/net_rpc_samsync.c index 64f2d3f68f..d1c8300a49 100644 --- a/source3/utils/net_rpc_samsync.c +++ b/source3/utils/net_rpc_samsync.c @@ -182,6 +182,9 @@ static void dump_database(struct cli_state *cli, unsigned db_type, DOM_CRED *ret result = cli_netlogon_sam_sync(cli, mem_ctx, ret_creds, db_type, sync_context, &num_deltas, &hdr_deltas, &deltas); + if (NT_STATUS_IS_ERR(result)) + break; + clnt_deal_with_creds(cli->sess_key, &(cli->clnt_cred), ret_creds); for (i = 0; i < num_deltas; i++) { display_sam_entry(&hdr_deltas[i], &deltas[i]); -- cgit From eae6e9f155c78a4f448c1a798f9d7d61f53a2795 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 15 Sep 2003 04:59:45 +0000 Subject: Merge from Samba 3.0: >Fix from Craig Barratt to fix restore >with filenames > 100 chars. >Jeremy. (This used to be commit a7bbfd636798232416c044df8a77dbbd8c77f9ed) --- source3/client/clitar.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'source3') diff --git a/source3/client/clitar.c b/source3/client/clitar.c index b01de5b8e7..f38d6fe91a 100644 --- a/source3/client/clitar.c +++ b/source3/client/clitar.c @@ -1054,9 +1054,11 @@ static int get_dir(file_info2 finfo) has the data. We only want the long file name, as the loop in do_tarput will deal with the rest. */ -static char * get_longfilename(file_info2 finfo) +static char *get_longfilename(file_info2 finfo) { - int namesize = strlen(finfo.name) + strlen(cur_dir) + 2; + /* finfo.size here is the length of the filename as written by the "/./@LongLink" name + * header call. */ + int namesize = finfo.size + strlen(cur_dir) + 2; char *longname = malloc(namesize); int offset = 0, left = finfo.size; BOOL first = True; -- cgit From a9cd4a6ae1709381f896605beb0c3e82c16b330e Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 15 Sep 2003 05:01:27 +0000 Subject: Merge from Samba 3.0: >For some reason testparm runs at debug level 2 which causes the module probe functions to >display verbose debugs. Increase the probe debugs to level 3. (This used to be commit be91bbd570bd94f67001aab9cfb2baf44b390097) --- source3/lib/module.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3') diff --git a/source3/lib/module.c b/source3/lib/module.c index e2c6f6dcf5..941a6cfbe3 100644 --- a/source3/lib/module.c +++ b/source3/lib/module.c @@ -41,7 +41,7 @@ static NTSTATUS do_smb_load_module(const char *module_name, BOOL is_probe) handle = sys_dlopen(module_name, RTLD_LAZY); if(!handle) { - int level = is_probe ? 2 : 0; + int level = is_probe ? 3 : 0; DEBUG(level, ("Error loading module '%s': %s\n", module_name, sys_dlerror())); -- cgit From d8231592bc4497fbec0a9ced20cd8cc84782bb9d Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 15 Sep 2003 05:02:12 +0000 Subject: Merge from Samba 3.0: >Fix for MacOS/X which uses STUPID BROKEN UNICODE COMPOSE CHARACTERS ! >(rant off :-). Inspired by work from Benjamin Riefenstahl . >Also add MacOSX/Darwin configure fixes. >Jerry - can we put this in 3.0 release ? :-). >Jeremy. (This used to be commit 67acde75d3569b612f87646ff0740f8020e8fdcf) --- source3/lib/charcnv.c | 79 +++++++++++++++++++++++++++++++++----------------- source3/lib/util_str.c | 14 +++++++-- 2 files changed, 65 insertions(+), 28 deletions(-) (limited to 'source3') diff --git a/source3/lib/charcnv.c b/source3/lib/charcnv.c index 5f3cf64a68..dafc88fb77 100644 --- a/source3/lib/charcnv.c +++ b/source3/lib/charcnv.c @@ -176,6 +176,14 @@ static size_t convert_string_internal(charset_t from, charset_t to, descriptor = conv_handles[from][to]; + if (srclen == (size_t)-1) { + if (from == CH_UCS2) { + srclen = (strlen_w((const smb_ucs2_t *)src)+1) * 2; + } else { + srclen = strlen((const char *)src)+1; + } + } + if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) { if (!conv_silent) DEBUG(0,("convert_string_internal: Conversion not supported.\n")); @@ -248,31 +256,40 @@ size_t convert_string(charset_t from, charset_t to, void const *src, size_t srclen, void *dest, size_t destlen) { + /* + * NB. We deliberately don't do a strlen here is srclen == -1. + * This is very expensive over millions of calls and is taken + * care of in the slow path in convert_string_internal. JRA. + */ + if (srclen == 0) return 0; if (from != CH_UCS2 && to != CH_UCS2) { const unsigned char *p = (const unsigned char *)src; unsigned char *q = (unsigned char *)dest; + size_t slen = srclen; + size_t dlen = destlen; unsigned char lastp; size_t retval = 0; /* If all characters are ascii, fast path here. */ - while (srclen && destlen) { + while (slen && dlen) { if ((lastp = *p) <= 0x7f) { *q++ = *p++; - if (srclen != (size_t)-1) { - srclen--; + if (slen != (size_t)-1) { + slen--; } - destlen--; + dlen--; retval++; if (!lastp) break; } else { - if (srclen == (size_t)-1) { - srclen = strlen(p)+1; - } - return retval + convert_string_internal(from, to, p, srclen, q, destlen); +#ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS + goto general_case; +#else + return retval + convert_string_internal(from, to, p, slen, q, dlen); +#endif } } return retval; @@ -280,25 +297,28 @@ size_t convert_string(charset_t from, charset_t to, const unsigned char *p = (const unsigned char *)src; unsigned char *q = (unsigned char *)dest; size_t retval = 0; + size_t slen = srclen; + size_t dlen = destlen; unsigned char lastp; /* If all characters are ascii, fast path here. */ - while ((srclen >= 2) && destlen) { - if ((lastp = *p) <= 0x7f && p[1] == 0) { + while ((slen >= 2) && dlen) { + if (((lastp = *p) <= 0x7f) && (p[1] == 0)) { *q++ = *p; - if (srclen != (size_t)-1) { - srclen -= 2; + if (slen != (size_t)-1) { + slen -= 2; } p += 2; - destlen--; + dlen--; retval++; if (!lastp) break; } else { - if (srclen == (size_t)-1) { - srclen = strlen_w((const void *)p)+2; - } - return retval + convert_string_internal(from, to, p, srclen, q, destlen); +#ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS + goto general_case; +#else + return retval + convert_string_internal(from, to, p, slen, q, dlen); +#endif } } return retval; @@ -306,29 +326,36 @@ size_t convert_string(charset_t from, charset_t to, const unsigned char *p = (const unsigned char *)src; unsigned char *q = (unsigned char *)dest; size_t retval = 0; + size_t slen = srclen; + size_t dlen = destlen; unsigned char lastp; /* If all characters are ascii, fast path here. */ - while (srclen && (destlen >= 2)) { + while (slen && (dlen >= 2)) { if ((lastp = *p) <= 0x7F) { *q++ = *p++; *q++ = '\0'; - if (srclen != (size_t)-1) { - srclen--; + if (slen != (size_t)-1) { + slen--; } - destlen -= 2; + dlen -= 2; retval += 2; if (!lastp) break; } else { - if (srclen == (size_t)-1) { - srclen = strlen(p)+1; - } - return retval + convert_string_internal(from, to, p, srclen, q, destlen); +#ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS + goto general_case; +#else + return retval + convert_string_internal(from, to, p, slen, q, dlen); +#endif } } return retval; } + +#ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS + general_case: +#endif return convert_string_internal(from, to, src, srclen, dest, destlen); } @@ -542,7 +569,7 @@ char *strdup_upper(const char *s) strupper_w(buffer); - size = convert_string(CH_UCS2, CH_UNIX, buffer, sizeof(buffer), out_buffer, sizeof(out_buffer)); + size = convert_string(CH_UCS2, CH_UNIX, buffer, -1, out_buffer, sizeof(out_buffer)); if (size == -1) { return NULL; } diff --git a/source3/lib/util_str.c b/source3/lib/util_str.c index 82b312e241..15ac1639a9 100644 --- a/source3/lib/util_str.c +++ b/source3/lib/util_str.c @@ -382,6 +382,10 @@ void string_replace(pstring s,char oldc,char newc) return; /* Slow (mb) path. */ +#ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS + /* With compose characters we must restart from the beginning. JRA. */ + p = s; +#endif push_ucs2(NULL, tmpbuf, p, sizeof(tmpbuf), STR_TERMINATE); string_replace_w(tmpbuf, UCS2_CHAR(oldc), UCS2_CHAR(newc)); pull_ucs2(NULL, p, tmpbuf, -1, sizeof(tmpbuf), STR_TERMINATE); @@ -1175,18 +1179,19 @@ char *string_truncate(char *s, unsigned int length) We convert via ucs2 for now. **/ -char *strchr_m(const char *s, char c) +char *strchr_m(const char *src, char c) { wpstring ws; pstring s2; smb_ucs2_t *p; + const char *s; /* this is quite a common operation, so we want it to be fast. We optimise for the ascii case, knowing that all our supported multi-byte character sets are ascii-compatible (ie. they match for the first 128 chars) */ - while (*s && (((unsigned char)s[0]) & 0x80)) { + for (s = src; *s && !(((unsigned char)s[0]) & 0x80); s++) { if (*s == c) return s; } @@ -1194,6 +1199,11 @@ char *strchr_m(const char *s, char c) if (!*s) return NULL; +#ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS + /* With compose characters we must restart from the beginning. JRA. */ + s = src; +#endif + push_ucs2(NULL, ws, s, sizeof(ws), STR_TERMINATE); p = strchr_w(ws, UCS2_CHAR(c)); if (!p) -- cgit From b584f74bd7fdc6a353b38d9e2e6e69fee1096fb4 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 15 Sep 2003 05:03:11 +0000 Subject: Merge from Samba 3.0: >Fix a nasty mess, and also bug #296. passdb/pdb_ldap.c was not converting >to/from utf8 for some calls. The libads code gets this right. Wonder why >the passdb code doesn't use it ? >Jeremy. (This used to be commit 258c106e2243f19c77fe35edd6dcba816a8fc8ee) --- source3/libads/ldap.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'source3') diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c index e925750e0a..48401cc3d8 100644 --- a/source3/libads/ldap.c +++ b/source3/libads/ldap.c @@ -709,7 +709,16 @@ char *ads_get_dn(ADS_STRUCT *ads, void *msg) utf8_dn = ldap_get_dn(ads->ld, msg); - pull_utf8_allocate((void **) &unix_dn, utf8_dn); + if (!utf8_dn) { + DEBUG (5, ("ads_get_dn: ldap_get_dn failed\n")); + return NULL; + } + + if (pull_utf8_allocate((void **) &unix_dn, utf8_dn) == (size_t)-1) { + DEBUG(0,("ads_get_dn: string conversion failure utf8 [%s]\n", + utf8_dn )); + return NULL; + } ldap_memfree(utf8_dn); return unix_dn; } -- cgit From aafb99dc8f14e061ca538c6f9822ba5b8253d40b Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 15 Sep 2003 05:19:07 +0000 Subject: Merge from Samba 3.0: >Still on my mb rampage. Ensure smbldap_make_mod() correctly detects old >values. >Jeremy. (This used to be commit 9df18a6c4ea30545297f9e5a0b10b440e6a0687e) --- source3/lib/smbldap.c | 48 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 15 deletions(-) (limited to 'source3') diff --git a/source3/lib/smbldap.c b/source3/lib/smbldap.c index 1ce03491da..781e6b976c 100644 --- a/source3/lib/smbldap.c +++ b/source3/lib/smbldap.c @@ -282,8 +282,9 @@ BOOL fetch_ldap_pw(char **dn, char** pw) } /******************************************************************* -search an attribute and return the first value found. + Search an attribute and return the first value found. ******************************************************************/ + BOOL smbldap_get_single_attribute (LDAP * ldap_struct, LDAPMessage * entry, const char *attribute, pstring value) { @@ -300,8 +301,7 @@ search an attribute and return the first value found. return False; } - if (convert_string(CH_UTF8, CH_UNIX,values[0], -1, value, sizeof(pstring)) == (size_t)-1) - { + if (convert_string(CH_UTF8, CH_UNIX,values[0], -1, value, sizeof(pstring)) == (size_t)-1) { DEBUG(1, ("smbldap_get_single_attribute: string conversion of [%s] = [%s] failed!\n", attribute, values[0])); ldap_value_free(values); @@ -402,32 +402,32 @@ search an attribute and return the first value found. *modlist = mods; } - /********************************************************************** Set attribute to newval in LDAP, regardless of what value the attribute had in LDAP before. *********************************************************************/ + void smbldap_make_mod(LDAP *ldap_struct, LDAPMessage *existing, LDAPMod ***mods, const char *attribute, const char *newval) { - char **values = NULL; + pstring oldval; + BOOL existed; if (existing != NULL) { - values = ldap_get_values(ldap_struct, existing, attribute); + existed = smbldap_get_single_attribute(ldap_struct, existing, attribute, oldval); + } else { + existed = False; + *oldval = '\0'; } /* all of our string attributes are case insensitive */ - if ((values != NULL) && (values[0] != NULL) && - StrCaseCmp(values[0], newval) == 0) - { + if (existed && (StrCaseCmp(oldval, newval) == 0)) { /* Believe it or not, but LDAP will deny a delete and an add at the same time if the values are the same... */ - - ldap_value_free(values); return; } @@ -439,7 +439,7 @@ search an attribute and return the first value found. smbldap_set_mod(mods, LDAP_MOD_ADD, attribute, newval); } - if (values == NULL) { + if (!existed) { /* There has been no value before, so don't delete it. Here's a possible race: We might end up with duplicate attributes */ @@ -451,11 +451,9 @@ search an attribute and return the first value found. deny the complete operation if somebody changed the attribute behind our back. */ - smbldap_set_mod(mods, LDAP_MOD_DELETE, attribute, values[0]); - ldap_value_free(values); + smbldap_set_mod(mods, LDAP_MOD_DELETE, attribute, oldval); } - /********************************************************************** Some varients of the LDAP rebind code do not pass in the third 'arg' pointer to a void*, so we try and work around it by assuming that the @@ -1329,3 +1327,23 @@ NTSTATUS smbldap_search_domain_info(struct smbldap_state *ldap_state, return ret; } +/******************************************************************* + Return a copy of the DN for a LDAPMessage. Convert from utf8 to CH_UNIX. +********************************************************************/ + +char *smbldap_get_dn(LDAP *ld, LDAPMessage *entry) +{ + char *utf8_dn, *unix_dn; + + utf8_dn = ldap_get_dn(ld, entry); + if (!utf8_dn) { + DEBUG (5, ("smbldap_get_dn: ldap_get_dn failed\n")); + return NULL; + } + if (pull_utf8_allocate((void **) &unix_dn, utf8_dn) == (size_t)-1) { + DEBUG (0, ("smbldap_get_dn: String conversion failure utf8 [%s]\n", utf8_dn)); + return NULL; + } + ldap_memfree(utf8_dn); + return unix_dn; +} -- cgit From ac4ae84d0848fde76887239b47a5deb5bbf76b21 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 15 Sep 2003 05:25:49 +0000 Subject: Merge from Samba 3.0: >Patch from Gregory Hinton Nietsky , >ensure the desired access is read from the incoming RPC request. >Jeremy. (This used to be commit a556637d0bc56aeb980c422c4d1da44311956c3b) --- source3/rpc_server/srv_samr_nt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3') diff --git a/source3/rpc_server/srv_samr_nt.c b/source3/rpc_server/srv_samr_nt.c index 7f7b5e8d5e..261d641ab1 100644 --- a/source3/rpc_server/srv_samr_nt.c +++ b/source3/rpc_server/srv_samr_nt.c @@ -4236,7 +4236,7 @@ NTSTATUS _samr_open_group(pipes_struct *p, SAMR_Q_OPEN_GROUP *q_u, SAMR_R_OPEN_G struct samr_info *info; SEC_DESC *psd = NULL; uint32 acc_granted; - uint32 des_access; + uint32 des_access = q_u->access_mask; size_t sd_size; NTSTATUS status; fstring sid_string; -- cgit From 4d0d68191173aae351f12dc5805856980dcbfeb7 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 15 Sep 2003 05:26:44 +0000 Subject: Merge from Samba 3.0: >Fix for typo in darwin detection. >Jeremy. >Fix for MacOS/X which uses STUPID BROKEN UNICODE COMPOSE CHARACTERS ! >(rant off :-). Inspired by work from Benjamin Riefenstahl . >Also add MacOSX/Darwin configure fixes. >Jerry - can we put this in 3.0 release ? :-). >Jeremy. (This used to be commit 7951dee600146623ce473659c3f41963ea873e3e) --- source3/configure.in | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) (limited to 'source3') diff --git a/source3/configure.in b/source3/configure.in index a2e04b5d48..0cf34bc9a7 100644 --- a/source3/configure.in +++ b/source3/configure.in @@ -402,7 +402,6 @@ case "$host_os" in *freebsd*) AC_DEFINE(FREEBSD, 1, [Whether the host os is FreeBSD]) ;; - # # VOS may need to have POSIX support and System V compatibility enabled. # @@ -503,6 +502,26 @@ main() { AC_MSG_RESULT([$LINUX_LFS_SUPPORT]) ;; +# +# MacOS X is the *only* system that uses compose character in utf8. This +# is so horribly broken.... +# + *darwin*) + AC_DEFINE(BROKEN_UNICODE_COMPOSE_CHARACTERS, 1, [Does this system use unicode compose characters]) +# Add Fink directories for various packages, like dlcompat. +# Note: iconv does that explicitly below, but other packages +# don't. + CPPFLAGS="$CPPFLAGS -I/sw/include" + LDFLAGS="$LDFLAGS -L/sw/lib" + +# If we have dlsym_prepend_underscore (from Fink's dlcompat), +# use that instead of plain dlsym. + + AC_CHECK_LIB(dl,dlopen) + AC_CHECK_FUNCS(dlsym_prepend_underscore, + [CPPFLAGS="$CPPFLAGS -Ddlsym=dlsym_prepend_underscore"]) + + ;; *hurd*) AC_MSG_CHECKING([for LFS support]) old_CPPFLAGS="$CPPFLAGS" @@ -1162,6 +1181,14 @@ if test "$enable_shared" = "yes"; then BLDSHARED="false" LDSHFLAGS="" ;; + + *darwin*) AC_DEFINE(DARWINOS,1,[Whether the host os is Darwin/MacOSX]) + BLDSHARED="true" + LDSHFLAGS="-bundle -flat_namespace -undefined suppress" + SHLIBEXT="dylib" + AC_DEFINE(STAT_ST_BLOCKSIZE,512) + ;; + *) AC_DEFINE(STAT_ST_BLOCKSIZE,512) ;; -- cgit From d26084868ac3088b7709889db9bd988c2e8a95ff Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 15 Sep 2003 05:27:55 +0000 Subject: Merge from Samba 3.0: >fix unitiailized timestamp where merging print_jobs and lpq listing (This used to be commit 1603d0e6848a8ec3f7d8a8f735c9d1a6d92aac0b) --- source3/printing/printing.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3') diff --git a/source3/printing/printing.c b/source3/printing/printing.c index 1a7066f906..1a878afb92 100644 --- a/source3/printing/printing.c +++ b/source3/printing/printing.c @@ -2184,6 +2184,7 @@ static BOOL get_stored_queue_info(struct tdb_print_db *pdb, int snum, int *pcoun queue[total_count].page_count = pjob->page_count; queue[total_count].status = pjob->status; queue[total_count].priority = 1; + queue[total_count].time = pjob->starttime; fstrcpy(queue[total_count].fs_user, pjob->user); fstrcpy(queue[total_count].fs_file, pjob->jobname); total_count++; -- cgit From 1d38ffec7a64d84bbfadd17d93a75cf2cd6451b5 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 15 Sep 2003 05:28:51 +0000 Subject: Merge from Samba 3.0: >Ensure we consistantly translate to/from utf8 for talking to LDAP. >Jeremy. (This used to be commit 5b0753bd98ffef5133da31f1c47a45e794d0bb72) --- source3/sam/idmap_ldap.c | 64 +++++++++++++++++++++++------------------------- 1 file changed, 31 insertions(+), 33 deletions(-) (limited to 'source3') diff --git a/source3/sam/idmap_ldap.c b/source3/sam/idmap_ldap.c index 6122641718..72fcb47b03 100644 --- a/source3/sam/idmap_ldap.c +++ b/source3/sam/idmap_ldap.c @@ -104,6 +104,7 @@ static BOOL sid_in_use(struct ldap_idmap_state *state, This also checks that this RID is actually free - in case the admin manually stole it :-). *********************************************************************/ + static NTSTATUS ldap_next_rid(struct ldap_idmap_state *state, uint32 *rid, int rid_type) { @@ -121,11 +122,9 @@ static NTSTATUS ldap_next_rid(struct ldap_idmap_state *state, uint32 *rid, int attempts = 0; char *ld_error = NULL; - while (attempts < 10) - { + while (attempts < 10) { if (!NT_STATUS_IS_OK(ret = smbldap_search_domain_info(state->smbldap_state, - &domain_result, get_global_sam_name(), True))) - { + &domain_result, get_global_sam_name(), True))) { return ret; } @@ -136,7 +135,7 @@ static NTSTATUS ldap_next_rid(struct ldap_idmap_state *state, uint32 *rid, return ret; } - if ((dn = ldap_get_dn(state->smbldap_state->ldap_struct, entry)) == NULL) { + if ((dn = smbldap_get_dn(state->smbldap_state->ldap_struct, entry)) == NULL) { DEBUG(0, ("Could not get domain info DN\n")); ldap_msgfree(domain_result); return ret; @@ -148,8 +147,7 @@ static NTSTATUS ldap_next_rid(struct ldap_idmap_state *state, uint32 *rid, if (smbldap_get_single_attribute(state->smbldap_state->ldap_struct, entry, get_attr_key2string(dominfo_attr_list, LDAP_ATTR_ALGORITHMIC_RID_BASE), - algorithmic_rid_base_string)) - { + algorithmic_rid_base_string)) { alg_rid_base = (uint32)atol(algorithmic_rid_base_string); } else { @@ -169,8 +167,7 @@ static NTSTATUS ldap_next_rid(struct ldap_idmap_state *state, uint32 *rid, can allocate to new users */ if (smbldap_get_single_attribute(state->smbldap_state->ldap_struct, entry, get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_RID), - old_rid_string)) - { + old_rid_string)) { *rid = (uint32)atol(old_rid_string); } else { *rid = BASE_RID; @@ -195,16 +192,14 @@ static NTSTATUS ldap_next_rid(struct ldap_idmap_state *state, uint32 *rid, case USER_RID_TYPE: if (smbldap_get_single_attribute(state->smbldap_state->ldap_struct, entry, get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_USERRID), - old_rid_string)) - { + old_rid_string)) { *rid = (uint32)atol(old_rid_string); } break; case GROUP_RID_TYPE: if (smbldap_get_single_attribute(state->smbldap_state->ldap_struct, entry, get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_GROUPRID), - old_rid_string)) - { + old_rid_string)) { *rid = (uint32)atol(old_rid_string); } break; @@ -236,32 +231,31 @@ static NTSTATUS ldap_next_rid(struct ldap_idmap_state *state, uint32 *rid, } } - if ((rc = ldap_modify_s(state->smbldap_state->ldap_struct, dn, mods)) == LDAP_SUCCESS) { + if ((rc = smbldap_modify(state->smbldap_state, dn, mods)) == LDAP_SUCCESS) { DOM_SID dom_sid; DOM_SID sid; pstring domain_sid_string; int error = 0; if (!smbldap_get_single_attribute(state->smbldap_state->ldap_struct, domain_result, - get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOM_SID), - domain_sid_string)) - { + get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOM_SID), + domain_sid_string)) { ldap_mods_free(mods, True); - ldap_memfree(dn); + SAFE_FREE(dn); ldap_msgfree(domain_result); return ret; } if (!string_to_sid(&dom_sid, domain_sid_string)) { ldap_mods_free(mods, True); - ldap_memfree(dn); + SAFE_FREE(dn); ldap_msgfree(domain_result); return ret; } ldap_mods_free(mods, True); mods = NULL; - ldap_memfree(dn); + SAFE_FREE(dn); ldap_msgfree(domain_result); sid_copy(&sid, &dom_sid); @@ -286,8 +280,7 @@ static NTSTATUS ldap_next_rid(struct ldap_idmap_state *state, uint32 *rid, ldap_mods_free(mods, True); mods = NULL; - ldap_memfree(dn); - dn = NULL; + SAFE_FREE(dn); ldap_msgfree(domain_result); domain_result = NULL; @@ -361,7 +354,10 @@ static NTSTATUS ldap_allocate_id(unid_t *id, int id_type) goto out; } - dn = ldap_get_dn(ldap_state.smbldap_state->ldap_struct, result); + dn = smbldap_get_dn(ldap_state.smbldap_state->ldap_struct, result); + if (!dn) { + goto out; + } entry = ldap_first_entry(ldap_state.smbldap_state->ldap_struct, result); if (!smbldap_get_single_attribute(ldap_state.smbldap_state->ldap_struct, entry, type, id_str)) { @@ -401,9 +397,9 @@ static NTSTATUS ldap_allocate_id(unid_t *id, int id_type) smbldap_set_mod( &mods, LDAP_MOD_DELETE, type, id_str ); smbldap_set_mod( &mods, LDAP_MOD_ADD, type, new_id_str ); - rc = ldap_modify_s(ldap_state.smbldap_state->ldap_struct, dn, mods); + rc = smbldap_modify(ldap_state.smbldap_state, dn, mods); - ldap_memfree(dn); + SAFE_FREE(dn); ldap_mods_free( mods, True ); if (rc != LDAP_SUCCESS) { @@ -663,12 +659,13 @@ static NTSTATUS ldap_get_id_from_sid(unid_t *id, int *id_type, const DOM_SID *si entry = ldap_first_entry(ldap_state.smbldap_state->ldap_struct, result); - dn = ldap_get_dn(ldap_state.smbldap_state->ldap_struct, result); + dn = smbldap_get_dn(ldap_state.smbldap_state->ldap_struct, result); + if (!dn) + goto out; DEBUG(10, ("Found mapping entry at dn=%s, looking for %s\n", dn, type)); - if ( smbldap_get_single_attribute(ldap_state.smbldap_state->ldap_struct, entry, type, id_str) ) - { + if ( smbldap_get_single_attribute(ldap_state.smbldap_state->ldap_struct, entry, type, id_str) ) { if ( (*id_type & ID_USERID) ) id->uid = strtoul(id_str, NULL, 10); else @@ -682,8 +679,7 @@ out: free_attr_list( attr_list ); if (result) ldap_msgfree(result); - if (dn) - ldap_memfree(dn); + SAFE_FREE(dn); return ret; } @@ -864,7 +860,9 @@ static NTSTATUS ldap_set_mapping(const DOM_SID *sid, unid_t id, int id_type) if (count == 1) { entry = ldap_first_entry(ldap_state.smbldap_state->ldap_struct, result); - dn = ldap_get_dn(ldap_state.smbldap_state->ldap_struct, result); + dn = smbldap_get_dn(ldap_state.smbldap_state->ldap_struct, result); + if (!dn) + goto out; DEBUG(10, ("Found partial mapping entry at dn=%s, looking for %s\n", dn, type)); ret = ldap_set_mapping_internals(sid, id, id_type, dn, entry); @@ -880,8 +878,7 @@ static NTSTATUS ldap_set_mapping(const DOM_SID *sid, unid_t id, int id_type) out: if (result) ldap_msgfree(result); - if (dn) - ldap_memfree(dn); + SAFE_FREE(dn); return ret; } @@ -945,6 +942,7 @@ static NTSTATUS verify_idpool( void ) /***************************************************************************** Initialise idmap database. *****************************************************************************/ + static NTSTATUS ldap_idmap_init( char *params ) { NTSTATUS nt_status; -- cgit From 5b5ed5a6dcc07b979f4386636a5430bfac39ad2a Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 15 Sep 2003 05:30:52 +0000 Subject: Merge from Samba 3.0: >remove getpwnam() calls from init_sam_from_xxx(). >This means that %u & %g will no longer expand, but %U >and %G still do. The payback is that winbindd local >accounts for users work with 'wbinfo -u' when winbind >is running on a PDC. (This used to be commit f047e24561688c697179b14549b1800e00b2a435) --- source3/passdb/passdb.c | 37 ++++++++----------------------------- 1 file changed, 8 insertions(+), 29 deletions(-) (limited to 'source3') diff --git a/source3/passdb/passdb.c b/source3/passdb/passdb.c index 76745be3f0..1dadee8a49 100644 --- a/source3/passdb/passdb.c +++ b/source3/passdb/passdb.c @@ -1311,9 +1311,6 @@ BOOL init_sam_from_buffer(SAM_ACCOUNT *sampass, uint8 *buf, uint32 buflen) uint32 len = 0; uint32 lm_pw_len, nt_pw_len, hourslen; BOOL ret = True; - uid_t uid = -1; - gid_t gid = -1; - struct passwd *pw = NULL; if(sampass == NULL || buf == NULL) { DEBUG(0, ("init_sam_from_buffer: NULL parameters found!\n")); @@ -1369,55 +1366,37 @@ BOOL init_sam_from_buffer(SAM_ACCOUNT *sampass, uint8 *buf, uint32 buflen) pdb_set_nt_username(sampass, nt_username, PDB_SET); pdb_set_fullname(sampass, fullname, PDB_SET); - - if ( (pw=Get_Pwnam(username)) != NULL ) { - uid = pw->pw_uid; - gid = pw->pw_gid; - } - if (homedir) { pdb_set_homedir(sampass, homedir, PDB_SET); } else { pdb_set_homedir(sampass, - talloc_sub_specified(sampass->mem_ctx, - lp_logon_home(), - username, domain, - uid, gid), - PDB_DEFAULT); + talloc_sub_basic(sampass->mem_ctx, username, lp_logon_home()), + PDB_DEFAULT); } if (dir_drive) pdb_set_dir_drive(sampass, dir_drive, PDB_SET); else { pdb_set_dir_drive(sampass, - talloc_sub_specified(sampass->mem_ctx, - lp_logon_drive(), - username, domain, - uid, gid), - PDB_DEFAULT); + talloc_sub_basic(sampass->mem_ctx, username, lp_logon_drive()), + PDB_DEFAULT); } if (logon_script) pdb_set_logon_script(sampass, logon_script, PDB_SET); else { pdb_set_logon_script(sampass, - talloc_sub_specified(sampass->mem_ctx, - lp_logon_script(), - username, domain, - uid, gid), - PDB_DEFAULT); + talloc_sub_basic(sampass->mem_ctx, username, lp_logon_script()), + PDB_DEFAULT); } if (profile_path) { pdb_set_profile_path(sampass, profile_path, PDB_SET); } else { pdb_set_profile_path(sampass, - talloc_sub_specified(sampass->mem_ctx, - lp_logon_path(), - username, domain, - uid, gid), - PDB_DEFAULT); + talloc_sub_basic(sampass->mem_ctx, username, lp_logon_path()), + PDB_DEFAULT); } pdb_set_acct_desc(sampass, acct_desc, PDB_SET); -- cgit From ca3d5310ce1ae62a8d169b68416096fca67a5f62 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 15 Sep 2003 05:33:34 +0000 Subject: Merge from Samba 3.0: >remove getpwnam() calls from init_sam_from_xxx(). >This means that %u & %g will no longer expand, but %U >and %G still do. The payback is that winbindd local >accounts for users work with 'wbinfo -u' when winbind >is running on a PDC. >Fix a nasty mess, and also bug #296. passdb/pdb_ldap.c was not converting >to/from utf8 for some calls. The libads code gets this right. Wonder why >the passdb code doesn't use it ? >Jeremy. (This used to be commit 1e60bbff70efe3b5c306bc1ef560ee8032b1a852) --- source3/passdb/pdb_ldap.c | 493 +++++++++++++++++++++------------------------- 1 file changed, 226 insertions(+), 267 deletions(-) (limited to 'source3') diff --git a/source3/passdb/pdb_ldap.c b/source3/passdb/pdb_ldap.c index 009425c5f6..e00631fb7d 100644 --- a/source3/passdb/pdb_ldap.c +++ b/source3/passdb/pdb_ldap.c @@ -99,7 +99,7 @@ struct ldapsam_privates { }; /********************************************************************** - Free a LDAPMessage (one is stored on the SAM_ACCOUNT) + Free a LDAPMessage (one is stored on the SAM_ACCOUNT). **********************************************************************/ static void private_data_free_fn(void **result) @@ -109,13 +109,12 @@ static void private_data_free_fn(void **result) } /********************************************************************** - get the attribute name given a user schame version + Get the attribute name given a user schame version. **********************************************************************/ static const char* get_userattr_key2string( int schema_ver, int key ) { - switch ( schema_ver ) - { + switch ( schema_ver ) { case SCHEMAVER_SAMBAACCOUNT: return get_attr_key2string( attrib_map_v22, key ); @@ -130,13 +129,12 @@ static const char* get_userattr_key2string( int schema_ver, int key ) } /********************************************************************** - return the list of attribute names given a user schema version - **********************************************************************/ + Return the list of attribute names given a user schema version. +**********************************************************************/ static char** get_userattr_list( int schema_ver ) { - switch ( schema_ver ) - { + switch ( schema_ver ) { case SCHEMAVER_SAMBAACCOUNT: return get_attr_list( attrib_map_v22 ); @@ -149,17 +147,17 @@ static char** get_userattr_list( int schema_ver ) return NULL; } + /******************************************************************* - generate the LDAP search filter for the objectclass based on the - version of the schema we are using - ******************************************************************/ + Generate the LDAP search filter for the objectclass based on the + version of the schema we are using. +******************************************************************/ static const char* get_objclass_filter( int schema_ver ) { static fstring objclass_filter; - switch( schema_ver ) - { + switch( schema_ver ) { case SCHEMAVER_SAMBAACCOUNT: fstr_sprintf( objclass_filter, "(objectclass=%s)", LDAP_OBJ_SAMBAACCOUNT ); break; @@ -167,7 +165,7 @@ static const char* get_objclass_filter( int schema_ver ) fstr_sprintf( objclass_filter, "(objectclass=%s)", LDAP_OBJ_SAMBASAMACCOUNT ); break; default: - DEBUG(0,("pdb_ldapsam: get_objclass_filter(): Invalid schema version specified!\n")); + DEBUG(0,("get_objclass_filter: Invalid schema version specified!\n")); break; } @@ -175,8 +173,9 @@ static const char* get_objclass_filter( int schema_ver ) } /******************************************************************* - run the search by name. + Run the search by name. ******************************************************************/ + static int ldapsam_search_suffix_by_name (struct ldapsam_privates *ldap_state, const char *user, LDAPMessage ** result, char **attr) @@ -208,8 +207,9 @@ static int ldapsam_search_suffix_by_name (struct ldapsam_privates *ldap_state, } /******************************************************************* - run the search by rid. + Run the search by rid. ******************************************************************/ + static int ldapsam_search_suffix_by_rid (struct ldapsam_privates *ldap_state, uint32 rid, LDAPMessage ** result, char **attr) @@ -226,8 +226,9 @@ static int ldapsam_search_suffix_by_rid (struct ldapsam_privates *ldap_state, } /******************************************************************* - run the search by SID. + Run the search by SID. ******************************************************************/ + static int ldapsam_search_suffix_by_sid (struct ldapsam_privates *ldap_state, const DOM_SID *sid, LDAPMessage ** result, char **attr) @@ -250,6 +251,7 @@ static int ldapsam_search_suffix_by_sid (struct ldapsam_privates *ldap_state, Delete complete object or objectclass and attrs from object found in search_result depending on lp_ldap_delete_dn ******************************************************************/ + static NTSTATUS ldapsam_delete_entry(struct ldapsam_privates *ldap_state, LDAPMessage *result, const char *objectclass, @@ -264,22 +266,25 @@ static NTSTATUS ldapsam_delete_entry(struct ldapsam_privates *ldap_state, rc = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result); if (rc != 1) { - DEBUG(0, ("Entry must exist exactly once!\n")); + DEBUG(0, ("ldapsam_delete_entry: Entry must exist exactly once!\n")); return NT_STATUS_UNSUCCESSFUL; } entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result); - dn = ldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry); + dn = smbldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry); + if (!dn) { + return NT_STATUS_UNSUCCESSFUL; + } if (lp_ldap_delete_dn()) { NTSTATUS ret = NT_STATUS_OK; rc = smbldap_delete(ldap_state->smbldap_state, dn); if (rc != LDAP_SUCCESS) { - DEBUG(0, ("Could not delete object %s\n", dn)); + DEBUG(0, ("ldapsam_delete_entry: Could not delete object %s\n", dn)); ret = NT_STATUS_UNSUCCESSFUL; } - ldap_memfree(dn); + SAFE_FREE(dn); return ret; } @@ -287,17 +292,15 @@ static NTSTATUS ldapsam_delete_entry(struct ldapsam_privates *ldap_state, for (name = ldap_first_attribute(ldap_state->smbldap_state->ldap_struct, entry, &ptr); name != NULL; - name = ldap_next_attribute(ldap_state->smbldap_state->ldap_struct, entry, ptr)) - { + name = ldap_next_attribute(ldap_state->smbldap_state->ldap_struct, entry, ptr)) { char **attrib; /* We are only allowed to delete the attributes that really exist. */ - for (attrib = attrs; *attrib != NULL; attrib++) - { + for (attrib = attrs; *attrib != NULL; attrib++) { if (StrCaseCmp(*attrib, name) == 0) { - DEBUG(10, ("deleting attribute %s\n", name)); + DEBUG(10, ("ldapsam_delete_entry: deleting attribute %s\n", name)); smbldap_set_mod(&mods, LDAP_MOD_DELETE, name, NULL); } } @@ -319,18 +322,17 @@ static NTSTATUS ldapsam_delete_entry(struct ldapsam_privates *ldap_state, ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error); - DEBUG(0, ("could not delete attributes for %s, error: %s (%s)\n", + DEBUG(0, ("ldapsam_delete_entry: Could not delete attributes for %s, error: %s (%s)\n", dn, ldap_err2string(rc), ld_error?ld_error:"unknown")); SAFE_FREE(ld_error); - ldap_memfree(dn); + SAFE_FREE(dn); return NT_STATUS_UNSUCCESSFUL; } - ldap_memfree(dn); + SAFE_FREE(dn); return NT_STATUS_OK; } - /* New Interface is being implemented here */ #if 0 /* JERRY - not uesed anymore */ @@ -390,9 +392,10 @@ static BOOL get_unix_attributes (struct ldapsam_privates *ldap_state, #endif /********************************************************************** -Initialize SAM_ACCOUNT from an LDAP query -(Based on init_sam_from_buffer in pdb_tdb.c) + Initialize SAM_ACCOUNT from an LDAP query. + (Based on init_sam_from_buffer in pdb_tdb.c) *********************************************************************/ + static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, SAM_ACCOUNT * sampass, LDAPMessage * entry) @@ -422,9 +425,6 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, uint32 hours_len; uint8 hours[MAX_HOURS_LEN]; pstring temp; - struct passwd *pw = NULL; - uid_t uid = -1; - gid_t gid = -1; /* * do a little initialization @@ -453,19 +453,11 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, } if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, "uid", username)) { - DEBUG(1, ("No uid attribute found for this user!\n")); + DEBUG(1, ("init_sam_from_ldap: No uid attribute found for this user!\n")); return False; } - DEBUG(2, ("Entry found for user: %s\n", username)); - - /* I'm not going to fail here, since there are checks - higher up the cal stack to do this --jerry */ - - if ( (pw=Get_Pwnam(username)) != NULL ) { - uid = pw->pw_uid; - gid = pw->pw_gid; - } + DEBUG(2, ("init_sam_from_ldap: Entry found for user: %s\n", username)); pstrcpy(nt_username, username); @@ -478,38 +470,27 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, /* deal with different attributes between the schema first */ - if ( ldap_state->schema_ver == SCHEMAVER_SAMBASAMACCOUNT ) - { + if ( ldap_state->schema_ver == SCHEMAVER_SAMBASAMACCOUNT ) { if (smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, - get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID), temp)) - { + get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID), temp)) { pdb_set_user_sid_from_string(sampass, temp, PDB_SET); } if (smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, - get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PRIMARY_GROUP_SID), temp)) - { + get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PRIMARY_GROUP_SID), temp)) { pdb_set_group_sid_from_string(sampass, temp, PDB_SET); - } - else - { + } else { pdb_set_group_sid_from_rid(sampass, DOMAIN_GROUP_RID_USERS, PDB_DEFAULT); } - - - } - else - { + } else { if (smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, - get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_RID), temp)) - { + get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_RID), temp)) { user_rid = (uint32)atol(temp); pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET); } if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, - get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PRIMARY_GROUP_RID), temp)) - { + get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PRIMARY_GROUP_RID), temp)) { pdb_set_group_sid_from_rid(sampass, DOMAIN_GROUP_RID_USERS, PDB_DEFAULT); } else { uint32 group_rid; @@ -527,7 +508,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, } if (pdb_get_init_flags(sampass,PDB_USERSID) == PDB_DEFAULT) { - DEBUG(1, ("no %s or %s attribute found for this user %s\n", + DEBUG(1, ("init_sam_from_ldap: no %s or %s attribute found for this user %s\n", get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID), get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_RID), username)); @@ -557,8 +538,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, #endif if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, - get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_LAST_SET), temp)) - { + get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_LAST_SET), temp)) { /* leave as default */ } else { pass_last_set_time = (time_t) atol(temp); @@ -566,8 +546,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, } if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, - get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGON_TIME), temp)) - { + get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGON_TIME), temp)) { /* leave as default */ } else { logon_time = (time_t) atol(temp); @@ -575,8 +554,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, } if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, - get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGOFF_TIME), temp)) - { + get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGOFF_TIME), temp)) { /* leave as default */ } else { logoff_time = (time_t) atol(temp); @@ -584,8 +562,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, } if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, - get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_KICKOFF_TIME), temp)) - { + get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_KICKOFF_TIME), temp)) { /* leave as default */ } else { kickoff_time = (time_t) atol(temp); @@ -593,8 +570,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, } if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, - get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_CAN_CHANGE), temp)) - { + get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_CAN_CHANGE), temp)) { /* leave as default */ } else { pass_can_change_time = (time_t) atol(temp); @@ -602,8 +578,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, } if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, - get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_MUST_CHANGE), temp)) - { + get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_MUST_CHANGE), temp)) { /* leave as default */ } else { pass_must_change_time = (time_t) atol(temp); @@ -617,11 +592,9 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, */ if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, - get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_DISPLAY_NAME), fullname)) - { + get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_DISPLAY_NAME), fullname)) { if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, - get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_CN), fullname)) - { + get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_CN), fullname)) { /* leave as default */ } else { pdb_set_fullname(sampass, fullname, PDB_SET); @@ -631,49 +604,41 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, } if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, - get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_HOME_DRIVE), dir_drive)) + get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_HOME_DRIVE), dir_drive)) { - pdb_set_dir_drive(sampass, talloc_sub_specified(sampass->mem_ctx, - lp_logon_drive(), - username, domain, - uid, gid), - PDB_DEFAULT); + pdb_set_dir_drive( sampass, + talloc_sub_basic(sampass->mem_ctx, username, lp_logon_drive()), + PDB_DEFAULT ); } else { pdb_set_dir_drive(sampass, dir_drive, PDB_SET); } if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, - get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_HOME_PATH), homedir)) + get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_HOME_PATH), homedir)) { - pdb_set_homedir(sampass, talloc_sub_specified(sampass->mem_ctx, - lp_logon_home(), - username, domain, - uid, gid), - PDB_DEFAULT); + pdb_set_homedir( sampass, + talloc_sub_basic(sampass->mem_ctx, username, lp_logon_home()), + PDB_DEFAULT ); } else { pdb_set_homedir(sampass, homedir, PDB_SET); } if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, - get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGON_SCRIPT), logon_script)) + get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGON_SCRIPT), logon_script)) { - pdb_set_logon_script(sampass, talloc_sub_specified(sampass->mem_ctx, - lp_logon_script(), - username, domain, - uid, gid), - PDB_DEFAULT); + pdb_set_logon_script( sampass, + talloc_sub_basic(sampass->mem_ctx, username, lp_logon_script()), + PDB_DEFAULT ); } else { pdb_set_logon_script(sampass, logon_script, PDB_SET); } if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, - get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PROFILE_PATH), profile_path)) + get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PROFILE_PATH), profile_path)) { - pdb_set_profile_path(sampass, talloc_sub_specified(sampass->mem_ctx, - lp_logon_path(), - username, domain, - uid, gid), - PDB_DEFAULT); + pdb_set_profile_path( sampass, + talloc_sub_basic( sampass->mem_ctx, username, lp_logon_path()), + PDB_DEFAULT ); } else { pdb_set_profile_path(sampass, profile_path, PDB_SET); } @@ -687,8 +652,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, } if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, - get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_WKS), workstations)) - { + get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_WKS), workstations)) { /* leave as default */; } else { pdb_set_workstations(sampass, workstations, PDB_SET); @@ -701,8 +665,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, memset(hours, 0xff, hours_len); if (!smbldap_get_single_attribute (ldap_state->smbldap_state->ldap_struct, entry, - get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LMPW), temp)) - { + get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LMPW), temp)) { /* leave as default */ } else { pdb_gethexpwd(temp, smblmpwd); @@ -713,8 +676,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, } if (!smbldap_get_single_attribute (ldap_state->smbldap_state->ldap_struct, entry, - get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_NTPW), temp)) - { + get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_NTPW), temp)) { /* leave as default */ } else { pdb_gethexpwd(temp, smbntpwd); @@ -725,8 +687,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, } if (!smbldap_get_single_attribute (ldap_state->smbldap_state->ldap_struct, entry, - get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_ACB_INFO), temp)) - { + get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_ACB_INFO), temp)) { acct_ctrl |= ACB_NORMAL; } else { acct_ctrl = pdb_decode_acct_ctrl(temp); @@ -752,9 +713,10 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, } /********************************************************************** -Initialize SAM_ACCOUNT from an LDAP query -(Based on init_buffer_from_sam in pdb_tdb.c) + Initialize SAM_ACCOUNT from an LDAP query. + (Based on init_buffer_from_sam in pdb_tdb.c) *********************************************************************/ + static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state, LDAPMessage *existing, LDAPMod *** mods, SAM_ACCOUNT * sampass, @@ -779,20 +741,18 @@ static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state, smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods, "uid", pdb_get_username(sampass)); - DEBUG(2, ("Setting entry for user: %s\n", pdb_get_username(sampass))); + DEBUG(2, ("init_ldap_from_sam: Setting entry for user: %s\n", pdb_get_username(sampass))); /* only update the RID if we actually need to */ - if (need_update(sampass, PDB_USERSID)) - { + if (need_update(sampass, PDB_USERSID)) { fstring sid_string; fstring dom_sid_string; const DOM_SID *user_sid = pdb_get_user_sid(sampass); - switch ( ldap_state->schema_ver ) - { + switch ( ldap_state->schema_ver ) { case SCHEMAVER_SAMBAACCOUNT: if (!sid_peek_check_rid(&ldap_state->domain_sid, user_sid, &rid)) { - DEBUG(1, ("User's SID (%s) is not for this domain (%s), cannot add to LDAP!\n", + DEBUG(1, ("init_ldap_from_sam: User's SID (%s) is not for this domain (%s), cannot add to LDAP!\n", sid_to_string(sid_string, user_sid), sid_to_string(dom_sid_string, &ldap_state->domain_sid))); return False; @@ -818,17 +778,15 @@ static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state, /* we don't need to store the primary group RID - so leaving it 'free' to hang off the unix primary group makes life easier */ - if (need_update(sampass, PDB_GROUPSID)) - { + if (need_update(sampass, PDB_GROUPSID)) { fstring sid_string; fstring dom_sid_string; const DOM_SID *group_sid = pdb_get_group_sid(sampass); - switch ( ldap_state->schema_ver ) - { + switch ( ldap_state->schema_ver ) { case SCHEMAVER_SAMBAACCOUNT: if (!sid_peek_check_rid(&ldap_state->domain_sid, group_sid, &rid)) { - DEBUG(1, ("User's Primary Group SID (%s) is not for this domain (%s), cannot add to LDAP!\n", + DEBUG(1, ("init_ldap_from_sam: User's Primary Group SID (%s) is not for this domain (%s), cannot add to LDAP!\n", sid_to_string(sid_string, group_sid), sid_to_string(dom_sid_string, &ldap_state->domain_sid))); return False; @@ -922,8 +880,7 @@ static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_MUST_CHANGE), temp); if ((pdb_get_acct_ctrl(sampass)&(ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST)) - || (lp_ldap_passwd_sync()!=LDAP_PASSWD_SYNC_ONLY)) - { + || (lp_ldap_passwd_sync()!=LDAP_PASSWD_SYNC_ONLY)) { pdb_sethexpwd(temp, pdb_get_lanman_passwd(sampass), pdb_get_acct_ctrl(sampass)); @@ -958,11 +915,10 @@ static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state, return True; } - - /********************************************************************** -Connect to LDAP server for password enumeration + Connect to LDAP server for password enumeration. *********************************************************************/ + static NTSTATUS ldapsam_setsampwent(struct pdb_methods *my_methods, BOOL update) { struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data; @@ -980,8 +936,8 @@ static NTSTATUS ldapsam_setsampwent(struct pdb_methods *my_methods, BOOL update) free_attr_list( attr_list ); 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)); + DEBUG(0, ("ldapsam_setsampwent: LDAP search failed: %s\n", ldap_err2string(rc))); + DEBUG(3, ("ldapsam_setsampwent: Query was: %s, %s\n", lp_ldap_suffix(), filter)); ldap_msgfree(ldap_state->result); ldap_state->result = NULL; return NT_STATUS_UNSUCCESSFUL; @@ -999,8 +955,9 @@ static NTSTATUS ldapsam_setsampwent(struct pdb_methods *my_methods, BOOL update) } /********************************************************************** -End enumeration of the LDAP password list + 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; @@ -1011,8 +968,9 @@ static void ldapsam_endsampwent(struct pdb_methods *my_methods) } /********************************************************************** -Get the next entry in the LDAP password database +Get the next entry in the LDAP password database. *********************************************************************/ + static NTSTATUS ldapsam_getsampwent(struct pdb_methods *my_methods, SAM_ACCOUNT *user) { NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; @@ -1034,8 +992,9 @@ static NTSTATUS ldapsam_getsampwent(struct pdb_methods *my_methods, SAM_ACCOUNT } /********************************************************************** -Get SAM_ACCOUNT entry from LDAP by username +Get SAM_ACCOUNT entry from LDAP by username. *********************************************************************/ + static NTSTATUS ldapsam_getsampwnam(struct pdb_methods *my_methods, SAM_ACCOUNT *user, const char *sname) { NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; @@ -1056,15 +1015,11 @@ static NTSTATUS ldapsam_getsampwnam(struct pdb_methods *my_methods, SAM_ACCOUNT count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result); if (count < 1) { - DEBUG(4, - ("Unable to locate user [%s] count=%d\n", sname, - count)); + DEBUG(4, ("ldapsam_getsampwnam: Unable to locate user [%s] count=%d\n", sname, count)); ldap_msgfree(result); return NT_STATUS_NO_SUCH_USER; } else if (count > 1) { - DEBUG(1, - ("Duplicate entries for this user [%s] Failing. count=%d\n", sname, - count)); + DEBUG(1, ("ldapsam_getsampwnam: Duplicate entries for this user [%s] Failing. count=%d\n", sname, count)); ldap_msgfree(result); return NT_STATUS_NO_SUCH_USER; } @@ -1093,8 +1048,7 @@ static int ldapsam_get_ldap_user_by_sid(struct ldapsam_privates *ldap_state, char ** attr_list; uint32 rid; - switch ( ldap_state->schema_ver ) - { + switch ( ldap_state->schema_ver ) { case SCHEMAVER_SAMBASAMACCOUNT: attr_list = get_userattr_list(ldap_state->schema_ver); rc = ldapsam_search_suffix_by_sid(ldap_state, sid, result, attr_list); @@ -1121,8 +1075,9 @@ static int ldapsam_get_ldap_user_by_sid(struct ldapsam_privates *ldap_state, } /********************************************************************** -Get SAM_ACCOUNT entry from LDAP by SID + Get SAM_ACCOUNT entry from LDAP by SID. *********************************************************************/ + static NTSTATUS ldapsam_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUNT * user, const DOM_SID *sid) { struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data; @@ -1139,26 +1094,20 @@ static NTSTATUS ldapsam_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUNT count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result); - if (count < 1) - { - DEBUG(4, - ("Unable to locate SID [%s] count=%d\n", sid_to_string(sid_string, sid), + if (count < 1) { + DEBUG(4, ("ldapsam_getsampwsid: Unable to locate SID [%s] count=%d\n", sid_to_string(sid_string, sid), count)); ldap_msgfree(result); return NT_STATUS_NO_SUCH_USER; - } - else if (count > 1) - { - DEBUG(1, - ("More than one user with SID [%s]. Failing. count=%d\n", sid_to_string(sid_string, sid), + } else if (count > 1) { + DEBUG(1, ("ldapsam_getsampwsid: More than one user with SID [%s]. Failing. count=%d\n", sid_to_string(sid_string, sid), count)); ldap_msgfree(result); return NT_STATUS_NO_SUCH_USER; } entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result); - if (!entry) - { + if (!entry) { ldap_msgfree(result); return NT_STATUS_NO_SUCH_USER; } @@ -1176,15 +1125,14 @@ static NTSTATUS ldapsam_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUNT } /******************************************************************** -Do the actual modification - also change a plaintext passord if -it it set. + Do the actual modification - also change a plaintext passord if + it it set. **********************************************************************/ static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods, SAM_ACCOUNT *newpwd, char *dn, LDAPMod **mods, int ldap_op, - BOOL (*need_update)(const SAM_ACCOUNT *, - enum pdb_elements)) + BOOL (*need_update)(const SAM_ACCOUNT *, enum pdb_elements)) { struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data; int rc; @@ -1194,11 +1142,10 @@ static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods, } if (!mods) { - DEBUG(5,("mods is empty: nothing to modify\n")); + DEBUG(5,("ldapsam_modify_entry: mods is empty: nothing to modify\n")); /* may be password change below however */ } else { - switch(ldap_op) - { + switch(ldap_op) { case LDAP_MOD_ADD: smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectclass", @@ -1211,7 +1158,7 @@ static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods, dn ,mods); break; default: - DEBUG(0,("Wrong LDAP operation type: %d!\n", + DEBUG(0,("ldapsam_modify_entry: Wrong LDAP operation type: %d!\n", ldap_op)); return NT_STATUS_INVALID_PARAMETER; } @@ -1220,8 +1167,7 @@ static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods, char *ld_error = NULL; ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error); - DEBUG(1, - ("failed to %s user dn= %s with: %s\n\t%s\n", + DEBUG(1, ("ldapsam_modify_entry: Failed to %s user dn= %s with: %s\n\t%s\n", ldap_op == LDAP_MOD_ADD ? "add" : "modify", dn, ldap_err2string(rc), ld_error?ld_error:"unknown")); @@ -1231,9 +1177,9 @@ static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods, } if (!(pdb_get_acct_ctrl(newpwd)&(ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST)) && - (lp_ldap_passwd_sync() != LDAP_PASSWD_SYNC_OFF) && - need_update(newpwd, PDB_PLAINTEXT_PW) && - (pdb_get_plaintext_passwd(newpwd)!=NULL)) { + (lp_ldap_passwd_sync() != LDAP_PASSWD_SYNC_OFF) && + need_update(newpwd, PDB_PLAINTEXT_PW) && + (pdb_get_plaintext_passwd(newpwd)!=NULL)) { BerElement *ber; struct berval *bv; char *retoid; @@ -1261,7 +1207,7 @@ static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods, ber_printf (ber, "N}"); if ((rc = ber_flatten (ber, &bv))<0) { - DEBUG(0,("ber_flatten returns a value <0\n")); + DEBUG(0,("ldapsam_modify_entry: ber_flatten returns a value <0\n")); ber_free(ber,1); SAFE_FREE(utf8_dn); SAFE_FREE(utf8_password); @@ -1276,12 +1222,12 @@ static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods, LDAP_EXOP_MODIFY_PASSWD, bv, NULL, NULL, &retoid, &retdata)) != LDAP_SUCCESS) { - DEBUG(0,("LDAP Password could not be changed for user %s: %s\n", + DEBUG(0,("ldapsam_modify_entry: 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))); + DEBUG(3,("ldapsam_modify_entry: LDAP Password changed for user %s\n",pdb_get_username(newpwd))); #ifdef DEBUG_PASSWORD - DEBUG(100,("LDAP Password changed to %s\n",pdb_get_plaintext_passwd(newpwd))); + DEBUG(100,("ldapsam_modify_entry: LDAP Password changed to %s\n",pdb_get_plaintext_passwd(newpwd))); #endif ber_bvfree(retdata); ber_memfree(retoid); @@ -1292,8 +1238,9 @@ static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods, } /********************************************************************** -Delete entry from LDAP for username + Delete entry from LDAP for username. *********************************************************************/ + static NTSTATUS ldapsam_delete_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * sam_acct) { struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data; @@ -1305,13 +1252,13 @@ static NTSTATUS ldapsam_delete_sam_account(struct pdb_methods *my_methods, SAM_A fstring objclass; if (!sam_acct) { - DEBUG(0, ("sam_acct was NULL!\n")); + DEBUG(0, ("ldapsam_delete_sam_account: sam_acct was NULL!\n")); return NT_STATUS_INVALID_PARAMETER; } sname = pdb_get_username(sam_acct); - DEBUG (3, ("Deleting user %s from LDAP.\n", sname)); + DEBUG (3, ("ldapsam_delete_sam_account: Deleting user %s from LDAP.\n", sname)); attr_list= get_userattr_list( ldap_state->schema_ver ); rc = ldapsam_search_suffix_by_name(ldap_state, sname, &result, attr_list); @@ -1321,8 +1268,7 @@ static NTSTATUS ldapsam_delete_sam_account(struct pdb_methods *my_methods, SAM_A return NT_STATUS_NO_SUCH_USER; } - switch ( ldap_state->schema_ver ) - { + switch ( ldap_state->schema_ver ) { case SCHEMAVER_SAMBASAMACCOUNT: fstrcpy( objclass, LDAP_OBJ_SAMBASAMACCOUNT ); break; @@ -1344,9 +1290,10 @@ static NTSTATUS ldapsam_delete_sam_account(struct pdb_methods *my_methods, SAM_A } /********************************************************************** - Helper function to determine for update_sam_account whether - we need LDAP modification. + Helper function to determine for update_sam_account whether + we need LDAP modification. *********************************************************************/ + static BOOL element_is_changed(const SAM_ACCOUNT *sampass, enum pdb_elements element) { @@ -1354,13 +1301,14 @@ static BOOL element_is_changed(const SAM_ACCOUNT *sampass, } /********************************************************************** -Update SAM_ACCOUNT + Update SAM_ACCOUNT. *********************************************************************/ + static NTSTATUS ldapsam_update_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * newpwd) { NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data; - int rc; + int rc = 0; char *dn; LDAPMessage *result; LDAPMessage *entry; @@ -1379,53 +1327,57 @@ static NTSTATUS ldapsam_update_sam_account(struct pdb_methods *my_methods, SAM_A } if (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result) == 0) { - DEBUG(0, ("No user to modify!\n")); + DEBUG(0, ("ldapsam_update_sam_account: No user to modify!\n")); return NT_STATUS_UNSUCCESSFUL; } entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result); - dn = ldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry); + dn = smbldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry); + if (!dn) { + return NT_STATUS_UNSUCCESSFUL; + } - DEBUG(4, ("user %s to be modified has dn: %s\n", pdb_get_username(newpwd), dn)); + DEBUG(4, ("ldapsam_update_sam_account: user %s to be modified has dn: %s\n", pdb_get_username(newpwd), dn)); if (!init_ldap_from_sam(ldap_state, entry, &mods, newpwd, element_is_changed)) { DEBUG(0, ("ldapsam_update_sam_account: init_ldap_from_sam failed!\n")); - ldap_memfree(dn); + SAFE_FREE(dn); return NT_STATUS_UNSUCCESSFUL; } if (mods == NULL) { - DEBUG(4,("mods is empty: nothing to update for user: %s\n", + DEBUG(4,("ldapsam_update_sam_account: mods is empty: nothing to update for user: %s\n", pdb_get_username(newpwd))); ldap_mods_free(mods, True); - ldap_memfree(dn); + SAFE_FREE(dn); return NT_STATUS_OK; } ret = ldapsam_modify_entry(my_methods,newpwd,dn,mods,LDAP_MOD_REPLACE, element_is_changed); ldap_mods_free(mods,True); - ldap_memfree(dn); + SAFE_FREE(dn); if (!NT_STATUS_IS_OK(ret)) { char *ld_error = NULL; ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error); - DEBUG(0,("failed to modify user with uid = %s, error: %s (%s)\n", + DEBUG(0,("ldapsam_update_sam_account: failed to modify user with uid = %s, error: %s (%s)\n", pdb_get_username(newpwd), ld_error?ld_error:"(unknwon)", ldap_err2string(rc))); SAFE_FREE(ld_error); return ret; } - DEBUG(2, ("successfully modified uid = %s in the LDAP database\n", + DEBUG(2, ("ldapsam_update_sam_account: successfully modified uid = %s in the LDAP database\n", pdb_get_username(newpwd))); return NT_STATUS_OK; } /********************************************************************** - Helper function to determine for update_sam_account whether - we need LDAP modification. + Helper function to determine for update_sam_account whether + we need LDAP modification. *********************************************************************/ + static BOOL element_is_set_or_changed(const SAM_ACCOUNT *sampass, enum pdb_elements element) { @@ -1434,7 +1386,7 @@ static BOOL element_is_set_or_changed(const SAM_ACCOUNT *sampass, } /********************************************************************** -Add SAM_ACCOUNT to LDAP + Add SAM_ACCOUNT to LDAP. *********************************************************************/ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * newpwd) @@ -1446,7 +1398,7 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCO LDAPMessage *entry = NULL; pstring dn; LDAPMod **mods = NULL; - int ldap_op; + int ldap_op = LDAP_MOD_REPLACE; uint32 num_result; char **attr_list; char *escape_user; @@ -1456,7 +1408,7 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCO fstring sid_string; if (!username || !*username) { - DEBUG(0, ("Cannot add user without a username!\n")); + DEBUG(0, ("ldapsam_add_sam_account: Cannot add user without a username!\n")); return NT_STATUS_INVALID_PARAMETER; } @@ -1471,7 +1423,7 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCO } if (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result) != 0) { - DEBUG(0,("User '%s' already in the base, with samba attributes\n", + DEBUG(0,("ldapsam_add_sam_account: User '%s' already in the base, with samba attributes\n", username)); ldap_msgfree(result); free_attr_list( attr_list ); @@ -1485,7 +1437,7 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCO sid, &result); if (rc == LDAP_SUCCESS) { if (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result) != 0) { - DEBUG(0,("SID '%s' already in the base, with samba attributes\n", + DEBUG(0,("ldapsam_add_sam_account: SID '%s' already in the base, with samba attributes\n", sid_to_string(sid_string, sid))); free_attr_list( attr_list ); return NT_STATUS_UNSUCCESSFUL; @@ -1512,7 +1464,7 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCO num_result = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result); if (num_result > 1) { - DEBUG (0, ("More than one user with that uid exists: bailing out!\n")); + DEBUG (0, ("ldapsam_add_sam_account: More than one user with that uid exists: bailing out!\n")); free_attr_list( attr_list ); ldap_msgfree(result); return NT_STATUS_UNSUCCESSFUL; @@ -1522,12 +1474,17 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCO if (num_result == 1) { char *tmp; - DEBUG(3,("User exists without samba attributes: adding them\n")); + DEBUG(3,("ldapsam_add_sam_account: User exists without samba attributes: adding them\n")); ldap_op = LDAP_MOD_REPLACE; entry = ldap_first_entry (ldap_state->smbldap_state->ldap_struct, result); - tmp = ldap_get_dn (ldap_state->smbldap_state->ldap_struct, entry); + tmp = smbldap_get_dn (ldap_state->smbldap_state->ldap_struct, entry); + if (!tmp) { + free_attr_list( attr_list ); + ldap_msgfree(result); + return NT_STATUS_UNSUCCESSFUL; + } slprintf (dn, sizeof (dn) - 1, "%s", tmp); - ldap_memfree (tmp); + SAFE_FREE(tmp); } else if (ldap_state->schema_ver == SCHEMAVER_SAMBASAMACCOUNT) { @@ -1550,7 +1507,7 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCO num_result = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result); if (num_result > 1) { - DEBUG (0, ("More than one user with that uid exists: bailing out!\n")); + DEBUG (0, ("ldapsam_add_sam_account: More than one user with that uid exists: bailing out!\n")); free_attr_list( attr_list ); ldap_msgfree(result); return NT_STATUS_UNSUCCESSFUL; @@ -1560,12 +1517,17 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCO if (num_result == 1) { char *tmp; - DEBUG(3,("User exists without samba attributes: adding them\n")); + DEBUG(3,("ldapsam_add_sam_account: User exists without samba attributes: adding them\n")); ldap_op = LDAP_MOD_REPLACE; entry = ldap_first_entry (ldap_state->smbldap_state->ldap_struct, result); - tmp = ldap_get_dn (ldap_state->smbldap_state->ldap_struct, entry); + tmp = smbldap_get_dn (ldap_state->smbldap_state->ldap_struct, entry); + if (!tmp) { + free_attr_list( attr_list ); + ldap_msgfree(result); + return NT_STATUS_UNSUCCESSFUL; + } slprintf (dn, sizeof (dn) - 1, "%s", tmp); - ldap_memfree (tmp); + SAFE_FREE(tmp); } } @@ -1573,7 +1535,7 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCO if (num_result == 0) { /* Check if we need to add an entry */ - DEBUG(3,("Adding new user\n")); + DEBUG(3,("ldapsam_add_sam_account: Adding new user\n")); ldap_op = LDAP_MOD_ADD; if (username[strlen(username)-1] == '$') { slprintf (dn, sizeof (dn) - 1, "uid=%s,%s", username, lp_ldap_machine_suffix ()); @@ -1592,11 +1554,10 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCO ldap_msgfree(result); if (mods == NULL) { - DEBUG(0,("mods is empty: nothing to add for user: %s\n",pdb_get_username(newpwd))); + DEBUG(0,("ldapsam_add_sam_account: mods is empty: nothing to add for user: %s\n",pdb_get_username(newpwd))); return NT_STATUS_UNSUCCESSFUL; } - switch ( ldap_state->schema_ver ) - { + switch ( ldap_state->schema_ver ) { case SCHEMAVER_SAMBAACCOUNT: smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_SAMBAACCOUNT); break; @@ -1610,13 +1571,13 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCO ret = ldapsam_modify_entry(my_methods,newpwd,dn,mods,ldap_op, element_is_set_or_changed); if (!NT_STATUS_IS_OK(ret)) { - DEBUG(0,("failed to modify/add user with uid = %s (dn = %s)\n", + DEBUG(0,("ldapsam_add_sam_account: failed to modify/add user with uid = %s (dn = %s)\n", pdb_get_username(newpwd),dn)); ldap_mods_free(mods, True); return ret; } - DEBUG(2,("added: uid == %s in the LDAP database\n", pdb_get_username(newpwd))); + DEBUG(2,("ldapsam_add_sam_account: added: uid == %s in the LDAP database\n", pdb_get_username(newpwd))); ldap_mods_free(mods, True); return NT_STATUS_OK; @@ -1666,64 +1627,58 @@ static BOOL init_group_from_ldap(struct ldapsam_privates *ldap_state, pstring temp; if (ldap_state == NULL || map == NULL || entry == NULL || - ldap_state->smbldap_state->ldap_struct == NULL) - { + ldap_state->smbldap_state->ldap_struct == NULL) { DEBUG(0, ("init_group_from_ldap: NULL parameters found!\n")); return False; } if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, - get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GIDNUMBER), temp)) - { - DEBUG(0, ("Mandatory attribute %s not found\n", + get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GIDNUMBER), temp)) { + DEBUG(0, ("init_group_from_ldap: Mandatory attribute %s not found\n", get_attr_key2string( groupmap_attr_list, LDAP_ATTR_GIDNUMBER))); return False; } - DEBUG(2, ("Entry found for group: %s\n", temp)); + DEBUG(2, ("init_group_from_ldap: Entry found for group: %s\n", temp)); map->gid = (gid_t)atol(temp); if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, - get_attr_key2string( groupmap_attr_list, LDAP_ATTR_GROUP_SID), temp)) - { - DEBUG(0, ("Mandatory attribute %s not found\n", + get_attr_key2string( groupmap_attr_list, LDAP_ATTR_GROUP_SID), temp)) { + DEBUG(0, ("init_group_from_ldap: Mandatory attribute %s not found\n", get_attr_key2string( groupmap_attr_list, LDAP_ATTR_GROUP_SID))); return False; } string_to_sid(&map->sid, temp); if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, - get_attr_key2string( groupmap_attr_list, LDAP_ATTR_GROUP_TYPE), temp)) - { - DEBUG(0, ("Mandatory attribute %s not found\n", + get_attr_key2string( groupmap_attr_list, LDAP_ATTR_GROUP_TYPE), temp)) { + DEBUG(0, ("init_group_from_ldap: Mandatory attribute %s not found\n", get_attr_key2string( groupmap_attr_list, LDAP_ATTR_GROUP_TYPE))); return False; } map->sid_name_use = (enum SID_NAME_USE)atol(temp); if ((map->sid_name_use < SID_NAME_USER) || - (map->sid_name_use > SID_NAME_UNKNOWN)) { - DEBUG(0, ("Unknown Group type: %d\n", map->sid_name_use)); + (map->sid_name_use > SID_NAME_UNKNOWN)) { + DEBUG(0, ("init_group_from_ldap: Unknown Group type: %d\n", map->sid_name_use)); return False; } if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, - get_attr_key2string( groupmap_attr_list, LDAP_ATTR_DISPLAY_NAME), temp)) - { + get_attr_key2string( groupmap_attr_list, LDAP_ATTR_DISPLAY_NAME), temp)) { temp[0] = '\0'; if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_attr_key2string( groupmap_attr_list, LDAP_ATTR_CN), temp)) { - DEBUG(0, ("Attributes cn not found either " - "for gidNumber(%lu)\n",(unsigned long)map->gid)); + DEBUG(0, ("init_group_from_ldap: Attributes cn not found either \ +for gidNumber(%lu)\n",(unsigned long)map->gid)); return False; } } fstrcpy(map->nt_name, temp); if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, - get_attr_key2string( groupmap_attr_list, LDAP_ATTR_DESC), temp)) - { + get_attr_key2string( groupmap_attr_list, LDAP_ATTR_DESC), temp)) { temp[0] = '\0'; } fstrcpy(map->comment, temp); @@ -1784,13 +1739,13 @@ static NTSTATUS ldapsam_getgroup(struct pdb_methods *methods, count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result); if (count < 1) { - DEBUG(4, ("Did not find group\n")); + DEBUG(4, ("ldapsam_getgroup: Did not find group\n")); ldap_msgfree(result); return NT_STATUS_NO_SUCH_GROUP; } if (count > 1) { - DEBUG(1, ("Duplicate entries for filter %s: count=%d\n", + DEBUG(1, ("ldapsam_getgroup: Duplicate entries for filter %s: count=%d\n", filter, count)); ldap_msgfree(result); return NT_STATUS_NO_SUCH_GROUP; @@ -1804,7 +1759,7 @@ static NTSTATUS ldapsam_getgroup(struct pdb_methods *methods, } if (!init_group_from_ldap(ldap_state, map, entry)) { - DEBUG(1, ("init_group_from_ldap failed for group filter %s\n", + DEBUG(1, ("ldapsam_getgroup: init_group_from_ldap failed for group filter %s\n", filter)); ldap_msgfree(result); return NT_STATUS_NO_SUCH_GROUP; @@ -1908,7 +1863,7 @@ static NTSTATUS ldapsam_add_group_mapping_entry(struct pdb_methods *methods, if (NT_STATUS_IS_OK(ldapsam_getgrgid(methods, &dummy, map->gid))) { - DEBUG(0, ("Group %ld already exists in LDAP\n", (unsigned long)map->gid)); + DEBUG(0, ("ldapsam_add_group_mapping_entry: Group %ld already exists in LDAP\n", (unsigned long)map->gid)); return NT_STATUS_UNSUCCESSFUL; } @@ -1926,20 +1881,24 @@ static NTSTATUS ldapsam_add_group_mapping_entry(struct pdb_methods *methods, } if (count > 1) { - DEBUG(2, ("Group %lu must exist exactly once in LDAP\n", + DEBUG(2, ("ldapsam_add_group_mapping_entry: Group %lu must exist exactly once in LDAP\n", (unsigned long)map->gid)); ldap_msgfree(result); return NT_STATUS_UNSUCCESSFUL; } entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result); - tmp = ldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry); + tmp = smbldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry); + if (!tmp) { + ldap_msgfree(result); + return NT_STATUS_UNSUCCESSFUL; + } pstrcpy(dn, tmp); - ldap_memfree(tmp); + SAFE_FREE(tmp); if (!init_ldap_from_group(ldap_state->smbldap_state->ldap_struct, result, &mods, map)) { - DEBUG(0, ("init_ldap_from_group failed!\n")); + DEBUG(0, ("ldapsam_add_group_mapping_entry: init_ldap_from_group failed!\n")); ldap_mods_free(mods, True); ldap_msgfree(result); return NT_STATUS_UNSUCCESSFUL; @@ -1948,7 +1907,7 @@ static NTSTATUS ldapsam_add_group_mapping_entry(struct pdb_methods *methods, ldap_msgfree(result); if (mods == NULL) { - DEBUG(0, ("mods is empty\n")); + DEBUG(0, ("ldapsam_add_group_mapping_entry: mods is empty\n")); return NT_STATUS_UNSUCCESSFUL; } @@ -1961,13 +1920,13 @@ static NTSTATUS ldapsam_add_group_mapping_entry(struct pdb_methods *methods, char *ld_error = NULL; ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error); - DEBUG(0, ("failed to add group %lu error: %s (%s)\n", (unsigned long)map->gid, + DEBUG(0, ("ldapsam_add_group_mapping_entry: failed to add group %lu error: %s (%s)\n", (unsigned long)map->gid, ld_error ? ld_error : "(unknown)", ldap_err2string(rc))); SAFE_FREE(ld_error); return NT_STATUS_UNSUCCESSFUL; } - DEBUG(2, ("successfully modified group %lu in LDAP\n", (unsigned long)map->gid)); + DEBUG(2, ("ldapsam_add_group_mapping_entry: successfully modified group %lu in LDAP\n", (unsigned long)map->gid)); return NT_STATUS_OK; } @@ -1992,17 +1951,16 @@ static NTSTATUS ldapsam_update_group_mapping_entry(struct pdb_methods *methods, } if (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result) == 0) { - DEBUG(0, ("No group to modify!\n")); + DEBUG(0, ("ldapsam_update_group_mapping_entry: No group to modify!\n")); ldap_msgfree(result); return NT_STATUS_UNSUCCESSFUL; } entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result); - dn = ldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry); if (!init_ldap_from_group(ldap_state->smbldap_state->ldap_struct, result, &mods, map)) { - DEBUG(0, ("init_ldap_from_group failed\n")); + DEBUG(0, ("ldapsam_update_group_mapping_entry: init_ldap_from_group failed\n")); ldap_msgfree(result); return NT_STATUS_UNSUCCESSFUL; } @@ -2010,11 +1968,16 @@ static NTSTATUS ldapsam_update_group_mapping_entry(struct pdb_methods *methods, ldap_msgfree(result); if (mods == NULL) { - DEBUG(4, ("mods is empty: nothing to do\n")); + DEBUG(4, ("ldapsam_update_group_mapping_entry: mods is empty: nothing to do\n")); return NT_STATUS_UNSUCCESSFUL; } + dn = smbldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry); + if (!dn) { + return NT_STATUS_UNSUCCESSFUL; + } rc = smbldap_modify(ldap_state->smbldap_state, dn, mods); + SAFE_FREE(dn); ldap_mods_free(mods, True); @@ -2022,12 +1985,12 @@ static NTSTATUS ldapsam_update_group_mapping_entry(struct pdb_methods *methods, char *ld_error = NULL; ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error); - DEBUG(0, ("failed to modify group %lu error: %s (%s)\n", (unsigned long)map->gid, + DEBUG(0, ("ldapsam_update_group_mapping_entry: failed to modify group %lu error: %s (%s)\n", (unsigned long)map->gid, ld_error ? ld_error : "(unknown)", ldap_err2string(rc))); SAFE_FREE(ld_error); } - DEBUG(2, ("successfully modified group %lu in LDAP\n", (unsigned long)map->gid)); + DEBUG(2, ("ldapsam_update_group_mapping_entry: successfully modified group %lu in LDAP\n", (unsigned long)map->gid)); return NT_STATUS_OK; } @@ -2082,8 +2045,8 @@ static NTSTATUS ldapsam_setsamgrent(struct pdb_methods *my_methods, BOOL update) free_attr_list( attr_list ); if (rc != LDAP_SUCCESS) { - DEBUG(0, ("LDAP search failed: %s\n", ldap_err2string(rc))); - DEBUG(3, ("Query was: %s, %s\n", lp_ldap_group_suffix(), filter)); + DEBUG(0, ("ldapsam_setsamgrent: LDAP search failed: %s\n", ldap_err2string(rc))); + DEBUG(3, ("ldapsam_setsamgrent: Query was: %s, %s\n", lp_ldap_group_suffix(), filter)); ldap_msgfree(ldap_state->result); ldap_state->result = NULL; return NT_STATUS_UNSUCCESSFUL; @@ -2147,24 +2110,24 @@ static NTSTATUS ldapsam_enum_group_mapping(struct pdb_methods *methods, *rmap = NULL; if (!NT_STATUS_IS_OK(ldapsam_setsamgrent(methods, False))) { - DEBUG(0, ("Unable to open passdb\n")); + DEBUG(0, ("ldapsam_enum_group_mapping: Unable to open passdb\n")); return NT_STATUS_ACCESS_DENIED; } while (NT_STATUS_IS_OK(ldapsam_getsamgrent(methods, &map))) { if (sid_name_use != SID_NAME_UNKNOWN && sid_name_use != map.sid_name_use) { - DEBUG(11,("enum_group_mapping: group %s is not of the requested type\n", map.nt_name)); + DEBUG(11,("ldapsam_enum_group_mapping: group %s is not of the requested type\n", map.nt_name)); continue; } if (unix_only==ENUM_ONLY_MAPPED && map.gid==-1) { - DEBUG(11,("enum_group_mapping: group %s is non mapped\n", map.nt_name)); + DEBUG(11,("ldapsam_enum_group_mapping: group %s is non mapped\n", map.nt_name)); continue; } mapt=(GROUP_MAP *)Realloc((*rmap), (entries+1)*sizeof(GROUP_MAP)); if (!mapt) { - DEBUG(0,("enum_group_mapping: Unable to enlarge group map!\n")); + DEBUG(0,("ldapsam_enum_group_mapping: Unable to enlarge group map!\n")); SAFE_FREE(*rmap); return NT_STATUS_UNSUCCESSFUL; } @@ -2235,7 +2198,7 @@ static NTSTATUS pdb_init_ldapsam_common(PDB_CONTEXT *pdb_context, PDB_METHODS ** ldap_state = talloc_zero(pdb_context->mem_ctx, sizeof(*ldap_state)); if (!ldap_state) { - DEBUG(0, ("talloc() failed for ldapsam private_data!\n")); + DEBUG(0, ("pdb_init_ldapsam_common: talloc() failed for ldapsam private_data!\n")); return NT_STATUS_NO_MEMORY; } @@ -2325,9 +2288,9 @@ static NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_met ldap_state->domain_name, True); if ( !NT_STATUS_IS_OK(nt_status) ) { - DEBUG(2, ("WARNING: Could not get domain info, nor add one to the domain\n")); - DEBUGADD(2, ("Continuing on regardless, will be unable to allocate new users/groups, " - "and will risk BDCs having inconsistant SIDs\n")); + DEBUG(2, ("pdb_init_ldapsam: WARNING: Could not get domain info, nor add one to the domain\n")); + DEBUGADD(2, ("pdb_init_ldapsam: Continuing on regardless, will be unable to allocate new users/groups, \ +and will risk BDCs having inconsistant SIDs\n")); sid_copy(&ldap_state->domain_sid, get_global_sam_sid()); return NT_STATUS_OK; } @@ -2336,15 +2299,14 @@ static NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_met entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result); if (!entry) { - DEBUG(0, ("Could not get domain info entry\n")); + DEBUG(0, ("pdb_init_ldapsam: Could not get domain info entry\n")); ldap_msgfree(result); return NT_STATUS_UNSUCCESSFUL; } if (smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID), - domain_sid_string)) - { + domain_sid_string)) { BOOL found_sid; string_to_sid(&ldap_domain_sid, domain_sid_string); found_sid = secrets_fetch_domain_sid(ldap_state->domain_name, &secrets_domain_sid); @@ -2357,12 +2319,11 @@ static NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_met if (smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_ALGORITHMIC_RID_BASE), - alg_rid_base_string)) - { + alg_rid_base_string)) { alg_rid_base = (uint32)atol(alg_rid_base_string); if (alg_rid_base != algorithmic_rid_base()) { - DEBUG(0, ("The value of 'algorithmic RID base' has changed since the LDAP\n" - "database was initialised. Aborting. \n")); + DEBUG(0, ("pdb_init_ldapsam: The value of 'algorithmic RID base' has changed since the LDAP\n\ +database was initialised. Aborting. \n")); ldap_msgfree(result); return NT_STATUS_UNSUCCESSFUL; } @@ -2383,5 +2344,3 @@ NTSTATUS pdb_ldap_init(void) return NT_STATUS_OK; } - - -- cgit From 240d5944e3b8e5b748465f9e974b2fab309703be Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 15 Sep 2003 05:35:02 +0000 Subject: Merge from Samba 3.0: >Fix a nasty mess, and also bug #296. passdb/pdb_ldap.c was not converting >to/from utf8 for some calls. The libads code gets this right. Wonder why >the passdb code doesn't use it ? >Jeremy. (This used to be commit 9b6328bcfd5b53a05926eb5a97c74275842d086b) --- source3/printing/nt_printing.c | 44 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 39 insertions(+), 5 deletions(-) (limited to 'source3') diff --git a/source3/printing/nt_printing.c b/source3/printing/nt_printing.c index 4859d785be..868f68c079 100644 --- a/source3/printing/nt_printing.c +++ b/source3/printing/nt_printing.c @@ -2587,7 +2587,8 @@ static WERROR publish_it(NT_PRINTER_INFO_LEVEL *printer) ADS_STATUS ads_rc; TALLOC_CTX *ctx = talloc_init("publish_it"); ADS_MODLIST mods = ads_init_mods(ctx); - char *prt_dn = NULL, *srv_dn, **srv_cn; + char *prt_dn = NULL, *srv_dn, *srv_cn_0; + char *srv_dn_utf8, **srv_cn_utf8; void *res = NULL; ADS_STRUCT *ads; const char *attrs[] = {"objectGUID", NULL}; @@ -2634,12 +2635,45 @@ static WERROR publish_it(NT_PRINTER_INFO_LEVEL *printer) /* figure out where to publish */ ads_find_machine_acct(ads, &res, global_myname()); - srv_dn = ldap_get_dn(ads->ld, res); + + /* We use ldap_get_dn here as we need the answer + * in utf8 to call ldap_explode_dn(). JRA. */ + + srv_dn_utf8 = ldap_get_dn(ads->ld, res); + if (!srv_dn_utf8) { + ads_destroy(&ads); + return WERR_SERVER_UNAVAILABLE; + } ads_msgfree(ads, res); - srv_cn = ldap_explode_dn(srv_dn, 1); - asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn[0], + srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1); + if (!srv_cn_utf8) { + ldap_memfree(srv_dn_utf8); + ads_destroy(&ads); + return WERR_SERVER_UNAVAILABLE; + } + /* Now convert to CH_UNIX. */ + if (pull_utf8_allocate((void **) &srv_dn, srv_dn_utf8) == (size_t)-1) { + ldap_memfree(srv_dn_utf8); + ldap_memfree(srv_cn_utf8); + ads_destroy(&ads); + return WERR_SERVER_UNAVAILABLE; + } + if (pull_utf8_allocate((void **) &srv_cn_0, srv_cn_utf8[0]) == (size_t)-1) { + ldap_memfree(srv_dn_utf8); + ldap_memfree(srv_cn_utf8); + ads_destroy(&ads); + SAFE_FREE(srv_dn); + return WERR_SERVER_UNAVAILABLE; + } + + ldap_memfree(srv_dn_utf8); + ldap_memfree(srv_cn_utf8); + + asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn_0, printer->info_2->sharename, srv_dn); - ads_memfree(ads, srv_dn); + + SAFE_FREE(srv_dn); + SAFE_FREE(srv_cn_0); /* publish it */ ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods); -- cgit From bbc4f18f22b1ce5a247121a65e1bc1d00e585847 Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Mon, 15 Sep 2003 12:59:09 +0000 Subject: Alias charset 646 internally (This used to be commit f4eb7acc7dfc400cc6524dccdd8081acd707f937) --- source3/lib/iconv.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3') diff --git a/source3/lib/iconv.c b/source3/lib/iconv.c index c09bff5fd7..3d26d7e17c 100644 --- a/source3/lib/iconv.c +++ b/source3/lib/iconv.c @@ -57,6 +57,7 @@ static struct charset_functions builtin_functions[] = { {"UCS-2LE", iconv_copy, iconv_copy}, {"UTF8", utf8_pull, utf8_push}, {"ASCII", ascii_pull, ascii_push}, + {"646", ascii_pull, ascii_push}, {"UCS2-HEX", ucs2hex_pull, ucs2hex_push}, {NULL, NULL, NULL} }; -- cgit From 5f91a15a66f8c530087ec438696cf42587d3cfdb Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Mon, 15 Sep 2003 14:21:32 +0000 Subject: fix online help -w option need the password on the command line (This used to be commit 0b8f32b7f53b145fb51f5537a7f42d11d69ed4c3) --- source3/utils/smbpasswd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3') diff --git a/source3/utils/smbpasswd.c b/source3/utils/smbpasswd.c index 6ab6d35e73..6854842b20 100644 --- a/source3/utils/smbpasswd.c +++ b/source3/utils/smbpasswd.c @@ -63,7 +63,7 @@ static void usage(void) printf(" -i interdomain trust account\n"); printf(" -m machine trust account\n"); printf(" -n set no password\n"); - printf(" -w ldap admin password\n"); + printf(" -w PASSWORD ldap admin password\n"); printf(" -x delete user\n"); printf(" -R ORDER name resolve order\n"); -- cgit From 4fd86794ecf4249ce04a3fbb57d3524fdfaa058d Mon Sep 17 00:00:00 2001 From: "Christopher R. Hertel" Date: Mon, 15 Sep 2003 17:01:45 +0000 Subject: Fixed test and wording for long share names. The RAP NetShareEnum() call has a length limit of 12 characters (not 8, as previously tested). Took DaveCB's suggested and added a note listing some of the client systems that might be affected. (This used to be commit cdfc0fc383ab63f47ddd547fddc4c28bbfddf5e5) --- source3/utils/testparm.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'source3') diff --git a/source3/utils/testparm.c b/source3/utils/testparm.c index 0a87b4bc1e..34c25480d9 100644 --- a/source3/utils/testparm.c +++ b/source3/utils/testparm.c @@ -248,9 +248,10 @@ via the %%o substitution. With encrypted passwords this is not possible.\n", lp_ for (s=0;s<1000;s++) { if (VALID_SNUM(s)) - if (strlen(lp_servicename(s)) > 8) { - printf("WARNING: You have some share names that are longer than 8 chars\n"); - printf("These may give errors while browsing or may not be accessible\nto some older clients\n"); + if (strlen(lp_servicename(s)) > 12) { + printf( "WARNING: You have some share names that are longer than 12 characters.\n" ); + printf( "These may not be accessible to some older clients.\n" ); + printf( "(Eg. Windows9x, WindowsMe, and smbclient prior to Samba 3.0.)\n" ); break; } } -- cgit From f208ab8ac24efd1cf34d01d6718cf2d9aa065b13 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 15 Sep 2003 21:22:15 +0000 Subject: Ensure HEAD is also up to date. Fix OOPS when dealing with mangled names reported by several users. This was my bug when removing a redundant strlen. Jeremy. (This used to be commit 3b3e19f66f783016ca3bc2d9e76328732ed4a84b) --- source3/smbd/mangle_hash2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3') diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index 9cd0438d51..e0efb3e41b 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -53,7 +53,7 @@ #include "includes.h" -#if 0 +#if 1 #define M_DEBUG(level, x) DEBUG(level, x) #else #define M_DEBUG(level, x) @@ -219,7 +219,7 @@ static BOOL is_mangled_component(const char *name, size_t len) if (len > 8) { if (name[8] != '.') return False; - for (i=9; name[i]; i++) { + for (i=9; name[i] && i < len; i++) { if (! FLAG_CHECK(name[i], FLAG_ASCII)) { return False; } -- cgit From 77adfbf4605bddeb1211586bb4ea4b1042ddbcd5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 15 Sep 2003 21:27:33 +0000 Subject: Fix from gregory@networksentry.co.za, don't clobber the comment if it exists. Jeremy. (This used to be commit a7ef2ce34931d9fcdeb8ecbcad981d96db4c409a) --- source3/utils/net_groupmap.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3') diff --git a/source3/utils/net_groupmap.c b/source3/utils/net_groupmap.c index f99876bbd8..323f4afbc3 100644 --- a/source3/utils/net_groupmap.c +++ b/source3/utils/net_groupmap.c @@ -274,10 +274,10 @@ static int net_groupmap_add(int argc, const char **argv) sid_to_string(string_sid, &sid); } - if (ntcomment[0]) + if (!ntcomment[0]) fstrcpy(ntcomment, "Local Unix group"); - if ( !ntgroup[0] ) + if (!ntgroup[0] ) fstrcpy( ntgroup, unixgrp ); -- cgit From 6df89dbe1020736f25a01b1e319e849f8db89851 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 16 Sep 2003 01:28:09 +0000 Subject: Fix #442 which Alexander considered a showstopper. Allow us to join mixed mode domains. Jeremy. (This used to be commit 07cfce283004d29d1f60e5d8c97e3e3d7c293805) --- source3/libsmb/cliconnect.c | 8 -------- source3/libsmb/ntlmssp.c | 6 ++++++ 2 files changed, 6 insertions(+), 8 deletions(-) (limited to 'source3') diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c index 48bcb61f92..b5f7b97ae8 100644 --- a/source3/libsmb/cliconnect.c +++ b/source3/libsmb/cliconnect.c @@ -547,14 +547,6 @@ static BOOL cli_session_setup_ntlmssp(struct cli_state *cli, const char *user, return False; } - ntlmssp_state->use_ntlmv2 = lp_client_ntlmv2_auth(); - - if (cli->sign_info.negotiated_smb_signing - || cli->sign_info.mandatory_signing) { - ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN; - ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN; - } - do { nt_status = ntlmssp_client_update(ntlmssp_state, blob_in, &blob_out); diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index 42bf18d1d2..c51b599b04 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -692,6 +692,12 @@ NTSTATUS ntlmssp_client_start(NTLMSSP_CLIENT_STATE **ntlmssp_state) NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_NTLM2 | NTLMSSP_NEGOTIATE_KEY_EXCH | + /* + * We need to set this to allow a later SetPassword + * via the SAMR pipe to succeed. Strange.... We could + * also add NTLMSSP_NEGOTIATE_SEAL here. JRA. + * */ + NTLMSSP_NEGOTIATE_SIGN | NTLMSSP_REQUEST_TARGET; (*ntlmssp_state)->ref_count = 1; -- cgit From c2505ca394942a5717cb434f3a025de72ee0df81 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Tue, 16 Sep 2003 02:50:21 +0000 Subject: Merge from 3.0: >Fix OOPS when dealing with mangled names reported by several users. >This was my bug when removing a redundant strlen. >Jerry - last showstopper I knew about. >Jeremy. (This used to be commit 3266777acb911f84e70f42f17cd9f6bbd3ba35d0) --- source3/smbd/statcache.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3') diff --git a/source3/smbd/statcache.c b/source3/smbd/statcache.c index 948173687d..76406f208e 100644 --- a/source3/smbd/statcache.c +++ b/source3/smbd/statcache.c @@ -119,7 +119,7 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat if (original_path_length != translated_path_length) { if (original_path_length < translated_path_length) { - DEBUG(0, ("OOPS - tried to store stat cache entry for werid length paths [%s] %u and [%s] %u)!\n", + DEBUG(0, ("OOPS - tried to store stat cache entry for weird length paths [%s] %u and [%s] %u)!\n", original_path, original_path_length, translated_path, translated_path_length)); SAFE_FREE(original_path); SAFE_FREE(translated_path); -- cgit From 9903a9d88ad70151b2f45552ece31c0ebd0fba81 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Tue, 16 Sep 2003 13:31:17 +0000 Subject: Fix typo. Found by Aurelien Degremont (This used to be commit 271111d6a7f5011c8300e060a9da3a972a28a704) --- source3/passdb/pdb_xml.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3') diff --git a/source3/passdb/pdb_xml.c b/source3/passdb/pdb_xml.c index 154d8c927f..7af2fdd940 100644 --- a/source3/passdb/pdb_xml.c +++ b/source3/passdb/pdb_xml.c @@ -410,7 +410,7 @@ static NTSTATUS xmlsam_add_sam_account(struct pdb_methods *methods, SAM_ACCOUNT sid_to_string(sid_str, pdb_get_group_sid(u))); if (pdb_get_init_flags(u, PDB_LOGONTIME) != PDB_DEFAULT) - xmlNewChild(user, data->ns, "login_time", + xmlNewChild(user, data->ns, "logon_time", iota(pdb_get_logon_time(u))); if (pdb_get_init_flags(u, PDB_LOGOFFTIME) != PDB_DEFAULT) -- cgit From 9dab796ed56ffea2e373df5be1ec17a77f600285 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 17 Sep 2003 17:57:18 +0000 Subject: Obviously correct typo bugfix from Lin Li . Jeremy. (This used to be commit f91da7d99bc2d9e57c411ceb0c2eb812654f3701) --- source3/nsswitch/winbindd_pam.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3') diff --git a/source3/nsswitch/winbindd_pam.c b/source3/nsswitch/winbindd_pam.c index 21ae6478de..ea2868b2cf 100644 --- a/source3/nsswitch/winbindd_pam.c +++ b/source3/nsswitch/winbindd_pam.c @@ -95,7 +95,7 @@ enum winbindd_result winbindd_pam_auth(struct winbindd_cli_state *state) /* Parse domain and username */ parse_domain_user(state->request.data.auth.user, name_domain, name_user); - if ( !name_domain ) { + if ( !*name_domain ) { DEBUG(5,("no domain separator (%s) in username (%s) - failing auth\n", lp_winbind_separator(), state->request.data.auth.user)); result = NT_STATUS_INVALID_PARAMETER; goto done; -- cgit From 53185ba285991b24d88f5b3c6c4e9e0eed1c1431 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 17 Sep 2003 19:36:53 +0000 Subject: Fix coredump from Samba4 torture suite. Jeremy. (This used to be commit 640bc276ba3d1ab83cd8994bddd64fd745f75101) --- source3/smbd/files.c | 2 ++ source3/smbd/nttrans.c | 3 +++ 2 files changed, 5 insertions(+) (limited to 'source3') diff --git a/source3/smbd/files.c b/source3/smbd/files.c index 1fe6f250e5..80544c9a30 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -405,6 +405,8 @@ files_struct *file_fsp(char *buf, int where) if (chain_fsp) return chain_fsp; + if (!buf) + return NULL; fnum = SVAL(buf, where); for (fsp=Files;fsp;fsp=fsp->next, count++) { diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index f8bd3ae15f..1c50744947 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1472,6 +1472,9 @@ static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf, files_struct *fsp; uint32 flags; + if(setup_count < 6) + return ERROR_DOS(ERRDOS,ERRbadfunc); + fsp = file_fsp(setup,4); flags = IVAL(setup, 0); -- cgit From 92347f2d0f3972db9e4e686db989d292689175be Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 17 Sep 2003 23:36:58 +0000 Subject: Unregister event fix from metze. Jeremy. (This used to be commit b3b2b3d5e7c9d4995890bf7b156fc1176b042cfc) --- source3/lib/module.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'source3') diff --git a/source3/lib/module.c b/source3/lib/module.c index 941a6cfbe3..38fcf0f329 100644 --- a/source3/lib/module.c +++ b/source3/lib/module.c @@ -210,18 +210,21 @@ void smb_run_idle_events(time_t now) struct smb_idle_list_ent *event = smb_idle_event_list; while (event) { + struct smb_idle_list_ent *next = event->next; time_t interval; - if (event->interval >= SMB_IDLE_EVENT_MIN_INTERVAL) { + if (event->interval <= 0) { + interval = SMB_IDLE_EVENT_DEFAULT_INTERVAL; + } else if (event->interval >= SMB_IDLE_EVENT_MIN_INTERVAL) { interval = event->interval; } else { interval = SMB_IDLE_EVENT_MIN_INTERVAL; } if (now >(event->lastrun+interval)) { - event->fn(&event->data,&event->interval,now); event->lastrun = now; + event->fn(&event->data,&event->interval,now); } - event = event->next; + event = next; } return; -- cgit From f4525f46ce0e807f11ad3eaeee10fb57bdd175bf Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 18 Sep 2003 01:17:20 +0000 Subject: Fix for #470 - unable to display SIDs in ACLs. Jeremy. (This used to be commit 1b343f710550a39815001c668c48d9b194f19243) --- source3/passdb/passdb.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'source3') diff --git a/source3/passdb/passdb.c b/source3/passdb/passdb.c index 1dadee8a49..743ea823bf 100644 --- a/source3/passdb/passdb.c +++ b/source3/passdb/passdb.c @@ -1073,8 +1073,16 @@ DOM_SID *local_uid_to_sid(DOM_SID *psid, uid_t uid) unix_pw = sys_getpwuid( uid ); if ( !unix_pw ) { - DEBUG(4,("local_uid_to_sid: host has know idea of uid %lu\n", (unsigned long)uid)); - return NULL; + DEBUG(4,("local_uid_to_sid: host has no idea of uid %lu\n", (unsigned long)uid)); + + if ( !lp_enable_rid_algorithm() ) + return NULL; + + DEBUG(8,("local_uid_to_sid: falling back to RID algorithm\n")); + + sid_copy( psid, get_global_sam_sid() ); + sid_append_rid( psid, fallback_pdb_uid_to_user_rid(uid) ); + goto out; } if ( !NT_STATUS_IS_OK(pdb_init_sam(&sampw)) ) { @@ -1101,6 +1109,7 @@ DOM_SID *local_uid_to_sid(DOM_SID *psid, uid_t uid) sid_append_rid( psid, fallback_pdb_uid_to_user_rid(uid) ); } +out: DEBUG(10,("local_uid_to_sid: uid (%d) -> SID %s (%s).\n", (unsigned int)uid, sid_string_static(psid), unix_pw->pw_name)); -- cgit From 8e0a88b7e2f84175860225363ff17584e6e1ddd4 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 18 Sep 2003 21:19:43 +0000 Subject: Oops. Proper fix for #470. Jeremy. (This used to be commit e121a2ec0c243477ea318d573166f342abbd1cce) --- source3/passdb/passdb.c | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) (limited to 'source3') diff --git a/source3/passdb/passdb.c b/source3/passdb/passdb.c index 743ea823bf..78f36eb9b6 100644 --- a/source3/passdb/passdb.c +++ b/source3/passdb/passdb.c @@ -1060,6 +1060,24 @@ BOOL local_password_change(const char *user_name, int local_flags, return True; } +/**************************************************************************** + Convert a uid to SID - algorithmic. +****************************************************************************/ + +static DOM_SID *algorithmic_uid_to_sid(DOM_SID *psid, uid_t uid) +{ + if ( !lp_enable_rid_algorithm() ) + return NULL; + + DEBUG(8,("algorithmic_uid_to_sid: falling back to RID algorithm\n")); + sid_copy( psid, get_global_sam_sid() ); + sid_append_rid( psid, fallback_pdb_uid_to_user_rid(uid) ); + DEBUG(10,("algorithmic_uid_to_sid: uid (%d) -> SID %s.\n", + (unsigned int)uid, sid_string_static(psid) )); + + return psid; +} + /**************************************************************************** Convert a uid to SID - locally. ****************************************************************************/ @@ -1074,15 +1092,7 @@ DOM_SID *local_uid_to_sid(DOM_SID *psid, uid_t uid) if ( !unix_pw ) { DEBUG(4,("local_uid_to_sid: host has no idea of uid %lu\n", (unsigned long)uid)); - - if ( !lp_enable_rid_algorithm() ) - return NULL; - - DEBUG(8,("local_uid_to_sid: falling back to RID algorithm\n")); - - sid_copy( psid, get_global_sam_sid() ); - sid_append_rid( psid, fallback_pdb_uid_to_user_rid(uid) ); - goto out; + return algorithmic_uid_to_sid( psid, uid); } if ( !NT_STATUS_IS_OK(pdb_init_sam(&sampw)) ) { @@ -1099,18 +1109,10 @@ DOM_SID *local_uid_to_sid(DOM_SID *psid, uid_t uid) else { DEBUG(4,("local_uid_to_sid: User %s [uid == %lu] has no samba account\n", unix_pw->pw_name, (unsigned long)uid)); - - if ( !lp_enable_rid_algorithm() ) - return NULL; - DEBUG(8,("local_uid_to_sid: falling back to RID algorithm\n")); - - sid_copy( psid, get_global_sam_sid() ); - sid_append_rid( psid, fallback_pdb_uid_to_user_rid(uid) ); + return algorithmic_uid_to_sid( psid, uid); } -out: - DEBUG(10,("local_uid_to_sid: uid (%d) -> SID %s (%s).\n", (unsigned int)uid, sid_string_static(psid), unix_pw->pw_name)); -- cgit From 30fd3599143260ee6893a5125e7ec7cec8bb2289 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 18 Sep 2003 23:54:12 +0000 Subject: The "unknown_5" 32 bit field in the user structs is actually 2 16-bit fields, bad_password_count and logon_count. Ensure this is stored/fetched in the various SAMs. As it replaces the unknown_5 field this fits exactly into the tdb SAM without any binary problems. It also is added to the LDAP SAM as two extra attributes. It breaks compatibility with the experimental SAMs xml and mysql. The maintainers of these SAMs must fix them so upgrades like this can be done transparently. I will insist on the "experimental" status until this is solved. Jeremy. (This used to be commit 71ecd10181cd35313b79f618c2928c2f45424812) --- source3/include/passdb.h | 8 ++++++-- source3/include/rpc_samr.h | 8 ++++++-- source3/include/smbldap.h | 2 ++ source3/passdb/passdb.c | 20 +++++++++++++------- source3/passdb/pdb_get_set.c | 30 ++++++++++++++++++++++++------ source3/passdb/pdb_ldap.c | 20 +++++++++++++++++++- source3/passdb/pdb_mysql.c | 16 ++++++++++------ source3/passdb/pdb_xml.c | 12 +++++++++--- source3/rpc_parse/parse_samr.c | 36 ++++++++++++++++++++---------------- source3/rpc_server/srv_samr_util.c | 26 ++++++++++++++++++-------- source3/rpcclient/cmd_samr.c | 3 ++- 11 files changed, 129 insertions(+), 52 deletions(-) (limited to 'source3') diff --git a/source3/include/passdb.h b/source3/include/passdb.h index e3077eee70..a4b2bcff3f 100644 --- a/source3/include/passdb.h +++ b/source3/include/passdb.h @@ -57,7 +57,8 @@ enum pdb_elements { PDB_MUNGEDDIAL, PDB_HOURS, PDB_UNKNOWN3, - PDB_UNKNOWN5, + PDB_BAD_PASSWORD_COUNT, + PDB_LOGON_COUNT, PDB_UNKNOWN6, PDB_LMPASSWD, PDB_NTPASSWD, @@ -136,7 +137,10 @@ typedef struct sam_passwd uint32 hours_len; /* normally 21 bytes */ uint8 hours[MAX_HOURS_LEN]; - uint32 unknown_5; /* 0x0002 0000 */ + /* Was unknown_5. */ + uint16 bad_password_count; + uint16 logon_count; + uint32 unknown_6; /* 0x0000 04ec */ /* a tag for who added the private methods */ const struct pdb_methods *backend_private_methods; diff --git a/source3/include/rpc_samr.h b/source3/include/rpc_samr.h index 4d9ad0b2e1..3b81042df3 100644 --- a/source3/include/rpc_samr.h +++ b/source3/include/rpc_samr.h @@ -189,7 +189,9 @@ typedef struct sam_user_info_23 /* uint8 pad[2] */ uint32 ptr_logon_hrs; /* pointer to logon hours */ - uint32 unknown_5; /* 0x0001 0000 */ + /* Was unknown_5. */ + uint16 bad_password_count; + uint16 logon_count; uint8 padding1[6]; @@ -312,7 +314,9 @@ typedef struct sam_user_info_21 /* uint8 pad[2] */ uint32 ptr_logon_hrs; /* unknown pointer */ - uint32 unknown_5; /* 0x0002 0000 */ + /* Was unknown_5. */ + uint16 bad_password_count; + uint16 logon_count; uint8 padding1[6]; diff --git a/source3/include/smbldap.h b/source3/include/smbldap.h index 826fc3c55a..9765b9fbd6 100644 --- a/source3/include/smbldap.h +++ b/source3/include/smbldap.h @@ -88,6 +88,8 @@ #define LDAP_ATTR_SID 32 #define LDAP_ATTR_ALGORITHMIC_RID_BASE 33 #define LDAP_ATTR_NEXT_RID 34 +#define LDAP_ATTR_BAD_PASSWORD_COUNT 35 +#define LDAP_ATTR_LOGON_COUNT 36 typedef struct _attrib_map_entry { int attrib; diff --git a/source3/passdb/passdb.c b/source3/passdb/passdb.c index 78f36eb9b6..cdbda38983 100644 --- a/source3/passdb/passdb.c +++ b/source3/passdb/passdb.c @@ -83,7 +83,8 @@ void pdb_fill_default_sam(SAM_ACCOUNT *user) user->private.logon_divs = 168; /* hours per week */ user->private.hours_len = 21; /* 21 times 8 bits = 168 */ memset(user->private.hours, 0xff, user->private.hours_len); /* available at all hours */ - user->private.unknown_5 = 0x00000000; /* don't know */ + user->private.bad_password_count = 0; + user->private.logon_count = 0; user->private.unknown_6 = 0x000004ec; /* don't know */ /* Some parts of samba strlen their pdb_get...() returns, @@ -1280,7 +1281,7 @@ BOOL local_sid_to_gid(gid_t *pgid, const DOM_SID *psid, enum SID_NAME_USE *name_ Marshall/unmarshall SAM_ACCOUNT structs. *********************************************************************/ -#define TDB_FORMAT_STRING "ddddddBBBBBBBBBBBBddBBwdwdBdd" +#define TDB_FORMAT_STRING "ddddddBBBBBBBBBBBBddBBwdwdBwwd" /********************************************************************** Intialize a SAM_ACCOUNT struct from a BYTE buffer of size len @@ -1315,8 +1316,9 @@ BOOL init_sam_from_buffer(SAM_ACCOUNT *sampass, uint8 *buf, uint32 buflen) fullname_len, homedir_len, logon_script_len, profile_path_len, acct_desc_len, workstations_len; - uint32 user_rid, group_rid, unknown_3, hours_len, unknown_5, unknown_6; + uint32 user_rid, group_rid, unknown_3, hours_len, unknown_6; uint16 acct_ctrl, logon_divs; + uint16 bad_password_count, logon_count; uint8 *hours; static uint8 *lm_pw_ptr, *nt_pw_ptr; uint32 len = 0; @@ -1357,7 +1359,8 @@ BOOL init_sam_from_buffer(SAM_ACCOUNT *sampass, uint8 *buf, uint32 buflen) &logon_divs, &hours_len, &hourslen, &hours, - &unknown_5, + &bad_password_count, + &logon_count, &unknown_6); if (len == -1) { @@ -1432,7 +1435,8 @@ BOOL init_sam_from_buffer(SAM_ACCOUNT *sampass, uint8 *buf, uint32 buflen) pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET); pdb_set_unknown_3(sampass, unknown_3, PDB_SET); pdb_set_hours_len(sampass, hours_len, PDB_SET); - pdb_set_unknown_5(sampass, unknown_5, PDB_SET); + pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET); + pdb_set_logon_count(sampass, logon_count, PDB_SET); pdb_set_unknown_6(sampass, unknown_6, PDB_SET); pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET); pdb_set_logon_divs(sampass, logon_divs, PDB_SET); @@ -1640,7 +1644,8 @@ uint32 init_buffer_from_sam (uint8 **buf, const SAM_ACCOUNT *sampass, BOOL size_ pdb_get_logon_divs(sampass), pdb_get_hours_len(sampass), MAX_HOURS_LEN, pdb_get_hours(sampass), - pdb_get_unknown_5(sampass), + pdb_get_bad_password_count(sampass), + pdb_get_logon_count(sampass), pdb_get_unknown_6(sampass)); @@ -1682,7 +1687,8 @@ uint32 init_buffer_from_sam (uint8 **buf, const SAM_ACCOUNT *sampass, BOOL size_ pdb_get_logon_divs(sampass), pdb_get_hours_len(sampass), MAX_HOURS_LEN, pdb_get_hours(sampass), - pdb_get_unknown_5(sampass), + pdb_get_bad_password_count(sampass), + pdb_get_logon_count(sampass), pdb_get_unknown_6(sampass)); diff --git a/source3/passdb/pdb_get_set.c b/source3/passdb/pdb_get_set.c index 1505458551..9c2b7e4c70 100644 --- a/source3/passdb/pdb_get_set.c +++ b/source3/passdb/pdb_get_set.c @@ -314,12 +314,20 @@ uint32 pdb_get_unknown_3 (const SAM_ACCOUNT *sampass) return (-1); } -uint32 pdb_get_unknown_5 (const SAM_ACCOUNT *sampass) +uint16 pdb_get_bad_password_count(const SAM_ACCOUNT *sampass) { if (sampass) - return (sampass->private.unknown_5); + return (sampass->private.bad_password_count); else - return (-1); + return 0; +} + +uint16 pdb_get_logon_count(const SAM_ACCOUNT *sampass) +{ + if (sampass) + return (sampass->private.logon_count); + else + return 0; } uint32 pdb_get_unknown_6 (const SAM_ACCOUNT *sampass) @@ -984,14 +992,24 @@ BOOL pdb_set_unknown_3 (SAM_ACCOUNT *sampass, uint32 unkn, enum pdb_value_state return pdb_set_init_flags(sampass, PDB_UNKNOWN3, flag); } -BOOL pdb_set_unknown_5 (SAM_ACCOUNT *sampass, uint32 unkn, enum pdb_value_state flag) +BOOL pdb_set_bad_password_count(SAM_ACCOUNT *sampass, uint16 bad_password_count, enum pdb_value_state flag) +{ + if (!sampass) + return False; + + sampass->private.bad_password_count = bad_password_count; + + return pdb_set_init_flags(sampass, PDB_BAD_PASSWORD_COUNT, flag); +} + +BOOL pdb_set_logon_count(SAM_ACCOUNT *sampass, uint16 logon_count, enum pdb_value_state flag) { if (!sampass) return False; - sampass->private.unknown_5 = unkn; + sampass->private.logon_count = logon_count; - return pdb_set_init_flags(sampass, PDB_UNKNOWN5, flag); + return pdb_set_init_flags(sampass, PDB_LOGON_COUNT, flag); } BOOL pdb_set_unknown_6 (SAM_ACCOUNT *sampass, uint32 unkn, enum pdb_value_state flag) diff --git a/source3/passdb/pdb_ldap.c b/source3/passdb/pdb_ldap.c index e00631fb7d..d4de6b2e96 100644 --- a/source3/passdb/pdb_ldap.c +++ b/source3/passdb/pdb_ldap.c @@ -422,6 +422,8 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, smbntpwd[NT_HASH_LEN]; uint16 acct_ctrl = 0, logon_divs; + uint16 bad_password_count = 0, + logon_count = 0; uint32 hours_len; uint8 hours[MAX_HOURS_LEN]; pstring temp; @@ -704,7 +706,23 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, pdb_set_munged_dial(sampass, munged_dial, PDB_SET); /* pdb_set_unknown_3(sampass, unknown3, PDB_SET); */ - /* pdb_set_unknown_5(sampass, unknown5, PDB_SET); */ + + if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, + get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_BAD_PASSWORD_COUNT), temp)) { + /* leave as default */ + } else { + bad_password_count = (uint32) atol(temp); + pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET); + } + + if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, + get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGON_COUNT), temp)) { + /* leave as default */ + } else { + logon_count = (uint32) atol(temp); + pdb_set_logon_count(sampass, logon_count, PDB_SET); + } + /* pdb_set_unknown_6(sampass, unknown6, PDB_SET); */ pdb_set_hours(sampass, hours, PDB_SET); diff --git a/source3/passdb/pdb_mysql.c b/source3/passdb/pdb_mysql.c index 6c200be504..460e260ddc 100644 --- a/source3/passdb/pdb_mysql.c +++ b/source3/passdb/pdb_mysql.c @@ -49,7 +49,8 @@ #define CONFIG_UNKNOWN_3_DEFAULT "unknown_3" #define CONFIG_LOGON_DIVS_DEFAULT "logon_divs" #define CONFIG_HOURS_LEN_DEFAULT "hours_len" -#define CONFIG_UNKNOWN_5_DEFAULT "unknown_5" +#define CONFIG_BAD_PASSWORD_COUNT_DEFAULT "bad_password_count" +#define CONFIG_LOGON_COUNT_DEFAULT "logon_count" #define CONFIG_UNKNOWN_6_DEFAULT "unknown_6" #define CONFIG_HOST_DEFAULT "localhost" #define CONFIG_USER_DEFAULT "samba" @@ -259,8 +260,9 @@ static NTSTATUS row_to_sam_account(MYSQL_RES * r, SAM_ACCOUNT * u) pdb_set_unknown_3(u, xatol(row[24]), PDB_SET); pdb_set_logon_divs(u, xatol(row[25]), PDB_SET); pdb_set_hours_len(u, xatol(row[26]), PDB_SET); - pdb_set_unknown_5(u, xatol(row[27]), PDB_SET); - pdb_set_unknown_6(u, xatol(row[28]), PDB_SET); + pdb_set_bad_password_count(u, xatol(row[27]), PDB_SET); + pdb_set_logon_count(u, xatol(row[28]), PDB_SET); + pdb_set_unknown_6(u, xatol(row[29]), PDB_SET); return NT_STATUS_OK; } @@ -278,7 +280,7 @@ static NTSTATUS mysqlsam_setsampwent(struct pdb_methods *methods, BOOL update) } asprintf(&query, - "SELECT %s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s FROM %s", + "SELECT %s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s FROM %s", config_value_read(data, "logon time column", CONFIG_LOGON_TIME_DEFAULT), config_value_read(data, "logoff time column", @@ -333,8 +335,10 @@ static NTSTATUS mysqlsam_setsampwent(struct pdb_methods *methods, BOOL update) CONFIG_LOGON_DIVS_DEFAULT), config_value_read(data, "hours len column", CONFIG_HOURS_LEN_DEFAULT), - config_value_read(data, "unknown 5 column", - CONFIG_UNKNOWN_5_DEFAULT), + config_value_read(data, "bad_password_count column", + CONFIG_BAD_PASSWORD_COUNT_DEFAULT), + config_value_read(data, "logon_count column", + CONFIG_LOGON_COUNT_DEFAULT), config_value_read(data, "unknown 6 column", CONFIG_UNKNOWN_6_DEFAULT), config_value(data, "table", CONFIG_TABLE_DEFAULT) diff --git a/source3/passdb/pdb_xml.c b/source3/passdb/pdb_xml.c index 7af2fdd940..29922bca4f 100644 --- a/source3/passdb/pdb_xml.c +++ b/source3/passdb/pdb_xml.c @@ -159,8 +159,13 @@ static BOOL parseUser(xmlDocPtr doc, xmlNsPtr ns, xmlNodePtr cur, SAM_ACCOUNT * atol(xmlNodeListGetString (doc, cur->xmlChildrenNode, 1)), PDB_SET); - else if (!strcmp(cur->name, "unknown_5") && cur->ns == ns) - pdb_set_unknown_5(u, + else if (!strcmp(cur->name, "bad_password_count") && cur->ns == ns) + pdb_set_bad_password_count(u, + atol(xmlNodeListGetString + (doc, cur->xmlChildrenNode, 1)), PDB_SET); + + else if (!strcmp(cur->name, "logon_count") && cur->ns == ns) + pdb_set_logon_count(u, atol(xmlNodeListGetString (doc, cur->xmlChildrenNode, 1)), PDB_SET); @@ -495,7 +500,8 @@ static NTSTATUS xmlsam_add_sam_account(struct pdb_methods *methods, SAM_ACCOUNT xmlNewChild(user, data->ns, "hours_len", iota(pdb_get_hours_len(u))); - xmlNewChild(user, data->ns, "unknown_5", iota(pdb_get_unknown_5(u))); + xmlNewChild(user, data->ns, "bad_password_count", iota(pdb_get_bad_password_count(u))); + xmlNewChild(user, data->ns, "logon_count", iota(pdb_get_logon_count(u))); xmlNewChild(user, data->ns, "unknown_6", iota(pdb_get_unknown_6(u))); xmlSaveFile(data->location, data->doc); diff --git a/source3/rpc_parse/parse_samr.c b/source3/rpc_parse/parse_samr.c index 1fe9b3231f..420a727765 100644 --- a/source3/rpc_parse/parse_samr.c +++ b/source3/rpc_parse/parse_samr.c @@ -5411,7 +5411,6 @@ static BOOL sam_io_user_info24(const char *desc, SAM_USER_INFO_24 * usr, init_sam_user_info23 unknown_3 = 0x09f8 27fa - unknown_5 = 0x0001 0000 unknown_6 = 0x0000 04ec *************************************************************************/ @@ -5438,7 +5437,8 @@ void init_sam_user_info23W(SAM_USER_INFO_23 * usr, NTTIME * logon_time, /* all z uint32 unknown_3, uint16 logon_divs, LOGON_HRS * hrs, - uint32 unknown_5, + uint16 bad_password_count, + uint16 logon_count, char newpass[516], uint32 unknown_6) { int len_user_name = user_name != NULL ? user_name->uni_str_len : 0; @@ -5487,11 +5487,11 @@ void init_sam_user_info23W(SAM_USER_INFO_23 * usr, NTTIME * logon_time, /* all z usr->passmustchange=0; } - ZERO_STRUCT(usr->padding1); ZERO_STRUCT(usr->padding2); - usr->unknown_5 = unknown_5; /* 0x0001 0000 */ + usr->bad_password_count = bad_password_count; + usr->logon_count = logon_count; memcpy(usr->pass, newpass, sizeof(usr->pass)); @@ -5516,7 +5516,6 @@ void init_sam_user_info23W(SAM_USER_INFO_23 * usr, NTTIME * logon_time, /* all z init_sam_user_info23 unknown_3 = 0x09f8 27fa - unknown_5 = 0x0001 0000 unknown_6 = 0x0000 04ec *************************************************************************/ @@ -5534,7 +5533,7 @@ void init_sam_user_info23A(SAM_USER_INFO_23 * usr, NTTIME * logon_time, /* all z char *unk_str, char *mung_dial, uint32 user_rid, /* 0x0000 0000 */ uint32 group_rid, uint32 acb_info, uint32 unknown_3, uint16 logon_divs, - LOGON_HRS * hrs, uint32 unknown_5, + LOGON_HRS * hrs, uint16 bad_password_count, uint16 logon_count, char newpass[516], uint32 unknown_6) { int len_user_name = user_name != NULL ? strlen(user_name) : 0; @@ -5586,7 +5585,8 @@ void init_sam_user_info23A(SAM_USER_INFO_23 * usr, NTTIME * logon_time, /* all z ZERO_STRUCT(usr->padding1); ZERO_STRUCT(usr->padding2); - usr->unknown_5 = unknown_5; /* 0x0001 0000 */ + usr->bad_password_count = bad_password_count; + usr->logon_count = logon_count; memcpy(usr->pass, newpass, sizeof(usr->pass)); @@ -5678,7 +5678,9 @@ static BOOL sam_io_user_info23(const char *desc, SAM_USER_INFO_23 * usr, if(!prs_uint32("ptr_logon_hrs ", ps, depth, &usr->ptr_logon_hrs)) return False; - if(!prs_uint32("unknown_5 ", ps, depth, &usr->unknown_5)) + if(!prs_uint16("bad_password_count ", ps, depth, &usr->bad_password_count)) + return False; + if(!prs_uint16("logon_count ", ps, depth, &usr->logon_count)) return False; if(!prs_uint8s(False, "padding1 ", ps, depth, usr->padding1, sizeof(usr->padding1))) @@ -5865,7 +5867,6 @@ static BOOL sam_io_user_info25(const char *desc, SAM_USER_INFO_25 * usr, prs_str init_sam_user_info21W unknown_3 = 0x00ff ffff - unknown_5 = 0x0002 0000 unknown_6 = 0x0000 04ec *************************************************************************/ @@ -5895,7 +5896,9 @@ void init_sam_user_info21W(SAM_USER_INFO_21 * usr, uint32 unknown_3, uint16 logon_divs, LOGON_HRS * hrs, - uint32 unknown_5, uint32 unknown_6) + uint16 bad_password_count, + uint16 logon_count, + uint32 unknown_6) { int len_user_name = user_name != NULL ? user_name->uni_str_len : 0; int len_full_name = full_name != NULL ? full_name->uni_str_len : 0; @@ -5936,7 +5939,8 @@ void init_sam_user_info21W(SAM_USER_INFO_21 * usr, usr->logon_divs = logon_divs; /* should be 168 (hours/week) */ usr->ptr_logon_hrs = hrs ? 1 : 0; - usr->unknown_5 = unknown_5; /* 0x0002 0000 */ + usr->bad_password_count = bad_password_count; + usr->logon_count = logon_count; if (nt_time_is_zero(pass_must_change_time)) { usr->passmustchange=PASS_MUST_CHANGE_AT_NEXT_LOGON; @@ -5944,7 +5948,6 @@ void init_sam_user_info21W(SAM_USER_INFO_21 * usr, usr->passmustchange=0; } - ZERO_STRUCT(usr->padding1); ZERO_STRUCT(usr->padding2); @@ -5969,7 +5972,6 @@ void init_sam_user_info21W(SAM_USER_INFO_21 * usr, init_sam_user_info21 unknown_3 = 0x00ff ffff - unknown_5 = 0x0002 0000 unknown_6 = 0x0000 04ec *************************************************************************/ @@ -6086,7 +6088,8 @@ NTSTATUS init_sam_user_info21A(SAM_USER_INFO_21 *usr, SAM_ACCOUNT *pw, DOM_SID * usr->logon_divs = pdb_get_logon_divs(pw); usr->ptr_logon_hrs = pdb_get_hours(pw) ? 1 : 0; - usr->unknown_5 = pdb_get_unknown_5(pw); /* 0x0002 0000 */ + usr->bad_password_count = pdb_get_bad_password_count(pw); + usr->logon_count = pdb_get_logon_count(pw); if (pdb_get_pass_must_change_time(pw) == 0) { usr->passmustchange=PASS_MUST_CHANGE_AT_NEXT_LOGON; @@ -6094,7 +6097,6 @@ NTSTATUS init_sam_user_info21A(SAM_USER_INFO_21 *usr, SAM_ACCOUNT *pw, DOM_SID * usr->passmustchange=0; } - ZERO_STRUCT(usr->padding1); ZERO_STRUCT(usr->padding2); @@ -6192,7 +6194,9 @@ static BOOL sam_io_user_info21(const char *desc, SAM_USER_INFO_21 * usr, if(!prs_uint32("ptr_logon_hrs ", ps, depth, &usr->ptr_logon_hrs)) return False; - if(!prs_uint32("unknown_5 ", ps, depth, &usr->unknown_5)) + if(!prs_uint16("bad_password_count ", ps, depth, &usr->bad_password_count)) + return False; + if(!prs_uint16("logon_count ", ps, depth, &usr->logon_count)) return False; if(!prs_uint8s(False, "padding1 ", ps, depth, usr->padding1, sizeof(usr->padding1))) diff --git a/source3/rpc_server/srv_samr_util.c b/source3/rpc_server/srv_samr_util.c index b81c441811..db6649073e 100644 --- a/source3/rpc_server/srv_samr_util.c +++ b/source3/rpc_server/srv_samr_util.c @@ -189,7 +189,7 @@ void copy_id21_to_sam_passwd(SAM_ACCOUNT *to, SAM_USER_INFO_21 *from) pdb_set_acct_ctrl(to, from->acb_info, PDB_CHANGED); } - DEBUG(10,("INFO_21 UNKOWN_3: %08X -> %08X\n",pdb_get_unknown_3(to),from->unknown_3)); + DEBUG(10,("INFO_21 UNKNOWN_3: %08X -> %08X\n",pdb_get_unknown_3(to),from->unknown_3)); if (from->unknown_3 != pdb_get_unknown_3(to)) { pdb_set_unknown_3(to, from->unknown_3, PDB_CHANGED); } @@ -208,12 +208,17 @@ void copy_id21_to_sam_passwd(SAM_ACCOUNT *to, SAM_USER_INFO_21 *from) /* Fix me: only update if it changes --metze */ pdb_set_hours(to, from->logon_hrs.hours, PDB_CHANGED); - DEBUG(10,("INFO_21 UNKOWN_5: %08X -> %08X\n",pdb_get_unknown_5(to),from->unknown_5)); - if (from->unknown_5 != pdb_get_unknown_5(to)) { - pdb_set_unknown_5(to, from->unknown_5, PDB_CHANGED); + DEBUG(10,("INFO_21 BAD_PASSWORD_COUNT: %08X -> %08X\n",pdb_get_bad_password_count(to),from->bad_password_count)); + if (from->bad_password_count != pdb_get_bad_password_count(to)) { + pdb_set_bad_password_count(to, from->bad_password_count, PDB_CHANGED); } - DEBUG(10,("INFO_21 UNKOWN_6: %08X -> %08X\n",pdb_get_unknown_6(to),from->unknown_6)); + DEBUG(10,("INFO_21 LOGON_COUNT: %08X -> %08X\n",pdb_get_logon_count(to),from->logon_count)); + if (from->logon_count != pdb_get_logon_count(to)) { + pdb_set_logon_count(to, from->logon_count, PDB_CHANGED); + } + + DEBUG(10,("INFO_21 UNKNOWN_6: %08X -> %08X\n",pdb_get_unknown_6(to),from->unknown_6)); if (from->unknown_6 != pdb_get_unknown_6(to)) { pdb_set_unknown_6(to, from->unknown_6, PDB_CHANGED); } @@ -413,9 +418,14 @@ void copy_id23_to_sam_passwd(SAM_ACCOUNT *to, SAM_USER_INFO_23 *from) /* Fix me: only update if it changes --metze */ pdb_set_hours(to, from->logon_hrs.hours, PDB_CHANGED); - DEBUG(10,("INFO_23 UNKOWN_5: %08X -> %08X\n",pdb_get_unknown_5(to),from->unknown_5)); - if (from->unknown_5 != pdb_get_unknown_5(to)) { - pdb_set_unknown_5(to, from->unknown_5, PDB_CHANGED); + DEBUG(10,("INFO_23 BAD_PASSWORD_COUNT: %08X -> %08X\n",pdb_get_bad_password_count(to),from->bad_password_count)); + if (from->bad_password_count != pdb_get_bad_password_count(to)) { + pdb_set_bad_password_count(to, from->bad_password_count, PDB_CHANGED); + } + + DEBUG(10,("INFO_23 LOGON_COUNT: %08X -> %08X\n",pdb_get_logon_count(to),from->logon_count)); + if (from->logon_count != pdb_get_logon_count(to)) { + pdb_set_logon_count(to, from->logon_count, PDB_CHANGED); } DEBUG(10,("INFO_23 UNKOWN_6: %08X -> %08X\n",pdb_get_unknown_6(to),from->unknown_6)); diff --git a/source3/rpcclient/cmd_samr.c b/source3/rpcclient/cmd_samr.c index 722d66621a..34c6fc35ab 100644 --- a/source3/rpcclient/cmd_samr.c +++ b/source3/rpcclient/cmd_samr.c @@ -85,7 +85,8 @@ static void display_sam_user_info_21(SAM_USER_INFO_21 *usr) printf("\tunknown_3:\t0x%08x\n", usr->unknown_3); /* 0x00ff ffff */ printf("\tlogon_divs:\t%d\n", usr->logon_divs); /* 0x0000 00a8 which is 168 which is num hrs in a week */ - printf("\tunknown_5:\t0x%08x\n", usr->unknown_5); /* 0x0002 0000 */ + printf("\tbad_password_count:\t0x%08x\n", usr->bad_password_count); + printf("\tlogon_count:\t0x%08x\n", usr->logon_count); printf("\tpadding1[0..7]...\n"); -- cgit From 7bb5182cf8ce3aa2b41a55083fedb8ae6d61d92a Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Fri, 19 Sep 2003 06:22:54 +0000 Subject: Merge from 3.0: >Applied Steve Langasek's patch for bug #450. (This used to be commit 50ae61b674550082e30f7156f2a9129b7abebb14) --- source3/libsmb/trusts_util.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'source3') diff --git a/source3/libsmb/trusts_util.c b/source3/libsmb/trusts_util.c index 4e02b29f92..c18641bc84 100644 --- a/source3/libsmb/trusts_util.c +++ b/source3/libsmb/trusts_util.c @@ -180,9 +180,10 @@ BOOL enumerate_domain_trusts( TALLOC_CTX *mem_ctx, const char *domain, done: /* cleanup */ - - cli_nt_session_close( cli ); - cli_shutdown( cli ); + if (cli) { + cli_nt_session_close( cli ); + cli_shutdown( cli ); + } return NT_STATUS_IS_OK(result); } -- cgit From 54b5bbb57aac951b5ee06833be6d69c66431d9bb Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Fri, 19 Sep 2003 06:23:51 +0000 Subject: Merge from 3.0: >Fix warnings on Sun cc Workshop Compilers 5.0. Reported by "Richard >Bollinger" . Also fixed script/gaptab.awk to >produce compatible tables. >Fix CP437 and CP850 syntax for old compilers removing ANSI C99-specifics (This used to be commit a9f34d9fde4ea5e043444803aeda70d5e64c3870) --- source3/modules/CP437.c | 84 ++++++++++++++++++++++++------------------------- source3/modules/CP850.c | 74 +++++++++++++++++++++---------------------- 2 files changed, 79 insertions(+), 79 deletions(-) (limited to 'source3') diff --git a/source3/modules/CP437.c b/source3/modules/CP437.c index b7e7409746..620f6cd9b6 100644 --- a/source3/modules/CP437.c +++ b/source3/modules/CP437.c @@ -89,48 +89,48 @@ static const struct charset_gap_table from_idx[] = { static const unsigned char from_ucs2[] = { - '\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07', - '\x08', '\x09', '\x0a', '\x0b', '\x0c', '\x0d', '\x0e', '\x0f', - '\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17', - '\x18', '\x19', '\x1a', '\x1b', '\x1c', '\x1d', '\x1e', '\x1f', - '\x20', '\x21', '\x22', '\x23', '\x24', '\x25', '\x26', '\x27', - '\x28', '\x29', '\x2a', '\x2b', '\x2c', '\x2d', '\x2e', '\x2f', - '\x30', '\x31', '\x32', '\x33', '\x34', '\x35', '\x36', '\x37', - '\x38', '\x39', '\x3a', '\x3b', '\x3c', '\x3d', '\x3e', '\x3f', - '\x40', '\x41', '\x42', '\x43', '\x44', '\x45', '\x46', '\x47', - '\x48', '\x49', '\x4a', '\x4b', '\x4c', '\x4d', '\x4e', '\x4f', - '\x50', '\x51', '\x52', '\x53', '\x54', '\x55', '\x56', '\x57', - '\x58', '\x59', '\x5a', '\x5b', '\x5c', '\x5d', '\x5e', '\x5f', - '\x60', '\x61', '\x62', '\x63', '\x64', '\x65', '\x66', '\x67', - '\x68', '\x69', '\x6a', '\x6b', '\x6c', '\x6d', '\x6e', '\x6f', - '\x70', '\x71', '\x72', '\x73', '\x74', '\x75', '\x76', '\x77', - '\x78', '\x79', '\x7a', '\x7b', '\x7c', '\x7d', '\x7e', '\x7f', - '\xff', '\xad', '\x9b', '\x9c', '\x00', '\x9d', '\x00', '\x00', - '\x00', '\x00', '\xa6', '\xae', '\xaa', '\x00', '\x00', '\x00', - '\xf8', '\xf1', '\xfd', '\x00', '\x00', '\xe6', '\x00', '\xfa', - '\x00', '\x00', '\xa7', '\xaf', '\xac', '\xab', '\x00', '\xa8', - '\x00', '\x00', '\x00', '\x00', '\x8e', '\x8f', '\x92', '\x80', - '\x00', '\x90', '\xa5', '\x00', '\x00', '\x00', '\x00', '\x99', - '\x00', '\x00', '\x00', '\x00', '\x00', '\x9a', '\x00', '\x00', - '\xe1', '\x85', '\xa0', '\x83', '\x00', '\x84', '\x86', '\x91', - '\x87', '\x8a', '\x82', '\x88', '\x89', '\x8d', '\xa1', '\x8c', - '\x8b', '\x00', '\xa4', '\x95', '\xa2', '\x93', '\x00', '\x94', - '\xf6', '\x00', '\x97', '\xa3', '\x96', '\x81', '\x00', '\x00', - '\x98', '\x9f', '\xe2', '\x00', '\x00', '\x00', '\x00', '\xe9', - '\xe4', '\x00', '\x00', '\xe8', '\x00', '\x00', '\xea', '\xe0', - '\x00', '\x00', '\xeb', '\xee', '\xe3', '\x00', '\x00', '\xe5', - '\xe7', '\x00', '\xed', '\xfc', '\x9e', '\xf9', '\xfb', '\x00', - '\x00', '\x00', '\xec', '\xef', '\xf7', '\xf0', '\x00', '\x00', - '\xf3', '\xf2', '\xa9', '\xf4', '\xf5', '\xc4', '\x00', '\xb3', - '\xda', '\x00', '\x00', '\x00', '\xbf', '\x00', '\x00', '\x00', - '\xc0', '\x00', '\x00', '\x00', '\xd9', '\x00', '\x00', '\x00', - '\xc3', '\xb4', '\xc2', '\xc1', '\xc5', '\xcd', '\xba', '\xd5', - '\xd6', '\xc9', '\xb8', '\xb7', '\xbb', '\xd4', '\xd3', '\xc8', - '\xbe', '\xbd', '\xbc', '\xc6', '\xc7', '\xcc', '\xb5', '\xb6', - '\xb9', '\xd1', '\xd2', '\xcb', '\xcf', '\xd0', '\xca', '\xd8', - '\xd7', '\xce', '\xdf', '\x00', '\x00', '\x00', '\xdc', '\x00', - '\x00', '\x00', '\xdb', '\x00', '\x00', '\x00', '\xdd', '\x00', - '\x00', '\x00', '\xde', '\xb0', '\xb1', '\xb2', '\xfe', + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0xff, 0xad, 0x9b, 0x9c, 0x00, 0x9d, 0x00, 0x00, + 0x00, 0x00, 0xa6, 0xae, 0xaa, 0x00, 0x00, 0x00, + 0xf8, 0xf1, 0xfd, 0x00, 0x00, 0xe6, 0x00, 0xfa, + 0x00, 0x00, 0xa7, 0xaf, 0xac, 0xab, 0x00, 0xa8, + 0x00, 0x00, 0x00, 0x00, 0x8e, 0x8f, 0x92, 0x80, + 0x00, 0x90, 0xa5, 0x00, 0x00, 0x00, 0x00, 0x99, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x9a, 0x00, 0x00, + 0xe1, 0x85, 0xa0, 0x83, 0x00, 0x84, 0x86, 0x91, + 0x87, 0x8a, 0x82, 0x88, 0x89, 0x8d, 0xa1, 0x8c, + 0x8b, 0x00, 0xa4, 0x95, 0xa2, 0x93, 0x00, 0x94, + 0xf6, 0x00, 0x97, 0xa3, 0x96, 0x81, 0x00, 0x00, + 0x98, 0x9f, 0xe2, 0x00, 0x00, 0x00, 0x00, 0xe9, + 0xe4, 0x00, 0x00, 0xe8, 0x00, 0x00, 0xea, 0xe0, + 0x00, 0x00, 0xeb, 0xee, 0xe3, 0x00, 0x00, 0xe5, + 0xe7, 0x00, 0xed, 0xfc, 0x9e, 0xf9, 0xfb, 0x00, + 0x00, 0x00, 0xec, 0xef, 0xf7, 0xf0, 0x00, 0x00, + 0xf3, 0xf2, 0xa9, 0xf4, 0xf5, 0xc4, 0x00, 0xb3, + 0xda, 0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x00, + 0xc0, 0x00, 0x00, 0x00, 0xd9, 0x00, 0x00, 0x00, + 0xc3, 0xb4, 0xc2, 0xc1, 0xc5, 0xcd, 0xba, 0xd5, + 0xd6, 0xc9, 0xb8, 0xb7, 0xbb, 0xd4, 0xd3, 0xc8, + 0xbe, 0xbd, 0xbc, 0xc6, 0xc7, 0xcc, 0xb5, 0xb6, + 0xb9, 0xd1, 0xd2, 0xcb, 0xcf, 0xd0, 0xca, 0xd8, + 0xd7, 0xce, 0xdf, 0x00, 0x00, 0x00, 0xdc, 0x00, + 0x00, 0x00, 0xdb, 0x00, 0x00, 0x00, 0xdd, 0x00, + 0x00, 0x00, 0xde, 0xb0, 0xb1, 0xb2, 0xfe, }; SMB_GENERATE_CHARSET_MODULE_8_BIT_GAP(CP437) diff --git a/source3/modules/CP850.c b/source3/modules/CP850.c index 311d651068..e6f70aa17a 100644 --- a/source3/modules/CP850.c +++ b/source3/modules/CP850.c @@ -79,43 +79,43 @@ static const struct charset_gap_table from_idx[] = { }; static const unsigned char from_ucs2[] = { - '\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07', - '\x08', '\x09', '\x0a', '\x0b', '\x0c', '\x0d', '\x0e', '\x0f', - '\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17', - '\x18', '\x19', '\x1a', '\x1b', '\x1c', '\x1d', '\x1e', '\x1f', - '\x20', '\x21', '\x22', '\x23', '\x24', '\x25', '\x26', '\x27', - '\x28', '\x29', '\x2a', '\x2b', '\x2c', '\x2d', '\x2e', '\x2f', - '\x30', '\x31', '\x32', '\x33', '\x34', '\x35', '\x36', '\x37', - '\x38', '\x39', '\x3a', '\x3b', '\x3c', '\x3d', '\x3e', '\x3f', - '\x40', '\x41', '\x42', '\x43', '\x44', '\x45', '\x46', '\x47', - '\x48', '\x49', '\x4a', '\x4b', '\x4c', '\x4d', '\x4e', '\x4f', - '\x50', '\x51', '\x52', '\x53', '\x54', '\x55', '\x56', '\x57', - '\x58', '\x59', '\x5a', '\x5b', '\x5c', '\x5d', '\x5e', '\x5f', - '\x60', '\x61', '\x62', '\x63', '\x64', '\x65', '\x66', '\x67', - '\x68', '\x69', '\x6a', '\x6b', '\x6c', '\x6d', '\x6e', '\x6f', - '\x70', '\x71', '\x72', '\x73', '\x74', '\x75', '\x76', '\x77', - '\x78', '\x79', '\x7a', '\x7b', '\x7c', '\x7d', '\x7e', '\x7f', - '\xff', '\xad', '\xbd', '\x9c', '\xcf', '\xbe', '\xdd', '\xf5', - '\xf9', '\xb8', '\xa6', '\xae', '\xaa', '\xf0', '\xa9', '\xee', - '\xf8', '\xf1', '\xfd', '\xfc', '\xef', '\xe6', '\xf4', '\xfa', - '\xf7', '\xfb', '\xa7', '\xaf', '\xac', '\xab', '\xf3', '\xa8', - '\xb7', '\xb5', '\xb6', '\xc7', '\x8e', '\x8f', '\x92', '\x80', - '\xd4', '\x90', '\xd2', '\xd3', '\xde', '\xd6', '\xd7', '\xd8', - '\xd1', '\xa5', '\xe3', '\xe0', '\xe2', '\xe5', '\x99', '\x9e', - '\x9d', '\xeb', '\xe9', '\xea', '\x9a', '\xed', '\xe8', '\xe1', - '\x85', '\xa0', '\x83', '\xc6', '\x84', '\x86', '\x91', '\x87', - '\x8a', '\x82', '\x88', '\x89', '\x8d', '\xa1', '\x8c', '\x8b', - '\xd0', '\xa4', '\x95', '\xa2', '\x93', '\xe4', '\x94', '\xf6', - '\x9b', '\x97', '\xa3', '\x96', '\x81', '\xec', '\xe7', '\x98', - '\xd5', '\x9f', '\xf2', '\xc4', '\x00', '\xb3', '\xda', '\x00', - '\x00', '\x00', '\xbf', '\x00', '\x00', '\x00', '\xc0', '\x00', - '\x00', '\x00', '\xd9', '\x00', '\x00', '\x00', '\xc3', '\xb4', - '\xc2', '\xc1', '\xc5', '\xcd', '\xba', '\x00', '\x00', '\xc9', - '\x00', '\x00', '\xbb', '\x00', '\x00', '\xc8', '\x00', '\x00', - '\xbc', '\x00', '\x00', '\xcc', '\x00', '\x00', '\xb9', '\x00', - '\x00', '\xcb', '\x00', '\x00', '\xca', '\x00', '\x00', '\xce', - '\xdf', '\x00', '\x00', '\x00', '\xdc', '\x00', '\x00', '\x00', - '\xdb', '\xb0', '\xb1', '\xb2', '\xfe', + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, + 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0xff, 0xad, 0xbd, 0x9c, 0xcf, 0xbe, 0xdd, 0xf5, + 0xf9, 0xb8, 0xa6, 0xae, 0xaa, 0xf0, 0xa9, 0xee, + 0xf8, 0xf1, 0xfd, 0xfc, 0xef, 0xe6, 0xf4, 0xfa, + 0xf7, 0xfb, 0xa7, 0xaf, 0xac, 0xab, 0xf3, 0xa8, + 0xb7, 0xb5, 0xb6, 0xc7, 0x8e, 0x8f, 0x92, 0x80, + 0xd4, 0x90, 0xd2, 0xd3, 0xde, 0xd6, 0xd7, 0xd8, + 0xd1, 0xa5, 0xe3, 0xe0, 0xe2, 0xe5, 0x99, 0x9e, + 0x9d, 0xeb, 0xe9, 0xea, 0x9a, 0xed, 0xe8, 0xe1, + 0x85, 0xa0, 0x83, 0xc6, 0x84, 0x86, 0x91, 0x87, + 0x8a, 0x82, 0x88, 0x89, 0x8d, 0xa1, 0x8c, 0x8b, + 0xd0, 0xa4, 0x95, 0xa2, 0x93, 0xe4, 0x94, 0xf6, + 0x9b, 0x97, 0xa3, 0x96, 0x81, 0xec, 0xe7, 0x98, + 0xd5, 0x9f, 0xf2, 0xc4, 0x00, 0xb3, 0xda, 0x00, + 0x00, 0x00, 0xbf, 0x00, 0x00, 0x00, 0xc0, 0x00, + 0x00, 0x00, 0xd9, 0x00, 0x00, 0x00, 0xc3, 0xb4, + 0xc2, 0xc1, 0xc5, 0xcd, 0xba, 0x00, 0x00, 0xc9, + 0x00, 0x00, 0xbb, 0x00, 0x00, 0xc8, 0x00, 0x00, + 0xbc, 0x00, 0x00, 0xcc, 0x00, 0x00, 0xb9, 0x00, + 0x00, 0xcb, 0x00, 0x00, 0xca, 0x00, 0x00, 0xce, + 0xdf, 0x00, 0x00, 0x00, 0xdc, 0x00, 0x00, 0x00, + 0xdb, 0xb0, 0xb1, 0xb2, 0xfe, }; SMB_GENERATE_CHARSET_MODULE_8_BIT_GAP(CP850) -- cgit From 8139c5fcfa6bd26ce03af41c374f84be48343666 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 19 Sep 2003 21:57:46 +0000 Subject: Ensure that dup_sec_desc copies the 'type' field correctly. This caused me to expose a type arguement to make_sec_desc(). We weren't copying the SE_DESC_DACL_AUTO_INHERITED flag which could cause errors on auto inherited checks. Jeremy. (This used to be commit 546b2271c08735ac1049a453abac996d794aa364) --- source3/lib/util_seaccess.c | 4 ++-- source3/printing/nt_printing.c | 6 +++--- source3/python/py_ntsec.c | 2 +- source3/rpc_parse/parse_sec.c | 20 +++++++++++--------- source3/rpc_server/srv_lsa_nt.c | 2 +- source3/rpc_server/srv_samr_nt.c | 8 ++++---- source3/rpc_server/srv_srvsvc_nt.c | 2 +- source3/utils/smbcacls.c | 6 +++--- 8 files changed, 26 insertions(+), 24 deletions(-) (limited to 'source3') diff --git a/source3/lib/util_seaccess.c b/source3/lib/util_seaccess.c index eba8cab7fb..2482d582d2 100644 --- a/source3/lib/util_seaccess.c +++ b/source3/lib/util_seaccess.c @@ -435,7 +435,7 @@ SEC_DESC_BUF *se_create_child_secdesc(TALLOC_CTX *ctx, SEC_DESC *parent_ctr, correct. Perhaps the user and group should be passed in as parameters by the caller? */ - sd = make_sec_desc(ctx, SEC_DESC_REVISION, + sd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, parent_ctr->owner_sid, parent_ctr->grp_sid, parent_ctr->sacl, @@ -479,7 +479,7 @@ NTSTATUS samr_make_sam_obj_sd(TALLOC_CTX *ctx, SEC_DESC **psd, size_t *sd_size) 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) + if ((*psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL, psa, sd_size)) == NULL) return NT_STATUS_NO_MEMORY; return NT_STATUS_OK; diff --git a/source3/printing/nt_printing.c b/source3/printing/nt_printing.c index 868f68c079..9c95cf9085 100644 --- a/source3/printing/nt_printing.c +++ b/source3/printing/nt_printing.c @@ -4572,7 +4572,7 @@ WERROR nt_printing_setsec(const char *printername, SEC_DESC_BUF *secdesc_ctr) /* Make a deep copy of the security descriptor */ - psd = make_sec_desc(mem_ctx, secdesc_ctr->sec->revision, + psd = make_sec_desc(mem_ctx, secdesc_ctr->sec->revision, secdesc_ctr->sec->type, owner_sid, group_sid, sacl, dacl, @@ -4665,7 +4665,7 @@ static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx) NT5 machine. */ if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 3, ace)) != NULL) { - psd = make_sec_desc(ctx, SEC_DESC_REVISION, + psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, &owner_sid, NULL, NULL, psa, &sd_size); } @@ -4741,7 +4741,7 @@ BOOL nt_printing_getsec(TALLOC_CTX *ctx, const char *printername, SEC_DESC_BUF * sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN); - psd = make_sec_desc(ctx, (*secdesc_ctr)->sec->revision, + psd = make_sec_desc(ctx, (*secdesc_ctr)->sec->revision, (*secdesc_ctr)->sec->type, &owner_sid, (*secdesc_ctr)->sec->grp_sid, (*secdesc_ctr)->sec->sacl, diff --git a/source3/python/py_ntsec.c b/source3/python/py_ntsec.c index 3d408e0bda..5ce5e8fc1b 100644 --- a/source3/python/py_ntsec.c +++ b/source3/python/py_ntsec.c @@ -276,7 +276,7 @@ BOOL py_to_SECDESC(SEC_DESC **sd, PyObject *dict, TALLOC_CTX *mem_ctx) { size_t sd_size; - *sd = make_sec_desc(mem_ctx, revision, + *sd = make_sec_desc(mem_ctx, revision, SEC_DESC_SELF_RELATIVE, got_owner_sid ? &owner_sid : NULL, got_group_sid ? &group_sid : NULL, got_sacl ? &sacl : NULL, diff --git a/source3/rpc_parse/parse_sec.c b/source3/rpc_parse/parse_sec.c index 3848bd7051..0ed930c08d 100644 --- a/source3/rpc_parse/parse_sec.c +++ b/source3/rpc_parse/parse_sec.c @@ -561,7 +561,7 @@ SEC_DESC_BUF *sec_desc_merge(TALLOC_CTX *ctx, SEC_DESC_BUF *new_sdb, SEC_DESC_BU /* Create new security descriptor from bits */ - psd = make_sec_desc(ctx, new_sdb->sec->revision, + psd = make_sec_desc(ctx, new_sdb->sec->revision, secdesc_type, owner_sid, group_sid, sacl, dacl, &secdesc_size); return_sdb = make_sec_desc_buf(ctx, secdesc_size, psd); @@ -573,7 +573,7 @@ SEC_DESC_BUF *sec_desc_merge(TALLOC_CTX *ctx, SEC_DESC_BUF *new_sdb, SEC_DESC_BU Creates a SEC_DESC structure ********************************************************************/ -SEC_DESC *make_sec_desc(TALLOC_CTX *ctx, uint16 revision, +SEC_DESC *make_sec_desc(TALLOC_CTX *ctx, uint16 revision, uint16 type, DOM_SID *owner_sid, DOM_SID *grp_sid, SEC_ACL *sacl, SEC_ACL *dacl, size_t *sd_size) { @@ -586,10 +586,12 @@ SEC_DESC *make_sec_desc(TALLOC_CTX *ctx, uint16 revision, return NULL; dst->revision = revision; - dst->type = SEC_DESC_SELF_RELATIVE; + dst->type = type; - if (sacl) dst->type |= SEC_DESC_SACL_PRESENT; - if (dacl) dst->type |= SEC_DESC_DACL_PRESENT; + if (sacl) + dst->type |= SEC_DESC_SACL_PRESENT; + if (dacl) + dst->type |= SEC_DESC_DACL_PRESENT; dst->off_owner_sid = 0; dst->off_grp_sid = 0; @@ -654,7 +656,7 @@ SEC_DESC *dup_sec_desc( TALLOC_CTX *ctx, SEC_DESC *src) if(src == NULL) return NULL; - return make_sec_desc( ctx, src->revision, + return make_sec_desc( ctx, src->revision, src->type, src->owner_sid, src->grp_sid, src->sacl, src->dacl, &dummy); } @@ -666,7 +668,7 @@ SEC_DESC *dup_sec_desc( TALLOC_CTX *ctx, SEC_DESC *src) SEC_DESC *make_standard_sec_desc(TALLOC_CTX *ctx, DOM_SID *owner_sid, DOM_SID *grp_sid, SEC_ACL *dacl, size_t *sd_size) { - return make_sec_desc(ctx, SEC_DESC_REVISION, + return make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, owner_sid, grp_sid, NULL, dacl, sd_size); } @@ -924,7 +926,7 @@ NTSTATUS sec_desc_add_sid(TALLOC_CTX *ctx, SEC_DESC **psd, DOM_SID *sid, uint32 if (!(dacl = make_sec_acl(ctx, psd[0]->dacl->revision, psd[0]->dacl->num_aces, ace))) return NT_STATUS_UNSUCCESSFUL; - if (!(sd = make_sec_desc(ctx, psd[0]->revision, psd[0]->owner_sid, + if (!(sd = make_sec_desc(ctx, psd[0]->revision, psd[0]->type, psd[0]->owner_sid, psd[0]->grp_sid, psd[0]->sacl, dacl, sd_size))) return NT_STATUS_UNSUCCESSFUL; @@ -976,7 +978,7 @@ NTSTATUS sec_desc_del_sid(TALLOC_CTX *ctx, SEC_DESC **psd, DOM_SID *sid, size_t if (!(dacl = make_sec_acl(ctx, psd[0]->dacl->revision, psd[0]->dacl->num_aces, ace))) return NT_STATUS_UNSUCCESSFUL; - if (!(sd = make_sec_desc(ctx, psd[0]->revision, psd[0]->owner_sid, + if (!(sd = make_sec_desc(ctx, psd[0]->revision, psd[0]->type, psd[0]->owner_sid, psd[0]->grp_sid, psd[0]->sacl, dacl, sd_size))) return NT_STATUS_UNSUCCESSFUL; diff --git a/source3/rpc_server/srv_lsa_nt.c b/source3/rpc_server/srv_lsa_nt.c index 330dd727ef..686a3069bb 100644 --- a/source3/rpc_server/srv_lsa_nt.c +++ b/source3/rpc_server/srv_lsa_nt.c @@ -334,7 +334,7 @@ static NTSTATUS lsa_get_generic_sd(TALLOC_CTX *mem_ctx, SEC_DESC **sd, size_t *s if((psa = make_sec_acl(mem_ctx, NT4_ACL_REVISION, 3, ace)) == NULL) return NT_STATUS_NO_MEMORY; - if((*sd = make_sec_desc(mem_ctx, SEC_DESC_REVISION, &adm_sid, NULL, NULL, psa, sd_size)) == NULL) + if((*sd = make_sec_desc(mem_ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, &adm_sid, NULL, NULL, psa, sd_size)) == NULL) return NT_STATUS_NO_MEMORY; return NT_STATUS_OK; diff --git a/source3/rpc_server/srv_samr_nt.c b/source3/rpc_server/srv_samr_nt.c index 261d641ab1..828e07c1ad 100644 --- a/source3/rpc_server/srv_samr_nt.c +++ b/source3/rpc_server/srv_samr_nt.c @@ -467,7 +467,7 @@ static NTSTATUS samr_make_dom_obj_sd(TALLOC_CTX *ctx, SEC_DESC **psd, size_t *sd 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) + if ((*psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL, psa, sd_size)) == NULL) return NT_STATUS_NO_MEMORY; return NT_STATUS_OK; @@ -510,7 +510,7 @@ static NTSTATUS samr_make_usr_obj_sd(TALLOC_CTX *ctx, SEC_DESC **psd, size_t *sd if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 4, ace)) == NULL) return NT_STATUS_NO_MEMORY; - if ((*psd = make_sec_desc(ctx, SEC_DESC_REVISION, NULL, NULL, NULL, psa, sd_size)) == NULL) + if ((*psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL, psa, sd_size)) == NULL) return NT_STATUS_NO_MEMORY; return NT_STATUS_OK; @@ -549,7 +549,7 @@ static NTSTATUS samr_make_grp_obj_sd(TALLOC_CTX *ctx, SEC_DESC **psd, size_t *sd 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) + if ((*psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL, psa, sd_size)) == NULL) return NT_STATUS_NO_MEMORY; return NT_STATUS_OK; @@ -588,7 +588,7 @@ static NTSTATUS samr_make_ali_obj_sd(TALLOC_CTX *ctx, SEC_DESC **psd, size_t *sd 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) + if ((*psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL, psa, sd_size)) == NULL) return NT_STATUS_NO_MEMORY; return NT_STATUS_OK; diff --git a/source3/rpc_server/srv_srvsvc_nt.c b/source3/rpc_server/srv_srvsvc_nt.c index ea66a7d38b..4d1cf9bddc 100644 --- a/source3/rpc_server/srv_srvsvc_nt.c +++ b/source3/rpc_server/srv_srvsvc_nt.c @@ -184,7 +184,7 @@ static SEC_DESC *get_share_security_default( TALLOC_CTX *ctx, int snum, size_t * init_sec_ace(&ace, &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, sa, 0); if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 1, &ace)) != NULL) { - psd = make_sec_desc(ctx, SEC_DESC_REVISION, NULL, NULL, NULL, psa, psize); + psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL, psa, psize); } if (!psd) { diff --git a/source3/utils/smbcacls.c b/source3/utils/smbcacls.c index 58ee57b5dd..5a70d16884 100644 --- a/source3/utils/smbcacls.c +++ b/source3/utils/smbcacls.c @@ -389,7 +389,7 @@ static SEC_DESC *sec_desc_parse(char *str) return NULL; } - ret = make_sec_desc(ctx,revision, owner_sid, grp_sid, + ret = make_sec_desc(ctx,revision, SEC_DESC_SELF_RELATIVE, owner_sid, grp_sid, NULL, dacl, &sd_size); SAFE_FREE(grp_sid); @@ -504,7 +504,7 @@ static int owner_set(struct cli_state *cli, enum chown_mode change_mode, return EXIT_FAILED; } - sd = make_sec_desc(ctx,old->revision, + sd = make_sec_desc(ctx,old->revision, old->type, (change_mode == REQUEST_CHOWN) ? &sid : NULL, (change_mode == REQUEST_CHGRP) ? &sid : NULL, NULL, NULL, &sd_size); @@ -679,7 +679,7 @@ static int cacl_set(struct cli_state *cli, char *filename, sort_acl(old->dacl); /* Create new security descriptor and set it */ - sd = make_sec_desc(ctx,old->revision, NULL, NULL, + sd = make_sec_desc(ctx,old->revision, old->type, NULL, NULL, NULL, old->dacl, &sd_size); fnum = cli_nt_create(cli, filename, WRITE_DAC_ACCESS); -- cgit From 2862f64374143e43ffe271ea22cfc73e43bc891b Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 21 Sep 2003 03:14:05 +0000 Subject: Fix typo (This used to be commit 68e044f60ddb6dc7d894f95eff8a866e713df253) --- source3/utils/pdbedit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3') diff --git a/source3/utils/pdbedit.c b/source3/utils/pdbedit.c index 0f1f6edf08..c69b149469 100644 --- a/source3/utils/pdbedit.c +++ b/source3/utils/pdbedit.c @@ -409,7 +409,7 @@ static int new_user (struct pdb_context *in, const char *username, if (NT_STATUS_IS_OK(in->pdb_add_sam_account (in, sam_pwent))) { print_user_info (in, username, True, False); } else { - fprintf (stderr, "Unable to add user! (does it alredy exist?)\n"); + fprintf (stderr, "Unable to add user! (does it already exist?)\n"); pdb_free_sam (&sam_pwent); return -1; } -- cgit From 8031b1655c41a9feecd064f7a125c1dcacb4a292 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 21 Sep 2003 03:16:05 +0000 Subject: Fix bug and do more error checking. Noticed by Wilco Baan Hofman (This used to be commit ec32501cefe1ea27bcf08b5be9d53cdce8cbbbdc) --- source3/passdb/pdb_mysql.c | 46 +++++++++++++++++++++++++++++++++------------- 1 file changed, 33 insertions(+), 13 deletions(-) (limited to 'source3') diff --git a/source3/passdb/pdb_mysql.c b/source3/passdb/pdb_mysql.c index 460e260ddc..7c2c56e359 100644 --- a/source3/passdb/pdb_mysql.c +++ b/source3/passdb/pdb_mysql.c @@ -156,7 +156,7 @@ static const char * config_value_write(pdb_mysql_data * data, const char *name, if (!v) return NULL; - swrite = strchr(v, ':'); + swrite = strrchr(v, ':'); /* Default to the same field as read field */ if (!swrite) @@ -182,7 +182,7 @@ static const char * config_value_read(pdb_mysql_data * data, const char *name, c if (!v) return "NULL"; - swrite = strchr(v, ':'); + swrite = strrchr(v, ':'); /* If no write is specified, there are no problems */ if (!swrite) { @@ -241,14 +241,20 @@ static NTSTATUS row_to_sam_account(MYSQL_RES * r, SAM_ACCOUNT * u) pdb_set_unknown_str(u, row[16], PDB_SET); pdb_set_munged_dial(u, row[17], PDB_SET); - if(row[18])string_to_sid(&sid, row[18]); - pdb_set_user_sid(u, &sid, PDB_SET); - if(row[19])string_to_sid(&sid, row[19]); - pdb_set_group_sid(u, &sid, PDB_SET); + if(!row[18] || !string_to_sid(&sid, row[18])) { + DEBUG(0,("No user SID retrieved from database!\n")); + } else { + pdb_set_user_sid(u, &sid, PDB_SET); + } + + if(row[19]) { + string_to_sid(&sid, row[19]); + pdb_set_group_sid(u, &sid, PDB_SET); + } - if (pdb_gethexpwd(row[20], temp), PDB_SET) + if (pdb_gethexpwd(row[20], temp)) pdb_set_lanman_passwd(u, temp, PDB_SET); - if (pdb_gethexpwd(row[21], temp), PDB_SET) + if (pdb_gethexpwd(row[21], temp)) pdb_set_nt_passwd(u, temp, PDB_SET); /* Only use plaintext password storage when lanman and nt are @@ -335,9 +341,9 @@ static NTSTATUS mysqlsam_setsampwent(struct pdb_methods *methods, BOOL update) CONFIG_LOGON_DIVS_DEFAULT), config_value_read(data, "hours len column", CONFIG_HOURS_LEN_DEFAULT), - config_value_read(data, "bad_password_count column", + config_value_read(data, "bad password count column", CONFIG_BAD_PASSWORD_COUNT_DEFAULT), - config_value_read(data, "logon_count column", + config_value_read(data, "logon count column", CONFIG_LOGON_COUNT_DEFAULT), config_value_read(data, "unknown 6 column", CONFIG_UNKNOWN_6_DEFAULT), @@ -446,7 +452,7 @@ static NTSTATUS mysqlsam_select_by_field(struct pdb_methods * methods, SAM_ACCOU } asprintf(&query, - "SELECT %s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s FROM %s WHERE %s = '%s'", + "SELECT %s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s FROM %s WHERE %s = '%s'", config_value_read(data, "logon time column", CONFIG_LOGON_TIME_DEFAULT), config_value_read(data, "logoff time column", @@ -501,8 +507,10 @@ static NTSTATUS mysqlsam_select_by_field(struct pdb_methods * methods, SAM_ACCOU CONFIG_LOGON_DIVS_DEFAULT), config_value_read(data, "hours len column", CONFIG_HOURS_LEN_DEFAULT), - config_value_read(data, "unknown 5 column", - CONFIG_UNKNOWN_5_DEFAULT), + config_value_read(data, "bad password count column", + CONFIG_BAD_PASSWORD_COUNT_DEFAULT), + config_value_read(data, "logon count column", + CONFIG_LOGON_COUNT_DEFAULT), config_value_read(data, "unknown 6 column", CONFIG_UNKNOWN_6_DEFAULT), config_value(data, "table", CONFIG_TABLE_DEFAULT), field, @@ -649,6 +657,7 @@ static NTSTATUS mysqlsam_replace_sam_account(struct pdb_methods *methods, const SAM_ACCOUNT * newpwd, char isupdate) { pstring temp; + char *field; struct pdb_mysql_data *data; pdb_mysql_query query; fstring sid_str; @@ -659,6 +668,7 @@ static NTSTATUS mysqlsam_replace_sam_account(struct pdb_methods *methods, } data = (struct pdb_mysql_data *) methods->private_data; + if (data == NULL || data->handle == NULL) { DEBUG(0, ("invalid handle!\n")); return NT_STATUS_INVALID_HANDLE; @@ -876,6 +886,7 @@ static NTSTATUS mysqlsam_init(struct pdb_context * pdb_context, struct pdb_metho { NTSTATUS nt_status; struct pdb_mysql_data *data; + const char *sid_column, *username_column; mysqlsam_debug_level = debug_add_class("mysqlsam"); if (mysqlsam_debug_level == -1) { @@ -884,6 +895,7 @@ static NTSTATUS mysqlsam_init(struct pdb_context * pdb_context, struct pdb_metho ("mysqlsam: Couldn't register custom debugging class!\n")); } + if (!pdb_context) { DEBUG(0, ("invalid pdb_methods specified\n")); return NT_STATUS_UNSUCCESSFUL; @@ -931,6 +943,14 @@ static NTSTATUS mysqlsam_init(struct pdb_context * pdb_context, struct pdb_metho DEBUG(0, ("Failed to connect to server\n")); return NT_STATUS_UNSUCCESSFUL; } + + sid_column = config_value_read(data, "user sid column", CONFIG_USER_SID_DEFAULT); + username_column = config_value_read(data, "username column", CONFIG_USERNAME_DEFAULT); + if(!strcmp(sid_column,"NULL") || !strcmp(username_column, "NULL")) { + DEBUG(0,("Please specify both a valid 'user sid column' and a valid 'username column' in smb.conf\n")); + return NT_STATUS_UNSUCCESSFUL; + } + /* Process correct entry in $HOME/.my.conf */ if (!mysql_real_connect(data->handle, config_value(data, "mysql host", CONFIG_HOST_DEFAULT), -- cgit From 492072314b12f09b85353be971a0ab7d1329b179 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Mon, 22 Sep 2003 17:54:34 +0000 Subject: fix some warnings found by the Sun C compiler (This used to be commit 585764305aa84a7732f71f2e01227e1a6a08664f) --- source3/lib/util_unistr.c | 2 +- source3/msdfs/msdfs.c | 2 +- source3/nsswitch/winbindd_util.c | 1 - source3/rpc_client/cli_samr.c | 2 +- source3/tdb/tdbutil.c | 4 ++-- source3/utils/net_groupmap.c | 5 ++--- source3/utils/net_rpc.c | 2 +- 7 files changed, 8 insertions(+), 10 deletions(-) (limited to 'source3') diff --git a/source3/lib/util_unistr.c b/source3/lib/util_unistr.c index fd51f3c57d..e7c200218e 100644 --- a/source3/lib/util_unistr.c +++ b/source3/lib/util_unistr.c @@ -841,5 +841,5 @@ UNISTR2* ucs2_to_unistr2(TALLOC_CTX *ctx, UNISTR2* dst, smb_ucs2_t* src) strncpy_w(dst->buffer, src, dst->uni_max_len); return dst; -}; +} diff --git a/source3/msdfs/msdfs.c b/source3/msdfs/msdfs.c index 4c86cd0f94..f8a97effee 100644 --- a/source3/msdfs/msdfs.c +++ b/source3/msdfs/msdfs.c @@ -330,8 +330,8 @@ BOOL dfs_redirect(char* pathname, connection_struct* conn, pathname)); return False; } + /* never reached */ - return False; } /********************************************************************** diff --git a/source3/nsswitch/winbindd_util.c b/source3/nsswitch/winbindd_util.c index 25de4eff71..850a0b1a2d 100644 --- a/source3/nsswitch/winbindd_util.c +++ b/source3/nsswitch/winbindd_util.c @@ -895,6 +895,5 @@ BOOL get_trust_pw(const char *domain, uint8 ret_pwd[16], } /* Failure */ - return False; } diff --git a/source3/rpc_client/cli_samr.c b/source3/rpc_client/cli_samr.c index 635b7e7135..f985ee9979 100644 --- a/source3/rpc_client/cli_samr.c +++ b/source3/rpc_client/cli_samr.c @@ -655,7 +655,7 @@ done: prs_mem_free(&rbuf); return result; -}; +} /* Enumerate domain groups */ diff --git a/source3/tdb/tdbutil.c b/source3/tdb/tdbutil.c index b01dacd0f5..bae9a8b9d4 100644 --- a/source3/tdb/tdbutil.c +++ b/source3/tdb/tdbutil.c @@ -807,7 +807,7 @@ TDB_LIST_NODE *tdb_search_keys(TDB_CONTEXT *tdb, const char* pattern) return list; -}; +} /** @@ -825,6 +825,6 @@ void tdb_search_list_free(TDB_LIST_NODE* node) SAFE_FREE(node); node = next_node; }; -}; +} diff --git a/source3/utils/net_groupmap.c b/source3/utils/net_groupmap.c index 323f4afbc3..06a8daa775 100644 --- a/source3/utils/net_groupmap.c +++ b/source3/utils/net_groupmap.c @@ -508,9 +508,8 @@ int net_groupmap(int argc, const char **argv) return -1; } - return net_run_function(argc, argv, func, net_help_groupmap); - if ( 0 == argc ) - return net_help_groupmap( argc, argv ); + if ( argc ) + return net_run_function(argc, argv, func, net_help_groupmap); return net_help_groupmap( argc, argv ); } diff --git a/source3/utils/net_rpc.c b/source3/utils/net_rpc.c index fefc5af365..85818152d1 100644 --- a/source3/utils/net_rpc.c +++ b/source3/utils/net_rpc.c @@ -1976,7 +1976,7 @@ static NTSTATUS rpc_query_domain_sid(const DOM_SID *domain_sid, struct cli_state sid_to_string(str_sid, domain_sid); d_printf("%s\n", str_sid); return NT_STATUS_OK; -}; +} static int rpc_trustdom_list(int argc, const char **argv) -- cgit From f6e0a1097460c1eaac8842f941dbb0a42713dfd1 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Wed, 24 Sep 2003 01:24:13 +0000 Subject: fixing a bug in the retry loop for winbindd_pam_auth[_crap]() (This used to be commit a1b6e28e9c1742dd5debe46b18fa474f11b31dd1) --- source3/nsswitch/winbindd_pam.c | 40 +++++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 15 deletions(-) (limited to 'source3') diff --git a/source3/nsswitch/winbindd_pam.c b/source3/nsswitch/winbindd_pam.c index ea2868b2cf..d696428de4 100644 --- a/source3/nsswitch/winbindd_pam.c +++ b/source3/nsswitch/winbindd_pam.c @@ -65,7 +65,7 @@ enum winbindd_result winbindd_pam_auth(struct winbindd_cli_state *state) time_t last_change_time; uint32 sec_channel_type; NET_USER_INFO_3 info3; - struct cli_state *cli; + struct cli_state *cli = NULL; uchar chal[8]; TALLOC_CTX *mem_ctx = NULL; DATA_BLOB lm_resp; @@ -128,7 +128,6 @@ enum winbindd_result winbindd_pam_auth(struct winbindd_cli_state *state) do { ZERO_STRUCT(info3); ZERO_STRUCT(ret_creds); - cli = NULL; retry = False; /* Don't shut this down - it belongs to the connection cache code */ @@ -148,8 +147,17 @@ enum winbindd_result winbindd_pam_auth(struct winbindd_cli_state *state) &info3); attempts += 1; + /* We have to try a second time as cm_get_netlogon_cli + might not yet have noticed that the DC has killed + our connection. */ + + if ( cli->fd == -1 ) { + retry = True; + continue; + } + /* if we get access denied, a possible cuase was that we had and open - connection to the DC, but someone changed our machine accoutn password + connection to the DC, but someone changed our machine account password out from underneath us using 'net rpc changetrustpw' */ if ( NT_STATUS_V(result) == NT_STATUS_V(NT_STATUS_ACCESS_DENIED) ) { @@ -158,12 +166,9 @@ enum winbindd_result winbindd_pam_auth(struct winbindd_cli_state *state) name_domain)); winbindd_cm_flush(); retry = True; + cli = NULL; } - /* We have to try a second time as cm_get_netlogon_cli - might not yet have noticed that the DC has killed - our connection. */ - } while ( (attempts < 2) && retry ); clnt_deal_with_creds(cli->sess_key, &(cli->clnt_cred), &ret_creds); @@ -206,7 +211,7 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state) time_t last_change_time; uint32 sec_channel_type; NET_USER_INFO_3 info3; - struct cli_state *cli; + struct cli_state *cli = NULL; TALLOC_CTX *mem_ctx = NULL; char *user = NULL; const char *domain = NULL; @@ -301,7 +306,6 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state) do { ZERO_STRUCT(info3); ZERO_STRUCT(ret_creds); - cli = NULL; retry = False; /* Don't shut this down - it belongs to the connection cache code */ @@ -323,8 +327,17 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state) attempts += 1; - /* if we get access denied, a possible cuase was that we had and open - connection to the DC, but someone changed our machine accoutn password + /* We have to try a second time as cm_get_netlogon_cli + might not yet have noticed that the DC has killed + our connection. */ + + if ( cli->fd == -1 ) { + retry = True; + continue; + } + + /* if we get access denied, a possible cause was that we had and open + connection to the DC, but someone changed our machine account password out from underneath us using 'net rpc changetrustpw' */ if ( NT_STATUS_V(result) == NT_STATUS_V(NT_STATUS_ACCESS_DENIED) ) { @@ -333,12 +346,9 @@ enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state) domain)); winbindd_cm_flush(); retry = True; + cli = NULL; } - /* We have to try a second time as cm_get_netlogon_cli - might not yet have noticed that the DC has killed - our connection. */ - } while ( (attempts < 2) && retry ); clnt_deal_with_creds(cli->sess_key, &(cli->clnt_cred), &ret_creds); -- cgit From a899daa93acbe398761d905426a9b2302e8497f1 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Wed, 24 Sep 2003 02:45:00 +0000 Subject: Another round of merges from 3.0: >Change error message displayed when --without-libiconv is used as >an argument to configure. Closes bug 468. (This used to be commit 4b73ba7df1764b47aae8b22980efdb05d1639e57) --- source3/configure.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3') diff --git a/source3/configure.in b/source3/configure.in index 0cf34bc9a7..b981313c9a 100644 --- a/source3/configure.in +++ b/source3/configure.in @@ -1573,7 +1573,7 @@ AC_ARG_WITH(libiconv, [ --with-libiconv=BASEDIR Use libiconv in BASEDIR/lib and BASEDIR/include (default=auto) ], [ if test "$withval" = "no" ; then - AC_MSG_ERROR(I won't take no for an answer) + AC_MSG_ERROR([argument to --with-libiconv must be a directory]) else if test "$withval" != "yes" ; then ICONV_PATH_SPEC=yes -- cgit From 238cac9581bb24555bfe8e4d5724c03e9594447b Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Wed, 24 Sep 2003 02:45:43 +0000 Subject: Another round of merges from 3.0: >Reformat - preparing to fix bug #480 (which will be ugly). >Jeremy. (This used to be commit cd91dd9cd8392d1b9cfcbd8ef42237b813dc89b5) --- source3/include/rpc_misc.h | 140 +++++++++++++++++++-------------------------- 1 file changed, 59 insertions(+), 81 deletions(-) (limited to 'source3') diff --git a/source3/include/rpc_misc.h b/source3/include/rpc_misc.h index a0572a0bfd..f9dd15c36b 100644 --- a/source3/include/rpc_misc.h +++ b/source3/include/rpc_misc.h @@ -85,49 +85,42 @@ typedef struct enum_hnd_info { uint32 ptr_hnd; /* pointer to enumeration handle */ uint32 handle; /* enumeration handle */ - } ENUM_HND; /* LOOKUP_LEVEL - switch value */ typedef struct lookup_level_info { - uint16 value; - + uint16 value; } LOOKUP_LEVEL; /* DOM_SID2 - security id */ typedef struct sid_info_2 { uint32 num_auths; /* length, bytes, including length of len :-) */ - DOM_SID sid; - } DOM_SID2; /* STRHDR - string header */ typedef struct header_info { - uint16 str_str_len; - uint16 str_max_len; - uint32 buffer; /* non-zero */ - + uint16 str_str_len; + uint16 str_max_len; + uint32 buffer; /* non-zero */ } STRHDR; /* UNIHDR - unicode string header */ typedef struct unihdr_info { - uint16 uni_str_len; - uint16 uni_max_len; - uint32 buffer; /* usually has a value of 4 */ - + uint16 uni_str_len; + uint16 uni_max_len; + uint32 buffer; /* usually has a value of 4 */ } UNIHDR; /* UNIHDR2 - unicode string header and undocumented buffer */ typedef struct unihdr2_info { - UNIHDR unihdr; - uint32 buffer; /* 32 bit buffer pointer */ - + UNIHDR unihdr; + uint32 buffer; /* 32 bit buffer pointer */ } UNIHDR2; /* clueless as to what maximum length should be */ @@ -138,16 +131,15 @@ typedef struct unihdr2_info /* UNISTR - unicode string size and buffer */ typedef struct unistr_info { - /* unicode characters. ***MUST*** be little-endian. ***MUST*** be null-terminated */ - uint16 *buffer; + /* unicode characters. ***MUST*** be little-endian. ***MUST*** be null-terminated */ + uint16 *buffer; } UNISTR; /* BUFHDR - buffer header */ typedef struct bufhdr_info { - uint32 buf_max_len; - uint32 buf_len; - + uint32 buf_max_len; + uint32 buf_len; } BUFHDR; /* BUFFER2 - unicode string, size (in uint8 ascii chars) and buffer */ @@ -155,51 +147,47 @@ typedef struct bufhdr_info /* of a unicode string different from the other \PIPE\ writers */ typedef struct buffer2_info { - uint32 buf_max_len; - uint32 undoc; - uint32 buf_len; - /* unicode characters. ***MUST*** be little-endian. **NOT** necessarily null-terminated */ - uint16 *buffer; - + uint32 buf_max_len; + uint32 undoc; + uint32 buf_len; + /* unicode characters. ***MUST*** be little-endian. **NOT** necessarily null-terminated */ + uint16 *buffer; } BUFFER2; /* BUFFER3 */ typedef struct buffer3_info { - uint32 buf_max_len; - uint8 *buffer; /* Data */ - uint32 buf_len; - + uint32 buf_max_len; + uint8 *buffer; /* Data */ + uint32 buf_len; } BUFFER3; /* BUFFER5 */ typedef struct buffer5_info { - uint32 buf_len; - uint16 *buffer; /* data */ + uint32 buf_len; + uint16 *buffer; /* data */ } BUFFER5; /* UNISTR2 - unicode string size (in uint16 unicode chars) and buffer */ typedef struct unistr2_info { - uint32 uni_max_len; - uint32 undoc; - uint32 uni_str_len; - /* unicode characters. ***MUST*** be little-endian. - **must** be null-terminated and the uni_str_len should include - the NULL character */ - uint16 *buffer; - + uint32 uni_max_len; + uint32 undoc; + uint32 uni_str_len; + /* unicode characters. ***MUST*** be little-endian. + **must** be null-terminated and the uni_str_len should include + the NULL character */ + uint16 *buffer; } UNISTR2; /* STRING2 - string size (in uint8 chars) and buffer */ typedef struct string2_info { - uint32 str_max_len; - uint32 undoc; - uint32 str_str_len; - uint8 *buffer; /* uint8 characters. **NOT** necessarily null-terminated */ - + uint32 str_max_len; + uint32 undoc; + uint32 str_str_len; + uint8 *buffer; /* uint8 characters. **NOT** necessarily null-terminated */ } STRING2; /* UNISTR3 - XXXX not sure about this structure */ @@ -266,85 +254,77 @@ typedef struct domrid3_info /* DOM_RID4 - rid + user attributes */ typedef struct domrid4_info { - uint32 unknown; - uint16 attr; - uint32 rid; /* user RID */ - + uint32 unknown; + uint16 attr; + uint32 rid; /* user RID */ } DOM_RID4; /* DOM_CLNT_SRV - client / server names */ typedef struct clnt_srv_info { - uint32 undoc_buffer; /* undocumented 32 bit buffer pointer */ - UNISTR2 uni_logon_srv; /* logon server name */ - uint32 undoc_buffer2; /* undocumented 32 bit buffer pointer */ - UNISTR2 uni_comp_name; /* client machine name */ - + uint32 undoc_buffer; /* undocumented 32 bit buffer pointer */ + UNISTR2 uni_logon_srv; /* logon server name */ + uint32 undoc_buffer2; /* undocumented 32 bit buffer pointer */ + UNISTR2 uni_comp_name; /* client machine name */ } DOM_CLNT_SRV; /* DOM_LOG_INFO - login info */ typedef struct log_info { - uint32 undoc_buffer; /* undocumented 32 bit buffer pointer */ - UNISTR2 uni_logon_srv; /* logon server name */ - UNISTR2 uni_acct_name; /* account name */ - uint16 sec_chan; /* secure channel type */ - UNISTR2 uni_comp_name; /* client machine name */ - + uint32 undoc_buffer; /* undocumented 32 bit buffer pointer */ + UNISTR2 uni_logon_srv; /* logon server name */ + UNISTR2 uni_acct_name; /* account name */ + uint16 sec_chan; /* secure channel type */ + UNISTR2 uni_comp_name; /* client machine name */ } DOM_LOG_INFO; /* DOM_CHAL - challenge info */ typedef struct chal_info { - uchar data[8]; /* credentials */ + uchar data[8]; /* credentials */ } DOM_CHAL; /* DOM_CREDs - timestamped client or server credentials */ typedef struct cred_info { - DOM_CHAL challenge; /* credentials */ - UTIME timestamp; /* credential time-stamp */ + DOM_CHAL challenge; /* credentials */ + UTIME timestamp; /* credential time-stamp */ } DOM_CRED; /* DOM_CLNT_INFO - client info */ typedef struct clnt_info { - DOM_LOG_INFO login; - DOM_CRED cred; - + DOM_LOG_INFO login; + DOM_CRED cred; } DOM_CLNT_INFO; /* DOM_CLNT_INFO2 - client info */ typedef struct clnt_info2 { - DOM_CLNT_SRV login; - uint32 ptr_cred; - DOM_CRED cred; - + DOM_CLNT_SRV login; + uint32 ptr_cred; + DOM_CRED cred; } DOM_CLNT_INFO2; /* DOM_LOGON_ID - logon id */ typedef struct logon_info { - uint32 low; - uint32 high; - + uint32 low; + uint32 high; } DOM_LOGON_ID; /* OWF INFO */ typedef struct owf_info { - uint8 data[16]; - + uint8 data[16]; } OWF_INFO; /* DOM_GID - group id + user attributes */ typedef struct gid_info { - uint32 g_rid; /* a group RID */ - uint32 attr; - + uint32 g_rid; /* a group RID */ + uint32 attr; } DOM_GID; /* POLICY_HND */ @@ -355,7 +335,6 @@ typedef struct lsa_policy_info uint16 data3; uint16 data4; uint8 data5[8]; - #ifdef __INSURE__ /* To prevent the leakage of policy handles mallocate a bit of @@ -366,7 +345,6 @@ typedef struct lsa_policy_info char *marker; #endif - } POLICY_HND; /* -- cgit From 43004ba8830874a8ab02bc755b1e99160af982b5 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Wed, 24 Sep 2003 02:46:59 +0000 Subject: Another round of merges from 3.0: >Fix return of result. Patch from Yasuma Takeda >Jeremy. >Applied Monyo's patch for bug #412 which allows \n characters to >appear in msg strings. >Put in some DEBUGs for swat language selection. Part of bug 456. (This used to be commit 0105b72db85141da30746c06ad7f5cec15bf9640) --- source3/intl/lang_tdb.c | 38 +++++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 13 deletions(-) (limited to 'source3') diff --git a/source3/intl/lang_tdb.c b/source3/intl/lang_tdb.c index f12b9b6f15..5409ce6619 100644 --- a/source3/intl/lang_tdb.c +++ b/source3/intl/lang_tdb.c @@ -58,6 +58,8 @@ static BOOL load_msg(const char *msg_file) if (*msgstr == 0) { msgstr = msgid; } + all_string_sub(msgid, "\\n", "\n", 0); + all_string_sub(msgstr, "\\n", "\n", 0); key.dptr = msgid; key.dsize = strlen(msgid)+1; data.dptr = msgstr; @@ -99,10 +101,12 @@ BOOL lang_tdb_init(const char *lang) struct stat st; static int initialised; time_t loadtime; + BOOL result = False; /* we only want to init once per process, unless given an override */ - if (initialised && !lang) return True; + if (initialised && !lang) + return True; if (initialised) { /* we are re-initialising, free up any old init */ @@ -121,41 +125,49 @@ BOOL lang_tdb_init(const char *lang) } /* if no lang then we don't translate */ - if (!lang) return True; + if (!lang) + return True; asprintf(&msg_path, "%s.msg", lib_path((const char *)lang)); if (stat(msg_path, &st) != 0) { /* the msg file isn't available */ - free(msg_path); - return False; + DEBUG(10, ("lang_tdb_init: %s: %s", msg_path, + strerror(errno))); + goto done; } - asprintf(&path, "%s%s.tdb", lock_path("lang_"), lang); + DEBUG(10, ("lang_tdb_init: loading %s\n", path)); + tdb = tdb_open_log(path, 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0644); if (!tdb) { tdb = tdb_open_log(path, 0, TDB_DEFAULT, O_RDONLY, 0); - free(path); - free(msg_path); - if (!tdb) return False; + if (!tdb) { + DEBUG(10, ("lang_tdb_init: %s: %s\n", path, + strerror(errno))); + goto done; + } current_lang = strdup(lang); - return True; + result = True; + goto done; } - free(path); - loadtime = tdb_fetch_int32(tdb, "/LOADTIME/"); if (loadtime == -1 || loadtime < st.st_mtime) { load_msg(msg_path); tdb_store_int32(tdb, "/LOADTIME/", (int)time(NULL)); } - free(msg_path); current_lang = strdup(lang); + result = True; - return True; + done: + SAFE_FREE(msg_path); + SAFE_FREE(path); + + return result; } /* translate a msgid to a message string in the current language -- cgit From 602ad283b4724acac0a416cd1fd1124ce89ee316 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Wed, 24 Sep 2003 15:16:57 +0000 Subject: * sync more files from 3.0 * set version string to "CVS 3.1.0alpha1" (This used to be commit c6a61ffcbd0c95afd94bd33fd832b24bc8209de5) --- source3/Makefile.in | 5 +++- source3/VERSION | 8 +++--- source3/lib/afs.c | 60 ++++++++++++++++++++++++++------------------ source3/lib/util_sec.c | 4 +++ source3/param/loadparm.c | 7 ++++++ source3/script/gaptab.awk | 4 +-- source3/script/installmsg.sh | 23 +++++++++++++++++ source3/smbd/service.c | 4 ++- source3/utils/net.c | 6 ++--- 9 files changed, 86 insertions(+), 35 deletions(-) create mode 100644 source3/script/installmsg.sh (limited to 'source3') diff --git a/source3/Makefile.in b/source3/Makefile.in index a2c4a360d4..0ea2c4411f 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -1205,7 +1205,10 @@ installscripts: installdirs installdat: installdirs @$(SHELL) $(srcdir)/script/installdat.sh $(DESTDIR)$(LIBDIR) $(srcdir) -installswat: installdirs +installmsg: installdirs + @$(SHELL) $(srcdir)/script/installmsg.sh $(DESTDIR)$(LIBDIR) $(srcdir) + +installswat: installdirs installmsg @$(SHELL) $(srcdir)/script/installswat.sh $(DESTDIR)$(SWATDIR) $(srcdir) installclientlib: installdirs libsmbclient diff --git a/source3/VERSION b/source3/VERSION index 9cf8b11ef1..d7f386ab42 100644 --- a/source3/VERSION +++ b/source3/VERSION @@ -18,8 +18,8 @@ # -> "3.0.0" # ######################################################## SAMBA_VERSION_MAJOR=3 -SAMBA_VERSION_MINOR=0 -SAMBA_VERSION_RELEASE=1 +SAMBA_VERSION_MINOR=1 +SAMBA_VERSION_RELEASE=0 ######################################################## # If a official release has a serious bug # @@ -41,7 +41,7 @@ SAMBA_VERSION_REVISION= # e.g. SAMBA_VERSION_PRE_RELEASE=1 # # -> "2.2.9pre1" # ######################################################## -SAMBA_VERSION_PRE_RELEASE=1 +SAMBA_VERSION_PRE_RELEASE= ######################################################## # For 'rc' releases the version will be # @@ -71,7 +71,7 @@ SAMBA_VERSION_BETA_RELEASE= # e.g. SAMBA_VERSION_ALPHA_RELEASE=1 # # -> "4.0.0alpha1" # ######################################################## -SAMBA_VERSION_ALPHA_RELEASE= +SAMBA_VERSION_ALPHA_RELEASE=1 ######################################################## # For 'test' releases the version will be # diff --git a/source3/lib/afs.c b/source3/lib/afs.c index b96703e986..882442a79f 100644 --- a/source3/lib/afs.c +++ b/source3/lib/afs.c @@ -35,18 +35,6 @@ _syscall5(int, afs_syscall, int, subcall, char *, cmarg, int, follow); -char *afs_cell(void) -{ - static char *cell = NULL; - - if (cell == NULL) { - cell = strdup(lp_realm()); - strlower_m(cell); - } - - return cell; -} - struct ClearToken { uint32 AuthHandle; char HandShakeKey[8]; @@ -65,7 +53,8 @@ struct ClearToken { to avoid. */ -static BOOL afs_settoken(char *username, const struct ClearToken *ctok, +static BOOL afs_settoken(const char *username, const char *cell, + const struct ClearToken *ctok, char *v4tkt_data, int v4tkt_length) { int ret; @@ -94,13 +83,13 @@ static BOOL afs_settoken(char *username, const struct ClearToken *ctok, memcpy(p, &tmp, sizeof(uint32)); p += sizeof(uint32); - tmp = strlen(afs_cell()); + tmp = strlen(cell); if (tmp >= MAXKTCREALMLEN) { DEBUG(1, ("Realm too long\n")); return False; } - strncpy(p, afs_cell(), tmp); + strncpy(p, cell, tmp); p += tmp; *p = 0; p +=1; @@ -135,12 +124,14 @@ static BOOL afs_settoken(char *username, const struct ClearToken *ctok, For the comments "Alice" is the User to be auth'ed, and "Bob" is the AFS server. */ -BOOL afs_login(char *username) +BOOL afs_login(connection_struct *conn) { fstring ticket; char *p = ticket; uint32 len; struct afs_key key; + pstring afs_username; + char *cell; struct ClearToken ct; @@ -148,13 +139,28 @@ BOOL afs_login(char *username) des_key_schedule key_schedule; - DEBUG(10, ("Trying to log into AFS for user %s@%s\n", - username, afs_cell())); + pstrcpy(afs_username, lp_afs_username_map()); + standard_sub_conn(conn, afs_username, sizeof(afs_username)); + + cell = strchr(afs_username, '@'); + + if (cell == NULL) { + DEBUG(1, ("AFS username doesn't contain a @, " + "could not find cell\n")); + return False; + } + + *cell = '\0'; + cell += 1; + strlower_m(cell); + + DEBUG(10, ("Trying to log into AFS for user %s@%s\n", + afs_username, cell)); if (!secrets_init()) return False; - if (!secrets_fetch_afs_key(afs_cell(), &key)) { + if (!secrets_fetch_afs_key(cell, &key)) { DEBUG(5, ("Could not fetch AFS service key\n")); return False; } @@ -172,14 +178,20 @@ BOOL afs_login(char *username) p += 1; /* "Alice", the client username */ - strncpy(p, username, sizeof(ticket)-PTR_DIFF(p,ticket)-1); + strncpy(p, afs_username, sizeof(ticket)-PTR_DIFF(p,ticket)-1); p += strlen(p)+1; strncpy(p, "", sizeof(ticket)-PTR_DIFF(p,ticket)-1); p += strlen(p)+1; - strncpy(p, afs_cell(), sizeof(ticket)-PTR_DIFF(p,ticket)-1); + strncpy(p, cell, sizeof(ticket)-PTR_DIFF(p,ticket)-1); p += strlen(p)+1; - ct.ViceId = getuid(); + /* As long as we still only use the effective UID we need to set the + * token for it here as well. This involves patching AFS in two + * places. Once we start using the real uid where we have the + * setresuid function, we can use getuid() here which would be more + * correct. */ + + ct.ViceId = geteuid(); DEBUG(10, ("Creating Token for uid %d\n", ct.ViceId)); /* Alice's network layer address. At least Openafs-1.2.10 @@ -235,12 +247,12 @@ BOOL afs_login(char *username) ZERO_STRUCT(key); - return afs_settoken(username, &ct, ticket, len); + return afs_settoken(afs_username, cell, &ct, ticket, len); } #else -BOOL afs_login(char *username) +BOOL afs_login(connection_struct *conn) { return True; } diff --git a/source3/lib/util_sec.c b/source3/lib/util_sec.c index 132748ce13..1980b8bfb7 100644 --- a/source3/lib/util_sec.c +++ b/source3/lib/util_sec.c @@ -183,6 +183,10 @@ void gain_root_group_privilege(void) void set_effective_uid(uid_t uid) { #if USE_SETRESUID + /* On Systems which have this function, would it not be more + * appropriate to also set the real uid by doing + * setresuid(uid,uid,-1)? This would make patching AFS + * unnecessary. See comment in lib/afs.c. */ setresuid(-1,uid,-1); #endif diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index b370b6b049..0efa2796c3 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -126,6 +126,7 @@ typedef struct char *szPasswordServer; char *szSocketOptions; char *szRealm; + char *szAfsUsernameMap; char *szUsernameMap; char *szLogonScript; char *szLogonPath; @@ -413,6 +414,7 @@ typedef struct BOOL bUseSendfile; BOOL bProfileAcls; BOOL bMap_acl_inherit; + BOOL bAfs_Share; param_opt_struct *param_opt; char dummy[3]; /* for alignment */ @@ -533,6 +535,7 @@ static service sDefault = { False, /* bUseSendfile */ False, /* bProfileAcls */ False, /* bMap_acl_inherit */ + False, /* bAfs_Share */ NULL, /* Parametric options */ @@ -762,6 +765,7 @@ static struct parm_struct parm_table[] = { #ifdef WITH_ADS {"realm", P_USTRING, P_GLOBAL, &Globals.szRealm, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD}, #endif + {"afs username map", P_USTRING, P_GLOBAL, &Globals.szAfsUsernameMap, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD}, {"netbios name", P_USTRING, P_GLOBAL, &Globals.szNetbiosName, handle_netbios_name, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_WIZARD}, {"netbios aliases", P_LIST, P_GLOBAL, &Globals.szNetbiosAliases, handle_netbios_aliases, NULL, FLAG_ADVANCED}, {"netbios scope", P_USTRING, P_GLOBAL, &Globals.szNetbiosScope, handle_netbios_scope, NULL, FLAG_ADVANCED}, @@ -890,6 +894,7 @@ static struct parm_struct parm_table[] = { {"announce version", P_STRING, P_GLOBAL, &Globals.szAnnounceVersion, NULL, NULL, FLAG_ADVANCED}, {"announce as", P_ENUM, P_GLOBAL, &Globals.announce_as, NULL, enum_announce_as, FLAG_ADVANCED}, {"map acl inherit", P_BOOL, P_LOCAL, &sDefault.bMap_acl_inherit, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, + {"afs share", P_BOOL, P_LOCAL, &sDefault.bAfs_Share, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, {"max mux", P_INTEGER, P_GLOBAL, &Globals.max_mux, NULL, NULL, FLAG_ADVANCED}, {"max xmit", P_INTEGER, P_GLOBAL, &Globals.max_xmit, NULL, NULL, FLAG_ADVANCED}, @@ -1634,6 +1639,7 @@ FN_GLOBAL_STRING(lp_passwd_chat, &Globals.szPasswdChat) FN_GLOBAL_STRING(lp_passwordserver, &Globals.szPasswordServer) FN_GLOBAL_STRING(lp_name_resolve_order, &Globals.szNameResolveOrder) FN_GLOBAL_STRING(lp_realm, &Globals.szRealm) +FN_GLOBAL_STRING(lp_afs_username_map, &Globals.szAfsUsernameMap) FN_GLOBAL_STRING(lp_username_map, &Globals.szUsernameMap) FN_GLOBAL_CONST_STRING(lp_logon_script, &Globals.szLogonScript) FN_GLOBAL_CONST_STRING(lp_logon_path, &Globals.szLogonPath) @@ -1871,6 +1877,7 @@ FN_LOCAL_BOOL(lp_nt_acl_support, bNTAclSupport) FN_LOCAL_BOOL(_lp_use_sendfile, bUseSendfile) FN_LOCAL_BOOL(lp_profile_acls, bProfileAcls) FN_LOCAL_BOOL(lp_map_acl_inherit, bMap_acl_inherit) +FN_LOCAL_BOOL(lp_afs_share, bAfs_Share) 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) diff --git a/source3/script/gaptab.awk b/source3/script/gaptab.awk index f9d1526361..a309089cd5 100644 --- a/source3/script/gaptab.awk +++ b/source3/script/gaptab.awk @@ -23,9 +23,9 @@ function tonum(str) function fmt(val) { if (f++ % 8 == 0) - { printf ("\n '\\x%02x',", val); } + { printf ("\n 0x%02x,", val); } else - { printf (" '\\x%02x',", val); } + { printf (" 0x%02x,", val); } } { diff --git a/source3/script/installmsg.sh b/source3/script/installmsg.sh new file mode 100644 index 0000000000..30ad404aa0 --- /dev/null +++ b/source3/script/installmsg.sh @@ -0,0 +1,23 @@ +#!/bin/sh +# first version (Sept 2003) written by Shiro Yamada +# based on the first verion (March 2002) of installdat.sh written by Herb Lewis + +MSGDIR=$1 +SRCDIR=$2/ + +echo Installing msg files in $MSGDIR + +for f in $SRCDIR/po/*.msg; do + FNAME=$MSGDIR/`basename $f` + echo $FNAME + cp $f $FNAME || echo Cannot install $FNAME. Does $USER have privileges? + chmod 0644 $FNAME +done + +cat << EOF +====================================================================== +The msg files have been installed. +====================================================================== +EOF + +exit 0 diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 70126b9e7f..44d73b2ab2 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -644,7 +644,9 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, } #ifdef WITH_FAKE_KASERVER - afs_login(user); + if (lp_afs_share(SNUM(conn))) { + afs_login(conn); + } #endif #if CHECK_PATH_ON_TCONX diff --git a/source3/utils/net.c b/source3/utils/net.c index e5c078da29..42966b4f83 100644 --- a/source3/utils/net.c +++ b/source3/utils/net.c @@ -476,8 +476,8 @@ static int net_afskey(int argc, const char **argv) int fd; struct afs_keyfile keyfile; - if (argc != 1) { - d_printf("usage: 'net afskey '\n"); + if (argc != 2) { + d_printf("usage: 'net afskey cell'\n"); return -1; } @@ -496,7 +496,7 @@ static int net_afskey(int argc, const char **argv) return -1; } - if (!secrets_store_afs_keyfile(afs_cell(), &keyfile)) { + if (!secrets_store_afs_keyfile(argv[1], &keyfile)) { d_printf("Could not write keyfile to secrets.tdb\n"); return -1; } -- cgit From 8efca15a8b45692f27ab783e4759646dee612eae Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Fri, 26 Sep 2003 14:44:11 +0000 Subject: don't write to static pointers; patch from Anthony (This used to be commit b766fe78a7d8e4095d42e123f2b21369113c1f14) --- source3/configure.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3') diff --git a/source3/configure.in b/source3/configure.in index b981313c9a..8c2e9e7f9b 100644 --- a/source3/configure.in +++ b/source3/configure.in @@ -480,7 +480,7 @@ main() { /* Ensure this is kernel 2.4 or higher */ uname(&uts); - release = uts.release; + release = strdup(uts.release); major = atoi(strsep(&release, ".")); minor = atoi(strsep(&release, ".")); -- cgit From fbb85e4b422f0f48f31e10025aa293ffacc53178 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Mon, 29 Sep 2003 02:40:09 +0000 Subject: Testparm fixes: - Also check global 'hosts allow'/'hosts deny' when checking access to share - Warn when user specifies 2 arguments instead of 1 or 3. Patch from Jay Fenlason (This used to be commit 034fe96f9c3d3328bc69ef328f10690336dc35b0) --- source3/utils/testparm.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'source3') diff --git a/source3/utils/testparm.c b/source3/utils/testparm.c index 34c25480d9..085156305b 100644 --- a/source3/utils/testparm.c +++ b/source3/utils/testparm.c @@ -226,7 +226,12 @@ via the %%o substitution. With encrypted passwords this is not possible.\n", lp_ cname = poptGetArg(pc); caddr = poptGetArg(pc); - + + if ( cname && ! caddr ) { + printf ( "ERROR: You must specify both a machine name and an IP address.\n" ); + return(1); + } + if (new_local_machine) { set_local_machine_name(new_local_machine, True); } @@ -346,8 +351,9 @@ via the %%o substitution. With encrypted passwords this is not possible.\n", lp_ if(cname && caddr){ /* this is totally ugly, a real `quick' hack */ for (s=0;s<1000;s++) { - if (VALID_SNUM(s)) { - if (allow_access(lp_hostsdeny(s), lp_hostsallow(s), cname, caddr)) { + if (VALID_SNUM(s)) { + if (allow_access(lp_hostsdeny(-1), lp_hostsallow(-1), cname, caddr) + && allow_access(lp_hostsdeny(s), lp_hostsallow(s), cname, caddr)) { printf("Allow connection from %s (%s) to %s\n", cname,caddr,lp_servicename(s)); } else { -- cgit From 64dbd7cbff3fa7a4e560571ec38207a7176e4646 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 29 Sep 2003 06:07:30 +0000 Subject: Merge from 3.0: >Change AC_CHECK_LIB_EXT to prepend libraries instead of append. This >is the same way AC_CHECK_LIB works. Fix for bug 508. > >This may have to go a few rounds on the build farm to ensure it works >everywhere. (This used to be commit e2da7c8a9dc0e4c698c330422682feccae879bbd) --- source3/aclocal.m4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3') diff --git a/source3/aclocal.m4 b/source3/aclocal.m4 index 52396e56d6..e1ea9385fd 100644 --- a/source3/aclocal.m4 +++ b/source3/aclocal.m4 @@ -179,7 +179,7 @@ AS_IF([test AS_VAR_GET(ac_Lib_ext) = yes], *-l$1*) ;; *) - $2="$$2 -l$1" + $2="-l$1 $$2" ;; esac]) [$6] -- cgit From 5400952f7f74d6e656fcf4ded173868ecec3cb77 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 29 Sep 2003 06:17:09 +0000 Subject: Merge from 3.0: >Fix for #480. Change the interface for init_unistr2 to not take a length >but a flags field. We were assuming that 2*strlen(mb_string) == length of ucs2-le string. >This is not the case. Count it after conversion. >Jeremy. (This used to be commit e2ab9e54cd0ec0002175cf18ff364f4aebaf85a0) --- source3/include/rpc_lsa.h | 2 - source3/include/rpc_misc.h | 8 +- source3/lib/util_unistr.c | 12 +- source3/python/py_spoolss_forms.c | 2 +- source3/python/py_spoolss_forms_conv.c | 2 +- source3/registry/reg_printing.c | 41 ++-- source3/rpc_client/cli_srvsvc.c | 16 +- source3/rpc_parse/parse_dfs.c | 20 +- source3/rpc_parse/parse_ds.c | 6 +- source3/rpc_parse/parse_lsa.c | 39 +--- source3/rpc_parse/parse_misc.c | 98 ++++---- source3/rpc_parse/parse_net.c | 108 ++++----- source3/rpc_parse/parse_reg.c | 64 ++--- source3/rpc_parse/parse_samr.c | 416 ++++++++++++++------------------- source3/rpc_parse/parse_spoolss.c | 79 +++---- source3/rpc_parse/parse_srv.c | 74 +++--- source3/rpc_server/srv_dfs_nt.c | 12 +- source3/rpc_server/srv_lsa_ds_nt.c | 6 +- source3/rpc_server/srv_lsa_nt.c | 71 +++--- source3/rpc_server/srv_samr_nt.c | 23 +- source3/rpc_server/srv_spoolss_nt.c | 14 +- source3/rpcclient/cmd_spoolss.c | 4 +- 22 files changed, 467 insertions(+), 650 deletions(-) (limited to 'source3') diff --git a/source3/include/rpc_lsa.h b/source3/include/rpc_lsa.h index fa49d76c88..93bc08a0ce 100644 --- a/source3/include/rpc_lsa.h +++ b/source3/include/rpc_lsa.h @@ -728,5 +728,3 @@ typedef struct lsa_r_removeprivs #endif /* _RPC_LSA_H */ - - diff --git a/source3/include/rpc_misc.h b/source3/include/rpc_misc.h index f9dd15c36b..aaaad55c20 100644 --- a/source3/include/rpc_misc.h +++ b/source3/include/rpc_misc.h @@ -148,7 +148,7 @@ typedef struct bufhdr_info typedef struct buffer2_info { uint32 buf_max_len; - uint32 undoc; + uint32 offset; uint32 buf_len; /* unicode characters. ***MUST*** be little-endian. **NOT** necessarily null-terminated */ uint16 *buffer; @@ -173,7 +173,7 @@ typedef struct buffer5_info typedef struct unistr2_info { uint32 uni_max_len; - uint32 undoc; + uint32 offset; uint32 uni_str_len; /* unicode characters. ***MUST*** be little-endian. **must** be null-terminated and the uni_str_len should include @@ -185,7 +185,7 @@ typedef struct unistr2_info typedef struct string2_info { uint32 str_max_len; - uint32 undoc; + uint32 offset; uint32 str_str_len; uint8 *buffer; /* uint8 characters. **NOT** necessarily null-terminated */ } STRING2; @@ -403,5 +403,5 @@ typedef struct buffer4_info } BUFFER4; - +enum unistr2_term_codes { UNI_FLAGS_NONE = 0, UNI_STR_TERMINATE = 1, UNI_MAXLEN_TERMINATE = 2 }; #endif /* _RPC_MISC_H */ diff --git a/source3/lib/util_unistr.c b/source3/lib/util_unistr.c index e7c200218e..e90a824395 100644 --- a/source3/lib/util_unistr.c +++ b/source3/lib/util_unistr.c @@ -819,22 +819,25 @@ UNISTR2* ucs2_to_unistr2(TALLOC_CTX *ctx, UNISTR2* dst, smb_ucs2_t* src) { size_t len; - if (!src) return NULL; + if (!src) + return NULL; len = strlen_w(src); /* allocate UNISTR2 destination if not given */ if (!dst) { dst = (UNISTR2*) talloc(ctx, sizeof(UNISTR2)); - if (!dst) return NULL; + if (!dst) + return NULL; } if (!dst->buffer) { dst->buffer = (uint16*) talloc(ctx, sizeof(uint16) * (len + 1)); - if (!dst->buffer) return NULL; + if (!dst->buffer) + return NULL; } /* set UNISTR2 parameters */ dst->uni_max_len = len + 1; - dst->undoc = 0; + dst->offset = 0; dst->uni_str_len = len; /* copy the actual unicode string */ @@ -842,4 +845,3 @@ UNISTR2* ucs2_to_unistr2(TALLOC_CTX *ctx, UNISTR2* dst, smb_ucs2_t* src) return dst; } - diff --git a/source3/python/py_spoolss_forms.c b/source3/python/py_spoolss_forms.c index ef9ed94533..66a6540e07 100644 --- a/source3/python/py_spoolss_forms.c +++ b/source3/python/py_spoolss_forms.c @@ -59,7 +59,7 @@ PyObject *spoolss_hnd_addform(PyObject *self, PyObject *args, PyObject *kw) PyObject *obj = PyDict_GetItemString(info, "name"); char *form_name = PyString_AsString(obj); - init_unistr2(&form.name, form_name, strlen(form_name) + 1); + init_unistr2(&form.name, form_name, UNI_STR_TERMINATE); break; } default: diff --git a/source3/python/py_spoolss_forms_conv.c b/source3/python/py_spoolss_forms_conv.c index 095a318fd2..ede729cad3 100644 --- a/source3/python/py_spoolss_forms_conv.c +++ b/source3/python/py_spoolss_forms_conv.c @@ -81,7 +81,7 @@ BOOL py_to_FORM(FORM *form, PyObject *dict) obj = PyDict_GetItemString(dict, "name"); name = PyString_AsString(obj); - init_unistr2(&form->name, name, strlen(name) + 1); + init_unistr2(&form->name, name, UNI_STR_TERMINATE); result = True; diff --git a/source3/registry/reg_printing.c b/source3/registry/reg_printing.c index 50ac81dcbb..e50a5f4d4f 100644 --- a/source3/registry/reg_printing.c +++ b/source3/registry/reg_printing.c @@ -288,34 +288,32 @@ static int print_subpath_values_environments( char *key, REGVAL_CTR *val ) info3 = driver_ctr.info_3; filename = dos_basename( info3->driverpath ); - init_unistr2( &data, filename, strlen(filename)+1 ); + init_unistr2( &data, filename, UNI_STR_TERMINATE); regval_ctr_addvalue( val, "Driver", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) ); filename = dos_basename( info3->configfile ); - init_unistr2( &data, filename, strlen(filename)+1 ); + init_unistr2( &data, filename, UNI_STR_TERMINATE); regval_ctr_addvalue( val, "Configuration File", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) ); filename = dos_basename( info3->datafile ); - init_unistr2( &data, filename, strlen(filename)+1 ); + init_unistr2( &data, filename, UNI_STR_TERMINATE); regval_ctr_addvalue( val, "Data File", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) ); filename = dos_basename( info3->helpfile ); - init_unistr2( &data, filename, strlen(filename)+1 ); + init_unistr2( &data, filename, UNI_STR_TERMINATE); 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 ); + init_unistr2( &data, info3->defaultdatatype, UNI_STR_TERMINATE); 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) ); - if ( info3->dependentfiles ) - { + if ( info3->dependentfiles ) { /* place the list of dependent files in a single character buffer, separating each file name by a NULL */ - for ( i=0; strcmp(info3->dependentfiles[i], ""); i++ ) - { + for ( i=0; strcmp(info3->dependentfiles[i], ""); i++ ) { /* strip the path to only the file's base name */ filename = dos_basename( info3->dependentfiles[i] ); @@ -327,7 +325,7 @@ static int print_subpath_values_environments( char *key, REGVAL_CTR *val ) break; buffer = buffer2; - init_unistr2( &data, filename, length+1 ); + init_unistr2( &data, filename, UNI_STR_TERMINATE); memcpy( buffer+buffer_size, (char*)data.buffer, data.uni_str_len*sizeof(uint16) ); buffer_size += (length + 1)*sizeof(uint16); @@ -339,8 +337,7 @@ static int print_subpath_values_environments( char *key, REGVAL_CTR *val ) if ( !buffer2 ) { SAFE_FREE( buffer ); buffer_size = 0; - } - else { + } else { buffer = buffer2; buffer[buffer_size++] = '\0'; buffer[buffer_size++] = '\0'; @@ -573,25 +570,25 @@ static int print_subpath_values_printers( char *key, REGVAL_CTR *val ) 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) ); - init_unistr2( &data, info2->printername, strlen(info2->printername)+1 ); + init_unistr2( &data, info2->printername, UNI_STR_TERMINATE); 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 ); + init_unistr2( &data, info2->location, UNI_STR_TERMINATE); 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 ); + init_unistr2( &data, info2->comment, UNI_STR_TERMINATE); 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 ); + init_unistr2( &data, info2->parameters, UNI_STR_TERMINATE); 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 ); + init_unistr2( &data, info2->portname, UNI_STR_TERMINATE); 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 ); + init_unistr2( &data, info2->servername, UNI_STR_TERMINATE); 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 ); + init_unistr2( &data, info2->sharename, UNI_STR_TERMINATE); 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 ); + init_unistr2( &data, info2->drivername, UNI_STR_TERMINATE); 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 ); + init_unistr2( &data, info2->sepfile, UNI_STR_TERMINATE); regval_ctr_addvalue( val, "Separator File", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) ); - init_unistr2( &data, "winprint", strlen("winprint")+1 ); + init_unistr2( &data, "winprint", UNI_STR_TERMINATE); regval_ctr_addvalue( val, "Print Processor", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) ); diff --git a/source3/rpc_client/cli_srvsvc.c b/source3/rpc_client/cli_srvsvc.c index 27349b7295..555703cf4d 100644 --- a/source3/rpc_client/cli_srvsvc.c +++ b/source3/rpc_client/cli_srvsvc.c @@ -138,11 +138,11 @@ WERROR cli_srvsvc_net_share_enum(struct cli_state *cli, TALLOC_CTX *mem_ctx, s = unistr2_tdup(mem_ctx, &r.ctr.share.info1[i].info_1_str.uni_netname); if (s) - init_unistr2(&info1->info_1_str.uni_netname, s, strlen(s) + 1); + init_unistr2(&info1->info_1_str.uni_netname, s, UNI_STR_TERMINATE); s = unistr2_tdup(mem_ctx, &r.ctr.share.info1[i].info_1_str.uni_remark); if (s) - init_unistr2(&info1->info_1_str.uni_remark, s, strlen(s) + 1); + init_unistr2(&info1->info_1_str.uni_remark, s, UNI_STR_TERMINATE); } @@ -166,19 +166,19 @@ WERROR cli_srvsvc_net_share_enum(struct cli_state *cli, TALLOC_CTX *mem_ctx, s = unistr2_tdup(mem_ctx, &r.ctr.share.info2[i].info_2_str.uni_netname); if (s) - init_unistr2(&info2->info_2_str.uni_netname, s, strlen(s) + 1); + init_unistr2(&info2->info_2_str.uni_netname, s, UNI_STR_TERMINATE); s = unistr2_tdup(mem_ctx, &r.ctr.share.info2[i].info_2_str.uni_remark); if (s) - init_unistr2(&info2->info_2_str.uni_remark, s, strlen(s) + 1); + init_unistr2(&info2->info_2_str.uni_remark, s, UNI_STR_TERMINATE); s = unistr2_tdup(mem_ctx, &r.ctr.share.info2[i].info_2_str.uni_path); if (s) - init_unistr2(&info2->info_2_str.uni_path, s, strlen(s) + 1); + init_unistr2(&info2->info_2_str.uni_path, s, UNI_STR_TERMINATE); s = unistr2_tdup(mem_ctx, &r.ctr.share.info2[i].info_2_str.uni_passwd); if (s) - init_unistr2(&info2->info_2_str.uni_passwd, s, strlen(s) + 1); + init_unistr2(&info2->info_2_str.uni_passwd, s, UNI_STR_TERMINATE); } break; } @@ -385,11 +385,11 @@ WERROR cli_srvsvc_net_file_enum(struct cli_state *cli, TALLOC_CTX *mem_ctx, s = unistr2_tdup(mem_ctx, &r.ctr.file.info3[i].info_3_str.uni_path_name); if (s) - init_unistr2(&info3->info_3_str.uni_path_name, s, strlen(s) + 1); + init_unistr2(&info3->info_3_str.uni_path_name, s, UNI_STR_TERMINATE); s = unistr2_tdup(mem_ctx, &r.ctr.file.info3[i].info_3_str.uni_user_name); if (s) - init_unistr2(&info3->info_3_str.uni_user_name, s, strlen(s) + 1); + init_unistr2(&info3->info_3_str.uni_user_name, s, UNI_STR_TERMINATE); } diff --git a/source3/rpc_parse/parse_dfs.c b/source3/rpc_parse/parse_dfs.c index 6f13500359..0d0ce557b2 100644 --- a/source3/rpc_parse/parse_dfs.c +++ b/source3/rpc_parse/parse_dfs.c @@ -80,9 +80,9 @@ BOOL init_dfs_q_dfs_remove(DFS_Q_DFS_REMOVE *q_d, const char *entrypath, const char *servername, const char *sharename) { DEBUG(5,("init_dfs_q_dfs_remove\n")); - init_unistr2(&q_d->DfsEntryPath, entrypath, strlen(entrypath)+1); - init_unistr2(&q_d->ServerName, servername, strlen(servername)+1); - init_unistr2(&q_d->ShareName, sharename, strlen(sharename)+1); + init_unistr2(&q_d->DfsEntryPath, entrypath, UNI_STR_TERMINATE); + init_unistr2(&q_d->ServerName, servername, UNI_STR_TERMINATE); + init_unistr2(&q_d->ShareName, sharename, UNI_STR_TERMINATE); q_d->ptr_ServerName = q_d->ptr_ShareName = 1; return True; } @@ -155,11 +155,11 @@ BOOL init_dfs_q_dfs_add(DFS_Q_DFS_ADD *q_d, const char *entrypath, { DEBUG(5,("init_dfs_q_dfs_add\n")); q_d->ptr_DfsEntryPath = q_d->ptr_ServerName = q_d->ptr_ShareName = 1; - init_unistr2(&q_d->DfsEntryPath, entrypath, strlen(entrypath)+1); - init_unistr2(&q_d->ServerName, servername, strlen(servername)+1); - init_unistr2(&q_d->ShareName, sharename, strlen(sharename)+1); + init_unistr2(&q_d->DfsEntryPath, entrypath, UNI_STR_TERMINATE); + init_unistr2(&q_d->ServerName, servername, UNI_STR_TERMINATE); + init_unistr2(&q_d->ShareName, sharename, UNI_STR_TERMINATE); if(comment != NULL) { - init_unistr2(&q_d->Comment, comment, strlen(comment)+1); + init_unistr2(&q_d->Comment, comment,UNI_STR_TERMINATE); q_d->ptr_Comment = 1; } else { q_d->ptr_Comment = 0; @@ -237,9 +237,9 @@ BOOL init_dfs_q_dfs_get_info(DFS_Q_DFS_GET_INFO *q_d, const char *entrypath, uint32 info_level) { DEBUG(5,("init_dfs_q2_get_info\n")); - init_unistr2(&q_d->uni_path, entrypath, strlen(entrypath)+1); - init_unistr2(&q_d->uni_server, servername, strlen(servername)+1); - init_unistr2(&q_d->uni_share, sharename, strlen(sharename)+1); + init_unistr2(&q_d->uni_path, entrypath, UNI_STR_TERMINATE); + init_unistr2(&q_d->uni_server, servername, UNI_STR_TERMINATE); + init_unistr2(&q_d->uni_share, sharename, UNI_STR_TERMINATE); q_d->level = info_level; q_d->ptr_server = q_d->ptr_share = 1; return True; diff --git a/source3/rpc_parse/parse_ds.c b/source3/rpc_parse/parse_ds.c index f954806036..26dcdb34b8 100644 --- a/source3/rpc_parse/parse_ds.c +++ b/source3/rpc_parse/parse_ds.c @@ -138,8 +138,6 @@ BOOL ds_io_r_getprimdominfo( const char *desc, prs_struct *ps, int depth, DS_R_G BOOL init_q_ds_enum_domain_trusts( DS_Q_ENUM_DOM_TRUSTS *q, const char *server, uint32 flags ) { - int len; - q->flags = flags; if ( server && *server ) @@ -147,9 +145,7 @@ BOOL init_q_ds_enum_domain_trusts( DS_Q_ENUM_DOM_TRUSTS *q, const char *server, else q->server_ptr = 0; - len = q->server_ptr ? strlen(server)+1 : 0; - - init_unistr2( &q->server, server, len ); + init_unistr2( &q->server, server, UNI_STR_TERMINATE); return True; } diff --git a/source3/rpc_parse/parse_lsa.c b/source3/rpc_parse/parse_lsa.c index 07b0da7e9c..3a5b232dc3 100644 --- a/source3/rpc_parse/parse_lsa.c +++ b/source3/rpc_parse/parse_lsa.c @@ -36,14 +36,9 @@ static BOOL lsa_io_trans_names(const char *desc, LSA_TRANS_NAME_ENUM *trn, prs_s void init_lsa_trans_name(LSA_TRANS_NAME *trn, UNISTR2 *uni_name, uint16 sid_name_use, const char *name, uint32 idx) { - int len_name = strlen(name); - - if(len_name == 0) - len_name = 1; - trn->sid_name_use = sid_name_use; - init_uni_hdr(&trn->hdr_name, len_name); - init_unistr2(uni_name, name, len_name); + init_unistr2(uni_name, name, UNI_FLAGS_NONE); + init_uni_hdr(&trn->hdr_name, uni_name); trn->domain_idx = idx; } @@ -346,8 +341,7 @@ void init_q_open_pol2(LSA_Q_OPEN_POL2 *r_q, const char *server_name, r_q->des_access = desired_access; - init_unistr2(&r_q->uni_server_name, server_name, - strlen(server_name) + 1); + init_unistr2(&r_q->uni_server_name, server_name, UNI_STR_TERMINATE); init_lsa_obj_attr(&r_q->attr, attributes, qos); } @@ -566,10 +560,10 @@ void init_r_enum_trust_dom(TALLOC_CTX *ctx, LSA_R_ENUM_TRUST_DOM *r_e, uint32 en /* don't know what actually is this for */ r_e->ptr_enum_domains = 1; - init_uni_hdr2(&r_e->hdr_domain_name[i], strlen_w((td[i])->name)); init_dom_sid2(&r_e->domain_sid[i], &(td[i])->sid); init_unistr2_w(ctx, &r_e->uni_domain_name[i], (td[i])->name); + init_uni_hdr2(&r_e->hdr_domain_name[i], &r_e->uni_domain_name[i]); }; } @@ -1087,11 +1081,8 @@ void init_q_lookup_names(TALLOC_CTX *mem_ctx, LSA_Q_LOOKUP_NAMES *q_l, } for (i = 0; i < num_names; i++) { - int len; - len = strlen(names[i]); - - init_uni_hdr(&q_l->hdr_name[i], len); - init_unistr2(&q_l->uni_name[i], names[i], len); + init_unistr2(&q_l->uni_name[i], names[i], UNI_FLAGS_NONE); + init_uni_hdr(&q_l->hdr_name[i], &q_l->uni_name[i]); } } @@ -1436,15 +1427,10 @@ BOOL lsa_io_r_enum_privs(const char *desc, LSA_R_ENUM_PRIVS *r_q, prs_struct *ps void init_lsa_priv_get_dispname(LSA_Q_PRIV_GET_DISPNAME *trn, POLICY_HND *hnd, const char *name, uint16 lang_id, uint16 lang_id_sys) { - int len_name = strlen(name); - - if(len_name == 0) - len_name = 1; - memcpy(&trn->pol, hnd, sizeof(trn->pol)); - init_uni_hdr(&trn->hdr_name, len_name); - init_unistr2(&trn->name, name, len_name); + init_unistr2(&trn->name, name, UNI_FLAGS_NONE); + init_uni_hdr(&trn->hdr_name, &trn->name); trn->lang_id = lang_id; trn->lang_id_sys = lang_id_sys; } @@ -1954,14 +1940,9 @@ BOOL lsa_io_r_setsystemaccount(const char *desc, LSA_R_SETSYSTEMACCOUNT *r_c, p void init_lsa_q_lookupprivvalue(LSA_Q_LOOKUPPRIVVALUE *trn, POLICY_HND *hnd, const char *name) { - int len_name = strlen(name); memcpy(&trn->pol, hnd, sizeof(trn->pol)); - - if(len_name == 0) - len_name = 1; - - init_uni_hdr(&trn->hdr_right, len_name); - init_unistr2(&trn->uni2_right, name, len_name); + init_unistr2(&trn->uni2_right, name, UNI_FLAGS_NONE); + init_uni_hdr(&trn->hdr_right, &trn->uni2_right); } /******************************************************************* diff --git a/source3/rpc_parse/parse_misc.c b/source3/rpc_parse/parse_misc.c index 17a96fff80..e182535532 100644 --- a/source3/rpc_parse/parse_misc.c +++ b/source3/rpc_parse/parse_misc.c @@ -361,11 +361,11 @@ BOOL smb_io_strhdr(const char *desc, STRHDR *hdr, prs_struct *ps, int depth) Inits a UNIHDR structure. ********************************************************************/ -void init_uni_hdr(UNIHDR *hdr, int len) +void init_uni_hdr(UNIHDR *hdr, UNISTR2 *str2) { - hdr->uni_str_len = 2 * len; - hdr->uni_max_len = 2 * len; - hdr->buffer = len != 0 ? 1 : 0; + hdr->uni_str_len = 2 * (str2->uni_str_len); + hdr->uni_max_len = 2 * (str2->uni_max_len); + hdr->buffer = (str2->uni_str_len != 0) ? 1 : 0; } /******************************************************************* @@ -482,10 +482,10 @@ BOOL smb_io_hdrbuf(const char *desc, BUFHDR *hdr, prs_struct *ps, int depth) creates a UNIHDR2 structure. ********************************************************************/ -void init_uni_hdr2(UNIHDR2 *hdr, int len) +void init_uni_hdr2(UNIHDR2 *hdr, UNISTR2 *str2) { - init_uni_hdr(&hdr->unihdr, len); - hdr->buffer = (len > 0) ? 1 : 0; + init_uni_hdr(&hdr->unihdr, str2); + hdr->buffer = (str2->uni_str_len > 0) ? 1 : 0; } /******************************************************************* @@ -703,7 +703,7 @@ void init_buffer2(BUFFER2 *str, const uint8 *buf, size_t len) /* max buffer size (allocated size) */ str->buf_max_len = len; - str->undoc = 0; + str->offset = 0; str->buf_len = buf != NULL ? len : 0; if (buf != NULL) { @@ -737,7 +737,7 @@ BOOL smb_io_buffer2(const char *desc, BUFFER2 *buf2, uint32 buffer, prs_struct * if(!prs_uint32("uni_max_len", ps, depth, &buf2->buf_max_len)) return False; - if(!prs_uint32("undoc ", ps, depth, &buf2->undoc)) + if(!prs_uint32("offset ", ps, depth, &buf2->offset)) return False; if(!prs_uint32("buf_len ", ps, depth, &buf2->buf_len)) return False; @@ -765,14 +765,11 @@ creates a UNISTR2 structure: sets up the buffer, too void init_buf_unistr2(UNISTR2 *str, uint32 *ptr, const char *buf) { if (buf != NULL) { - *ptr = 1; - init_unistr2(str, buf, strlen(buf)+1); - + init_unistr2(str, buf, UNI_STR_TERMINATE); } else { - *ptr = 0; - init_unistr2(str, "", 0); + init_unistr2(str, NULL, UNI_FLAGS_NONE); } } @@ -783,10 +780,8 @@ void init_buf_unistr2(UNISTR2 *str, uint32 *ptr, const char *buf) void copy_unistr2(UNISTR2 *str, const UNISTR2 *from) { - - /* set up string lengths. add one if string is not null-terminated */ str->uni_max_len = from->uni_max_len; - str->undoc = from->undoc; + str->offset = from->offset; str->uni_str_len = from->uni_str_len; if (from->buffer == NULL) @@ -803,8 +798,7 @@ void copy_unistr2(UNISTR2 *str, const UNISTR2 *from) len *= sizeof(uint16); str->buffer = (uint16 *)talloc_zero(get_talloc_ctx(), len); - if ((str->buffer == NULL) && (len > 0 )) - { + if ((str->buffer == NULL) && (len > 0 )) { smb_panic("copy_unistr2: talloc fail\n"); return; } @@ -824,7 +818,7 @@ void init_string2(STRING2 *str, const char *buf, int max_len, int str_len) /* set up string lengths. */ str->str_max_len = max_len; - str->undoc = 0; + str->offset = 0; str->str_str_len = str_len; /* store the string */ @@ -835,7 +829,7 @@ void init_string2(STRING2 *str, const char *buf, int max_len, int str_len) if (str->buffer == NULL) smb_panic("init_string2: malloc fail\n"); memcpy(str->buffer, buf, str_len); - } + } } /******************************************************************* @@ -860,7 +854,7 @@ BOOL smb_io_string2(const char *desc, STRING2 *str2, uint32 buffer, prs_struct * if(!prs_uint32("str_max_len", ps, depth, &str2->str_max_len)) return False; - if(!prs_uint32("undoc ", ps, depth, &str2->undoc)) + if(!prs_uint32("offset ", ps, depth, &str2->offset)) return False; if(!prs_uint32("str_str_len", ps, depth, &str2->str_str_len)) return False; @@ -885,34 +879,43 @@ BOOL smb_io_string2(const char *desc, STRING2 *str2, uint32 buffer, prs_struct * Inits a UNISTR2 structure. ********************************************************************/ -void init_unistr2(UNISTR2 *str, const char *buf, size_t len) +void init_unistr2(UNISTR2 *str, const char *buf, enum unistr2_term_codes flags) { - ZERO_STRUCTP(str); + size_t len = 0; + uint32 num_chars = 0; - /* set up string lengths. */ - str->uni_max_len = (uint32)len; - str->undoc = 0; - str->uni_str_len = (uint32)len; + if (buf) { + /* We always null terminate the copy. */ + len = strlen(buf) + 1; + } if (len < MAX_UNISTRLEN) len = MAX_UNISTRLEN; len *= sizeof(uint16); str->buffer = (uint16 *)talloc_zero(get_talloc_ctx(), len); - if ((str->buffer == NULL) && (len > 0)) - { + if ((str->buffer == NULL) && (len > 0)) { smb_panic("init_unistr2: malloc fail\n"); return; } /* - * don't move this test above ! The UNISTR2 must be initialized !!! + * The UNISTR2 must be initialized !!! * jfm, 7/7/2001. */ - if (buf==NULL) - return; + if (buf) { + rpcstr_push((char *)str->buffer, buf, len, STR_TERMINATE); + num_chars = strlen_w(str->buffer); + if (flags == STR_TERMINATE || flags == UNI_MAXLEN_TERMINATE) { + num_chars++; + } + } - rpcstr_push((char *)str->buffer, buf, len, STR_TERMINATE); + str->uni_max_len = num_chars; + str->offset = 0; + str->uni_str_len = num_chars; + if (num_chars && (flags == UNI_MAXLEN_TERMINATE)) + str->uni_max_len++; } /** @@ -932,7 +935,7 @@ void init_unistr2_w(TALLOC_CTX *ctx, UNISTR2 *str, const smb_ucs2_t *buf) /* set up string lengths. */ str->uni_max_len = len; - str->undoc = 0; + str->offset = 0; str->uni_str_len = len; if (max_len < MAX_UNISTRLEN) @@ -941,8 +944,7 @@ void init_unistr2_w(TALLOC_CTX *ctx, UNISTR2 *str, const smb_ucs2_t *buf) alloc_len = (max_len + 1) * sizeof(uint16); str->buffer = (uint16 *)talloc_zero(ctx, alloc_len); - if ((str->buffer == NULL) && (alloc_len > 0)) - { + if ((str->buffer == NULL) && (alloc_len > 0)) { smb_panic("init_unistr2_w: malloc fail\n"); return; } @@ -963,9 +965,9 @@ void init_unistr2_w(TALLOC_CTX *ctx, UNISTR2 *str, const smb_ucs2_t *buf) /******************************************************************* Inits a UNISTR2 structure from a UNISTR ********************************************************************/ -void init_unistr2_from_unistr (UNISTR2 *to, const UNISTR *from) -{ +void init_unistr2_from_unistr(UNISTR2 *to, const UNISTR *from) +{ uint32 i; /* the destination UNISTR2 should never be NULL. @@ -987,7 +989,7 @@ void init_unistr2_from_unistr (UNISTR2 *to, const UNISTR *from) /* set up string lengths; uni_max_len is set to i+1 because we need to account for the final NULL termination */ to->uni_max_len = i; - to->undoc = 0; + to->offset = 0; to->uni_str_len = i; /* allocate the space and copy the string buffer */ @@ -995,11 +997,9 @@ void init_unistr2_from_unistr (UNISTR2 *to, const UNISTR *from) if (to->buffer == NULL) smb_panic("init_unistr2_from_unistr: malloc fail\n"); memcpy(to->buffer, from->buffer, to->uni_max_len*sizeof(uint16)); - return; } - /******************************************************************* Reads or writes a UNISTR2 structure. XXXX NOTE: UNISTR2 structures need NOT be null-terminated. @@ -1022,7 +1022,7 @@ BOOL smb_io_unistr2(const char *desc, UNISTR2 *uni2, uint32 buffer, prs_struct * if(!prs_uint32("uni_max_len", ps, depth, &uni2->uni_max_len)) return False; - if(!prs_uint32("undoc ", ps, depth, &uni2->undoc)) + if(!prs_uint32("offset ", ps, depth, &uni2->offset)) return False; if(!prs_uint32("uni_str_len", ps, depth, &uni2->uni_str_len)) return False; @@ -1064,7 +1064,7 @@ BOOL init_unistr2_array(UNISTR2_ARRAY *array, } for (i=0;istrings[i].string, strings[i], strlen(strings[i])); + init_unistr2(&array->strings[i].string, strings[i], UNI_FLAGS_NONE); array->strings[i].size = array->strings[i].string.uni_max_len*2; array->strings[i].length = array->strings[i].size; array->strings[i].ref_id = 1; @@ -1223,14 +1223,14 @@ static void init_clnt_srv(DOM_CLNT_SRV *logcln, const char *logon_srv, const cha if (logon_srv != NULL) { logcln->undoc_buffer = 1; - init_unistr2(&logcln->uni_logon_srv, logon_srv, strlen(logon_srv)+1); + init_unistr2(&logcln->uni_logon_srv, logon_srv, UNI_STR_TERMINATE); } else { logcln->undoc_buffer = 0; } if (comp_name != NULL) { logcln->undoc_buffer2 = 1; - init_unistr2(&logcln->uni_comp_name, comp_name, strlen(comp_name)+1); + init_unistr2(&logcln->uni_comp_name, comp_name, UNI_STR_TERMINATE); } else { logcln->undoc_buffer2 = 0; } @@ -1284,12 +1284,12 @@ void init_log_info(DOM_LOG_INFO *loginfo, const char *logon_srv, const char *acc loginfo->undoc_buffer = 1; - init_unistr2(&loginfo->uni_logon_srv, logon_srv, strlen(logon_srv)+1); - init_unistr2(&loginfo->uni_acct_name, acct_name, strlen(acct_name)+1); + init_unistr2(&loginfo->uni_logon_srv, logon_srv, UNI_STR_TERMINATE); + init_unistr2(&loginfo->uni_acct_name, acct_name, UNI_STR_TERMINATE); loginfo->sec_chan = sec_chan; - init_unistr2(&loginfo->uni_comp_name, comp_name, strlen(comp_name)+1); + init_unistr2(&loginfo->uni_comp_name, comp_name, UNI_STR_TERMINATE); } /******************************************************************* diff --git a/source3/rpc_parse/parse_net.c b/source3/rpc_parse/parse_net.c index dd319df5a0..3b096e088a 100644 --- a/source3/rpc_parse/parse_net.c +++ b/source3/rpc_parse/parse_net.c @@ -136,16 +136,15 @@ static BOOL net_io_netinfo_1(const char *desc, NETLOGON_INFO_1 *info, prs_struct static void init_netinfo_2(NETLOGON_INFO_2 *info, uint32 flags, uint32 pdc_status, uint32 tc_status, const char *trusted_dc_name) { - int len_dc_name = strlen(trusted_dc_name); info->flags = flags; info->pdc_status = pdc_status; info->ptr_trusted_dc_name = 1; info->tc_status = tc_status; if (trusted_dc_name != NULL) - init_unistr2(&info->uni_trusted_dc_name, trusted_dc_name, len_dc_name+1); + init_unistr2(&info->uni_trusted_dc_name, trusted_dc_name, UNI_STR_TERMINATE); else - init_unistr2(&info->uni_trusted_dc_name, "", 1); + init_unistr2(&info->uni_trusted_dc_name, "", UNI_STR_TERMINATE); } /******************************************************************* @@ -230,7 +229,7 @@ void init_net_q_logon_ctrl2(NET_Q_LOGON_CTRL2 *q_l, const char *srv_name, q_l->query_level = query_level; q_l->switch_value = 0x01; - init_unistr2(&q_l->uni_server_name, srv_name, strlen(srv_name) + 1); + init_unistr2(&q_l->uni_server_name, srv_name, UNI_STR_TERMINATE); } /******************************************************************* @@ -360,7 +359,7 @@ void init_net_q_logon_ctrl(NET_Q_LOGON_CTRL *q_l, const char *srv_name, q_l->function_code = 0x01; /* ??? */ q_l->query_level = query_level; - init_unistr2(&q_l->uni_server_name, srv_name, strlen(srv_name) + 1); + init_unistr2(&q_l->uni_server_name, srv_name, UNI_STR_TERMINATE); } /******************************************************************* @@ -447,9 +446,9 @@ void init_r_trust_dom(NET_R_TRUST_DOM_LIST *r_t, fstring domain_name; fstrcpy(domain_name, dom_name); strupper_m(domain_name); - init_unistr2(&r_t->uni_trust_dom_name[i], domain_name, strlen(domain_name)+1); + init_unistr2(&r_t->uni_trust_dom_name[i], domain_name, UNI_STR_TERMINATE); /* the use of UNISTR2 here is non-standard. */ - r_t->uni_trust_dom_name[i].undoc = 0x1; + r_t->uni_trust_dom_name[i].offset = 0x1; } r_t->status = NT_STATUS_OK; @@ -539,8 +538,8 @@ void init_q_req_chal(NET_Q_REQ_CHAL *q_c, q_c->undoc_buffer = 1; /* don't know what this buffer is */ - init_unistr2(&q_c->uni_logon_srv, logon_srv , strlen(logon_srv )+1); - init_unistr2(&q_c->uni_logon_clnt, logon_clnt, strlen(logon_clnt)+1); + init_unistr2(&q_c->uni_logon_srv, logon_srv , UNI_STR_TERMINATE); + init_unistr2(&q_c->uni_logon_clnt, logon_clnt, UNI_STR_TERMINATE); memcpy(q_c->clnt_chal.data, clnt_chal->data, sizeof(clnt_chal->data)); @@ -910,10 +909,6 @@ void init_id_info1(NET_ID_INFO_1 *id, const char *domain_name, const char *sess_key, unsigned char lm_cypher[16], unsigned char nt_cypher[16]) { - int len_domain_name = strlen(domain_name); - int len_user_name = strlen(user_name ); - int len_wksta_name = strlen(wksta_name ); - unsigned char lm_owf[16]; unsigned char nt_owf[16]; @@ -921,13 +916,9 @@ void init_id_info1(NET_ID_INFO_1 *id, const char *domain_name, id->ptr_id_info1 = 1; - init_uni_hdr(&id->hdr_domain_name, len_domain_name); - id->param_ctrl = param_ctrl; init_logon_id(&id->logon_id, log_id_low, log_id_high); - init_uni_hdr(&id->hdr_user_name, len_user_name); - init_uni_hdr(&id->hdr_wksta_name, len_wksta_name); if (lm_cypher && nt_cypher) { unsigned char key[16]; @@ -962,9 +953,12 @@ void init_id_info1(NET_ID_INFO_1 *id, const char *domain_name, init_owf_info(&id->lm_owf, lm_cypher); init_owf_info(&id->nt_owf, nt_cypher); - init_unistr2(&id->uni_domain_name, domain_name, len_domain_name); - init_unistr2(&id->uni_user_name, user_name, len_user_name); - init_unistr2(&id->uni_wksta_name, wksta_name, len_wksta_name); + init_unistr2(&id->uni_domain_name, domain_name, UNI_FLAGS_NONE); + init_uni_hdr(&id->hdr_domain_name, &id->uni_domain_name); + init_unistr2(&id->uni_user_name, user_name, UNI_FLAGS_NONE); + init_uni_hdr(&id->hdr_user_name, &id->uni_user_name); + init_unistr2(&id->uni_wksta_name, wksta_name, UNI_FLAGS_NONE); + init_uni_hdr(&id->hdr_wksta_name, &id->uni_wksta_name); } /******************************************************************* @@ -1041,9 +1035,6 @@ void init_id_info2(NET_ID_INFO_2 * id, const char *domain_name, const uchar * lm_chal_resp, size_t lm_chal_resp_len, const uchar * nt_chal_resp, size_t nt_chal_resp_len) { - size_t len_domain_name = strlen(domain_name); - size_t len_user_name = strlen(user_name ); - size_t len_wksta_name = strlen(wksta_name ); unsigned char lm_owf[24]; unsigned char nt_owf[128]; @@ -1051,14 +1042,10 @@ void init_id_info2(NET_ID_INFO_2 * id, const char *domain_name, id->ptr_id_info2 = 1; - init_uni_hdr(&id->hdr_domain_name, len_domain_name); id->param_ctrl = param_ctrl; init_logon_id(&id->logon_id, log_id_low, log_id_high); - init_uni_hdr(&id->hdr_user_name, len_user_name); - init_uni_hdr(&id->hdr_wksta_name, len_wksta_name); - if (nt_chal_resp) { /* oops. can only send what-ever-it-is direct */ memcpy(nt_owf, nt_chal_resp, MIN(sizeof(nt_owf), nt_chal_resp_len)); @@ -1074,9 +1061,12 @@ void init_id_info2(NET_ID_INFO_2 * id, const char *domain_name, init_str_hdr(&id->hdr_nt_chal_resp, nt_chal_resp_len, nt_chal_resp_len, (nt_chal_resp != NULL) ? 1 : 0); init_str_hdr(&id->hdr_lm_chal_resp, lm_chal_resp_len, lm_chal_resp_len, (lm_chal_resp != NULL) ? 1 : 0); - init_unistr2(&id->uni_domain_name, domain_name, len_domain_name); - init_unistr2(&id->uni_user_name, user_name, len_user_name); - init_unistr2(&id->uni_wksta_name, wksta_name, len_wksta_name); + init_unistr2(&id->uni_domain_name, domain_name, UNI_FLAGS_NONE); + init_uni_hdr(&id->hdr_domain_name, &id->uni_domain_name); + init_unistr2(&id->uni_user_name, user_name, UNI_FLAGS_NONE); + init_uni_hdr(&id->hdr_user_name, &id->uni_user_name); + init_unistr2(&id->uni_wksta_name, wksta_name, UNI_FLAGS_NONE); + init_uni_hdr(&id->hdr_wksta_name, &id->uni_wksta_name); init_string2(&id->nt_chal_resp, (const char *)nt_chal_resp, nt_chal_resp_len, nt_chal_resp_len); init_string2(&id->lm_chal_resp, (const char *)lm_chal_resp, lm_chal_resp_len, lm_chal_resp_len); @@ -1288,26 +1278,10 @@ void init_net_user_info3(TALLOC_CTX *ctx, NET_USER_INFO_3 *usr, pass_last_set_time, pass_can_change_time, pass_must_change_time; - int len_user_name, len_full_name, len_home_dir, - len_dir_drive, len_logon_script, len_profile_path; - - int len_logon_srv = strlen(logon_srv); - int len_logon_dom = strlen(logon_dom); - - len_user_name = strlen(user_name ); - len_full_name = strlen(full_name ); - len_home_dir = strlen(home_dir ); - len_dir_drive = strlen(dir_drive ); - len_logon_script = strlen(logon_script); - len_profile_path = strlen(profile_path); - - ZERO_STRUCTP(usr); usr->ptr_user_info = 1; /* yes, we're bothering to put USER_INFO data here */ - - /* Create NTTIME structs */ unix_to_nt_time (&logon_time, unix_logon_time); unix_to_nt_time (&logoff_time, unix_logoff_time); @@ -1323,13 +1297,6 @@ void init_net_user_info3(TALLOC_CTX *ctx, NET_USER_INFO_3 *usr, usr->pass_can_change_time = pass_can_change_time; usr->pass_must_change_time = pass_must_change_time; - init_uni_hdr(&usr->hdr_user_name, len_user_name); - init_uni_hdr(&usr->hdr_full_name, len_full_name); - init_uni_hdr(&usr->hdr_logon_script, len_logon_script); - init_uni_hdr(&usr->hdr_profile_path, len_profile_path); - init_uni_hdr(&usr->hdr_home_dir, len_home_dir); - init_uni_hdr(&usr->hdr_dir_drive, len_dir_drive); - usr->logon_count = logon_count; usr->bad_pw_count = bad_pw_count; @@ -1345,9 +1312,6 @@ void init_net_user_info3(TALLOC_CTX *ctx, NET_USER_INFO_3 *usr, else memset((char *)usr->user_sess_key, '\0', sizeof(usr->user_sess_key)); - init_uni_hdr(&usr->hdr_logon_srv, len_logon_srv); - init_uni_hdr(&usr->hdr_logon_dom, len_logon_dom); - usr->buffer_dom_id = dom_sid ? 1 : 0; /* yes, we're bothering to put a domain SID in */ memset((char *)usr->padding, '\0', sizeof(usr->padding)); @@ -1357,12 +1321,18 @@ void init_net_user_info3(TALLOC_CTX *ctx, NET_USER_INFO_3 *usr, usr->num_other_sids = num_other_sids; usr->buffer_other_sids = (num_other_sids != 0) ? 1 : 0; - init_unistr2(&usr->uni_user_name, user_name, len_user_name); - init_unistr2(&usr->uni_full_name, full_name, len_full_name); - init_unistr2(&usr->uni_logon_script, logon_script, len_logon_script); - init_unistr2(&usr->uni_profile_path, profile_path, len_profile_path); - init_unistr2(&usr->uni_home_dir, home_dir, len_home_dir); - init_unistr2(&usr->uni_dir_drive, dir_drive, len_dir_drive); + init_unistr2(&usr->uni_user_name, user_name, UNI_FLAGS_NONE); + init_uni_hdr(&usr->hdr_user_name, &usr->uni_user_name); + init_unistr2(&usr->uni_full_name, full_name, UNI_FLAGS_NONE); + init_uni_hdr(&usr->hdr_full_name, &usr->uni_full_name); + init_unistr2(&usr->uni_logon_script, logon_script, UNI_FLAGS_NONE); + init_uni_hdr(&usr->hdr_logon_script, &usr->uni_logon_script); + init_unistr2(&usr->uni_profile_path, profile_path, UNI_FLAGS_NONE); + init_uni_hdr(&usr->hdr_profile_path, &usr->uni_profile_path); + init_unistr2(&usr->uni_home_dir, home_dir, UNI_FLAGS_NONE); + init_uni_hdr(&usr->hdr_home_dir, &usr->uni_home_dir); + init_unistr2(&usr->uni_dir_drive, dir_drive, UNI_FLAGS_NONE); + init_uni_hdr(&usr->hdr_dir_drive, &usr->uni_dir_drive); usr->num_groups2 = num_groups; @@ -1373,8 +1343,10 @@ void init_net_user_info3(TALLOC_CTX *ctx, NET_USER_INFO_3 *usr, for (i = 0; i < num_groups; i++) usr->gids[i] = gids[i]; - init_unistr2(&usr->uni_logon_srv, logon_srv, len_logon_srv); - init_unistr2(&usr->uni_logon_dom, logon_dom, len_logon_dom); + init_unistr2(&usr->uni_logon_srv, logon_srv, UNI_FLAGS_NONE); + init_uni_hdr(&usr->hdr_logon_srv, &usr->uni_logon_srv); + init_unistr2(&usr->uni_logon_dom, logon_dom, UNI_FLAGS_NONE); + init_uni_hdr(&usr->hdr_logon_dom, &usr->uni_logon_dom); init_dom_sid2(&usr->dom_sid, dom_sid); /* "other" sids are set up above */ @@ -1670,8 +1642,8 @@ BOOL init_net_q_sam_sync(NET_Q_SAM_SYNC * q_s, const char *srv_name, { DEBUG(5, ("init_q_sam_sync\n")); - init_unistr2(&q_s->uni_srv_name, srv_name, strlen(srv_name) + 1); - init_unistr2(&q_s->uni_cli_name, cli_name, strlen(cli_name) + 1); + init_unistr2(&q_s->uni_srv_name, srv_name, UNI_STR_TERMINATE); + init_unistr2(&q_s->uni_cli_name, cli_name, UNI_STR_TERMINATE); if (cli_creds) memcpy(&q_s->cli_creds, cli_creds, sizeof(q_s->cli_creds)); @@ -2858,8 +2830,8 @@ BOOL init_net_q_sam_deltas(NET_Q_SAM_DELTAS *q_s, const char *srv_name, { DEBUG(5, ("init_net_q_sam_deltas\n")); - init_unistr2(&q_s->uni_srv_name, srv_name, strlen(srv_name) + 1); - init_unistr2(&q_s->uni_cli_name, cli_name, strlen(cli_name) + 1); + init_unistr2(&q_s->uni_srv_name, srv_name, UNI_STR_TERMINATE); + init_unistr2(&q_s->uni_cli_name, cli_name, UNI_STR_TERMINATE); memcpy(&q_s->cli_creds, cli_creds, sizeof(q_s->cli_creds)); memset(&q_s->ret_creds, 0, sizeof(q_s->ret_creds)); diff --git a/source3/rpc_parse/parse_reg.c b/source3/rpc_parse/parse_reg.c index bbf6e6a8e3..69c0dfc754 100644 --- a/source3/rpc_parse/parse_reg.c +++ b/source3/rpc_parse/parse_reg.c @@ -281,18 +281,15 @@ void init_reg_q_create_key(REG_Q_CREATE_KEY *q_c, POLICY_HND *hnd, char *name, char *class, SEC_ACCESS *sam_access, SEC_DESC_BUF *sec_buf) { - int len_name = name != NULL ? strlen(name ) + 1: 0; - int len_class = class != NULL ? strlen(class) + 1: 0; - ZERO_STRUCTP(q_c); memcpy(&q_c->pnt_pol, hnd, sizeof(q_c->pnt_pol)); - init_uni_hdr(&q_c->hdr_name, len_name); - init_unistr2(&q_c->uni_name, name, len_name); + init_unistr2(&q_c->uni_name, name, UNI_STR_TERMINATE); + init_uni_hdr(&q_c->hdr_name, &q_c->uni_name); - init_uni_hdr(&q_c->hdr_class, len_class); - init_unistr2(&q_c->uni_class, class, len_class); + init_unistr2(&q_c->uni_class, class, UNI_STR_TERMINATE); + init_uni_hdr(&q_c->hdr_class, &q_c->uni_class); q_c->reserved = 0x00000000; memcpy(&q_c->sam_access, sam_access, sizeof(q_c->sam_access)); @@ -397,13 +394,12 @@ BOOL reg_io_r_create_key(const char *desc, REG_R_CREATE_KEY *r_r, prs_struct *p void init_reg_q_delete_val(REG_Q_DELETE_VALUE *q_c, POLICY_HND *hnd, char *name) { - int len_name = name != NULL ? strlen(name ) + 1: 0; ZERO_STRUCTP(q_c); memcpy(&q_c->pnt_pol, hnd, sizeof(q_c->pnt_pol)); - init_uni_hdr(&q_c->hdr_name, len_name); - init_unistr2(&q_c->uni_name, name, len_name); + init_unistr2(&q_c->uni_name, name, UNI_STR_TERMINATE); + init_uni_hdr(&q_c->hdr_name, &q_c->uni_name); } /******************************************************************* @@ -463,13 +459,12 @@ BOOL reg_io_r_delete_val(const char *desc, REG_R_DELETE_VALUE *r_r, prs_struct void init_reg_q_delete_key(REG_Q_DELETE_KEY *q_c, POLICY_HND *hnd, char *name) { - int len_name = name != NULL ? strlen(name ) + 1: 0; ZERO_STRUCTP(q_c); memcpy(&q_c->pnt_pol, hnd, sizeof(q_c->pnt_pol)); - init_uni_hdr(&q_c->hdr_name, len_name); - init_unistr2(&q_c->uni_name, name, len_name); + init_unistr2(&q_c->uni_name, name, UNI_STR_TERMINATE); + init_uni_hdr(&q_c->hdr_name, &q_c->uni_name); } /******************************************************************* @@ -525,14 +520,12 @@ BOOL reg_io_r_delete_key(const char *desc, REG_R_DELETE_KEY *r_r, prs_struct *p Inits a structure. ********************************************************************/ -void init_reg_q_query_key(REG_Q_QUERY_KEY *q_o, POLICY_HND *hnd, - uint32 max_class_len) +void init_reg_q_query_key(REG_Q_QUERY_KEY *q_o, POLICY_HND *hnd, UNISTR2 *uni2) { ZERO_STRUCTP(q_o); memcpy(&q_o->pol, hnd, sizeof(q_o->pol)); - init_uni_hdr(&q_o->hdr_class, max_class_len); - q_o->uni_class.uni_max_len = max_class_len; + init_uni_hdr(&q_o->hdr_class, uni2); } /******************************************************************* @@ -1010,15 +1003,13 @@ makes a structure. BOOL init_reg_q_info(REG_Q_INFO *q_i, POLICY_HND *pol, char* val_name) { - int len_type = val_name != NULL ? strlen(val_name) + 1 : 0; - if (q_i == NULL) return False; q_i->pol = *pol; - init_uni_hdr(&(q_i->hdr_type), len_type); - init_unistr2(&(q_i->uni_type), val_name, len_type); + init_unistr2(&q_i->uni_type, val_name, UNI_STR_TERMINATE); + init_uni_hdr(&q_i->hdr_type, &q_i->uni_type); q_i->ptr_reserved = 1; q_i->ptr_buf = 1; @@ -1230,7 +1221,7 @@ makes a structure. ********************************************************************/ void init_reg_q_enum_val(REG_Q_ENUM_VALUE *q_i, POLICY_HND *pol, - uint32 val_idx, uint32 max_val_len, + uint32 val_idx, UNISTR2 *uni2, uint32 max_buf_len) { ZERO_STRUCTP(q_i); @@ -1238,8 +1229,7 @@ void init_reg_q_enum_val(REG_Q_ENUM_VALUE *q_i, POLICY_HND *pol, memcpy(&q_i->pol, pol, sizeof(q_i->pol)); q_i->val_index = val_idx; - init_uni_hdr(&q_i->hdr_name, max_val_len); - q_i->uni_name.uni_max_len = max_val_len; + init_uni_hdr(&q_i->hdr_name, uni2); q_i->ptr_type = 1; q_i->type = 0x0; @@ -1270,8 +1260,8 @@ void init_reg_r_enum_val(REG_R_ENUM_VALUE *r_u, REGISTRY_VALUE *val ) DEBUG(10,("init_reg_r_enum_val: Valuename => [%s]\n", val->valuename)); - init_uni_hdr( &r_u->hdr_name, strlen(val->valuename)+1 ); - init_unistr2( &r_u->uni_name, val->valuename, strlen(val->valuename)+1 ); + init_unistr2( &r_u->uni_name, val->valuename, UNI_STR_TERMINATE); + init_uni_hdr( &r_u->hdr_name, &r_u->uni_name); /* type */ @@ -1418,14 +1408,12 @@ void init_reg_q_create_val(REG_Q_CREATE_VALUE *q_i, POLICY_HND *pol, char *val_name, uint32 type, BUFFER3 *val) { - int val_len = strlen(val_name) + 1; - ZERO_STRUCTP(q_i); memcpy(&q_i->pol, pol, sizeof(q_i->pol)); - init_uni_hdr(&q_i->hdr_name, val_len); - init_unistr2(&q_i->uni_name, val_name, val_len); + init_unistr2(&q_i->uni_name, val_name, UNI_STR_TERMINATE); + init_uni_hdr(&q_i->hdr_name, &q_i->uni_name); q_i->type = type; q_i->buf_value = val; @@ -1650,12 +1638,10 @@ makes a structure. void init_reg_q_open_entry(REG_Q_OPEN_ENTRY *r_q, POLICY_HND *pol, char *key_name, uint32 access_desired) { - int len_name = strlen(key_name)+1; - memcpy(&r_q->pol, pol, sizeof(r_q->pol)); - init_uni_hdr(&r_q->hdr_name, len_name); - init_unistr2(&r_q->uni_name, key_name, len_name); + init_unistr2(&r_q->uni_name, key_name, UNI_STR_TERMINATE); + init_uni_hdr(&r_q->hdr_name, &r_q->uni_name); r_q->unknown_0 = 0x00000000; r_q->access_desired = access_desired; @@ -1736,29 +1722,27 @@ BOOL reg_io_r_open_entry(const char *desc, REG_R_OPEN_ENTRY *r_r, prs_struct *p /******************************************************************* Inits a structure. ********************************************************************/ + void init_reg_q_shutdown(REG_Q_SHUTDOWN * q_s, const char *msg, uint32 timeout, BOOL do_reboot, BOOL force) { - int msg_len; - msg_len = strlen(msg); - q_s->ptr_0 = 1; q_s->ptr_1 = 1; q_s->ptr_2 = 1; - init_uni_hdr(&(q_s->hdr_msg), msg_len); - init_unistr2(&(q_s->uni_msg), msg, msg_len); + init_unistr2(&q_s->uni_msg, msg, UNI_FLAGS_NONE); + init_uni_hdr(&q_s->hdr_msg, &q_s->uni_msg); q_s->timeout = timeout; q_s->reboot = do_reboot ? 1 : 0; q_s->force = force ? 1 : 0; - } /******************************************************************* reads or writes a structure. ********************************************************************/ + BOOL reg_io_q_shutdown(const char *desc, REG_Q_SHUTDOWN * q_s, prs_struct *ps, int depth) { diff --git a/source3/rpc_parse/parse_samr.c b/source3/rpc_parse/parse_samr.c index 420a727765..939b652a1e 100644 --- a/source3/rpc_parse/parse_samr.c +++ b/source3/rpc_parse/parse_samr.c @@ -93,14 +93,12 @@ inits a SAMR_Q_LOOKUP_DOMAIN structure. void init_samr_q_lookup_domain(SAMR_Q_LOOKUP_DOMAIN * q_u, POLICY_HND *pol, char *dom_name) { - int len_name = strlen(dom_name); - DEBUG(5, ("init_samr_q_lookup_domain\n")); q_u->connect_pol = *pol; - init_uni_hdr(&q_u->hdr_domain, len_name); - init_unistr2(&q_u->uni_domain, dom_name, len_name); + init_unistr2(&q_u->uni_domain, dom_name, UNI_FLAGS_NONE); + init_uni_hdr(&q_u->hdr_domain, &q_u->uni_domain); } /******************************************************************* @@ -630,13 +628,11 @@ static BOOL sam_io_unk_info12(const char *desc, SAM_UNK_INFO_12 * u_12, /******************************************************************* inits a structure. ********************************************************************/ + void init_unk_info5(SAM_UNK_INFO_5 * u_5,const char *server) { - int len_server = strlen(server); - - init_uni_hdr(&u_5->hdr_server, len_server); - - init_unistr2(&u_5->uni_server, server, len_server); + init_unistr2(&u_5->uni_server, server, UNI_FLAGS_NONE); + init_uni_hdr(&u_5->hdr_server, &u_5->uni_server); } /******************************************************************* @@ -664,20 +660,16 @@ static BOOL sam_io_unk_info5(const char *desc, SAM_UNK_INFO_5 * u_5, /******************************************************************* inits a structure. ********************************************************************/ + void init_unk_info2(SAM_UNK_INFO_2 * u_2, const char *domain, const char *server, uint32 seq_num, uint32 num_users, uint32 num_groups, uint32 num_alias) { - int len_domain = strlen(domain); - int len_server = strlen(server); - u_2->unknown_0 = 0x00000000; u_2->unknown_1 = 0x80000000; u_2->unknown_2 = 0x00000000; u_2->ptr_0 = 1; - init_uni_hdr(&u_2->hdr_domain, len_domain); - init_uni_hdr(&u_2->hdr_server, len_server); u_2->seq_num = seq_num; u_2->unknown_3 = 0x00000000; @@ -691,8 +683,10 @@ void init_unk_info2(SAM_UNK_INFO_2 * u_2, memset(u_2->padding, 0, sizeof(u_2->padding)); /* 12 bytes zeros */ - init_unistr2(&u_2->uni_domain, domain, len_domain); - init_unistr2(&u_2->uni_server, server, len_server); + init_unistr2(&u_2->uni_domain, domain, UNI_FLAGS_NONE); + init_uni_hdr(&u_2->hdr_domain, &u_2->uni_domain); + init_unistr2(&u_2->uni_server, server, UNI_FLAGS_NONE); + init_uni_hdr(&u_2->hdr_server, &u_2->uni_server); } /******************************************************************* @@ -984,9 +978,9 @@ static BOOL sam_io_sam_str1(const char *desc, SAM_STR1 * sam, uint32 acct_buf, inits a SAM_ENTRY1 structure. ********************************************************************/ -static void init_sam_entry1(SAM_ENTRY1 * sam, uint32 user_idx, - uint32 len_sam_name, uint32 len_sam_full, - uint32 len_sam_desc, uint32 rid_user, +static void init_sam_entry1(SAM_ENTRY1 *sam, uint32 user_idx, + UNISTR2 *sam_name, UNISTR2 *sam_full, + UNISTR2 *sam_desc, uint32 rid_user, uint16 acb_info) { DEBUG(5, ("init_sam_entry1\n")); @@ -997,9 +991,9 @@ static void init_sam_entry1(SAM_ENTRY1 * sam, uint32 user_idx, sam->rid_user = rid_user; sam->acb_info = acb_info; - init_uni_hdr(&sam->hdr_acct_name, len_sam_name); - init_uni_hdr(&sam->hdr_user_name, len_sam_full); - init_uni_hdr(&sam->hdr_user_desc, len_sam_desc); + init_uni_hdr(&sam->hdr_acct_name, sam_name); + init_uni_hdr(&sam->hdr_user_name, sam_full); + init_uni_hdr(&sam->hdr_user_desc, sam_desc); } /******************************************************************* @@ -1067,7 +1061,7 @@ static BOOL sam_io_sam_str2(const char *desc, SAM_STR2 * sam, uint32 acct_buf, inits a SAM_ENTRY2 structure. ********************************************************************/ static void init_sam_entry2(SAM_ENTRY2 * sam, uint32 user_idx, - uint32 len_sam_name, uint32 len_sam_desc, + UNISTR2 *sam_name, UNISTR2 *sam_desc, uint32 rid_user, uint16 acb_info) { DEBUG(5, ("init_sam_entry2\n")); @@ -1076,8 +1070,8 @@ static void init_sam_entry2(SAM_ENTRY2 * sam, uint32 user_idx, sam->rid_user = rid_user; sam->acb_info = acb_info; - init_uni_hdr(&sam->hdr_srv_name, len_sam_name); - init_uni_hdr(&sam->hdr_srv_desc, len_sam_desc); + init_uni_hdr(&sam->hdr_srv_name, sam_name); + init_uni_hdr(&sam->hdr_srv_desc, sam_desc); } /******************************************************************* @@ -1144,7 +1138,7 @@ inits a SAM_ENTRY3 structure. ********************************************************************/ static void init_sam_entry3(SAM_ENTRY3 * sam, uint32 grp_idx, - uint32 len_grp_name, uint32 len_grp_desc, + UNISTR2 *grp_name, UNISTR2 *grp_desc, uint32 rid_grp) { DEBUG(5, ("init_sam_entry3\n")); @@ -1153,8 +1147,8 @@ static void init_sam_entry3(SAM_ENTRY3 * sam, uint32 grp_idx, sam->rid_grp = rid_grp; sam->attr = 0x07; /* group rid attributes - gets ignored by nt 4.0 */ - init_uni_hdr(&sam->hdr_grp_name, len_grp_name); - init_uni_hdr(&sam->hdr_grp_desc, len_grp_desc); + init_uni_hdr(&sam->hdr_grp_name, grp_name); + init_uni_hdr(&sam->hdr_grp_desc, grp_desc); } /******************************************************************* @@ -1268,12 +1262,12 @@ static BOOL sam_io_sam_entry5(const char *desc, SAM_ENTRY5 * sam, inits a SAM_ENTRY structure. ********************************************************************/ -void init_sam_entry(SAM_ENTRY * sam, uint32 len_sam_name, uint32 rid) +void init_sam_entry(SAM_ENTRY *sam, UNISTR2 *uni2, uint32 rid) { - DEBUG(10, ("init_sam_entry: %d %d\n", len_sam_name, rid)); + DEBUG(10, ("init_sam_entry: %d\n", rid)); sam->rid = rid; - init_uni_hdr(&sam->hdr_name, len_sam_name); + init_uni_hdr(&sam->hdr_name, uni2); } /******************************************************************* @@ -1502,7 +1496,6 @@ NTSTATUS init_sam_dispinfo_1(TALLOC_CTX *ctx, SAM_DISPINFO_1 *sam, uint32 num_en uint32 start_idx, SAM_ACCOUNT *disp_user_info, DOM_SID *domain_sid) { - uint32 len_sam_name, len_sam_full, len_sam_desc; uint32 i; SAM_ACCOUNT *pwd = NULL; @@ -1560,21 +1553,14 @@ NTSTATUS init_sam_dispinfo_1(TALLOC_CTX *ctx, SAM_DISPINFO_1 *sam, uint32 num_en return NT_STATUS_UNSUCCESSFUL; } - len_sam_name = strlen(username); - len_sam_full = strlen(fullname); - len_sam_desc = strlen(acct_desc); + init_unistr2(&sam->str[i].uni_acct_name, pdb_get_username(pwd), UNI_FLAGS_NONE); + init_unistr2(&sam->str[i].uni_full_name, pdb_get_fullname(pwd), UNI_FLAGS_NONE); + init_unistr2(&sam->str[i].uni_acct_desc, pdb_get_acct_desc(pwd), UNI_FLAGS_NONE); init_sam_entry1(&sam->sam[i], start_idx + i + 1, - len_sam_name, len_sam_full, len_sam_desc, + &sam->str[i].uni_acct_name, &sam->str[i].uni_full_name, &sam->str[i].uni_acct_desc, user_rid, pdb_get_acct_ctrl(pwd)); - ZERO_STRUCTP(&sam->str[i].uni_acct_name); - ZERO_STRUCTP(&sam->str[i].uni_full_name); - ZERO_STRUCTP(&sam->str[i].uni_acct_desc); - - init_unistr2(&sam->str[i].uni_acct_name, pdb_get_username(pwd), len_sam_name); - init_unistr2(&sam->str[i].uni_full_name, pdb_get_fullname(pwd), len_sam_full); - init_unistr2(&sam->str[i].uni_acct_desc, pdb_get_acct_desc(pwd), len_sam_desc); } return NT_STATUS_OK; @@ -1637,7 +1623,6 @@ NTSTATUS init_sam_dispinfo_2(TALLOC_CTX *ctx, SAM_DISPINFO_2 *sam, uint32 num_en uint32 start_idx, SAM_ACCOUNT *disp_user_info, DOM_SID *domain_sid ) { - uint32 len_sam_name, len_sam_desc; uint32 i; SAM_ACCOUNT *pwd = NULL; @@ -1680,18 +1665,12 @@ NTSTATUS init_sam_dispinfo_2(TALLOC_CTX *ctx, SAM_DISPINFO_2 *sam, uint32 num_en return NT_STATUS_UNSUCCESSFUL; } - len_sam_name = strlen(username); - len_sam_desc = strlen(acct_desc); - + init_unistr2(&sam->str[i].uni_srv_name, username, UNI_FLAGS_NONE); + init_unistr2(&sam->str[i].uni_srv_desc, pdb_get_acct_desc(pwd), UNI_FLAGS_NONE); + init_sam_entry2(&sam->sam[i], start_idx + i + 1, - len_sam_name, len_sam_desc, + &sam->str[i].uni_srv_name, &sam->str[i].uni_srv_desc, user_rid, pdb_get_acct_ctrl(pwd)); - - ZERO_STRUCTP(&sam->str[i].uni_srv_name); - ZERO_STRUCTP(&sam->str[i].uni_srv_desc); - - init_unistr2(&sam->str[i].uni_srv_name, username, len_sam_name); - init_unistr2(&sam->str[i].uni_srv_desc, pdb_get_acct_desc(pwd), len_sam_desc); } return NT_STATUS_OK; @@ -1755,7 +1734,6 @@ inits a SAM_DISPINFO_3 structure. NTSTATUS init_sam_dispinfo_3(TALLOC_CTX *ctx, SAM_DISPINFO_3 *sam, uint32 num_entries, uint32 start_idx, DOMAIN_GRP *disp_group_info) { - uint32 len_sam_name, len_sam_desc; uint32 i; ZERO_STRUCTP(sam); @@ -1779,13 +1757,11 @@ NTSTATUS init_sam_dispinfo_3(TALLOC_CTX *ctx, SAM_DISPINFO_3 *sam, uint32 num_en DEBUG(11, ("init_sam_dispinfo_3: entry: %d\n",i)); - len_sam_name = strlen(grp->name); - len_sam_desc = strlen(grp->comment); + init_unistr2(&sam->str[i].uni_grp_name, grp->name, UNI_FLAGS_NONE); + init_unistr2(&sam->str[i].uni_grp_desc, grp->comment, UNI_FLAGS_NONE); - init_sam_entry3(&sam->sam[i], start_idx + i + 1, len_sam_name, len_sam_desc, grp->rid); - - init_unistr2(&sam->str[i].uni_grp_name, grp->name, len_sam_name); - init_unistr2(&sam->str[i].uni_grp_desc, grp->comment, len_sam_desc); + init_sam_entry3(&sam->sam[i], start_idx + i + 1, &sam->str[i].uni_grp_name, + &sam->str[i].uni_grp_desc, grp->rid); } return NT_STATUS_OK; @@ -2210,20 +2186,15 @@ void init_samr_group_info1(GROUP_INFO1 * gr1, char *acct_name, char *acct_desc, uint32 num_members) { - int desc_len = acct_desc != NULL ? strlen(acct_desc) : 0; - int acct_len = acct_name != NULL ? strlen(acct_name) : 0; - DEBUG(5, ("init_samr_group_info1\n")); - init_uni_hdr(&gr1->hdr_acct_name, acct_len); - gr1->unknown_1 = 0x3; gr1->num_members = num_members; - init_uni_hdr(&gr1->hdr_acct_desc, desc_len); - - init_unistr2(&gr1->uni_acct_name, acct_name, acct_len); - init_unistr2(&gr1->uni_acct_desc, acct_desc, desc_len); + init_unistr2(&gr1->uni_acct_name, acct_name, UNI_FLAGS_NONE); + init_uni_hdr(&gr1->hdr_acct_name, &gr1->uni_acct_name); + init_unistr2(&gr1->uni_acct_desc, acct_desc, UNI_FLAGS_NONE); + init_uni_hdr(&gr1->hdr_acct_desc, &gr1->uni_acct_desc); } /******************************************************************* @@ -2302,12 +2273,10 @@ inits a GROUP_INFO4 structure. void init_samr_group_info4(GROUP_INFO4 * gr4, char *acct_desc) { - int acct_len = acct_desc != NULL ? strlen(acct_desc) : 0; - DEBUG(5, ("init_samr_group_info4\n")); - init_uni_hdr(&gr4->hdr_acct_desc, acct_len); - init_unistr2(&gr4->uni_acct_desc, acct_desc, acct_len); + init_unistr2(&gr4->uni_acct_desc, acct_desc, UNI_FLAGS_NONE); + init_uni_hdr(&gr4->hdr_acct_desc, &gr4->uni_acct_desc); } /******************************************************************* @@ -2383,14 +2352,12 @@ void init_samr_q_create_dom_group(SAMR_Q_CREATE_DOM_GROUP * q_e, POLICY_HND *pol, char *acct_desc, uint32 access_mask) { - int acct_len = acct_desc != NULL ? strlen(acct_desc) : 0; - DEBUG(5, ("init_samr_q_create_dom_group\n")); q_e->pol = *pol; - init_uni_hdr(&q_e->hdr_acct_desc, acct_len); - init_unistr2(&q_e->uni_acct_desc, acct_desc, acct_len); + init_unistr2(&q_e->uni_acct_desc, acct_desc, UNI_FLAGS_NONE); + init_uni_hdr(&q_e->hdr_acct_desc, &q_e->uni_acct_desc); q_e->access_mask = access_mask; } @@ -3502,18 +3469,15 @@ inits a ALIAS_INFO1 structure. void init_samr_alias_info1(ALIAS_INFO1 * al1, char *acct_name, uint32 num_member, char *acct_desc) { - int acct_len_name = acct_name != NULL ? strlen(acct_name) : 0; - int acct_len_desc = acct_desc != NULL ? strlen(acct_desc) : 0; - DEBUG(5, ("init_samr_alias_info1\n")); - init_uni_hdr(&al1->hdr_acct_name, acct_len_name); - init_unistr2(&al1->uni_acct_name, acct_name, acct_len_name); + init_unistr2(&al1->uni_acct_name, acct_name, UNI_FLAGS_NONE); + init_uni_hdr(&al1->hdr_acct_name, &al1->uni_acct_name); al1->num_member=num_member; - init_uni_hdr(&al1->hdr_acct_desc, acct_len_desc); - init_unistr2(&al1->uni_acct_desc, acct_desc, acct_len_desc); + init_unistr2(&al1->uni_acct_desc, acct_desc, UNI_FLAGS_NONE); + init_uni_hdr(&al1->hdr_acct_desc, &al1->uni_acct_name); } /******************************************************************* @@ -3559,12 +3523,10 @@ inits a ALIAS_INFO3 structure. void init_samr_alias_info3(ALIAS_INFO3 * al3, char *acct_desc) { - int acct_len = acct_desc != NULL ? strlen(acct_desc) : 0; - DEBUG(5, ("init_samr_alias_info3\n")); - init_uni_hdr(&al3->hdr_acct_desc, acct_len); - init_unistr2(&al3->uni_acct_desc, acct_desc, acct_len); + init_unistr2(&al3->uni_acct_desc, acct_desc, UNI_FLAGS_NONE); + init_uni_hdr(&al3->hdr_acct_desc, &al3->uni_acct_desc); } /******************************************************************* @@ -4272,14 +4234,12 @@ inits a SAMR_Q_CREATE_DOM_ALIAS structure. void init_samr_q_create_dom_alias(SAMR_Q_CREATE_DOM_ALIAS * q_u, POLICY_HND *hnd, char *acct_desc) { - int acct_len = acct_desc != NULL ? strlen(acct_desc) : 0; - DEBUG(5, ("init_samr_q_create_dom_alias\n")); q_u->dom_pol = *hnd; - init_uni_hdr(&q_u->hdr_acct_desc, acct_len); - init_unistr2(&q_u->uni_acct_desc, acct_desc, acct_len); + init_unistr2(&q_u->uni_acct_desc, acct_desc, UNI_FLAGS_NONE); + init_uni_hdr(&q_u->hdr_acct_desc, &q_u->uni_acct_desc); q_u->access_mask = 0x001f000f; } @@ -4675,9 +4635,8 @@ NTSTATUS init_samr_q_lookup_names(TALLOC_CTX *ctx, SAMR_Q_LOOKUP_NAMES * q_u, return NT_STATUS_NO_MEMORY; for (i = 0; i < num_names; i++) { - int len_name = name[i] != NULL ? strlen(name[i]) : 0; - init_uni_hdr(&q_u->hdr_name[i], len_name); /* unicode header for user_name */ - init_unistr2(&q_u->uni_name[i], name[i], len_name); /* unicode string for machine account */ + init_unistr2(&q_u->uni_name[i], name[i], UNI_FLAGS_NONE); /* unicode string for machine account */ + init_uni_hdr(&q_u->hdr_name[i], &q_u->uni_name[i]); /* unicode header for user_name */ } return NT_STATUS_OK; @@ -5013,15 +4972,12 @@ void init_samr_q_create_user(SAMR_Q_CREATE_USER * q_u, const char *name, uint32 acb_info, uint32 access_mask) { - int len_name; - len_name = strlen(name); - DEBUG(5, ("samr_init_samr_q_create_user\n")); q_u->domain_pol = *pol; - init_uni_hdr(&q_u->hdr_name, len_name); - init_unistr2(&q_u->uni_name, name, len_name); + init_unistr2(&q_u->uni_name, name, UNI_FLAGS_NONE); + init_uni_hdr(&q_u->hdr_name, &q_u->uni_name); q_u->acb_info = acb_info; q_u->access_mask = access_mask; @@ -5244,16 +5200,11 @@ void init_sam_user_info11(SAM_USER_INFO_11 * usr, char *mach_acct, uint32 rid_user, uint32 rid_group, uint16 acct_ctrl) { - int len_mach_acct; - DEBUG(5, ("init_sam_user_info11\n")); - len_mach_acct = strlen(mach_acct); - - memcpy(&(usr->expiry), expiry, sizeof(usr->expiry)); /* expiry time or something? */ + memcpy(&usr->expiry, expiry, sizeof(usr->expiry)); /* expiry time or something? */ ZERO_STRUCT(usr->padding_1); /* 0 - padding 24 bytes */ - init_uni_hdr(&usr->hdr_mach_acct, len_mach_acct); /* unicode header for machine account */ usr->padding_2 = 0; /* 0 - padding 4 bytes */ usr->ptr_1 = 1; /* pointer */ @@ -5278,7 +5229,8 @@ void init_sam_user_info11(SAM_USER_INFO_11 * usr, ZERO_STRUCT(usr->padding_7); /* 0 - padding 16 bytes */ usr->padding_8 = 0; /* 0 - padding 4 bytes */ - init_unistr2(&usr->uni_mach_acct, mach_acct, len_mach_acct); /* unicode string for machine account */ + init_unistr2(&usr->uni_mach_acct, mach_acct, UNI_FLAGS_NONE); /* unicode string for machine account */ + init_uni_hdr(&usr->hdr_mach_acct, &usr->uni_mach_acct); /* unicode header for machine account */ } /******************************************************************* @@ -5441,17 +5393,6 @@ void init_sam_user_info23W(SAM_USER_INFO_23 * usr, NTTIME * logon_time, /* all z uint16 logon_count, char newpass[516], uint32 unknown_6) { - int len_user_name = user_name != NULL ? user_name->uni_str_len : 0; - int len_full_name = full_name != NULL ? full_name->uni_str_len : 0; - int len_home_dir = home_dir != NULL ? home_dir->uni_str_len : 0; - int len_dir_drive = dir_drive != NULL ? dir_drive->uni_str_len : 0; - int len_logon_script = log_scr != NULL ? log_scr->uni_str_len : 0; - int len_profile_path = prof_path != NULL ? prof_path->uni_str_len : 0; - int len_description = desc != NULL ? desc->uni_str_len : 0; - int len_workstations = wkstas != NULL ? wkstas->uni_str_len : 0; - int len_unknown_str = unk_str != NULL ? unk_str->uni_str_len : 0; - int len_munged_dial = mung_dial != NULL ? mung_dial->uni_str_len : 0; - usr->logon_time = *logon_time; /* all zeros */ usr->logoff_time = *logoff_time; /* all zeros */ usr->kickoff_time = *kickoff_time; /* all zeros */ @@ -5459,17 +5400,6 @@ void init_sam_user_info23W(SAM_USER_INFO_23 * usr, NTTIME * logon_time, /* all z usr->pass_can_change_time = *pass_can_change_time; /* all zeros */ usr->pass_must_change_time = *pass_must_change_time; /* all zeros */ - init_uni_hdr(&usr->hdr_user_name, len_user_name); /* NULL */ - init_uni_hdr(&usr->hdr_full_name, len_full_name); - init_uni_hdr(&usr->hdr_home_dir, len_home_dir); - init_uni_hdr(&usr->hdr_dir_drive, len_dir_drive); - init_uni_hdr(&usr->hdr_logon_script, len_logon_script); - init_uni_hdr(&usr->hdr_profile_path, len_profile_path); - init_uni_hdr(&usr->hdr_acct_desc, len_description); - init_uni_hdr(&usr->hdr_workstations, len_workstations); - init_uni_hdr(&usr->hdr_unknown_str, len_unknown_str); - init_uni_hdr(&usr->hdr_munged_dial, len_munged_dial); - ZERO_STRUCT(usr->nt_pwd); ZERO_STRUCT(usr->lm_pwd); @@ -5496,15 +5426,34 @@ void init_sam_user_info23W(SAM_USER_INFO_23 * usr, NTTIME * logon_time, /* all z memcpy(usr->pass, newpass, sizeof(usr->pass)); copy_unistr2(&usr->uni_user_name, user_name); + init_uni_hdr(&usr->hdr_user_name, &usr->uni_user_name); + copy_unistr2(&usr->uni_full_name, full_name); + init_uni_hdr(&usr->hdr_full_name, &usr->uni_full_name); + copy_unistr2(&usr->uni_home_dir, home_dir); + init_uni_hdr(&usr->hdr_home_dir, &usr->uni_home_dir); + copy_unistr2(&usr->uni_dir_drive, dir_drive); + init_uni_hdr(&usr->hdr_dir_drive, &usr->uni_dir_drive); + copy_unistr2(&usr->uni_logon_script, log_scr); + init_uni_hdr(&usr->hdr_logon_script, &usr->uni_logon_script); + copy_unistr2(&usr->uni_profile_path, prof_path); + init_uni_hdr(&usr->hdr_profile_path, &usr->uni_profile_path); + copy_unistr2(&usr->uni_acct_desc, desc); + init_uni_hdr(&usr->hdr_acct_desc, &usr->uni_acct_desc); + copy_unistr2(&usr->uni_workstations, wkstas); + init_uni_hdr(&usr->hdr_workstations, &usr->uni_workstations); + copy_unistr2(&usr->uni_unknown_str, unk_str); + init_uni_hdr(&usr->hdr_unknown_str, &usr->uni_unknown_str); + copy_unistr2(&usr->uni_munged_dial, mung_dial); + init_uni_hdr(&usr->hdr_munged_dial, &usr->uni_munged_dial); usr->unknown_6 = unknown_6; /* 0x0000 04ec */ usr->padding4 = 0; @@ -5536,17 +5485,6 @@ void init_sam_user_info23A(SAM_USER_INFO_23 * usr, NTTIME * logon_time, /* all z LOGON_HRS * hrs, uint16 bad_password_count, uint16 logon_count, char newpass[516], uint32 unknown_6) { - int len_user_name = user_name != NULL ? strlen(user_name) : 0; - int len_full_name = full_name != NULL ? strlen(full_name) : 0; - int len_home_dir = home_dir != NULL ? strlen(home_dir) : 0; - int len_dir_drive = dir_drive != NULL ? strlen(dir_drive) : 0; - int len_logon_script = log_scr != NULL ? strlen(log_scr) : 0; - int len_profile_path = prof_path != NULL ? strlen(prof_path) : 0; - int len_description = desc != NULL ? strlen(desc) : 0; - int len_workstations = wkstas != NULL ? strlen(wkstas) : 0; - int len_unknown_str = unk_str != NULL ? strlen(unk_str) : 0; - int len_munged_dial = mung_dial != NULL ? strlen(mung_dial) : 0; - usr->logon_time = *logon_time; /* all zeros */ usr->logoff_time = *logoff_time; /* all zeros */ usr->kickoff_time = *kickoff_time; /* all zeros */ @@ -5554,17 +5492,6 @@ void init_sam_user_info23A(SAM_USER_INFO_23 * usr, NTTIME * logon_time, /* all z usr->pass_can_change_time = *pass_can_change_time; /* all zeros */ usr->pass_must_change_time = *pass_must_change_time; /* all zeros */ - init_uni_hdr(&usr->hdr_user_name, len_user_name); /* NULL */ - init_uni_hdr(&usr->hdr_full_name, len_full_name); - init_uni_hdr(&usr->hdr_home_dir, len_home_dir); - init_uni_hdr(&usr->hdr_dir_drive, len_dir_drive); - init_uni_hdr(&usr->hdr_logon_script, len_logon_script); - init_uni_hdr(&usr->hdr_profile_path, len_profile_path); - init_uni_hdr(&usr->hdr_acct_desc, len_description); - init_uni_hdr(&usr->hdr_workstations, len_workstations); - init_uni_hdr(&usr->hdr_unknown_str, len_unknown_str); - init_uni_hdr(&usr->hdr_munged_dial, len_munged_dial); - ZERO_STRUCT(usr->nt_pwd); ZERO_STRUCT(usr->lm_pwd); @@ -5590,16 +5517,35 @@ void init_sam_user_info23A(SAM_USER_INFO_23 * usr, NTTIME * logon_time, /* all z memcpy(usr->pass, newpass, sizeof(usr->pass)); - init_unistr2(&usr->uni_user_name, user_name, len_user_name); /* NULL */ - init_unistr2(&usr->uni_full_name, full_name, len_full_name); - init_unistr2(&usr->uni_home_dir, home_dir, len_home_dir); - init_unistr2(&usr->uni_dir_drive, dir_drive, len_dir_drive); - init_unistr2(&usr->uni_logon_script, log_scr, len_logon_script); - init_unistr2(&usr->uni_profile_path, prof_path, len_profile_path); - init_unistr2(&usr->uni_acct_desc, desc, len_description); - init_unistr2(&usr->uni_workstations, wkstas, len_workstations); - init_unistr2(&usr->uni_unknown_str, unk_str, len_unknown_str); - init_unistr2(&usr->uni_munged_dial, mung_dial, len_munged_dial); + init_unistr2(&usr->uni_user_name, user_name, UNI_FLAGS_NONE); + init_uni_hdr(&usr->hdr_user_name, &usr->uni_user_name); + + init_unistr2(&usr->uni_full_name, full_name, UNI_FLAGS_NONE); + init_uni_hdr(&usr->hdr_full_name, &usr->uni_full_name); + + init_unistr2(&usr->uni_home_dir, home_dir, UNI_FLAGS_NONE); + init_uni_hdr(&usr->hdr_home_dir, &usr->uni_home_dir); + + init_unistr2(&usr->uni_dir_drive, dir_drive, UNI_FLAGS_NONE); + init_uni_hdr(&usr->hdr_dir_drive, &usr->uni_dir_drive); + + init_unistr2(&usr->uni_logon_script, log_scr, UNI_FLAGS_NONE); + init_uni_hdr(&usr->hdr_logon_script, &usr->uni_logon_script); + + init_unistr2(&usr->uni_profile_path, prof_path, UNI_FLAGS_NONE); + init_uni_hdr(&usr->hdr_profile_path, &usr->uni_profile_path); + + init_unistr2(&usr->uni_acct_desc, desc, UNI_FLAGS_NONE); + init_uni_hdr(&usr->hdr_acct_desc, &usr->uni_acct_desc); + + init_unistr2(&usr->uni_workstations, wkstas, UNI_FLAGS_NONE); + init_uni_hdr(&usr->hdr_workstations, &usr->uni_workstations); + + init_unistr2(&usr->uni_unknown_str, unk_str, UNI_FLAGS_NONE); + init_uni_hdr(&usr->hdr_unknown_str, &usr->uni_unknown_str); + + init_unistr2(&usr->uni_munged_dial, mung_dial, UNI_FLAGS_NONE); + init_uni_hdr(&usr->hdr_munged_dial, &usr->uni_munged_dial); usr->unknown_6 = unknown_6; /* 0x0000 04ec */ usr->padding4 = 0; @@ -5900,17 +5846,6 @@ void init_sam_user_info21W(SAM_USER_INFO_21 * usr, uint16 logon_count, uint32 unknown_6) { - int len_user_name = user_name != NULL ? user_name->uni_str_len : 0; - int len_full_name = full_name != NULL ? full_name->uni_str_len : 0; - int len_home_dir = home_dir != NULL ? home_dir->uni_str_len : 0; - int len_dir_drive = dir_drive != NULL ? dir_drive->uni_str_len : 0; - int len_logon_script = log_scr != NULL ? log_scr->uni_str_len : 0; - int len_profile_path = prof_path != NULL ? prof_path->uni_str_len : 0; - int len_description = desc != NULL ? desc->uni_str_len : 0; - int len_workstations = wkstas != NULL ? wkstas->uni_str_len : 0; - int len_unknown_str = unk_str != NULL ? unk_str->uni_str_len : 0; - int len_munged_dial = mung_dial != NULL ? mung_dial->uni_str_len : 0; - usr->logon_time = *logon_time; usr->logoff_time = *logoff_time; usr->kickoff_time = *kickoff_time; @@ -5918,17 +5853,6 @@ void init_sam_user_info21W(SAM_USER_INFO_21 * usr, usr->pass_can_change_time = *pass_can_change_time; usr->pass_must_change_time = *pass_must_change_time; - init_uni_hdr(&usr->hdr_user_name, len_user_name); - init_uni_hdr(&usr->hdr_full_name, len_full_name); - init_uni_hdr(&usr->hdr_home_dir, len_home_dir); - init_uni_hdr(&usr->hdr_dir_drive, len_dir_drive); - init_uni_hdr(&usr->hdr_logon_script, len_logon_script); - init_uni_hdr(&usr->hdr_profile_path, len_profile_path); - init_uni_hdr(&usr->hdr_acct_desc, len_description); - init_uni_hdr(&usr->hdr_workstations, len_workstations); - init_uni_hdr(&usr->hdr_unknown_str, len_unknown_str); - init_uni_hdr(&usr->hdr_munged_dial, len_munged_dial); - memcpy(usr->lm_pwd, lm_pwd, sizeof(usr->lm_pwd)); memcpy(usr->nt_pwd, nt_pwd, sizeof(usr->nt_pwd)); @@ -5952,15 +5876,34 @@ void init_sam_user_info21W(SAM_USER_INFO_21 * usr, ZERO_STRUCT(usr->padding2); copy_unistr2(&usr->uni_user_name, user_name); + init_uni_hdr(&usr->hdr_user_name, &usr->uni_user_name); + copy_unistr2(&usr->uni_full_name, full_name); + init_uni_hdr(&usr->hdr_full_name, &usr->uni_full_name); + copy_unistr2(&usr->uni_home_dir, home_dir); + init_uni_hdr(&usr->hdr_home_dir, &usr->uni_home_dir); + copy_unistr2(&usr->uni_dir_drive, dir_drive); + init_uni_hdr(&usr->hdr_dir_drive, &usr->uni_dir_drive); + copy_unistr2(&usr->uni_logon_script, log_scr); + init_uni_hdr(&usr->hdr_logon_script, &usr->uni_logon_script); + copy_unistr2(&usr->uni_profile_path, prof_path); + init_uni_hdr(&usr->hdr_profile_path, &usr->uni_profile_path); + copy_unistr2(&usr->uni_acct_desc, desc); + init_uni_hdr(&usr->hdr_acct_desc, &usr->uni_acct_desc); + copy_unistr2(&usr->uni_workstations, wkstas); + init_uni_hdr(&usr->hdr_workstations, &usr->uni_workstations); + copy_unistr2(&usr->uni_unknown_str, unk_str); + init_uni_hdr(&usr->hdr_unknown_str, &usr->uni_unknown_str); + copy_unistr2(&usr->uni_munged_dial, mung_dial); + init_uni_hdr(&usr->hdr_munged_dial, &usr->uni_munged_dial); usr->unknown_6 = unknown_6; /* 0x0000 04ec */ usr->padding4 = 0; @@ -5981,11 +5924,6 @@ NTSTATUS init_sam_user_info21A(SAM_USER_INFO_21 *usr, SAM_ACCOUNT *pw, DOM_SID * NTTIME logon_time, logoff_time, kickoff_time, pass_last_set_time, pass_can_change_time, pass_must_change_time; - - int len_user_name, len_full_name, len_home_dir, - len_dir_drive, len_logon_script, len_profile_path, - len_description, len_workstations, len_unknown_str, - len_munged_dial; const char* user_name = pdb_get_username(pw); const char* full_name = pdb_get_fullname(pw); @@ -6003,18 +5941,6 @@ NTSTATUS init_sam_user_info21A(SAM_USER_INFO_21 *usr, SAM_ACCOUNT *pw, DOM_SID * uint32 group_rid; const DOM_SID *group_sid; - len_user_name = user_name != NULL ? strlen(user_name )+1 : 0; - len_full_name = full_name != NULL ? strlen(full_name )+1 : 0; - len_home_dir = home_dir != NULL ? strlen(home_dir )+1 : 0; - len_dir_drive = dir_drive != NULL ? strlen(dir_drive )+1 : 0; - len_logon_script = logon_script != NULL ? strlen(logon_script)+1 : 0; - len_profile_path = profile_path != NULL ? strlen(profile_path)+1 : 0; - len_description = description != NULL ? strlen(description )+1 : 0; - len_workstations = workstations != NULL ? strlen(workstations)+1 : 0; - len_unknown_str = 0; - len_munged_dial = munged_dial != NULL ? strlen(munged_dial )+1 : 0; - - /* Create NTTIME structs */ unix_to_nt_time (&logon_time, pdb_get_logon_time(pw)); unix_to_nt_time (&logoff_time, pdb_get_logoff_time(pw)); @@ -6031,17 +5957,6 @@ NTSTATUS init_sam_user_info21A(SAM_USER_INFO_21 *usr, SAM_ACCOUNT *pw, DOM_SID * usr->pass_can_change_time = pass_can_change_time; usr->pass_must_change_time = pass_must_change_time; - init_uni_hdr(&usr->hdr_user_name, len_user_name); - init_uni_hdr(&usr->hdr_full_name, len_full_name); - init_uni_hdr(&usr->hdr_home_dir, len_home_dir); - init_uni_hdr(&usr->hdr_dir_drive, len_dir_drive); - init_uni_hdr(&usr->hdr_logon_script, len_logon_script); - init_uni_hdr(&usr->hdr_profile_path, len_profile_path); - init_uni_hdr(&usr->hdr_acct_desc, len_description); - init_uni_hdr(&usr->hdr_workstations, len_workstations); - init_uni_hdr(&usr->hdr_unknown_str, len_unknown_str); - init_uni_hdr(&usr->hdr_munged_dial, len_munged_dial); - ZERO_STRUCT(usr->nt_pwd); ZERO_STRUCT(usr->lm_pwd); @@ -6100,16 +6015,35 @@ NTSTATUS init_sam_user_info21A(SAM_USER_INFO_21 *usr, SAM_ACCOUNT *pw, DOM_SID * ZERO_STRUCT(usr->padding1); ZERO_STRUCT(usr->padding2); - init_unistr2(&usr->uni_user_name, user_name, len_user_name); - init_unistr2(&usr->uni_full_name, full_name, len_full_name); - init_unistr2(&usr->uni_home_dir, home_dir, len_home_dir); - init_unistr2(&usr->uni_dir_drive, dir_drive, len_dir_drive); - init_unistr2(&usr->uni_logon_script, logon_script, len_logon_script); - init_unistr2(&usr->uni_profile_path, profile_path, len_profile_path); - init_unistr2(&usr->uni_acct_desc, description, len_description); - init_unistr2(&usr->uni_workstations, workstations, len_workstations); - init_unistr2(&usr->uni_unknown_str, NULL, len_unknown_str); - init_unistr2(&usr->uni_munged_dial, munged_dial, len_munged_dial); + init_unistr2(&usr->uni_user_name, user_name, UNI_STR_TERMINATE); + init_uni_hdr(&usr->hdr_user_name, &usr->uni_user_name); + + init_unistr2(&usr->uni_full_name, full_name, UNI_STR_TERMINATE); + init_uni_hdr(&usr->hdr_full_name, &usr->uni_full_name); + + init_unistr2(&usr->uni_home_dir, home_dir, UNI_STR_TERMINATE); + init_uni_hdr(&usr->hdr_home_dir, &usr->uni_home_dir); + + init_unistr2(&usr->uni_dir_drive, dir_drive, UNI_STR_TERMINATE); + init_uni_hdr(&usr->hdr_dir_drive, &usr->uni_dir_drive); + + init_unistr2(&usr->uni_logon_script, logon_script, UNI_STR_TERMINATE); + init_uni_hdr(&usr->hdr_logon_script, &usr->uni_logon_script); + + init_unistr2(&usr->uni_profile_path, profile_path, UNI_STR_TERMINATE); + init_uni_hdr(&usr->hdr_profile_path, &usr->uni_profile_path); + + init_unistr2(&usr->uni_acct_desc, description, UNI_STR_TERMINATE); + init_uni_hdr(&usr->hdr_acct_desc, &usr->uni_acct_desc); + + init_unistr2(&usr->uni_workstations, workstations, UNI_STR_TERMINATE); + init_uni_hdr(&usr->hdr_workstations, &usr->uni_workstations); + + init_unistr2(&usr->uni_unknown_str, NULL, UNI_STR_TERMINATE); + init_uni_hdr(&usr->hdr_unknown_str, &usr->uni_unknown_str); + + init_unistr2(&usr->uni_munged_dial, munged_dial, UNI_STR_TERMINATE); + init_uni_hdr(&usr->hdr_munged_dial, &usr->uni_munged_dial); usr->unknown_6 = pdb_get_unknown_6(pw); usr->padding4 = 0; @@ -6249,12 +6183,10 @@ static BOOL sam_io_user_info21(const char *desc, SAM_USER_INFO_21 * usr, void init_sam_user_info20A(SAM_USER_INFO_20 *usr, SAM_ACCOUNT *pw) { - int len_munged_dial; - const char* munged_dial = pdb_get_munged_dial(pw); + const char *munged_dial = pdb_get_munged_dial(pw); - len_munged_dial = munged_dial != NULL ? strlen(munged_dial )+1 : 0; - init_uni_hdr(&usr->hdr_munged_dial, len_munged_dial); - init_unistr2(&usr->uni_munged_dial, munged_dial, len_munged_dial); + init_unistr2(&usr->uni_munged_dial, munged_dial, UNI_STR_TERMINATE); + init_uni_hdr(&usr->hdr_munged_dial, &usr->uni_munged_dial); } @@ -6720,13 +6652,11 @@ inits a SAMR_Q_CONNECT structure. void init_samr_q_connect(SAMR_Q_CONNECT * q_u, char *srv_name, uint32 access_mask) { - int len_srv_name = strlen(srv_name); - DEBUG(5, ("init_samr_q_connect\n")); /* make PDC server name \\server */ - q_u->ptr_srv_name = len_srv_name > 0 ? 1 : 0; - init_unistr2(&q_u->uni_srv_name, srv_name, len_srv_name + 1); + q_u->ptr_srv_name = (srv_name != NULL && *srv_name) ? 1 : 0; + init_unistr2(&q_u->uni_srv_name, srv_name, UNI_STR_TERMINATE); /* example values: 0x0000 0002 */ q_u->access_mask = access_mask; @@ -6793,13 +6723,11 @@ inits a SAMR_Q_CONNECT4 structure. void init_samr_q_connect4(SAMR_Q_CONNECT4 * q_u, char *srv_name, uint32 access_mask) { - int len_srv_name = strlen(srv_name); - DEBUG(5, ("init_samr_q_connect\n")); /* make PDC server name \\server */ - q_u->ptr_srv_name = len_srv_name > 0 ? 1 : 0; - init_unistr2(&q_u->uni_srv_name, srv_name, len_srv_name + 1); + q_u->ptr_srv_name = (srv_name != NULL && *srv_name) ? 1 : 0; + init_unistr2(&q_u->uni_srv_name, srv_name, UNI_STR_TERMINATE); /* Only value we've seen, possibly an address type ? */ q_u->unk_0 = 2; @@ -6938,13 +6866,11 @@ inits a SAMR_Q_GET_DOM_PWINFO structure. void init_samr_q_get_dom_pwinfo(SAMR_Q_GET_DOM_PWINFO * q_u, char *srv_name) { - int len_srv_name = strlen(srv_name); - DEBUG(5, ("init_samr_q_get_dom_pwinfo\n")); q_u->ptr = 1; - init_uni_hdr(&q_u->hdr_srv_name, len_srv_name); - init_unistr2(&q_u->uni_srv_name, srv_name, len_srv_name); + init_unistr2(&q_u->uni_srv_name, srv_name, UNI_FLAGS_NONE); + init_uni_hdr(&q_u->hdr_srv_name, &q_u->uni_srv_name); } /******************************************************************* @@ -7105,16 +7031,14 @@ void init_samr_q_chgpasswd_user(SAMR_Q_CHGPASSWD_USER * q_u, char lm_newpass[516], uchar lm_oldhash[16]) { - int len_dest_host = strlen(dest_host); - int len_user_name = strlen(user_name); - DEBUG(5, ("init_samr_q_chgpasswd_user\n")); q_u->ptr_0 = 1; - init_uni_hdr(&q_u->hdr_dest_host, len_dest_host); - init_unistr2(&q_u->uni_dest_host, dest_host, len_dest_host); - init_uni_hdr(&q_u->hdr_user_name, len_user_name); - init_unistr2(&q_u->uni_user_name, user_name, len_user_name); + init_unistr2(&q_u->uni_dest_host, dest_host, UNI_FLAGS_NONE); + init_uni_hdr(&q_u->hdr_dest_host, &q_u->uni_dest_host); + + init_unistr2(&q_u->uni_user_name, user_name, UNI_FLAGS_NONE); + init_uni_hdr(&q_u->hdr_user_name, &q_u->uni_user_name); init_enc_passwd(&q_u->nt_newpass, nt_newpass); init_enc_hash(&q_u->nt_oldhash, nt_oldhash); diff --git a/source3/rpc_parse/parse_spoolss.c b/source3/rpc_parse/parse_spoolss.c index 7ca9bccab4..65f16414a0 100644 --- a/source3/rpc_parse/parse_spoolss.c +++ b/source3/rpc_parse/parse_spoolss.c @@ -916,12 +916,12 @@ BOOL make_spoolss_q_open_printer_ex(SPOOL_Q_OPEN_PRINTER_EX *q_u, { DEBUG(5,("make_spoolss_q_open_printer_ex\n")); q_u->printername_ptr = (printername!=NULL)?1:0; - init_unistr2(&q_u->printername, printername, strlen(printername)+1); + init_unistr2(&q_u->printername, printername, UNI_STR_TERMINATE); q_u->printer_default.datatype_ptr = 0; /* q_u->printer_default.datatype_ptr = (datatype!=NULL)?1:0; - init_unistr2(&q_u->printer_default.datatype, datatype, strlen(datatype)); + init_unistr2(&q_u->printer_default.datatype, datatype, UNI_FLAGS_NONE); */ q_u->printer_default.devmode_cont.size=0; q_u->printer_default.devmode_cont.devmode_ptr=0; @@ -937,8 +937,8 @@ BOOL make_spoolss_q_open_printer_ex(SPOOL_Q_OPEN_PRINTER_EX *q_u, q_u->user_ctr.user1.major=2; q_u->user_ctr.user1.minor=0; q_u->user_ctr.user1.processor=0; - init_unistr2(&q_u->user_ctr.user1.client_name, clientname, strlen(clientname)+1); - init_unistr2(&q_u->user_ctr.user1.user_name, user_name, strlen(user_name)+1); + init_unistr2(&q_u->user_ctr.user1.client_name, clientname, UNI_STR_TERMINATE); + init_unistr2(&q_u->user_ctr.user1.user_name, user_name, UNI_STR_TERMINATE); return True; } @@ -963,7 +963,7 @@ BOOL make_spoolss_q_addprinterex( ZERO_STRUCTP(q_u); q_u->server_name_ptr = (srv_name!=NULL)?1:0; - init_unistr2(&q_u->server_name, srv_name, strlen(srv_name)); + init_unistr2(&q_u->server_name, srv_name, UNI_FLAGS_NONE); q_u->level = level; @@ -991,8 +991,8 @@ BOOL make_spoolss_q_addprinterex( q_u->user_ctr.user1.major=2; q_u->user_ctr.user1.minor=0; q_u->user_ctr.user1.processor=0; - init_unistr2(&q_u->user_ctr.user1.client_name, clientname, strlen(clientname)+1); - init_unistr2(&q_u->user_ctr.user1.user_name, user_name, strlen(user_name)+1); + init_unistr2(&q_u->user_ctr.user1.client_name, clientname, UNI_STR_TERMINATE); + init_unistr2(&q_u->user_ctr.user1.user_name, user_name, UNI_STR_TERMINATE); q_u->user_ctr.user1.size=q_u->user_ctr.user1.user_name.uni_str_len + q_u->user_ctr.user1.client_name.uni_str_len + 2; @@ -1187,15 +1187,13 @@ BOOL make_spoolss_q_deleteprinterdriver( /* these must be NULL terminated or else NT4 will complain about invalid parameters --jerry */ - init_unistr2(&q_u->server, server, strlen(server)+1); - init_unistr2(&q_u->arch, arch, strlen(arch)+1); - init_unistr2(&q_u->driver, driver, strlen(driver)+1); - + init_unistr2(&q_u->server, server, UNI_STR_TERMINATE); + init_unistr2(&q_u->arch, arch, UNI_STR_TERMINATE); + init_unistr2(&q_u->driver, driver, UNI_STR_TERMINATE); return True; } - /******************************************************************* * make a structure. ********************************************************************/ @@ -1209,7 +1207,7 @@ BOOL make_spoolss_q_getprinterdata(SPOOL_Q_GETPRINTERDATA *q_u, DEBUG(5,("make_spoolss_q_getprinterdata\n")); q_u->handle = *handle; - init_unistr2(&q_u->valuename, valuename, strlen(valuename) + 1); + init_unistr2(&q_u->valuename, valuename, UNI_STR_TERMINATE); q_u->size = size; return True; @@ -1229,8 +1227,8 @@ BOOL make_spoolss_q_getprinterdataex(SPOOL_Q_GETPRINTERDATAEX *q_u, 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); + init_unistr2(&q_u->valuename, valuename, UNI_STR_TERMINATE); + init_unistr2(&q_u->keyname, keyname, UNI_STR_TERMINATE); q_u->size = size; return True; @@ -5317,7 +5315,7 @@ BOOL smb_io_unibuffer(const char *desc, UNISTR2 *buffer, prs_struct *ps, int dep { if (buffer==NULL) return False; - buffer->undoc=0; + buffer->offset=0; buffer->uni_str_len=buffer->uni_max_len; if(!prs_uint32("buffer_size", ps, depth, &buffer->uni_max_len)) @@ -5374,7 +5372,7 @@ BOOL make_spoolss_q_addprinterdriver(TALLOC_CTX *mem_ctx, DEBUG(5,("make_spoolss_q_addprinterdriver\n")); q_u->server_name_ptr = (srv_name!=NULL)?1:0; - init_unistr2(&q_u->server_name, srv_name, strlen(srv_name)+1); + init_unistr2(&q_u->server_name, srv_name, UNI_STR_TERMINATE); q_u->level = level; @@ -6162,7 +6160,7 @@ BOOL make_spoolss_q_enumprinterdataex(SPOOL_Q_ENUMPRINTERDATAEX *q_u, uint32 size) { memcpy(&q_u->handle, hnd, sizeof(q_u->handle)); - init_unistr2(&q_u->key, key, strlen(key)+1); + init_unistr2(&q_u->key, key, UNI_STR_TERMINATE); q_u->size = size; return True; @@ -6175,7 +6173,7 @@ BOOL make_spoolss_q_setprinterdata(SPOOL_Q_SETPRINTERDATA *q_u, const POLICY_HND { memcpy(&q_u->handle, hnd, sizeof(q_u->handle)); q_u->type = data_type; - init_unistr2(&q_u->value, value, strlen(value)+1); + init_unistr2(&q_u->value, value, UNI_STR_TERMINATE); q_u->max_len = q_u->real_len = data_size; q_u->data = (unsigned char *)data; @@ -6191,8 +6189,8 @@ BOOL make_spoolss_q_setprinterdataex(SPOOL_Q_SETPRINTERDATAEX *q_u, const POLICY { memcpy(&q_u->handle, hnd, sizeof(q_u->handle)); q_u->type = data_type; - init_unistr2(&q_u->value, value, strlen(value)+1); - init_unistr2(&q_u->key, key, strlen(key)+1); + init_unistr2(&q_u->value, value, UNI_STR_TERMINATE); + init_unistr2(&q_u->key, key, UNI_STR_TERMINATE); q_u->max_len = q_u->real_len = data_size; q_u->data = (unsigned char *)data; @@ -6589,7 +6587,7 @@ BOOL make_spoolss_q_replyopenprinter(SPOOL_Q_REPLYOPENPRINTER *q_u, if (q_u == NULL) return False; - init_unistr2(&q_u->string, string, strlen(string)+1); + init_unistr2(&q_u->string, string, UNI_STR_TERMINATE); q_u->printer=printer; q_u->type=type; @@ -7092,7 +7090,7 @@ BOOL make_spoolss_q_enumprinterkey(SPOOL_Q_ENUMPRINTERKEY *q_u, DEBUG(5,("make_spoolss_q_enumprinterkey\n")); memcpy(&q_u->handle, hnd, sizeof(q_u->handle)); - init_unistr2(&q_u->key, key, strlen(key)+1); + init_unistr2(&q_u->key, key, UNI_STR_TERMINATE); q_u->size = size; return True; @@ -7161,7 +7159,7 @@ BOOL make_spoolss_q_deleteprinterkey(SPOOL_Q_DELETEPRINTERKEY *q_u, DEBUG(5,("make_spoolss_q_deleteprinterkey\n")); memcpy(&q_u->handle, hnd, sizeof(q_u->handle)); - init_unistr2(&q_u->keyname, keyname, strlen(keyname)+1); + init_unistr2(&q_u->keyname, keyname, UNI_STR_TERMINATE); return True; } @@ -7382,8 +7380,8 @@ BOOL make_spoolss_q_getprintprocessordirectory(SPOOL_Q_GETPRINTPROCESSORDIRECTOR { DEBUG(5,("make_spoolss_q_getprintprocessordirectory\n")); - init_unistr2(&q_u->name, name, strlen(name)+1); - init_unistr2(&q_u->environment, environment, strlen(environment)+1); + init_unistr2(&q_u->name, name, UNI_STR_TERMINATE); + init_unistr2(&q_u->environment, environment, UNI_STR_TERMINATE); q_u->level = level; @@ -7509,7 +7507,7 @@ BOOL make_spoolss_q_setform(SPOOL_Q_SETFORM *q_u, POLICY_HND *handle, q_u->level = level; q_u->level2 = level; memcpy(&q_u->form, form, sizeof(FORM)); - init_unistr2(&q_u->name, form_name, strlen(form_name) + 1); + init_unistr2(&q_u->name, form_name, UNI_STR_TERMINATE); return True; } @@ -7522,7 +7520,7 @@ BOOL make_spoolss_q_deleteform(SPOOL_Q_DELETEFORM *q_u, POLICY_HND *handle, const char *form) { memcpy(&q_u->handle, handle, sizeof(POLICY_HND)); - init_unistr2(&q_u->name, form, strlen(form) + 1); + init_unistr2(&q_u->name, form, UNI_STR_TERMINATE); return True; } @@ -7536,7 +7534,7 @@ BOOL make_spoolss_q_getform(SPOOL_Q_GETFORM *q_u, POLICY_HND *handle, { memcpy(&q_u->handle, handle, sizeof(POLICY_HND)); q_u->level = level; - init_unistr2(&q_u->formname, formname, strlen(formname) + 1); + init_unistr2(&q_u->formname, formname, UNI_STR_TERMINATE); q_u->buffer=buffer; q_u->offered=offered; @@ -7642,17 +7640,9 @@ BOOL make_spoolss_q_startdocprinter(SPOOL_Q_STARTDOCPRINTER *q_u, ctr->docinfo.doc_info_1.p_outputfile = outputfile ? 1 : 0; ctr->docinfo.doc_info_1.p_datatype = datatype ? 1 : 0; - if (docname) - init_unistr2(&ctr->docinfo.doc_info_1.docname, docname, - strlen(docname) + 1); - - if (outputfile) - init_unistr2(&ctr->docinfo.doc_info_1.outputfile, outputfile, - strlen(outputfile) + 1); - - if (datatype) - init_unistr2(&ctr->docinfo.doc_info_1.datatype, datatype, - strlen(datatype) + 1); + init_unistr2(&ctr->docinfo.doc_info_1.docname, docname, UNI_STR_TERMINATE); + init_unistr2(&ctr->docinfo.doc_info_1.outputfile, outputfile, UNI_STR_TERMINATE); + init_unistr2(&ctr->docinfo.doc_info_1.datatype, datatype, UNI_STR_TERMINATE); break; case 2: @@ -7701,7 +7691,7 @@ BOOL make_spoolss_q_deleteprinterdata(SPOOL_Q_DELETEPRINTERDATA *q_u, POLICY_HND *handle, char *valuename) { memcpy(&q_u->handle, handle, sizeof(POLICY_HND)); - init_unistr2(&q_u->valuename, valuename, strlen(valuename) + 1); + init_unistr2(&q_u->valuename, valuename, UNI_STR_TERMINATE); return True; } @@ -7715,8 +7705,8 @@ BOOL make_spoolss_q_deleteprinterdataex(SPOOL_Q_DELETEPRINTERDATAEX *q_u, 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); + init_unistr2(&q_u->valuename, value, UNI_STR_TERMINATE); + init_unistr2(&q_u->keyname, key, UNI_STR_TERMINATE); return True; } @@ -7736,8 +7726,7 @@ BOOL make_spoolss_q_rffpcnex(SPOOL_Q_RFFPCNEX *q_u, POLICY_HND *handle, q_u->localmachine_ptr = 1; - init_unistr2(&q_u->localmachine, localmachine, - strlen(localmachine) + 1); + init_unistr2(&q_u->localmachine, localmachine, UNI_STR_TERMINATE); q_u->printerlocal = printerlocal; diff --git a/source3/rpc_parse/parse_srv.c b/source3/rpc_parse/parse_srv.c index bbb5193ddc..6349fc1632 100644 --- a/source3/rpc_parse/parse_srv.c +++ b/source3/rpc_parse/parse_srv.c @@ -36,8 +36,7 @@ void init_srv_share_info0_str(SH_INFO_0_STR *sh0, const char *net_name) { DEBUG(5,("init_srv_share_info0_str\n")); - if(net_name) - init_unistr2(&sh0->uni_netname, net_name, strlen(net_name)+1); + init_unistr2(&sh0->uni_netname, net_name, UNI_STR_TERMINATE); } /******************************************************************* @@ -101,10 +100,8 @@ void init_srv_share_info1_str(SH_INFO_1_STR *sh1, const char *net_name, const ch { DEBUG(5,("init_srv_share_info1_str\n")); - if(net_name) - init_unistr2(&sh1->uni_netname, net_name, strlen(net_name)+1); - if(remark) - init_unistr2(&sh1->uni_remark, remark, strlen(remark)+1); + init_unistr2(&sh1->uni_netname, net_name, UNI_STR_TERMINATE); + init_unistr2(&sh1->uni_remark, remark, UNI_STR_TERMINATE); } /******************************************************************* @@ -184,14 +181,10 @@ void init_srv_share_info2_str(SH_INFO_2_STR *sh2, { DEBUG(5,("init_srv_share_info2_str\n")); - if (net_name) - init_unistr2(&sh2->uni_netname, net_name, strlen(net_name)+1); - if (remark) - init_unistr2(&sh2->uni_remark, remark, strlen(remark)+1); - if (path) - init_unistr2(&sh2->uni_path, path, strlen(path)+1); - if (passwd) - init_unistr2(&sh2->uni_passwd, passwd, strlen(passwd)+1); + init_unistr2(&sh2->uni_netname, net_name, UNI_STR_TERMINATE); + init_unistr2(&sh2->uni_remark, remark, UNI_STR_TERMINATE); + init_unistr2(&sh2->uni_path, path, UNI_STR_TERMINATE); + init_unistr2(&sh2->uni_passwd, passwd, UNI_STR_TERMINATE); } /******************************************************************* @@ -296,10 +289,8 @@ void init_srv_share_info501_str(SH_INFO_501_STR *sh501, { DEBUG(5,("init_srv_share_info501_str\n")); - if(net_name) - init_unistr2(&sh501->uni_netname, net_name, strlen(net_name)+1); - if(remark) - init_unistr2(&sh501->uni_remark, remark, strlen(remark)+1); + init_unistr2(&sh501->uni_netname, net_name, UNI_STR_TERMINATE); + init_unistr2(&sh501->uni_remark, remark, UNI_STR_TERMINATE); } /******************************************************************* @@ -446,17 +437,13 @@ void init_srv_share_info502_str(SH_INFO_502_STR *sh502str, { DEBUG(5,("init_srv_share_info502_str\n")); - if(net_name) - init_unistr2(&sh502str->uni_netname, net_name, strlen(net_name)+1); - if(remark) - init_unistr2(&sh502str->uni_remark, remark, strlen(remark)+1); - if(path) - init_unistr2(&sh502str->uni_path, path, strlen(path)+1); - if(passwd) - init_unistr2(&sh502str->uni_passwd, passwd, strlen(passwd)+1); - sh502str->sd = psd; + init_unistr2(&sh502str->uni_netname, net_name, UNI_STR_TERMINATE); + init_unistr2(&sh502str->uni_remark, remark, UNI_STR_TERMINATE); + init_unistr2(&sh502str->uni_path, path, UNI_STR_TERMINATE); + init_unistr2(&sh502str->uni_passwd, passwd, UNI_STR_TERMINATE); + sh502str->sd = psd; sh502str->reserved = 0; - sh502str->sd_size = sd_size; + sh502str->sd_size = sd_size; } /******************************************************************* @@ -551,8 +538,7 @@ void init_srv_share_info1004_str(SH_INFO_1004_STR *sh1004, const char *remark) { DEBUG(5,("init_srv_share_info1004_str\n")); - if(remark) - init_unistr2(&sh1004->uni_remark, remark, strlen(remark)+1); + init_unistr2(&sh1004->uni_remark, remark, UNI_STR_TERMINATE); } /******************************************************************* @@ -659,8 +645,7 @@ void init_srv_share_info1007_str(SH_INFO_1007_STR *sh1007, const char *alternate { DEBUG(5,("init_srv_share_info1007_str\n")); - if(alternate_directory_name) - init_unistr2(&sh1007->uni_AlternateDirectoryName, alternate_directory_name, strlen(alternate_directory_name)+1); + init_unistr2(&sh1007->uni_AlternateDirectoryName, alternate_directory_name, UNI_STR_TERMINATE); } /******************************************************************* @@ -1474,7 +1459,7 @@ void init_srv_q_net_share_add(SRV_Q_NET_SHARE_ADD *q, const char *srvname, const char *path, const char *passwd) { q->ptr_srv_name = 1; - init_unistr2(&q->uni_srv_name, srvname, strlen(srvname) +1); + init_unistr2(&q->uni_srv_name, srvname, UNI_STR_TERMINATE); q->info.switch_value = q->info_level = 2; q->info.ptr_share_ctr = 1; @@ -1525,8 +1510,8 @@ void init_srv_q_net_share_del(SRV_Q_NET_SHARE_DEL *del, const char *srvname, const char *sharename) { del->ptr_srv_name = 1; - init_unistr2(&del->uni_srv_name, srvname, strlen(srvname) +1 ); - init_unistr2(&del->uni_share_name, sharename, strlen(sharename) + 1); + init_unistr2(&del->uni_srv_name, srvname, UNI_STR_TERMINATE); + init_unistr2(&del->uni_share_name, sharename, UNI_STR_TERMINATE); } /******************************************************************* @@ -1589,7 +1574,7 @@ void init_srv_sess_info0_str(SESS_INFO_0_STR *ss0, const char *name) { DEBUG(5,("init_srv_sess_info0_str\n")); - init_unistr2(&ss0->uni_name, name, strlen(name)+1); + init_unistr2(&ss0->uni_name, name, UNI_STR_TERMINATE); } /******************************************************************* @@ -1703,8 +1688,8 @@ void init_srv_sess_info1_str(SESS_INFO_1_STR *ss1, const char *name, const char { DEBUG(5,("init_srv_sess_info1_str\n")); - init_unistr2(&ss1->uni_name, name, strlen(name)+1); - init_unistr2(&ss1->uni_user, user, strlen(user)+1); + init_unistr2(&ss1->uni_name, name, UNI_STR_TERMINATE); + init_unistr2(&ss1->uni_user, user, UNI_STR_TERMINATE); } /******************************************************************* @@ -2075,8 +2060,8 @@ void init_srv_conn_info1_str(CONN_INFO_1_STR *ss1, const char *usr_name, const c { DEBUG(5,("init_srv_conn_info1_str\n")); - init_unistr2(&ss1->uni_usr_name, usr_name, strlen(usr_name)+1); - init_unistr2(&ss1->uni_net_name, net_name, strlen(net_name)+1); + init_unistr2(&ss1->uni_usr_name, usr_name, UNI_STR_TERMINATE); + init_unistr2(&ss1->uni_net_name, net_name, UNI_STR_TERMINATE); } /******************************************************************* @@ -2365,8 +2350,8 @@ void init_srv_file_info3_str(FILE_INFO_3_STR *fi3, const char *user_name, const { DEBUG(5,("init_srv_file_info3_str\n")); - init_unistr2(&fi3->uni_path_name, path_name, strlen(path_name)+1); - init_unistr2(&fi3->uni_user_name, user_name, strlen(user_name)+1); + init_unistr2(&fi3->uni_path_name, path_name, UNI_STR_TERMINATE); + init_unistr2(&fi3->uni_user_name, user_name, UNI_STR_TERMINATE); } /******************************************************************* @@ -2628,7 +2613,7 @@ void init_srv_q_net_file_close(SRV_Q_NET_FILE_CLOSE *q_n, const char *server, uint32 file_id) { q_n->ptr_srv_name = 1; - init_unistr2(&q_n->uni_srv_name, server, strlen(server) + 1); + init_unistr2(&q_n->uni_srv_name, server, UNI_STR_TERMINATE); q_n->file_id = file_id; } @@ -3586,6 +3571,5 @@ BOOL srv_io_r_net_file_set_secdesc(const char *desc, SRV_R_NET_FILE_SET_SECDESC void init_srv_q_net_remote_tod(SRV_Q_NET_REMOTE_TOD *q_u, const char *server) { q_u->ptr_srv_name = 1; - init_unistr2(&q_u->uni_srv_name, server, strlen(server) + 1); + init_unistr2(&q_u->uni_srv_name, server, UNI_STR_TERMINATE); } - diff --git a/source3/rpc_server/srv_dfs_nt.c b/source3/rpc_server/srv_dfs_nt.c index 3470ad99b4..751cb6e642 100644 --- a/source3/rpc_server/srv_dfs_nt.c +++ b/source3/rpc_server/srv_dfs_nt.c @@ -198,7 +198,7 @@ static BOOL init_reply_dfs_info_1(struct junction_map* j, DFS_INFO_1* dfs1, int slprintf(str, sizeof(pstring)-1, "\\\\%s\\%s\\%s", global_myname(), j[i].service_name, j[i].volume_name); DEBUG(5,("init_reply_dfs_info_1: %d) initing entrypath: %s\n",i,str)); - init_unistr2(&dfs1[i].entrypath,str,strlen(str)+1); + init_unistr2(&dfs1[i].entrypath,str,UNI_STR_TERMINATE); } return True; } @@ -212,7 +212,7 @@ static BOOL init_reply_dfs_info_2(struct junction_map* j, DFS_INFO_2* dfs2, int dfs2[i].ptr_entrypath = 1; slprintf(str, sizeof(pstring)-1, "\\\\%s\\%s\\%s", global_myname(), j[i].service_name, j[i].volume_name); - init_unistr2(&dfs2[i].entrypath, str, strlen(str)+1); + init_unistr2(&dfs2[i].entrypath, str, UNI_STR_TERMINATE); dfs2[i].ptr_comment = 0; dfs2[i].state = 1; /* set up state of dfs junction as OK */ dfs2[i].num_storages = j[i].referral_count; @@ -234,9 +234,9 @@ static BOOL init_reply_dfs_info_3(TALLOC_CTX *ctx, struct junction_map* j, DFS_I slprintf(str, sizeof(pstring)-1, "\\\\%s\\%s\\%s", global_myname(), j[i].service_name, j[i].volume_name); - init_unistr2(&dfs3[i].entrypath, str, strlen(str)+1); + init_unistr2(&dfs3[i].entrypath, str, UNI_STR_TERMINATE); dfs3[i].ptr_comment = 1; - init_unistr2(&dfs3[i].comment, "", 1); + init_unistr2(&dfs3[i].comment, "", UNI_STR_TERMINATE); dfs3[i].state = 1; dfs3[i].num_storages = dfs3[i].num_storage_infos = j[i].referral_count; dfs3[i].ptr_storages = 1; @@ -267,8 +267,8 @@ static BOOL init_reply_dfs_info_3(TALLOC_CTX *ctx, struct junction_map* j, DFS_I *p = '\0'; DEBUG(5,("storage %d: %s.%s\n",ii,path,p+1)); stor->state = 2; /* set all storages as ONLINE */ - init_unistr2(&stor->servername, path, strlen(path)+1); - init_unistr2(&stor->sharename, p+1, strlen(p+1)+1); + init_unistr2(&stor->servername, path, UNI_STR_TERMINATE); + init_unistr2(&stor->sharename, p+1, UNI_STR_TERMINATE); stor->ptr_servername = stor->ptr_sharename = 1; } } diff --git a/source3/rpc_server/srv_lsa_ds_nt.c b/source3/rpc_server/srv_lsa_ds_nt.c index 37540a9668..97e9dc361d 100644 --- a/source3/rpc_server/srv_lsa_ds_nt.c +++ b/source3/rpc_server/srv_lsa_ds_nt.c @@ -77,12 +77,12 @@ static NTSTATUS fill_dsrole_dominfo_basic(TALLOC_CTX *ctx, DSROLE_PRIMARY_DOMAIN basic->netbios_ptr = 1; netbios_domain = get_global_sam_name(); - init_unistr2( &basic->netbios_domain, netbios_domain, strlen(netbios_domain) ); + init_unistr2( &basic->netbios_domain, netbios_domain, UNI_FLAGS_NONE); basic->dnsname_ptr = 1; - init_unistr2( &basic->dns_domain, dnsdomain, strlen(dnsdomain) ); + init_unistr2( &basic->dns_domain, dnsdomain, UNI_FLAGS_NONE); basic->forestname_ptr = 1; - init_unistr2( &basic->forest_domain, dnsdomain, strlen(dnsdomain) ); + init_unistr2( &basic->forest_domain, dnsdomain, UNI_FLAGS_NONE); /* fill in some additional fields if we are a member of an AD domain */ diff --git a/source3/rpc_server/srv_lsa_nt.c b/source3/rpc_server/srv_lsa_nt.c index 686a3069bb..0921824cad 100644 --- a/source3/rpc_server/srv_lsa_nt.c +++ b/source3/rpc_server/srv_lsa_nt.c @@ -61,7 +61,12 @@ Init dom_query static void init_dom_query(DOM_QUERY *d_q, const char *dom_name, DOM_SID *dom_sid) { - int domlen = (dom_name != NULL) ? strlen(dom_name) : 0; + d_q->buffer_dom_name = (dom_name != NULL) ? 1 : 0; /* domain buffer pointer */ + d_q->buffer_dom_sid = (dom_sid != NULL) ? 1 : 0; /* domain sid pointer */ + + /* this string is supposed to be non-null terminated. */ + /* But the maxlen in this UNISTR2 must include the terminating null. */ + init_unistr2(&d_q->uni_domain_name, dom_name, UNI_MAXLEN_TERMINATE); /* * I'm not sure why this really odd combination of length @@ -71,14 +76,15 @@ static void init_dom_query(DOM_QUERY *d_q, const char *dom_name, DOM_SID *dom_si * a domain with both odd and even length names... JRA. */ - d_q->uni_dom_str_len = domlen ? ((domlen + 1) * 2) : 0; - d_q->uni_dom_max_len = domlen * 2; - d_q->buffer_dom_name = domlen != 0 ? 1 : 0; /* domain buffer pointer */ - d_q->buffer_dom_sid = dom_sid != NULL ? 1 : 0; /* domain sid pointer */ + /* + * IMPORTANT NOTE !!!! + * The two fields below probably are reversed in meaning, ie. + * the first field is probably the str_len, the second the max + * len. Both are measured in bytes anyway. + */ - /* this string is supposed to be character short */ - init_unistr2(&d_q->uni_domain_name, dom_name, domlen); - d_q->uni_domain_name.uni_max_len++; + d_q->uni_dom_str_len = d_q->uni_domain_name.uni_max_len * 2; + d_q->uni_dom_max_len = d_q->uni_domain_name.uni_str_len * 2; if (dom_sid != NULL) init_dom_sid2(&d_q->dom_sid, dom_sid); @@ -91,7 +97,6 @@ static void init_dom_query(DOM_QUERY *d_q, const char *dom_name, DOM_SID *dom_si static int init_dom_ref(DOM_R_REF *ref, char *dom_name, DOM_SID *dom_sid) { int num = 0; - int len; if (dom_name != NULL) { for (num = 0; num < ref->num_ref_doms_1; num++) { @@ -114,14 +119,11 @@ static int init_dom_ref(DOM_R_REF *ref, char *dom_name, DOM_SID *dom_sid) ref->max_entries = MAX_REF_DOMAINS; ref->num_ref_doms_2 = num+1; - len = (dom_name != NULL) ? strlen(dom_name) : 0; - if(dom_name != NULL && len == 0) - len = 1; - - init_uni_hdr(&ref->hdr_ref_dom[num].hdr_dom_name, len); ref->hdr_ref_dom[num].ptr_dom_sid = dom_sid != NULL ? 1 : 0; - init_unistr2(&ref->ref_dom[num].uni_dom_name, dom_name, len); + init_unistr2(&ref->ref_dom[num].uni_dom_name, dom_name, UNI_FLAGS_NONE); + init_uni_hdr(&ref->hdr_ref_dom[num].hdr_dom_name, &ref->ref_dom[num].uni_dom_name); + init_dom_sid2(&ref->ref_dom[num].ref_dom, dom_sid ); return num; @@ -349,25 +351,22 @@ static void init_dns_dom_info(LSA_DNS_DOM_INFO *r_l, const char *nb_name, GUID *dom_guid, DOM_SID *dom_sid) { if (nb_name && *nb_name) { - init_uni_hdr(&r_l->hdr_nb_dom_name, strlen(nb_name)); - init_unistr2(&r_l->uni_nb_dom_name, nb_name, - strlen(nb_name)); + init_unistr2(&r_l->uni_nb_dom_name, nb_name, UNI_FLAGS_NONE); + init_uni_hdr(&r_l->hdr_nb_dom_name, &r_l->uni_nb_dom_name); r_l->hdr_nb_dom_name.uni_max_len += 2; r_l->uni_nb_dom_name.uni_max_len += 1; } if (dns_name && *dns_name) { - init_uni_hdr(&r_l->hdr_dns_dom_name, strlen(dns_name)); - init_unistr2(&r_l->uni_dns_dom_name, dns_name, - strlen(dns_name)); + init_unistr2(&r_l->uni_dns_dom_name, dns_name, UNI_FLAGS_NONE); + init_uni_hdr(&r_l->hdr_dns_dom_name, &r_l->uni_dns_dom_name); r_l->hdr_dns_dom_name.uni_max_len += 2; r_l->uni_dns_dom_name.uni_max_len += 1; } if (forest_name && *forest_name) { - init_uni_hdr(&r_l->hdr_forest_name, strlen(forest_name)); - init_unistr2(&r_l->uni_forest_name, forest_name, - strlen(forest_name)); + init_unistr2(&r_l->uni_forest_name, forest_name, UNI_FLAGS_NONE); + init_uni_hdr(&r_l->hdr_forest_name, &r_l->uni_forest_name); r_l->hdr_forest_name.uni_max_len += 2; r_l->uni_forest_name.uni_max_len += 1; } @@ -774,13 +773,13 @@ NTSTATUS _lsa_enum_privs(pipes_struct *p, LSA_Q_ENUM_PRIVS *q_u, LSA_R_ENUM_PRIV for (i = 0; i < PRIV_ALL_INDEX; i++, entry++) { if( ihdr_name, 0); - init_unistr2(&entry->name, NULL, 0 ); + init_unistr2(&entry->name, NULL, UNI_FLAGS_NONE); + init_uni_hdr(&entry->hdr_name, &entry->name); entry->luid_low = 0; entry->luid_high = 0; } else { - init_uni_hdr(&entry->hdr_name, strlen(privs[i+1].priv)); - init_unistr2(&entry->name, privs[i+1].priv, strlen(privs[i+1].priv) ); + init_unistr2(&entry->name, privs[i+1].priv, UNI_FLAGS_NONE); + init_uni_hdr(&entry->hdr_name, &entry->name); entry->luid_low = privs[i+1].se_priv; entry->luid_high = 0; } @@ -822,8 +821,8 @@ NTSTATUS _lsa_priv_get_dispname(pipes_struct *p, LSA_Q_PRIV_GET_DISPNAME *q_u, L if (privs[i].se_priv!=SE_PRIV_ALL) { DEBUG(10,(": %s\n", privs[i].description)); - init_uni_hdr(&r_u->hdr_desc, strlen(privs[i].description)); - init_unistr2(&r_u->desc, privs[i].description, strlen(privs[i].description) ); + init_unistr2(&r_u->desc, privs[i].description, UNI_FLAGS_NONE); + init_uni_hdr(&r_u->hdr_desc, &r_u->desc); r_u->ptr_info=0xdeadbeef; r_u->lang_id=q_u->lang_id; @@ -890,7 +889,6 @@ NTSTATUS _lsa_enum_accounts(pipes_struct *p, LSA_Q_ENUM_ACCOUNTS *q_u, LSA_R_ENU NTSTATUS _lsa_unk_get_connuser(pipes_struct *p, LSA_Q_UNK_GET_CONNUSER *q_u, LSA_R_UNK_GET_CONNUSER *r_u) { fstring username, domname; - int ulen, dlen; user_struct *vuser = get_valid_user_struct(p->vuid); if (vuser == NULL) @@ -899,18 +897,15 @@ NTSTATUS _lsa_unk_get_connuser(pipes_struct *p, LSA_Q_UNK_GET_CONNUSER *q_u, LSA fstrcpy(username, vuser->user.smb_name); fstrcpy(domname, vuser->user.domain); - ulen = strlen(username) + 1; - dlen = strlen(domname) + 1; - - init_uni_hdr(&r_u->hdr_user_name, ulen); r_u->ptr_user_name = 1; - init_unistr2(&r_u->uni2_user_name, username, ulen); + init_unistr2(&r_u->uni2_user_name, username, UNI_STR_TERMINATE); + init_uni_hdr(&r_u->hdr_user_name, &r_u->uni2_user_name); r_u->unk1 = 1; - init_uni_hdr(&r_u->hdr_dom_name, dlen); r_u->ptr_dom_name = 1; - init_unistr2(&r_u->uni2_dom_name, domname, dlen); + init_unistr2(&r_u->uni2_dom_name, domname, UNI_STR_TERMINATE); + init_uni_hdr(&r_u->hdr_dom_name, &r_u->uni2_dom_name); r_u->status = NT_STATUS_OK; diff --git a/source3/rpc_server/srv_samr_nt.c b/source3/rpc_server/srv_samr_nt.c index 828e07c1ad..71e5bc7d70 100644 --- a/source3/rpc_server/srv_samr_nt.c +++ b/source3/rpc_server/srv_samr_nt.c @@ -719,7 +719,7 @@ static NTSTATUS make_user_sam_entry_list(TALLOC_CTX *ctx, SAM_ENTRY **sam_pp, UN for (i = 0; i < num_entries; i++) { pwd = &disp_user_info[i+start_idx]; temp_name = pdb_get_username(pwd); - init_unistr2(&uni_temp_name, temp_name, strlen(temp_name)+1); + init_unistr2(&uni_temp_name, temp_name, UNI_STR_TERMINATE); user_sid = pdb_get_user_sid(pwd); if (!sid_peek_check_rid(domain_sid, user_sid, &user_rid)) { @@ -731,7 +731,7 @@ static NTSTATUS make_user_sam_entry_list(TALLOC_CTX *ctx, SAM_ENTRY **sam_pp, UN return NT_STATUS_UNSUCCESSFUL; } - init_sam_entry(&sam[i], uni_temp_name.uni_str_len, user_rid); + init_sam_entry(&sam[i], &uni_temp_name, user_rid); copy_unistr2(&uni_name[i], &uni_temp_name); } @@ -865,10 +865,8 @@ static void make_group_sam_entry_list(TALLOC_CTX *ctx, SAM_ENTRY **sam_pp, UNIST /* * JRA. I think this should include the null. TNG does not. */ - int len = strlen(grp[i].name)+1; - - init_sam_entry(&sam[i], len, grp[i].rid); - init_unistr2(&uni_name[i], grp[i].name, len); + init_unistr2(&uni_name[i], grp[i].name, UNI_STR_TERMINATE); + init_sam_entry(&sam[i], &uni_name[i], grp[i].rid); } *sam_pp = sam; @@ -1580,10 +1578,9 @@ static BOOL make_samr_lookup_rids(TALLOC_CTX *ctx, uint32 num_names, fstring nam } for (i = 0; i < num_names; i++) { - int len = names[i] != NULL ? strlen(names[i]) : 0; - DEBUG(10, ("names[%d]:%s\n", i, names[i])); - init_uni_hdr(&hdr_name[i], len); - init_unistr2(&uni_name[i], names[i], len); + DEBUG(10, ("names[%d]:%s\n", i, names[i] ? names[i] : "")); + init_unistr2(&uni_name[i], names[i], UNI_FLAGS_NONE); + init_uni_hdr(&hdr_name[i], &uni_name[i]); } *pp_uni_name = uni_name; @@ -2570,10 +2567,8 @@ static BOOL make_enum_domains(TALLOC_CTX *ctx, SAM_ENTRY **pp_sam, return False; for (i = 0; i < num_sam_entries; i++) { - int len = doms[i] != NULL ? strlen(doms[i]) : 0; - - init_sam_entry(&sam[i], len, 0); - init_unistr2(&uni_name[i], doms[i], len); + init_unistr2(&uni_name[i], doms[i], UNI_FLAGS_NONE); + init_sam_entry(&sam[i], &uni_name[i], 0); } *pp_sam = sam; diff --git a/source3/rpc_server/srv_spoolss_nt.c b/source3/rpc_server/srv_spoolss_nt.c index 7159527a7d..493f58f8a8 100644 --- a/source3/rpc_server/srv_spoolss_nt.c +++ b/source3/rpc_server/srv_spoolss_nt.c @@ -690,7 +690,7 @@ static void notify_string(struct spoolss_notify_msg *msg, /* The length of the message includes the trailing \0 */ - init_unistr2(&unistr, msg->notify.data, msg->len); + init_unistr2(&unistr, msg->notify.data, UNI_STR_TERMINATE); data->notify_data.data.length = msg->len * 2; data->notify_data.data.string = (uint16 *)talloc(mem_ctx, msg->len * 2); @@ -6121,7 +6121,7 @@ static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level, */ if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) { - init_unistr2( &buffer, printer->info_2->comment, strlen(printer->info_2->comment)+1 ); + init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE); set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description", REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 ); @@ -6129,7 +6129,7 @@ static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level, } if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) { - init_unistr2( &buffer, printer->info_2->sharename, strlen(printer->info_2->sharename)+1 ); + init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE); set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName", REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 ); set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName", @@ -6139,7 +6139,7 @@ static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level, } if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) { - init_unistr2( &buffer, printer->info_2->portname, strlen(printer->info_2->portname)+1 ); + init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE); set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName", REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 ); @@ -6147,7 +6147,7 @@ static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level, } if (!strequal(printer->info_2->location, old_printer->info_2->location)) { - init_unistr2( &buffer, printer->info_2->location, strlen(printer->info_2->location)+1 ); + init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE); set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location", REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 ); @@ -6157,7 +6157,7 @@ static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level, /* here we need to update some more DsSpooler keys */ /* uNCName, serverName, shortServerName */ - init_unistr2( &buffer, global_myname(), strlen(global_myname())+1 ); + init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE); set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName", REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 ); set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName", @@ -6165,7 +6165,7 @@ static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level, slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s", global_myname(), printer->info_2->sharename ); - init_unistr2( &buffer, asc_buffer, strlen(asc_buffer)+1 ); + init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE); set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName", REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 ); diff --git a/source3/rpcclient/cmd_spoolss.c b/source3/rpcclient/cmd_spoolss.c index 61e100c03b..05bfb2a0dc 100644 --- a/source3/rpcclient/cmd_spoolss.c +++ b/source3/rpcclient/cmd_spoolss.c @@ -1568,7 +1568,7 @@ static WERROR cmd_spoolss_addform(struct cli_state *cli, TALLOC_CTX *mem_ctx, form.right = 20; form.bottom = 30; - init_unistr2(&form.name, argv[2], strlen(argv[2]) + 1); + init_unistr2(&form.name, argv[2], UNI_STR_TERMINATE); /* Add the form */ @@ -1627,7 +1627,7 @@ static WERROR cmd_spoolss_setform(struct cli_state *cli, TALLOC_CTX *mem_ctx, form.right = 2000; form.bottom = 3000; - init_unistr2(&form.name, argv[2], strlen(argv[2]) + 1); + init_unistr2(&form.name, argv[2], UNI_STR_TERMINATE); /* Set the form */ -- cgit From 3f5f051d0086507280f820d9423009619357612e Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 29 Sep 2003 06:18:00 +0000 Subject: Merge from 3.0: >Fix for valid users = %S in homes share. >Jeremy. (This used to be commit 799da7092c5b56914512f843789adbedec5ac8f5) --- source3/smbd/password.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'source3') diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 32c24b3d67..958ed663e6 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -291,7 +291,9 @@ BOOL user_ok(const char *user,int snum, gid_t *groups, size_t n_groups) if (lp_invalid_users(snum)) { str_list_copy(&invalid, lp_invalid_users(snum)); if (invalid && str_list_substitute(invalid, "%S", lp_servicename(snum))) { - ret = !user_in_list(user, (const char **)invalid, groups, n_groups); + if ( invalid && str_list_sub_basic(invalid, current_user_info.smb_name) ) { + ret = !user_in_list(user, (const char **)invalid, groups, n_groups); + } } } if (invalid) @@ -299,8 +301,10 @@ BOOL user_ok(const char *user,int snum, gid_t *groups, size_t n_groups) if (ret && lp_valid_users(snum)) { str_list_copy(&valid, lp_valid_users(snum)); - if ( valid && str_list_sub_basic(valid, current_user_info.smb_name) ) { - ret = user_in_list(user, (const char **)valid, groups, n_groups); + if ( valid && str_list_substitute(valid, "%S", lp_servicename(snum)) ) { + if ( valid && str_list_sub_basic(valid, current_user_info.smb_name) ) { + ret = user_in_list(user, (const char **)valid, groups, n_groups); + } } } if (valid) -- cgit From a21e1f781f0bbf783cda6237fa4103deb8a43474 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 29 Sep 2003 06:18:42 +0000 Subject: Merge from 3.0: >Ensure %S gets expanded in read/write lists. >Jeremy. (This used to be commit 424acd6ee92c46c565886c3305c3492737538d3d) --- source3/smbd/service.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) (limited to 'source3') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 44d73b2ab2..e4c3890f86 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -259,23 +259,27 @@ static NTSTATUS share_sanity_checks(int snum, fstring dev) return NT_STATUS_OK; } - /**************************************************************************** readonly share? ****************************************************************************/ + static void set_read_only(connection_struct *conn, gid_t *groups, size_t n_groups) { char **list; - char *service = lp_servicename(conn->service); + const char *service = lp_servicename(conn->service); conn->read_only = lp_readonly(conn->service); - if (!service) return; + if (!service) + return; str_list_copy(&list, lp_readlist(conn->service)); if (list) { - if ( !str_list_sub_basic(list, current_user_info.smb_name) ) { + if (!str_list_sub_basic(list, current_user_info.smb_name) ) { DEBUG(0, ("ERROR: read list substitution failed\n")); } + if (!str_list_substitute(list, "%S", service)) { + DEBUG(0, ("ERROR: read list service substitution failed\n")); + } if (user_in_list(conn->user, (const char **)list, groups, n_groups)) conn->read_only = True; str_list_free(&list); @@ -283,19 +287,22 @@ static void set_read_only(connection_struct *conn, gid_t *groups, size_t n_group str_list_copy(&list, lp_writelist(conn->service)); if (list) { - if ( !str_list_sub_basic(list, current_user_info.smb_name) ) { + if (!str_list_sub_basic(list, current_user_info.smb_name) ) { DEBUG(0, ("ERROR: write list substitution failed\n")); } + if (!str_list_substitute(list, "%S", service)) { + DEBUG(0, ("ERROR: write list service substitution failed\n")); + } if (user_in_list(conn->user, (const char **)list, groups, n_groups)) conn->read_only = False; str_list_free(&list); } } - /**************************************************************************** admin user check ****************************************************************************/ + static void set_admin_user(connection_struct *conn, gid_t *groups, size_t n_groups) { /* admin user check */ -- cgit From 4663c471a35079cdea8b97559c02f865ec6dffd8 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 29 Sep 2003 06:20:11 +0000 Subject: Merge from 3.0: >More bug #413. Fix bad html table row termination in SWAT wizard code found by >Monyo. Also remove debugging d_printf() which snuck in the last commit. >Change title of SWAT globals page from 'Global Variables' to 'Global >Parameters' to be more consistent with the other pages. (This used to be commit 1ab70b41a9eba59272c0af5a8036c32366734177) --- source3/web/swat.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'source3') diff --git a/source3/web/swat.c b/source3/web/swat.c index 1c892559dd..2b2686cc5a 100644 --- a/source3/web/swat.c +++ b/source3/web/swat.c @@ -737,8 +737,10 @@ static void wizard_page(void) d_printf("", (winstype == 0) ? "checked" : ""); d_printf("", (winstype == 1) ? "checked" : ""); d_printf("", (winstype == 2) ? "checked" : ""); + d_printf("\n"); + d_printf(""); d_printf(""); } - d_printf(""); d_printf("\n","Expose Home Directories: "); d_printf("", (have_home == -1) ? "" : "checked "); d_printf("", (have_home == -1 ) ? "checked" : ""); @@ -780,7 +781,7 @@ static void globals_page(void) unsigned int parm_filter = FLAG_BASIC; int mode = 0; - d_printf("

%s

\n", _("Global Variables")); + d_printf("

%s

\n", _("Global Parameters")); if (cgi_variable("Commit")) { commit_parameters(GLOBAL_SECTION_SNUM); -- cgit From 22634870b8f3672755276a28270365ba15e6e44f Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 29 Sep 2003 06:20:55 +0000 Subject: Merge from 3.0: >Fix to parse the level-2 strings. From Anthony Liguori aliguor@us.ibm.com. >Jeremy. (This used to be commit 3420320714798427bf9b760ed89fa4ce9346ad19) --- source3/utils/net_ads_cldap.c | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) (limited to 'source3') diff --git a/source3/utils/net_ads_cldap.c b/source3/utils/net_ads_cldap.c index 595e6e9434..44de9cb891 100644 --- a/source3/utils/net_ads_cldap.c +++ b/source3/utils/net_ads_cldap.c @@ -32,19 +32,15 @@ struct cldap_netlogon_reply { GUID guid; char forest[MAX_DNS_LABEL]; - char unk0[MAX_DNS_LABEL]; char domain[MAX_DNS_LABEL]; char hostname[MAX_DNS_LABEL]; char netbios_domain[MAX_DNS_LABEL]; - char unk1[MAX_DNS_LABEL]; char netbios_hostname[MAX_DNS_LABEL]; - char unk2[MAX_DNS_LABEL]; + char unk[MAX_DNS_LABEL]; char user_name[MAX_DNS_LABEL]; - char unk3[MAX_DNS_LABEL]; char site_name[MAX_DNS_LABEL]; - char unk4[MAX_DNS_LABEL]; char site_name_2[MAX_DNS_LABEL]; uint32 version; @@ -115,7 +111,7 @@ static unsigned pull_netlogon_string(char *ret, const char *ptr, } } while (*ptr); - return ret_len ? ret_len : 1; + return followed_ptr ? ret_len : ret_len + 1; } /* @@ -249,13 +245,11 @@ static int recv_cldap_netlogon(int sock, struct cldap_netlogon_reply *reply) p += GUID_SIZE; p += pull_netlogon_string(reply->forest, p, (const char *)os3.data); - p += pull_netlogon_string(reply->unk0, p, (const char *)os3.data); p += pull_netlogon_string(reply->domain, p, (const char *)os3.data); p += pull_netlogon_string(reply->hostname, p, (const char *)os3.data); p += pull_netlogon_string(reply->netbios_domain, p, (const char *)os3.data); - p += pull_netlogon_string(reply->unk1, p, (const char *)os3.data); p += pull_netlogon_string(reply->netbios_hostname, p, (const char *)os3.data); - p += pull_netlogon_string(reply->unk2, p, (const char *)os3.data); + p += pull_netlogon_string(reply->unk, p, (const char *)os3.data); if (reply->type == SAMLOGON_AD_R) { p += pull_netlogon_string(reply->user_name, p, (const char *)os3.data); @@ -263,9 +257,7 @@ static int recv_cldap_netlogon(int sock, struct cldap_netlogon_reply *reply) *reply->user_name = 0; } - p += pull_netlogon_string(reply->unk3, p, (const char *)os3.data); p += pull_netlogon_string(reply->site_name, p, (const char *)os3.data); - p += pull_netlogon_string(reply->unk4, p, (const char *)os3.data); p += pull_netlogon_string(reply->site_name_2, p, (const char *)os3.data); reply->version = IVAL(p, 0); @@ -349,20 +341,16 @@ int ads_cldap_netlogon(ADS_STRUCT *ads) (reply.flags & ADS_NDNC) ? "yes" : "no"); printf("Forest:\t\t\t%s\n", reply.forest); - if (*reply.unk0) printf("Unk0:\t\t\t%s\n", reply.unk0); printf("Domain:\t\t\t%s\n", reply.domain); printf("Domain Controller:\t%s\n", reply.hostname); printf("Pre-Win2k Domain:\t%s\n", reply.netbios_domain); - if (*reply.unk1) printf("Unk1:\t\t\t%s\n", reply.unk1); printf("Pre-Win2k Hostname:\t%s\n", reply.netbios_hostname); - if (*reply.unk2) printf("Unk2:\t\t\t%s\n", reply.unk2); + if (*reply.unk) printf("Unk:\t\t\t%s\n", reply.unk); if (*reply.user_name) printf("User name:\t%s\n", reply.user_name); - if (*reply.unk3) printf("Unk3:\t\t\t%s\n", reply.unk3); printf("Site Name:\t\t%s\n", reply.site_name); - if (*reply.unk4) printf("Unk4:\t\t\t%s\n", reply.unk4); printf("Site Name (2):\t\t%s\n", reply.site_name_2); d_printf("NT Version: %d\n", reply.version); -- cgit From 981c82b16e82da859f7205cfc37ffe849e58b78c Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 29 Sep 2003 06:22:04 +0000 Subject: Merge from 3.0: >Allow d_printf() to handle strings with escaped quotation marks since the >msg file includes the escape character. > >Fixes bug #489. (This used to be commit 0871be2bfad8bfa5d4f0ff78e732c1073055da2e) --- source3/intl/lang_tdb.c | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) (limited to 'source3') diff --git a/source3/intl/lang_tdb.c b/source3/intl/lang_tdb.c index 5409ce6619..af70b529ff 100644 --- a/source3/intl/lang_tdb.c +++ b/source3/intl/lang_tdb.c @@ -176,16 +176,47 @@ BOOL lang_tdb_init(const char *lang) const char *lang_msg(const char *msgid) { TDB_DATA key, data; + char *p, *q, *msgid_quoted; + int count; lang_tdb_init(NULL); if (!tdb) return msgid; - key.dptr = (char *)msgid; - key.dsize = strlen(msgid)+1; + /* Due to the way quotes in msgids are escaped in the msg file we + must replace " with \" before doing a lookup in the tdb. */ + + count = 0; + + for(p = msgid; *p; p++) { + if (*p == '\"') + count++; + } + + if (!(msgid_quoted = malloc(strlen(msgid) + count + 1))) + return msgid; + + /* string_sub() is unsuitable here as it replaces some punctuation + chars with underscores. */ + + for(p = msgid, q = msgid_quoted; *p; p++) { + if (*p == '\"') { + *q = '\\'; + q++; + } + *q = *p; + q++; + } + + *q = 0; + + key.dptr = (char *)msgid_quoted; + key.dsize = strlen(msgid_quoted)+1; data = tdb_fetch(tdb, key); + free(msgid_quoted); + /* if the message isn't found then we still need to return a pointer that can be freed. Pity. */ if (!data.dptr) -- cgit From 1052b52178fb4ce0e83ddfc48339d68d34fd43c3 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 29 Sep 2003 06:22:55 +0000 Subject: Merge from 3.0: >Apply some NULL pointer paranoia to previous wins hook fix. >Fix broken wins hook functionality. A i18n fixe caused the name type >to be appended to the netbios name between angle brackets. This interfered >the 'sh -c' used to implement smbrun(). Closes bug #528. (This used to be commit 12659ae74965f8a088361cb4fbf8730cdad84af1) --- source3/nmbd/nmbd_winsserver.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'source3') diff --git a/source3/nmbd/nmbd_winsserver.c b/source3/nmbd/nmbd_winsserver.c index 484588c662..3694072420 100644 --- a/source3/nmbd/nmbd_winsserver.c +++ b/source3/nmbd/nmbd_winsserver.c @@ -107,7 +107,7 @@ static void wins_hook(const char *operation, struct name_record *namerec, int tt { pstring command; char *cmd = lp_wins_hook(); - char *p; + char *p, *namestr; int i; if (!cmd || !*cmd) return; @@ -119,11 +119,17 @@ static void wins_hook(const char *operation, struct name_record *namerec, int tt } } + /* Use the name without the nametype (and scope) appended */ + + namestr = nmb_namestr(&namerec->name); + if ((p = strchr(namestr, '<'))) + *p = 0; + p = command; p += slprintf(p, sizeof(command)-1, "%s %s %s %02x %d", cmd, operation, - nmb_namestr(&namerec->name), + namestr, namerec->name.name_type, ttl); -- cgit From 10ab4ce58abbd9b38bfb43165452cf45005159b4 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 29 Sep 2003 06:23:56 +0000 Subject: Merge from 3.0: >iconv isn't const safe. Neither should smb_iconv be. >Jeremy. (This used to be commit 7bd450f8b678e835ba4f9cfdc3d096b04da6f8f7) --- source3/lib/iconv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3') diff --git a/source3/lib/iconv.c b/source3/lib/iconv.c index 3d26d7e17c..0326ca7061 100644 --- a/source3/lib/iconv.c +++ b/source3/lib/iconv.c @@ -136,7 +136,7 @@ static size_t sys_iconv(void *cd, * enough that Samba works on systems that don't have iconv. **/ size_t smb_iconv(smb_iconv_t cd, - const char **inbuf, size_t *inbytesleft, + char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft) { char cvtbuf[2048]; -- cgit From 0dde70c2330b7fad898f27ba3102f425a8e5f579 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 29 Sep 2003 23:35:39 +0000 Subject: Take care of condition where DOS and NT error codes must differ. Found by DOS program test by Amir Hardon . Jeremy. (This used to be commit 294f376aa908a9c56b73b9bfe48d56012a8f557b) --- source3/smbd/reply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 6ac4cffddb..303e33cc48 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -417,7 +417,7 @@ int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size if (check_name(name,conn)) { if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,name,&sbuf) == 0) if (!(ok = S_ISDIR(sbuf.st_mode))) - errno = ENOTDIR; + return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY,ERRDOS,ERRbadpath); } if (!ok) { -- cgit From e1f16f33219b44f0a66af0da0a02d8e8781a24f6 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Wed, 1 Oct 2003 17:02:09 +0000 Subject: merge of parameter changes from 3.0 and fix for bug 550 (This used to be commit b6433f5db77a1d62309946c6f23c18c6c299d0c5) --- source3/lib/system.c | 8 +++++--- source3/lib/system_smbd.c | 2 +- source3/param/loadparm.c | 5 +---- 3 files changed, 7 insertions(+), 8 deletions(-) (limited to 'source3') diff --git a/source3/lib/system.c b/source3/lib/system.c index b020a20373..2e95efec79 100644 --- a/source3/lib/system.c +++ b/source3/lib/system.c @@ -693,7 +693,6 @@ int sys_getgroups(int setlen, gid_t *gidset) #endif /* HAVE_BROKEN_GETGROUPS */ } -#ifdef HAVE_SETGROUPS /************************************************************************** Wrapper for setgroups. Deals with broken (int) case. Automatically used @@ -702,6 +701,11 @@ int sys_getgroups(int setlen, gid_t *gidset) int sys_setgroups(int setlen, gid_t *gidset) { +#if !defined(HAVE_SETGROUPS) + errno = ENOSYS; + return -1; +#endif /* HAVE_SETGROUPS */ + #if !defined(HAVE_BROKEN_GETGROUPS) return setgroups(setlen, gidset); #else @@ -742,8 +746,6 @@ int sys_setgroups(int setlen, gid_t *gidset) #endif /* HAVE_BROKEN_GETGROUPS */ } -#endif /* HAVE_SETGROUPS */ - /************************************************************************** Wrappers for setpwent(), getpwent() and endpwent() ****************************************************************************/ diff --git a/source3/lib/system_smbd.c b/source3/lib/system_smbd.c index bcbc8c61e6..73c910e631 100644 --- a/source3/lib/system_smbd.c +++ b/source3/lib/system_smbd.c @@ -92,7 +92,7 @@ static int getgrouplist_internals(const char *user, gid_t gid, gid_t *groups, in restore_re_gid(); - if (setgroups(ngrp_saved, gids_saved) != 0) { + if (sys_setgroups(ngrp_saved, gids_saved) != 0) { /* yikes! */ DEBUG(0,("ERROR: getgrouplist: failed to reset group list!\n")); smb_panic("getgrouplist: failed to reset group list!\n"); diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index 0efa2796c3..45626192db 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -185,7 +185,6 @@ typedef struct int mangle_prefix; int max_log_size; char *szLogLevel; - int mangled_stack; int max_xmit; int max_mux; int max_open_files; @@ -972,7 +971,6 @@ static struct parm_struct parm_table[] = { {"mangling method", P_STRING, P_GLOBAL, &Globals.szManglingMethod, NULL, NULL, FLAG_ADVANCED}, {"mangle prefix", P_INTEGER, P_GLOBAL, &Globals.mangle_prefix, NULL, NULL, FLAG_ADVANCED}, - {"mangled stack", P_INTEGER, P_GLOBAL, &Globals.mangled_stack, NULL, NULL, FLAG_ADVANCED}, {"default case", P_ENUM, P_LOCAL, &sDefault.iDefaultCase, NULL, enum_case, FLAG_ADVANCED | FLAG_SHARE}, {"case sensitive", P_BOOL, P_LOCAL, &sDefault.bCaseSensitive, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, {"casesignames", P_BOOL, P_LOCAL, &sDefault.bCaseSensitive, NULL, NULL, FLAG_HIDE}, @@ -992,7 +990,7 @@ static struct parm_struct parm_table[] = { {"map hidden", P_BOOL, P_LOCAL, &sDefault.bMap_hidden, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, {"map archive", P_BOOL, P_LOCAL, &sDefault.bMap_archive, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, {"mangled names", P_BOOL, P_LOCAL, &sDefault.bMangledNames, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, - {"mangled map", P_STRING, P_LOCAL, &sDefault.szMangledMap, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, + {"mangled map", P_STRING, P_LOCAL, &sDefault.szMangledMap, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL | FLAG_DEPRECATED }, {"stat cache", P_BOOL, P_GLOBAL, &Globals.bStatCache, NULL, NULL, FLAG_ADVANCED}, {"Domain Options", P_SEP, P_SEPARATOR}, @@ -1361,7 +1359,6 @@ static void init_globals(void) Globals.AlgorithmicRidBase = BASE_RID; Globals.bLoadPrinters = True; - Globals.mangled_stack = 50; /* Was 65535 (0xFFFF). 0x4101 matches W2K and causes major speed improvements... */ /* Discovered by 2 days of pain by Don McCall @ HP :-). */ Globals.max_xmit = 0x4104; -- cgit From 4d0f0c0594c5a81e22686ff006ff689a2ca1fe47 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Wed, 1 Oct 2003 18:54:29 +0000 Subject: save and restore CFLAGS before/after AC_PROG_CC; this macro seems to overwrite the CFLAGS variable (This used to be commit aa7fccf6ad81da8a4a14abd699d1f765e18cd10c) --- source3/configure.in | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'source3') diff --git a/source3/configure.in b/source3/configure.in index 8c2e9e7f9b..987e1ceb6b 100644 --- a/source3/configure.in +++ b/source3/configure.in @@ -166,6 +166,7 @@ AC_SUBST(EXTRA_ALL_TARGETS) AC_ARG_ENABLE(debug, [ --enable-debug Turn on compiler debugging information (default=no)], [if eval "test x$enable_debug = xyes"; then + echo "DEBUGGING TURNED ON!!!!" CFLAGS="${CFLAGS} -g" fi]) @@ -192,7 +193,15 @@ then fi dnl Checks for programs. + +## +## for some reason this macro resets the CFLAGS +## so save and restore +## +OLD_CFLAGS=${CFLAGS} AC_PROG_CC +CFLAGS=${OLD_CFLAGS} + AC_PROG_INSTALL AC_PROG_AWK AC_PATH_PROG(PERL, perl) -- cgit From 73953efac3e219e67d127e31e965756d8fa46104 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 1 Oct 2003 19:33:27 +0000 Subject: Allow ^C to interrupt smbpasswd if using our getpass. Jeremy. (This used to be commit 8a284463458cfaaff9986bbc459dfc113f921c6c) --- source3/lib/getsmbpass.c | 148 +++++++++++++++++++++++++++-------------------- 1 file changed, 86 insertions(+), 62 deletions(-) (limited to 'source3') diff --git a/source3/lib/getsmbpass.c b/source3/lib/getsmbpass.c index b6ae09b318..93449b004d 100644 --- a/source3/lib/getsmbpass.c +++ b/source3/lib/getsmbpass.c @@ -83,71 +83,95 @@ static int tcsetattr(int fd, int flags, struct sgttyb *t) static struct termios t; #endif /* SYSV_TERMIO */ +static SIG_ATOMIC_T gotintr; +static int in_fd = -1; + +/*************************************************************** + Signal function to tell us were ^C'ed. +****************************************************************/ + +static void gotintr_sig(void) +{ + gotintr = 1; + if (in_fd != -1) + close(in_fd); /* Safe way to force a return. */ + in_fd = -1; +} + char *getsmbpass(const char *prompt) { - FILE *in, *out; - int echo_off; - static char buf[256]; - static size_t bufsize = sizeof(buf); - size_t nread; - - /* Catch problematic signals */ - CatchSignal(SIGINT, SIGNAL_CAST SIG_IGN); - - /* Try to write to and read from the terminal if we can. - If we can't open the terminal, use stderr and stdin. */ - - in = fopen ("/dev/tty", "w+"); - if (in == NULL) - { - in = stdin; - out = stderr; - } - else - out = in; - - setvbuf(in, NULL, _IONBF, 0); - - /* Turn echoing off if it is on now. */ - - if (tcgetattr (fileno (in), &t) == 0) - { - if (ECHO_IS_ON(t)) - { - TURN_ECHO_OFF(t); - echo_off = tcsetattr (fileno (in), TCSAFLUSH, &t) == 0; - TURN_ECHO_ON(t); + FILE *in, *out; + int echo_off; + static char buf[256]; + static size_t bufsize = sizeof(buf); + size_t nread; + + /* Catch problematic signals */ + CatchSignal(SIGINT, SIGNAL_CAST gotintr_sig); + + /* Try to write to and read from the terminal if we can. + If we can't open the terminal, use stderr and stdin. */ + + in = fopen ("/dev/tty", "w+"); + if (in == NULL) { + in = stdin; + out = stderr; + } else { + out = in; + } + + setvbuf(in, NULL, _IONBF, 0); + + /* Turn echoing off if it is on now. */ + + if (tcgetattr (fileno (in), &t) == 0) { + if (ECHO_IS_ON(t)) { + TURN_ECHO_OFF(t); + echo_off = tcsetattr (fileno (in), TCSAFLUSH, &t) == 0; + TURN_ECHO_ON(t); + } else { + echo_off = 0; + } + } else { + echo_off = 0; + } + + /* Write the prompt. */ + fputs(prompt, out); + fflush(out); + + /* Read the password. */ + buf[0] = 0; + if (!gotintr) { + in_fd = fileno(in); + fgets(buf, bufsize, in); + } + nread = strlen(buf); + if (buf[nread - 1] == '\n') + buf[nread - 1] = '\0'; + + /* Restore echoing. */ + if (echo_off) { + if (gotintr && in_fd == -1) + in = fopen ("/dev/tty", "w+"); + if (in != NULL) + tcsetattr (fileno (in), TCSANOW, &t); + } + + if (in != stdin) /* We opened the terminal; now close it. */ + fclose(in); + + /* Catch problematic signals */ + CatchSignal(SIGINT, SIGNAL_CAST SIG_DFL); + + printf("\n"); + + if (gotintr_sig) { + printf("Interupted by signal.\n"); + fflush(stdout); + exit(1); } - else - echo_off = 0; - } - else - echo_off = 0; - - /* Write the prompt. */ - fputs (prompt, out); - fflush (out); - - /* Read the password. */ - buf[0] = 0; - fgets(buf, bufsize, in); - nread = strlen(buf); - if (buf[nread - 1] == '\n') - buf[nread - 1] = '\0'; - - /* Restore echoing. */ - if (echo_off) - (void) tcsetattr (fileno (in), TCSANOW, &t); - - if (in != stdin) - /* We opened the terminal; now close it. */ - fclose (in); - - /* Catch problematic signals */ - CatchSignal(SIGINT, SIGNAL_CAST SIG_DFL); - - printf("\n"); - return buf; + return buf; } #else -- cgit From b8092fbf99d01783110566b51dfaf26d4802f403 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 1 Oct 2003 21:17:46 +0000 Subject: Fixed silly typo checking for signal_handler not signal. Jeremy. (This used to be commit 202d4e46527993d359df7cd04fb611c22cc920c3) --- source3/lib/getsmbpass.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3') diff --git a/source3/lib/getsmbpass.c b/source3/lib/getsmbpass.c index 93449b004d..27cd5e6dfa 100644 --- a/source3/lib/getsmbpass.c +++ b/source3/lib/getsmbpass.c @@ -166,7 +166,7 @@ char *getsmbpass(const char *prompt) printf("\n"); - if (gotintr_sig) { + if (gotintr) { printf("Interupted by signal.\n"); fflush(stdout); exit(1); -- cgit From e9568f8df282a8de58d077fb88b54b43023795ca Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Wed, 1 Oct 2003 22:00:19 +0000 Subject: commit sign only patch from Andrew; bug 167; tested using 2k & XP clientspreviously joined to the Samba domain (This used to be commit 9d2e585e5e6f9066c6901aa8d8308734f8667296) --- source3/include/rpc_dce.h | 11 +++- source3/rpc_client/cli_pipe.c | 29 ++++----- source3/rpc_parse/parse_prs.c | 147 +++++++++++++++++++++++++----------------- source3/rpc_parse/parse_rpc.c | 6 +- source3/rpc_server/srv_pipe.c | 30 +++++---- source3/rpcclient/rpcclient.c | 50 ++++++++------ 6 files changed, 159 insertions(+), 114 deletions(-) (limited to 'source3') diff --git a/source3/include/rpc_dce.h b/source3/include/rpc_dce.h index 2e4a418bb7..52fe08d875 100644 --- a/source3/include/rpc_dce.h +++ b/source3/include/rpc_dce.h @@ -61,8 +61,14 @@ enum RPC_PKT_TYPE /* Netlogon schannel auth type and level */ #define NETSEC_AUTH_TYPE 0x44 -#define NETSEC_SIGNATURE { 0x77, 0x00, 0x7a, 0x00, 0xff, 0xff, 0x00, 0x00 } +#define NETSEC_SIGN_SIGNATURE { 0x77, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00 } +#define NETSEC_SEAL_SIGNATURE { 0x77, 0x00, 0x7a, 0x00, 0xff, 0xff, 0x00, 0x00 } #define RPC_AUTH_NETSEC_CHK_LEN 0x20 + +/* The 7 here seems to be required to get Win2k not to downgrade us + to NT4. Actually, anything other than 1ff would seem to do... */ +#define NETLOGON_NEG_AUTH2_FLAGS 0x000701ff + #define NETLOGON_NEG_SCHANNEL 0x40000000 enum netsec_direction @@ -239,13 +245,14 @@ typedef struct rpc_auth_netsec_chk_info uint8 sig [8]; /* 77 00 7a 00 ff ff 00 00 */ uint8 packet_digest[8]; /* checksum over the packet, MD5'ed with session key */ uint8 seq_num[8]; /* verifier, seq num */ - uint8 data8[8]; /* random 8-byte nonce */ + uint8 confounder[8]; /* random 8-byte nonce */ } RPC_AUTH_NETSEC_CHK; struct netsec_auth_struct { uchar sess_key[16]; uint32 seq_num; + int auth_flags; }; /* RPC_BIND_REQ - ms req bind */ diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index dedbf017a9..9ce10202db 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -29,7 +29,9 @@ extern struct pipe_id_info pipe_names[]; -static void get_auth_type_level(int pipe_auth_flags, int *auth_type, int *auth_level) +/* convert pipe auth flags into the RPC auth type and level */ + +void get_auth_type_level(int pipe_auth_flags, int *auth_type, int *auth_level) { *auth_type = 0; *auth_level = 0; @@ -938,7 +940,6 @@ BOOL rpc_api_pipe_req(struct cli_state *cli, uint8 op_num, uint32 data_len, send_size; uint8 flags = 0; uint32 auth_padding = 0; - RPC_AUTH_NETSEC_CHK verf; DATA_BLOB sign_blob; /* @@ -1022,14 +1023,10 @@ BOOL rpc_api_pipe_req(struct cli_state *cli, uint8 op_num, } else if (cli->pipe_auth_flags & AUTH_PIPE_NETSEC) { - static const uchar netsec_sig[8] = NETSEC_SIGNATURE; - static const uchar nullbytes[8] = { 0,0,0,0,0,0,0,0 }; size_t parse_offset_marker; + RPC_AUTH_NETSEC_CHK verf; DEBUG(10,("SCHANNEL seq_num=%d\n", cli->auth_info.seq_num)); - init_rpc_auth_netsec_chk(&verf, netsec_sig, nullbytes, - nullbytes, nullbytes); - netsec_encode(&cli->auth_info, cli->pipe_auth_flags, SENDER_IS_INITIATOR, @@ -1277,8 +1274,10 @@ static BOOL rpc_send_auth_reply(struct cli_state *cli, prs_struct *rdata, uint32 prs_init(&rpc_out, RPC_HEADER_LEN + RPC_HDR_AUTHA_LEN, /* need at least this much */ cli->mem_ctx, MARSHALL); - create_rpc_bind_resp(cli, rpc_call_id, - &rpc_out); + if (!NT_STATUS_IS_OK(create_rpc_bind_resp(cli, rpc_call_id, + &rpc_out))) { + return False; + } if ((ret = cli_write(cli, cli->nt_pipe_fnum, 0x8, prs_data_p(&rpc_out), 0, (size_t)prs_offset(&rpc_out))) != (ssize_t)prs_offset(&rpc_out)) { @@ -1493,9 +1492,7 @@ NTSTATUS cli_nt_establish_netlogon(struct cli_state *cli, int sec_chan, const uchar trust_password[16]) { NTSTATUS result; - /* The 7 here seems to be required to get Win2k not to downgrade us - to NT4. Actually, anything other than 1ff would seem to do... */ - uint32 neg_flags = 0x000701ff; + uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS; int fnum; cli_nt_netlogon_netsec_session_close(cli); @@ -1584,13 +1581,11 @@ NTSTATUS cli_nt_establish_netlogon(struct cli_state *cli, int sec_chan, } -NTSTATUS cli_nt_setup_netsec(struct cli_state *cli, int sec_chan, +NTSTATUS cli_nt_setup_netsec(struct cli_state *cli, int sec_chan, int auth_flags, const uchar trust_password[16]) { NTSTATUS result; - /* The 7 here seems to be required to get Win2k not to downgrade us - to NT4. Actually, anything other than 1ff would seem to do... */ - uint32 neg_flags = 0x000701ff; + uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS; cli->pipe_auth_flags = 0; if (lp_client_schannel() == False) { @@ -1632,7 +1627,7 @@ NTSTATUS cli_nt_setup_netsec(struct cli_state *cli, int sec_chan, cli->nt_pipe_fnum = 0; /* doing schannel, not per-user auth */ - cli->pipe_auth_flags = AUTH_PIPE_NETSEC | AUTH_PIPE_SIGN | AUTH_PIPE_SEAL; + cli->pipe_auth_flags = auth_flags; return NT_STATUS_OK; } diff --git a/source3/rpc_parse/parse_prs.c b/source3/rpc_parse/parse_prs.c index 81a9573077..b30c41c090 100644 --- a/source3/rpc_parse/parse_prs.c +++ b/source3/rpc_parse/parse_prs.c @@ -3,7 +3,8 @@ Samba memory buffer functions Copyright (C) Andrew Tridgell 1992-1997 Copyright (C) Luke Kenneth Casson Leighton 1996-1997 - Copyright (C) Jeremy Allison 1999. + Copyright (C) Jeremy Allison 1999 + Copyright (C) Andrew Bartlett 2003. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -1337,47 +1338,6 @@ BOOL prs_hash1(prs_struct *ps, uint32 offset, uint8 sess_key[16], int len) return True; } -static void netsechash(uchar * key, uchar * data, int data_len) -{ - uchar hash[256]; - uchar index_i = 0; - uchar index_j = 0; - uchar j = 0; - int ind; - - for (ind = 0; ind < 256; ind++) - { - hash[ind] = (uchar) ind; - } - - for (ind = 0; ind < 256; ind++) - { - uchar tc; - - j += (hash[ind] + key[ind % 16]); - - tc = hash[ind]; - hash[ind] = hash[j]; - hash[j] = tc; - } - - for (ind = 0; ind < data_len; ind++) - { - uchar tc; - uchar t; - - index_i++; - index_j += hash[index_i]; - - tc = hash[index_i]; - hash[index_i] = hash[index_j]; - hash[index_j] = tc; - - t = hash[index_i] + hash[index_j]; - data[ind] ^= hash[t]; - } -} - /******************************************************************* Create a digest over the entire packet (including the data), and @@ -1400,7 +1360,7 @@ static void netsec_digest(struct netsec_auth_struct *a, MD5Update(&ctx3, zeros, sizeof(zeros)); MD5Update(&ctx3, verf->sig, sizeof(verf->sig)); if (auth_flags & AUTH_PIPE_SEAL) { - MD5Update(&ctx3, verf->data8, sizeof(verf->data8)); + MD5Update(&ctx3, verf->confounder, sizeof(verf->confounder)); } MD5Update(&ctx3, (const unsigned char *)data, data_len); MD5Final(whole_packet_digest, &ctx3); @@ -1456,10 +1416,29 @@ static void netsec_deal_with_seq_num(struct netsec_auth_struct *a, dump_data_pw("sequence_key:\n", sequence_key, sizeof(sequence_key)); dump_data_pw("seq_num (before):\n", verf->seq_num, sizeof(verf->seq_num)); - netsechash(sequence_key, verf->seq_num, 8); + SamOEMhash(verf->seq_num, sequence_key, 8); dump_data_pw("seq_num (after):\n", verf->seq_num, sizeof(verf->seq_num)); } +/******************************************************************* +creates an RPC_AUTH_NETSEC_CHK structure. +********************************************************************/ +static BOOL init_rpc_auth_netsec_chk(RPC_AUTH_NETSEC_CHK * chk, + const uchar sig[8], + const uchar packet_digest[8], + const uchar seq_num[8], const uchar confounder[8]) +{ + if (chk == NULL) + return False; + + memcpy(chk->sig, sig, sizeof(chk->sig)); + memcpy(chk->packet_digest, packet_digest, sizeof(chk->packet_digest)); + memcpy(chk->seq_num, seq_num, sizeof(chk->seq_num)); + memcpy(chk->confounder, confounder, sizeof(chk->confounder)); + + return True; +} + /******************************************************************* Encode a blob of data using the netsec (schannel) alogrithm, also produceing @@ -1469,26 +1448,47 @@ static void netsec_deal_with_seq_num(struct netsec_auth_struct *a, ********************************************************************/ void netsec_encode(struct netsec_auth_struct *a, int auth_flags, enum netsec_direction direction, - RPC_AUTH_NETSEC_CHK * verf, char *data, size_t data_len) + RPC_AUTH_NETSEC_CHK * verf, + char *data, size_t data_len) { uchar digest_final[16]; + uchar confounder[8]; + uchar seq_num[8]; + static const uchar nullbytes[8]; + + static const uchar netsec_seal_sig[8] = NETSEC_SEAL_SIGNATURE; + static const uchar netsec_sign_sig[8] = NETSEC_SIGN_SIGNATURE; + const uchar *netsec_sig; DEBUG(10,("SCHANNEL: netsec_encode seq_num=%d data_len=%lu\n", a->seq_num, (unsigned long)data_len)); + + if (auth_flags & AUTH_PIPE_SEAL) { + netsec_sig = netsec_seal_sig; + } else if (auth_flags & AUTH_PIPE_SIGN) { + netsec_sig = netsec_sign_sig; + } + + /* fill the 'confounder' with random data */ + generate_random_buffer(confounder, sizeof(confounder), False); + dump_data_pw("a->sess_key:\n", a->sess_key, sizeof(a->sess_key)); - RSIVAL(verf->seq_num, 0, a->seq_num); + RSIVAL(seq_num, 0, a->seq_num); switch (direction) { case SENDER_IS_INITIATOR: - SIVAL(verf->seq_num, 4, 0x80); + SIVAL(seq_num, 4, 0x80); break; case SENDER_IS_ACCEPTOR: - SIVAL(verf->seq_num, 4, 0x0); + SIVAL(seq_num, 4, 0x0); break; } - dump_data_pw("verf->seq_num:\n", verf->seq_num, sizeof(verf->seq_num)); + dump_data_pw("verf->seq_num:\n", seq_num, sizeof(verf->seq_num)); + init_rpc_auth_netsec_chk(verf, netsec_sig, nullbytes, + seq_num, confounder); + /* produce a digest of the packet to prove it's legit (before we seal it) */ netsec_digest(a, auth_flags, verf, data, data_len, digest_final); memcpy(verf->packet_digest, digest_final, sizeof(verf->packet_digest)); @@ -1500,14 +1500,14 @@ void netsec_encode(struct netsec_auth_struct *a, int auth_flags, netsec_get_sealing_key(a, verf, sealing_key); /* encode the verification data */ - dump_data_pw("verf->data8:\n", verf->data8, sizeof(verf->data8)); - netsechash(sealing_key, verf->data8, 8); + dump_data_pw("verf->confounder:\n", verf->confounder, sizeof(verf->confounder)); + SamOEMhash(verf->confounder, sealing_key, 8); - dump_data_pw("verf->data8_enc:\n", verf->data8, sizeof(verf->data8)); + dump_data_pw("verf->confounder_enc:\n", verf->confounder, sizeof(verf->confounder)); /* encode the packet payload */ dump_data_pw("data:\n", (const unsigned char *)data, data_len); - netsechash(sealing_key, (unsigned char *)data, data_len); + SamOEMhash((unsigned char *)data, sealing_key, data_len); dump_data_pw("data_enc:\n", (const unsigned char *)data, data_len); } @@ -1531,8 +1531,21 @@ BOOL netsec_decode(struct netsec_auth_struct *a, int auth_flags, { uchar digest_final[16]; - /* Create the expected sequence number for comparison */ + static const uchar netsec_seal_sig[8] = NETSEC_SEAL_SIGNATURE; + static const uchar netsec_sign_sig[8] = NETSEC_SIGN_SIGNATURE; + const uchar *netsec_sig; + uchar seq_num[8]; + + DEBUG(10,("SCHANNEL: netsec_encode seq_num=%d data_len=%lu\n", a->seq_num, (unsigned long)data_len)); + + if (auth_flags & AUTH_PIPE_SEAL) { + netsec_sig = netsec_seal_sig; + } else if (auth_flags & AUTH_PIPE_SIGN) { + netsec_sig = netsec_sign_sig; + } + + /* Create the expected sequence number for comparison */ RSIVAL(seq_num, 0, a->seq_num); switch (direction) { @@ -1560,6 +1573,20 @@ BOOL netsec_decode(struct netsec_auth_struct *a, int auth_flags, digest, as supplied by the client. We check that it's a valid checksum after the decode, below */ + DEBUG(2, ("netsec_decode: FAILED: packet sequence number:\n")); + dump_data(2, verf->seq_num, sizeof(verf->seq_num)); + DEBUG(2, ("should be:\n")); + dump_data(2, seq_num, sizeof(seq_num)); + + return False; + } + + if (memcmp(verf->sig, netsec_sig, sizeof(verf->sig))) { + /* Validate that the other end sent the expected header */ + DEBUG(2, ("netsec_decode: FAILED: packet header:\n")); + dump_data(2, verf->sig, sizeof(verf->sig)); + DEBUG(2, ("should be:\n")); + dump_data(2, netsec_sig, sizeof(netsec_sig)); return False; } @@ -1570,16 +1597,16 @@ BOOL netsec_decode(struct netsec_auth_struct *a, int auth_flags, netsec_get_sealing_key(a, verf, sealing_key); /* extract the verification data */ - dump_data_pw("verf->data8:\n", verf->data8, - sizeof(verf->data8)); - netsechash(sealing_key, verf->data8, 8); + dump_data_pw("verf->confounder:\n", verf->confounder, + sizeof(verf->confounder)); + SamOEMhash(verf->confounder, sealing_key, 8); - dump_data_pw("verf->data8_dec:\n", verf->data8, - sizeof(verf->data8)); + dump_data_pw("verf->confounder_dec:\n", verf->confounder, + sizeof(verf->confounder)); /* extract the packet payload */ dump_data_pw("data :\n", (const unsigned char *)data, data_len); - netsechash(sealing_key, (unsigned char *)data, data_len); + SamOEMhash((unsigned char *)data, sealing_key, data_len); dump_data_pw("datadec:\n", (const unsigned char *)data, data_len); } diff --git a/source3/rpc_parse/parse_rpc.c b/source3/rpc_parse/parse_rpc.c index 34ba62caa9..558378548a 100644 --- a/source3/rpc_parse/parse_rpc.c +++ b/source3/rpc_parse/parse_rpc.c @@ -1175,7 +1175,7 @@ creates an RPC_AUTH_NETSEC_CHK structure. BOOL init_rpc_auth_netsec_chk(RPC_AUTH_NETSEC_CHK * chk, const uchar sig[8], const uchar packet_digest[8], - const uchar seq_num[8], const uchar data8[8]) + const uchar seq_num[8], const uchar confounder[8]) { if (chk == NULL) return False; @@ -1183,7 +1183,7 @@ BOOL init_rpc_auth_netsec_chk(RPC_AUTH_NETSEC_CHK * chk, memcpy(chk->sig, sig, sizeof(chk->sig)); memcpy(chk->packet_digest, packet_digest, sizeof(chk->packet_digest)); memcpy(chk->seq_num, seq_num, sizeof(chk->seq_num)); - memcpy(chk->data8, data8, sizeof(chk->data8)); + memcpy(chk->confounder, confounder, sizeof(chk->confounder)); return True; } @@ -1203,7 +1203,7 @@ BOOL smb_io_rpc_auth_netsec_chk(const char *desc, RPC_AUTH_NETSEC_CHK * chk, prs_uint8s(False, "sig ", ps, depth, chk->sig, sizeof(chk->sig)); prs_uint8s(False, "seq_num", ps, depth, chk->seq_num, sizeof(chk->seq_num)); prs_uint8s(False, "packet_digest", ps, depth, chk->packet_digest, sizeof(chk->packet_digest)); - prs_uint8s(False, "data8", ps, depth, chk->data8, sizeof(chk->data8)); + prs_uint8s(False, "data8", ps, depth, chk->confounder, sizeof(chk->confounder)); return True; } diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c index d1fb587d74..96261c665f 100644 --- a/source3/rpc_server/srv_pipe.c +++ b/source3/rpc_server/srv_pipe.c @@ -254,18 +254,19 @@ BOOL create_next_pdu(pipes_struct *p) } if (p->netsec_auth_validated) { + int auth_type, auth_level; char *data; RPC_HDR_AUTH auth_info; - static const uchar netsec_sig[8] = NETSEC_SIGNATURE; - static const uchar nullbytes[8] = { 0,0,0,0,0,0,0,0 }; RPC_AUTH_NETSEC_CHK verf; prs_struct rverf; prs_struct rauth; data = prs_data_p(&outgoing_pdu) + data_pos; + /* Check it's the type of reply we were expecting to decode */ - init_rpc_hdr_auth(&auth_info, NETSEC_AUTH_TYPE, RPC_PIPE_AUTH_SEAL_LEVEL, + get_auth_type_level(p->netsec_auth.auth_flags, &auth_type, &auth_level); + init_rpc_hdr_auth(&auth_info, auth_type, auth_level, RPC_HDR_AUTH_LEN, 1); if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, &outgoing_pdu, 0)) { @@ -277,10 +278,8 @@ BOOL create_next_pdu(pipes_struct *p) prs_init(&rverf, 0, p->mem_ctx, MARSHALL); prs_init(&rauth, 0, p->mem_ctx, MARSHALL); - init_rpc_auth_netsec_chk(&verf, netsec_sig, nullbytes, nullbytes, nullbytes); - netsec_encode(&p->netsec_auth, - AUTH_PIPE_NETSEC|AUTH_PIPE_SIGN|AUTH_PIPE_SEAL, + p->netsec_auth.auth_flags, SENDER_IS_ACCEPTOR, &verf, data, data_len); @@ -1337,10 +1336,19 @@ BOOL api_pipe_netsec_process(pipes_struct *p, prs_struct *rpc_in) return False; } - if ((auth_info.auth_type != NETSEC_AUTH_TYPE) || - (auth_info.auth_level != RPC_PIPE_AUTH_SEAL_LEVEL)) { - DEBUG(0,("Invalid auth info %d or level %d on schannel\n", - auth_info.auth_type, auth_info.auth_level)); + if (auth_info.auth_type != NETSEC_AUTH_TYPE) { + DEBUG(0,("Invalid auth info %d on schannel\n", + auth_info.auth_type)); + return False; + } + + if (auth_info.auth_level == RPC_PIPE_AUTH_SEAL_LEVEL) { + p->netsec_auth.auth_flags = AUTH_PIPE_NETSEC|AUTH_PIPE_SIGN|AUTH_PIPE_SEAL; + } else if (auth_info.auth_level == RPC_PIPE_AUTH_SIGN_LEVEL) { + p->netsec_auth.auth_flags = AUTH_PIPE_NETSEC|AUTH_PIPE_SIGN; + } else { + DEBUG(0,("Invalid auth level %d on schannel\n", + auth_info.auth_level)); return False; } @@ -1350,7 +1358,7 @@ BOOL api_pipe_netsec_process(pipes_struct *p, prs_struct *rpc_in) } if (!netsec_decode(&p->netsec_auth, - AUTH_PIPE_NETSEC|AUTH_PIPE_SIGN|AUTH_PIPE_SEAL, + p->netsec_auth.auth_flags, SENDER_IS_INITIATOR, &netsec_chk, prs_data_p(rpc_in)+old_offset, data_len)) { diff --git a/source3/rpcclient/rpcclient.c b/source3/rpcclient/rpcclient.c index 515489292b..773441a27c 100644 --- a/source3/rpcclient/rpcclient.c +++ b/source3/rpcclient/rpcclient.c @@ -352,38 +352,33 @@ static NTSTATUS cmd_none(struct cli_state *cli, TALLOC_CTX *mem_ctx, return NT_STATUS_OK; } -static NTSTATUS cmd_schannel(struct cli_state *cli, TALLOC_CTX *mem_ctx, - int argc, const char **argv) +static NTSTATUS setup_schannel(struct cli_state *cli, int pipe_auth_flags, + int argc, const char **argv) { NTSTATUS ret; + static uchar zeros[16]; uchar trust_password[16]; uint32 sec_channel_type; - static uchar zeros[16]; - if (argc == 2) { strhex_to_str((char *)cli->auth_info.sess_key, strlen(argv[1]), argv[1]); memcpy(cli->sess_key, cli->auth_info.sess_key, sizeof(cli->sess_key)); - cli->pipe_auth_flags = AUTH_PIPE_NETSEC; - cli->pipe_auth_flags |= AUTH_PIPE_SIGN; - cli->pipe_auth_flags |= AUTH_PIPE_SEAL; - + cli->pipe_auth_flags = pipe_auth_flags; return NT_STATUS_OK; } /* Cleanup */ if ((memcmp(cli->auth_info.sess_key, zeros, sizeof(cli->auth_info.sess_key)) != 0)) { - if (cli->pipe_auth_flags == (AUTH_PIPE_NETSEC|AUTH_PIPE_SIGN|AUTH_PIPE_SEAL)) { + if (cli->pipe_auth_flags == pipe_auth_flags) { /* already in this mode nothing to do */ return NT_STATUS_OK; } else { - /* schannel is setup, just need to use it again */ - cli->pipe_auth_flags = AUTH_PIPE_NETSEC; - cli->pipe_auth_flags |= AUTH_PIPE_SIGN; - cli->pipe_auth_flags |= AUTH_PIPE_SEAL; + /* schannel is setup, just need to use it again with new flags */ + cli->pipe_auth_flags = pipe_auth_flags; + if (cli->nt_pipe_fnum != 0) cli_nt_session_close(cli); return NT_STATUS_OK; @@ -393,17 +388,13 @@ static NTSTATUS cmd_schannel(struct cli_state *cli, TALLOC_CTX *mem_ctx, if (cli->nt_pipe_fnum != 0) cli_nt_session_close(cli); - cli->pipe_auth_flags = AUTH_PIPE_NETSEC; - cli->pipe_auth_flags |= AUTH_PIPE_SIGN; - cli->pipe_auth_flags |= AUTH_PIPE_SEAL; - if (!secrets_fetch_trust_account_password(lp_workgroup(), trust_password, NULL, &sec_channel_type)) { return NT_STATUS_UNSUCCESSFUL; } - ret = cli_nt_setup_netsec(cli, sec_channel_type, trust_password); + ret = cli_nt_setup_netsec(cli, sec_channel_type, pipe_auth_flags, trust_password); if (NT_STATUS_IS_OK(ret)) { char *hex_session_key; hex_encode(cli->auth_info.sess_key, @@ -415,6 +406,24 @@ static NTSTATUS cmd_schannel(struct cli_state *cli, TALLOC_CTX *mem_ctx, return ret; } + +static NTSTATUS cmd_schannel(struct cli_state *cli, TALLOC_CTX *mem_ctx, + int argc, const char **argv) +{ + d_printf("Setting schannel - sign and seal\n"); + return setup_schannel(cli, AUTH_PIPE_NETSEC | AUTH_PIPE_SIGN | AUTH_PIPE_SEAL, + argc, argv); +} + +static NTSTATUS cmd_schannel_sign(struct cli_state *cli, TALLOC_CTX *mem_ctx, + int argc, const char **argv) +{ + d_printf("Setting schannel - sign only\n"); + return setup_schannel(cli, AUTH_PIPE_NETSEC | AUTH_PIPE_SIGN, + argc, argv); +} + + /* Built in rpcclient commands */ static struct cmd_set rpcclient_commands[] = { @@ -430,6 +439,7 @@ static struct cmd_set rpcclient_commands[] = { { "sign", RPC_RTYPE_NTSTATUS, cmd_sign, NULL, -1, "Force RPC pipe connections to be signed", "" }, { "seal", RPC_RTYPE_NTSTATUS, cmd_seal, NULL, -1, "Force RPC pipe connections to be sealed", "" }, { "schannel", RPC_RTYPE_NTSTATUS, cmd_schannel, NULL, -1, "Force RPC pipe connections to be sealed with 'schannel' (NETSEC). Assumes valid machine account to this domain controller.", "" }, + { "schannelsign", RPC_RTYPE_NTSTATUS, cmd_schannel_sign, NULL, -1, "Force RPC pipe connections to be signed (not sealed) with 'schannel' (NETSEC). Assumes valid machine account to this domain controller.", "" }, { "none", RPC_RTYPE_NTSTATUS, cmd_none, NULL, -1, "Force RPC pipe connections to have no special properties", "" }, { NULL } @@ -522,9 +532,7 @@ static NTSTATUS do_cmd(struct cli_state *cli, /* some of the DsXXX commands use the netlogon pipe */ if (lp_client_schannel() && (cmd_entry->pipe_idx == PI_NETLOGON) && !(cli->pipe_auth_flags & AUTH_PIPE_NETSEC)) { - /* The 7 here seems to be required to get Win2k not to downgrade us - to NT4. Actually, anything other than 1ff would seem to do... */ - uint32 neg_flags = 0x000001ff; + uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS; uint32 sec_channel_type; if (!secrets_fetch_trust_account_password(lp_workgroup(), -- cgit From 418749050ba387a4657cc23dfb86cf06548703cf Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 2 Oct 2003 00:55:20 +0000 Subject: Fix for not opening Excel 2000 files that are read-only. Needs tidying up but works for now. Jeremy. (This used to be commit d9b9113a0815aeeddb8fdcccb64e7692fe02a9c2) --- source3/smbd/error.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'source3') diff --git a/source3/smbd/error.c b/source3/smbd/error.c index 9d0e34bf52..7eec5e25df 100644 --- a/source3/smbd/error.c +++ b/source3/smbd/error.c @@ -61,9 +61,6 @@ int unix_error_packet(char *outbuf,int def_class,uint32 def_code, eclass = unix_ERR_class; ecode = unix_ERR_code; ntstatus = unix_ERR_ntstatus; - unix_ERR_class = SMB_SUCCESS; - unix_ERR_code = 0; - unix_ERR_ntstatus = NT_STATUS_OK; } else { while (unix_dos_nt_errmap[i].dos_class != 0) { if (unix_dos_nt_errmap[i].unix_error == errno) { @@ -93,6 +90,10 @@ int error_packet(char *outbuf,NTSTATUS ntstatus, if (errno != 0) DEBUG(3,("error string = %s\n",strerror(errno))); + unix_ERR_class = SMB_SUCCESS; + unix_ERR_code = 0; + unix_ERR_ntstatus = NT_STATUS_OK; + /* * We can explicitly force 32 bit error codes even when the * parameter "nt status" is set to no by pre-setting the -- cgit From 64f88c008cc4f047ecd8e457fbdcafde32e9def5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 2 Oct 2003 17:26:44 +0000 Subject: Correct fix for excel read-only bug. Add panic for logic error in developer mode. Jeremy. (This used to be commit 0857932c1c1960fd68a10f3d1f8c300b7a28b6d7) --- source3/smbd/error.c | 10 +++++++--- source3/smbd/trans2.c | 3 --- 2 files changed, 7 insertions(+), 6 deletions(-) (limited to 'source3') diff --git a/source3/smbd/error.c b/source3/smbd/error.c index 7eec5e25df..795bf0949c 100644 --- a/source3/smbd/error.c +++ b/source3/smbd/error.c @@ -61,6 +61,9 @@ int unix_error_packet(char *outbuf,int def_class,uint32 def_code, eclass = unix_ERR_class; ecode = unix_ERR_code; ntstatus = unix_ERR_ntstatus; + unix_ERR_class = SMB_SUCCESS; + unix_ERR_code = 0; + unix_ERR_ntstatus = NT_STATUS_OK; } else { while (unix_dos_nt_errmap[i].dos_class != 0) { if (unix_dos_nt_errmap[i].unix_error == errno) { @@ -90,9 +93,10 @@ int error_packet(char *outbuf,NTSTATUS ntstatus, if (errno != 0) DEBUG(3,("error string = %s\n",strerror(errno))); - unix_ERR_class = SMB_SUCCESS; - unix_ERR_code = 0; - unix_ERR_ntstatus = NT_STATUS_OK; +#if defined(DEVELOPER) + if (unix_ERR_class != SMB_SUCCESS || unix_ERR_code != 0 || !NT_STATUS_IS_OK(unix_ERR_ntstatus)) + smb_panic("logic error in error processing"); +#endif /* * We can explicitly force 32 bit error codes even when the diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 033e76a33e..ee63220d18 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1785,12 +1785,9 @@ int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint err, (int)bad_path )); if(err == ENOENT) { - unix_ERR_class = ERRDOS; if (bad_path) { - unix_ERR_code = ERRbadpath; return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); } else { - unix_ERR_code = ERRbadfile; return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND); } } -- cgit From 460aa846391df5a29bcbc80317c7b73d68a6a78b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 2 Oct 2003 17:36:45 +0000 Subject: Portability fix from schmitz@hp.com (Joachim Schmitz) for bug #548. Jeremy. (This used to be commit a0828a2a1ce04075f0a7cb4a201cea0781998237) --- source3/rpc_server/srv_spoolss_nt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3') diff --git a/source3/rpc_server/srv_spoolss_nt.c b/source3/rpc_server/srv_spoolss_nt.c index 493f58f8a8..f2fb02176b 100644 --- a/source3/rpc_server/srv_spoolss_nt.c +++ b/source3/rpc_server/srv_spoolss_nt.c @@ -1803,7 +1803,7 @@ Can't find printer handle we created for printer %s\n", name )); && (RA_WIN2K == get_remote_arch()) ) { DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n")); - usleep( 500000 ); + sys_usleep( 500000 ); } return WERR_OK; -- cgit From e8fb38d8dda4fe44324c454c88e3e58d2e877a56 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 2 Oct 2003 17:53:55 +0000 Subject: Portability fix from schmitz@hp.com (Joachim Schmitz). Bug #547. Jeremy. (This used to be commit 9519ffc7cbdb37a4279c8804230596978679220e) --- source3/passdb/pdb_smbpasswd.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3') diff --git a/source3/passdb/pdb_smbpasswd.c b/source3/passdb/pdb_smbpasswd.c index 8171b65adc..8cdbec9b9d 100644 --- a/source3/passdb/pdb_smbpasswd.c +++ b/source3/passdb/pdb_smbpasswd.c @@ -261,7 +261,11 @@ static FILE *startsmbfilepwent(const char *pfile, enum pwf_access_type type, int setvbuf(fp, (char *)NULL, _IOFBF, 1024); /* Make sure it is only rw by the owner */ +#ifdef HAVE_FCHMOD if(fchmod(fileno(fp), S_IRUSR|S_IWUSR) == -1) { +#else + if(chmod(pfile, S_IRUSR|S_IWUSR) == -1) { +#endif DEBUG(0, ("startsmbfilepwent_internal: failed to set 0600 permissions on password file %s. \ Error was %s\n.", pfile, strerror(errno) )); pw_file_unlock(fileno(fp), lock_depth); -- cgit From 4ed89be00f0239179182da04b6c3d017a639664d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 2 Oct 2003 18:22:48 +0000 Subject: Portability fixes from schmitz@hp.com (Joachim Schmitz). Bug #549. Jeremy. (This used to be commit 6defe43e6d48619cee31b6c7fc602973e8eeef3f) --- source3/tdb/tdbback.c | 11 +++++++++++ source3/tdb/tdbbackup.c | 12 ++++++++++++ source3/utils/profiles.c | 8 +++++++- 3 files changed, 30 insertions(+), 1 deletion(-) (limited to 'source3') diff --git a/source3/tdb/tdbback.c b/source3/tdb/tdbback.c index 744cface55..9466c29991 100644 --- a/source3/tdb/tdbback.c +++ b/source3/tdb/tdbback.c @@ -18,6 +18,11 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#ifdef STANDALONE +#if HAVE_CONFIG_H +#include +#endif + #include #include #include @@ -27,10 +32,16 @@ #include #include #include + #include #include #include #include + +#else +#include "includes.h" +#endif + #include "tdb.h" static int failed; diff --git a/source3/tdb/tdbbackup.c b/source3/tdb/tdbbackup.c index 0eaf6b6c0b..1a0e1c1588 100644 --- a/source3/tdb/tdbbackup.c +++ b/source3/tdb/tdbbackup.c @@ -41,6 +41,11 @@ */ +#ifdef STANDALONE +#if HAVE_CONFIG_H +#include +#endif + #include #include #include @@ -54,6 +59,13 @@ #include #include #include + +#else + +#include "includes.h" + +#endif + #include "tdb.h" #include "tdbback.h" diff --git a/source3/utils/profiles.c b/source3/utils/profiles.c index 3230eb21fc..20b1222e72 100644 --- a/source3/utils/profiles.c +++ b/source3/utils/profiles.c @@ -295,7 +295,6 @@ Hope this helps.... (Although it was "fun" for me to uncover this things, #include #include #include -#include typedef unsigned int DWORD; typedef unsigned short WORD; @@ -610,7 +609,12 @@ int main(int argc, char *argv[]) * dealing with the records. We are interested in the sk record */ start = 0; + +#ifdef HAVE_MMAP base = mmap(&start, sbuf.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); +#else + base = (char *)-1; +#endif if ((int)base == -1) { fprintf(stderr, "Could not mmap file: %s, %s\n", poptPeekArg(pc), @@ -726,7 +730,9 @@ int main(int argc, char *argv[]) sk_hdr = (SK_HDR *)(base + OFF(IVAL(&sk_hdr->prev_off, 0))); } while (sk_off != first_sk_off); +#ifdef HAVE_MMAP munmap(base, sbuf.st_size); +#endif poptFreeContext(pc); -- cgit From 8ae168b46df07414f1d56a74e2ecb8aa2332d50a Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Fri, 3 Oct 2003 15:08:16 +0000 Subject: abstract UUID parsing code to an individual function; patch from Anthony (This used to be commit 6cbdbdf9e1e76837c8ef03e795db11caa74ccf18) --- source3/rpc_parse/parse_rpc.c | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) (limited to 'source3') diff --git a/source3/rpc_parse/parse_rpc.c b/source3/rpc_parse/parse_rpc.c index 558378548a..c1e663f877 100644 --- a/source3/rpc_parse/parse_rpc.c +++ b/source3/rpc_parse/parse_rpc.c @@ -243,29 +243,48 @@ BOOL smb_io_rpc_hdr(const char *desc, RPC_HDR *rpc, prs_struct *ps, int depth) } /******************************************************************* - Reads or writes an RPC_IFACE structure. + Reads or writes an RPC_UUID structure. ********************************************************************/ -static BOOL smb_io_rpc_iface(const char *desc, RPC_IFACE *ifc, prs_struct *ps, int depth) +static BOOL smb_io_rpc_uuid(const char *desc, RPC_UUID *uuid, prs_struct *ps, int depth) { if (ifc == NULL) return False; - prs_debug(ps, depth, desc, "smb_io_rpc_iface"); + prs_debug(ps, depth, desc, "smb_io_rpc_uuid"); depth++; if(!prs_align(ps)) return False; - if(!prs_uint32 ("data ", ps, depth, &ifc->uuid.time_low)) + if(!prs_uint32 ("data ", ps, depth, &uuid->time_low)) + return False; + if(!prs_uint16 ("data ", ps, depth, &uuid->time_mid)) + return False; + if(!prs_uint16 ("data ", ps, depth, &uuid->time_hi_and_version)) return False; - if(!prs_uint16 ("data ", ps, depth, &ifc->uuid.time_mid)) + + if(!prs_uint8s (False, "data ", ps, depth, uuid->remaining, sizeof(uuid->remaining))) return False; - if(!prs_uint16 ("data ", ps, depth, &ifc->uuid.time_hi_and_version)) + + return true; +} + +/******************************************************************* + Reads or writes an RPC_IFACE structure. +********************************************************************/ + +static BOOL smb_io_rpc_iface(const char *desc, RPC_IFACE *ifc, prs_struct *ps, int depth) +{ + if (ifc == NULL) return False; - if(!prs_uint8s (False, "data ", ps, depth, ifc->uuid.remaining, sizeof(ifc->uuid.remaining))) + prs_debug(ps, depth, desc, "smb_io_rpc_iface"); + depth++; + + if (!smb_io_rpc_uuid( "uuid", ps, depth, &ifc->uuid)) return False; + if(!prs_uint32 ( "version", ps, depth, &ifc->version)) return False; -- cgit From ec7716734ef8860ec8071ef7872672c4cb02a4e8 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Fri, 3 Oct 2003 15:11:38 +0000 Subject: cleaning out patch list; patch from Steve L. to change the cwd before the postexec script (This used to be commit bbc403ec6ee119f1bbb636deb40563dfdf258a74) --- source3/smbd/service.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index e4c3890f86..e5655bd9f4 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -894,6 +894,9 @@ void close_cnum(connection_struct *conn, uint16 vuid) file_close_conn(conn); dptr_closecnum(conn); + /* make sure we leave the directory available for unmount */ + vfs_ChDir(conn, "/"); + /* execute any "postexec = " line */ if (*lp_postexec(SNUM(conn)) && change_to_user(conn, vuid)) { @@ -913,8 +916,5 @@ void close_cnum(connection_struct *conn, uint16 vuid) smbrun(cmd,NULL); } - /* make sure we leave the directory available for unmount */ - vfs_ChDir(conn, "/"); - conn_free(conn); } -- cgit From 9cfd26141cf9530f27e673bfae119d9879894dd4 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Fri, 3 Oct 2003 21:43:56 +0000 Subject: don't call ads_destroy() twice; fixes segfault in winbindd when DC goes down; bug 437 (This used to be commit 9da4d1f7dbb289dd1db5e57a4fd78004bbfbd26b) --- source3/libads/ldap.c | 3 ++- source3/libads/ldap_utils.c | 7 ++++++- source3/nsswitch/winbindd_ads.c | 15 +++++++++++---- 3 files changed, 19 insertions(+), 6 deletions(-) (limited to 'source3') diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c index 48401cc3d8..8c3185ea5e 100644 --- a/source3/libads/ldap.c +++ b/source3/libads/ldap.c @@ -1787,7 +1787,8 @@ ADS_STATUS ads_USN(ADS_STRUCT *ads, uint32 *usn) void *res; status = ads_do_search_retry(ads, "", LDAP_SCOPE_BASE, "(objectclass=*)", attrs, &res); - if (!ADS_ERR_OK(status)) return status; + if (!ADS_ERR_OK(status)) + return status; if (ads_count_replies(ads, res) != 1) { return ADS_ERROR(LDAP_NO_RESULTS_RETURNED); diff --git a/source3/libads/ldap_utils.c b/source3/libads/ldap_utils.c index 1fa9ebfc97..4142bceabc 100644 --- a/source3/libads/ldap_utils.c +++ b/source3/libads/ldap_utils.c @@ -54,15 +54,20 @@ ADS_STATUS ads_do_search_retry(ADS_STRUCT *ads, const char *bind_path, int scope return status; } - if (*res) ads_msgfree(ads, *res); + if (*res) + ads_msgfree(ads, *res); *res = NULL; + DEBUG(3,("Reopening ads connection to realm '%s' after error %s\n", ads->config.realm, ads_errstr(status))); + if (ads->ld) { ldap_unbind(ads->ld); } + ads->ld = NULL; status = ads_connect(ads); + if (!ADS_ERR_OK(status)) { DEBUG(1,("ads_search_retry: failed to reconnect (%s)\n", ads_errstr(status))); diff --git a/source3/nsswitch/winbindd_ads.c b/source3/nsswitch/winbindd_ads.c index c64359a224..ef3f0f8fc2 100644 --- a/source3/nsswitch/winbindd_ads.c +++ b/source3/nsswitch/winbindd_ads.c @@ -787,9 +787,13 @@ static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq) } rc = ads_USN(ads, seq); + if (!ADS_ERR_OK(rc)) { - /* its a dead connection */ - ads_destroy(&ads); + + /* its a dead connection ; don't destroy it + through since ads_USN() has already done + that indirectly */ + domain->private = NULL; } return ads_ntstatus(rc); @@ -910,8 +914,11 @@ static NTSTATUS domain_sid(struct winbindd_domain *domain, DOM_SID *sid) rc = ads_domain_sid(ads, sid); if (!ADS_ERR_OK(rc)) { - /* its a dead connection */ - ads_destroy(&ads); + + /* its a dead connection; don't destroy it though + since that has already been done indirectly + by ads_domain_sid() */ + domain->private = NULL; } -- cgit From 762e7e1dff89cc14b0130fc9a22038b0845630a2 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Mon, 6 Oct 2003 01:24:48 +0000 Subject: split some security related functions in their own files. (no need to include all of smbd files to use some basic sec functions) also minor compile fixes (This used to be commit 66074d3b097d8cf2a231bf08c7f4db62da68189d) --- source3/Makefile.in | 7 +- source3/include/privileges.h | 2 + source3/include/rpc_lsa.h | 6 +- source3/include/talloc.h | 21 ++ source3/lib/privileges.c | 345 +++++++++++++++++++ source3/lib/secace.c | 285 ++++++++++++++++ source3/lib/secacl.c | 118 +++++++ source3/lib/secdesc.c | 522 +++++++++++++++++++++++++++++ source3/lib/talloc.c | 21 -- source3/lib/util_seaccess.c | 129 ------- source3/lib/util_sid.c | 2 +- source3/passdb/pdb_get_set.c | 4 +- source3/rpc_client/cli_lsarpc.c | 6 +- source3/rpc_parse/parse_lsa.c | 43 ++- source3/rpc_parse/parse_rpc.c | 6 +- source3/rpc_parse/parse_sec.c | 727 ---------------------------------------- source3/rpc_server/srv_lsa.c | 2 +- source3/rpc_server/srv_lsa_nt.c | 70 ++-- source3/script/mkproto.awk | 2 +- source3/tdb/tdbback.c | 3 +- 20 files changed, 1376 insertions(+), 945 deletions(-) create mode 100644 source3/lib/privileges.c create mode 100644 source3/lib/secace.c create mode 100644 source3/lib/secacl.c create mode 100644 source3/lib/secdesc.c (limited to 'source3') diff --git a/source3/Makefile.in b/source3/Makefile.in index 0ea2c4411f..57950bebde 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -181,7 +181,8 @@ LIB_OBJ = lib/version.o lib/charcnv.o lib/debug.o lib/fault.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/gencache.o $(TDB_OBJ) \ - lib/module.o lib/ldap_escape.o @CHARSET_STATIC@ + lib/module.o lib/ldap_escape.o @CHARSET_STATIC@ \ + lib/privileges.o lib/secdesc.o lib/secace.o lib/secacl.o LIB_SMBD_OBJ = lib/system_smbd.o lib/util_smbd.o @@ -218,7 +219,7 @@ LIBSMB_OBJ = libsmb/clientgen.o libsmb/cliconnect.o libsmb/clifile.o \ libsmb/clirap.o libsmb/clierror.o libsmb/climessage.o \ libsmb/clireadwrite.o libsmb/clilist.o libsmb/cliprint.o \ libsmb/clitrans.o libsmb/clisecdesc.o libsmb/clidgram.o \ - libsmb/clistr.o \ + libsmb/clistr.o lib/util_seaccess.o \ libsmb/cliquota.o libsmb/clifsinfo.o \ libsmb/smberr.o libsmb/credentials.o libsmb/pwd_cache.o \ libsmb/clioplock.o libsmb/errormap.o libsmb/clirap2.o \ @@ -345,7 +346,7 @@ SMBD_OBJ_SRV = smbd/files.o smbd/chgpasswd.o smbd/connection.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 \ + printing/printfsp.o \ lib/sysquotas.o smbd/change_trust_pw.o smbd/fake_file.o \ smbd/quotas.o smbd/ntquotas.o lib/afs.o \ $(MANGLE_OBJ) @VFS_STATIC@ diff --git a/source3/include/privileges.h b/source3/include/privileges.h index 67d8a2cbcc..b7e1b44c2a 100644 --- a/source3/include/privileges.h +++ b/source3/include/privileges.h @@ -53,6 +53,8 @@ typedef struct LUID_ATTR typedef struct privilege_set { + TALLOC_CTX *mem_ctx; + BOOL ext_ctx; uint32 count; uint32 control; LUID_ATTR *set; diff --git a/source3/include/rpc_lsa.h b/source3/include/rpc_lsa.h index 93bc08a0ce..2064a38056 100644 --- a/source3/include/rpc_lsa.h +++ b/source3/include/rpc_lsa.h @@ -657,7 +657,7 @@ typedef struct lsa_r_enumprivsaccount { uint32 ptr; uint32 count; - PRIVILEGE_SET set; + PRIVILEGE_SET *set; NTSTATUS status; } LSA_R_ENUMPRIVSACCOUNT; @@ -703,7 +703,7 @@ typedef struct lsa_q_addprivs { POLICY_HND pol; /* policy handle */ uint32 count; - PRIVILEGE_SET set; + PRIVILEGE_SET *set; } LSA_Q_ADDPRIVS; typedef struct lsa_r_addprivs @@ -718,7 +718,7 @@ typedef struct lsa_q_removeprivs uint32 allrights; uint32 ptr; uint32 count; - PRIVILEGE_SET set; + PRIVILEGE_SET *set; } LSA_Q_REMOVEPRIVS; typedef struct lsa_r_removeprivs diff --git a/source3/include/talloc.h b/source3/include/talloc.h index 4badddbb88..433b52ec95 100644 --- a/source3/include/talloc.h +++ b/source3/include/talloc.h @@ -30,6 +30,27 @@ /** * talloc allocation pool. All allocated blocks can be freed in one go. **/ + +struct talloc_chunk { + struct talloc_chunk *next; + size_t size; + void *ptr; +}; + +struct talloc_ctx { + struct talloc_chunk *list; + size_t total_alloc_size; + + /** The name recorded for this pool, if any. Should describe + * the purpose for which it was allocated. The string is + * allocated within the pool. **/ + char *name; + + /** Pointer to the next allocate talloc pool, so that we can + * summarize all talloc memory usage. **/ + struct talloc_ctx *next_ctx; +}; + typedef struct talloc_ctx TALLOC_CTX; TALLOC_CTX *talloc_init(char const *fmt, ...) PRINTF_ATTRIBUTE(1, 2); diff --git a/source3/lib/privileges.c b/source3/lib/privileges.c new file mode 100644 index 0000000000..1c23d9e40e --- /dev/null +++ b/source3/lib/privileges.c @@ -0,0 +1,345 @@ +/* + Unix SMB/CIFS implementation. + Privileges handling functions + Copyright (C) Jean François Micouleau 1998-2001 + Copyright (C) Simo Sorce 2002-2003 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +/* defines */ + +#define ALLOC_CHECK(ptr, err, label, str) do { if ((ptr) == NULL) { DEBUG(0, ("%s: out of memory!\n", str)); err = NT_STATUS_NO_MEMORY; goto label; } } while(0) +#define NTSTATUS_CHECK(err, label, str1, str2) do { if (!NT_STATUS_IS_OK(err)) { DEBUG(0, ("%s: %s failed!\n", str1, str2)); } } while(0) + +/**************************************************************************** + Check if a user is a mapped group. + + This function will check if the group SID is mapped onto a + system managed gid or onto a winbind manged sid. + In the first case it will be threated like a mapped group + and the backend should take the member list with a getgrgid + and ignore any user that have been possibly set into the group + object. + + In the second case, the group is a fully SAM managed group + served back to the system through winbind. In this case the + members of a Local group are "unrolled" to cope with the fact + that unix cannot contain groups inside groups. + The backend MUST never call any getgr* / getpw* function or + loops with winbind may happen. + ****************************************************************************/ + +#if 0 +NTSTATUS is_mapped_group(BOOL *mapped, const DOM_SID *sid) +{ + NTSTATUS result; + gid_t id; + + /* look if mapping exist, do not make idmap alloc an uid if SID is not found */ + result = idmap_get_gid_from_sid(&id, sid, False); + if (NT_STATUS_IS_OK(result)) { + *mapped = gid_is_in_winbind_range(id); + } else { + *mapped = False; + } + + return result; +} +#endif + +/**************************************************************************** + duplicate alloc luid_attr + ****************************************************************************/ +NTSTATUS dupalloc_luid_attr(TALLOC_CTX *mem_ctx, LUID_ATTR **new_la, LUID_ATTR *old_la) +{ + NTSTATUS ret; + + *new_la = (LUID_ATTR *)talloc(mem_ctx, sizeof(LUID_ATTR)); + ALLOC_CHECK(new_la, ret, done, "dupalloc_luid_attr"); + + (*new_la)->luid.high = old_la->luid.high; + (*new_la)->luid.low = old_la->luid.low; + (*new_la)->attr = old_la->attr; + + ret = NT_STATUS_OK; + +done: + return ret; +} + +/**************************************************************************** + initialise a privilege list + ****************************************************************************/ +NTSTATUS init_privilege(PRIVILEGE_SET **priv_set) +{ + NTSTATUS ret; + TALLOC_CTX *mem_ctx = talloc_init("privilege set"); + ALLOC_CHECK(mem_ctx, ret, done, "init_privilege"); + + *priv_set = talloc_zero(mem_ctx, sizeof(PRIVILEGE_SET)); + ALLOC_CHECK(*priv_set, ret, done, "init_privilege"); + + (*priv_set)->mem_ctx = mem_ctx; + + ret = NT_STATUS_OK; + +done: + return ret; +} + +NTSTATUS init_priv_with_ctx(TALLOC_CTX *mem_ctx, PRIVILEGE_SET **priv_set) +{ + NTSTATUS ret; + + *priv_set = talloc_zero(mem_ctx, sizeof(PRIVILEGE_SET)); + ALLOC_CHECK(*priv_set, ret, done, "init_privilege"); + + (*priv_set)->mem_ctx = mem_ctx; + (*priv_set)->ext_ctx = True; + + ret = NT_STATUS_OK; + +done: + return ret; +} + +void reset_privilege(PRIVILEGE_SET *priv_set) +{ + priv_set->count = 0; + priv_set->control = 0; + priv_set->set = NULL; +} + +void destroy_privilege(PRIVILEGE_SET **priv_set) +{ + reset_privilege(*priv_set); + if (!((*priv_set)->ext_ctx)) + /* mem_ctx is local, destroy it */ + talloc_destroy((*priv_set)->mem_ctx); + *priv_set = NULL; +} + +/**************************************************************************** + add a privilege to a privilege array + ****************************************************************************/ +NTSTATUS add_privilege(PRIVILEGE_SET *priv_set, LUID_ATTR set) +{ + NTSTATUS ret; + LUID_ATTR *new_set; + + /* check if the privilege is not already in the list */ + if (NT_STATUS_IS_OK(check_priv_in_privilege(priv_set, set))) + return NT_STATUS_UNSUCCESSFUL; + + /* we can allocate memory to add the new privilege */ + + new_set = (LUID_ATTR *)talloc_realloc(priv_set->mem_ctx, priv_set->set, (priv_set->count + 1) * (sizeof(LUID_ATTR))); + ALLOC_CHECK(new_set, ret, done, "add_privilege"); + + new_set[priv_set->count].luid.high = set.luid.high; + new_set[priv_set->count].luid.low = set.luid.low; + new_set[priv_set->count].attr = set.attr; + + priv_set->count++; + priv_set->set = new_set; + + ret = NT_STATUS_OK; + +done: + return ret; +} + +/**************************************************************************** + add all the privileges to a privilege array + ****************************************************************************/ +NTSTATUS add_all_privilege(PRIVILEGE_SET *priv_set) +{ + NTSTATUS result = NT_STATUS_OK; + LUID_ATTR set; + + set.attr = 0; + set.luid.high = 0; + + /* TODO: set a proper list of privileges */ + set.luid.low = SE_PRIV_ADD_USERS; + result = add_privilege(priv_set, set); + NTSTATUS_CHECK(result, done, "add_all_privilege", "add_privilege"); + + set.luid.low = SE_PRIV_ADD_MACHINES; + result = add_privilege(priv_set, set); + NTSTATUS_CHECK(result, done, "add_all_privilege", "add_privilege"); + + set.luid.low = SE_PRIV_PRINT_OPERATOR; + result = add_privilege(priv_set, set); + NTSTATUS_CHECK(result, done, "add_all_privilege", "add_privilege"); + +done: + return result; +} + +/**************************************************************************** + check if the privilege list is empty + ****************************************************************************/ +NTSTATUS check_empty_privilege(PRIVILEGE_SET *priv_set) +{ + if (!priv_set) + return NT_STATUS_INVALID_PARAMETER; + + if (priv_set->count == 0) + return NT_STATUS_OK; + + return NT_STATUS_UNSUCCESSFUL; +} + +/**************************************************************************** + check if the privilege is in the privilege list + ****************************************************************************/ +NTSTATUS check_priv_in_privilege(PRIVILEGE_SET *priv_set, LUID_ATTR set) +{ + int i; + + if (!priv_set) + return NT_STATUS_INVALID_PARAMETER; + + /* if the list is empty, obviously we can't have it */ + if (NT_STATUS_IS_OK(check_empty_privilege(priv_set))) + return NT_STATUS_UNSUCCESSFUL; + + for (i = 0; i < priv_set->count; i++) { + LUID_ATTR *cur_set; + + cur_set = &priv_set->set[i]; + /* check only the low and high part. Checking the attr field has no meaning */ + if ( (cur_set->luid.low == set.luid.low) && + (cur_set->luid.high == set.luid.high) ) { + return NT_STATUS_OK; + } + } + + return NT_STATUS_UNSUCCESSFUL; +} + +/**************************************************************************** + remove a privilege from a privilege array + ****************************************************************************/ +NTSTATUS remove_privilege(PRIVILEGE_SET *priv_set, LUID_ATTR set) +{ + NTSTATUS ret; + LUID_ATTR *new_set; + LUID_ATTR *old_set; + int i,j; + + if (!priv_set) + return NT_STATUS_INVALID_PARAMETER; + + /* check if the privilege is in the list */ + if (!NT_STATUS_IS_OK(check_priv_in_privilege(priv_set, set))) + return NT_STATUS_UNSUCCESSFUL; + + /* special case if it's the only privilege in the list */ + if (priv_set->count == 1) { + reset_privilege(priv_set); + return NT_STATUS_OK; + } + + /* + * the privilege is there, create a new list, + * and copy the other privileges + */ + + old_set = priv_set->set; + + new_set = (LUID_ATTR *)talloc(priv_set->mem_ctx, (priv_set->count - 1) * (sizeof(LUID_ATTR))); + ALLOC_CHECK(new_set, ret, done, "remove_privilege"); + + for (i=0, j=0; i < priv_set->count; i++) { + if ( (old_set[i].luid.low == set.luid.low) && + (old_set[i].luid.high == set.luid.high) ) { + continue; + } + + new_set[j].luid.low = old_set[i].luid.low; + new_set[j].luid.high = old_set[i].luid.high; + new_set[j].attr = old_set[i].attr; + + j++; + } + + if (j != priv_set->count - 1) { + DEBUG(0,("remove_privilege: mismatch ! difference is not -1\n")); + DEBUGADD(0,("old count:%d, new count:%d\n", priv_set->count, j)); + return NT_STATUS_INTERNAL_ERROR; + } + + /* ok everything is fine */ + + priv_set->count--; + priv_set->set = new_set; + + ret = NT_STATUS_OK; + +done: + return ret; +} + +/**************************************************************************** + duplicates a privilege array + the new privilege set must be passed inited + (use init_privilege or init_priv_with_ctx) + ****************************************************************************/ +NTSTATUS dup_priv_set(PRIVILEGE_SET *new_priv_set, PRIVILEGE_SET *priv_set) +{ + NTSTATUS ret; + LUID_ATTR *new_set; + LUID_ATTR *old_set; + int i; + + if (!new_priv_set || !priv_set) + return NT_STATUS_INVALID_PARAMETER; + + /* special case if there are no privileges in the list */ + if (priv_set->count == 0) { + return NT_STATUS_OK; + } + + /* + * create a new list, + * and copy the other privileges + */ + + old_set = priv_set->set; + + new_set = (LUID_ATTR *)talloc(new_priv_set->mem_ctx, (priv_set->count - 1) * (sizeof(LUID_ATTR))); + ALLOC_CHECK(new_set, ret, done, "dup_priv_set"); + + for (i=0; i < priv_set->count; i++) { + + new_set[i].luid.low = old_set[i].luid.low; + new_set[i].luid.high = old_set[i].luid.high; + new_set[i].attr = old_set[i].attr; + } + + new_priv_set->count = priv_set->count; + new_priv_set->control = priv_set->control; + new_priv_set->set = new_set; + + ret = NT_STATUS_OK; + +done: + return ret; +} diff --git a/source3/lib/secace.c b/source3/lib/secace.c new file mode 100644 index 0000000000..6769f1288a --- /dev/null +++ b/source3/lib/secace.c @@ -0,0 +1,285 @@ +/* + * Unix SMB/Netbios implementation. + * SEC_ACE handling functions + * Copyright (C) Andrew Tridgell 1992-1998, + * Copyright (C) Jeremy R. Allison 1995-2003. + * Copyright (C) Luke Kenneth Casson Leighton 1996-1998, + * Copyright (C) Paul Ashton 1997-1998. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "includes.h" + +/******************************************************************* + Check if ACE has OBJECT type. +********************************************************************/ + +BOOL sec_ace_object(uint8 type) +{ + if (type == SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT || + type == SEC_ACE_TYPE_ACCESS_DENIED_OBJECT || + type == SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT || + type == SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT) { + return True; + } + return False; +} + +/******************************************************************* + copy a SEC_ACE structure. +********************************************************************/ +void sec_ace_copy(SEC_ACE *ace_dest, SEC_ACE *ace_src) +{ + ace_dest->type = ace_src->type; + ace_dest->flags = ace_src->flags; + ace_dest->size = ace_src->size; + ace_dest->info.mask = ace_src->info.mask; + ace_dest->obj_flags = ace_src->obj_flags; + memcpy(&ace_dest->obj_guid, &ace_src->obj_guid, GUID_SIZE); + memcpy(&ace_dest->inh_guid, &ace_src->inh_guid, GUID_SIZE); + sid_copy(&ace_dest->trustee, &ace_src->trustee); +} + +/******************************************************************* + Sets up a SEC_ACE structure. +********************************************************************/ + +void init_sec_ace(SEC_ACE *t, DOM_SID *sid, uint8 type, SEC_ACCESS mask, uint8 flag) +{ + t->type = type; + t->flags = flag; + t->size = sid_size(sid) + 8; + t->info = mask; + + ZERO_STRUCTP(&t->trustee); + sid_copy(&t->trustee, sid); +} + +/******************************************************************* + adds new SID with its permissions to ACE list +********************************************************************/ + +NTSTATUS sec_ace_add_sid(TALLOC_CTX *ctx, SEC_ACE **new, SEC_ACE *old, unsigned *num, DOM_SID *sid, uint32 mask) +{ + unsigned int i = 0; + + if (!ctx || !new || !old || !sid || !num) return NT_STATUS_INVALID_PARAMETER; + + *num += 1; + + if((new[0] = (SEC_ACE *) talloc_zero(ctx, (*num) * sizeof(SEC_ACE))) == 0) + return NT_STATUS_NO_MEMORY; + + for (i = 0; i < *num - 1; i ++) + sec_ace_copy(&(*new)[i], &old[i]); + + (*new)[i].type = 0; + (*new)[i].flags = 0; + (*new)[i].size = SEC_ACE_HEADER_SIZE + sid_size(sid); + (*new)[i].info.mask = mask; + sid_copy(&(*new)[i].trustee, sid); + return NT_STATUS_OK; +} + +/******************************************************************* + modify SID's permissions at ACL +********************************************************************/ + +NTSTATUS sec_ace_mod_sid(SEC_ACE *ace, size_t num, DOM_SID *sid, uint32 mask) +{ + unsigned int i = 0; + + if (!ace || !sid) return NT_STATUS_INVALID_PARAMETER; + + for (i = 0; i < num; i ++) { + if (sid_compare(&ace[i].trustee, sid) == 0) { + ace[i].info.mask = mask; + return NT_STATUS_OK; + } + } + return NT_STATUS_NOT_FOUND; +} + +/******************************************************************* + delete SID from ACL +********************************************************************/ + +NTSTATUS sec_ace_del_sid(TALLOC_CTX *ctx, SEC_ACE **new, SEC_ACE *old, uint32 *num, DOM_SID *sid) +{ + unsigned int i = 0; + unsigned int n_del = 0; + + if (!ctx || !new || !old || !sid || !num) return NT_STATUS_INVALID_PARAMETER; + + if((new[0] = (SEC_ACE *) talloc_zero(ctx, (*num) * sizeof(SEC_ACE))) == 0) + return NT_STATUS_NO_MEMORY; + + for (i = 0; i < *num; i ++) { + if (sid_compare(&old[i].trustee, sid) != 0) + sec_ace_copy(&(*new)[i], &old[i]); + else + n_del ++; + } + if (n_del == 0) + return NT_STATUS_NOT_FOUND; + else { + *num -= n_del; + return NT_STATUS_OK; + } +} + +/******************************************************************* + Compares two SEC_ACE structures +********************************************************************/ + +BOOL sec_ace_equal(SEC_ACE *s1, SEC_ACE *s2) +{ + /* Trivial case */ + + if (!s1 && !s2) return True; + + /* Check top level stuff */ + + if (s1->type != s2->type || s1->flags != s2->flags || + s1->info.mask != s2->info.mask) { + return False; + } + + /* Check SID */ + + if (!sid_equal(&s1->trustee, &s2->trustee)) { + return False; + } + + return True; +} + +int nt_ace_inherit_comp( SEC_ACE *a1, SEC_ACE *a2) +{ + int a1_inh = a1->flags & SEC_ACE_FLAG_INHERITED_ACE; + int a2_inh = a2->flags & SEC_ACE_FLAG_INHERITED_ACE; + + if (a1_inh == a2_inh) + return 0; + + if (!a1_inh && a2_inh) + return -1; + return 1; +} + +/******************************************************************* + Comparison function to apply the order explained below in a group. +*******************************************************************/ + +int nt_ace_canon_comp( SEC_ACE *a1, SEC_ACE *a2) +{ + if ((a1->type == SEC_ACE_TYPE_ACCESS_DENIED) && + (a2->type != SEC_ACE_TYPE_ACCESS_DENIED)) + return -1; + + if ((a2->type == SEC_ACE_TYPE_ACCESS_DENIED) && + (a1->type != SEC_ACE_TYPE_ACCESS_DENIED)) + return 1; + + /* Both access denied or access allowed. */ + + /* 1. ACEs that apply to the object itself */ + + if (!(a1->flags & SEC_ACE_FLAG_INHERIT_ONLY) && + (a2->flags & SEC_ACE_FLAG_INHERIT_ONLY)) + return -1; + else if (!(a2->flags & SEC_ACE_FLAG_INHERIT_ONLY) && + (a1->flags & SEC_ACE_FLAG_INHERIT_ONLY)) + return 1; + + /* 2. ACEs that apply to a subobject of the object, such as + * a property set or property. */ + + if (a1->flags & (SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT) && + !(a2->flags & (SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT))) + return -1; + else if (a2->flags & (SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT) && + !(a1->flags & (SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT))) + return 1; + + return 0; +} + +/******************************************************************* + Functions to convert a SEC_DESC ACE DACL list into canonical order. + JRA. + +--- from http://msdn.microsoft.com/library/default.asp?url=/library/en-us/security/security/order_of_aces_in_a_dacl.asp + +The following describes the preferred order: + + To ensure that noninherited ACEs have precedence over inherited ACEs, + place all noninherited ACEs in a group before any inherited ACEs. + This ordering ensures, for example, that a noninherited access-denied ACE + is enforced regardless of any inherited ACE that allows access. + + Within the groups of noninherited ACEs and inherited ACEs, order ACEs according to ACE type, as the following shows: + 1. Access-denied ACEs that apply to the object itself + 2. Access-denied ACEs that apply to a subobject of the object, such as a property set or property + 3. Access-allowed ACEs that apply to the object itself + 4. Access-allowed ACEs that apply to a subobject of the object" + +********************************************************************/ + +void dacl_sort_into_canonical_order(SEC_ACE *srclist, unsigned int num_aces) +{ + unsigned int i; + + if (!srclist || num_aces == 0) + return; + + /* Sort so that non-inherited ACE's come first. */ + qsort( srclist, num_aces, sizeof(srclist[0]), QSORT_CAST nt_ace_inherit_comp); + + /* Find the boundary between non-inherited ACEs. */ + for (i = 0; i < num_aces; i++ ) { + SEC_ACE *curr_ace = &srclist[i]; + + if (curr_ace->flags & SEC_ACE_FLAG_INHERITED_ACE) + break; + } + + /* i now points at entry number of the first inherited ACE. */ + + /* Sort the non-inherited ACEs. */ + if (i) + qsort( srclist, i, sizeof(srclist[0]), QSORT_CAST nt_ace_canon_comp); + + /* Now sort the inherited ACEs. */ + if (num_aces - i) + qsort( &srclist[i], num_aces - i, sizeof(srclist[0]), QSORT_CAST nt_ace_canon_comp); +} + +/******************************************************************* + Check if this ACE has a SID in common with the token. +********************************************************************/ + +BOOL token_sid_in_ace(const NT_USER_TOKEN *token, const SEC_ACE *ace) +{ + size_t i; + + for (i = 0; i < token->num_sids; i++) { + if (sid_equal(&ace->trustee, &token->user_sids[i])) + return True; + } + + return False; +} diff --git a/source3/lib/secacl.c b/source3/lib/secacl.c new file mode 100644 index 0000000000..756685a821 --- /dev/null +++ b/source3/lib/secacl.c @@ -0,0 +1,118 @@ +/* + * Unix SMB/Netbios implementation. + * SEC_ACL handling routines + * Copyright (C) Andrew Tridgell 1992-1998, + * Copyright (C) Jeremy R. Allison 1995-2003. + * Copyright (C) Luke Kenneth Casson Leighton 1996-1998, + * Copyright (C) Paul Ashton 1997-1998. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "includes.h" + +/******************************************************************* + Create a SEC_ACL structure. +********************************************************************/ + +SEC_ACL *make_sec_acl(TALLOC_CTX *ctx, uint16 revision, int num_aces, SEC_ACE *ace_list) +{ + SEC_ACL *dst; + int i; + + if((dst = (SEC_ACL *)talloc_zero(ctx,sizeof(SEC_ACL))) == NULL) + return NULL; + + dst->revision = revision; + dst->num_aces = num_aces; + dst->size = SEC_ACL_HEADER_SIZE; + + /* Now we need to return a non-NULL address for the ace list even + if the number of aces required is zero. This is because there + is a distinct difference between a NULL ace and an ace with zero + entries in it. This is achieved by checking that num_aces is a + positive number. */ + + if ((num_aces) && + ((dst->ace = (SEC_ACE *)talloc(ctx, sizeof(SEC_ACE) * num_aces)) + == NULL)) { + return NULL; + } + + for (i = 0; i < num_aces; i++) { + dst->ace[i] = ace_list[i]; /* Structure copy. */ + dst->size += ace_list[i].size; + } + + return dst; +} + +/******************************************************************* + Duplicate a SEC_ACL structure. +********************************************************************/ + +SEC_ACL *dup_sec_acl(TALLOC_CTX *ctx, SEC_ACL *src) +{ + if(src == NULL) + return NULL; + + return make_sec_acl(ctx, src->revision, src->num_aces, src->ace); +} + +/******************************************************************* + Compares two SEC_ACL structures +********************************************************************/ + +BOOL sec_acl_equal(SEC_ACL *s1, SEC_ACL *s2) +{ + unsigned int i, j; + + /* Trivial cases */ + + if (!s1 && !s2) return True; + if (!s1 || !s2) return False; + + /* Check top level stuff */ + + if (s1->revision != s2->revision) { + DEBUG(10, ("sec_acl_equal(): revision differs (%d != %d)\n", + s1->revision, s2->revision)); + return False; + } + + if (s1->num_aces != s2->num_aces) { + DEBUG(10, ("sec_acl_equal(): num_aces differs (%d != %d)\n", + s1->revision, s2->revision)); + return False; + } + + /* The ACEs could be in any order so check each ACE in s1 against + each ACE in s2. */ + + for (i = 0; i < s1->num_aces; i++) { + BOOL found = False; + + for (j = 0; j < s2->num_aces; j++) { + if (sec_ace_equal(&s1->ace[i], &s2->ace[j])) { + found = True; + break; + } + } + + if (!found) return False; + } + + return True; +} diff --git a/source3/lib/secdesc.c b/source3/lib/secdesc.c new file mode 100644 index 0000000000..411185dbfa --- /dev/null +++ b/source3/lib/secdesc.c @@ -0,0 +1,522 @@ +/* + * Unix SMB/Netbios implementation. + * SEC_DESC handling functions + * Copyright (C) Andrew Tridgell 1992-1998, + * Copyright (C) Jeremy R. Allison 1995-2003. + * Copyright (C) Luke Kenneth Casson Leighton 1996-1998, + * Copyright (C) Paul Ashton 1997-1998. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "includes.h" + +/******************************************************************* + Works out the linearization size of a SEC_DESC. +********************************************************************/ + +size_t sec_desc_size(SEC_DESC *psd) +{ + size_t offset; + + if (!psd) return 0; + + offset = SEC_DESC_HEADER_SIZE; + + /* don't align */ + + if (psd->owner_sid != NULL) + offset += sid_size(psd->owner_sid); + + if (psd->grp_sid != NULL) + offset += sid_size(psd->grp_sid); + + if (psd->sacl != NULL) + offset += psd->sacl->size; + + if (psd->dacl != NULL) + offset += psd->dacl->size; + + return offset; +} + +/******************************************************************* + Compares two SEC_DESC structures +********************************************************************/ + +BOOL sec_desc_equal(SEC_DESC *s1, SEC_DESC *s2) +{ + /* Trivial case */ + + if (!s1 && !s2) { + goto done; + } + + /* Check top level stuff */ + + if (s1->revision != s2->revision) { + DEBUG(10, ("sec_desc_equal(): revision differs (%d != %d)\n", + s1->revision, s2->revision)); + return False; + } + + if (s1->type!= s2->type) { + DEBUG(10, ("sec_desc_equal(): type differs (%d != %d)\n", + s1->type, s2->type)); + return False; + } + + /* Check owner and group */ + + if (!sid_equal(s1->owner_sid, s2->owner_sid)) { + fstring str1, str2; + + sid_to_string(str1, s1->owner_sid); + sid_to_string(str2, s2->owner_sid); + + DEBUG(10, ("sec_desc_equal(): owner differs (%s != %s)\n", + str1, str2)); + return False; + } + + if (!sid_equal(s1->grp_sid, s2->grp_sid)) { + fstring str1, str2; + + sid_to_string(str1, s1->grp_sid); + sid_to_string(str2, s2->grp_sid); + + DEBUG(10, ("sec_desc_equal(): group differs (%s != %s)\n", + str1, str2)); + return False; + } + + /* Check ACLs present in one but not the other */ + + if ((s1->dacl && !s2->dacl) || (!s1->dacl && s2->dacl) || + (s1->sacl && !s2->sacl) || (!s1->sacl && s2->sacl)) { + DEBUG(10, ("sec_desc_equal(): dacl or sacl not present\n")); + return False; + } + + /* Sigh - we have to do it the hard way by iterating over all + the ACEs in the ACLs */ + + if (!sec_acl_equal(s1->dacl, s2->dacl) || + !sec_acl_equal(s1->sacl, s2->sacl)) { + DEBUG(10, ("sec_desc_equal(): dacl/sacl list not equal\n")); + return False; + } + + done: + DEBUG(10, ("sec_desc_equal(): secdescs are identical\n")); + return True; +} + +/******************************************************************* + Merge part of security descriptor old_sec in to the empty sections of + security descriptor new_sec. +********************************************************************/ + +SEC_DESC_BUF *sec_desc_merge(TALLOC_CTX *ctx, SEC_DESC_BUF *new_sdb, SEC_DESC_BUF *old_sdb) +{ + DOM_SID *owner_sid, *group_sid; + SEC_DESC_BUF *return_sdb; + SEC_ACL *dacl, *sacl; + SEC_DESC *psd = NULL; + uint16 secdesc_type; + size_t secdesc_size; + + /* Copy over owner and group sids. There seems to be no flag for + this so just check the pointer values. */ + + owner_sid = new_sdb->sec->owner_sid ? new_sdb->sec->owner_sid : + old_sdb->sec->owner_sid; + + group_sid = new_sdb->sec->grp_sid ? new_sdb->sec->grp_sid : + old_sdb->sec->grp_sid; + + secdesc_type = new_sdb->sec->type; + + /* Ignore changes to the system ACL. This has the effect of making + changes through the security tab audit button not sticking. + Perhaps in future Samba could implement these settings somehow. */ + + sacl = NULL; + secdesc_type &= ~SEC_DESC_SACL_PRESENT; + + /* Copy across discretionary ACL */ + + if (secdesc_type & SEC_DESC_DACL_PRESENT) { + dacl = new_sdb->sec->dacl; + } else { + dacl = old_sdb->sec->dacl; + } + + /* Create new security descriptor from bits */ + + psd = make_sec_desc(ctx, new_sdb->sec->revision, secdesc_type, + owner_sid, group_sid, sacl, dacl, &secdesc_size); + + return_sdb = make_sec_desc_buf(ctx, secdesc_size, psd); + + return(return_sdb); +} + +/******************************************************************* + Creates a SEC_DESC structure +********************************************************************/ + +SEC_DESC *make_sec_desc(TALLOC_CTX *ctx, uint16 revision, uint16 type, + DOM_SID *owner_sid, DOM_SID *grp_sid, + SEC_ACL *sacl, SEC_ACL *dacl, size_t *sd_size) +{ + SEC_DESC *dst; + uint32 offset = 0; + + *sd_size = 0; + + if(( dst = (SEC_DESC *)talloc_zero(ctx, sizeof(SEC_DESC))) == NULL) + return NULL; + + dst->revision = revision; + dst->type = type; + + if (sacl) + dst->type |= SEC_DESC_SACL_PRESENT; + if (dacl) + dst->type |= SEC_DESC_DACL_PRESENT; + + dst->off_owner_sid = 0; + dst->off_grp_sid = 0; + dst->off_sacl = 0; + dst->off_dacl = 0; + + if(owner_sid && ((dst->owner_sid = sid_dup_talloc(ctx,owner_sid)) == NULL)) + goto error_exit; + + if(grp_sid && ((dst->grp_sid = sid_dup_talloc(ctx,grp_sid)) == NULL)) + goto error_exit; + + if(sacl && ((dst->sacl = dup_sec_acl(ctx, sacl)) == NULL)) + goto error_exit; + + if(dacl && ((dst->dacl = dup_sec_acl(ctx, dacl)) == NULL)) + goto error_exit; + + offset = SEC_DESC_HEADER_SIZE; + + /* + * Work out the linearization sizes. + */ + + if (dst->sacl != NULL) { + dst->off_sacl = offset; + offset += dst->sacl->size; + } + if (dst->dacl != NULL) { + dst->off_dacl = offset; + offset += dst->dacl->size; + } + + if (dst->owner_sid != NULL) { + dst->off_owner_sid = offset; + offset += sid_size(dst->owner_sid); + } + + if (dst->grp_sid != NULL) { + dst->off_grp_sid = offset; + offset += sid_size(dst->grp_sid); + } + + *sd_size = (size_t)offset; + return dst; + +error_exit: + + *sd_size = 0; + return NULL; +} + +/******************************************************************* + Duplicate a SEC_DESC structure. +********************************************************************/ + +SEC_DESC *dup_sec_desc(TALLOC_CTX *ctx, const SEC_DESC *src) +{ + size_t dummy; + + if(src == NULL) + return NULL; + + return make_sec_desc( ctx, src->revision, src->type, + src->owner_sid, src->grp_sid, src->sacl, + src->dacl, &dummy); +} + +/******************************************************************* + Creates a SEC_DESC structure with typical defaults. +********************************************************************/ + +SEC_DESC *make_standard_sec_desc(TALLOC_CTX *ctx, DOM_SID *owner_sid, DOM_SID *grp_sid, + SEC_ACL *dacl, size_t *sd_size) +{ + return make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, + owner_sid, grp_sid, NULL, dacl, sd_size); +} + +/******************************************************************* + Creates a SEC_DESC_BUF structure. +********************************************************************/ + +SEC_DESC_BUF *make_sec_desc_buf(TALLOC_CTX *ctx, size_t len, SEC_DESC *sec_desc) +{ + SEC_DESC_BUF *dst; + + if((dst = (SEC_DESC_BUF *)talloc_zero(ctx, sizeof(SEC_DESC_BUF))) == NULL) + return NULL; + + /* max buffer size (allocated size) */ + dst->max_len = (uint32)len; + dst->len = (uint32)len; + + if(sec_desc && ((dst->sec = dup_sec_desc(ctx, sec_desc)) == NULL)) { + return NULL; + } + + dst->ptr = 0x1; + + return dst; +} + +/******************************************************************* + Duplicates a SEC_DESC_BUF structure. +********************************************************************/ + +SEC_DESC_BUF *dup_sec_desc_buf(TALLOC_CTX *ctx, SEC_DESC_BUF *src) +{ + if(src == NULL) + return NULL; + + return make_sec_desc_buf( ctx, src->len, src->sec); +} + +/******************************************************************* + Add a new SID with its permissions to SEC_DESC. +********************************************************************/ + +NTSTATUS sec_desc_add_sid(TALLOC_CTX *ctx, SEC_DESC **psd, DOM_SID *sid, uint32 mask, size_t *sd_size) +{ + SEC_DESC *sd = 0; + SEC_ACL *dacl = 0; + SEC_ACE *ace = 0; + NTSTATUS status; + + *sd_size = 0; + + if (!ctx || !psd || !sid || !sd_size) + return NT_STATUS_INVALID_PARAMETER; + + status = sec_ace_add_sid(ctx, &ace, psd[0]->dacl->ace, &psd[0]->dacl->num_aces, sid, mask); + + if (!NT_STATUS_IS_OK(status)) + return status; + + if (!(dacl = make_sec_acl(ctx, psd[0]->dacl->revision, psd[0]->dacl->num_aces, ace))) + return NT_STATUS_UNSUCCESSFUL; + + if (!(sd = make_sec_desc(ctx, psd[0]->revision, psd[0]->type, psd[0]->owner_sid, + psd[0]->grp_sid, psd[0]->sacl, dacl, sd_size))) + return NT_STATUS_UNSUCCESSFUL; + + *psd = sd; + sd = 0; + return NT_STATUS_OK; +} + +/******************************************************************* + Modify a SID's permissions in a SEC_DESC. +********************************************************************/ + +NTSTATUS sec_desc_mod_sid(SEC_DESC *sd, DOM_SID *sid, uint32 mask) +{ + NTSTATUS status; + + if (!sd || !sid) + return NT_STATUS_INVALID_PARAMETER; + + status = sec_ace_mod_sid(sd->dacl->ace, sd->dacl->num_aces, sid, mask); + + if (!NT_STATUS_IS_OK(status)) + return status; + + return NT_STATUS_OK; +} + +/******************************************************************* + Delete a SID from a SEC_DESC. +********************************************************************/ + +NTSTATUS sec_desc_del_sid(TALLOC_CTX *ctx, SEC_DESC **psd, DOM_SID *sid, size_t *sd_size) +{ + SEC_DESC *sd = 0; + SEC_ACL *dacl = 0; + SEC_ACE *ace = 0; + NTSTATUS status; + + *sd_size = 0; + + if (!ctx || !psd[0] || !sid || !sd_size) + return NT_STATUS_INVALID_PARAMETER; + + status = sec_ace_del_sid(ctx, &ace, psd[0]->dacl->ace, &psd[0]->dacl->num_aces, sid); + + if (!NT_STATUS_IS_OK(status)) + return status; + + if (!(dacl = make_sec_acl(ctx, psd[0]->dacl->revision, psd[0]->dacl->num_aces, ace))) + return NT_STATUS_UNSUCCESSFUL; + + if (!(sd = make_sec_desc(ctx, psd[0]->revision, psd[0]->type, psd[0]->owner_sid, + psd[0]->grp_sid, psd[0]->sacl, dacl, sd_size))) + return NT_STATUS_UNSUCCESSFUL; + + *psd = sd; + sd = 0; + return NT_STATUS_OK; +} + +/* Create a child security descriptor using another security descriptor as + the parent container. This child object can either be a container or + non-container object. */ + +SEC_DESC_BUF *se_create_child_secdesc(TALLOC_CTX *ctx, SEC_DESC *parent_ctr, + BOOL child_container) +{ + SEC_DESC_BUF *sdb; + SEC_DESC *sd; + SEC_ACL *new_dacl, *the_acl; + SEC_ACE *new_ace_list = NULL; + unsigned int new_ace_list_ndx = 0, i; + size_t size; + + /* Currently we only process the dacl when creating the child. The + sacl should also be processed but this is left out as sacls are + not implemented in Samba at the moment.*/ + + the_acl = parent_ctr->dacl; + + if (!(new_ace_list = talloc(ctx, sizeof(SEC_ACE) * the_acl->num_aces))) + return NULL; + + for (i = 0; the_acl && i < the_acl->num_aces; i++) { + SEC_ACE *ace = &the_acl->ace[i]; + SEC_ACE *new_ace = &new_ace_list[new_ace_list_ndx]; + uint8 new_flags = 0; + BOOL inherit = False; + fstring sid_str; + + /* The OBJECT_INHERIT_ACE flag causes the ACE to be + inherited by non-container children objects. Container + children objects will inherit it as an INHERIT_ONLY + ACE. */ + + if (ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) { + + if (!child_container) { + new_flags |= SEC_ACE_FLAG_OBJECT_INHERIT; + } else { + new_flags |= SEC_ACE_FLAG_INHERIT_ONLY; + } + + inherit = True; + } + + /* The CONAINER_INHERIT_ACE flag means all child container + objects will inherit and use the ACE. */ + + if (ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) { + if (!child_container) { + inherit = False; + } else { + new_flags |= SEC_ACE_FLAG_CONTAINER_INHERIT; + } + } + + /* The INHERIT_ONLY_ACE is not used by the se_access_check() + function for the parent container, but is inherited by + all child objects as a normal ACE. */ + + if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) { + /* Move along, nothing to see here */ + } + + /* The SEC_ACE_FLAG_NO_PROPAGATE_INHERIT flag means the ACE + is inherited by child objects but not grandchildren + objects. We clear the object inherit and container + inherit flags in the inherited ACE. */ + + if (ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) { + new_flags &= ~(SEC_ACE_FLAG_OBJECT_INHERIT | + SEC_ACE_FLAG_CONTAINER_INHERIT); + } + + /* Add ACE to ACE list */ + + if (!inherit) + continue; + + init_sec_access(&new_ace->info, ace->info.mask); + init_sec_ace(new_ace, &ace->trustee, ace->type, + new_ace->info, new_flags); + + sid_to_string(sid_str, &ace->trustee); + + DEBUG(5, ("se_create_child_secdesc(): %s:%d/0x%02x/0x%08x " + " inherited as %s:%d/0x%02x/0x%08x\n", sid_str, + ace->type, ace->flags, ace->info.mask, + sid_str, new_ace->type, new_ace->flags, + new_ace->info.mask)); + + new_ace_list_ndx++; + } + + /* Create child security descriptor to return */ + + new_dacl = make_sec_acl(ctx, ACL_REVISION, new_ace_list_ndx, new_ace_list); + + /* Use the existing user and group sids. I don't think this is + correct. Perhaps the user and group should be passed in as + parameters by the caller? */ + + sd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, + parent_ctr->owner_sid, + parent_ctr->grp_sid, + parent_ctr->sacl, + new_dacl, &size); + + sdb = make_sec_desc_buf(ctx, size, sd); + + return sdb; +} + +/******************************************************************* + Sets up a SEC_ACCESS structure. +********************************************************************/ + +void init_sec_access(SEC_ACCESS *t, uint32 mask) +{ + t->mask = mask; +} + diff --git a/source3/lib/talloc.c b/source3/lib/talloc.c index b6c8b2efdf..485dc28f31 100644 --- a/source3/lib/talloc.c +++ b/source3/lib/talloc.c @@ -54,27 +54,6 @@ #include "includes.h" -struct talloc_chunk { - struct talloc_chunk *next; - size_t size; - void *ptr; -}; - - -struct talloc_ctx { - struct talloc_chunk *list; - size_t total_alloc_size; - - /** The name recorded for this pool, if any. Should describe - * the purpose for which it was allocated. The string is - * allocated within the pool. **/ - char *name; - - /** Pointer to the next allocate talloc pool, so that we can - * summarize all talloc memory usage. **/ - struct talloc_ctx *next_ctx; -}; - /** * Start of linked list of all talloc pools. diff --git a/source3/lib/util_seaccess.c b/source3/lib/util_seaccess.c index 2482d582d2..cb0f46e2f9 100644 --- a/source3/lib/util_seaccess.c +++ b/source3/lib/util_seaccess.c @@ -23,22 +23,6 @@ extern DOM_SID global_sid_Builtin; -/********************************************************************************** - Check if this ACE has a SID in common with the token. -**********************************************************************************/ - -static BOOL token_sid_in_ace(const NT_USER_TOKEN *token, const SEC_ACE *ace) -{ - size_t i; - - for (i = 0; i < token->num_sids; i++) { - if (sid_equal(&ace->trustee, &token->user_sids[i])) - return True; - } - - return False; -} - /********************************************************************************* Check an ACE against a SID. We return the remaining needed permission bits not yet granted. Zero means permission allowed (no more needed bits). @@ -332,119 +316,6 @@ BOOL se_access_check(const SEC_DESC *sd, const NT_USER_TOKEN *token, return False; } -/* Create a child security descriptor using another security descriptor as - the parent container. This child object can either be a container or - non-container object. */ - -SEC_DESC_BUF *se_create_child_secdesc(TALLOC_CTX *ctx, SEC_DESC *parent_ctr, - BOOL child_container) -{ - SEC_DESC_BUF *sdb; - SEC_DESC *sd; - SEC_ACL *new_dacl, *the_acl; - SEC_ACE *new_ace_list = NULL; - unsigned int new_ace_list_ndx = 0, i; - size_t size; - - /* Currently we only process the dacl when creating the child. The - sacl should also be processed but this is left out as sacls are - not implemented in Samba at the moment.*/ - - the_acl = parent_ctr->dacl; - - if (!(new_ace_list = talloc(ctx, sizeof(SEC_ACE) * the_acl->num_aces))) - return NULL; - - for (i = 0; the_acl && i < the_acl->num_aces; i++) { - SEC_ACE *ace = &the_acl->ace[i]; - SEC_ACE *new_ace = &new_ace_list[new_ace_list_ndx]; - uint8 new_flags = 0; - BOOL inherit = False; - fstring sid_str; - - /* The OBJECT_INHERIT_ACE flag causes the ACE to be - inherited by non-container children objects. Container - children objects will inherit it as an INHERIT_ONLY - ACE. */ - - if (ace->flags & SEC_ACE_FLAG_OBJECT_INHERIT) { - - if (!child_container) { - new_flags |= SEC_ACE_FLAG_OBJECT_INHERIT; - } else { - new_flags |= SEC_ACE_FLAG_INHERIT_ONLY; - } - - inherit = True; - } - - /* The CONAINER_INHERIT_ACE flag means all child container - objects will inherit and use the ACE. */ - - if (ace->flags & SEC_ACE_FLAG_CONTAINER_INHERIT) { - if (!child_container) { - inherit = False; - } else { - new_flags |= SEC_ACE_FLAG_CONTAINER_INHERIT; - } - } - - /* The INHERIT_ONLY_ACE is not used by the se_access_check() - function for the parent container, but is inherited by - all child objects as a normal ACE. */ - - if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) { - /* Move along, nothing to see here */ - } - - /* The SEC_ACE_FLAG_NO_PROPAGATE_INHERIT flag means the ACE - is inherited by child objects but not grandchildren - objects. We clear the object inherit and container - inherit flags in the inherited ACE. */ - - if (ace->flags & SEC_ACE_FLAG_NO_PROPAGATE_INHERIT) { - new_flags &= ~(SEC_ACE_FLAG_OBJECT_INHERIT | - SEC_ACE_FLAG_CONTAINER_INHERIT); - } - - /* Add ACE to ACE list */ - - if (!inherit) - continue; - - init_sec_access(&new_ace->info, ace->info.mask); - init_sec_ace(new_ace, &ace->trustee, ace->type, - new_ace->info, new_flags); - - sid_to_string(sid_str, &ace->trustee); - - DEBUG(5, ("se_create_child_secdesc(): %s:%d/0x%02x/0x%08x " - " inherited as %s:%d/0x%02x/0x%08x\n", sid_str, - ace->type, ace->flags, ace->info.mask, - sid_str, new_ace->type, new_ace->flags, - new_ace->info.mask)); - - new_ace_list_ndx++; - } - - /* Create child security descriptor to return */ - - new_dacl = make_sec_acl(ctx, ACL_REVISION, new_ace_list_ndx, new_ace_list); - - /* Use the existing user and group sids. I don't think this is - correct. Perhaps the user and group should be passed in as - parameters by the caller? */ - - sd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, - parent_ctr->owner_sid, - parent_ctr->grp_sid, - parent_ctr->sacl, - new_dacl, &size); - - sdb = make_sec_desc_buf(ctx, size, sd); - - return sdb; -} /******************************************************************* samr_make_sam_obj_sd diff --git a/source3/lib/util_sid.c b/source3/lib/util_sid.c index fbb393770d..50bbb4c72c 100644 --- a/source3/lib/util_sid.c +++ b/source3/lib/util_sid.c @@ -638,7 +638,7 @@ void print_guid(GUID *guid) Tallocs a duplicate SID. ********************************************************************/ -DOM_SID *sid_dup_talloc(TALLOC_CTX *ctx, DOM_SID *src) +DOM_SID *sid_dup_talloc(TALLOC_CTX *ctx, const DOM_SID *src) { DOM_SID *dst; diff --git a/source3/passdb/pdb_get_set.c b/source3/passdb/pdb_get_set.c index 9c2b7e4c70..46c49be8b1 100644 --- a/source3/passdb/pdb_get_set.c +++ b/source3/passdb/pdb_get_set.c @@ -509,7 +509,7 @@ BOOL pdb_set_init_flags (SAM_ACCOUNT *sampass, enum pdb_elements element, enum p return True; } -BOOL pdb_set_user_sid (SAM_ACCOUNT *sampass, DOM_SID *u_sid, enum pdb_value_state flag) +BOOL pdb_set_user_sid (SAM_ACCOUNT *sampass, const DOM_SID *u_sid, enum pdb_value_state flag) { if (!sampass || !u_sid) return False; @@ -545,7 +545,7 @@ BOOL pdb_set_user_sid_from_string (SAM_ACCOUNT *sampass, fstring u_sid, enum pdb return True; } -BOOL pdb_set_group_sid (SAM_ACCOUNT *sampass, DOM_SID *g_sid, enum pdb_value_state flag) +BOOL pdb_set_group_sid (SAM_ACCOUNT *sampass, const DOM_SID *g_sid, enum pdb_value_state flag) { if (!sampass || !g_sid) return False; diff --git a/source3/rpc_client/cli_lsarpc.c b/source3/rpc_client/cli_lsarpc.c index db873236e4..65115419b4 100644 --- a/source3/rpc_client/cli_lsarpc.c +++ b/source3/rpc_client/cli_lsarpc.c @@ -1035,9 +1035,9 @@ NTSTATUS cli_lsa_enum_privsaccount(struct cli_state *cli, TALLOC_CTX *mem_ctx, } for (i=0; iset[i].luid.low; + (*set)[i].luid.high = r.set->set[i].luid.high; + (*set)[i].attr = r.set->set[i].attr; } *count=r.count; diff --git a/source3/rpc_parse/parse_lsa.c b/source3/rpc_parse/parse_lsa.c index 3a5b232dc3..22dbd5307a 100644 --- a/source3/rpc_parse/parse_lsa.c +++ b/source3/rpc_parse/parse_lsa.c @@ -1809,14 +1809,20 @@ static BOOL lsa_io_privilege_set(const char *desc, PRIVILEGE_SET *r_c, prs_struc return True; } -void init_lsa_r_enum_privsaccount(LSA_R_ENUMPRIVSACCOUNT *r_u, LUID_ATTR *set, uint32 count, uint32 control) +NTSTATUS init_lsa_r_enum_privsaccount(TALLOC_CTX *mem_ctx, LSA_R_ENUMPRIVSACCOUNT *r_u, LUID_ATTR *set, uint32 count, uint32 control) { - r_u->ptr=1; - r_u->count=count; - r_u->set.set=set; - r_u->set.count=count; - r_u->set.control=control; - DEBUG(10,("init_lsa_r_enum_privsaccount: %d %d privileges\n", r_u->count, r_u->set.count)); + NTSTATUS ret; + + r_u->ptr = 1; + r_u->count = count; + + if (!NT_STATUS_IS_OK(ret = init_priv_with_ctx(mem_ctx, &(r_u->set)))) + return ret; + + if (!NT_STATUS_IS_OK(ret = dupalloc_luid_attr(r_u->set->mem_ctx, &(r_u->set->set), set))) + return ret; + + DEBUG(10,("init_lsa_r_enum_privsaccount: %d %d privileges\n", r_u->count, r_u->set->count)); } /******************************************************************* @@ -1840,13 +1846,16 @@ BOOL lsa_io_r_enum_privsaccount(const char *desc, LSA_R_ENUMPRIVSACCOUNT *r_c, p /* malloc memory if unmarshalling here */ - if (UNMARSHALLING(ps) && r_c->count!=0) { - if (!(r_c->set.set = (LUID_ATTR *)prs_alloc_mem(ps,sizeof(LUID_ATTR) * r_c->count))) + if (UNMARSHALLING(ps) && r_c->count != 0) { + if (!NT_STATUS_IS_OK(init_priv_with_ctx(ps->mem_ctx, &(r_c->set)))) + return False; + + if (!(r_c->set->set = (LUID_ATTR *)prs_alloc_mem(ps,sizeof(LUID_ATTR) * r_c->count))) return False; } - if(!lsa_io_privilege_set(desc, &r_c->set, ps, depth)) + if(!lsa_io_privilege_set(desc, r_c->set, ps, depth)) return False; } @@ -2008,11 +2017,14 @@ BOOL lsa_io_q_addprivs(const char *desc, LSA_Q_ADDPRIVS *r_c, prs_struct *ps, in return False; if (UNMARSHALLING(ps) && r_c->count!=0) { - if (!(r_c->set.set = (LUID_ATTR *)prs_alloc_mem(ps,sizeof(LUID_ATTR) * r_c->count))) + if (!NT_STATUS_IS_OK(init_priv_with_ctx(ps->mem_ctx, &(r_c->set)))) + return False; + + if (!(r_c->set->set = (LUID_ATTR *)prs_alloc_mem(ps, sizeof(LUID_ATTR) * r_c->count))) return False; } - if(!lsa_io_privilege_set(desc, &r_c->set, ps, depth)) + if(!lsa_io_privilege_set(desc, r_c->set, ps, depth)) return False; return True; @@ -2067,11 +2079,14 @@ BOOL lsa_io_q_removeprivs(const char *desc, LSA_Q_REMOVEPRIVS *r_c, prs_struct * return False; if (UNMARSHALLING(ps) && r_c->count!=0) { - if (!(r_c->set.set = (LUID_ATTR *)prs_alloc_mem(ps,sizeof(LUID_ATTR) * r_c->count))) + if (!NT_STATUS_IS_OK(init_priv_with_ctx(ps->mem_ctx, &(r_c->set)))) + return False; + + if (!(r_c->set->set = (LUID_ATTR *)prs_alloc_mem(ps, sizeof(LUID_ATTR) * r_c->count))) return False; } - if(!lsa_io_privilege_set(desc, &r_c->set, ps, depth)) + if(!lsa_io_privilege_set(desc, r_c->set, ps, depth)) return False; } diff --git a/source3/rpc_parse/parse_rpc.c b/source3/rpc_parse/parse_rpc.c index c1e663f877..7e51f1e35b 100644 --- a/source3/rpc_parse/parse_rpc.c +++ b/source3/rpc_parse/parse_rpc.c @@ -248,7 +248,7 @@ BOOL smb_io_rpc_hdr(const char *desc, RPC_HDR *rpc, prs_struct *ps, int depth) static BOOL smb_io_rpc_uuid(const char *desc, RPC_UUID *uuid, prs_struct *ps, int depth) { - if (ifc == NULL) + if (uuid == NULL) return False; prs_debug(ps, depth, desc, "smb_io_rpc_uuid"); @@ -267,7 +267,7 @@ static BOOL smb_io_rpc_uuid(const char *desc, RPC_UUID *uuid, prs_struct *ps, in if(!prs_uint8s (False, "data ", ps, depth, uuid->remaining, sizeof(uuid->remaining))) return False; - return true; + return True; } /******************************************************************* @@ -282,7 +282,7 @@ static BOOL smb_io_rpc_iface(const char *desc, RPC_IFACE *ifc, prs_struct *ps, i prs_debug(ps, depth, desc, "smb_io_rpc_iface"); depth++; - if (!smb_io_rpc_uuid( "uuid", ps, depth, &ifc->uuid)) + if (!smb_io_rpc_uuid( "uuid", &ifc->uuid, ps, depth)) return False; if(!prs_uint32 ( "version", ps, depth, &ifc->version)) diff --git a/source3/rpc_parse/parse_sec.c b/source3/rpc_parse/parse_sec.c index 0ed930c08d..bf43ef288a 100644 --- a/source3/rpc_parse/parse_sec.c +++ b/source3/rpc_parse/parse_sec.c @@ -27,15 +27,6 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_RPC_PARSE -/******************************************************************* - Sets up a SEC_ACCESS structure. -********************************************************************/ - -void init_sec_access(SEC_ACCESS *t, uint32 mask) -{ - t->mask = mask; -} - /******************************************************************* Reads or writes a SEC_ACCESS structure. ********************************************************************/ @@ -54,51 +45,6 @@ BOOL sec_io_access(const char *desc, SEC_ACCESS *t, prs_struct *ps, int depth) return True; } -/******************************************************************* - Check if ACE has OBJECT type. -********************************************************************/ - -BOOL sec_ace_object(uint8 type) -{ - if (type == SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT || - type == SEC_ACE_TYPE_ACCESS_DENIED_OBJECT || - type == SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT || - type == SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT) { - return True; - } - return False; -} - -/******************************************************************* - copy a SEC_ACE structure. -********************************************************************/ -void sec_ace_copy(SEC_ACE *ace_dest, SEC_ACE *ace_src) -{ - ace_dest->type = ace_src->type; - ace_dest->flags = ace_src->flags; - ace_dest->size = ace_src->size; - ace_dest->info.mask = ace_src->info.mask; - ace_dest->obj_flags = ace_src->obj_flags; - memcpy(&ace_dest->obj_guid, &ace_src->obj_guid, GUID_SIZE); - memcpy(&ace_dest->inh_guid, &ace_src->inh_guid, GUID_SIZE); - sid_copy(&ace_dest->trustee, &ace_src->trustee); -} - -/******************************************************************* - Sets up a SEC_ACE structure. -********************************************************************/ - -void init_sec_ace(SEC_ACE *t, DOM_SID *sid, uint8 type, SEC_ACCESS mask, uint8 flag) -{ - t->type = type; - t->flags = flag; - t->size = sid_size(sid) + 8; - t->info = mask; - - ZERO_STRUCTP(&t->trustee); - sid_copy(&t->trustee, sid); -} - /******************************************************************* Reads or writes a SEC_ACE structure. ********************************************************************/ @@ -153,127 +99,6 @@ BOOL sec_io_ace(const char *desc, SEC_ACE *psa, prs_struct *ps, int depth) return True; } -/******************************************************************* - adds new SID with its permissions to ACE list -********************************************************************/ - -NTSTATUS sec_ace_add_sid(TALLOC_CTX *ctx, SEC_ACE **new, SEC_ACE *old, unsigned *num, DOM_SID *sid, uint32 mask) -{ - unsigned int i = 0; - - if (!ctx || !new || !old || !sid || !num) return NT_STATUS_INVALID_PARAMETER; - - *num += 1; - - if((new[0] = (SEC_ACE *) talloc_zero(ctx, (*num) * sizeof(SEC_ACE))) == 0) - return NT_STATUS_NO_MEMORY; - - for (i = 0; i < *num - 1; i ++) - sec_ace_copy(&(*new)[i], &old[i]); - - (*new)[i].type = 0; - (*new)[i].flags = 0; - (*new)[i].size = SEC_ACE_HEADER_SIZE + sid_size(sid); - (*new)[i].info.mask = mask; - sid_copy(&(*new)[i].trustee, sid); - return NT_STATUS_OK; -} - -/******************************************************************* - modify SID's permissions at ACL -********************************************************************/ - -NTSTATUS sec_ace_mod_sid(SEC_ACE *ace, size_t num, DOM_SID *sid, uint32 mask) -{ - unsigned int i = 0; - - if (!ace || !sid) return NT_STATUS_INVALID_PARAMETER; - - for (i = 0; i < num; i ++) { - if (sid_compare(&ace[i].trustee, sid) == 0) { - ace[i].info.mask = mask; - return NT_STATUS_OK; - } - } - return NT_STATUS_NOT_FOUND; -} - -/******************************************************************* - delete SID from ACL -********************************************************************/ - -static NTSTATUS sec_ace_del_sid(TALLOC_CTX *ctx, SEC_ACE **new, SEC_ACE *old, uint32 *num, DOM_SID *sid) -{ - unsigned int i = 0; - unsigned int n_del = 0; - - if (!ctx || !new || !old || !sid || !num) return NT_STATUS_INVALID_PARAMETER; - - if((new[0] = (SEC_ACE *) talloc_zero(ctx, (*num) * sizeof(SEC_ACE))) == 0) - return NT_STATUS_NO_MEMORY; - - for (i = 0; i < *num; i ++) { - if (sid_compare(&old[i].trustee, sid) != 0) - sec_ace_copy(&(*new)[i], &old[i]); - else - n_del ++; - } - if (n_del == 0) - return NT_STATUS_NOT_FOUND; - else { - *num -= n_del; - return NT_STATUS_OK; - } -} - -/******************************************************************* - Create a SEC_ACL structure. -********************************************************************/ - -SEC_ACL *make_sec_acl(TALLOC_CTX *ctx, uint16 revision, int num_aces, SEC_ACE *ace_list) -{ - SEC_ACL *dst; - int i; - - if((dst = (SEC_ACL *)talloc_zero(ctx,sizeof(SEC_ACL))) == NULL) - return NULL; - - dst->revision = revision; - dst->num_aces = num_aces; - dst->size = SEC_ACL_HEADER_SIZE; - - /* Now we need to return a non-NULL address for the ace list even - if the number of aces required is zero. This is because there - is a distinct difference between a NULL ace and an ace with zero - entries in it. This is achieved by checking that num_aces is a - positive number. */ - - if ((num_aces) && - ((dst->ace = (SEC_ACE *)talloc(ctx, sizeof(SEC_ACE) * num_aces)) - == NULL)) { - return NULL; - } - - for (i = 0; i < num_aces; i++) { - dst->ace[i] = ace_list[i]; /* Structure copy. */ - dst->size += ace_list[i].size; - } - - return dst; -} - -/******************************************************************* - Duplicate a SEC_ACL structure. -********************************************************************/ - -SEC_ACL *dup_sec_acl(TALLOC_CTX *ctx, SEC_ACL *src) -{ - if(src == NULL) - return NULL; - - return make_sec_acl(ctx, src->revision, src->num_aces, src->ace); -} - /******************************************************************* Reads or writes a SEC_ACL structure. @@ -346,332 +171,6 @@ BOOL sec_io_acl(const char *desc, SEC_ACL **ppsa, prs_struct *ps, int depth) return True; } -/******************************************************************* - Works out the linearization size of a SEC_DESC. -********************************************************************/ - -size_t sec_desc_size(SEC_DESC *psd) -{ - size_t offset; - - if (!psd) return 0; - - offset = SEC_DESC_HEADER_SIZE; - - /* don't align */ - - if (psd->owner_sid != NULL) - offset += sid_size(psd->owner_sid); - - if (psd->grp_sid != NULL) - offset += sid_size(psd->grp_sid); - - if (psd->sacl != NULL) - offset += psd->sacl->size; - - if (psd->dacl != NULL) - offset += psd->dacl->size; - - return offset; -} - -/******************************************************************* - Compares two SEC_ACE structures -********************************************************************/ - -BOOL sec_ace_equal(SEC_ACE *s1, SEC_ACE *s2) -{ - /* Trivial case */ - - if (!s1 && !s2) return True; - - /* Check top level stuff */ - - if (s1->type != s2->type || s1->flags != s2->flags || - s1->info.mask != s2->info.mask) { - return False; - } - - /* Check SID */ - - if (!sid_equal(&s1->trustee, &s2->trustee)) { - return False; - } - - return True; -} - -/******************************************************************* - Compares two SEC_ACL structures -********************************************************************/ - -BOOL sec_acl_equal(SEC_ACL *s1, SEC_ACL *s2) -{ - unsigned int i, j; - - /* Trivial cases */ - - if (!s1 && !s2) return True; - if (!s1 || !s2) return False; - - /* Check top level stuff */ - - if (s1->revision != s2->revision) { - DEBUG(10, ("sec_acl_equal(): revision differs (%d != %d)\n", - s1->revision, s2->revision)); - return False; - } - - if (s1->num_aces != s2->num_aces) { - DEBUG(10, ("sec_acl_equal(): num_aces differs (%d != %d)\n", - s1->revision, s2->revision)); - return False; - } - - /* The ACEs could be in any order so check each ACE in s1 against - each ACE in s2. */ - - for (i = 0; i < s1->num_aces; i++) { - BOOL found = False; - - for (j = 0; j < s2->num_aces; j++) { - if (sec_ace_equal(&s1->ace[i], &s2->ace[j])) { - found = True; - break; - } - } - - if (!found) return False; - } - - return True; -} - -/******************************************************************* - Compares two SEC_DESC structures -********************************************************************/ - -BOOL sec_desc_equal(SEC_DESC *s1, SEC_DESC *s2) -{ - /* Trivial case */ - - if (!s1 && !s2) { - goto done; - } - - /* Check top level stuff */ - - if (s1->revision != s2->revision) { - DEBUG(10, ("sec_desc_equal(): revision differs (%d != %d)\n", - s1->revision, s2->revision)); - return False; - } - - if (s1->type!= s2->type) { - DEBUG(10, ("sec_desc_equal(): type differs (%d != %d)\n", - s1->type, s2->type)); - return False; - } - - /* Check owner and group */ - - if (!sid_equal(s1->owner_sid, s2->owner_sid)) { - fstring str1, str2; - - sid_to_string(str1, s1->owner_sid); - sid_to_string(str2, s2->owner_sid); - - DEBUG(10, ("sec_desc_equal(): owner differs (%s != %s)\n", - str1, str2)); - return False; - } - - if (!sid_equal(s1->grp_sid, s2->grp_sid)) { - fstring str1, str2; - - sid_to_string(str1, s1->grp_sid); - sid_to_string(str2, s2->grp_sid); - - DEBUG(10, ("sec_desc_equal(): group differs (%s != %s)\n", - str1, str2)); - return False; - } - - /* Check ACLs present in one but not the other */ - - if ((s1->dacl && !s2->dacl) || (!s1->dacl && s2->dacl) || - (s1->sacl && !s2->sacl) || (!s1->sacl && s2->sacl)) { - DEBUG(10, ("sec_desc_equal(): dacl or sacl not present\n")); - return False; - } - - /* Sigh - we have to do it the hard way by iterating over all - the ACEs in the ACLs */ - - if (!sec_acl_equal(s1->dacl, s2->dacl) || - !sec_acl_equal(s1->sacl, s2->sacl)) { - DEBUG(10, ("sec_desc_equal(): dacl/sacl list not equal\n")); - return False; - } - - done: - DEBUG(10, ("sec_desc_equal(): secdescs are identical\n")); - return True; -} - -/******************************************************************* - Merge part of security descriptor old_sec in to the empty sections of - security descriptor new_sec. -********************************************************************/ - -SEC_DESC_BUF *sec_desc_merge(TALLOC_CTX *ctx, SEC_DESC_BUF *new_sdb, SEC_DESC_BUF *old_sdb) -{ - DOM_SID *owner_sid, *group_sid; - SEC_DESC_BUF *return_sdb; - SEC_ACL *dacl, *sacl; - SEC_DESC *psd = NULL; - uint16 secdesc_type; - size_t secdesc_size; - - /* Copy over owner and group sids. There seems to be no flag for - this so just check the pointer values. */ - - owner_sid = new_sdb->sec->owner_sid ? new_sdb->sec->owner_sid : - old_sdb->sec->owner_sid; - - group_sid = new_sdb->sec->grp_sid ? new_sdb->sec->grp_sid : - old_sdb->sec->grp_sid; - - secdesc_type = new_sdb->sec->type; - - /* Ignore changes to the system ACL. This has the effect of making - changes through the security tab audit button not sticking. - Perhaps in future Samba could implement these settings somehow. */ - - sacl = NULL; - secdesc_type &= ~SEC_DESC_SACL_PRESENT; - - /* Copy across discretionary ACL */ - - if (secdesc_type & SEC_DESC_DACL_PRESENT) { - dacl = new_sdb->sec->dacl; - } else { - dacl = old_sdb->sec->dacl; - } - - /* Create new security descriptor from bits */ - - psd = make_sec_desc(ctx, new_sdb->sec->revision, secdesc_type, - owner_sid, group_sid, sacl, dacl, &secdesc_size); - - return_sdb = make_sec_desc_buf(ctx, secdesc_size, psd); - - return(return_sdb); -} - -/******************************************************************* - Creates a SEC_DESC structure -********************************************************************/ - -SEC_DESC *make_sec_desc(TALLOC_CTX *ctx, uint16 revision, uint16 type, - DOM_SID *owner_sid, DOM_SID *grp_sid, - SEC_ACL *sacl, SEC_ACL *dacl, size_t *sd_size) -{ - SEC_DESC *dst; - uint32 offset = 0; - - *sd_size = 0; - - if(( dst = (SEC_DESC *)talloc_zero(ctx, sizeof(SEC_DESC))) == NULL) - return NULL; - - dst->revision = revision; - dst->type = type; - - if (sacl) - dst->type |= SEC_DESC_SACL_PRESENT; - if (dacl) - dst->type |= SEC_DESC_DACL_PRESENT; - - dst->off_owner_sid = 0; - dst->off_grp_sid = 0; - dst->off_sacl = 0; - dst->off_dacl = 0; - - if(owner_sid && ((dst->owner_sid = sid_dup_talloc(ctx,owner_sid)) == NULL)) - goto error_exit; - - if(grp_sid && ((dst->grp_sid = sid_dup_talloc(ctx,grp_sid)) == NULL)) - goto error_exit; - - if(sacl && ((dst->sacl = dup_sec_acl(ctx, sacl)) == NULL)) - goto error_exit; - - if(dacl && ((dst->dacl = dup_sec_acl(ctx, dacl)) == NULL)) - goto error_exit; - - offset = SEC_DESC_HEADER_SIZE; - - /* - * Work out the linearization sizes. - */ - - if (dst->sacl != NULL) { - dst->off_sacl = offset; - offset += dst->sacl->size; - } - - if (dst->dacl != NULL) { - dst->off_dacl = offset; - offset += dst->dacl->size; - } - - if (dst->owner_sid != NULL) { - dst->off_owner_sid = offset; - offset += sid_size(dst->owner_sid); - } - - if (dst->grp_sid != NULL) { - dst->off_grp_sid = offset; - offset += sid_size(dst->grp_sid); - } - - *sd_size = (size_t)offset; - return dst; - -error_exit: - - *sd_size = 0; - return NULL; -} - -/******************************************************************* - Duplicate a SEC_DESC structure. -********************************************************************/ - -SEC_DESC *dup_sec_desc( TALLOC_CTX *ctx, SEC_DESC *src) -{ - size_t dummy; - - if(src == NULL) - return NULL; - - return make_sec_desc( ctx, src->revision, src->type, - src->owner_sid, src->grp_sid, src->sacl, - src->dacl, &dummy); -} - -/******************************************************************* - Creates a SEC_DESC structure with typical defaults. -********************************************************************/ - -SEC_DESC *make_standard_sec_desc(TALLOC_CTX *ctx, DOM_SID *owner_sid, DOM_SID *grp_sid, - SEC_ACL *dacl, size_t *sd_size) -{ - return make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, - owner_sid, grp_sid, NULL, dacl, sd_size); -} - /******************************************************************* Reads or writes a SEC_DESC structure. If reading and the *ppsd = NULL, allocates the structure. @@ -807,42 +306,6 @@ BOOL sec_io_desc(const char *desc, SEC_DESC **ppsd, prs_struct *ps, int depth) return True; } -/******************************************************************* - Creates a SEC_DESC_BUF structure. -********************************************************************/ - -SEC_DESC_BUF *make_sec_desc_buf(TALLOC_CTX *ctx, size_t len, SEC_DESC *sec_desc) -{ - SEC_DESC_BUF *dst; - - if((dst = (SEC_DESC_BUF *)talloc_zero(ctx, sizeof(SEC_DESC_BUF))) == NULL) - return NULL; - - /* max buffer size (allocated size) */ - dst->max_len = (uint32)len; - dst->len = (uint32)len; - - if(sec_desc && ((dst->sec = dup_sec_desc(ctx, sec_desc)) == NULL)) { - return NULL; - } - - dst->ptr = 0x1; - - return dst; -} - -/******************************************************************* - Duplicates a SEC_DESC_BUF structure. -********************************************************************/ - -SEC_DESC_BUF *dup_sec_desc_buf(TALLOC_CTX *ctx, SEC_DESC_BUF *src) -{ - if(src == NULL) - return NULL; - - return make_sec_desc_buf( ctx, src->len, src->sec); -} - /******************************************************************* Reads or writes a SEC_DESC_BUF structure. ********************************************************************/ @@ -901,193 +364,3 @@ BOOL sec_io_desc_buf(const char *desc, SEC_DESC_BUF **ppsdb, prs_struct *ps, int return True; } - -/******************************************************************* - Add a new SID with its permissions to SEC_DESC. -********************************************************************/ - -NTSTATUS sec_desc_add_sid(TALLOC_CTX *ctx, SEC_DESC **psd, DOM_SID *sid, uint32 mask, size_t *sd_size) -{ - SEC_DESC *sd = 0; - SEC_ACL *dacl = 0; - SEC_ACE *ace = 0; - NTSTATUS status; - - *sd_size = 0; - - if (!ctx || !psd || !sid || !sd_size) - return NT_STATUS_INVALID_PARAMETER; - - status = sec_ace_add_sid(ctx, &ace, psd[0]->dacl->ace, &psd[0]->dacl->num_aces, sid, mask); - - if (!NT_STATUS_IS_OK(status)) - return status; - - if (!(dacl = make_sec_acl(ctx, psd[0]->dacl->revision, psd[0]->dacl->num_aces, ace))) - return NT_STATUS_UNSUCCESSFUL; - - if (!(sd = make_sec_desc(ctx, psd[0]->revision, psd[0]->type, psd[0]->owner_sid, - psd[0]->grp_sid, psd[0]->sacl, dacl, sd_size))) - return NT_STATUS_UNSUCCESSFUL; - - *psd = sd; - sd = 0; - return NT_STATUS_OK; -} - -/******************************************************************* - Modify a SID's permissions in a SEC_DESC. -********************************************************************/ - -NTSTATUS sec_desc_mod_sid(SEC_DESC *sd, DOM_SID *sid, uint32 mask) -{ - NTSTATUS status; - - if (!sd || !sid) - return NT_STATUS_INVALID_PARAMETER; - - status = sec_ace_mod_sid(sd->dacl->ace, sd->dacl->num_aces, sid, mask); - - if (!NT_STATUS_IS_OK(status)) - return status; - - return NT_STATUS_OK; -} - -/******************************************************************* - Delete a SID from a SEC_DESC. -********************************************************************/ - -NTSTATUS sec_desc_del_sid(TALLOC_CTX *ctx, SEC_DESC **psd, DOM_SID *sid, size_t *sd_size) -{ - SEC_DESC *sd = 0; - SEC_ACL *dacl = 0; - SEC_ACE *ace = 0; - NTSTATUS status; - - *sd_size = 0; - - if (!ctx || !psd[0] || !sid || !sd_size) - return NT_STATUS_INVALID_PARAMETER; - - status = sec_ace_del_sid(ctx, &ace, psd[0]->dacl->ace, &psd[0]->dacl->num_aces, sid); - - if (!NT_STATUS_IS_OK(status)) - return status; - - if (!(dacl = make_sec_acl(ctx, psd[0]->dacl->revision, psd[0]->dacl->num_aces, ace))) - return NT_STATUS_UNSUCCESSFUL; - - if (!(sd = make_sec_desc(ctx, psd[0]->revision, psd[0]->type, psd[0]->owner_sid, - psd[0]->grp_sid, psd[0]->sacl, dacl, sd_size))) - return NT_STATUS_UNSUCCESSFUL; - - *psd = sd; - sd = 0; - return NT_STATUS_OK; -} - -/******************************************************************* - Comparison function to sort non-inherited first. -*******************************************************************/ - -static int nt_ace_inherit_comp( SEC_ACE *a1, SEC_ACE *a2) -{ - int a1_inh = a1->flags & SEC_ACE_FLAG_INHERITED_ACE; - int a2_inh = a2->flags & SEC_ACE_FLAG_INHERITED_ACE; - - if (a1_inh == a2_inh) - return 0; - - if (!a1_inh && a2_inh) - return -1; - return 1; -} - -/******************************************************************* - Comparison function to apply the order explained below in a group. -*******************************************************************/ - -static int nt_ace_canon_comp( SEC_ACE *a1, SEC_ACE *a2) -{ - if ((a1->type == SEC_ACE_TYPE_ACCESS_DENIED) && - (a2->type != SEC_ACE_TYPE_ACCESS_DENIED)) - return -1; - - if ((a2->type == SEC_ACE_TYPE_ACCESS_DENIED) && - (a1->type != SEC_ACE_TYPE_ACCESS_DENIED)) - return 1; - - /* Both access denied or access allowed. */ - - /* 1. ACEs that apply to the object itself */ - - if (!(a1->flags & SEC_ACE_FLAG_INHERIT_ONLY) && - (a2->flags & SEC_ACE_FLAG_INHERIT_ONLY)) - return -1; - else if (!(a2->flags & SEC_ACE_FLAG_INHERIT_ONLY) && - (a1->flags & SEC_ACE_FLAG_INHERIT_ONLY)) - return 1; - - /* 2. ACEs that apply to a subobject of the object, such as - * a property set or property. */ - - if (a1->flags & (SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT) && - !(a2->flags & (SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT))) - return -1; - else if (a2->flags & (SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT) && - !(a1->flags & (SEC_ACE_FLAG_CONTAINER_INHERIT|SEC_ACE_FLAG_OBJECT_INHERIT))) - return 1; - - return 0; -} - -/******************************************************************* - Functions to convert a SEC_DESC ACE DACL list into canonical order. - JRA. - ---- from http://msdn.microsoft.com/library/default.asp?url=/library/en-us/security/security/order_of_aces_in_a_dacl.asp - -The following describes the preferred order: - - To ensure that noninherited ACEs have precedence over inherited ACEs, - place all noninherited ACEs in a group before any inherited ACEs. - This ordering ensures, for example, that a noninherited access-denied ACE - is enforced regardless of any inherited ACE that allows access. - - Within the groups of noninherited ACEs and inherited ACEs, order ACEs according to ACE type, as the following shows: - 1. Access-denied ACEs that apply to the object itself - 2. Access-denied ACEs that apply to a subobject of the object, such as a property set or property - 3. Access-allowed ACEs that apply to the object itself - 4. Access-allowed ACEs that apply to a subobject of the object" - -********************************************************************/ - -void dacl_sort_into_canonical_order(SEC_ACE *srclist, unsigned int num_aces) -{ - unsigned int i; - - if (!srclist || num_aces == 0) - return; - - /* Sort so that non-inherited ACE's come first. */ - qsort( srclist, num_aces, sizeof(srclist[0]), QSORT_CAST nt_ace_inherit_comp); - - /* Find the boundary between non-inherited ACEs. */ - for (i = 0; i < num_aces; i++ ) { - SEC_ACE *curr_ace = &srclist[i]; - - if (curr_ace->flags & SEC_ACE_FLAG_INHERITED_ACE) - break; - } - - /* i now points at entry number of the first inherited ACE. */ - - /* Sort the non-inherited ACEs. */ - if (i) - qsort( srclist, i, sizeof(srclist[0]), QSORT_CAST nt_ace_canon_comp); - - /* Now sort the inherited ACEs. */ - if (num_aces - i) - qsort( &srclist[i], num_aces - i, sizeof(srclist[0]), QSORT_CAST nt_ace_canon_comp); -} diff --git a/source3/rpc_server/srv_lsa.c b/source3/rpc_server/srv_lsa.c index 138fb1d7ef..5d6c1551c9 100644 --- a/source3/rpc_server/srv_lsa.c +++ b/source3/rpc_server/srv_lsa.c @@ -443,7 +443,7 @@ static BOOL api_lsa_enum_privsaccount(pipes_struct *p) return False; } - r_u.status = _lsa_enum_privsaccount(p, &q_u, &r_u); + r_u.status = _lsa_enum_privsaccount(p, rdata, &q_u, &r_u); /* store the response in the SMB stream */ if(!lsa_io_r_enum_privsaccount("", &r_u, rdata, 0)) { diff --git a/source3/rpc_server/srv_lsa_nt.c b/source3/rpc_server/srv_lsa_nt.c index 0921824cad..0a8ad404cb 100644 --- a/source3/rpc_server/srv_lsa_nt.c +++ b/source3/rpc_server/srv_lsa_nt.c @@ -955,7 +955,7 @@ NTSTATUS _lsa_open_account(pipes_struct *p, LSA_Q_OPENACCOUNT *q_u, LSA_R_OPENAC For a given SID, enumerate all the privilege this account has. ***************************************************************************/ -NTSTATUS _lsa_enum_privsaccount(pipes_struct *p, LSA_Q_ENUMPRIVSACCOUNT *q_u, LSA_R_ENUMPRIVSACCOUNT *r_u) +NTSTATUS _lsa_enum_privsaccount(pipes_struct *p, prs_struct *ps, LSA_Q_ENUMPRIVSACCOUNT *q_u, LSA_R_ENUMPRIVSACCOUNT *r_u) { struct lsa_info *info=NULL; GROUP_MAP map; @@ -971,29 +971,29 @@ NTSTATUS _lsa_enum_privsaccount(pipes_struct *p, LSA_Q_ENUMPRIVSACCOUNT *q_u, LS return NT_STATUS_NO_SUCH_GROUP; #if 0 /* privileges currently not implemented! */ - DEBUG(10,("_lsa_enum_privsaccount: %d privileges\n", map.priv_set.count)); - if (map.priv_set.count!=0) { + DEBUG(10,("_lsa_enum_privsaccount: %d privileges\n", map.priv_set->count)); + if (map.priv_set->count!=0) { - set=(LUID_ATTR *)talloc(p->mem_ctx, map.priv_set.count*sizeof(LUID_ATTR)); + set=(LUID_ATTR *)talloc(map.priv_set->mem_ctx, map.priv_set.count*sizeof(LUID_ATTR)); if (set == NULL) { - free_privilege(&map.priv_set); + destroy_privilege(&map.priv_set); return NT_STATUS_NO_MEMORY; } - for (i=0; iset[i].luid.low; + set[i].luid.high = map.priv_set->set[i].luid.high; + set[i].attr = map.priv_set->set[i].attr; DEBUG(10,("_lsa_enum_privsaccount: priv %d: %d:%d:%d\n", i, set[i].luid.high, set[i].luid.low, set[i].attr)); } } - init_lsa_r_enum_privsaccount(r_u, set, map.priv_set.count, 0); - free_privilege(&map.priv_set); + init_lsa_r_enum_privsaccount(ps->mem_ctx, r_u, set, map.priv_set->count, 0); + destroy_privilege(&map.priv_set); #endif - init_lsa_r_enum_privsaccount(r_u, set, 0, 0); + init_lsa_r_enum_privsaccount(ps->mem_ctx, r_u, set, 0, 0); return r_u->status; } @@ -1059,11 +1059,11 @@ NTSTATUS _lsa_setsystemaccount(pipes_struct *p, LSA_Q_SETSYSTEMACCOUNT *q_u, LSA NTSTATUS _lsa_addprivs(pipes_struct *p, LSA_Q_ADDPRIVS *q_u, LSA_R_ADDPRIVS *r_u) { #if 0 - struct lsa_info *info=NULL; + struct lsa_info *info = NULL; GROUP_MAP map; - int i=0; - LUID_ATTR *luid_attr=NULL; - PRIVILEGE_SET *set=NULL; + int i = 0; + LUID_ATTR *luid_attr = NULL; + PRIVILEGE_SET *set = NULL; #endif r_u->status = NT_STATUS_OK; @@ -1076,24 +1076,24 @@ NTSTATUS _lsa_addprivs(pipes_struct *p, LSA_Q_ADDPRIVS *q_u, LSA_R_ADDPRIVS *r_u if (!pdb_getgrsid(&map, info->sid)) return NT_STATUS_NO_SUCH_GROUP; - set=&q_u->set; + set = &q_u->set; - for (i=0; icount; i++) { - luid_attr=&set->set[i]; + for (i = 0; i < set->count; i++) { + luid_attr = &set->set[i]; /* check if the privilege is already there */ - if (check_priv_in_privilege(&map.priv_set, *luid_attr)){ - free_privilege(&map.priv_set); + if (check_priv_in_privilege(map.priv_set, *luid_attr)){ + destroy_privilege(&map.priv_set); return NT_STATUS_NO_SUCH_PRIVILEGE; } - add_privilege(&map.priv_set, *luid_attr); + add_privilege(map.priv_set, *luid_attr); } if(!pdb_update_group_mapping_entry(&map)) return NT_STATUS_NO_SUCH_GROUP; - free_privilege(&map.priv_set); + destroy_privilege(&map.priv_set); #endif return r_u->status; @@ -1106,11 +1106,11 @@ NTSTATUS _lsa_addprivs(pipes_struct *p, LSA_Q_ADDPRIVS *q_u, LSA_R_ADDPRIVS *r_u NTSTATUS _lsa_removeprivs(pipes_struct *p, LSA_Q_REMOVEPRIVS *q_u, LSA_R_REMOVEPRIVS *r_u) { #if 0 - struct lsa_info *info=NULL; + struct lsa_info *info = NULL; GROUP_MAP map; int i=0; - LUID_ATTR *luid_attr=NULL; - PRIVILEGE_SET *set=NULL; + LUID_ATTR *luid_attr = NULL; + PRIVILEGE_SET *set = NULL; #endif r_u->status = NT_STATUS_OK; @@ -1123,37 +1123,37 @@ NTSTATUS _lsa_removeprivs(pipes_struct *p, LSA_Q_REMOVEPRIVS *q_u, LSA_R_REMOVEP if (!pdb_getgrsid(&map, info->sid)) return NT_STATUS_NO_SUCH_GROUP; - if (q_u->allrights!=0) { + if (q_u->allrights != 0) { /* log it and return, until I see one myself don't do anything */ DEBUG(5,("_lsa_removeprivs: trying to remove all privileges ?\n")); return NT_STATUS_OK; } - if (q_u->ptr==0) { + if (q_u->ptr == 0) { /* log it and return, until I see one myself don't do anything */ DEBUG(5,("_lsa_removeprivs: no privileges to remove ?\n")); return NT_STATUS_OK; } - set=&q_u->set; + set = &q_u->set; - for (i=0; icount; i++) { - luid_attr=&set->set[i]; + for (i = 0; i < set->count; i++) { + luid_attr = &set->set[i]; /* if we don't have the privilege, we're trying to remove, give up */ /* what else can we do ??? JFM. */ - if (!check_priv_in_privilege(&map.priv_set, *luid_attr)){ - free_privilege(&map.priv_set); + if (!check_priv_in_privilege(map.priv_set, *luid_attr)){ + destroy_privilege(&map.priv_set); return NT_STATUS_NO_SUCH_PRIVILEGE; } - remove_privilege(&map.priv_set, *luid_attr); + remove_privilege(map.priv_set, *luid_attr); } if(!pdb_update_group_mapping_entry(&map)) return NT_STATUS_NO_SUCH_GROUP; - free_privilege(&map.priv_set); + destroy_privilege(&map.priv_set); #endif return r_u->status; } diff --git a/source3/script/mkproto.awk b/source3/script/mkproto.awk index b6e911699e..3835ea3af3 100644 --- a/source3/script/mkproto.awk +++ b/source3/script/mkproto.awk @@ -120,7 +120,7 @@ END { gotstart = 1; } - if( $0 ~ /^ADS_STRUCT|^ADS_STATUS|^DATA_BLOB|^ASN1_DATA|^TDB_CONTEXT|^TDB_DATA|^smb_ucs2_t|^TALLOC_CTX|^hash_element|^NT_DEVICEMODE|^enum.*\(|^NT_USER_TOKEN|^SAM_ACCOUNT/ ) { + if( $0 ~ /^ADS_STRUCT|^ADS_STATUS|^DATA_BLOB|^ASN1_DATA|^TDB_CONTEXT|^TDB_DATA|^smb_ucs2_t|^TALLOC_CTX|^hash_element|^NT_DEVICEMODE|^enum.*\(|^NT_USER_TOKEN|^SAM_ACCOUNT|^NTTIME/ ) { gotstart = 1; } diff --git a/source3/tdb/tdbback.c b/source3/tdb/tdbback.c index 9466c29991..68b6fadc88 100644 --- a/source3/tdb/tdbback.c +++ b/source3/tdb/tdbback.c @@ -55,8 +55,7 @@ char *add_suffix(const char *name, const char *suffix) fprintf(stderr,"Out of memory!\n"); exit(1); } - strncpy(ret, name, len); - strncat(ret, suffix, len); + snprintf(ret, len, "%s%s", name, suffix); return ret; } -- cgit
%s%s
%s%s
%s%s Not Used  Server for client use  Client of another WINS server 
Remote WINS Server 
Remote WINS Server 
Error: WINS Server Mode and WINS Support both set in smb.conf
Please Select desired WINS mode above.
Not Used  Server for client use  Client of another WINS server 
Remote WINS Server Error: WINS Server Mode and WINS Support both set in smb.conf
Please Select desired WINS mode above.
%s Yes No