diff options
author | Gerald Carter <jerry@samba.org> | 2003-07-16 05:34:56 +0000 |
---|---|---|
committer | Gerald Carter <jerry@samba.org> | 2003-07-16 05:34:56 +0000 |
commit | 4a090ba06a54f5da179ac02bb307cc03d08831bf (patch) | |
tree | ed652ef36be7f16682c358816334f969a22f1c27 /source3 | |
parent | 95fe82670032a3a43571b46d7bbf2c26bc8cdcd9 (diff) | |
download | samba-4a090ba06a54f5da179ac02bb307cc03d08831bf.tar.gz samba-4a090ba06a54f5da179ac02bb307cc03d08831bf.tar.bz2 samba-4a090ba06a54f5da179ac02bb307cc03d08831bf.zip |
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)
Diffstat (limited to 'source3')
254 files changed, 16772 insertions, 12944 deletions
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 <stdlib.h> -#include <giconv.h>], - [iconv_t cd = iconv_open("",""); - iconv(cd,NULL,NULL,NULL,NULL); - iconv_close(cd);], +#include <biconv.h>], + [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 <stdlib.h> -#include <iconv.h>], +#include <giconv.h>], [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 <stdlib.h> +#include <iconv.h>], + [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 <stdlib.h> +#include <giconv.h>], + [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 <stdlib.h> -#include <giconv.h>], +#include <iconv.h>], [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 <stdlib.h> -#include <iconv.h>], - [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); @@ -232,61 +129,6 @@ machine %s. Error was : %s.\n", remote_machine, cli_errstr(*cli))); } /*********************************************************************** - 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 use it, otherwise figure out a server from the 'password server' param. @@ -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; } /*************************************************************************** @@ -847,6 +881,43 @@ NTSTATUS make_server_info_guest(auth_serversupplied_info **server_info) } /*************************************************************************** + 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", "<c|x>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 <sys/types.h>],[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 <iconv.h> +#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.h>], -[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.h>], -[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.h>], -[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.h>], -[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.h>], -[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.h>], + [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.h>], + [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.h>], + [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.h>], + [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.h>], + [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 <lber.h> #include <ldap.h>], [ldap_set_rebind_proc(0, 0, 0);], [pam_ldap_cv_ldap_set_rebind_proc=3], [pam_ldap_cv_ldap_set_rebind_proc=2]) ]) AC_DEFINE_UNQUOTED(LDAP_SET_REBIND_PROC_ARGS, $pam_ldap_cv_ldap_set_rebind_proc, [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=<list> 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 <stdio.h> -#include <sys/types.h> -#include <asm/types.h> -#include <linux/quota.h> -#include <mntent.h> -#include <linux/unistd.h>],[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 <linux/quota.h> we should use it +AC_CACHE_CHECK([for struct if_dqblk in <linux/quota.h>],samba_cv_HAVE_STRUCT_IF_DQBLK, [ +AC_TRY_COMPILE([ +#include "confdefs.h" +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#ifdef HAVE_ASM_TYPES_H +#include <asm/types.h> +#endif +#include <linux/quota.h> +],[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 <linux/quota.h> we should use it +AC_CACHE_CHECK([for struct mem_dqblk in <linux/quota.h>],samba_cv_HAVE_STRUCT_MEM_DQBLK, [ +AC_TRY_COMPILE([ +#include "confdefs.h" +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#ifdef HAVE_ASM_TYPES_H +#include <asm/types.h> +#endif +#include <linux/quota.h> +],[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 <sys/quota.h> +#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 <sys/types.h> +#include <sys/acl.h>], +[ 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 <sys/types.h> +#include <sys/acl.h>], +[ 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 <pwd.h>]) - -AC_CACHE_CHECK([whether struct passwd has pw_comment],samba_cv_passwd_pw_comment, [ - AC_TRY_COMPILE([#include <pwd.h>],[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 <pwd.h>]) +# 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 <pwd.h>]) -AC_CACHE_CHECK([whether struct passwd has pw_age],samba_cv_passwd_pw_age, [ - AC_TRY_COMPILE([#include <pwd.h>],[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 <pwd.h>]) ################################################# # 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 @@ -3515,6 +3899,18 @@ if test "${ac_cv_prog_CC}" = "insure"; then 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 AC_MSG_CHECKING([configure summary]) 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; i<set->count; 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; 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 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; 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)); - 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; i<set->count; 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; i<set->count; 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; i<set->count; 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; i<set->count; 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; i<se_priv->count; 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 <com_err.h> #endif +#if HAVE_ATTR_XATTR_H +#include <attr/xattr.h> +#endif + +#if HAVE_LOCALE_H +#include <locale.h> +#endif + +#if HAVE_LANGINFO_H +#include <langinfo.h> +#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,12 +164,225 @@ 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) These values are used by VFS subsystem when building vfs_ops for connection @@ -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_<module_name>) - 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<num_groups; i++ ) + DEBUGADD(10,("%d ", groups[i])); + DEBUGADD(10,("\n")); } /* @@ -571,10 +589,16 @@ BOOL user_in_list(const char *user,const char **list, gid_t *groups, size_t n_gr fstrcpy(domain, *list); domain[PTR_DIFF(p, *list)] = 0; - /* Check to see if name is a Windows group */ - if (winbind_lookup_name(domain, groupname, &g_sid, &name_type) && name_type == SID_NAME_DOM_GRP) { + /* Check to see if name is a Windows group; Win2k native mode DCs + will return domain local groups; while NT4 or mixed mode 2k DCs + will not */ + + if ( winbind_lookup_name(NULL, *list, &g_sid, &name_type) + && ( name_type==SID_NAME_DOM_GRP || + (strequal(lp_workgroup(), domain) && name_type==SID_NAME_ALIAS) ) ) + { - /* Check if user name is in the Windows group */ + /* Check if user name is in the Windows group */ ret = user_in_winbind_group_list(user, *list, &winbind_answered); if (winbind_answered && ret == True) { diff --git a/source3/lib/util.c b/source3/lib/util.c index e1ddd57883..a7c939fe5a 100644 --- a/source3/lib/util.c +++ b/source3/lib/util.c @@ -99,7 +99,7 @@ BOOL set_global_myname(const char *myname) smb_myname = strdup(myname); if (!smb_myname) return False; - strupper(smb_myname); + strupper_m(smb_myname); return True; } @@ -118,7 +118,7 @@ BOOL set_global_myworkgroup(const char *myworkgroup) smb_myworkgroup = strdup(myworkgroup); if (!smb_myworkgroup) return False; - strupper(smb_myworkgroup); + strupper_m(smb_myworkgroup); return True; } @@ -137,7 +137,7 @@ BOOL set_global_scope(const char *scope) smb_scope = strdup(scope); if (!smb_scope) return False; - strupper(smb_scope); + strupper_m(smb_scope); return True; } @@ -184,7 +184,7 @@ static BOOL set_my_netbios_names(const char *name, int i) smb_my_netbios_names[i] = strdup(name); if (!smb_my_netbios_names[i]) return False; - strupper(smb_my_netbios_names[i]); + strupper_m(smb_my_netbios_names[i]); return True; } @@ -265,7 +265,7 @@ BOOL init_names(void) p = strchr( local_machine, ' ' ); if (p) *p = 0; - strlower( local_machine ); + strlower_m( local_machine ); DEBUG( 5, ("Netbios name list:-\n") ); for( n=0; my_netbios_names(n); n++ ) @@ -937,6 +937,19 @@ void *Realloc(void *p,size_t size) return(ret); } +void *Realloc_zero(void *ptr, size_t size) +{ + void *tptr = NULL; + + tptr = Realloc(ptr, size); + if(tptr == NULL) + return NULL; + + memset((char *)tptr,'\0',size); + + return tptr; +} + /**************************************************************************** Free memory, checks for NULL. Use directly SAFE_FREE() @@ -1367,7 +1380,7 @@ char *gidtoname(gid_t gid) Convert a user name into a uid. ********************************************************************/ -uid_t nametouid(char *name) +uid_t nametouid(const char *name) { struct passwd *pass; char *p; @@ -1898,6 +1911,17 @@ void dump_data(int level, const char *buf1,int len) } } +void dump_data_pw(const char *msg, const uchar * data, size_t len) +{ +#ifdef DEBUG_PASSWORD + DEBUG(11, ("%s", msg)); + if (data != NULL && len > 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) && i<count; + i++ ) + { struct in_addr addr; + unsigned port = 0; + char *p = strchr(token_str, ':'); + + if (p) { + *p = 0; + port = atoi(p+1); + } /* convert single token to ip address */ if ( (addr.s_addr = inet_addr(token_str)) == INADDR_NONE ) break; - - /* prepare place for another in_addr structure */ - *ip_list = Realloc(*ip_list, (count + 1) * sizeof(struct in_addr)); - if (!*ip_list) return -1; - - (*ip_list)[count] = addr; + + (*ip_list)[i].ip = addr; + (*ip_list)[i].port = port; } return count; @@ -1713,3 +1750,25 @@ char * base64_encode_data_blob(DATA_BLOB data) return result; } +/* read a SMB_BIG_UINT from a string */ +SMB_BIG_UINT STR_TO_SMB_BIG_UINT(const char *nptr, const char **entptr) +{ + + SMB_BIG_UINT val = -1; + const char *p = nptr; + + while (p && *p && isspace(*p)) + p++; +#ifdef LARGE_SMB_OFF_T + sscanf(p,"%llu",&val); +#else /* LARGE_SMB_OFF_T */ + sscanf(p,"%lu",&val); +#endif /* LARGE_SMB_OFF_T */ + if (entptr) { + while (p && *p && isdigit(*p)) + p++; + *entptr = p; + } + + return val; +} diff --git a/source3/lib/util_unistr.c b/source3/lib/util_unistr.c index 5df0828295..ae000fba02 100644 --- a/source3/lib/util_unistr.c +++ b/source3/lib/util_unistr.c @@ -391,8 +391,9 @@ size_t strnlen_w(const smb_ucs2_t *src, size_t max) } /******************************************************************* -wide strchr() + Wide strchr(). ********************************************************************/ + smb_ucs2_t *strchr_w(const smb_ucs2_t *s, smb_ucs2_t c) { while (*s != 0) { @@ -409,6 +410,10 @@ smb_ucs2_t *strchr_wa(const smb_ucs2_t *s, char c) return strchr_w(s, UCS2_CHAR(c)); } +/******************************************************************* + Wide strrchr(). +********************************************************************/ + smb_ucs2_t *strrchr_w(const smb_ucs2_t *s, smb_ucs2_t c) { const smb_ucs2_t *p = s; @@ -422,8 +427,30 @@ smb_ucs2_t *strrchr_w(const smb_ucs2_t *s, smb_ucs2_t c) } /******************************************************************* -wide strstr() + Wide version of strrchr that returns after doing strrchr 'n' times. ********************************************************************/ + +smb_ucs2_t *strnrchr_w(const smb_ucs2_t *s, smb_ucs2_t c, unsigned int n) +{ + const smb_ucs2_t *p = s; + int len = strlen_w(s); + if (len == 0 || !n) + return NULL; + p += (len - 1); + do { + if (c == *p) + n--; + + if (!n) + return (smb_ucs2_t *)p; + } while (p-- != s); + return NULL; +} + +/******************************************************************* + Wide strstr(). +********************************************************************/ + smb_ucs2_t *strstr_w(const smb_ucs2_t *s, const smb_ucs2_t *ins) { smb_ucs2_t *r; diff --git a/source3/lib/util_uuid.c b/source3/lib/util_uuid.c index 699f2cd632..83553ec28e 100644 --- a/source3/lib/util_uuid.c +++ b/source3/lib/util_uuid.c @@ -58,7 +58,7 @@ static void uuid_unpack(const GUID in, struct uuid *uu) memcpy(uu->node, 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 @@ -89,52 +89,6 @@ uint32 ads_uf2atype(uint32 uf) } /* -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 */ uint32 ads_gtype2atype(uint32 gtype) 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;i<count;i++) { - if (ads_try_connect(ads, inet_ntoa(ip_list[i].ip), ip_list[i].port)) { - free(ip_list); + + /* if we fail this loop, then giveup since all the IP addresses returned were dead */ + for ( i=0; i<count; i++ ) { + /* since this is an ads conection request, default to LDAP_PORT is not set */ + int port = (ip_list[i].port!=PORT_NONE) ? ip_list[i].port : LDAP_PORT; + fstring server; + + fstrcpy( server, inet_ntoa(ip_list[i].ip) ); + + if ( !NT_STATUS_IS_OK(check_negative_conn_cache(realm, server)) ) + continue; + + if ( ads_try_connect(ads, server, port) ) { + SAFE_FREE(ip_list); return True; } + + /* keep track of failures */ + add_failed_connection_entry( realm, server, NT_STATUS_UNSUCCESSFUL ); } SAFE_FREE(ip_list); + return False; } -/* try connecting to a ldap server via netbios */ -static BOOL ads_try_netbios(ADS_STRUCT *ads) -{ - struct in_addr *ip_list, pdc_ip; - int count; - int i; - const char *workgroup = ads->server.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;i<count;i++) { - DEBUG(6,("ads_try_netbios: trying server '%s'\n", - inet_ntoa(ip_list[i]))); - if (ads_try_connect(ads, inet_ntoa(ip_list[i]), LDAP_PORT)) { - free(ip_list); - return True; - } - } - free(ip_list); - } - - return False; -} /** * Connect to the LDAP server @@ -244,20 +195,7 @@ ADS_STATUS ads_connect(ADS_STRUCT *ads) goto got_connection; } - /* try with a smb.conf ads server setting if we are connecting - to the primary workgroup or realm */ - if (!ads->server.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 */ @@ -303,17 +305,50 @@ struct cli_state *cli_initialise(struct cli_state *cli) } /**************************************************************************** +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<count; i++ ) { + if ( is_zero_ip(iplist[i].ip) ) + continue; + + for ( j=i+1; j<count; j++ ) { + if ( ip_service_equal(iplist[i], iplist[j]) ) + zero_ip(&iplist[j].ip); + } + } + + /* one loop to clean up any holes we left */ + /* first ip should never be a zero_ip() */ + for (i = 0; i<count; ) { + if ( is_zero_ip(iplist[i].ip) ) { + if (i != count-1 ) + memmove(&iplist[i], &iplist[i+1], (count - i - 1)*sizeof(iplist[i])); + count--; + continue; + } + i++; + } + + return count; +} /**************************************************************************** Do a netbios name query to find someones IP. @@ -264,6 +343,7 @@ static void sort_ip_list(struct in_addr *iplist, int count) *count will be set to the number of addresses returned. *timed_out is set if we failed by timing out ****************************************************************************/ + struct in_addr *name_query(int fd,const char *name,int name_type, BOOL bcast,BOOL recurse, struct in_addr to_ip, int *count, int *flags, @@ -436,7 +516,9 @@ struct in_addr *name_query(int fd,const char *name,int name_type, } } - if (timed_out) { + /* only set timed_out if we didn't fund what we where looking for*/ + + if ( !found && timed_out ) { *timed_out = True; } @@ -556,23 +638,49 @@ void endlmhosts(XFILE *fp) x_fclose(fp); } +/******************************************************** + convert an array if struct in_addrs to struct ip_service + return False on failure. Port is set to PORT_NONE; +*********************************************************/ + +static BOOL convert_ip2service( struct ip_service **return_iplist, struct in_addr *ip_list, int count ) +{ + int i; + + if ( count==0 || !ip_list ) + return False; + + /* copy the ip address; port will be PORT_NONE */ + if ( (*return_iplist = (struct ip_service*)malloc(count*sizeof(struct ip_service))) == NULL ) { + DEBUG(0,("convert_ip2service: malloc failed for %d enetries!\n", count )); + return False; + } + + for ( i=0; i<count; i++ ) { + (*return_iplist)[i].ip = ip_list[i]; + (*return_iplist)[i].port = PORT_NONE; + } + return True; +} /******************************************************** Resolve via "bcast" method. *********************************************************/ BOOL name_resolve_bcast(const char *name, int name_type, - struct in_addr **return_ip_list, int *return_count) + struct ip_service **return_iplist, int *return_count) { int sock, i; int num_interfaces = iface_count(); + struct in_addr *ip_list; + BOOL ret; if (lp_disable_netbios()) { DEBUG(5,("name_resolve_bcast(%s#%02x): netbios is disabled\n", name, name_type)); return False; } - *return_ip_list = NULL; + *return_iplist = NULL; *return_count = 0; /* @@ -596,27 +704,38 @@ BOOL name_resolve_bcast(const char *name, int name_type, int flags; /* Done this way to fix compiler error on IRIX 5.x */ sendto_ip = *iface_n_bcast(i); - *return_ip_list = name_query(sock, name, name_type, True, + ip_list = name_query(sock, name, name_type, True, True, sendto_ip, return_count, &flags, NULL); - if(*return_ip_list != NULL) { - close(sock); - return True; - } + if( ip_list ) + goto success; } - + + /* failed - no response */ + close(sock); return False; + +success: + ret = True; + if ( !convert_ip2service(return_iplist, ip_list, *return_count) ) + ret = False; + + SAFE_FREE( ip_list ); + close(sock); + return ret; } /******************************************************** Resolve via "wins" method. *********************************************************/ + BOOL resolve_wins(const char *name, int name_type, - struct in_addr **return_iplist, int *return_count) + struct ip_service **return_iplist, int *return_count) { int sock, t, i; char **wins_tags; - struct in_addr src_ip; + struct in_addr src_ip, *ip_list = NULL; + BOOL ret; if (lp_disable_netbios()) { DEBUG(5,("resolve_wins(%s#%02x): netbios is disabled\n", name, name_type)); @@ -672,12 +791,15 @@ BOOL resolve_wins(const char *name, int name_type, continue; } - *return_iplist = name_query(sock,name,name_type, False, + ip_list = name_query(sock,name,name_type, False, True, wins_ip, return_count, &flags, &timed_out); - if (*return_iplist != NULL) { + + /* exit loop if we got a list of addresses */ + + if ( ip_list ) goto success; - } + close(sock); if (timed_out) { @@ -695,9 +817,15 @@ BOOL resolve_wins(const char *name, int name_type, return False; success: + ret = True; + if ( !convert_ip2service( return_iplist, ip_list, *return_count ) ) + ret = False; + + SAFE_FREE( ip_list ); wins_srv_tags_free(wins_tags); close(sock); - return True; + + return ret; } /******************************************************** @@ -705,7 +833,7 @@ success: *********************************************************/ static BOOL resolve_lmhosts(const char *name, int name_type, - struct in_addr **return_iplist, int *return_count) + struct ip_service **return_iplist, int *return_count) { /* * "lmhosts" means parse the local lmhosts file. @@ -728,12 +856,12 @@ static BOOL resolve_lmhosts(const char *name, int name_type, ((name_type2 == -1) || (name_type == name_type2)) ) { endlmhosts(fp); - *return_iplist = (struct in_addr *)malloc(sizeof(struct in_addr)); - if(*return_iplist == NULL) { + if ( (*return_iplist = (struct ip_service *)malloc(sizeof(struct ip_service))) == NULL ) { DEBUG(3,("resolve_lmhosts: malloc fail !\n")); return False; } - **return_iplist = return_ip; + (*return_iplist)[0].ip = return_ip; + (*return_iplist)[0].port = PORT_NONE; *return_count = 1; return True; } @@ -748,13 +876,67 @@ static BOOL resolve_lmhosts(const char *name, int name_type, Resolve via "hosts" method. *********************************************************/ -static BOOL resolve_hosts(const char *name, - struct in_addr **return_iplist, int *return_count) +static BOOL resolve_hosts(const char *name, int name_type, + struct ip_service **return_iplist, int *return_count) { /* * "host" means do a localhost, or dns lookup. */ struct hostent *hp; + +#ifdef HAVE_ADS + if ( name_type == 0x1c ) { + int count, i = 0; + char *list = NULL; + const char *ptr; + pstring tok; + + /* try to lookup the _ldap._tcp.<domain> 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.<domain> 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; i<count; i++) { - char *ip_str = inet_ntoa(ip_list[i]); + char *ip_str = inet_ntoa(ip_list[i].ip); if (ip_str && strcmp(ip_str, "255.255.255.255") != 0 && - strcmp(ip_str, "0.0.0.0") != 0) { - *return_ip = ip_list[i]; + strcmp(ip_str, "0.0.0.0") != 0) + { + *return_ip = ip_list[i].ip; SAFE_FREE(ip_list); return True; } } } + SAFE_FREE(ip_list); return False; } @@ -974,7 +1151,7 @@ BOOL resolve_name(const char *name, struct in_addr *return_ip, int name_type) BOOL find_master_ip(const char *group, struct in_addr *master_ip) { - struct in_addr *ip_list = NULL; + struct ip_service *ip_list = NULL; int count = 0; if (lp_disable_netbios()) { @@ -982,13 +1159,13 @@ BOOL find_master_ip(const char *group, struct in_addr *master_ip) return False; } - if (internal_resolve_name(group, 0x1D, &ip_list, &count)) { - *master_ip = ip_list[0]; + if (internal_resolve_name(group, 0x1D, &ip_list, &count, lp_name_resolve_order())) { + *master_ip = ip_list[0].ip; SAFE_FREE(ip_list); return True; } - if(internal_resolve_name(group, 0x1B, &ip_list, &count)) { - *master_ip = ip_list[0]; + if(internal_resolve_name(group, 0x1B, &ip_list, &count, lp_name_resolve_order())) { + *master_ip = ip_list[0].ip; SAFE_FREE(ip_list); return True; } @@ -998,285 +1175,87 @@ BOOL find_master_ip(const char *group, struct in_addr *master_ip) } /******************************************************** - Lookup a DC name given a Domain name and IP address. -*********************************************************/ - -BOOL lookup_dc_name(const char *srcname, const char *domain, - struct in_addr *dc_ip, char *ret_name) -{ -#if !defined(I_HATE_WINDOWS_REPLY_CODE) - fstring dc_name; - BOOL ret; - - if (lp_disable_netbios()) { - DEBUG(5,("lookup_dc_name(%s): netbios is disabled\n", domain)); - return False; - } - - /* - * Due to the fact win WinNT *sucks* we must do a node status - * query here... JRA. - */ - - *dc_name = '\0'; - - ret = name_status_find(domain, 0x1c, 0x20, *dc_ip, dc_name); - - if(ret && *dc_name) { - fstrcpy(ret_name, dc_name); - return True; - } - - return False; - -#else /* defined(I_HATE_WINDOWS_REPLY_CODE) */ - -JRA - This code is broken with BDC rollover - we need to do a full -NT GETDC call, UNICODE, NT domain SID and uncle tom cobbley and all... - - int retries = 3; - int retry_time = 2000; - struct timeval tval; - struct packet_struct p; - struct dgram_packet *dgram = &p.packet.dgram; - char *ptr,*p2; - char tmp[4]; - int len; - struct sockaddr_in sock_name; - int sock_len = sizeof(sock_name); - const char *mailslot = NET_LOGON_MAILSLOT; - char *mailslot_name; - char buffer[1024]; - char *bufp; - int dgm_id = generate_trn_id(); - int sock = open_socket_in(SOCK_DGRAM, 0, 3, interpret_addr(lp_socket_address()), True ); - - if(sock == -1) - return False; - - /* Find out the transient UDP port we have been allocated. */ - if(getsockname(sock, (struct sockaddr *)&sock_name, &sock_len)<0) { - DEBUG(0,("lookup_pdc_name: Failed to get local UDP port. Error was %s\n", - strerror(errno))); - close(sock); - return False; - } - - /* - * Create the request data. - */ - - memset(buffer,'\0',sizeof(buffer)); - bufp = buffer; - SSVAL(bufp,0,QUERYFORPDC); - bufp += 2; - fstrcpy(bufp,srcname); - bufp += (strlen(bufp) + 1); - slprintf(bufp, sizeof(fstring)-1, "\\MAILSLOT\\NET\\GETDC%d", dgm_id); - mailslot_name = bufp; - bufp += (strlen(bufp) + 1); - bufp = ALIGN2(bufp, buffer); - bufp += push_ucs2(NULL, bufp, srcname, sizeof(buffer) - (bufp - buffer), STR_TERMINATE); - - SIVAL(bufp,0,1); - SSVAL(bufp,4,0xFFFF); - SSVAL(bufp,6,0xFFFF); - bufp += 8; - len = PTR_DIFF(bufp,buffer); - - memset((char *)&p,'\0',sizeof(p)); - - /* DIRECT GROUP or UNIQUE datagram. */ - dgram->header.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. *********************************************************/ 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<count; i++ ) { - if ( is_local_net( ip_list[i] ) ) - break; - } - - /* if we hit then end then just grab the first - one from the list */ - - if ( i == count ) - i = 0; + DEBUG(6,("get_pdc_ip: PDC has %d IP addresses!\n", count)); + sort_ip_list2( ip_list, count ); } - *ip = ip_list[i]; + *ip = ip_list[0].ip; SAFE_FREE(ip_list); return True; } +/********************************************************************* + small wrapper function to get the DC list and sort it if neccessary +*********************************************************************/ +BOOL get_sorted_dc_list( const char *domain, struct ip_service **ip_list, int *count, BOOL dns_only ) +{ + BOOL ordered; + + DEBUG(8,("get_sorted_dc_list: attempting lookup using [%s]\n", + (dns_only ? "hosts" : lp_name_resolve_order()))); + + if ( !get_dc_list(domain, ip_list, count, dns_only, &ordered) ) + return False; + + /* only sort if we don't already have an ordered list */ + if ( !ordered ) + sort_ip_list2( *ip_list, *count ); + + return True; +} + /******************************************************** Get the IP address list of the domain controllers for a domain. *********************************************************/ -BOOL get_dc_list(const char *domain, struct in_addr **ip_list, int *count, int *ordered) +BOOL get_dc_list(const char *domain, struct ip_service **ip_list, + int *count, BOOL dns_only, int *ordered) { - + /* defined the name resolve order to internal_name_resolve() + only used for looking up 0x1c names */ + const char *resolve_oder = (dns_only ? "hosts" : lp_name_resolve_order()); + *ordered = False; /* If it's our domain then use the 'password server' parameter. */ - if (strequal(domain, lp_workgroup())) { + if ( strequal(domain, lp_workgroup()) || strequal(domain, lp_realm()) ) { const char *p; char *pserver = lp_passwordserver(); /* UNIX charset. */ + char *port_str; + int port; fstring name; int num_addresses = 0; int local_count, i, j; - struct in_addr *return_iplist = NULL; - struct in_addr *auto_ip_list = NULL; + struct ip_service *return_iplist = NULL; + struct ip_service *auto_ip_list = NULL; BOOL done_auto_lookup = False; int auto_count = 0; if (!*pserver) - return internal_resolve_name( - domain, 0x1C, ip_list, count); + return internal_resolve_name(domain, 0x1C, ip_list, count, resolve_oder); p = pserver; @@ -1289,7 +1268,7 @@ BOOL get_dc_list(const char *domain, struct in_addr **ip_list, int *count, int * while (next_token(&p,name,LIST_SEP,sizeof(name))) { if (strequal(name, "*")) { - if ( internal_resolve_name(domain, 0x1C, &auto_ip_list, &auto_count) ) + if ( internal_resolve_name(domain, 0x1C, &auto_ip_list, &auto_count, resolve_oder) ) num_addresses += auto_count; done_auto_lookup = True; DEBUG(8,("Adding %d DC's from auto lookup\n", auto_count)); @@ -1302,11 +1281,18 @@ BOOL get_dc_list(const char *domain, struct in_addr **ip_list, int *count, int * just return the list of DC's */ if ( (num_addresses == 0) && !done_auto_lookup ) - return internal_resolve_name(domain, 0x1C, ip_list, count); + return internal_resolve_name(domain, 0x1C, ip_list, count, resolve_oder); - return_iplist = (struct in_addr *)malloc(num_addresses * sizeof(struct in_addr)); - - if (return_iplist == NULL) { + /* maybe we just failed? */ + + if ( num_addresses == 0 ) { + DEBUG(4,("get_dc_list: no servers found\n")); + return False; + } + + if ( (return_iplist = (struct ip_service *) + malloc(num_addresses * sizeof(struct ip_service))) == NULL ) + { DEBUG(3,("get_dc_list: malloc fail !\n")); return False; } @@ -1322,59 +1308,59 @@ BOOL get_dc_list(const char *domain, struct in_addr **ip_list, int *count, int * /* copy any addersses from the auto lookup */ if ( strequal(name, "*") ) { - for ( j=0; j<auto_count; j++ ) - return_iplist[local_count++] = auto_ip_list[j]; + for ( j=0; j<auto_count; j++ ) { + return_iplist[local_count].ip = auto_ip_list[j].ip; + return_iplist[local_count].port = auto_ip_list[j].port; + local_count++; + } continue; } + + /* added support for address:port syntax for ads (not that I think + anyone will ever run the LDAP server in an AD domain on something + other than port 389 */ + + port = (lp_security() == SEC_ADS) ? LDAP_PORT : PORT_NONE; + if ( (port_str=strchr(name, ':')) != NULL ) { + *port_str = '\0'; + port_str++; + port = atoi( port_str ); + } + /* explicit lookup; resolve_name() will handle names & IP addresses */ - - if ( resolve_name( name, &name_ip, 0x20) ) { - return_iplist[local_count++] = name_ip; + if ( resolve_name( name, &name_ip, 0x20 ) ) { + return_iplist[local_count].ip = name_ip; + return_iplist[local_count].port = port; + local_count++; *ordered = True; } - } SAFE_FREE(auto_ip_list); - /* need to remove duplicates in the list if we have - any explicit password servers */ + /* need to remove duplicates in the list if we have any + explicit password servers */ - if ( *ordered ) { - /* one loop to remove duplicates */ - for ( i=0; i<local_count; i++ ) { - if ( is_zero_ip(return_iplist[i]) ) - continue; - - for ( j=i+1; j<local_count; j++ ) { - if ( ip_equal( return_iplist[i], return_iplist[j]) ) - zero_ip(&return_iplist[j]); - } - } - - /* one loop to clean up any holes we left */ - /* first ip should never be a zero_ip() */ - for (i = 0; i<local_count; ) { - if ( is_zero_ip(return_iplist[i]) ) { - if (i != local_count-1 ) - memmove(&return_iplist[i], &return_iplist[i+1], - (local_count - i - 1)*sizeof(return_iplist[i])); - local_count--; - continue; - } - i++; - } - } + if ( local_count ) + local_count = remove_duplicate_addrs2( return_iplist, local_count ); + if ( DEBUGLEVEL >= 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; i<local_count; i++ ) + DEBUGADD(4,("%s:%d ", inet_ntoa(return_iplist[i].ip), return_iplist[i].port )); + DEBUGADD(4,("\n")); + } + *ip_list = return_iplist; *count = local_count; - - DEBUG(8,("get_dc_list: return %d ip addresses\n", *count)); return (*count != 0); } - return internal_resolve_name(domain, 0x1C, ip_list, count); + DEBUG(10,("get_dc_list: defaulting to internal auto lookup for domain %s\n", domain)); + + return internal_resolve_name(domain, 0x1C, ip_list, count, resolve_oder); } - diff --git a/source3/libsmb/namequery_dc.c b/source3/libsmb/namequery_dc.c index ffc64139e9..c9d45a7acc 100644 --- a/source3/libsmb/namequery_dc.c +++ b/source3/libsmb/namequery_dc.c @@ -5,6 +5,7 @@ Copyright (C) Tim Potter 2001 Copyright (C) Andrew Bartlett 2002 + 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 @@ -24,16 +25,60 @@ #include "includes.h" +/************************************************************************** + Find the name and IP address for a server in he realm/domain + *************************************************************************/ + +static BOOL ads_dc_name(const char *domain, struct in_addr *dc_ip, fstring srv_name) +{ + ADS_STRUCT *ads; + const char *realm = domain; -/* - find the DC for a domain using methods appropriate for a RPC domain -*/ -BOOL rpc_find_dc(const char *domain, fstring srv_name, struct in_addr *ip_out) + 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,("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; @@ -235,97 +311,6 @@ BOOL cli_simple_set_signing(struct cli_state *cli, const uchar user_session_key[ } /*********************************************************** - 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; i<num_domains; i++ ) { + trustdom_cache_store( domain_names[i], NULL, &dom_sids[i], + now+TRUSTDOM_UPDATE_INTERVAL); + } + + trustdom_cache_store_timestamp( now, now+TRUSTDOM_UPDATE_INTERVAL ); + } + +done: + /* unlock and we're done */ + trustdom_cache_unlock_timestamp(); + + talloc_destroy( mem_ctx ); + + return; +} diff --git a/source3/libsmb/trusts_util.c b/source3/libsmb/trusts_util.c index 6244c844f2..77e63709aa 100644 --- a/source3/libsmb/trusts_util.c +++ b/source3/libsmb/trusts_util.c @@ -1,4 +1,4 @@ -/* +/* * Unix SMB/CIFS implementation. * Routines to operate on various trust relationships * Copyright (C) Andrew Bartlett 2001 @@ -123,47 +123,68 @@ NTSTATUS trust_pw_find_change_and_store_it(struct cli_state *cli, } +/********************************************************************* + Enumerate the list of trusted domains from a DC +*********************************************************************/ -/** - * 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) +BOOL enumerate_domain_trusts( TALLOC_CTX *mem_ctx, const char *domain, + char ***domain_names, uint32 *num_domains, + DOM_SID **sids ) { - DOM_SID trustdom_sid; - char *pass = NULL; - time_t lct; - BOOL ret; - - if (lp_server_role() == ROLE_DOMAIN_BDC || lp_server_role() == ROLE_DOMAIN_PDC) { - /* - * Query the secrets db as an ultimate source of information - * about trusted domain names. This is PDC or BDC case. - */ - ret = secrets_fetch_trusted_domain_password(dom_name, &pass, &trustdom_sid, &lct); - SAFE_FREE(pass); - if (ret) - return ret; + POLICY_HND pol; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + fstring dc_name; + struct in_addr dc_ip; + uint32 enum_ctx = 0; + struct cli_state *cli = NULL; + BOOL retry; + + *domain_names = NULL; + *num_domains = 0; + *sids = NULL; + + /* lookup a DC first */ + + if ( !get_dc_name(domain, dc_name, &dc_ip) ) { + DEBUG(3,("enumerate_domain_trusts: can't locate a DC for domain %s\n", + domain)); + return False; } - /* - * Query the trustdom_cache updated periodically. The only - * way for domain member server. - */ - if (trustdom_cache_enable() && - trustdom_cache_fetch(dom_name, &trustdom_sid)) { - trustdom_cache_shutdown(); - return True; + /* setup the anonymous connection */ + + result = cli_full_connection( &cli, global_myname(), dc_name, &dc_ip, 0, "IPC$", "IPC", + "", "", "", 0, &retry); + if ( !NT_STATUS_IS_OK(result) ) + goto done; + + /* open the LSARPC_PIPE */ + + if ( !cli_nt_session_open( cli, PI_LSARPC ) ) { + result = NT_STATUS_UNSUCCESSFUL; + goto done; } - /* - * if nothing's been found, then give up here, although - * the last resort might be to query the PDC. - */ - return False; + /* get a handle */ + + result = cli_lsa_open_policy(cli, mem_ctx, True, + POLICY_VIEW_LOCAL_INFORMATION, &pol); + if ( !NT_STATUS_IS_OK(result) ) + goto done; + + /* Lookup list of trusted domains */ + + result = cli_lsa_enum_trust_dom(cli, mem_ctx, &pol, &enum_ctx, + num_domains, domain_names, sids); + if ( !NT_STATUS_IS_OK(result) ) + goto done; + +done: + /* cleanup */ + + cli_nt_session_close( cli ); + cli_shutdown( cli ); + + return NT_STATUS_IS_OK(result); } diff --git a/source3/locking/posix.c b/source3/locking/posix.c index 2b64631d39..6173c80b2f 100644 --- a/source3/locking/posix.c +++ b/source3/locking/posix.c @@ -205,7 +205,7 @@ int fd_close_posix(struct connection_struct *conn, files_struct *fsp) /* * No POSIX to worry about, just close. */ - ret = conn->vfs_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 <stdio.h> -#include <sys/stat.h> -#ifdef HAVE_UTIME_H -#include <utime.h> -#endif -#ifdef HAVE_DIRENT_H -#include <dirent.h> -#endif -#include <syslog.h> -#ifdef HAVE_FCNTL_H -#include <fcntl.h> -#endif -#include <errno.h> -#include <string.h> -#include <includes.h> -#include <vfs.h> - -#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 <stdio.h> -#include <sys/stat.h> -#ifdef HAVE_UTIME_H -#include <utime.h> -#endif -#ifdef HAVE_DIRENT_H -#include <dirent.h> -#endif -#include <syslog.h> -#ifdef HAVE_FCNTL_H -#include <fcntl.h> -#endif -#include <errno.h> -#include <string.h> -#include <includes.h> -#include <vfs.h> - -#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 <stdio.h> -#include <sys/stat.h> -#ifdef HAVE_UTIME_H -#include <utime.h> -#endif -#ifdef HAVE_DIRENT_H -#include <dirent.h> -#endif -#ifdef HAVE_FCNTL_H -#include <fcntl.h> -#endif -#include <errno.h> -#include <string.h> +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_VFS -#include <includes.h> -#include <vfs.h> - -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 <stdio.h> -#include <sys/stat.h> -#ifdef HAVE_UTIME_H -#include <utime.h> -#endif -#ifdef HAVE_DIRENT_H -#include <dirent.h> -#endif -#ifdef HAVE_FCNTL_H -#include <fcntl.h> -#endif -#include <errno.h> -#include <string.h> -#include <includes.h> -#include <vfs.h> +#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 @@ -299,12 +299,35 @@ static BOOL reload_nmbd_services(BOOL test) } /**************************************************************************** ** + * 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. **************************************************************************** */ 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; i<num_members; i++ ) + len += strlen(members[i])+1; + + *buffer = (char*)smb_xmalloc(len); + for ( i=0; i<num_members; i++ ) { + snprintf( &(*buffer)[idx], len-idx, "%s,", members[i]); + idx += strlen(members[i])+1; + } + /* terminate with NULL */ + (*buffer)[len-1] = '\0'; + + return len; +} + /*************************************************************** Empty static struct for negative caching. ****************************************************************/ @@ -75,9 +104,12 @@ static BOOL fill_grent_mem(struct winbindd_domain *domain, *num_gr_mem = 0; - if (group_name_type != SID_NAME_DOM_GRP) { - DEBUG(1, ("SID %s in domain %s isn't a domain group\n", - sid_to_string(sid_string, group_sid), domain->name)); + 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 <ldap.h> + +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 <lber.h> #include <ldap.h> -#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; } /********************************************************************** @@ -287,52 +130,6 @@ static const char* get_userattr_key2string( int schema_ver, int key ) } /********************************************************************** - 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,617 +149,6 @@ 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); - - *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) -{ - 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; - } - -#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) - { - 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 - } - - DEBUG(2, ("ldapsam_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 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)); - - *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 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? */ - - 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, static_ldap_state); - -} -# endif /*LDAP_SET_REBIND_PROC_ARGS == 2*/ -#endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/ - -/******************************************************************* - a rebind function for authenticated referrals - this also does the connection, but no void*. -******************************************************************/ -#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000) -# if LDAP_SET_REBIND_PROC_ARGS == 2 -static int rebindproc_connect (LDAP * ld, LDAP_CONST char *url, int request, - ber_int_t msgid) -{ - return rebindproc_connect_with_state(ld, url, (ber_tag_t)request, msgid, - static_ldap_state); -} -# endif /*LDAP_SET_REBIND_PROC_ARGS == 2*/ -#endif /*defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)*/ - -/******************************************************************* - connect to the ldap server under system privilege. -******************************************************************/ -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) -{ - 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; - } - - DEBUG(5,("The connection to the LDAP server was closed\n")); - /* maybe free the results here --metze */ - - return NT_STATUS_OK; -} - -static int ldapsam_retry_open(struct ldapsam_privates *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 = 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; - - 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)); - ldapsam_close(ldap_state); - } - - SAFE_FREE(utf8_filter); - return rc; -} - -static int ldapsam_modify(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_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 @@ -981,7 +167,7 @@ static const char* get_objclass_filter( int schema_ver ) 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")); + DEBUG(0,("pdb_ldapsam: get_objclass_filter(): Invalid schema version specified!\n")); break; } @@ -991,8 +177,9 @@ static const char* get_objclass_filter( int schema_ver ) /******************************************************************* run the search by name. ******************************************************************/ -static int ldapsam_search_suffix_by_name (struct ldapsam_privates *ldap_state, const char *user, - LDAPMessage ** result, char **attr) +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); @@ -1017,25 +204,23 @@ static int ldapsam_search_suffix_by_name (struct ldapsam_privates *ldap_state, c all_string_sub(filter, "%u", escape_user, sizeof(pstring)); SAFE_FREE(escape_user); - return ldapsam_search_suffix(ldap_state, filter, attr, result); + return smbldap_search_suffix(ldap_state->smbldap_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) + 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); + rc = smbldap_search_suffix(ldap_state->smbldap_state, filter, attr, result); return rc; } @@ -1044,199 +229,24 @@ static int ldapsam_search_suffix_by_rid (struct ldapsam_privates *ldap_state, 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) + 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); + rc = smbldap_search_suffix(ldap_state->smbldap_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] = [<does not exist>]\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 ******************************************************************/ @@ -1251,19 +261,19 @@ static NTSTATUS ldapsam_delete_entry(struct ldapsam_privates *ldap_state, 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); + entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result); + dn = ldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry); if (lp_ldap_delete_dn()) { NTSTATUS ret = NT_STATUS_OK; - rc = ldapsam_delete(ldap_state, dn); + rc = smbldap_delete(ldap_state->smbldap_state, dn); if (rc != LDAP_SUCCESS) { DEBUG(0, ("Could not delete object %s\n", dn)); @@ -1275,9 +285,9 @@ static NTSTATUS ldapsam_delete_entry(struct ldapsam_privates *ldap_state, /* Ok, delete only the SAM attributes */ - for (name = ldap_first_attribute(ldap_state->ldap_struct, entry, &ptr); + for (name = ldap_first_attribute(ldap_state->smbldap_state->ldap_struct, entry, &ptr); name != NULL; - name = ldap_next_attribute(ldap_state->ldap_struct, entry, ptr)) + name = ldap_next_attribute(ldap_state->smbldap_state->ldap_struct, entry, ptr)) { char **attrib; @@ -1288,7 +298,7 @@ static NTSTATUS ldapsam_delete_entry(struct ldapsam_privates *ldap_state, { if (StrCaseCmp(*attrib, name) == 0) { DEBUG(10, ("deleting attribute %s\n", name)); - make_a_mod(&mods, LDAP_MOD_DELETE, name, NULL); + smbldap_set_mod(&mods, LDAP_MOD_DELETE, name, NULL); } } @@ -1299,14 +309,14 @@ static NTSTATUS ldapsam_delete_entry(struct ldapsam_privates *ldap_state, ber_free(ptr, 0); } - make_a_mod(&mods, LDAP_MOD_DELETE, "objectClass", objectclass); + smbldap_set_mod(&mods, LDAP_MOD_DELETE, "objectClass", objectclass); - 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, ("could not delete attributes for %s, error: %s (%s)\n", @@ -1319,511 +329,7 @@ static NTSTATUS ldapsam_delete_entry(struct ldapsam_privates *ldap_state, 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; - } - - if (!string_to_sid(&dom_sid, domain_sid_string)) { - ldap_mods_free(mods, 1); - ldap_memfree(dn); - ldap_msgfree(result); - return ret; - } - - ldap_mods_free(mods, 1); - mods = NULL; - ldap_memfree(dn); - ldap_msgfree(result); - - sid_copy(&sid, &dom_sid); - sid_append_rid(&sid, *rid); - - /* check RID is not in use */ - if (sid_in_use(ldap_state, &sid, &error)) { - if (error) { - return ret; - } - continue; - } - - 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_mods_free(mods, 1); - mods = NULL; - - 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); - } - } - - DEBUG(0, ("Failed to set new RID\n")); - return ret; -} + /* 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,44 +1592,20 @@ 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 */ -} - -/********************************************************************** *********************************************************************/ static int ldapsam_search_one_group (struct ldapsam_privates *ldap_state, @@ -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; - /* check for non-unix account ranges */ + /* 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; + } - if (lp_idmap_uid(&low_idmap_uid, &high_idmap_uid) - && lp_idmap_gid(&low_idmap_gid, &high_idmap_gid)) - { - DEBUG(2, ("Enabling non-unix account ranges\n")); + /* 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; + } - ldap_state->permit_non_unix_accounts = True; + 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)) + { + 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;i<count;i++) { - array->sids[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;i<array->count;i++) { - if(!prs_uint32("ref_id", ps, depth, &array->sids[i].ref_id)) - return False; - } - - for (i=0;i<array->count;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 @@ -603,15 +603,6 @@ BOOL smb_io_rpc_hdr_autha(const char *desc, RPC_HDR_AUTHA *rai, prs_struct *ps, } /******************************************************************* - 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;i<num_rights;i++) { - free(rights[i]); - } - safe_free(rights); - - return r_u->status; -} - -/*************************************************************************** -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;i<q_u->rights.count;i++) { - DEBUG(5,("\t%s\n", unistr2_static(&q_u->rights.strings[i].string))); - } - - - for (i=0;i<q_u->rights.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;i<q_u->rights.count;i++) { - DEBUG(5,("\t%s\n", unistr2_static(&q_u->rights.strings[i].string))); - } - - for (i=0;i<q_u->rights.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; i<info->disp_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; i<group_entries; i++) { - - grp_array[i].grp=(DOMAIN_GRP *)talloc(mem_ctx, sizeof(DOMAIN_GRP)); - - fstrcpy(grp_array[i].grp->name, 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)) @@ -2738,6 +2744,41 @@ static BOOL set_user_info_12(SAM_USER_INFO_12 *id12, DOM_SID *sid) } /******************************************************************* + 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; i<count && found==False; i++) { - if (queue[i].job==(int)jobid) + if ((*queue)[i].job==(int)jobid) found=True; } @@ -8463,7 +8498,7 @@ static WERROR getjob_level_1(print_queue_struct *queue, int count, int snum, uin return WERR_INVALID_PARAM; } - fill_job_info_1(info_1, &(queue[i-1]), i, snum); + fill_job_info_1(info_1, &((*queue)[i-1]), i, snum); *needed += spoolss_size_job_info_1(info_1); @@ -8485,7 +8520,7 @@ static WERROR getjob_level_1(print_queue_struct *queue, int count, int snum, uin /**************************************************************************** ****************************************************************************/ -static WERROR getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed) +static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed) { int i = 0; BOOL found = False; @@ -8506,7 +8541,7 @@ static WERROR getjob_level_2(print_queue_struct *queue, int count, int snum, uin for ( i=0; i<count && found==False; i++ ) { - if (queue[i].job == (int)jobid) + if ((*queue)[i].job == (int)jobid) found = True; } @@ -8537,7 +8572,7 @@ static WERROR getjob_level_2(print_queue_struct *queue, int count, int snum, uin } } - fill_job_info_2(info_2, &(queue[i-1]), i, snum, ntprinter, devmode); + fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode); *needed += spoolss_size_job_info_2(info_2); @@ -8601,11 +8636,11 @@ WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_ switch ( level ) { case 1: - wstatus = getjob_level_1(queue, count, snum, jobid, + wstatus = getjob_level_1(&queue, count, snum, jobid, buffer, offered, needed); break; case 2: - wstatus = getjob_level_2(queue, count, snum, jobid, + wstatus = getjob_level_2(&queue, count, snum, jobid, buffer, offered, needed); break; default: @@ -9143,12 +9178,12 @@ static WERROR getprintprocessordirectory_level_1(UNISTR2 *name, { pstring path; pstring long_archi; - pstring short_archi; + const char *short_archi; PRINTPROCESSOR_DIRECTORY_1 *info=NULL; unistr2_to_ascii(long_archi, 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=(PRINTPROCESSOR_DIRECTORY_1 *)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1))) == NULL) diff --git a/source3/rpc_server/srv_srvsvc_nt.c b/source3/rpc_server/srv_srvsvc_nt.c index 4d9130fb97..ea66a7d38b 100644 --- a/source3/rpc_server/srv_srvsvc_nt.c +++ b/source3/rpc_server/srv_srvsvc_nt.c @@ -432,10 +432,13 @@ static void init_srv_share_info_1004(pipes_struct *p, SRV_SHARE_INFO_1004* sh100 static void init_srv_share_info_1005(pipes_struct *p, SRV_SHARE_INFO_1005* sh1005, int snum) { - sh1005->dfs_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<num_groups;i++) { - if(!get_group_from_gid(groups[i], &map, MAPPING_WITHOUT_PRIV)) { + + if (!get_group_from_gid(groups[i], &map)) { DEBUG(10,("get_alias_user_groups: gid %d. not found\n", (int)groups[i])); continue; } /* if it's not an alias, continue */ - if (map.sid_name_use!=SID_NAME_ALIAS) { + if (map.sid_name_use != SID_NAME_ALIAS) { DEBUG(10,("get_alias_user_groups: not returing %s, not an ALIAS group.\n", map.nt_name)); continue; } @@ -194,7 +197,9 @@ NTSTATUS get_alias_user_groups(TALLOC_CTX *ctx, DOM_SID *sid, int *numgroups, ui break; } - free(groups); + unbecome_root(); + + if(num_groups) free(groups); /* now check for the user's gid (the primary group rid) */ for (i=0; i<cur_rid && grid!=rids[i]; i++) @@ -208,11 +213,15 @@ NTSTATUS get_alias_user_groups(TALLOC_CTX *ctx, DOM_SID *sid, int *numgroups, ui DEBUG(10,("get_alias_user_groups: looking for gid %d of user %s\n", (int)gid, user_name)); - if(!get_group_from_gid(gid, &map, MAPPING_WITHOUT_PRIV)) { + become_root(); + + if(!get_group_from_gid(gid, &map)) { DEBUG(0,("get_alias_user_groups: gid of user %s doesn't exist. Check your /etc/passwd and /etc/group files\n", user_name)); goto done; } + unbecome_root(); + /* the primary group isn't an alias */ if (map.sid_name_use!=SID_NAME_ALIAS) { DEBUG(10,("get_alias_user_groups: not returing %s, not an ALIAS group.\n", map.nt_name)); @@ -280,11 +289,17 @@ BOOL get_domain_user_groups(TALLOC_CTX *ctx, int *numgroups, DOM_GID **pgids, SA DEBUG(10,("get_domain_user_groups: searching domain groups [%s] is a member of\n", user_name)); + /* we must wrap this is become/unbecome root for ldap backends */ + become_root(); + /* first get the list of the domain groups */ - if (!pdb_enum_group_mapping(SID_NAME_DOM_GRP, &map, &num_entries, ENUM_ONLY_MAPPED, MAPPING_WITHOUT_PRIV)) + if (!pdb_enum_group_mapping(SID_NAME_DOM_GRP, &map, &num_entries, ENUM_ONLY_MAPPED)) return False; DEBUG(10,("get_domain_user_groups: there are %d mapped groups\n", num_entries)); + unbecome_root(); + /* end wrapper for group enumeration */ + /* * alloc memory. In the worse case, we alloc memory for nothing. * but I prefer to alloc for nothing diff --git a/source3/rpc_server/srv_wkssvc_nt.c b/source3/rpc_server/srv_wkssvc_nt.c index bda7b14a42..25fa029237 100644 --- a/source3/rpc_server/srv_wkssvc_nt.c +++ b/source3/rpc_server/srv_wkssvc_nt.c @@ -40,10 +40,10 @@ static void create_wks_info_100(WKS_INFO_100 *inf) DEBUG(5,("create_wks_info_100: %d\n", __LINE__)); pstrcpy (my_name, global_myname()); - strupper(my_name); + strupper_m(my_name); pstrcpy (domain, lp_workgroup()); - strupper(domain); + strupper_m(domain); init_wks_info_100(inf, 0x000001f4, /* platform id info */ diff --git a/source3/rpcclient/cmd_lsarpc.c b/source3/rpcclient/cmd_lsarpc.c index 808ef50a45..db74370bc0 100644 --- a/source3/rpcclient/cmd_lsarpc.c +++ b/source3/rpcclient/cmd_lsarpc.c @@ -543,50 +543,6 @@ static NTSTATUS cmd_lsa_enum_acct_rights(struct cli_state *cli, } -/* Enumerate the accounts with a specific right */ - -static NTSTATUS cmd_lsa_enum_acct_with_right(struct cli_state *cli, - TALLOC_CTX *mem_ctx, int argc, - const char **argv) -{ - POLICY_HND dom_pol; - NTSTATUS result = NT_STATUS_UNSUCCESSFUL; - DOM_SID *sids; - uint32 count; - const char *right; - - int i; - - if (argc != 2 ) { - printf("Usage: %s <RIGHT>\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>", "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 <aliguor@us.ibm.com> 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 <lber.h> #include <ldap.h> +#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)<time(NULL))) { - struct sockaddr_un addr; - socklen_t len = sizeof(addr); - int sd; - - if (!ldap_get_option(state->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] = [<does not exist>]\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 <<EOF -/* This file is automatically generated with "make build_env". DO NOT EDIT */ +/* This file is automatically generated with "make include/build_env.h". DO NOT EDIT */ #ifndef _BUILD_ENV_H #define _BUILD_ENV_H diff --git a/source3/script/installswat.sh b/source3/script/installswat.sh index c66604cdb8..d1f8ea191d 100755 --- a/source3/script/installswat.sh +++ b/source3/script/installswat.sh @@ -1,5 +1,5 @@ #!/bin/sh -#fist version March 1998, Andrew Tridgell +#first version March 1998, Andrew Tridgell SWATDIR=$1 SRCDIR=$2/ diff --git a/source3/script/mkproto.awk b/source3/script/mkproto.awk index 919ae2aa7e..6a45a70cc3 100644 --- a/source3/script/mkproto.awk +++ b/source3/script/mkproto.awk @@ -142,7 +142,11 @@ END { gotstart = 1; } - if( $0 ~ /^SAM_ACCT_INFO_NODE|^SMB_ACL_T|^ADS_MODLIST|^PyObject|^SORTED_TREE|^REGISTRY_HOOK|^REGISTRY_VALUE|^DEVICEMODE|^PAC_DATA/ ) { + if( $0 ~ /^SAM_ACCT_INFO_NODE|^SMB_ACL_T|^ADS_MODLIST|^PyObject|^SORTED_TREE|^REGISTRY_HOOK|^REGISTRY_VALUE|^DEVICEMODE|^PAC_DATA|^NET_USER_INFO_3|^smb_event_id_t/ ) { + gotstart = 1; + } + + if( $0 ~ /^WINBINDD_PW|^WINBINDD_GR|^NT_PRINTER_INFO_LEVEL_2/ ) { gotstart = 1; } diff --git a/source3/smbd/.cvsignore b/source3/smbd/.cvsignore index 5f2a5c4cf7..d2b1fd5b2e 100644 --- a/source3/smbd/.cvsignore +++ b/source3/smbd/.cvsignore @@ -1,2 +1,3 @@ *.po *.po32 +build_options.c diff --git a/source3/smbd/change_trust_pw.c b/source3/smbd/change_trust_pw.c index 8aff96d0d6..4993e285ca 100644 --- a/source3/smbd/change_trust_pw.c +++ b/source3/smbd/change_trust_pw.c @@ -43,7 +43,7 @@ NTSTATUS change_trust_account_password( const char *domain, const char *remote_m goto failed; } - if ( !lookup_dc_name(global_myname(), domain, &pdc_ip, dc_name) ) + if ( !name_status_find( domain, 0x1b, 0x20, pdc_ip, dc_name) ) goto failed; } /* supoport old deprecated "smbpasswd -j DOMAIN -r MACHINE" behavior */ diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 5cca85500f..1be13270ba 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -185,7 +185,7 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close) if (normal_close && delete_on_close) { DEBUG(5,("close_file: file %s. Delete on close was set - deleting file.\n", fsp->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)<max_data_count)); + tmp_list=tmp_list->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 <nadavd@exanet.com>. 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;i<MAX_SESSION_ID;i++) { slprintf(keystr, sizeof(keystr)-1, "ID/%d", i); @@ -82,7 +83,6 @@ BOOL session_claim(user_struct *vuser) slprintf(sessionid.id_str, sizeof(sessionid.id_str)-1, SESSION_UTMP_TEMPLATE, i); tdb_store_flag = TDB_MODIFY; } else -#endif { slprintf(keystr, sizeof(keystr)-1, "ID/%lu/%u", (long unsigned int)sys_getpid(), @@ -117,6 +117,8 @@ BOOL session_claim(user_struct *vuser) fstrcpy(sessionid.remote_machine, get_remote_machine_name()); fstrcpy(sessionid.ip_addr, client_addr()); + client_ip = client_inaddr(&sa); + if (!smb_pam_claim_session(sessionid.username, sessionid.id_str, sessionid.hostname)) { DEBUG(1,("pam_session rejected the session for %s [%s]\n", sessionid.username, sessionid.id_str)); @@ -133,12 +135,11 @@ BOOL session_claim(user_struct *vuser) return False; } -#if WITH_UTMP if (lp_utmp()) { sys_utmp_claim(sessionid.username, sessionid.hostname, + client_ip, sessionid.id_str, sessionid.id_num); } -#endif vuser->session_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)); @@ -1915,28 +2096,6 @@ static int call_trans2qfilepathinfo(connection_struct *conn, 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 * it then NTws gets a BSOD! (tridge). @@ -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 <michael.steffens@hp.com>, + 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 <utmp.h> #ifdef HAVE_UTMPX_H @@ -126,33 +138,6 @@ Notes: #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,71 +297,31 @@ 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<SMB_VFS_OP_LAST; i++) { - vfs_opaque_ops[i].op = ((void**)&default_vfs_ops)[i]; - vfs_opaque_ops[i].type = i; - vfs_opaque_ops[i].layer = SMB_VFS_LAYER_OPAQUE; + + for (i=0; vfs_objects[i] ;) { + i++; } - vfs_path = lp_vfs_path(SNUM(conn)); - - for (i=0; vfs_objects[i]; i++); /* count passed modules */ - for (j=i-1; j >= 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; i<SMB_VFS_OP_LAST; i++) { - ((void**)ops)[i] = vfs_opaque_ops[i].op; - } - return ops; -} - -/******************************************************************* Check if directory exists. ********************************************************************/ @@ -390,7 +333,7 @@ BOOL vfs_directory_exist(connection_struct *conn, const char *dname, SMB_STRUCT_ if (!st) st = &st2; - if (vfs_stat(conn,dname,st) != 0) + if (SMB_VFS_STAT(conn,dname,st) != 0) return(False); ret = S_ISDIR(st->st_mode); @@ -401,24 +344,15 @@ BOOL vfs_directory_exist(connection_struct *conn, const char *dname, SMB_STRUCT_ } /******************************************************************* - vfs getwd wrapper -********************************************************************/ - -static char *vfs_getwd(connection_struct *conn, char *path) -{ - return conn->vfs_ops.getwd(conn,path); -} - -/******************************************************************* 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 <ctype.h> #include <signal.h> #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] <fname...>\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 <module path>\n"); + if (argc < 2) { + printf("Usage: load <modules>\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 <fname>\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 <path>\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 <fd> <op> <offset> <count> <type>\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 <path> <link>\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 <path> <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 <smb.conf>\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 <printer>" +"\n\tsearch for a printer in the directory" "\nnet ads printer info <printer> <server>" "\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); @@ -229,52 +281,6 @@ static int recv_cldap_netlogon(int sock, struct cldap_netlogon_reply *reply) } /* - 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 */ int ads_cldap_netlogon(ADS_STRUCT *ads) @@ -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<entries; i++) { print_map_entry( map[i], long_list ); - free_privilege(&(map[i].priv_set)); } + + SAFE_FREE(map); } return 0; @@ -182,9 +179,8 @@ int net_groupmap_list(int argc, const char **argv) Add a new group mapping entry **********************************************************/ -int net_groupmap_add(int argc, const char **argv) +static int net_groupmap_add(int argc, const char **argv) { - PRIVILEGE_SET se_priv; DOM_SID sid; fstring ntgroup = ""; fstring unixgrp = ""; @@ -280,25 +276,16 @@ int net_groupmap_add(int argc, const char **argv) fstrcpy( ntgroup, unixgrp ); - init_privilege(&se_priv); -#if 0 - if (privilege!=NULL) - convert_priv_from_text(&se_priv, privilege); -#endif - - if (!add_initial_entry(gid, string_sid, sid_type, ntgroup, - ntcomment, se_priv, PR_ACCESS_FROM_NETWORK) ) { + if (!add_initial_entry(gid, string_sid, sid_type, ntgroup, ntcomment)) { d_printf("adding entry for group %s failed!\n", ntgroup); return -1; } - free_privilege(&se_priv); - d_printf("Successully added group %s to the mapping db\n", ntgroup); return 0; } -int net_groupmap_modify(int argc, const char **argv) +static int net_groupmap_modify(int argc, const char **argv) { DOM_SID sid; GROUP_MAP map; @@ -381,7 +368,7 @@ int net_groupmap_modify(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; } @@ -390,9 +377,8 @@ int net_groupmap_modify(int argc, const char **argv) * Allow changing of group type only between domain and local * We disallow changing Builtin groups !!! (SID problem) */ - if ( sid_type != SID_NAME_UNKNOWN ) - { - if ( map.sid_name_use == SID_NAME_WKN_GRP ) { + if (sid_type != SID_NAME_UNKNOWN) { + if (map.sid_name_use == SID_NAME_WKN_GRP) { d_printf("You can only change between domain and local groups.\n"); return -1; } @@ -418,26 +404,17 @@ int net_groupmap_modify(int argc, const char **argv) map.gid = gid; } -#if 0 - /* Change the privilege if new one */ - if (privilege!=NULL) - convert_priv_from_text(&map.priv_set, privilege); -#endif - if ( !pdb_update_group_mapping_entry(&map) ) { d_printf("Could not update group database\n"); - free_privilege(&map.priv_set); return -1; } - free_privilege(&map.priv_set); - d_printf("Updated mapping entry for %s\n", ntgroup); return 0; } -int net_groupmap_delete(int argc, const char **argv) +static int net_groupmap_delete(int argc, const char **argv) { DOM_SID sid; fstring ntgroup = ""; @@ -491,3 +468,45 @@ int net_groupmap_delete(int argc, const char **argv) return 0; } +int net_help_groupmap(int argc, const char **argv) +{ + d_printf("net groupmap add"\ + "\n Create a new group mapping\n"); + d_printf("net groupmap modify"\ + "\n Update a group mapping\n"); + d_printf("net groupmap delete"\ + "\n Remove a group mapping\n"); + d_printf("net groupmap list"\ + "\n List current group map\n"); + + return -1; +} + + +/*********************************************************** + migrated functionality from smbgroupedit + **********************************************************/ +int net_groupmap(int argc, const char **argv) +{ + struct functable func[] = { + {"add", net_groupmap_add}, + {"modify", net_groupmap_modify}, + {"delete", net_groupmap_delete}, + {"list", net_groupmap_list}, + {"help", net_help_groupmap}, + {NULL, NULL} + }; + + /* we shouldn't have silly checks like this */ + if (getuid() != 0) { + d_printf("You must be root to edit group mappings.\nExiting...\n"); + return -1; + } + + return net_run_function(argc, argv, func, net_help_groupmap); + if ( 0 == argc ) + return net_help_groupmap( argc, argv ); + + return net_help_groupmap( argc, argv ); +} + diff --git a/source3/utils/net_help.c b/source3/utils/net_help.c index f24367f246..1f3afb1690 100644 --- a/source3/utils/net_help.c +++ b/source3/utils/net_help.c @@ -99,26 +99,6 @@ int net_help_group(int argc, const char **argv) return -1; } -int net_help_groupmap(int argc, const char **argv) -{ - if (getuid() != 0) { - d_printf("You must be root to edit group mappings.\nExiting...\n"); - return -1; - } - - d_printf("net groupmap add"\ - "\n Create a new group mapping\n"); - d_printf("net groupmap modify"\ - "\n Update a group mapping\n"); - d_printf("net groupmap delete"\ - "\n Remove a group mapping\n"); - d_printf("net groupmap list"\ - "\n List current group map\n"); - - return -1; -} - - int net_help_join(int argc, const char **argv) { d_printf("\nnet [<method>] 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<count;i++) { - char *dc_str = inet_ntoa(ip_list[i]); + char *dc_str = inet_ntoa(ip_list[i].ip); if (!strequal(pdc_str, dc_str)) d_printf("%s\n", dc_str); } diff --git a/source3/utils/net_rpc.c b/source3/utils/net_rpc.c index 3f5a339948..890d4a012b 100644 --- a/source3/utils/net_rpc.c +++ b/source3/utils/net_rpc.c @@ -74,7 +74,7 @@ static DOM_SID *net_get_remote_domain_sid(struct cli_state *cli) goto error; } - result = cli_lsa_open_policy(cli, mem_ctx, True, + result = cli_lsa_open_policy(cli, mem_ctx, False, SEC_RIGHTS_MAXIMUM_ALLOWED, &pol); if (!NT_STATUS_IS_OK(result)) { @@ -235,16 +235,27 @@ int net_rpc_changetrustpw(int argc, const char **argv) * @return Normal NTSTATUS return. **/ -static NTSTATUS rpc_join_oldstyle_internals(const DOM_SID *domain_sid, struct cli_state *cli, +static NTSTATUS rpc_oldjoin_internals(const DOM_SID *domain_sid, struct cli_state *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { fstring trust_passwd; unsigned char orig_trust_passwd_hash[16]; NTSTATUS result; + uint32 sec_channel_type; + /* + check what type of join - if the user want's to join as + a BDC, the server must agree that we are a BDC. + */ + if (argc >= 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); @@ -285,40 +292,11 @@ static NTSTATUS rpc_join_oldstyle_internals(const DOM_SID *domain_sid, struct cl * @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. - * - * @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_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 <domain_name>\n"); + if (argc != 2) { + d_printf("Usage: net rpc trustdom add <domain_name> <pw>\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 <dest> 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 <dest> 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 <dest> 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 <dest> 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 <dest> 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 <dest> 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 <dest> 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 <dest> 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 <dest> 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 <dest> 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 <dest> 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 <dest> " @@ -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 <dest> 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 <dest> 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 <dest> 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("<H2>Wizard Parameter Edit Page</H2>\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("<p>\n"); d_printf("<table>\n"); - show_parameters(GLOBALS_SNUM, 1, parm_filter, 0); + show_parameters(GLOBAL_SECTION_SNUM, 1, parm_filter, 0); d_printf("</table>\n"); d_printf("</form>\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("<H2>Note: smb.conf %s</H2>\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("<H2>%s</H2>\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("<p>\n"); d_printf("<table>\n"); - show_parameters(GLOBALS_SNUM, 1, parm_filter, 0); + show_parameters(GLOBAL_SECTION_SNUM, 1, parm_filter, 0); d_printf("</table>\n"); d_printf("</form>\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"); |