From f0f7108060652a3f0d1b5ca4783cf62cd84fac12 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Tue, 12 Apr 2005 00:37:55 +0000 Subject: r6303: Setting up for 3.0.15pre1 current as of r6296 --- source/Makefile.in | 82 ++- source/VERSION | 4 +- source/auth/auth_compat.c | 5 +- source/auth/auth_sam.c | 3 +- source/auth/auth_util.c | 5 - source/client/client.c | 30 +- source/client/clitar.c | 4 +- source/client/mount.cifs.c | 194 +++++- source/client/smbspool.c | 4 +- source/client/umount.cifs.c | 273 +++++++++ source/configure.in | 55 +- source/groupdb/mapping.c | 41 +- source/include/doserr.h | 2 + source/include/includes.h | 11 + source/include/libsmb_internal.h | 2 +- source/include/libsmbclient.h | 295 ++-------- source/include/msdfs.h | 7 +- source/include/nt_status.h | 1 + source/include/ntdomain.h | 3 + source/include/nterr.h | 3 + source/include/passdb.h | 49 +- source/include/rpc_buffer.h | 35 ++ source/include/rpc_client.h | 21 +- source/include/rpc_eventlog.h | 193 ++++++ source/include/rpc_lsa.h | 56 +- source/include/rpc_misc.h | 337 ++++++----- source/include/rpc_netlogon.h | 14 +- source/include/rpc_reg.h | 589 +++++++------------ source/include/rpc_secdes.h | 47 ++ source/include/rpc_shutdown.h | 65 ++- source/include/rpc_spoolss.h | 221 +++---- source/include/rpc_srvsvc.h | 22 + source/include/rpc_svcctl.h | 246 ++++++++ source/include/smb.h | 62 +- source/include/smb_macros.h | 46 +- source/include/trans2.h | 12 + source/intl/lang_tdb.c | 4 +- source/lib/access.c | 2 +- source/lib/account_pol.c | 8 - source/lib/charcnv.c | 15 + source/lib/data_blob.c | 2 +- source/lib/iconv.c | 2 +- source/lib/ms_fnmatch.c | 4 +- source/lib/privileges.c | 9 +- source/lib/secace.c | 2 +- source/lib/secdesc.c | 4 +- source/lib/select.c | 26 +- source/lib/smbldap.c | 7 +- source/lib/substitute.c | 3 +- source/lib/system.c | 192 +++++- source/lib/system_smbd.c | 4 +- source/lib/talloc.c | 13 + source/lib/time.c | 22 + source/lib/util.c | 65 ++- source/lib/util_seaccess.c | 41 +- source/lib/util_sid.c | 168 +++--- source/lib/util_smbd.c | 4 +- source/lib/util_str.c | 46 +- source/lib/util_unistr.c | 39 +- source/lib/util_uuid.c | 2 +- source/lib/wins_srv.c | 3 +- source/libads/kerberos.c | 3 +- source/libads/ldap.c | 21 +- source/libads/ldap_printer.c | 6 +- source/libads/sasl.c | 9 +- source/libsmb/cliconnect.c | 7 +- source/libsmb/clientgen.c | 3 +- source/libsmb/clifile.c | 4 +- source/libsmb/clifsinfo.c | 115 ++++ source/libsmb/clikrb5.c | 3 + source/libsmb/clilist.c | 4 +- source/libsmb/clirap.c | 38 +- source/libsmb/clirap2.c | 124 ++++ source/libsmb/clispnego.c | 3 +- source/libsmb/doserr.c | 2 + source/libsmb/libsmbclient.c | 967 ++++++++++++++++++------------ source/libsmb/nmblib.c | 5 +- source/libsmb/smb_signing.c | 3 + source/libsmb/smbencrypt.c | 2 +- source/libsmb/spnego.c | 15 +- source/modules/getdate.c | 9 +- source/modules/getdate.y | 9 +- source/modules/vfs_catia.c | 317 ++++++++++ source/modules/vfs_fake_perms.c | 6 +- source/modules/weird.c | 4 +- source/nmbd/nmbd.c | 4 +- source/nmbd/nmbd_subnetdb.c | 2 +- source/nmbd/nmbd_synclists.c | 3 +- source/nsswitch/wb_client.c | 2 - source/nsswitch/wb_common.c | 7 +- source/nsswitch/winbindd.c | 2 - source/nsswitch/winbindd.h | 1 - source/nsswitch/winbindd_acct.c | 2 +- source/nsswitch/winbindd_ads.c | 3 +- source/nsswitch/winbindd_cache.c | 12 +- source/nsswitch/winbindd_group.c | 54 +- source/nsswitch/winbindd_nss.h | 2 +- source/nsswitch/winbindd_rpc.c | 3 +- source/nsswitch/winbindd_util.c | 21 +- source/param/loadparm.c | 58 +- source/param/params.c | 3 +- source/passdb/machine_sid.c | 2 - source/passdb/passdb.c | 2 +- source/passdb/pdb_get_set.c | 2 +- source/passdb/pdb_interface.c | 485 ++++++++++++++- source/passdb/pdb_ldap.c | 289 +++++++-- source/passdb/secrets.c | 19 +- source/passdb/util_sam_sid.c | 10 +- source/printing/nt_printing.c | 5 +- source/printing/printfsp.c | 3 +- source/printing/printing.c | 51 +- source/python/py_smb.c | 2 +- source/registry/reg_db.c | 7 + source/registry/reg_eventlog.c | 302 ++++++++++ source/registry/reg_frontend.c | 5 +- source/rpc_client/cli_lsarpc.c | 107 ++-- source/rpc_client/cli_reg.c | 721 ++++++++++++++++++++++- source/rpc_client/cli_shutdown.c | 52 +- source/rpc_client/cli_spoolss.c | 84 ++- source/rpc_client/cli_svcctl.c | 415 +++++++++++++ source/rpc_parse/parse_buffer.c | 491 ++++++++++++++++ source/rpc_parse/parse_eventlog.c | 457 +++++++++++++++ source/rpc_parse/parse_lsa.c | 171 +++--- source/rpc_parse/parse_misc.c | 480 ++++++++------- source/rpc_parse/parse_net.c | 21 +- source/rpc_parse/parse_prs.c | 53 +- source/rpc_parse/parse_reg.c | 1103 ++++++++++++++++------------------- source/rpc_parse/parse_rpc.c | 45 +- source/rpc_parse/parse_sec.c | 2 +- source/rpc_parse/parse_shutdown.c | 123 +++- source/rpc_parse/parse_spoolss.c | 689 +++++----------------- source/rpc_parse/parse_srv.c | 73 +++ source/rpc_parse/parse_svcctl.c | 660 +++++++++++++++++++++ source/rpc_server/srv_eventlog.c | 206 +++++++ source/rpc_server/srv_eventlog_nt.c | 923 +++++++++++++++++++++++++++++ source/rpc_server/srv_lsa_ds_nt.c | 7 +- source/rpc_server/srv_lsa_nt.c | 35 +- source/rpc_server/srv_netlog.c | 2 +- source/rpc_server/srv_netlog_nt.c | 5 +- source/rpc_server/srv_pipe.c | 12 +- source/rpc_server/srv_reg.c | 97 ++- source/rpc_server/srv_reg_nt.c | 205 +++++-- source/rpc_server/srv_samr_nt.c | 136 ++--- source/rpc_server/srv_samr_util.c | 2 +- source/rpc_server/srv_spoolss.c | 3 + source/rpc_server/srv_spoolss_nt.c | 953 ++++++++++++++++-------------- source/rpc_server/srv_srvsvc.c | 29 + source/rpc_server/srv_srvsvc_nt.c | 71 ++- source/rpc_server/srv_svcctl.c | 294 ++++++++++ source/rpc_server/srv_svcctl_nt.c | 295 ++++++++++ source/rpc_server/srv_util.c | 3 +- source/rpcclient/cmd_reg.c | 32 +- source/rpcclient/cmd_samr.c | 82 ++- source/rpcclient/cmd_shutdown.c | 6 + source/rpcclient/cmd_spoolss.c | 85 +-- source/rpcclient/rpcclient.c | 2 - source/sam/idmap_util.c | 103 ---- source/script/installman.sh | 2 +- source/smbd/chgpasswd.c | 7 +- source/smbd/dir.c | 15 +- source/smbd/dosmode.c | 4 +- source/smbd/error.c | 145 +++-- source/smbd/fake_file.c | 3 +- source/smbd/filename.c | 2 +- source/smbd/files.c | 6 +- source/smbd/lanman.c | 107 ++-- source/smbd/msdfs.c | 42 +- source/smbd/negprot.c | 3 +- source/smbd/notify_kernel.c | 10 +- source/smbd/nttrans.c | 303 +++++++--- source/smbd/open.c | 258 ++++---- source/smbd/oplock.c | 18 +- source/smbd/oplock_linux.c | 30 +- source/smbd/posix_acls.c | 31 +- source/smbd/process.c | 12 +- source/smbd/quotas.c | 15 +- source/smbd/reply.c | 340 ++++++++--- source/smbd/server.c | 4 +- source/smbd/service.c | 4 +- source/smbd/sesssetup.c | 27 +- source/smbd/statcache.c | 5 + source/smbd/trans2.c | 998 +++++++++++++++++++++++-------- source/smbwrapper/smbw.c | 2 +- source/smbwrapper/smbw_stat.c | 24 +- source/tdb/tdb.c | 2 +- source/tdb/tdbbackup.c | 5 +- source/tdb/tdbtool.c | 4 +- source/tdb/tdbutil.c | 11 +- source/torture/torture.c | 6 +- source/torture/utable.c | 2 +- source/utils/net.c | 74 +-- source/utils/net_ads.c | 4 +- source/utils/net_groupmap.c | 52 +- source/utils/net_lookup.c | 4 +- source/utils/net_rap.c | 18 +- source/utils/net_rpc.c | 90 ++- source/utils/net_rpc_rights.c | 182 +++++- source/utils/net_rpc_samsync.c | 4 +- source/utils/net_rpc_service.c | 529 +++++++++++++++++ source/utils/pdbedit.c | 4 +- source/utils/smbcontrol.c | 3 +- source/utils/smbpasswd.c | 2 +- source/web/diagnose.c | 2 - source/web/neg_lang.c | 4 +- 204 files changed, 14179 insertions(+), 5343 deletions(-) create mode 100644 source/client/umount.cifs.c create mode 100644 source/include/rpc_buffer.h create mode 100644 source/include/rpc_eventlog.h create mode 100644 source/include/rpc_svcctl.h create mode 100644 source/modules/vfs_catia.c create mode 100644 source/registry/reg_eventlog.c create mode 100644 source/rpc_client/cli_svcctl.c create mode 100644 source/rpc_parse/parse_buffer.c create mode 100644 source/rpc_parse/parse_eventlog.c create mode 100644 source/rpc_parse/parse_svcctl.c create mode 100644 source/rpc_server/srv_eventlog.c create mode 100644 source/rpc_server/srv_eventlog_nt.c create mode 100644 source/rpc_server/srv_svcctl.c create mode 100644 source/rpc_server/srv_svcctl_nt.c create mode 100644 source/utils/net_rpc_service.c diff --git a/source/Makefile.in b/source/Makefile.in index fda2bd3d93a..c4619079841 100644 --- a/source/Makefile.in +++ b/source/Makefile.in @@ -92,8 +92,6 @@ LOCKDIR = @lockdir@ # the directory where pid files go PIDDIR = @piddir@ -# man pages language(s) -man_langs = "@manlangs@" LIBSMBCLIENT=bin/libsmbclient.a @LIBSMBCLIENT_SHARED@ LIBSMBCLIENT_MAJOR=0 @@ -173,6 +171,8 @@ SNPRINTF_OBJ = lib/snprintf.o WBCOMMON_OBJ = nsswitch/wb_common.o +DUMMYROOT_OBJ = lib/dummyroot.o + AFS_OBJ = lib/afs.o AFS_SETTOKEN_OBJ = lib/afs_settoken.o @@ -206,7 +206,7 @@ LIB_OBJ = $(VERSION_OBJ) lib/charcnv.o lib/debug.o lib/fault.o \ lib/module.o lib/ldap_escape.o @CHARSET_STATIC@ \ lib/privileges.o lib/secdesc.o lib/secace.o lib/secacl.o -LIB_NONSMBD_OBJ = $(LIB_OBJ) lib/dummyroot.o lib/dummysmbd.o +LIB_NONSMBD_OBJ = $(LIB_OBJ) lib/dummysmbd.o READLINE_OBJ = lib/readline.o @@ -255,12 +255,12 @@ LIBMSRPC_OBJ = rpc_client/cli_lsarpc.o rpc_client/cli_samr.o \ rpc_client/cli_reg.o $(RPC_CLIENT_OBJ) \ rpc_client/cli_spoolss.o rpc_client/cli_spoolss_notify.o \ rpc_client/cli_ds.o rpc_client/cli_echo.o \ - rpc_client/cli_shutdown.o + rpc_client/cli_shutdown.o rpc_client/cli_svcctl.o REGOBJS_OBJ = registry/reg_objects.o REGISTRY_OBJ = registry/reg_frontend.o registry/reg_cachehook.o registry/reg_printing.o \ - registry/reg_db.o + registry/reg_db.o registry/reg_eventlog.o RPC_LSA_OBJ = rpc_server/srv_lsa.o rpc_server/srv_lsa_nt.o @@ -277,10 +277,14 @@ RPC_SVC_OBJ = rpc_server/srv_srvsvc.o rpc_server/srv_srvsvc_nt.o RPC_WKS_OBJ = rpc_server/srv_wkssvc.o rpc_server/srv_wkssvc_nt.o +RPC_SVCCTL_OBJ = rpc_server/srv_svcctl.o rpc_server/srv_svcctl_nt.o + RPC_DFS_OBJ = rpc_server/srv_dfs.o rpc_server/srv_dfs_nt.o RPC_SPOOLSS_OBJ = rpc_server/srv_spoolss.o rpc_server/srv_spoolss_nt.o +RPC_EVENTLOG_OBJ = rpc_server/srv_eventlog.o rpc_server/srv_eventlog_nt.o + RPC_PIPE_OBJ = rpc_server/srv_pipe_hnd.o rpc_server/srv_util.o \ rpc_server/srv_pipe.o rpc_server/srv_lsa_hnd.o @@ -298,7 +302,8 @@ RPC_PARSE_OBJ = rpc_parse/parse_lsa.o rpc_parse/parse_net.o \ rpc_parse/parse_wks.o rpc_parse/parse_ds.o \ rpc_parse/parse_spoolss.o rpc_parse/parse_dfs.o \ rpc_parse/parse_echo.o rpc_parse/parse_shutdown.o \ - $(REGOBJS_OBJ) + rpc_parse/parse_svcctl.o \ + rpc_parse/parse_eventlog.o rpc_parse/parse_buffer.o $(REGOBJS_OBJ) RPC_CLIENT_OBJ = rpc_client/cli_pipe.o @@ -342,6 +347,7 @@ VFS_CAP_OBJ = modules/vfs_cap.o VFS_EXPAND_MSDFS_OBJ = modules/vfs_expand_msdfs.o VFS_SHADOW_COPY_OBJ = modules/vfs_shadow_copy.o VFS_AFSACL_OBJ = modules/vfs_afsacl.o +VFS_CATIA_OBJ = modules/vfs_catia.o PLAINTEXT_AUTH_OBJ = auth/pampass.o auth/pass_check.o @@ -434,20 +440,20 @@ SWAT_OBJ = $(SWAT_OBJ1) $(PARAM_OBJ) $(PRINTING_OBJ) $(LIBSMB_OBJ) \ $(LOCKING_OBJ) $(PASSDB_OBJ) $(SECRETS_OBJ) $(KRBCLIENT_OBJ) \ $(LIB_NONSMBD_OBJ) $(GROUPDB_OBJ) $(PLAINTEXT_AUTH_OBJ) \ $(POPT_LIB_OBJ) $(SMBLDAP_OBJ) $(RPC_PARSE_OBJ) $(LIBMSRPC_OBJ) \ - $(PASSCHANGE_OBJ) + $(PASSCHANGE_OBJ) $(DUMMYROOT_OBJ) SMBSH_OBJ = smbwrapper/smbsh.o smbwrapper/shared.o \ $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) STATUS_OBJ = utils/status.o $(LOCKING_OBJ) $(PARAM_OBJ) \ $(PROFILE_OBJ) $(LIB_NONSMBD_OBJ) $(POPT_LIB_OBJ) \ - $(SECRETS_OBJ) $(LIBSAMBA_OBJ) $(ERRORMAP_OBJ) + $(SECRETS_OBJ) $(LIBSAMBA_OBJ) $(DUMMYROOT_OBJ) $(ERRORMAP_OBJ) SMBCONTROL_OBJ = utils/smbcontrol.o $(LOCKING_OBJ) $(PARAM_OBJ) \ $(PROFILE_OBJ) $(LIB_NONSMBD_OBJ) $(POPT_LIB_OBJ) \ $(SECRETS_OBJ) $(LIBSAMBA_OBJ) \ - $(PRINTBASE_OBJ) $(ERRORMAP_OBJ) + $(PRINTBASE_OBJ) $(DUMMYROOT_OBJ) $(ERRORMAP_OBJ) SMBTREE_OBJ = utils/smbtree.o $(PARAM_OBJ) \ $(PROFILE_OBJ) $(LIB_NONSMBD_OBJ) $(LIBSMB_OBJ) \ @@ -463,11 +469,11 @@ TESTPRNS_OBJ = utils/testprns.o $(PARAM_OBJ) $(PRINTING_OBJ) \ SMBPASSWD_OBJ = utils/smbpasswd.o $(PASSCHANGE_OBJ) $(PARAM_OBJ) $(SECRETS_OBJ) \ $(LIBSMB_OBJ) $(PASSDB_OBJ) $(GROUPDB_OBJ)\ $(LIB_NONSMBD_OBJ) $(KRBCLIENT_OBJ) \ - $(SMBLDAP_OBJ) $(RPC_PARSE_OBJ) $(LIBMSRPC_OBJ) + $(SMBLDAP_OBJ) $(RPC_PARSE_OBJ) $(LIBMSRPC_OBJ) $(DUMMYROOT_OBJ) PDBEDIT_OBJ = utils/pdbedit.o $(PARAM_OBJ) $(PASSDB_OBJ) $(LIBSAMBA_OBJ) \ $(LIB_NONSMBD_OBJ) $(GROUPDB_OBJ) $(SECRETS_OBJ) \ - $(POPT_LIB_OBJ) $(SMBLDAP_OBJ) + $(POPT_LIB_OBJ) $(SMBLDAP_OBJ) $(DUMMYROOT_OBJ) libsmb/asn1.o SMBGET_OBJ = utils/smbget.o $(POPT_LIB_OBJ) $(LIBSMBCLIENT_OBJ) @@ -483,7 +489,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) \ - $(SMBLDAP_OBJ) $(DCUTIL_OBJ) + $(SMBLDAP_OBJ) $(DCUTIL_OBJ) $(DUMMYROOT_OBJ) PAM_WINBIND_PICOBJ = nsswitch/pam_winbind.@PICSUFFIX@ \ nsswitch/wb_common.@PICSUFFIX@ lib/replace1.@PICSUFFIX@ \ @@ -505,8 +511,8 @@ LIBSMBCLIENT_OBJ = libsmb/libsmbclient.o libsmb/libsmb_compat.o \ libsmb/libsmb_cache.o \ $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) \ $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) \ - $(LIBMSRPC_OBJ) $(RPC_PARSE_OBJ) $(PASSDB_GET_SET_OBJ) \ - $(SECRETS_OBJ) + $(LIBMSRPC_OBJ) $(RPC_PARSE_OBJ) \ + $(SECRETS_OBJ) $(PASSDB_OBJ) $(SMBLDAP_OBJ) $(GROUPDB_OBJ) $(DUMMYROOT_OBJ) # This shared library is intended for linking with unit test programs # to test Samba internals. It's called libbigballofmud.so to @@ -516,7 +522,7 @@ LIBBIGBALLOFMUD_MAJOR = 0 LIBBIGBALLOFMUD_OBJ = $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) $(UBIQX_OBJ) $(SECRETS_OBJ) \ $(LIBSMB_OBJ) $(LIBMSRPC_OBJ) $(RPC_PARSE_OBJ) $(PASSDB_OBJ) \ - $(GROUPDB_OBJ) $(KRBCLIENT_OBJ) $(SMBLDAP_OBJ) + $(GROUPDB_OBJ) $(KRBCLIENT_OBJ) $(SMBLDAP_OBJ) $(DUMMYROOT_OBJ) LIBBIGBALLOFMUD_PICOBJS = $(LIBBIGBALLOFMUD_OBJ:.o=.@PICSUFFIX@) @@ -530,15 +536,16 @@ 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_idmap.o \ - utils/net_status.o utils/net_rpc_printer.o utils/net_rpc_rights.o + utils/net_status.o utils/net_rpc_printer.o utils/net_rpc_rights.o \ + utils/net_rpc_service.o NET_OBJ = $(NET_OBJ1) $(PARAM_OBJ) $(SECRETS_OBJ) $(LIBSMB_OBJ) \ $(RPC_PARSE_OBJ) $(PASSDB_OBJ) $(GROUPDB_OBJ) \ $(KRBCLIENT_OBJ) $(LIB_NONSMBD_OBJ) \ $(LIBMSRPC_OBJ) $(IDMAP_OBJ) \ $(LIBADS_OBJ) $(LIBADS_SERVER_OBJ) $(POPT_LIB_OBJ) \ - $(SMBLDAP_OBJ) $(DCUTIL_OBJ) $(SERVER_MUTEX_OBJ) \ - $(AFS_OBJ) $(AFS_SETTOKEN_OBJ) + $(SMBLDAP_OBJ) $(DCUTIL_OBJ) $(DUMMYROOT_OBJ) $(SERVER_MUTEX_OBJ) \ + $(AFS_OBJ) $(AFS_SETTOKEN_OBJ) $(PRINTERDB_OBJ) CUPS_OBJ = client/smbspool.o $(PARAM_OBJ) $(LIBSMB_OBJ) \ $(LIB_NONSMBD_OBJ) $(KRBCLIENT_OBJ) $(SECRETS_OBJ) @@ -566,7 +573,7 @@ MSGTEST_OBJ = torture/msgtest.o $(PARAM_OBJ) $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) \ $(LIB_NONSMBD_OBJ) $(SECRETS_OBJ) LOCKTEST_OBJ = torture/locktest.o $(PARAM_OBJ) $(LOCKING_OBJ) $(KRBCLIENT_OBJ) \ - $(LIBSMB_OBJ) $(LIB_NONSMBD_OBJ) $(SECRETS_OBJ) + $(LIBSMB_OBJ) $(LIB_NONSMBD_OBJ) $(DUMMYROOT_OBJ) $(SECRETS_OBJ) NSSTEST_OBJ = torture/nsstest.o $(PARAM_OBJ) $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) \ $(LIB_NONSMBD_OBJ) $(SECRETS_OBJ) @@ -578,17 +585,18 @@ SMBICONV_OBJ = $(PARAM_OBJ) torture/smbiconv.o $(LIB_NONSMBD_OBJ) $(POPT_LIB_OBJ LOG2PCAP_OBJ = utils/log2pcaphex.o LOCKTEST2_OBJ = torture/locktest2.o $(PARAM_OBJ) $(LOCKING_OBJ) $(LIBSMB_OBJ) \ - $(KRBCLIENT_OBJ) $(LIB_NONSMBD_OBJ) $(SECRETS_OBJ) + $(KRBCLIENT_OBJ) $(LIB_NONSMBD_OBJ) $(DUMMYROOT_OBJ) $(SECRETS_OBJ) SMBCACLS_OBJ = utils/smbcacls.o $(PARAM_OBJ) $(LIBSMB_OBJ) \ $(KRBCLIENT_OBJ) $(LIB_NONSMBD_OBJ) $(RPC_PARSE_OBJ) \ - $(PASSDB_GET_SET_OBJ) $(LIBMSRPC_OBJ) $(SECRETS_OBJ) \ - $(POPT_LIB_OBJ) $(DCUTIL_OBJ) $(LIBADS_OBJ) + $(PASSDB_OBJ) $(GROUPDB_OBJ) $(DUMMYROOT_OBJ) $(LIBMSRPC_OBJ) $(SECRETS_OBJ) \ + $(POPT_LIB_OBJ) $(DCUTIL_OBJ) $(LIBADS_OBJ) $(SMBLDAP_OBJ) SMBCQUOTAS_OBJ = utils/smbcquotas.o $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) \ $(PARAM_OBJ) \ - $(LIB_NONSMBD_OBJ) $(RPC_PARSE_OBJ) $(PASSDB_GET_SET_OBJ) \ - $(LIBMSRPC_OBJ) $(SECRETS_OBJ) $(POPT_LIB_OBJ) + $(LIB_NONSMBD_OBJ) $(RPC_PARSE_OBJ) \ + $(LIBMSRPC_OBJ) $(SECRETS_OBJ) $(POPT_LIB_OBJ) \ + $(PASSDB_OBJ) $(SMBLDAP_OBJ) $(GROUPDB_OBJ) $(DUMMYROOT_OBJ) TALLOCTORT_OBJ = lib/talloctort.o $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) libsmb/nterr.o @@ -619,7 +627,8 @@ PROTO_OBJ = $(SMBD_OBJ_MAIN) \ $(AUTH_SAM_OBJ) $(REGISTRY_OBJ) $(POPT_LIB_OBJ) \ $(RPC_LSA_OBJ) $(RPC_NETLOG_OBJ) $(RPC_SAMR_OBJ) $(RPC_REG_OBJ) $(RPC_LSA_DS_OBJ) \ $(RPC_SVC_OBJ) $(RPC_WKS_OBJ) $(RPC_DFS_OBJ) $(RPC_SPOOLSS_OBJ) \ - $(RPC_ECHO_OBJ) $(SMBLDAP_OBJ) $(IDMAP_OBJ) libsmb/spnego.o $(PASSCHANGE_OBJ) + $(RPC_ECHO_OBJ) $(RPC_SVCCTL_OBJ) $(RPC_EVENTLOG_OBJ) $(SMBLDAP_OBJ) \ + $(IDMAP_OBJ) libsmb/spnego.o $(PASSCHANGE_OBJ) WINBIND_WINS_NSS_OBJ = nsswitch/wins.o $(PARAM_OBJ) \ $(LIBSMB_OBJ) $(LIB_NONSMBD_OBJ) $(NSSWINS_OBJ) $(KRBCLIENT_OBJ) @@ -631,7 +640,7 @@ LIBSMBCLIENT_PICOBJS = $(LIBSMBCLIENT_OBJ:.o=.@PICSUFFIX@) PAM_SMBPASS_OBJ_0 = pam_smbpass/pam_smb_auth.o pam_smbpass/pam_smb_passwd.o \ pam_smbpass/pam_smb_acct.o pam_smbpass/support.o \ - $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) $(PASSDB_OBJ) $(GROUPDB_OBJ) \ + $(DUMMYROOT_OBJ) $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) $(PASSDB_OBJ) $(GROUPDB_OBJ) \ $(SECRETS_OBJ) $(SMBLDAP_OBJ) $(LIBSAMBA_OBJ) PAM_SMBPASS_PICOOBJ = $(PAM_SMBPASS_OBJ_0:.o=.@PICSUFFIX@) @@ -661,7 +670,7 @@ WINBINDD_OBJ = \ $(LIBSMB_OBJ) $(LIBMSRPC_OBJ) $(RPC_PARSE_OBJ) \ $(PROFILE_OBJ) $(SLCACHE_OBJ) $(SMBLDAP_OBJ) \ $(SECRETS_OBJ) $(LIBADS_OBJ) $(KRBCLIENT_OBJ) $(POPT_LIB_OBJ) \ - $(DCUTIL_OBJ) $(IDMAP_OBJ) \ + $(DCUTIL_OBJ) $(IDMAP_OBJ) $(DUMMYROOT_OBJ) \ $(AFS_OBJ) $(AFS_SETTOKEN_OBJ) WBINFO_OBJ = nsswitch/wbinfo.o $(LIBSAMBA_OBJ) $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) \ @@ -970,7 +979,7 @@ bin/debug2html@EXEEXT@: $(DEBUG2HTML_OBJ) bin/.dummy bin/smbfilter@EXEEXT@: $(SMBFILTER_OBJ) bin/.dummy @echo Linking $@ - @$(CC) $(FLAGS) -o $@ $(SMBFILTER_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) + @$(CC) $(FLAGS) -o $@ $(SMBFILTER_OBJ) $(LDFLAGS) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) bin/smbw_sample@EXEEXT@: $(SMBW_OBJ) utils/smbw_sample.o bin/.dummy @echo Linking $@ @@ -1026,6 +1035,11 @@ bin/librpc_srvsvc.@SHLIBEXT@: $(RPC_SVC_OBJ) @$(SHLD) $(LDSHFLAGS) -o $@ $(RPC_SVC_OBJ) -lc \ @SONAMEFLAG@`basename $@` +bin/librpc_svcctl.@SHLIBEXT@: $(RPC_SVCCTL_OBJ) + @echo "Linking $@" + @$(SHLD) $(LDSHFLAGS) -o $@ $(RPC_SVCCTL_OBJ) -lc \ + @SONAMEFLAG@`basename $@` + bin/librpc_wkssvc.@SHLIBEXT@: $(RPC_WKS_OBJ) @echo "Linking $@" @$(SHLD) $(LDSHFLAGS) -o $@ $(RPC_WKS_OBJ) -lc \ @@ -1228,6 +1242,12 @@ bin/afsacl.@SHLIBEXT@: $(VFS_AFSACL_OBJ:.o=.po) @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_AFSACL_OBJ:.o=.po) \ @SONAMEFLAG@`basename $@` +bin/catia.@SHLIBEXT@: $(VFS_CATIA_OBJ:.o=.@PICSUFFIX@) + @echo "Building plugin $@" + @$(SHLD) $(LDSHFLAGS) -o $@ $(VFS_CATIA_OBJ:.o=.@PICSUFFIX@) \ + @SONAMEFLAG@`basename $@` + + bin/wbinfo@EXEEXT@: $(WBINFO_OBJ) @BUILD_POPT@ bin/.dummy @echo Linking $@ @$(CC) $(FLAGS) -o $@ $(LDFLAGS) $(WBINFO_OBJ) $(DYNEXP) $(LIBS) @POPTLIBS@ @@ -1335,7 +1355,7 @@ installclientlib: installdirs libsmbclient PYTHON_OBJS = $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) $(LIBSMB_OBJ) $(RPC_PARSE_OBJ) \ $(LIBMSRPC_OBJ) $(PASSDB_OBJ) $(GROUPDB_OBJ) \ - $(SECRETS_OBJ) $(KRBCLIENT_OBJ) $(SMBLDAP_OBJ) + $(SECRETS_OBJ) $(KRBCLIENT_OBJ) $(SMBLDAP_OBJ) $(DUMMYROOT_OBJ) PYTHON_PICOBJS = $(PYTHON_OBJS:.o=.@PICSUFFIX@) @@ -1368,7 +1388,7 @@ revert: @$(SHELL) $(srcdir)/script/revert.sh $(BINDIR) $(BIN_PROGS) $(SCRIPTS) installman: installdirs - @$(SHELL) $(srcdir)/script/installman.sh $(DESTDIR)$(MANDIR) $(srcdir) $(man_langs) "@ROFF@" + @$(SHELL) $(srcdir)/script/installman.sh $(DESTDIR)$(MANDIR) $(srcdir) C "@ROFF@" .PHONY: showlayout @@ -1390,7 +1410,7 @@ showlayout: uninstall: uninstallman uninstallbin uninstallscripts uninstallmodules uninstallman: - @$(SHELL) $(srcdir)/script/uninstallman.sh $(DESTDIR)$(MANDIR) $(srcdir) $(man_langs) + @$(SHELL) $(srcdir)/script/uninstallman.sh $(DESTDIR)$(MANDIR) $(srcdir) C uninstallbin: @$(SHELL) $(srcdir)/script/uninstallbin.sh $(INSTALLPERMS) $(DESTDIR)$(BASEDIR) $(DESTDIR)$(SBINDIR) $(DESTDIR)$(LIBDIR) $(DESTDIR)$(VARDIR) $(DESTDIR)$(SBIN_PROGS) diff --git a/source/VERSION b/source/VERSION index 026b4553ff8..4d50fe3468e 100644 --- a/source/VERSION +++ b/source/VERSION @@ -19,7 +19,7 @@ ######################################################## SAMBA_VERSION_MAJOR=3 SAMBA_VERSION_MINOR=0 -SAMBA_VERSION_RELEASE=14 +SAMBA_VERSION_RELEASE=15 ######################################################## # For 'pre' releases the version will be # @@ -29,7 +29,7 @@ SAMBA_VERSION_RELEASE=14 # e.g. SAMBA_VERSION_PRE_RELEASE=1 # # -> "2.2.9pre1" # ######################################################## -SAMBA_VERSION_PRE_RELEASE= +SAMBA_VERSION_PRE_RELEASE=1 ######################################################## # For 'rc' releases the version will be # diff --git a/source/auth/auth_compat.c b/source/auth/auth_compat.c index a70f1e98b72..2ac70d73546 100644 --- a/source/auth/auth_compat.c +++ b/source/auth/auth_compat.c @@ -20,6 +20,9 @@ #include "includes.h" +extern struct auth_context *negprot_global_auth_context; +extern BOOL global_encrypted_passwords_negotiated; + #undef DBGC_CLASS #define DBGC_CLASS DBGC_AUTH @@ -68,7 +71,6 @@ static NTSTATUS pass_check_smb(const char *smb_name, { NTSTATUS nt_status; - extern struct auth_context *negprot_global_auth_context; auth_serversupplied_info *server_info = NULL; if (encrypted) { auth_usersupplied_info *user_info = NULL; @@ -94,7 +96,6 @@ BOOL password_ok(char *smb_name, DATA_BLOB password_blob) { DATA_BLOB null_password = data_blob(NULL, 0); - extern BOOL global_encrypted_passwords_negotiated; BOOL encrypted = (global_encrypted_passwords_negotiated && password_blob.length == 24); if (encrypted) { diff --git a/source/auth/auth_sam.c b/source/auth/auth_sam.c index 9da59f220aa..023e441e241 100644 --- a/source/auth/auth_sam.c +++ b/source/auth/auth_sam.c @@ -23,6 +23,8 @@ #include "includes.h" +extern struct timeval smb_last_time; + #undef DBGC_CLASS #define DBGC_CLASS DBGC_AUTH @@ -74,7 +76,6 @@ static NTSTATUS sam_password_ok(const struct auth_context *auth_context, static BOOL logon_hours_ok(SAM_ACCOUNT *sampass) { /* In logon hours first bit is Sunday from 12AM to 1AM */ - extern struct timeval smb_last_time; const uint8 *hours; struct tm *utctime; uint8 bitmask, bitpos; diff --git a/source/auth/auth_util.c b/source/auth/auth_util.c index 7cab3df99e4..a50a449815c 100644 --- a/source/auth/auth_util.c +++ b/source/auth/auth_util.c @@ -26,11 +26,6 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_AUTH -extern DOM_SID global_sid_World; -extern DOM_SID global_sid_Network; -extern DOM_SID global_sid_Builtin_Guests; -extern DOM_SID global_sid_Authenticated_Users; - /**************************************************************************** Create a UNIX user on demand. diff --git a/source/client/client.c b/source/client/client.c index 07eb02cf05c..604bf0989a8 100644 --- a/source/client/client.c +++ b/source/client/client.c @@ -29,6 +29,9 @@ #define REGISTER 0 #endif +extern BOOL AllowDebugChange; +extern BOOL override_logfile; +extern char tar_type; extern BOOL in_client; static int port = 0; pstring cur_dir = "\\"; @@ -711,7 +714,7 @@ static int do_get(char *rname, char *lname, BOOL reget) struct timeval tp_start; int read_size = io_bufsize; uint16 attr; - size_t size; + SMB_OFF_T size; off_t start = 0; off_t nread = 0; int rc = 0; @@ -1135,7 +1138,7 @@ static int do_put(char *rname, char *lname, BOOL reput) { int fnum; XFILE *f; - size_t start = 0; + SMB_OFF_T start = 0; off_t nread = 0; char *buf = NULL; int maxwrite = io_bufsize; @@ -2235,6 +2238,25 @@ static int cmd_rename(void) return 0; } +/**************************************************************************** + Print the volume name. +****************************************************************************/ + +static int cmd_volume(void) +{ + fstring volname; + uint32 serial_num; + time_t create_date; + + if (!cli_get_fs_volume_info(cli, volname, &serial_num, &create_date)) { + d_printf("Errr %s getting volume info\n",cli_errstr(cli)); + return 1; + } + + d_printf("Volume: |%s| serial number 0x%x\n", volname, (unsigned int)serial_num); + return 0; +} + /**************************************************************************** Hard link files using the NT call. ****************************************************************************/ @@ -2748,6 +2770,7 @@ static struct {"tar",cmd_tar,"tar [IXFqbgNan] current directory to/from ",{COMPL_NONE,COMPL_NONE}}, {"tarmode",cmd_tarmode," tar's behaviour towards archive bits",{COMPL_NONE,COMPL_NONE}}, {"translate",cmd_translate,"toggle text translation for printing",{COMPL_NONE,COMPL_NONE}}, + {"volume",cmd_volume,"print the volume name",{COMPL_NONE,COMPL_NONE}}, {"vuid",cmd_vuid,"change current vuid",{COMPL_NONE,COMPL_NONE}}, {"logon",cmd_logon,"establish new logon",{COMPL_NONE,COMPL_NONE}}, {"listconnect",cmd_list_connect,"list open connections",{COMPL_NONE,COMPL_NONE}}, @@ -3271,13 +3294,10 @@ static int do_message_op(void) int main(int argc,char *argv[]) { - extern BOOL AllowDebugChange; - extern BOOL override_logfile; pstring base_directory; int opt; pstring query_host; BOOL message = False; - extern char tar_type; pstring term_code; static const char *new_name_resolve_order = NULL; poptContext pc; diff --git a/source/client/clitar.c b/source/client/clitar.c index 524feca1d2a..b241bd0ec2a 100644 --- a/source/client/clitar.c +++ b/source/client/clitar.c @@ -44,7 +44,7 @@ static int clipfind(char **aret, int ret, char *tok); typedef struct file_info_struct file_info2; struct file_info_struct { - SMB_BIG_UINT size; + SMB_OFF_T size; uint16 mode; uid_t uid; gid_t gid; @@ -63,6 +63,7 @@ typedef struct { } stack; #define SEPARATORS " \t\n\r" +extern time_t newer_than; extern struct cli_state *cli; /* These defines are for the do_setrattr routine, to indicate @@ -1621,7 +1622,6 @@ int tar_parseargs(int argc, char *argv[], const char *Optarg, int Optind) return 0; } else { SMB_STRUCT_STAT stbuf; - extern time_t newer_than; if (sys_stat(argv[Optind], &stbuf) == 0) { newer_than = stbuf.st_mtime; diff --git a/source/client/mount.cifs.c b/source/client/mount.cifs.c index 7b30b98fa7b..3145447cc4e 100755 --- a/source/client/mount.cifs.c +++ b/source/client/mount.cifs.c @@ -1,6 +1,6 @@ /* Mount helper utility for Linux CIFS VFS (virtual filesystem) client - Copyright (C) 2003 Steve French (sfrench@us.ibm.com) + Copyright (C) 2003,2005 Steve French (sfrench@us.ibm.com) 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 @@ -39,7 +39,7 @@ #include #define MOUNT_CIFS_VERSION_MAJOR "1" -#define MOUNT_CIFS_VERSION_MINOR "6" +#define MOUNT_CIFS_VERSION_MINOR "7" #ifndef MOUNT_CIFS_VENDOR_SUFFIX #define MOUNT_CIFS_VENDOR_SUFFIX "" @@ -60,7 +60,8 @@ static int got_uid = 0; static int got_gid = 0; static int free_share_name = 0; static char * user_name = NULL; -char * mountpassword = NULL; +static char * mountpassword = NULL; +char * domain_name = NULL; /* BB finish BB @@ -72,6 +73,9 @@ char * mountpassword = NULL; BB end finish BB */ +static char * check_for_domain(char **); + + static void mount_cifs_usage(void) { printf("\nUsage: %s -o \n", thisprogram); @@ -79,11 +83,11 @@ static void mount_cifs_usage(void) printf(" to a local directory.\n\nOptions:\n"); printf("\tuser=\n\tpass=\n\tdom=\n"); printf("\nLess commonly used options:"); - printf("\n\tcredentials=,guest,perm,noperm,setuids,nosetuids,\n\trw,ro,sep=,iocharset=,suid,nosuid,exec,noexec,directio"); - printf("\n\nOptions not needed for servers supporting CIFS Unix extensions (e.g. most Samba versions):"); + printf("\n\tcredentials=,guest,perm,noperm,setuids,nosetuids,rw,ro,\n\tsep=,iocharset=,suid,nosuid,exec,noexec,serverino,\n\tdirectio"); + printf("\n\nOptions not needed for servers supporting CIFS Unix extensions\n\t(e.g. most Samba versions):"); printf("\n\tuid=,gid=,dir_mode=,file_mode="); printf("\n\nRarely used options:"); - printf("\n\tport=,rsize=,wsize=,unc=,ip=,dev,nodev"); + printf("\n\tport=,rsize=,wsize=,unc=,ip=,\n\tdev,nodev,nouser_xattr,netbiosname,hard,soft,intr,nointr,noacl"); printf("\n\nOptions are described in more detail in the manual page"); printf("\n\tman 8 mount.cifs\n"); printf("\nTo display the version number of the mount helper:"); @@ -107,7 +111,7 @@ static char * getusername(void) { return username; } -char * parse_cifs_url(char * unc_name) +static char * parse_cifs_url(char * unc_name) { printf("\nMounting cifs URL not implemented yet. Attempt to mount %s\n",unc_name); return NULL; @@ -264,7 +268,9 @@ static int parse_options(char * options, int * filesys_flags) data = options; if(verboseflag) - printf("\n parsing options: %s", options); + printf("parsing options: %s\n", options); + + /* BB fixme check for separator override BB */ /* while ((data = strsep(&options, ",")) != NULL) { */ while(data != NULL) { @@ -276,15 +282,12 @@ static int parse_options(char * options, int * filesys_flags) /* data = next keyword */ /* value = next value ie stuff after equal sign */ - next_keyword = strchr(data,','); + next_keyword = strchr(data,','); /* BB handle sep= */ /* temporarily null terminate end of keyword=value pair */ if(next_keyword) *next_keyword = 0; - /* if (!*data) - continue; */ - /* temporarily null terminate keyword to make keyword and value distinct */ if ((value = strchr(data, '=')) != NULL) { *value = '\0'; @@ -298,6 +301,7 @@ static int parse_options(char * options, int * filesys_flags) } else if (strncmp(data, "user_xattr",10) == 0) { /* do nothing - need to skip so not parsed as user name */ } else if (strncmp(data, "user", 4) == 0) { + if (!value || !*value) { if(data[4] == '\0') { if(verboseflag) @@ -308,7 +312,6 @@ static int parse_options(char * options, int * filesys_flags) data[1] = ','; data[2] = ','; data[3] = ','; - /* BB remove it from mount line so as not to confuse kernel code */ } else { printf("username specified with no parameter\n"); return 1; /* needs_arg; */ @@ -334,6 +337,13 @@ static int parse_options(char * options, int * filesys_flags) } } } + /* this is only case in which the user + name buf is not malloc - so we have to + check for domain name embedded within + the user name here since the later + call to check_for_domain will not be + invoked */ + domain_name = check_for_domain(&value); } else { printf("username too long\n"); return 1; @@ -516,15 +526,135 @@ static int parse_options(char * options, int * filesys_flags) /* put previous overwritten comma back */ if(next_keyword) - *next_keyword = ','; + *next_keyword = ','; /* BB handle sep= */ else data = NULL; } return 0; } +/* replace all (one or more) commas with double commas */ +static void check_for_comma(char ** ppasswrd) +{ + char *new_pass_buf; + char *pass; + int i,j; + int number_of_commas = 0; + int len = strlen(*ppasswrd); + + if(ppasswrd == NULL) + return; + else + (pass = *ppasswrd); + + for(i=0;i 64) { + /* would otherwise overflow the mount options buffer */ + printf("\nInvalid password. Password contains too many commas.\n"); + return; + } + + new_pass_buf = malloc(len+number_of_commas+1); + if(new_pass_buf == NULL) + return; + + for(i=0,j=0;i= original_len) { + /* should not happen */ + return domainnm; + } + + for(i=0;i +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define UNMOUNT_CIFS_VERSION_MAJOR "0" +#define UNMOUNT_CIFS_VERSION_MINOR "1" + +#ifndef UNMOUNT_CIFS_VENDOR_SUFFIX +#define UNMOUNT_CIFS_VENDOR_SUFFIX "" +#endif + +#ifndef MNT_DETACH +#define MNT_DETACH 0x02 +#endif + +#ifndef MNT_EXPIRE +#define MNT_EXPIRE 0x04 +#endif + +#define CIFS_IOC_CHECKUMOUNT _IO('c', 2) + +static struct option longopts[] = { + { "all", 0, NULL, 'a' }, + { "help",0, NULL, 'h' }, + { "read-only", 0, NULL, 'r' }, + { "ro", 0, NULL, 'r' }, + { "verbose", 0, NULL, 'v' }, + { "version", 0, NULL, 'V' }, + { "expire", 0, NULL, 'e' }, + { "force", 0, 0, 'f' }, + { "lazy", 0, 0, 'l' }, + { "no-mtab", 0, 0, 'n' }, + { NULL, 0, NULL, 0 } +}; + +char * thisprogram; +int verboseflg = 0; + +static void umount_cifs_usage(void) +{ + printf("\nUsage: %s \n", thisprogram); + printf("\nUnmount the specified directory\n"); + printf("\nLess commonly used options:"); + printf("\n\t-r\tIf mount fails, retry with readonly remount."); + printf("\n\t-n\tDo not write to mtab."); + printf("\n\t-f\tAttempt a forced unmount, even if the fs is busy."); + printf("\n\t-l\tAttempt lazy unmount, Unmount now, cleanup later."); + printf("\n\t-v\tEnable verbose mode (may be useful for debugging)."); + printf("\n\t-h\tDisplay this help."); + printf("\n\nOptions are described in more detail in the manual page"); + printf("\n\tman 8 umount.cifs\n"); + printf("\nTo display the version number of the cifs umount utility:"); + printf("\n\t%s -V\n",thisprogram); +} + +static int umount_check_perm(char * dir) +{ + int fileid; + int rc; + + /* presumably can not chdir into the target as we do on mount */ + + fileid = open(dir, O_RDONLY | O_DIRECTORY | O_NOFOLLOW, 0); + if(fileid == -1) { + if(verboseflg) + printf("error opening mountpoint %d %s",errno,strerror(errno)); + return errno; + } + + rc = ioctl(fileid, CIFS_IOC_CHECKUMOUNT, NULL); + + if(verboseflg) + printf("ioctl returned %d with errno %d %s\n",rc,errno,strerror(errno)); + + if(rc == ENOTTY) + printf("user unmounting via %s is an optional feature of the cifs filesystem driver (cifs.ko)\n\tand requires cifs.ko version 1.32 or later\n",thisprogram); + else if (rc > 0) + printf("user unmount of %s failed with %d %s",dir,errno,strerror(errno)); + close(fileid); + + return rc; +} + +int main(int argc, char ** argv) +{ + int c; + int rc; + int flags = 0; + int nomtab = 0; + int retry_remount = 0; + struct mntent mountent; + char * mountpoint; + FILE * pmntfile; + + if(argc && argv) { + thisprogram = argv[0]; + } else { + umount_cifs_usage(); + return -EINVAL; + } + + if(argc < 2) { + umount_cifs_usage(); + return -EINVAL; + } + + if(thisprogram == NULL) + thisprogram = "umount.cifs"; + + /* add sharename in opts string as unc= parm */ + + while ((c = getopt_long (argc, argv, "afhilnrvV", + longopts, NULL)) != -1) { + switch (c) { +/* No code to do the following option yet */ +/* case 'a': + ++umount_all; + break; */ + case '?': + case 'h': /* help */ + umount_cifs_usage(); + exit(1); + case 'n': + ++nomtab; + break; + case 'f': + flags |= MNT_FORCE; + break; + case 'l': + flags |= MNT_DETACH; /* lazy unmount */ + break; + case 'e': + flags |= MNT_EXPIRE; /* gradually timeout */ + break; + case 'r': + ++retry_remount; + break; + case 'v': + ++verboseflg; + break; + case 'V': + printf ("umount.cifs version: %s.%s%s\n", + UNMOUNT_CIFS_VERSION_MAJOR, + UNMOUNT_CIFS_VERSION_MINOR, + UNMOUNT_CIFS_VENDOR_SUFFIX); + exit (0); + default: + printf("unknown unmount option %c\n",c); + umount_cifs_usage(); + exit(1); + } + } + + /* move past the umount options */ + argv += optind; + argc -= optind; + + mountpoint = argv[0]; + + if((argc < 1) || (argv[0] == NULL)) { + printf("\nMissing name of unmount directory\n"); + umount_cifs_usage(); + return -EINVAL; + } + + if(verboseflg) + printf("optind %d unmount dir %s\n",optind, mountpoint); + + /* check if running effectively root */ + if(geteuid() != 0) + printf("Trying to unmount when %s not installed suid\n",thisprogram); + + /* fixup path if needed */ + + /* check if our uid was the one who mounted */ + rc = umount_check_perm(mountpoint); + if (rc) { + return rc; + } + + if(umount2(mountpoint, flags)) { + /* remember to kill daemon on error */ + + switch (errno) { + case 0: + printf("mount failed but no error number set\n"); + break; + default: + + printf("mount error %d = %s\n",errno,strerror(errno)); + } + printf("Refer to the umount.cifs(8) manual page (e.g.man 8 umount.cifs)\n"); + return -1; + } else { + pmntfile = setmntent(MOUNTED, "a+"); + if(pmntfile) { +/* mountent.mnt_fsname = share_name; + mountent.mnt_dir = mountpoint; + mountent.mnt_type = "cifs"; + mountent.mnt_opts = malloc(220); + if(mountent.mnt_opts) { + char * mount_user = getusername(); + memset(mountent.mnt_opts,0,200); + if(flags & MS_RDONLY) + strcat(mountent.mnt_opts,"ro"); + else + strcat(mountent.mnt_opts,"rw"); + if(flags & MS_MANDLOCK) + strcat(mountent.mnt_opts,",mand"); + else + strcat(mountent.mnt_opts,",nomand"); + if(flags & MS_NOEXEC) + strcat(mountent.mnt_opts,",noexec"); + if(flags & MS_NOSUID) + strcat(mountent.mnt_opts,",nosuid"); + if(flags & MS_NODEV) + strcat(mountent.mnt_opts,",nodev"); + if(flags & MS_SYNCHRONOUS) + strcat(mountent.mnt_opts,",synch"); + if(mount_user) { + if(getuid() != 0) { + strcat(mountent.mnt_opts,",user="); + strcat(mountent.mnt_opts,mount_user); + } + free(mount_user); + } + } + mountent.mnt_freq = 0; + mountent.mnt_passno = 0; + rc = addmntent(pmntfile,&mountent); + endmntent(pmntfile); + if(mountent.mnt_opts) + free(mountent.mnt_opts);*/ + } else { + printf("could not update mount table\n"); + } + } + + return 0; +} + diff --git a/source/configure.in b/source/configure.in index f81d7fbb17d..fce7e268256 100644 --- a/source/configure.in +++ b/source/configure.in @@ -248,7 +248,7 @@ fi AC_ARG_ENABLE(developer, [ --enable-developer Turn on developer warnings and debugging (default=no)], [if eval "test x$enable_developer = xyes"; then developer=yes - CFLAGS="${CFLAGS} -gstabs -Wall -Wshadow -Wstrict-prototypes -Wpointer-arith -Wcast-qual -Wcast-align -Wwrite-strings -DDEBUG_PASSWORD -DDEVELOPER" + CFLAGS="${CFLAGS} -gstabs -Wall -Wshadow -Wstrict-prototypes -Wpointer-arith -Wcast-align -Wwrite-strings -DDEBUG_PASSWORD -DDEVELOPER" # Add -Wdeclaration-after-statement if compiler supports it AC_CACHE_CHECK( [that the C compiler understands -Wdeclaration-after-statement], @@ -416,7 +416,7 @@ DYNEXP= dnl Add modules that have to be built by default here dnl These have to be built static: -default_static_modules="pdb_smbpasswd pdb_tdbsam rpc_lsa rpc_samr rpc_reg rpc_lsa_ds rpc_wks rpc_net rpc_dfs rpc_srv rpc_spoolss auth_rhosts auth_sam auth_unix auth_winbind auth_server auth_domain auth_builtin" +default_static_modules="pdb_smbpasswd pdb_tdbsam rpc_lsa rpc_samr rpc_reg rpc_lsa_ds rpc_wks rpc_svcctl rpc_net rpc_dfs rpc_srv rpc_spoolss rpc_eventlog auth_rhosts auth_sam auth_unix auth_winbind auth_server auth_domain auth_builtin printerdb_file" dnl These are preferably build shared, and static if dlopen() is not available default_shared_modules="vfs_recycle vfs_audit vfs_extd_audit vfs_full_audit vfs_netatalk vfs_fake_perms vfs_default_quota vfs_readonly vfs_cap vfs_expand_msdfs vfs_shadow_copy charset_CP850 charset_CP437" @@ -691,8 +691,10 @@ AC_HEADER_TIME AC_HEADER_SYS_WAIT AC_CHECK_HEADERS(arpa/inet.h sys/fcntl.h sys/select.h fcntl.h sys/time.h sys/unistd.h rpc/nettype.h) AC_CHECK_HEADERS(unistd.h utime.h grp.h sys/id.h limits.h memory.h) -AC_CHECK_HEADERS(rpc/rpc.h rpcsvc/nis.h rpcsvc/yp_prot.h rpcsvc/ypclnt.h) -AC_CHECK_HEADERS(sys/param.h ctype.h sys/wait.h sys/resource.h sys/ioctl.h sys/ipc.h sys/mode.h) +AC_CHECK_HEADERS(rpc/rpc.h rpcsvc/nis.h rpcsvc/ypclnt.h) +## These fail to compile on IRIX so just check for their presence +AC_CHECK_HEADERS(rpcsvc/yp_prot.h, sys/mode.h, [], [] -) +AC_CHECK_HEADERS(sys/param.h ctype.h sys/wait.h sys/resource.h sys/ioctl.h sys/ipc.h) AC_CHECK_HEADERS(sys/mman.h sys/filio.h sys/priv.h sys/shm.h string.h strings.h stdlib.h sys/socket.h) AC_CHECK_HEADERS(sys/mount.h sys/vfs.h sys/fs/s5param.h sys/filsys.h termios.h termio.h) AC_CHECK_HEADERS(sys/termio.h sys/statfs.h sys/dustat.h sys/statvfs.h stdarg.h sys/sockio.h) @@ -727,8 +729,10 @@ AC_CHECK_HEADERS(shadow.h netinet/tcp.h netinet/in_systm.h netinet/in_ip.h) AC_CHECK_HEADERS(nss.h nss_common.h nsswitch.h ns_api.h sys/security.h security/pam_appl.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/attributes.h attr/xattr.h sys/xattr.h sys/cdefs.h glob.h) -# These faile to compile on Solaris so just check for their presence +AC_CHECK_HEADERS(sys/acl.h sys/attributes.h attr/xattr.h sys/xattr.h sys/extattr.h sys/uio.h) +AC_CHECK_HEADERS(sys/cdefs.h glob.h) + +## These faile to compile on Solaris so just check for their presence AC_CHECK_HEADERS(security/pam_modules.h net/if.h netinet/ip.h, [], [], -) # For experimental utmp support (lastlog on some BSD-like systems) @@ -1162,6 +1166,18 @@ AC_CHECK_FUNCS(flistxattr removexattr lremovexattr fremovexattr) AC_CHECK_FUNCS(setxattr lsetxattr fsetxattr) AC_CHECK_FUNCS(attr_get attr_list attr_set attr_remove) AC_CHECK_FUNCS(attr_getf attr_listf attr_setf attr_removef) +# Check if we have extattr +case "$host_os" in + *freebsd4* | *DragonFly* ) + AC_DEFINE(BROKEN_EXTATTR, 1, [Does extattr API work]) + ;; + *) + AC_CHECK_FUNCS(extattr_delete_fd extattr_delete_file extattr_delete_link) + AC_CHECK_FUNCS(extattr_get_fd extattr_get_file extattr_get_link) + AC_CHECK_FUNCS(extattr_list_fd extattr_list_file extattr_list_link) + AC_CHECK_FUNCS(extattr_set_fd extattr_set_file extattr_set_link) + ;; +esac # Assume non-shared by default and override below BLDSHARED="false" @@ -3631,30 +3647,6 @@ else AC_MSG_RESULT(no$utmp_no_reason) fi -################################################# -# choose native language(s) of man pages -AC_MSG_CHECKING(chosen man pages' language(s)) -AC_ARG_WITH(manpages-langs, -[ --with-manpages-langs={en,ja,pl} Choose man pages' language(s). (en)], -[ case "$withval" in - yes|no) - AC_MSG_WARN(--with-manpages-langs called without argument - will use default) - manlangs="en" - ;; - *) - manlangs="$withval" - ;; - esac - - AC_MSG_RESULT($manlangs) - manlangs=`echo $manlangs | sed "s/,/ /g"` # replacing commas with spaces to produce a list - AC_SUBST(manlangs)], - - [manlangs="en" - AC_MSG_RESULT($manlangs) - AC_SUBST(manlangs)] -) - ################################################# # should we build libsmbclient? @@ -4555,10 +4547,12 @@ SMB_MODULE(rpc_lsa, \$(RPC_LSA_OBJ), "bin/librpc_lsarpc.$SHLIBEXT", RPC) SMB_MODULE(rpc_reg, \$(RPC_REG_OBJ), "bin/librpc_winreg.$SHLIBEXT", RPC) SMB_MODULE(rpc_lsa_ds, \$(RPC_LSA_DS_OBJ), "bin/librpc_lsa_ds.$SHLIBEXT", RPC) SMB_MODULE(rpc_wks, \$(RPC_WKS_OBJ), "bin/librpc_wkssvc.$SHLIBEXT", RPC) +SMB_MODULE(rpc_svcctl, \$(RPC_SVCCTL_OBJ), "bin/librpc_svcctl.$SHLIBEXT", RPC) SMB_MODULE(rpc_net, \$(RPC_NETLOG_OBJ), "bin/librpc_NETLOGON.$SHLIBEXT", RPC) SMB_MODULE(rpc_dfs, \$(RPC_DFS_OBJ), "bin/librpc_netdfs.$SHLIBEXT", RPC) SMB_MODULE(rpc_srv, \$(RPC_SVC_OBJ), "bin/librpc_srvsvc.$SHLIBEXT", RPC) SMB_MODULE(rpc_spoolss, \$(RPC_SPOOLSS_OBJ), "bin/librpc_spoolss.$SHLIBEXT", RPC) +SMB_MODULE(rpc_eventlog, \$(RPC_EVENTLOG_OBJ), "bin/librpc_eventlog.$SHLIBEXT", RPC) SMB_MODULE(rpc_samr, \$(RPC_SAMR_OBJ), "bin/librpc_samr.$SHLIBEXT", RPC) SMB_MODULE(rpc_echo, \$(RPC_ECHO_OBJ), "bin/librpc_echo.$SHLIBEXT", RPC) SMB_SUBSYSTEM(RPC,smbd/server.o) @@ -4595,6 +4589,7 @@ SMB_MODULE(vfs_cap, \$(VFS_CAP_OBJ), "bin/cap.$SHLIBEXT", VFS) SMB_MODULE(vfs_expand_msdfs, \$(VFS_EXPAND_MSDFS_OBJ), "bin/expand_msdfs.$SHLIBEXT", VFS) SMB_MODULE(vfs_shadow_copy, \$(VFS_SHADOW_COPY_OBJ), "bin/shadow_copy.$SHLIBEXT", VFS) SMB_MODULE(vfs_afsacl, \$(VFS_AFSACL_OBJ), "bin/afsacl.$SHLIBEXT", VFS) +SMB_MODULE(vfs_catia, \$(VFS_AFSACL_OBJ), "bin/catia.$SHLIBEXT", VFS) SMB_SUBSYSTEM(VFS,smbd/vfs.o) AC_DEFINE_UNQUOTED(STRING_STATIC_MODULES, "$string_static_modules", [String list of builtin modules]) diff --git a/source/groupdb/mapping.c b/source/groupdb/mapping.c index 5613240a121..6e9d9b8e6cf 100644 --- a/source/groupdb/mapping.c +++ b/source/groupdb/mapping.c @@ -518,7 +518,7 @@ static NTSTATUS one_alias_membership(const DOM_SID *member, if (!string_to_sid(&alias, string_sid)) continue; - add_sid_to_array_unique(&alias, sids, num); + add_sid_to_array_unique(NULL, &alias, sids, num); if (sids == NULL) return NT_STATUS_NO_MEMORY; @@ -665,7 +665,7 @@ static int collect_aliasmem(TDB_CONTEXT *tdb_ctx, TDB_DATA key, TDB_DATA data, if (!string_to_sid(&member, member_string)) continue; - add_sid_to_array(&member, closure->sids, closure->num); + add_sid_to_array(NULL, &member, closure->sids, closure->num); } return 0; @@ -1253,8 +1253,6 @@ NTSTATUS pdb_default_enum_aliases(struct pdb_methods *methods, uint32 *num_aliases, struct acct_info **info) { - extern DOM_SID global_sid_Builtin; - GROUP_MAP *map; int i, num_maps; enum SID_NAME_USE type = SID_NAME_UNKNOWN; @@ -1348,11 +1346,42 @@ NTSTATUS pdb_default_enum_aliasmem(struct pdb_methods *methods, } NTSTATUS pdb_default_alias_memberships(struct pdb_methods *methods, + TALLOC_CTX *mem_ctx, + const DOM_SID *domain_sid, const DOM_SID *members, int num_members, - DOM_SID **aliases, int *num) + uint32 **alias_rids, + int *num_alias_rids) { - return alias_memberships(members, num_members, aliases, num); + DOM_SID *alias_sids; + int i, num_alias_sids; + NTSTATUS result; + + alias_sids = NULL; + num_alias_sids = 0; + + result = alias_memberships(members, num_members, + &alias_sids, &num_alias_sids); + + if (!NT_STATUS_IS_OK(result)) + return result; + + *alias_rids = TALLOC_ARRAY(mem_ctx, uint32, num_alias_sids); + if ((alias_sids != 0) && (*alias_rids == NULL)) + return NT_STATUS_NO_MEMORY; + + *num_alias_rids = 0; + + for (i=0; i #endif +#ifdef HAVE_SYS_EXTATTR_H +#include +#endif + +#ifdef HAVE_SYS_UIO_H +#include +#endif + #if HAVE_LOCALE_H #include #endif @@ -1372,4 +1380,7 @@ LDAP *ldap_open_with_timeout(const char *server, int port, unsigned int to); #undef HAVE_MMAP #endif +#define CONST_DISCARD(type, ptr) ((type) ((void *) (ptr))) +#define CONST_ADD(type, ptr) ((type) ((const void *) (ptr))) + #endif /* _INCLUDES_H */ diff --git a/source/include/libsmb_internal.h b/source/include/libsmb_internal.h index a1db5c27926..2eca879cbe2 100644 --- a/source/include/libsmb_internal.h +++ b/source/include/libsmb_internal.h @@ -35,7 +35,7 @@ struct smbc_dir_list { struct _SMBCFILE { int cli_fd; char *fname; - off_t offset; + SMB_OFF_T offset; struct _SMBCSRV *srv; BOOL file; struct smbc_dir_list *dir_list, *dir_end, *dir_next; diff --git a/source/include/libsmbclient.h b/source/include/libsmbclient.h index 636083b41d4..ea013c113a0 100644 --- a/source/include/libsmbclient.h +++ b/source/include/libsmbclient.h @@ -26,6 +26,10 @@ #ifndef SMBCLIENT_H_INCLUDED #define SMBCLIENT_H_INCLUDED +#ifdef __cplusplus +extern "C" { +#endif + /*-------------------------------------------------------------------*/ /* The following are special comments to instruct DOXYGEN (automated * documentation tool: @@ -550,13 +554,7 @@ struct _SMBCCTX { * * @note Do not forget to smbc_init_context() the returned SMBCCTX pointer ! */ -#ifdef __cplusplus -extern "C" { -#endif SMBCCTX * smbc_new_context(void); -#ifdef __cplusplus -} -#endif /**@ingroup misc * Delete a SBMCCTX (a context) acquired from smbc_new_context(). @@ -579,13 +577,8 @@ SMBCCTX * smbc_new_context(void); * just before exit()'ing. When shutdown_ctx is 0, this function can be * use in periodical cleanup functions for example. */ -#ifdef __cplusplus -extern "C" { -#endif int smbc_free_context(SMBCCTX * context, int shutdown_ctx); -#ifdef __cplusplus -} -#endif + /**@ingroup misc * Initialize a SBMCCTX (a context). @@ -605,13 +598,8 @@ int smbc_free_context(SMBCCTX * context, int shutdown_ctx); * but it might leak memory on smbc_context_init() failure. Avoid this. * You'll have to call smbc_free_context() yourself on failure. */ -#ifdef __cplusplus -extern "C" { -#endif + SMBCCTX * smbc_init_context(SMBCCTX * context); -#ifdef __cplusplus -} -#endif /**@ingroup misc * Initialize the samba client library. @@ -631,13 +619,7 @@ SMBCCTX * smbc_init_context(SMBCCTX * context); * */ -#ifdef __cplusplus -extern "C" { -#endif int smbc_init(smbc_get_auth_data_fn fn, int debug); -#ifdef __cplusplus -} -#endif /**@ingroup misc * Set or retrieve the compatibility library's context pointer @@ -661,13 +643,7 @@ int smbc_init(smbc_get_auth_data_fn fn, int debug); * authentication functions have been freed, if necessary. */ -#ifdef __cplusplus -extern "C" { -#endif SMBCCTX * smbc_set_context(SMBCCTX * new_context); -#ifdef __cplusplus -} -#endif /**@ingroup file * Open a file on an SMB server. @@ -720,13 +696,8 @@ SMBCCTX * smbc_set_context(SMBCCTX * new_context); * try again with an empty username and password. This * often gets mapped to the guest account on some machines. */ -#ifdef __cplusplus -extern "C" { -#endif + int smbc_open(const char *furl, int flags, mode_t mode); -#ifdef __cplusplus -} -#endif /**@ingroup file * Create a file on an SMB server. @@ -759,13 +730,8 @@ int smbc_open(const char *furl, int flags, mode_t mode); * @see smbc_open() * */ -#ifdef __cplusplus -extern "C" { -#endif + int smbc_creat(const char *furl, mode_t mode); -#ifdef __cplusplus -} -#endif /**@ingroup file * Read from a file using an opened file handle. @@ -787,13 +753,8 @@ int smbc_creat(const char *furl, mode_t mode); * @see smbc_open(), smbc_write() * */ -#ifdef __cplusplus -extern "C" { -#endif ssize_t smbc_read(int fd, void *buf, size_t bufsize); -#ifdef __cplusplus -} -#endif + /**@ingroup file * Write to a file using an opened file handle. @@ -815,13 +776,8 @@ ssize_t smbc_read(int fd, void *buf, size_t bufsize); * @see smbc_open(), smbc_read() * */ -#ifdef __cplusplus -extern "C" { -#endif ssize_t smbc_write(int fd, void *buf, size_t bufsize); -#ifdef __cplusplus -} -#endif + /**@ingroup file * Seek to a specific location in a file. @@ -851,13 +807,8 @@ ssize_t smbc_write(int fd, void *buf, size_t bufsize); * * @todo Are errno values complete and correct? */ -#ifdef __cplusplus -extern "C" { -#endif off_t smbc_lseek(int fd, off_t offset, int whence); -#ifdef __cplusplus -} -#endif + /**@ingroup file * Close an open file handle. @@ -870,13 +821,8 @@ off_t smbc_lseek(int fd, off_t offset, int whence); * * @see smbc_open(), smbc_creat() */ -#ifdef __cplusplus -extern "C" { -#endif int smbc_close(int fd); -#ifdef __cplusplus -} -#endif + /**@ingroup directory * Unlink (delete) a file or directory. @@ -899,13 +845,8 @@ int smbc_close(int fd); * * @todo Are errno values complete and correct? */ -#ifdef __cplusplus -extern "C" { -#endif int smbc_unlink(const char *furl); -#ifdef __cplusplus -} -#endif + /**@ingroup directory * Rename or move a file or directory. @@ -947,13 +888,8 @@ int smbc_unlink(const char *furl); * share? I say no... NOTE. I agree for the moment. * */ -#ifdef __cplusplus -extern "C" { -#endif int smbc_rename(const char *ourl, const char *nurl); -#ifdef __cplusplus -} -#endif + /**@ingroup directory * Open a directory used to obtain directory entries. @@ -975,13 +911,8 @@ int smbc_rename(const char *ourl, const char *nurl); * @see smbc_getdents(), smbc_readdir(), smbc_closedir() * */ -#ifdef __cplusplus -extern "C" { -#endif int smbc_opendir(const char *durl); -#ifdef __cplusplus -} -#endif + /**@ingroup directory * Close a directory handle opened by smbc_opendir(). @@ -993,13 +924,8 @@ int smbc_opendir(const char *durl); * * @see smbc_opendir() */ -#ifdef __cplusplus -extern "C" { -#endif int smbc_closedir(int dh); -#ifdef __cplusplus -} -#endif + /**@ingroup directory * Get multiple directory entries. @@ -1027,13 +953,8 @@ int smbc_closedir(int dh); * * @todo Add example code so people know how to parse buffers. */ -#ifdef __cplusplus -extern "C" { -#endif int smbc_getdents(unsigned int dh, struct smbc_dirent *dirp, int count); -#ifdef __cplusplus -} -#endif + /**@ingroup directory * Get a single directory entry. @@ -1047,13 +968,8 @@ int smbc_getdents(unsigned int dh, struct smbc_dirent *dirp, int count); * * @see smbc_dirent, smbc_getdents(), smbc_open() */ -#ifdef __cplusplus -extern "C" { -#endif struct smbc_dirent* smbc_readdir(unsigned int dh); -#ifdef __cplusplus -} -#endif + /**@ingroup directory * Get the current directory offset. @@ -1075,13 +991,8 @@ struct smbc_dirent* smbc_readdir(unsigned int dh); * @see smbc_readdir() * */ -#ifdef __cplusplus -extern "C" { -#endif off_t smbc_telldir(int dh); -#ifdef __cplusplus -} -#endif + /**@ingroup directory * lseek on directories. @@ -1105,13 +1016,7 @@ off_t smbc_telldir(int dh); * * @todo In what does the reture and errno values mean? */ -#ifdef __cplusplus -extern "C" { -#endif int smbc_lseekdir(int fd, off_t offset); -#ifdef __cplusplus -} -#endif /**@ingroup directory * Create a directory. @@ -1134,13 +1039,8 @@ int smbc_lseekdir(int fd, off_t offset); * @see smbc_rmdir() * */ -#ifdef __cplusplus -extern "C" { -#endif int smbc_mkdir(const char *durl, mode_t mode); -#ifdef __cplusplus -} -#endif + /**@ingroup directory * Remove a directory. @@ -1160,13 +1060,8 @@ int smbc_mkdir(const char *durl, mode_t mode); * * @todo Are errno values complete and correct? */ -#ifdef __cplusplus -extern "C" { -#endif int smbc_rmdir(const char *durl); -#ifdef __cplusplus -} -#endif + /**@ingroup attribute * Get information about a file or directory. @@ -1187,13 +1082,8 @@ int smbc_rmdir(const char *durl); * @see Unix stat() * */ -#ifdef __cplusplus -extern "C" { -#endif int smbc_stat(const char *url, struct stat *st); -#ifdef __cplusplus -} -#endif + /**@ingroup attribute * Get file information via an file descriptor. @@ -1213,13 +1103,8 @@ int smbc_stat(const char *url, struct stat *st); * @see smbc_stat(), Unix stat() * */ -#ifdef __cplusplus -extern "C" { -#endif int smbc_fstat(int fd, struct stat *st); -#ifdef __cplusplus -} -#endif + /**@ingroup attribue * Change the ownership of a file or directory. @@ -1244,13 +1129,8 @@ int smbc_fstat(int fd, struct stat *st); * @todo How do we abstract owner and group uid and gid? * */ -#ifdef __cplusplus -extern "C" { -#endif int smbc_chown(const char *url, uid_t owner, gid_t group); -#ifdef __cplusplus -} -#endif + /**@ingroup attribute * Change the permissions of a file. @@ -1272,13 +1152,7 @@ int smbc_chown(const char *url, uid_t owner, gid_t group); * * @todo Are errno values complete and correct? */ -#ifdef __cplusplus -extern "C" { -#endif int smbc_chmod(const char *url, mode_t mode); -#ifdef __cplusplus -} -#endif /**@ingroup attribute * Change the last modification time on a file @@ -1295,13 +1169,7 @@ int smbc_chmod(const char *url, mode_t mode); * - EPERM Permission was denied. * */ -#ifdef __cplusplus -extern "C" { -#endif int smbc_utimes(const char *url, struct timeval *tbuf); -#ifdef __cplusplus -} -#endif #ifdef HAVE_UTIME_H /**@ingroup attribute @@ -1320,13 +1188,7 @@ int smbc_utimes(const char *url, struct timeval *tbuf); * - EPERM Permission was denied. * */ -#ifdef __cplusplus -extern "C" { -#endif int smbc_utime(const char *fname, struct utimbuf *utbuf); -#ifdef __cplusplus -} -#endif #endif /**@ingroup attribute @@ -1428,17 +1290,12 @@ int smbc_utime(const char *fname, struct utimbuf *utbuf); * sYsTeM.nt_sEc_desc.owNER * */ -#ifdef __cplusplus -extern "C" { -#endif int smbc_setxattr(const char *url, const char *name, const void *value, size_t size, int flags); -#ifdef __cplusplus -} -#endif + /**@ingroup attribute * Set extended attributes for a file. This is used for modifying a file's @@ -1543,17 +1400,12 @@ int smbc_setxattr(const char *url, * sYsTeM.nt_sEc_desc.owNER * */ -#ifdef __cplusplus -extern "C" { -#endif int smbc_lsetxattr(const char *url, const char *name, const void *value, size_t size, int flags); -#ifdef __cplusplus -} -#endif + /**@ingroup attribute * Set extended attributes for a file. This is used for modifying a file's @@ -1655,17 +1507,12 @@ int smbc_lsetxattr(const char *url, * sYsTeM.nt_sEc_desc.owNER * */ -#ifdef __cplusplus -extern "C" { -#endif int smbc_fsetxattr(int fd, const char *name, const void *value, size_t size, int flags); -#ifdef __cplusplus -} -#endif + /**@ingroup attribute * Get extended attributes for a file. @@ -1723,16 +1570,11 @@ int smbc_fsetxattr(int fd, * extended attributes * */ -#ifdef __cplusplus -extern "C" { -#endif int smbc_getxattr(const char *url, const char *name, const void *value, size_t size); -#ifdef __cplusplus -} -#endif + /**@ingroup attribute * Get extended attributes for a file. The POSIX function which this maps to @@ -1793,16 +1635,11 @@ int smbc_getxattr(const char *url, * extended attributes * */ -#ifdef __cplusplus -extern "C" { -#endif int smbc_lgetxattr(const char *url, const char *name, const void *value, size_t size); -#ifdef __cplusplus -} -#endif + /**@ingroup attribute * Get extended attributes for a file. @@ -1861,16 +1698,11 @@ int smbc_lgetxattr(const char *url, * extended attributes * */ -#ifdef __cplusplus -extern "C" { -#endif int smbc_fgetxattr(int fd, const char *name, const void *value, size_t size); -#ifdef __cplusplus -} -#endif + /**@ingroup attribute * Remove extended attributes for a file. This is used for modifying a file's @@ -1915,14 +1747,9 @@ int smbc_fgetxattr(int fd, * extended attributes * */ -#ifdef __cplusplus -extern "C" { -#endif int smbc_removexattr(const char *url, const char *name); -#ifdef __cplusplus -} -#endif + /**@ingroup attribute * Remove extended attributes for a file. This is used for modifying a file's @@ -1970,14 +1797,9 @@ int smbc_removexattr(const char *url, * extended attributes * */ -#ifdef __cplusplus -extern "C" { -#endif int smbc_lremovexattr(const char *url, const char *name); -#ifdef __cplusplus -} -#endif + /**@ingroup attribute * Remove extended attributes for a file. This is used for modifying a file's @@ -2023,14 +1845,9 @@ int smbc_lremovexattr(const char *url, * extended attributes * */ -#ifdef __cplusplus -extern "C" { -#endif int smbc_fremovexattr(int fd, const char *name); -#ifdef __cplusplus -} -#endif + /**@ingroup attribute * List the supported extended attribute names associated with a file @@ -2062,15 +1879,9 @@ int smbc_fremovexattr(int fd, * extended attributes at all. Whether this is a feature or * a bug is yet to be decided. */ -#ifdef __cplusplus -extern "C" { -#endif int smbc_listxattr(const char *url, char *list, size_t size); -#ifdef __cplusplus -} -#endif /**@ingroup attribute * List the supported extended attribute names associated with a file The @@ -2106,15 +1917,9 @@ int smbc_listxattr(const char *url, * extended attributes at all. Whether this is a feature or * a bug is yet to be decided. */ -#ifdef __cplusplus -extern "C" { -#endif int smbc_llistxattr(const char *url, char *list, size_t size); -#ifdef __cplusplus -} -#endif /**@ingroup attribute * List the supported extended attribute names associated with a file @@ -2147,15 +1952,9 @@ int smbc_llistxattr(const char *url, * extended attributes at all. Whether this is a feature or * a bug is yet to be decided. */ -#ifdef __cplusplus -extern "C" { -#endif int smbc_flistxattr(int fd, char *list, size_t size); -#ifdef __cplusplus -} -#endif /**@ingroup print * Print a file given the name in fname. It would be a URL ... @@ -2172,13 +1971,7 @@ int smbc_flistxattr(int fd, * and errors returned by smbc_open * */ -#ifdef __cplusplus -extern "C" { -#endif int smbc_print_file(const char *fname, const char *printq); -#ifdef __cplusplus -} -#endif /**@ingroup print * Open a print file that can be written to by other calls. This simply @@ -2193,13 +1986,7 @@ int smbc_print_file(const char *fname, const char *printq); * - all errors returned by smbc_open * */ -#ifdef __cplusplus -extern "C" { -#endif int smbc_open_print_job(const char *fname); -#ifdef __cplusplus -} -#endif /**@ingroup print * List the print jobs on a print share, for the moment, pass a callback @@ -2212,13 +1999,7 @@ int smbc_open_print_job(const char *fname); * - EINVAL fname was NULL or smbc_init not called * - EACCES ??? */ -#ifdef __cplusplus -extern "C" { -#endif int smbc_list_print_jobs(const char *purl, smbc_list_print_job_fn fn); -#ifdef __cplusplus -} -#endif /**@ingroup print * Delete a print job @@ -2232,13 +2013,7 @@ int smbc_list_print_jobs(const char *purl, smbc_list_print_job_fn fn); * * @todo what errno values are possible here? */ -#ifdef __cplusplus -extern "C" { -#endif int smbc_unlink_print_job(const char *purl, int id); -#ifdef __cplusplus -} -#endif /**@ingroup callback * Remove a server from the cached server list it's unused. @@ -2250,10 +2025,8 @@ int smbc_unlink_print_job(const char *purl, int id); * @return On success, 0 is returned. 1 is returned if the server could not * be removed. Also useable outside libsmbclient. */ -#ifdef __cplusplus -extern "C" { -#endif int smbc_remove_unused_server(SMBCCTX * context, SMBCSRV * srv); + #ifdef __cplusplus } #endif diff --git a/source/include/msdfs.h b/source/include/msdfs.h index afbbe738fe1..8d6b23bcbfb 100644 --- a/source/include/msdfs.h +++ b/source/include/msdfs.h @@ -68,18 +68,17 @@ struct dfs_path #define RESOLVE_DFSPATH(name, conn, inbuf, outbuf) \ { if ((SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES) && \ lp_host_msdfs() && lp_msdfs_root(SNUM(conn)) && \ - dfs_redirect(name,conn,False)) \ + dfs_redirect(name, conn, False)) \ return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, \ ERRSRV, ERRbadpath);; } -#define RESOLVE_FINDFIRST_DFSPATH(name, conn, inbuf, outbuf) \ +#define RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf) \ { if ((SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES) && \ lp_host_msdfs() && lp_msdfs_root(SNUM(conn)) && \ - dfs_redirect(name,conn,True)) \ + dfs_redirect(name,conn, True)) \ return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, \ ERRSRV, ERRbadpath);; } - #define init_dfsroot(conn, inbuf, outbuf) \ { if (lp_msdfs_root(SNUM(conn)) && lp_host_msdfs()) { \ DEBUG(2,("Serving %s as a Dfs root\n", \ diff --git a/source/include/nt_status.h b/source/include/nt_status.h index 9747f73eb18..ab768258df1 100644 --- a/source/include/nt_status.h +++ b/source/include/nt_status.h @@ -56,6 +56,7 @@ typedef uint32 WERROR; #define NT_STATUS_IS_OK(x) (NT_STATUS_V(x) == 0) #define NT_STATUS_IS_ERR(x) ((NT_STATUS_V(x) & 0xc0000000) == 0xc0000000) +#define NT_STATUS_IS_INVALID(x) (NT_STATUS_V(x) == 0xFFFFFFFF) #define NT_STATUS_EQUAL(x,y) (NT_STATUS_V(x) == NT_STATUS_V(y)) #define W_ERROR_IS_OK(x) (W_ERROR_V(x) == 0) #define W_ERROR_EQUAL(x,y) (W_ERROR_V(x) == W_ERROR_V(y)) diff --git a/source/include/ntdomain.h b/source/include/ntdomain.h index 45d64cf6331..87fac492db3 100644 --- a/source/include/ntdomain.h +++ b/source/include/ntdomain.h @@ -391,13 +391,16 @@ typedef struct { #include "authdata.h" /* different dce/rpc pipes */ +#include "rpc_buffer.h" #include "rpc_lsa.h" #include "rpc_netlogon.h" #include "rpc_reg.h" #include "rpc_samr.h" #include "rpc_srvsvc.h" #include "rpc_wkssvc.h" +#include "rpc_svcctl.h" #include "rpc_spoolss.h" +#include "rpc_eventlog.h" #include "rpc_dfs.h" #include "rpc_ds.h" #include "rpc_echo.h" diff --git a/source/include/nterr.h b/source/include/nterr.h index 6cf5a756d29..417719625e7 100644 --- a/source/include/nterr.h +++ b/source/include/nterr.h @@ -37,6 +37,9 @@ #define STATUS_NOTIFY_ENUM_DIR NT_STATUS(0x010c) #define ERROR_INVALID_DATATYPE NT_STATUS(0x070c) +/* Special "invalid" NT status code. */ +#define NT_STATUS_INVALID NT_STATUS(0xFFFFFFFF) + /* Win32 Error codes extracted using a loop in smbclient then printing a netmon sniff to a file. */ diff --git a/source/include/passdb.h b/source/include/passdb.h index 5a70bb45a8c..624f0c5fea6 100644 --- a/source/include/passdb.h +++ b/source/include/passdb.h @@ -337,10 +337,20 @@ typedef struct pdb_context DOM_SID **members, int *num_members); NTSTATUS (*pdb_enum_alias_memberships)(struct pdb_context *context, + TALLOC_CTX *mem_ctx, + const DOM_SID *domain_sid, const DOM_SID *members, int num_members, - DOM_SID **aliases, - int *num_aliases); + uint32 **alias_rids, + int *num_alias_rids); + + NTSTATUS (*pdb_lookup_rids)(struct pdb_context *context, + TALLOC_CTX *mem_ctx, + const DOM_SID *domain_sid, + int num_rids, + uint32 *rids, + const char ***names, + uint32 **attrs); void (*free_fn)(struct pdb_context **); @@ -437,9 +447,19 @@ typedef struct pdb_methods const DOM_SID *alias, DOM_SID **members, int *num_members); NTSTATUS (*enum_alias_memberships)(struct pdb_methods *methods, + TALLOC_CTX *mem_ctx, + const DOM_SID *domain_sid, const DOM_SID *members, int num_members, - DOM_SID **aliases, int *num); + uint32 **alias_rids, + int *num_alias_rids); + NTSTATUS (*lookup_rids)(struct pdb_methods *methods, + TALLOC_CTX *mem_ctx, + const DOM_SID *domain_sid, + int num_rids, + uint32 *rids, + const char ***names, + uint32 **attrs); void *private_data; /* Private data of some kind */ @@ -460,4 +480,27 @@ struct pdb_init_function_entry { enum sql_search_field { SQL_SEARCH_NONE = 0, SQL_SEARCH_USER_SID = 1, SQL_SEARCH_USER_NAME = 2}; +struct samr_displayentry { + uint32 rid; + uint16 acct_flags; + const char *account_name; + const char *fullname; + const char *description; +}; + +enum pdb_search_type { + PDB_USER_SEARCH, + PDB_GROUP_SEARCH, + PDB_ALIAS_SEARCH +}; + +struct pdb_search { + TALLOC_CTX *mem_ctx; + enum pdb_search_type type; + struct samr_displayentry *cache; + uint32 cache_size; + BOOL search_ended; + void *private; +}; + #endif /* _PASSDB_H */ diff --git a/source/include/rpc_buffer.h b/source/include/rpc_buffer.h new file mode 100644 index 00000000000..da2be8a4df6 --- /dev/null +++ b/source/include/rpc_buffer.h @@ -0,0 +1,35 @@ +/* + Unix SMB/Netbios implementation. + + Copyright (C) Andrew Tridgell 1992-2000, + Copyright (C) Luke Kenneth Casson Leighton 1996-2000, + Copyright (C) Jean Francois Micouleau 1998-2000. + Copyright (C) Gerald Carter 2001-2005. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef _RPC_BUFFER_H /* _RPC_SPOOLSS_H */ +#define _RPC_BUFFER_H + +typedef struct { + uint32 size; + prs_struct prs; + uint32 struct_start; + uint32 string_at_end; +} RPC_BUFFER; + + +#endif /* _RPC_BUFFER_H */ diff --git a/source/include/rpc_client.h b/source/include/rpc_client.h index bce9ec7f273..4ac2f43ee00 100644 --- a/source/include/rpc_client.h +++ b/source/include/rpc_client.h @@ -1,7 +1,7 @@ /* Unix SMB/CIFS implementation. SMB parameters and setup - Copyright (C) Elrond 2000 + Copyright (C) Gerald (Jerry) Carter 2005. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -21,8 +21,21 @@ #ifndef _RPC_CLIENT_H #define _RPC_CLIENT_H -#if 0 /* JERRY */ -#include "rpc_client_proto.h" -#endif +/* macro to expand cookie-cutter code in cli_xxx() */ + +#define CLI_DO_RPC( pcli, ctx, pipe_num, opnum, q_in, r_out, q_ps, r_ps, q_io_fn, r_io_fn, default_error) \ +{ r_out.status = default_error;\ + prs_init( &q_ps, MAX_PDU_FRAG_LEN, ctx, MARSHALL ); \ + prs_init( &r_ps, 0, ctx, UNMARSHALL );\ + if ( q_io_fn("", &q_in, &q_ps, 0) ) {\ + if ( rpc_api_pipe_req(pcli, pipe_num, opnum, &q_ps, &r_ps) ) {\ + if (!r_io_fn("", &r_out, &r_ps, 0)) {\ + r_out.status = default_error;\ + }\ + }\ + }\ + prs_mem_free( &q_ps );\ + prs_mem_free( &r_ps );\ +} #endif /* _RPC_CLIENT_H */ diff --git a/source/include/rpc_eventlog.h b/source/include/rpc_eventlog.h new file mode 100644 index 00000000000..b692a762257 --- /dev/null +++ b/source/include/rpc_eventlog.h @@ -0,0 +1,193 @@ +/* + * Unix SMB/CIFS implementation. + * RPC Pipe client / server routines + * Copyright (C) Marcin Krzysztof Porwit 2005. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _RPC_EVENTLOG_H /* _RPC_EVENTLOG_H */ +#define _RPC_EVENTLOG_H + +/* opcodes */ + +#define EVENTLOG_CLEAREVENTLOG 0x00 +#define EVENTLOG_CLOSEEVENTLOG 0x02 +#define EVENTLOG_GETNUMRECORDS 0x04 +#define EVENTLOG_GETOLDESTENTRY 0x05 +#define EVENTLOG_OPENEVENTLOG 0x07 +#define EVENTLOG_READEVENTLOG 0x0a + +/* Eventlog read flags */ + +#define EVENTLOG_SEQUENTIAL_READ 0x0001 +#define EVENTLOG_SEEK_READ 0x0002 +#define EVENTLOG_FORWARDS_READ 0x0004 +#define EVENTLOG_BACKWARDS_READ 0x0008 + +/* Event types */ + +#define EVENTLOG_SUCCESS 0x0000 +#define EVENTLOG_ERROR_TYPE 0x0001 +#define EVENTLOG_WARNING_TYPE 0x0002 +#define EVENTLOG_INFORMATION_TYPE 0x0004 +#define EVENTLOG_AUDIT_SUCCESS 0x0008 +#define EVENTLOG_AUDIT_FAILURE 0x0010 + + +typedef struct eventlog_q_open_eventlog +{ + uint32 unknown1; + uint16 unknown2; + uint16 unknown3; + uint16 sourcename_length; + uint16 sourcename_size; + uint32 sourcename_ptr; + UNISTR2 sourcename; + uint32 servername_ptr; + UNISTR2 servername; +} +EVENTLOG_Q_OPEN_EVENTLOG; + +typedef struct eventlog_r_open_eventlog +{ + POLICY_HND handle; + WERROR status; +} +EVENTLOG_R_OPEN_EVENTLOG; + +typedef struct eventlog_q_close_eventlog +{ + POLICY_HND handle; +} +EVENTLOG_Q_CLOSE_EVENTLOG; + +typedef struct eventlog_r_close_eventlog +{ + POLICY_HND handle; + WERROR status; +} +EVENTLOG_R_CLOSE_EVENTLOG; + +typedef struct eventlog_q_get_num_records +{ + POLICY_HND handle; +} +EVENTLOG_Q_GET_NUM_RECORDS; + +typedef struct eventlog_r_get_num_records +{ + uint32 num_records; + WERROR status; +} +EVENTLOG_R_GET_NUM_RECORDS; + +typedef struct eventlog_q_get_oldest_entry +{ + POLICY_HND handle; +} +EVENTLOG_Q_GET_OLDEST_ENTRY; + +typedef struct eventlog_r_get_oldest_entry +{ + uint32 oldest_entry; + WERROR status; +} +EVENTLOG_R_GET_OLDEST_ENTRY; + +typedef struct eventlog_q_read_eventlog +{ + POLICY_HND handle; + uint32 flags; + uint32 offset; + uint32 max_read_size; +} +EVENTLOG_Q_READ_EVENTLOG; + +typedef struct eventlog_record +{ + uint32 length; + uint32 reserved1; + uint32 record_number; + uint32 time_generated; + uint32 time_written; + uint32 event_id; + uint16 event_type; + uint16 num_strings; + uint16 event_category; + uint16 reserved2; + uint32 closing_record_number; + uint32 string_offset; + uint32 user_sid_length; + uint32 user_sid_offset; + uint32 data_length; + uint32 data_offset; +} Eventlog_record; + +typedef struct eventlog_data_record +{ + uint32 source_name_len; + wpstring source_name; + uint32 computer_name_len; + wpstring computer_name; + uint32 sid_padding; + wpstring sid; + uint32 strings_len; + wpstring strings; + uint32 user_data_len; + pstring user_data; + uint32 data_padding; +} Eventlog_data_record; + +typedef struct eventlog_entry +{ + Eventlog_record record; + Eventlog_data_record data_record; + uint8 *data; + uint8 *end_of_data_padding; + struct eventlog_entry *next; +} Eventlog_entry; + +typedef struct eventlog_r_read_eventlog +{ + uint32 num_bytes_in_resp; + uint32 bytes_in_next_record; + uint32 num_records; + Eventlog_entry *entry; + uint8 *end_of_entries_padding; + uint32 sent_size; + uint32 real_size; + WERROR status; +} +EVENTLOG_R_READ_EVENTLOG; + +typedef struct eventlog_q_clear_eventlog +{ + POLICY_HND handle; + uint32 unknown1; + uint16 backup_file_length; + uint16 backup_file_size; + uint32 backup_file_ptr; + UNISTR2 backup_file; +} +EVENTLOG_Q_CLEAR_EVENTLOG; + +typedef struct eventlog_r_clear_eventlog +{ + WERROR status; +} +EVENTLOG_R_CLEAR_EVENTLOG; + +#endif /* _RPC_EVENTLOG_H */ diff --git a/source/include/rpc_lsa.h b/source/include/rpc_lsa.h index a0d78280c20..8eaf68a234d 100644 --- a/source/include/rpc_lsa.h +++ b/source/include/rpc_lsa.h @@ -1,9 +1,10 @@ /* Unix SMB/CIFS implementation. SMB parameters and setup - Copyright (C) Andrew Tridgell 1992-1997 - Copyright (C) Luke Kenneth Casson Leighton 1996-1997 - Copyright (C) Paul Ashton 1997 + Copyright (C) Andrew Tridgell 1992-1997 + Copyright (C) Luke Kenneth Casson Leighton 1996-1997 + Copyright (C) Paul Ashton 1997 + Copyright (C) Gerald (Jerry) Carter 2005 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -68,7 +69,7 @@ #define LSA_LOOKUPPRIVNAME 0x20 #define LSA_PRIV_GET_DISPNAME 0x21 #define LSA_DELETEOBJECT 0x22 -#define LSA_ENUMACCTWITHRIGHT 0x23 +#define LSA_ENUMACCTWITHRIGHT 0x23 /* TODO: implement this one -- jerry */ #define LSA_ENUMACCTRIGHTS 0x24 #define LSA_ADDACCTRIGHTS 0x25 #define LSA_REMOVEACCTRIGHTS 0x26 @@ -305,32 +306,33 @@ typedef struct lsa_r_query_info2 NTSTATUS status; } LSA_R_QUERY_INFO2; -/* LSA_Q_ENUM_TRUST_DOM - LSA enumerate trusted domains */ -typedef struct lsa_enum_trust_dom_info -{ - POLICY_HND pol; /* policy handle */ - uint32 enum_context; /* enumeration context handle */ - uint32 preferred_len; /* preferred maximum length */ +/*******************************************************/ +typedef struct { + POLICY_HND pol; + uint32 enum_context; + uint32 preferred_len; /* preferred maximum length */ } LSA_Q_ENUM_TRUST_DOM; -/* LSA_R_ENUM_TRUST_DOM - response to LSA enumerate trusted domains */ -typedef struct lsa_r_enum_trust_dom_info -{ - uint32 enum_context; /* enumeration context handle */ - uint32 num_domains; /* number of domains */ - uint32 ptr_enum_domains; /* buffer pointer to num domains */ - - /* this lot is only added if ptr_enum_domains is non-NULL */ - uint32 num_domains2; /* number of domains */ - UNIHDR2 *hdr_domain_name; - UNISTR2 *uni_domain_name; - DOM_SID2 *domain_sid; +typedef struct { + UNISTR4 name; + DOM_SID2 *sid; +} DOMAIN_INFO; - NTSTATUS status; /* return code */ +typedef struct { + uint32 count; + DOMAIN_INFO *domains; +} DOMAIN_LIST; +typedef struct { + uint32 enum_context; + uint32 count; + DOMAIN_LIST *domlist; + NTSTATUS status; } LSA_R_ENUM_TRUST_DOM; +/*******************************************************/ + /* LSA_Q_CLOSE */ typedef struct lsa_q_close_info { @@ -423,7 +425,7 @@ typedef struct lsa_q_lookup_sids POLICY_HND pol; /* policy handle */ LSA_SID_ENUM sids; LSA_TRANS_NAME_ENUM names; - LOOKUP_LEVEL level; + uint16 level; uint32 mapped_count; } LSA_Q_LOOKUP_SIDS; @@ -532,7 +534,7 @@ typedef struct typedef struct { uint32 count; - UNISTR2_ARRAY rights; + UNISTR4_ARRAY *rights; NTSTATUS status; } LSA_R_ENUM_ACCT_RIGHTS; @@ -542,8 +544,8 @@ typedef struct { POLICY_HND pol; /* policy handle */ DOM_SID2 sid; - UNISTR2_ARRAY rights; uint32 count; + UNISTR4_ARRAY *rights; } LSA_Q_ADD_ACCT_RIGHTS; /* LSA_R_ADD_ACCT_RIGHTS - LSA add account rights */ @@ -559,8 +561,8 @@ typedef struct POLICY_HND pol; /* policy handle */ DOM_SID2 sid; uint32 removeall; - UNISTR2_ARRAY rights; uint32 count; + UNISTR4_ARRAY *rights; } LSA_Q_REMOVE_ACCT_RIGHTS; /* LSA_R_REMOVE_ACCT_RIGHTS - LSA remove account rights */ diff --git a/source/include/rpc_misc.h b/source/include/rpc_misc.h index 6abc85a4cac..dcc0ecc554a 100644 --- a/source/include/rpc_misc.h +++ b/source/include/rpc_misc.h @@ -1,9 +1,10 @@ /* Unix SMB/CIFS implementation. - SMB parameters and setup - Copyright (C) Andrew Tridgell 1992-1997 - Copyright (C) Luke Kenneth Casson Leighton 1996-1997 - Copyright (C) Paul Ashton 1997 + + Copyright (C) Andrew Tridgell 1992-1997 + Copyright (C) Luke Kenneth Casson Leighton 1996-1997 + Copyright (C) Paul Ashton 1997 + Copyright (C) Gerald (Jerry) Carter 2005 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -27,8 +28,15 @@ #define _RPC_MISC_H #define SMB_RPC_INTERFACE_VERSION 1 +#define PRS_POINTER_CAST BOOL (*)(const char*, prs_struct*, int, void*) + +enum unistr2_term_codes { UNI_FLAGS_NONE = 0, UNI_STR_TERMINATE = 1, UNI_MAXLEN_TERMINATE = 2, UNI_BROKEN_NON_NULL = 3 }; + + -/* well-known RIDs - Relative IDs */ +/********************************************************************** + * well-known RIDs - Relative IDs + **********************************************************************/ /* RIDs - Well-known users ... */ #define DOMAIN_USER_RID_ADMIN (0x000001F4L) @@ -65,186 +73,208 @@ #define BUILTIN_ALIAS_RID_RAS_SERVERS (0x00000229L) #define BUILTIN_ALIAS_RID_PRE_2K_ACCESS (0x0000022aL) -/* + +/********************************************************************** * Masks for mappings between unix uid and gid types and * NT RIDS. - */ - + **********************************************************************/ #define BASE_RID (0x000003E8L) /* Take the bottom bit. */ -#define RID_TYPE_MASK 1 -#define RID_MULTIPLIER 2 +#define RID_TYPE_MASK 1 +#define RID_MULTIPLIER 2 /* The two common types. */ -#define USER_RID_TYPE 0 -#define GROUP_RID_TYPE 1 +#define USER_RID_TYPE 0 +#define GROUP_RID_TYPE 1 -/* ENUM_HND */ -typedef struct enum_hnd_info -{ + + +/********************************************************************** + * RPC policy handle used pretty much everywhere + **********************************************************************/ + +typedef struct { uint32 ptr_hnd; /* pointer to enumeration handle */ uint32 handle; /* enumeration handle */ } ENUM_HND; -/* LOOKUP_LEVEL - switch value */ -typedef struct lookup_level_info -{ - uint16 value; -} LOOKUP_LEVEL; -/* DOM_SID2 - security id */ -typedef struct sid_info_2 -{ - uint32 num_auths; /* length, bytes, including length of len :-) */ - DOM_SID sid; -} DOM_SID2; -/* STRHDR - string header */ -typedef struct header_info -{ - uint16 str_str_len; - uint16 str_max_len; - uint32 buffer; /* non-zero */ -} STRHDR; +/********************************************************************** + * RPC policy handle used pretty much everywhere + **********************************************************************/ -/* UNIHDR - unicode string header */ -typedef struct unihdr_info -{ - uint16 uni_str_len; - uint16 uni_max_len; - uint32 buffer; /* usually has a value of 4 */ -} UNIHDR; +typedef struct { + uint32 data1; + uint32 data2; + uint16 data3; + uint16 data4; + uint8 data5[8]; +#ifdef __INSURE__ -/* UNIHDR2 - unicode string header and undocumented buffer */ -typedef struct unihdr2_info -{ - UNIHDR unihdr; - uint32 buffer; /* 32 bit buffer pointer */ -} UNIHDR2; + /* To prevent the leakage of policy handles mallocate a bit of + memory when a policy handle is created and free it when the + handle is closed. This should cause Insure to flag an error + when policy handles are overwritten or fall out of scope without + being freed. */ -/* UNISTR - unicode string size and buffer */ -typedef struct unistr_info -{ - /* unicode characters. ***MUST*** be little-endian. ***MUST*** be null-terminated */ - uint16 *buffer; -} UNISTR; + char *marker; +#endif +} POLICY_HND; -/* BUFHDR - buffer header */ -typedef struct bufhdr_info -{ + +/********************************************************************** + * Buffer Headers -- use by SEC_DESC_BUF in winreg and netlogon code + **********************************************************************/ + +typedef struct { uint32 buf_max_len; uint32 buf_len; } BUFHDR; -/* BUFFER2 - unicode string, size (in uint8 ascii chars) and buffer */ -/* pathetic. some stupid team of \PIPE\winreg writers got the concept */ -/* of a unicode string different from the other \PIPE\ writers */ -typedef struct buffer2_info -{ +typedef struct { + uint32 info_level; + uint32 length; /* uint8 chars */ + uint32 buffer; +} BUFHDR2; + +typedef struct { + uint32 size; + uint32 buffer; +} BUFHDR4; + + +/********************************************************************** + * Buffers + **********************************************************************/ + +/* buffer used by \winreg\ calls to fill in arbitrary REG_XXX values. + It *may* look like a UNISTR2 but it is *not*. This is not a goof + by the winreg developers. It is a generic buffer */ + +typedef struct { uint32 buf_max_len; uint32 offset; uint32 buf_len; - /* unicode characters. ***MUST*** be little-endian. **NOT** necessarily null-terminated */ uint16 *buffer; -} BUFFER2; +} REGVAL_BUFFER; -/* BUFFER3 */ -typedef struct buffer3_info -{ - uint32 buf_max_len; - uint8 *buffer; /* Data */ +/* generic rpc version of the DATA_BLOB. Just a length and uint8 array */ + +typedef struct { uint32 buf_len; -} BUFFER3; + uint8 *buffer; +} RPC_DATA_BLOB; -/* BUFFER5 */ -typedef struct buffer5_info -{ +/********************************************************************** + * Buffers use by spoolss (i might be able to replace it with + * an RPC_DATA_BLOB) + **********************************************************************/ + +typedef struct { uint32 buf_len; uint16 *buffer; /* data */ } BUFFER5; -/* UNISTR2 - unicode string size (in uint16 unicode chars) and buffer */ -typedef struct unistr2_info -{ + +/********************************************************************** + * Unicode and basic string headers + **********************************************************************/ + +typedef struct { + uint16 str_str_len; + uint16 str_max_len; + uint32 buffer; /* non-zero */ +} STRHDR; + +typedef struct { + uint16 uni_str_len; + uint16 uni_max_len; + uint32 buffer; +} UNIHDR; + +/********************************************************************** + * UNICODE string variations + **********************************************************************/ + + +typedef struct { /* UNISTR - unicode string size and buffer */ + uint16 *buffer; /* unicode characters. ***MUST*** be + little-endian. ***MUST*** be null-terminated */ +} UNISTR; + +typedef struct { /* UNISTR2 - unicode string size (in + uint16 unicode chars) and buffer */ uint32 uni_max_len; uint32 offset; uint32 uni_str_len; - /* unicode characters. ***MUST*** be little-endian. - **must** be null-terminated and the uni_str_len should include - the NULL character */ - uint16 *buffer; + uint16 *buffer; /* unicode characters. ***MUST*** be little-endian. + **must** be null-terminated and the uni_str_len + should include the NULL character */ } UNISTR2; -/* STRING2 - string size (in uint8 chars) and buffer */ -typedef struct string2_info -{ +typedef struct { /* UNISTR3 - XXXX not sure about this structure */ + uint32 uni_str_len; + UNISTR str; + +} UNISTR3; + +typedef struct { /* Buffer wrapped around a UNISTR2 */ + uint16 length; /* number of bytes not counting NULL terminatation */ + uint16 size; /* number of bytes including NULL terminatation */ + UNISTR2 *string; +} UNISTR4; + +typedef struct { + uint32 count; + UNISTR4 *strings; +} UNISTR4_ARRAY; + + +/********************************************************************** + * String variations + **********************************************************************/ + +typedef struct { /* STRING2 - string size (in uint8 chars) and buffer */ uint32 str_max_len; uint32 offset; uint32 str_str_len; - uint8 *buffer; /* uint8 characters. **NOT** necessarily null-terminated */ + uint8 *buffer; /* uint8 characters. **NOT** necessarily null-terminated */ } STRING2; -/* UNISTR3 - XXXX not sure about this structure */ -typedef struct unistr3_info -{ - uint32 uni_str_len; - UNISTR str; -} UNISTR3; -/* an element in a unicode string array */ -typedef struct -{ - uint16 length; - uint16 size; - uint32 ref_id; - UNISTR2 string; -} UNISTR2_ARRAY_EL; - -/* an array of unicode strings */ -typedef struct -{ - uint32 ref_id; - uint32 count; - UNISTR2_ARRAY_EL *strings; -} UNISTR2_ARRAY; +/********************************************************************** + * Domain SID structures + **********************************************************************/ -/* an element in a sid array */ -typedef struct -{ - uint32 ref_id; - DOM_SID2 sid; -} SID_ARRAY_EL; +typedef struct { + uint32 num_auths; /* length, bytes, including length of len :-) */ + DOM_SID sid; +} DOM_SID2; -/* an array of sids */ -typedef struct -{ - uint32 ref_id; - uint32 count; - SID_ARRAY_EL *sids; -} SID_ARRAY; + +/********************************************************************** + * Domain SID structures + **********************************************************************/ /* DOM_RID2 - domain RID structure for ntlsa pipe */ -typedef struct domrid2_info -{ +typedef struct { uint8 type; /* value is SID_NAME_USE enum */ uint32 rid; uint32 rid_idx; /* referenced domain index */ - } DOM_RID2; -/* DOM_RID3 - domain RID structure for samr pipe */ -typedef struct domrid3_info -{ + +typedef struct { /* DOM_RID3 - domain RID structure for samr pipe */ uint32 rid; /* domain-relative (to a SID) id */ uint32 type1; /* value is 0x1 */ uint32 ptr_type; /* undocumented pointer */ uint32 type2; /* value is 0x1 */ uint32 unk; /* value is 0x2 */ - } DOM_RID3; /* DOM_RID4 - rid + user attributes */ @@ -255,6 +285,16 @@ typedef struct domrid4_info uint32 rid; /* user RID */ } DOM_RID4; +/* DOM_GID - group id + user attributes */ +typedef struct { + uint32 g_rid; /* a group RID */ + uint32 attr; +} DOM_GID; + +/********************************************************************** + * ???? + **********************************************************************/ + /* DOM_CLNT_SRV - client / server names */ typedef struct clnt_srv_info { @@ -316,32 +356,8 @@ typedef struct owf_info } OWF_INFO; -/* DOM_GID - group id + user attributes */ -typedef struct gid_info -{ - uint32 g_rid; /* a group RID */ - uint32 attr; -} DOM_GID; -/* POLICY_HND */ -typedef struct lsa_policy_info -{ - uint32 data1; - uint32 data2; - uint16 data3; - uint16 data4; - uint8 data5[8]; -#ifdef __INSURE__ - - /* To prevent the leakage of policy handles mallocate a bit of - memory when a policy handle is created and free it when the - handle is closed. This should cause Insure to flag an error - when policy handles are overwritten or fall out of scope without - being freed. */ - char *marker; -#endif -} POLICY_HND; /* * A client connection's state, pipe name, @@ -380,33 +396,8 @@ typedef struct uint64_s uint32 high; } UINT64_S; -/* BUFHDR2 - another buffer header, with info level */ -typedef struct bufhdr2_info -{ - uint32 info_level; - uint32 length; /* uint8 chars */ - uint32 buffer; -} -BUFHDR2; -/* BUFHDR4 - another buffer header */ -typedef struct bufhdr4_info -{ - uint32 size; - uint32 buffer; -} -BUFHDR4; -/* BUFFER4 - simple length and buffer */ -typedef struct buffer4_info -{ - uint32 buf_len; - uint8 *buffer; - -} -BUFFER4; - -enum unistr2_term_codes { UNI_FLAGS_NONE = 0, UNI_STR_TERMINATE = 1, UNI_MAXLEN_TERMINATE = 2, UNI_BROKEN_NON_NULL = 3 }; #endif /* _RPC_MISC_H */ diff --git a/source/include/rpc_netlogon.h b/source/include/rpc_netlogon.h index 3ba1ce6465b..6812358575a 100644 --- a/source/include/rpc_netlogon.h +++ b/source/include/rpc_netlogon.h @@ -643,7 +643,7 @@ typedef struct sam_domain_info_info UNISTR2 uni_dom_name; UNISTR2 buf_oem_info; - BUFFER4 buf_sec_desc; + RPC_DATA_BLOB buf_sec_desc; LOCKOUT_STRING account_lockout; @@ -670,7 +670,7 @@ typedef struct sam_group_info_info UNISTR2 uni_grp_name; UNISTR2 uni_grp_desc; - BUFFER4 buf_sec_desc; + RPC_DATA_BLOB buf_sec_desc; } SAM_GROUP_INFO; @@ -748,11 +748,11 @@ typedef struct sam_account_info_info uint32 unknown1; /* 0x4EC */ uint32 unknown2; /* 0 */ - BUFFER4 buf_logon_hrs; + RPC_DATA_BLOB buf_logon_hrs; UNISTR2 uni_comment; UNISTR2 uni_parameters; SAM_PWD pass; - BUFFER4 buf_sec_desc; + RPC_DATA_BLOB buf_sec_desc; UNISTR2 uni_profile; } SAM_ACCOUNT_INFO; @@ -783,7 +783,7 @@ typedef struct sam_alias_info_info uint8 reserved[40]; UNISTR2 uni_als_name; - BUFFER4 buf_sec_desc; + RPC_DATA_BLOB buf_sec_desc; UNISTR2 uni_als_desc; } SAM_ALIAS_INFO; @@ -829,7 +829,7 @@ typedef struct UNISTR2 domain_name; DOM_SID2 domain_sid; - BUFFER4 buf_sec_desc; + RPC_DATA_BLOB buf_sec_desc; } SAM_DELTA_POLICY; /* SAM_DELTA_TRUST_DOMS */ @@ -881,7 +881,7 @@ typedef struct UNIHDR *hdr_privslist; UNISTR2 *uni_privslist; - BUFFER4 buf_sec_desc; + RPC_DATA_BLOB buf_sec_desc; } SAM_DELTA_PRIVS; /* SAM_DELTA_SECRET */ diff --git a/source/include/rpc_reg.h b/source/include/rpc_reg.h index bfb5f1e0763..f70fb5f03cf 100644 --- a/source/include/rpc_reg.h +++ b/source/include/rpc_reg.h @@ -4,7 +4,8 @@ Copyright (C) Andrew Tridgell 1992-1997. Copyright (C) Luke Kenneth Casson Leighton 1996-1997. Copyright (C) Paul Ashton 1997. - Copyright (C) Gerald Carter 2002. + Copyright (C) Jeremy Cooper 2004. + Copyright (C) Gerald Carter 2002-2005. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -24,50 +25,44 @@ #ifndef _RPC_REG_H /* _RPC_REG_H */ #define _RPC_REG_H +/* RPC opnum */ -/* winreg pipe defines - NOT IMPLEMENTED !! -#define _REG_UNK_01 0x01 -#define _REG_UNK_03 0x03 -#define REG_CREATE_KEY 0x06 -#define REG_DELETE_KEY 0x07 -#define REG_DELETE_VALUE 0x08 -#define REG_FLUSH_KEY 0x0b -#define REG_GET_KEY_SEC 0x0c -#define _REG_UNK_0D 0x0d -#define _REG_UNK_0E 0x0e -#define _REG_UNK_12 0x12 -#define _REG_UNK_13 0x13 -#define REG_SET_KEY_SEC 0x15 -#define REG_CREATE_VALUE 0x16 -#define _REG_UNK_17 0x17 -*/ - -/* Implemented */ #define REG_OPEN_HKCR 0x00 #define REG_OPEN_HKLM 0x02 +#define REG_OPEN_HKPD 0x03 #define REG_OPEN_HKU 0x04 #define REG_CLOSE 0x05 +#define REG_CREATE_KEY 0x06 +#define REG_DELETE_KEY 0x07 +#define REG_DELETE_VALUE 0x08 #define REG_ENUM_KEY 0x09 #define REG_ENUM_VALUE 0x0a +#define REG_FLUSH_KEY 0x0b +#define REG_GET_KEY_SEC 0x0c #define REG_OPEN_ENTRY 0x0f #define REG_QUERY_KEY 0x10 #define REG_INFO 0x11 +#define REG_RESTORE_KEY 0x13 +#define REG_SAVE_KEY 0x14 +#define REG_SET_KEY_SEC 0x15 +#define REG_SET_VALUE 0x16 #define REG_SHUTDOWN 0x18 #define REG_ABORT_SHUTDOWN 0x19 -#define REG_SAVE_KEY 0x14 /* no idea what the real name is */ -#define REG_UNKNOWN_1A 0x1a +#define REG_GETVERSION 0x1a +#define REG_SHUTDOWN_EX 0x1e #define HKEY_CLASSES_ROOT 0x80000000 #define HKEY_CURRENT_USER 0x80000001 #define HKEY_LOCAL_MACHINE 0x80000002 #define HKEY_USERS 0x80000003 +#define HKEY_PERFORMANCE_DATA 0x80000004 #define KEY_HKLM "HKLM" #define KEY_HKU "HKU" #define KEY_HKCR "HKCR" #define KEY_PRINTING "HKLM\\SYSTEM\\CurrentControlSet\\Control\\Print" +#define KEY_EVENTLOG "HKLM\\SYSTEM\\CurrentControlSet\\Services\\Eventlog" #define KEY_TREE_ROOT "" /* Registry data types */ @@ -85,6 +80,10 @@ #define REG_FULL_RESOURCE_DESCRIPTOR 9 #define REG_RESOURCE_REQUIREMENTS_LIST 10 +/* + * INTERNAL REGISTRY STRUCTURES + */ + /* structure to contain registry values */ typedef struct { @@ -94,7 +93,7 @@ typedef struct { uint8 *data_p; } REGISTRY_VALUE; -/* container for regostry values */ +/* container for registry values */ typedef struct { TALLOC_CTX *ctx; @@ -143,379 +142,253 @@ typedef struct _RegistryKey { } REGISTRY_KEY; +/* + * RPC REGISTRY STRUCTURES + */ -/* REG_Q_OPEN_HKCR */ -typedef struct q_reg_open_hkcr_info -{ - uint32 ptr; - uint16 unknown_0; /* 0x5428 - 16 bit unknown */ - uint16 unknown_1; /* random. changes */ - uint32 level; /* 0x0000 0002 - 32 bit unknown */ - -} REG_Q_OPEN_HKCR ; - -/* REG_R_OPEN_HKCR */ -typedef struct r_reg_open_hkcr_info -{ - POLICY_HND pol; /* policy handle */ - WERROR status; /* return status */ - -} REG_R_OPEN_HKCR; - - -/* REG_Q_OPEN_HKLM */ -typedef struct q_reg_open_hklm_info -{ - uint32 ptr; - uint16 unknown_0; /* 0xE084 - 16 bit unknown */ - uint16 unknown_1; /* random. changes */ - uint32 access_mask; +/***********************************************/ -} -REG_Q_OPEN_HKLM; - -/* REG_R_OPEN_HKLM */ -typedef struct r_reg_open_hklm_info -{ - POLICY_HND pol; /* policy handle */ - WERROR status; /* return status */ - -} -REG_R_OPEN_HKLM; - - -/* REG_Q_OPEN_HKU */ -typedef struct q_reg_open_hku_info -{ - uint32 ptr; - uint16 unknown_0; - uint16 unknown_1; - uint32 access_mask; - -} REG_Q_OPEN_HKU; - -/* REG_R_OPEN_HKU */ -typedef struct r_reg_open_hku_info -{ - POLICY_HND pol; /* policy handle */ - WERROR status; /* return status */ +typedef struct { + uint16 *server; + uint32 access; +} REG_Q_OPEN_HIVE; -} REG_R_OPEN_HKU; +typedef struct { + POLICY_HND pol; + WERROR status; +} REG_R_OPEN_HIVE; -/* REG_Q_FLUSH_KEY */ -typedef struct q_reg_open_flush_key_info -{ - POLICY_HND pol; /* policy handle */ +/***********************************************/ +typedef struct { + POLICY_HND pol; } REG_Q_FLUSH_KEY; -/* REG_R_FLUSH_KEY */ -typedef struct r_reg_open_flush_key_info -{ - WERROR status; /* return status */ - +typedef struct { + WERROR status; } REG_R_FLUSH_KEY; -/* REG_Q_SET_KEY_SEC */ -typedef struct q_reg_set_key_sec_info -{ - POLICY_HND pol; /* policy handle */ - - uint32 sec_info; /* xxxx_SECURITY_INFORMATION */ +/***********************************************/ - uint32 ptr; /* pointer */ - BUFHDR hdr_sec; /* header for security data */ - SEC_DESC_BUF *data; /* security data */ - +typedef struct { + POLICY_HND pol; + uint32 sec_info; + uint32 ptr; + BUFHDR hdr_sec; + SEC_DESC_BUF *data; } REG_Q_SET_KEY_SEC; -/* REG_R_SET_KEY_SEC */ -typedef struct r_reg_set_key_sec_info -{ +typedef struct { WERROR status; - } REG_R_SET_KEY_SEC; -/* REG_Q_GET_KEY_SEC */ -typedef struct q_reg_get_key_sec_info -{ - POLICY_HND pol; /* policy handle */ - - uint32 sec_info; /* xxxx_SECURITY_INFORMATION */ +/***********************************************/ - uint32 ptr; /* pointer */ - BUFHDR hdr_sec; /* header for security data */ - SEC_DESC_BUF *data; /* security data */ - +typedef struct { + POLICY_HND pol; + uint32 sec_info; + uint32 ptr; + BUFHDR hdr_sec; + SEC_DESC_BUF *data; } REG_Q_GET_KEY_SEC; -/* REG_R_GET_KEY_SEC */ -typedef struct r_reg_get_key_sec_info -{ - uint32 sec_info; /* xxxx_SECURITY_INFORMATION */ - - uint32 ptr; /* pointer */ - BUFHDR hdr_sec; /* header for security data */ - SEC_DESC_BUF *data; /* security data */ - +typedef struct { + uint32 sec_info; + uint32 ptr; + BUFHDR hdr_sec; + SEC_DESC_BUF *data; WERROR status; - } REG_R_GET_KEY_SEC; -/* REG_Q_CREATE_VALUE */ -typedef struct q_reg_create_value_info -{ - POLICY_HND pol; /* policy handle */ - - UNIHDR hdr_name; /* name of value */ - UNISTR2 uni_name; - - uint32 type; /* 1 = UNISTR, 3 = BYTES, 4 = DWORD, 7 = MULTI_UNISTR */ - - BUFFER3 *buf_value; /* value, in byte buffer */ - -} REG_Q_CREATE_VALUE; +/***********************************************/ -/* REG_R_CREATE_VALUE */ -typedef struct r_reg_create_value_info -{ - WERROR status; /* return status */ - -} REG_R_CREATE_VALUE; - -/* REG_Q_ENUM_VALUE */ -typedef struct q_reg_query_value_info -{ - POLICY_HND pol; /* policy handle */ - - uint32 val_index; /* index */ - - UNIHDR hdr_name; /* name of value */ - UNISTR2 uni_name; - - uint32 ptr_type; /* pointer */ - uint32 type; /* 1 = UNISTR, 3 = BYTES, 4 = DWORD, 7 = MULTI_UNISTR */ - - uint32 ptr_value; /* pointer */ - BUFFER2 buf_value; /* value, in byte buffer */ - - uint32 ptr1; /* pointer */ - uint32 len_value1; /* */ - - uint32 ptr2; /* pointer */ - uint32 len_value2; /* */ +typedef struct { + POLICY_HND pol; + UNISTR4 name; + uint32 type; + RPC_DATA_BLOB value; + uint32 size; +} REG_Q_SET_VALUE; + +typedef struct { + WERROR status; +} REG_R_SET_VALUE; +/***********************************************/ +typedef struct { + POLICY_HND pol; + uint32 val_index; + UNISTR4 name; + uint32 *type; + REGVAL_BUFFER *value; /* value, in byte buffer */ + uint32 *len_value1; + uint32 *len_value2; } REG_Q_ENUM_VALUE; -/* REG_R_ENUM_VALUE */ -typedef struct r_reg_enum_value_info -{ - UNIHDR hdr_name; /* name of value */ - UNISTR2 uni_name; - - uint32 ptr_type; /* pointer */ - uint32 type; /* 1 = UNISTR, 3 = BYTES, 4 = DWORD, 7 = MULTI_UNISTR */ - - uint32 ptr_value; /* pointer */ - BUFFER2 buf_value; /* value, in byte buffer */ - - uint32 ptr1; /* pointer */ - uint32 len_value1; /* */ - - uint32 ptr2; /* pointer */ - uint32 len_value2; /* */ - - WERROR status; /* return status */ - +typedef struct { + UNISTR4 name; + uint32 *type; + REGVAL_BUFFER *value; + uint32 *len_value1; + uint32 *len_value2; + WERROR status; } REG_R_ENUM_VALUE; -/* REG_Q_CREATE_KEY */ -typedef struct q_reg_create_key_info -{ - POLICY_HND pnt_pol; /* parent key policy handle */ +/***********************************************/ - UNIHDR hdr_name; - UNISTR2 uni_name; - - UNIHDR hdr_class; - UNISTR2 uni_class; - - uint32 reserved; /* 0x0000 0000 */ - SEC_ACCESS sam_access; /* access rights flags, see rpc_secdes.h */ - - uint32 ptr1; - uint32 sec_info; /* xxxx_SECURITY_INFORMATION */ - - uint32 ptr2; /* pointer */ - BUFHDR hdr_sec; /* header for security data */ - uint32 ptr3; /* pointer */ +typedef struct { + POLICY_HND pnt_pol; + UNISTR4 name; + UNISTR4 class; + uint32 reserved; + uint32 access; + uint32 *sec_info; + uint32 ptr2; + BUFHDR hdr_sec; + uint32 ptr3; SEC_DESC_BUF *data; - uint32 unknown_2; /* 0x0000 0000 */ - } REG_Q_CREATE_KEY; -/* REG_R_CREATE_KEY */ -typedef struct r_reg_create_key_info -{ - POLICY_HND key_pol; /* policy handle */ - uint32 unknown; /* 0x0000 0000 */ - - WERROR status; /* return status */ - +typedef struct { + POLICY_HND key_pol; + uint32 unknown; + WERROR status; } REG_R_CREATE_KEY; -/* REG_Q_DELETE_KEY */ -typedef struct q_reg_delete_key_info -{ - POLICY_HND pnt_pol; /* parent key policy handle */ +/***********************************************/ - UNIHDR hdr_name; - UNISTR2 uni_name; +typedef struct { + POLICY_HND pnt_pol; + UNISTR4 name; } REG_Q_DELETE_KEY; -/* REG_R_DELETE_KEY */ -typedef struct r_reg_delete_key_info -{ - POLICY_HND key_pol; /* policy handle */ - - WERROR status; /* return status */ - +typedef struct { + POLICY_HND key_pol; + WERROR status; } REG_R_DELETE_KEY; -/* REG_Q_DELETE_VALUE */ -typedef struct q_reg_delete_val_info -{ - POLICY_HND pnt_pol; /* parent key policy handle */ - - UNIHDR hdr_name; - UNISTR2 uni_name; +/***********************************************/ +typedef struct { + POLICY_HND pnt_pol; + UNISTR4 name; } REG_Q_DELETE_VALUE; -/* REG_R_DELETE_VALUE */ -typedef struct r_reg_delete_val_info -{ - POLICY_HND key_pol; /* policy handle */ - - WERROR status; /* return status */ - +typedef struct { + POLICY_HND key_pol; + WERROR status; } REG_R_DELETE_VALUE; -/* REG_Q_QUERY_KEY */ -typedef struct q_reg_query_info -{ - POLICY_HND pol; /* policy handle */ - UNIHDR hdr_class; - UNISTR2 uni_class; +/***********************************************/ +typedef struct { + POLICY_HND pol; + UNISTR4 class; } REG_Q_QUERY_KEY; -/* REG_R_QUERY_KEY */ -typedef struct r_reg_query_key_info -{ - UNIHDR hdr_class; - UNISTR2 uni_class; - +typedef struct { + UNISTR4 class; uint32 num_subkeys; uint32 max_subkeylen; - uint32 reserved; /* 0x0000 0000 - according to MSDN (max_subkeysize?) */ + uint32 reserved; /* 0x0000 0000 - according to MSDN (max_subkeysize?) */ uint32 num_values; uint32 max_valnamelen; uint32 max_valbufsize; - uint32 sec_desc; /* 0x0000 0078 */ - NTTIME mod_time; /* modified time */ - - WERROR status; /* return status */ - + uint32 sec_desc; /* 0x0000 0078 */ + NTTIME mod_time; /* modified time */ + WERROR status; } REG_R_QUERY_KEY; -/* REG_Q_UNKNOWN_1A */ -typedef struct q_reg_unk_1a_info -{ - POLICY_HND pol; /* policy handle */ +/***********************************************/ -} REG_Q_UNKNOWN_1A; +typedef struct { + POLICY_HND pol; /* policy handle */ +} REG_Q_GETVERSION; -/* REG_R_UNKNOWN_1A */ -typedef struct r_reg_unk_1a_info -{ +typedef struct { uint32 unknown; /* 0x0500 0000 */ WERROR status; /* return status */ +} REG_R_GETVERSION; -} REG_R_UNKNOWN_1A; +/***********************************************/ -/* REG_Q_UNKNOWN_1A */ -typedef struct q_reg_unknown_14 -{ - POLICY_HND pol; /* policy handle */ - - UNIHDR hdr_file; /* unicode product type header */ - UNISTR2 uni_file; /* local filename to save key as from regedt32.exe */ - /* e.g. "c:\temp\test.dat" */ - - uint32 unknown; /* 0x0000 0000 */ +typedef struct { + POLICY_HND pol; + UNISTR4 filename; + uint32 flags; +} REG_Q_RESTORE_KEY; -} REG_Q_SAVE_KEY; +typedef struct { + WERROR status; /* return status */ +} REG_R_RESTORE_KEY; -/* REG_R_UNKNOWN_1A */ -typedef struct r_reg_unknown_14 -{ - WERROR status; /* return status */ +/***********************************************/ -} REG_R_SAVE_KEY; +/* I have no idea if this is correct since I + have not seen the full structure on the wire + as of yet */ + +typedef struct { + uint32 max_len; + uint32 len; + SEC_DESC *secdesc; +} REG_SEC_DESC_BUF; +typedef struct { + uint32 size; /* size in bytes of security descriptor */ + REG_SEC_DESC_BUF secdesc; + uint8 inherit; /* see MSDN for a description */ +} SECURITY_ATTRIBUTE; -/* REG_Q_CLOSE */ -typedef struct reg_q_close_info -{ - POLICY_HND pol; /* policy handle */ +typedef struct { + POLICY_HND pol; + UNISTR4 filename; + SECURITY_ATTRIBUTE *sec_attr; +} REG_Q_SAVE_KEY; -} REG_Q_CLOSE; +typedef struct { + WERROR status; /* return status */ +} REG_R_SAVE_KEY; -/* REG_R_CLOSE */ -typedef struct reg_r_close_info -{ - POLICY_HND pol; /* policy handle. should be all zeros. */ - WERROR status; /* return code */ +/***********************************************/ +typedef struct { + POLICY_HND pol; /* policy handle */ +} REG_Q_CLOSE; + +typedef struct { + POLICY_HND pol; + WERROR status; } REG_R_CLOSE; -/* REG_Q_ENUM_KEY */ -typedef struct q_reg_enum_value_info -{ - POLICY_HND pol; /* policy handle */ +/***********************************************/ +typedef struct { + POLICY_HND pol; uint32 key_index; - uint16 key_name_len; /* 0x0000 */ uint16 unknown_1; /* 0x0414 */ - uint32 ptr1; /* pointer */ uint32 unknown_2; /* 0x0000 020A */ uint8 pad1[8]; /* padding - zeros */ - uint32 ptr2; /* pointer */ uint8 pad2[8]; /* padding - zeros */ - uint32 ptr3; /* pointer */ NTTIME time; /* current time? */ - } REG_Q_ENUM_KEY; -/* REG_R_ENUM_KEY */ -typedef struct r_reg_enum_key_info -{ +typedef struct { uint16 key_name_len; /* number of bytes in key name */ uint16 unknown_1; /* 0x0414 - matches with query unknown_1 */ @@ -532,17 +405,14 @@ typedef struct r_reg_enum_key_info NTTIME time; /* current time? */ WERROR status; /* return status */ - } REG_R_ENUM_KEY; -/* REG_Q_INFO */ -typedef struct q_reg_info_info -{ - POLICY_HND pol; /* policy handle */ +/***********************************************/ - UNIHDR hdr_type; /* unicode product type header */ - UNISTR2 uni_type; /* unicode product type - "ProductType" */ +typedef struct { + POLICY_HND pol; /* policy handle */ + UNISTR4 name; uint32 ptr_reserved; /* pointer */ @@ -560,83 +430,66 @@ typedef struct q_reg_info_info } REG_Q_INFO; -/* REG_R_INFO */ -typedef struct r_reg_info_info -{ - uint32 ptr_type; /* key type pointer */ - uint32 type; /* key datatype */ - - uint32 ptr_uni_val; /* key value pointer */ - BUFFER2 uni_val; /* key value */ - - uint32 ptr_max_len; - uint32 buf_max_len; - - uint32 ptr_len; - uint32 buf_len; - +typedef struct { + uint32 *type; + REGVAL_BUFFER *value; /* key value */ + uint32 *buf_max_len; + uint32 *buf_len; WERROR status; /* return status */ - } REG_R_INFO; -/* REG_Q_OPEN_ENTRY */ -typedef struct q_reg_open_entry_info -{ - POLICY_HND pol; /* policy handle */ - - UNIHDR hdr_name; /* unicode registry string header */ - UNISTR2 uni_name; /* unicode registry string name */ +/***********************************************/ +typedef struct { + POLICY_HND pol; + UNISTR4 name; uint32 unknown_0; /* 32 bit unknown - 0x0000 0000 */ - uint32 access_desired; - + uint32 access; } REG_Q_OPEN_ENTRY; - - -/* REG_R_OPEN_ENTRY */ -typedef struct r_reg_open_entry_info -{ - POLICY_HND pol; /* policy handle */ - WERROR status; /* return status */ - +typedef struct { + POLICY_HND pol; + WERROR status; } REG_R_OPEN_ENTRY; -/* REG_Q_SHUTDOWN */ -typedef struct q_reg_shutdown_info -{ - uint32 ptr_0; - uint32 ptr_1; - uint32 ptr_2; - UNIHDR hdr_msg; /* shutdown message */ - UNISTR2 uni_msg; /* seconds */ - uint32 timeout; /* seconds */ +/***********************************************/ + +typedef struct { + uint16 *server; + UNISTR4 *message; + uint32 timeout; /* in seconds */ uint8 force; /* boolean: force shutdown */ - uint8 reboot; /* boolean: reboot on shutdown */ - + uint8 reboot; /* boolean: reboot on shutdown */ } REG_Q_SHUTDOWN; -/* REG_R_SHUTDOWN */ -typedef struct r_reg_shutdown_info -{ +typedef struct { WERROR status; /* return status */ - } REG_R_SHUTDOWN; -/* REG_Q_ABORT_SHUTDOWN */ -typedef struct q_reg_abort_shutdown_info -{ - uint32 ptr_server; - uint16 server; +/***********************************************/ + +typedef struct { + uint16 *server; + UNISTR4 *message; + uint32 timeout; /* in seconds */ + uint8 force; /* boolean: force shutdown */ + uint8 reboot; /* boolean: reboot on shutdown */ + uint32 reason; /* reason - must be defined code */ +} REG_Q_SHUTDOWN_EX; -} REG_Q_ABORT_SHUTDOWN; +typedef struct { + WERROR status; +} REG_R_SHUTDOWN_EX; + +/***********************************************/ -/* REG_R_ABORT_SHUTDOWN */ -typedef struct r_reg_abort_shutdown_info -{ - WERROR status; /* return status */ +typedef struct { + uint16 *server; +} REG_Q_ABORT_SHUTDOWN; +typedef struct { + WERROR status; } REG_R_ABORT_SHUTDOWN; diff --git a/source/include/rpc_secdes.h b/source/include/rpc_secdes.h index 3e4c47dce9a..ea987f9e4e0 100644 --- a/source/include/rpc_secdes.h +++ b/source/include/rpc_secdes.h @@ -472,4 +472,51 @@ typedef struct standard_mapping { (STANDARD_RIGHTS_EXECUTE_ACCESS | \ SA_RIGHT_ALIAS_LOOKUP_INFO ) /* 0x00020008 */ +/* + * Acces bits for the svcctl objects + */ + +/* Service Control Manager Bits */ + +#define SC_RIGHT_MGR_CONNECT 0x0001 +#define SC_RIGHT_MGR_CREATE_SERVICE 0x0002 +#define SC_RIGHT_MGR_ENUMERATE_SERVICE 0x0004 +#define SC_RIGHT_MGR_LOCK 0x0008 +#define SC_RIGHT_MGR_QUERY_LOCK_STATUS 0x0010 +#define SC_RIGHT_MGR_MODIFY_BOOT_CONFIG 0x0020 + +#define SC_MANAGER_ALL_ACCESS \ + ( STANDARD_RIGHTS_REQUIRED_ACCESS | \ + SC_RIGHT_MGR_CONNECT | \ + SC_RIGHT_MGR_CREATE_SERVICE | \ + SC_RIGHT_MGR_ENUMERATE_SERVICE | \ + SC_RIGHT_MGR_LOCK | \ + SC_RIGHT_MGR_QUERY_LOCK_STATUS | \ + SC_RIGHT_MGR_MODIFY_BOOT_CONFIG ) + +/* Service Object Bits */ + +#define SC_RIGHT_SVC_QUERY_CONFIG 0x0001 +#define SC_RIGHT_SVC_CHANGE_CONFIG 0x0002 +#define SC_RIGHT_SVC_QUERY_STATUS 0x0004 +#define SC_RIGHT_SVC_ENUMERATE_DEPENDENTS 0x0008 +#define SC_RIGHT_SVC_START 0x0010 +#define SC_RIGHT_SVC_STOP 0x0020 +#define SC_RIGHT_SVC_PAUSE_CONTINUE 0x0040 +#define SC_RIGHT_SVC_INTERROGATE 0x0080 +#define SC_RIGHT_SVC_USER_DEFINED_CONTROL 0x0100 + +#define SERVICE_ALL_ACCESS \ + ( STANDARD_RIGHTS_REQUIRED_ACCESS | \ + SC_RIGHT_SVC_QUERY_CONFIG | \ + SC_RIGHT_SVC_CHANGE_CONFIG | \ + SC_RIGHT_SVC_QUERY_STATUS | \ + SC_RIGHT_SVC_ENUMERATE_DEPENDENTS | \ + SC_RIGHT_SVC_START | \ + SC_RIGHT_SVC_STOP | \ + SC_RIGHT_SVC_PAUSE_CONTINUE | \ + SC_RIGHT_SVC_INTERROGATE | \ + SC_RIGHT_SVC_USER_DEFINED_CONTROL ) + + #endif /* _RPC_SECDES_H */ diff --git a/source/include/rpc_shutdown.h b/source/include/rpc_shutdown.h index b8e50b835f5..a9d86aec26c 100644 --- a/source/include/rpc_shutdown.h +++ b/source/include/rpc_shutdown.h @@ -1,7 +1,8 @@ /* Unix SMB/CIFS implementation. - SMB parameters and setup + Copyright (C) Jim McDonough (jmcd@us.ibm.com) 2003. + Copyright (C) Gerald (Jerry) Carter 2005. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -22,49 +23,53 @@ #define _RPC_SHUTDOWN_H -/* Implemented */ +/* opnums */ + #define SHUTDOWN_INIT 0x00 #define SHUTDOWN_ABORT 0x01 -/* NOT IMPLEMENTED #define SHUTDOWN_INIT_EX 0x02 -*/ -/* SHUTDOWN_Q_INIT */ -typedef struct q_shutodwn_init_info -{ - uint32 ptr_server; - uint16 server; - uint32 ptr_msg; - UNIHDR hdr_msg; /* shutdown message */ - UNISTR2 uni_msg; /* seconds */ - uint32 timeout; /* seconds */ + +/***********************************************/ + +typedef struct { + uint16 *server; + UNISTR4 *message; + uint32 timeout; /* in seconds */ uint8 force; /* boolean: force shutdown */ - uint8 reboot; /* boolean: reboot on shutdown */ - + uint8 reboot; /* boolean: reboot on shutdown */ } SHUTDOWN_Q_INIT; -/* SHUTDOWN_R_INIT */ -typedef struct r_shutdown_init_info -{ - NTSTATUS status; /* return status */ - +typedef struct { + WERROR status; /* return status */ } SHUTDOWN_R_INIT; -/* SHUTDOWN_Q_ABORT */ -typedef struct q_shutdown_abort_info -{ - uint32 ptr_server; - uint16 server; +/***********************************************/ + +typedef struct { + uint16 *server; + UNISTR4 *message; + uint32 timeout; /* in seconds */ + uint8 force; /* boolean: force shutdown */ + uint8 reboot; /* boolean: reboot on shutdown */ + uint32 reason; /* reason - must be defined code */ +} SHUTDOWN_Q_INIT_EX; -} SHUTDOWN_Q_ABORT; +typedef struct { + WERROR status; +} SHUTDOWN_R_INIT_EX; -/* SHUTDOWN_R_ABORT */ -typedef struct r_shutdown_abort_info -{ - NTSTATUS status; /* return status */ +/***********************************************/ +typedef struct { + uint16 *server; +} SHUTDOWN_Q_ABORT; + +typedef struct { + WERROR status; } SHUTDOWN_R_ABORT; + #endif /* _RPC_SHUTDOWN_H */ diff --git a/source/include/rpc_spoolss.h b/source/include/rpc_spoolss.h index 7c5942759f4..64533635083 100755 --- a/source/include/rpc_spoolss.h +++ b/source/include/rpc_spoolss.h @@ -1,11 +1,10 @@ /* Unix SMB/Netbios implementation. - Version 1.9. - SMB parameters and setup + Copyright (C) Andrew Tridgell 1992-2000, Copyright (C) Luke Kenneth Casson Leighton 1996-2000, Copyright (C) Jean Francois Micouleau 1998-2000. - Copyright (C) Gerald Carter 2001-2002. + Copyright (C) Gerald Carter 2001-2005. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -427,27 +426,22 @@ PRINTER_MESSAGE_INFO; /* this struct is undocumented */ /* thanks to the ddk ... */ -typedef struct spool_user_1 -{ +typedef struct { uint32 size; /* length of user_name & client_name + 2? */ - uint32 client_name_ptr; - uint32 user_name_ptr; + UNISTR2 *client_name; + UNISTR2 *user_name; uint32 build; uint32 major; uint32 minor; uint32 processor; - UNISTR2 client_name; - UNISTR2 user_name; -} -SPOOL_USER_1; +} SPOOL_USER_1; -typedef struct spool_user_ctr_info -{ +typedef struct { uint32 level; - uint32 ptr; - SPOOL_USER_1 user1; -} -SPOOL_USER_CTR; + union { + SPOOL_USER_1 *user1; + } user; +} SPOOL_USER_CTR; /* * various bits in the DEVICEMODE.fields member @@ -544,41 +538,33 @@ typedef struct _printer_default } PRINTER_DEFAULT; -/* SPOOL_Q_OPEN_PRINTER request to open a printer */ -typedef struct spool_q_open_printer -{ - uint32 printername_ptr; - UNISTR2 printername; +/********************************************/ + +typedef struct { + UNISTR2 *printername; PRINTER_DEFAULT printer_default; -} -SPOOL_Q_OPEN_PRINTER; +} SPOOL_Q_OPEN_PRINTER; -/* SPOOL_R_OPEN_PRINTER reply to an open printer */ -typedef struct spool_r_open_printer -{ +typedef struct { POLICY_HND handle; /* handle used along all transactions (20*uint8) */ WERROR status; -} -SPOOL_R_OPEN_PRINTER; +} SPOOL_R_OPEN_PRINTER; -/* SPOOL_Q_OPEN_PRINTER_EX request to open a printer */ -typedef struct spool_q_open_printer_ex -{ - uint32 printername_ptr; - UNISTR2 printername; +/********************************************/ + +typedef struct { + UNISTR2 *printername; PRINTER_DEFAULT printer_default; uint32 user_switch; SPOOL_USER_CTR user_ctr; -} -SPOOL_Q_OPEN_PRINTER_EX; +} SPOOL_Q_OPEN_PRINTER_EX; -/* SPOOL_R_OPEN_PRINTER_EX reply to an open printer */ -typedef struct spool_r_open_printer_ex -{ +typedef struct { POLICY_HND handle; /* handle used along all transactions (20*uint8) */ WERROR status; -} -SPOOL_R_OPEN_PRINTER_EX; +} SPOOL_R_OPEN_PRINTER_EX; + +/********************************************/ typedef struct spool_notify_option_type { @@ -614,15 +600,6 @@ typedef struct s_header_type } HEADER_TYPE; -typedef struct new_buffer -{ - uint32 ptr; - uint32 size; - prs_struct prs; - uint32 struct_start; - uint32 string_at_end; -} -NEW_BUFFER; typedef struct spool_q_getprinterdata { @@ -1014,7 +991,7 @@ typedef struct spool_q_enumprinters uint32 servername_ptr; UNISTR2 servername; uint32 level; - NEW_BUFFER *buffer; + RPC_BUFFER *buffer; uint32 offered; } SPOOL_Q_ENUMPRINTERS; @@ -1033,7 +1010,7 @@ PRINTER_INFO_CTR; typedef struct spool_r_enumprinters { - NEW_BUFFER *buffer; + RPC_BUFFER *buffer; uint32 needed; /* bytes needed */ uint32 returned; /* number of printers */ WERROR status; @@ -1045,7 +1022,7 @@ typedef struct spool_q_getprinter { POLICY_HND handle; uint32 level; - NEW_BUFFER *buffer; + RPC_BUFFER *buffer; uint32 offered; } SPOOL_Q_GETPRINTER; @@ -1063,7 +1040,7 @@ typedef struct printer_info_info typedef struct spool_r_getprinter { - NEW_BUFFER *buffer; + RPC_BUFFER *buffer; uint32 needed; WERROR status; } SPOOL_R_GETPRINTER; @@ -1137,7 +1114,7 @@ typedef struct spool_q_getprinterdriver2 uint32 architecture_ptr; UNISTR2 architecture; uint32 level; - NEW_BUFFER *buffer; + RPC_BUFFER *buffer; uint32 offered; uint32 clientmajorversion; uint32 clientminorversion; @@ -1146,7 +1123,7 @@ SPOOL_Q_GETPRINTERDRIVER2; typedef struct spool_r_getprinterdriver2 { - NEW_BUFFER *buffer; + RPC_BUFFER *buffer; uint32 needed; uint32 servermajorversion; uint32 serverminorversion; @@ -1167,14 +1144,14 @@ typedef struct spool_q_addjob { POLICY_HND handle; uint32 level; - NEW_BUFFER *buffer; + RPC_BUFFER *buffer; uint32 offered; } SPOOL_Q_ADDJOB; typedef struct spool_r_addjob { - NEW_BUFFER *buffer; + RPC_BUFFER *buffer; uint32 needed; WERROR status; } @@ -1251,7 +1228,7 @@ typedef struct spool_q_enumjobs uint32 firstjob; uint32 numofjobs; uint32 level; - NEW_BUFFER *buffer; + RPC_BUFFER *buffer; uint32 offered; } SPOOL_Q_ENUMJOBS; @@ -1269,7 +1246,7 @@ typedef struct job_info_ctr_info typedef struct spool_r_enumjobs { - NEW_BUFFER *buffer; + RPC_BUFFER *buffer; uint32 needed; uint32 returned; WERROR status; @@ -1316,7 +1293,7 @@ typedef struct spool_q_enumports uint32 name_ptr; UNISTR2 name; uint32 level; - NEW_BUFFER *buffer; + RPC_BUFFER *buffer; uint32 offered; } SPOOL_Q_ENUMPORTS; @@ -1335,7 +1312,7 @@ PORT_INFO_CTR; typedef struct spool_r_enumports { - NEW_BUFFER *buffer; + RPC_BUFFER *buffer; uint32 needed; /* bytes needed */ uint32 returned; /* number of printers */ WERROR status; @@ -1385,14 +1362,14 @@ typedef struct spool_q_enumprinterdrivers uint32 environment_ptr; UNISTR2 environment; uint32 level; - NEW_BUFFER *buffer; + RPC_BUFFER *buffer; uint32 offered; } SPOOL_Q_ENUMPRINTERDRIVERS; typedef struct spool_r_enumprinterdrivers { - NEW_BUFFER *buffer; + RPC_BUFFER *buffer; uint32 needed; uint32 returned; WERROR status; @@ -1420,14 +1397,14 @@ typedef struct spool_q_enumforms { POLICY_HND handle; uint32 level; - NEW_BUFFER *buffer; + RPC_BUFFER *buffer; uint32 offered; } SPOOL_Q_ENUMFORMS; typedef struct spool_r_enumforms { - NEW_BUFFER *buffer; + RPC_BUFFER *buffer; uint32 needed; uint32 numofforms; WERROR status; @@ -1439,14 +1416,14 @@ typedef struct spool_q_getform POLICY_HND handle; UNISTR2 formname; uint32 level; - NEW_BUFFER *buffer; + RPC_BUFFER *buffer; uint32 offered; } SPOOL_Q_GETFORM; typedef struct spool_r_getform { - NEW_BUFFER *buffer; + RPC_BUFFER *buffer; uint32 needed; WERROR status; } @@ -1601,28 +1578,6 @@ typedef struct spool_printer_driver_info_level SPOOL_PRINTER_DRIVER_INFO_LEVEL; -/* this struct is undocumented */ -/* thanks to the ddk ... */ -typedef struct spool_user_level_1 -{ - uint32 size; - uint32 client_name_ptr; - uint32 user_name_ptr; - uint32 build; - uint32 major; - uint32 minor; - uint32 processor; - UNISTR2 client_name; - UNISTR2 user_name; -} -SPOOL_USER_LEVEL_1; - -typedef struct spool_user_level -{ - SPOOL_USER_LEVEL_1 *user_level_1; -} -SPOOL_USER_LEVEL; - typedef struct spool_q_setprinter { POLICY_HND handle; @@ -1642,70 +1597,46 @@ typedef struct spool_r_setprinter } SPOOL_R_SETPRINTER; -typedef struct spool_q_addprinter -{ - UNISTR2 server_name; - uint32 level; - SPOOL_PRINTER_INFO_LEVEL info; - DEVMODE_CTR devmode_ctr; - SEC_DESC_BUF *secdesc_ctr; - uint32 user_level; - SPOOL_USER_LEVEL user; -} -SPOOL_Q_ADDPRINTER; - -typedef struct spool_r_addprinter -{ - WERROR status; -} -SPOOL_R_ADDPRINTER; +/********************************************/ -typedef struct spool_q_deleteprinter -{ +typedef struct { POLICY_HND handle; -} -SPOOL_Q_DELETEPRINTER; +} SPOOL_Q_DELETEPRINTER; -typedef struct spool_r_deleteprinter -{ +typedef struct { POLICY_HND handle; WERROR status; -} -SPOOL_R_DELETEPRINTER; +} SPOOL_R_DELETEPRINTER; -typedef struct spool_q_abortprinter -{ +/********************************************/ + +typedef struct { POLICY_HND handle; -} -SPOOL_Q_ABORTPRINTER; +} SPOOL_Q_ABORTPRINTER; -typedef struct spool_r_abortprinter -{ +typedef struct { WERROR status; -} -SPOOL_R_ABORTPRINTER; +} SPOOL_R_ABORTPRINTER; -typedef struct spool_q_addprinterex -{ - uint32 server_name_ptr; - UNISTR2 server_name; +/********************************************/ + +typedef struct { + UNISTR2 *server_name; uint32 level; SPOOL_PRINTER_INFO_LEVEL info; DEVMODE_CTR devmode_ctr; SEC_DESC_BUF *secdesc_ctr; uint32 user_switch; SPOOL_USER_CTR user_ctr; -} -SPOOL_Q_ADDPRINTEREX; +} SPOOL_Q_ADDPRINTEREX; -typedef struct spool_r_addprinterex -{ +typedef struct { POLICY_HND handle; WERROR status; -} -SPOOL_R_ADDPRINTEREX; +} SPOOL_R_ADDPRINTEREX; +/********************************************/ typedef struct spool_q_addprinterdriver { @@ -1758,14 +1689,14 @@ typedef struct spool_q_getprinterdriverdirectory uint32 environment_ptr; UNISTR2 environment; uint32 level; - NEW_BUFFER *buffer; + RPC_BUFFER *buffer; uint32 offered; } SPOOL_Q_GETPRINTERDRIVERDIR; typedef struct spool_r_getprinterdriverdirectory { - NEW_BUFFER *buffer; + RPC_BUFFER *buffer; uint32 needed; WERROR status; } @@ -1795,7 +1726,7 @@ typedef struct spool_q_enumprintprocessors uint32 environment_ptr; UNISTR2 environment; uint32 level; - NEW_BUFFER *buffer; + RPC_BUFFER *buffer; uint32 offered; } SPOOL_Q_ENUMPRINTPROCESSORS; @@ -1808,7 +1739,7 @@ PRINTPROCESSOR_1; typedef struct spool_r_enumprintprocessors { - NEW_BUFFER *buffer; + RPC_BUFFER *buffer; uint32 needed; uint32 returned; WERROR status; @@ -1822,7 +1753,7 @@ typedef struct spool_q_enumprintprocdatatypes uint32 processor_ptr; UNISTR2 processor; uint32 level; - NEW_BUFFER *buffer; + RPC_BUFFER *buffer; uint32 offered; } SPOOL_Q_ENUMPRINTPROCDATATYPES; @@ -1835,7 +1766,7 @@ PRINTPROCDATATYPE_1; typedef struct spool_r_enumprintprocdatatypes { - NEW_BUFFER *buffer; + RPC_BUFFER *buffer; uint32 needed; uint32 returned; WERROR status; @@ -1861,14 +1792,14 @@ typedef struct spool_q_enumprintmonitors uint32 name_ptr; UNISTR2 name; uint32 level; - NEW_BUFFER *buffer; + RPC_BUFFER *buffer; uint32 offered; } SPOOL_Q_ENUMPRINTMONITORS; typedef struct spool_r_enumprintmonitors { - NEW_BUFFER *buffer; + RPC_BUFFER *buffer; uint32 needed; uint32 returned; WERROR status; @@ -1996,7 +1927,7 @@ typedef struct spool_q_getjob POLICY_HND handle; uint32 jobid; uint32 level; - NEW_BUFFER *buffer; + RPC_BUFFER *buffer; uint32 offered; } SPOOL_Q_GETJOB; @@ -2016,7 +1947,7 @@ PJOB_INFO; typedef struct spool_r_getjob { - NEW_BUFFER *buffer; + RPC_BUFFER *buffer; uint32 needed; WERROR status; } @@ -2217,14 +2148,14 @@ typedef struct spool_q_getprintprocessordirectory UNISTR2 name; UNISTR2 environment; uint32 level; - NEW_BUFFER *buffer; + RPC_BUFFER *buffer; uint32 offered; } SPOOL_Q_GETPRINTPROCESSORDIRECTORY; typedef struct spool_r_getprintprocessordirectory { - NEW_BUFFER *buffer; + RPC_BUFFER *buffer; uint32 needed; WERROR status; } diff --git a/source/include/rpc_srvsvc.h b/source/include/rpc_srvsvc.h index 5ebb77a8c21..f84054b878b 100644 --- a/source/include/rpc_srvsvc.h +++ b/source/include/rpc_srvsvc.h @@ -29,6 +29,7 @@ #define SRV_NET_FILE_ENUM 0x09 #define SRV_NET_FILE_CLOSE 0x0b #define SRV_NET_SESS_ENUM 0x0c +#define SRV_NET_SESS_DEL 0x0d #define SRV_NET_SHARE_ADD 0x0e #define SRV_NET_SHARE_ENUM_ALL 0x0f #define SRV_NET_SHARE_GET_INFO 0x10 @@ -193,6 +194,27 @@ typedef struct r_net_sess_enum_info } SRV_R_NET_SESS_ENUM; +/* SRV_Q_NET_SESS_DEL */ +typedef struct q_net_sess_del +{ + uint32 ptr_srv_name; /* pointer (to server name?) */ + UNISTR2 uni_srv_name; /* server name */ + + uint32 ptr_cli_name; /* pointer (to qualifier name) */ + UNISTR2 uni_cli_name; /* qualifier name "\\qualifier" */ + + uint32 ptr_user_name; /* pointer (to user name */ + UNISTR2 uni_user_name; /* user name */ + +} SRV_Q_NET_SESS_DEL; + +/* SRV_R_NET_SESS_DEL */ +typedef struct r_net_sess_del +{ + WERROR status; /* return status */ + +} SRV_R_NET_SESS_DEL; + /* CONN_INFO_0 (pointers to level 0 connection info strings) */ typedef struct ptr_conn_info0 { diff --git a/source/include/rpc_svcctl.h b/source/include/rpc_svcctl.h new file mode 100644 index 00000000000..90b90bd24b1 --- /dev/null +++ b/source/include/rpc_svcctl.h @@ -0,0 +1,246 @@ +/* + Unix SMB/CIFS implementation. + SMB parameters and setup + Copyright (C) Andrew Tridgell 1992-1997, + Copyright (C) Gerald (Jerry) Carter 2005 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef _RPC_SVCCTL_H /* _RPC_SVCCTL_H */ +#define _RPC_SVCCTL_H + + +/* svcctl pipe */ + +#define SVCCTL_CLOSE_SERVICE 0x00 +#define SVCCTL_CONTROL_SERVICE 0x01 +#define SVCCTL_QUERY_STATUS 0x06 +#define SVCCTL_ENUM_DEPENDENT_SERVICES_W 0x0d +#define SVCCTL_ENUM_SERVICES_STATUS_W 0x0e +#define SVCCTL_OPEN_SCMANAGER_W 0x0f +#define SVCCTL_OPEN_SERVICE_W 0x10 +#define SVCCTL_QUERY_SERVICE_CONFIG_W 0x11 +#define SVCCTL_START_SERVICE_W 0x13 +#define SVCCTL_GET_DISPLAY_NAME 0x14 +#define SVCCTL_QUERY_SERVICE_CONFIG2_W 0x27 + +/* ANSI versions not implemented currently +#define SVCCTL_ENUM_SERVICES_STATUS_A 0x0e +#define SVCCTL_OPEN_SCMANAGER_A 0x1b +*/ + +/* SERVER_STATUS - type */ + +#define SVCCTL_TYPE_WIN32 0x00000030 +#define SVCCTL_TYPE_DRIVER 0x0000000f + +/* SERVER_STATUS - state */ +#define SVCCTL_STATE_ACTIVE 0x00000001 +#define SVCCTL_STATE_INACTIVE 0x00000002 +#define SVCCTL_STATE_ALL ( SVCCTL_STATE_ACTIVE | SVCCTL_STATE_INACTIVE ) + +/* SERVER_STATUS - CurrentState */ + +#define SVCCTL_STOPPED 0x00000001 +#define SVCCTL_START_PENDING 0x00000002 +#define SVCCTL_STOP_PENDING 0x00000003 +#define SVCCTL_RUNNING 0x00000004 +#define SVCCTL_CONTINUE_PENDING 0x00000005 +#define SVCCTL_PAUSE_PENDING 0x00000006 +#define SVCCTL_PAUSED 0x00000007 + +/* SERVER_STATUS - ControlAccepted */ + +#define SVCCTL_ACCEPT_STOP 0x00000001 +#define SVCCTL_ACCEPT_PAUSE_CONTINUE 0x00000002 +#define SVCCTL_ACCEPT_SHUTDOWN 0x00000004 +#define SVCCTL_ACCEPT_PARAMCHANGE 0x00000008 +#define SVCCTL_ACCEPT_NETBINDCHANGE 0x00000010 +#define SVCCTL_ACCEPT_HARDWAREPROFILECHANGE 0x00000020 +#define SVCCTL_ACCEPT_POWEREVENT 0x00000040 + +/* Service Controls */ + +#define SVCCTL_CONTROL_STOP 0x00000001 +#define SVCCTL_CONTROL_PAUSE 0x00000002 +#define SVCCTL_CONTROL_CONTINUE 0x00000003 + +/* utility structures for RPCs */ + +typedef struct { + uint32 type; + uint32 state; + uint32 controls_accepted; + uint32 win32_exit_code; + uint32 service_exit_code; + uint32 check_point; + uint32 wait_hint; +} SERVICE_STATUS; + +typedef struct { + UNISTR servicename; + UNISTR displayname; + SERVICE_STATUS status; +} ENUM_SERVICES_STATUS; + +typedef struct { + uint32 service_type; + uint32 start_type; + uint32 error_control; + UNISTR2 *executablepath; + UNISTR2 *loadordergroup; + uint32 tag_id; + UNISTR2 *dependencies; + UNISTR2 *startname; + UNISTR2 *displayname; +} SERVICE_CONFIG; + + +/* rpc structures */ + +/**************************/ + +typedef struct { + POLICY_HND handle; +} SVCCTL_Q_CLOSE_SERVICE; + +typedef struct { + WERROR status; +} SVCCTL_R_CLOSE_SERVICE; + +/**************************/ + +typedef struct { + UNISTR2 *servername; + UNISTR2 *database; + uint32 access; +} SVCCTL_Q_OPEN_SCMANAGER; + +typedef struct { + POLICY_HND handle; + WERROR status; +} SVCCTL_R_OPEN_SCMANAGER; + +/**************************/ + +typedef struct { + POLICY_HND handle; + UNISTR2 servicename; + uint32 display_name_len; +} SVCCTL_Q_GET_DISPLAY_NAME; + +typedef struct { + UNISTR2 displayname; + uint32 display_name_len; + WERROR status; +} SVCCTL_R_GET_DISPLAY_NAME; + +/**************************/ + +typedef struct { + POLICY_HND handle; + UNISTR2 servicename; + uint32 access; +} SVCCTL_Q_OPEN_SERVICE; + +typedef struct { + POLICY_HND handle; + WERROR status; +} SVCCTL_R_OPEN_SERVICE; + +/**************************/ + +typedef struct { + POLICY_HND handle; + uint32 parmcount; + UNISTR4_ARRAY *parameters; +} SVCCTL_Q_START_SERVICE; + +typedef struct { + WERROR status; +} SVCCTL_R_START_SERVICE; + +/**************************/ + +typedef struct { + POLICY_HND handle; + uint32 control; +} SVCCTL_Q_CONTROL_SERVICE; + +typedef struct { + SERVICE_STATUS svc_status; + WERROR status; +} SVCCTL_R_CONTROL_SERVICE; + +/**************************/ + +typedef struct { + POLICY_HND handle; +} SVCCTL_Q_QUERY_STATUS; + +typedef struct { + SERVICE_STATUS svc_status; + WERROR status; +} SVCCTL_R_QUERY_STATUS; + +/**************************/ + +typedef struct { + POLICY_HND handle; + uint32 type; + uint32 state; + uint32 buffer_size; + uint32 *resume; +} SVCCTL_Q_ENUM_SERVICES_STATUS; + +typedef struct { + RPC_BUFFER buffer; + uint32 needed; + uint32 returned; + uint32 *resume; + WERROR status; +} SVCCTL_R_ENUM_SERVICES_STATUS; + +/**************************/ + +typedef struct { + POLICY_HND handle; + uint32 state; + uint32 buffer_size; +} SVCCTL_Q_ENUM_DEPENDENT_SERVICES; + +typedef struct { + RPC_BUFFER buffer; + uint32 needed; + uint32 returned; + WERROR status; +} SVCCTL_R_ENUM_DEPENDENT_SERVICES; + +/**************************/ + +typedef struct { + POLICY_HND handle; + uint32 buffer_size; +} SVCCTL_Q_QUERY_SERVICE_CONFIG; + +typedef struct { + SERVICE_CONFIG config; + uint32 needed; + WERROR status; +} SVCCTL_R_QUERY_SERVICE_CONFIG; + +#endif /* _RPC_SVCCTL_H */ + diff --git a/source/include/smb.h b/source/include/smb.h index 91ec52df237..80b20756517 100644 --- a/source/include/smb.h +++ b/source/include/smb.h @@ -103,6 +103,7 @@ typedef int BOOL; #define DOS_OPEN_RDONLY 0 #define DOS_OPEN_WRONLY 1 #define DOS_OPEN_RDWR 2 +#define DOS_OPEN_EXEC 3 #define DOS_OPEN_FCB 0xF /* define shifts and masks for share and open modes. */ @@ -193,6 +194,9 @@ typedef smb_ucs2_t wfstring[FSTRING_LEN]; #define PIPE_NETDFS "\\PIPE\\netdfs" #define PIPE_ECHO "\\PIPE\\rpcecho" #define PIPE_SHUTDOWN "\\PIPE\\initshutdown" +#define PIPE_EPM "\\PIPE\\epmapper" +#define PIPE_SVCCTL "\\PIPE\\svcctl" +#define PIPE_EVENTLOG "\\PIPE\\eventlog" #define PIPE_NETLOGON_PLAIN "\\NETLOGON" @@ -207,7 +211,9 @@ typedef smb_ucs2_t wfstring[FSTRING_LEN]; #define PI_NETDFS 8 #define PI_ECHO 9 #define PI_SHUTDOWN 10 -#define PI_MAX_PIPES 11 +#define PI_SVCCTL 11 +#define PI_EVENTLOG 12 +#define PI_MAX_PIPES 13 /* 64 bit time (100usec) since ????? - cifs6.txt, section 3.5, page 30 */ typedef struct nttime_info @@ -281,10 +287,28 @@ typedef struct sid_info } DOM_SID; -typedef struct sid_list { - uint32 count; - DOM_SID *list; -} SID_LIST; +/* Some well-known SIDs */ +extern const DOM_SID global_sid_World_Domain; +extern const DOM_SID global_sid_World; +extern const DOM_SID global_sid_Creator_Owner_Domain; +extern const DOM_SID global_sid_NT_Authority; +extern const DOM_SID global_sid_System; +extern const DOM_SID global_sid_NULL; +extern const DOM_SID global_sid_Authenticated_Users; +extern const DOM_SID global_sid_Network; +extern const DOM_SID global_sid_Creator_Owner; +extern const DOM_SID global_sid_Creator_Group; +extern const DOM_SID global_sid_Anonymous; +extern const DOM_SID global_sid_Builtin; +extern const DOM_SID global_sid_Builtin_Administrators; +extern const DOM_SID global_sid_Builtin_Users; +extern const DOM_SID global_sid_Builtin_Guests; +extern const DOM_SID global_sid_Builtin_Power_Users; +extern const DOM_SID global_sid_Builtin_Account_Operators; +extern const DOM_SID global_sid_Builtin_Server_Operators; +extern const DOM_SID global_sid_Builtin_Print_Operators; +extern const DOM_SID global_sid_Builtin_Backup_Operators; +extern const DOM_SID global_sid_Builtin_Replicator; /* * The complete list of SIDS belonging to this user. @@ -355,14 +379,14 @@ typedef struct time_info } UTIME; /* Structure used when SMBwritebmpx is active */ -typedef struct -{ - size_t wr_total_written; /* So we know when to discard this */ - int32 wr_timeout; - int32 wr_errclass; - int32 wr_error; /* Cached errors */ - BOOL wr_mode; /* write through mode) */ - BOOL wr_discard; /* discard all further data */ +typedef struct { + size_t wr_total_written; /* So we know when to discard this */ + int32 wr_timeout; + int32 wr_errclass; /* Cached errors */ + int32 wr_error; /* Cached errors */ + NTSTATUS wr_status; /* Cached errors */ + BOOL wr_mode; /* write through mode) */ + BOOL wr_discard; /* discard all further data */ } write_bmpx_struct; typedef struct write_cache @@ -1382,13 +1406,6 @@ enum case_handling {CASE_LOWER,CASE_UPPER}; */ #define COPYBUF_SIZE (8*1024) -/* - * Values used to override error codes. - */ -extern int unix_ERR_class; -extern int unix_ERR_code; -extern NTSTATUS unix_ERR_ntstatus; - /* * Used in chaining code. */ @@ -1717,6 +1734,11 @@ struct ea_struct { DATA_BLOB value; }; +struct ea_list { + struct ea_list *next, *prev; + struct ea_struct ea; +}; + /* EA names used internally in Samba. KEEP UP TO DATE with prohibited_ea_names in trans2.c !. */ #define SAMBA_POSIX_INHERITANCE_EA_NAME "user.SAMBA_PAI" /* EA to use for DOS attributes */ diff --git a/source/include/smb_macros.h b/source/include/smb_macros.h index 4fa9ffa5ace..ab4ee5ee73b 100644 --- a/source/include/smb_macros.h +++ b/source/include/smb_macros.h @@ -43,7 +43,7 @@ * @note You are explicitly allowed to pass NULL pointers -- they will * always be ignored. **/ -#define SAFE_FREE(x) do { if ((x) != NULL) {free(x); x=NULL;} } while(0) +#define SAFE_FREE(x) do { if ((x) != NULL) {free(CONST_DISCARD(void *, (x))); x=NULL;} } while(0) #endif /* zero a structure */ @@ -76,16 +76,20 @@ #define OPEN_CONN(conn) ((conn) && (conn)->open) #define IS_IPC(conn) ((conn) && (conn)->ipc) #define IS_PRINT(conn) ((conn) && (conn)->printer) +/* you must add the following extern declaration to files using this macro + * extern struct current_user current_user; + */ #define FSP_BELONGS_CONN(fsp,conn) do {\ - extern struct current_user current_user;\ if (!((fsp) && (conn) && ((conn)==(fsp)->conn) && (current_user.vuid==(fsp)->vuid))) \ return(ERROR_DOS(ERRDOS,ERRbadfid));\ } while(0) #define FNUM_OK(fsp,c) (OPEN_FSP(fsp) && (c)==(fsp)->conn && current_user.vuid==(fsp)->vuid) +/* you must add the following extern declaration to files using this macro + * extern struct current_user current_user; + */ #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) \ @@ -97,9 +101,6 @@ #define CHECK_WRITE(fsp) if (!(fsp)->can_write) \ return(ERROR_DOS(ERRDOS,ERRbadaccess)) -#define CHECK_ERROR(fsp) if (HAS_CACHED_ERROR(fsp)) \ - return(CACHED_ERROR(fsp)) - #define ERROR_WAS_LOCK_DENIED(status) (NT_STATUS_EQUAL((status), NT_STATUS_LOCK_NOT_GRANTED) || \ NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT) ) @@ -158,25 +159,23 @@ #define SMB_LARGE_LKLEN_OFFSET_HIGH(indx) (12 + (20 * (indx))) #define SMB_LARGE_LKLEN_OFFSET_LOW(indx) (16 + (20 * (indx))) -/* Macro to cache an error in a write_bmpx_struct */ -#define CACHE_ERROR(w,c,e) ((w)->wr_errclass = (c), (w)->wr_error = (e), \ - w->wr_discard = True, -1) /* Macro to test if an error has been cached for this fnum */ #define HAS_CACHED_ERROR(fsp) ((fsp)->wbmpx_ptr && \ (fsp)->wbmpx_ptr->wr_discard) /* Macro to turn the cached error into an error packet */ #define CACHED_ERROR(fsp) cached_error_packet(outbuf,fsp,__LINE__,__FILE__) -/* these are the datagram types */ -#define DGRAM_DIRECT_UNIQUE 0x10 - -#define ERROR_DOS(class,code) error_packet(outbuf,NT_STATUS_OK,class,code,False,__LINE__,__FILE__) -#define ERROR_FORCE_DOS(class,code) error_packet(outbuf,NT_STATUS_OK,class,code,True,__LINE__,__FILE__) -#define ERROR_NT(status) error_packet(outbuf,status,0,0,False,__LINE__,__FILE__) -#define ERROR_BOTH(status,class,code) error_packet(outbuf,status,class,code,False,__LINE__,__FILE__) +#define ERROR_DOS(class,code) error_packet(outbuf,class,code,NT_STATUS_OK,__LINE__,__FILE__) +#define ERROR_FORCE_DOS(class,code) error_packet(outbuf,class,code,NT_STATUS_INVALID,__LINE__,__FILE__) +#define ERROR_NT(status) error_packet(outbuf,0,0,status,__LINE__,__FILE__) +#define ERROR_FORCE_NT(status) error_packet(outbuf,-1,-1,status,__LINE__,__FILE__) +#define ERROR_BOTH(status,class,code) error_packet(outbuf,class,code,status,__LINE__,__FILE__) /* this is how errors are generated */ -#define UNIXERROR(defclass,deferror) unix_error_packet(outbuf,defclass,deferror,__LINE__,__FILE__) +#define UNIXERROR(defclass,deferror) unix_error_packet(outbuf,defclass,deferror,NT_STATUS_OK,__LINE__,__FILE__) + +/* these are the datagram types */ +#define DGRAM_DIRECT_UNIQUE 0x10 #define SMB_ROUNDUP(x,r) ( ((x)%(r)) ? ( (((x)+(r))/(r))*(r) ) : (x)) @@ -290,6 +289,8 @@ copy an IP address from one buffer to another #define TALLOC_REALLOC_ARRAY(ctx, ptr, type, count) (type *)talloc_realloc_array_((ctx),(ptr),sizeof(type),(count)) #define PRS_ALLOC_MEM(ps, type, count) (type *)prs_alloc_mem_((ps),sizeof(type),(count)) +#define PRS_ALLOC_MEM_VOID(ps, size) prs_alloc_mem_((ps),(size),1) + /* Get medieval on our ass about malloc.... */ @@ -338,6 +339,7 @@ copy an IP address from one buffer to another #define TALLOC_REALLOC_ARRAY(ctx, ptr, type, count) (type *)talloc_realloc_array((ctx),(ptr),sizeof(type),(count)) #define PRS_ALLOC_MEM(ps, type, count) (type *)prs_alloc_mem((ps),sizeof(type),(count)) +#define PRS_ALLOC_MEM_VOID(ps, size) prs_alloc_mem((ps),(size),1) /* Regular malloc code. */ @@ -349,4 +351,14 @@ copy an IP address from one buffer to another #endif +#define ADD_TO_ARRAY(mem_ctx, type, elem, array, num) \ +do { \ + *(array) = ((mem_ctx) != NULL) ? \ + TALLOC_REALLOC_ARRAY(mem_ctx, (*(array)), type, (*(num))+1) : \ + SMB_REALLOC_ARRAY((*(array)), type, (*(num))+1); \ + SMB_ASSERT((*(array)) != NULL); \ + (*(array))[*(num)] = (elem); \ + (*(num)) += 1; \ +} while (0) + #endif /* _SMB_MACROS_H */ diff --git a/source/include/trans2.h b/source/include/trans2.h index 68358344f4e..2aae1137dd7 100644 --- a/source/include/trans2.h +++ b/source/include/trans2.h @@ -226,6 +226,9 @@ Byte offset Type name description #define SMB_QUERY_FILE_STREAM_INFO 0x109 #define SMB_QUERY_COMPRESSION_INFO 0x10b +#define SMB_FIND_INFO_STANDARD 1 +#define SMB_FIND_EA_SIZE 2 +#define SMB_FIND_EA_LIST 3 #define SMB_FIND_FILE_DIRECTORY_INFO 0x101 #define SMB_FIND_FILE_FULL_DIRECTORY_INFO 0x102 #define SMB_FIND_FILE_NAMES_INFO 0x103 @@ -437,6 +440,9 @@ Offset Size Name #define SMB_QUERY_XATTR 0x205 /* need for non-user XATTRs */ #define SMB_QUERY_ATTR_FLAGS 0x206 /* chflags, chattr */ #define SMB_SET_ATTR_FLAGS 0x206 +#define SMB_QUERY_POSIX_PERMISSION 0x207 +#define SMB_QUERY_POSIX_LOCK 0x208 +#define SMB_SET_POSIX_LOCK 0x208 /* Transact 2 Find First levels */ #define SMB_FIND_FILE_UNIX 0x202 @@ -461,6 +467,12 @@ Offset Size Name #define CIFS_UNIX_FCNTL_LOCKS_CAP 0x1 #define CIFS_UNIX_POSIX_ACLS_CAP 0x2 +#define CIFS_UNIX_XATTTR_CAP 0x4 /* for support of other xattr + namespaces such as system, + security and trusted */ +#define CIFS_UNIX_EXTATTR_CAP 0x8 /* for support of chattr + (chflags) and lsattr */ + #define SMB_QUERY_POSIX_FS_INFO 0x201 diff --git a/source/intl/lang_tdb.c b/source/intl/lang_tdb.c index d3422f0d78a..d8f7fc8c933 100644 --- a/source/intl/lang_tdb.c +++ b/source/intl/lang_tdb.c @@ -231,7 +231,7 @@ const char *lang_msg(const char *msgid) void lang_msg_free(const char *msgstr) { if (!tdb) return; - free((void *)msgstr); + free(CONST_DISCARD(void *, msgstr)); } @@ -248,7 +248,7 @@ const char *lang_msg_rotate(const char *msgid) static pstring bufs[NUM_LANG_BUFS]; static int next; - msgstr = (char *)lang_msg(msgid); + msgstr = CONST_DISCARD(char *, lang_msg(msgid)); if (!msgstr) return msgid; pstrcpy(bufs[next], msgstr); diff --git a/source/lib/access.c b/source/lib/access.c index fcc795d1f26..d8e40c99f76 100644 --- a/source/lib/access.c +++ b/source/lib/access.c @@ -133,7 +133,7 @@ static BOOL string_match(const char *tok,const char *s, char *invalid_char) /* client_match - match host name and address against token */ static BOOL client_match(const char *tok, const char *item) { - const char **client = (const char **)item; + const char **client = CONST_ADD(const char **, item); BOOL match; char invalid_char = '\0'; diff --git a/source/lib/account_pol.c b/source/lib/account_pol.c index 72d6e77ddda..423dc1675a6 100644 --- a/source/lib/account_pol.c +++ b/source/lib/account_pol.c @@ -24,14 +24,6 @@ static TDB_CONTEXT *tdb; #define DATABASE_VERSION 2 -extern DOM_SID global_sid_World; -extern DOM_SID global_sid_Builtin_Administrators; -extern DOM_SID global_sid_Builtin_Account_Operators; -extern DOM_SID global_sid_Builtin_Server_Operators; -extern DOM_SID global_sid_Builtin_Print_Operators; -extern DOM_SID global_sid_Builtin_Backup_Operators; - - /**************************************************************************** Set default for a field if it is empty ****************************************************************************/ diff --git a/source/lib/charcnv.c b/source/lib/charcnv.c index b9b9d90db67..4fbad0f3d18 100644 --- a/source/lib/charcnv.c +++ b/source/lib/charcnv.c @@ -1268,6 +1268,21 @@ size_t pull_utf8_allocate(char **dest, const char *src) return convert_string_allocate(NULL, CH_UTF8, CH_UNIX, src, src_len, (void **)dest, True); } +/** + * Copy a string from a DOS src to a unix char * destination, allocating a buffer using talloc + * + * @param dest always set at least to NULL + * + * @returns The number of bytes occupied by the string in the destination + **/ + +size_t pull_ascii_talloc(TALLOC_CTX *ctx, char **dest, const char *src) +{ + size_t src_len = strlen(src)+1; + *dest = NULL; + return convert_string_talloc(ctx, CH_DOS, CH_UNIX, src, src_len, (void **)dest, True); +} + /** Copy a string from a char* src to a unicode or ascii dos codepage destination choosing unicode or ascii based on the diff --git a/source/lib/data_blob.c b/source/lib/data_blob.c index a1c3af2d492..35805f861c5 100644 --- a/source/lib/data_blob.c +++ b/source/lib/data_blob.c @@ -47,7 +47,7 @@ DATA_BLOB data_blob(const void *p, size_t length) if (p) { ret.data = smb_xmemdup(p, length); } else { - ret.data = SMB_XMALLOC_ARRAY(char, length); + ret.data = SMB_XMALLOC_ARRAY(unsigned char, length); } ret.length = length; ret.free = free_data_blob; diff --git a/source/lib/iconv.c b/source/lib/iconv.c index d58165fed03..f23e4351c02 100644 --- a/source/lib/iconv.c +++ b/source/lib/iconv.c @@ -135,7 +135,7 @@ static size_t sys_iconv(void *cd, { #ifdef HAVE_NATIVE_ICONV size_t ret = iconv((iconv_t)cd, - (char **)inbuf, inbytesleft, + CONST_DISCARD(char **, inbuf), inbytesleft, outbuf, outbytesleft); if (ret == (size_t)-1) { int saved_errno = errno; diff --git a/source/lib/ms_fnmatch.c b/source/lib/ms_fnmatch.c index a0cbfd2ee21..c7cf54d26b5 100644 --- a/source/lib/ms_fnmatch.c +++ b/source/lib/ms_fnmatch.c @@ -146,7 +146,7 @@ static int ms_fnmatch_core(const smb_ucs2_t *p, const smb_ucs2_t *n, return -1; } -int ms_fnmatch(const char *pattern, const char *string, enum protocol_types protocol, +int ms_fnmatch(const char *pattern, const char *string, BOOL translate_pattern, BOOL is_case_sensitive) { wpstring p, s; @@ -179,7 +179,7 @@ int ms_fnmatch(const char *pattern, const char *string, enum protocol_types prot return -1; } - if (protocol <= PROTOCOL_LANMAN2) { + if (translate_pattern) { /* for older negotiated protocols it is possible to translate the pattern to produce a "new style" diff --git a/source/lib/privileges.c b/source/lib/privileges.c index 8b5348e1f25..e01561de06f 100644 --- a/source/lib/privileges.c +++ b/source/lib/privileges.c @@ -95,7 +95,12 @@ PRIVS privs[] = { {SE_END, "", ""} }; -typedef struct priv_sid_list { +typedef struct { + int count; + DOM_SID *list; +} SID_LIST; + +typedef struct { SE_PRIV privilege; SID_LIST sids; } PRIV_SID_LIST; @@ -492,7 +497,7 @@ static int priv_traverse_fn(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void *s return 0; } - add_sid_to_array( &sid, &priv->sids.list, &priv->sids.count ); + add_sid_to_array( NULL, &sid, &priv->sids.list, &priv->sids.count ); return 0; } diff --git a/source/lib/secace.c b/source/lib/secace.c index e44d9aa940e..c550dcce311 100644 --- a/source/lib/secace.c +++ b/source/lib/secace.c @@ -57,7 +57,7 @@ void sec_ace_copy(SEC_ACE *ace_dest, SEC_ACE *ace_src) Sets up a SEC_ACE structure. ********************************************************************/ -void init_sec_ace(SEC_ACE *t, DOM_SID *sid, uint8 type, SEC_ACCESS mask, uint8 flag) +void init_sec_ace(SEC_ACE *t, const DOM_SID *sid, uint8 type, SEC_ACCESS mask, uint8 flag) { t->type = type; t->flags = flag; diff --git a/source/lib/secdesc.c b/source/lib/secdesc.c index 686a4edf77c..ace0aee8664 100644 --- a/source/lib/secdesc.c +++ b/source/lib/secdesc.c @@ -179,7 +179,7 @@ SEC_DESC_BUF *sec_desc_merge(TALLOC_CTX *ctx, SEC_DESC_BUF *new_sdb, SEC_DESC_BU ********************************************************************/ SEC_DESC *make_sec_desc(TALLOC_CTX *ctx, uint16 revision, uint16 type, - DOM_SID *owner_sid, DOM_SID *grp_sid, + const DOM_SID *owner_sid, const DOM_SID *grp_sid, SEC_ACL *sacl, SEC_ACL *dacl, size_t *sd_size) { SEC_DESC *dst; @@ -269,7 +269,7 @@ SEC_DESC *dup_sec_desc(TALLOC_CTX *ctx, const SEC_DESC *src) Creates a SEC_DESC structure with typical defaults. ********************************************************************/ -SEC_DESC *make_standard_sec_desc(TALLOC_CTX *ctx, DOM_SID *owner_sid, DOM_SID *grp_sid, +SEC_DESC *make_standard_sec_desc(TALLOC_CTX *ctx, const DOM_SID *owner_sid, const DOM_SID *grp_sid, SEC_ACL *dacl, size_t *sd_size) { return make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, diff --git a/source/lib/select.c b/source/lib/select.c index f3d119bdb15..2e55f9753db 100644 --- a/source/lib/select.c +++ b/source/lib/select.c @@ -99,20 +99,23 @@ int sys_select(int maxfd, fd_set *readfds, fd_set *writefds, fd_set *errorfds, s FD_ZERO(writefds); if (errorfds) FD_ZERO(errorfds); - } - - if (FD_ISSET(select_pipe[0], readfds2)) { + } else if (FD_ISSET(select_pipe[0], readfds2)) { char c; saved_errno = errno; if (read(select_pipe[0], &c, 1) == 1) { pipe_read++; - } - errno = saved_errno; - FD_CLR(select_pipe[0], readfds2); - ret--; - if (ret == 0) { + /* Mark Weaver pointed out a critical + fix to ensure we don't lose signals. We must always + return -1 when the select pipe is set, otherwise if another + fd is also ready (so ret == 2) then we used to eat the + byte in the pipe and lose the signal. JRA. + */ ret = -1; errno = EINTR; + } else { + FD_CLR(select_pipe[0], readfds2); + ret--; + errno = saved_errno; } } @@ -167,7 +170,12 @@ int sys_select_intr(int maxfd, fd_set *readfds, fd_set *writefds, fd_set *errorf ptval->tv_usec = tdif % 1000000; } - ret = sys_select(maxfd, readfds2, writefds2, errorfds2, ptval); + /* We must use select and not sys_select here. If we use + sys_select we'd lose the fact a signal occurred when sys_select + read a byte from the pipe. Fix from Mark Weaver + + */ + ret = select(maxfd, readfds2, writefds2, errorfds2, ptval); } while (ret == -1 && errno == EINTR); if (readfds) diff --git a/source/lib/smbldap.c b/source/lib/smbldap.c index 68084b04045..cf2f03e0a24 100644 --- a/source/lib/smbldap.c +++ b/source/lib/smbldap.c @@ -1066,7 +1066,9 @@ int smbldap_search(struct smbldap_state *ldap_state, while (another_ldap_try(ldap_state, &rc, &attempts, endtime)) rc = ldap_search_s(ldap_state->ldap_struct, base, scope, - utf8_filter, attrs, attrsonly, res); + utf8_filter, + CONST_DISCARD(char **, attrs), + attrsonly, res); SAFE_FREE(utf8_filter); return rc; @@ -1471,7 +1473,8 @@ static BOOL smbldap_check_root_dse(struct smbldap_state *ldap_state, const char } rc = ldap_search_s(ldap_state->ldap_struct, "", LDAP_SCOPE_BASE, - "(objectclass=*)", attrs, 0 , &msg); + "(objectclass=*)", CONST_DISCARD(char **, attrs), + 0 , &msg); if (rc != LDAP_SUCCESS) { DEBUG(3,("smbldap_check_root_dse: Could not search rootDSE\n")); diff --git a/source/lib/substitute.c b/source/lib/substitute.c index 615a8d73b0a..af30e900ace 100644 --- a/source/lib/substitute.c +++ b/source/lib/substitute.c @@ -21,6 +21,8 @@ #include "includes.h" +extern struct current_user current_user; + fstring local_machine=""; fstring remote_arch="UNKNOWN"; userdom_struct current_user_info; @@ -800,7 +802,6 @@ char *alloc_sub_conn(connection_struct *conn, const char *str) void standard_sub_snum(int snum, char *str, size_t len) { - extern struct current_user current_user; static uid_t cached_uid = -1; static fstring cached_user; /* calling uidtoname() on every substitute would be too expensive, so diff --git a/source/lib/system.c b/source/lib/system.c index 7434cbe35ee..a2e5352aa5f 100644 --- a/source/lib/system.c +++ b/source/lib/system.c @@ -1373,10 +1373,17 @@ ssize_t sys_getxattr (const char *path, const char *name, void *value, size_t si { #if defined(HAVE_GETXATTR) return getxattr(path, name, value, size); +#elif defined(HAVE_EXTATTR_GET_FILE) + char *s; + int attrnamespace = (strncmp(name, "system", 6) == 0) ? + EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER; + const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1; + + return extattr_get_file(path, attrnamespace, attrname, value, size); #elif defined(HAVE_ATTR_GET) int retval, flags = 0; int valuelength = (int)size; - char *attrname = strchr(name,'.') +1; + char *attrname = strchr(name,'.') + 1; if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT; @@ -1393,10 +1400,17 @@ ssize_t sys_lgetxattr (const char *path, const char *name, void *value, size_t s { #if defined(HAVE_LGETXATTR) return lgetxattr(path, name, value, size); +#elif defined(HAVE_EXTATTR_GET_LINK) + char *s; + int attrnamespace = (strncmp(name, "system", 6) == 0) ? + EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER; + const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1; + + return extattr_get_link(path, attrnamespace, attrname, value, size); #elif defined(HAVE_ATTR_GET) int retval, flags = ATTR_DONTFOLLOW; int valuelength = (int)size; - char *attrname = strchr(name,'.') +1; + char *attrname = strchr(name,'.') + 1; if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT; @@ -1413,10 +1427,17 @@ ssize_t sys_fgetxattr (int filedes, const char *name, void *value, size_t size) { #if defined(HAVE_FGETXATTR) return fgetxattr(filedes, name, value, size); +#elif defined(HAVE_EXTATTR_GET_FD) + char *s; + int attrnamespace = (strncmp(name, "system", 6) == 0) ? + EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER; + const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1; + + return extattr_get_fd(filedes, attrnamespace, attrname, value, size); #elif defined(HAVE_ATTR_GETF) int retval, flags = 0; int valuelength = (int)size; - char *attrname = strchr(name,'.') +1; + char *attrname = strchr(name,'.') + 1; if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT; @@ -1429,6 +1450,99 @@ ssize_t sys_fgetxattr (int filedes, const char *name, void *value, size_t size) #endif } +#if defined(HAVE_EXTATTR_LIST_FILE) + +#define EXTATTR_PREFIX(s) (s), (sizeof((s))-1) + +static struct { + int space; + const char *name; + size_t len; +} +extattr[] = { + { EXTATTR_NAMESPACE_SYSTEM, EXTATTR_PREFIX("system.") }, + { EXTATTR_NAMESPACE_USER, EXTATTR_PREFIX("user.") }, +}; + +typedef union { + const char *path; + int filedes; +} extattr_arg; + +static ssize_t bsd_attr_list (int type, extattr_arg arg, char *list, size_t size) +{ + ssize_t list_size, total_size = 0; + int i, t, len; + char *buf; + /* Iterate through extattr(2) namespaces */ + for(t = 0; t < (sizeof(extattr)/sizeof(extattr[0])); t++) { + switch(type) { +#if defined(HAVE_EXTATTR_LIST_FILE) + case 0: + list_size = extattr_list_file(arg.path, extattr[t].space, list, size); + break; +#endif +#if defined(HAVE_EXTATTR_LIST_LINK) + case 1: + list_size = extattr_list_link(arg.path, extattr[t].space, list, size); + break; +#endif +#if defined(HAVE_EXTATTR_LIST_FD) + case 2: + list_size = extattr_list_fd(arg.filedes, extattr[t].space, list, size); + break; +#endif + default: + errno = ENOSYS; + return -1; + } + /* Some error happend. Errno should be set by the previous call */ + if(list_size < 0) + return -1; + /* No attributes */ + if(list_size == 0) + continue; + /* XXX: Call with an empty buffer may be used to calculate + necessary buffer size. Unfortunately, we can't say, how + many attributes were returned, so here is the potential + problem with the emulation. + */ + if(list == NULL) { + /* Take the worse case of one char attribute names - + two bytes per name plus one more for sanity. + */ + total_size += list_size + (list_size/2 + 1)*extattr[t].len; + continue; + } + /* Count necessary offset to fit namespace prefixes */ + len = 0; + for(i = 0; i < list_size; i += list[i] + 1) + len += extattr[t].len; + + total_size += list_size + len; + /* Buffer is too small to fit the results */ + if(total_size > size) { + errno = ERANGE; + return -1; + } + /* Shift the results back, so we can prepend prefixes */ + buf = memmove(list + len, list, list_size); + + for(i = 0; i < list_size; i += len + 1) { + len = buf[i]; + strncpy(list, extattr[t].name, extattr[t].len + 1); + list += extattr[t].len; + strncpy(list, buf + i + 1, len); + list[len] = '\0'; + list += len + 1; + } + size -= total_size; + } + return total_size; +} + +#endif + #if defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H) static char attr_buffer[ATTR_MAX_VALUELEN]; @@ -1501,6 +1615,10 @@ ssize_t sys_listxattr (const char *path, char *list, size_t size) { #if defined(HAVE_LISTXATTR) return listxattr(path, list, size); +#elif defined(HAVE_EXTATTR_LIST_FILE) + extattr_arg arg; + arg.path = path; + return bsd_attr_list(0, arg, list, size); #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H) return irix_attr_list(path, 0, list, size, 0); #else @@ -1513,6 +1631,10 @@ ssize_t sys_llistxattr (const char *path, char *list, size_t size) { #if defined(HAVE_LLISTXATTR) return llistxattr(path, list, size); +#elif defined(HAVE_EXTATTR_LIST_LINK) + extattr_arg arg; + arg.path = path; + return bsd_attr_list(1, arg, list, size); #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H) return irix_attr_list(path, 0, list, size, ATTR_DONTFOLLOW); #else @@ -1525,6 +1647,10 @@ ssize_t sys_flistxattr (int filedes, char *list, size_t size) { #if defined(HAVE_FLISTXATTR) return flistxattr(filedes, list, size); +#elif defined(HAVE_EXTATTR_LIST_FD) + extattr_arg arg; + arg.filedes = filedes; + return bsd_attr_list(2, arg, list, size); #elif defined(HAVE_ATTR_LISTF) return irix_attr_list(NULL, filedes, list, size, 0); #else @@ -1537,9 +1663,16 @@ int sys_removexattr (const char *path, const char *name) { #if defined(HAVE_REMOVEXATTR) return removexattr(path, name); +#elif defined(HAVE_EXTATTR_DELETE_FILE) + char *s; + int attrnamespace = (strncmp(name, "system", 6) == 0) ? + EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER; + const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1; + + return extattr_delete_file(path, attrnamespace, attrname); #elif defined(HAVE_ATTR_REMOVE) int flags = 0; - char *attrname = strchr(name,'.') +1; + char *attrname = strchr(name,'.') + 1; if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT; @@ -1554,9 +1687,16 @@ int sys_lremovexattr (const char *path, const char *name) { #if defined(HAVE_LREMOVEXATTR) return lremovexattr(path, name); +#elif defined(HAVE_EXTATTR_DELETE_LINK) + char *s; + int attrnamespace = (strncmp(name, "system", 6) == 0) ? + EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER; + const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1; + + return extattr_delete_link(path, attrnamespace, attrname); #elif defined(HAVE_ATTR_REMOVE) int flags = ATTR_DONTFOLLOW; - char *attrname = strchr(name,'.') +1; + char *attrname = strchr(name,'.') + 1; if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT; @@ -1571,9 +1711,16 @@ int sys_fremovexattr (int filedes, const char *name) { #if defined(HAVE_FREMOVEXATTR) return fremovexattr(filedes, name); +#elif defined(HAVE_EXTATTR_DELETE_FD) + char *s; + int attrnamespace = (strncmp(name, "system", 6) == 0) ? + EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER; + const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1; + + return extattr_delete_fd(filedes, attrnamespace, attrname); #elif defined(HAVE_ATTR_REMOVEF) int flags = 0; - char *attrname = strchr(name,'.') +1; + char *attrname = strchr(name,'.') + 1; if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT; @@ -1593,9 +1740,18 @@ int sys_setxattr (const char *path, const char *name, const void *value, size_t { #if defined(HAVE_SETXATTR) return setxattr(path, name, value, size, flags); +#elif defined(HAVE_EXTATTR_SET_FILE) + char *s; + int retval = 0; + int attrnamespace = (strncmp(name, "system", 6) == 0) ? + EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER; + const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1; + + retval = extattr_set_file(path, attrnamespace, attrname, value, size); + return (retval < 0) ? -1 : 0; #elif defined(HAVE_ATTR_SET) int myflags = 0; - char *attrname = strchr(name,'.') +1; + char *attrname = strchr(name,'.') + 1; if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT; if (flags & XATTR_CREATE) myflags |= ATTR_CREATE; @@ -1612,9 +1768,18 @@ int sys_lsetxattr (const char *path, const char *name, const void *value, size_t { #if defined(HAVE_LSETXATTR) return lsetxattr(path, name, value, size, flags); +#elif defined(HAVE_EXTATTR_SET_LINK) + char *s; + int retval = 0; + int attrnamespace = (strncmp(name, "system", 6) == 0) ? + EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER; + const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1; + + retval = extattr_set_link(path, attrnamespace, attrname, value, size); + return (retval < 0) ? -1 : 0; #elif defined(HAVE_ATTR_SET) int myflags = ATTR_DONTFOLLOW; - char *attrname = strchr(name,'.') +1; + char *attrname = strchr(name,'.') + 1; if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT; if (flags & XATTR_CREATE) myflags |= ATTR_CREATE; @@ -1631,9 +1796,18 @@ int sys_fsetxattr (int filedes, const char *name, const void *value, size_t size { #if defined(HAVE_FSETXATTR) return fsetxattr(filedes, name, value, size, flags); +#elif defined(HAVE_EXTATTR_SET_FD) + char *s; + int retval = 0; + int attrnamespace = (strncmp(name, "system", 6) == 0) ? + EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER; + const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1; + + retval = extattr_set_fd(filedes, attrnamespace, attrname, value, size); + return (retval < 0) ? -1 : 0; #elif defined(HAVE_ATTR_SETF) int myflags = 0; - char *attrname = strchr(name,'.') +1; + char *attrname = strchr(name,'.') + 1; if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT; if (flags & XATTR_CREATE) myflags |= ATTR_CREATE; diff --git a/source/lib/system_smbd.c b/source/lib/system_smbd.c index c83eecf1733..f124983006d 100644 --- a/source/lib/system_smbd.c +++ b/source/lib/system_smbd.c @@ -178,10 +178,10 @@ BOOL getgroups_user(const char *user, gid_t primary_gid, groups = NULL; /* Add in primary group first */ - add_gid_to_array_unique(primary_gid, &groups, &ngrp); + add_gid_to_array_unique(NULL, primary_gid, &groups, &ngrp); for (i=0; itv_sec - smallt->tv_sec; return (sec_diff * 1000000) + (SMB_BIG_INT)(larget->tv_usec - smallt->tv_usec); } + + +/**************************************************************************** + convert ASN.1 GeneralizedTime string to unix-time + returns 0 on failure; Currently ignores timezone. +****************************************************************************/ +time_t generalized_to_unix_time(const char *str) +{ + struct tm tm; + + ZERO_STRUCT(tm); + + if (sscanf(str, "%4d%2d%2d%2d%2d%2d", + &tm.tm_year, &tm.tm_mon, &tm.tm_mday, + &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) { + return 0; + } + tm.tm_year -= 1900; + tm.tm_mon -= 1; + + return timegm(&tm); +} diff --git a/source/lib/util.c b/source/lib/util.c index 42ead313a92..d244e390d22 100644 --- a/source/lib/util.c +++ b/source/lib/util.c @@ -23,6 +23,11 @@ #include "includes.h" +extern fstring local_machine; +extern char *global_clobber_region_function; +extern unsigned int global_clobber_region_line; +extern fstring remote_arch; + /* Max allowable allococation - 256mb - 0x10000000 */ #define MAX_ALLOC_SIZE (1024*1024*256) @@ -230,7 +235,6 @@ BOOL set_netbios_aliases(const char **str_array) BOOL init_names(void) { - extern fstring local_machine; char *p; int n; @@ -273,29 +277,12 @@ const char *tmpdir(void) return "/tmp"; } -/**************************************************************************** - Determine whether we are in the specified group. -****************************************************************************/ - -BOOL in_group(gid_t group, gid_t current_gid, int ngroups, const gid_t *groups) -{ - int i; - - if (group == current_gid) - return(True); - - for (i=0;i> 16)&0xFFFF); - push_ascii(buf+30,fname,12,0); + /* We only uppercase if FLAGS2_LONG_PATH_COMPONENTS is zero in the input buf. + Strange, but verified on W2K3. Needed for OS/2. JRA. */ + push_ascii(buf+30,fname,12, uc ? STR_UPPER : 0); DEBUG(8,("put name [%s] from [%s] into dir struct\n",buf+30, fname)); } @@ -1465,8 +1457,6 @@ void smb_panic2(const char *why, BOOL decrement_pid_count ) #ifdef DEVELOPER { - extern char *global_clobber_region_function; - extern unsigned int global_clobber_region_line; if (global_clobber_region_function) { DEBUG(0,("smb_panic: clobber_region() last called from [%s(%u)]\n", @@ -1931,7 +1921,6 @@ void ra_lanman_string( const char *native_lanman ) void set_remote_arch(enum remote_arch_types type) { - extern fstring remote_arch; ra_type = type; switch( type ) { case RA_WFWG: @@ -2172,8 +2161,12 @@ BOOL reg_split_key(const char *full_keyname, uint32 *reg_type, char *key_name) if (strequal(tmp, "HKLM") || strequal(tmp, "HKEY_LOCAL_MACHINE")) (*reg_type) = HKEY_LOCAL_MACHINE; + else if (strequal(tmp, "HKCR") || strequal(tmp, "HKEY_CLASSES_ROOT")) + (*reg_type) = HKEY_CLASSES_ROOT; else if (strequal(tmp, "HKU") || strequal(tmp, "HKEY_USERS")) (*reg_type) = HKEY_USERS; + else if (strequal(tmp, "HKPD")||strequal(tmp, "HKEY_PERFORMANCE_DATA")) + (*reg_type) = HKEY_PERFORMANCE_DATA; else { DEBUG(10,("reg_split_key: unrecognised hive key %s\n", tmp)); return False; @@ -2469,7 +2462,23 @@ BOOL mask_match(const char *string, char *pattern, BOOL is_case_sensitive) if (strcmp(pattern,".") == 0) return False; - return ms_fnmatch(pattern, string, Protocol, is_case_sensitive) == 0; + return ms_fnmatch(pattern, string, Protocol <= PROTOCOL_LANMAN2, is_case_sensitive) == 0; +} + +/******************************************************************* + A wrapper that handles case sensitivity and the special handling + of the ".." name. Varient that is only called by old search code which requires + pattern translation. +*******************************************************************/ + +BOOL mask_match_search(const char *string, char *pattern, BOOL is_case_sensitive) +{ + if (strcmp(string,"..") == 0) + string = "."; + if (strcmp(pattern,".") == 0) + return False; + + return ms_fnmatch(pattern, string, True, is_case_sensitive) == 0; } /******************************************************************* diff --git a/source/lib/util_seaccess.c b/source/lib/util_seaccess.c index b5a9010b5c4..73fc45c844d 100644 --- a/source/lib/util_seaccess.c +++ b/source/lib/util_seaccess.c @@ -21,7 +21,7 @@ #include "includes.h" -extern DOM_SID global_sid_Builtin; +extern NT_USER_TOKEN anonymous_token; /********************************************************************************* Check an ACE against a SID. We return the remaining needed permission @@ -214,7 +214,6 @@ BOOL se_access_check(const SEC_DESC *sd, const NT_USER_TOKEN *token, uint32 acc_desired, uint32 *acc_granted, NTSTATUS *status) { - extern NT_USER_TOKEN anonymous_token; size_t i; SEC_ACL *the_acl; fstring sid_str; @@ -316,3 +315,41 @@ BOOL se_access_check(const SEC_DESC *sd, const NT_USER_TOKEN *token, return False; } + +/******************************************************************* + samr_make_sam_obj_sd + ********************************************************************/ + +NTSTATUS samr_make_sam_obj_sd(TALLOC_CTX *ctx, SEC_DESC **psd, size_t *sd_size) +{ + DOM_SID adm_sid; + DOM_SID act_sid; + + SEC_ACE ace[3]; + SEC_ACCESS mask; + + SEC_ACL *psa = NULL; + + sid_copy(&adm_sid, &global_sid_Builtin); + sid_append_rid(&adm_sid, BUILTIN_ALIAS_RID_ADMINS); + + sid_copy(&act_sid, &global_sid_Builtin); + sid_append_rid(&act_sid, BUILTIN_ALIAS_RID_ACCOUNT_OPS); + + /*basic access for every one*/ + init_sec_access(&mask, GENERIC_RIGHTS_SAM_EXECUTE | GENERIC_RIGHTS_SAM_READ); + init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); + + /*full access for builtin aliases Administrators and Account Operators*/ + init_sec_access(&mask, GENERIC_RIGHTS_SAM_ALL_ACCESS); + init_sec_ace(&ace[1], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); + init_sec_ace(&ace[2], &act_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); + + if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 3, ace)) == NULL) + return NT_STATUS_NO_MEMORY; + + if ((*psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL, psa, sd_size)) == NULL) + return NT_STATUS_NO_MEMORY; + + return NT_STATUS_OK; +} diff --git a/source/lib/util_sid.c b/source/lib/util_sid.c index 0ba774e184d..1838da1313d 100644 --- a/source/lib/util_sid.c +++ b/source/lib/util_sid.c @@ -28,29 +28,51 @@ * Some useful sids */ -DOM_SID global_sid_World_Domain; /* Everyone domain */ -DOM_SID global_sid_World; /* Everyone */ -DOM_SID global_sid_Creator_Owner_Domain; /* Creator Owner domain */ -DOM_SID global_sid_NT_Authority; /* NT Authority */ -DOM_SID global_sid_System; /* System */ -DOM_SID global_sid_NULL; /* NULL sid */ -DOM_SID global_sid_Authenticated_Users; /* All authenticated rids */ -DOM_SID global_sid_Network; /* Network rids */ - -DOM_SID global_sid_Creator_Owner; /* Creator Owner */ -DOM_SID global_sid_Creator_Group; /* Creator Group */ -DOM_SID global_sid_Anonymous; /* Anonymous login */ - -DOM_SID global_sid_Builtin; /* Local well-known domain */ -DOM_SID global_sid_Builtin_Administrators; /* Builtin administrators */ -DOM_SID global_sid_Builtin_Users; /* Builtin users */ -DOM_SID global_sid_Builtin_Guests; /* Builtin guest users */ -DOM_SID global_sid_Builtin_Power_Users; /* Builtin power users */ -DOM_SID global_sid_Builtin_Account_Operators; /* Builtin account operators */ -DOM_SID global_sid_Builtin_Server_Operators; /* Builtin server operators */ -DOM_SID global_sid_Builtin_Print_Operators; /* Builtin print operators */ -DOM_SID global_sid_Builtin_Backup_Operators; /* Builtin backup operators */ -DOM_SID global_sid_Builtin_Replicator; /* Builtin replicator */ + +const DOM_SID global_sid_World_Domain = /* Everyone domain */ +{ 1, 0, {0,0,0,0,0,1}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}; +const DOM_SID global_sid_World = /* Everyone */ +{ 1, 1, {0,0,0,0,0,1}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}; +const DOM_SID global_sid_Creator_Owner_Domain = /* Creator Owner domain */ +{ 1, 0, {0,0,0,0,0,3}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}; +const DOM_SID global_sid_NT_Authority = /* NT Authority */ +{ 1, 0, {0,0,0,0,0,5}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}; +const DOM_SID global_sid_System = /* System */ +{ 1, 1, {0,0,0,0,0,5}, {18,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}; +const DOM_SID global_sid_NULL = /* NULL sid */ +{ 1, 1, {0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}; +const DOM_SID global_sid_Authenticated_Users = /* All authenticated rids */ +{ 1, 1, {0,0,0,0,0,5}, {11,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}; +const DOM_SID global_sid_Network = /* Network rids */ +{ 1, 1, {0,0,0,0,0,5}, {2,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}; + +const DOM_SID global_sid_Creator_Owner = /* Creator Owner */ +{ 1, 1, {0,0,0,0,0,3}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}; +const DOM_SID global_sid_Creator_Group = /* Creator Group */ +{ 1, 1, {0,0,0,0,0,3}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}; +const DOM_SID global_sid_Anonymous = /* Anonymous login */ +{ 1, 1, {0,0,0,0,0,5}, {7,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}; + +const DOM_SID global_sid_Builtin = /* Local well-known domain */ +{ 1, 1, {0,0,0,0,0,5}, {32,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}; +const DOM_SID global_sid_Builtin_Administrators = /* Builtin administrators */ +{ 1, 2, {0,0,0,0,0,5}, {32,544,0,0,0,0,0,0,0,0,0,0,0,0,0}}; +const DOM_SID global_sid_Builtin_Users = /* Builtin users */ +{ 1, 2, {0,0,0,0,0,5}, {32,545,0,0,0,0,0,0,0,0,0,0,0,0,0}}; +const DOM_SID global_sid_Builtin_Guests = /* Builtin guest users */ +{ 1, 2, {0,0,0,0,0,5}, {32,546,0,0,0,0,0,0,0,0,0,0,0,0,0}}; +const DOM_SID global_sid_Builtin_Power_Users = /* Builtin power users */ +{ 1, 2, {0,0,0,0,0,5}, {32,547,0,0,0,0,0,0,0,0,0,0,0,0,0}}; +const DOM_SID global_sid_Builtin_Account_Operators = /* Builtin account operators */ +{ 1, 2, {0,0,0,0,0,5}, {32,548,0,0,0,0,0,0,0,0,0,0,0,0,0}}; +const DOM_SID global_sid_Builtin_Server_Operators = /* Builtin server operators */ +{ 1, 2, {0,0,0,0,0,5}, {32,549,0,0,0,0,0,0,0,0,0,0,0,0,0}}; +const DOM_SID global_sid_Builtin_Print_Operators = /* Builtin print operators */ +{ 1, 2, {0,0,0,0,0,5}, {32,550,0,0,0,0,0,0,0,0,0,0,0,0,0}}; +const DOM_SID global_sid_Builtin_Backup_Operators = /* Builtin backup operators */ +{ 1, 2, {0,0,0,0,0,5}, {32,551,0,0,0,0,0,0,0,0,0,0,0,0,0}}; +const DOM_SID global_sid_Builtin_Replicator = /* Builtin replicator */ +{ 1, 2, {0,0,0,0,0,5}, {32,552,0,0,0,0,0,0,0,0,0,0,0,0,0}}; #define SECURITY_NULL_SID_AUTHORITY 0 #define SECURITY_WORLD_SID_AUTHORITY 1 @@ -62,18 +84,15 @@ DOM_SID global_sid_Builtin_Replicator; /* Builtin replicator */ * An NT compatible anonymous token. */ -static DOM_SID anon_sid_array[3]; - -NT_USER_TOKEN anonymous_token = { - 3, - anon_sid_array -}; +static DOM_SID anon_sid_array[3] = +{ { 1, 1, {0,0,0,0,0,1}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}, + { 1, 1, {0,0,0,0,0,5}, {2,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}, + { 1, 1, {0,0,0,0,0,5}, {7,0,0,0,0,0,0,0,0,0,0,0,0,0,0}} }; +NT_USER_TOKEN anonymous_token = { 3, anon_sid_array, SE_NONE }; -static DOM_SID system_sid_array[4]; -NT_USER_TOKEN system_token = { - 1, - system_sid_array -}; +static DOM_SID system_sid_array[1] = +{ { 1, 1, {0,0,0,0,0,5}, {18,0,0,0,0,0,0,0,0,0,0,0,0,0,0}} }; +NT_USER_TOKEN system_token = { 1, system_sid_array, SE_ALL_PRIVS }; /**************************************************************************** Lookup string names for SID types. @@ -111,66 +130,12 @@ const char *sid_type_lookup(uint32 sid_type) return "SID *TYPE* is INVALID"; } -/**************************************************************************** - Creates some useful well known sids -****************************************************************************/ - -void generate_wellknown_sids(void) -{ - static BOOL initialised = False; - - if (initialised) - return; - - /* SECURITY_NULL_SID_AUTHORITY */ - string_to_sid(&global_sid_NULL, "S-1-0-0"); - - /* SECURITY_WORLD_SID_AUTHORITY */ - string_to_sid(&global_sid_World_Domain, "S-1-1"); - string_to_sid(&global_sid_World, "S-1-1-0"); - - /* SECURITY_CREATOR_SID_AUTHORITY */ - string_to_sid(&global_sid_Creator_Owner_Domain, "S-1-3"); - string_to_sid(&global_sid_Creator_Owner, "S-1-3-0"); - string_to_sid(&global_sid_Creator_Group, "S-1-3-1"); - - /* SECURITY_NT_AUTHORITY */ - string_to_sid(&global_sid_NT_Authority, "S-1-5"); - string_to_sid(&global_sid_Network, "S-1-5-2"); - string_to_sid(&global_sid_Anonymous, "S-1-5-7"); - string_to_sid(&global_sid_Authenticated_Users, "S-1-5-11"); - string_to_sid(&global_sid_System, "S-1-5-18"); - - /* SECURITY_BUILTIN_DOMAIN_RID */ - string_to_sid(&global_sid_Builtin, "S-1-5-32"); - string_to_sid(&global_sid_Builtin_Administrators, "S-1-5-32-544"); - string_to_sid(&global_sid_Builtin_Users, "S-1-5-32-545"); - string_to_sid(&global_sid_Builtin_Guests, "S-1-5-32-546"); - string_to_sid(&global_sid_Builtin_Power_Users, "S-1-5-32-547"); - string_to_sid(&global_sid_Builtin_Account_Operators, "S-1-5-32-548"); - string_to_sid(&global_sid_Builtin_Server_Operators, "S-1-5-32-549"); - string_to_sid(&global_sid_Builtin_Print_Operators, "S-1-5-32-550"); - string_to_sid(&global_sid_Builtin_Backup_Operators, "S-1-5-32-551"); - string_to_sid(&global_sid_Builtin_Replicator, "S-1-5-32-552"); - - /* Create the anon token. */ - sid_copy( &anonymous_token.user_sids[0], &global_sid_World); - sid_copy( &anonymous_token.user_sids[1], &global_sid_Network); - sid_copy( &anonymous_token.user_sids[2], &global_sid_Anonymous); - - /* Create the system token. */ - sid_copy( &system_token.user_sids[0], &global_sid_System); - - initialised = True; -} - /************************************************************************** Create the SYSTEM token. ***************************************************************************/ NT_USER_TOKEN *get_system_token(void) { - generate_wellknown_sids(); /* The token is initialised here */ return &system_token; } @@ -351,6 +316,19 @@ BOOL string_to_sid(DOM_SID *sidout, const char *sidstr) return True; } +DOM_SID *string_sid_talloc(TALLOC_CTX *mem_ctx, const char *sidstr) +{ + DOM_SID *result = TALLOC_P(mem_ctx, DOM_SID); + + if (result == NULL) + return NULL; + + if (!string_to_sid(result, sidstr)) + return NULL; + + return result; +} + /***************************************************************** Add a rid to the end of a sid *****************************************************************/ @@ -652,9 +630,14 @@ DOM_SID *sid_dup_talloc(TALLOC_CTX *ctx, const DOM_SID *src) Add SID to an array SIDs ********************************************************************/ -void add_sid_to_array(const DOM_SID *sid, DOM_SID **sids, int *num) +void add_sid_to_array(TALLOC_CTX *mem_ctx, const DOM_SID *sid, + DOM_SID **sids, int *num) { - *sids = SMB_REALLOC_ARRAY(*sids, DOM_SID, (*num)+1); + if (mem_ctx != NULL) + *sids = TALLOC_REALLOC_ARRAY(mem_ctx, *sids, DOM_SID, + (*num)+1); + else + *sids = SMB_REALLOC_ARRAY(*sids, DOM_SID, (*num)+1); if (*sids == NULL) return; @@ -670,7 +653,8 @@ void add_sid_to_array(const DOM_SID *sid, DOM_SID **sids, int *num) Add SID to an array SIDs ensuring that it is not already there ********************************************************************/ -void add_sid_to_array_unique(const DOM_SID *sid, DOM_SID **sids, int *num_sids) +void add_sid_to_array_unique(TALLOC_CTX *mem_ctx, const DOM_SID *sid, + DOM_SID **sids, int *num_sids) { int i; @@ -679,7 +663,7 @@ void add_sid_to_array_unique(const DOM_SID *sid, DOM_SID **sids, int *num_sids) return; } - add_sid_to_array(sid, sids, num_sids); + add_sid_to_array(mem_ctx, sid, sids, num_sids); } /******************************************************************** diff --git a/source/lib/util_smbd.c b/source/lib/util_smbd.c index 586362c1e4c..c6f6bc0a32a 100644 --- a/source/lib/util_smbd.c +++ b/source/lib/util_smbd.c @@ -73,10 +73,10 @@ BOOL getgroups_user(const char *user, gid_t primary_gid, gid_t **ret_groups, int groups = NULL; /* Add in primary group first */ - add_gid_to_array_unique(primary_gid, &groups, &ngrp); + add_gid_to_array_unique(NULL, primary_gid, &groups, &ngrp); for (i=0; ibuffer, maxlen, str->uni_str_len*2, STR_NOALIGN); } +/******************************************************************* + Convert a (little-endian) UNISTR3 structure to an ASCII string +********************************************************************/ +void unistr3_to_ascii(char *dest, const UNISTR3 *str, size_t maxlen) +{ + if (str == NULL) { + *dest='\0'; + return; + } + pull_ucs2(NULL, dest, str->str.buffer, maxlen, str->uni_str_len*2, + STR_NOALIGN); +} + /******************************************************************* give a static string for displaying a UNISTR2 ********************************************************************/ @@ -310,18 +323,6 @@ char *unistr2_tdup(TALLOC_CTX *ctx, const UNISTR2 *str) } -/******************************************************************* -Return a number stored in a buffer -********************************************************************/ - -uint32 buffer2_to_uint32(BUFFER2 *str) -{ - if (str->buf_len == 4) - return IVAL(str->buffer, 0); - else - return 0; -} - /******************************************************************* Convert a wchar to upper case. ********************************************************************/ @@ -397,10 +398,10 @@ size_t strnlen_w(const smb_ucs2_t *src, size_t max) smb_ucs2_t *strchr_w(const smb_ucs2_t *s, smb_ucs2_t c) { while (*s != 0) { - if (c == *s) return (smb_ucs2_t *)s; + if (c == *s) return CONST_DISCARD(smb_ucs2_t *, s); s++; } - if (c == *s) return (smb_ucs2_t *)s; + if (c == *s) return CONST_DISCARD(smb_ucs2_t *, s); return NULL; } @@ -421,7 +422,7 @@ smb_ucs2_t *strrchr_w(const smb_ucs2_t *s, smb_ucs2_t c) if (len == 0) return NULL; p += (len - 1); do { - if (c == *p) return (smb_ucs2_t *)p; + if (c == *p) return CONST_DISCARD(smb_ucs2_t *, p); } while (p-- != s); return NULL; } @@ -442,7 +443,7 @@ smb_ucs2_t *strnrchr_w(const smb_ucs2_t *s, smb_ucs2_t c, unsigned int n) n--; if (!n) - return (smb_ucs2_t *)p; + return CONST_DISCARD(smb_ucs2_t *, p); } while (p-- != s); return NULL; } @@ -460,7 +461,7 @@ smb_ucs2_t *strstr_w(const smb_ucs2_t *s, const smb_ucs2_t *ins) return NULL; inslen = strlen_w(ins); - r = (smb_ucs2_t *)s; + r = CONST_DISCARD(smb_ucs2_t *, s); while ((r = strchr_w(r, *ins))) { if (strncmp_w(r, ins, inslen) == 0) @@ -731,7 +732,7 @@ smb_ucs2_t *strpbrk_wa(const smb_ucs2_t *s, const char *p) int i; for (i=0; p[i] && *s != UCS2_CHAR(p[i]); i++) ; - if (p[i]) return (smb_ucs2_t *)s; + if (p[i]) return CONST_DISCARD(smb_ucs2_t *, s); s++; } return NULL; @@ -746,7 +747,7 @@ smb_ucs2_t *strstr_wa(const smb_ucs2_t *s, const char *ins) return NULL; inslen = strlen(ins); - r = (smb_ucs2_t *)s; + r = CONST_DISCARD(smb_ucs2_t *, s); while ((r = strchr_w(r, UCS2_CHAR(*ins)))) { if (strncmp_wa(r, ins, inslen) == 0) diff --git a/source/lib/util_uuid.c b/source/lib/util_uuid.c index df70740b33c..8b8e70a36ef 100644 --- a/source/lib/util_uuid.c +++ b/source/lib/util_uuid.c @@ -94,7 +94,7 @@ BOOL smb_string_to_uuid(const char *in, struct uuid* uu) { BOOL ret = False; const char *ptr = in; - char *end = (char *)in; + char *end = CONST_DISCARD(char *, in); int i; unsigned v1, v2; diff --git a/source/lib/wins_srv.c b/source/lib/wins_srv.c index b82e04e13cc..c139f427ca8 100644 --- a/source/lib/wins_srv.c +++ b/source/lib/wins_srv.c @@ -22,6 +22,8 @@ #include "includes.h" +extern struct in_addr loopback_ip; + /* This is pretty much a complete rewrite of the earlier code. The main aim of the rewrite is to add support for having multiple wins server @@ -280,7 +282,6 @@ struct in_addr wins_srv_ip_tag(const char *tag, struct in_addr src_ip) /* if we are a wins server then we always just talk to ourselves */ if (lp_wins_support()) { - extern struct in_addr loopback_ip; return loopback_ip; } diff --git a/source/libads/kerberos.c b/source/libads/kerberos.c index 4c9997e080e..18820d9e312 100644 --- a/source/libads/kerberos.c +++ b/source/libads/kerberos.c @@ -88,7 +88,8 @@ int kerberos_kinit_password(const char *principal, return code; } - if ((code = krb5_get_init_creds_password(ctx, &my_creds, me, password, + if ((code = krb5_get_init_creds_password(ctx, &my_creds, me, + CONST_DISCARD(char *, password), kerb_prompter, NULL, 0, NULL, NULL))) { krb5_free_principal(ctx, me); diff --git a/source/libads/ldap.c b/source/libads/ldap.c index 6e1b011c37c..7a59da5a6d3 100644 --- a/source/libads/ldap.c +++ b/source/libads/ldap.c @@ -481,15 +481,15 @@ ADS_STATUS ads_do_paged_search(ADS_STRUCT *ads, const char *bind_path, ber_printf(cookie_be, "{io}", (ber_int_t) 1000, "", 0); } ber_flatten(cookie_be, &cookie_bv); - PagedResults.ldctl_oid = ADS_PAGE_CTL_OID; + PagedResults.ldctl_oid = CONST_DISCARD(char *, ADS_PAGE_CTL_OID); PagedResults.ldctl_iscritical = (char) 1; PagedResults.ldctl_value.bv_len = cookie_bv->bv_len; PagedResults.ldctl_value.bv_val = cookie_bv->bv_val; - NoReferrals.ldctl_oid = ADS_NO_REFERRALS_OID; + NoReferrals.ldctl_oid = CONST_DISCARD(char *, ADS_NO_REFERRALS_OID); NoReferrals.ldctl_iscritical = (char) 0; NoReferrals.ldctl_value.bv_len = 0; - NoReferrals.ldctl_value.bv_val = ""; + NoReferrals.ldctl_value.bv_val = CONST_DISCARD(char *, ""); controls[0] = &NoReferrals; @@ -831,7 +831,7 @@ ADS_MODLIST ads_init_mods(TALLOC_CTX *ctx) need to reset it to NULL before doing ldap modify */ mods[ADS_MODLIST_ALLOC_SIZE] = (LDAPMod *) -1; - return mods; + return (ADS_MODLIST)mods; } @@ -868,7 +868,7 @@ static ADS_STATUS ads_modlist_add(TALLOC_CTX *ctx, ADS_MODLIST *mods, memset(&modlist[curmod], 0, ADS_MODLIST_ALLOC_SIZE*sizeof(LDAPMod *)); modlist[curmod+ADS_MODLIST_ALLOC_SIZE] = (LDAPMod *) -1; - *mods = modlist; + *mods = (ADS_MODLIST)modlist; } if (!(modlist[curmod] = TALLOC_ZERO_P(ctx, LDAPMod))) @@ -962,7 +962,7 @@ ADS_STATUS ads_gen_mod(ADS_STRUCT *ads, const char *mod_dn, ADS_MODLIST mods) non-existent attribute (but allowable for the object) to run */ LDAPControl PermitModify = { - ADS_PERMIT_MODIFY_OID, + CONST_DISCARD(char *, ADS_PERMIT_MODIFY_OID), {0, NULL}, (char) 1}; LDAPControl *controls[2]; @@ -1006,7 +1006,7 @@ ADS_STATUS ads_gen_add(ADS_STRUCT *ads, const char *new_dn, ADS_MODLIST mods) /* make sure the end of the list is NULL */ mods[i] = NULL; - ret = ldap_add_s(ads->ld, utf8_dn, mods); + ret = ldap_add_s(ads->ld, utf8_dn, (LDAPMod**)mods); SAFE_FREE(utf8_dn); return ADS_ERROR(ret); } @@ -1267,7 +1267,7 @@ ADS_STATUS ads_add_service_principal_name(ADS_STRUCT *ads, const char *machine_n ADS_STATUS ret; TALLOC_CTX *ctx; LDAPMessage *res = NULL; - char *host_spn, *host_upn, *psp1, *psp2, *psp3; + char *host_spn, *psp1, *psp2, *psp3; ADS_MODLIST mods; fstring my_fqdn; char *dn_string = NULL; @@ -1297,11 +1297,6 @@ ADS_STATUS ads_add_service_principal_name(ADS_STRUCT *ads, const char *machine_n ads_msgfree(ads, res); return ADS_ERROR(LDAP_NO_SUCH_OBJECT); } - if (!(host_upn = talloc_asprintf(ctx, "%s@%s", host_spn, ads->config.realm))) { - talloc_destroy(ctx); - ads_msgfree(ads, res); - return ADS_ERROR(LDAP_NO_SUCH_OBJECT); - } /* Add the extra principal */ psp1 = talloc_asprintf(ctx, "%s/%s", spn, machine_name); diff --git a/source/libads/ldap_printer.c b/source/libads/ldap_printer.c index 68e67358910..61275e40d11 100644 --- a/source/libads/ldap_printer.c +++ b/source/libads/ldap_printer.c @@ -61,8 +61,10 @@ ADS_STATUS ads_find_printers(ADS_STRUCT *ads, void **res) /* For the moment only display all printers */ - ldap_expr = "(&(!(showInAdvancedViewOnly=TRUE))(uncName=*)" - "(objectCategory=printQueue))"; + ldap_expr = + CONST_DISCARD(char *, + "(&(!(showInAdvancedViewOnly=TRUE))(uncName=*)" + "(objectCategory=printQueue))"); return ads_search(ads, res, ldap_expr, attrs); } diff --git a/source/libads/sasl.c b/source/libads/sasl.c index 97ba9c92862..e657f2114e6 100644 --- a/source/libads/sasl.c +++ b/source/libads/sasl.c @@ -18,6 +18,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#define KRB5_PRIVATE 1 /* this file uses PRIVATE interfaces! */ + #include "includes.h" #ifdef HAVE_LDAP @@ -173,7 +175,9 @@ static ADS_STATUS ads_sasl_spnego_bind(ADS_STRUCT *ads) DATA_BLOB blob; char *principal = NULL; char *OIDs[ASN1_MAX_OIDS]; +#ifdef HAVE_KRB5 BOOL got_kerberos_mechanism = False; +#endif rc = ldap_sasl_bind_s(ads->ld, NULL, "GSS-SPNEGO", NULL, NULL, NULL, &scred); @@ -202,10 +206,12 @@ static ADS_STATUS ads_sasl_spnego_bind(ADS_STRUCT *ads) /* make sure the server understands kerberos */ for (i=0;OIDs[i];i++) { DEBUG(3,("ads_sasl_spnego_bind: got OID=%s\n", OIDs[i])); +#ifdef HAVE_KRB5 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 || strcmp(OIDs[i], OID_KERBEROS5) == 0) { got_kerberos_mechanism = True; } +#endif free(OIDs[i]); } DEBUG(3,("ads_sasl_spnego_bind: got server principal name =%s\n", principal)); @@ -281,7 +287,8 @@ static ADS_STATUS ads_sasl_gssapi_bind(ADS_STRUCT *ads) ENCTYPE_DES_CBC_MD5, ENCTYPE_NULL}; gss_OID_desc nt_principal = - {10, "\052\206\110\206\367\022\001\002\002\002"}; + {10, CONST_DISCARD(char *, + "\052\206\110\206\367\022\001\002\002\002")}; /* we need to fetch a service ticket as the ldap user in the servers realm, regardless of our realm */ diff --git a/source/libsmb/cliconnect.c b/source/libsmb/cliconnect.c index dce51a2c8bb..5a9992d4e03 100644 --- a/source/libsmb/cliconnect.c +++ b/source/libsmb/cliconnect.c @@ -23,6 +23,7 @@ #include "includes.h" +extern pstring user_socket_options; static const struct { int prot; @@ -702,7 +703,9 @@ ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user, char *principal; char *OIDs[ASN1_MAX_OIDS]; int i; +#ifdef HAVE_KRB5 BOOL got_kerberos_mechanism = False; +#endif DATA_BLOB blob; DEBUG(3,("Doing spnego session setup (blob length=%lu)\n", (unsigned long)cli->secblob.length)); @@ -731,10 +734,12 @@ ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user, /* make sure the server understands kerberos */ for (i=0;OIDs[i];i++) { DEBUG(3,("got OID=%s\n", OIDs[i])); +#ifdef HAVE_KRB5 if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 || strcmp(OIDs[i], OID_KERBEROS5) == 0) { got_kerberos_mechanism = True; } +#endif free(OIDs[i]); } DEBUG(3,("got principal=%s\n", principal)); @@ -1196,7 +1201,6 @@ BOOL cli_session_request(struct cli_state *cli, { char *p; int len = 4; - extern pstring user_socket_options; memcpy(&(cli->calling), calling, sizeof(*calling)); memcpy(&(cli->called ), called , sizeof(*called )); @@ -1286,7 +1290,6 @@ BOOL cli_session_request(struct cli_state *cli, BOOL cli_connect(struct cli_state *cli, const char *host, struct in_addr *ip) { - extern pstring user_socket_options; int name_type = 0x20; char *p; diff --git a/source/libsmb/clientgen.c b/source/libsmb/clientgen.c index b7bc780a1a1..e787650c2f5 100644 --- a/source/libsmb/clientgen.c +++ b/source/libsmb/clientgen.c @@ -22,6 +22,8 @@ #include "includes.h" +extern int smb_read_error; + /**************************************************************************** Change the timeout (in milliseconds). ****************************************************************************/ @@ -81,7 +83,6 @@ static BOOL client_receive_smb(int fd,char *buffer, unsigned int timeout) BOOL cli_receive_smb(struct cli_state *cli) { - extern int smb_read_error; BOOL ret; /* fd == -1 causes segfaults -- Tom (tom@ninja.nl) */ diff --git a/source/libsmb/clifile.c b/source/libsmb/clifile.c index 9d20ed3adcd..93492ec0822 100644 --- a/source/libsmb/clifile.c +++ b/source/libsmb/clifile.c @@ -1071,7 +1071,7 @@ BOOL cli_unlock64(struct cli_state *cli, int fnum, SMB_BIG_UINT offset, SMB_BIG_ ****************************************************************************/ BOOL cli_getattrE(struct cli_state *cli, int fd, - uint16 *attr, SMB_BIG_UINT *size, + uint16 *attr, SMB_OFF_T *size, time_t *c_time, time_t *a_time, time_t *m_time) { memset(cli->outbuf,'\0',smb_size); @@ -1122,7 +1122,7 @@ BOOL cli_getattrE(struct cli_state *cli, int fd, ****************************************************************************/ BOOL cli_getatr(struct cli_state *cli, const char *fname, - uint16 *attr, size_t *size, time_t *t) + uint16 *attr, SMB_OFF_T *size, time_t *t) { char *p; diff --git a/source/libsmb/clifsinfo.c b/source/libsmb/clifsinfo.c index 22c8bff3ba0..2874ee6ca1c 100644 --- a/source/libsmb/clifsinfo.c +++ b/source/libsmb/clifsinfo.c @@ -132,3 +132,118 @@ cleanup: return ret; } + +BOOL cli_get_fs_volume_info_old(struct cli_state *cli, fstring volume_name, uint32 *pserial_number) +{ + BOOL ret = False; + uint16 setup; + char param[2]; + char *rparam=NULL, *rdata=NULL; + unsigned int rparam_count=0, rdata_count=0; + unsigned char nlen; + + setup = TRANSACT2_QFSINFO; + + SSVAL(param,0,SMB_INFO_VOLUME); + + if (!cli_send_trans(cli, SMBtrans2, + NULL, + 0, 0, + &setup, 1, 0, + param, 2, 0, + NULL, 0, 560)) { + goto cleanup; + } + + if (!cli_receive_trans(cli, SMBtrans2, + &rparam, &rparam_count, + &rdata, &rdata_count)) { + goto cleanup; + } + + if (cli_is_error(cli)) { + ret = False; + goto cleanup; + } else { + ret = True; + } + + if (rdata_count < 5) { + goto cleanup; + } + + if (pserial_number) { + *pserial_number = IVAL(rdata,0); + } + nlen = CVAL(rdata,l2_vol_cch); + clistr_pull(cli, volume_name, rdata + l2_vol_szVolLabel, sizeof(fstring), nlen, STR_NOALIGN); + + /* todo: but not yet needed + * return the other stuff + */ + +cleanup: + SAFE_FREE(rparam); + SAFE_FREE(rdata); + + return ret; +} + +BOOL cli_get_fs_volume_info(struct cli_state *cli, fstring volume_name, uint32 *pserial_number, time_t *pdate) +{ + BOOL ret = False; + uint16 setup; + char param[2]; + char *rparam=NULL, *rdata=NULL; + unsigned int rparam_count=0, rdata_count=0; + unsigned int nlen; + + setup = TRANSACT2_QFSINFO; + + SSVAL(param,0,SMB_QUERY_FS_VOLUME_INFO); + + if (!cli_send_trans(cli, SMBtrans2, + NULL, + 0, 0, + &setup, 1, 0, + param, 2, 0, + NULL, 0, 560)) { + goto cleanup; + } + + if (!cli_receive_trans(cli, SMBtrans2, + &rparam, &rparam_count, + &rdata, &rdata_count)) { + goto cleanup; + } + + if (cli_is_error(cli)) { + ret = False; + goto cleanup; + } else { + ret = True; + } + + if (rdata_count < 19) { + goto cleanup; + } + + if (pdate) { + *pdate = interpret_long_date(rdata); + } + if (pserial_number) { + *pserial_number = IVAL(rdata,8); + } + nlen = IVAL(rdata,12); + clistr_pull(cli, volume_name, rdata + 18, sizeof(fstring), nlen, STR_UNICODE); + + /* todo: but not yet needed + * return the other stuff + */ + +cleanup: + SAFE_FREE(rparam); + SAFE_FREE(rdata); + + return ret; +} diff --git a/source/libsmb/clikrb5.c b/source/libsmb/clikrb5.c index 66c16b69aef..c35b53a9dd8 100644 --- a/source/libsmb/clikrb5.c +++ b/source/libsmb/clikrb5.c @@ -19,6 +19,9 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#define KRB5_PRIVATE 1 /* this file uses PRIVATE interfaces! */ +#define KRB5_DEPRECATED 1 /* this file uses DEPRECATED interfaces! */ + #include "includes.h" #ifdef HAVE_KRB5 diff --git a/source/libsmb/clilist.c b/source/libsmb/clilist.c index 0f1b9efed0e..79c2ef66a19 100644 --- a/source/libsmb/clilist.c +++ b/source/libsmb/clilist.c @@ -22,6 +22,8 @@ #include "includes.h" +extern file_info def_finfo; + /**************************************************************************** Interpret a long filename structure - this is mostly guesses at the moment. The length of the structure is returned @@ -32,7 +34,6 @@ static size_t interpret_long_filename(struct cli_state *cli, int level,char *p,file_info *finfo) { - extern file_info def_finfo; file_info finfo2; int len; char *base = p; @@ -332,7 +333,6 @@ int cli_list_new(struct cli_state *cli,const char *Mask,uint16 attribute, static int interpret_short_filename(struct cli_state *cli, char *p,file_info *finfo) { - extern file_info def_finfo; *finfo = def_finfo; diff --git a/source/libsmb/clirap.c b/source/libsmb/clirap.c index 8e6742d4380..06b683b0385 100644 --- a/source/libsmb/clirap.c +++ b/source/libsmb/clirap.c @@ -382,7 +382,7 @@ send a qpathinfo call ****************************************************************************/ BOOL cli_qpathinfo(struct cli_state *cli, const char *fname, time_t *c_time, time_t *a_time, time_t *m_time, - size_t *size, uint16 *mode) + SMB_OFF_T *size, uint16 *mode) { unsigned int data_len = 0; unsigned int param_len = 0; @@ -462,7 +462,7 @@ send a qpathinfo call with the SMB_QUERY_FILE_ALL_INFO info level ****************************************************************************/ BOOL cli_qpathinfo2(struct cli_state *cli, const char *fname, time_t *c_time, time_t *a_time, time_t *m_time, - time_t *w_time, size_t *size, uint16 *mode, + time_t *w_time, SMB_OFF_T *size, uint16 *mode, SMB_INO_T *ino) { unsigned int data_len = 0; @@ -501,22 +501,22 @@ BOOL cli_qpathinfo2(struct cli_state *cli, const char *fname, } if (c_time) { - *c_time = interpret_long_date(rdata+0) - cli->serverzone; + *c_time = interpret_long_date(rdata+0); } if (a_time) { - *a_time = interpret_long_date(rdata+8) - cli->serverzone; + *a_time = interpret_long_date(rdata+8); } if (m_time) { - *m_time = interpret_long_date(rdata+16) - cli->serverzone; + *m_time = interpret_long_date(rdata+16); } if (w_time) { - *w_time = interpret_long_date(rdata+24) - cli->serverzone; + *w_time = interpret_long_date(rdata+24); } if (mode) { *mode = SVAL(rdata, 32); } if (size) { - *size = IVAL(rdata, 48); + *size = IVAL2_TO_SMB_BIG_UINT(rdata,48); } if (ino) { *ino = IVAL(rdata, 64); @@ -546,11 +546,11 @@ BOOL cli_qfilename(struct cli_state *cli, int fnum, SSVAL(param, 2, SMB_QUERY_FILE_NAME_INFO); if (!cli_send_trans(cli, SMBtrans2, - NULL, /* name */ - -1, 0, /* fid, flags */ - &setup, 1, 0, /* setup, length, max */ - param, param_len, 2, /* param, length, max */ - NULL, data_len, cli->max_xmit /* data, length, max */ + NULL, /* name */ + -1, 0, /* fid, flags */ + &setup, 1, 0, /* setup, length, max */ + param, param_len, 2, /* param, length, max */ + NULL, data_len, cli->max_xmit /* data, length, max */ )) { return False; } @@ -575,7 +575,7 @@ BOOL cli_qfilename(struct cli_state *cli, int fnum, send a qfileinfo call ****************************************************************************/ BOOL cli_qfileinfo(struct cli_state *cli, int fnum, - uint16 *mode, size_t *size, + uint16 *mode, SMB_OFF_T *size, time_t *c_time, time_t *a_time, time_t *m_time, time_t *w_time, SMB_INO_T *ino) { @@ -596,11 +596,11 @@ BOOL cli_qfileinfo(struct cli_state *cli, int fnum, SSVAL(param, 2, SMB_QUERY_FILE_ALL_INFO); if (!cli_send_trans(cli, SMBtrans2, - NULL, /* name */ - -1, 0, /* fid, flags */ - &setup, 1, 0, /* setup, length, max */ - param, param_len, 2, /* param, length, max */ - NULL, data_len, cli->max_xmit /* data, length, max */ + NULL, /* name */ + -1, 0, /* fid, flags */ + &setup, 1, 0, /* setup, length, max */ + param, param_len, 2, /* param, length, max */ + NULL, data_len, cli->max_xmit /* data, length, max */ )) { return False; } @@ -631,7 +631,7 @@ BOOL cli_qfileinfo(struct cli_state *cli, int fnum, *mode = SVAL(rdata, 32); } if (size) { - *size = IVAL(rdata, 48); + *size = IVAL2_TO_SMB_BIG_UINT(rdata,48); } if (ino) { *ino = IVAL(rdata, 64); diff --git a/source/libsmb/clirap2.c b/source/libsmb/clirap2.c index 12a3d63aff3..d8a85195502 100644 --- a/source/libsmb/clirap2.c +++ b/source/libsmb/clirap2.c @@ -329,6 +329,70 @@ int cli_RNetGroupEnum(struct cli_state *cli, void (*fn)(const char *, const char return res; } +int cli_RNetGroupEnum0(struct cli_state *cli, + void (*fn)(const char *, void *), + void *state) +{ + char param[WORDSIZE /* api number */ + +sizeof(RAP_NetGroupEnum_REQ) /* parm string */ + +sizeof(RAP_GROUP_INFO_L0) /* return string */ + +WORDSIZE /* info level */ + +WORDSIZE]; /* buffer size */ + char *p; + char *rparam = NULL; + char *rdata = NULL; + unsigned int rprcnt, rdrcnt; + int res = -1; + + + memset(param, '\0', sizeof(param)); + p = make_header(param, RAP_WGroupEnum, + RAP_NetGroupEnum_REQ, RAP_GROUP_INFO_L0); + PUTWORD(p,0); /* Info level 0 */ /* Hmmm. I *very* much suspect this + is the resume count, at least + that's what smbd believes... */ + PUTWORD(p,0xFFE0); /* Return buffer size */ + + if (cli_api(cli, + param, PTR_DIFF(p,param),8, + NULL, 0, 0xFFE0 /* data area size */, + &rparam, &rprcnt, + &rdata, &rdrcnt)) { + res = GETRES(rparam); + cli->rap_error = res; + if(cli->rap_error == 234) + DEBUG(1,("Not all group names were returned (such as those longer than 21 characters)\n")); + else if (cli->rap_error != 0) { + DEBUG(1,("NetGroupEnum gave error %d\n", cli->rap_error)); + } + } + + if (rdata) { + if (res == 0 || res == ERRmoredata) { + int i, converter, count; + + p = rparam + WORDSIZE; /* skip result */ + GETWORD(p, converter); + GETWORD(p, count); + + for (i=0,p=rdata;irap_error = res; + if (cli->rap_error != 0) { + DEBUG(1,("NetUserEnum gave error %d\n", cli->rap_error)); + } + } + if (rdata) { + if (res == 0 || res == ERRmoredata) { + int i, converter, count; + char username[RAP_USERNAME_LEN]; + + p = rparam + WORDSIZE; /* skip result */ + GETWORD(p, converter); + GETWORD(p, count); + + for (i=0,p=rdata;iflags & SMBCCTX_FLAG_NO_AUTO_ANONYMOUS_LOGON) || - !cli_session_setup(&c, "", "", 1,"", 0, workgroup))) { - cli_shutdown(&c); - errno = EPERM; - return NULL; + workgroup)) { + + /* Failed. Try an anonymous login, if allowed by flags. */ + username_used = ""; + + if ((context->flags & SMBCCTX_FLAG_NO_AUTO_ANONYMOUS_LOGON) || + !cli_session_setup(&c, username_used, + password, 1, + password, 0, + workgroup)) { + + cli_shutdown(&c); + errno = EPERM; + return NULL; + } } DEBUG(4,(" session setup ok\n")); @@ -750,7 +764,7 @@ SMBCSRV *smbc_server(SMBCCTX *context, /* now add it to the cache (internal or external) */ /* Let the cache function set errno if it wants to */ errno = 0; - if (context->callbacks.add_cached_srv_fn(context, srv, server, share, workgroup, username)) { + if (context->callbacks.add_cached_srv_fn(context, srv, server, share, workgroup, username_used)) { int saved_errno = errno; DEBUG(3, (" Failed to add server to cache\n")); errno = saved_errno; @@ -968,6 +982,37 @@ static SMBCFILE *smbc_open_ctx(SMBCCTX *context, const char *fname, int flags, m file->file = True; DLIST_ADD(context->internal->_files, file); + + /* + * If the file was opened in O_APPEND mode, all write + * operations should be appended to the file. To do that, + * though, using this protocol, would require a getattrE() + * call for each and every write, to determine where the end + * of the file is. (There does not appear to be an append flag + * in the protocol.) Rather than add all of that overhead of + * retrieving the current end-of-file offset prior to each + * write operation, we'll assume that most append operations + * will continuously write, so we'll just set the offset to + * the end of the file now and hope that's adequate. + * + * Note to self: If this proves inadequate, and O_APPEND + * should, in some cases, be forced for each write, add a + * field in the context options structure, for + * "strict_append_mode" which would select between the current + * behavior (if FALSE) or issuing a getattrE() prior to each + * write and forcing the write to the end of the file (if + * TRUE). Adding that capability will likely require adding + * an "append" flag into the _SMBCFILE structure to track + * whether a file was opened in O_APPEND mode. -- djl + */ + if (flags & O_APPEND) { + if (smbc_lseek_ctx(context, file, 0, SEEK_END) < 0) { + (void) smbc_close_ctx(context, file); + errno = ENXIO; + return NULL; + } + } + return file; } @@ -1017,6 +1062,17 @@ static ssize_t smbc_read_ctx(SMBCCTX *context, SMBCFILE *file, void *buf, size_t { int ret; + /* + * offset: + * + * Compiler bug (possibly) -- gcc (GCC) 3.3.5 (Debian 1:3.3.5-2) -- + * appears to pass file->offset (which is type off_t) differently than + * a local variable of type off_t. Using local variable "offset" in + * the call to cli_read() instead of file->offset fixes a problem + * retrieving data at an offset greater than 4GB. + */ + off_t offset = file->offset; + if (!context || !context->internal || !context->internal->_initialized) { @@ -1043,7 +1099,7 @@ static ssize_t smbc_read_ctx(SMBCCTX *context, SMBCFILE *file, void *buf, size_t } - ret = cli_read(&file->srv->cli, file->cli_fd, buf, file->offset, count); + ret = cli_read(&file->srv->cli, file->cli_fd, buf, offset, count); if (ret < 0) { @@ -1067,6 +1123,7 @@ static ssize_t smbc_read_ctx(SMBCCTX *context, SMBCFILE *file, void *buf, size_t static ssize_t smbc_write_ctx(SMBCCTX *context, SMBCFILE *file, void *buf, size_t count) { int ret; + off_t offset = file->offset; /* See "offset" comment in smbc_read_ctx() */ if (!context || !context->internal || !context->internal->_initialized) { @@ -1092,7 +1149,7 @@ static ssize_t smbc_write_ctx(SMBCCTX *context, SMBCFILE *file, void *buf, size_ } - ret = cli_write(&file->srv->cli, file->cli_fd, 0, buf, file->offset, count); + ret = cli_write(&file->srv->cli, file->cli_fd, 0, buf, offset, count); if (ret <= 0) { @@ -1165,7 +1222,7 @@ static int smbc_close_ctx(SMBCCTX *context, SMBCFILE *file) * and if that fails, use getatr, as Win95 sometimes refuses qpathinfo */ static BOOL smbc_getatr(SMBCCTX * context, SMBCSRV *srv, char *path, - uint16 *mode, size_t *size, + uint16 *mode, SMB_OFF_T *size, time_t *c_time, time_t *a_time, time_t *m_time, SMB_INO_T *ino) { @@ -1272,7 +1329,7 @@ static int smbc_unlink_ctx(SMBCCTX *context, const char *fname) if (errno == EACCES) { /* Check if the file is a directory */ int saverr = errno; - size_t size = 0; + SMB_OFF_T size = 0; uint16 mode = 0; time_t m_time = 0, a_time = 0, c_time = 0; SMB_INO_T ino = 0; @@ -1396,7 +1453,7 @@ static int smbc_rename_ctx(SMBCCTX *ocontext, const char *oname, static off_t smbc_lseek_ctx(SMBCCTX *context, SMBCFILE *file, off_t offset, int whence) { - size_t size; + SMB_OFF_T size; if (!context || !context->internal || !context->internal->_initialized) { @@ -1482,7 +1539,8 @@ ino_t smbc_inode(SMBCCTX *context, const char *name) */ static -int smbc_setup_stat(SMBCCTX *context, struct stat *st, char *fname, size_t size, int mode) +int smbc_setup_stat(SMBCCTX *context, struct stat *st, char *fname, + SMB_OFF_T size, int mode) { st->st_mode = 0; @@ -1532,7 +1590,7 @@ static int smbc_stat_ctx(SMBCCTX *context, const char *fname, struct stat *st) fstring server, share, user, password, workgroup; pstring path; time_t m_time = 0, a_time = 0, c_time = 0; - size_t size = 0; + SMB_OFF_T size = 0; uint16 mode = 0; SMB_INO_T ino = 0; @@ -1602,7 +1660,7 @@ static int smbc_stat_ctx(SMBCCTX *context, const char *fname, struct stat *st) static int smbc_fstat_ctx(SMBCCTX *context, SMBCFILE *file, struct stat *st) { time_t c_time, a_time, m_time; - size_t size; + SMB_OFF_T size; uint16 mode; SMB_INO_T ino = 0; @@ -1629,15 +1687,12 @@ static int smbc_fstat_ctx(SMBCCTX *context, SMBCFILE *file, struct stat *st) if (!cli_qfileinfo(&file->srv->cli, file->cli_fd, &mode, &size, &c_time, &a_time, &m_time, NULL, &ino)) { - SMB_BIG_UINT b_size = size; if (!cli_getattrE(&file->srv->cli, file->cli_fd, - &mode, &b_size, &c_time, &a_time, &m_time)) { + &mode, &size, &c_time, &a_time, &m_time)) { errno = EINVAL; return -1; - } else - size = b_size; - + } } st->st_ino = ino; @@ -1960,7 +2015,7 @@ static SMBCFILE *smbc_opendir_ctx(SMBCCTX *context, const char *fname) } for (i = 0; i < count && i < max_lmb_count; i++) { - DEBUG(99, ("Found master browser %s\n", inet_ntoa(ip_list[i].ip))); + DEBUG(99, ("Found master browser %d of %d: %s\n", i+1, MAX(count, max_lmb_count), inet_ntoa(ip_list[i].ip))); cli = get_ipc_connect_master_ip(&ip_list[i], workgroup, &u_info); /* cli == NULL is the master browser refused to talk or @@ -1983,12 +2038,7 @@ static SMBCFILE *smbc_opendir_ctx(SMBCCTX *context, const char *fname) srv = smbc_server(context, server, "IPC$", workgroup, user, password); if (!srv) { - - if (dir) { - SAFE_FREE(dir->fname); - SAFE_FREE(dir); - } - return NULL; + continue; } dir->srv = srv; @@ -1999,13 +2049,7 @@ static SMBCFILE *smbc_opendir_ctx(SMBCCTX *context, const char *fname) if (!cli_NetServerEnum(&srv->cli, workgroup, SV_TYPE_DOMAIN_ENUM, list_unique_wg_fn, (void *)dir)) { - if (dir) { - SAFE_FREE(dir->fname); - SAFE_FREE(dir); - } - - return NULL; - + continue; } } } else { @@ -3233,7 +3277,7 @@ static DOS_ATTR_DESC *dos_attr_query(SMBCCTX *context, SMBCSRV *srv) { time_t m_time = 0, a_time = 0, c_time = 0; - size_t size = 0; + SMB_OFF_T size = 0; uint16 mode = 0; SMB_INO_T inode = 0; DOS_ATTR_DESC *ret; @@ -3245,7 +3289,8 @@ static DOS_ATTR_DESC *dos_attr_query(SMBCCTX *context, } /* Obtain the DOS attributes */ - if (!smbc_getatr(context, srv, filename, &mode, &size, + if (!smbc_getatr(context, srv, CONST_DISCARD(char *, filename), + &mode, &size, &c_time, &a_time, &m_time, &inode)) { errno = smbc_errno(context, &srv->cli); @@ -3314,42 +3359,124 @@ retrieve the acls for a file *******************************************************/ static int cacl_get(SMBCCTX *context, TALLOC_CTX *ctx, SMBCSRV *srv, struct cli_state *ipc_cli, POLICY_HND *pol, - char *filename, char *name, char *buf, int bufsize) + char *filename, char *attr_name, char *buf, int bufsize) { uint32 i; int n = 0; int n_used; BOOL all; BOOL all_nt; + BOOL all_nt_acls; BOOL all_dos; BOOL some_nt; BOOL some_dos; + BOOL exclude_nt_revision = False; + BOOL exclude_nt_owner = False; + BOOL exclude_nt_group = False; + BOOL exclude_nt_acl = False; + BOOL exclude_dos_mode = False; + BOOL exclude_dos_size = False; + BOOL exclude_dos_ctime = False; + BOOL exclude_dos_atime = False; + BOOL exclude_dos_mtime = False; + BOOL exclude_dos_inode = False; BOOL numeric = True; BOOL determine_size = (bufsize == 0); int fnum = -1; SEC_DESC *sd; fstring sidstr; + fstring name_sandbox; + char *name; + char *pExclude; char *p; time_t m_time = 0, a_time = 0, c_time = 0; - size_t size = 0; + SMB_OFF_T size = 0; uint16 mode = 0; SMB_INO_T ino = 0; struct cli_state *cli = &srv->cli; + /* Copy name so we can strip off exclusions (if any are specified) */ + strncpy(name_sandbox, attr_name, sizeof(name_sandbox) - 1); + + /* Ensure name is null terminated */ + name_sandbox[sizeof(name_sandbox) - 1] = '\0'; + + /* Play in the sandbox */ + name = name_sandbox; + + /* If there are any exclusions, point to them and mask them from name */ + if ((pExclude = strchr(name, '!')) != NULL) + { + *pExclude++ = '\0'; + } + all = (StrnCaseCmp(name, "system.*", 8) == 0); all_nt = (StrnCaseCmp(name, "system.nt_sec_desc.*", 20) == 0); + all_nt_acls = (StrnCaseCmp(name, "system.nt_sec_desc.acl.*", 24) == 0); all_dos = (StrnCaseCmp(name, "system.dos_attr.*", 17) == 0); some_nt = (StrnCaseCmp(name, "system.nt_sec_desc.", 19) == 0); some_dos = (StrnCaseCmp(name, "system.dos_attr.", 16) == 0); numeric = (* (name + strlen(name) - 1) != '+'); + /* Look for exclusions from "all" requests */ + if (all || all_nt || all_dos) { + + /* Exclusions are delimited by '!' */ + for (; pExclude != NULL; pExclude = (p == NULL ? NULL : p + 1)) { + + /* Find end of this exclusion name */ + if ((p = strchr(pExclude, '!')) != NULL) + { + *p = '\0'; + } + + /* Which exclusion name is this? */ + if (StrCaseCmp(pExclude, "nt_sec_desc.revision") == 0) { + exclude_nt_revision = True; + } + else if (StrCaseCmp(pExclude, "nt_sec_desc.owner") == 0) { + exclude_nt_owner = True; + } + else if (StrCaseCmp(pExclude, "nt_sec_desc.group") == 0) { + exclude_nt_group = True; + } + else if (StrCaseCmp(pExclude, "nt_sec_desc.acl") == 0) { + exclude_nt_acl = True; + } + else if (StrCaseCmp(pExclude, "dos_attr.mode") == 0) { + exclude_dos_mode = True; + } + else if (StrCaseCmp(pExclude, "dos_attr.size") == 0) { + exclude_dos_size = True; + } + else if (StrCaseCmp(pExclude, "dos_attr.c_time") == 0) { + exclude_dos_ctime = True; + } + else if (StrCaseCmp(pExclude, "dos_attr.a_time") == 0) { + exclude_dos_atime = True; + } + else if (StrCaseCmp(pExclude, "dos_attr.m_time") == 0) { + exclude_dos_mtime = True; + } + else if (StrCaseCmp(pExclude, "dos_attr.inode") == 0) { + exclude_dos_inode = True; + } + else { + DEBUG(5, ("cacl_get received unknown exclusion: %s\n", + pExclude)); + errno = ENOATTR; + return -1; + } + } + } + n_used = 0; /* * If we are (possibly) talking to an NT or new system and some NT * attributes have been requested... */ - if (ipc_cli && (all || some_nt)) { + if (ipc_cli && (all || some_nt || all_nt_acls)) { /* Point to the portion after "system.nt_sec_desc." */ name += 19; /* if (all) this will be invalid but unused */ @@ -3374,139 +3501,105 @@ static int cacl_get(SMBCCTX *context, TALLOC_CTX *ctx, SMBCSRV *srv, cli_close(cli, fnum); - if (all || all_nt) { - if (determine_size) { - p = talloc_asprintf(ctx, - "REVISION:%d", - sd->revision); - if (!p) { - errno = ENOMEM; - return -1; + if (! exclude_nt_revision) { + if (all || all_nt) { + if (determine_size) { + p = talloc_asprintf(ctx, + "REVISION:%d", + sd->revision); + if (!p) { + errno = ENOMEM; + return -1; + } + n = strlen(p); + } else { + n = snprintf(buf, bufsize, + "REVISION:%d", sd->revision); } - n = strlen(p); - } else { - n = snprintf(buf, bufsize, - "REVISION:%d", sd->revision); - } - } else if (StrCaseCmp(name, "revision") == 0) { - if (determine_size) { - p = talloc_asprintf(ctx, "%d", sd->revision); - if (!p) { - errno = ENOMEM; - return -1; + } else if (StrCaseCmp(name, "revision") == 0) { + if (determine_size) { + p = talloc_asprintf(ctx, "%d", + sd->revision); + if (!p) { + errno = ENOMEM; + return -1; + } + n = strlen(p); + } else { + n = snprintf(buf, bufsize, "%d", + sd->revision); } - n = strlen(p); - } else { - n = snprintf(buf, bufsize, "%d", sd->revision); } - } - if (!determine_size && n > bufsize) { - errno = ERANGE; - return -1; - } - buf += n; - n_used += n; - bufsize -= n; - - /* Get owner and group sid */ - - if (sd->owner_sid) { - convert_sid_to_string(ipc_cli, pol, - sidstr, numeric, sd->owner_sid); - } else { - fstrcpy(sidstr, ""); + if (!determine_size && n > bufsize) { + errno = ERANGE; + return -1; + } + buf += n; + n_used += n; + bufsize -= n; } - if (all || all_nt) { - if (determine_size) { - p = talloc_asprintf(ctx, ",OWNER:%s", sidstr); - if (!p) { - errno = ENOMEM; - return -1; - } - n = strlen(p); - } else { - n = snprintf(buf, bufsize, - ",OWNER:%s", sidstr); - } - } else if (StrnCaseCmp(name, "owner", 5) == 0) { - if (determine_size) { - p = talloc_asprintf(ctx, "%s", sidstr); - if (!p) { - errno = ENOMEM; - return -1; - } - n = strlen(p); + if (! exclude_nt_owner) { + /* Get owner and group sid */ + if (sd->owner_sid) { + convert_sid_to_string(ipc_cli, pol, + sidstr, + numeric, + sd->owner_sid); } else { - n = snprintf(buf, bufsize, "%s", sidstr); + fstrcpy(sidstr, ""); } - } - - if (!determine_size && n > bufsize) { - errno = ERANGE; - return -1; - } - buf += n; - n_used += n; - bufsize -= n; - if (sd->grp_sid) { - convert_sid_to_string(ipc_cli, pol, - sidstr, numeric, sd->grp_sid); - } else { - fstrcpy(sidstr, ""); - } - - if (all || all_nt) { - if (determine_size) { - p = talloc_asprintf(ctx, ",GROUP:%s", sidstr); - if (!p) { - errno = ENOMEM; - return -1; + if (all || all_nt) { + if (determine_size) { + p = talloc_asprintf(ctx, ",OWNER:%s", + sidstr); + if (!p) { + errno = ENOMEM; + return -1; + } + n = strlen(p); + } else { + n = snprintf(buf, bufsize, + ",OWNER:%s", sidstr); } - n = strlen(p); - } else { - n = snprintf(buf, bufsize, - ",GROUP:%s", sidstr); - } - } else if (StrnCaseCmp(name, "group", 5) == 0) { - if (determine_size) { - p = talloc_asprintf(ctx, "%s", sidstr); - if (!p) { - errno = ENOMEM; - return -1; + } else if (StrnCaseCmp(name, "owner", 5) == 0) { + if (determine_size) { + p = talloc_asprintf(ctx, "%s", sidstr); + if (!p) { + errno = ENOMEM; + return -1; + } + n = strlen(p); + } else { + n = snprintf(buf, bufsize, "%s", + sidstr); } - n = strlen(p); - } else { - n = snprintf(buf, bufsize, "%s", sidstr); } - } - if (!determine_size && n > bufsize) { - errno = ERANGE; - return -1; + if (!determine_size && n > bufsize) { + errno = ERANGE; + return -1; + } + buf += n; + n_used += n; + bufsize -= n; } - buf += n; - n_used += n; - bufsize -= n; - - /* Add aces to value buffer */ - for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) { - SEC_ACE *ace = &sd->dacl->ace[i]; - convert_sid_to_string(ipc_cli, pol, - sidstr, numeric, &ace->trustee); + if (! exclude_nt_group) { + if (sd->grp_sid) { + convert_sid_to_string(ipc_cli, pol, + sidstr, numeric, + sd->grp_sid); + } else { + fstrcpy(sidstr, ""); + } if (all || all_nt) { if (determine_size) { - p = talloc_asprintf(ctx, - ",ACL:" - "%s:%d/%d/0x%08x", - sidstr, - ace->type, - ace->flags, - ace->info.mask); + p = talloc_asprintf(ctx, ",GROUP:%s", + sidstr); if (!p) { errno = ENOMEM; return -1; @@ -3514,36 +3607,22 @@ static int cacl_get(SMBCCTX *context, TALLOC_CTX *ctx, SMBCSRV *srv, n = strlen(p); } else { n = snprintf(buf, bufsize, - ",ACL:%s:%d/%d/0x%08x", - sidstr, - ace->type, - ace->flags, - ace->info.mask); + ",GROUP:%s", sidstr); } - } else if ((StrnCaseCmp(name, "acl", 3) == 0 && - StrCaseCmp(name + 3, sidstr) == 0) || - (StrnCaseCmp(name, "acl+", 4) == 0 && - StrCaseCmp(name + 4, sidstr) == 0)) { + } else if (StrnCaseCmp(name, "group", 5) == 0) { if (determine_size) { - p = talloc_asprintf(ctx, - "%d/%d/0x%08x", - ace->type, - ace->flags, - ace->info.mask); + p = talloc_asprintf(ctx, "%s", sidstr); if (!p) { errno = ENOMEM; return -1; } n = strlen(p); } else { - n = snprintf(buf, bufsize, - "%d/%d/0x%08x", - ace->type, - ace->flags, - ace->info.mask); + n = snprintf(buf, bufsize, "%s", sidstr); } } - if (n > bufsize) { + + if (!determine_size && n > bufsize) { errno = ERANGE; return -1; } @@ -3552,6 +3631,97 @@ static int cacl_get(SMBCCTX *context, TALLOC_CTX *ctx, SMBCSRV *srv, bufsize -= n; } + if (! exclude_nt_acl) { + /* Add aces to value buffer */ + for (i = 0; sd->dacl && i < sd->dacl->num_aces; i++) { + + SEC_ACE *ace = &sd->dacl->ace[i]; + convert_sid_to_string(ipc_cli, pol, + sidstr, numeric, + &ace->trustee); + + if (all || all_nt) { + if (determine_size) { + p = talloc_asprintf( + ctx, + ",ACL:" + "%s:%d/%d/0x%08x", + sidstr, + ace->type, + ace->flags, + ace->info.mask); + if (!p) { + errno = ENOMEM; + return -1; + } + n = strlen(p); + } else { + n = snprintf( + buf, bufsize, + ",ACL:%s:%d/%d/0x%08x", + sidstr, + ace->type, + ace->flags, + ace->info.mask); + } + } else if ((StrnCaseCmp(name, "acl", 3) == 0 && + StrCaseCmp(name + 3, sidstr) == 0) || + (StrnCaseCmp(name, "acl+", 4) == 0 && + StrCaseCmp(name + 4, sidstr) == 0)) { + if (determine_size) { + p = talloc_asprintf( + ctx, + "%d/%d/0x%08x", + ace->type, + ace->flags, + ace->info.mask); + if (!p) { + errno = ENOMEM; + return -1; + } + n = strlen(p); + } else { + n = snprintf(buf, bufsize, + "%d/%d/0x%08x", + ace->type, + ace->flags, + ace->info.mask); + } + } else if (all_nt_acls) { + if (determine_size) { + p = talloc_asprintf( + ctx, + "%s%s:%d/%d/0x%08x", + i ? "," : "", + sidstr, + ace->type, + ace->flags, + ace->info.mask); + if (!p) { + errno = ENOMEM; + return -1; + } + n = strlen(p); + } else { + n = snprintf(buf, bufsize, + "%s%s:%d/%d/0x%08x", + i ? "," : "", + sidstr, + ace->type, + ace->flags, + ace->info.mask); + } + } + if (n > bufsize) { + errno = ERANGE; + return -1; + } + buf += n; + n_used += n; + bufsize -= n; + } + } + /* Restore name pointer to its original value */ name -= 19; } @@ -3569,231 +3739,250 @@ static int cacl_get(SMBCCTX *context, TALLOC_CTX *ctx, SMBCSRV *srv, } - if (all || all_dos) { - if (determine_size) { - p = talloc_asprintf(ctx, - "%sMODE:0x%x", - (ipc_cli && - (all || some_nt) - ? "," - : ""), - mode); - if (!p) { - errno = ENOMEM; - return -1; + if (! exclude_dos_mode) { + if (all || all_dos) { + if (determine_size) { + p = talloc_asprintf(ctx, + "%sMODE:0x%x", + (ipc_cli && + (all || some_nt) + ? "," + : ""), + mode); + if (!p) { + errno = ENOMEM; + return -1; + } + n = strlen(p); + } else { + n = snprintf(buf, bufsize, + "%sMODE:0x%x", + (ipc_cli && + (all || some_nt) + ? "," + : ""), + mode); } - n = strlen(p); - } else { - n = snprintf(buf, bufsize, - "%sMODE:0x%x", - (ipc_cli && - (all || some_nt) - ? "," - : ""), - mode); - } - } else if (StrCaseCmp(name, "mode") == 0) { - if (determine_size) { - p = talloc_asprintf(ctx, "0x%x", mode); - if (!p) { - errno = ENOMEM; - return -1; + } else if (StrCaseCmp(name, "mode") == 0) { + if (determine_size) { + p = talloc_asprintf(ctx, "0x%x", mode); + if (!p) { + errno = ENOMEM; + return -1; + } + n = strlen(p); + } else { + n = snprintf(buf, bufsize, "0x%x", mode); } - n = strlen(p); - } else { - n = snprintf(buf, bufsize, "0x%x", mode); } - } - if (!determine_size && n > bufsize) { - errno = ERANGE; - return -1; + if (!determine_size && n > bufsize) { + errno = ERANGE; + return -1; + } + buf += n; + n_used += n; + bufsize -= n; } - buf += n; - n_used += n; - bufsize -= n; - - if (all || all_dos) { - if (determine_size) { - p = talloc_asprintf(ctx, - ",SIZE:%llu", - (unsigned long long) size); - if (!p) { - errno = ENOMEM; - return -1; + + if (! exclude_dos_size) { + if (all || all_dos) { + if (determine_size) { + p = talloc_asprintf( + ctx, + ",SIZE:%llu", + (unsigned long long) size); + if (!p) { + errno = ENOMEM; + return -1; + } + n = strlen(p); + } else { + n = snprintf(buf, bufsize, + ",SIZE:%llu", + (unsigned long long) size); } - n = strlen(p); - } else { - n = snprintf(buf, bufsize, - ",SIZE:%llu", - (unsigned long long) size); - } - } else if (StrCaseCmp(name, "size") == 0) { - if (determine_size) { - p = talloc_asprintf(ctx, - "%llu", - (unsigned long long) size); - if (!p) { - errno = ENOMEM; - return -1; + } else if (StrCaseCmp(name, "size") == 0) { + if (determine_size) { + p = talloc_asprintf( + ctx, + "%llu", + (unsigned long long) size); + if (!p) { + errno = ENOMEM; + return -1; + } + n = strlen(p); + } else { + n = snprintf(buf, bufsize, + "%llu", + (unsigned long long) size); } - n = strlen(p); - } else { - n = snprintf(buf, bufsize, - "%llu", - (unsigned long long) size); } - } - if (!determine_size && n > bufsize) { - errno = ERANGE; - return -1; + if (!determine_size && n > bufsize) { + errno = ERANGE; + return -1; + } + buf += n; + n_used += n; + bufsize -= n; } - buf += n; - n_used += n; - bufsize -= n; - - if (all || all_dos) { - if (determine_size) { - p = talloc_asprintf(ctx, - ",C_TIME:%lu", c_time); - if (!p) { - errno = ENOMEM; - return -1; + + if (! exclude_dos_ctime) { + if (all || all_dos) { + if (determine_size) { + p = talloc_asprintf(ctx, + ",C_TIME:%lu", + c_time); + if (!p) { + errno = ENOMEM; + return -1; + } + n = strlen(p); + } else { + n = snprintf(buf, bufsize, + ",C_TIME:%lu", c_time); } - n = strlen(p); - } else { - n = snprintf(buf, bufsize, - ",C_TIME:%lu", c_time); - } - } else if (StrCaseCmp(name, "c_time") == 0) { - if (determine_size) { - p = talloc_asprintf(ctx, "%lu", c_time); - if (!p) { - errno = ENOMEM; - return -1; + } else if (StrCaseCmp(name, "c_time") == 0) { + if (determine_size) { + p = talloc_asprintf(ctx, "%lu", c_time); + if (!p) { + errno = ENOMEM; + return -1; + } + n = strlen(p); + } else { + n = snprintf(buf, bufsize, "%lu", c_time); } - n = strlen(p); - } else { - n = snprintf(buf, bufsize, "%lu", c_time); } - } - if (!determine_size && n > bufsize) { - errno = ERANGE; - return -1; + if (!determine_size && n > bufsize) { + errno = ERANGE; + return -1; + } + buf += n; + n_used += n; + bufsize -= n; } - buf += n; - n_used += n; - bufsize -= n; - - if (all || all_dos) { - if (determine_size) { - p = talloc_asprintf(ctx, - ",A_TIME:%lu", a_time); - if (!p) { - errno = ENOMEM; - return -1; + + if (! exclude_dos_atime) { + if (all || all_dos) { + if (determine_size) { + p = talloc_asprintf(ctx, + ",A_TIME:%lu", + a_time); + if (!p) { + errno = ENOMEM; + return -1; + } + n = strlen(p); + } else { + n = snprintf(buf, bufsize, + ",A_TIME:%lu", a_time); } - n = strlen(p); - } else { - n = snprintf(buf, bufsize, - ",A_TIME:%lu", a_time); - } - } else if (StrCaseCmp(name, "a_time") == 0) { - if (determine_size) { - p = talloc_asprintf(ctx, "%lu", a_time); - if (!p) { - errno = ENOMEM; - return -1; + } else if (StrCaseCmp(name, "a_time") == 0) { + if (determine_size) { + p = talloc_asprintf(ctx, "%lu", a_time); + if (!p) { + errno = ENOMEM; + return -1; + } + n = strlen(p); + } else { + n = snprintf(buf, bufsize, "%lu", a_time); } - n = strlen(p); - } else { - n = snprintf(buf, bufsize, "%lu", a_time); } - } - if (!determine_size && n > bufsize) { - errno = ERANGE; - return -1; + if (!determine_size && n > bufsize) { + errno = ERANGE; + return -1; + } + buf += n; + n_used += n; + bufsize -= n; } - buf += n; - n_used += n; - bufsize -= n; - - if (all || all_dos) { - if (determine_size) { - p = talloc_asprintf(ctx, - ",M_TIME:%lu", m_time); - if (!p) { - errno = ENOMEM; - return -1; + + if (! exclude_dos_mtime) { + if (all || all_dos) { + if (determine_size) { + p = talloc_asprintf(ctx, + ",M_TIME:%lu", + m_time); + if (!p) { + errno = ENOMEM; + return -1; + } + n = strlen(p); + } else { + n = snprintf(buf, bufsize, + ",M_TIME:%lu", m_time); } - n = strlen(p); - } else { - n = snprintf(buf, bufsize, - ",M_TIME:%lu", m_time); - } - } else if (StrCaseCmp(name, "m_time") == 0) { - if (determine_size) { - p = talloc_asprintf(ctx, "%lu", m_time); - if (!p) { - errno = ENOMEM; - return -1; + } else if (StrCaseCmp(name, "m_time") == 0) { + if (determine_size) { + p = talloc_asprintf(ctx, "%lu", m_time); + if (!p) { + errno = ENOMEM; + return -1; + } + n = strlen(p); + } else { + n = snprintf(buf, bufsize, "%lu", m_time); } - n = strlen(p); - } else { - n = snprintf(buf, bufsize, "%lu", m_time); } - } - if (!determine_size && n > bufsize) { - errno = ERANGE; - return -1; + if (!determine_size && n > bufsize) { + errno = ERANGE; + return -1; + } + buf += n; + n_used += n; + bufsize -= n; } - buf += n; - n_used += n; - bufsize -= n; - - if (all || all_dos) { - if (determine_size) { - p = talloc_asprintf(ctx, - ",INODE:%llu", - (unsigned long long) ino); - if (!p) { - errno = ENOMEM; - return -1; + + if (! exclude_dos_inode) { + if (all || all_dos) { + if (determine_size) { + p = talloc_asprintf( + ctx, + ",INODE:%llu", + (unsigned long long) ino); + if (!p) { + errno = ENOMEM; + return -1; + } + n = strlen(p); + } else { + n = snprintf(buf, bufsize, + ",INODE:%llu", + (unsigned long long) ino); } - n = strlen(p); - } else { - n = snprintf(buf, bufsize, - ",INODE:%llu", - (unsigned long long) ino); - } - } else if (StrCaseCmp(name, "inode") == 0) { - if (determine_size) { - p = talloc_asprintf(ctx, - "%llu", - (unsigned long long) ino); - if (!p) { - errno = ENOMEM; - return -1; + } else if (StrCaseCmp(name, "inode") == 0) { + if (determine_size) { + p = talloc_asprintf( + ctx, + "%llu", + (unsigned long long) ino); + if (!p) { + errno = ENOMEM; + return -1; + } + n = strlen(p); + } else { + n = snprintf(buf, bufsize, + "%llu", + (unsigned long long) ino); } - n = strlen(p); - } else { - n = snprintf(buf, bufsize, - "%llu", - (unsigned long long) ino); } - } - if (!determine_size && n > bufsize) { - errno = ERANGE; - return -1; + if (!determine_size && n > bufsize) { + errno = ERANGE; + return -1; + } + buf += n; + n_used += n; + bufsize -= n; } - buf += n; - n_used += n; - bufsize -= n; /* Restore name pointer to its original value */ name -= 16; @@ -3840,7 +4029,8 @@ static int cacl_set(TALLOC_CTX *ctx, struct cli_state *cli, the_acl = p + 1; } - sd = sec_desc_parse(ctx, ipc_cli, pol, numeric, the_acl); + sd = sec_desc_parse(ctx, ipc_cli, pol, numeric, + CONST_DISCARD(char *, the_acl)); if (!sd) { errno = EINVAL; @@ -4347,9 +4537,13 @@ int smbc_getxattr_ctx(SMBCCTX *context, /* Are they requesting a supported attribute? */ if (StrCaseCmp(name, "system.*") == 0 || + StrnCaseCmp(name, "system.*!", 9) == 0 || StrCaseCmp(name, "system.*+") == 0 || + StrnCaseCmp(name, "system.*+!", 10) == 0 || StrCaseCmp(name, "system.nt_sec_desc.*") == 0 || + StrnCaseCmp(name, "system.nt_sec_desc.*!", 21) == 0 || StrCaseCmp(name, "system.nt_sec_desc.*+") == 0 || + StrnCaseCmp(name, "system.nt_sec_desc.*+!", 22) == 0 || StrCaseCmp(name, "system.nt_sec_desc.revision") == 0 || StrCaseCmp(name, "system.nt_sec_desc.owner") == 0 || StrCaseCmp(name, "system.nt_sec_desc.owner+") == 0 || @@ -4358,6 +4552,7 @@ int smbc_getxattr_ctx(SMBCCTX *context, StrnCaseCmp(name, "system.nt_sec_desc.acl", 22) == 0 || StrnCaseCmp(name, "system.nt_sec_desc.acl+", 23) == 0 || StrCaseCmp(name, "system.dos_attr.*") == 0 || + StrnCaseCmp(name, "system.dos_attr.*!", 18) == 0 || StrCaseCmp(name, "system.dos_attr.mode") == 0 || StrCaseCmp(name, "system.dos_attr.size") == 0 || StrCaseCmp(name, "system.dos_attr.c_time") == 0 || @@ -4368,7 +4563,9 @@ int smbc_getxattr_ctx(SMBCCTX *context, /* Yup. */ ret = cacl_get(context, ctx, srv, ipc_srv == NULL ? NULL : &ipc_srv->cli, - &pol, path, name, (const char *) value, size); + &pol, path, + CONST_DISCARD(char *, name), + CONST_DISCARD(char *, value), size); if (ret < 0 && errno == 0) { errno = smbc_errno(context, &srv->cli); } @@ -4507,6 +4704,7 @@ int smbc_listxattr_ctx(SMBCCTX *context, "system.nt_sec_desc.owner+\0" "system.nt_sec_desc.group\0" "system.nt_sec_desc.group+\0" + "system.nt_sec_desc.acl.*\0" "system.nt_sec_desc.acl\0" "system.nt_sec_desc.acl+\0" "system.nt_sec_desc.*\0" @@ -4982,10 +5180,25 @@ SMBCCTX * smbc_init_context(SMBCCTX * context) * defaults ... */ - if (!lp_load(dyn_CONFIGFILE, True, False, False)) { - DEBUG(5, ("Could not load either config file: %s or %s\n", - conf, dyn_CONFIGFILE)); - } + if (!lp_load(dyn_CONFIGFILE, True, False, False)) { + DEBUG(5, ("Could not load either config file: " + "%s or %s\n", + conf, dyn_CONFIGFILE)); + } else { + /* + * We loaded the global config file. Now lets + * load user-specific modifications to the + * global config. + */ + slprintf(conf, sizeof(conf), + "%s/.smb/smb.conf.append", home); + if (!lp_load(conf, True, False, False)) { + DEBUG(10, + ("Could not append config file: " + "%s\n", + conf)); + } + } } reopen_logs(); /* Get logging working ... */ diff --git a/source/libsmb/nmblib.c b/source/libsmb/nmblib.c index 1c93f7b1e2b..164f85be7bf 100644 --- a/source/libsmb/nmblib.c +++ b/source/libsmb/nmblib.c @@ -21,6 +21,9 @@ #include "includes.h" +extern struct in_addr lastip; +extern int lastport; + int num_good_sends = 0; int num_good_receives = 0; @@ -692,8 +695,6 @@ void free_packet(struct packet_struct *packet) struct packet_struct *parse_packet(char *buf,int length, enum packet_type packet_type) { - extern struct in_addr lastip; - extern int lastport; struct packet_struct *p; BOOL ok=False; diff --git a/source/libsmb/smb_signing.c b/source/libsmb/smb_signing.c index 500ff7cc6e2..f0f2024e7b9 100644 --- a/source/libsmb/smb_signing.c +++ b/source/libsmb/smb_signing.c @@ -255,7 +255,10 @@ static void simple_packet_signature(struct smb_basic_signing_context *data, const size_t offset_end_of_sig = (smb_ss_field + 8); unsigned char sequence_buf[8]; struct MD5Context md5_ctx; +#if 0 + /* JRA - apparently this is incorrect. */ unsigned char key_buf[16]; +#endif /* * Firstly put the sequence number into the first 4 bytes. diff --git a/source/libsmb/smbencrypt.c b/source/libsmb/smbencrypt.c index d4b05574118..55e06ffe972 100644 --- a/source/libsmb/smbencrypt.c +++ b/source/libsmb/smbencrypt.c @@ -513,7 +513,7 @@ BOOL encode_pw_buffer(char buffer[516], const char *password, int string_flags) *new_pw_len is the length in bytes of the possibly mulitbyte returned password including termination. ************************************************************/ -BOOL decode_pw_buffer(char in_buffer[516], char *new_pwrd, +BOOL decode_pw_buffer(uint8 in_buffer[516], char *new_pwrd, int new_pwrd_size, uint32 *new_pw_len, int string_flags) { diff --git a/source/libsmb/spnego.c b/source/libsmb/spnego.c index a0f5565d4f3..0387e8f67d8 100644 --- a/source/libsmb/spnego.c +++ b/source/libsmb/spnego.c @@ -42,12 +42,14 @@ static BOOL read_negTokenInit(ASN1_DATA *asn1, negTokenInit_t *token) asn1_start_tag(asn1, ASN1_CONTEXT(0)); asn1_start_tag(asn1, ASN1_SEQUENCE(0)); - token->mechTypes = SMB_MALLOC_P(char *); + token->mechTypes = SMB_MALLOC_P(const char *); for (i = 0; !asn1->has_error && 0 < asn1_tag_remaining(asn1); i++) { token->mechTypes = - SMB_REALLOC_ARRAY(token->mechTypes, char *, i + 2); - asn1_read_OID(asn1, token->mechTypes + i); + SMB_REALLOC_ARRAY(token->mechTypes, const char *, i + 2); + asn1_read_OID(asn1, + CONST_DISCARD(char **, + (token->mechTypes + i))); } token->mechTypes[i] = NULL; @@ -182,7 +184,7 @@ static BOOL read_negTokenTarg(ASN1_DATA *asn1, negTokenTarg_t *token) break; case ASN1_CONTEXT(1): asn1_start_tag(asn1, ASN1_CONTEXT(1)); - asn1_read_OID(asn1, &token->supportedMech); + asn1_read_OID(asn1, CONST_DISCARD(char **, &token->supportedMech)); asn1_end_tag(asn1); break; case ASN1_CONTEXT(2): @@ -317,7 +319,8 @@ BOOL free_spnego_data(SPNEGO_DATA *spnego) if (spnego->negTokenInit.mechTypes) { int i; for (i = 0; spnego->negTokenInit.mechTypes[i]; i++) { - free(spnego->negTokenInit.mechTypes[i]); + free(CONST_DISCARD(void *, + spnego->negTokenInit.mechTypes[i])); } free(spnego->negTokenInit.mechTypes); } @@ -326,7 +329,7 @@ BOOL free_spnego_data(SPNEGO_DATA *spnego) break; case SPNEGO_NEG_TOKEN_TARG: if (spnego->negTokenTarg.supportedMech) { - free(spnego->negTokenTarg.supportedMech); + free(CONST_DISCARD(void *, spnego->negTokenTarg.supportedMech)); } data_blob_free(&spnego->negTokenTarg.responseToken); data_blob_free(&spnego->negTokenTarg.mechListMIC); diff --git a/source/modules/getdate.c b/source/modules/getdate.c index 491c51294e9..2ce07f898ca 100644 --- a/source/modules/getdate.c +++ b/source/modules/getdate.c @@ -120,11 +120,10 @@ the right thing about local DST. Unlike previous versions, this version is reentrant. */ -#ifdef HAVE_CONFIG_H -# include -# ifdef HAVE_ALLOCA_H -# include -# endif +#include + +#ifdef HAVE_ALLOCA_H +# include #endif /* Since the code of getdate.y is not included in the Emacs executable diff --git a/source/modules/getdate.y b/source/modules/getdate.y index aab37f4d235..ecae7311ac8 100644 --- a/source/modules/getdate.y +++ b/source/modules/getdate.y @@ -25,11 +25,10 @@ the right thing about local DST. Unlike previous versions, this version is reentrant. */ -#ifdef HAVE_CONFIG_H -# include -# ifdef HAVE_ALLOCA_H -# include -# endif +#include + +#ifdef HAVE_ALLOCA_H +# include #endif /* Since the code of getdate.y is not included in the Emacs executable diff --git a/source/modules/vfs_catia.c b/source/modules/vfs_catia.c new file mode 100644 index 00000000000..f77739b23a4 --- /dev/null +++ b/source/modules/vfs_catia.c @@ -0,0 +1,317 @@ +/* + * Catia VFS module + * + * Implement a fixed mapping of forbidden NT characters in filenames that are + * used a lot by the CAD package Catia. + * + * Yes, this a BAD BAD UGLY INCOMPLETE hack, but it helps quite some people + * out there. Catia V4 on AIX uses characters like "<*$ a *lot*, all forbidden + * under Windows... + * + * Copyright (C) Volker Lendecke, 2005 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +#include "includes.h" + +static void catia_string_replace(char *s, unsigned char oldc, unsigned + char newc) +{ + static smb_ucs2_t tmpbuf[sizeof(pstring)]; + smb_ucs2_t *ptr = tmpbuf; + smb_ucs2_t old = oldc; + + push_ucs2(NULL, tmpbuf, s, sizeof(tmpbuf), STR_TERMINATE); + + for (;*ptr;ptr++) + if (*ptr==old) *ptr=newc; + + pull_ucs2(NULL, s, tmpbuf, -1, sizeof(tmpbuf), STR_TERMINATE); +} + +static void from_unix(char *s) +{ + catia_string_replace(s, '\x22', '\xa8'); + catia_string_replace(s, '\x2a', '\xa4'); + catia_string_replace(s, '\x2f', '\xf8'); + catia_string_replace(s, '\x3a', '\xf7'); + catia_string_replace(s, '\x3c', '\xab'); + catia_string_replace(s, '\x3e', '\xbb'); + catia_string_replace(s, '\x3f', '\xbf'); + catia_string_replace(s, '\x5c', '\xff'); + catia_string_replace(s, '\x7c', '\xa6'); + catia_string_replace(s, ' ', '\xb1'); +} + +static void to_unix(char *s) +{ + catia_string_replace(s, '\xa8', '\x22'); + catia_string_replace(s, '\xa4', '\x2a'); + catia_string_replace(s, '\xf8', '\x2f'); + catia_string_replace(s, '\xf7', '\x3a'); + catia_string_replace(s, '\xab', '\x3c'); + catia_string_replace(s, '\xbb', '\x3e'); + catia_string_replace(s, '\xbf', '\x3f'); + catia_string_replace(s, '\xff', '\x5c'); + catia_string_replace(s, '\xa6', '\x7c'); + catia_string_replace(s, '\xb1', ' '); +} + +static DIR *catia_opendir(vfs_handle_struct *handle, connection_struct + *conn, const char *fname) +{ + pstring name; + pstrcpy(name, fname); + to_unix(name); + + return SMB_VFS_NEXT_OPENDIR(handle, conn, name); +} + +static SMB_STRUCT_DIRENT *catia_readdir(vfs_handle_struct *handle, + connection_struct *conn, DIR *dirp) +{ + SMB_STRUCT_DIRENT *result = SMB_VFS_NEXT_READDIR(handle, conn, dirp); + + if (result == NULL) + return result; + + from_unix(result->d_name); + return result; +} + +static int catia_open(vfs_handle_struct *handle, connection_struct *conn, + const char *fname, int flags, mode_t mode) +{ + pstring name; + + pstrcpy(name, fname); + to_unix(name); + + return SMB_VFS_NEXT_OPEN(handle, conn, name, flags, mode); +} + +static int catia_rename(vfs_handle_struct *handle, connection_struct *conn, + const char *old, const char *new) +{ + pstring oname, nname; + + pstrcpy(oname, old); + to_unix(oname); + pstrcpy(nname, new); + to_unix(nname); + + DEBUG(10, ("converted old name: %s\n", oname)); + DEBUG(10, ("converted new name: %s\n", nname)); + + return SMB_VFS_NEXT_RENAME(handle, conn, oname, nname); +} + +static int catia_stat(vfs_handle_struct *handle, connection_struct *conn, + const char *fname, SMB_STRUCT_STAT *sbuf) +{ + pstring name; + pstrcpy(name, fname); + to_unix(name); + + return SMB_VFS_NEXT_STAT(handle, conn, name, sbuf); +} + +static int catia_lstat(vfs_handle_struct *handle, connection_struct *conn, + const char *path, SMB_STRUCT_STAT *sbuf) +{ + pstring name; + pstrcpy(name, path); + to_unix(name); + + return SMB_VFS_NEXT_LSTAT(handle, conn, name, sbuf); +} + +static int catia_unlink(vfs_handle_struct *handle, connection_struct *conn, + const char *path) +{ + pstring name; + pstrcpy(name, path); + to_unix(name); + + return SMB_VFS_NEXT_UNLINK(handle, conn, name); +} + +static int catia_chmod(vfs_handle_struct *handle, connection_struct *conn, + const char *path, mode_t mode) +{ + pstring name; + pstrcpy(name, path); + to_unix(name); + + return SMB_VFS_NEXT_CHMOD(handle, conn, name, mode); +} + +static int catia_chown(vfs_handle_struct *handle, connection_struct *conn, + const char *path, uid_t uid, gid_t gid) +{ + pstring name; + pstrcpy(name, path); + to_unix(name); + + return SMB_VFS_NEXT_CHOWN(handle, conn, name, uid, gid); +} + +static int catia_chdir(vfs_handle_struct *handle, connection_struct *conn, + const char *path) +{ + pstring name; + pstrcpy(name, path); + to_unix(name); + + return SMB_VFS_NEXT_CHDIR(handle, conn, name); +} + +static char *catia_getwd(vfs_handle_struct *handle, connection_struct *conn, + char *buf) +{ + return SMB_VFS_NEXT_GETWD(handle, conn, buf); +} + +static int catia_utime(vfs_handle_struct *handle, connection_struct *conn, + const char *path, struct utimbuf *times) +{ + return SMB_VFS_NEXT_UTIME(handle, conn, path, times); +} + +static BOOL catia_symlink(vfs_handle_struct *handle, connection_struct *conn, + const char *oldpath, const char *newpath) +{ + return SMB_VFS_NEXT_SYMLINK(handle, conn, oldpath, newpath); +} + +static BOOL catia_readlink(vfs_handle_struct *handle, connection_struct *conn, + const char *path, char *buf, size_t bufsiz) +{ + return SMB_VFS_NEXT_READLINK(handle, conn, path, buf, bufsiz); +} + +static int catia_link(vfs_handle_struct *handle, connection_struct *conn, + const char *oldpath, const char *newpath) +{ + return SMB_VFS_NEXT_LINK(handle, conn, oldpath, newpath); +} + +static int catia_mknod(vfs_handle_struct *handle, connection_struct *conn, + const char *path, mode_t mode, SMB_DEV_T dev) +{ + return SMB_VFS_NEXT_MKNOD(handle, conn, path, mode, dev); +} + +static char *catia_realpath(vfs_handle_struct *handle, connection_struct *conn, + const char *path, char *resolved_path) +{ + return SMB_VFS_NEXT_REALPATH(handle, conn, path, resolved_path); +} + +static size_t catia_get_nt_acl(vfs_handle_struct *handle, files_struct *fsp, + const char *name, uint32 security_info, + struct security_descriptor_info **ppdesc) +{ + return SMB_VFS_NEXT_GET_NT_ACL(handle, fsp, name, security_info, + ppdesc); +} + +static BOOL catia_set_nt_acl(vfs_handle_struct *handle, files_struct *fsp, + const char *name, uint32 security_info_sent, + struct security_descriptor_info *psd) +{ + return SMB_VFS_NEXT_SET_NT_ACL(handle, fsp, name, security_info_sent, + psd); +} + +static int catia_chmod_acl(vfs_handle_struct *handle, connection_struct *conn, + const char *name, mode_t mode) +{ + /* If the underlying VFS doesn't have ACL support... */ + if (!handle->vfs_next.ops.chmod_acl) { + errno = ENOSYS; + return -1; + } + return SMB_VFS_NEXT_CHMOD_ACL(handle, conn, name, mode); +} + +/* VFS operations structure */ + +static vfs_op_tuple catia_op_tuples[] = { + + /* Directory operations */ + + {SMB_VFS_OP(catia_opendir), SMB_VFS_OP_OPENDIR, +SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(catia_readdir), SMB_VFS_OP_READDIR, +SMB_VFS_LAYER_TRANSPARENT}, + + /* File operations */ + + {SMB_VFS_OP(catia_open), SMB_VFS_OP_OPEN, +SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(catia_rename), SMB_VFS_OP_RENAME, + SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(catia_stat), SMB_VFS_OP_STAT, +SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(catia_lstat), SMB_VFS_OP_LSTAT, +SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(catia_unlink), SMB_VFS_OP_UNLINK, + SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(catia_chmod), SMB_VFS_OP_CHMOD, +SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(catia_chown), SMB_VFS_OP_CHOWN, +SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(catia_chdir), SMB_VFS_OP_CHDIR, +SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(catia_getwd), SMB_VFS_OP_GETWD, +SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(catia_utime), SMB_VFS_OP_UTIME, +SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(catia_symlink), SMB_VFS_OP_SYMLINK, +SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(catia_readlink), SMB_VFS_OP_READLINK, +SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(catia_link), SMB_VFS_OP_LINK, +SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(catia_mknod), SMB_VFS_OP_MKNOD, +SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(catia_realpath), SMB_VFS_OP_REALPATH, +SMB_VFS_LAYER_TRANSPARENT}, + + /* NT File ACL operations */ + + {SMB_VFS_OP(catia_get_nt_acl), SMB_VFS_OP_GET_NT_ACL, +SMB_VFS_LAYER_TRANSPARENT}, + {SMB_VFS_OP(catia_set_nt_acl), SMB_VFS_OP_SET_NT_ACL, +SMB_VFS_LAYER_TRANSPARENT}, + + /* POSIX ACL operations */ + + {SMB_VFS_OP(catia_chmod_acl), SMB_VFS_OP_CHMOD_ACL, +SMB_VFS_LAYER_TRANSPARENT}, + + + {NULL, SMB_VFS_OP_NOOP, +SMB_VFS_LAYER_NOOP} +}; + +NTSTATUS init_module(void) +{ + return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "catia", +catia_op_tuples); +} diff --git a/source/modules/vfs_fake_perms.c b/source/modules/vfs_fake_perms.c index 740218dcd41..4d10ea5f337 100644 --- a/source/modules/vfs_fake_perms.c +++ b/source/modules/vfs_fake_perms.c @@ -24,6 +24,8 @@ #include "includes.h" +extern struct current_user current_user; + #undef DBGC_CLASS #define DBGC_CLASS DBGC_VFS @@ -33,8 +35,6 @@ static int fake_perms_stat(vfs_handle_struct *handle, connection_struct *conn, c ret = SMB_VFS_NEXT_STAT(handle, conn, fname, sbuf); if (ret == 0) { - extern struct current_user current_user; - if (S_ISDIR(sbuf->st_mode)) { sbuf->st_mode = S_IFDIR | S_IRWXU; } else { @@ -53,8 +53,6 @@ static int fake_perms_fstat(vfs_handle_struct *handle, files_struct *fsp, int fd ret = SMB_VFS_NEXT_FSTAT(handle, fsp, fd, sbuf); if (ret == 0) { - extern struct current_user current_user; - if (S_ISDIR(sbuf->st_mode)) { sbuf->st_mode = S_IFDIR | S_IRWXU; } else { diff --git a/source/modules/weird.c b/source/modules/weird.c index 3c59fd9d61f..e4809a64c42 100644 --- a/source/modules/weird.c +++ b/source/modules/weird.c @@ -26,8 +26,8 @@ static struct { char *to; int len; } weird_table[] = { - {'q', "^q^", 3}, - {'Q', "^Q^", 3}, + {'q', CONST_DISCARD(char *, "^q^"), 3}, + {'Q', CONST_DISCARD(char *, "^Q^"), 3}, {0, NULL} }; diff --git a/source/nmbd/nmbd.c b/source/nmbd/nmbd.c index f8006a22a9e..532b578f3c7 100644 --- a/source/nmbd/nmbd.c +++ b/source/nmbd/nmbd.c @@ -27,6 +27,8 @@ int ClientNMB = -1; int ClientDGRAM = -1; int global_nmb_port = -1; +extern BOOL rescan_listen_set; +extern struct in_addr loopback_ip; extern BOOL global_in_nmbd; extern BOOL override_logfile; @@ -196,8 +198,6 @@ static BOOL reload_interfaces(time_t t) static time_t lastt; int n; struct subnet_record *subrec; - extern BOOL rescan_listen_set; - extern struct in_addr loopback_ip; if (t && ((t - lastt) < NMBD_INTERFACES_RELOAD)) return False; lastt = t; diff --git a/source/nmbd/nmbd_subnetdb.c b/source/nmbd/nmbd_subnetdb.c index ecfd92719bf..b53a6d7328f 100644 --- a/source/nmbd/nmbd_subnetdb.c +++ b/source/nmbd/nmbd_subnetdb.c @@ -25,6 +25,7 @@ #include "includes.h" +extern struct in_addr loopback_ip; extern int ClientNMB; extern int ClientDGRAM; extern int global_nmb_port; @@ -211,7 +212,6 @@ BOOL create_subnets(void) int num_interfaces = iface_count(); int i; struct in_addr unicast_ip, ipzero; - extern struct in_addr loopback_ip; if(num_interfaces == 0) { DEBUG(0,("create_subnets: No local interfaces !\n")); diff --git a/source/nmbd/nmbd_synclists.c b/source/nmbd/nmbd_synclists.c index c6bcb3e5742..33690133bf8 100644 --- a/source/nmbd/nmbd_synclists.c +++ b/source/nmbd/nmbd_synclists.c @@ -29,6 +29,8 @@ #include "includes.h" +extern fstring local_machine; + struct sync_record { struct sync_record *next, *prev; unstring workgroup; @@ -65,7 +67,6 @@ static void sync_child(char *name, int nm_type, struct in_addr ip, BOOL local, BOOL servers, char *fname) { - extern fstring local_machine; fstring unix_workgroup; static struct cli_state cli; uint32 local_type = local ? SV_TYPE_LOCAL_LIST_ONLY : 0; diff --git a/source/nsswitch/wb_client.c b/source/nsswitch/wb_client.c index 3a920c1134b..5e08c0853e1 100644 --- a/source/nsswitch/wb_client.c +++ b/source/nsswitch/wb_client.c @@ -28,8 +28,6 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_WINBIND -extern DOM_SID global_sid_NULL; /* NULL sid */ - NSS_STATUS winbindd_request(int req_type, struct winbindd_request *request, struct winbindd_response *response); diff --git a/source/nsswitch/wb_common.c b/source/nsswitch/wb_common.c index 9caf7affc39..6ba0cbbf428 100644 --- a/source/nsswitch/wb_common.c +++ b/source/nsswitch/wb_common.c @@ -26,6 +26,9 @@ #include "winbind_client.h" +#define CONST_DISCARD(type, ptr) ((type) ((void *) (ptr))) +#define CONST_ADD(type, ptr) ((type) ((const void *) (ptr))) + /* Global variables. These are effectively the client state information */ int winbindd_fd = -1; /* fd for winbindd socket */ @@ -606,14 +609,14 @@ NSS_STATUS winbindd_request(int req_type, BOOL winbind_off( void ) { - static char *s = WINBINDD_DONT_ENV "=1"; + static char *s = CONST_DISCARD(char *, WINBINDD_DONT_ENV "=1"); return putenv(s) != -1; } BOOL winbind_on( void ) { - static char *s = WINBINDD_DONT_ENV "=0"; + static char *s = CONST_DISCARD(char *, WINBINDD_DONT_ENV "=0"); return putenv(s) != -1; } diff --git a/source/nsswitch/winbindd.c b/source/nsswitch/winbindd.c index 6f4a0a27533..6840dd91871 100644 --- a/source/nsswitch/winbindd.c +++ b/source/nsswitch/winbindd.c @@ -898,8 +898,6 @@ int main(int argc, char **argv) idmap_proxyonly(); } - generate_wellknown_sids(); - /* Unblock all signals we are interested in as they may have been blocked by the parent process. */ diff --git a/source/nsswitch/winbindd.h b/source/nsswitch/winbindd.h index cd1d16e3441..863ae35fed4 100644 --- a/source/nsswitch/winbindd.h +++ b/source/nsswitch/winbindd.h @@ -245,7 +245,6 @@ struct winbindd_idmap_methods { #include "nsswitch/winbindd_proto.h" #include "rpc_parse.h" -#include "rpc_client.h" #define WINBINDD_ESTABLISH_LOOP 30 #define WINBINDD_RESCAN_FREQ 300 diff --git a/source/nsswitch/winbindd_acct.c b/source/nsswitch/winbindd_acct.c index 2c8b7cae287..cd0b5b7e066 100644 --- a/source/nsswitch/winbindd_acct.c +++ b/source/nsswitch/winbindd_acct.c @@ -222,7 +222,7 @@ static WINBINDD_GR* string2group( char *string ) gr_members = SMB_XMALLOC_ARRAY(char*, num_gr_members+1); i = 0; - while ( next_token(&str, buffer, ",", sizeof(buffer)) && iconfig.realm) { - 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); diff --git a/source/nsswitch/winbindd_cache.c b/source/nsswitch/winbindd_cache.c index 3fc62df005f..cc385a1dd72 100644 --- a/source/nsswitch/winbindd_cache.c +++ b/source/nsswitch/winbindd_cache.c @@ -26,6 +26,12 @@ #include "includes.h" #include "winbindd.h" +extern BOOL opt_nocache; +extern struct winbindd_methods msrpc_methods; +extern struct winbindd_methods ads_methods; +extern BOOL opt_dual_daemon; +extern BOOL background_process; + #undef DBGC_CLASS #define DBGC_CLASS DBGC_WINBIND @@ -47,8 +53,6 @@ static struct winbind_cache *wcache; /* flush the cache */ void wcache_flush_cache(void) { - extern BOOL opt_nocache; - if (!wcache) return; if (wcache->tdb) { @@ -102,11 +106,9 @@ static struct winbind_cache *get_cache(struct winbindd_domain *domain) struct winbind_cache *ret = wcache; if (!domain->backend) { - extern struct winbindd_methods msrpc_methods; switch (lp_security()) { #ifdef HAVE_ADS case SEC_ADS: { - extern struct winbindd_methods ads_methods; /* always obey the lp_security parameter for our domain */ if (domain->primary) { domain->backend = &ads_methods; @@ -469,13 +471,11 @@ static struct cache_entry *wcache_fetch(struct winbind_cache *cache, centry->sequence_number = centry_uint32(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 )); diff --git a/source/nsswitch/winbindd_group.c b/source/nsswitch/winbindd_group.c index 51618bd00fd..f0d3bc43ea6 100644 --- a/source/nsswitch/winbindd_group.c +++ b/source/nsswitch/winbindd_group.c @@ -920,6 +920,52 @@ enum winbindd_result winbindd_list_groups(struct winbindd_cli_state *state) return WINBINDD_OK; } +static BOOL enum_alias_memberships(const DOM_SID *member_sid, + DOM_SID **aliases, int *num_aliases) +{ + TALLOC_CTX *mem_ctx = talloc_init("enum_alias_memberships"); + + uint32 *rids = NULL; + int i, num_rids = 0; + + BOOL result = False; + + if (mem_ctx == NULL) + return False; + + *aliases = NULL; + *num_aliases = 0; + + if (!pdb_enum_alias_memberships(mem_ctx, get_global_sam_sid(), + member_sid, 1, &rids, &num_rids)) + goto done; + + for (i=0; i= 0) && ((i) < iNumServices) && ServicePtrs[(i)]->valid) -#define VALID(i) ServicePtrs[i]->valid +#define VALID(i) (ServicePtrs != NULL && ServicePtrs[i]->valid) int keepalive = DEFAULT_KEEPALIVE; BOOL use_getwd_cache = True; @@ -183,8 +184,16 @@ typedef struct char *szAddShareCommand; char *szChangeShareCommand; char *szDeleteShareCommand; + char *szEventLogOpenCommand; + char *szEventLogReadCommand; + char *szEventLogClearCommand; + char *szEventLogNumRecordsCommand; + char *szEventLogOldestRecordCommand; + char *szEventLogCloseCommand; + char **szEventLogs; char *szGuestaccount; char *szManglingMethod; + char **szServicesList; int mangle_prefix; int max_log_size; char *szLogLevel; @@ -272,6 +281,7 @@ typedef struct BOOL bNTPipeSupport; BOOL bNTStatusSupport; BOOL bStatCache; + int iMaxStatCacheSize; BOOL bKernelOplocks; BOOL bAllowTrustedDomains; BOOL bLanmanAuth; @@ -413,6 +423,7 @@ typedef struct BOOL bBlockingLocks; BOOL bInheritPerms; BOOL bInheritACLS; + BOOL bInheritOwner; BOOL bMSDfsRoot; BOOL bUseClientDriver; BOOL bDefaultDevmode; @@ -539,6 +550,7 @@ static service sDefault = { True, /* bBlockingLocks */ False, /* bInheritPerms */ False, /* bInheritACLS */ + False, /* bInheritOwner */ False, /* bMSDfsRoot */ False, /* bUseClientDriver */ False, /* bDefaultDevmode */ @@ -581,6 +593,7 @@ static BOOL handle_netbios_scope( int snum, const char *pszParmValue, char **ptr static BOOL handle_charset( int snum, const char *pszParmValue, char **ptr ); static BOOL handle_acl_compatibility( int snum, const char *pszParmValue, char **ptr); static BOOL handle_printing( int snum, const char *pszParmValue, char **ptr); +static BOOL handle_eventlog( int snum, const char *pszParmValue, char **ptr); static void set_server_role(void); static void set_default_server_announce_type(void); @@ -864,6 +877,7 @@ static struct parm_struct parm_table[] = { {"force unknown acl user", P_BOOL, P_LOCAL, &sDefault.bForceUnknownAclUser, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, {"inherit permissions", P_BOOL, P_LOCAL, &sDefault.bInheritPerms, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, {"inherit acls", P_BOOL, P_LOCAL, &sDefault.bInheritACLS, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, + {"inherit owner", P_BOOL, P_LOCAL, &sDefault.bInheritOwner, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, {"guest only", P_BOOL, P_LOCAL, &sDefault.bGuest_only, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, {"only guest", P_BOOL, P_LOCAL, &sDefault.bGuest_only, NULL, NULL, FLAG_HIDE}, @@ -932,6 +946,8 @@ static struct parm_struct parm_table[] = { {"server signing", P_ENUM, P_GLOBAL, &Globals.server_signing, NULL, enum_smb_signing_vals, FLAG_ADVANCED}, {"client use spnego", P_BOOL, P_GLOBAL, &Globals.bClientUseSpnego, NULL, NULL, FLAG_ADVANCED}, + {"enable svcctl", P_LIST, P_GLOBAL, &Globals.szServicesList, NULL, NULL, FLAG_ADVANCED}, + {N_("Tuning Options"), P_SEP, P_SEPARATOR}, {"block size", P_INTEGER, P_LOCAL, &sDefault.iBlock_size, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, @@ -975,6 +991,7 @@ static struct parm_struct parm_table[] = { {"cups server", P_STRING, P_GLOBAL, &Globals.szCupsServer, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL}, {"print command", P_STRING, P_LOCAL, &sDefault.szPrintcommand, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL}, {"disable spoolss", P_BOOL, P_GLOBAL, &Globals.bDisableSpoolss, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL}, + {"enable spoolss", P_BOOLREV, P_GLOBAL, &Globals.bDisableSpoolss, NULL, NULL, FLAG_HIDE}, {"lpq command", P_STRING, P_LOCAL, &sDefault.szLpqcommand, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL}, {"lprm command", P_STRING, P_LOCAL, &sDefault.szLprmcommand, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL}, {"lppause command", P_STRING, P_LOCAL, &sDefault.szLppausecommand, NULL, NULL, FLAG_ADVANCED | FLAG_PRINT | FLAG_GLOBAL}, @@ -1017,6 +1034,7 @@ static struct parm_struct parm_table[] = { {"map archive", P_BOOL, P_LOCAL, &sDefault.bMap_archive, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, {"mangled names", P_BOOL, P_LOCAL, &sDefault.bMangledNames, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, {"mangled map", P_STRING, P_LOCAL, &sDefault.szMangledMap, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL | FLAG_DEPRECATED }, + {"max stat cache size", P_INTEGER, P_GLOBAL, &Globals.iMaxStatCacheSize, NULL, NULL, FLAG_ADVANCED}, {"stat cache", P_BOOL, P_GLOBAL, &Globals.bStatCache, NULL, NULL, FLAG_ADVANCED}, {"store dos attributes", P_BOOL, P_LOCAL, &sDefault.bStoreDosAttributes, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL}, @@ -1110,6 +1128,14 @@ static struct parm_struct parm_table[] = { {"change share command", P_STRING, P_GLOBAL, &Globals.szChangeShareCommand, NULL, NULL, FLAG_ADVANCED}, {"delete share command", P_STRING, P_GLOBAL, &Globals.szDeleteShareCommand, NULL, NULL, FLAG_ADVANCED}, + {N_("EventLog Options"), P_SEP, P_SEPARATOR}, + {"eventlog open command", P_STRING, P_GLOBAL, &Globals.szEventLogOpenCommand, handle_eventlog, NULL, FLAG_ADVANCED}, + {"eventlog read command", P_STRING, P_GLOBAL, &Globals.szEventLogReadCommand, handle_eventlog, NULL, FLAG_ADVANCED}, + {"eventlog clear command", P_STRING, P_GLOBAL, &Globals.szEventLogClearCommand, handle_eventlog, NULL, FLAG_ADVANCED}, + {"eventlog num records command", P_STRING, P_GLOBAL, &Globals.szEventLogNumRecordsCommand, handle_eventlog, NULL, FLAG_ADVANCED}, + {"eventlog oldest record command", P_STRING, P_GLOBAL, &Globals.szEventLogOldestRecordCommand, handle_eventlog, NULL, FLAG_ADVANCED}, + {"eventlog list", P_LIST, P_GLOBAL, &Globals.szEventLogs, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, + {"config file", P_STRING, P_GLOBAL, &Globals.szConfigFile, NULL, NULL, FLAG_HIDE}, {"preload", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL, NULL, FLAG_ADVANCED}, {"auto services", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL, NULL, FLAG_ADVANCED}, @@ -1378,7 +1404,7 @@ static void init_globals(void) Globals.AlgorithmicRidBase = BASE_RID; Globals.bLoadPrinters = True; - Globals.PrintcapCacheTime = 0; + Globals.PrintcapCacheTime = 750; /* 12.5 minutes */ /* Was 65535 (0xFFFF). 0x4101 matches W2K and causes major speed improvements... */ /* Discovered by 2 days of pain by Don McCall @ HP :-). */ Globals.max_xmit = 0x4104; @@ -1438,6 +1464,7 @@ static void init_globals(void) Globals.bNTPipeSupport = True; /* Do NT pipes by default. */ Globals.bNTStatusSupport = True; /* Use NT status by default. */ Globals.bStatCache = True; /* use stat cache by default */ + Globals.iMaxStatCacheSize = 0; /* unlimited size in kb 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 */ @@ -1527,6 +1554,12 @@ static void init_globals(void) string_set(&Globals.szAclCompat, ""); string_set(&Globals.szCupsServer, ""); + string_set(&Globals.szEventLogOpenCommand, ""); + string_set(&Globals.szEventLogReadCommand, ""); + string_set(&Globals.szEventLogClearCommand, ""); + string_set(&Globals.szEventLogNumRecordsCommand, ""); + string_set(&Globals.szEventLogOldestRecordCommand, ""); + Globals.winbind_cache_time = 300; /* 5 minutes */ Globals.bWinbindEnableLocalAccounts = False; Globals.bWinbindEnumUsers = True; @@ -1553,6 +1586,8 @@ static void init_globals(void) operations as root */ Globals.bEnablePrivileges = False; + + Globals.szServicesList = str_list_make( "Spooler NETLOGON", NULL ); } static TALLOC_CTX *lp_talloc; @@ -1719,6 +1754,7 @@ FN_GLOBAL_BOOL(lp_winbind_use_default_domain, &Globals.bWinbindUseDefaultDomain) FN_GLOBAL_BOOL(lp_winbind_trusted_domains_only, &Globals.bWinbindTrustedDomainsOnly) FN_GLOBAL_BOOL(lp_winbind_nested_groups, &Globals.bWinbindNestedGroups) + FN_GLOBAL_LIST(lp_idmap_backend, &Globals.szIdmapBackend) FN_GLOBAL_BOOL(lp_enable_rid_algorithm, &Globals.bEnableRidAlgorithm) @@ -1738,6 +1774,14 @@ FN_GLOBAL_STRING(lp_add_share_cmd, &Globals.szAddShareCommand) FN_GLOBAL_STRING(lp_change_share_cmd, &Globals.szChangeShareCommand) FN_GLOBAL_STRING(lp_delete_share_cmd, &Globals.szDeleteShareCommand) +FN_GLOBAL_STRING(lp_eventlog_open_cmd, &Globals.szEventLogOpenCommand) +FN_GLOBAL_STRING(lp_eventlog_read_cmd, &Globals.szEventLogReadCommand) +FN_GLOBAL_STRING(lp_eventlog_clear_cmd, &Globals.szEventLogClearCommand) +FN_GLOBAL_STRING(lp_eventlog_num_records_cmd, &Globals.szEventLogNumRecordsCommand) +FN_GLOBAL_STRING(lp_eventlog_oldest_record_cmd, &Globals.szEventLogOldestRecordCommand) +FN_GLOBAL_STRING(lp_eventlog_close_cmd, &Globals.szEventLogCloseCommand) +FN_GLOBAL_LIST(lp_eventlog_list, &Globals.szEventLogs) + FN_GLOBAL_BOOL(lp_disable_netbios, &Globals.bDisableNetbios) FN_GLOBAL_BOOL(lp_ms_add_printer_wizard, &Globals.bMsAddPrinterWizard) FN_GLOBAL_BOOL(lp_dns_proxy, &Globals.bDNSproxy) @@ -1773,6 +1817,7 @@ FN_GLOBAL_INTEGER(lp_passwd_chat_timeout, &Globals.iPasswdChatTimeout) FN_GLOBAL_BOOL(lp_nt_pipe_support, &Globals.bNTPipeSupport) FN_GLOBAL_BOOL(lp_nt_status_support, &Globals.bNTStatusSupport) FN_GLOBAL_BOOL(lp_stat_cache, &Globals.bStatCache) +FN_GLOBAL_INTEGER(lp_max_stat_cache_size, &Globals.iMaxStatCacheSize) 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) @@ -1835,6 +1880,7 @@ FN_LOCAL_STRING(lp_username, szUsername) FN_LOCAL_LIST(lp_invalid_users, szInvalidUsers) FN_LOCAL_LIST(lp_valid_users, szValidUsers) FN_LOCAL_LIST(lp_admin_users, szAdminUsers) +FN_GLOBAL_LIST(lp_enable_svcctl, &Globals.szServicesList) FN_LOCAL_STRING(lp_cups_options, szCupsOptions) FN_GLOBAL_STRING(lp_cups_server, &Globals.szCupsServer) FN_LOCAL_STRING(lp_printcommand, szPrintcommand) @@ -1907,6 +1953,7 @@ FN_LOCAL_BOOL(lp_fake_dir_create_times, bFakeDirCreateTimes) FN_LOCAL_BOOL(lp_blocking_locks, bBlockingLocks) FN_LOCAL_BOOL(lp_inherit_perms, bInheritPerms) FN_LOCAL_BOOL(lp_inherit_acls, bInheritACLS) +FN_LOCAL_BOOL(lp_inherit_owner, bInheritOwner) FN_LOCAL_BOOL(lp_use_client_driver, bUseClientDriver) FN_LOCAL_BOOL(lp_default_devmode, bDefaultDevmode) FN_LOCAL_BOOL(lp_force_printername, bForcePrintername) @@ -2765,6 +2812,12 @@ static BOOL handle_charset(int snum, const char *pszParmValue, char **ptr) return True; } +static BOOL handle_eventlog(int snum, const char *pszParmValue, char **ptr) +{ + string_set(ptr, pszParmValue); + return True; +} + static BOOL handle_workgroup(int snum, const char *pszParmValue, char **ptr) { BOOL ret; @@ -4311,7 +4364,6 @@ const char *lp_printcapname(void) BOOL lp_use_sendfile(int snum) { - extern enum protocol_types Protocol; /* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */ if (Protocol < PROTOCOL_NT1) { return False; diff --git a/source/param/params.c b/source/param/params.c index 9d21d25a240..3b736113bef 100644 --- a/source/param/params.c +++ b/source/param/params.c @@ -81,6 +81,8 @@ #include "includes.h" +extern BOOL in_client; + /* -------------------------------------------------------------------------- ** * Constants... */ @@ -523,7 +525,6 @@ static BOOL Parse( myFILE *InFile, static myFILE *OpenConfFile( const char *FileName ) { const char *func = "params.c:OpenConfFile() -"; - extern BOOL in_client; int lvl = in_client?1:0; myFILE *ret; diff --git a/source/passdb/machine_sid.c b/source/passdb/machine_sid.c index ae0b16273f2..ecc7d291f6d 100644 --- a/source/passdb/machine_sid.c +++ b/source/passdb/machine_sid.c @@ -86,8 +86,6 @@ static DOM_SID *pdb_generate_sam_sid(void) if(!(sam_sid=SMB_MALLOC_P(DOM_SID))) return NULL; - generate_wellknown_sids(); - switch (lp_server_role()) { case ROLE_DOMAIN_PDC: case ROLE_DOMAIN_BDC: diff --git a/source/passdb/passdb.c b/source/passdb/passdb.c index deac2bbd6e3..203fa2bf21e 100644 --- a/source/passdb/passdb.c +++ b/source/passdb/passdb.c @@ -1894,7 +1894,7 @@ BOOL init_sam_from_buffer_v2(SAM_ACCOUNT *sampass, uint8 *buf, uint32 buflen) /* Change from V1 is addition of password history field. */ account_policy_get(AP_PASSWORD_HISTORY, &pwHistLen); if (pwHistLen) { - char *pw_hist = SMB_MALLOC(pwHistLen * PW_HISTORY_ENTRY_LEN); + uint8 *pw_hist = SMB_MALLOC(pwHistLen * PW_HISTORY_ENTRY_LEN); if (!pw_hist) { ret = False; goto done; diff --git a/source/passdb/pdb_get_set.c b/source/passdb/pdb_get_set.c index 4b59b5fdf95..99afac133ac 100644 --- a/source/passdb/pdb_get_set.c +++ b/source/passdb/pdb_get_set.c @@ -1195,7 +1195,7 @@ BOOL pdb_set_plaintext_passwd (SAM_ACCOUNT *sampass, const char *plaintext) /* We need to make sure we don't have a race condition here - the account policy history length can change between when the pw_history was first loaded into the SAM_ACCOUNT struct and now.... JRA. */ - pwhistory = (uchar *)pdb_get_pw_history(sampass, ¤t_history_len); + pwhistory = CONST_DISCARD(uchar *, pdb_get_pw_history(sampass, ¤t_history_len)); if (current_history_len != pwHistLen) { /* After closing and reopening SAM_ACCOUNT the history diff --git a/source/passdb/pdb_interface.c b/source/passdb/pdb_interface.c index 84d398ccd64..301dc101eb4 100644 --- a/source/passdb/pdb_interface.c +++ b/source/passdb/pdb_interface.c @@ -48,7 +48,7 @@ static struct pdb_init_function_entry *pdb_find_backend_entry(const char *name); static void pdb_force_pw_initialization(SAM_ACCOUNT *pass) { - const char *lm_pwd, *nt_pwd; + const uint8 *lm_pwd, *nt_pwd; /* only reset a password if the last set time has been explicitly been set to zero. A default last set time @@ -233,7 +233,7 @@ static NTSTATUS context_getsampwsid(struct pdb_context *context, SAM_ACCOUNT *sa static NTSTATUS context_add_sam_account(struct pdb_context *context, SAM_ACCOUNT *sam_acct) { NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; - const char *lm_pw, *nt_pw; + const uint8 *lm_pw, *nt_pw; uint16 acb_flags; if ((!context) || (!context->pdb_methods)) { @@ -262,7 +262,7 @@ static NTSTATUS context_add_sam_account(struct pdb_context *context, SAM_ACCOUNT static NTSTATUS context_update_sam_account(struct pdb_context *context, SAM_ACCOUNT *sam_acct) { NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; - const char *lm_pw, *nt_pw; + const uint8 *lm_pw, *nt_pw; uint16 acb_flags; if (!context) { @@ -643,9 +643,12 @@ static NTSTATUS context_enum_aliasmem(struct pdb_context *context, } static NTSTATUS context_enum_alias_memberships(struct pdb_context *context, + TALLOC_CTX *mem_ctx, + const DOM_SID *domain_sid, const DOM_SID *members, int num_members, - DOM_SID **aliases, int *num) + uint32 **alias_rids, + int *num_alias_rids) { NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; @@ -655,8 +658,29 @@ static NTSTATUS context_enum_alias_memberships(struct pdb_context *context, } return context->pdb_methods-> - enum_alias_memberships(context->pdb_methods, members, - num_members, aliases, num); + enum_alias_memberships(context->pdb_methods, mem_ctx, + domain_sid, members, num_members, + alias_rids, num_alias_rids); +} + +static NTSTATUS context_lookup_rids(struct pdb_context *context, + TALLOC_CTX *mem_ctx, + const DOM_SID *domain_sid, + int num_rids, + uint32 *rids, + const char ***names, + uint32 **attrs) +{ + NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; + + if ((!context) || (!context->pdb_methods)) { + DEBUG(0, ("invalid pdb_context specified!\n")); + return ret; + } + + return context->pdb_methods->lookup_rids(context->pdb_methods, + mem_ctx, domain_sid, num_rids, + rids, names, attrs); } /****************************************************************** @@ -788,6 +812,7 @@ static NTSTATUS make_pdb_context(struct pdb_context **context) (*context)->pdb_del_aliasmem = context_del_aliasmem; (*context)->pdb_enum_aliasmem = context_enum_aliasmem; (*context)->pdb_enum_alias_memberships = context_enum_alias_memberships; + (*context)->pdb_lookup_rids = context_lookup_rids; (*context)->free_fn = free_pdb_context; @@ -1252,8 +1277,9 @@ BOOL pdb_enum_aliasmem(const DOM_SID *alias, members, num_members)); } -BOOL pdb_enum_alias_memberships(const DOM_SID *members, int num_members, - DOM_SID **aliases, int *num) +BOOL pdb_enum_alias_memberships(TALLOC_CTX *mem_ctx, const DOM_SID *domain_sid, + const DOM_SID *members, int num_members, + uint32 **alias_rids, int *num_alias_rids) { struct pdb_context *pdb_context = pdb_get_static_context(False); @@ -1262,9 +1288,28 @@ BOOL pdb_enum_alias_memberships(const DOM_SID *members, int num_members, } return NT_STATUS_IS_OK(pdb_context-> - pdb_enum_alias_memberships(pdb_context, members, - num_members, - aliases, num)); + pdb_enum_alias_memberships(pdb_context, mem_ctx, + domain_sid, + members, num_members, + alias_rids, + num_alias_rids)); +} + +NTSTATUS pdb_lookup_rids(TALLOC_CTX *mem_ctx, + const DOM_SID *domain_sid, + int num_rids, + uint32 *rids, + const char ***names, + uint32 **attrs) +{ + struct pdb_context *pdb_context = pdb_get_static_context(False); + + if (!pdb_context) { + return NT_STATUS_NOT_IMPLEMENTED; + } + + return pdb_context->pdb_lookup_rids(pdb_context, mem_ctx, domain_sid, + num_rids, rids, names, attrs); } /*************************************************************** @@ -1439,6 +1484,65 @@ NTSTATUS pdb_default_enum_group_members(struct pdb_methods *methods, return NT_STATUS_OK; } +NTSTATUS pdb_default_lookup_rids(struct pdb_methods *methods, + TALLOC_CTX *mem_ctx, + const DOM_SID *domain_sid, + int num_rids, + uint32 *rids, + const char ***names, + uint32 **attrs) +{ + int i; + NTSTATUS result; + BOOL have_mapped = False; + BOOL have_unmapped = False; + + (*names) = TALLOC_ZERO_ARRAY(mem_ctx, const char *, num_rids); + (*attrs) = TALLOC_ZERO_ARRAY(mem_ctx, uint32, num_rids); + + if ((num_rids != 0) && (((*names) == NULL) || ((*attrs) == NULL))) + return NT_STATUS_NO_MEMORY; + + if (!sid_equal(domain_sid, get_global_sam_sid())) { + /* TODO: Sooner or later we need to look up BUILTIN rids as + * well. -- vl */ + goto done; + } + + for (i = 0; i < num_rids; i++) { + fstring tmpname; + fstring domname; + DOM_SID sid; + enum SID_NAME_USE type; + + (*attrs)[i] = SID_NAME_UNKNOWN; + + sid_copy(&sid, domain_sid); + sid_append_rid(&sid, rids[i]); + + if (lookup_sid(&sid, domname, tmpname, &type)) { + (*attrs)[i] = (uint32)type; + (*names)[i] = talloc_strdup(mem_ctx, tmpname); + if ((*names)[i] == NULL) + return NT_STATUS_NO_MEMORY; + DEBUG(5,("lookup_rids: %s:%d\n", (*names)[i], + (*attrs)[i])); + have_mapped = True; + } else { + have_unmapped = True; + } + } + + done: + + result = NT_STATUS_NONE_MAPPED; + + if (have_mapped) + result = have_unmapped ? STATUS_SOME_UNMAPPED : NT_STATUS_OK; + + return result; +} + NTSTATUS make_pdb_methods(TALLOC_CTX *mem_ctx, PDB_METHODS **methods) { *methods = TALLOC_P(mem_ctx, struct pdb_methods); @@ -1478,6 +1582,365 @@ NTSTATUS make_pdb_methods(TALLOC_CTX *mem_ctx, PDB_METHODS **methods) (*methods)->del_aliasmem = pdb_default_del_aliasmem; (*methods)->enum_aliasmem = pdb_default_enum_aliasmem; (*methods)->enum_alias_memberships = pdb_default_alias_memberships; + (*methods)->lookup_rids = pdb_default_lookup_rids; return NT_STATUS_OK; } + +struct pdb_search *pdb_search_users(uint16 acct_flags); +struct pdb_search *pdb_search_groups(void); +struct pdb_search *pdb_search_aliases(const DOM_SID *sid); +uint32 pdb_search_entries(struct pdb_search *search, uint32 start_idx, uint32 max_entries, struct samr_displayentry **result); +void pdb_search_destroy(struct pdb_search *search); + +static struct pdb_search *pdb_search_init(enum pdb_search_type type) +{ + TALLOC_CTX *mem_ctx; + struct pdb_search *result; + + mem_ctx = talloc_init("pdb_search"); + if (mem_ctx == NULL) { + DEBUG(0, ("talloc_init failed\n")); + return NULL; + } + + result = TALLOC_P(mem_ctx, struct pdb_search); + if (result == NULL) { + DEBUG(0, ("talloc failed\n")); + return NULL; + } + + result->mem_ctx = mem_ctx; + result->type = type; + result->cache = NULL; + result->cache_size = 0; + result->search_ended = False; + + return result; +} + +static void fill_displayentry(TALLOC_CTX *mem_ctx, uint32 rid, + uint16 acct_flags, + const char *account_name, + const char *fullname, + const char *description, + struct samr_displayentry *entry) +{ + entry->rid = rid; + entry->acct_flags = acct_flags; + + if (account_name != NULL) + entry->account_name = talloc_strdup(mem_ctx, account_name); + + if (fullname != NULL) + entry->fullname = talloc_strdup(mem_ctx, fullname); + + if (description != NULL) + entry->description = talloc_strdup(mem_ctx, description); +} + +static BOOL user_search_in_progress = False; +struct user_search { + uint16 acct_flags; +}; + +struct pdb_search *pdb_search_users(uint16 acct_flags) +{ + struct pdb_search *result; + struct user_search *state; + + if (user_search_in_progress) { + DEBUG(1, ("user search in progress\n")); + return NULL; + } + + if (!pdb_setsampwent(False, acct_flags)) + return NULL; + + user_search_in_progress = True; + + result = pdb_search_init(PDB_USER_SEARCH); + if (result == NULL) + return NULL; + + state = TALLOC_P(result->mem_ctx, struct user_search); + if (state == NULL) { + DEBUG(0, ("talloc failed\n")); + talloc_destroy(result->mem_ctx); + return NULL; + } + + state->acct_flags = acct_flags; + + result->private = state; + return result; +} + +static BOOL pdb_search_entry_users(struct pdb_search *s, TALLOC_CTX *mem_ctx, + struct samr_displayentry *entry) +{ + struct user_search *state = s->private; + SAM_ACCOUNT *user = NULL; + NTSTATUS status; + + next: + status = pdb_init_sam(&user); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0, ("Could not pdb_init_sam\n")); + return False; + } + + if (!pdb_getsampwent(user)) { + pdb_free_sam(&user); + return False; + } + + if ((state->acct_flags != 0) && + ((pdb_get_acct_ctrl(user) & state->acct_flags) == 0)) { + pdb_free_sam(&user); + goto next; + } + + fill_displayentry(mem_ctx, pdb_get_user_rid(user), + pdb_get_acct_ctrl(user), pdb_get_username(user), + pdb_get_fullname(user), pdb_get_acct_desc(user), + entry); + + pdb_free_sam(&user); + return True; +} + +static void pdb_search_end_users(struct pdb_search *search) +{ + pdb_endsampwent(); + user_search_in_progress = False; +} + +struct group_search { + GROUP_MAP *groups; + int num_groups, current_group; +}; + +struct pdb_search *pdb_search_groups(void) +{ + struct pdb_search *result; + struct group_search *state; + + result = pdb_search_init(PDB_GROUP_SEARCH); + if (result == NULL) + return NULL; + + state = TALLOC_P(result->mem_ctx, struct group_search); + if (state == NULL) { + DEBUG(0, ("talloc failed\n")); + talloc_destroy(result->mem_ctx); + return NULL; + } + + if (!pdb_enum_group_mapping(SID_NAME_DOM_GRP, &state->groups, + &state->num_groups, True)) { + DEBUG(0, ("Could not enum groups\n")); + talloc_destroy(result->mem_ctx); + return NULL; + } + + state->current_group = 0; + result->private = state; + return result; +} + +static BOOL pdb_search_entry_group(struct pdb_search *s, TALLOC_CTX *mem_ctx, + struct samr_displayentry *entry) +{ + struct group_search *state = s->private; + uint32 rid; + GROUP_MAP *map = &state->groups[state->current_group]; + + if (state->current_group == state->num_groups) + return False; + + sid_peek_rid(&map->sid, &rid); + + fill_displayentry(mem_ctx, rid, 0, map->nt_name, NULL, map->comment, + entry); + + state->current_group += 1; + return True; +} + +static void pdb_search_end_groups(struct pdb_search *search) +{ + struct group_search *state = search->private; + SAFE_FREE(state->groups); +} + +struct alias_search { + GROUP_MAP *aliases; + int num_aliases, current_alias; +}; + +struct pdb_search *pdb_search_aliases(const DOM_SID *sid) +{ + struct pdb_search *result; + struct alias_search *state; + enum SID_NAME_USE type = SID_NAME_UNKNOWN; + DOM_SID builtin_sid; + + if (sid_equal(sid, get_global_sam_sid())) + type = SID_NAME_ALIAS; + + string_to_sid(&builtin_sid, "S-1-5-32"); + + if (sid_equal(sid, &builtin_sid)) + type = SID_NAME_WKN_GRP; + + if (type == SID_NAME_UNKNOWN) { + DEBUG(3, ("unknown domain sid: %s\n", sid_string_static(sid))); + return NULL; + } + + result = pdb_search_init(PDB_ALIAS_SEARCH); + if (result == NULL) + return NULL; + + state = TALLOC_P(result->mem_ctx, struct alias_search); + if (state == NULL) { + DEBUG(0, ("talloc failed\n")); + talloc_destroy(result->mem_ctx); + return NULL; + } + + if (!pdb_enum_group_mapping(type, &state->aliases, + &state->num_aliases, False)) { + DEBUG(0, ("Could not enum aliases\n")); + talloc_destroy(result->mem_ctx); + return NULL; + } + + state->current_alias = 0; + result->private = state; + return result; +} + +static BOOL pdb_search_entry_alias(struct pdb_search *s, TALLOC_CTX *mem_ctx, + struct samr_displayentry *entry) +{ + struct alias_search *state = s->private; + uint32 rid; + GROUP_MAP *map = &state->aliases[state->current_alias]; + + if (state->current_alias == state->num_aliases) + return False; + + sid_peek_rid(&map->sid, &rid); + + fill_displayentry(mem_ctx, rid, 0, map->nt_name, NULL, map->comment, + entry); + + state->current_alias += 1; + return True; +} + +static void pdb_search_end_aliases(struct pdb_search *search) +{ + struct alias_search *state = search->private; + SAFE_FREE(state->aliases); +} + +static BOOL pdb_search_entry(struct pdb_search *search, TALLOC_CTX *mem_ctx, + struct samr_displayentry *entry) +{ + BOOL result = False; + switch (search->type) { + case PDB_USER_SEARCH: + result = pdb_search_entry_users(search, mem_ctx, entry); + break; + case PDB_GROUP_SEARCH: + result = pdb_search_entry_group(search, mem_ctx, entry); + break; + case PDB_ALIAS_SEARCH: + result = pdb_search_entry_alias(search, mem_ctx, entry); + break; + default: + DEBUG(0, ("unknown search type: %d\n", search->type)); + break; + } + return result; +} + +static void pdb_search_end(struct pdb_search *search) +{ + switch (search->type) { + case PDB_USER_SEARCH: + pdb_search_end_users(search); + break; + case PDB_GROUP_SEARCH: + pdb_search_end_groups(search); + break; + case PDB_ALIAS_SEARCH: + pdb_search_end_aliases(search); + break; + default: + DEBUG(0, ("unknown search type: %d\n", search->type)); + break; + } +} + +static struct samr_displayentry *pdb_search_getentry(struct pdb_search *search, + uint32 idx) +{ + if (idx < search->cache_size) + return &search->cache[idx]; + + if (search->search_ended) + return NULL; + + while (idx >= search->cache_size) { + struct samr_displayentry entry; + + if (!pdb_search_entry(search, search->mem_ctx, &entry)) { + pdb_search_end(search); + search->search_ended = True; + break; + } + + ADD_TO_ARRAY(search->mem_ctx, struct samr_displayentry, + entry, &search->cache, &search->cache_size); + } + + return (search->cache_size > idx) ? &search->cache[idx] : NULL; +} + +uint32 pdb_search_entries(struct pdb_search *search, + uint32 start_idx, uint32 max_entries, + struct samr_displayentry **result) +{ + struct samr_displayentry *end_entry; + uint32 end_idx = start_idx+max_entries-1; + + /* The first entry needs to be searched after the last. Otherwise the + * first entry might have moved due to a realloc during the search for + * the last entry. */ + + end_entry = pdb_search_getentry(search, end_idx); + *result = pdb_search_getentry(search, start_idx); + + if (end_entry != NULL) + return max_entries; + + if (start_idx >= search->cache_size) + return 0; + + return search->cache_size - start_idx; +} + +void pdb_search_destroy(struct pdb_search *search) +{ + if (search == NULL) + return; + + if (!search->search_ended) + pdb_search_end(search); + + talloc_destroy(search->mem_ctx); +} diff --git a/source/passdb/pdb_ldap.c b/source/passdb/pdb_ldap.c index 3dab919cb46..3899949058a 100644 --- a/source/passdb/pdb_ldap.c +++ b/source/passdb/pdb_ldap.c @@ -462,7 +462,7 @@ static BOOL init_sam_from_ldap(struct ldapsam_privates *ldap_state, uint8 hours[MAX_HOURS_LEN]; pstring temp; LOGIN_CACHE *cache_entry = NULL; - int pwHistLen; + uint32 pwHistLen; pstring tmpstring; /* @@ -694,8 +694,8 @@ static BOOL init_sam_from_ldap(struct ldapsam_privates *ldap_state, if (ldap_state->is_nds_ldap) { char *user_dn; - size_t pwd_len; - uchar clear_text_pw[512]; + int pwd_len; + char clear_text_pw[512]; /* Make call to Novell eDirectory ldap extension to get clear text password. NOTE: This will only work if we have an SSL connection to eDirectory. */ @@ -1086,14 +1086,15 @@ static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state, } if (need_update(sampass, PDB_PWHISTORY)) { - int pwHistLen = 0; + uint32 pwHistLen = 0; account_policy_get(AP_PASSWORD_HISTORY, &pwHistLen); if (pwHistLen == 0) { /* Remove any password history from the LDAP store. */ memset(temp, '0', 64); /* NOTE !!!! '0' *NOT '\0' */ temp[64] = '\0'; } else { - int i, currHistLen = 0; + int i; + uint32 currHistLen = 0; const uint8 *pwhist = pdb_get_pw_history(sampass, &currHistLen); if (pwhist != NULL) { /* We can only store (sizeof(pstring)-1)/64 password history entries. */ @@ -1122,7 +1123,7 @@ static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state, } if (need_update(sampass, PDB_HOURS)) { - const char *hours = pdb_get_hours(sampass); + const uint8 *hours = pdb_get_hours(sampass); if (hours) { pdb_sethexhours(temp, hours); smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, @@ -2207,6 +2208,39 @@ static void add_rid_to_array_unique(TALLOC_CTX *mem_ctx, *num += 1; } +static BOOL ldapsam_extract_rid_from_entry(LDAP *ldap_struct, + LDAPMessage *entry, + const DOM_SID *domain_sid, + uint32 *rid) +{ + fstring str; + DOM_SID sid; + + if (!smbldap_get_single_attribute(ldap_struct, entry, "sambaSID", + str, sizeof(str)-1)) { + DEBUG(10, ("Could not find sambaSID attribute\n")); + return False; + } + + if (!string_to_sid(&sid, str)) { + DEBUG(10, ("Could not convert string %s to sid\n", str)); + return False; + } + + if (sid_compare_domain(&sid, domain_sid) != 0) { + DEBUG(10, ("SID %s is not in expected domain %s\n", + str, sid_string_static(domain_sid))); + return False; + } + + if (!sid_peek_rid(&sid, rid)) { + DEBUG(10, ("Could not peek into RID\n")); + return False; + } + + return True; +} + static NTSTATUS ldapsam_enum_group_members(struct pdb_methods *methods, TALLOC_CTX *mem_ctx, const DOM_SID *group, @@ -2253,26 +2287,16 @@ static NTSTATUS ldapsam_enum_group_members(struct pdb_methods *methods, entry != NULL; entry = ldap_next_entry(conn->ldap_struct, entry)) { - fstring str; - DOM_SID sid; uint32 rid; - if (!smbldap_get_single_attribute(conn->ldap_struct, - entry, "sambaSID", - str, sizeof(str)-1)) - continue; - - if (!string_to_sid(&sid, str)) - goto done; - - if (!sid_check_is_in_our_domain(&sid)) { - DEBUG(1, ("Inconsistent SAM -- group member uid not " - "in our domain\n")); + if (!ldapsam_extract_rid_from_entry(conn->ldap_struct, + entry, + get_global_sam_sid(), + &rid)) { + DEBUG(2, ("Could not find sid from ldap entry\n")); continue; } - sid_peek_rid(&sid, &rid); - add_rid_to_array_unique(mem_ctx, rid, member_rids, num_members); } @@ -2412,7 +2436,6 @@ static NTSTATUS ldapsam_enum_group_memberships(struct pdb_methods *methods, LDAPMessage *entry; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; int num_sids, num_gids; - extern DOM_SID global_sid_NULL; if (!lp_parm_bool(-1, "ldapsam", "trusted", False)) return pdb_default_enum_group_memberships(methods, username, @@ -2445,11 +2468,11 @@ static NTSTATUS ldapsam_enum_group_memberships(struct pdb_methods *methods, /* We need to add the primary group as the first gid/sid */ - add_gid_to_array_unique(primary_gid, gids, &num_gids); + add_gid_to_array_unique(NULL, primary_gid, gids, &num_gids); /* This sid will be replaced later */ - add_sid_to_array_unique(&global_sid_NULL, sids, &num_sids); + add_sid_to_array_unique(NULL, &global_sid_NULL, sids, &num_sids); for (entry = ldap_first_entry(conn->ldap_struct, msg); entry != NULL; @@ -2481,8 +2504,8 @@ static NTSTATUS ldapsam_enum_group_memberships(struct pdb_methods *methods, if (gid == primary_gid) { sid_copy(&(*sids)[0], &sid); } else { - add_gid_to_array_unique(gid, gids, &num_gids); - add_sid_to_array_unique(&sid, sids, &num_sids); + add_gid_to_array_unique(NULL, gid, gids, &num_gids); + add_sid_to_array_unique(NULL, &sid, sids, &num_sids); } } @@ -3028,7 +3051,7 @@ static NTSTATUS ldapsam_enum_aliasmem(struct pdb_methods *methods, if (!string_to_sid(&member, values[i])) continue; - add_sid_to_array(&member, members, num_members); + add_sid_to_array(NULL, &member, members, num_members); } ldap_value_free(values); @@ -3038,9 +3061,12 @@ static NTSTATUS ldapsam_enum_aliasmem(struct pdb_methods *methods, } static NTSTATUS ldapsam_alias_memberships(struct pdb_methods *methods, + TALLOC_CTX *mem_ctx, + const DOM_SID *domain_sid, const DOM_SID *members, int num_members, - DOM_SID **aliases, int *num_aliases) + uint32 **alias_rids, + int *num_alias_rids) { struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)methods->private_data; @@ -3053,12 +3079,6 @@ static NTSTATUS ldapsam_alias_memberships(struct pdb_methods *methods, int i; int rc; char *filter; - TALLOC_CTX *mem_ctx; - - mem_ctx = talloc_init("ldapsam_alias_memberships"); - - if (mem_ctx == NULL) - return NT_STATUS_NO_MEMORY; /* This query could be further optimized by adding a (&(sambaSID=*)) so that only those aliases that are @@ -3083,9 +3103,6 @@ static NTSTATUS ldapsam_alias_memberships(struct pdb_methods *methods, if (rc != LDAP_SUCCESS) return NT_STATUS_UNSUCCESSFUL; - *aliases = NULL; - *num_aliases = 0; - ldap_struct = ldap_state->smbldap_state->ldap_struct; for (entry = ldap_first_entry(ldap_struct, result); @@ -3094,6 +3111,7 @@ static NTSTATUS ldapsam_alias_memberships(struct pdb_methods *methods, { fstring sid_str; DOM_SID sid; + uint32 rid; if (!smbldap_get_single_attribute(ldap_struct, entry, LDAP_ATTRIBUTE_SID, @@ -3104,13 +3122,207 @@ static NTSTATUS ldapsam_alias_memberships(struct pdb_methods *methods, if (!string_to_sid(&sid, sid_str)) continue; - add_sid_to_array_unique(&sid, aliases, num_aliases); + if (!sid_peek_check_rid(domain_sid, &sid, &rid)) + continue; + + add_rid_to_array_unique(mem_ctx, rid, alias_rids, + num_alias_rids); } ldap_msgfree(result); return NT_STATUS_OK; } +static NTSTATUS ldapsam_lookup_rids(struct pdb_methods *methods, + TALLOC_CTX *mem_ctx, + const DOM_SID *domain_sid, + int num_rids, + uint32 *rids, + const char ***names, + uint32 **attrs) +{ + struct ldapsam_privates *ldap_state = + (struct ldapsam_privates *)methods->private_data; + LDAP *ldap_struct = ldap_state->smbldap_state->ldap_struct; + LDAPMessage *msg = NULL; + LDAPMessage *entry; + char *allsids = NULL; + char *tmp; + int i, rc, num_mapped; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + + if (!lp_parm_bool(-1, "ldapsam", "trusted", False)) + return pdb_default_lookup_rids(methods, mem_ctx, domain_sid, + num_rids, rids, names, attrs); + + if (!sid_equal(domain_sid, get_global_sam_sid())) { + /* TODO: Sooner or later we need to look up BUILTIN rids as + * well. -- vl */ + goto done; + } + + (*names) = TALLOC_ZERO_ARRAY(mem_ctx, const char *, num_rids); + (*attrs) = TALLOC_ARRAY(mem_ctx, uint32, num_rids); + + if ((num_rids != 0) && (((*names) == NULL) || ((*attrs) == NULL))) + return NT_STATUS_NO_MEMORY; + + for (i=0; ismbldap_state, + lp_ldap_user_suffix(), + LDAP_SCOPE_SUBTREE, filter, ldap_attrs, 0, + &msg); + + SAFE_FREE(filter); + } + + if (rc != LDAP_SUCCESS) + goto done; + + num_mapped = 0; + + for (entry = ldap_first_entry(ldap_struct, msg); + entry != NULL; + entry = ldap_next_entry(ldap_struct, entry)) + { + uint32 rid; + int rid_index; + fstring str; + + if (!ldapsam_extract_rid_from_entry(ldap_struct, entry, + get_global_sam_sid(), + &rid)) { + DEBUG(2, ("Could not find sid from ldap entry\n")); + continue; + } + + if (!smbldap_get_single_attribute(ldap_struct, entry, + "uid", str, sizeof(str)-1)) { + DEBUG(2, ("Could not retrieve uid attribute\n")); + continue; + } + + for (rid_index = 0; rid_index < num_rids; rid_index++) { + if (rid == rids[rid_index]) + break; + } + + if (rid_index == num_rids) { + DEBUG(2, ("Got a RID not asked for: %d\n", rid)); + continue; + } + + (*attrs)[rid_index] = SID_NAME_USER; + (*names)[rid_index] = talloc_strdup(mem_ctx, str); + if ((*names)[rid_index] == NULL) return NT_STATUS_NO_MEMORY; + + num_mapped += 1; + } + + if (num_mapped == num_rids) { + /* No need to look for groups anymore -- we're done */ + result = NT_STATUS_OK; + goto done; + } + + /* Same game for groups */ + + { + char *filter; + const char *ldap_attrs[] = { "cn", "sambaSid", NULL }; + + asprintf(&filter, ("(&(objectClass=sambaGroupMapping)(|%s))"), + allsids); + if (filter == NULL) return NT_STATUS_NO_MEMORY; + + rc = smbldap_search(ldap_state->smbldap_state, + lp_ldap_group_suffix(), + LDAP_SCOPE_SUBTREE, filter, ldap_attrs, 0, + &msg); + + SAFE_FREE(filter); + } + + if (rc != LDAP_SUCCESS) + goto done; + + for (entry = ldap_first_entry(ldap_struct, msg); + entry != NULL; + entry = ldap_next_entry(ldap_struct, entry)) + { + uint32 rid; + int rid_index; + fstring str; + + if (!ldapsam_extract_rid_from_entry(ldap_struct, entry, + get_global_sam_sid(), + &rid)) { + DEBUG(2, ("Could not find sid from ldap entry\n")); + continue; + } + + if (!smbldap_get_single_attribute(ldap_struct, entry, + "cn", str, sizeof(str)-1)) { + DEBUG(2, ("Could not retrieve cn attribute\n")); + continue; + } + + for (rid_index = 0; rid_index < num_rids; rid_index++) { + if (rid == rids[rid_index]) + break; + } + + if (rid_index == num_rids) { + DEBUG(2, ("Got a RID not asked for: %d\n", rid)); + continue; + } + + (*attrs)[rid_index] = SID_NAME_DOM_GRP; + (*names)[rid_index] = talloc_strdup(mem_ctx, str); + if ((*names)[rid_index] == NULL) return NT_STATUS_NO_MEMORY; + num_mapped += 1; + } + + result = NT_STATUS_NONE_MAPPED; + + if (num_mapped > 0) + result = (num_mapped == num_rids) ? + NT_STATUS_OK : STATUS_SOME_UNMAPPED; + done: + SAFE_FREE(allsids); + + if (msg != NULL) + ldap_msgfree(msg); + + return result; +} + /********************************************************************** Housekeeping *********************************************************************/ @@ -3168,6 +3380,7 @@ static NTSTATUS pdb_init_ldapsam_common(PDB_CONTEXT *pdb_context, PDB_METHODS ** (*pdb_method)->enum_group_mapping = ldapsam_enum_group_mapping; (*pdb_method)->enum_group_members = ldapsam_enum_group_members; (*pdb_method)->enum_group_memberships = ldapsam_enum_group_memberships; + (*pdb_method)->lookup_rids = ldapsam_lookup_rids; /* TODO: Setup private data and free */ diff --git a/source/passdb/secrets.c b/source/passdb/secrets.c index 6be63e4f9d6..c7ff2f80b00 100644 --- a/source/passdb/secrets.c +++ b/source/passdb/secrets.c @@ -84,13 +84,11 @@ BOOL secrets_init(void) */ void *secrets_fetch(const char *key, size_t *size) { - TDB_DATA kbuf, dbuf; + TDB_DATA dbuf; secrets_init(); if (!tdb) return NULL; - kbuf.dptr = (char *)key; - kbuf.dsize = strlen(key); - dbuf = tdb_fetch(tdb, kbuf); + dbuf = tdb_fetch(tdb, string_tdb_data(key)); if (size) *size = dbuf.dsize; return dbuf.dptr; @@ -100,15 +98,11 @@ void *secrets_fetch(const char *key, size_t *size) */ BOOL secrets_store(const char *key, const void *data, size_t size) { - TDB_DATA kbuf, dbuf; secrets_init(); if (!tdb) return False; - kbuf.dptr = (char *)key; - kbuf.dsize = strlen(key); - dbuf.dptr = (char *)data; - dbuf.dsize = size; - return tdb_store(tdb, kbuf, dbuf, TDB_REPLACE) == 0; + return tdb_store(tdb, string_tdb_data(key), make_tdb_data(data, size), + TDB_REPLACE) == 0; } @@ -116,13 +110,10 @@ BOOL secrets_store(const char *key, const void *data, size_t size) */ BOOL secrets_delete(const char *key) { - TDB_DATA kbuf; secrets_init(); if (!tdb) return False; - kbuf.dptr = (char *)key; - kbuf.dsize = strlen(key); - return tdb_delete(tdb, kbuf) == 0; + return tdb_delete(tdb, string_tdb_data(key)) == 0; } BOOL secrets_store_domain_sid(const char *domain, const DOM_SID *sid) diff --git a/source/passdb/util_sam_sid.c b/source/passdb/util_sam_sid.c index 1fddfc79255..a9e1921e0d0 100644 --- a/source/passdb/util_sam_sid.c +++ b/source/passdb/util_sam_sid.c @@ -32,17 +32,11 @@ typedef struct _known_sid_users { static struct sid_name_map_info { - DOM_SID *sid; + const DOM_SID *sid; const char *name; const known_sid_users *known_users; } sid_name_map[MAX_SID_NAMES]; -extern DOM_SID global_sid_Builtin; /* Local well-known domain */ -extern DOM_SID global_sid_World_Domain; /* Everyone domain */ -extern DOM_SID global_sid_Creator_Owner_Domain; /* Creator Owner domain */ -extern DOM_SID global_sid_NT_Authority; /* NT Authority */ - - static BOOL sid_name_map_initialized = False; /* static known_sid_users no_users[] = {{0, 0, NULL}}; */ @@ -99,8 +93,6 @@ static void init_sid_name_map (void) if (sid_name_map_initialized) return; - generate_wellknown_sids(); - if ((lp_security() == SEC_USER) && lp_domain_logons()) { sid_name_map[i].sid = get_global_sam_sid(); /* This is not lp_workgroup() for good reason: diff --git a/source/printing/nt_printing.c b/source/printing/nt_printing.c index ad911c3b05b..40d815cead1 100644 --- a/source/printing/nt_printing.c +++ b/source/printing/nt_printing.c @@ -22,7 +22,7 @@ #include "includes.h" -extern DOM_SID global_sid_World; +extern struct current_user current_user; static TDB_CONTEXT *tdb_forms; /* used for forms files */ static TDB_CONTEXT *tdb_drivers; /* used for driver files */ @@ -1494,7 +1494,7 @@ BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, DEBUG(5,("Creating first directory\n")); slprintf(new_dir, sizeof(new_dir)-1, "%s/%d", architecture, driver->cversion); driver_unix_convert(new_dir, conn, NULL, &bad_path, &st); - mkdir_internal(conn, new_dir); + mkdir_internal(conn, new_dir, bad_path); /* For each driver file, archi\filexxx.yyy, if there is a duplicate file * listed for this driver which has already been moved, skip it (note: @@ -5115,7 +5115,6 @@ BOOL print_access_check(struct current_user *user, int snum, int access_type) BOOL result; const char *pname; TALLOC_CTX *mem_ctx = NULL; - extern struct current_user current_user; SE_PRIV se_printop = SE_PRINT_OPERATOR; /* If user is NULL then use the current_user structure */ diff --git a/source/printing/printfsp.c b/source/printing/printfsp.c index 7c5de468701..25f4d9bd464 100644 --- a/source/printing/printfsp.c +++ b/source/printing/printfsp.c @@ -21,6 +21,8 @@ #include "includes.h" +extern struct current_user current_user; + /*************************************************************************** open a print file and setup a fsp for it. This is a wrapper around print_job_start(). @@ -30,7 +32,6 @@ files_struct *print_fsp_open(connection_struct *conn, char *fname) { int jobid; SMB_STRUCT_STAT sbuf; - extern struct current_user current_user; files_struct *fsp = file_new(conn); fstring name; diff --git a/source/printing/printing.c b/source/printing/printing.c index 5483005e1bd..572ecb373a8 100644 --- a/source/printing/printing.c +++ b/source/printing/printing.c @@ -45,7 +45,7 @@ static BOOL remove_from_jobs_changed(const char* sharename, uint32 jobid); struct print_queue_update_context { char* sharename; - enum printing_types printing_type; + int printing_type; char* lpqcommand; }; @@ -235,7 +235,7 @@ void printing_end(void) when asked for (and only when supported) ****************************************************************************/ -static struct printif *get_printer_fns_from_type( enum printing_types type ) +static struct printif *get_printer_fns_from_type( int type ) { struct printif *printer_fns = &generic_printif; @@ -907,7 +907,7 @@ static int printjob_comp(print_queue_struct *j1, print_queue_struct *j2) static void store_queue_struct(struct tdb_print_db *pdb, struct traverse_struct *pts) { - TDB_DATA data, key; + TDB_DATA data; int max_reported_jobs = lp_max_reported_jobs(pts->snum); print_queue_struct *queue = pts->queue; size_t len; @@ -951,22 +951,19 @@ static void store_queue_struct(struct tdb_print_db *pdb, struct traverse_struct queue[i].fs_file); } - key.dptr = "INFO/linear_queue_array"; - key.dsize = strlen(key.dptr); - tdb_store(pdb->tdb, key, data, TDB_REPLACE); + tdb_store(pdb->tdb, string_tdb_data("INFO/linear_queue_array"), data, + TDB_REPLACE); SAFE_FREE(data.dptr); return; } static TDB_DATA get_jobs_changed_data(struct tdb_print_db *pdb) { - TDB_DATA data, key; + TDB_DATA data; - key.dptr = "INFO/jobs_changed"; - key.dsize = strlen(key.dptr); ZERO_STRUCT(data); - data = tdb_fetch(pdb->tdb, key); + data = tdb_fetch(pdb->tdb, string_tdb_data("INFO/jobs_changed")); if (data.dptr == NULL || data.dsize == 0 || (data.dsize % 4 != 0)) { SAFE_FREE(data.dptr); ZERO_STRUCT(data); @@ -1035,7 +1032,7 @@ static BOOL print_cache_expired(const char *sharename, BOOL check_pending) snprintf(key, sizeof(key), "MSG_PENDING/%s", sharename); if ( check_pending - && tdb_fetch_uint32( pdb->tdb, key, &msg_pending_time ) + && tdb_fetch_uint32( pdb->tdb, key, (uint32*)&msg_pending_time ) && msg_pending_time > 0 && msg_pending_time <= time_now && (time_now - msg_pending_time) < 60 ) @@ -1382,7 +1379,7 @@ static void print_queue_update(int snum, BOOL force) size_t len = 0; size_t newlen; struct tdb_print_db *pdb; - enum printing_types type; + int type; struct printif *current_printif; fstrcpy( sharename, lp_const_servicename(snum)); @@ -1736,10 +1733,10 @@ static BOOL remove_from_jobs_changed(const char* sharename, uint32 jobid) BOOL ret = False; BOOL gotlock = False; - key.dptr = "INFO/jobs_changed"; - key.dsize = strlen(key.dptr); ZERO_STRUCT(data); + key = string_tdb_data("INFO/jobs_changed"); + if (tdb_chainlock_with_timeout(pdb->tdb, key, 5) == -1) goto out; @@ -2057,7 +2054,7 @@ int print_job_write(int snum, uint32 jobid, const char *buf, int size) static int get_queue_status(const char* sharename, print_status_struct *status) { fstring keystr; - TDB_DATA data, key; + TDB_DATA data; struct tdb_print_db *pdb = get_print_db_byname(sharename); int len; @@ -2066,10 +2063,8 @@ static int get_queue_status(const char* sharename, print_status_struct *status) if (status) { ZERO_STRUCTP(status); - slprintf(keystr, sizeof(keystr)-1, "STATUS/%s", sharename); - key.dptr = keystr; - key.dsize = strlen(keystr); - data = tdb_fetch(pdb->tdb, key); + fstr_sprintf(keystr, "STATUS/%s", sharename); + data = tdb_fetch(pdb->tdb, string_tdb_data(keystr)); if (data.dptr) { if (data.dsize == sizeof(print_status_struct)) /* this memcpy is ok since the status struct was @@ -2179,18 +2174,17 @@ static BOOL allocate_print_jobid(struct tdb_print_db *pdb, int snum, const char static BOOL add_to_jobs_changed(struct tdb_print_db *pdb, uint32 jobid) { - TDB_DATA data, key; + TDB_DATA data; uint32 store_jobid; - key.dptr = "INFO/jobs_changed"; - key.dsize = strlen(key.dptr); SIVAL(&store_jobid, 0, jobid); data.dptr = (char *)&store_jobid; data.dsize = 4; DEBUG(10,("add_to_jobs_changed: Added jobid %u\n", (unsigned int)jobid )); - return (tdb_append(pdb->tdb, key, data) == 0); + return (tdb_append(pdb->tdb, string_tdb_data("INFO/jobs_changed"), + data) == 0); } /*************************************************************************** @@ -2429,7 +2423,7 @@ fail: static BOOL get_stored_queue_info(struct tdb_print_db *pdb, int snum, int *pcount, print_queue_struct **ppqueue) { - TDB_DATA data, key, cgdata; + TDB_DATA data, cgdata; print_queue_struct *queue = NULL; uint32 qcount = 0; uint32 extra_count = 0; @@ -2449,20 +2443,15 @@ static BOOL get_stored_queue_info(struct tdb_print_db *pdb, int snum, int *pcoun ZERO_STRUCT(data); ZERO_STRUCT(cgdata); - key.dptr = "INFO/linear_queue_array"; - key.dsize = strlen(key.dptr); /* Get the stored queue data. */ - data = tdb_fetch(pdb->tdb, key); + data = tdb_fetch(pdb->tdb, string_tdb_data("INFO/linear_queue_array")); if (data.dptr && data.dsize >= sizeof(qcount)) len += tdb_unpack(data.dptr + len, data.dsize - len, "d", &qcount); /* Get the changed jobs list. */ - key.dptr = "INFO/jobs_changed"; - key.dsize = strlen(key.dptr); - - cgdata = tdb_fetch(pdb->tdb, key); + cgdata = tdb_fetch(pdb->tdb, string_tdb_data("INFO/jobs_changed")); if (cgdata.dptr != NULL && (cgdata.dsize % 4 == 0)) extra_count = cgdata.dsize/4; diff --git a/source/python/py_smb.c b/source/python/py_smb.c index c3d59d4fb8c..ad83e469b24 100644 --- a/source/python/py_smb.c +++ b/source/python/py_smb.c @@ -212,7 +212,7 @@ static PyObject *py_smb_read(PyObject *self, PyObject *args, PyObject *kw) static char *kwlist[] = { "fnum", "offset", "size", NULL }; int fnum, offset=0, size=0; ssize_t result; - size_t fsize; + SMB_OFF_T fsize; char *data; PyObject *ret; diff --git a/source/registry/reg_db.c b/source/registry/reg_db.c index 5ac83293090..f93b7e1ffba 100644 --- a/source/registry/reg_db.c +++ b/source/registry/reg_db.c @@ -65,6 +65,13 @@ static BOOL init_registry_data( void ) return False; regsubkey_ctr_destroy( &subkeys ); +#ifdef REG_TEST_CODE + pstrcpy( keyname, KEY_HKLM ); + pstrcat( keyname, "/SOFTWARE/Microsoft/Windows NT/CurrentVersion/Print" ); + if ( !regdb_store_reg_keys( keyname, &subkeys )) + return False; +#endif + regsubkey_ctr_init( &subkeys ); pstrcpy( keyname, KEY_HKLM ); pstrcat( keyname, "/SYSTEM/CurrentControlSet/Control" ); diff --git a/source/registry/reg_eventlog.c b/source/registry/reg_eventlog.c new file mode 100644 index 00000000000..cc2ffb5a057 --- /dev/null +++ b/source/registry/reg_eventlog.c @@ -0,0 +1,302 @@ +/* + * Unix SMB/CIFS implementation. + * RPC Pipe client / server routines + * Copyright (C) Marcin Krzysztof Porwit 2005. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "includes.h" + +/********************************************************************** + handle enumeration of values AT KEY_EVENTLOG + *********************************************************************/ + +static int eventlog_topkey_values( char *key, REGVAL_CTR *val ) +{ + int num_values = 0; + char *keystr, *key2 = NULL; + char *base, *new_path; + fstring evtlogname; + UNISTR2 data; + int iDisplayNameId; + int iMaxSize; + + /* + * TODO - callout to get these values... + */ + + if ( key ) + { + key2 = strdup( key ); + keystr = key2; + reg_split_path( keystr, &base, &new_path ); + + iDisplayNameId = 0x00000100; + iMaxSize= 0x00080000; + + fstrcpy( evtlogname, base ); + DEBUG(10,("eventlog_topkey_values: subkey root=> [%s] subkey path=>[%s]\n", base,new_path)); + + if ( !new_path ) + { + iDisplayNameId = 0x01; + regval_ctr_addvalue( val, "ErrorControl", REG_DWORD, (char*)&iDisplayNameId, sizeof(int) ); + + init_unistr2( &data, "EventLog", UNI_STR_TERMINATE); + regval_ctr_addvalue( val, "DisplayName", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) ); + + num_values = regval_ctr_numvals( val ); + + + num_values = 0; + } + } + + SAFE_FREE( key2 ); + return num_values; +} + +/********************************************************************** + handle enumeration of values below KEY_EVENTLOG\ + *********************************************************************/ + +static int eventlog_subkey_values( char *key, REGVAL_CTR *val ) +{ + int num_values = 0; + char *keystr, *key2 = NULL; + char *base, *new_path; + fstring evtlogname; + UNISTR2 data; + int iDisplayNameId; + int iMaxSize; + int iRetention; + + /* + * TODO - callout to get these values... + */ + + if ( !key ) + return num_values; + + key2 = SMB_STRDUP( key ); + keystr = key2; + reg_split_path( keystr, &base, &new_path ); + + iDisplayNameId = 0x00000100; + /* MaxSize is limited to 0xFFFF0000 (UINT_MAX - USHRT_MAX) as per MSDN documentation */ + iMaxSize= 0xFFFF0000; + /* records in the samba log are not overwritten */ + iRetention = 0xFFFFFFFF; + + fstrcpy( evtlogname, base ); + DEBUG(10,("eventlog_subpath_values_printer: eventlogname [%s]\n", base)); + DEBUG(10,("eventlog_subpath_values_printer: new_path [%s]\n", new_path)); + if ( !new_path ) + { +#if 0 + regval_ctr_addvalue( val, "DisplayNameId", REG_DWORD, (char*)&iDisplayNameId, sizeof(int) ); + + init_unistr2( &data, "%SystemRoot%\\system32\\els.dll", UNI_STR_TERMINATE); + regval_ctr_addvalue( val, "DisplayNameFile", REG_EXPAND_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) ); +#endif + regval_ctr_addvalue( val, "MaxSize", REG_DWORD, (char*)&iMaxSize, sizeof(int)); + regval_ctr_addvalue( val, "Retention", REG_DWORD, (char *)&iRetention, sizeof(int)); +#if 0 + init_unistr2( &data, lp_logfile(), UNI_STR_TERMINATE); + regval_ctr_addvalue( val, "File", REG_EXPAND_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) ); +#endif + init_unistr2( &data, base, UNI_STR_TERMINATE); + regval_ctr_addvalue( val, "PrimaryModule", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) ); + + init_unistr2( &data, base, UNI_STR_TERMINATE); + regval_ctr_addvalue( val, "Sources", REG_MULTI_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) ); + + num_values = regval_ctr_numvals( val ); + + } + else + { + iDisplayNameId = 0x07; + regval_ctr_addvalue( val, "CategoryCount", REG_DWORD, (char*)&iDisplayNameId, sizeof(int) ); + + init_unistr2( &data, "%SystemRoot%\\system32\\eventlog.dll", UNI_STR_TERMINATE); + regval_ctr_addvalue( val, "CategoryMessageFile", REG_EXPAND_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) ); + + num_values = regval_ctr_numvals( val ); + + num_values = 0; + } + + SAFE_FREE( key2 ); + return num_values; +} + + +/********************************************************************** + It is safe to assume that every registry path passed into on of + the exported functions here begins with KEY_EVENTLOG else + these functions would have never been called. This is a small utility + function to strip the beginning of the path and make a copy that the + caller can modify. Note that the caller is responsible for releasing + the memory allocated here. + **********************************************************************/ + +static char* trim_eventlog_reg_path( char *path ) +{ + char *p; + uint16 key_len = strlen(KEY_EVENTLOG); + + /* + * sanity check...this really should never be True. + * It is only here to prevent us from accessing outside + * the path buffer in the extreme case. + */ + + if ( strlen(path) < key_len ) { + DEBUG(0,("trim_reg_path: Registry path too short! [%s]\n", path)); + DEBUG(0,("trim_reg_path: KEY_EVENTLOG => [%s]!\n", KEY_EVENTLOG)); + return NULL; + } + + + p = path + strlen( KEY_EVENTLOG ); + + if ( *p == '\\' ) + p++; + + if ( *p ) + return SMB_STRDUP(p); + else + return NULL; +} +/********************************************************************** + Enumerate registry subkey names given a registry path. + Caller is responsible for freeing memory to **subkeys + *********************************************************************/ +int eventlog_subkey_info( char *key, REGSUBKEY_CTR *subkey_ctr ) +{ + char *path; + BOOL top_level = False; + int num_subkeys = 0; + const char **evtlog_list; + + path = trim_eventlog_reg_path( key ); + DEBUG(10,("eventlog_subkey_info: entire key=>[%s] SUBkey=>[%s]\n", key,path)); + + /* check to see if we are dealing with the top level key */ + num_subkeys = 0; + + if ( !path ) + top_level = True; + + evtlog_list = lp_eventlog_list(); + num_subkeys = 0; + + if ( top_level ) + { + /* todo - get the eventlog subkey values from the smb.conf file + for ( num_subkeys=0; num_subkeys[%s]\n",*evtlog_list)); + regsubkey_ctr_addkey( subkey_ctr, *evtlog_list); + evtlog_list++; + num_subkeys++; + } + } + else + { + while (*evtlog_list && (0==num_subkeys) ) + { + if (0 == StrCaseCmp(path,*evtlog_list)) + { + DEBUG(10,("eventlog_subkey_info: Adding subkey [%s] for key =>[%s]\n",path,*evtlog_list)); + regsubkey_ctr_addkey( subkey_ctr, *evtlog_list); + num_subkeys = 1; + } + evtlog_list++; + } + + if (0==num_subkeys) + DEBUG(10,("eventlog_subkey_info: No match on SUBkey=>[%s]\n", path)); + } + + SAFE_FREE( path ); + return num_subkeys; +} + +/********************************************************************** + Enumerate registry values given a registry path. + Caller is responsible for freeing memory + *********************************************************************/ + +int eventlog_value_info( char *key, REGVAL_CTR *val ) +{ + char *path; + BOOL top_level = False; + int num_values = 0; + + DEBUG(10,("eventlog_value_info: key=>[%s]\n", key)); + + path = trim_eventlog_reg_path( key ); + + /* check to see if we are dealing with the top level key */ + + if ( !path ) + top_level = True; + if ( top_level ) + num_values = eventlog_topkey_values(path,val); + else + { + DEBUG(10,("eventlog_value_info: SUBkey=>[%s]\n", path)); + num_values = eventlog_subkey_values(path,val); + } + return num_values; +} + +/********************************************************************** + Stub function which always returns failure since we don't want + people storing eventlog information directly via registry calls + (for now at least) + *********************************************************************/ +BOOL eventlog_store_subkey( char *key, REGSUBKEY_CTR *subkeys ) +{ + return False; +} + +/********************************************************************** + Stub function which always returns failure since we don't want + people storing eventlog information directly via registry calls + (for now at least) + *********************************************************************/ +BOOL eventlog_store_value( char *key, REGVAL_CTR *val ) +{ + return False; +} + +/* + * Table of function pointers for accessing eventlog data + */ +REGISTRY_OPS eventlog_ops = { + eventlog_subkey_info, + eventlog_value_info, + eventlog_store_subkey, + eventlog_store_value +}; diff --git a/source/registry/reg_frontend.c b/source/registry/reg_frontend.c index 1f8c9362901..9f8747ef378 100644 --- a/source/registry/reg_frontend.c +++ b/source/registry/reg_frontend.c @@ -26,13 +26,14 @@ #define DBGC_CLASS DBGC_RPC_SRV extern REGISTRY_OPS printing_ops; +extern REGISTRY_OPS eventlog_ops; extern REGISTRY_OPS regdb_ops; /* these are the default */ /* array of REGISTRY_HOOK's which are read into a tree for easy access */ - REGISTRY_HOOK reg_hooks[] = { { KEY_PRINTING, &printing_ops }, + { KEY_EVENTLOG, &eventlog_ops }, { NULL, NULL } }; @@ -124,6 +125,8 @@ BOOL fetch_reg_keys_specific( REGISTRY_KEY *key, char** subkey, uint32 key_index *subkey = NULL; /* simple caching for performance; very basic heuristic */ + + DEBUG(8,("fetch_reg_keys_specific: Looking for key [%d] of [%s]\n", key_index, key->name)); if ( !ctr_init ) { DEBUG(8,("fetch_reg_keys_specific: Initializing cache of subkeys for [%s]\n", key->name)); diff --git a/source/rpc_client/cli_lsarpc.c b/source/rpc_client/cli_lsarpc.c index 45b7509d451..f404b5144a6 100644 --- a/source/rpc_client/cli_lsarpc.c +++ b/source/rpc_client/cli_lsarpc.c @@ -24,6 +24,7 @@ */ #include "includes.h" +#include "rpc_client.h" /** @defgroup lsa LSA - Local Security Architecture * @ingroup rpc_client @@ -636,89 +637,68 @@ NTSTATUS cli_lsa_enum_trust_dom(struct cli_state *cli, TALLOC_CTX *mem_ctx, char ***domain_names, DOM_SID **domain_sids) { prs_struct qbuf, rbuf; - LSA_Q_ENUM_TRUST_DOM q; - LSA_R_ENUM_TRUST_DOM r; - NTSTATUS result; + LSA_Q_ENUM_TRUST_DOM in; + LSA_R_ENUM_TRUST_DOM out; int i; + fstring tmp; - 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 */ + ZERO_STRUCT(in); + ZERO_STRUCT(out); /* 64k is enough for about 2000 trusted domains */ - init_q_enum_trust_dom(&q, pol, *enum_ctx, 0x10000); - - if (!lsa_io_q_enum_trust_dom("", &q, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_LSARPC, LSA_ENUMTRUSTDOM, &qbuf, &rbuf)) { - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } - - /* Unmarshall response */ - - if (!lsa_io_r_enum_trust_dom("", &r, &rbuf, 0)) { - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } + + init_q_enum_trust_dom(&in, pol, *enum_ctx, 0x10000); - result = r.status; + CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_ENUMTRUSTDOM, + in, out, + qbuf, rbuf, + lsa_io_q_enum_trust_dom, + lsa_io_r_enum_trust_dom, + NT_STATUS_UNSUCCESSFUL ); - if (!NT_STATUS_IS_OK(result) && - !NT_STATUS_EQUAL(result, NT_STATUS_NO_MORE_ENTRIES) && - !NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) { - /* An actual error ocured */ + /* check for an actual error */ - goto done; + if ( !NT_STATUS_IS_OK(out.status) + && !NT_STATUS_EQUAL(out.status, NT_STATUS_NO_MORE_ENTRIES) + && !NT_STATUS_EQUAL(out.status, STATUS_MORE_ENTRIES) ) + { + return out.status; } - + /* Return output parameters */ - if (r.num_domains) { + *num_domains = out.count; + *enum_ctx = out.enum_context; + + if ( out.count ) { /* Allocate memory for trusted domain names and sids */ - *domain_names = TALLOC_ARRAY(mem_ctx, char *, r.num_domains); - - if (!*domain_names) { + if ( !(*domain_names = TALLOC_ARRAY(mem_ctx, char *, out.count)) ) { DEBUG(0, ("cli_lsa_enum_trust_dom(): out of memory\n")); - result = NT_STATUS_NO_MEMORY; - goto done; + return NT_STATUS_NO_MEMORY; } - *domain_sids = TALLOC_ARRAY(mem_ctx, DOM_SID, r.num_domains); - if (!domain_sids) { + if ( !(*domain_sids = TALLOC_ARRAY(mem_ctx, DOM_SID, out.count)) ) { DEBUG(0, ("cli_lsa_enum_trust_dom(): out of memory\n")); - result = NT_STATUS_NO_MEMORY; - goto done; + return NT_STATUS_NO_MEMORY; } /* Copy across names and sids */ - for (i = 0; i < r.num_domains; i++) { - fstring tmp; + for (i = 0; i < out.count; i++) { - unistr2_to_ascii(tmp, &r.uni_domain_name[i], - sizeof(tmp) - 1); + rpcstr_pull( tmp, out.domlist->domains[i].name.string->buffer, + sizeof(tmp), out.domlist->domains[i].name.length, 0); (*domain_names)[i] = talloc_strdup(mem_ctx, tmp); - sid_copy(&(*domain_sids)[i], &r.domain_sid[i].sid); + + sid_copy(&(*domain_sids)[i], &out.domlist->domains[i].sid->sid ); } } - *num_domains = r.num_domains; - *enum_ctx = r.enum_context; - - done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); - - return result; + return out.status; } @@ -1260,12 +1240,16 @@ NTSTATUS cli_lsa_enum_account_rights(struct cli_state *cli, TALLOC_CTX *mem_ctx, } - privileges = TALLOC_ARRAY(mem_ctx, fstring, *count); - names = TALLOC_ARRAY(mem_ctx, char *, *count); + privileges = TALLOC_ARRAY( mem_ctx, fstring, *count ); + names = TALLOC_ARRAY( mem_ctx, char *, *count ); + for ( i=0; i<*count; i++ ) { - /* ensure NULL termination ... what a hack */ - pull_ucs2(NULL, privileges[i], r.rights.strings[i].string.buffer, - sizeof(fstring), r.rights.strings[i].string.uni_str_len*2 , 0); + UNISTR4 *uni_string = &r.rights->strings[i]; + + if ( !uni_string->string ) + continue; + + rpcstr_pull( privileges[i], uni_string->string->buffer, sizeof(privileges[i]), -1, STR_TERMINATE ); /* now copy to the return array */ names[i] = talloc_strdup( mem_ctx, privileges[i] ); @@ -1284,7 +1268,8 @@ done: NTSTATUS cli_lsa_add_account_rights(struct cli_state *cli, TALLOC_CTX *mem_ctx, POLICY_HND *pol, DOM_SID sid, - uint32 count, const char **privs_name) + +uint32 count, const char **privs_name) { prs_struct qbuf, rbuf; LSA_Q_ADD_ACCT_RIGHTS q; diff --git a/source/rpc_client/cli_reg.c b/source/rpc_client/cli_reg.c index 25f56085bac..0d7d194850c 100644 --- a/source/rpc_client/cli_reg.c +++ b/source/rpc_client/cli_reg.c @@ -2,11 +2,12 @@ Unix SMB/CIFS implementation. RPC Pipe client - Copyright (C) Andrew Tridgell 1992-1998, - Copyright (C) Luke Kenneth Casson Leighton 1996-1998, - Copyright (C) Paul Ashton 1997-1998. + Copyright (C) Andrew Tridgell 1992-2000, + Copyright (C) Luke Kenneth Casson Leighton 1996-2000, + Copyright (C) Paul Ashton 1997-2000. Copyright (C) Jeremy Allison 1999. Copyright (C) Simo Sorce 2001 + Copyright (C) Jeremy Cooper 2004 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -27,6 +28,51 @@ /* Shutdown a server */ +/* internal connect to a registry hive root (open a registry policy) */ + +static WERROR cli_reg_open_hive_int(struct cli_state *cli, + TALLOC_CTX *mem_ctx, uint16 op_code, + const char *op_name, + uint32 access_mask, POLICY_HND *hnd) +{ + prs_struct rbuf; + prs_struct qbuf; + REG_Q_OPEN_HIVE q_o; + REG_R_OPEN_HIVE r_o; + WERROR result = WERR_GENERAL_FAILURE; + + ZERO_STRUCT(q_o); + ZERO_STRUCT(r_o); + + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); + + init_reg_q_open_hive(&q_o, access_mask); + + /* Marshall the query parameters */ + if (!reg_io_q_open_hive("", &q_o, &qbuf, 0)) + goto done; + + /* Send the request, receive the response */ + if (!rpc_api_pipe_req(cli, PI_WINREG, op_code, &qbuf, &rbuf)) + goto done; + + /* Unmarshall the response */ + if (!reg_io_r_open_hive("", &r_o, &rbuf, 0)) + goto done; + + result = r_o.status; + if (NT_STATUS_IS_OK(result)) + *hnd = r_o.pol; + +done: + prs_mem_free(&rbuf); + prs_mem_free(&qbuf); + + return result; +} + + WERROR cli_reg_shutdown(struct cli_state * cli, TALLOC_CTX *mem_ctx, const char *msg, uint32 timeout, BOOL do_reboot, BOOL force) @@ -90,7 +136,7 @@ WERROR cli_reg_abort_shutdown(struct cli_state * cli, TALLOC_CTX *mem_ctx) !rpc_api_pipe_req(cli, PI_WINREG, REG_ABORT_SHUTDOWN, &qbuf, &rbuf)) goto done; - /* Unmarshall response */ + /* Unmarshall response */ if (reg_io_r_abort_shutdown("", &r_s, &rbuf, 0)) result = r_s.status; @@ -101,3 +147,670 @@ done: return result; } + +/* connect to a registry hive root (open a registry policy) */ + +WERROR cli_reg_connect(struct cli_state *cli, TALLOC_CTX *mem_ctx, + uint32 reg_type, uint32 access_mask, + POLICY_HND *reg_hnd) +{ uint16 op_code; + const char *op_name; + + ZERO_STRUCTP(reg_hnd); + + switch (reg_type) + { + case HKEY_CLASSES_ROOT: + op_code = REG_OPEN_HKCR; + op_name = "REG_OPEN_HKCR"; + break; + case HKEY_LOCAL_MACHINE: + op_code = REG_OPEN_HKLM; + op_name = "REG_OPEN_HKLM"; + break; + case HKEY_USERS: + op_code = REG_OPEN_HKU; + op_name = "REG_OPEN_HKU"; + break; + case HKEY_PERFORMANCE_DATA: + op_code = REG_OPEN_HKPD; + op_name = "REG_OPEN_HKPD"; + break; + default: + return WERR_INVALID_PARAM; + } + + return cli_reg_open_hive_int(cli, mem_ctx, op_code, op_name, + access_mask, reg_hnd); +} + +/**************************************************************************** +do a REG Unknown 0xB command. sent after a create key or create value. +this might be some sort of "sync" or "refresh" command, sent after +modification of the registry... +****************************************************************************/ +WERROR cli_reg_flush_key(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *hnd) +{ + prs_struct rbuf; + prs_struct qbuf; + REG_Q_FLUSH_KEY q_o; + REG_R_FLUSH_KEY r_o; + WERROR result = WERR_GENERAL_FAILURE; + + prs_init(&qbuf , MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); + + /* Marshall data and send request */ + + init_reg_q_flush_key(&q_o, hnd); + + if (!reg_io_q_flush_key("", &q_o, &qbuf, 0) || + !rpc_api_pipe_req(cli, PI_WINREG, REG_FLUSH_KEY, &qbuf, &rbuf)) + goto done; + + ZERO_STRUCT(r_o); + + /* Unmarshall response */ + + if (reg_io_r_flush_key("", &r_o, &rbuf, 0)) + result = r_o.status; + +done: + prs_mem_free(&rbuf); + prs_mem_free(&qbuf); + + return result; +} + +/**************************************************************************** +do a REG Query Key +****************************************************************************/ +WERROR cli_reg_query_key(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *hnd, + char *key_class, uint32 *class_len, + uint32 *num_subkeys, uint32 *max_subkeylen, + uint32 *max_classlen, uint32 *num_values, + uint32 *max_valnamelen, uint32 *max_valbufsize, + uint32 *sec_desc, NTTIME *mod_time) +{ + prs_struct rbuf; + prs_struct qbuf; + REG_Q_QUERY_KEY q_o; + REG_R_QUERY_KEY r_o; + uint32 saved_class_len = *class_len; + WERROR result = WERR_GENERAL_FAILURE; + + prs_init(&qbuf , MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); + + /* Marshall data and send request */ + + init_reg_q_query_key( &q_o, hnd, key_class ); + + if (!reg_io_q_query_key("", &q_o, &qbuf, 0) || + !rpc_api_pipe_req(cli, PI_WINREG, REG_QUERY_KEY, &qbuf, &rbuf)) + goto done; + + ZERO_STRUCT(r_o); + + /* Unmarshall response */ + + if (!reg_io_r_query_key("", &r_o, &rbuf, 0)) + goto done; + + result = r_o.status; + if (NT_STATUS_EQUAL(result, ERROR_INSUFFICIENT_BUFFER)) { + *class_len = r_o.class.string->uni_max_len; + goto done; + } else if (!NT_STATUS_IS_OK(result)) + goto done; + + *class_len = r_o.class.string->uni_max_len; + unistr2_to_ascii(key_class, r_o.class.string, saved_class_len-1); + *num_subkeys = r_o.num_subkeys ; + *max_subkeylen = r_o.max_subkeylen ; + *num_values = r_o.num_values ; + *max_valnamelen = r_o.max_valnamelen; + *max_valbufsize = r_o.max_valbufsize; + *sec_desc = r_o.sec_desc ; + *mod_time = r_o.mod_time ; + /* Maybe: *max_classlen = r_o.reserved; */ + +done: + prs_mem_free(&rbuf); + prs_mem_free(&qbuf); + + return result; +} + +/**************************************************************************** +do a REG Unknown 1A +****************************************************************************/ +WERROR cli_reg_getversion(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *hnd, uint32 *unk) +{ + prs_struct rbuf; + prs_struct qbuf; + REG_Q_GETVERSION q_o; + REG_R_GETVERSION r_o; + WERROR result = WERR_GENERAL_FAILURE; + + prs_init(&qbuf , MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); + + /* Marshall data and send request */ + + init_reg_q_getversion(&q_o, hnd); + + if (!reg_io_q_getversion("", &q_o, &qbuf, 0) || + !rpc_api_pipe_req(cli, PI_WINREG, REG_GETVERSION, &qbuf, &rbuf)) + goto done; + + ZERO_STRUCT(r_o); + + /* Unmarshall response */ + + if (!reg_io_r_getversion("", &r_o, &rbuf, 0)) + goto done; + + result = r_o.status; + if (NT_STATUS_IS_OK(result)) + if (unk != NULL) + *unk = r_o.unknown; + +done: + prs_mem_free(&rbuf); + prs_mem_free(&qbuf); + + return result; +} + +/**************************************************************************** +do a REG Query Info +****************************************************************************/ +WERROR cli_reg_query_info(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *hnd, const char *val_name, + uint32 *type, REGVAL_BUFFER *buffer) +{ + prs_struct rbuf; + prs_struct qbuf; + REG_Q_INFO q_o; + REG_R_INFO r_o; + WERROR result = WERR_GENERAL_FAILURE; + + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); + + /* Marshall data and send request */ + + init_reg_q_info(&q_o, hnd, val_name, buffer); + + if (!reg_io_q_info("", &q_o, &qbuf, 0) || + !rpc_api_pipe_req(cli, PI_WINREG, REG_INFO, &qbuf, &rbuf)) + goto done; + + ZERO_STRUCT(r_o); + + /* Unmarshall response */ + + if (!reg_io_r_info("", &r_o, &rbuf, 0)) + goto done; + + result = r_o.status; + if (NT_STATUS_IS_OK(result)) { + *type = *r_o.type; + *buffer = *r_o.value; + } + +done: + prs_mem_free(&rbuf); + prs_mem_free(&qbuf); + + return result; +} + +/**************************************************************************** +do a REG Set Key Security +****************************************************************************/ +WERROR cli_reg_set_key_sec(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *hnd, uint32 sec_info, + size_t secdesc_size, SEC_DESC *sec_desc) +{ + prs_struct rbuf; + prs_struct qbuf; + REG_Q_SET_KEY_SEC q_o; + REG_R_SET_KEY_SEC r_o; + SEC_DESC_BUF *sec_desc_buf; + WERROR result = WERR_GENERAL_FAILURE; + + /* + * Flatten the security descriptor. + */ + sec_desc_buf = make_sec_desc_buf(mem_ctx, secdesc_size, sec_desc); + if (sec_desc_buf == NULL) + goto done; + + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); + + /* Marshall data and send request */ + + init_reg_q_set_key_sec(&q_o, hnd, sec_info, sec_desc_buf); + + if (!reg_io_q_set_key_sec("", &q_o, &qbuf, 0) || + !rpc_api_pipe_req(cli, PI_WINREG, REG_SET_KEY_SEC, &qbuf, &rbuf)) + goto done; + + ZERO_STRUCT(r_o); + + /* Unmarshall response */ + + if (reg_io_r_set_key_sec("", &r_o, &rbuf, 0)) + result = r_o.status; + +done: + prs_mem_free(&rbuf); + prs_mem_free(&qbuf); + + return result; +} + + +/**************************************************************************** +do a REG Query Key Security +****************************************************************************/ +WERROR cli_reg_get_key_sec(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *hnd, uint32 sec_info, + uint32 *sec_buf_size, SEC_DESC_BUF *sec_buf) +{ + prs_struct rbuf; + prs_struct qbuf; + REG_Q_GET_KEY_SEC q_o; + REG_R_GET_KEY_SEC r_o; + WERROR result = WERR_GENERAL_FAILURE; + + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); + + /* Marshall data and send request */ + + init_reg_q_get_key_sec(&q_o, hnd, sec_info, *sec_buf_size, sec_buf); + + if (!reg_io_q_get_key_sec("", &q_o, &qbuf, 0) || + !rpc_api_pipe_req(cli, PI_WINREG, REG_GET_KEY_SEC, &qbuf, &rbuf)) + goto done; + + ZERO_STRUCT(r_o); + + /* Unmarshall response */ + + r_o.data = sec_buf; + + if (*sec_buf_size != 0) + { + sec_buf->sec = (SEC_DESC*)talloc(mem_ctx, *sec_buf_size); + } + + if (!reg_io_r_get_key_sec("", &r_o, &rbuf, 0)) + goto done; + + result = r_o.status; + if (NT_STATUS_IS_OK(result)) + (*sec_buf_size) = r_o.data->len; + else if (NT_STATUS_EQUAL(result, ERROR_INSUFFICIENT_BUFFER)) + { + /* + * get the maximum buffer size: it was too small + */ + (*sec_buf_size) = r_o.hdr_sec.buf_max_len; + } + +done: + prs_mem_free(&rbuf); + prs_mem_free(&qbuf); + + return result; +} + +/**************************************************************************** +do a REG Delete Value +****************************************************************************/ +WERROR cli_reg_delete_val(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *hnd, char *val_name) +{ + prs_struct rbuf; + prs_struct qbuf; + REG_Q_DELETE_VALUE q_o; + REG_R_DELETE_VALUE r_o; + WERROR result = WERR_GENERAL_FAILURE; + + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); + + /* Marshall data and send request */ + + init_reg_q_delete_val(&q_o, hnd, val_name); + + if (!reg_io_q_delete_val("", &q_o, &qbuf, 0) || + !rpc_api_pipe_req(cli, PI_WINREG, REG_DELETE_VALUE, &qbuf, &rbuf)) + goto done; + + ZERO_STRUCT(r_o); + + /* Unmarshall response */ + + if (reg_io_r_delete_val("", &r_o, &rbuf, 0)) + result = r_o.status; + +done: + prs_mem_free(&rbuf); + prs_mem_free(&qbuf); + + return result; +} + +/**************************************************************************** +do a REG Delete Key +****************************************************************************/ +WERROR cli_reg_delete_key(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *hnd, char *key_name) +{ + prs_struct rbuf; + prs_struct qbuf; + REG_Q_DELETE_KEY q_o; + REG_R_DELETE_KEY r_o; + WERROR result = WERR_GENERAL_FAILURE; + + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); + + /* Marshall data and send request */ + + init_reg_q_delete_key(&q_o, hnd, key_name); + + if (!reg_io_q_delete_key("", &q_o, &qbuf, 0) || + !rpc_api_pipe_req(cli, PI_WINREG, REG_DELETE_KEY, &qbuf, &rbuf)) + goto done; + + ZERO_STRUCT(r_o); + + /* Unmarshall response */ + + if (reg_io_r_delete_key("", &r_o, &rbuf, 0)) + result = r_o.status; + +done: + prs_mem_free(&rbuf); + prs_mem_free(&qbuf); + + return result; +} + +/**************************************************************************** +do a REG Create Key +****************************************************************************/ +WERROR cli_reg_create_key(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *hnd, char *key_name, char *key_class, + uint32 access_desired, POLICY_HND *key) +{ + prs_struct rbuf; + prs_struct qbuf; + REG_Q_CREATE_KEY q_o; + REG_R_CREATE_KEY r_o; + SEC_DESC *sec; + SEC_DESC_BUF *sec_buf; + size_t sec_len; + WERROR result = WERR_GENERAL_FAILURE; + + ZERO_STRUCT(q_o); + + if ((sec = make_sec_desc(mem_ctx, 1, SEC_DESC_SELF_RELATIVE, + NULL, NULL, NULL, NULL, &sec_len)) == NULL) + goto done; + + if ((sec_buf = make_sec_desc_buf(mem_ctx, sec_len, sec)) == NULL) + goto done; + + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); + + /* Marshall data and send request */ + + init_reg_q_create_key(&q_o, hnd, key_name, key_class, access_desired, sec_buf); + + if (!reg_io_q_create_key("", &q_o, &qbuf, 0) || + !rpc_api_pipe_req(cli, PI_WINREG, REG_CREATE_KEY, &qbuf, &rbuf)) + goto done; + + ZERO_STRUCT(r_o); + + /* Unmarshall response */ + + if (!reg_io_r_create_key("", &r_o, &rbuf, 0)) + goto done; + + result = r_o.status; + if (NT_STATUS_IS_OK(result)) + *key = r_o.key_pol; + +done: + prs_mem_free(&rbuf); + prs_mem_free(&qbuf); + + return result; +} + +/**************************************************************************** +do a REG Enum Key +****************************************************************************/ +WERROR cli_reg_enum_key(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *hnd, int key_index, fstring key_name, + uint32 *unk_1, uint32 *unk_2, time_t *mod_time) +{ + prs_struct rbuf; + prs_struct qbuf; + REG_Q_ENUM_KEY q_o; + REG_R_ENUM_KEY r_o; + WERROR result = WERR_GENERAL_FAILURE; + + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); + + /* Marshall data and send request */ + + init_reg_q_enum_key(&q_o, hnd, key_index); + + if (!reg_io_q_enum_key("", &q_o, &qbuf, 0) || + !rpc_api_pipe_req(cli, PI_WINREG, REG_ENUM_KEY, &qbuf, &rbuf)) + goto done; + + ZERO_STRUCT(r_o); + + /* Unmarshall response */ + + if (!reg_io_r_enum_key("", &r_o, &rbuf, 0)) + goto done; + + result = r_o.status; + if (NT_STATUS_IS_OK(result)) { + (*unk_1) = r_o.unknown_1; + (*unk_2) = r_o.unknown_2; + unistr3_to_ascii(key_name, &r_o.key_name, + sizeof(fstring)-1); + (*mod_time) = nt_time_to_unix(&r_o.time); + } + +done: + prs_mem_free(&rbuf); + prs_mem_free(&qbuf); + + return result; +} + +/**************************************************************************** +do a REG Create Value +****************************************************************************/ +WERROR cli_reg_set_val(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *hnd, char *val_name, uint32 type, + RPC_DATA_BLOB *data) +{ + prs_struct rbuf; + prs_struct qbuf; + REG_Q_SET_VALUE q_o; + REG_R_SET_VALUE r_o; + WERROR result = WERR_GENERAL_FAILURE; + + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); + + /* Marshall data and send request */ + + init_reg_q_set_val(&q_o, hnd, val_name, type, data); + + if (!reg_io_q_set_val("", &q_o, &qbuf, 0) || + !rpc_api_pipe_req(cli, PI_WINREG, REG_SET_VALUE, &qbuf, &rbuf)) + goto done; + + ZERO_STRUCT(r_o); + + /* Unmarshal response */ + + if (reg_io_r_set_val("", &r_o, &rbuf, 0)) + result = r_o.status; + +done: + prs_mem_free(&rbuf); + prs_mem_free(&qbuf); + + return result; +} + +/**************************************************************************** +do a REG Enum Value +****************************************************************************/ +WERROR cli_reg_enum_val(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *hnd, int val_index, int max_valnamelen, + int max_valbufsize, fstring val_name, + uint32 *val_type, REGVAL_BUFFER *value) +{ + prs_struct rbuf; + prs_struct qbuf; + REG_Q_ENUM_VALUE q_o; + REG_R_ENUM_VALUE r_o; + WERROR result = WERR_GENERAL_FAILURE; + + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); + + /* Marshall data and send request */ + + init_reg_q_enum_val(&q_o, hnd, val_index, val_name, max_valbufsize); + + if (!reg_io_q_enum_val("", &q_o, &qbuf, 0) || + !rpc_api_pipe_req(cli, PI_WINREG, REG_ENUM_VALUE, &qbuf, &rbuf)) + goto done; + + ZERO_STRUCT(r_o); + + /* Unmarshall response */ + + if (!reg_io_r_enum_val("", &r_o, &rbuf, 0)) + goto done; + + result = r_o.status; + if (NT_STATUS_IS_OK(result) || + NT_STATUS_EQUAL(result, NT_STATUS_MORE_PROCESSING_REQUIRED)) { + (*val_type) = *r_o.type; + unistr2_to_ascii(val_name, r_o.name.string, sizeof(fstring)-1); + *value = *r_o.value; + } + +done: + prs_mem_free(&rbuf); + prs_mem_free(&qbuf); + + return result; +} + +/**************************************************************************** +do a REG Open Key +****************************************************************************/ +WERROR cli_reg_open_entry(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *hnd, char *key_name, + uint32 access_desired, POLICY_HND *key_hnd) +{ + prs_struct rbuf; + prs_struct qbuf; + REG_Q_OPEN_ENTRY q_o; + REG_R_OPEN_ENTRY r_o; + WERROR result = WERR_GENERAL_FAILURE; + + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); + + /* Marshall data and send request */ + + init_reg_q_open_entry(&q_o, hnd, key_name, access_desired); + + /* turn parameters into data stream */ + if (!reg_io_q_open_entry("", &q_o, &qbuf, 0) || + !rpc_api_pipe_req(cli, PI_WINREG, REG_OPEN_ENTRY, &qbuf, &rbuf)) + goto done; + + ZERO_STRUCT(r_o); + + /* Unmarsall response */ + + if (!reg_io_r_open_entry("", &r_o, &rbuf, 0)) + goto done; + + result = r_o.status; + if (NT_STATUS_IS_OK(result)) + *key_hnd = r_o.pol; + +done: + prs_mem_free(&rbuf); + prs_mem_free(&qbuf); + + return result; +} + +/**************************************************************************** +do a REG Close +****************************************************************************/ +WERROR cli_reg_close(struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *hnd) +{ + prs_struct rbuf; + prs_struct qbuf; + REG_Q_CLOSE q_c; + REG_R_CLOSE r_c; + WERROR result = WERR_GENERAL_FAILURE; + + prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); + + /* Marshall data and send request */ + + init_reg_q_close(&q_c, hnd); + + if (!reg_io_q_close("", &q_c, &qbuf, 0) || + !rpc_api_pipe_req(cli, PI_WINREG, REG_CLOSE, &qbuf, &rbuf)) + goto done; + + ZERO_STRUCT(r_c); + + /* Unmarshall response */ + + if (reg_io_r_close("", &r_c, &rbuf, 0)) + result = r_c.status; + +done: + prs_mem_free(&rbuf); + prs_mem_free(&qbuf); + + return result; +} + + diff --git a/source/rpc_client/cli_shutdown.c b/source/rpc_client/cli_shutdown.c index 9ad0510d1db..c342f255a9f 100644 --- a/source/rpc_client/cli_shutdown.c +++ b/source/rpc_client/cli_shutdown.c @@ -36,9 +36,10 @@ NTSTATUS cli_shutdown_init(struct cli_state * cli, TALLOC_CTX *mem_ctx, prs_struct rbuf; SHUTDOWN_Q_INIT q_s; SHUTDOWN_R_INIT r_s; - NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + WERROR result = WERR_GENERAL_FAILURE; - if (msg == NULL) return NT_STATUS_INVALID_PARAMETER; + if (msg == NULL) + return NT_STATUS_INVALID_PARAMETER; ZERO_STRUCT (q_s); ZERO_STRUCT (r_s); @@ -63,7 +64,48 @@ done: prs_mem_free(&rbuf); prs_mem_free(&qbuf); - return result; + return werror_to_ntstatus(result); +} + +/* Shutdown a server */ + +NTSTATUS cli_shutdown_init_ex(struct cli_state * cli, TALLOC_CTX *mem_ctx, + const char *msg, uint32 timeout, BOOL do_reboot, + BOOL force, uint32 reason) +{ + prs_struct qbuf; + prs_struct rbuf; + SHUTDOWN_Q_INIT_EX q_s; + SHUTDOWN_R_INIT_EX r_s; + WERROR result = WERR_GENERAL_FAILURE; + + if (msg == NULL) + return NT_STATUS_INVALID_PARAMETER; + + ZERO_STRUCT (q_s); + ZERO_STRUCT (r_s); + + prs_init(&qbuf , MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); + + /* Marshall data and send request */ + + init_shutdown_q_init_ex(&q_s, msg, timeout, do_reboot, force, reason); + + if (!shutdown_io_q_init_ex("", &q_s, &qbuf, 0) || + !rpc_api_pipe_req(cli, PI_SHUTDOWN, SHUTDOWN_INIT_EX, &qbuf, &rbuf)) + goto done; + + /* Unmarshall response */ + + if(shutdown_io_r_init_ex("", &r_s, &rbuf, 0)) + result = r_s.status; + +done: + prs_mem_free(&rbuf); + prs_mem_free(&qbuf); + + return werror_to_ntstatus(result); } @@ -75,7 +117,7 @@ NTSTATUS cli_shutdown_abort(struct cli_state * cli, TALLOC_CTX *mem_ctx) prs_struct qbuf; SHUTDOWN_Q_ABORT q_s; SHUTDOWN_R_ABORT r_s; - NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + WERROR result = WERR_GENERAL_FAILURE; ZERO_STRUCT (q_s); ZERO_STRUCT (r_s); @@ -100,5 +142,5 @@ done: prs_mem_free(&rbuf); prs_mem_free(&qbuf ); - return result; + return werror_to_ntstatus(result); } diff --git a/source/rpc_client/cli_spoolss.c b/source/rpc_client/cli_spoolss.c index 6ce74fed665..518c20ff9b0 100644 --- a/source/rpc_client/cli_spoolss.c +++ b/source/rpc_client/cli_spoolss.c @@ -31,25 +31,13 @@ * @{ **/ -/********************************************************************** - Initialize a new spoolss buff for use by a client rpc -**********************************************************************/ -static void init_buffer(NEW_BUFFER *buffer, uint32 size, TALLOC_CTX *ctx) -{ - buffer->ptr = (size != 0); - buffer->size = size; - buffer->string_at_end = size; - prs_init(&buffer->prs, size, ctx, MARSHALL); - buffer->struct_start = prs_offset(&buffer->prs); -} - /********************************************************************* Decode various spoolss rpc's and info levels ********************************************************************/ /********************************************************************** **********************************************************************/ -static void decode_printer_info_0(TALLOC_CTX *mem_ctx, NEW_BUFFER *buffer, +static void decode_printer_info_0(TALLOC_CTX *mem_ctx, RPC_BUFFER *buffer, uint32 returned, PRINTER_INFO_0 **info) { uint32 i; @@ -69,7 +57,7 @@ static void decode_printer_info_0(TALLOC_CTX *mem_ctx, NEW_BUFFER *buffer, /********************************************************************** **********************************************************************/ -static void decode_printer_info_1(TALLOC_CTX *mem_ctx, NEW_BUFFER *buffer, +static void decode_printer_info_1(TALLOC_CTX *mem_ctx, RPC_BUFFER *buffer, uint32 returned, PRINTER_INFO_1 **info) { uint32 i; @@ -89,7 +77,7 @@ static void decode_printer_info_1(TALLOC_CTX *mem_ctx, NEW_BUFFER *buffer, /********************************************************************** **********************************************************************/ -static void decode_printer_info_2(TALLOC_CTX *mem_ctx, NEW_BUFFER *buffer, +static void decode_printer_info_2(TALLOC_CTX *mem_ctx, RPC_BUFFER *buffer, uint32 returned, PRINTER_INFO_2 **info) { uint32 i; @@ -111,7 +99,7 @@ static void decode_printer_info_2(TALLOC_CTX *mem_ctx, NEW_BUFFER *buffer, /********************************************************************** **********************************************************************/ -static void decode_printer_info_3(TALLOC_CTX *mem_ctx, NEW_BUFFER *buffer, +static void decode_printer_info_3(TALLOC_CTX *mem_ctx, RPC_BUFFER *buffer, uint32 returned, PRINTER_INFO_3 **info) { uint32 i; @@ -132,7 +120,7 @@ static void decode_printer_info_3(TALLOC_CTX *mem_ctx, NEW_BUFFER *buffer, /********************************************************************** **********************************************************************/ -static void decode_printer_info_7(TALLOC_CTX *mem_ctx, NEW_BUFFER *buffer, +static void decode_printer_info_7(TALLOC_CTX *mem_ctx, RPC_BUFFER *buffer, uint32 returned, PRINTER_INFO_7 **info) { uint32 i; @@ -153,7 +141,7 @@ static void decode_printer_info_7(TALLOC_CTX *mem_ctx, NEW_BUFFER *buffer, /********************************************************************** **********************************************************************/ -static void decode_port_info_1(TALLOC_CTX *mem_ctx, NEW_BUFFER *buffer, +static void decode_port_info_1(TALLOC_CTX *mem_ctx, RPC_BUFFER *buffer, uint32 returned, PORT_INFO_1 **info) { uint32 i; @@ -173,7 +161,7 @@ static void decode_port_info_1(TALLOC_CTX *mem_ctx, NEW_BUFFER *buffer, /********************************************************************** **********************************************************************/ -static void decode_port_info_2(TALLOC_CTX *mem_ctx, NEW_BUFFER *buffer, +static void decode_port_info_2(TALLOC_CTX *mem_ctx, RPC_BUFFER *buffer, uint32 returned, PORT_INFO_2 **info) { uint32 i; @@ -193,7 +181,7 @@ static void decode_port_info_2(TALLOC_CTX *mem_ctx, NEW_BUFFER *buffer, /********************************************************************** **********************************************************************/ -static void decode_printer_driver_1(TALLOC_CTX *mem_ctx, NEW_BUFFER *buffer, +static void decode_printer_driver_1(TALLOC_CTX *mem_ctx, RPC_BUFFER *buffer, uint32 returned, DRIVER_INFO_1 **info) { uint32 i; @@ -213,7 +201,7 @@ static void decode_printer_driver_1(TALLOC_CTX *mem_ctx, NEW_BUFFER *buffer, /********************************************************************** **********************************************************************/ -static void decode_printer_driver_2(TALLOC_CTX *mem_ctx, NEW_BUFFER *buffer, +static void decode_printer_driver_2(TALLOC_CTX *mem_ctx, RPC_BUFFER *buffer, uint32 returned, DRIVER_INFO_2 **info) { uint32 i; @@ -233,7 +221,7 @@ static void decode_printer_driver_2(TALLOC_CTX *mem_ctx, NEW_BUFFER *buffer, /********************************************************************** **********************************************************************/ -static void decode_printer_driver_3(TALLOC_CTX *mem_ctx, NEW_BUFFER *buffer, +static void decode_printer_driver_3(TALLOC_CTX *mem_ctx, RPC_BUFFER *buffer, uint32 returned, DRIVER_INFO_3 **info) { uint32 i; @@ -253,7 +241,7 @@ static void decode_printer_driver_3(TALLOC_CTX *mem_ctx, NEW_BUFFER *buffer, /********************************************************************** **********************************************************************/ -static void decode_printerdriverdir_1 (TALLOC_CTX *mem_ctx, NEW_BUFFER *buffer, +static void decode_printerdriverdir_1 (TALLOC_CTX *mem_ctx, RPC_BUFFER *buffer, uint32 returned, DRIVER_DIRECTORY_1 **info ) { @@ -430,7 +418,7 @@ WERROR cli_spoolss_enum_printers(struct cli_state *cli, TALLOC_CTX *mem_ctx, prs_struct qbuf, rbuf; SPOOL_Q_ENUMPRINTERS q; SPOOL_R_ENUMPRINTERS r; - NEW_BUFFER buffer; + RPC_BUFFER buffer; WERROR result = W_ERROR(ERRgeneral); ZERO_STRUCT(q); @@ -438,7 +426,7 @@ WERROR cli_spoolss_enum_printers(struct cli_state *cli, TALLOC_CTX *mem_ctx, /* Initialise input parameters */ - init_buffer(&buffer, offered, mem_ctx); + rpcbuf_init(&buffer, offered, mem_ctx); prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); @@ -525,7 +513,7 @@ WERROR cli_spoolss_enum_ports(struct cli_state *cli, TALLOC_CTX *mem_ctx, prs_struct qbuf, rbuf; SPOOL_Q_ENUMPORTS q; SPOOL_R_ENUMPORTS r; - NEW_BUFFER buffer; + RPC_BUFFER buffer; WERROR result = W_ERROR(ERRgeneral); fstring server; @@ -537,7 +525,7 @@ WERROR cli_spoolss_enum_ports(struct cli_state *cli, TALLOC_CTX *mem_ctx, /* Initialise input parameters */ - init_buffer(&buffer, offered, mem_ctx); + rpcbuf_init(&buffer, offered, mem_ctx); prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); @@ -600,7 +588,7 @@ WERROR cli_spoolss_getprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx, prs_struct qbuf, rbuf; SPOOL_Q_GETPRINTER q; SPOOL_R_GETPRINTER r; - NEW_BUFFER buffer; + RPC_BUFFER buffer; WERROR result = W_ERROR(ERRgeneral); ZERO_STRUCT(q); @@ -608,7 +596,7 @@ WERROR cli_spoolss_getprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx, /* Initialise input parameters */ - init_buffer(&buffer, offered, mem_ctx); + rpcbuf_init(&buffer, offered, mem_ctx); prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); @@ -749,7 +737,7 @@ WERROR cli_spoolss_getprinterdriver(struct cli_state *cli, prs_struct qbuf, rbuf; SPOOL_Q_GETPRINTERDRIVER2 q; SPOOL_R_GETPRINTERDRIVER2 r; - NEW_BUFFER buffer; + RPC_BUFFER buffer; WERROR result = W_ERROR(ERRgeneral); fstring server; @@ -761,7 +749,7 @@ WERROR cli_spoolss_getprinterdriver(struct cli_state *cli, /* Initialise input parameters */ - init_buffer(&buffer, offered, mem_ctx); + rpcbuf_init(&buffer, offered, mem_ctx); prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); @@ -830,7 +818,7 @@ WERROR cli_spoolss_enumprinterdrivers (struct cli_state *cli, prs_struct qbuf, rbuf; SPOOL_Q_ENUMPRINTERDRIVERS q; SPOOL_R_ENUMPRINTERDRIVERS r; - NEW_BUFFER buffer; + RPC_BUFFER buffer; WERROR result = W_ERROR(ERRgeneral); fstring server; @@ -842,7 +830,7 @@ WERROR cli_spoolss_enumprinterdrivers (struct cli_state *cli, /* Initialise input parameters */ - init_buffer(&buffer, offered, mem_ctx); + rpcbuf_init(&buffer, offered, mem_ctx); prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); @@ -916,7 +904,7 @@ WERROR cli_spoolss_getprinterdriverdir (struct cli_state *cli, prs_struct qbuf, rbuf; SPOOL_Q_GETPRINTERDRIVERDIR q; SPOOL_R_GETPRINTERDRIVERDIR r; - NEW_BUFFER buffer; + RPC_BUFFER buffer; WERROR result = W_ERROR(ERRgeneral); fstring server; @@ -928,7 +916,7 @@ WERROR cli_spoolss_getprinterdriverdir (struct cli_state *cli, /* Initialise input parameters */ - init_buffer(&buffer, offered, mem_ctx); + rpcbuf_init(&buffer, offered, mem_ctx); prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); @@ -1204,7 +1192,7 @@ WERROR cli_spoolss_getprintprocessordirectory(struct cli_state *cli, SPOOL_R_GETPRINTPROCESSORDIRECTORY r; int level = 1; WERROR result = W_ERROR(ERRgeneral); - NEW_BUFFER buffer; + RPC_BUFFER buffer; ZERO_STRUCT(q); ZERO_STRUCT(r); @@ -1216,7 +1204,7 @@ WERROR cli_spoolss_getprintprocessordirectory(struct cli_state *cli, /* Initialise input parameters */ - init_buffer(&buffer, offered, mem_ctx); + rpcbuf_init(&buffer, offered, mem_ctx); make_spoolss_q_getprintprocessordirectory( &q, name, environment, level, &buffer, offered); @@ -1388,14 +1376,14 @@ WERROR cli_spoolss_getform(struct cli_state *cli, TALLOC_CTX *mem_ctx, SPOOL_Q_GETFORM q; SPOOL_R_GETFORM r; WERROR result = W_ERROR(ERRgeneral); - NEW_BUFFER buffer; + RPC_BUFFER buffer; ZERO_STRUCT(q); ZERO_STRUCT(r); /* Initialise parse structures */ - init_buffer(&buffer, offered, mem_ctx); + rpcbuf_init(&buffer, offered, mem_ctx); prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); @@ -1494,7 +1482,7 @@ WERROR cli_spoolss_deleteform(struct cli_state *cli, TALLOC_CTX *mem_ctx, return result; } -static void decode_forms_1(TALLOC_CTX *mem_ctx, NEW_BUFFER *buffer, +static void decode_forms_1(TALLOC_CTX *mem_ctx, RPC_BUFFER *buffer, uint32 num_forms, FORM_1 **forms) { int i; @@ -1530,14 +1518,14 @@ WERROR cli_spoolss_enumforms(struct cli_state *cli, TALLOC_CTX *mem_ctx, SPOOL_Q_ENUMFORMS q; SPOOL_R_ENUMFORMS r; WERROR result = W_ERROR(ERRgeneral); - NEW_BUFFER buffer; + RPC_BUFFER buffer; ZERO_STRUCT(q); ZERO_STRUCT(r); /* Initialise parse structures */ - init_buffer(&buffer, offered, mem_ctx); + rpcbuf_init(&buffer, offered, mem_ctx); prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); @@ -1576,7 +1564,7 @@ WERROR cli_spoolss_enumforms(struct cli_state *cli, TALLOC_CTX *mem_ctx, return result; } -static void decode_jobs_1(TALLOC_CTX *mem_ctx, NEW_BUFFER *buffer, +static void decode_jobs_1(TALLOC_CTX *mem_ctx, RPC_BUFFER *buffer, uint32 num_jobs, JOB_INFO_1 **jobs) { uint32 i; @@ -1588,7 +1576,7 @@ static void decode_jobs_1(TALLOC_CTX *mem_ctx, NEW_BUFFER *buffer, smb_io_job_info_1("", buffer, &((*jobs)[i]), 0); } -static void decode_jobs_2(TALLOC_CTX *mem_ctx, NEW_BUFFER *buffer, +static void decode_jobs_2(TALLOC_CTX *mem_ctx, RPC_BUFFER *buffer, uint32 num_jobs, JOB_INFO_2 **jobs) { uint32 i; @@ -1611,14 +1599,14 @@ WERROR cli_spoolss_enumjobs(struct cli_state *cli, TALLOC_CTX *mem_ctx, SPOOL_Q_ENUMJOBS q; SPOOL_R_ENUMJOBS r; WERROR result = W_ERROR(ERRgeneral); - NEW_BUFFER buffer; + RPC_BUFFER buffer; ZERO_STRUCT(q); ZERO_STRUCT(r); /* Initialise parse structures */ - init_buffer(&buffer, offered, mem_ctx); + rpcbuf_init(&buffer, offered, mem_ctx); prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); @@ -1728,14 +1716,14 @@ WERROR cli_spoolss_getjob(struct cli_state *cli, TALLOC_CTX *mem_ctx, SPOOL_Q_GETJOB q; SPOOL_R_GETJOB r; WERROR result = W_ERROR(ERRgeneral); - NEW_BUFFER buffer; + RPC_BUFFER buffer; ZERO_STRUCT(q); ZERO_STRUCT(r); /* Initialise parse structures */ - init_buffer(&buffer, offered, mem_ctx); + rpcbuf_init(&buffer, offered, mem_ctx); prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); diff --git a/source/rpc_client/cli_svcctl.c b/source/rpc_client/cli_svcctl.c new file mode 100644 index 00000000000..9f80bb79a39 --- /dev/null +++ b/source/rpc_client/cli_svcctl.c @@ -0,0 +1,415 @@ +/* + * Unix SMB/CIFS implementation. + * RPC Pipe client / server routines + * Copyright (C) Gerald Carter 2005. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +#include "includes.h" +#include "rpc_client.h" + +struct svc_state_msg { + uint32 flag; + const char *message; +}; + +static struct svc_state_msg state_msg_table[] = { + { SVCCTL_STOPPED, "stopped" }, + { SVCCTL_START_PENDING, "start pending" }, + { SVCCTL_STOP_PENDING, "stop pending" }, + { SVCCTL_RUNNING, "running" }, + { SVCCTL_CONTINUE_PENDING, "resume pending" }, + { SVCCTL_PAUSE_PENDING, "pause pending" }, + { SVCCTL_PAUSED, "paused" }, + { 0, NULL } +}; + + +/******************************************************************** +********************************************************************/ +const char* svc_status_string( uint32 state ) +{ + static fstring msg; + int i; + + fstr_sprintf( msg, "Unknown State [%d]", state ); + + for ( i=0; state_msg_table[i].message; i++ ) { + if ( state_msg_table[i].flag == state ) { + fstrcpy( msg, state_msg_table[i].message ); + break; + } + } + + return msg; +} + +/******************************************************************** +********************************************************************/ + +WERROR cli_svcctl_open_scm( struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *hSCM, uint32 access_desired ) +{ + SVCCTL_Q_OPEN_SCMANAGER in; + SVCCTL_R_OPEN_SCMANAGER out; + prs_struct qbuf, rbuf; + fstring server; + + ZERO_STRUCT(in); + ZERO_STRUCT(out); + + /* leave the database name NULL to get the default service db */ + + in.database = NULL; + + /* set the server name */ + + if ( !(in.servername = TALLOC_P( mem_ctx, UNISTR2 )) ) + return WERR_NOMEM; + fstr_sprintf( server, "\\\\%s", cli->desthost ); + init_unistr2( in.servername, server, UNI_STR_TERMINATE ); + + in.access = access_desired; + + CLI_DO_RPC( cli, mem_ctx, PI_SVCCTL, SVCCTL_OPEN_SCMANAGER_W, + in, out, + qbuf, rbuf, + svcctl_io_q_open_scmanager, + svcctl_io_r_open_scmanager, + WERR_GENERAL_FAILURE ); + + if ( !W_ERROR_IS_OK( out.status ) ) + return out.status; + + memcpy( hSCM, &out.handle, sizeof(POLICY_HND) ); + + return out.status; +} + +/******************************************************************** +********************************************************************/ + +WERROR cli_svcctl_open_service( struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *hSCM, POLICY_HND *hService, + const char *servicename, uint32 access_desired ) +{ + SVCCTL_Q_OPEN_SERVICE in; + SVCCTL_R_OPEN_SERVICE out; + prs_struct qbuf, rbuf; + + ZERO_STRUCT(in); + ZERO_STRUCT(out); + + memcpy( &in.handle, hSCM, sizeof(POLICY_HND) ); + init_unistr2( &in.servicename, servicename, UNI_STR_TERMINATE ); + in.access = access_desired; + + CLI_DO_RPC( cli, mem_ctx, PI_SVCCTL, SVCCTL_OPEN_SERVICE_W, + in, out, + qbuf, rbuf, + svcctl_io_q_open_service, + svcctl_io_r_open_service, + WERR_GENERAL_FAILURE ); + + if ( !W_ERROR_IS_OK( out.status ) ) + return out.status; + + memcpy( hService, &out.handle, sizeof(POLICY_HND) ); + + return out.status; +} + +/******************************************************************** +********************************************************************/ + +WERROR cli_svcctl_close_service( struct cli_state *cli, TALLOC_CTX *mem_ctx, POLICY_HND *hService ) +{ + SVCCTL_Q_CLOSE_SERVICE in; + SVCCTL_R_CLOSE_SERVICE out; + prs_struct qbuf, rbuf; + + ZERO_STRUCT(in); + ZERO_STRUCT(out); + + memcpy( &in.handle, hService, sizeof(POLICY_HND) ); + + CLI_DO_RPC( cli, mem_ctx, PI_SVCCTL, SVCCTL_CLOSE_SERVICE, + in, out, + qbuf, rbuf, + svcctl_io_q_close_service, + svcctl_io_r_close_service, + WERR_GENERAL_FAILURE ); + + return out.status; +} + +/******************************************************************* +*******************************************************************/ + +WERROR cli_svcctl_enumerate_services( struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *hSCM, uint32 type, uint32 state, + uint32 *returned, ENUM_SERVICES_STATUS **service_array ) +{ + SVCCTL_Q_ENUM_SERVICES_STATUS in; + SVCCTL_R_ENUM_SERVICES_STATUS out; + prs_struct qbuf, rbuf; + uint32 resume = 0; + ENUM_SERVICES_STATUS *services; + int i; + + ZERO_STRUCT(in); + ZERO_STRUCT(out); + + /* setup the request */ + + memcpy( &in.handle, hSCM, sizeof(POLICY_HND) ); + + in.type = type; + in.state = state; + in.resume = &resume; + + /* first time is to get the buffer size */ + in.buffer_size = 0; + + CLI_DO_RPC( cli, mem_ctx, PI_SVCCTL, SVCCTL_ENUM_SERVICES_STATUS_W, + in, out, + qbuf, rbuf, + svcctl_io_q_enum_services_status, + svcctl_io_r_enum_services_status, + WERR_GENERAL_FAILURE ); + + /* second time with correct buffer size...should be ok */ + + if ( W_ERROR_EQUAL( out.status, WERR_MORE_DATA ) ) { + in.buffer_size = out.needed; + + CLI_DO_RPC( cli, mem_ctx, PI_SVCCTL, SVCCTL_ENUM_SERVICES_STATUS_W, + in, out, + qbuf, rbuf, + svcctl_io_q_enum_services_status, + svcctl_io_r_enum_services_status, + WERR_GENERAL_FAILURE ); + } + + if ( !W_ERROR_IS_OK(out.status) ) + return out.status; + + /* pull out the data */ + if ( !(services = TALLOC_ARRAY( mem_ctx, ENUM_SERVICES_STATUS, out.returned )) ) + return WERR_NOMEM; + + for ( i=0; iexecutablepath = TALLOC_ZERO_P( mem_ctx, UNISTR2 ); + config->loadordergroup = TALLOC_ZERO_P( mem_ctx, UNISTR2 ); + config->dependencies = TALLOC_ZERO_P( mem_ctx, UNISTR2 ); + config->startname = TALLOC_ZERO_P( mem_ctx, UNISTR2 ); + config->displayname = TALLOC_ZERO_P( mem_ctx, UNISTR2 ); + + copy_unistr2( config->executablepath, out.config.executablepath ); + copy_unistr2( config->loadordergroup, out.config.loadordergroup ); + copy_unistr2( config->dependencies, out.config.dependencies ); + copy_unistr2( config->startname, out.config.startname ); + copy_unistr2( config->displayname, out.config.displayname ); + + return out.status; +} + +/******************************************************************* +*******************************************************************/ + +WERROR cli_svcctl_start_service( struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *hService, + const char **parm_array, uint32 parmcount ) +{ + SVCCTL_Q_START_SERVICE in; + SVCCTL_R_START_SERVICE out; + prs_struct qbuf, rbuf; + + ZERO_STRUCT(in); + ZERO_STRUCT(out); + + memcpy( &in.handle, hService, sizeof(POLICY_HND) ); + + in.parmcount = 0; + in.parameters = NULL; + + CLI_DO_RPC( cli, mem_ctx, PI_SVCCTL, SVCCTL_START_SERVICE_W, + in, out, + qbuf, rbuf, + svcctl_io_q_start_service, + svcctl_io_r_start_service, + WERR_GENERAL_FAILURE ); + + return out.status; +} + +/******************************************************************* +*******************************************************************/ + +WERROR cli_svcctl_control_service( struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *hService, uint32 control, + SERVICE_STATUS *status ) +{ + SVCCTL_Q_CONTROL_SERVICE in; + SVCCTL_R_CONTROL_SERVICE out; + prs_struct qbuf, rbuf; + + ZERO_STRUCT(in); + ZERO_STRUCT(out); + + memcpy( &in.handle, hService, sizeof(POLICY_HND) ); + in.control = control; + + CLI_DO_RPC( cli, mem_ctx, PI_SVCCTL, SVCCTL_CONTROL_SERVICE, + in, out, + qbuf, rbuf, + svcctl_io_q_control_service, + svcctl_io_r_control_service, + WERR_GENERAL_FAILURE ); + + if ( !W_ERROR_IS_OK( out.status ) ) + return out.status; + + memcpy( status, &out.svc_status, sizeof(SERVICE_STATUS) ); + + return out.status; +} + + +/******************************************************************* +*******************************************************************/ + +WERROR cli_svcctl_get_dispname( struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *hService, fstring displayname ) +{ + SVCCTL_Q_GET_DISPLAY_NAME in; + SVCCTL_R_GET_DISPLAY_NAME out; + prs_struct qbuf, rbuf; + + ZERO_STRUCT(in); + ZERO_STRUCT(out); + + memcpy( &in.handle, hService, sizeof(POLICY_HND) ); + in.display_name_len = 0; + + CLI_DO_RPC( cli, mem_ctx, PI_SVCCTL, SVCCTL_GET_DISPLAY_NAME, + in, out, + qbuf, rbuf, + svcctl_io_q_get_display_name, + svcctl_io_r_get_display_name, + WERR_GENERAL_FAILURE ); + + /* second time with correct buffer size...should be ok */ + + if ( W_ERROR_EQUAL( out.status, WERR_INSUFFICIENT_BUFFER ) ) { + in.display_name_len = out.display_name_len; + + CLI_DO_RPC( cli, mem_ctx, PI_SVCCTL, SVCCTL_GET_DISPLAY_NAME, + in, out, + qbuf, rbuf, + svcctl_io_q_get_display_name, + svcctl_io_r_get_display_name, + WERR_GENERAL_FAILURE ); + } + + if ( !W_ERROR_IS_OK( out.status ) ) + return out.status; + + rpcstr_pull( displayname, out.displayname.buffer, sizeof(displayname), -1, STR_TERMINATE ); + + return out.status; +} + diff --git a/source/rpc_parse/parse_buffer.c b/source/rpc_parse/parse_buffer.c new file mode 100644 index 00000000000..a48d5cfa982 --- /dev/null +++ b/source/rpc_parse/parse_buffer.c @@ -0,0 +1,491 @@ +/* + * Unix SMB/CIFS implementation. + * RPC Pipe client / server routines + * + * Copyright (C) Andrew Tridgell 1992-2000, + * Copyright (C) Luke Kenneth Casson Leighton 1996-2000, + * Copyright (C) Jean François Micouleau 1998-2000, + * Copyright (C) Gerald Carter 2000-2005, + * Copyright (C) Tim Potter 2001-2002. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "includes.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_RPC_PARSE + +/********************************************************************** + Initialize a new spoolss buff for use by a client rpc +**********************************************************************/ +void rpcbuf_init(RPC_BUFFER *buffer, uint32 size, TALLOC_CTX *ctx) +{ + buffer->size = size; + buffer->string_at_end = size; + prs_init(&buffer->prs, size, ctx, MARSHALL); + buffer->struct_start = prs_offset(&buffer->prs); +} + +/******************************************************************* + Read/write a RPC_BUFFER struct. +********************************************************************/ + +BOOL prs_rpcbuffer(const char *desc, prs_struct *ps, int depth, RPC_BUFFER *buffer) +{ + prs_debug(ps, depth, desc, "prs_rpcbuffer"); + depth++; + + /* reading */ + if (UNMARSHALLING(ps)) { + buffer->size=0; + buffer->string_at_end=0; + + if (!prs_uint32("size", ps, depth, &buffer->size)) + return False; + + /* + * JRA. I'm not sure if the data in here is in big-endian format if + * the client is big-endian. Leave as default (little endian) for now. + */ + + if (!prs_init(&buffer->prs, buffer->size, prs_get_mem_context(ps), UNMARSHALL)) + return False; + + if (!prs_append_some_prs_data(&buffer->prs, ps, prs_offset(ps), buffer->size)) + return False; + + if (!prs_set_offset(&buffer->prs, 0)) + return False; + + if (!prs_set_offset(ps, buffer->size+prs_offset(ps))) + return False; + + buffer->string_at_end=buffer->size; + + return True; + } + else { + BOOL ret = False; + + if (!prs_uint32("size", ps, depth, &buffer->size)) + goto out; + + if (!prs_append_some_prs_data(ps, &buffer->prs, 0, buffer->size)) + goto out; + + ret = True; + out: + + /* We have finished with the data in buffer->prs - free it. */ + prs_mem_free(&buffer->prs); + + return ret; + } +} + +/******************************************************************* + Read/write an RPC_BUFFER* struct.(allocate memory if unmarshalling) +********************************************************************/ + +BOOL prs_rpcbuffer_p(const char *desc, prs_struct *ps, int depth, RPC_BUFFER **buffer) +{ + uint32 data_p; + + /* caputure the pointer value to stream */ + + data_p = (uint32) *buffer; + + if ( !prs_uint32("ptr", ps, depth, &data_p )) + return False; + + /* we're done if there is no data */ + + if ( !data_p ) + return True; + + if ( UNMARSHALLING(ps) ) { + if ( !(*buffer = PRS_ALLOC_MEM(ps, RPC_BUFFER, 1)) ) + return False; + } + + return prs_rpcbuffer( desc, ps, depth, *buffer); +} + +/**************************************************************************** + Allocate more memory for a RPC_BUFFER. +****************************************************************************/ + +BOOL rpcbuf_alloc_size(RPC_BUFFER *buffer, uint32 buffer_size) +{ + prs_struct *ps; + uint32 extra_space; + uint32 old_offset; + + /* if we don't need anything. don't do anything */ + + if ( buffer_size == 0x0 ) + return True; + + ps= &buffer->prs; + + /* damn, I'm doing the reverse operation of prs_grow() :) */ + if (buffer_size < prs_data_size(ps)) + extra_space=0; + else + extra_space = buffer_size - prs_data_size(ps); + + /* + * save the offset and move to the end of the buffer + * prs_grow() checks the extra_space against the offset + */ + old_offset=prs_offset(ps); + prs_set_offset(ps, prs_data_size(ps)); + + if (!prs_grow(ps, extra_space)) + return False; + + prs_set_offset(ps, old_offset); + + buffer->string_at_end=prs_data_size(ps); + + return True; +} + +/******************************************************************* + move a BUFFER from the query to the reply. + As the data pointers in RPC_BUFFER are malloc'ed, not talloc'ed, + this is ok. This is an OPTIMIZATION and is not strictly neccessary. + Clears the memory to zero also. +********************************************************************/ + +void rpcbuf_move(RPC_BUFFER *src, RPC_BUFFER **dest) +{ + SMB_ASSERT( src != NULL ); + + prs_switch_type(&src->prs, MARSHALL); + if(!prs_set_offset(&src->prs, 0)) + return; + prs_force_dynamic(&src->prs); + prs_mem_clear(&src->prs); + *dest=src; +} + +/******************************************************************* + Get the size of a BUFFER struct. +********************************************************************/ + +uint32 rpcbuf_get_size(RPC_BUFFER *buffer) +{ + return (buffer->size); +} + + +/******************************************************************* + * write a UNICODE string and its relative pointer. + * used by all the RPC structs passing a buffer + * + * As I'm a nice guy, I'm forcing myself to explain this code. + * MS did a good job in the overall spoolss code except in some + * functions where they are passing the API buffer directly in the + * RPC request/reply. That's to maintain compatiility at the API level. + * They could have done it the good way the first time. + * + * So what happen is: the strings are written at the buffer's end, + * in the reverse order of the original structure. Some pointers to + * the strings are also in the buffer. Those are relative to the + * buffer's start. + * + * If you don't understand or want to change that function, + * first get in touch with me: jfm@samba.org + * + ********************************************************************/ + +BOOL smb_io_relstr(const char *desc, RPC_BUFFER *buffer, int depth, UNISTR *string) +{ + prs_struct *ps=&buffer->prs; + + if (MARSHALLING(ps)) { + uint32 struct_offset = prs_offset(ps); + uint32 relative_offset; + + buffer->string_at_end -= (size_of_relative_string(string) - 4); + if(!prs_set_offset(ps, buffer->string_at_end)) + return False; +#if 0 /* JERRY */ + /* + * Win2k does not align strings in a buffer + * Tested against WinNT 4.0 SP 6a & 2k SP2 --jerry + */ + if (!prs_align(ps)) + return False; +#endif + buffer->string_at_end = prs_offset(ps); + + /* write the string */ + if (!smb_io_unistr(desc, string, ps, depth)) + return False; + + if(!prs_set_offset(ps, struct_offset)) + return False; + + relative_offset=buffer->string_at_end - buffer->struct_start; + /* write its offset */ + if (!prs_uint32("offset", ps, depth, &relative_offset)) + return False; + } + else { + uint32 old_offset; + + /* read the offset */ + if (!prs_uint32("offset", ps, depth, &(buffer->string_at_end))) + return False; + + if (buffer->string_at_end == 0) + return True; + + old_offset = prs_offset(ps); + if(!prs_set_offset(ps, buffer->string_at_end+buffer->struct_start)) + return False; + + /* read the string */ + if (!smb_io_unistr(desc, string, ps, depth)) + return False; + + if(!prs_set_offset(ps, old_offset)) + return False; + } + return True; +} + +/******************************************************************* + * write a array of UNICODE strings and its relative pointer. + * used by 2 RPC structs + ********************************************************************/ + +BOOL smb_io_relarraystr(const char *desc, RPC_BUFFER *buffer, int depth, uint16 **string) +{ + UNISTR chaine; + + prs_struct *ps=&buffer->prs; + + if (MARSHALLING(ps)) { + uint32 struct_offset = prs_offset(ps); + uint32 relative_offset; + uint16 *p; + uint16 *q; + uint16 zero=0; + p=*string; + q=*string; + + /* first write the last 0 */ + buffer->string_at_end -= 2; + if(!prs_set_offset(ps, buffer->string_at_end)) + return False; + + if(!prs_uint16("leading zero", ps, depth, &zero)) + return False; + + while (p && (*p!=0)) { + while (*q!=0) + q++; + + /* Yes this should be malloc not talloc. Don't change. */ + + chaine.buffer = SMB_MALLOC((q-p+1)*sizeof(uint16)); + if (chaine.buffer == NULL) + return False; + + memcpy(chaine.buffer, p, (q-p+1)*sizeof(uint16)); + + buffer->string_at_end -= (q-p+1)*sizeof(uint16); + + if(!prs_set_offset(ps, buffer->string_at_end)) { + SAFE_FREE(chaine.buffer); + return False; + } + + /* write the string */ + if (!smb_io_unistr(desc, &chaine, ps, depth)) { + SAFE_FREE(chaine.buffer); + return False; + } + q++; + p=q; + + SAFE_FREE(chaine.buffer); + } + + if(!prs_set_offset(ps, struct_offset)) + return False; + + relative_offset=buffer->string_at_end - buffer->struct_start; + /* write its offset */ + if (!prs_uint32("offset", ps, depth, &relative_offset)) + return False; + + } else { + + /* UNMARSHALLING */ + + uint32 old_offset; + uint16 *chaine2=NULL; + int l_chaine=0; + int l_chaine2=0; + size_t realloc_size = 0; + + *string=NULL; + + /* read the offset */ + if (!prs_uint32("offset", ps, depth, &buffer->string_at_end)) + return False; + + old_offset = prs_offset(ps); + if(!prs_set_offset(ps, buffer->string_at_end + buffer->struct_start)) + return False; + + do { + if (!smb_io_unistr(desc, &chaine, ps, depth)) + return False; + + l_chaine=str_len_uni(&chaine); + + /* we're going to add two more bytes here in case this + is the last string in the array and we need to add + an extra NULL for termination */ + if (l_chaine > 0) + { + uint16 *tc2; + + realloc_size = (l_chaine2+l_chaine+2)*sizeof(uint16); + + /* Yes this should be realloc - it's freed below. JRA */ + + if((tc2=(uint16 *)SMB_REALLOC(chaine2, realloc_size)) == NULL) { + SAFE_FREE(chaine2); + return False; + } + else chaine2 = tc2; + memcpy(chaine2+l_chaine2, chaine.buffer, (l_chaine+1)*sizeof(uint16)); + l_chaine2+=l_chaine+1; + } + + } while(l_chaine!=0); + + /* the end should be bould NULL terminated so add + the second one here */ + if (chaine2) + { + chaine2[l_chaine2] = '\0'; + *string=(uint16 *)TALLOC_MEMDUP(prs_get_mem_context(ps),chaine2,realloc_size); + SAFE_FREE(chaine2); + } + + if(!prs_set_offset(ps, old_offset)) + return False; + } + return True; +} + +/******************************************************************* + Parse a DEVMODE structure and its relative pointer. +********************************************************************/ + +BOOL smb_io_relsecdesc(const char *desc, RPC_BUFFER *buffer, int depth, SEC_DESC **secdesc) +{ + prs_struct *ps= &buffer->prs; + + prs_debug(ps, depth, desc, "smb_io_relsecdesc"); + depth++; + + if (MARSHALLING(ps)) { + uint32 struct_offset = prs_offset(ps); + uint32 relative_offset; + + if (! *secdesc) { + relative_offset = 0; + if (!prs_uint32("offset", ps, depth, &relative_offset)) + return False; + return True; + } + + if (*secdesc != NULL) { + buffer->string_at_end -= sec_desc_size(*secdesc); + + if(!prs_set_offset(ps, buffer->string_at_end)) + return False; + /* write the secdesc */ + if (!sec_io_desc(desc, secdesc, ps, depth)) + return False; + + if(!prs_set_offset(ps, struct_offset)) + return False; + } + + relative_offset=buffer->string_at_end - buffer->struct_start; + /* write its offset */ + + if (!prs_uint32("offset", ps, depth, &relative_offset)) + return False; + } else { + uint32 old_offset; + + /* read the offset */ + if (!prs_uint32("offset", ps, depth, &buffer->string_at_end)) + return False; + + old_offset = prs_offset(ps); + if(!prs_set_offset(ps, buffer->string_at_end + buffer->struct_start)) + return False; + + /* read the sd */ + if (!sec_io_desc(desc, secdesc, ps, depth)) + return False; + + if(!prs_set_offset(ps, old_offset)) + return False; + } + return True; +} + + + +/******************************************************************* + * return the length of a UNICODE string in number of char, includes: + * - the leading zero + * - the relative pointer size + ********************************************************************/ + +uint32 size_of_relative_string(UNISTR *string) +{ + uint32 size=0; + + size=str_len_uni(string); /* the string length */ + size=size+1; /* add the trailing zero */ + size=size*2; /* convert in char */ + size=size+4; /* add the size of the ptr */ + +#if 0 /* JERRY */ + /* + * Do not include alignment as Win2k does not align relative + * strings within a buffer --jerry + */ + /* Ensure size is 4 byte multiple (prs_align is being called...). */ + /* size += ((4 - (size & 3)) & 3); */ +#endif + + return size; +} + diff --git a/source/rpc_parse/parse_eventlog.c b/source/rpc_parse/parse_eventlog.c new file mode 100644 index 00000000000..9bb0a131697 --- /dev/null +++ b/source/rpc_parse/parse_eventlog.c @@ -0,0 +1,457 @@ +/* + * Unix SMB/CIFS implementation. + * RPC Pipe client / server routines + * Copyright (C) Marcin Krzysztof Porwit 2005. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "includes.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_RPC_PARSE + +/* + * called from eventlog_q_open_eventlog (srv_eventlog.c) + */ + +BOOL eventlog_io_q_open_eventlog(const char *desc, EVENTLOG_Q_OPEN_EVENTLOG *q_u, + prs_struct *ps, int depth) +{ + if(q_u == NULL) + return False; + + /* Data format seems to be: + UNKNOWN structure + uint32 unknown + uint16 unknown + uint16 unknown + Eventlog name + uint16 eventlog name length + uint16 eventlog name size + Character Array + uint32 unknown + uint32 max count + uint32 offset + uint32 actual count + UNISTR2 log file name + Server Name + uint16 server name length + uint16 server name size + Character Array + UNISTR2 server name + */ + + prs_debug(ps, depth, desc, "eventlog_io_q_open_eventlog"); + depth++; + + if(!prs_align(ps)) + return False; + + /* Munch unknown bits */ + + if(!prs_uint32("", ps, depth, &q_u->unknown1)) + return False; + if(!prs_uint16("", ps, depth, &q_u->unknown2)) + return False; + if(!prs_uint16("", ps, depth, &q_u->unknown3)) + return False; + if(!prs_align(ps)) + return False; + + /* Get name of log source */ + + if(!prs_uint16("sourcename_length", ps, depth, &q_u->sourcename_length)) + return False; + if(!prs_uint16("sourcename_size", ps, depth, &q_u->sourcename_size)) + return False; + if(!prs_uint32("sourcename_ptr", ps, depth, &q_u->sourcename_ptr)) + return False; + if(!smb_io_unistr2("", &q_u->sourcename, q_u->sourcename_ptr, ps, depth)) + return False; + if(!prs_align(ps)) + return False; + + /* Get server name */ + + if(!prs_uint32("servername_ptr", ps, depth, &q_u->servername_ptr)) + return False; + if(!smb_io_unistr2("", &q_u->servername, q_u->servername_ptr, ps, depth)) + return False; + + return True; +} + +BOOL eventlog_io_r_open_eventlog(const char *desc, EVENTLOG_R_OPEN_EVENTLOG *r_u, + prs_struct *ps, int depth) +{ + if(r_u == NULL) + return False; + + prs_debug(ps, depth, desc, "eventlog_io_r_open_eventlog"); + depth++; + + if(!prs_align(ps)) + return False; + + if(!(smb_io_pol_hnd("log handle", &(r_u->handle), ps, depth))) + return False; + + if(!(prs_werror("status code", ps, depth, &(r_u->status)))) + return False; + + return True; +} + +BOOL eventlog_io_q_get_num_records(const char *desc, EVENTLOG_Q_GET_NUM_RECORDS *q_u, + prs_struct *ps, int depth) +{ + if(q_u == NULL) + return False; + + prs_debug(ps, depth, desc, "eventlog_io_q_get_num_records"); + depth++; + + if(!(prs_align(ps))) + return False; + + if(!(smb_io_pol_hnd("log handle", &(q_u->handle), ps, depth))) + return False; + + return True; +} + +BOOL eventlog_io_r_get_num_records(const char *desc, EVENTLOG_R_GET_NUM_RECORDS *r_u, + prs_struct *ps, int depth) +{ + if(r_u == NULL) + return False; + + prs_debug(ps, depth, desc, "eventlog_io_r_get_num_records"); + depth++; + + if(!(prs_align(ps))) + return False; + + if(!(prs_uint32("num records", ps, depth, &(r_u->num_records)))) + return False; + + if(!(prs_werror("status code", ps, depth, &(r_u->status)))) + return False; + + return True; +} + +BOOL eventlog_io_q_get_oldest_entry(const char *desc, EVENTLOG_Q_GET_OLDEST_ENTRY *q_u, + prs_struct *ps, int depth) +{ + if(q_u == NULL) + return False; + + prs_debug(ps, depth, desc, "eventlog_io_q_get_oldest_entry"); + depth++; + + if(!(prs_align(ps))) + return False; + + if(!(smb_io_pol_hnd("log handle", &(q_u->handle), ps, depth))) + return False; + + return True; +} + +BOOL eventlog_io_r_get_oldest_entry(const char *desc, EVENTLOG_R_GET_OLDEST_ENTRY *r_u, + prs_struct *ps, int depth) +{ + if(r_u == NULL) + return False; + + prs_debug(ps, depth, desc, "eventlog_io_r_get_oldest_entry"); + depth++; + + if(!(prs_align(ps))) + return False; + + if(!(prs_uint32("oldest entry", ps, depth, &(r_u->oldest_entry)))) + return False; + + if(!(prs_werror("status code", ps, depth, &(r_u->status)))) + return False; + + return True; +} + +BOOL eventlog_io_q_close_eventlog(const char *desc, EVENTLOG_Q_CLOSE_EVENTLOG *q_u, + prs_struct *ps, int depth) +{ + if(q_u == NULL) + return False; + + prs_debug(ps, depth, desc, "eventlog_io_q_close_eventlog"); + depth++; + + if(!(prs_align(ps))) + return False; + + if(!(smb_io_pol_hnd("log handle", &(q_u->handle), ps, depth))) + return False; + + return True; +} + +BOOL eventlog_io_r_close_eventlog(const char *desc, EVENTLOG_R_CLOSE_EVENTLOG *r_u, + prs_struct *ps, int depth) +{ + if(r_u == NULL) + return False; + + prs_debug(ps, depth, desc, "eventlog_io_r_close_eventlog"); + depth++; + + if(!(prs_align(ps))) + return False; + + if(!(smb_io_pol_hnd("log handle", &(r_u->handle), ps, depth))) + return False; + + if(!(prs_werror("status code", ps, depth, &(r_u->status)))) + return False; + + return True; +} + +BOOL eventlog_io_q_read_eventlog(const char *desc, EVENTLOG_Q_READ_EVENTLOG *q_u, + prs_struct *ps, int depth) +{ + if(q_u == NULL) + return False; + + prs_debug(ps, depth, desc, "eventlog_io_q_read_eventlog"); + depth++; + + if(!(prs_align(ps))) + return False; + + if(!(smb_io_pol_hnd("log handle", &(q_u->handle), ps, depth))) + return False; + + if(!(prs_uint32("read flags", ps, depth, &(q_u->flags)))) + return False; + + if(!(prs_uint32("read offset", ps, depth, &(q_u->offset)))) + return False; + + if(!(prs_uint32("read buf size", ps, depth, &(q_u->max_read_size)))) + return False; + + return True; +} +/* Structure of response seems to be: + DWORD num_bytes_in_resp -- MUST be the same as q_u->max_read_size + for i=0..n + EVENTLOGRECORD record + DWORD sent_size -- sum of EVENTLOGRECORD lengths if records returned, 0 otherwise + DWORD real_size -- 0 if records returned, otherwise length of next record to be returned + WERROR status */ +BOOL eventlog_io_r_read_eventlog(const char *desc, + EVENTLOG_Q_READ_EVENTLOG *q_u, + EVENTLOG_R_READ_EVENTLOG *r_u, + prs_struct *ps, + int depth) +{ + Eventlog_entry *entry; + uint32 record_written = 0; + uint32 record_total = 0; + + if(r_u == NULL) + return False; + + prs_debug(ps, depth, desc, "eventlog_io_r_read_eventlog"); + depth++; + + /* First, see if we've read more logs than we can output */ + + if(r_u->num_bytes_in_resp > q_u->max_read_size) { + entry = r_u->entry; + + /* remove the size of the last entry from the list */ + + while(entry->next != NULL) + entry = entry->next; + + r_u->num_bytes_in_resp -= entry->record.length; + + /* do not output the last log entry */ + + r_u->num_records--; + } + + entry = r_u->entry; + record_total = r_u->num_records; + + if(r_u->num_bytes_in_resp != 0) + r_u->sent_size = r_u->num_bytes_in_resp; + else + r_u->real_size = entry->record.length; + + if(!(prs_align(ps))) + return False; + if(!(prs_uint32("bytes in resp", ps, depth, &(q_u->max_read_size)))) + return False; + + while(entry != NULL && record_written < record_total) + { + DEBUG(10, ("eventlog_io_r_read_eventlog: writing record [%d] out of [%d].\n", record_written, record_total)); + + /* Encode the actual eventlog record record */ + + if(!(prs_uint32("length", ps, depth, &(entry->record.length)))) + return False; + if(!(prs_uint32("reserved", ps, depth, &(entry->record.reserved1)))) + return False; + if(!(prs_uint32("record number", ps, depth, &(entry->record.record_number)))) + return False; + if(!(prs_uint32("time generated", ps, depth, &(entry->record.time_generated)))) + return False; + if(!(prs_uint32("time written", ps, depth, &(entry->record.time_written)))) + return False; + if(!(prs_uint32("event id", ps, depth, &(entry->record.event_id)))) + return False; + if(!(prs_uint16("event type", ps, depth, &(entry->record.event_type)))) + return False; + if(!(prs_uint16("num strings", ps, depth, &(entry->record.num_strings)))) + return False; + if(!(prs_uint16("event category", ps, depth, &(entry->record.event_category)))) + return False; + if(!(prs_uint16("reserved2", ps, depth, &(entry->record.reserved2)))) + return False; + if(!(prs_uint32("closing record", ps, depth, &(entry->record.closing_record_number)))) + return False; + if(!(prs_uint32("string offset", ps, depth, &(entry->record.string_offset)))) + return False; + if(!(prs_uint32("user sid length", ps, depth, &(entry->record.user_sid_length)))) + return False; + if(!(prs_uint32("user sid offset", ps, depth, &(entry->record.user_sid_offset)))) + return False; + if(!(prs_uint32("data length", ps, depth, &(entry->record.data_length)))) + return False; + if(!(prs_uint32("data offset", ps, depth, &(entry->record.data_offset)))) + return False; + if(!(prs_align(ps))) + return False; + + /* Now encoding data */ + + if(!(prs_uint8s(False, "buffer", ps, depth, entry->data, + entry->record.length - sizeof(Eventlog_record) - sizeof(entry->record.length)))) + { + return False; + } + + if(!(prs_align(ps))) + return False; + if(!(prs_uint32("length 2", ps, depth, &(entry->record.length)))) + return False; + + entry = entry->next; + record_written++; + + } /* end of encoding EVENTLOGRECORD */ + + /* Now pad with whitespace until the end of the response buffer */ + + r_u->end_of_entries_padding = (uint8 *)calloc(q_u->max_read_size - r_u->num_bytes_in_resp, sizeof(uint8)); + + if(!(prs_uint8s(False, "end of entries padding", ps, + depth, r_u->end_of_entries_padding, + (q_u->max_read_size - r_u->num_bytes_in_resp)))) + { + return False; + } + + free(r_u->end_of_entries_padding); + + /* We had better be DWORD aligned here */ + + if(!(prs_uint32("sent size", ps, depth, &(r_u->sent_size)))) + return False; + if(!(prs_uint32("real size", ps, depth, &(r_u->real_size)))) + return False; + if(!(prs_werror("status code", ps, depth, &(r_u->status)))) + return False; + + return True; +} + +/* The windows client seems to be doing something funny with the file name + A call like + ClearEventLog(handle, "backup_file") + on the client side will result in the backup file name looking like this on the + server side: + \??\${CWD of client}\backup_file + If an absolute path gets specified, such as + ClearEventLog(handle, "C:\\temp\\backup_file") + then it is still mangled by the client into this: + \??\C:\temp\backup_file + when it is on the wire. + I'm not sure where the \?? is coming from, or why the ${CWD} of the client process + would be added in given that the backup file gets written on the server side. */ + +BOOL eventlog_io_q_clear_eventlog(const char *desc, EVENTLOG_Q_CLEAR_EVENTLOG *q_u, + prs_struct *ps, int depth) +{ + if(q_u == NULL) + return False; + + prs_debug(ps, depth, desc, "eventlog_io_q_clear_eventlog"); + depth++; + + if(!prs_align(ps)) + return False; + if(!(smb_io_pol_hnd("log handle", &(q_u->handle), ps, depth))) + return False; + if(!prs_align(ps)) + return False; + if(!(prs_uint32("unknown1", ps, depth, &q_u->unknown1))) + return False; + if(!(prs_uint16("backup_file_length", ps, depth, &q_u->backup_file_length))) + return False; + if(!(prs_uint16("backup_file_size", ps, depth, &q_u->backup_file_size))) + return False; + if(!prs_uint32("backup_file_ptr", ps, depth, &q_u->backup_file_ptr)) + return False; + if(!smb_io_unistr2("backup file", &q_u->backup_file, q_u->backup_file_ptr, ps, depth)) + return False; + + return True; + +} + +BOOL eventlog_io_r_clear_eventlog(const char *desc, EVENTLOG_R_CLEAR_EVENTLOG *r_u, + prs_struct *ps, int depth) +{ + if(r_u == NULL) + return False; + + prs_debug(ps, depth, desc, "eventlog_io_r_clear_eventlog"); + depth++; + + if(!prs_align(ps)) + return False; + if(!(prs_werror("status code", ps, depth, &(r_u->status)))) + return False; + + return True; +} diff --git a/source/rpc_parse/parse_lsa.c b/source/rpc_parse/parse_lsa.c index bbff258722a..ab3d3fcfe81 100644 --- a/source/rpc_parse/parse_lsa.c +++ b/source/rpc_parse/parse_lsa.c @@ -6,6 +6,7 @@ * Copyright (C) Paul Ashton 1997, * Copyright (C) Andrew Bartlett 2002, * Copyright (C) Jim McDonough 2002. + * Copyright (C) Gerald )Jerry) Carter 2005 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -516,100 +517,99 @@ void init_r_enum_trust_dom(TALLOC_CTX *ctx, LSA_R_ENUM_TRUST_DOM *r_e, uint32 en DEBUG(5, ("init_r_enum_trust_dom\n")); - r_e->enum_context = enum_context; - r_e->num_domains = num_domains; - r_e->ptr_enum_domains = 0; - r_e->num_domains2 = num_domains; - - if (num_domains != 0) { + r_e->enum_context = enum_context; + r_e->count = num_domains; + + if ( num_domains != 0 ) { - /* - * allocating empty arrays of unicode headers, strings - * and sids of enumerated trusted domains - */ - if (!(r_e->hdr_domain_name = TALLOC_ARRAY(ctx,UNIHDR2,num_domains))) { - r_e->status = NT_STATUS_NO_MEMORY; - return; - } + /* allocate container memory */ - if (!(r_e->uni_domain_name = TALLOC_ARRAY(ctx,UNISTR2,num_domains))) { - r_e->status = NT_STATUS_NO_MEMORY; - return; - } - - if (!(r_e->domain_sid = TALLOC_ARRAY(ctx,DOM_SID2,num_domains))) { + r_e->domlist = TALLOC_P( ctx, DOMAIN_LIST ); + r_e->domlist->domains = TALLOC_ARRAY( ctx, DOMAIN_INFO, r_e->count ); + + if ( !r_e->domlist || !r_e->domlist->domains ) { r_e->status = NT_STATUS_NO_MEMORY; return; } + + r_e->domlist->count = r_e->count; + + /* initialize the list of domains and their sid */ + + for (i = 0; i < num_domains; i++) { + if ( !(r_e->domlist->domains[i].sid = TALLOC_P(ctx, DOM_SID2)) ) { + r_e->status = NT_STATUS_NO_MEMORY; + return; + } - for (i = 0; i < num_domains; i++) { - - /* don't know what actually is this for */ - r_e->ptr_enum_domains = 1; - - init_dom_sid2(&r_e->domain_sid[i], &(td[i])->sid); - - init_unistr2_w(ctx, &r_e->uni_domain_name[i], (td[i])->name); - init_uni_hdr2(&r_e->hdr_domain_name[i], &r_e->uni_domain_name[i]); - - }; + init_dom_sid2(r_e->domlist->domains[i].sid, &(td[i])->sid); + init_unistr4_w(ctx, &r_e->domlist->domains[i].name, (td[i])->name); + } } } /******************************************************************* - Reads or writes an LSA_R_ENUM_TRUST_DOM structure. ********************************************************************/ -BOOL lsa_io_r_enum_trust_dom(const char *desc, LSA_R_ENUM_TRUST_DOM *r_e, - prs_struct *ps, int depth) +BOOL lsa_io_domain_list( const char *desc, prs_struct *ps, int depth, DOMAIN_LIST *domlist ) { - prs_debug(ps, depth, desc, "lsa_io_r_enum_trust_dom"); + int i; + + prs_debug(ps, depth, desc, "lsa_io_domain_list"); depth++; - if(!prs_uint32("enum_context ", ps, depth, &r_e->enum_context)) - return False; - if(!prs_uint32("num_domains ", ps, depth, &r_e->num_domains)) - return False; - if(!prs_uint32("ptr_enum_domains", ps, depth, &r_e->ptr_enum_domains)) + if(!prs_uint32("count", ps, depth, &domlist->count)) return False; - if (r_e->ptr_enum_domains) { - int i, num_domains; + if ( domlist->count == 0 ) + return True; + + if ( UNMARSHALLING(ps) ) { + if ( !(domlist->domains = PRS_ALLOC_MEM( ps, DOMAIN_INFO, domlist->count )) ) + return False; + } + + /* headers */ + + for ( i=0; icount; i++ ) { + if ( !prs_unistr4_hdr("name_header", ps, depth, &domlist->domains[i].name) ) + return False; + if ( !smb_io_dom_sid2_p("sid_header", ps, depth, &domlist->domains[i].sid) ) + return False; + } - if(!prs_uint32("num_domains2", ps, depth, &r_e->num_domains2)) + /* data */ + + for ( i=0; icount; i++ ) { + if ( !prs_unistr4_str("name", ps, depth, &domlist->domains[i].name) ) return False; + if( !smb_io_dom_sid2("sid", domlist->domains[i].sid, ps, depth) ) + return False; + } + + return True; +} - num_domains = r_e->num_domains2; +/******************************************************************* + Reads or writes an LSA_R_ENUM_TRUST_DOM structure. +********************************************************************/ - if (UNMARSHALLING(ps)) { - if (!(r_e->hdr_domain_name = PRS_ALLOC_MEM(ps,UNIHDR2,num_domains))) - return False; +BOOL lsa_io_r_enum_trust_dom(const char *desc, LSA_R_ENUM_TRUST_DOM *r_e, + prs_struct *ps, int depth) +{ + prs_debug(ps, depth, desc, "lsa_io_r_enum_trust_dom"); + depth++; - if (!(r_e->uni_domain_name = PRS_ALLOC_MEM(ps,UNISTR2,num_domains))) - return False; + if(!prs_uint32("enum_context", ps, depth, &r_e->enum_context)) + return False; - if (!(r_e->domain_sid = PRS_ALLOC_MEM(ps,DOM_SID2,num_domains))) - return False; - } + if(!prs_uint32("count", ps, depth, &r_e->count)) + return False; - for (i = 0; i < num_domains; i++) { - if(!smb_io_unihdr2 ("", &r_e->hdr_domain_name[i], ps, - depth)) - return False; - } + if ( !prs_pointer("trusted_domains", ps, depth, (void**)&r_e->domlist, sizeof(DOMAIN_LIST), (PRS_POINTER_CAST)lsa_io_domain_list)) + return False; - for (i = 0; i < num_domains; i++) { - if(!smb_io_unistr2 ("", &r_e->uni_domain_name[i], - r_e->hdr_domain_name[i].buffer, - ps, depth)) - return False; - if(!smb_io_dom_sid2("", &r_e->domain_sid[i], ps, - depth)) - return False; - } - } - if(!prs_ntstatus("status", ps, depth, &r_e->status)) return False; @@ -906,7 +906,7 @@ void init_q_lookup_sids(TALLOC_CTX *mem_ctx, LSA_Q_LOOKUP_SIDS *q_l, memcpy(&q_l->pol, hnd, sizeof(q_l->pol)); init_lsa_sid_enum(mem_ctx, &q_l->sids, num_sids, sids); - q_l->level.value = level; + q_l->level = level; } /******************************************************************* @@ -928,7 +928,10 @@ BOOL lsa_io_q_lookup_sids(const char *desc, LSA_Q_LOOKUP_SIDS *q_s, prs_struct * return False; if(!lsa_io_trans_names("names ", &q_s->names, ps, depth)) /* translated names */ return False; - if(!smb_io_lookup_level("switch ", &q_s->level, ps, depth)) /* lookup level */ + + if(!prs_uint16("level", ps, depth, &q_s->level)) /* lookup level */ + return False; + if(!prs_align(ps)) return False; if(!prs_uint32("mapped_count", ps, depth, &q_s->mapped_count)) @@ -2319,7 +2322,9 @@ NTSTATUS init_r_enum_acct_rights( LSA_R_ENUM_ACCT_RIGHTS *r_u, PRIVILEGE_SET *pr } if ( num_priv ) { - if ( !init_unistr2_array( &r_u->rights, num_priv, privname_array ) ) + r_u->rights = TALLOC_P( get_talloc_ctx(), UNISTR4_ARRAY ); + + if ( !init_unistr4_array( r_u->rights, num_priv, privname_array ) ) return NT_STATUS_NO_MEMORY; r_u->count = num_priv; @@ -2361,7 +2366,7 @@ BOOL lsa_io_r_enum_acct_rights(const char *desc, LSA_R_ENUM_ACCT_RIGHTS *r_c, pr if(!prs_uint32("count ", ps, depth, &r_c->count)) return False; - if(!smb_io_unistr2_array("rights", &r_c->rights, ps, depth)) + if ( !prs_pointer("rights", ps, depth, (void**)&r_c->rights, sizeof(UNISTR4_ARRAY), (PRS_POINTER_CAST)prs_unistr4_array) ) return False; if(!prs_align(ps)) @@ -2377,17 +2382,17 @@ BOOL lsa_io_r_enum_acct_rights(const char *desc, LSA_R_ENUM_ACCT_RIGHTS *r_c, pr /******************************************************************* Inits an LSA_Q_ADD_ACCT_RIGHTS structure. ********************************************************************/ -void init_q_add_acct_rights(LSA_Q_ADD_ACCT_RIGHTS *q_q, - POLICY_HND *hnd, - DOM_SID *sid, - uint32 count, - const char **rights) +void init_q_add_acct_rights( LSA_Q_ADD_ACCT_RIGHTS *q_q, POLICY_HND *hnd, + DOM_SID *sid, uint32 count, const char **rights ) { DEBUG(5, ("init_q_add_acct_rights\n")); q_q->pol = *hnd; init_dom_sid2(&q_q->sid, sid); - init_unistr2_array(&q_q->rights, count, rights); + + q_q->rights = TALLOC_P( get_talloc_ctx(), UNISTR4_ARRAY ); + init_unistr4_array( q_q->rights, count, rights ); + q_q->count = count; } @@ -2409,7 +2414,7 @@ BOOL lsa_io_q_add_acct_rights(const char *desc, LSA_Q_ADD_ACCT_RIGHTS *q_q, prs_ if(!prs_uint32("count", ps, depth, &q_q->count)) return False; - if(!smb_io_unistr2_array("rights", &q_q->rights, ps, depth)) + if ( !prs_pointer("rights", ps, depth, (void**)&q_q->rights, sizeof(UNISTR4_ARRAY), (PRS_POINTER_CAST)prs_unistr4_array) ) return False; return True; @@ -2443,10 +2448,14 @@ void init_q_remove_acct_rights(LSA_Q_REMOVE_ACCT_RIGHTS *q_q, DEBUG(5, ("init_q_remove_acct_rights\n")); q_q->pol = *hnd; + init_dom_sid2(&q_q->sid, sid); + q_q->removeall = removeall; - init_unistr2_array(&q_q->rights, count, rights); q_q->count = count; + + q_q->rights = TALLOC_P( get_talloc_ctx(), UNISTR4_ARRAY ); + init_unistr4_array( q_q->rights, count, rights ); } @@ -2470,7 +2479,7 @@ BOOL lsa_io_q_remove_acct_rights(const char *desc, LSA_Q_REMOVE_ACCT_RIGHTS *q_q if(!prs_uint32("count", ps, depth, &q_q->count)) return False; - if(!smb_io_unistr2_array("rights", &q_q->rights, ps, depth)) + if ( !prs_pointer("rights", ps, depth, (void**)&q_q->rights, sizeof(UNISTR4_ARRAY), (PRS_POINTER_CAST)prs_unistr4_array) ) return False; return True; diff --git a/source/rpc_parse/parse_misc.c b/source/rpc_parse/parse_misc.c index bca40a64c82..faa00d18624 100644 --- a/source/rpc_parse/parse_misc.c +++ b/source/rpc_parse/parse_misc.c @@ -4,6 +4,7 @@ * Copyright (C) Andrew Tridgell 1992-1997, * Copyright (C) Luke Kenneth Casson Leighton 1996-1997, * Copyright (C) Paul Ashton 1997. + * Copyright (C) Gerald (Jerry) Carter 2005 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -131,28 +132,6 @@ BOOL smb_io_time(const char *desc, NTTIME *nttime, prs_struct *ps, int depth) return True; } -/******************************************************************* - Reads or writes a LOOKUP_LEVEL structure. -********************************************************************/ - -BOOL smb_io_lookup_level(const char *desc, LOOKUP_LEVEL *level, prs_struct *ps, int depth) -{ - if (level == NULL) - return False; - - prs_debug(ps, depth, desc, "smb_io_lookup_level"); - depth++; - - if(!prs_align(ps)) - return False; - if(!prs_uint16("value", ps, depth, &level->value)) - return False; - if(!prs_align(ps)) - return False; - - return True; -} - /******************************************************************* Gets an enumeration handle from an ENUM_HND structure. ********************************************************************/ @@ -302,6 +281,33 @@ void init_dom_sid2(DOM_SID2 *sid2, const DOM_SID *sid) Reads or writes a DOM_SID2 structure. ********************************************************************/ +BOOL smb_io_dom_sid2_p(const char *desc, prs_struct *ps, int depth, DOM_SID2 **sid2) +{ + uint32 data_p; + + /* caputure the pointer value to stream */ + + data_p = (uint32) *sid2; + + if ( !prs_uint32("dom_sid2_p", ps, depth, &data_p )) + return False; + + /* we're done if there is no data */ + + if ( !data_p ) + return True; + + if (UNMARSHALLING(ps)) { + if ( !(*sid2 = PRS_ALLOC_MEM(ps, DOM_SID2, 1)) ) + return False; + } + + return True; +} +/******************************************************************* + Reads or writes a DOM_SID2 structure. +********************************************************************/ + BOOL smb_io_dom_sid2(const char *desc, DOM_SID2 *sid, prs_struct *ps, int depth) { if (sid == NULL) @@ -506,39 +512,6 @@ BOOL smb_io_hdrbuf(const char *desc, BUFHDR *hdr, prs_struct *ps, int depth) return True; } -/******************************************************************* -creates a UNIHDR2 structure. -********************************************************************/ - -void init_uni_hdr2(UNIHDR2 *hdr, UNISTR2 *str2) -{ - init_uni_hdr(&hdr->unihdr, str2); - hdr->buffer = (str2->uni_str_len > 0) ? 1 : 0; -} - -/******************************************************************* - Reads or writes a UNIHDR2 structure. -********************************************************************/ - -BOOL smb_io_unihdr2(const char *desc, UNIHDR2 *hdr2, prs_struct *ps, int depth) -{ - if (hdr2 == NULL) - return False; - - prs_debug(ps, depth, desc, "smb_io_unihdr2"); - depth++; - - if(!prs_align(ps)) - return False; - - if(!smb_io_unihdr("hdr", &hdr2->unihdr, ps, depth)) - return False; - if(!prs_uint32("buffer", ps, depth, &hdr2->buffer)) - return False; - - return True; -} - /******************************************************************* Inits a UNISTR structure. ********************************************************************/ @@ -581,105 +554,69 @@ BOOL smb_io_unistr(const char *desc, UNISTR *uni, prs_struct *ps, int depth) } /******************************************************************* - Allocate the BUFFER3 memory. + Allocate the RPC_DATA_BLOB memory. ********************************************************************/ -static size_t create_buffer3(BUFFER3 *str, size_t len) +static size_t create_rpc_blob(RPC_DATA_BLOB *str, size_t len) { str->buffer = TALLOC_ZERO(get_talloc_ctx(), len); if (str->buffer == NULL) - smb_panic("create_buffer3: talloc fail\n"); + smb_panic("create_rpc_blob: talloc fail\n"); return len; } /******************************************************************* - Inits a BUFFER3 structure from a uint32 + Inits a RPC_DATA_BLOB structure from a uint32 ********************************************************************/ -void init_buffer3_uint32(BUFFER3 *str, uint32 val) +void init_rpc_blob_uint32(RPC_DATA_BLOB *str, uint32 val) { ZERO_STRUCTP(str); /* set up string lengths. */ - str->buf_max_len = str->buf_len = create_buffer3(str, sizeof(uint32)); + str->buf_len = create_rpc_blob(str, sizeof(uint32)); SIVAL(str->buffer, 0, val); } /******************************************************************* - Inits a BUFFER3 structure. + Inits a RPC_DATA_BLOB structure. ********************************************************************/ -void init_buffer3_str(BUFFER3 *str, const char *buf, int len) +void init_rpc_blob_str(RPC_DATA_BLOB *str, const char *buf, int len) { ZERO_STRUCTP(str); /* set up string lengths. */ - str->buf_max_len = str->buf_len = create_buffer3(str, len*2); - rpcstr_push(str->buffer, buf, str->buf_max_len, STR_TERMINATE); + str->buf_len = create_rpc_blob(str, len*2); + rpcstr_push(str->buffer, buf, str->buf_len, STR_TERMINATE); } /******************************************************************* - Inits a BUFFER3 structure from a hex string. + Inits a RPC_DATA_BLOB structure from a hex string. ********************************************************************/ -void init_buffer3_hex(BUFFER3 *str, const char *buf) +void init_rpc_blob_hex(RPC_DATA_BLOB *str, const char *buf) { ZERO_STRUCTP(str); - str->buf_max_len = str->buf_len = create_buffer3(str, strlen(buf)); - str->buf_max_len = str->buf_len = strhex_to_str((char *)str->buffer, str->buf_len, buf); + str->buf_len = create_rpc_blob(str, strlen(buf)); + str->buf_len = strhex_to_str((char *)str->buffer, str->buf_len, buf); } /******************************************************************* - Inits a BUFFER3 structure. + Inits a RPC_DATA_BLOB structure. ********************************************************************/ -void init_buffer3_bytes(BUFFER3 *str, uint8 *buf, size_t len) +void init_rpc_blob_bytes(RPC_DATA_BLOB *str, uint8 *buf, size_t len) { ZERO_STRUCTP(str); /* max buffer size (allocated size) */ if (buf != NULL) { - len = create_buffer3(str, len); + len = create_rpc_blob(str, len); memcpy(str->buffer, buf, len); } - str->buf_max_len = len; - str->buf_len = buf != NULL ? len : 0; -} - -/******************************************************************* - Reads or writes a BUFFER3 structure. - the uni_max_len member tells you how large the buffer is. - the uni_str_len member tells you how much of the buffer is really used. -********************************************************************/ - -BOOL smb_io_buffer3(const char *desc, BUFFER3 *buf3, prs_struct *ps, int depth) -{ - if (buf3 == NULL) - return False; - - prs_debug(ps, depth, desc, "smb_io_buffer3"); - depth++; - - if(!prs_align(ps)) - return False; - - if(!prs_uint32("uni_max_len", ps, depth, &buf3->buf_max_len)) - return False; - - if (UNMARSHALLING(ps)) { - buf3->buffer = PRS_ALLOC_MEM(ps, unsigned char, buf3->buf_max_len); - if (buf3->buffer == NULL) - return False; - } - - if(!prs_uint8s(True, "buffer ", ps, depth, buf3->buffer, buf3->buf_max_len)) - return False; - - if(!prs_uint32("buf_len ", ps, depth, &buf3->buf_len)) - return False; - - return True; + str->buf_len = len; } /******************************************************************* @@ -707,10 +644,10 @@ BOOL smb_io_buffer5(const char *desc, BUFFER5 *buf5, prs_struct *ps, int depth) } /******************************************************************* - Inits a BUFFER2 structure. + Inits a REGVAL_BUFFER structure. ********************************************************************/ -void init_buffer2(BUFFER2 *str, const uint8 *buf, size_t len) +void init_regval_buffer(REGVAL_BUFFER *str, const uint8 *buf, size_t len) { ZERO_STRUCTP(str); @@ -723,50 +660,39 @@ void init_buffer2(BUFFER2 *str, const uint8 *buf, size_t len) SMB_ASSERT(str->buf_max_len >= str->buf_len); str->buffer = TALLOC_ZERO(get_talloc_ctx(), str->buf_max_len); if (str->buffer == NULL) - smb_panic("init_buffer2: talloc fail\n"); + smb_panic("init_regval_buffer: talloc fail\n"); memcpy(str->buffer, buf, str->buf_len); } } /******************************************************************* - Reads or writes a BUFFER2 structure. + Reads or writes a REGVAL_BUFFER structure. the uni_max_len member tells you how large the buffer is. the uni_str_len member tells you how much of the buffer is really used. ********************************************************************/ -BOOL smb_io_buffer2(const char *desc, BUFFER2 *buf2, uint32 buffer, prs_struct *ps, int depth) +BOOL smb_io_regval_buffer(const char *desc, prs_struct *ps, int depth, REGVAL_BUFFER *buf2) { - if (buf2 == NULL) - return False; - if (buffer) { - - prs_debug(ps, depth, desc, "smb_io_buffer2"); - depth++; + prs_debug(ps, depth, desc, "smb_io_regval_buffer"); + depth++; - if(!prs_align(ps)) - return False; + if(!prs_align(ps)) + return False; - if(!prs_uint32("uni_max_len", ps, depth, &buf2->buf_max_len)) - return False; - if(!prs_uint32("offset ", ps, depth, &buf2->offset)) - return False; - if(!prs_uint32("buf_len ", ps, depth, &buf2->buf_len)) - return False; - - /* buffer advanced by indicated length of string - NOT by searching for null-termination */ - - if(!prs_buffer2(True, "buffer ", ps, depth, buf2)) - return False; + if(!prs_uint32("uni_max_len", ps, depth, &buf2->buf_max_len)) + return False; + if(!prs_uint32("offset ", ps, depth, &buf2->offset)) + return False; + if(!prs_uint32("buf_len ", ps, depth, &buf2->buf_len)) + return False; - } else { + /* buffer advanced by indicated length of string + NOT by searching for null-termination */ - prs_debug(ps, depth, desc, "smb_io_buffer2 - NULL"); - depth++; - memset((char *)buf2, '\0', sizeof(*buf2)); + if(!prs_regval_buffer(True, "buffer ", ps, depth, buf2)) + return False; - } return True; } @@ -933,6 +859,28 @@ void init_unistr2(UNISTR2 *str, const char *buf, enum unistr2_term_codes flags) str->uni_max_len++; } +/******************************************************************* + Inits a UNISTR4 structure. +********************************************************************/ + +void init_unistr4(UNISTR4 *uni4, const char *buf, enum unistr2_term_codes flags) +{ + uni4->string = TALLOC_P( get_talloc_ctx(), UNISTR2 ); + init_unistr2( uni4->string, buf, flags ); + + uni4->length = 2 * (uni4->string->uni_str_len); + uni4->size = 2 * (uni4->string->uni_max_len); +} + +void init_unistr4_w( TALLOC_CTX *ctx, UNISTR4 *uni4, const smb_ucs2_t *buf ) +{ + uni4->string = TALLOC_P( ctx, UNISTR2 ); + init_unistr2_w( ctx, uni4->string, buf ); + + uni4->length = 2 * (uni4->string->uni_str_len); + uni4->size = 2 * (uni4->string->uni_max_len); +} + /** * Inits a UNISTR2 structure. * @param ctx talloc context to allocate string on @@ -1033,6 +981,57 @@ void init_unistr2_from_datablob(UNISTR2 *str, DATA_BLOB *blob) } } +/******************************************************************* + UNISTR2* are a little different in that the pointer and the UNISTR2 + are not necessarily read/written back to back. So we break it up + into 2 separate functions. + See SPOOL_USER_1 in include/rpc_spoolss.h for an example. +********************************************************************/ + +BOOL prs_io_unistr2_p(const char *desc, prs_struct *ps, int depth, UNISTR2 **uni2) +{ + uint32 data_p; + + /* caputure the pointer value to stream */ + + data_p = (uint32) *uni2; + + if ( !prs_uint32("ptr", ps, depth, &data_p )) + return False; + + /* we're done if there is no data */ + + if ( !data_p ) + return True; + + if (UNMARSHALLING(ps)) { + if ( !(*uni2 = PRS_ALLOC_MEM(ps, UNISTR2, 1)) ) + return False; + } + + return True; +} + +/******************************************************************* + now read/write the actual UNISTR2. Memory for the UNISTR2 (but + not UNISTR2.buffer) has been allocated previously by prs_unistr2_p() +********************************************************************/ + +BOOL prs_io_unistr2(const char *desc, prs_struct *ps, int depth, UNISTR2 *uni2 ) +{ + /* just return true if there is no pointer to deal with. + the memory must have been previously allocated on unmarshalling + by prs_unistr2_p() */ + + if ( !uni2 ) + return True; + + /* just pass off to smb_io_unstr2() passing the uni2 address as + the pointer (like you would expect) */ + + return smb_io_unistr2( desc, uni2, (uint32)uni2, ps, depth ); +} + /******************************************************************* Reads or writes a UNISTR2 structure. XXXX NOTE: UNISTR2 structures need NOT be null-terminated. @@ -1076,32 +1075,114 @@ BOOL smb_io_unistr2(const char *desc, UNISTR2 *uni2, uint32 buffer, prs_struct * return True; } +/******************************************************************* + now read/write UNISTR4 +********************************************************************/ + +BOOL prs_unistr4(const char *desc, prs_struct *ps, int depth, UNISTR4 *uni4) +{ + if ( !prs_uint16("length", ps, depth, &uni4->length )) + return False; + if ( !prs_uint16("size", ps, depth, &uni4->size )) + return False; + + if ( !prs_pointer( desc, ps, depth, (void**)&uni4->string, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2 ) ) + return False; + + return True; +} + +/******************************************************************* + now read/write UNISTR4 header +********************************************************************/ + +BOOL prs_unistr4_hdr(const char *desc, prs_struct *ps, int depth, UNISTR4 *uni4) +{ + prs_debug(ps, depth, desc, "prs_unistr4_hdr"); + depth++; + + if ( !prs_uint16("length", ps, depth, &uni4->length) ) + return False; + if ( !prs_uint16("size", ps, depth, &uni4->size) ) + return False; + if ( !prs_io_unistr2_p(desc, ps, depth, &uni4->string) ) + return False; + + return True; +} + +/******************************************************************* + now read/write UNISTR4 string +********************************************************************/ + +BOOL prs_unistr4_str(const char *desc, prs_struct *ps, int depth, UNISTR4 *uni4) +{ + prs_debug(ps, depth, desc, "prs_unistr4_str"); + depth++; + + if ( !prs_io_unistr2(desc, ps, depth, uni4->string) ) + return False; + + return True; +} + +/******************************************************************* + Reads or writes a UNISTR2_ARRAY structure. +********************************************************************/ -/* +BOOL prs_unistr4_array(const char *desc, prs_struct *ps, int depth, UNISTR4_ARRAY *array ) +{ + unsigned int i; + + prs_debug(ps, depth, desc, "prs_unistr4_array"); + depth++; + + if(!prs_uint32("count", ps, depth, &array->count)) + return False; + + if ( array->count == 0 ) + return True; + + if (UNMARSHALLING(ps)) { + if ( !(array->strings = TALLOC_ZERO_ARRAY( get_talloc_ctx(), UNISTR4, array->count)) ) + return False; + } + + /* write the headers and then the actual string buffer */ + + for ( i=0; icount; i++ ) { + if ( !prs_unistr4_hdr( "string", ps, depth, &array->strings[i]) ) + return False; + } + + for (i=0;icount;i++) { + if ( !prs_unistr4_str("string", ps, depth, &array->strings[i]) ) + return False; + } + + return True; +} + +/******************************************************************** initialise a UNISTR_ARRAY from a char** -*/ -BOOL init_unistr2_array(UNISTR2_ARRAY *array, - uint32 count, const char **strings) +********************************************************************/ + +BOOL init_unistr4_array( UNISTR4_ARRAY *array, uint32 count, const char **strings ) { unsigned int i; array->count = count; - array->ref_id = count?1:0; - if (array->count == 0) { + + if ( array->count == 0 ) return True; - } - array->strings = TALLOC_ZERO_ARRAY(get_talloc_ctx(), UNISTR2_ARRAY_EL, count ); - if (!array->strings) { + /* allocate memory for the array of UNISTR4 objects */ + + if ( !(array->strings = TALLOC_ZERO_ARRAY(get_talloc_ctx(), UNISTR4, count )) ) return False; - } - for (i=0;istrings[i].string, strings[i], UNI_FLAGS_NONE); - array->strings[i].size = array->strings[i].string.uni_max_len*2; - array->strings[i].length = array->strings[i].size; - array->strings[i].ref_id = 1; - } + for ( i=0; istrings[i], strings[i], STR_TERMINATE ); return True; } @@ -1153,55 +1234,6 @@ BOOL smb_io_account_lockout_str(const char *desc, LOCKOUT_STRING *account_lockou return True; } -/******************************************************************* - Reads or writes a UNISTR2_ARRAY structure. -********************************************************************/ -BOOL smb_io_unistr2_array(const char *desc, UNISTR2_ARRAY *array, prs_struct *ps, int depth) -{ - unsigned int i; - - prs_debug(ps, depth, desc, "smb_io_unistr2_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->strings = TALLOC_ZERO_ARRAY(get_talloc_ctx(), UNISTR2_ARRAY_EL, array->count ); - } - if (! array->strings) { - return False; - } - - for (i=0;icount;i++) { - if(!prs_uint16("length", ps, depth, &array->strings[i].length)) - return False; - if(!prs_uint16("size", ps, depth, &array->strings[i].size)) - return False; - if(!prs_uint32("ref_id", ps, depth, &array->strings[i].ref_id)) - return False; - } - - for (i=0;icount;i++) { - if (! smb_io_unistr2("string", &array->strings[i].string, array->strings[i].ref_id, ps, depth)) - return False; - } - - return True; -} - - /******************************************************************* Inits a DOM_RID2 structure. ********************************************************************/ @@ -1748,23 +1780,30 @@ BOOL smb_io_bufhdr4(const char *desc, BUFHDR4 *hdr, prs_struct *ps, int depth) } /******************************************************************* -reads or writes a BUFFER4 structure. +reads or writes a RPC_DATA_BLOB structure. ********************************************************************/ -BOOL smb_io_buffer4(const char *desc, BUFFER4 *buf4, uint32 buffer, prs_struct *ps, int depth) +BOOL smb_io_rpc_blob(const char *desc, RPC_DATA_BLOB *blob, prs_struct *ps, int depth) { - prs_debug(ps, depth, desc, "smb_io_buffer4"); + prs_debug(ps, depth, desc, "smb_io_rpc_blob"); depth++; prs_align(ps); - prs_uint32("buf_len", ps, depth, &buf4->buf_len); + if ( !prs_uint32("buf_len", ps, depth, &blob->buf_len) ) + return False; + + if ( blob->buf_len == 0 ) + return True; + if (UNMARSHALLING(ps)) { - buf4->buffer = PRS_ALLOC_MEM(ps, uint8, buf4->buf_len); - if (!buf4->buffer) { + blob->buffer = PRS_ALLOC_MEM(ps, uint8, blob->buf_len); + if (!blob->buffer) { return False; } } - prs_uint8s(True, "buffer", ps, depth, buf4->buffer, buf4->buf_len); + + if ( !prs_uint8s(True, "buffer", ps, depth, blob->buffer, blob->buf_len) ) + return False; return True; } @@ -1797,3 +1836,22 @@ BOOL make_bufhdr2(BUFHDR2 *hdr, uint32 info_level, uint32 length, uint32 buffer) return True; } + +/******************************************************************* +return the length of a UNISTR string. +********************************************************************/ + +uint32 str_len_uni(UNISTR *source) +{ + uint32 i=0; + + if (!source->buffer) + return 0; + + while (source->buffer[i]) + i++; + + return i; +} + + diff --git a/source/rpc_parse/parse_net.c b/source/rpc_parse/parse_net.c index d7bdca4df99..ed95656fdae 100644 --- a/source/rpc_parse/parse_net.c +++ b/source/rpc_parse/parse_net.c @@ -1972,8 +1972,7 @@ static BOOL net_io_sam_domain_info(const char *desc, SAM_DOMAIN_INFO * info, info->hdr_oem_info.buffer, ps, depth)) return False; - if (!smb_io_buffer4("buf_sec_desc", &info->buf_sec_desc, - info->hdr_sec_desc.buffer, ps, depth)) + if (!smb_io_rpc_blob("buf_sec_desc", &info->buf_sec_desc, ps, depth)) return False; if (!smb_io_account_lockout_str("account_lockout", &info->account_lockout, @@ -2021,8 +2020,7 @@ static BOOL net_io_sam_group_info(const char *desc, SAM_GROUP_INFO * info, if (!smb_io_unistr2("uni_grp_desc", &info->uni_grp_desc, info->hdr_grp_desc.buffer, ps, depth)) return False; - if (!smb_io_buffer4("buf_sec_desc", &info->buf_sec_desc, - info->hdr_sec_desc.buffer, ps, depth)) + if (!smb_io_rpc_blob("buf_sec_desc", &info->buf_sec_desc, ps, depth)) return False; return True; @@ -2274,8 +2272,7 @@ static BOOL net_io_sam_account_info(const char *desc, uint8 sess_key[16], if (!prs_uint32("unknown2", ps, depth, &info->unknown2)) return False; - if (!smb_io_buffer4("buf_logon_hrs", &info->buf_logon_hrs, - info->ptr_logon_hrs, ps, depth)) + if (!smb_io_rpc_blob("buf_logon_hrs", &info->buf_logon_hrs, ps, depth)) return False; prs_align(ps); if (!smb_io_unistr2("uni_comment", &info->uni_comment, @@ -2316,8 +2313,7 @@ static BOOL net_io_sam_account_info(const char *desc, uint8 sess_key[16], return False; ps->data_offset = old_offset + len; } - if (!smb_io_buffer4("buf_sec_desc", &info->buf_sec_desc, - info->hdr_sec_desc.buffer, ps, depth)) + if (!smb_io_rpc_blob("buf_sec_desc", &info->buf_sec_desc, ps, depth)) return False; prs_align(ps); if (!smb_io_unistr2("uni_profile", &info->uni_profile, @@ -2436,8 +2432,7 @@ static BOOL net_io_sam_alias_info(const char *desc, SAM_ALIAS_INFO * info, if (!smb_io_unistr2("uni_als_name", &info->uni_als_name, info->hdr_als_name.buffer, ps, depth)) return False; - if (!smb_io_buffer4("buf_sec_desc", &info->buf_sec_desc, - info->hdr_sec_desc.buffer, ps, depth)) + if (!smb_io_rpc_blob("buf_sec_desc", &info->buf_sec_desc, ps, depth)) return False; if (!smb_io_unistr2("uni_als_desc", &info->uni_als_desc, @@ -2596,8 +2591,7 @@ static BOOL net_io_sam_policy_info(const char *desc, SAM_DELTA_POLICY *info, if(!smb_io_dom_sid2("domain_sid", &info->domain_sid, ps, depth)) return False; - if (!smb_io_buffer4("buf_sec_desc", &info->buf_sec_desc, - info->hdr_sec_desc.buffer, ps, depth)) + if (!smb_io_rpc_blob("buf_sec_desc", &info->buf_sec_desc, ps, depth)) return False; @@ -2831,8 +2825,7 @@ static BOOL net_io_sam_privs_info(const char *desc, SAM_DELTA_PRIVS *info, if (!smb_io_unistr2("uni_privslist", &info->uni_privslist[i], True, ps, depth)) return False; - if (!smb_io_buffer4("buf_sec_desc", &info->buf_sec_desc, - info->hdr_sec_desc.buffer, ps, depth)) + if (!smb_io_rpc_blob("buf_sec_desc", &info->buf_sec_desc, ps, depth)) return False; return True; diff --git a/source/rpc_parse/parse_prs.c b/source/rpc_parse/parse_prs.c index 4b78d373bab..1b9ac51c613 100644 --- a/source/rpc_parse/parse_prs.c +++ b/source/rpc_parse/parse_prs.c @@ -588,6 +588,37 @@ BOOL prs_uint8(const char *name, prs_struct *ps, int depth, uint8 *data8) return True; } +/******************************************************************* + Stream a uint16* (allocate memory if unmarshalling) + ********************************************************************/ + +BOOL prs_pointer( const char *name, prs_struct *ps, int depth, + void **data, size_t data_size, + BOOL(*prs_fn)(const char*, prs_struct*, int, void*) ) +{ + uint32 data_p; + + /* caputure the pointer value to stream */ + + data_p = (uint32) *data; + + if ( !prs_uint32("ptr", ps, depth, &data_p )) + return False; + + /* we're done if there is no data */ + + if ( !data_p ) + return True; + + if (UNMARSHALLING(ps)) { + if ( !(*data = PRS_ALLOC_MEM_VOID(ps, data_size)) ) + return False; + } + + return prs_fn(name, ps, depth, *data); +} + + /******************************************************************* Stream a uint16. ********************************************************************/ @@ -598,12 +629,12 @@ BOOL prs_uint16(const char *name, prs_struct *ps, int depth, uint16 *data16) if (q == NULL) return False; - if (UNMARSHALLING(ps)) { + if (UNMARSHALLING(ps)) { if (ps->bigendian_data) *data16 = RSVAL(q,0); else *data16 = SVAL(q,0); - } else { + } else { if (ps->bigendian_data) RSSVAL(q,0,*data16); else @@ -916,28 +947,28 @@ BOOL prs_buffer5(BOOL charmode, const char *name, prs_struct *ps, int depth, BUF in byte chars. String is in little-endian format. ********************************************************************/ -BOOL prs_buffer2(BOOL charmode, const char *name, prs_struct *ps, int depth, BUFFER2 *str) +BOOL prs_regval_buffer(BOOL charmode, const char *name, prs_struct *ps, int depth, REGVAL_BUFFER *buf) { char *p; - char *q = prs_mem_get(ps, str->buf_len); + char *q = prs_mem_get(ps, buf->buf_len); if (q == NULL) return False; if (UNMARSHALLING(ps)) { - if (str->buf_len > str->buf_max_len) { + if (buf->buf_len > buf->buf_max_len) { return False; } - if ( str->buf_max_len ) { - str->buffer = PRS_ALLOC_MEM(ps, uint16, str->buf_max_len); - if ( str->buffer == NULL ) + if ( buf->buf_max_len ) { + buf->buffer = PRS_ALLOC_MEM(ps, uint16, buf->buf_max_len); + if ( buf->buffer == NULL ) return False; } } - p = (char *)str->buffer; + p = (char *)buf->buffer; - dbg_rw_punival(charmode, name, depth, ps, q, p, str->buf_len/2); - ps->data_offset += str->buf_len; + dbg_rw_punival(charmode, name, depth, ps, q, p, buf->buf_len/2); + ps->data_offset += buf->buf_len; return True; } diff --git a/source/rpc_parse/parse_reg.c b/source/rpc_parse/parse_reg.c index a67a3973b95..a51b4269e3a 100644 --- a/source/rpc_parse/parse_reg.c +++ b/source/rpc_parse/parse_reg.c @@ -6,7 +6,8 @@ * Copyright (C) Paul Ashton 1997. * Copyright (C) Marc Jacobsen 1999. * Copyright (C) Simo Sorce 2000. - * Copyright (C) Gerald Carter 2002. + * Copyright (C) Jeremy Cooper 2004 + * Copyright (C) Gerald Carter 2002-2005. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -29,10 +30,10 @@ #define DBGC_CLASS DBGC_RPC_PARSE /******************************************************************* - Fill in a BUFFER2 for the data given a REGISTRY_VALUE + Fill in a REGVAL_BUFFER for the data given a REGISTRY_VALUE *******************************************************************/ -static uint32 reg_init_buffer2( BUFFER2 *buf2, REGISTRY_VALUE *val ) +static uint32 reg_init_regval_buffer( REGVAL_BUFFER *buf2, REGISTRY_VALUE *val ) { uint32 real_size = 0; @@ -40,151 +41,72 @@ static uint32 reg_init_buffer2( BUFFER2 *buf2, REGISTRY_VALUE *val ) return 0; real_size = regval_size(val); - init_buffer2( buf2, (unsigned char*)regval_data_p(val), real_size ); + init_regval_buffer( buf2, (unsigned char*)regval_data_p(val), real_size ); return real_size; } /******************************************************************* - Inits a structure. + Inits a hive connect request structure ********************************************************************/ -void init_reg_q_open_hkcr(REG_Q_OPEN_HKCR *q_o, - uint16 unknown_0, uint32 level) +void init_reg_q_open_hive( REG_Q_OPEN_HIVE *q_o, uint32 access_desired ) { - q_o->ptr = 1; - q_o->unknown_0 = unknown_0; - q_o->unknown_1 = 0x0; /* random - changes */ - q_o->level = level; + + q_o->server = TALLOC_P( get_talloc_ctx(), uint16); + *q_o->server = 0x1; + + q_o->access = access_desired; } /******************************************************************* -reads or writes a structure. +Marshalls a hive connect request ********************************************************************/ -BOOL reg_io_q_open_hkcr(const char *desc, REG_Q_OPEN_HKCR *r_q, prs_struct *ps, int depth) +BOOL reg_io_q_open_hive(const char *desc, REG_Q_OPEN_HIVE *q_u, + prs_struct *ps, int depth) { - if (r_q == NULL) - return False; - - prs_debug(ps, depth, desc, "reg_io_q_open_hkcr"); + prs_debug(ps, depth, desc, "reg_io_q_open_hive"); depth++; if(!prs_align(ps)) return False; - if(!prs_uint32("ptr ", ps, depth, &r_q->ptr)) + if(!prs_pointer("server", ps, depth, (void**)&q_u->server, sizeof(uint16), (PRS_POINTER_CAST)prs_uint16)) return False; - if (r_q->ptr != 0) { - if(!prs_uint16("unknown_0", ps, depth, &r_q->unknown_0)) - return False; - if(!prs_uint16("unknown_1", ps, depth, &r_q->unknown_1)) - return False; - if(!prs_uint32("level ", ps, depth, &r_q->level)) - return False; - } + if(!prs_uint32("access", ps, depth, &q_u->access)) + return False; return True; } /******************************************************************* -reads or writes a structure. +Unmarshalls a hive connect response ********************************************************************/ -BOOL reg_io_r_open_hkcr(const char *desc, REG_R_OPEN_HKCR *r_r, prs_struct *ps, int depth) +BOOL reg_io_r_open_hive(const char *desc, REG_R_OPEN_HIVE *r_u, + prs_struct *ps, int depth) { - if (r_r == NULL) + if ( !r_u ) return False; - prs_debug(ps, depth, desc, "reg_io_r_open_hkcr"); + prs_debug(ps, depth, desc, "reg_io_r_open_hive"); depth++; if(!prs_align(ps)) return False; - if(!smb_io_pol_hnd("", &r_r->pol, ps, depth)) - return False; - - if(!prs_werror("status", ps, depth, &r_r->status)) - return False; - - return True; -} - -/******************************************************************* - Inits a structure. -********************************************************************/ - -void init_reg_q_open_hklm(REG_Q_OPEN_HKLM * q_o, - uint16 unknown_0, uint32 access_mask) -{ - q_o->ptr = 1; - q_o->unknown_0 = unknown_0; - q_o->unknown_1 = 0x0; /* random - changes */ - q_o->access_mask = access_mask; - -} - -/******************************************************************* -reads or writes a structure. -********************************************************************/ -BOOL reg_io_q_open_hklm(const char *desc, REG_Q_OPEN_HKLM * r_q, prs_struct *ps, - int depth) -{ - if (r_q == NULL) - return False; - - prs_debug(ps, depth, desc, "reg_io_q_open_hklm"); - depth++; - - if (!prs_align(ps)) - return False; - - if (!prs_uint32("ptr ", ps, depth, &(r_q->ptr))) - return False; - if (r_q->ptr != 0) - { - if (!prs_uint16("unknown_0", ps, depth, &(r_q->unknown_0))) - return False; - if (!prs_uint16("unknown_1", ps, depth, &(r_q->unknown_1))) - return False; - if (!prs_uint32("access_mask", ps, depth, &(r_q->access_mask))) - return False; - } - - return True; -} - - -/******************************************************************* -reads or writes a structure. -********************************************************************/ -BOOL reg_io_r_open_hklm(const char *desc, REG_R_OPEN_HKLM * r_r, prs_struct *ps, - int depth) -{ - if (r_r == NULL) - return False; - - prs_debug(ps, depth, desc, "reg_io_r_open_hklm"); - depth++; - - if (!prs_align(ps)) - return False; - - if (!smb_io_pol_hnd("", &r_r->pol, ps, depth)) + if(!smb_io_pol_hnd("", &r_u->pol, ps, depth)) return False; - if (!prs_werror("status", ps, depth, &r_r->status)) + if(!prs_werror("status", ps, depth, &r_u->status)) return False; return True; } - - - /******************************************************************* Inits a structure. ********************************************************************/ @@ -198,9 +120,9 @@ void init_reg_q_flush_key(REG_Q_FLUSH_KEY *q_u, POLICY_HND *pol) reads or writes a structure. ********************************************************************/ -BOOL reg_io_q_flush_key(const char *desc, REG_Q_FLUSH_KEY *r_q, prs_struct *ps, int depth) +BOOL reg_io_q_flush_key(const char *desc, REG_Q_FLUSH_KEY *q_u, prs_struct *ps, int depth) { - if (r_q == NULL) + if ( !q_u ) return False; prs_debug(ps, depth, desc, "reg_io_q_flush_key"); @@ -209,19 +131,20 @@ BOOL reg_io_q_flush_key(const char *desc, REG_Q_FLUSH_KEY *r_q, prs_struct *ps, if(!prs_align(ps)) return False; - if(!smb_io_pol_hnd("", &r_q->pol, ps, depth)) + if(!smb_io_pol_hnd("", &q_u->pol, ps, depth)) return False; return True; } /******************************************************************* -reads or writes a structure. +Unmarshalls a registry key flush response ********************************************************************/ -BOOL reg_io_r_flush_key(const char *desc, REG_R_FLUSH_KEY *r_r, prs_struct *ps, int depth) +BOOL reg_io_r_flush_key(const char *desc, REG_R_FLUSH_KEY *r_u, + prs_struct *ps, int depth) { - if (r_r == NULL) + if ( !r_u ) return False; prs_debug(ps, depth, desc, "reg_io_r_flush_key"); @@ -230,7 +153,7 @@ BOOL reg_io_r_flush_key(const char *desc, REG_R_FLUSH_KEY *r_r, prs_struct *ps, if(!prs_align(ps)) return False; - if(!prs_werror("status", ps, depth, &r_r->status)) + if(!prs_werror("status", ps, depth, &r_u->status)) return False; return True; @@ -240,12 +163,14 @@ BOOL reg_io_r_flush_key(const char *desc, REG_R_FLUSH_KEY *r_r, prs_struct *ps, reads or writes SEC_DESC_BUF and SEC_DATA structures. ********************************************************************/ -static BOOL reg_io_hdrbuf_sec(uint32 ptr, uint32 *ptr3, BUFHDR *hdr_sec, SEC_DESC_BUF *data, prs_struct *ps, int depth) +static BOOL reg_io_hdrbuf_sec(uint32 ptr, uint32 *ptr3, BUFHDR *hdr_sec, + SEC_DESC_BUF *data, prs_struct *ps, int depth) { if (ptr != 0) { uint32 hdr_offset; uint32 old_offset; - if(!smb_io_hdrbuf_pre("hdr_sec", hdr_sec, ps, depth, &hdr_offset)) + if(!smb_io_hdrbuf_pre("hdr_sec", hdr_sec, ps, depth, + &hdr_offset)) return False; old_offset = prs_offset(ps); @@ -256,14 +181,16 @@ static BOOL reg_io_hdrbuf_sec(uint32 ptr, uint32 *ptr3, BUFHDR *hdr_sec, SEC_DES } if (ptr3 == NULL || *ptr3 != 0) { - if(!sec_io_desc_buf("data ", &data, ps, depth)) /* JRA - this line is probably wrong... */ + /* JRA - this next line is probably wrong... */ + if(!sec_io_desc_buf("data ", &data, ps, depth)) return False; } - if(!smb_io_hdrbuf_post("hdr_sec", hdr_sec, ps, depth, hdr_offset, - data->max_len, data->len)) + if(!smb_io_hdrbuf_post("hdr_sec", hdr_sec, ps, depth, + hdr_offset, data->max_len, data->len)) return False; - if(!prs_set_offset(ps, old_offset + data->len + sizeof(uint32) * ((ptr3 != NULL) ? 5 : 3))) + if(!prs_set_offset(ps, old_offset + data->len + + sizeof(uint32) * ((ptr3 != NULL) ? 5 : 3))) return False; if(!prs_align(ps)) @@ -274,28 +201,25 @@ static BOOL reg_io_hdrbuf_sec(uint32 ptr, uint32 *ptr3, BUFHDR *hdr_sec, SEC_DES } /******************************************************************* - Inits a structure. + Inits a registry key create request ********************************************************************/ void init_reg_q_create_key(REG_Q_CREATE_KEY *q_c, POLICY_HND *hnd, - char *name, char *class, SEC_ACCESS *sam_access, - SEC_DESC_BUF *sec_buf) + char *name, char *class, uint32 access_desired, + SEC_DESC_BUF *sec_buf) { ZERO_STRUCTP(q_c); memcpy(&q_c->pnt_pol, hnd, sizeof(q_c->pnt_pol)); - init_unistr2(&q_c->uni_name, name, UNI_STR_TERMINATE); - init_uni_hdr(&q_c->hdr_name, &q_c->uni_name); - init_unistr2(&q_c->uni_class, class, UNI_STR_TERMINATE); - init_uni_hdr(&q_c->hdr_class, &q_c->uni_class); + init_unistr4( &q_c->name, name, UNI_STR_TERMINATE ); + init_unistr4( &q_c->class, class, UNI_STR_TERMINATE ); - q_c->reserved = 0x00000000; - memcpy(&q_c->sam_access, sam_access, sizeof(q_c->sam_access)); + q_c->access = access_desired; - q_c->ptr1 = 1; - q_c->sec_info = DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION; + q_c->sec_info = TALLOC_P( get_talloc_ctx(), uint32 ); + *q_c->sec_info = DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION; q_c->data = sec_buf; q_c->ptr2 = 1; @@ -305,12 +229,13 @@ void init_reg_q_create_key(REG_Q_CREATE_KEY *q_c, POLICY_HND *hnd, } /******************************************************************* -reads or writes a structure. +Marshalls a registry key create request ********************************************************************/ -BOOL reg_io_q_create_key(const char *desc, REG_Q_CREATE_KEY *r_q, prs_struct *ps, int depth) +BOOL reg_io_q_create_key(const char *desc, REG_Q_CREATE_KEY *q_u, + prs_struct *ps, int depth) { - if (r_q == NULL) + if ( !q_u ) return False; prs_debug(ps, depth, desc, "reg_io_q_create_key"); @@ -319,54 +244,49 @@ BOOL reg_io_q_create_key(const char *desc, REG_Q_CREATE_KEY *r_q, prs_struct *p if(!prs_align(ps)) return False; - if(!smb_io_pol_hnd("", &r_q->pnt_pol, ps, depth)) + if(!smb_io_pol_hnd("", &q_u->pnt_pol, ps, depth)) return False; - if(!smb_io_unihdr ("", &r_q->hdr_name, ps, depth)) - return False; - if(!smb_io_unistr2("", &r_q->uni_name, r_q->hdr_name.buffer, ps, depth)) + if(!prs_unistr4 ("name", ps, depth, &q_u->name)) return False; if(!prs_align(ps)) return False; - if(!smb_io_unihdr ("", &r_q->hdr_class, ps, depth)) - return False; - if(!smb_io_unistr2("", &r_q->uni_class, r_q->hdr_class.buffer, ps, depth)) + if(!prs_unistr4 ("class", ps, depth, &q_u->class)) return False; if(!prs_align(ps)) return False; - if(!prs_uint32("reserved", ps, depth, &r_q->reserved)) + if(!prs_uint32("reserved", ps, depth, &q_u->reserved)) return False; - if(!sec_io_access("sam_access", &r_q->sam_access, ps, depth)) + if(!prs_uint32("access", ps, depth, &q_u->access)) return False; - if(!prs_uint32("ptr1", ps, depth, &r_q->ptr1)) + if(!prs_pointer("sec_info", ps, depth, (void**)&q_u->sec_info, sizeof(uint32), (PRS_POINTER_CAST)prs_uint32)) return False; - if (r_q->ptr1 != 0) { - if(!prs_uint32("sec_info", ps, depth, &r_q->sec_info)) - return False; - } - - if(!prs_uint32("ptr2", ps, depth, &r_q->ptr2)) + if(!prs_uint32("ptr2", ps, depth, &q_u->ptr2)) return False; - if(!reg_io_hdrbuf_sec(r_q->ptr2, &r_q->ptr3, &r_q->hdr_sec, r_q->data, ps, depth)) + if(!reg_io_hdrbuf_sec(q_u->ptr2, &q_u->ptr3, &q_u->hdr_sec, q_u->data, + ps, depth)) return False; - if(!prs_uint32("unknown_2", ps, depth, &r_q->unknown_2)) +#if 0 + if(!prs_uint32("unknown_2", ps, depth, &q_u->unknown_2)) return False; +#endif return True; } /******************************************************************* -reads or writes a structure. +Unmarshalls a registry key create response ********************************************************************/ -BOOL reg_io_r_create_key(const char *desc, REG_R_CREATE_KEY *r_r, prs_struct *ps, int depth) +BOOL reg_io_r_create_key(const char *desc, REG_R_CREATE_KEY *r_u, + prs_struct *ps, int depth) { - if (r_r == NULL) + if ( !r_u ) return False; prs_debug(ps, depth, desc, "reg_io_r_create_key"); @@ -375,12 +295,12 @@ BOOL reg_io_r_create_key(const char *desc, REG_R_CREATE_KEY *r_r, prs_struct *p if(!prs_align(ps)) return False; - if(!smb_io_pol_hnd("", &r_r->key_pol, ps, depth)) + if(!smb_io_pol_hnd("", &r_u->key_pol, ps, depth)) return False; - if(!prs_uint32("unknown", ps, depth, &r_r->unknown)) + if(!prs_uint32("unknown", ps, depth, &r_u->unknown)) return False; - if(!prs_werror("status", ps, depth, &r_r->status)) + if(!prs_werror("status", ps, depth, &r_u->status)) return False; return True; @@ -392,23 +312,22 @@ BOOL reg_io_r_create_key(const char *desc, REG_R_CREATE_KEY *r_r, prs_struct *p ********************************************************************/ void init_reg_q_delete_val(REG_Q_DELETE_VALUE *q_c, POLICY_HND *hnd, - char *name) + char *name) { ZERO_STRUCTP(q_c); memcpy(&q_c->pnt_pol, hnd, sizeof(q_c->pnt_pol)); - - init_unistr2(&q_c->uni_name, name, UNI_STR_TERMINATE); - init_uni_hdr(&q_c->hdr_name, &q_c->uni_name); + init_unistr4(&q_c->name, name, UNI_STR_TERMINATE); } /******************************************************************* reads or writes a structure. ********************************************************************/ -BOOL reg_io_q_delete_val(const char *desc, REG_Q_DELETE_VALUE *r_q, prs_struct *ps, int depth) +BOOL reg_io_q_delete_val(const char *desc, REG_Q_DELETE_VALUE *q_u, + prs_struct *ps, int depth) { - if (r_q == NULL) + if ( !q_u ) return False; prs_debug(ps, depth, desc, "reg_io_q_delete_val"); @@ -417,12 +336,10 @@ BOOL reg_io_q_delete_val(const char *desc, REG_Q_DELETE_VALUE *r_q, prs_struct if(!prs_align(ps)) return False; - if(!smb_io_pol_hnd("", &r_q->pnt_pol, ps, depth)) + if(!smb_io_pol_hnd("", &q_u->pnt_pol, ps, depth)) return False; - if(!smb_io_unihdr ("", &r_q->hdr_name, ps, depth)) - return False; - if(!smb_io_unistr2("", &r_q->uni_name, r_q->hdr_name.buffer, ps, depth)) + if(!prs_unistr4("name", ps, depth, &q_u->name)) return False; if(!prs_align(ps)) return False; @@ -435,9 +352,10 @@ BOOL reg_io_q_delete_val(const char *desc, REG_Q_DELETE_VALUE *r_q, prs_struct reads or writes a structure. ********************************************************************/ -BOOL reg_io_r_delete_val(const char *desc, REG_R_DELETE_VALUE *r_r, prs_struct *ps, int depth) +BOOL reg_io_r_delete_val(const char *desc, REG_R_DELETE_VALUE *r_u, + prs_struct *ps, int depth) { - if (r_r == NULL) + if ( !r_u ) return False; prs_debug(ps, depth, desc, "reg_io_r_delete_val"); @@ -446,7 +364,7 @@ BOOL reg_io_r_delete_val(const char *desc, REG_R_DELETE_VALUE *r_r, prs_struct if(!prs_align(ps)) return False; - if(!prs_werror("status", ps, depth, &r_r->status)) + if(!prs_werror("status", ps, depth, &r_u->status)) return False; return True; @@ -457,23 +375,23 @@ BOOL reg_io_r_delete_val(const char *desc, REG_R_DELETE_VALUE *r_r, prs_struct ********************************************************************/ void init_reg_q_delete_key(REG_Q_DELETE_KEY *q_c, POLICY_HND *hnd, - char *name) + char *name) { ZERO_STRUCTP(q_c); memcpy(&q_c->pnt_pol, hnd, sizeof(q_c->pnt_pol)); - init_unistr2(&q_c->uni_name, name, UNI_STR_TERMINATE); - init_uni_hdr(&q_c->hdr_name, &q_c->uni_name); + init_unistr4(&q_c->name, name, UNI_STR_TERMINATE); } /******************************************************************* reads or writes a structure. ********************************************************************/ -BOOL reg_io_q_delete_key(const char *desc, REG_Q_DELETE_KEY *r_q, prs_struct *ps, int depth) +BOOL reg_io_q_delete_key(const char *desc, REG_Q_DELETE_KEY *q_u, + prs_struct *ps, int depth) { - if (r_q == NULL) + if ( !q_u ) return False; prs_debug(ps, depth, desc, "reg_io_q_delete_key"); @@ -482,12 +400,10 @@ BOOL reg_io_q_delete_key(const char *desc, REG_Q_DELETE_KEY *r_q, prs_struct *p if(!prs_align(ps)) return False; - if(!smb_io_pol_hnd("", &r_q->pnt_pol, ps, depth)) + if(!smb_io_pol_hnd("", &q_u->pnt_pol, ps, depth)) return False; - if(!smb_io_unihdr ("", &r_q->hdr_name, ps, depth)) - return False; - if(!smb_io_unistr2("", &r_q->uni_name, r_q->hdr_name.buffer, ps, depth)) + if(!prs_unistr4("", ps, depth, &q_u->name)) return False; if(!prs_align(ps)) return False; @@ -499,9 +415,9 @@ BOOL reg_io_q_delete_key(const char *desc, REG_Q_DELETE_KEY *r_q, prs_struct *p reads or writes a structure. ********************************************************************/ -BOOL reg_io_r_delete_key(const char *desc, REG_R_DELETE_KEY *r_r, prs_struct *ps, int depth) +BOOL reg_io_r_delete_key(const char *desc, REG_R_DELETE_KEY *r_u, prs_struct *ps, int depth) { - if (r_r == NULL) + if ( !r_u ) return False; prs_debug(ps, depth, desc, "reg_io_r_delete_key"); @@ -510,7 +426,7 @@ BOOL reg_io_r_delete_key(const char *desc, REG_R_DELETE_KEY *r_r, prs_struct *p if(!prs_align(ps)) return False; - if(!prs_werror("status", ps, depth, &r_r->status)) + if(!prs_werror("status", ps, depth, &r_u->status)) return False; return True; @@ -520,21 +436,21 @@ BOOL reg_io_r_delete_key(const char *desc, REG_R_DELETE_KEY *r_r, prs_struct *p Inits a structure. ********************************************************************/ -void init_reg_q_query_key(REG_Q_QUERY_KEY *q_o, POLICY_HND *hnd, UNISTR2 *uni2) +void init_reg_q_query_key(REG_Q_QUERY_KEY *q_o, POLICY_HND *hnd, const char *class) { ZERO_STRUCTP(q_o); memcpy(&q_o->pol, hnd, sizeof(q_o->pol)); - init_uni_hdr(&q_o->hdr_class, uni2); + init_unistr4(&q_o->class, class, UNI_STR_TERMINATE); } /******************************************************************* reads or writes a structure. ********************************************************************/ -BOOL reg_io_q_query_key(const char *desc, REG_Q_QUERY_KEY *r_q, prs_struct *ps, int depth) +BOOL reg_io_q_query_key(const char *desc, REG_Q_QUERY_KEY *q_u, prs_struct *ps, int depth) { - if (r_q == NULL) + if ( !q_u ) return False; prs_debug(ps, depth, desc, "reg_io_q_query_key"); @@ -543,11 +459,9 @@ BOOL reg_io_q_query_key(const char *desc, REG_Q_QUERY_KEY *r_q, prs_struct *ps, if(!prs_align(ps)) return False; - if(!smb_io_pol_hnd("", &r_q->pol, ps, depth)) - return False; - if(!smb_io_unihdr ("", &r_q->hdr_class, ps, depth)) + if(!smb_io_pol_hnd("", &q_u->pol, ps, depth)) return False; - if(!smb_io_unistr2("", &r_q->uni_class, r_q->hdr_class.buffer, ps, depth)) + if(!prs_unistr4("class", ps, depth, &q_u->class)) return False; if(!prs_align(ps)) @@ -561,9 +475,9 @@ BOOL reg_io_q_query_key(const char *desc, REG_Q_QUERY_KEY *r_q, prs_struct *ps, reads or writes a structure. ********************************************************************/ -BOOL reg_io_r_query_key(const char *desc, REG_R_QUERY_KEY *r_r, prs_struct *ps, int depth) +BOOL reg_io_r_query_key(const char *desc, REG_R_QUERY_KEY *r_u, prs_struct *ps, int depth) { - if (r_r == NULL) + if ( !r_u ) return False; prs_debug(ps, depth, desc, "reg_io_r_query_key"); @@ -572,32 +486,30 @@ BOOL reg_io_r_query_key(const char *desc, REG_R_QUERY_KEY *r_r, prs_struct *ps, if(!prs_align(ps)) return False; - if(!smb_io_unihdr ("", &r_r->hdr_class, ps, depth)) - return False; - if(!smb_io_unistr2("", &r_r->uni_class, r_r->hdr_class.buffer, ps, depth)) + if(!prs_unistr4("class", ps, depth, &r_u->class)) return False; if(!prs_align(ps)) return False; - if(!prs_uint32("num_subkeys ", ps, depth, &r_r->num_subkeys)) + if(!prs_uint32("num_subkeys ", ps, depth, &r_u->num_subkeys)) return False; - if(!prs_uint32("max_subkeylen ", ps, depth, &r_r->max_subkeylen)) + if(!prs_uint32("max_subkeylen ", ps, depth, &r_u->max_subkeylen)) return False; - if(!prs_uint32("reserved ", ps, depth, &r_r->reserved)) + if(!prs_uint32("reserved ", ps, depth, &r_u->reserved)) return False; - if(!prs_uint32("num_values ", ps, depth, &r_r->num_values)) + if(!prs_uint32("num_values ", ps, depth, &r_u->num_values)) return False; - if(!prs_uint32("max_valnamelen", ps, depth, &r_r->max_valnamelen)) + if(!prs_uint32("max_valnamelen", ps, depth, &r_u->max_valnamelen)) return False; - if(!prs_uint32("max_valbufsize", ps, depth, &r_r->max_valbufsize)) + if(!prs_uint32("max_valbufsize", ps, depth, &r_u->max_valbufsize)) return False; - if(!prs_uint32("sec_desc ", ps, depth, &r_r->sec_desc)) + if(!prs_uint32("sec_desc ", ps, depth, &r_u->sec_desc)) return False; - if(!smb_io_time("mod_time ", &r_r->mod_time, ps, depth)) + if(!smb_io_time("mod_time ", &r_u->mod_time, ps, depth)) return False; - if(!prs_werror("status", ps, depth, &r_r->status)) + if(!prs_werror("status", ps, depth, &r_u->status)) return False; return True; @@ -607,7 +519,7 @@ BOOL reg_io_r_query_key(const char *desc, REG_R_QUERY_KEY *r_r, prs_struct *ps, Inits a structure. ********************************************************************/ -void init_reg_q_unknown_1a(REG_Q_UNKNOWN_1A *q_o, POLICY_HND *hnd) +void init_reg_q_getversion(REG_Q_GETVERSION *q_o, POLICY_HND *hnd) { memcpy(&q_o->pol, hnd, sizeof(q_o->pol)); } @@ -617,18 +529,18 @@ void init_reg_q_unknown_1a(REG_Q_UNKNOWN_1A *q_o, POLICY_HND *hnd) reads or writes a structure. ********************************************************************/ -BOOL reg_io_q_unknown_1a(const char *desc, REG_Q_UNKNOWN_1A *r_q, prs_struct *ps, int depth) +BOOL reg_io_q_getversion(const char *desc, REG_Q_GETVERSION *q_u, prs_struct *ps, int depth) { - if (r_q == NULL) + if ( !q_u ) return False; - prs_debug(ps, depth, desc, "reg_io_q_unknown_1a"); + prs_debug(ps, depth, desc, "reg_io_q_getversion"); depth++; if(!prs_align(ps)) return False; - if(!smb_io_pol_hnd("", &r_q->pol, ps, depth)) + if(!smb_io_pol_hnd("", &q_u->pol, ps, depth)) return False; return True; @@ -638,20 +550,20 @@ BOOL reg_io_q_unknown_1a(const char *desc, REG_Q_UNKNOWN_1A *r_q, prs_struct *p reads or writes a structure. ********************************************************************/ -BOOL reg_io_r_unknown_1a(const char *desc, REG_R_UNKNOWN_1A *r_r, prs_struct *ps, int depth) +BOOL reg_io_r_getversion(const char *desc, REG_R_GETVERSION *r_u, prs_struct *ps, int depth) { - if (r_r == NULL) + if ( !r_u ) return False; - prs_debug(ps, depth, desc, "reg_io_r_unknown_1a"); + prs_debug(ps, depth, desc, "reg_io_r_getversion"); depth++; if(!prs_align(ps)) return False; - if(!prs_uint32("unknown", ps, depth, &r_r->unknown)) + if(!prs_uint32("unknown", ps, depth, &r_u->unknown)) return False; - if(!prs_werror("status" , ps, depth, &r_r->status)) + if(!prs_werror("status" , ps, depth, &r_u->status)) return False; return True; @@ -662,26 +574,24 @@ BOOL reg_io_r_unknown_1a(const char *desc, REG_R_UNKNOWN_1A *r_r, prs_struct *p reads or writes a structure. ********************************************************************/ -BOOL reg_io_q_save_key(const char *desc, REG_Q_SAVE_KEY *r_q, prs_struct *ps, int depth) +BOOL reg_io_q_restore_key(const char *desc, REG_Q_RESTORE_KEY *q_u, prs_struct *ps, int depth) { - if (r_q == NULL) + if ( !q_u ) return False; - prs_debug(ps, depth, desc, "reg_io_q_save_key"); + prs_debug(ps, depth, desc, "reg_io_q_restore_key"); depth++; if(!prs_align(ps)) return False; - if(!smb_io_pol_hnd("", &r_q->pol, ps, depth)) + if(!smb_io_pol_hnd("", &q_u->pol, ps, depth)) return False; - if(!smb_io_unihdr ("hdr_file", &r_q->hdr_file, ps, depth)) - return False; - if(!smb_io_unistr2("uni_file", &r_q->uni_file, r_q->hdr_file.buffer, ps, depth)) + if(!prs_unistr4("filename", ps, depth, &q_u->filename)) return False; - if(!prs_uint32("unknown", ps, depth, &r_q->unknown)) + if(!prs_uint32("flags", ps, depth, &q_u->flags)) return False; return True; @@ -691,61 +601,48 @@ BOOL reg_io_q_save_key(const char *desc, REG_Q_SAVE_KEY *r_q, prs_struct *ps, i reads or writes a structure. ********************************************************************/ -BOOL reg_io_r_save_key(const char *desc, REG_R_SAVE_KEY *r_r, prs_struct *ps, int depth) +BOOL reg_io_r_restore_key(const char *desc, REG_R_RESTORE_KEY *r_u, prs_struct *ps, int depth) { - if (r_r == NULL) + if ( !r_u ) return False; - prs_debug(ps, depth, desc, "reg_io_r_save_key"); + prs_debug(ps, depth, desc, "reg_io_r_restore_key"); depth++; if(!prs_align(ps)) return False; - if(!prs_werror("status" , ps, depth, &r_r->status)) + if(!prs_werror("status" , ps, depth, &r_u->status)) return False; return True; } -/******************************************************************* - Inits a structure. -********************************************************************/ - -void init_reg_q_open_hku(REG_Q_OPEN_HKU *q_o, - uint16 unknown_0, uint32 access_mask) -{ - q_o->ptr = 1; - q_o->unknown_0 = unknown_0; - q_o->unknown_1 = 0x0; /* random - changes */ - q_o->access_mask = access_mask; -} - /******************************************************************* reads or writes a structure. ********************************************************************/ -BOOL reg_io_q_open_hku(const char *desc, REG_Q_OPEN_HKU *r_q, prs_struct *ps, int depth) +BOOL reg_io_q_save_key(const char *desc, REG_Q_SAVE_KEY *q_u, prs_struct *ps, int depth) { - if (r_q == NULL) + if ( !q_u ) return False; - prs_debug(ps, depth, desc, "reg_io_q_open_hku"); + prs_debug(ps, depth, desc, "reg_io_q_save_key"); depth++; if(!prs_align(ps)) return False; - - if(!prs_uint32("ptr ", ps, depth, &r_q->ptr)) + + if(!smb_io_pol_hnd("", &q_u->pol, ps, depth)) return False; - if (r_q->ptr != 0) { - if(!prs_uint16("unknown_0 ", ps, depth, &r_q->unknown_0)) - return False; - if(!prs_uint16("unknown_1 ", ps, depth, &r_q->unknown_1)) - return False; - if(!prs_uint32("access_mask ", ps, depth, &r_q->access_mask)) - return False; - } + + if(!prs_unistr4("filename", ps, depth, &q_u->filename)) + return False; + +#if 0 /* reg_io_sec_attr() */ + if(!prs_uint32("unknown", ps, depth, &q_u->unknown)) + return False; +#endif return True; } @@ -754,21 +651,18 @@ BOOL reg_io_q_open_hku(const char *desc, REG_Q_OPEN_HKU *r_q, prs_struct *ps, i reads or writes a structure. ********************************************************************/ -BOOL reg_io_r_open_hku(const char *desc, REG_R_OPEN_HKU *r_r, prs_struct *ps, int depth) +BOOL reg_io_r_save_key(const char *desc, REG_R_SAVE_KEY *r_u, prs_struct *ps, int depth) { - if (r_r == NULL) + if ( !r_u ) return False; - prs_debug(ps, depth, desc, "reg_io_r_open_hku"); + prs_debug(ps, depth, desc, "reg_io_r_save_key"); depth++; if(!prs_align(ps)) return False; - if(!smb_io_pol_hnd("", &r_r->pol, ps, depth)) - return False; - - if(!prs_werror("status", ps, depth, &r_r->status)) + if(!prs_werror("status" , ps, depth, &r_u->status)) return False; return True; @@ -814,7 +708,7 @@ reads or writes a structure. BOOL reg_io_r_close(const char *desc, REG_R_CLOSE *r_u, prs_struct *ps, int depth) { - if (r_u == NULL) + if ( !r_u ) return False; prs_debug(ps, depth, desc, "reg_io_r_close"); @@ -838,24 +732,25 @@ BOOL reg_io_r_close(const char *desc, REG_R_CLOSE *r_u, prs_struct *ps, int dep makes a structure. ********************************************************************/ -void init_reg_q_set_key_sec(REG_Q_SET_KEY_SEC *q_i, POLICY_HND *pol, SEC_DESC_BUF *sec_desc_buf) +void init_reg_q_set_key_sec(REG_Q_SET_KEY_SEC *q_u, POLICY_HND *pol, + uint32 sec_info, SEC_DESC_BUF *sec_desc_buf) { - memcpy(&q_i->pol, pol, sizeof(q_i->pol)); + memcpy(&q_u->pol, pol, sizeof(q_u->pol)); - q_i->sec_info = DACL_SECURITY_INFORMATION; + q_u->sec_info = sec_info; - q_i->ptr = 1; - init_buf_hdr(&q_i->hdr_sec, sec_desc_buf->len, sec_desc_buf->len); - q_i->data = sec_desc_buf; + q_u->ptr = 1; + init_buf_hdr(&q_u->hdr_sec, sec_desc_buf->len, sec_desc_buf->len); + q_u->data = sec_desc_buf; } /******************************************************************* reads or writes a structure. ********************************************************************/ -BOOL reg_io_q_set_key_sec(const char *desc, REG_Q_SET_KEY_SEC *r_q, prs_struct *ps, int depth) +BOOL reg_io_q_set_key_sec(const char *desc, REG_Q_SET_KEY_SEC *q_u, prs_struct *ps, int depth) { - if (r_q == NULL) + if ( !q_u ) return False; prs_debug(ps, depth, desc, "reg_io_q_set_key_sec"); @@ -864,15 +759,15 @@ BOOL reg_io_q_set_key_sec(const char *desc, REG_Q_SET_KEY_SEC *r_q, prs_struct if(!prs_align(ps)) return False; - if(!smb_io_pol_hnd("", &r_q->pol, ps, depth)) + if(!smb_io_pol_hnd("", &q_u->pol, ps, depth)) return False; - if(!prs_uint32("sec_info", ps, depth, &r_q->sec_info)) + if(!prs_uint32("sec_info", ps, depth, &q_u->sec_info)) return False; - if(!prs_uint32("ptr ", ps, depth, &r_q->ptr)) + if(!prs_uint32("ptr ", ps, depth, &q_u->ptr)) return False; - if(!reg_io_hdrbuf_sec(r_q->ptr, NULL, &r_q->hdr_sec, r_q->data, ps, depth)) + if(!reg_io_hdrbuf_sec(q_u->ptr, NULL, &q_u->hdr_sec, q_u->data, ps, depth)) return False; return True; @@ -882,9 +777,9 @@ BOOL reg_io_q_set_key_sec(const char *desc, REG_Q_SET_KEY_SEC *r_q, prs_struct reads or writes a structure. ********************************************************************/ -BOOL reg_io_r_set_key_sec(const char *desc, REG_R_SET_KEY_SEC *r_q, prs_struct *ps, int depth) +BOOL reg_io_r_set_key_sec(const char *desc, REG_R_SET_KEY_SEC *q_u, prs_struct *ps, int depth) { - if (r_q == NULL) + if ( !q_u ) return False; prs_debug(ps, depth, desc, "reg_io_r_set_key_sec"); @@ -893,7 +788,7 @@ BOOL reg_io_r_set_key_sec(const char *desc, REG_R_SET_KEY_SEC *r_q, prs_struct * if(!prs_align(ps)) return False; - if(!prs_werror("status", ps, depth, &r_q->status)) + if(!prs_werror("status", ps, depth, &q_u->status)) return False; return True; @@ -904,28 +799,27 @@ BOOL reg_io_r_set_key_sec(const char *desc, REG_R_SET_KEY_SEC *r_q, prs_struct * makes a structure. ********************************************************************/ -void init_reg_q_get_key_sec(REG_Q_GET_KEY_SEC *q_i, POLICY_HND *pol, - uint32 sec_buf_size, SEC_DESC_BUF *psdb) +void init_reg_q_get_key_sec(REG_Q_GET_KEY_SEC *q_u, POLICY_HND *pol, + uint32 sec_info, uint32 sec_buf_size, + SEC_DESC_BUF *psdb) { - memcpy(&q_i->pol, pol, sizeof(q_i->pol)); + memcpy(&q_u->pol, pol, sizeof(q_u->pol)); - q_i->sec_info = OWNER_SECURITY_INFORMATION | - GROUP_SECURITY_INFORMATION | - DACL_SECURITY_INFORMATION; + q_u->sec_info = sec_info; - q_i->ptr = psdb != NULL ? 1 : 0; - q_i->data = psdb; + q_u->ptr = psdb != NULL ? 1 : 0; + q_u->data = psdb; - init_buf_hdr(&q_i->hdr_sec, sec_buf_size, 0); + init_buf_hdr(&q_u->hdr_sec, sec_buf_size, 0); } /******************************************************************* reads or writes a structure. ********************************************************************/ -BOOL reg_io_q_get_key_sec(const char *desc, REG_Q_GET_KEY_SEC *r_q, prs_struct *ps, int depth) +BOOL reg_io_q_get_key_sec(const char *desc, REG_Q_GET_KEY_SEC *q_u, prs_struct *ps, int depth) { - if (r_q == NULL) + if ( !q_u ) return False; prs_debug(ps, depth, desc, "reg_io_q_get_key_sec"); @@ -934,15 +828,15 @@ BOOL reg_io_q_get_key_sec(const char *desc, REG_Q_GET_KEY_SEC *r_q, prs_struct if(!prs_align(ps)) return False; - if(!smb_io_pol_hnd("", &r_q->pol, ps, depth)) + if(!smb_io_pol_hnd("", &q_u->pol, ps, depth)) return False; - if(!prs_uint32("sec_info", ps, depth, &r_q->sec_info)) + if(!prs_uint32("sec_info", ps, depth, &q_u->sec_info)) return False; - if(!prs_uint32("ptr ", ps, depth, &r_q->ptr)) + if(!prs_uint32("ptr ", ps, depth, &q_u->ptr)) return False; - if(!reg_io_hdrbuf_sec(r_q->ptr, NULL, &r_q->hdr_sec, r_q->data, ps, depth)) + if(!reg_io_hdrbuf_sec(q_u->ptr, NULL, &q_u->hdr_sec, q_u->data, ps, depth)) return False; return True; @@ -968,9 +862,9 @@ makes a structure. reads or writes a structure. ********************************************************************/ -BOOL reg_io_r_get_key_sec(const char *desc, REG_R_GET_KEY_SEC *r_q, prs_struct *ps, int depth) +BOOL reg_io_r_get_key_sec(const char *desc, REG_R_GET_KEY_SEC *q_u, prs_struct *ps, int depth) { - if (r_q == NULL) + if ( !q_u ) return False; prs_debug(ps, depth, desc, "reg_io_r_get_key_sec"); @@ -979,19 +873,19 @@ BOOL reg_io_r_get_key_sec(const char *desc, REG_R_GET_KEY_SEC *r_q, prs_struct if(!prs_align(ps)) return False; - if(!prs_uint32("ptr ", ps, depth, &r_q->ptr)) + if(!prs_uint32("ptr ", ps, depth, &q_u->ptr)) return False; - if (r_q->ptr != 0) { - if(!smb_io_hdrbuf("", &r_q->hdr_sec, ps, depth)) + if (q_u->ptr != 0) { + if(!smb_io_hdrbuf("", &q_u->hdr_sec, ps, depth)) return False; - if(!sec_io_desc_buf("", &r_q->data, ps, depth)) + if(!sec_io_desc_buf("", &q_u->data, ps, depth)) return False; if(!prs_align(ps)) return False; } - if(!prs_werror("status", ps, depth, &r_q->status)) + if(!prs_werror("status", ps, depth, &q_u->status)) return False; return True; @@ -1001,29 +895,29 @@ BOOL reg_io_r_get_key_sec(const char *desc, REG_R_GET_KEY_SEC *r_q, prs_struct makes a structure. ********************************************************************/ -BOOL init_reg_q_info(REG_Q_INFO *q_i, POLICY_HND *pol, char* val_name) +BOOL init_reg_q_info(REG_Q_INFO *q_u, POLICY_HND *pol, const char *val_name, + REGVAL_BUFFER *value_output) { - if (q_i == NULL) + if (q_u == NULL) return False; - q_i->pol = *pol; + q_u->pol = *pol; - init_unistr2(&q_i->uni_type, val_name, UNI_STR_TERMINATE); - init_uni_hdr(&q_i->hdr_type, &q_i->uni_type); + init_unistr4(&q_u->name, val_name, UNI_STR_TERMINATE); - q_i->ptr_reserved = 1; - q_i->ptr_buf = 1; + q_u->ptr_reserved = 1; + q_u->ptr_buf = 1; - q_i->ptr_bufsize = 1; - q_i->bufsize = 0; - q_i->buf_unk = 0; + q_u->ptr_bufsize = 1; + q_u->bufsize = value_output->buf_max_len; + q_u->buf_unk = 0; - q_i->unk1 = 0; - q_i->ptr_buflen = 1; - q_i->buflen = 0; + q_u->unk1 = 0; + q_u->ptr_buflen = 1; + q_u->buflen = value_output->buf_max_len; - q_i->ptr_buflen2 = 1; - q_i->buflen2 = 0; + q_u->ptr_buflen2 = 1; + q_u->buflen2 = 0; return True; } @@ -1032,9 +926,9 @@ BOOL init_reg_q_info(REG_Q_INFO *q_i, POLICY_HND *pol, char* val_name) reads or writes a structure. ********************************************************************/ -BOOL reg_io_q_info(const char *desc, REG_Q_INFO *r_q, prs_struct *ps, int depth) +BOOL reg_io_q_info(const char *desc, REG_Q_INFO *q_u, prs_struct *ps, int depth) { - if (r_q == NULL) + if ( !q_u ) return False; prs_debug(ps, depth, desc, "reg_io_q_info"); @@ -1043,43 +937,41 @@ BOOL reg_io_q_info(const char *desc, REG_Q_INFO *r_q, prs_struct *ps, int depth if(!prs_align(ps)) return False; - if(!smb_io_pol_hnd("", &r_q->pol, ps, depth)) - return False; - if(!smb_io_unihdr ("", &r_q->hdr_type, ps, depth)) + if(!smb_io_pol_hnd("", &q_u->pol, ps, depth)) return False; - if(!smb_io_unistr2("", &r_q->uni_type, r_q->hdr_type.buffer, ps, depth)) + if(!prs_unistr4("name", ps, depth, &q_u->name)) return False; if(!prs_align(ps)) return False; - if(!prs_uint32("ptr_reserved", ps, depth, &(r_q->ptr_reserved))) + if(!prs_uint32("ptr_reserved", ps, depth, &(q_u->ptr_reserved))) return False; - if(!prs_uint32("ptr_buf", ps, depth, &(r_q->ptr_buf))) + if(!prs_uint32("ptr_buf", ps, depth, &(q_u->ptr_buf))) return False; - if(r_q->ptr_buf) { - if(!prs_uint32("ptr_bufsize", ps, depth, &(r_q->ptr_bufsize))) + if(q_u->ptr_buf) { + if(!prs_uint32("ptr_bufsize", ps, depth, &(q_u->ptr_bufsize))) return False; - if(!prs_uint32("bufsize", ps, depth, &(r_q->bufsize))) + if(!prs_uint32("bufsize", ps, depth, &(q_u->bufsize))) return False; - if(!prs_uint32("buf_unk", ps, depth, &(r_q->buf_unk))) + if(!prs_uint32("buf_unk", ps, depth, &(q_u->buf_unk))) return False; } - if(!prs_uint32("unk1", ps, depth, &(r_q->unk1))) + if(!prs_uint32("unk1", ps, depth, &(q_u->unk1))) return False; - if(!prs_uint32("ptr_buflen", ps, depth, &(r_q->ptr_buflen))) + if(!prs_uint32("ptr_buflen", ps, depth, &(q_u->ptr_buflen))) return False; - if (r_q->ptr_buflen) { - if(!prs_uint32("buflen", ps, depth, &(r_q->buflen))) + if (q_u->ptr_buflen) { + if(!prs_uint32("buflen", ps, depth, &(q_u->buflen))) return False; - if(!prs_uint32("ptr_buflen2", ps, depth, &(r_q->ptr_buflen2))) + if(!prs_uint32("ptr_buflen2", ps, depth, &(q_u->ptr_buflen2))) return False; - if(!prs_uint32("buflen2", ps, depth, &(r_q->buflen2))) + if(!prs_uint32("buflen2", ps, depth, &(q_u->buflen2))) return False; } @@ -1091,72 +983,36 @@ BOOL reg_io_q_info(const char *desc, REG_Q_INFO *r_q, prs_struct *ps, int depth New version to replace older init_reg_r_info() ********************************************************************/ -BOOL new_init_reg_r_info(uint32 include_keyval, REG_R_INFO *r_r, +BOOL init_reg_r_info(uint32 include_keyval, REG_R_INFO *r_u, REGISTRY_VALUE *val, WERROR status) { - uint32 buf_len = 0; - BUFFER2 buf2; + uint32 buf_len = 0; + REGVAL_BUFFER buf2; - if(r_r == NULL) + if( !r_u || !val ) return False; - if ( !val ) - return False; - - r_r->ptr_type = 1; - r_r->type = val->type; + r_u->type = TALLOC_P( get_talloc_ctx(), uint32 ); + *r_u->type = val->type; - /* if include_keyval is not set, don't send the key value, just - the buflen data. probably used by NT5 to allocate buffer space - SK */ - - if ( include_keyval ) { - r_r->ptr_uni_val = 1; - buf_len = reg_init_buffer2( &r_r->uni_val, val ); + buf_len = reg_init_regval_buffer( &buf2, val ); - } - else { - /* dummy buffer used so we can get the size */ - r_r->ptr_uni_val = 0; - buf_len = reg_init_buffer2( &buf2, val ); - } - - r_r->ptr_max_len = 1; - r_r->buf_max_len = buf_len; - - r_r->ptr_len = 1; - r_r->buf_len = buf_len; - - r_r->status = status; - - return True; -} - -/******************************************************************* - Inits a structure. -********************************************************************/ - -BOOL init_reg_r_info(uint32 include_keyval, REG_R_INFO *r_r, - BUFFER2* buf, uint32 type, WERROR status) -{ - if(r_r == NULL) - return False; - - r_r->ptr_type = 1; - r_r->type = type; + r_u->buf_max_len = TALLOC_P( get_talloc_ctx(), uint32 ); + *r_u->buf_max_len = buf_len; + r_u->buf_len = TALLOC_P( get_talloc_ctx(), uint32 ); + *r_u->buf_len = buf_len; + /* if include_keyval is not set, don't send the key value, just the buflen data. probably used by NT5 to allocate buffer space - SK */ - r_r->ptr_uni_val = include_keyval ? 1:0; - r_r->uni_val = *buf; - - r_r->ptr_max_len = 1; - r_r->buf_max_len = r_r->uni_val.buf_max_len; - - r_r->ptr_len = 1; - r_r->buf_len = r_r->uni_val.buf_len; + if ( include_keyval ) { + r_u->value = TALLOC_P( get_talloc_ctx(), REGVAL_BUFFER ); + /* steal the memory */ + *r_u->value = buf2; + } - r_r->status = status; + r_u->status = status; return True; } @@ -1165,9 +1021,9 @@ BOOL init_reg_r_info(uint32 include_keyval, REG_R_INFO *r_r, reads or writes a structure. ********************************************************************/ -BOOL reg_io_r_info(const char *desc, REG_R_INFO *r_r, prs_struct *ps, int depth) +BOOL reg_io_r_info(const char *desc, REG_R_INFO *r_u, prs_struct *ps, int depth) { - if (r_r == NULL) + if ( !r_u ) return False; prs_debug(ps, depth, desc, "reg_io_r_info"); @@ -1176,41 +1032,20 @@ BOOL reg_io_r_info(const char *desc, REG_R_INFO *r_r, prs_struct *ps, int depth) if(!prs_align(ps)) return False; - if(!prs_uint32("ptr_type", ps, depth, &(r_r->ptr_type))) + if ( !prs_pointer("type", ps, depth, (void**)&r_u->type, sizeof(uint32), (PRS_POINTER_CAST)prs_uint32)) return False; - if (r_r->ptr_type != 0) { - if(!prs_uint32("type", ps, depth, &r_r->type)) - return False; - } - - if(!prs_uint32("ptr_uni_val", ps, depth, &(r_r->ptr_uni_val))) + if ( !prs_pointer("value", ps, depth, (void**)&r_u->value, sizeof(REGVAL_BUFFER), (PRS_POINTER_CAST)smb_io_regval_buffer)) return False; - - if(r_r->ptr_uni_val != 0) { - if(!smb_io_buffer2("uni_val", &r_r->uni_val, r_r->ptr_uni_val, ps, depth)) - return False; - } - if(!prs_align(ps)) return False; - if(!prs_uint32("ptr_max_len", ps, depth, &(r_r->ptr_max_len))) + if ( !prs_pointer("buf_max_len", ps, depth, (void**)&r_u->buf_max_len, sizeof(uint32), (PRS_POINTER_CAST)prs_uint32)) return False; - - if (r_r->ptr_max_len != 0) { - if(!prs_uint32("buf_max_len", ps, depth, &(r_r->buf_max_len))) + if ( !prs_pointer("buf_len", ps, depth, (void**)&r_u->buf_len, sizeof(uint32), (PRS_POINTER_CAST)prs_uint32)) return False; - } - if(!prs_uint32("ptr_len", ps, depth, &(r_r->ptr_len))) - return False; - if (r_r->ptr_len != 0) { - if(!prs_uint32("buf_len", ps, depth, &(r_r->buf_len))) - return False; - } - - if(!prs_werror("status", ps, depth, &r_r->status)) + if(!prs_werror("status", ps, depth, &r_u->status)) return False; return True; @@ -1220,28 +1055,29 @@ BOOL reg_io_r_info(const char *desc, REG_R_INFO *r_r, prs_struct *ps, int depth) makes a structure. ********************************************************************/ -void init_reg_q_enum_val(REG_Q_ENUM_VALUE *q_i, POLICY_HND *pol, - uint32 val_idx, UNISTR2 *uni2, +void init_reg_q_enum_val(REG_Q_ENUM_VALUE *q_u, POLICY_HND *pol, + uint32 val_idx, char *name, uint32 max_buf_len) { - ZERO_STRUCTP(q_i); + ZERO_STRUCTP(q_u); + + memcpy(&q_u->pol, pol, sizeof(q_u->pol)); - memcpy(&q_i->pol, pol, sizeof(q_i->pol)); + q_u->val_index = val_idx; - q_i->val_index = val_idx; - init_uni_hdr(&q_i->hdr_name, uni2); + init_unistr4( &q_u->name, name, UNI_STR_TERMINATE ); - q_i->ptr_type = 1; - q_i->type = 0x0; + q_u->type = TALLOC_P( get_talloc_ctx(), uint32 ); + *q_u->type = 0x0; - q_i->ptr_value = 1; - q_i->buf_value.buf_max_len = max_buf_len; + q_u->value = TALLOC_P( get_talloc_ctx(), REGVAL_BUFFER ); + q_u->value->buf_max_len = max_buf_len; - q_i->ptr1 = 1; - q_i->len_value1 = max_buf_len; + q_u->len_value1 = TALLOC_P( get_talloc_ctx(), uint32 ); + *q_u->len_value1 = max_buf_len; - q_i->ptr2 = 1; - q_i->len_value2 = 0; + q_u->len_value2 = TALLOC_P( get_talloc_ctx(), uint32 ); + *q_u->len_value2 = max_buf_len; } /******************************************************************* @@ -1260,26 +1096,25 @@ void init_reg_r_enum_val(REG_R_ENUM_VALUE *r_u, REGISTRY_VALUE *val ) DEBUG(10,("init_reg_r_enum_val: Valuename => [%s]\n", val->valuename)); - init_unistr2( &r_u->uni_name, val->valuename, UNI_STR_TERMINATE); - init_uni_hdr( &r_u->hdr_name, &r_u->uni_name); + init_unistr4( &r_u->name, val->valuename, UNI_STR_TERMINATE); /* type */ - r_u->ptr_type = 1; - r_u->type = val->type; + r_u->type = TALLOC_P( get_talloc_ctx(), uint32 ); + *r_u->type = val->type; /* REG_SZ & REG_MULTI_SZ must be converted to UNICODE */ - r_u->ptr_value = 1; - real_size = reg_init_buffer2( &r_u->buf_value, val ); + r_u->value = TALLOC_P( get_talloc_ctx(), REGVAL_BUFFER ); + real_size = reg_init_regval_buffer( r_u->value, val ); /* lengths */ - r_u->ptr1 = 1; - r_u->len_value1 = real_size; + r_u->len_value1 = TALLOC_P( get_talloc_ctx(), uint32 ); + *r_u->len_value1 = real_size; - r_u->ptr2 = 1; - r_u->len_value2 = real_size; + r_u->len_value2 = TALLOC_P( get_talloc_ctx(), uint32 ); + *r_u->len_value2 = real_size; DEBUG(8,("init_reg_r_enum_val: Exit\n")); } @@ -1288,9 +1123,9 @@ void init_reg_r_enum_val(REG_R_ENUM_VALUE *r_u, REGISTRY_VALUE *val ) reads or writes a structure. ********************************************************************/ -BOOL reg_io_q_enum_val(const char *desc, REG_Q_ENUM_VALUE *q_q, prs_struct *ps, int depth) +BOOL reg_io_q_enum_val(const char *desc, REG_Q_ENUM_VALUE *q_u, prs_struct *ps, int depth) { - if (q_q == NULL) + if (q_u == NULL) return False; prs_debug(ps, depth, desc, "reg_io_q_enum_val"); @@ -1299,46 +1134,29 @@ BOOL reg_io_q_enum_val(const char *desc, REG_Q_ENUM_VALUE *q_q, prs_struct *ps, if(!prs_align(ps)) return False; - if(!smb_io_pol_hnd("", &q_q->pol, ps, depth)) + if(!smb_io_pol_hnd("", &q_u->pol, ps, depth)) return False; - if(!prs_uint32("val_index", ps, depth, &q_q->val_index)) + if(!prs_uint32("val_index", ps, depth, &q_u->val_index)) return False; - if(!smb_io_unihdr ("hdr_name", &q_q->hdr_name, ps, depth)) - return False; - if(!smb_io_unistr2("uni_name", &q_q->uni_name, q_q->hdr_name.buffer, ps, depth)) + if(!prs_unistr4("name", ps, depth, &q_u->name )) return False; if(!prs_align(ps)) return False; - if(!prs_uint32("ptr_type", ps, depth, &q_q->ptr_type)) + if(!prs_pointer("type", ps, depth, (void**)&q_u->type, sizeof(uint32), (PRS_POINTER_CAST)prs_uint32)) return False; - if (q_q->ptr_type != 0) { - if(!prs_uint32("type", ps, depth, &q_q->type)) - return False; - } - - if(!prs_uint32("ptr_value", ps, depth, &q_q->ptr_value)) - return False; - if(!smb_io_buffer2("buf_value", &q_q->buf_value, q_q->ptr_value, ps, depth)) + if ( !prs_pointer("value", ps, depth, (void**)&q_u->value, sizeof(REGVAL_BUFFER), (PRS_POINTER_CAST)smb_io_regval_buffer)) return False; if(!prs_align(ps)) return False; - if(!prs_uint32("ptr1", ps, depth, &q_q->ptr1)) + if(!prs_pointer("len_value1", ps, depth, (void**)&q_u->len_value1, sizeof(uint32), (PRS_POINTER_CAST)prs_uint32)) return False; - if (q_q->ptr1 != 0) { - if(!prs_uint32("len_value1", ps, depth, &q_q->len_value1)) - return False; - } - if(!prs_uint32("ptr2", ps, depth, &q_q->ptr2)) + if(!prs_pointer("len_value2", ps, depth, (void**)&q_u->len_value2, sizeof(uint32), (PRS_POINTER_CAST)prs_uint32)) return False; - if (q_q->ptr2 != 0) { - if(!prs_uint32("len_value2", ps, depth, &q_q->len_value2)) - return False; - } return True; } @@ -1347,9 +1165,9 @@ BOOL reg_io_q_enum_val(const char *desc, REG_Q_ENUM_VALUE *q_q, prs_struct *ps, reads or writes a structure. ********************************************************************/ -BOOL reg_io_r_enum_val(const char *desc, REG_R_ENUM_VALUE *r_q, prs_struct *ps, int depth) +BOOL reg_io_r_enum_val(const char *desc, REG_R_ENUM_VALUE *r_u, prs_struct *ps, int depth) { - if (r_q == NULL) + if ( !r_u ) return False; prs_debug(ps, depth, desc, "reg_io_r_enum_val"); @@ -1358,43 +1176,26 @@ BOOL reg_io_r_enum_val(const char *desc, REG_R_ENUM_VALUE *r_q, prs_struct *ps, if(!prs_align(ps)) return False; - if(!smb_io_unihdr ("hdr_name", &r_q->hdr_name, ps, depth)) - return False; - if(!smb_io_unistr2("uni_name", &r_q->uni_name, r_q->hdr_name.buffer, ps, depth)) + if(!prs_unistr4("name", ps, depth, &r_u->name )) return False; if(!prs_align(ps)) return False; - if(!prs_uint32("ptr_type", ps, depth, &r_q->ptr_type)) + if(!prs_pointer("type", ps, depth, (void**)&r_u->type, sizeof(uint32), (PRS_POINTER_CAST)prs_uint32)) return False; - if (r_q->ptr_type != 0) { - if(!prs_uint32("type", ps, depth, &r_q->type)) - return False; - } - - if(!prs_uint32("ptr_value", ps, depth, &r_q->ptr_value)) - return False; - if(!smb_io_buffer2("buf_value", &r_q->buf_value, r_q->ptr_value, ps, depth)) + if ( !prs_pointer("value", ps, depth, (void**)&r_u->value, sizeof(REGVAL_BUFFER), (PRS_POINTER_CAST)smb_io_regval_buffer)) return False; if(!prs_align(ps)) return False; - if(!prs_uint32("ptr1", ps, depth, &r_q->ptr1)) + if(!prs_pointer("len_value1", ps, depth, (void**)&r_u->len_value1, sizeof(uint32), (PRS_POINTER_CAST)prs_uint32)) return False; - if (r_q->ptr1 != 0) { - if(!prs_uint32("len_value1", ps, depth, &r_q->len_value1)) - return False; - } - - if(!prs_uint32("ptr2", ps, depth, &r_q->ptr2)) + if(!prs_pointer("len_value2", ps, depth, (void**)&r_u->len_value2, sizeof(uint32), (PRS_POINTER_CAST)prs_uint32)) return False; - if (r_q->ptr2 != 0) { - if(!prs_uint32("len_value2", ps, depth, &r_q->len_value2)) - return False; - } - if(!prs_werror("status", ps, depth, &r_q->status)) + + if(!prs_werror("status", ps, depth, &r_u->status)) return False; return True; @@ -1404,53 +1205,55 @@ BOOL reg_io_r_enum_val(const char *desc, REG_R_ENUM_VALUE *r_q, prs_struct *ps, makes a structure. ********************************************************************/ -void init_reg_q_create_val(REG_Q_CREATE_VALUE *q_i, POLICY_HND *pol, +void init_reg_q_set_val(REG_Q_SET_VALUE *q_u, POLICY_HND *pol, char *val_name, uint32 type, - BUFFER3 *val) + RPC_DATA_BLOB *val) { - ZERO_STRUCTP(q_i); + ZERO_STRUCTP(q_u); - memcpy(&q_i->pol, pol, sizeof(q_i->pol)); + memcpy(&q_u->pol, pol, sizeof(q_u->pol)); - init_unistr2(&q_i->uni_name, val_name, UNI_STR_TERMINATE); - init_uni_hdr(&q_i->hdr_name, &q_i->uni_name); + init_unistr4(&q_u->name, val_name, UNI_STR_TERMINATE); - q_i->type = type; - q_i->buf_value = val; + q_u->type = type; + q_u->value = *val; + q_u->size = val->buf_len; } /******************************************************************* reads or writes a structure. ********************************************************************/ -BOOL reg_io_q_create_val(const char *desc, REG_Q_CREATE_VALUE *q_q, prs_struct *ps, int depth) +BOOL reg_io_q_set_val(const char *desc, REG_Q_SET_VALUE *q_u, prs_struct *ps, int depth) { - if (q_q == NULL) + if (q_u == NULL) return False; - prs_debug(ps, depth, desc, "reg_io_q_create_val"); + prs_debug(ps, depth, desc, "reg_io_q_set_val"); depth++; if(!prs_align(ps)) return False; - if(!smb_io_pol_hnd("", &q_q->pol, ps, depth)) + if(!smb_io_pol_hnd("", &q_u->pol, ps, depth)) return False; - if(!smb_io_unihdr ("hdr_name", &q_q->hdr_name, ps, depth)) - return False; - if(!smb_io_unistr2("uni_name", &q_q->uni_name, q_q->hdr_name.buffer, ps, depth)) + if(!prs_unistr4("name", ps, depth, &q_u->name )) return False; if(!prs_align(ps)) return False; - if(!prs_uint32("type", ps, depth, &q_q->type)) + if(!prs_uint32("type", ps, depth, &q_u->type)) return False; - if(!smb_io_buffer3("buf_value", q_q->buf_value, ps, depth)) + + if(!smb_io_rpc_blob("value", &q_u->value, ps, depth )) return False; if(!prs_align(ps)) return False; + if(!prs_uint32("size", ps, depth, &q_u->size)) + return False; + return True; } @@ -1458,18 +1261,18 @@ BOOL reg_io_q_create_val(const char *desc, REG_Q_CREATE_VALUE *q_q, prs_struct reads or writes a structure. ********************************************************************/ -BOOL reg_io_r_create_val(const char *desc, REG_R_CREATE_VALUE *r_q, prs_struct *ps, int depth) +BOOL reg_io_r_set_val(const char *desc, REG_R_SET_VALUE *q_u, prs_struct *ps, int depth) { - if (r_q == NULL) + if ( !q_u ) return False; - prs_debug(ps, depth, desc, "reg_io_r_create_val"); + prs_debug(ps, depth, desc, "reg_io_r_set_val"); depth++; if(!prs_align(ps)) return False; - if(!prs_werror("status", ps, depth, &r_q->status)) + if(!prs_werror("status", ps, depth, &q_u->status)) return False; return True; @@ -1479,23 +1282,23 @@ BOOL reg_io_r_create_val(const char *desc, REG_R_CREATE_VALUE *r_q, prs_struct makes a structure. ********************************************************************/ -void init_reg_q_enum_key(REG_Q_ENUM_KEY *q_i, POLICY_HND *pol, uint32 key_idx) +void init_reg_q_enum_key(REG_Q_ENUM_KEY *q_u, POLICY_HND *pol, uint32 key_idx) { - memcpy(&q_i->pol, pol, sizeof(q_i->pol)); + memcpy(&q_u->pol, pol, sizeof(q_u->pol)); - q_i->key_index = key_idx; - q_i->key_name_len = 0; - q_i->unknown_1 = 0x0414; + q_u->key_index = key_idx; + q_u->key_name_len = 0; + q_u->unknown_1 = 0x0414; - q_i->ptr1 = 1; - q_i->unknown_2 = 0x0000020A; - memset(q_i->pad1, 0, sizeof(q_i->pad1)); + q_u->ptr1 = 1; + q_u->unknown_2 = 0x0000020A; + memset(q_u->pad1, 0, sizeof(q_u->pad1)); - q_i->ptr2 = 1; - memset(q_i->pad2, 0, sizeof(q_i->pad2)); + q_u->ptr2 = 1; + memset(q_u->pad2, 0, sizeof(q_u->pad2)); - q_i->ptr3 = 1; - unix_to_nt_time(&q_i->time, 0); /* current time? */ + q_u->ptr3 = 1; + unix_to_nt_time(&q_u->time, 0); /* current time? */ } /******************************************************************* @@ -1525,9 +1328,9 @@ void init_reg_r_enum_key(REG_R_ENUM_KEY *r_u, char *subkey, uint32 unknown_1, reads or writes a structure. ********************************************************************/ -BOOL reg_io_q_enum_key(const char *desc, REG_Q_ENUM_KEY *q_q, prs_struct *ps, int depth) +BOOL reg_io_q_enum_key(const char *desc, REG_Q_ENUM_KEY *q_u, prs_struct *ps, int depth) { - if (q_q == NULL) + if (q_u == NULL) return False; prs_debug(ps, depth, desc, "reg_io_q_enum_key"); @@ -1536,39 +1339,39 @@ BOOL reg_io_q_enum_key(const char *desc, REG_Q_ENUM_KEY *q_q, prs_struct *ps, i if(!prs_align(ps)) return False; - if(!smb_io_pol_hnd("", &q_q->pol, ps, depth)) + if(!smb_io_pol_hnd("", &q_u->pol, ps, depth)) return False; - if(!prs_uint32("key_index", ps, depth, &q_q->key_index)) + if(!prs_uint32("key_index", ps, depth, &q_u->key_index)) return False; - if(!prs_uint16("key_name_len", ps, depth, &q_q->key_name_len)) + if(!prs_uint16("key_name_len", ps, depth, &q_u->key_name_len)) return False; - if(!prs_uint16("unknown_1", ps, depth, &q_q->unknown_1)) + if(!prs_uint16("unknown_1", ps, depth, &q_u->unknown_1)) return False; - if(!prs_uint32("ptr1", ps, depth, &q_q->ptr1)) + if(!prs_uint32("ptr1", ps, depth, &q_u->ptr1)) return False; - if (q_q->ptr1 != 0) { - if(!prs_uint32("unknown_2", ps, depth, &q_q->unknown_2)) + if (q_u->ptr1 != 0) { + if(!prs_uint32("unknown_2", ps, depth, &q_u->unknown_2)) return False; - if(!prs_uint8s(False, "pad1", ps, depth, q_q->pad1, sizeof(q_q->pad1))) + if(!prs_uint8s(False, "pad1", ps, depth, q_u->pad1, sizeof(q_u->pad1))) return False; } - if(!prs_uint32("ptr2", ps, depth, &q_q->ptr2)) + if(!prs_uint32("ptr2", ps, depth, &q_u->ptr2)) return False; - if (q_q->ptr2 != 0) { - if(!prs_uint8s(False, "pad2", ps, depth, q_q->pad2, sizeof(q_q->pad2))) + if (q_u->ptr2 != 0) { + if(!prs_uint8s(False, "pad2", ps, depth, q_u->pad2, sizeof(q_u->pad2))) return False; } - if(!prs_uint32("ptr3", ps, depth, &q_q->ptr3)) + if(!prs_uint32("ptr3", ps, depth, &q_u->ptr3)) return False; - if (q_q->ptr3 != 0) { - if(!smb_io_time("", &q_q->time, ps, depth)) + if (q_u->ptr3 != 0) { + if(!smb_io_time("", &q_u->time, ps, depth)) return False; } @@ -1579,9 +1382,9 @@ BOOL reg_io_q_enum_key(const char *desc, REG_Q_ENUM_KEY *q_q, prs_struct *ps, i reads or writes a structure. ********************************************************************/ -BOOL reg_io_r_enum_key(const char *desc, REG_R_ENUM_KEY *r_q, prs_struct *ps, int depth) +BOOL reg_io_r_enum_key(const char *desc, REG_R_ENUM_KEY *q_u, prs_struct *ps, int depth) { - if (r_q == NULL) + if ( !q_u ) return False; prs_debug(ps, depth, desc, "reg_io_r_enum_key"); @@ -1590,42 +1393,42 @@ BOOL reg_io_r_enum_key(const char *desc, REG_R_ENUM_KEY *r_q, prs_struct *ps, i if(!prs_align(ps)) return False; - if(!prs_uint16("key_name_len", ps, depth, &r_q->key_name_len)) + if(!prs_uint16("key_name_len", ps, depth, &q_u->key_name_len)) return False; - if(!prs_uint16("unknown_1", ps, depth, &r_q->unknown_1)) + if(!prs_uint16("unknown_1", ps, depth, &q_u->unknown_1)) return False; - if(!prs_uint32("ptr1", ps, depth, &r_q->ptr1)) + if(!prs_uint32("ptr1", ps, depth, &q_u->ptr1)) return False; - if (r_q->ptr1 != 0) { - if(!prs_uint32("unknown_2", ps, depth, &r_q->unknown_2)) + if (q_u->ptr1 != 0) { + if(!prs_uint32("unknown_2", ps, depth, &q_u->unknown_2)) return False; - if(!prs_uint32("unknown_3", ps, depth, &r_q->unknown_3)) + if(!prs_uint32("unknown_3", ps, depth, &q_u->unknown_3)) return False; - if(!smb_io_unistr3("key_name", &r_q->key_name, ps, depth)) + if(!smb_io_unistr3("key_name", &q_u->key_name, ps, depth)) return False; if(!prs_align(ps)) return False; } - if(!prs_uint32("ptr2", ps, depth, &r_q->ptr2)) + if(!prs_uint32("ptr2", ps, depth, &q_u->ptr2)) return False; - if (r_q->ptr2 != 0) { - if(!prs_uint8s(False, "pad2", ps, depth, r_q->pad2, sizeof(r_q->pad2))) + if (q_u->ptr2 != 0) { + if(!prs_uint8s(False, "pad2", ps, depth, q_u->pad2, sizeof(q_u->pad2))) return False; } - if(!prs_uint32("ptr3", ps, depth, &r_q->ptr3)) + if(!prs_uint32("ptr3", ps, depth, &q_u->ptr3)) return False; - if (r_q->ptr3 != 0) { - if(!smb_io_time("", &r_q->time, ps, depth)) + if (q_u->ptr3 != 0) { + if(!smb_io_time("", &q_u->time, ps, depth)) return False; } - if(!prs_werror("status", ps, depth, &r_q->status)) + if(!prs_werror("status", ps, depth, &q_u->status)) return False; return True; @@ -1635,46 +1438,43 @@ BOOL reg_io_r_enum_key(const char *desc, REG_R_ENUM_KEY *r_q, prs_struct *ps, i makes a structure. ********************************************************************/ -void init_reg_q_open_entry(REG_Q_OPEN_ENTRY *r_q, POLICY_HND *pol, +void init_reg_q_open_entry(REG_Q_OPEN_ENTRY *q_u, POLICY_HND *pol, char *key_name, uint32 access_desired) { - memcpy(&r_q->pol, pol, sizeof(r_q->pol)); + memcpy(&q_u->pol, pol, sizeof(q_u->pol)); - init_unistr2(&r_q->uni_name, key_name, UNI_STR_TERMINATE); - init_uni_hdr(&r_q->hdr_name, &r_q->uni_name); + init_unistr4(&q_u->name, key_name, UNI_STR_TERMINATE); - r_q->unknown_0 = 0x00000000; - r_q->access_desired = access_desired; + q_u->unknown_0 = 0x00000000; + q_u->access = access_desired; } /******************************************************************* reads or writes a structure. ********************************************************************/ -BOOL reg_io_q_open_entry(const char *desc, REG_Q_OPEN_ENTRY *r_q, prs_struct *ps, int depth) +BOOL reg_io_q_open_entry(const char *desc, REG_Q_OPEN_ENTRY *q_u, prs_struct *ps, int depth) { - if (r_q == NULL) + if ( !q_u ) return False; - prs_debug(ps, depth, desc, "reg_io_q_entry"); + prs_debug(ps, depth, desc, "reg_io_q_open_entry"); depth++; if(!prs_align(ps)) return False; - if(!smb_io_pol_hnd("", &r_q->pol, ps, depth)) - return False; - if(!smb_io_unihdr ("", &r_q->hdr_name, ps, depth)) + if(!smb_io_pol_hnd("", &q_u->pol, ps, depth)) return False; - if(!smb_io_unistr2("", &r_q->uni_name, r_q->hdr_name.buffer, ps, depth)) + if(!prs_unistr4("name", ps, depth, &q_u->name)) return False; if(!prs_align(ps)) return False; - if(!prs_uint32("unknown_0 ", ps, depth, &r_q->unknown_0)) + if(!prs_uint32("unknown_0 ", ps, depth, &q_u->unknown_0)) return False; - if(!prs_uint32("access_desired ", ps, depth, &r_q->access_desired)) + if(!prs_uint32("access", ps, depth, &q_u->access)) return False; return True; @@ -1684,24 +1484,24 @@ BOOL reg_io_q_open_entry(const char *desc, REG_Q_OPEN_ENTRY *r_q, prs_struct *p Inits a structure. ********************************************************************/ -void init_reg_r_open_entry(REG_R_OPEN_ENTRY *r_r, +void init_reg_r_open_entry(REG_R_OPEN_ENTRY *r_u, POLICY_HND *pol, WERROR werr) { if (W_ERROR_IS_OK(werr)) { - memcpy(&r_r->pol, pol, sizeof(r_r->pol)); + memcpy(&r_u->pol, pol, sizeof(r_u->pol)); } else { - ZERO_STRUCT(r_r->pol); + ZERO_STRUCT(r_u->pol); } - r_r->status = werr; + r_u->status = werr; } /******************************************************************* reads or writes a structure. ********************************************************************/ -BOOL reg_io_r_open_entry(const char *desc, REG_R_OPEN_ENTRY *r_r, prs_struct *ps, int depth) +BOOL reg_io_r_open_entry(const char *desc, REG_R_OPEN_ENTRY *r_u, prs_struct *ps, int depth) { - if (r_r == NULL) + if ( !r_u ) return False; prs_debug(ps, depth, desc, "reg_io_r_open_entry"); @@ -1710,10 +1510,10 @@ BOOL reg_io_r_open_entry(const char *desc, REG_R_OPEN_ENTRY *r_r, prs_struct *p if(!prs_align(ps)) return False; - if(!smb_io_pol_hnd("", &r_r->pol, ps, depth)) + if(!smb_io_pol_hnd("", &r_u->pol, ps, depth)) return False; - if(!prs_werror("status", ps, depth, &r_r->status)) + if(!prs_werror("status", ps, depth, &r_u->status)) return False; return True; @@ -1723,30 +1523,53 @@ BOOL reg_io_r_open_entry(const char *desc, REG_R_OPEN_ENTRY *r_r, prs_struct *p Inits a structure. ********************************************************************/ -void init_reg_q_shutdown(REG_Q_SHUTDOWN * q_s, const char *msg, +void init_reg_q_shutdown(REG_Q_SHUTDOWN *q_u, const char *msg, uint32 timeout, BOOL do_reboot, BOOL force) { - q_s->ptr_0 = 1; - q_s->ptr_1 = 1; - q_s->ptr_2 = 1; + q_u->server = TALLOC_P( get_talloc_ctx(), uint16 ); + *q_u->server = 0x1; + + q_u->message = TALLOC_P( get_talloc_ctx(), UNISTR4 ); + init_unistr4( q_u->message, msg, UNI_FLAGS_NONE ); - init_unistr2(&q_s->uni_msg, msg, UNI_FLAGS_NONE); - init_uni_hdr(&q_s->hdr_msg, &q_s->uni_msg); + q_u->timeout = timeout; + + q_u->reboot = do_reboot ? 1 : 0; + q_u->force = force ? 1 : 0; +} - q_s->timeout = timeout; +/******************************************************************* +Inits a REG_Q_SHUTDOWN_EX structure. +********************************************************************/ - q_s->reboot = do_reboot ? 1 : 0; - q_s->force = force ? 1 : 0; +void init_reg_q_shutdown_ex(REG_Q_SHUTDOWN_EX * q_u_ex, const char *msg, + uint32 timeout, BOOL do_reboot, BOOL force, uint32 reason) +{ + REG_Q_SHUTDOWN q_u; + + ZERO_STRUCT( q_u ); + + init_reg_q_shutdown( &q_u, msg, timeout, do_reboot, force ); + + /* steal memory */ + + q_u_ex->server = q_u.server; + q_u_ex->message = q_u.message; + + q_u_ex->reboot = q_u.reboot; + q_u_ex->force = q_u.force; + + q_u_ex->reason = reason; } /******************************************************************* reads or writes a structure. ********************************************************************/ -BOOL reg_io_q_shutdown(const char *desc, REG_Q_SHUTDOWN * q_s, prs_struct *ps, +BOOL reg_io_q_shutdown(const char *desc, REG_Q_SHUTDOWN *q_u, prs_struct *ps, int depth) { - if (q_s == NULL) + if ( !q_u ) return False; prs_debug(ps, depth, desc, "reg_io_q_shutdown"); @@ -1755,37 +1578,34 @@ BOOL reg_io_q_shutdown(const char *desc, REG_Q_SHUTDOWN * q_s, prs_struct *ps, if (!prs_align(ps)) return False; - if (!prs_uint32("ptr_0", ps, depth, &(q_s->ptr_0))) - return False; - if (!prs_uint32("ptr_1", ps, depth, &(q_s->ptr_1))) - return False; - if (!prs_uint32("ptr_2", ps, depth, &(q_s->ptr_2))) + if (!prs_pointer("server", ps, depth, (void**)&q_u->server, sizeof(uint16), (PRS_POINTER_CAST)prs_uint16)) return False; - if (!smb_io_unihdr("hdr_msg", &(q_s->hdr_msg), ps, depth)) - return False; - if (!smb_io_unistr2("uni_msg", &(q_s->uni_msg), q_s->hdr_msg.buffer, ps, depth)) + if (!prs_pointer("message", ps, depth, (void**)&q_u->message, sizeof(UNISTR4), (PRS_POINTER_CAST)prs_unistr4)) return False; + if (!prs_align(ps)) return False; - if (!prs_uint32("timeout", ps, depth, &(q_s->timeout))) + if (!prs_uint32("timeout", ps, depth, &(q_u->timeout))) return False; - if (!prs_uint8("force ", ps, depth, &(q_s->force))) + + if (!prs_uint8("force ", ps, depth, &(q_u->force))) return False; - if (!prs_uint8("reboot ", ps, depth, &(q_s->reboot))) + if (!prs_uint8("reboot ", ps, depth, &(q_u->reboot))) return False; + return True; } /******************************************************************* reads or writes a structure. ********************************************************************/ -BOOL reg_io_r_shutdown(const char *desc, REG_R_SHUTDOWN * r_s, prs_struct *ps, +BOOL reg_io_r_shutdown(const char *desc, REG_R_SHUTDOWN *r_u, prs_struct *ps, int depth) { - if (r_s == NULL) + if ( !r_u ) return False; prs_debug(ps, depth, desc, "reg_io_r_shutdown"); @@ -1794,29 +1614,93 @@ BOOL reg_io_r_shutdown(const char *desc, REG_R_SHUTDOWN * r_s, prs_struct *ps, if(!prs_align(ps)) return False; - if(!prs_werror("status", ps, depth, &r_s->status)) + if(!prs_werror("status", ps, depth, &r_u->status)) return False; return True; } /******************************************************************* -Inits a structure. +reads or writes a REG_Q_SHUTDOWN_EX structure. ********************************************************************/ -void init_reg_q_abort_shutdown(REG_Q_ABORT_SHUTDOWN * q_s) + +BOOL reg_io_q_shutdown_ex(const char *desc, REG_Q_SHUTDOWN_EX *q_u, prs_struct *ps, + int depth) { + if ( !q_u ) + return False; + + prs_debug(ps, depth, desc, "reg_io_q_shutdown_ex"); + depth++; + + if (!prs_align(ps)) + return False; + + if (!prs_pointer("server", ps, depth, (void**)&q_u->server, sizeof(uint16), (PRS_POINTER_CAST)prs_uint16)) + return False; + + if (!prs_pointer("message", ps, depth, (void**)&q_u->message, sizeof(UNISTR4), (PRS_POINTER_CAST)prs_unistr4)) + return False; - q_s->ptr_server = 0; + if (!prs_align(ps)) + return False; + if (!prs_uint32("timeout", ps, depth, &(q_u->timeout))) + return False; + + if (!prs_uint8("force ", ps, depth, &(q_u->force))) + return False; + if (!prs_uint8("reboot ", ps, depth, &(q_u->reboot))) + return False; + + if (!prs_align(ps)) + return False; + if (!prs_uint32("reason", ps, depth, &(q_u->reason))) + return False; + + + return True; +} + +/******************************************************************* +reads or writes a REG_R_SHUTDOWN_EX structure. +********************************************************************/ +BOOL reg_io_r_shutdown_ex(const char *desc, REG_R_SHUTDOWN_EX *r_u, prs_struct *ps, + int depth) +{ + if ( !r_u ) + return False; + + prs_debug(ps, depth, desc, "reg_io_r_shutdown_ex"); + depth++; + + if(!prs_align(ps)) + return False; + + if(!prs_werror("status", ps, depth, &r_u->status)) + return False; + + return True; +} + + + +/******************************************************************* +Inits a structure. +********************************************************************/ +void init_reg_q_abort_shutdown(REG_Q_ABORT_SHUTDOWN *q_u) +{ + q_u->server = TALLOC_P( get_talloc_ctx(), uint16 ); + *q_u->server = 0x1; } /******************************************************************* reads or writes a structure. ********************************************************************/ -BOOL reg_io_q_abort_shutdown(const char *desc, REG_Q_ABORT_SHUTDOWN * q_s, +BOOL reg_io_q_abort_shutdown(const char *desc, REG_Q_ABORT_SHUTDOWN *q_u, prs_struct *ps, int depth) { - if (q_s == NULL) + if ( !q_u ) return False; prs_debug(ps, depth, desc, "reg_io_q_abort_shutdown"); @@ -1825,11 +1709,8 @@ BOOL reg_io_q_abort_shutdown(const char *desc, REG_Q_ABORT_SHUTDOWN * q_s, if (!prs_align(ps)) return False; - if (!prs_uint32("ptr_server", ps, depth, &(q_s->ptr_server))) + if (!prs_pointer("server", ps, depth, (void**)&q_u->server, sizeof(uint16), (PRS_POINTER_CAST)prs_uint16)) return False; - if (q_s->ptr_server != 0) - if (!prs_uint16("server", ps, depth, &(q_s->server))) - return False; return True; } @@ -1837,10 +1718,10 @@ BOOL reg_io_q_abort_shutdown(const char *desc, REG_Q_ABORT_SHUTDOWN * q_s, /******************************************************************* reads or writes a structure. ********************************************************************/ -BOOL reg_io_r_abort_shutdown(const char *desc, REG_R_ABORT_SHUTDOWN * r_s, +BOOL reg_io_r_abort_shutdown(const char *desc, REG_R_ABORT_SHUTDOWN *r_u, prs_struct *ps, int depth) { - if (r_s == NULL) + if ( !r_u ) return False; prs_debug(ps, depth, desc, "reg_io_r_abort_shutdown"); @@ -1849,7 +1730,7 @@ BOOL reg_io_r_abort_shutdown(const char *desc, REG_R_ABORT_SHUTDOWN * r_s, if (!prs_align(ps)) return False; - if (!prs_werror("status", ps, depth, &r_s->status)) + if (!prs_werror("status", ps, depth, &r_u->status)) return False; return True; diff --git a/source/rpc_parse/parse_rpc.c b/source/rpc_parse/parse_rpc.c index aa296eb70a1..6bdab2e437c 100644 --- a/source/rpc_parse/parse_rpc.c +++ b/source/rpc_parse/parse_rpc.c @@ -36,7 +36,7 @@ interface/version dce/rpc pipe identification 0x8a885d04, 0x1ceb, 0x11c9, \ { 0x9f, 0xe8 }, \ { 0x08, 0x00, \ - 0x2b, 0x10, 0x48, 0x60 } \ + 0x2b, 0x10, 0x48, 0x60 } \ }, 0x02 \ } @@ -46,7 +46,7 @@ interface/version dce/rpc pipe identification 0x8a885d04, 0x1ceb, 0x11c9, \ { 0x9f, 0xe8 }, \ { 0x08, 0x00, \ - 0x2b, 0x10, 0x48, 0x60 } \ + 0x2b, 0x10, 0x48, 0x60 } \ }, 0x02 \ } @@ -56,7 +56,7 @@ interface/version dce/rpc pipe identification 0x6bffd098, 0xa112, 0x3610, \ { 0x98, 0x33 }, \ { 0x46, 0xc3, \ - 0xf8, 0x7e, 0x34, 0x5a } \ + 0xf8, 0x7e, 0x34, 0x5a } \ }, 0x01 \ } @@ -66,7 +66,7 @@ interface/version dce/rpc pipe identification 0x4b324fc8, 0x1670, 0x01d3, \ { 0x12, 0x78 }, \ { 0x5a, 0x47, \ - 0xbf, 0x6e, 0xe1, 0x88 } \ + 0xbf, 0x6e, 0xe1, 0x88 } \ }, 0x03 \ } @@ -76,7 +76,7 @@ interface/version dce/rpc pipe identification 0x12345778, 0x1234, 0xabcd, \ { 0xef, 0x00 }, \ { 0x01, 0x23, \ - 0x45, 0x67, 0x89, 0xab } \ + 0x45, 0x67, 0x89, 0xab } \ }, 0x00 \ } @@ -86,7 +86,7 @@ interface/version dce/rpc pipe identification 0x3919286a, 0xb10c, 0x11d0, \ { 0x9b, 0xa8 }, \ { 0x00, 0xc0, \ - 0x4f, 0xd9, 0x2e, 0xf5 } \ + 0x4f, 0xd9, 0x2e, 0xf5 } \ }, 0x00 \ } @@ -96,7 +96,7 @@ interface/version dce/rpc pipe identification 0x12345778, 0x1234, 0xabcd, \ { 0xef, 0x00 }, \ { 0x01, 0x23, \ - 0x45, 0x67, 0x89, 0xac } \ + 0x45, 0x67, 0x89, 0xac } \ }, 0x01 \ } @@ -106,7 +106,7 @@ interface/version dce/rpc pipe identification 0x12345678, 0x1234, 0xabcd, \ { 0xef, 0x00 }, \ { 0x01, 0x23, \ - 0x45, 0x67, 0xcf, 0xfb } \ + 0x45, 0x67, 0xcf, 0xfb } \ }, 0x01 \ } @@ -116,7 +116,7 @@ interface/version dce/rpc pipe identification 0x338cd001, 0x2244, 0x31f1, \ { 0xaa, 0xaa }, \ { 0x90, 0x00, \ - 0x38, 0x00, 0x10, 0x03 } \ + 0x38, 0x00, 0x10, 0x03 } \ }, 0x01 \ } @@ -126,7 +126,7 @@ interface/version dce/rpc pipe identification 0x12345678, 0x1234, 0xabcd, \ { 0xef, 0x00 }, \ { 0x01, 0x23, \ - 0x45, 0x67, 0x89, 0xab } \ + 0x45, 0x67, 0x89, 0xab } \ }, 0x01 \ } @@ -136,7 +136,7 @@ interface/version dce/rpc pipe identification 0x0, 0x0, 0x0, \ { 0x00, 0x00 }, \ { 0x00, 0x00, \ - 0x00, 0x00, 0x00, 0x00 } \ + 0x00, 0x00, 0x00, 0x00 } \ }, 0x00 \ } @@ -170,6 +170,27 @@ interface/version dce/rpc pipe identification }, 0x01 \ } +#define SYNT_SVCCTL_V2 \ +{ \ + { \ + 0x367abb81, 0x9844, 0x35f1, \ + { 0xad, 0x32 }, \ + { 0x98, 0xf0, \ + 0x38, 0x00, 0x10, 0x03 } \ + }, 0x02 \ +} + + +#define SYNT_EVENTLOG_V0 \ +{ \ + { \ + 0x82273fdc, 0xe32a, 0x18c3, \ + { 0x3f, 0x78 }, \ + { 0x82, 0x79, \ + 0x29, 0xdc, 0x23, 0xea } \ + }, 0x00 \ +} + /* * IMPORTANT!! If you update this structure, make sure to * update the index #defines in smb.h. @@ -189,6 +210,8 @@ const struct pipe_id_info pipe_names [] = { PIPE_NETDFS , SYNT_NETDFS_V3 , PIPE_NETDFS , TRANS_SYNT_V2 }, { PIPE_ECHO , SYNT_ECHO_V1 , PIPE_ECHO , TRANS_SYNT_V2 }, { PIPE_SHUTDOWN, SYNT_SHUTDOWN_V1 , PIPE_SHUTDOWN , TRANS_SYNT_V2 }, + { PIPE_SVCCTL , SYNT_SVCCTL_V2 , PIPE_NTSVCS , TRANS_SYNT_V2 }, + { PIPE_EVENTLOG, SYNT_EVENTLOG_V0 , PIPE_EVENTLOG , TRANS_SYNT_V2 }, { NULL , SYNT_NONE_V0 , NULL , SYNT_NONE_V0 } }; diff --git a/source/rpc_parse/parse_sec.c b/source/rpc_parse/parse_sec.c index f6fdf102928..6a752688a0b 100644 --- a/source/rpc_parse/parse_sec.c +++ b/source/rpc_parse/parse_sec.c @@ -133,7 +133,7 @@ BOOL sec_io_acl(const char *desc, SEC_ACL **ppsa, prs_struct *ps, int depth) * Note that the size is always a multiple of 4 bytes due to the * nature of the data structure. Therefore the prs_align() calls * have been removed as they through us off when doing two-layer - * marshalling such as in the printing code (NEW_BUFFER). --jerry + * marshalling such as in the printing code (RPC_BUFFER). --jerry */ if (ppsa == NULL) diff --git a/source/rpc_parse/parse_shutdown.c b/source/rpc_parse/parse_shutdown.c index ad2d6e1a028..00daeaaaee7 100644 --- a/source/rpc_parse/parse_shutdown.c +++ b/source/rpc_parse/parse_shutdown.c @@ -2,6 +2,7 @@ * Unix SMB/CIFS implementation. * RPC Pipe client / server routines * Copyright (C) Jim McDonough (jmcd@us.ibm.com) 2003. + * Copyright (C) Gerald (Jerry) Carter 2002-2005. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -30,12 +31,11 @@ Inits a structure. void init_shutdown_q_init(SHUTDOWN_Q_INIT *q_s, const char *msg, uint32 timeout, BOOL do_reboot, BOOL force) { - q_s->ptr_server = 1; - q_s->server = 1; - q_s->ptr_msg = 1; + q_s->server = TALLOC_P( get_talloc_ctx(), uint16 ); + *q_s->server = 0x1; - init_unistr2(&q_s->uni_msg, msg, UNI_FLAGS_NONE); - init_uni_hdr(&q_s->hdr_msg, &q_s->uni_msg); + q_s->message = TALLOC_P( get_talloc_ctx(), UNISTR4 ); + init_unistr4( q_s->message, msg, UNI_FLAGS_NONE ); q_s->timeout = timeout; @@ -43,6 +43,29 @@ void init_shutdown_q_init(SHUTDOWN_Q_INIT *q_s, const char *msg, q_s->force = force ? 1 : 0; } +/******************************************************************* +********************************************************************/ + +void init_shutdown_q_init_ex(SHUTDOWN_Q_INIT_EX * q_u_ex, const char *msg, + uint32 timeout, BOOL do_reboot, BOOL force, uint32 reason) +{ + SHUTDOWN_Q_INIT q_u; + + ZERO_STRUCT( q_u ); + + init_shutdown_q_init( &q_u, msg, timeout, do_reboot, force ); + + /* steal memory */ + + q_u_ex->server = q_u.server; + q_u_ex->message = q_u.message; + + q_u_ex->reboot = q_u.reboot; + q_u_ex->force = q_u.force; + + q_u_ex->reason = reason; +} + /******************************************************************* reads or writes a structure. ********************************************************************/ @@ -59,62 +82,119 @@ BOOL shutdown_io_q_init(const char *desc, SHUTDOWN_Q_INIT *q_s, prs_struct *ps, if (!prs_align(ps)) return False; - if (!prs_uint32("ptr_server", ps, depth, &(q_s->ptr_server))) + if (!prs_pointer("server", ps, depth, (void**)&q_s->server, sizeof(uint16), (PRS_POINTER_CAST)prs_uint16)) return False; - if (!prs_uint16("server", ps, depth, &(q_s->server))) + + if (!prs_pointer("message", ps, depth, (void**)&q_s->message, sizeof(UNISTR4), (PRS_POINTER_CAST)prs_unistr4)) return False; if (!prs_align(ps)) return False; - if (!prs_uint32("ptr_msg", ps, depth, &(q_s->ptr_msg))) + + if (!prs_uint32("timeout", ps, depth, &(q_s->timeout))) return False; - if (!smb_io_unihdr("hdr_msg", &(q_s->hdr_msg), ps, depth)) + if (!prs_uint8("force ", ps, depth, &(q_s->force))) return False; - if (!smb_io_unistr2("uni_msg", &(q_s->uni_msg), q_s->hdr_msg.buffer, ps, depth)) + if (!prs_uint8("reboot ", ps, depth, &(q_s->reboot))) return False; + + + return True; +} + +/******************************************************************* +reads or writes a structure. +********************************************************************/ +BOOL shutdown_io_r_init(const char *desc, SHUTDOWN_R_INIT* r_s, prs_struct *ps, + int depth) +{ + if (r_s == NULL) + return False; + + prs_debug(ps, depth, desc, "shutdown_io_r_init"); + depth++; + + if(!prs_align(ps)) + return False; + + if(!prs_werror("status", ps, depth, &r_s->status)) + return False; + + return True; +} + +/******************************************************************* +reads or writes a REG_Q_SHUTDOWN_EX structure. +********************************************************************/ + +BOOL shutdown_io_q_init_ex(const char *desc, SHUTDOWN_Q_INIT_EX * q_s, prs_struct *ps, + int depth) +{ + if (q_s == NULL) + return False; + + prs_debug(ps, depth, desc, "shutdown_io_q_init_ex"); + depth++; + + if (!prs_align(ps)) + return False; + + if (!prs_pointer("server", ps, depth, (void**)&q_s->server, sizeof(uint16), (PRS_POINTER_CAST)prs_uint16)) + return False; + + if (!prs_pointer("message", ps, depth, (void**)&q_s->message, sizeof(UNISTR4), (PRS_POINTER_CAST)prs_unistr4)) + return False; + if (!prs_align(ps)) return False; if (!prs_uint32("timeout", ps, depth, &(q_s->timeout))) return False; + if (!prs_uint8("force ", ps, depth, &(q_s->force))) return False; if (!prs_uint8("reboot ", ps, depth, &(q_s->reboot))) return False; + if (!prs_align(ps)) + return False; + if (!prs_uint32("reason", ps, depth, &(q_s->reason))) + return False; + + return True; } /******************************************************************* -reads or writes a structure. +reads or writes a REG_R_SHUTDOWN_EX structure. ********************************************************************/ -BOOL shutdown_io_r_init(const char *desc, SHUTDOWN_R_INIT* r_s, prs_struct *ps, - int depth) +BOOL shutdown_io_r_init_ex(const char *desc, SHUTDOWN_R_INIT_EX * r_s, prs_struct *ps, + int depth) { if (r_s == NULL) return False; - prs_debug(ps, depth, desc, "shutdown_io_r_init"); + prs_debug(ps, depth, desc, "shutdown_io_r_init_ex"); depth++; if(!prs_align(ps)) return False; - if(!prs_ntstatus("status", ps, depth, &r_s->status)) + if(!prs_werror("status", ps, depth, &r_s->status)) return False; return True; } + /******************************************************************* Inits a structure. ********************************************************************/ void init_shutdown_q_abort(SHUTDOWN_Q_ABORT *q_s) { - - q_s->ptr_server = 0; - + q_s->server = TALLOC_P( get_talloc_ctx(), uint16 ); + *q_s->server = 0x1; } /******************************************************************* @@ -132,11 +212,8 @@ BOOL shutdown_io_q_abort(const char *desc, SHUTDOWN_Q_ABORT *q_s, if (!prs_align(ps)) return False; - if (!prs_uint32("ptr_server", ps, depth, &(q_s->ptr_server))) + if (!prs_pointer("server", ps, depth, (void**)&q_s->server, sizeof(uint16), (PRS_POINTER_CAST)prs_uint16)) return False; - if (q_s->ptr_server != 0) - if (!prs_uint16("server", ps, depth, &(q_s->server))) - return False; return True; } @@ -156,7 +233,7 @@ BOOL shutdown_io_r_abort(const char *desc, SHUTDOWN_R_ABORT *r_s, if (!prs_align(ps)) return False; - if (!prs_ntstatus("status", ps, depth, &r_s->status)) + if (!prs_werror("status", ps, depth, &r_s->status)) return False; return True; diff --git a/source/rpc_parse/parse_spoolss.c b/source/rpc_parse/parse_spoolss.c index dc419a73b5f..78602dd806a 100644 --- a/source/rpc_parse/parse_spoolss.c +++ b/source/rpc_parse/parse_spoolss.c @@ -27,22 +27,6 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_RPC_PARSE -/******************************************************************* -return the length of a UNISTR string. -********************************************************************/ - -static uint32 str_len_uni(UNISTR *source) -{ - uint32 i=0; - - if (!source->buffer) - return 0; - - while (source->buffer[i]) - i++; - - return i; -} /******************************************************************* This should be moved in a more generic lib. @@ -566,23 +550,22 @@ static BOOL smb_io_notify_info(const char *desc, SPOOL_NOTIFY_INFO *info, prs_st /******************************************************************* ********************************************************************/ -static BOOL spool_io_user_level_1(const char *desc, SPOOL_USER_1 *q_u, prs_struct *ps, int depth) +BOOL spool_io_user_level_1( const char *desc, prs_struct *ps, int depth, SPOOL_USER_1 *q_u ) { prs_debug(ps, depth, desc, ""); depth++; - /* reading */ - if (UNMARSHALLING(ps)) - ZERO_STRUCTP(q_u); - if (!prs_align(ps)) return False; + if (!prs_uint32("size", ps, depth, &q_u->size)) return False; - if (!prs_uint32("client_name_ptr", ps, depth, &q_u->client_name_ptr)) + + if (!prs_io_unistr2_p("", ps, depth, &q_u->client_name)) return False; - if (!prs_uint32("user_name_ptr", ps, depth, &q_u->user_name_ptr)) + if (!prs_io_unistr2_p("", ps, depth, &q_u->user_name)) return False; + if (!prs_uint32("build", ps, depth, &q_u->build)) return False; if (!prs_uint32("major", ps, depth, &q_u->major)) @@ -592,11 +575,12 @@ static BOOL spool_io_user_level_1(const char *desc, SPOOL_USER_1 *q_u, prs_struc if (!prs_uint32("processor", ps, depth, &q_u->processor)) return False; - if (!smb_io_unistr2("", &q_u->client_name, q_u->client_name_ptr, ps, depth)) + if (!prs_io_unistr2("", ps, depth, q_u->client_name)) return False; if (!prs_align(ps)) return False; - if (!smb_io_unistr2("", &q_u->user_name, q_u->user_name_ptr, ps, depth)) + + if (!prs_io_unistr2("", ps, depth, q_u->user_name)) return False; return True; @@ -616,21 +600,20 @@ static BOOL spool_io_user_level(const char *desc, SPOOL_USER_CTR *q_u, prs_struc if (!prs_align(ps)) return False; - /* From looking at many captures in ethereal, it looks like - the level and ptr fields should be transposed. -tpot */ - if (!prs_uint32("level", ps, depth, &q_u->level)) return False; - if (!prs_uint32("ptr", ps, depth, &q_u->ptr)) - return False; - switch (q_u->level) { - case 1: - if (!spool_io_user_level_1("", &q_u->user1, ps, depth)) - return False; - break; - default: - return False; + switch ( q_u->level ) + { + case 1: + if ( !prs_pointer( "" , ps, depth, (void**)&q_u->user.user1, + sizeof(SPOOL_USER_1), (PRS_POINTER_CAST)spool_io_user_level_1 )) + { + return False; + } + break; + default: + return False; } return True; @@ -915,30 +898,31 @@ BOOL make_spoolss_q_open_printer_ex(SPOOL_Q_OPEN_PRINTER_EX *q_u, const fstring user_name) { DEBUG(5,("make_spoolss_q_open_printer_ex\n")); - q_u->printername_ptr = (printername!=NULL)?1:0; - init_unistr2(&q_u->printername, printername, UNI_STR_TERMINATE); + + q_u->printername = TALLOC_P( get_talloc_ctx(), UNISTR2 ); + init_unistr2(q_u->printername, printername, UNI_STR_TERMINATE); q_u->printer_default.datatype_ptr = 0; -/* - q_u->printer_default.datatype_ptr = (datatype!=NULL)?1:0; - init_unistr2(&q_u->printer_default.datatype, datatype, UNI_FLAGS_NONE); -*/ + q_u->printer_default.devmode_cont.size=0; q_u->printer_default.devmode_cont.devmode_ptr=0; q_u->printer_default.devmode_cont.devmode=NULL; q_u->printer_default.access_required=access_required; - q_u->user_switch=1; - q_u->user_ctr.level=1; - q_u->user_ctr.ptr=1; - q_u->user_ctr.user1.size=strlen(clientname)+strlen(user_name)+10; - q_u->user_ctr.user1.client_name_ptr = (clientname!=NULL)?1:0; - q_u->user_ctr.user1.user_name_ptr = (user_name!=NULL)?1:0; - q_u->user_ctr.user1.build=1381; - q_u->user_ctr.user1.major=2; - q_u->user_ctr.user1.minor=0; - q_u->user_ctr.user1.processor=0; - init_unistr2(&q_u->user_ctr.user1.client_name, clientname, UNI_STR_TERMINATE); - init_unistr2(&q_u->user_ctr.user1.user_name, user_name, UNI_STR_TERMINATE); + + q_u->user_switch = 1; + + q_u->user_ctr.level = 1; + q_u->user_ctr.user.user1->size = strlen(clientname) + strlen(user_name) + 10; + q_u->user_ctr.user.user1->build = 1381; + q_u->user_ctr.user.user1->major = 2; + q_u->user_ctr.user.user1->minor = 0; + q_u->user_ctr.user.user1->processor = 0; + + q_u->user_ctr.user.user1->client_name = TALLOC_P( get_talloc_ctx(), UNISTR2 ); + q_u->user_ctr.user.user1->user_name = TALLOC_P( get_talloc_ctx(), UNISTR2 ); + + init_unistr2(q_u->user_ctr.user.user1->client_name, clientname, UNI_STR_TERMINATE); + init_unistr2(q_u->user_ctr.user.user1->user_name, user_name, UNI_STR_TERMINATE); return True; } @@ -947,23 +931,19 @@ BOOL make_spoolss_q_open_printer_ex(SPOOL_Q_OPEN_PRINTER_EX *q_u, * init a structure. ********************************************************************/ -BOOL make_spoolss_q_addprinterex( - TALLOC_CTX *mem_ctx, - SPOOL_Q_ADDPRINTEREX *q_u, - const char *srv_name, - const char* clientname, - const char* user_name, - uint32 level, - PRINTER_INFO_CTR *ctr) +BOOL make_spoolss_q_addprinterex( TALLOC_CTX *mem_ctx, SPOOL_Q_ADDPRINTEREX *q_u, + const char *srv_name, const char* clientname, const char* user_name, + uint32 level, PRINTER_INFO_CTR *ctr) { DEBUG(5,("make_spoolss_q_addprinterex\n")); - if (!ctr) return False; + if (!ctr) + return False; ZERO_STRUCTP(q_u); - q_u->server_name_ptr = (srv_name!=NULL)?1:0; - init_unistr2(&q_u->server_name, srv_name, UNI_FLAGS_NONE); + q_u->server_name = TALLOC_P( mem_ctx, UNISTR2 ); + init_unistr2(q_u->server_name, srv_name, UNI_FLAGS_NONE); q_u->level = level; @@ -983,18 +963,20 @@ BOOL make_spoolss_q_addprinterex( q_u->user_switch=1; - q_u->user_ctr.level=1; - q_u->user_ctr.ptr=1; - q_u->user_ctr.user1.client_name_ptr = (clientname!=NULL)?1:0; - q_u->user_ctr.user1.user_name_ptr = (user_name!=NULL)?1:0; - q_u->user_ctr.user1.build=1381; - q_u->user_ctr.user1.major=2; - q_u->user_ctr.user1.minor=0; - q_u->user_ctr.user1.processor=0; - init_unistr2(&q_u->user_ctr.user1.client_name, clientname, UNI_STR_TERMINATE); - init_unistr2(&q_u->user_ctr.user1.user_name, user_name, UNI_STR_TERMINATE); - q_u->user_ctr.user1.size=q_u->user_ctr.user1.user_name.uni_str_len + - q_u->user_ctr.user1.client_name.uni_str_len + 2; + q_u->user_ctr.level = 1; + q_u->user_ctr.user.user1->build = 1381; + q_u->user_ctr.user.user1->major = 2; + q_u->user_ctr.user.user1->minor = 0; + q_u->user_ctr.user.user1->processor = 0; + + q_u->user_ctr.user.user1->client_name = TALLOC_P( mem_ctx, UNISTR2 ); + q_u->user_ctr.user.user1->user_name = TALLOC_P( mem_ctx, UNISTR2 ); + + init_unistr2(q_u->user_ctr.user.user1->client_name, clientname, UNI_STR_TERMINATE); + init_unistr2(q_u->user_ctr.user.user1->user_name, user_name, UNI_STR_TERMINATE); + + q_u->user_ctr.user.user1->size = q_u->user_ctr.user.user1->user_name->uni_str_len + + q_u->user_ctr.user.user1->client_name->uni_str_len + 2; return True; } @@ -1118,9 +1100,9 @@ BOOL spoolss_io_q_open_printer(const char *desc, SPOOL_Q_OPEN_PRINTER *q_u, prs_ if (!prs_align(ps)) return False; - if (!prs_uint32("printername_ptr", ps, depth, &q_u->printername_ptr)) + if (!prs_io_unistr2_p("ptr", ps, depth, &q_u->printername)) return False; - if (!smb_io_unistr2("", &q_u->printername, q_u->printername_ptr, ps,depth)) + if (!prs_io_unistr2("printername", ps, depth, q_u->printername)) return False; if (!prs_align(ps)) @@ -1174,9 +1156,9 @@ BOOL spoolss_io_q_open_printer_ex(const char *desc, SPOOL_Q_OPEN_PRINTER_EX *q_u if (!prs_align(ps)) return False; - if (!prs_uint32("printername_ptr", ps, depth, &q_u->printername_ptr)) + if (!prs_io_unistr2_p("ptr", ps, depth, &q_u->printername)) return False; - if (!smb_io_unistr2("", &q_u->printername, q_u->printername_ptr, ps,depth)) + if (!prs_io_unistr2("printername", ps, depth, q_u->printername)) return False; if (!prs_align(ps)) @@ -2067,33 +2049,6 @@ static uint32 size_of_nttime(NTTIME *value) return (sizeof(*value)); } -/******************************************************************* - * return the length of a UNICODE string in number of char, includes: - * - the leading zero - * - the relative pointer size - ********************************************************************/ - -static uint32 size_of_relative_string(UNISTR *string) -{ - uint32 size=0; - - size=str_len_uni(string); /* the string length */ - size=size+1; /* add the trailing zero */ - size=size*2; /* convert in char */ - size=size+4; /* add the size of the ptr */ - -#if 0 /* JERRY */ - /* - * Do not include alignment as Win2k does not align relative - * strings within a buffer --jerry - */ - /* Ensure size is 4 byte multiple (prs_align is being called...). */ - /* size += ((4 - (size & 3)) & 3); */ -#endif - - return size; -} - /******************************************************************* * return the length of a uint32 (obvious, but the code is clean) ********************************************************************/ @@ -2118,278 +2073,11 @@ static uint32 size_of_systemtime(SYSTEMTIME *systime) return (sizeof(SYSTEMTIME) +4); } -/******************************************************************* - * write a UNICODE string and its relative pointer. - * used by all the RPC structs passing a buffer - * - * As I'm a nice guy, I'm forcing myself to explain this code. - * MS did a good job in the overall spoolss code except in some - * functions where they are passing the API buffer directly in the - * RPC request/reply. That's to maintain compatiility at the API level. - * They could have done it the good way the first time. - * - * So what happen is: the strings are written at the buffer's end, - * in the reverse order of the original structure. Some pointers to - * the strings are also in the buffer. Those are relative to the - * buffer's start. - * - * If you don't understand or want to change that function, - * first get in touch with me: jfm@samba.org - * - ********************************************************************/ - -static BOOL smb_io_relstr(const char *desc, NEW_BUFFER *buffer, int depth, UNISTR *string) -{ - prs_struct *ps=&buffer->prs; - - if (MARSHALLING(ps)) { - uint32 struct_offset = prs_offset(ps); - uint32 relative_offset; - - buffer->string_at_end -= (size_of_relative_string(string) - 4); - if(!prs_set_offset(ps, buffer->string_at_end)) - return False; -#if 0 /* JERRY */ - /* - * Win2k does not align strings in a buffer - * Tested against WinNT 4.0 SP 6a & 2k SP2 --jerry - */ - if (!prs_align(ps)) - return False; -#endif - buffer->string_at_end = prs_offset(ps); - - /* write the string */ - if (!smb_io_unistr(desc, string, ps, depth)) - return False; - - if(!prs_set_offset(ps, struct_offset)) - return False; - - relative_offset=buffer->string_at_end - buffer->struct_start; - /* write its offset */ - if (!prs_uint32("offset", ps, depth, &relative_offset)) - return False; - } - else { - uint32 old_offset; - - /* read the offset */ - if (!prs_uint32("offset", ps, depth, &(buffer->string_at_end))) - return False; - - if (buffer->string_at_end == 0) - return True; - - old_offset = prs_offset(ps); - if(!prs_set_offset(ps, buffer->string_at_end+buffer->struct_start)) - return False; - - /* read the string */ - if (!smb_io_unistr(desc, string, ps, depth)) - return False; - - if(!prs_set_offset(ps, old_offset)) - return False; - } - return True; -} - -/******************************************************************* - * write a array of UNICODE strings and its relative pointer. - * used by 2 RPC structs - ********************************************************************/ - -static BOOL smb_io_relarraystr(const char *desc, NEW_BUFFER *buffer, int depth, uint16 **string) -{ - UNISTR chaine; - - prs_struct *ps=&buffer->prs; - - if (MARSHALLING(ps)) { - uint32 struct_offset = prs_offset(ps); - uint32 relative_offset; - uint16 *p; - uint16 *q; - uint16 zero=0; - p=*string; - q=*string; - - /* first write the last 0 */ - buffer->string_at_end -= 2; - if(!prs_set_offset(ps, buffer->string_at_end)) - return False; - - if(!prs_uint16("leading zero", ps, depth, &zero)) - return False; - - while (p && (*p!=0)) { - while (*q!=0) - q++; - - /* Yes this should be malloc not talloc. Don't change. */ - - chaine.buffer = SMB_MALLOC((q-p+1)*sizeof(uint16)); - if (chaine.buffer == NULL) - return False; - - memcpy(chaine.buffer, p, (q-p+1)*sizeof(uint16)); - - buffer->string_at_end -= (q-p+1)*sizeof(uint16); - - if(!prs_set_offset(ps, buffer->string_at_end)) { - SAFE_FREE(chaine.buffer); - return False; - } - - /* write the string */ - if (!smb_io_unistr(desc, &chaine, ps, depth)) { - SAFE_FREE(chaine.buffer); - return False; - } - q++; - p=q; - - SAFE_FREE(chaine.buffer); - } - - if(!prs_set_offset(ps, struct_offset)) - return False; - - relative_offset=buffer->string_at_end - buffer->struct_start; - /* write its offset */ - if (!prs_uint32("offset", ps, depth, &relative_offset)) - return False; - - } else { - - /* UNMARSHALLING */ - - uint32 old_offset; - uint16 *chaine2=NULL; - int l_chaine=0; - int l_chaine2=0; - size_t realloc_size = 0; - - *string=NULL; - - /* read the offset */ - if (!prs_uint32("offset", ps, depth, &buffer->string_at_end)) - return False; - - old_offset = prs_offset(ps); - if(!prs_set_offset(ps, buffer->string_at_end + buffer->struct_start)) - return False; - - do { - if (!smb_io_unistr(desc, &chaine, ps, depth)) - return False; - - l_chaine=str_len_uni(&chaine); - - /* we're going to add two more bytes here in case this - is the last string in the array and we need to add - an extra NULL for termination */ - if (l_chaine > 0) - { - uint16 *tc2; - - realloc_size = (l_chaine2+l_chaine+2)*sizeof(uint16); - - /* Yes this should be realloc - it's freed below. JRA */ - - if((tc2=(uint16 *)SMB_REALLOC(chaine2, realloc_size)) == NULL) { - SAFE_FREE(chaine2); - return False; - } - else chaine2 = tc2; - memcpy(chaine2+l_chaine2, chaine.buffer, (l_chaine+1)*sizeof(uint16)); - l_chaine2+=l_chaine+1; - } - - } while(l_chaine!=0); - - /* the end should be bould NULL terminated so add - the second one here */ - if (chaine2) - { - chaine2[l_chaine2] = '\0'; - *string=(uint16 *)TALLOC_MEMDUP(prs_get_mem_context(ps),chaine2,realloc_size); - SAFE_FREE(chaine2); - } - - if(!prs_set_offset(ps, old_offset)) - return False; - } - return True; -} - /******************************************************************* Parse a DEVMODE structure and its relative pointer. ********************************************************************/ -static BOOL smb_io_relsecdesc(const char *desc, NEW_BUFFER *buffer, int depth, SEC_DESC **secdesc) -{ - prs_struct *ps= &buffer->prs; - - prs_debug(ps, depth, desc, "smb_io_relsecdesc"); - depth++; - - if (MARSHALLING(ps)) { - uint32 struct_offset = prs_offset(ps); - uint32 relative_offset; - - if (! *secdesc) { - relative_offset = 0; - if (!prs_uint32("offset", ps, depth, &relative_offset)) - return False; - return True; - } - - if (*secdesc != NULL) { - buffer->string_at_end -= sec_desc_size(*secdesc); - - if(!prs_set_offset(ps, buffer->string_at_end)) - return False; - /* write the secdesc */ - if (!sec_io_desc(desc, secdesc, ps, depth)) - return False; - - if(!prs_set_offset(ps, struct_offset)) - return False; - } - - relative_offset=buffer->string_at_end - buffer->struct_start; - /* write its offset */ - - if (!prs_uint32("offset", ps, depth, &relative_offset)) - return False; - } else { - uint32 old_offset; - - /* read the offset */ - if (!prs_uint32("offset", ps, depth, &buffer->string_at_end)) - return False; - - old_offset = prs_offset(ps); - if(!prs_set_offset(ps, buffer->string_at_end + buffer->struct_start)) - return False; - - /* read the sd */ - if (!sec_io_desc(desc, secdesc, ps, depth)) - return False; - - if(!prs_set_offset(ps, old_offset)) - return False; - } - return True; -} - -/******************************************************************* - Parse a DEVMODE structure and its relative pointer. -********************************************************************/ - -static BOOL smb_io_reldevmode(const char *desc, NEW_BUFFER *buffer, int depth, DEVICEMODE **devmode) +static BOOL smb_io_reldevmode(const char *desc, RPC_BUFFER *buffer, int depth, DEVICEMODE **devmode) { prs_struct *ps=&buffer->prs; @@ -2457,7 +2145,7 @@ static BOOL smb_io_reldevmode(const char *desc, NEW_BUFFER *buffer, int depth, D Parse a PRINTER_INFO_0 structure. ********************************************************************/ -BOOL smb_io_printer_info_0(const char *desc, NEW_BUFFER *buffer, PRINTER_INFO_0 *info, int depth) +BOOL smb_io_printer_info_0(const char *desc, RPC_BUFFER *buffer, PRINTER_INFO_0 *info, int depth) { prs_struct *ps=&buffer->prs; @@ -2558,7 +2246,7 @@ BOOL smb_io_printer_info_0(const char *desc, NEW_BUFFER *buffer, PRINTER_INFO_0 Parse a PRINTER_INFO_1 structure. ********************************************************************/ -BOOL smb_io_printer_info_1(const char *desc, NEW_BUFFER *buffer, PRINTER_INFO_1 *info, int depth) +BOOL smb_io_printer_info_1(const char *desc, RPC_BUFFER *buffer, PRINTER_INFO_1 *info, int depth) { prs_struct *ps=&buffer->prs; @@ -2583,7 +2271,7 @@ BOOL smb_io_printer_info_1(const char *desc, NEW_BUFFER *buffer, PRINTER_INFO_1 Parse a PRINTER_INFO_2 structure. ********************************************************************/ -BOOL smb_io_printer_info_2(const char *desc, NEW_BUFFER *buffer, PRINTER_INFO_2 *info, int depth) +BOOL smb_io_printer_info_2(const char *desc, RPC_BUFFER *buffer, PRINTER_INFO_2 *info, int depth) { prs_struct *ps=&buffer->prs; uint32 dm_offset, sd_offset, current_offset; @@ -2674,7 +2362,7 @@ BOOL smb_io_printer_info_2(const char *desc, NEW_BUFFER *buffer, PRINTER_INFO_2 Parse a PRINTER_INFO_3 structure. ********************************************************************/ -BOOL smb_io_printer_info_3(const char *desc, NEW_BUFFER *buffer, PRINTER_INFO_3 *info, int depth) +BOOL smb_io_printer_info_3(const char *desc, RPC_BUFFER *buffer, PRINTER_INFO_3 *info, int depth) { prs_struct *ps=&buffer->prs; @@ -2695,7 +2383,7 @@ BOOL smb_io_printer_info_3(const char *desc, NEW_BUFFER *buffer, PRINTER_INFO_3 Parse a PRINTER_INFO_4 structure. ********************************************************************/ -BOOL smb_io_printer_info_4(const char *desc, NEW_BUFFER *buffer, PRINTER_INFO_4 *info, int depth) +BOOL smb_io_printer_info_4(const char *desc, RPC_BUFFER *buffer, PRINTER_INFO_4 *info, int depth) { prs_struct *ps=&buffer->prs; @@ -2717,7 +2405,7 @@ BOOL smb_io_printer_info_4(const char *desc, NEW_BUFFER *buffer, PRINTER_INFO_4 Parse a PRINTER_INFO_5 structure. ********************************************************************/ -BOOL smb_io_printer_info_5(const char *desc, NEW_BUFFER *buffer, PRINTER_INFO_5 *info, int depth) +BOOL smb_io_printer_info_5(const char *desc, RPC_BUFFER *buffer, PRINTER_INFO_5 *info, int depth) { prs_struct *ps=&buffer->prs; @@ -2743,7 +2431,7 @@ BOOL smb_io_printer_info_5(const char *desc, NEW_BUFFER *buffer, PRINTER_INFO_5 Parse a PRINTER_INFO_7 structure. ********************************************************************/ -BOOL smb_io_printer_info_7(const char *desc, NEW_BUFFER *buffer, PRINTER_INFO_7 *info, int depth) +BOOL smb_io_printer_info_7(const char *desc, RPC_BUFFER *buffer, PRINTER_INFO_7 *info, int depth) { prs_struct *ps=&buffer->prs; @@ -2763,7 +2451,7 @@ BOOL smb_io_printer_info_7(const char *desc, NEW_BUFFER *buffer, PRINTER_INFO_7 Parse a PORT_INFO_1 structure. ********************************************************************/ -BOOL smb_io_port_info_1(const char *desc, NEW_BUFFER *buffer, PORT_INFO_1 *info, int depth) +BOOL smb_io_port_info_1(const char *desc, RPC_BUFFER *buffer, PORT_INFO_1 *info, int depth) { prs_struct *ps=&buffer->prs; @@ -2782,7 +2470,7 @@ BOOL smb_io_port_info_1(const char *desc, NEW_BUFFER *buffer, PORT_INFO_1 *info, Parse a PORT_INFO_2 structure. ********************************************************************/ -BOOL smb_io_port_info_2(const char *desc, NEW_BUFFER *buffer, PORT_INFO_2 *info, int depth) +BOOL smb_io_port_info_2(const char *desc, RPC_BUFFER *buffer, PORT_INFO_2 *info, int depth) { prs_struct *ps=&buffer->prs; @@ -2809,7 +2497,7 @@ BOOL smb_io_port_info_2(const char *desc, NEW_BUFFER *buffer, PORT_INFO_2 *info, Parse a DRIVER_INFO_1 structure. ********************************************************************/ -BOOL smb_io_printer_driver_info_1(const char *desc, NEW_BUFFER *buffer, DRIVER_INFO_1 *info, int depth) +BOOL smb_io_printer_driver_info_1(const char *desc, RPC_BUFFER *buffer, DRIVER_INFO_1 *info, int depth) { prs_struct *ps=&buffer->prs; @@ -2828,7 +2516,7 @@ BOOL smb_io_printer_driver_info_1(const char *desc, NEW_BUFFER *buffer, DRIVER_I Parse a DRIVER_INFO_2 structure. ********************************************************************/ -BOOL smb_io_printer_driver_info_2(const char *desc, NEW_BUFFER *buffer, DRIVER_INFO_2 *info, int depth) +BOOL smb_io_printer_driver_info_2(const char *desc, RPC_BUFFER *buffer, DRIVER_INFO_2 *info, int depth) { prs_struct *ps=&buffer->prs; @@ -2857,7 +2545,7 @@ BOOL smb_io_printer_driver_info_2(const char *desc, NEW_BUFFER *buffer, DRIVER_I Parse a DRIVER_INFO_3 structure. ********************************************************************/ -BOOL smb_io_printer_driver_info_3(const char *desc, NEW_BUFFER *buffer, DRIVER_INFO_3 *info, int depth) +BOOL smb_io_printer_driver_info_3(const char *desc, RPC_BUFFER *buffer, DRIVER_INFO_3 *info, int depth) { prs_struct *ps=&buffer->prs; @@ -2896,7 +2584,7 @@ BOOL smb_io_printer_driver_info_3(const char *desc, NEW_BUFFER *buffer, DRIVER_I Parse a DRIVER_INFO_6 structure. ********************************************************************/ -BOOL smb_io_printer_driver_info_6(const char *desc, NEW_BUFFER *buffer, DRIVER_INFO_6 *info, int depth) +BOOL smb_io_printer_driver_info_6(const char *desc, RPC_BUFFER *buffer, DRIVER_INFO_6 *info, int depth) { prs_struct *ps=&buffer->prs; @@ -2961,7 +2649,7 @@ BOOL smb_io_printer_driver_info_6(const char *desc, NEW_BUFFER *buffer, DRIVER_I Parse a JOB_INFO_1 structure. ********************************************************************/ -BOOL smb_io_job_info_1(const char *desc, NEW_BUFFER *buffer, JOB_INFO_1 *info, int depth) +BOOL smb_io_job_info_1(const char *desc, RPC_BUFFER *buffer, JOB_INFO_1 *info, int depth) { prs_struct *ps=&buffer->prs; @@ -3004,7 +2692,7 @@ BOOL smb_io_job_info_1(const char *desc, NEW_BUFFER *buffer, JOB_INFO_1 *info, i Parse a JOB_INFO_2 structure. ********************************************************************/ -BOOL smb_io_job_info_2(const char *desc, NEW_BUFFER *buffer, JOB_INFO_2 *info, int depth) +BOOL smb_io_job_info_2(const char *desc, RPC_BUFFER *buffer, JOB_INFO_2 *info, int depth) { uint32 pipo=0; prs_struct *ps=&buffer->prs; @@ -3071,7 +2759,7 @@ BOOL smb_io_job_info_2(const char *desc, NEW_BUFFER *buffer, JOB_INFO_2 *info, i /******************************************************************* ********************************************************************/ -BOOL smb_io_form_1(const char *desc, NEW_BUFFER *buffer, FORM_1 *info, int depth) +BOOL smb_io_form_1(const char *desc, RPC_BUFFER *buffer, FORM_1 *info, int depth) { prs_struct *ps=&buffer->prs; @@ -3102,123 +2790,13 @@ BOOL smb_io_form_1(const char *desc, NEW_BUFFER *buffer, FORM_1 *info, int depth return True; } -/******************************************************************* - Read/write a BUFFER struct. -********************************************************************/ -static BOOL spoolss_io_buffer(const char *desc, prs_struct *ps, int depth, NEW_BUFFER **pp_buffer) -{ - NEW_BUFFER *buffer = *pp_buffer; - - prs_debug(ps, depth, desc, "spoolss_io_buffer"); - depth++; - - if (UNMARSHALLING(ps)) - buffer = *pp_buffer = PRS_ALLOC_MEM(ps, NEW_BUFFER, 1); - - if (buffer == NULL) - return False; - - if (!prs_uint32("ptr", ps, depth, &buffer->ptr)) - return False; - - /* reading */ - if (UNMARSHALLING(ps)) { - buffer->size=0; - buffer->string_at_end=0; - - if (buffer->ptr==0) { - /* - * JRA. I'm not sure if the data in here is in big-endian format if - * the client is big-endian. Leave as default (little endian) for now. - */ - - if (!prs_init(&buffer->prs, 0, prs_get_mem_context(ps), UNMARSHALL)) - return False; - return True; - } - - if (!prs_uint32("size", ps, depth, &buffer->size)) - return False; - - /* - * JRA. I'm not sure if the data in here is in big-endian format if - * the client is big-endian. Leave as default (little endian) for now. - */ - - if (!prs_init(&buffer->prs, buffer->size, prs_get_mem_context(ps), UNMARSHALL)) - return False; - - if (!prs_append_some_prs_data(&buffer->prs, ps, prs_offset(ps), buffer->size)) - return False; - - if (!prs_set_offset(&buffer->prs, 0)) - return False; - - if (!prs_set_offset(ps, buffer->size+prs_offset(ps))) - return False; - - buffer->string_at_end=buffer->size; - - return True; - } - else { - BOOL ret = False; - - /* writing */ - if (buffer->ptr==0) { - /* We have finished with the data in buffer->prs - free it. */ - prs_mem_free(&buffer->prs); - return True; - } - - if (!prs_uint32("size", ps, depth, &buffer->size)) - goto out; - - if (!prs_append_some_prs_data(ps, &buffer->prs, 0, buffer->size)) - goto out; - - ret = True; - out: - - /* We have finished with the data in buffer->prs - free it. */ - prs_mem_free(&buffer->prs); - - return ret; - } -} - -/******************************************************************* - move a BUFFER from the query to the reply. - As the data pointers in NEW_BUFFER are malloc'ed, not talloc'ed, - this is ok. This is an OPTIMIZATION and is not strictly neccessary. - Clears the memory to zero also. -********************************************************************/ - -void spoolss_move_buffer(NEW_BUFFER *src, NEW_BUFFER **dest) -{ - prs_switch_type(&src->prs, MARSHALL); - if(!prs_set_offset(&src->prs, 0)) - return; - prs_force_dynamic(&src->prs); - prs_mem_clear(&src->prs); - *dest=src; -} - -/******************************************************************* - Get the size of a BUFFER struct. -********************************************************************/ - -uint32 new_get_buffer_size(NEW_BUFFER *buffer) -{ - return (buffer->size); -} /******************************************************************* Parse a DRIVER_DIRECTORY_1 structure. ********************************************************************/ -BOOL smb_io_driverdir_1(const char *desc, NEW_BUFFER *buffer, DRIVER_DIRECTORY_1 *info, int depth) +BOOL smb_io_driverdir_1(const char *desc, RPC_BUFFER *buffer, DRIVER_DIRECTORY_1 *info, int depth) { prs_struct *ps=&buffer->prs; @@ -3237,7 +2815,7 @@ BOOL smb_io_driverdir_1(const char *desc, NEW_BUFFER *buffer, DRIVER_DIRECTORY_1 Parse a PORT_INFO_1 structure. ********************************************************************/ -BOOL smb_io_port_1(const char *desc, NEW_BUFFER *buffer, PORT_INFO_1 *info, int depth) +BOOL smb_io_port_1(const char *desc, RPC_BUFFER *buffer, PORT_INFO_1 *info, int depth) { prs_struct *ps=&buffer->prs; @@ -3256,7 +2834,7 @@ BOOL smb_io_port_1(const char *desc, NEW_BUFFER *buffer, PORT_INFO_1 *info, int Parse a PORT_INFO_2 structure. ********************************************************************/ -BOOL smb_io_port_2(const char *desc, NEW_BUFFER *buffer, PORT_INFO_2 *info, int depth) +BOOL smb_io_port_2(const char *desc, RPC_BUFFER *buffer, PORT_INFO_2 *info, int depth) { prs_struct *ps=&buffer->prs; @@ -3282,7 +2860,7 @@ BOOL smb_io_port_2(const char *desc, NEW_BUFFER *buffer, PORT_INFO_2 *info, int /******************************************************************* ********************************************************************/ -BOOL smb_io_printprocessor_info_1(const char *desc, NEW_BUFFER *buffer, PRINTPROCESSOR_1 *info, int depth) +BOOL smb_io_printprocessor_info_1(const char *desc, RPC_BUFFER *buffer, PRINTPROCESSOR_1 *info, int depth) { prs_struct *ps=&buffer->prs; @@ -3300,7 +2878,7 @@ BOOL smb_io_printprocessor_info_1(const char *desc, NEW_BUFFER *buffer, PRINTPRO /******************************************************************* ********************************************************************/ -BOOL smb_io_printprocdatatype_info_1(const char *desc, NEW_BUFFER *buffer, PRINTPROCDATATYPE_1 *info, int depth) +BOOL smb_io_printprocdatatype_info_1(const char *desc, RPC_BUFFER *buffer, PRINTPROCDATATYPE_1 *info, int depth) { prs_struct *ps=&buffer->prs; @@ -3318,7 +2896,7 @@ BOOL smb_io_printprocdatatype_info_1(const char *desc, NEW_BUFFER *buffer, PRINT /******************************************************************* ********************************************************************/ -BOOL smb_io_printmonitor_info_1(const char *desc, NEW_BUFFER *buffer, PRINTMONITOR_1 *info, int depth) +BOOL smb_io_printmonitor_info_1(const char *desc, RPC_BUFFER *buffer, PRINTMONITOR_1 *info, int depth) { prs_struct *ps=&buffer->prs; @@ -3336,7 +2914,7 @@ BOOL smb_io_printmonitor_info_1(const char *desc, NEW_BUFFER *buffer, PRINTMONIT /******************************************************************* ********************************************************************/ -BOOL smb_io_printmonitor_info_2(const char *desc, NEW_BUFFER *buffer, PRINTMONITOR_2 *info, int depth) +BOOL smb_io_printmonitor_info_2(const char *desc, RPC_BUFFER *buffer, PRINTMONITOR_2 *info, int depth) { prs_struct *ps=&buffer->prs; @@ -3859,7 +3437,7 @@ BOOL make_spoolss_q_getprinterdriver2(SPOOL_Q_GETPRINTERDRIVER2 *q_u, const POLICY_HND *hnd, const fstring architecture, uint32 level, uint32 clientmajor, uint32 clientminor, - NEW_BUFFER *buffer, uint32 offered) + RPC_BUFFER *buffer, uint32 offered) { if (q_u == NULL) return False; @@ -3903,7 +3481,7 @@ BOOL spoolss_io_q_getprinterdriver2(const char *desc, SPOOL_Q_GETPRINTERDRIVER2 if(!prs_uint32("level", ps, depth, &q_u->level)) return False; - if(!spoolss_io_buffer("", ps, depth, &q_u->buffer)) + if(!prs_rpcbuffer_p("", ps, depth, &q_u->buffer)) return False; if(!prs_align(ps)) @@ -3933,7 +3511,7 @@ BOOL spoolss_io_r_getprinterdriver2(const char *desc, SPOOL_R_GETPRINTERDRIVER2 if (!prs_align(ps)) return False; - if (!spoolss_io_buffer("", ps, depth, &r_u->buffer)) + if (!prs_rpcbuffer_p("", ps, depth, &r_u->buffer)) return False; if (!prs_align(ps)) @@ -3959,7 +3537,7 @@ BOOL make_spoolss_q_enumprinters( uint32 flags, char *servername, uint32 level, - NEW_BUFFER *buffer, + RPC_BUFFER *buffer, uint32 offered ) { @@ -3981,7 +3559,7 @@ BOOL make_spoolss_q_enumprinters( BOOL make_spoolss_q_enumports(SPOOL_Q_ENUMPORTS *q_u, fstring servername, uint32 level, - NEW_BUFFER *buffer, uint32 offered) + RPC_BUFFER *buffer, uint32 offered) { q_u->name_ptr = (servername != NULL) ? 1 : 0; init_buf_unistr2(&q_u->name, &q_u->name_ptr, servername); @@ -4019,7 +3597,7 @@ BOOL spoolss_io_q_enumprinters(const char *desc, SPOOL_Q_ENUMPRINTERS *q_u, prs_ if (!prs_uint32("level", ps, depth, &q_u->level)) return False; - if (!spoolss_io_buffer("", ps, depth, &q_u->buffer)) + if (!prs_rpcbuffer_p("", ps, depth, &q_u->buffer)) return False; if (!prs_align(ps)) @@ -4042,7 +3620,7 @@ BOOL spoolss_io_r_enumprinters(const char *desc, SPOOL_R_ENUMPRINTERS *r_u, prs_ if (!prs_align(ps)) return False; - if (!spoolss_io_buffer("", ps, depth, &r_u->buffer)) + if (!prs_rpcbuffer_p("", ps, depth, &r_u->buffer)) return False; if (!prs_align(ps)) @@ -4074,7 +3652,7 @@ BOOL spoolss_io_r_getprinter(const char *desc, SPOOL_R_GETPRINTER *r_u, prs_stru if (!prs_align(ps)) return False; - if (!spoolss_io_buffer("", ps, depth, &r_u->buffer)) + if (!prs_rpcbuffer_p("", ps, depth, &r_u->buffer)) return False; if (!prs_align(ps)) @@ -4107,7 +3685,7 @@ BOOL spoolss_io_q_getprinter(const char *desc, SPOOL_Q_GETPRINTER *q_u, prs_stru if (!prs_uint32("level", ps, depth, &q_u->level)) return False; - if (!spoolss_io_buffer("", ps, depth, &q_u->buffer)) + if (!prs_rpcbuffer_p("", ps, depth, &q_u->buffer)) return False; if (!prs_align(ps)) @@ -4127,7 +3705,7 @@ BOOL make_spoolss_q_getprinter( SPOOL_Q_GETPRINTER *q_u, const POLICY_HND *hnd, uint32 level, - NEW_BUFFER *buffer, + RPC_BUFFER *buffer, uint32 offered ) { @@ -4349,7 +3927,7 @@ BOOL spoolss_io_r_addjob(const char *desc, SPOOL_R_ADDJOB *r_u, prs_struct *ps, if(!prs_align(ps)) return False; - if(!spoolss_io_buffer("", ps, depth, &r_u->buffer)) + if(!prs_rpcbuffer_p("", ps, depth, &r_u->buffer)) return False; if(!prs_align(ps)) @@ -4380,7 +3958,7 @@ BOOL spoolss_io_q_addjob(const char *desc, SPOOL_Q_ADDJOB *q_u, prs_struct *ps, if(!prs_uint32("level", ps, depth, &q_u->level)) return False; - if(!spoolss_io_buffer("", ps, depth, &q_u->buffer)) + if(!prs_rpcbuffer_p("", ps, depth, &q_u->buffer)) return False; if(!prs_align(ps)) @@ -4403,7 +3981,7 @@ BOOL spoolss_io_r_enumjobs(const char *desc, SPOOL_R_ENUMJOBS *r_u, prs_struct * if (!prs_align(ps)) return False; - if (!spoolss_io_buffer("", ps, depth, &r_u->buffer)) + if (!prs_rpcbuffer_p("", ps, depth, &r_u->buffer)) return False; if (!prs_align(ps)) @@ -4428,7 +4006,7 @@ BOOL make_spoolss_q_enumjobs(SPOOL_Q_ENUMJOBS *q_u, const POLICY_HND *hnd, uint32 firstjob, uint32 numofjobs, uint32 level, - NEW_BUFFER *buffer, + RPC_BUFFER *buffer, uint32 offered) { if (q_u == NULL) @@ -4465,7 +4043,7 @@ BOOL spoolss_io_q_enumjobs(const char *desc, SPOOL_Q_ENUMJOBS *q_u, prs_struct * if (!prs_uint32("level", ps, depth, &q_u->level)) return False; - if (!spoolss_io_buffer("", ps, depth, &q_u->buffer)) + if (!prs_rpcbuffer_p("", ps, depth, &q_u->buffer)) return False; if(!prs_align(ps)) @@ -4569,7 +4147,7 @@ BOOL spoolss_io_r_enumprinterdrivers(const char *desc, SPOOL_R_ENUMPRINTERDRIVER if (!prs_align(ps)) return False; - if (!spoolss_io_buffer("", ps, depth, &r_u->buffer)) + if (!prs_rpcbuffer_p("", ps, depth, &r_u->buffer)) return False; if (!prs_align(ps)) @@ -4595,7 +4173,7 @@ BOOL make_spoolss_q_enumprinterdrivers(SPOOL_Q_ENUMPRINTERDRIVERS *q_u, const char *name, const char *environment, uint32 level, - NEW_BUFFER *buffer, uint32 offered) + RPC_BUFFER *buffer, uint32 offered) { init_buf_unistr2(&q_u->name, &q_u->name_ptr, name); init_buf_unistr2(&q_u->environment, &q_u->environment_ptr, environment); @@ -4637,7 +4215,7 @@ BOOL spoolss_io_q_enumprinterdrivers(const char *desc, SPOOL_Q_ENUMPRINTERDRIVER if (!prs_uint32("level", ps, depth, &q_u->level)) return False; - if (!spoolss_io_buffer("", ps, depth, &q_u->buffer)) + if (!prs_rpcbuffer_p("", ps, depth, &q_u->buffer)) return False; if (!prs_align(ps)) @@ -4665,7 +4243,7 @@ BOOL spoolss_io_q_enumforms(const char *desc, SPOOL_Q_ENUMFORMS *q_u, prs_struct if (!prs_uint32("level", ps, depth, &q_u->level)) return False; - if (!spoolss_io_buffer("", ps, depth, &q_u->buffer)) + if (!prs_rpcbuffer_p("", ps, depth, &q_u->buffer)) return False; if (!prs_align(ps)) @@ -4687,7 +4265,7 @@ BOOL spoolss_io_r_enumforms(const char *desc, SPOOL_R_ENUMFORMS *r_u, prs_struct if (!prs_align(ps)) return False; - if (!spoolss_io_buffer("", ps, depth, &r_u->buffer)) + if (!prs_rpcbuffer_p("", ps, depth, &r_u->buffer)) return False; if (!prs_align(ps)) @@ -4727,7 +4305,7 @@ BOOL spoolss_io_q_getform(const char *desc, SPOOL_Q_GETFORM *q_u, prs_struct *ps if (!prs_uint32("level", ps, depth, &q_u->level)) return False; - if (!spoolss_io_buffer("", ps, depth, &q_u->buffer)) + if (!prs_rpcbuffer_p("", ps, depth, &q_u->buffer)) return False; if (!prs_align(ps)) @@ -4749,7 +4327,7 @@ BOOL spoolss_io_r_getform(const char *desc, SPOOL_R_GETFORM *r_u, prs_struct *ps if (!prs_align(ps)) return False; - if (!spoolss_io_buffer("", ps, depth, &r_u->buffer)) + if (!prs_rpcbuffer_p("", ps, depth, &r_u->buffer)) return False; if (!prs_align(ps)) @@ -4776,7 +4354,7 @@ BOOL spoolss_io_r_enumports(const char *desc, SPOOL_R_ENUMPORTS *r_u, prs_struct if (!prs_align(ps)) return False; - if (!spoolss_io_buffer("", ps, depth, &r_u->buffer)) + if (!prs_rpcbuffer_p("", ps, depth, &r_u->buffer)) return False; if (!prs_align(ps)) @@ -4815,7 +4393,7 @@ BOOL spoolss_io_q_enumports(const char *desc, SPOOL_Q_ENUMPORTS *q_u, prs_struct if (!prs_uint32("level", ps, depth, &q_u->level)) return False; - if (!spoolss_io_buffer("", ps, depth, &q_u->buffer)) + if (!prs_rpcbuffer_p("", ps, depth, &q_u->buffer)) return False; if (!prs_align(ps)) @@ -5065,9 +4643,10 @@ BOOL spoolss_io_q_addprinterex(const char *desc, SPOOL_Q_ADDPRINTEREX *q_u, prs_ if(!prs_align(ps)) return False; - if(!prs_uint32("", ps, depth, &q_u->server_name_ptr)) + + if (!prs_io_unistr2_p("ptr", ps, depth, &q_u->server_name)) return False; - if(!smb_io_unistr2("", &q_u->server_name, q_u->server_name_ptr, ps, depth)) + if (!prs_io_unistr2("servername", ps, depth, q_u->server_name)) return False; if(!prs_align(ps)) @@ -5815,7 +5394,7 @@ BOOL uni_2_asc_printer_info_2(const SPOOL_PRINTER_INFO_LEVEL_2 *uni, BOOL make_spoolss_q_getprinterdriverdir(SPOOL_Q_GETPRINTERDRIVERDIR *q_u, fstring servername, fstring env_name, uint32 level, - NEW_BUFFER *buffer, uint32 offered) + RPC_BUFFER *buffer, uint32 offered) { init_buf_unistr2(&q_u->name, &q_u->name_ptr, servername); init_buf_unistr2(&q_u->environment, &q_u->environment_ptr, env_name); @@ -5857,7 +5436,7 @@ BOOL spoolss_io_q_getprinterdriverdir(const char *desc, SPOOL_Q_GETPRINTERDRIVER if(!prs_uint32("level", ps, depth, &q_u->level)) return False; - if(!spoolss_io_buffer("", ps, depth, &q_u->buffer)) + if(!prs_rpcbuffer_p("", ps, depth, &q_u->buffer)) return False; if(!prs_align(ps)) @@ -5881,7 +5460,7 @@ BOOL spoolss_io_r_getprinterdriverdir(const char *desc, SPOOL_R_GETPRINTERDRIVER if (!prs_align(ps)) return False; - if (!spoolss_io_buffer("", ps, depth, &r_u->buffer)) + if (!prs_rpcbuffer_p("", ps, depth, &r_u->buffer)) return False; if (!prs_align(ps)) @@ -5907,7 +5486,7 @@ BOOL spoolss_io_r_enumprintprocessors(const char *desc, SPOOL_R_ENUMPRINTPROCESS if (!prs_align(ps)) return False; - if (!spoolss_io_buffer("", ps, depth, &r_u->buffer)) + if (!prs_rpcbuffer_p("", ps, depth, &r_u->buffer)) return False; if (!prs_align(ps)) @@ -5955,7 +5534,7 @@ BOOL spoolss_io_q_enumprintprocessors(const char *desc, SPOOL_Q_ENUMPRINTPROCESS if (!prs_uint32("level", ps, depth, &q_u->level)) return False; - if(!spoolss_io_buffer("", ps, depth, &q_u->buffer)) + if(!prs_rpcbuffer_p("", ps, depth, &q_u->buffer)) return False; if (!prs_align(ps)) @@ -6029,7 +5608,7 @@ BOOL spoolss_io_r_enumprintprocdatatypes(const char *desc, SPOOL_R_ENUMPRINTPROC if (!prs_align(ps)) return False; - if (!spoolss_io_buffer("", ps, depth, &r_u->buffer)) + if (!prs_rpcbuffer_p("", ps, depth, &r_u->buffer)) return False; if (!prs_align(ps)) @@ -6077,7 +5656,7 @@ BOOL spoolss_io_q_enumprintprocdatatypes(const char *desc, SPOOL_Q_ENUMPRINTPROC if (!prs_uint32("level", ps, depth, &q_u->level)) return False; - if(!spoolss_io_buffer("buffer", ps, depth, &q_u->buffer)) + if(!prs_rpcbuffer_p("buffer", ps, depth, &q_u->buffer)) return False; if (!prs_align(ps)) @@ -6112,7 +5691,7 @@ BOOL spoolss_io_q_enumprintmonitors(const char *desc, SPOOL_Q_ENUMPRINTMONITORS if (!prs_uint32("level", ps, depth, &q_u->level)) return False; - if(!spoolss_io_buffer("", ps, depth, &q_u->buffer)) + if(!prs_rpcbuffer_p("", ps, depth, &q_u->buffer)) return False; if (!prs_align(ps)) @@ -6135,7 +5714,7 @@ BOOL spoolss_io_r_enumprintmonitors(const char *desc, SPOOL_R_ENUMPRINTMONITORS if (!prs_align(ps)) return False; - if (!spoolss_io_buffer("", ps, depth, &r_u->buffer)) + if (!prs_rpcbuffer_p("", ps, depth, &r_u->buffer)) return False; if (!prs_align(ps)) @@ -6578,7 +6157,7 @@ BOOL spoolss_io_r_getjob(const char *desc, SPOOL_R_GETJOB *r_u, prs_struct *ps, if (!prs_align(ps)) return False; - if (!spoolss_io_buffer("", ps, depth, &r_u->buffer)) + if (!prs_rpcbuffer_p("", ps, depth, &r_u->buffer)) return False; if (!prs_align(ps)) @@ -6612,7 +6191,7 @@ BOOL spoolss_io_q_getjob(const char *desc, SPOOL_Q_GETJOB *q_u, prs_struct *ps, if(!prs_uint32("level", ps, depth, &q_u->level)) return False; - if(!spoolss_io_buffer("", ps, depth, &q_u->buffer)) + if(!prs_rpcbuffer_p("", ps, depth, &q_u->buffer)) return False; if(!prs_align(ps)) @@ -7463,7 +7042,7 @@ BOOL spoolss_io_r_enumprinterdataex(const char *desc, SPOOL_R_ENUMPRINTERDATAEX [in] unistr2 *name, [in] unistr2 *environment, [in] uint32 level, - [in,out] NEW_BUFFER buffer, + [in,out] RPC_BUFFER buffer, [in] uint32 offered, [out] uint32 needed, [out] uint32 returned @@ -7471,7 +7050,7 @@ BOOL spoolss_io_r_enumprinterdataex(const char *desc, SPOOL_R_ENUMPRINTERDATAEX */ -BOOL make_spoolss_q_getprintprocessordirectory(SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, const char *name, char *environment, int level, NEW_BUFFER *buffer, uint32 offered) +BOOL make_spoolss_q_getprintprocessordirectory(SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, const char *name, char *environment, int level, RPC_BUFFER *buffer, uint32 offered) { DEBUG(5,("make_spoolss_q_getprintprocessordirectory\n")); @@ -7522,7 +7101,7 @@ BOOL spoolss_io_q_getprintprocessordirectory(const char *desc, SPOOL_Q_GETPRINTP if(!prs_uint32("level", ps, depth, &q_u->level)) return False; - if(!spoolss_io_buffer("", ps, depth, &q_u->buffer)) + if(!prs_rpcbuffer_p("", ps, depth, &q_u->buffer)) return False; if(!prs_align(ps)) @@ -7546,7 +7125,7 @@ BOOL spoolss_io_r_getprintprocessordirectory(const char *desc, SPOOL_R_GETPRINTP if(!prs_align(ps)) return False; - if(!spoolss_io_buffer("", ps, depth, &r_u->buffer)) + if(!prs_rpcbuffer_p("", ps, depth, &r_u->buffer)) return False; if(!prs_align(ps)) @@ -7561,7 +7140,7 @@ BOOL spoolss_io_r_getprintprocessordirectory(const char *desc, SPOOL_R_GETPRINTP return True; } -BOOL smb_io_printprocessordirectory_1(const char *desc, NEW_BUFFER *buffer, PRINTPROCESSOR_DIRECTORY_1 *info, int depth) +BOOL smb_io_printprocessordirectory_1(const char *desc, RPC_BUFFER *buffer, PRINTPROCESSOR_DIRECTORY_1 *info, int depth) { prs_struct *ps=&buffer->prs; @@ -7625,7 +7204,7 @@ BOOL make_spoolss_q_deleteform(SPOOL_Q_DELETEFORM *q_u, POLICY_HND *handle, BOOL make_spoolss_q_getform(SPOOL_Q_GETFORM *q_u, POLICY_HND *handle, const char *formname, uint32 level, - NEW_BUFFER *buffer, uint32 offered) + RPC_BUFFER *buffer, uint32 offered) { memcpy(&q_u->handle, handle, sizeof(POLICY_HND)); q_u->level = level; @@ -7641,7 +7220,7 @@ BOOL make_spoolss_q_getform(SPOOL_Q_GETFORM *q_u, POLICY_HND *handle, ********************************************************************/ BOOL make_spoolss_q_enumforms(SPOOL_Q_ENUMFORMS *q_u, POLICY_HND *handle, - uint32 level, NEW_BUFFER *buffer, + uint32 level, RPC_BUFFER *buffer, uint32 offered) { memcpy(&q_u->handle, handle, sizeof(POLICY_HND)); @@ -7676,7 +7255,7 @@ BOOL make_spoolss_q_setjob(SPOOL_Q_SETJOB *q_u, POLICY_HND *handle, ********************************************************************/ BOOL make_spoolss_q_getjob(SPOOL_Q_GETJOB *q_u, POLICY_HND *handle, - uint32 jobid, uint32 level, NEW_BUFFER *buffer, + uint32 jobid, uint32 level, RPC_BUFFER *buffer, uint32 offered) { memcpy(&q_u->handle, handle, sizeof(POLICY_HND)); diff --git a/source/rpc_parse/parse_srv.c b/source/rpc_parse/parse_srv.c index 84c45b59014..7d15eda630f 100644 --- a/source/rpc_parse/parse_srv.c +++ b/source/rpc_parse/parse_srv.c @@ -1995,6 +1995,79 @@ BOOL srv_io_r_net_sess_enum(const char *desc, SRV_R_NET_SESS_ENUM *r_n, prs_stru return True; } +/******************************************************************* + Inits a SRV_Q_NET_SESS_DEL structure. +********************************************************************/ + +void init_srv_q_net_sess_del(SRV_Q_NET_SESS_DEL *q_n, const char *srv_name, + const char *cli_name, const char *user_name) +{ + DEBUG(5,("init_q_net_sess_enum\n")); + + init_buf_unistr2(&q_n->uni_srv_name, &q_n->ptr_srv_name, srv_name); + init_buf_unistr2(&q_n->uni_cli_name, &q_n->ptr_cli_name, cli_name); + init_buf_unistr2(&q_n->uni_user_name, &q_n->ptr_user_name, user_name); +} + +/******************************************************************* + Reads or writes a structure. +********************************************************************/ + +BOOL srv_io_q_net_sess_del(const char *desc, SRV_Q_NET_SESS_DEL *q_n, prs_struct *ps, int depth) +{ + if (q_n == NULL) + return False; + + prs_debug(ps, depth, desc, "srv_io_q_net_sess_del"); + depth++; + + if(!prs_align(ps)) + return False; + + if(!prs_uint32("ptr_srv_name", ps, depth, &q_n->ptr_srv_name)) + return False; + if(!smb_io_unistr2("", &q_n->uni_srv_name, True, ps, depth)) + return False; + + if(!prs_align(ps)) + return False; + + if(!prs_uint32("ptr_cli_name", ps, depth, &q_n->ptr_cli_name)) + return False; + if(!smb_io_unistr2("", &q_n->uni_cli_name, q_n->ptr_cli_name, ps, depth)) + return False; + + if(!prs_align(ps)) + return False; + if(!prs_uint32("ptr_user_name", ps, depth, &q_n->ptr_user_name)) + return False; + if(!smb_io_unistr2("", &q_n->uni_user_name, q_n->ptr_user_name, ps, depth)) + return False; + + return True; +} + +/******************************************************************* + Reads or writes a structure. +********************************************************************/ + +BOOL srv_io_r_net_sess_del(const char *desc, SRV_R_NET_SESS_DEL *r_n, prs_struct *ps, int depth) +{ + if (r_n == NULL) + return False; + + prs_debug(ps, depth, desc, "srv_io_r_net_sess_del"); + depth++; + + if(!prs_align(ps)) + return False; + + if(!prs_werror("status", ps, depth, &r_n->status)) + return False; + + return True; +} + /******************************************************************* Inits a CONN_INFO_0 structure ********************************************************************/ diff --git a/source/rpc_parse/parse_svcctl.c b/source/rpc_parse/parse_svcctl.c new file mode 100644 index 00000000000..1c41a18b99e --- /dev/null +++ b/source/rpc_parse/parse_svcctl.c @@ -0,0 +1,660 @@ +/* + * Unix SMB/CIFS implementation. + * RPC Pipe client / server routines + * Copyright (C) Gerald (Jerry) Carter 2005. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "includes.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_RPC_PARSE + +/******************************************************************* +********************************************************************/ + +static BOOL svcctl_io_service_status( const char *desc, SERVICE_STATUS *status, prs_struct *ps, int depth ) +{ + + prs_debug(ps, depth, desc, "svcctl_io_service_status"); + depth++; + + if(!prs_uint32("type", ps, depth, &status->type)) + return False; + + if(!prs_uint32("state", ps, depth, &status->state)) + return False; + + if(!prs_uint32("controls_accepted", ps, depth, &status->controls_accepted)) + return False; + + if(!prs_uint32("win32_exit_code", ps, depth, &status->win32_exit_code)) + return False; + + if(!prs_uint32("service_exit_code", ps, depth, &status->service_exit_code)) + return False; + + if(!prs_uint32("check_point", ps, depth, &status->check_point)) + return False; + + if(!prs_uint32("wait_hint", ps, depth, &status->wait_hint)) + return False; + + return True; +} + +/******************************************************************* +********************************************************************/ + +static BOOL svcctl_io_service_config( const char *desc, SERVICE_CONFIG *config, prs_struct *ps, int depth ) +{ + + prs_debug(ps, depth, desc, "svcctl_io_service_config"); + depth++; + + if(!prs_uint32("service_type", ps, depth, &config->service_type)) + return False; + if(!prs_uint32("start_type", ps, depth, &config->start_type)) + return False; + if(!prs_uint32("error_control", ps, depth, &config->error_control)) + return False; + + if (!prs_io_unistr2_p("", ps, depth, &config->executablepath)) + return False; + if (!prs_io_unistr2_p("", ps, depth, &config->loadordergroup)) + return False; + + if(!prs_uint32("tag_id", ps, depth, &config->tag_id)) + return False; + + if (!prs_io_unistr2_p("", ps, depth, &config->dependencies)) + return False; + if (!prs_io_unistr2_p("", ps, depth, &config->startname)) + return False; + if (!prs_io_unistr2_p("", ps, depth, &config->displayname)) + return False; + + if (!prs_io_unistr2("", ps, depth, config->executablepath)) + return False; + if (!prs_io_unistr2("", ps, depth, config->loadordergroup)) + return False; + if (!prs_io_unistr2("", ps, depth, config->dependencies)) + return False; + if (!prs_io_unistr2("", ps, depth, config->startname)) + return False; + if (!prs_io_unistr2("", ps, depth, config->displayname)) + return False; + + return True; +} + + +/******************************************************************* +********************************************************************/ + +BOOL svcctl_io_enum_services_status( const char *desc, ENUM_SERVICES_STATUS *enum_status, RPC_BUFFER *buffer, int depth ) +{ + prs_struct *ps=&buffer->prs; + + prs_debug(ps, depth, desc, "svcctl_io_enum_services_status"); + depth++; + + if ( !smb_io_relstr("servicename", buffer, depth, &enum_status->servicename) ) + return False; + if ( !smb_io_relstr("displayname", buffer, depth, &enum_status->displayname) ) + return False; + + if ( !svcctl_io_service_status("svc_status", &enum_status->status, ps, depth) ) + return False; + + return True; +} + +/******************************************************************* +********************************************************************/ + +uint32 svcctl_sizeof_enum_services_status( ENUM_SERVICES_STATUS *status ) +{ + uint32 size = 0; + + size += size_of_relative_string( &status->servicename ); + size += size_of_relative_string( &status->displayname ); + size += sizeof(SERVICE_STATUS); + + return size; +} + +/******************************************************************* +********************************************************************/ + +BOOL svcctl_io_q_close_service(const char *desc, SVCCTL_Q_CLOSE_SERVICE *q_u, prs_struct *ps, int depth) +{ + if (q_u == NULL) + return False; + + prs_debug(ps, depth, desc, "svcctl_io_q_close_service"); + depth++; + + if(!prs_align(ps)) + return False; + + if(!smb_io_pol_hnd("scm_pol", &q_u->handle, ps, depth)) + return False; + + return True; +} + + +/******************************************************************* +********************************************************************/ + +BOOL svcctl_io_r_close_service(const char *desc, SVCCTL_R_CLOSE_SERVICE *r_u, prs_struct *ps, int depth) +{ + if (r_u == NULL) + return False; + + prs_debug(ps, depth, desc, "svcctl_io_r_close_service"); + depth++; + + if(!prs_align(ps)) + return False; + + if(!prs_werror("status", ps, depth, &r_u->status)) + return False; + + return True; +} + +/******************************************************************* +********************************************************************/ + +BOOL svcctl_io_q_open_scmanager(const char *desc, SVCCTL_Q_OPEN_SCMANAGER *q_u, prs_struct *ps, int depth) +{ + if (q_u == NULL) + return False; + + prs_debug(ps, depth, desc, "svcctl_io_q_open_scmanager"); + depth++; + + if(!prs_align(ps)) + return False; + + if(!prs_pointer("servername", ps, depth, (void**)&q_u->servername, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2)) + return False; + if(!prs_align(ps)) + return False; + + if(!prs_pointer("database", ps, depth, (void**)&q_u->database, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2)) + return False; + if(!prs_align(ps)) + return False; + + if(!prs_uint32("access", ps, depth, &q_u->access)) + return False; + + return True; +} + +/******************************************************************* +********************************************************************/ + +BOOL svcctl_io_r_open_scmanager(const char *desc, SVCCTL_R_OPEN_SCMANAGER *r_u, prs_struct *ps, int depth) +{ + if (r_u == NULL) + return False; + + prs_debug(ps, depth, desc, "svcctl_io_r_open_scmanager"); + depth++; + + if(!prs_align(ps)) + return False; + + if(!smb_io_pol_hnd("scm_pol", &r_u->handle, ps, depth)) + return False; + + if(!prs_werror("status", ps, depth, &r_u->status)) + return False; + + return True; +} + +/******************************************************************* +********************************************************************/ + +BOOL svcctl_io_q_get_display_name(const char *desc, SVCCTL_Q_GET_DISPLAY_NAME *q_u, prs_struct *ps, int depth) +{ + if (q_u == NULL) + return False; + + prs_debug(ps, depth, desc, "svcctl_io_q_get_display_name"); + depth++; + + if(!prs_align(ps)) + return False; + + if(!smb_io_pol_hnd("scm_pol", &q_u->handle, ps, depth)) + return False; + + if(!smb_io_unistr2("servicename", &q_u->servicename, 1, ps, depth)) + return False; + + if(!prs_align(ps)) + return False; + + if(!prs_uint32("display_name_len", ps, depth, &q_u->display_name_len)) + return False; + + return True; +} + +/******************************************************************* +********************************************************************/ + +BOOL init_svcctl_r_get_display_name( SVCCTL_R_GET_DISPLAY_NAME *r_u, const char *displayname ) +{ + r_u->display_name_len = strlen(displayname); + init_unistr2( &r_u->displayname, displayname, UNI_STR_TERMINATE ); + + return True; +} + +/******************************************************************* +********************************************************************/ + +BOOL svcctl_io_r_get_display_name(const char *desc, SVCCTL_R_GET_DISPLAY_NAME *r_u, prs_struct *ps, int depth) +{ + if (r_u == NULL) + return False; + + prs_debug(ps, depth, desc, "svcctl_io_r_get_display_name"); + depth++; + + if(!prs_align(ps)) + return False; + + + if(!smb_io_unistr2("displayname", &r_u->displayname, 1, ps, depth)) + return False; + + if(!prs_align(ps)) + return False; + + if(!prs_uint32("display_name_len", ps, depth, &r_u->display_name_len)) + return False; + + if(!prs_werror("status", ps, depth, &r_u->status)) + return False; + + return True; +} + + +/******************************************************************* +********************************************************************/ + +BOOL svcctl_io_q_open_service(const char *desc, SVCCTL_Q_OPEN_SERVICE *q_u, prs_struct *ps, int depth) +{ + if (q_u == NULL) + return False; + + prs_debug(ps, depth, desc, "svcctl_io_q_open_service"); + depth++; + + if(!prs_align(ps)) + return False; + + if(!smb_io_pol_hnd("scm_pol", &q_u->handle, ps, depth)) + return False; + + if(!smb_io_unistr2("servicename", &q_u->servicename, 1, ps, depth)) + return False; + + if(!prs_align(ps)) + return False; + + if(!prs_uint32("access", ps, depth, &q_u->access)) + return False; + + return True; +} + +/******************************************************************* +********************************************************************/ + +BOOL svcctl_io_r_open_service(const char *desc, SVCCTL_R_OPEN_SERVICE *r_u, prs_struct *ps, int depth) +{ + if (r_u == NULL) + return False; + + prs_debug(ps, depth, desc, "svcctl_io_r_open_service"); + depth++; + + if(!prs_align(ps)) + return False; + + if(!smb_io_pol_hnd("service_pol", &r_u->handle, ps, depth)) + return False; + + if(!prs_werror("status", ps, depth, &r_u->status)) + return False; + + return True; +} + +/******************************************************************* +********************************************************************/ + +BOOL svcctl_io_q_query_status(const char *desc, SVCCTL_Q_QUERY_STATUS *q_u, prs_struct *ps, int depth) +{ + if (q_u == NULL) + return False; + + prs_debug(ps, depth, desc, "svcctl_io_q_query_status"); + depth++; + + if(!prs_align(ps)) + return False; + + if(!smb_io_pol_hnd("service_pol", &q_u->handle, ps, depth)) + return False; + + return True; +} + +/******************************************************************* +********************************************************************/ + +BOOL svcctl_io_r_query_status(const char *desc, SVCCTL_R_QUERY_STATUS *r_u, prs_struct *ps, int depth) +{ + if (r_u == NULL) + return False; + + prs_debug(ps, depth, desc, "svcctl_io_r_query_status"); + depth++; + + if(!prs_align(ps)) + return False; + + if(!svcctl_io_service_status("service_status", &r_u->svc_status, ps, depth)) + return False; + + if(!prs_werror("status", ps, depth, &r_u->status)) + return False; + + return True; +} + +/******************************************************************* +********************************************************************/ + +BOOL svcctl_io_q_enum_services_status(const char *desc, SVCCTL_Q_ENUM_SERVICES_STATUS *q_u, prs_struct *ps, int depth) +{ + if (q_u == NULL) + return False; + + prs_debug(ps, depth, desc, "svcctl_io_q_enum_services_status"); + depth++; + + if(!prs_align(ps)) + return False; + + if(!smb_io_pol_hnd("scm_pol", &q_u->handle, ps, depth)) + return False; + + if(!prs_uint32("type", ps, depth, &q_u->type)) + return False; + if(!prs_uint32("state", ps, depth, &q_u->state)) + return False; + if(!prs_uint32("buffer_size", ps, depth, &q_u->buffer_size)) + return False; + + if(!prs_pointer("resume", ps, depth, (void**)&q_u->resume, sizeof(uint32), (PRS_POINTER_CAST)prs_uint32)) + return False; + + return True; +} + +/******************************************************************* +********************************************************************/ + +BOOL svcctl_io_r_enum_services_status(const char *desc, SVCCTL_R_ENUM_SERVICES_STATUS *r_u, prs_struct *ps, int depth) +{ + if (r_u == NULL) + return False; + + prs_debug(ps, depth, desc, "svcctl_io_r_enum_services_status"); + depth++; + + if(!prs_align(ps)) + return False; + + if (!prs_rpcbuffer("", ps, depth, &r_u->buffer)) + return False; + + if(!prs_align(ps)) + return False; + + if(!prs_uint32("needed", ps, depth, &r_u->needed)) + return False; + if(!prs_uint32("returned", ps, depth, &r_u->returned)) + return False; + + if(!prs_pointer("resume", ps, depth, (void**)&r_u->resume, sizeof(uint32), (PRS_POINTER_CAST)prs_uint32)) + return False; + + if(!prs_werror("status", ps, depth, &r_u->status)) + return False; + + return True; +} + +/******************************************************************* +********************************************************************/ + +BOOL svcctl_io_q_start_service(const char *desc, SVCCTL_Q_START_SERVICE *q_u, prs_struct *ps, int depth) +{ + if (q_u == NULL) + return False; + + prs_debug(ps, depth, desc, "svcctl_io_q_start_service"); + depth++; + + if(!prs_align(ps)) + return False; + + if(!smb_io_pol_hnd("service_pol", &q_u->handle, ps, depth)) + return False; + + if(!prs_uint32("parmcount", ps, depth, &q_u->parmcount)) + return False; + + if ( !prs_pointer("rights", ps, depth, (void**)&q_u->parameters, sizeof(UNISTR4_ARRAY), (PRS_POINTER_CAST)prs_unistr4_array) ) + return False; + + return True; +} + +/******************************************************************* +********************************************************************/ + +BOOL svcctl_io_r_start_service(const char *desc, SVCCTL_R_START_SERVICE *r_u, prs_struct *ps, int depth) +{ + if (r_u == NULL) + return False; + + prs_debug(ps, depth, desc, "svcctl_io_r_start_service"); + depth++; + + if(!prs_werror("status", ps, depth, &r_u->status)) + return False; + + return True; +} + + +/******************************************************************* +********************************************************************/ + +BOOL svcctl_io_q_enum_dependent_services(const char *desc, SVCCTL_Q_ENUM_DEPENDENT_SERVICES *q_u, prs_struct *ps, int depth) +{ + if (q_u == NULL) + return False; + + prs_debug(ps, depth, desc, "svcctl_io_q_enum_dependent_services"); + depth++; + + if(!prs_align(ps)) + return False; + + if(!smb_io_pol_hnd("service_pol", &q_u->handle, ps, depth)) + return False; + + if(!prs_uint32("state", ps, depth, &q_u->state)) + return False; + if(!prs_uint32("buffer_size", ps, depth, &q_u->buffer_size)) + return False; + + return True; +} + +/******************************************************************* +********************************************************************/ + +BOOL svcctl_io_r_enum_dependent_services(const char *desc, SVCCTL_R_ENUM_DEPENDENT_SERVICES *r_u, prs_struct *ps, int depth) +{ + if (r_u == NULL) + return False; + + prs_debug(ps, depth, desc, "svcctl_io_r_enum_dependent_services"); + depth++; + + if(!prs_align(ps)) + return False; + + if (!prs_rpcbuffer("", ps, depth, &r_u->buffer)) + return False; + + if(!prs_align(ps)) + return False; + + if(!prs_uint32("needed", ps, depth, &r_u->needed)) + return False; + if(!prs_uint32("returned", ps, depth, &r_u->returned)) + return False; + + if(!prs_werror("status", ps, depth, &r_u->status)) + return False; + + return True; +} + +/******************************************************************* +********************************************************************/ + +BOOL svcctl_io_q_control_service(const char *desc, SVCCTL_Q_CONTROL_SERVICE *q_u, prs_struct *ps, int depth) +{ + if (q_u == NULL) + return False; + + prs_debug(ps, depth, desc, "svcctl_io_q_control_service"); + depth++; + + if(!prs_align(ps)) + return False; + + if(!smb_io_pol_hnd("service_pol", &q_u->handle, ps, depth)) + return False; + + if(!prs_uint32("control", ps, depth, &q_u->control)) + return False; + + return True; +} + +/******************************************************************* +********************************************************************/ + +BOOL svcctl_io_r_control_service(const char *desc, SVCCTL_R_CONTROL_SERVICE *r_u, prs_struct *ps, int depth) +{ + if (r_u == NULL) + return False; + + prs_debug(ps, depth, desc, "svcctl_io_r_control_service"); + depth++; + + if(!prs_align(ps)) + return False; + + if(!svcctl_io_service_status("service_status", &r_u->svc_status, ps, depth)) + return False; + + if(!prs_werror("status", ps, depth, &r_u->status)) + return False; + + return True; +} + + +/******************************************************************* +********************************************************************/ + +BOOL svcctl_io_q_query_service_config(const char *desc, SVCCTL_Q_QUERY_SERVICE_CONFIG *q_u, prs_struct *ps, int depth) +{ + if (q_u == NULL) + return False; + + prs_debug(ps, depth, desc, "svcctl_io_q_query_service_config"); + depth++; + + if(!prs_align(ps)) + return False; + + if(!smb_io_pol_hnd("service_pol", &q_u->handle, ps, depth)) + return False; + + if(!prs_uint32("buffer_size", ps, depth, &q_u->buffer_size)) + return False; + + return True; +} + +/******************************************************************* +********************************************************************/ + +BOOL svcctl_io_r_query_service_config(const char *desc, SVCCTL_R_QUERY_SERVICE_CONFIG *r_u, prs_struct *ps, int depth) +{ + if (r_u == NULL) + return False; + + prs_debug(ps, depth, desc, "svcctl_io_r_query_service_config"); + depth++; + + if(!prs_align(ps)) + return False; + + if(!svcctl_io_service_config("config", &r_u->config, ps, depth)) + return False; + + if(!prs_uint32("needed", ps, depth, &r_u->needed)) + return False; + + if(!prs_werror("status", ps, depth, &r_u->status)) + return False; + + return True; +} + + diff --git a/source/rpc_server/srv_eventlog.c b/source/rpc_server/srv_eventlog.c new file mode 100644 index 00000000000..07aebcd2faa --- /dev/null +++ b/source/rpc_server/srv_eventlog.c @@ -0,0 +1,206 @@ +/* + * Unix SMB/CIFS implementation. + * RPC Pipe client / server routines + * Copyright (C) Marcin Krzysztof Porwit 2005. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "includes.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_RPC_SRV + +static BOOL api_eventlog_open_eventlog(pipes_struct *p) +{ + EVENTLOG_Q_OPEN_EVENTLOG q_u; + EVENTLOG_R_OPEN_EVENTLOG r_u; + + prs_struct *data = &p->in_data.data; + prs_struct *rdata = &p->out_data.rdata; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + if (!(eventlog_io_q_open_eventlog("", &q_u, data, 0))) { + DEBUG(0, ("eventlog_io_q_open_eventlog: unable to unmarshall EVENTLOG_Q_OPEN_EVENTLOG.\n")); + return False; + } + + r_u.status = _eventlog_open_eventlog(p, &q_u, &r_u); + + if (!(eventlog_io_r_open_eventlog("", &r_u, rdata, 0))) { + DEBUG(0, ("eventlog_io_r_open_eventlog: unable to marshall EVENTLOG_R_OPEN_EVENTLOG.\n")); + return False; + } + + return True; +} + +static BOOL api_eventlog_close_eventlog(pipes_struct *p) +{ + EVENTLOG_Q_CLOSE_EVENTLOG q_u; + EVENTLOG_R_CLOSE_EVENTLOG r_u; + + prs_struct *data = &p->in_data.data; + prs_struct *rdata = &p->out_data.rdata; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + if (!(eventlog_io_q_close_eventlog("", &q_u, data, 0))) { + DEBUG(0, ("eventlog_io_q_close_eventlog: unable to unmarshall EVENTLOG_Q_CLOSE_EVENTLOG.\n")); + return False; + } + + r_u.status = _eventlog_close_eventlog(p, &q_u, &r_u); + + if (!(eventlog_io_r_close_eventlog("", &r_u, rdata, 0))) { + DEBUG(0, ("eventlog_io_r_close_eventlog: unable to marshall EVENTLOG_R_CLOSE_EVENTLOG.\n")); + return False; + } + + return True; +} + +static BOOL api_eventlog_get_num_records(pipes_struct *p) +{ + EVENTLOG_Q_GET_NUM_RECORDS q_u; + EVENTLOG_R_GET_NUM_RECORDS r_u; + + prs_struct *data = &p->in_data.data; + prs_struct *rdata = &p->out_data.rdata; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + if (!(eventlog_io_q_get_num_records("", &q_u, data, 0))) { + DEBUG(0, ("eventlog_io_q_get_num_records: unable to unmarshall EVENTLOG_Q_GET_NUM_RECORDS.\n")); + return False; + } + + r_u.status = _eventlog_get_num_records(p, &q_u, &r_u); + + if (!(eventlog_io_r_get_num_records("", &r_u, rdata, 0))) { + DEBUG(0, ("eventlog_io_r_get_num_records: unable to marshall EVENTLOG_R_GET_NUM_RECORDS.\n")); + return False; + } + + return True; +} + +static BOOL api_eventlog_get_oldest_entry(pipes_struct *p) +{ + EVENTLOG_Q_GET_OLDEST_ENTRY q_u; + EVENTLOG_R_GET_OLDEST_ENTRY r_u; + + prs_struct *data = &p->in_data.data; + prs_struct *rdata = &p->out_data.rdata; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + if (!(eventlog_io_q_get_oldest_entry("", &q_u, data, 0))) { + DEBUG(0, ("eventlog_io_q_get_oldest_entry: unable to unmarshall EVENTLOG_Q_GET_OLDEST_ENTRY.\n")); + return False; + } + + r_u.status = _eventlog_get_oldest_entry(p, &q_u, &r_u); + + if (!(eventlog_io_r_get_oldest_entry("", &r_u, rdata, 0))) { + DEBUG(0, ("eventlog_io_r_get_oldest_entry: unable to marshall EVENTLOG_R_GET_OLDEST_ENTRY.\n")); + return False; + } + + return True; +} + +static BOOL api_eventlog_read_eventlog(pipes_struct *p) +{ + EVENTLOG_Q_READ_EVENTLOG q_u; + EVENTLOG_R_READ_EVENTLOG r_u; + + prs_struct *data = &p->in_data.data; + prs_struct *rdata = &p->out_data.rdata; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + if (!(eventlog_io_q_read_eventlog("", &q_u, data, 0))) { + DEBUG(0, ("eventlog_io_q_read_eventlog: unable to unmarshall EVENTLOG_Q_READ_EVENTLOG.\n")); + return False; + } + + r_u.status = _eventlog_read_eventlog(p, &q_u, &r_u); + + if (!(eventlog_io_r_read_eventlog("", &q_u, &r_u, rdata, 0))) { + DEBUG(0, ("eventlog_io_r_read_eventlog: unable to marshall EVENTLOG_R_READ_EVENTLOG.\n")); + return False; + } + + return True; +} + +static BOOL api_eventlog_clear_eventlog(pipes_struct *p) +{ + EVENTLOG_Q_CLEAR_EVENTLOG q_u; + EVENTLOG_R_CLEAR_EVENTLOG r_u; + + prs_struct *data = &p->in_data.data; + prs_struct *rdata = &p->out_data.rdata; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + if (!(eventlog_io_q_clear_eventlog("", &q_u, data, 0))) { + DEBUG(0, ("eventlog_io_q_clear_eventlog: unable to unmarshall EVENTLOG_Q_CLEAR_EVENTLOG.\n")); + return False; + } + + r_u.status = _eventlog_clear_eventlog(p, &q_u, &r_u); + + if (!(eventlog_io_r_clear_eventlog("", &r_u, rdata, 0))) { + DEBUG(0, ("eventlog_io_q_clear_eventlog: unable to marshall EVENTLOG_Q_CLEAR_EVENTLOG.\n")); + return False; + } + + return True; +} + +/* + \pipe\eventlog commands +*/ +struct api_struct api_eventlog_cmds[] = +{ + {"EVENTLOG_OPENEVENTLOG", EVENTLOG_OPENEVENTLOG, api_eventlog_open_eventlog }, + {"EVENTLOG_CLOSEVENTLOG", EVENTLOG_CLOSEEVENTLOG, api_eventlog_close_eventlog }, + {"EVENTLOG_GETNUMRECORDS", EVENTLOG_GETNUMRECORDS, api_eventlog_get_num_records }, + {"EVENTLOG_GETOLDESTENTRY", EVENTLOG_GETOLDESTENTRY, api_eventlog_get_oldest_entry }, + {"EVENTLOG_READEVENTLOG", EVENTLOG_READEVENTLOG, api_eventlog_read_eventlog }, + {"EVENTLOG_CLEAREVENTLOG", EVENTLOG_CLEAREVENTLOG, api_eventlog_clear_eventlog } +}; + +NTSTATUS rpc_eventlog_init(void) +{ + return rpc_pipe_register_commands(SMB_RPC_INTERFACE_VERSION, + "eventlog", "eventlog", api_eventlog_cmds, + sizeof(api_eventlog_cmds)/sizeof(struct api_struct)); +} + +void eventlog_get_pipe_fns(struct api_struct **fns, int *n_fns) +{ + *fns = api_eventlog_cmds; + *n_fns = sizeof(api_eventlog_cmds) / sizeof(struct api_struct); +} diff --git a/source/rpc_server/srv_eventlog_nt.c b/source/rpc_server/srv_eventlog_nt.c new file mode 100644 index 00000000000..7501434a134 --- /dev/null +++ b/source/rpc_server/srv_eventlog_nt.c @@ -0,0 +1,923 @@ +/* + * Unix SMB/CIFS implementation. + * RPC Pipe client / server routines + * Copyright (C) Marcin Krzysztof Porwit 2005. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "includes.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_RPC_SRV + +typedef struct eventlog_info +{ + /* for use by the \PIPE\eventlog policy */ + fstring source_log_file_name; + fstring source_server_name; + fstring handle_string; + uint32 num_records; + uint32 oldest_entry; +} Eventlog_info; + +static void free_eventlog_info(void *ptr) +{ + struct eventlog_info *info = (struct eventlog_info *)ptr; + memset(info->source_log_file_name, '0', sizeof(*(info->source_log_file_name))); + memset(info->source_server_name, '0', sizeof(*(info->source_server_name))); + memset(info->handle_string, '0', sizeof(*(info->handle_string))); + memset(info, 0, sizeof(*(info))); + SAFE_FREE(info); +} + +static Eventlog_info *find_eventlog_info_by_hnd(pipes_struct *p, + POLICY_HND *handle) +{ + Eventlog_info *info = NULL; + + if(!(find_policy_by_hnd(p,handle,(void **)&info))) + { + DEBUG(2,("find_eventlog_info_by_hnd: eventlog not found.\n")); + } + + return info; +} + +void policy_handle_to_string(POLICY_HND *handle, fstring *dest) +{ + memset(dest, 0, sizeof(*dest)); + snprintf((char *)dest, sizeof(*dest), "%08X-%08X-%04X-%04X-%02X%02X%02X%02X%02X", + handle->data1, + handle->data2, + handle->data3, + handle->data4, + handle->data5[0], + handle->data5[1], + handle->data5[2], + handle->data5[3], + handle->data5[4]); +} + +/** + * Callout to open the specified event log + * + * smbrun calling convention -- + * INPUT: + * OUTPUT: the string "SUCCESS" if the command succeeded + * no such string if there was a failure. + */ +static BOOL _eventlog_open_eventlog_hook(Eventlog_info *info) +{ + char *cmd = lp_eventlog_open_cmd(); + char **qlines; + pstring command; + int numlines = 0; + int ret; + int fd = -1; + + if(cmd == NULL || strlen(cmd) == 0) + { + DEBUG(0, ("Must define an \"eventlog open command\" entry in the config.\n")); + return False; + } + + memset(command, 0, sizeof(command)); + slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\"", + cmd, + info->source_log_file_name, + info->handle_string); + + DEBUG(10, ("Running [%s]\n", command)); + ret = smbrun(command, &fd); + DEBUGADD(10, ("returned [%d]\n", ret)); + + if(ret != 0) + { + if(fd != -1) + close(fd); + return False; + } + + qlines = fd_lines_load(fd, &numlines); + DEBUGADD(10, ("Lines returned = [%d]\n", numlines)); + close(fd); + + if(numlines) + { + DEBUGADD(10, ("Line[0] = [%s]\n", qlines[0])); + if(0 == strncmp(qlines[0], "SUCCESS", strlen("SUCCESS"))) + { + DEBUGADD(10, ("Able to open [%s].\n", info->source_log_file_name)); + file_lines_free(qlines); + return True; + } + } + + file_lines_free(qlines); + return False; +} + +WERROR _eventlog_open_eventlog(pipes_struct *p, + EVENTLOG_Q_OPEN_EVENTLOG *q_u, + EVENTLOG_R_OPEN_EVENTLOG *r_u) +{ + Eventlog_info *info = NULL; + + if(!q_u || !r_u) + return WERR_NOMEM; + + if((info = SMB_MALLOC_P(Eventlog_info)) == NULL) + return WERR_NOMEM; + + ZERO_STRUCTP(info); + + if(q_u->servername_ptr != 0) + { + unistr2_to_ascii(info->source_server_name, &(q_u->servername), sizeof(info->source_server_name)); + } + else + { + /* if servername == NULL, use the local computer */ + fstrcpy(info->source_server_name, global_myname()); + } + DEBUG(10, ("_eventlog_open_eventlog: Using [%s] as the server name.\n", info->source_server_name)); + + if(q_u->sourcename_ptr != 0) + { + unistr2_to_ascii(info->source_log_file_name, &(q_u->sourcename), sizeof(info->source_log_file_name)); + } + else + { + /* if sourcename == NULL, default to "Application" log */ + fstrcpy(info->source_log_file_name, "Application"); + } + DEBUG(10, ("_eventlog_open_eventlog: Using [%s] as the source log file.\n", info->source_log_file_name)); + + if(!create_policy_hnd(p, &(r_u->handle), free_eventlog_info, (void *)info)) + return WERR_NOMEM; + + policy_handle_to_string(&r_u->handle, &info->handle_string); + + if(!(_eventlog_open_eventlog_hook(info))) + return WERR_BADFILE; + + return WERR_OK; +} +/** + * Callout to get the number of records in the specified event log + * + * smbrun calling convention -- + * INPUT: + * OUTPUT: A single line with a single integer containing the number of + * entries in the log. If there are no entries in the log, return 0. + */ +static BOOL _eventlog_get_num_records_hook(Eventlog_info *info) +{ + char *cmd = lp_eventlog_num_records_cmd(); + char **qlines; + pstring command; + int numlines = 0; + int ret; + int fd = -1; + + if(cmd == NULL || strlen(cmd) == 0) + { + DEBUG(0, ("Must define an \"eventlog num records command\" entry in the config.\n")); + return False; + } + + memset(command, 0, sizeof(command)); + slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\"", + cmd, + info->source_log_file_name, + info->handle_string); + + DEBUG(10, ("Running [%s]\n", command)); + ret = smbrun(command, &fd); + DEBUGADD(10, ("returned [%d]\n", ret)); + + if(ret != 0) + { + if(fd != -1) + close(fd); + return False; + } + + qlines = fd_lines_load(fd, &numlines); + DEBUGADD(10, ("Lines returned = [%d]\n", numlines)); + close(fd); + + if(numlines) + { + DEBUGADD(10, ("Line[0] = [%s]\n", qlines[0])); + sscanf(qlines[0], "%d", &(info->num_records)); + file_lines_free(qlines); + return True; + } + + file_lines_free(qlines); + return False; +} + +WERROR _eventlog_get_num_records(pipes_struct *p, + EVENTLOG_Q_GET_NUM_RECORDS *q_u, + EVENTLOG_R_GET_NUM_RECORDS *r_u) +{ + Eventlog_info *info = NULL; + POLICY_HND *handle = NULL; + + if(!q_u || !r_u) + return WERR_NOMEM; + + handle = &(q_u->handle); + info = find_eventlog_info_by_hnd(p, handle); + + if(!(_eventlog_get_num_records_hook(info))) + return WERR_BADFILE; + + r_u->num_records = info->num_records; + + return WERR_OK; +} +/** + * Callout to find the oldest record in the log + * + * smbrun calling convention -- + * INPUT: + * OUTPUT: If there are entries in the event log, the index of the + * oldest entry. Must be 1 or greater. + * If there are no entries in the log, returns a 0 + */ +static BOOL _eventlog_get_oldest_entry_hook(Eventlog_info *info) +{ + char *cmd = lp_eventlog_oldest_record_cmd(); + char **qlines; + pstring command; + int numlines = 0; + int ret; + int fd = -1; + + if(cmd == NULL || strlen(cmd) == 0) + { + DEBUG(0, ("Must define an \"eventlog oldest record command\" entry in the config.\n")); + return False; + } + + memset(command, 0, sizeof(command)); + slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\"", + cmd, + info->source_log_file_name, + info->handle_string); + + DEBUG(10, ("Running [%s]\n", command)); + ret = smbrun(command, &fd); + DEBUGADD(10, ("returned [%d]\n", ret)); + + if(ret != 0) + { + if(fd != -1) + close(fd); + return False; + } + + qlines = fd_lines_load(fd, &numlines); + DEBUGADD(10, ("Lines returned = [%d]\n", numlines)); + close(fd); + + if(numlines) + { + DEBUGADD(10, ("Line[0] = [%s]\n", qlines[0])); + sscanf(qlines[0], "%d", &(info->oldest_entry)); + file_lines_free(qlines); + return True; + } + + file_lines_free(qlines); + return False; +} + +WERROR _eventlog_get_oldest_entry(pipes_struct *p, + EVENTLOG_Q_GET_OLDEST_ENTRY *q_u, + EVENTLOG_R_GET_OLDEST_ENTRY *r_u) +{ + Eventlog_info *info = NULL; + POLICY_HND *handle = NULL; + + if(!q_u || !r_u) + return WERR_NOMEM; + + handle = &(q_u->handle); + info = find_eventlog_info_by_hnd(p, handle); + + if(!(_eventlog_get_oldest_entry_hook(info))) + return WERR_BADFILE; + + r_u->oldest_entry = info->oldest_entry; + + return WERR_OK; +} + +/** + * Callout to close the specified event log + * + * smbrun calling convention -- + * INPUT: + * OUTPUT: the string "SUCCESS" if the command succeeded + * no such string if there was a failure. + */ +static BOOL _eventlog_close_eventlog_hook(Eventlog_info *info) +{ + char *cmd = lp_eventlog_close_cmd(); + char **qlines; + pstring command; + int numlines = 0; + int ret; + int fd = -1; + + if(cmd == NULL || strlen(cmd) == 0) + { + DEBUG(0, ("Must define an \"eventlog close command\" entry in the config.\n")); + return False; + } + + memset(command, 0, sizeof(command)); + slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\"", + cmd, + info->source_log_file_name, + info->handle_string); + + DEBUG(10, ("Running [%s]\n", command)); + ret = smbrun(command, &fd); + DEBUGADD(10, ("returned [%d]\n", ret)); + + if(ret != 0) + { + if(fd != -1) + close(fd); + return False; + } + + qlines = fd_lines_load(fd, &numlines); + DEBUGADD(10, ("Lines returned = [%d]\n", numlines)); + close(fd); + + if(numlines) + { + DEBUGADD(10, ("Line[0] = [%s]\n", qlines[0])); + if(0 == strncmp(qlines[0], "SUCCESS", strlen("SUCCESS"))) + { + DEBUGADD(10, ("Able to close [%s].\n", info->source_log_file_name)); + file_lines_free(qlines); + return True; + } + } + + file_lines_free(qlines); + return False; +} + +WERROR _eventlog_close_eventlog(pipes_struct *p, + EVENTLOG_Q_CLOSE_EVENTLOG *q_u, + EVENTLOG_R_CLOSE_EVENTLOG *r_u) +{ + Eventlog_info *info = NULL; + POLICY_HND *handle; + + if(!q_u || !r_u) + return WERR_NOMEM; + + handle = &(q_u->handle); + + info = find_eventlog_info_by_hnd(p, handle); + if(!(_eventlog_close_eventlog_hook(info))) + return WERR_BADFILE; + + if(!(close_policy_hnd(p, handle))) + { + /* WERR_NOMEM is probably not the correct error, but until I figure out a better + one it will have to do */ + return WERR_NOMEM; + } + + return WERR_OK; +} + +static BOOL _eventlog_read_parse_line(char *line, Eventlog_entry *entry) +{ + char *start = NULL, *stop = NULL; + pstring temp; + int temp_len = 0, i; + + start = line; + + if(start == NULL || strlen(start) == 0) + return False; + if(!(stop = strchr(line, ':'))) + return False; + + DEBUG(6, ("_eventlog_read_parse_line: trying to parse [%s].\n", line)); + + if(0 == strncmp(start, "LEN", stop - start)) + { + /* This will get recomputed later anyway -- probably not necessary */ + entry->record.length = atoi(stop + 1); + } + else if(0 == strncmp(start, "RS1", stop - start)) + { + /* For now all these reserved entries seem to have the same value, + which can be hardcoded to int(1699505740) for now */ + entry->record.reserved1 = atoi(stop + 1); + } + else if(0 == strncmp(start, "RCN", stop - start)) + { + entry->record.record_number = atoi(stop + 1); + } + else if(0 == strncmp(start, "TMG", stop - start)) + { + entry->record.time_generated = atoi(stop + 1); + } + else if(0 == strncmp(start, "TMW", stop - start)) + { + entry->record.time_written = atoi(stop + 1); + } + else if(0 == strncmp(start, "EID", stop - start)) + { + entry->record.event_id = atoi(stop + 1); + } + else if(0 == strncmp(start, "ETP", stop - start)) + { + if(strstr(start, "ERROR")) + { + entry->record.event_type = EVENTLOG_ERROR_TYPE; + } + else if(strstr(start, "WARNING")) + { + entry->record.event_type = EVENTLOG_WARNING_TYPE; + } + else if(strstr(start, "INFO")) + { + entry->record.event_type = EVENTLOG_INFORMATION_TYPE; + } + else if(strstr(start, "AUDIT_SUCCESS")) + { + entry->record.event_type = EVENTLOG_AUDIT_SUCCESS; + } + else if(strstr(start, "AUDIT_FAILURE")) + { + entry->record.event_type = EVENTLOG_AUDIT_FAILURE; + } + else if(strstr(start, "SUCCESS")) + { + entry->record.event_type = EVENTLOG_SUCCESS; + } + else + { + /* some other eventlog type -- currently not defined in MSDN docs, so error out */ + return False; + } + } +/* + else if(0 == strncmp(start, "NST", stop - start)) + { + entry->record.num_strings = atoi(stop + 1); + } +*/ + else if(0 == strncmp(start, "ECT", stop - start)) + { + entry->record.event_category = atoi(stop + 1); + } + else if(0 == strncmp(start, "RS2", stop - start)) + { + entry->record.reserved2 = atoi(stop + 1); + } + else if(0 == strncmp(start, "CRN", stop - start)) + { + entry->record.closing_record_number = atoi(stop + 1); + } + else if(0 == strncmp(start, "USL", stop - start)) + { + entry->record.user_sid_length = atoi(stop + 1); + } + else if(0 == strncmp(start, "SRC", stop - start)) + { + memset(temp, 0, sizeof(temp)); + sscanf(stop+1, "%s", temp); + temp_len = strlen(temp); + rpcstr_push((void *)(entry->data_record.source_name), temp, + sizeof(entry->data_record.source_name), STR_TERMINATE); + entry->data_record.source_name_len = (strlen_w(entry->data_record.source_name)* 2) + 2; + } + else if(0 == strncmp(start, "SRN", stop - start)) + { + memset(temp, 0, sizeof(temp)); + sscanf(stop+1, "%s", temp); + temp_len = strlen(temp); + rpcstr_push((void *)(entry->data_record.computer_name), temp, + sizeof(entry->data_record.computer_name), STR_TERMINATE); + entry->data_record.computer_name_len = (strlen_w(entry->data_record.computer_name)* 2) + 2; + } + else if(0 == strncmp(start, "SID", stop - start)) + { + memset(temp, 0, sizeof(temp)); + sscanf(stop+1, "%s", temp); + temp_len = strlen(temp); + rpcstr_push((void *)(entry->data_record.sid), temp, + sizeof(entry->data_record.sid), STR_TERMINATE); + entry->record.user_sid_length = (strlen_w(entry->data_record.sid) * 2) + 2; + } + else if(0 == strncmp(start, "STR", stop - start)) + { + /* skip past initial ":" */ + stop++; + /* now skip any other leading whitespace */ + while(isspace(stop[0])) + stop++; + temp_len = strlen(stop); + memset(temp, 0, sizeof(temp)); + strncpy(temp, stop, temp_len); + rpcstr_push((void *)(entry->data_record.strings + entry->data_record.strings_len), + temp, + sizeof(entry->data_record.strings) - entry->data_record.strings_len, + STR_TERMINATE); + entry->data_record.strings_len += temp_len + 1; + fprintf(stderr, "Dumping strings:\n"); + for(i = 0; i < entry->data_record.strings_len; i++) + { + fputc((char)entry->data_record.strings[i], stderr); + } + fprintf(stderr, "\nDone\n"); + entry->record.num_strings++; + } + else if(0 == strncmp(start, "DAT", stop - start)) + { + /* Now that we're done processing the STR data, adjust the length to account for + unicode, then proceed with the DAT data. */ + entry->data_record.strings_len *= 2; + /* skip past initial ":" */ + stop++; + /* now skip any other leading whitespace */ + while(isspace(stop[0])) + stop++; + memset(temp, 0, sizeof(temp)); + temp_len = strlen(stop); + strncpy(temp, stop, temp_len); + rpcstr_push((void *)(entry->data_record.user_data), temp, + sizeof(entry->data_record.user_data), STR_TERMINATE); + entry->data_record.user_data_len = (strlen_w((const smb_ucs2_t *)entry->data_record.user_data) * 2) + 2; + } + else + { + /* some other eventlog entry -- not implemented, so dropping on the floor */ + DEBUG(10, ("Unknown entry [%s]. Ignoring.\n", line)); + /* For now return true so that we can keep on parsing this mess. Eventually + we will return False here. */ + return True; + } + return True; +} +/** + * Callout to read entries from the specified event log + * + * smbrun calling convention -- + * INPUT: + * where direction is either "forward" or "backward", the starting record is somewhere + * between the oldest_record and oldest_record+num_records, and the buffer size is the + * maximum size of the buffer that the client can accomodate. + * OUTPUT: A buffer containing a set of entries, one to a line, of the format: + * line type:line data + * These are the allowed line types: + * RS1:(uint32) - reserved. All M$ entries seem to have int(1699505740) for now + * RCN:(uint32) - record number of the record, however it may be calculated by the script + * TMG:(uint32) - time generated, seconds since January 1, 1970, 0000 UTC + * TMW:(uint32) - time written, seconds since January 1, 1970, 0000 UTC + * EID:(uint32) - eventlog source defined event identifier. If there's a stringfile for the event, it is an index into that + * ETP:(uint16) - eventlog type - one of ERROR, WARNING, INFO, AUDIT_SUCCESS, AUDIT_FAILURE + * ECT:(uint16) - event category - depends on the eventlog generator... + * RS2:(uint16) - reserved, make it 0000 + * CRN:(uint32) - reserved, make it 00000000 for now + * USL:(uint32) - user SID length. No sid? Make this 0. Must match SID below + * SRC:[(uint8)] - Name of the source, for example ccPwdSvc, in hex bytes. Can not be multiline. + * SRN:[(uint8)] - Name of the computer on which this is generated, the short hostname usually. + * SID:[(uint8)] - User sid if one exists. Must be present even if there is no SID. + * STR:[(uint8)] - String data. One string per line. Multiple strings can be specified using consecutive "STR" lines, + * up to a total aggregate string length of 1024 characters. + * DAT:[(uint8)] - The user-defined data portion of the event log. Can not be multiple lines. + */ +static BOOL _eventlog_read_eventlog_hook(Eventlog_info *info, Eventlog_entry *entry, const char *direction, int starting_record, int buffer_size, BOOL *eof) +{ + char *cmd = lp_eventlog_read_cmd(); + char **qlines; + pstring command; + int numlines = 0; + int ret; + int fd = -1; + int i; + + if(info == NULL) + return False; + + if(cmd == NULL || strlen(cmd) == 0) + { + DEBUG(0, ("Must define an \"eventlog read command\" entry in the config.\n")); + return False; + } + + slprintf(command, sizeof(command)-1, "%s \"%s\" %s %d %d \"%s\"", + cmd, + info->source_log_file_name, + direction, + starting_record, + buffer_size, + info->handle_string); + + DEBUG(10, ("Running [%s]\n", command)); + ret = smbrun(command, &fd); + DEBUGADD(10, ("returned [%d]\n", ret)); + + if(ret != 0) + { + if(fd != -1) + close(fd); + return False; + } + + qlines = fd_lines_load(fd, &numlines); + DEBUGADD(10, ("Lines returned = [%d]\n", numlines)); + close(fd); + + if(numlines) + { + for(i = 0; i < numlines; i++) + { + DEBUGADD(10, ("Line[%d] = %s\n", i, qlines[i])); + _eventlog_read_parse_line(qlines[i], entry); + } + file_lines_free(qlines); + return True; + } + else + *eof = True; + + file_lines_free(qlines); + return False; +} + +static BOOL _eventlog_read_prepare_data_buffer(prs_struct *ps, + EVENTLOG_Q_READ_EVENTLOG *q_u, + EVENTLOG_R_READ_EVENTLOG *r_u, + Eventlog_entry *entry) +{ + uint8 *offset; + Eventlog_entry *new = NULL, *insert_point = NULL; + + new = PRS_ALLOC_MEM(ps, Eventlog_entry, 1); + if(new == NULL) + return False; + + entry->data_record.sid_padding = ((4 - ((entry->data_record.source_name_len + + entry->data_record.computer_name_len) % 4)) %4); + entry->data_record.data_padding = (4 - ((entry->data_record.strings_len + + entry->data_record.user_data_len) % 4)) % 4; + entry->record.length = sizeof(Eventlog_record); + entry->record.length += entry->data_record.source_name_len; + entry->record.length += entry->data_record.computer_name_len; + if(entry->record.user_sid_length == 0) + { + /* Should not pad to a DWORD boundary for writing out the sid if there is + no SID, so just propagate the padding to pad the data */ + entry->data_record.data_padding += entry->data_record.sid_padding; + entry->data_record.sid_padding = 0; + } + DEBUG(10, ("sid_padding is [%d].\n", entry->data_record.sid_padding)); + DEBUG(10, ("data_padding is [%d].\n", entry->data_record.data_padding)); + + entry->record.length += entry->data_record.sid_padding; + entry->record.length += entry->record.user_sid_length; + entry->record.length += entry->data_record.strings_len; + entry->record.length += entry->data_record.user_data_len; + entry->record.length += entry->data_record.data_padding; + /* need another copy of length at the end of the data */ + entry->record.length += sizeof(entry->record.length); + DEBUG(10, ("entry->record.length is [%d].\n", entry->record.length)); + entry->data = PRS_ALLOC_MEM(ps, uint8, entry->record.length - sizeof(Eventlog_record) - sizeof(entry->record.length)); + if(entry->data == NULL) + return False; + offset = entry->data; + memcpy(offset, &(entry->data_record.source_name), entry->data_record.source_name_len); + offset += entry->data_record.source_name_len; + memcpy(offset, &(entry->data_record.computer_name), entry->data_record.computer_name_len); + offset += entry->data_record.computer_name_len; + /* SID needs to be DWORD-aligned */ + offset += entry->data_record.sid_padding; + entry->record.user_sid_offset = sizeof(Eventlog_record) + (offset - entry->data); + memcpy(offset, &(entry->data_record.sid), entry->record.user_sid_length); + offset += entry->record.user_sid_length; + /* Now do the strings */ + entry->record.string_offset = sizeof(Eventlog_record) + (offset - entry->data); + memcpy(offset, &(entry->data_record.strings), entry->data_record.strings_len); + offset += entry->data_record.strings_len; + /* Now do the data */ + entry->record.data_length = entry->data_record.user_data_len; + entry->record.data_offset = sizeof(Eventlog_record) + (offset - entry->data); + memcpy(offset, &(entry->data_record.user_data), entry->data_record.user_data_len); + offset += entry->data_record.user_data_len; + /* Now that we've massaged the current entry, copy it into the new entry and add it + to end of the list */ + insert_point=r_u->entry; + + if (NULL == insert_point) + { + r_u->entry = new; + new->next = NULL; + } + else + { + while ((NULL != insert_point->next)) + { + insert_point=insert_point->next; + } + new->next = NULL; + insert_point->next = new; + } + + memcpy(&(new->record), &entry->record, sizeof(Eventlog_record)); + memcpy(&(new->data_record), &entry->data_record, sizeof(Eventlog_data_record)); + new->data = entry->data; + + r_u->num_records++; + r_u->num_bytes_in_resp += entry->record.length; + + return True; +} + +WERROR _eventlog_read_eventlog(pipes_struct *p, + EVENTLOG_Q_READ_EVENTLOG *q_u, + EVENTLOG_R_READ_EVENTLOG *r_u) +{ + Eventlog_info *info = NULL; + POLICY_HND *handle; + Eventlog_entry entry; + BOOL eof = False; + const char *direction = ""; + int starting_record; + prs_struct *ps; + + if(!q_u || !r_u) + return WERR_NOMEM; + + handle = &(q_u->handle); + info = find_eventlog_info_by_hnd(p, handle); + ps = &p->out_data.rdata; + /* Rather than checking the EVENTLOG_SEQUENTIAL_READ/EVENTLOG_SEEK_READ flags, + we'll just go to the offset specified in the request, or the oldest entry + if no offset is specified */ + if(q_u->offset > 0) + starting_record = q_u->offset; + else + starting_record = info->oldest_entry; + if(q_u->flags & EVENTLOG_FORWARDS_READ) + direction = "forward"; + else if(q_u->flags & EVENTLOG_BACKWARDS_READ) + direction = "backward"; + + do + { + ZERO_STRUCT(entry); + if(!(_eventlog_read_eventlog_hook(info, &entry, direction, starting_record, q_u->max_read_size, &eof))) + { + if(eof == False) + return WERR_NOMEM; + } + if(eof == False) + { + /* only if the read hook returned data */ + if(!(_eventlog_read_prepare_data_buffer(ps, q_u, r_u, &entry))) + return WERR_NOMEM; + DEBUG(10, ("_eventlog_read_eventlog: read [%d] bytes out of a max of [%d].\n", + r_u->num_bytes_in_resp, + q_u->max_read_size)); + } + } while((r_u->num_bytes_in_resp <= q_u->max_read_size) && (eof != True)); + + return WERR_OK; +} +/** + * Callout to clear (and optionally backup) a specified event log + * + * smbrun calling convention -- + * INPUT: + * OUTPUT: A single line with the string "SUCCESS" if the command succeeded. + * Otherwise it is assumed to have failed + * + * INPUT: + * OUTPUT: A single line with the string "SUCCESS" if the command succeeded. + * Otherwise it is assumed to have failed + * The given log is copied to that location on the server. See comments for + * eventlog_io_q_clear_eventlog for info about odd file name behavior + */ +static BOOL _eventlog_clear_eventlog_hook(Eventlog_info *info, + pstring backup_file_name) +{ + char *cmd = lp_eventlog_clear_cmd(); + char **qlines; + pstring command; + int numlines = 0; + int ret; + int fd = -1; + + if(cmd == NULL || strlen(cmd) == 0) + { + DEBUG(0, ("Must define an \"eventlog clear command\" entry in the config.\n")); + return False; + } + + memset(command, 0, sizeof(command)); + if(strlen(backup_file_name) > 0) + slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\"", + cmd, + info->source_log_file_name, + backup_file_name, + info->handle_string); + else + slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\"", + cmd, + info->source_log_file_name, + info->handle_string); + + DEBUG(10, ("Running [%s]\n", command)); + ret = smbrun(command, &fd); + DEBUGADD(10, ("returned [%d]\n", ret)); + + if(ret != 0) + { + if(fd != -1) + close(fd); + return False; + } + + qlines = fd_lines_load(fd, &numlines); + DEBUGADD(10, ("Lines returned = [%d]\n", numlines)); + close(fd); + + if(numlines) + { + DEBUGADD(10, ("Line[0] = [%s]\n", qlines[0])); + if(0 == strncmp(qlines[0], "SUCCESS", strlen("SUCCESS"))) + { + DEBUGADD(10, ("Able to clear [%s].\n", info->source_log_file_name)); + file_lines_free(qlines); + return True; + } + } + + file_lines_free(qlines); + return False; +} + +WERROR _eventlog_clear_eventlog(pipes_struct *p, + EVENTLOG_Q_CLEAR_EVENTLOG *q_u, + EVENTLOG_R_CLEAR_EVENTLOG *r_u) +{ + Eventlog_info *info = NULL; + pstring backup_file_name; + POLICY_HND *handle = NULL; + + if(!q_u || !r_u) + return WERR_NOMEM; + + handle = &(q_u->handle); + info = find_eventlog_info_by_hnd(p, handle); + memset(backup_file_name, 0, sizeof(backup_file_name)); + + if(q_u->backup_file_ptr != 0) + { + unistr2_to_ascii(backup_file_name, &(q_u->backup_file), sizeof(backup_file_name)); + DEBUG(10, ("_eventlog_clear_eventlog: Using [%s] as the backup file name for log [%s].", + backup_file_name, + info->source_log_file_name)); + } + else + { + /* if backup_file == NULL, do not back up the log before clearing it */ + DEBUG(10, ("_eventlog_clear_eventlog: clearing [%s] log without making a backup.", + info->source_log_file_name)); + } + + if(!(_eventlog_clear_eventlog_hook(info, backup_file_name))) + return WERR_BADFILE; + + return WERR_OK; +} diff --git a/source/rpc_server/srv_lsa_ds_nt.c b/source/rpc_server/srv_lsa_ds_nt.c index d0b7a299be3..b410af8dedf 100644 --- a/source/rpc_server/srv_lsa_ds_nt.c +++ b/source/rpc_server/srv_lsa_ds_nt.c @@ -46,6 +46,9 @@ static NTSTATUS fill_dsrole_dominfo_basic(TALLOC_CTX *ctx, DSROLE_PRIMARY_DOMAIN return NT_STATUS_NO_MEMORY; } + get_mydnsdomname(dnsdomain); + strlower_m(dnsdomain); + switch ( lp_server_role() ) { case ROLE_STANDALONE: basic->machine_role = DSROLE_STANDALONE_SRV; @@ -58,16 +61,12 @@ static NTSTATUS fill_dsrole_dominfo_basic(TALLOC_CTX *ctx, DSROLE_PRIMARY_DOMAIN basic->flags = DSROLE_PRIMARY_DS_RUNNING|DSROLE_PRIMARY_DS_MIXED_MODE; if ( secrets_fetch_domain_guid( lp_workgroup(), &basic->domain_guid ) ) basic->flags |= DSROLE_PRIMARY_DOMAIN_GUID_PRESENT; - get_mydnsdomname(dnsdomain); - strlower_m(dnsdomain); break; case ROLE_DOMAIN_PDC: basic->machine_role = DSROLE_PDC; basic->flags = DSROLE_PRIMARY_DS_RUNNING|DSROLE_PRIMARY_DS_MIXED_MODE; if ( secrets_fetch_domain_guid( lp_workgroup(), &basic->domain_guid ) ) basic->flags |= DSROLE_PRIMARY_DOMAIN_GUID_PRESENT; - get_mydnsdomname(dnsdomain); - strlower_m(dnsdomain); break; } diff --git a/source/rpc_server/srv_lsa_nt.c b/source/rpc_server/srv_lsa_nt.c index 7ea35a91faf..5e949f0e63f 100644 --- a/source/rpc_server/srv_lsa_nt.c +++ b/source/rpc_server/srv_lsa_nt.c @@ -314,8 +314,6 @@ static void init_reply_lookup_sids(LSA_R_LOOKUP_SIDS *r_l, static NTSTATUS lsa_get_generic_sd(TALLOC_CTX *mem_ctx, SEC_DESC **sd, size_t *sd_size) { - extern DOM_SID global_sid_World; - extern DOM_SID global_sid_Builtin; DOM_SID local_adm_sid; DOM_SID adm_sid; @@ -523,6 +521,7 @@ NTSTATUS _lsa_enum_trust_dom(pipes_struct *p, LSA_Q_ENUM_TRUST_DOM *q_u, LSA_R_E } /* set up the lsa_enum_trust_dom response */ + init_r_enum_trust_dom(p->mem_ctx, r_u, enum_context, max_num_domains, num_domains, trust_doms); return r_u->status; @@ -1337,7 +1336,7 @@ NTSTATUS _lsa_add_acct_rights(pipes_struct *p, LSA_Q_ADD_ACCT_RIGHTS *q_u, LSA_R int i = 0; DOM_SID sid; fstring privname; - UNISTR2_ARRAY *uni_privnames = &q_u->rights; + UNISTR4_ARRAY *uni_privnames = q_u->rights; struct current_user user; @@ -1368,11 +1367,16 @@ NTSTATUS _lsa_add_acct_rights(pipes_struct *p, LSA_Q_ADD_ACCT_RIGHTS *q_u, LSA_R } for ( i=0; icount; i++ ) { - unistr2_to_ascii( privname, &uni_privnames->strings[i].string, sizeof(fstring)-1 ); - + UNISTR4 *uni4_str = &uni_privnames->strings[i]; + /* only try to add non-null strings */ + + if ( !uni4_str->string ) + continue; + + rpcstr_pull( privname, uni4_str->string->buffer, sizeof(privname), -1, STR_TERMINATE ); - if ( *privname && !grant_privilege_by_name( &sid, privname ) ) { + if ( !grant_privilege_by_name( &sid, privname ) ) { DEBUG(2,("_lsa_add_acct_rights: Failed to add privilege [%s]\n", privname )); return NT_STATUS_NO_SUCH_PRIVILEGE; } @@ -1390,7 +1394,7 @@ NTSTATUS _lsa_remove_acct_rights(pipes_struct *p, LSA_Q_REMOVE_ACCT_RIGHTS *q_u, int i = 0; DOM_SID sid; fstring privname; - UNISTR2_ARRAY *uni_privnames = &q_u->rights; + UNISTR4_ARRAY *uni_privnames = q_u->rights; struct current_user user; @@ -1425,11 +1429,16 @@ NTSTATUS _lsa_remove_acct_rights(pipes_struct *p, LSA_Q_REMOVE_ACCT_RIGHTS *q_u, } for ( i=0; icount; i++ ) { - unistr2_to_ascii( privname, &uni_privnames->strings[i].string, sizeof(fstring)-1 ); - + UNISTR4 *uni4_str = &uni_privnames->strings[i]; + /* only try to add non-null strings */ + + if ( !uni4_str->string ) + continue; + + rpcstr_pull( privname, uni4_str->string->buffer, sizeof(privname), -1, STR_TERMINATE ); - if ( *privname && !revoke_privilege_by_name( &sid, privname ) ) { + if ( !revoke_privilege_by_name( &sid, privname ) ) { DEBUG(2,("_lsa_remove_acct_rights: Failed to revoke privilege [%s]\n", privname )); return NT_STATUS_NO_SUCH_PRIVILEGE; } @@ -1439,6 +1448,9 @@ NTSTATUS _lsa_remove_acct_rights(pipes_struct *p, LSA_Q_REMOVE_ACCT_RIGHTS *q_u, } +/*************************************************************************** + ***************************************************************************/ + 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; @@ -1478,6 +1490,9 @@ NTSTATUS _lsa_enum_acct_rights(pipes_struct *p, LSA_Q_ENUM_ACCT_RIGHTS *q_u, LSA } +/*************************************************************************** + ***************************************************************************/ + NTSTATUS _lsa_lookup_priv_value(pipes_struct *p, LSA_Q_LOOKUP_PRIV_VALUE *q_u, LSA_R_LOOKUP_PRIV_VALUE *r_u) { struct lsa_info *info = NULL; diff --git a/source/rpc_server/srv_netlog.c b/source/rpc_server/srv_netlog.c index 705b629732a..a45a7eebf6a 100644 --- a/source/rpc_server/srv_netlog.c +++ b/source/rpc_server/srv_netlog.c @@ -299,7 +299,7 @@ static BOOL api_net_logon_ctrl(pipes_struct *p) r_u.status = _net_logon_ctrl(p, &q_u, &r_u); if(!net_io_r_logon_ctrl("", &r_u, rdata, 0)) { - DEBUG(0,("net_reply_logon_ctrl2: Failed to marshall NET_R_LOGON_CTRL2.\n")); + DEBUG(0,("net_reply_logon_ctrl2: Failed to marshall NET_R_LOGON_CTRL.\n")); return False; } diff --git a/source/rpc_server/srv_netlog_nt.c b/source/rpc_server/srv_netlog_nt.c index 2bc0cf301e5..c8ffa18c5a7 100644 --- a/source/rpc_server/srv_netlog_nt.c +++ b/source/rpc_server/srv_netlog_nt.c @@ -26,6 +26,9 @@ #include "includes.h" +extern struct dcinfo last_dcinfo; +extern userdom_struct current_user_info; + #undef DBGC_CLASS #define DBGC_CLASS DBGC_RPC_SRV @@ -424,7 +427,6 @@ NTSTATUS _net_auth_2(pipes_struct *p, NET_Q_AUTH_2 *q_u, NET_R_AUTH_2 *r_u) init_net_r_auth_2(r_u, &srv_cred, &srv_flgs, status); if (NT_STATUS_IS_OK(status)) { - extern struct dcinfo last_dcinfo; last_dcinfo = p->dc; } @@ -575,7 +577,6 @@ NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON * fstring nt_username, nt_domain, nt_workstation; auth_usersupplied_info *user_info = NULL; auth_serversupplied_info *server_info = NULL; - extern userdom_struct current_user_info; SAM_ACCOUNT *sampw; struct auth_context *auth_context = NULL; diff --git a/source/rpc_server/srv_pipe.c b/source/rpc_server/srv_pipe.c index 01e91ce6c50..ee6c42bd88f 100644 --- a/source/rpc_server/srv_pipe.c +++ b/source/rpc_server/srv_pipe.c @@ -40,6 +40,9 @@ #include "includes.h" +extern struct pipe_id_info pipe_names[]; +extern struct current_user current_user; + #undef DBGC_CLASS #define DBGC_CLASS DBGC_RPC_SRV @@ -751,7 +754,6 @@ BOOL setup_fault_pdu(pipes_struct *p, NTSTATUS status) BOOL check_bind_req(struct pipes_struct *p, RPC_IFACE* abstract, RPC_IFACE* transfer, uint32 context_id) { - extern struct pipe_id_info pipe_names[]; char *pipe_name = p->name; int i=0; fstring pname; @@ -765,6 +767,7 @@ BOOL check_bind_req(struct pipes_struct *p, RPC_IFACE* abstract, for ( i=0; pipe_names[i].client_pipe; i++ ) { + DEBUG(10,("checking %s\n", pipe_names[i].client_pipe)); if ( strequal(pipe_names[i].client_pipe, pname) && (abstract->version == pipe_names[i].abstr_syntax.version) && (memcmp(&abstract->uuid, &pipe_names[i].abstr_syntax.uuid, sizeof(struct uuid)) == 0) @@ -1426,7 +1429,6 @@ struct current_user *get_current_user(struct current_user *user, pipes_struct *p if (p->ntlmssp_auth_validated) { memcpy(user, &p->pipe_user, sizeof(struct current_user)); } else { - extern struct current_user current_user; memcpy(user, ¤t_user, sizeof(struct current_user)); } @@ -1631,6 +1633,12 @@ void get_pipe_fns( int idx, struct api_struct **fns, int *n_fns ) case PI_NETDFS: netdfs_get_pipe_fns( &cmds, &n_cmds ); break; + case PI_SVCCTL: + svcctl_get_pipe_fns( &cmds, &n_cmds ); + break; + case PI_EVENTLOG: + eventlog_get_pipe_fns( &cmds, &n_cmds ); + break; #ifdef DEVELOPER case PI_ECHO: echo_get_pipe_fns( &cmds, &n_cmds ); diff --git a/source/rpc_server/srv_reg.c b/source/rpc_server/srv_reg.c index b780be0aff3..a90650c536d 100644 --- a/source/rpc_server/srv_reg.c +++ b/source/rpc_server/srv_reg.c @@ -63,8 +63,8 @@ static BOOL api_reg_close(pipes_struct *p) static BOOL api_reg_open_hklm(pipes_struct *p) { - REG_Q_OPEN_HKLM q_u; - REG_R_OPEN_HKLM r_u; + REG_Q_OPEN_HIVE q_u; + REG_R_OPEN_HIVE r_u; prs_struct *data = &p->in_data.data; prs_struct *rdata = &p->out_data.rdata; @@ -72,12 +72,12 @@ static BOOL api_reg_open_hklm(pipes_struct *p) ZERO_STRUCT(r_u); /* grab the reg open */ - if(!reg_io_q_open_hklm("", &q_u, data, 0)) + if(!reg_io_q_open_hive("", &q_u, data, 0)) return False; r_u.status = _reg_open_hklm(p, &q_u, &r_u); - if(!reg_io_r_open_hklm("", &r_u, rdata, 0)) + if(!reg_io_r_open_hive("", &r_u, rdata, 0)) return False; return True; @@ -89,8 +89,8 @@ static BOOL api_reg_open_hklm(pipes_struct *p) static BOOL api_reg_open_hku(pipes_struct *p) { - REG_Q_OPEN_HKU q_u; - REG_R_OPEN_HKU r_u; + REG_Q_OPEN_HIVE q_u; + REG_R_OPEN_HIVE r_u; prs_struct *data = &p->in_data.data; prs_struct *rdata = &p->out_data.rdata; @@ -98,12 +98,12 @@ static BOOL api_reg_open_hku(pipes_struct *p) ZERO_STRUCT(r_u); /* grab the reg open */ - if(!reg_io_q_open_hku("", &q_u, data, 0)) + if(!reg_io_q_open_hive("", &q_u, data, 0)) return False; r_u.status = _reg_open_hku(p, &q_u, &r_u); - if(!reg_io_r_open_hku("", &r_u, rdata, 0)) + if(!reg_io_r_open_hive("", &r_u, rdata, 0)) return False; return True; @@ -115,8 +115,8 @@ static BOOL api_reg_open_hku(pipes_struct *p) static BOOL api_reg_open_hkcr(pipes_struct *p) { - REG_Q_OPEN_HKCR q_u; - REG_R_OPEN_HKCR r_u; + REG_Q_OPEN_HIVE q_u; + REG_R_OPEN_HIVE r_u; prs_struct *data = &p->in_data.data; prs_struct *rdata = &p->out_data.rdata; @@ -124,12 +124,12 @@ static BOOL api_reg_open_hkcr(pipes_struct *p) ZERO_STRUCT(r_u); /* grab the reg open */ - if(!reg_io_q_open_hkcr("", &q_u, data, 0)) + if(!reg_io_q_open_hive("", &q_u, data, 0)) return False; r_u.status = _reg_open_hkcr(p, &q_u, &r_u); - if(!reg_io_r_open_hkcr("", &r_u, rdata, 0)) + if(!reg_io_r_open_hive("", &r_u, rdata, 0)) return False; return True; @@ -215,6 +215,32 @@ static BOOL api_reg_shutdown(pipes_struct *p) return True; } +/******************************************************************* + api_reg_shutdown_ex + ********************************************************************/ + +static BOOL api_reg_shutdown_ex(pipes_struct *p) +{ + REG_Q_SHUTDOWN_EX q_u; + REG_R_SHUTDOWN_EX r_u; + prs_struct *data = &p->in_data.data; + prs_struct *rdata = &p->out_data.rdata; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + /* grab the reg shutdown ex */ + if(!reg_io_q_shutdown_ex("", &q_u, data, 0)) + return False; + + r_u.status = _reg_shutdown_ex(p, &q_u, &r_u); + + if(!reg_io_r_shutdown_ex("", &r_u, rdata, 0)) + return False; + + return True; +} + /******************************************************************* api_reg_abort_shutdown ********************************************************************/ @@ -268,25 +294,25 @@ static BOOL api_reg_query_key(pipes_struct *p) } /******************************************************************* - api_reg_unknown_1a + api_reg_getversion ********************************************************************/ -static BOOL api_reg_unknown_1a(pipes_struct *p) +static BOOL api_reg_getversion(pipes_struct *p) { - REG_Q_UNKNOWN_1A q_u; - REG_R_UNKNOWN_1A r_u; + REG_Q_GETVERSION q_u; + REG_R_GETVERSION 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(!reg_io_q_unknown_1a("", &q_u, data, 0)) + if(!reg_io_q_getversion("", &q_u, data, 0)) return False; - r_u.status = _reg_unknown_1a(p, &q_u, &r_u); + r_u.status = _reg_getversion(p, &q_u, &r_u); - if(!reg_io_r_unknown_1a("", &r_u, rdata, 0)) + if(!reg_io_r_getversion("", &r_u, rdata, 0)) return False; return True; @@ -343,8 +369,31 @@ static BOOL api_reg_enum_value(pipes_struct *p) } /******************************************************************* - api_reg_save_key - ********************************************************************/ + ******************************************************************/ + +static BOOL api_reg_restore_key(pipes_struct *p) +{ + REG_Q_RESTORE_KEY q_u; + REG_R_RESTORE_KEY 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(!reg_io_q_restore_key("", &q_u, data, 0)) + return False; + + r_u.status = _reg_restore_key(p, &q_u, &r_u); + + if(!reg_io_r_restore_key("", &r_u, rdata, 0)) + return False; + + return True; +} + +/******************************************************************* + ******************************************************************/ static BOOL api_reg_save_key(pipes_struct *p) { @@ -383,9 +432,11 @@ static struct api_struct api_reg_cmds[] = { "REG_QUERY_KEY" , REG_QUERY_KEY , api_reg_query_key }, { "REG_INFO" , REG_INFO , api_reg_info }, { "REG_SHUTDOWN" , REG_SHUTDOWN , api_reg_shutdown }, + { "REG_SHUTDOWN_EX" , REG_SHUTDOWN_EX , api_reg_shutdown_ex }, { "REG_ABORT_SHUTDOWN" , REG_ABORT_SHUTDOWN , api_reg_abort_shutdown }, - { "REG_UNKNOWN_1A" , REG_UNKNOWN_1A , api_reg_unknown_1a }, - { "REG_SAVE_KEY" , REG_SAVE_KEY , api_reg_save_key } + { "REG_GETVERSION" , REG_GETVERSION , api_reg_getversion }, + { "REG_SAVE_KEY" , REG_SAVE_KEY , api_reg_save_key }, + { "REG_RESTORE_KEY" , REG_RESTORE_KEY , api_reg_restore_key } }; void reg_get_pipe_fns( struct api_struct **fns, int *n_fns ) diff --git a/source/rpc_server/srv_reg_nt.c b/source/rpc_server/srv_reg_nt.c index c11e0d59a05..f031a3213f2 100644 --- a/source/rpc_server/srv_reg_nt.c +++ b/source/rpc_server/srv_reg_nt.c @@ -5,7 +5,7 @@ * Copyright (C) Luke Kenneth Casson Leighton 1996-1997. * Copyright (C) Paul Ashton 1997. * Copyright (C) Jeremy Allison 2001. - * Copyright (C) Gerald Carter 2002. + * Copyright (C) Gerald Carter 2002-2005. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -291,7 +291,7 @@ WERROR _reg_close(pipes_struct *p, REG_Q_CLOSE *q_u, REG_R_CLOSE *r_u) /******************************************************************* ********************************************************************/ -WERROR _reg_open_hklm(pipes_struct *p, REG_Q_OPEN_HKLM *q_u, REG_R_OPEN_HKLM *r_u) +WERROR _reg_open_hklm(pipes_struct *p, REG_Q_OPEN_HIVE *q_u, REG_R_OPEN_HIVE *r_u) { return open_registry_key( p, &r_u->pol, NULL, KEY_HKLM, 0x0 ); } @@ -299,7 +299,7 @@ WERROR _reg_open_hklm(pipes_struct *p, REG_Q_OPEN_HKLM *q_u, REG_R_OPEN_HKLM *r_ /******************************************************************* ********************************************************************/ -WERROR _reg_open_hkcr(pipes_struct *p, REG_Q_OPEN_HKCR *q_u, REG_R_OPEN_HKCR *r_u) +WERROR _reg_open_hkcr(pipes_struct *p, REG_Q_OPEN_HIVE *q_u, REG_R_OPEN_HIVE *r_u) { return open_registry_key( p, &r_u->pol, NULL, KEY_HKCR, 0x0 ); } @@ -307,7 +307,7 @@ WERROR _reg_open_hkcr(pipes_struct *p, REG_Q_OPEN_HKCR *q_u, REG_R_OPEN_HKCR *r_ /******************************************************************* ********************************************************************/ -WERROR _reg_open_hku(pipes_struct *p, REG_Q_OPEN_HKU *q_u, REG_R_OPEN_HKU *r_u) +WERROR _reg_open_hku(pipes_struct *p, REG_Q_OPEN_HIVE *q_u, REG_R_OPEN_HIVE *r_u) { return open_registry_key( p, &r_u->pol, NULL, KEY_HKU, 0x0 ); } @@ -328,7 +328,7 @@ WERROR _reg_open_entry(pipes_struct *p, REG_Q_OPEN_ENTRY *q_u, REG_R_OPEN_ENTRY if ( !key ) return WERR_BADFID; /* This will be reported as an RPC fault anyway. */ - rpcstr_pull(name,q_u->uni_name.buffer,sizeof(name),q_u->uni_name.uni_str_len*2,0); + rpcstr_pull( name, q_u->name.string->buffer, sizeof(name), q_u->name.string->uni_str_len*2, 0 ); result = open_registry_key( p, &pol, key, name, 0x0 ); @@ -362,7 +362,7 @@ WERROR _reg_info(pipes_struct *p, REG_Q_INFO *q_u, REG_R_INFO *r_u) DEBUG(7,("_reg_info: policy key name = [%s]\n", regkey->name)); - rpcstr_pull(name, q_u->uni_type.buffer, sizeof(name), q_u->uni_type.uni_str_len*2, 0); + rpcstr_pull(name, q_u->name.string->buffer, sizeof(name), q_u->name.string->uni_str_len*2, 0); DEBUG(5,("reg_info: looking up value: [%s]\n", name)); @@ -439,7 +439,7 @@ WERROR _reg_info(pipes_struct *p, REG_Q_INFO *q_u, REG_R_INFO *r_u) out: - new_init_reg_r_info(q_u->ptr_buf, r_u, val, status); + init_reg_r_info(q_u->ptr_buf, r_u, val, status); regval_ctr_destroy( ®vals ); free_registry_value( val ); @@ -485,22 +485,22 @@ WERROR _reg_query_key(pipes_struct *p, REG_Q_QUERY_KEY *q_u, REG_R_QUERY_KEY *r_ /***************************************************************************** - Implementation of REG_UNKNOWN_1A + Implementation of REG_GETVERSION ****************************************************************************/ -WERROR _reg_unknown_1a(pipes_struct *p, REG_Q_UNKNOWN_1A *q_u, REG_R_UNKNOWN_1A *r_u) +WERROR _reg_getversion(pipes_struct *p, REG_Q_GETVERSION *q_u, REG_R_GETVERSION *r_u) { WERROR status = WERR_OK; REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol ); - DEBUG(5,("_reg_unknown_1a: Enter\n")); + DEBUG(5,("_reg_getversion: Enter\n")); if ( !regkey ) return WERR_BADFID; /* This will be reported as an RPC fault anyway. */ r_u->unknown = 0x00000005; /* seems to be consistent...no idea what it means */ - DEBUG(5,("_reg_unknown_1a: Exit\n")); + DEBUG(5,("_reg_getversion: Exit\n")); return status; } @@ -561,8 +561,7 @@ WERROR _reg_enum_value(pipes_struct *p, REG_Q_ENUM_VALUE *q_u, REG_R_ENUM_VALUE DEBUG(8,("_reg_enum_key: enumerating values for key [%s]\n", regkey->name)); - if ( !fetch_reg_values_specific( regkey, &val, q_u->val_index ) ) - { + if ( !fetch_reg_values_specific( regkey, &val, q_u->val_index ) ) { status = WERR_NO_MORE_ITEMS; goto done; } @@ -587,110 +586,190 @@ done: reg_shutdwon ********************************************************************/ +WERROR _reg_shutdown(pipes_struct *p, REG_Q_SHUTDOWN *q_u, REG_R_SHUTDOWN *r_u) +{ + REG_Q_SHUTDOWN_EX q_u_ex; + REG_R_SHUTDOWN_EX r_u_ex; + + /* copy fields (including stealing memory) */ + + q_u_ex.server = q_u->server; + q_u_ex.message = q_u->message; + q_u_ex.timeout = q_u->timeout; + q_u_ex.force = q_u->force; + q_u_ex.reboot = q_u->reboot; + q_u_ex.reason = 0x0; /* don't care for now */ + + /* thunk down to _reg_shutdown_ex() (just returns a status) */ + + return _reg_shutdown_ex( p, &q_u_ex, &r_u_ex ); +} + +/******************************************************************* + reg_shutdown_ex + ********************************************************************/ + #define SHUTDOWN_R_STRING "-r" #define SHUTDOWN_F_STRING "-f" -WERROR _reg_shutdown(pipes_struct *p, REG_Q_SHUTDOWN *q_u, REG_R_SHUTDOWN *r_u) +WERROR _reg_shutdown_ex(pipes_struct *p, REG_Q_SHUTDOWN_EX *q_u, REG_R_SHUTDOWN_EX *r_u) { - WERROR status = WERR_OK; pstring shutdown_script; - UNISTR2 unimsg = q_u->uni_msg; pstring message; pstring chkmsg; fstring timeout; + fstring reason; fstring r; fstring f; + int ret; + BOOL can_shutdown; + + pstrcpy(shutdown_script, lp_shutdown_script()); - /* message */ - rpcstr_pull (message, unimsg.buffer, sizeof(message), unimsg.uni_str_len*2,0); - /* security check */ + if ( !*shutdown_script ) + return WERR_ACCESS_DENIED; + + /* pull the message string and perform necessary sanity checks on it */ + + pstrcpy( message, "" ); + if ( q_u->message ) { + UNISTR2 *msg_string = q_u->message->string; + + rpcstr_pull( message, msg_string->buffer, sizeof(message), msg_string->uni_str_len*2, 0 ); + } alpha_strcpy (chkmsg, message, NULL, sizeof(message)); - /* timeout */ + fstr_sprintf(timeout, "%d", q_u->timeout); - /* reboot */ fstr_sprintf(r, (q_u->reboot) ? SHUTDOWN_R_STRING : ""); - /* force */ fstr_sprintf(f, (q_u->force) ? SHUTDOWN_F_STRING : ""); + fstr_sprintf( reason, "%d", q_u->reason ); - pstrcpy(shutdown_script, lp_shutdown_script()); + all_string_sub( shutdown_script, "%z", chkmsg, sizeof(shutdown_script) ); + all_string_sub( shutdown_script, "%t", timeout, sizeof(shutdown_script) ); + all_string_sub( shutdown_script, "%r", r, sizeof(shutdown_script) ); + all_string_sub( shutdown_script, "%f", f, sizeof(shutdown_script) ); + all_string_sub( shutdown_script, "%x", reason, sizeof(shutdown_script) ); + + can_shutdown = user_has_privileges( p->pipe_user.nt_user_token, &se_remote_shutdown ); + + /* IF someone has privs, run the shutdown script as root. OTHERWISE run it as not root + Take the error return from the script and provide it as the Windows return code. */ + + /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/ + + if ( can_shutdown ) + become_root(); - if(*shutdown_script) { - int shutdown_ret; - SE_PRIV se_shutdown = SE_REMOTE_SHUTDOWN; - BOOL can_shutdown; + ret = smbrun( shutdown_script, NULL ); - can_shutdown = user_has_privileges( p->pipe_user.nt_user_token, &se_shutdown ); + if ( can_shutdown ) + unbecome_root(); + + /********** END SeRemoteShutdownPrivilege BLOCK **********/ + + DEBUG(3,("_reg_shutdown_ex: Running the command `%s' gave %d\n", + shutdown_script, ret)); - /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/ - if ( can_shutdown ) - become_root(); - all_string_sub(shutdown_script, "%m", chkmsg, sizeof(shutdown_script)); - all_string_sub(shutdown_script, "%t", timeout, sizeof(shutdown_script)); - all_string_sub(shutdown_script, "%r", r, sizeof(shutdown_script)); - all_string_sub(shutdown_script, "%f", f, sizeof(shutdown_script)); - shutdown_ret = smbrun(shutdown_script,NULL); - DEBUG(3,("_reg_shutdown: Running the command `%s' gave %d\n",shutdown_script,shutdown_ret)); - if ( can_shutdown ) - unbecome_root(); - /********** END SeRemoteShutdownPrivilege BLOCK **********/ - } - return status; + return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED; } + + + /******************************************************************* reg_abort_shutdwon ********************************************************************/ WERROR _reg_abort_shutdown(pipes_struct *p, REG_Q_ABORT_SHUTDOWN *q_u, REG_R_ABORT_SHUTDOWN *r_u) { - WERROR status = WERR_OK; pstring abort_shutdown_script; + int ret; + BOOL can_shutdown; pstrcpy(abort_shutdown_script, lp_abort_shutdown_script()); - if(*abort_shutdown_script) { - int abort_shutdown_ret; - SE_PRIV se_shutdown = SE_REMOTE_SHUTDOWN; - BOOL can_shutdown; + if ( !*abort_shutdown_script ) + return WERR_ACCESS_DENIED; - can_shutdown = user_has_privileges( p->pipe_user.nt_user_token, &se_shutdown ); + can_shutdown = user_has_privileges( p->pipe_user.nt_user_token, &se_remote_shutdown ); - /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/ - if ( can_shutdown ) - become_root(); - abort_shutdown_ret = smbrun(abort_shutdown_script,NULL); - DEBUG(3,("_reg_abort_shutdown: Running the command `%s' gave %d\n",abort_shutdown_script,abort_shutdown_ret)); - if ( can_shutdown ) - unbecome_root(); - /********** END SeRemoteShutdownPrivilege BLOCK **********/ + /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/ + + if ( can_shutdown ) + become_root(); - } + ret = smbrun( abort_shutdown_script, NULL ); + + if ( can_shutdown ) + unbecome_root(); + + /********** END SeRemoteShutdownPrivilege BLOCK **********/ - return status; + DEBUG(3,("_reg_abort_shutdown: Running the command `%s' gave %d\n", + abort_shutdown_script, ret)); + + + return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED; +} + +/******************************************************************* + ********************************************************************/ + +WERROR _reg_restore_key(pipes_struct *p, REG_Q_RESTORE_KEY *q_u, REG_R_RESTORE_KEY *r_u) +{ + REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol ); + pstring filename; + + DEBUG(5,("_reg_restore_key: Enter\n")); + + /* + * basically this is a no op function which just verifies + * that the client gave us a valid registry key handle + */ + + if ( !regkey ) + return WERR_BADFID; + + rpcstr_pull(filename, q_u->filename.string->buffer, sizeof(filename), q_u->filename.string->uni_str_len*2, STR_TERMINATE); + + DEBUG(8,("_reg_restore_key: verifying restore of key [%s] from \"%s\"\n", regkey->name, filename)); + +#if 0 + validate_reg_filemame( filename ); + return restore_registry_key( regkey, filename ); +#endif + + return WERR_OK; } /******************************************************************* - REG_SAVE_KEY (0x14) ********************************************************************/ WERROR _reg_save_key(pipes_struct *p, REG_Q_SAVE_KEY *q_u, REG_R_SAVE_KEY *r_u) { REGISTRY_KEY *regkey = find_regkey_index_by_hnd( p, &q_u->pol ); + pstring filename; DEBUG(5,("_reg_save_key: Enter\n")); /* - * basically this is a no op function which just gverifies + * basically this is a no op function which just verifies * that the client gave us a valid registry key handle */ if ( !regkey ) - return WERR_BADFID; /* This will be reported as an RPC fault anyway. */ + return WERR_BADFID; - DEBUG(8,("_reg_save_key: berifying backup of key [%s]\n", regkey->name)); - + rpcstr_pull(filename, q_u->filename.string->buffer, sizeof(filename), q_u->filename.string->uni_str_len*2, STR_TERMINATE); + + DEBUG(8,("_reg_save_key: verifying backup of key [%s] to \"%s\"\n", regkey->name, filename)); + +#if 0 + validate_reg_filemame( filename ); + return backup_registry_key( regkey, filename ); +#endif return WERR_OK; } diff --git a/source/rpc_server/srv_samr_nt.c b/source/rpc_server/srv_samr_nt.c index 139960f6613..84c78eab641 100644 --- a/source/rpc_server/srv_samr_nt.c +++ b/source/rpc_server/srv_samr_nt.c @@ -39,8 +39,6 @@ SA_RIGHT_USER_CHANGE_PASSWORD | \ SA_RIGHT_USER_SET_LOC_COM ) -extern DOM_SID global_sid_Builtin; - extern rid_name domain_group_rids[]; extern rid_name domain_alias_rids[]; extern rid_name builtin_alias_rids[]; @@ -80,7 +78,6 @@ static NTSTATUS make_samr_object_sd( TALLOC_CTX *ctx, SEC_DESC **psd, size_t *sd struct generic_mapping *map, DOM_SID *sid, uint32 sid_access ) { - extern DOM_SID global_sid_World; DOM_SID adm_sid, act_sid, domadmin_sid; SEC_ACE ace[5]; /* at most 5 entries */ SEC_ACCESS mask; @@ -867,6 +864,7 @@ static NTSTATUS get_group_domain_entries( TALLOC_CTX *ctx, int i; uint32 group_entries = 0; uint32 num_entries = 0; + NTSTATUS result = NT_STATUS_OK; *p_num_entries = 0; @@ -884,6 +882,7 @@ static NTSTATUS get_group_domain_entries( TALLOC_CTX *ctx, if (num_entries>max_entries) { DEBUG(5,("Limiting to %d entries\n", max_entries)); num_entries=max_entries; + result = STATUS_MORE_ENTRIES; } *d_grp=TALLOC_ZERO_ARRAY(ctx, DOMAIN_GRP, num_entries); @@ -906,7 +905,7 @@ static NTSTATUS get_group_domain_entries( TALLOC_CTX *ctx, DEBUG(10,("get_group_domain_entries: returning %d entries\n", *p_num_entries)); - return NT_STATUS_OK; + return result; } /******************************************************************* @@ -973,13 +972,19 @@ NTSTATUS _samr_enum_dom_groups(pipes_struct *p, SAMR_Q_ENUM_DOM_GROUPS *q_u, SAM DEBUG(5,("samr_reply_enum_dom_groups: %d\n", __LINE__)); /* the domain group array is being allocated in the function below */ - if (!NT_STATUS_IS_OK(r_u->status = get_group_domain_entries(p->mem_ctx, &grp, &sid, q_u->start_idx, &num_entries, MAX_SAM_ENTRIES))) { + r_u->status = get_group_domain_entries(p->mem_ctx, &grp, &sid, + q_u->start_idx, &num_entries, + MAX_SAM_ENTRIES); + + if (!NT_STATUS_IS_OK(r_u->status) && + !NT_STATUS_EQUAL(r_u->status, STATUS_MORE_ENTRIES)) return r_u->status; - } - make_group_sam_entry_list(p->mem_ctx, &r_u->sam, &r_u->uni_grp_name, num_entries, grp); + make_group_sam_entry_list(p->mem_ctx, &r_u->sam, &r_u->uni_grp_name, + num_entries, grp); - init_samr_r_enum_dom_groups(r_u, q_u->start_idx, num_entries); + init_samr_r_enum_dom_groups(r_u, q_u->start_idx+num_entries, + num_entries); DEBUG(5,("samr_enum_dom_groups: %d\n", __LINE__)); @@ -1464,8 +1469,9 @@ NTSTATUS _samr_chgpasswd_user(pipes_struct *p, SAMR_Q_CHGPASSWD_USER *q_u, SAMR_ makes a SAMR_R_LOOKUP_RIDS structure. ********************************************************************/ -static BOOL make_samr_lookup_rids(TALLOC_CTX *ctx, uint32 num_names, fstring names[], - UNIHDR **pp_hdr_name, UNISTR2 **pp_uni_name) +static BOOL make_samr_lookup_rids(TALLOC_CTX *ctx, uint32 num_names, + const char **names, UNIHDR **pp_hdr_name, + UNISTR2 **pp_uni_name) { uint32 i; UNIHDR *hdr_name=NULL; @@ -1485,7 +1491,7 @@ static BOOL make_samr_lookup_rids(TALLOC_CTX *ctx, uint32 num_names, fstring nam } for (i = 0; i < num_names; i++) { - DEBUG(10, ("names[%d]:%s\n", i, names[i] ? names[i] : "")); + DEBUG(10, ("names[%d]:%s\n", i, *names[i] ? names[i] : "")); init_unistr2(&uni_name[i], names[i], UNI_FLAGS_NONE); init_uni_hdr(&hdr_name[i], &uni_name[i]); } @@ -1502,16 +1508,13 @@ static BOOL make_samr_lookup_rids(TALLOC_CTX *ctx, uint32 num_names, fstring nam NTSTATUS _samr_lookup_rids(pipes_struct *p, SAMR_Q_LOOKUP_RIDS *q_u, SAMR_R_LOOKUP_RIDS *r_u) { - fstring group_names[MAX_SAM_ENTRIES]; - uint32 *group_attrs = NULL; + const char **names; + uint32 *attrs = NULL; UNIHDR *hdr_name = NULL; UNISTR2 *uni_name = NULL; DOM_SID pol_sid; int num_rids = q_u->num_rids1; - int i; uint32 acc_granted; - BOOL have_mapped = False; - BOOL have_unmapped = False; r_u->status = NT_STATUS_OK; @@ -1527,11 +1530,12 @@ NTSTATUS _samr_lookup_rids(pipes_struct *p, SAMR_Q_LOOKUP_RIDS *q_u, SAMR_R_LOOK return NT_STATUS_UNSUCCESSFUL; } - if (num_rids) { - if ((group_attrs = TALLOC_ZERO_ARRAY(p->mem_ctx, uint32, num_rids )) == NULL) - return NT_STATUS_NO_MEMORY; - } - + names = TALLOC_ZERO_ARRAY(p->mem_ctx, const char *, num_rids); + attrs = TALLOC_ZERO_ARRAY(p->mem_ctx, uint32, num_rids); + + if ((num_rids != 0) && ((names == NULL) || (attrs == NULL))) + return NT_STATUS_NO_MEMORY; + if (!sid_equal(&pol_sid, get_global_sam_sid())) { /* TODO: Sooner or later we need to look up BUILTIN rids as * well. -- vl */ @@ -1539,44 +1543,17 @@ NTSTATUS _samr_lookup_rids(pipes_struct *p, SAMR_Q_LOOKUP_RIDS *q_u, SAMR_R_LOOK } become_root(); /* lookup_sid can require root privs */ - - for (i = 0; i < num_rids; i++) { - fstring tmpname; - fstring domname; - DOM_SID sid; - enum SID_NAME_USE type; - - group_attrs[i] = SID_NAME_UNKNOWN; - *group_names[i] = '\0'; - - sid_copy(&sid, &pol_sid); - sid_append_rid(&sid, q_u->rid[i]); - - if (lookup_sid(&sid, domname, tmpname, &type)) { - group_attrs[i] = (uint32)type; - fstrcpy(group_names[i],tmpname); - DEBUG(5,("_samr_lookup_rids: %s:%d\n", group_names[i], - group_attrs[i])); - have_mapped = True; - } else { - have_unmapped = True; - } - } - + r_u->status = pdb_lookup_rids(p->mem_ctx, &pol_sid, num_rids, q_u->rid, + &names, &attrs); unbecome_root(); done: - r_u->status = NT_STATUS_NONE_MAPPED; - - if (have_mapped) - r_u->status = - have_unmapped ? STATUS_SOME_UNMAPPED : NT_STATUS_OK; - - if(!make_samr_lookup_rids(p->mem_ctx, num_rids, group_names, &hdr_name, &uni_name)) + if(!make_samr_lookup_rids(p->mem_ctx, num_rids, names, + &hdr_name, &uni_name)) return NT_STATUS_NO_MEMORY; - init_samr_r_lookup_rids(r_u, num_rids, hdr_name, uni_name, group_attrs); + init_samr_r_lookup_rids(r_u, num_rids, hdr_name, uni_name, attrs); DEBUG(5,("_samr_lookup_rids: %d\n", __LINE__)); @@ -1977,7 +1954,7 @@ NTSTATUS _samr_query_usergroups(pipes_struct *p, SAMR_Q_QUERY_USERGROUPS *q_u, S DOM_GID *gids = NULL; int num_groups = 0; gid_t *unix_gids; - int i, num_gids, num_sids; + int i, num_gids; uint32 acc_granted; BOOL ret; NTSTATUS result; @@ -2027,7 +2004,6 @@ NTSTATUS _samr_query_usergroups(pipes_struct *p, SAMR_Q_QUERY_USERGROUPS *q_u, S } sids = NULL; - num_sids = 0; become_root(); result = pdb_enum_group_memberships(pdb_get_username(sam_pass), @@ -2900,7 +2876,7 @@ static BOOL set_user_info_23(SAM_USER_INFO_23 *id23, SAM_ACCOUNT *pwd) acct_ctrl = pdb_get_acct_ctrl(pwd); - if (!decode_pw_buffer((char*)id23->pass, plaintext_buf, 256, &len, STR_UNICODE)) { + if (!decode_pw_buffer(id23->pass, plaintext_buf, 256, &len, STR_UNICODE)) { pdb_free_sam(&pwd); return False; } @@ -2951,7 +2927,7 @@ static BOOL set_user_info_23(SAM_USER_INFO_23 *id23, SAM_ACCOUNT *pwd) set_user_info_pw ********************************************************************/ -static BOOL set_user_info_pw(char *pass, SAM_ACCOUNT *pwd) +static BOOL set_user_info_pw(uint8 *pass, SAM_ACCOUNT *pwd) { uint32 len; pstring plaintext_buf; @@ -3097,7 +3073,7 @@ NTSTATUS _samr_set_userinfo(pipes_struct *p, SAMR_Q_SET_USERINFO *q_u, SAMR_R_SE dump_data(100, (char *)ctr->info.id24->pass, 516); - if (!set_user_info_pw((char *)ctr->info.id24->pass, pwd)) + if (!set_user_info_pw(ctr->info.id24->pass, pwd)) r_u->status = NT_STATUS_ACCESS_DENIED; break; @@ -3259,8 +3235,8 @@ NTSTATUS _samr_set_userinfo2(pipes_struct *p, SAMR_Q_SET_USERINFO2 *q_u, SAMR_R_ NTSTATUS _samr_query_useraliases(pipes_struct *p, SAMR_Q_QUERY_USERALIASES *q_u, SAMR_R_QUERY_USERALIASES *r_u) { - int num_groups = 0; - uint32 *rids=NULL; + int num_alias_rids; + uint32 *alias_rids; struct samr_info *info = NULL; int i; @@ -3268,8 +3244,6 @@ NTSTATUS _samr_query_useraliases(pipes_struct *p, SAMR_Q_QUERY_USERALIASES *q_u, NTSTATUS ntstatus2; DOM_SID *members; - DOM_SID *aliases; - int num_aliases; BOOL res; r_u->status = NT_STATUS_OK; @@ -3302,35 +3276,20 @@ NTSTATUS _samr_query_useraliases(pipes_struct *p, SAMR_Q_QUERY_USERALIASES *q_u, for (i=0; inum_sids1; i++) sid_copy(&members[i], &q_u->sid[i].sid); + alias_rids = NULL; + num_alias_rids = 0; + become_root(); - res = pdb_enum_alias_memberships(members, - q_u->num_sids1, &aliases, - &num_aliases); + res = pdb_enum_alias_memberships(p->mem_ctx, &info->sid, members, + q_u->num_sids1, + &alias_rids, &num_alias_rids); unbecome_root(); if (!res) return NT_STATUS_UNSUCCESSFUL; - rids = NULL; - num_groups = 0; - - for (i=0; isid, &aliases[i], &rid)) - continue; - - rids = TALLOC_REALLOC_ARRAY(p->mem_ctx, rids, uint32, num_groups+1); - - if (rids == NULL) - return NT_STATUS_NO_MEMORY; - - rids[num_groups] = rid; - num_groups += 1; - } - SAFE_FREE(aliases); - - init_samr_r_query_useraliases(r_u, num_groups, rids, NT_STATUS_OK); + init_samr_r_query_useraliases(r_u, num_alias_rids, alias_rids, + NT_STATUS_OK); return NT_STATUS_OK; } @@ -3821,7 +3780,6 @@ NTSTATUS _samr_delete_dom_user(pipes_struct *p, SAMR_Q_DELETE_DOM_USER *q_u, SAM DOM_SID user_sid; SAM_ACCOUNT *sam_pass=NULL; uint32 acc_granted; - SE_PRIV se_rights; BOOL can_add_accounts; BOOL ret; @@ -3847,8 +3805,7 @@ NTSTATUS _samr_delete_dom_user(pipes_struct *p, SAMR_Q_DELETE_DOM_USER *q_u, SAM return NT_STATUS_NO_SUCH_USER; } - se_priv_copy( &se_rights, &se_add_users ); - can_add_accounts = user_has_privileges( p->pipe_user.nt_user_token, &se_rights ); + can_add_accounts = user_has_privileges( p->pipe_user.nt_user_token, &se_add_users ); /******** BEGIN SeAddUsers BLOCK *********/ @@ -4121,7 +4078,6 @@ NTSTATUS _samr_create_dom_alias(pipes_struct *p, SAMR_Q_CREATE_DOM_ALIAS *q_u, S DOM_SID dom_sid; DOM_SID info_sid; fstring name; - struct group *grp; struct samr_info *info; uint32 acc_granted; gid_t gid; @@ -4168,7 +4124,7 @@ NTSTATUS _samr_create_dom_alias(pipes_struct *p, SAMR_Q_CREATE_DOM_ALIAS *q_u, S return NT_STATUS_ACCESS_DENIED; /* check if the group has been successfully created */ - if ((grp=getgrgid(gid)) == NULL) + if ( getgrgid(gid) == NULL ) return NT_STATUS_ACCESS_DENIED; if ((info = get_samr_info_by_sid(&info_sid)) == NULL) diff --git a/source/rpc_server/srv_samr_util.c b/source/rpc_server/srv_samr_util.c index 6797730be97..61160ccaa02 100644 --- a/source/rpc_server/srv_samr_util.c +++ b/source/rpc_server/srv_samr_util.c @@ -264,7 +264,7 @@ void copy_id21_to_sam_passwd(SAM_ACCOUNT *to, SAM_USER_INFO_21 *from) DEBUG(15,("INFO_21 LOGON_HRS.HOURS: %s -> %s\n",pdb_get_hours(to),from->logon_hrs.hours)); pdb_sethexhours(old, pdb_get_hours(to)); - pdb_sethexhours(new, (const char *)from->logon_hrs.hours); + pdb_sethexhours(new, from->logon_hrs.hours); if (!strequal(old, new)) { pdb_set_hours(to, from->logon_hrs.hours, PDB_CHANGED); } diff --git a/source/rpc_server/srv_spoolss.c b/source/rpc_server/srv_spoolss.c index f846813a40b..b3a67dd6cfd 100755 --- a/source/rpc_server/srv_spoolss.c +++ b/source/rpc_server/srv_spoolss.c @@ -1244,6 +1244,9 @@ static BOOL api_spoolss_getjob(pipes_struct *p) prs_struct *data = &p->in_data.data; prs_struct *rdata = &p->out_data.rdata; + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + if(!spoolss_io_q_getjob("", &q_u, data, 0)) { DEBUG(0,("spoolss_io_q_getjob: unable to unmarshall SPOOL_Q_GETJOB.\n")); return False; diff --git a/source/rpc_server/srv_spoolss_nt.c b/source/rpc_server/srv_spoolss_nt.c index ffeeb0af9a9..0f33fd7dec8 100644 --- a/source/rpc_server/srv_spoolss_nt.c +++ b/source/rpc_server/srv_spoolss_nt.c @@ -28,6 +28,8 @@ #include "includes.h" +extern userdom_struct current_user_info; + #undef DBGC_CLASS #define DBGC_CLASS DBGC_RPC_SRV @@ -644,41 +646,6 @@ static BOOL open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint3 return True; } -/**************************************************************************** - Allocate more memory for a BUFFER. -****************************************************************************/ - -static BOOL alloc_buffer_size(NEW_BUFFER *buffer, uint32 buffer_size) -{ - prs_struct *ps; - uint32 extra_space; - uint32 old_offset; - - ps= &buffer->prs; - - /* damn, I'm doing the reverse operation of prs_grow() :) */ - if (buffer_size < prs_data_size(ps)) - extra_space=0; - else - extra_space = buffer_size - prs_data_size(ps); - - /* - * save the offset and move to the end of the buffer - * prs_grow() checks the extra_space against the offset - */ - old_offset=prs_offset(ps); - prs_set_offset(ps, prs_data_size(ps)); - - if (!prs_grow(ps, extra_space)) - return False; - - prs_set_offset(ps, old_offset); - - buffer->string_at_end=prs_data_size(ps); - - return True; -} - /*************************************************************************** check to see if the client motify handle is monitoring the notification given by (notify_type, notify_field). @@ -1526,10 +1493,10 @@ static void convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q DEBUG(8,("convert_to_openprinterex\n")); - q_u_ex->printername_ptr = q_u->printername_ptr; - - if (q_u->printername_ptr) - copy_unistr2(&q_u_ex->printername, &q_u->printername); + if ( q_u->printername ) { + q_u_ex->printername = TALLOC_P( ctx, UNISTR2 ); + copy_unistr2(q_u_ex->printername, q_u->printername); + } copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default); } @@ -1623,7 +1590,6 @@ WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u) { - UNISTR2 *printername = NULL; PRINTER_DEFAULT *printer_default = &q_u->printer_default; POLICY_HND *handle = &r_u->handle; @@ -1632,15 +1598,13 @@ WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, struct current_user user; Printer_entry *Printer=NULL; - if (q_u->printername_ptr != 0) - printername = &q_u->printername; - - if (printername == NULL) + if ( !q_u->printername ) return WERR_INVALID_PRINTER_NAME; /* some sanity check because you can open a printer or a print server */ /* aka: \\server\printer or \\server */ - unistr2_to_ascii(name, printername, sizeof(name)-1); + + unistr2_to_ascii(name, q_u->printername, sizeof(name)-1); DEBUGADD(3,("checking name: %s\n",name)); @@ -4121,7 +4085,7 @@ static void free_dev_mode(DEVICEMODE *dev) if (dev == NULL) return; - SAFE_FREE(dev->private); + SAFE_FREE(dev->private); SAFE_FREE(dev); } @@ -4404,13 +4368,14 @@ static BOOL construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *p Spoolss_enumprinters. ********************************************************************/ -static WERROR enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned) +static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned) { int snum; int i; int n_services=lp_numservices(); PRINTER_INFO_1 *tp, *printers=NULL; PRINTER_INFO_1 current_prt; + WERROR result = WERR_OK; DEBUG(4,("enum_all_printers_info_1\n")); @@ -4438,29 +4403,36 @@ static WERROR enum_all_printers_info_1(uint32 flags, NEW_BUFFER *buffer, uint32 for (i=0; i<*returned; i++) (*needed) += spoolss_size_printer_info_1(&printers[i]); - if (!alloc_buffer_size(buffer, *needed)) - return WERR_INSUFFICIENT_BUFFER; + if (*needed > offered) { + result = WERR_INSUFFICIENT_BUFFER; + goto out; + } + + if (!rpcbuf_alloc_size(buffer, *needed)) { + result = WERR_NOMEM; + goto out; + } /* fill the buffer with the structures */ for (i=0; i<*returned; i++) smb_io_printer_info_1("", buffer, &printers[i], 0); +out: /* clear memory */ + SAFE_FREE(printers); - if (*needed > offered) { - *returned=0; - return WERR_INSUFFICIENT_BUFFER; - } - else - return WERR_OK; + if ( !W_ERROR_IS_OK(result) ) + *returned = 0; + + return result; } /******************************************************************** enum_all_printers_info_1_local. *********************************************************************/ -static WERROR enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned) +static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned) { DEBUG(4,("enum_all_printers_info_1_local\n")); @@ -4471,7 +4443,7 @@ static WERROR enum_all_printers_info_1_local(NEW_BUFFER *buffer, uint32 offered, enum_all_printers_info_1_name. *********************************************************************/ -static WERROR enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned) +static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned) { char *s = name; @@ -4492,13 +4464,14 @@ static WERROR enum_all_printers_info_1_name(fstring name, NEW_BUFFER *buffer, ui enum_all_printers_info_1_remote. *********************************************************************/ -static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned) +static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned) { PRINTER_INFO_1 *printer; fstring printername; fstring desc; fstring comment; DEBUG(4,("enum_all_printers_info_1_remote\n")); + WERROR result = WERR_OK; /* JFM: currently it's more a place holder than anything else. * In the spooler world there is a notion of server registration. @@ -4525,23 +4498,27 @@ static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, /* check the required size. */ *needed += spoolss_size_printer_info_1(printer); - if (!alloc_buffer_size(buffer, *needed)) { - SAFE_FREE(printer); - return WERR_INSUFFICIENT_BUFFER; + if (*needed > offered) { + result = WERR_INSUFFICIENT_BUFFER; + goto out; + } + + if (!rpcbuf_alloc_size(buffer, *needed)) { + result = WERR_NOMEM; + goto out; } /* fill the buffer with the structures */ smb_io_printer_info_1("", buffer, printer, 0); +out: /* clear memory */ SAFE_FREE(printer); - if (*needed > offered) { - *returned=0; - return WERR_INSUFFICIENT_BUFFER; - } - else - return WERR_OK; + if ( !W_ERROR_IS_OK(result) ) + *returned = 0; + + return result; } #endif @@ -4550,7 +4527,7 @@ static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, enum_all_printers_info_1_network. *********************************************************************/ -static WERROR enum_all_printers_info_1_network(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned) +static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned) { char *s = name; @@ -4579,13 +4556,14 @@ static WERROR enum_all_printers_info_1_network(fstring name, NEW_BUFFER *buffer, * called from api_spoolss_enumprinters (see this to understand) ********************************************************************/ -static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned) +static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned) { int snum; int i; int n_services=lp_numservices(); PRINTER_INFO_2 *tp, *printers=NULL; PRINTER_INFO_2 current_prt; + WERROR result = WERR_OK; for (snum=0; snum offered) { + result = WERR_INSUFFICIENT_BUFFER; + goto out; + } + + if (!rpcbuf_alloc_size(buffer, *needed)) { + result = WERR_NOMEM; + goto out; } /* fill the buffer with the structures */ for (i=0; i<*returned; i++) smb_io_printer_info_2("", buffer, &(printers[i]), 0); +out: /* clear memory */ for (i=0; i<*returned; i++) { free_devmode(printers[i].devmode); } SAFE_FREE(printers); - if (*needed > offered) { - *returned=0; - return WERR_INSUFFICIENT_BUFFER; - } - else - return WERR_OK; + if ( !W_ERROR_IS_OK(result) ) + *returned = 0; + + return result; } /******************************************************************** @@ -4641,7 +4620,7 @@ static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint3 ********************************************************************/ static WERROR enumprinters_level1( uint32 flags, fstring name, - NEW_BUFFER *buffer, uint32 offered, + RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned) { /* Not all the flags are equals */ @@ -4668,7 +4647,7 @@ static WERROR enumprinters_level1( uint32 flags, fstring name, ********************************************************************/ static WERROR enumprinters_level2( uint32 flags, fstring servername, - NEW_BUFFER *buffer, uint32 offered, + RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned) { char *s = servername; @@ -4697,7 +4676,7 @@ static WERROR enumprinters_level2( uint32 flags, fstring servername, ********************************************************************/ static WERROR enumprinters_level5( uint32 flags, fstring servername, - NEW_BUFFER *buffer, uint32 offered, + RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned) { /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/ @@ -4715,7 +4694,7 @@ WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_ uint32 flags = q_u->flags; UNISTR2 *servername = &q_u->servername; uint32 level = q_u->level; - NEW_BUFFER *buffer = NULL; + RPC_BUFFER *buffer = NULL; uint32 offered = q_u->offered; uint32 *needed = &r_u->needed; uint32 *returned = &r_u->returned; @@ -4723,8 +4702,11 @@ WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_ fstring name; /* that's an [in out] buffer */ - spoolss_move_buffer(q_u->buffer, &r_u->buffer); - buffer = r_u->buffer; + + if ( q_u->buffer ) { + rpcbuf_move(q_u->buffer, &r_u->buffer); + buffer = r_u->buffer; + } DEBUG(4,("_spoolss_enumprinters\n")); @@ -4764,9 +4746,10 @@ WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_ /**************************************************************************** ****************************************************************************/ -static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed) +static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed) { PRINTER_INFO_0 *printer=NULL; + WERROR result = WERR_OK; if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL) return WERR_NOMEM; @@ -4776,30 +4759,34 @@ static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, NEW_BUFFER /* check the required size. */ *needed += spoolss_size_printer_info_0(printer); - if (!alloc_buffer_size(buffer, *needed)) { - SAFE_FREE(printer); - return WERR_INSUFFICIENT_BUFFER; + if (*needed > offered) { + result = WERR_INSUFFICIENT_BUFFER; + goto out; + } + + if (!rpcbuf_alloc_size(buffer, *needed)) { + result = WERR_NOMEM; + goto out; } /* fill the buffer with the structures */ smb_io_printer_info_0("", buffer, printer, 0); +out: /* clear memory */ - SAFE_FREE(printer); - if (*needed > offered) { - return WERR_INSUFFICIENT_BUFFER; - } + SAFE_FREE(printer); - return WERR_OK; + return result; } /**************************************************************************** ****************************************************************************/ -static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed) +static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed) { PRINTER_INFO_1 *printer=NULL; + WERROR result = WERR_OK; if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL) return WERR_NOMEM; @@ -4809,30 +4796,33 @@ static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, NEW_BUFFER /* check the required size. */ *needed += spoolss_size_printer_info_1(printer); - if (!alloc_buffer_size(buffer, *needed)) { - SAFE_FREE(printer); - return WERR_INSUFFICIENT_BUFFER; + if (*needed > offered) { + result = WERR_INSUFFICIENT_BUFFER; + goto out; + } + + if (!rpcbuf_alloc_size(buffer, *needed)) { + result = WERR_NOMEM; + goto out; } /* fill the buffer with the structures */ smb_io_printer_info_1("", buffer, printer, 0); +out: /* clear memory */ SAFE_FREE(printer); - if (*needed > offered) { - return WERR_INSUFFICIENT_BUFFER; - } - - return WERR_OK; + return result; } /**************************************************************************** ****************************************************************************/ -static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed) +static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed) { PRINTER_INFO_2 *printer=NULL; + WERROR result = WERR_OK; if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL) return WERR_NOMEM; @@ -4842,33 +4832,34 @@ static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, NEW_BUFFER /* check the required size. */ *needed += spoolss_size_printer_info_2(printer); - if (!alloc_buffer_size(buffer, *needed)) { - free_printer_info_2(printer); - return WERR_INSUFFICIENT_BUFFER; + if (*needed > offered) { + result = WERR_INSUFFICIENT_BUFFER; + goto out; } - /* fill the buffer with the structures */ - if (!smb_io_printer_info_2("", buffer, printer, 0)) { - free_printer_info_2(printer); - return WERR_NOMEM; + if (!rpcbuf_alloc_size(buffer, *needed)) { + result = WERR_NOMEM; + goto out; } + + /* fill the buffer with the structures */ + if (!smb_io_printer_info_2("", buffer, printer, 0)) + result = WERR_NOMEM; +out: /* clear memory */ free_printer_info_2(printer); - if (*needed > offered) { - return WERR_INSUFFICIENT_BUFFER; - } - - return WERR_OK; + return result; } /**************************************************************************** ****************************************************************************/ -static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed) +static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed) { PRINTER_INFO_3 *printer=NULL; + WERROR result = WERR_OK; if (!construct_printer_info_3(print_hnd, &printer, snum)) return WERR_NOMEM; @@ -4876,30 +4867,33 @@ static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, NEW_BUFFER /* check the required size. */ *needed += spoolss_size_printer_info_3(printer); - if (!alloc_buffer_size(buffer, *needed)) { - free_printer_info_3(printer); - return WERR_INSUFFICIENT_BUFFER; + if (*needed > offered) { + result = WERR_INSUFFICIENT_BUFFER; + goto out; + } + + if (!rpcbuf_alloc_size(buffer, *needed)) { + result = WERR_NOMEM; + goto out; } /* fill the buffer with the structures */ smb_io_printer_info_3("", buffer, printer, 0); +out: /* clear memory */ free_printer_info_3(printer); - if (*needed > offered) { - return WERR_INSUFFICIENT_BUFFER; - } - - return WERR_OK; + return result; } /**************************************************************************** ****************************************************************************/ -static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed) +static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed) { PRINTER_INFO_4 *printer=NULL; + WERROR result = WERR_OK; if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL) return WERR_NOMEM; @@ -4910,30 +4904,33 @@ static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, NEW_BUFFER /* check the required size. */ *needed += spoolss_size_printer_info_4(printer); - if (!alloc_buffer_size(buffer, *needed)) { - free_printer_info_4(printer); - return WERR_INSUFFICIENT_BUFFER; + if (*needed > offered) { + result = WERR_INSUFFICIENT_BUFFER; + goto out; + } + + if (!rpcbuf_alloc_size(buffer, *needed)) { + result = WERR_NOMEM; + goto out; } /* fill the buffer with the structures */ smb_io_printer_info_4("", buffer, printer, 0); +out: /* clear memory */ free_printer_info_4(printer); - if (*needed > offered) { - return WERR_INSUFFICIENT_BUFFER; - } - - return WERR_OK; + return result; } /**************************************************************************** ****************************************************************************/ -static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed) +static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed) { PRINTER_INFO_5 *printer=NULL; + WERROR result = WERR_OK; if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL) return WERR_NOMEM; @@ -4944,27 +4941,30 @@ static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, NEW_BUFFER /* check the required size. */ *needed += spoolss_size_printer_info_5(printer); - if (!alloc_buffer_size(buffer, *needed)) { - free_printer_info_5(printer); - return WERR_INSUFFICIENT_BUFFER; + if (*needed > offered) { + result = WERR_INSUFFICIENT_BUFFER; + goto out; + } + + if (!rpcbuf_alloc_size(buffer, *needed)) { + result = WERR_NOMEM; + goto out; } /* fill the buffer with the structures */ smb_io_printer_info_5("", buffer, printer, 0); +out: /* clear memory */ free_printer_info_5(printer); - if (*needed > offered) { - return WERR_INSUFFICIENT_BUFFER; - } - - return WERR_OK; + return result; } -static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed) +static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed) { PRINTER_INFO_7 *printer=NULL; + WERROR result = WERR_OK; if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL) return WERR_NOMEM; @@ -4975,22 +4975,25 @@ static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, NEW_BUFFER /* check the required size. */ *needed += spoolss_size_printer_info_7(printer); - if (!alloc_buffer_size(buffer, *needed)) { - free_printer_info_7(printer); - return WERR_INSUFFICIENT_BUFFER; + if (*needed > offered) { + result = WERR_INSUFFICIENT_BUFFER; + goto out; + } + + if (!rpcbuf_alloc_size(buffer, *needed)) { + result = WERR_NOMEM; + goto out; + } /* fill the buffer with the structures */ smb_io_printer_info_7("", buffer, printer, 0); +out: /* clear memory */ free_printer_info_7(printer); - if (*needed > offered) { - return WERR_INSUFFICIENT_BUFFER; - } - - return WERR_OK; + return result; } /**************************************************************************** @@ -5000,7 +5003,7 @@ WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GET { POLICY_HND *handle = &q_u->handle; uint32 level = q_u->level; - NEW_BUFFER *buffer = NULL; + RPC_BUFFER *buffer = NULL; uint32 offered = q_u->offered; uint32 *needed = &r_u->needed; Printer_entry *Printer=find_printer_index_by_hnd(p, handle); @@ -5008,8 +5011,11 @@ WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GET int snum; /* that's an [in out] buffer */ - spoolss_move_buffer(q_u->buffer, &r_u->buffer); - buffer = r_u->buffer; + + if ( q_u->buffer ) { + rpcbuf_move(q_u->buffer, &r_u->buffer); + buffer = r_u->buffer; + } *needed=0; @@ -5433,149 +5439,154 @@ static void free_printer_driver_info_3(DRIVER_INFO_3 *info) static void free_printer_driver_info_6(DRIVER_INFO_6 *info) { SAFE_FREE(info->dependentfiles); - } /**************************************************************************** ****************************************************************************/ -static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed) +static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed) { DRIVER_INFO_1 *info=NULL; - WERROR status; + WERROR result; if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL) return WERR_NOMEM; - status=construct_printer_driver_info_1(info, snum, servername, architecture, version); - if (!W_ERROR_IS_OK(status)) { - SAFE_FREE(info); - return status; - } + result = construct_printer_driver_info_1(info, snum, servername, architecture, version); + if (!W_ERROR_IS_OK(result)) + goto out; /* check the required size. */ *needed += spoolss_size_printer_driver_info_1(info); - if (!alloc_buffer_size(buffer, *needed)) { - SAFE_FREE(info); - return WERR_INSUFFICIENT_BUFFER; + if (*needed > offered) { + result = WERR_INSUFFICIENT_BUFFER; + goto out; + } + + if (!rpcbuf_alloc_size(buffer, *needed)) { + result = WERR_NOMEM; + goto out; } /* fill the buffer with the structures */ smb_io_printer_driver_info_1("", buffer, info, 0); +out: /* clear memory */ SAFE_FREE(info); - if (*needed > offered) - return WERR_INSUFFICIENT_BUFFER; - - return WERR_OK; + return result; } /**************************************************************************** ****************************************************************************/ -static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed) +static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed) { DRIVER_INFO_2 *info=NULL; - WERROR status; + WERROR result; if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL) return WERR_NOMEM; - status=construct_printer_driver_info_2(info, snum, servername, architecture, version); - if (!W_ERROR_IS_OK(status)) { - SAFE_FREE(info); - return status; - } + result = construct_printer_driver_info_2(info, snum, servername, architecture, version); + if (!W_ERROR_IS_OK(result)) + goto out; /* check the required size. */ *needed += spoolss_size_printer_driver_info_2(info); - if (!alloc_buffer_size(buffer, *needed)) { - SAFE_FREE(info); - return WERR_INSUFFICIENT_BUFFER; + if (*needed > offered) { + result = WERR_INSUFFICIENT_BUFFER; + goto out; + } + + if (!rpcbuf_alloc_size(buffer, *needed)) { + result = WERR_NOMEM; + goto out; } /* fill the buffer with the structures */ smb_io_printer_driver_info_2("", buffer, info, 0); +out: /* clear memory */ SAFE_FREE(info); - if (*needed > offered) - return WERR_INSUFFICIENT_BUFFER; - - return WERR_OK; + return result; } /**************************************************************************** ****************************************************************************/ -static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed) +static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed) { DRIVER_INFO_3 info; - WERROR status; + WERROR result; ZERO_STRUCT(info); - status=construct_printer_driver_info_3(&info, snum, servername, architecture, version); - if (!W_ERROR_IS_OK(status)) { - return status; - } + result = construct_printer_driver_info_3(&info, snum, servername, architecture, version); + if (!W_ERROR_IS_OK(result)) + goto out; /* check the required size. */ *needed += spoolss_size_printer_driver_info_3(&info); - if (!alloc_buffer_size(buffer, *needed)) { - free_printer_driver_info_3(&info); - return WERR_INSUFFICIENT_BUFFER; + if (*needed > offered) { + result = WERR_INSUFFICIENT_BUFFER; + goto out; + } + + if (!rpcbuf_alloc_size(buffer, *needed)) { + result = WERR_NOMEM; + goto out; } /* fill the buffer with the structures */ smb_io_printer_driver_info_3("", buffer, &info, 0); +out: free_printer_driver_info_3(&info); - if (*needed > offered) - return WERR_INSUFFICIENT_BUFFER; - - return WERR_OK; + return result; } /**************************************************************************** ****************************************************************************/ -static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, NEW_BUFFER *buffer, uint32 offered, uint32 *needed) +static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed) { DRIVER_INFO_6 info; - WERROR status; + WERROR result; ZERO_STRUCT(info); - status=construct_printer_driver_info_6(&info, snum, servername, architecture, version); - if (!W_ERROR_IS_OK(status)) { - return status; - } + result = construct_printer_driver_info_6(&info, snum, servername, architecture, version); + if (!W_ERROR_IS_OK(result)) + goto out; /* check the required size. */ *needed += spoolss_size_printer_driver_info_6(&info); - if (!alloc_buffer_size(buffer, *needed)) { - free_printer_driver_info_6(&info); - return WERR_INSUFFICIENT_BUFFER; + if (*needed > offered) { + result = WERR_INSUFFICIENT_BUFFER; + goto out; + } + + if (!rpcbuf_alloc_size(buffer, *needed)) { + result = WERR_NOMEM; + goto out; } /* fill the buffer with the structures */ smb_io_printer_driver_info_6("", buffer, &info, 0); +out: free_printer_driver_info_6(&info); - if (*needed > offered) - return WERR_INSUFFICIENT_BUFFER; - - return WERR_OK; + return result; } /**************************************************************************** @@ -5587,7 +5598,7 @@ WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_ UNISTR2 *uni_arch = &q_u->architecture; uint32 level = q_u->level; uint32 clientmajorversion = q_u->clientmajorversion; - NEW_BUFFER *buffer = NULL; + RPC_BUFFER *buffer = NULL; uint32 offered = q_u->offered; uint32 *needed = &r_u->needed; uint32 *servermajorversion = &r_u->servermajorversion; @@ -5599,8 +5610,11 @@ WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_ int snum; /* that's an [in out] buffer */ - spoolss_move_buffer(q_u->buffer, &r_u->buffer); - buffer = r_u->buffer; + + if ( q_u->buffer ) { + rpcbuf_move(q_u->buffer, &r_u->buffer); + buffer = r_u->buffer; + } DEBUG(4,("_spoolss_getprinterdriver2\n")); @@ -6015,7 +6029,6 @@ static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum) static BOOL add_printer_hook(NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer) { - extern userdom_struct current_user_info; char *cmd = lp_addprinter_cmd(); char **qlines; pstring command; @@ -6389,8 +6402,10 @@ WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u) WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u) { - /* that's an [in out] buffer (despite appearences to the contrary) */ - spoolss_move_buffer(q_u->buffer, &r_u->buffer); + /* that's an [in out] buffer */ + + if ( q_u->buffer ) + rpcbuf_move(q_u->buffer, &r_u->buffer); r_u->needed = 0; return WERR_INVALID_PARAM; /* this is what a NT server @@ -6476,11 +6491,12 @@ static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue, static WERROR enumjobs_level1(print_queue_struct *queue, int snum, NT_PRINTER_INFO_LEVEL *ntprinter, - NEW_BUFFER *buffer, uint32 offered, + RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned) { JOB_INFO_1 *info; int i; + WERROR result = WERR_OK; info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned); if (info==NULL) { @@ -6498,24 +6514,28 @@ static WERROR enumjobs_level1(print_queue_struct *queue, int snum, for (i=0; i<*returned; i++) (*needed) += spoolss_size_job_info_1(&info[i]); - if (!alloc_buffer_size(buffer, *needed)) { - SAFE_FREE(info); - return WERR_INSUFFICIENT_BUFFER; + if (*needed > offered) { + result = WERR_INSUFFICIENT_BUFFER; + goto out; + } + + if (!rpcbuf_alloc_size(buffer, *needed)) { + result = WERR_NOMEM; + goto out; } /* fill the buffer with the structures */ for (i=0; i<*returned; i++) smb_io_job_info_1("", buffer, &info[i], 0); +out: /* clear memory */ SAFE_FREE(info); - if (*needed > offered) { - *returned=0; - return WERR_INSUFFICIENT_BUFFER; - } + if ( !W_ERROR_IS_OK(result) ) + *returned = 0; - return WERR_OK; + return result; } /**************************************************************************** @@ -6524,19 +6544,17 @@ static WERROR enumjobs_level1(print_queue_struct *queue, int snum, static WERROR enumjobs_level2(print_queue_struct *queue, int snum, NT_PRINTER_INFO_LEVEL *ntprinter, - NEW_BUFFER *buffer, uint32 offered, + RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned) { JOB_INFO_2 *info = NULL; int i; - WERROR result; + WERROR result = WERR_OK; DEVICEMODE *devmode = NULL; - info=SMB_MALLOC_ARRAY(JOB_INFO_2,*returned); - if (info==NULL) { + if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) { *returned=0; - result = WERR_NOMEM; - goto done; + return WERR_NOMEM; } /* this should not be a failure condition if the devmode is NULL */ @@ -6544,8 +6562,7 @@ static WERROR enumjobs_level2(print_queue_struct *queue, int snum, devmode = construct_dev_mode(snum); for (i=0; i<*returned; i++) - fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, - devmode); + fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode); free_a_printer(&ntprinter, 2); SAFE_FREE(queue); @@ -6555,29 +6572,26 @@ static WERROR enumjobs_level2(print_queue_struct *queue, int snum, (*needed) += spoolss_size_job_info_2(&info[i]); if (*needed > offered) { - *returned=0; result = WERR_INSUFFICIENT_BUFFER; - goto done; + goto out; } - if (!alloc_buffer_size(buffer, *needed)) { - SAFE_FREE(info); - result = WERR_INSUFFICIENT_BUFFER; - goto done; + if (!rpcbuf_alloc_size(buffer, *needed)) { + result = WERR_NOMEM; + goto out; } /* fill the buffer with the structures */ for (i=0; i<*returned; i++) smb_io_job_info_2("", buffer, &info[i], 0); - result = WERR_OK; - - done: - free_a_printer(&ntprinter, 2); +out: free_devmode(devmode); - SAFE_FREE(queue); SAFE_FREE(info); + if ( !W_ERROR_IS_OK(result) ) + *returned = 0; + return result; } @@ -6590,7 +6604,7 @@ WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJO { POLICY_HND *handle = &q_u->handle; uint32 level = q_u->level; - NEW_BUFFER *buffer = NULL; + RPC_BUFFER *buffer = NULL; uint32 offered = q_u->offered; uint32 *needed = &r_u->needed; uint32 *returned = &r_u->returned; @@ -6601,8 +6615,11 @@ WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJO print_queue_struct *queue=NULL; /* that's an [in out] buffer */ - spoolss_move_buffer(q_u->buffer, &r_u->buffer); - buffer = r_u->buffer; + + if ( q_u->buffer ) { + rpcbuf_move(q_u->buffer, &r_u->buffer); + buffer = r_u->buffer; + } DEBUG(4,("_spoolss_enumjobs\n")); @@ -6703,15 +6720,15 @@ WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u Enumerates all printer drivers at level 1. ****************************************************************************/ -static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned) +static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned) { int i; int ndrivers; uint32 version; fstring *list = NULL; - NT_PRINTER_DRIVER_INFO_LEVEL driver; DRIVER_INFO_1 *tdi1, *driver_info_1=NULL; + WERROR result = WERR_OK; *returned=0; @@ -6757,9 +6774,14 @@ static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]); } - if (!alloc_buffer_size(buffer, *needed)) { - SAFE_FREE(driver_info_1); - return WERR_INSUFFICIENT_BUFFER; + if (*needed > offered) { + result = WERR_INSUFFICIENT_BUFFER; + goto out; + } + + if (!rpcbuf_alloc_size(buffer, *needed)) { + result = WERR_NOMEM; + goto out; } /* fill the buffer with the driver structures */ @@ -6768,29 +6790,28 @@ static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0); } +out: SAFE_FREE(driver_info_1); - if (*needed > offered) { - *returned=0; - return WERR_INSUFFICIENT_BUFFER; - } + if ( !W_ERROR_IS_OK(result) ) + *returned = 0; - return WERR_OK; + return result; } /**************************************************************************** Enumerates all printer drivers at level 2. ****************************************************************************/ -static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned) +static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned) { int i; int ndrivers; uint32 version; fstring *list = NULL; - NT_PRINTER_DRIVER_INFO_LEVEL driver; DRIVER_INFO_2 *tdi2, *driver_info_2=NULL; + WERROR result = WERR_OK; *returned=0; @@ -6837,9 +6858,14 @@ static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i])); } - if (!alloc_buffer_size(buffer, *needed)) { - SAFE_FREE(driver_info_2); - return WERR_INSUFFICIENT_BUFFER; + if (*needed > offered) { + result = WERR_INSUFFICIENT_BUFFER; + goto out; + } + + if (!rpcbuf_alloc_size(buffer, *needed)) { + result = WERR_NOMEM; + goto out; } /* fill the buffer with the form structures */ @@ -6848,29 +6874,28 @@ static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0); } +out: SAFE_FREE(driver_info_2); - if (*needed > offered) { - *returned=0; - return WERR_INSUFFICIENT_BUFFER; - } + if ( !W_ERROR_IS_OK(result) ) + *returned = 0; - return WERR_OK; + return result; } /**************************************************************************** Enumerates all printer drivers at level 3. ****************************************************************************/ -static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned) +static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned) { int i; int ndrivers; uint32 version; fstring *list = NULL; - NT_PRINTER_DRIVER_INFO_LEVEL driver; DRIVER_INFO_3 *tdi3, *driver_info_3=NULL; + WERROR result = WERR_OK; *returned=0; @@ -6917,28 +6942,32 @@ static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]); } - if (!alloc_buffer_size(buffer, *needed)) { - SAFE_FREE(driver_info_3); - return WERR_INSUFFICIENT_BUFFER; + if (*needed > offered) { + result = WERR_INSUFFICIENT_BUFFER; + goto out; } - + + if (!rpcbuf_alloc_size(buffer, *needed)) { + result = WERR_NOMEM; + goto out; + } + /* fill the buffer with the driver structures */ for (i=0; i<*returned; i++) { DEBUGADD(6,("adding driver [%d] to buffer\n",i)); smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0); } +out: for (i=0; i<*returned; i++) SAFE_FREE(driver_info_3[i].dependentfiles); - + SAFE_FREE(driver_info_3); - if (*needed > offered) { - *returned=0; - return WERR_INSUFFICIENT_BUFFER; - } + if ( !W_ERROR_IS_OK(result) ) + *returned = 0; - return WERR_OK; + return result; } /**************************************************************************** @@ -6948,22 +6977,25 @@ static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u) { uint32 level = q_u->level; - NEW_BUFFER *buffer = NULL; + RPC_BUFFER *buffer = NULL; uint32 offered = q_u->offered; uint32 *needed = &r_u->needed; uint32 *returned = &r_u->returned; - fstring *list = NULL; fstring servername; fstring architecture; /* that's an [in out] buffer */ - spoolss_move_buffer(q_u->buffer, &r_u->buffer); - buffer = r_u->buffer; + + if ( q_u->buffer ) { + rpcbuf_move(q_u->buffer, &r_u->buffer); + buffer = r_u->buffer; + } DEBUG(4,("_spoolss_enumprinterdrivers\n")); - *needed=0; - *returned=0; + + *needed = 0; + *returned = 0; unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture)-1); unistr2_to_ascii(servername, &q_u->name, sizeof(servername)-1); @@ -6979,8 +7011,6 @@ WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS case 3: return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned); default: - *returned=0; - SAFE_FREE(list); return WERR_UNKNOWN_LEVEL; } } @@ -7006,7 +7036,7 @@ static void fill_form_1(FORM_1 *form, nt_forms_struct *list) WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u) { uint32 level = q_u->level; - NEW_BUFFER *buffer = NULL; + RPC_BUFFER *buffer = NULL; uint32 offered = q_u->offered; uint32 *needed = &r_u->needed; uint32 *numofforms = &r_u->numofforms; @@ -7019,8 +7049,11 @@ WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMF int i; /* that's an [in out] buffer */ - spoolss_move_buffer(q_u->buffer, &r_u->buffer); - buffer = r_u->buffer; + + if ( q_u->buffer ) { + rpcbuf_move(q_u->buffer, &r_u->buffer); + buffer = r_u->buffer; + } DEBUG(4,("_spoolss_enumforms\n")); DEBUGADD(5,("Offered buffer size [%d]\n", offered)); @@ -7032,7 +7065,8 @@ WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMF DEBUGADD(5,("Number of user forms [%d]\n", *numofforms)); *numofforms += numbuiltinforms; - if (*numofforms == 0) return WERR_NO_MORE_ITEMS; + if (*numofforms == 0) + return WERR_NO_MORE_ITEMS; switch (level) { case 1: @@ -7068,10 +7102,17 @@ WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMF *needed=buffer_size; - if (!alloc_buffer_size(buffer, buffer_size)){ + if (*needed > offered) { SAFE_FREE(forms_1); + *numofforms=0; return WERR_INSUFFICIENT_BUFFER; } + + if (!rpcbuf_alloc_size(buffer, buffer_size)){ + SAFE_FREE(forms_1); + *numofforms=0; + return WERR_NOMEM; + } /* fill the buffer with the form structures */ for (i=0; i offered) { - *numofforms=0; - return WERR_INSUFFICIENT_BUFFER; - } - else - return WERR_OK; + return WERR_OK; default: SAFE_FREE(list); @@ -7107,7 +7143,7 @@ WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM * { uint32 level = q_u->level; UNISTR2 *uni_formname = &q_u->formname; - NEW_BUFFER *buffer = NULL; + RPC_BUFFER *buffer = NULL; uint32 offered = q_u->offered; uint32 *needed = &r_u->needed; @@ -7120,8 +7156,11 @@ WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM * int numofforms=0, i=0; /* that's an [in out] buffer */ - spoolss_move_buffer(q_u->buffer, &r_u->buffer); - buffer = r_u->buffer; + + if ( q_u->buffer ) { + rpcbuf_move(q_u->buffer, &r_u->buffer); + buffer = r_u->buffer; + } unistr2_to_ascii(form_name, uni_formname, sizeof(form_name)-1); @@ -7165,13 +7204,11 @@ WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM * *needed=spoolss_size_form_1(&form_1); - if (!alloc_buffer_size(buffer, buffer_size)){ + if (*needed > offered) return WERR_INSUFFICIENT_BUFFER; - } - if (*needed > offered) { - return WERR_INSUFFICIENT_BUFFER; - } + if (!rpcbuf_alloc_size(buffer, buffer_size)) + return WERR_NOMEM; /* fill the buffer with the form structures */ DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i)); @@ -7209,10 +7246,11 @@ static void fill_port_2(PORT_INFO_2 *port, const char *name) enumports level 1. ****************************************************************************/ -static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned) +static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned) { PORT_INFO_1 *ports=NULL; int i=0; + WERROR result = WERR_OK; if (*lp_enumports_cmd()) { char *cmd = lp_enumports_cmd(); @@ -7274,9 +7312,14 @@ static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *need *needed += spoolss_size_port_info_1(&ports[i]); } - if (!alloc_buffer_size(buffer, *needed)) { - SAFE_FREE(ports); - return WERR_INSUFFICIENT_BUFFER; + if (*needed > offered) { + result = WERR_INSUFFICIENT_BUFFER; + goto out; + } + + if (!rpcbuf_alloc_size(buffer, *needed)) { + result = WERR_NOMEM; + goto out; } /* fill the buffer with the ports structures */ @@ -7285,24 +7328,24 @@ static WERROR enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *need smb_io_port_1("", buffer, &ports[i], 0); } +out: SAFE_FREE(ports); - if (*needed > offered) { - *returned=0; - return WERR_INSUFFICIENT_BUFFER; - } + if ( !W_ERROR_IS_OK(result) ) + *returned = 0; - return WERR_OK; + return result; } /**************************************************************************** enumports level 2. ****************************************************************************/ -static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned) +static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned) { PORT_INFO_2 *ports=NULL; int i=0; + WERROR result = WERR_OK; if (*lp_enumports_cmd()) { char *cmd = lp_enumports_cmd(); @@ -7372,9 +7415,14 @@ static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *need *needed += spoolss_size_port_info_2(&ports[i]); } - if (!alloc_buffer_size(buffer, *needed)) { - SAFE_FREE(ports); - return WERR_INSUFFICIENT_BUFFER; + if (*needed > offered) { + result = WERR_INSUFFICIENT_BUFFER; + goto out; + } + + if (!rpcbuf_alloc_size(buffer, *needed)) { + result = WERR_NOMEM; + goto out; } /* fill the buffer with the ports structures */ @@ -7383,14 +7431,13 @@ static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *need smb_io_port_2("", buffer, &ports[i], 0); } +out: SAFE_FREE(ports); - if (*needed > offered) { - *returned=0; - return WERR_INSUFFICIENT_BUFFER; - } + if ( !W_ERROR_IS_OK(result) ) + *returned = 0; - return WERR_OK; + return result; } /**************************************************************************** @@ -7400,14 +7447,17 @@ static WERROR enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *need WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u) { uint32 level = q_u->level; - NEW_BUFFER *buffer = NULL; + RPC_BUFFER *buffer = NULL; uint32 offered = q_u->offered; uint32 *needed = &r_u->needed; uint32 *returned = &r_u->returned; /* that's an [in out] buffer */ - spoolss_move_buffer(q_u->buffer, &r_u->buffer); - buffer = r_u->buffer; + + if ( q_u->buffer ) { + rpcbuf_move(q_u->buffer, &r_u->buffer); + buffer = r_u->buffer; + } DEBUG(4,("_spoolss_enumports\n")); @@ -7543,7 +7593,7 @@ static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_ WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u) { - UNISTR2 *uni_srv_name = &q_u->server_name; + UNISTR2 *uni_srv_name = q_u->server_name; uint32 level = q_u->level; SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info; DEVICEMODE *devmode = q_u->devmode_ctr.devmode; @@ -7741,7 +7791,7 @@ static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name) /**************************************************************************** ****************************************************************************/ -static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, NEW_BUFFER *buffer, uint32 offered, uint32 *needed) +static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, RPC_BUFFER *buffer, uint32 offered, uint32 *needed) { pstring path; pstring long_archi; @@ -7749,6 +7799,7 @@ static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environmen char *pservername; const char *short_archi; DRIVER_DIRECTORY_1 *info=NULL; + WERROR result = WERR_OK; unistr2_to_ascii(servername, name, sizeof(servername)-1); unistr2_to_ascii(long_archi, uni_environment, sizeof(long_archi)-1); @@ -7778,19 +7829,22 @@ static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environmen *needed += spoolss_size_driverdir_info_1(info); - if (!alloc_buffer_size(buffer, *needed)) { - SAFE_FREE(info); - return WERR_INSUFFICIENT_BUFFER; + if (*needed > offered) { + result = WERR_INSUFFICIENT_BUFFER; + goto out; + } + + if (!rpcbuf_alloc_size(buffer, *needed)) { + result = WERR_NOMEM; + goto out; } smb_io_driverdir_1("", buffer, info, 0); +out: SAFE_FREE(info); - if (*needed > offered) - return WERR_INSUFFICIENT_BUFFER; - - return WERR_OK; + return result; } /**************************************************************************** @@ -7801,13 +7855,16 @@ WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRI UNISTR2 *name = &q_u->name; UNISTR2 *uni_environment = &q_u->environment; uint32 level = q_u->level; - NEW_BUFFER *buffer = NULL; + RPC_BUFFER *buffer = NULL; uint32 offered = q_u->offered; uint32 *needed = &r_u->needed; /* that's an [in out] buffer */ - spoolss_move_buffer(q_u->buffer, &r_u->buffer); - buffer = r_u->buffer; + + if ( q_u->buffer ) { + rpcbuf_move(q_u->buffer, &r_u->buffer); + buffer = r_u->buffer; + } DEBUG(4,("_spoolss_getprinterdriverdirectory\n")); @@ -8367,9 +8424,10 @@ done: enumprintprocessors level 1. ****************************************************************************/ -static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned) +static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned) { PRINTPROCESSOR_1 *info_1=NULL; + WERROR result = WERR_OK; if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL) return WERR_NOMEM; @@ -8380,19 +8438,25 @@ static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, ui *needed += spoolss_size_printprocessor_info_1(info_1); - if (!alloc_buffer_size(buffer, *needed)) - return WERR_INSUFFICIENT_BUFFER; + if (*needed > offered) { + result = WERR_INSUFFICIENT_BUFFER; + goto out; + } + + if (!rpcbuf_alloc_size(buffer, *needed)) { + result = WERR_NOMEM; + goto out; + } smb_io_printprocessor_info_1("", buffer, info_1, 0); +out: SAFE_FREE(info_1); - if (*needed > offered) { - *returned=0; - return WERR_INSUFFICIENT_BUFFER; - } + if ( !W_ERROR_IS_OK(result) ) + *returned = 0; - return WERR_OK; + return result; } /**************************************************************************** @@ -8401,14 +8465,17 @@ static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, ui WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u) { uint32 level = q_u->level; - NEW_BUFFER *buffer = NULL; + RPC_BUFFER *buffer = NULL; uint32 offered = q_u->offered; uint32 *needed = &r_u->needed; uint32 *returned = &r_u->returned; /* that's an [in out] buffer */ - spoolss_move_buffer(q_u->buffer, &r_u->buffer); - buffer = r_u->buffer; + + if ( q_u->buffer ) { + rpcbuf_move(q_u->buffer, &r_u->buffer); + buffer = r_u->buffer; + } DEBUG(5,("spoolss_enumprintprocessors\n")); @@ -8434,9 +8501,10 @@ WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS enumprintprocdatatypes level 1. ****************************************************************************/ -static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned) +static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned) { PRINTPROCDATATYPE_1 *info_1=NULL; + WERROR result = WERR_NOMEM; if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL) return WERR_NOMEM; @@ -8447,19 +8515,25 @@ static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, *needed += spoolss_size_printprocdatatype_info_1(info_1); - if (!alloc_buffer_size(buffer, *needed)) - return WERR_INSUFFICIENT_BUFFER; + if (*needed > offered) { + result = WERR_INSUFFICIENT_BUFFER; + goto out; + } + + if (!rpcbuf_alloc_size(buffer, *needed)) { + result = WERR_NOMEM; + goto out; + } smb_io_printprocdatatype_info_1("", buffer, info_1, 0); +out: SAFE_FREE(info_1); - if (*needed > offered) { - *returned=0; - return WERR_INSUFFICIENT_BUFFER; - } + if ( !W_ERROR_IS_OK(result) ) + *returned = 0; - return WERR_OK; + return result; } /**************************************************************************** @@ -8468,14 +8542,17 @@ static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u) { uint32 level = q_u->level; - NEW_BUFFER *buffer = NULL; + RPC_BUFFER *buffer = NULL; uint32 offered = q_u->offered; uint32 *needed = &r_u->needed; uint32 *returned = &r_u->returned; /* that's an [in out] buffer */ - spoolss_move_buffer(q_u->buffer, &r_u->buffer); - buffer = r_u->buffer; + + if ( q_u->buffer ) { + rpcbuf_move(q_u->buffer, &r_u->buffer); + buffer = r_u->buffer; + } DEBUG(5,("_spoolss_enumprintprocdatatypes\n")); @@ -8494,9 +8571,10 @@ WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDAT enumprintmonitors level 1. ****************************************************************************/ -static WERROR enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned) +static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned) { PRINTMONITOR_1 *info_1=NULL; + WERROR result = WERR_OK; if((info_1 = SMB_MALLOC_P(PRINTMONITOR_1)) == NULL) return WERR_NOMEM; @@ -8507,28 +8585,35 @@ static WERROR enumprintmonitors_level_1(NEW_BUFFER *buffer, uint32 offered, uint *needed += spoolss_size_printmonitor_info_1(info_1); - if (!alloc_buffer_size(buffer, *needed)) - return WERR_INSUFFICIENT_BUFFER; + if (*needed > offered) { + result = WERR_INSUFFICIENT_BUFFER; + goto out; + } + + if (!rpcbuf_alloc_size(buffer, *needed)) { + result = WERR_NOMEM; + goto out; + } smb_io_printmonitor_info_1("", buffer, info_1, 0); +out: SAFE_FREE(info_1); - if (*needed > offered) { - *returned=0; - return WERR_INSUFFICIENT_BUFFER; - } + if ( !W_ERROR_IS_OK(result) ) + *returned = 0; - return WERR_OK; + return result; } /**************************************************************************** enumprintmonitors level 2. ****************************************************************************/ -static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned) +static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned) { PRINTMONITOR_2 *info_2=NULL; + WERROR result = WERR_OK; if((info_2 = SMB_MALLOC_P(PRINTMONITOR_2)) == NULL) return WERR_NOMEM; @@ -8541,19 +8626,25 @@ static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint *needed += spoolss_size_printmonitor_info_2(info_2); - if (!alloc_buffer_size(buffer, *needed)) - return WERR_INSUFFICIENT_BUFFER; + if (*needed > offered) { + result = WERR_INSUFFICIENT_BUFFER; + goto out; + } + + if (!rpcbuf_alloc_size(buffer, *needed)) { + result = WERR_NOMEM; + goto out; + } smb_io_printmonitor_info_2("", buffer, info_2, 0); +out: SAFE_FREE(info_2); - if (*needed > offered) { - *returned=0; - return WERR_INSUFFICIENT_BUFFER; - } - - return WERR_OK; + if ( !W_ERROR_IS_OK(result) ) + *returned = 0; + + return result; } /**************************************************************************** @@ -8562,14 +8653,17 @@ static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u) { uint32 level = q_u->level; - NEW_BUFFER *buffer = NULL; + RPC_BUFFER *buffer = NULL; uint32 offered = q_u->offered; uint32 *needed = &r_u->needed; uint32 *returned = &r_u->returned; /* that's an [in out] buffer */ - spoolss_move_buffer(q_u->buffer, &r_u->buffer); - buffer = r_u->buffer; + + if ( q_u->buffer ) { + rpcbuf_move(q_u->buffer, &r_u->buffer); + buffer = r_u->buffer; + } DEBUG(5,("spoolss_enumprintmonitors\n")); @@ -8598,12 +8692,13 @@ WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_ static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum, NT_PRINTER_INFO_LEVEL *ntprinter, - uint32 jobid, NEW_BUFFER *buffer, uint32 offered, + uint32 jobid, RPC_BUFFER *buffer, uint32 offered, uint32 *needed) { int i=0; BOOL found=False; JOB_INFO_1 *info_1=NULL; + WERROR result = WERR_OK; info_1=SMB_MALLOC_P(JOB_INFO_1); @@ -8626,19 +8721,22 @@ static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum, *needed += spoolss_size_job_info_1(info_1); - if (!alloc_buffer_size(buffer, *needed)) { - SAFE_FREE(info_1); - return WERR_INSUFFICIENT_BUFFER; + if (*needed > offered) { + result = WERR_INSUFFICIENT_BUFFER; + goto out; + } + + if (!rpcbuf_alloc_size(buffer, *needed)) { + result = WERR_NOMEM; + goto out; } smb_io_job_info_1("", buffer, info_1, 0); +out: SAFE_FREE(info_1); - if (*needed > offered) - return WERR_INSUFFICIENT_BUFFER; - - return WERR_OK; + return result; } /**************************************************************************** @@ -8646,36 +8744,31 @@ static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum, static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum, NT_PRINTER_INFO_LEVEL *ntprinter, - uint32 jobid, NEW_BUFFER *buffer, uint32 offered, + uint32 jobid, RPC_BUFFER *buffer, uint32 offered, uint32 *needed) { int i = 0; BOOL found = False; JOB_INFO_2 *info_2; - WERROR ret; + WERROR result; DEVICEMODE *devmode = NULL; NT_DEVICEMODE *nt_devmode = NULL; - info_2=SMB_MALLOC_P(JOB_INFO_2); + if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) ) + return WERR_NOMEM; ZERO_STRUCTP(info_2); - if (info_2 == NULL) { - ret = WERR_NOMEM; - goto done; - } - for ( i=0; i offered) { + result = WERR_INSUFFICIENT_BUFFER; goto done; } - smb_io_job_info_2("", buffer, info_2, 0); - - if (*needed > offered) { - ret = WERR_INSUFFICIENT_BUFFER; + if (!rpcbuf_alloc_size(buffer, *needed)) { + result = WERR_NOMEM; goto done; } - ret = WERR_OK; + smb_io_job_info_2("", buffer, info_2, 0); + + result = WERR_OK; done: /* Cleanup allocated memory */ @@ -8718,7 +8811,7 @@ static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum, free_job_info_2(info_2); /* Also frees devmode */ SAFE_FREE(info_2); - return ret; + return result; } /**************************************************************************** @@ -8729,7 +8822,7 @@ WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_ POLICY_HND *handle = &q_u->handle; uint32 jobid = q_u->jobid; uint32 level = q_u->level; - NEW_BUFFER *buffer = NULL; + RPC_BUFFER *buffer = NULL; uint32 offered = q_u->offered; uint32 *needed = &r_u->needed; WERROR wstatus = WERR_OK; @@ -8740,8 +8833,11 @@ WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_ print_status_struct prt_status; /* that's an [in out] buffer */ - spoolss_move_buffer(q_u->buffer, &r_u->buffer); - buffer = r_u->buffer; + + if ( q_u->buffer ) { + rpcbuf_move(q_u->buffer, &r_u->buffer); + buffer = r_u->buffer; + } DEBUG(5,("spoolss_getjob\n")); @@ -9307,13 +9403,14 @@ static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, cha static WERROR getprintprocessordirectory_level_1(UNISTR2 *name, UNISTR2 *environment, - NEW_BUFFER *buffer, + RPC_BUFFER *buffer, uint32 offered, uint32 *needed) { pstring path; pstring long_archi; PRINTPROCESSOR_DIRECTORY_1 *info=NULL; + WERROR result = WERR_OK; unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1); @@ -9329,32 +9426,38 @@ static WERROR getprintprocessordirectory_level_1(UNISTR2 *name, *needed += spoolss_size_printprocessordirectory_info_1(info); - if (!alloc_buffer_size(buffer, *needed)) { - safe_free(info); - return WERR_INSUFFICIENT_BUFFER; + if (*needed > offered) { + result = WERR_INSUFFICIENT_BUFFER; + goto out; + } + + if (!rpcbuf_alloc_size(buffer, *needed)) { + result = WERR_INSUFFICIENT_BUFFER; + goto out; } smb_io_printprocessordirectory_1("", buffer, info, 0); - safe_free(info); +out: + SAFE_FREE(info); - if (*needed > offered) - return WERR_INSUFFICIENT_BUFFER; - else - return WERR_OK; + return result; } WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u) { uint32 level = q_u->level; - NEW_BUFFER *buffer = NULL; + RPC_BUFFER *buffer = NULL; uint32 offered = q_u->offered; uint32 *needed = &r_u->needed; WERROR result; /* that's an [in out] buffer */ - spoolss_move_buffer(q_u->buffer, &r_u->buffer); - buffer = r_u->buffer; + + if ( q_u->buffer ) { + rpcbuf_move(q_u->buffer, &r_u->buffer); + buffer = r_u->buffer; + } DEBUG(5,("_spoolss_getprintprocessordirectory\n")); diff --git a/source/rpc_server/srv_srvsvc.c b/source/rpc_server/srv_srvsvc.c index 9d85088e568..0b4eac5cc73 100644 --- a/source/rpc_server/srv_srvsvc.c +++ b/source/rpc_server/srv_srvsvc.c @@ -165,6 +165,34 @@ static BOOL api_srv_net_sess_enum(pipes_struct *p) return True; } +/******************************************************************* + Delete session. +********************************************************************/ + +static BOOL api_srv_net_sess_del(pipes_struct *p) +{ + SRV_Q_NET_SESS_DEL q_u; + SRV_R_NET_SESS_DEL r_u; + prs_struct *data = &p->in_data.data; + prs_struct *rdata = &p->out_data.rdata; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + /* grab the net server get enum */ + if (!srv_io_q_net_sess_del("", &q_u, data, 0)) + return False; + + /* construct reply. always indicate success */ + r_u.status = _srv_net_sess_del(p, &q_u, &r_u); + + /* store the response in the SMB stream */ + if (!srv_io_r_net_sess_del("", &r_u, rdata, 0)) + return False; + + return True; +} + /******************************************************************* RPC to enumerate shares. ********************************************************************/ @@ -530,6 +558,7 @@ static struct api_struct api_srv_cmds[] = { { "SRV_NET_CONN_ENUM" , SRV_NET_CONN_ENUM , api_srv_net_conn_enum }, { "SRV_NET_SESS_ENUM" , SRV_NET_SESS_ENUM , api_srv_net_sess_enum }, + { "SRV_NET_SESS_DEL" , SRV_NET_SESS_DEL , api_srv_net_sess_del }, { "SRV_NET_SHARE_ENUM_ALL" , SRV_NET_SHARE_ENUM_ALL , api_srv_net_share_enum_all }, { "SRV_NET_SHARE_ENUM" , SRV_NET_SHARE_ENUM , api_srv_net_share_enum }, { "SRV_NET_SHARE_ADD" , SRV_NET_SHARE_ADD , api_srv_net_share_add }, diff --git a/source/rpc_server/srv_srvsvc_nt.c b/source/rpc_server/srv_srvsvc_nt.c index 13e1971925a..b5768a09af0 100644 --- a/source/rpc_server/srv_srvsvc_nt.c +++ b/source/rpc_server/srv_srvsvc_nt.c @@ -24,6 +24,8 @@ #include "includes.h" +extern struct generic_mapping file_generic_mapping; + #undef DBGC_CLASS #define DBGC_CLASS DBGC_RPC_SRV @@ -170,8 +172,6 @@ BOOL share_info_db_init(void) static SEC_DESC *get_share_security_default( TALLOC_CTX *ctx, int snum, size_t *psize) { - extern DOM_SID global_sid_World; - extern struct generic_mapping file_generic_mapping; SEC_ACCESS sa; SEC_ACE ace; SEC_ACL *psa = NULL; @@ -293,7 +293,6 @@ static BOOL delete_share_security(int snum) void map_generic_share_sd_bits(SEC_DESC *psd) { - extern struct generic_mapping file_generic_mapping; int i; SEC_ACL *ps_dacl = NULL; @@ -1348,6 +1347,70 @@ WERROR _srv_net_sess_enum(pipes_struct *p, SRV_Q_NET_SESS_ENUM *q_u, SRV_R_NET_S return r_u->status; } +/******************************************************************* +net sess del +********************************************************************/ + +WERROR _srv_net_sess_del(pipes_struct *p, SRV_Q_NET_SESS_DEL *q_u, SRV_R_NET_SESS_DEL *r_u) +{ + struct sessionid *session_list; + struct current_user user; + int num_sessions, snum, ret; + fstring username; + fstring machine; + BOOL not_root = False; + + rpcstr_pull_unistr2_fstring(username, &q_u->uni_user_name); + rpcstr_pull_unistr2_fstring(machine, &q_u->uni_cli_name); + + /* strip leading backslashes if any */ + while (machine[0] == '\\') { + memmove(machine, &machine[1], strlen(machine)); + } + + num_sessions = list_sessions(&session_list); + + DEBUG(5,("_srv_net_sess_del: %d\n", __LINE__)); + + r_u->status = WERR_ACCESS_DENIED; + + get_current_user(&user, p); + + /* fail out now if you are not root or not a domain admin */ + + if ((user.uid != sec_initial_uid()) && + ( ! nt_token_check_domain_rid(p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS))) { + + goto done; + } + + for (snum = 0; snum < num_sessions; snum++) { + + if ((strequal(session_list[snum].username, username) || username[0] == '\0' ) && + strequal(session_list[snum].remote_machine, machine)) { + + if (user.uid != sec_initial_uid()) { + not_root = True; + become_root(); + } + + if ((ret = message_send_pid(session_list[snum].pid, MSG_SHUTDOWN, NULL, 0, False))) + r_u->status = WERR_OK; + + if (not_root) + unbecome_root(); + } + } + + DEBUG(5,("_srv_net_sess_del: %d\n", __LINE__)); + + +done: + SAFE_FREE(session_list); + + return r_u->status; +} + /******************************************************************* Net share enum all. ********************************************************************/ @@ -1454,7 +1517,7 @@ WERROR _srv_net_share_set_info(pipes_struct *p, SRV_Q_NET_SHARE_SET_INFO *q_u, S char *path; SEC_DESC *psd = NULL; SE_PRIV se_diskop = SE_DISK_OPERATOR; - BOOL is_disk_op; + BOOL is_disk_op = False; DEBUG(5,("_srv_net_share_set_info: %d\n", __LINE__)); diff --git a/source/rpc_server/srv_svcctl.c b/source/rpc_server/srv_svcctl.c new file mode 100644 index 00000000000..85fb9f9ce3d --- /dev/null +++ b/source/rpc_server/srv_svcctl.c @@ -0,0 +1,294 @@ +/* + * Unix SMB/CIFS implementation. + * RPC Pipe client / server routines + * Copyright (C) Gerald Carter 2005. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "includes.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_RPC_SRV + +/******************************************************************* + ********************************************************************/ + +static BOOL api_svcctl_close_service(pipes_struct *p) +{ + SVCCTL_Q_CLOSE_SERVICE q_u; + SVCCTL_R_CLOSE_SERVICE r_u; + prs_struct *data = &p->in_data.data; + prs_struct *rdata = &p->out_data.rdata; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + if(!svcctl_io_q_close_service("", &q_u, data, 0)) + return False; + + r_u.status = _svcctl_close_service(p, &q_u, &r_u); + + if(!svcctl_io_r_close_service("", &r_u, rdata, 0)) + return False; + + return True; +} + +/******************************************************************* + ********************************************************************/ + +static BOOL api_svcctl_open_scmanager(pipes_struct *p) +{ + SVCCTL_Q_OPEN_SCMANAGER q_u; + SVCCTL_R_OPEN_SCMANAGER r_u; + prs_struct *data = &p->in_data.data; + prs_struct *rdata = &p->out_data.rdata; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + if(!svcctl_io_q_open_scmanager("", &q_u, data, 0)) + return False; + + r_u.status = _svcctl_open_scmanager(p, &q_u, &r_u); + + if(!svcctl_io_r_open_scmanager("", &r_u, rdata, 0)) + return False; + + return True; +} + +/******************************************************************* + ********************************************************************/ + +static BOOL api_svcctl_open_service(pipes_struct *p) +{ + SVCCTL_Q_OPEN_SERVICE q_u; + SVCCTL_R_OPEN_SERVICE r_u; + prs_struct *data = &p->in_data.data; + prs_struct *rdata = &p->out_data.rdata; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + if(!svcctl_io_q_open_service("", &q_u, data, 0)) + return False; + + r_u.status = _svcctl_open_service(p, &q_u, &r_u); + + if(!svcctl_io_r_open_service("", &r_u, rdata, 0)) + return False; + + return True; +} + +/******************************************************************* + ********************************************************************/ + +static BOOL api_svcctl_get_display_name(pipes_struct *p) +{ + SVCCTL_Q_GET_DISPLAY_NAME q_u; + SVCCTL_R_GET_DISPLAY_NAME r_u; + prs_struct *data = &p->in_data.data; + prs_struct *rdata = &p->out_data.rdata; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + if(!svcctl_io_q_get_display_name("", &q_u, data, 0)) + return False; + + r_u.status = _svcctl_get_display_name(p, &q_u, &r_u); + + if(!svcctl_io_r_get_display_name("", &r_u, rdata, 0)) + return False; + + return True; +} + +/******************************************************************* + ********************************************************************/ + +static BOOL api_svcctl_query_status(pipes_struct *p) +{ + SVCCTL_Q_QUERY_STATUS q_u; + SVCCTL_R_QUERY_STATUS r_u; + prs_struct *data = &p->in_data.data; + prs_struct *rdata = &p->out_data.rdata; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + if(!svcctl_io_q_query_status("", &q_u, data, 0)) + return False; + + r_u.status = _svcctl_query_status(p, &q_u, &r_u); + + if(!svcctl_io_r_query_status("", &r_u, rdata, 0)) + return False; + + return True; +} + +/******************************************************************* + ********************************************************************/ + +static BOOL api_svcctl_enum_services_status(pipes_struct *p) +{ + SVCCTL_Q_ENUM_SERVICES_STATUS q_u; + SVCCTL_R_ENUM_SERVICES_STATUS r_u; + prs_struct *data = &p->in_data.data; + prs_struct *rdata = &p->out_data.rdata; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + if(!svcctl_io_q_enum_services_status("", &q_u, data, 0)) + return False; + + r_u.status = _svcctl_enum_services_status(p, &q_u, &r_u); + + if(!svcctl_io_r_enum_services_status("", &r_u, rdata, 0)) + return False; + + return True; +} + +/******************************************************************* + ********************************************************************/ + +static BOOL api_svcctl_enum_dependent_services(pipes_struct *p) +{ + SVCCTL_Q_ENUM_DEPENDENT_SERVICES q_u; + SVCCTL_R_ENUM_DEPENDENT_SERVICES r_u; + prs_struct *data = &p->in_data.data; + prs_struct *rdata = &p->out_data.rdata; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + if(!svcctl_io_q_enum_dependent_services("", &q_u, data, 0)) + return False; + + r_u.status = _svcctl_enum_dependent_services(p, &q_u, &r_u); + + if(!svcctl_io_r_enum_dependent_services("", &r_u, rdata, 0)) + return False; + + return True; +} + +/******************************************************************* + ********************************************************************/ + +static BOOL api_svcctl_start_service(pipes_struct *p) +{ + SVCCTL_Q_START_SERVICE q_u; + SVCCTL_R_START_SERVICE r_u; + prs_struct *data = &p->in_data.data; + prs_struct *rdata = &p->out_data.rdata; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + if(!svcctl_io_q_start_service("", &q_u, data, 0)) + return False; + + r_u.status = _svcctl_start_service(p, &q_u, &r_u); + + if(!svcctl_io_r_start_service("", &r_u, rdata, 0)) + return False; + + return True; +} + +/******************************************************************* + ********************************************************************/ + +static BOOL api_svcctl_control_service(pipes_struct *p) +{ + SVCCTL_Q_CONTROL_SERVICE q_u; + SVCCTL_R_CONTROL_SERVICE r_u; + prs_struct *data = &p->in_data.data; + prs_struct *rdata = &p->out_data.rdata; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + if(!svcctl_io_q_control_service("", &q_u, data, 0)) + return False; + + r_u.status = _svcctl_control_service(p, &q_u, &r_u); + + if(!svcctl_io_r_control_service("", &r_u, rdata, 0)) + return False; + + return True; +} + +/******************************************************************* + ********************************************************************/ + +static BOOL api_svcctl_query_service_config(pipes_struct *p) +{ + SVCCTL_Q_QUERY_SERVICE_CONFIG q_u; + SVCCTL_R_QUERY_SERVICE_CONFIG r_u; + prs_struct *data = &p->in_data.data; + prs_struct *rdata = &p->out_data.rdata; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + if(!svcctl_io_q_query_service_config("", &q_u, data, 0)) + return False; + + r_u.status = _svcctl_query_service_config(p, &q_u, &r_u); + + if(!svcctl_io_r_query_service_config("", &r_u, rdata, 0)) + return False; + + return True; +} + +/******************************************************************* + \PIPE\svcctl commands + ********************************************************************/ + +static struct api_struct api_svcctl_cmds[] = +{ + { "SVCCTL_CLOSE_SERVICE" , SVCCTL_CLOSE_SERVICE , api_svcctl_close_service }, + { "SVCCTL_OPEN_SCMANAGER_W" , SVCCTL_OPEN_SCMANAGER_W , api_svcctl_open_scmanager }, + { "SVCCTL_OPEN_SERVICE_W" , SVCCTL_OPEN_SERVICE_W , api_svcctl_open_service }, + { "SVCCTL_GET_DISPLAY_NAME" , SVCCTL_GET_DISPLAY_NAME , api_svcctl_get_display_name }, + { "SVCCTL_QUERY_STATUS" , SVCCTL_QUERY_STATUS , api_svcctl_query_status }, + { "SVCCTL_QUERY_SERVICE_CONFIG_W", SVCCTL_QUERY_SERVICE_CONFIG_W, api_svcctl_query_service_config }, + { "SVCCTL_ENUM_SERVICES_STATUS_W", SVCCTL_ENUM_SERVICES_STATUS_W, api_svcctl_enum_services_status }, + { "SVCCTL_ENUM_DEPENDENT_SERVICES_W", SVCCTL_ENUM_DEPENDENT_SERVICES_W, api_svcctl_enum_dependent_services }, + { "SVCCTL_START_SERVICE_W" , SVCCTL_START_SERVICE_W , api_svcctl_start_service }, + { "SVCCTL_CONTROL_SERVICE" , SVCCTL_CONTROL_SERVICE , api_svcctl_control_service } +}; + +void svcctl_get_pipe_fns( struct api_struct **fns, int *n_fns ) +{ + *fns = api_svcctl_cmds; + *n_fns = sizeof(api_svcctl_cmds) / sizeof(struct api_struct); +} + +NTSTATUS rpc_svcctl_init(void) +{ + return rpc_pipe_register_commands(SMB_RPC_INTERFACE_VERSION, "svcctl", "ntsvcs", api_svcctl_cmds, + sizeof(api_svcctl_cmds) / sizeof(struct api_struct)); +} diff --git a/source/rpc_server/srv_svcctl_nt.c b/source/rpc_server/srv_svcctl_nt.c new file mode 100644 index 00000000000..a76e68a312c --- /dev/null +++ b/source/rpc_server/srv_svcctl_nt.c @@ -0,0 +1,295 @@ +/* + * Unix SMB/CIFS implementation. + * RPC Pipe client / server routines + * Copyright (C) Gerald (Jerry) Carter 2005 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "includes.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_RPC_SRV + +/* + * sertup the \PIPE\svcctl db API + */ + +#define SCVCTL_DATABASE_VERSION_V1 1 + +/******************************************************************** +********************************************************************/ + +#if 0 /* unused static function and static variable*/ + +static TDB_CONTEXT *svcctl_tdb; /* used for share security descriptors */ + +static BOOL init_svcctl_db( void ) +{ + static pid_t local_pid; + const char *vstring = "INFO/version"; + + /* see if we've already opened the tdb */ + + if (svcctl_tdb && local_pid == sys_getpid()) + return True; + + /* so open it */ + if ( !(svcctl_tdb = tdb_open_log(lock_path("svcctl.tdb"), 0, TDB_DEFAULT, + O_RDWR|O_CREAT, 0600))) + { + DEBUG(0,("Failed to open svcctl database %s (%s)\n", + lock_path("svcctl.tdb"), strerror(errno) )); + return False; + } + + local_pid = sys_getpid(); + + /***** BEGIN Check the tdb version ******/ + + tdb_lock_bystring(svcctl_tdb, vstring, 0); + + if ( tdb_fetch_int32(svcctl_tdb, vstring) != SCVCTL_DATABASE_VERSION_V1 ) + tdb_store_int32(svcctl_tdb, vstring, SCVCTL_DATABASE_VERSION_V1); + + tdb_unlock_bystring(svcctl_tdb, vstring); + + /***** END Check the tdb version ******/ + + return True; +} + +#endif + +/******************************************************************** + TODO + (a) get and set security descriptors on services + (b) read and write QUERY_SERVICE_CONFIG structures + (c) create default secdesc objects for services and SCM + (d) check access control masks with se_access_check() + (e) implement SERVICE * for associating with open handles +********************************************************************/ + +/******************************************************************** +********************************************************************/ + +WERROR _svcctl_open_scmanager(pipes_struct *p, SVCCTL_Q_OPEN_SCMANAGER *q_u, SVCCTL_R_OPEN_SCMANAGER *r_u) +{ + /* just fake it for now */ + + if ( !create_policy_hnd( p, &r_u->handle, NULL, NULL ) ) + return WERR_ACCESS_DENIED; + + return WERR_OK; +} + +/******************************************************************** +********************************************************************/ + +WERROR _svcctl_open_service(pipes_struct *p, SVCCTL_Q_OPEN_SERVICE *q_u, SVCCTL_R_OPEN_SERVICE *r_u) +{ + fstring service; + + rpcstr_pull(service, q_u->servicename.buffer, sizeof(service), q_u->servicename.uni_str_len*2, 0); + + /* can only be called on service name (not displayname) */ + + if ( !(strequal( service, "NETLOGON") || strequal(service, "Spooler")) ) + return WERR_NO_SUCH_SERVICE; + + if ( !create_policy_hnd( p, &r_u->handle, NULL, NULL ) ) + return WERR_ACCESS_DENIED; + + return WERR_OK; +} + +/******************************************************************** +********************************************************************/ + +WERROR _svcctl_close_service(pipes_struct *p, SVCCTL_Q_CLOSE_SERVICE *q_u, SVCCTL_R_CLOSE_SERVICE *r_u) +{ + if ( !close_policy_hnd( p, &q_u->handle ) ) + return WERR_BADFID; + + return WERR_OK; +} + +/******************************************************************** +********************************************************************/ + +WERROR _svcctl_get_display_name(pipes_struct *p, SVCCTL_Q_GET_DISPLAY_NAME *q_u, SVCCTL_R_GET_DISPLAY_NAME *r_u) +{ + fstring service; + fstring displayname; + + rpcstr_pull(service, q_u->servicename.buffer, sizeof(service), q_u->servicename.uni_str_len*2, 0); + + DEBUG(10,("_svcctl_get_display_name: service name [%s]\n", service)); + + if ( !strequal( service, "NETLOGON" ) ) + return WERR_ACCESS_DENIED; + + fstrcpy( displayname, "Net Logon"); + init_svcctl_r_get_display_name( r_u, displayname ); + + return WERR_OK; +} + +/******************************************************************** +********************************************************************/ + +WERROR _svcctl_query_status(pipes_struct *p, SVCCTL_Q_QUERY_STATUS *q_u, SVCCTL_R_QUERY_STATUS *r_u) +{ + + r_u->svc_status.type = 0x0110; + r_u->svc_status.state = 0x0004; + r_u->svc_status.controls_accepted = 0x0005; + + return WERR_OK; +} + +/******************************************************************** +********************************************************************/ + +WERROR _svcctl_enum_services_status(pipes_struct *p, SVCCTL_Q_ENUM_SERVICES_STATUS *q_u, SVCCTL_R_ENUM_SERVICES_STATUS *r_u) +{ + ENUM_SERVICES_STATUS *services = NULL; + uint32 num_services = 0; + int i = 0; + size_t buffer_size; + WERROR result = WERR_OK; + + /* num_services = str_list_count( lp_enable_svcctl() ); */ + num_services = 2; + + if ( !(services = TALLOC_ARRAY( p->mem_ctx, ENUM_SERVICES_STATUS, num_services )) ) + return WERR_NOMEM; + + DEBUG(8,("_svcctl_enum_services_status: Enumerating %d services\n", num_services)); + + init_unistr( &services[i].servicename, "Spooler" ); + init_unistr( &services[i].displayname, "Spooler" ); + + services[i].status.type = 0x110; + services[i].status.controls_accepted = 0x0; + services[i].status.win32_exit_code = 0x0; + services[i].status.service_exit_code = 0x0; + services[i].status.check_point = 0x0; + services[i].status.wait_hint = 0x0; + if ( !lp_disable_spoolss() ) + services[i].status.state = SVCCTL_RUNNING; + else + services[i].status.state = SVCCTL_STOPPED; + + i++; + + init_unistr( &services[i].servicename, "Netlogon" ); + init_unistr( &services[i].displayname, "Net Logon" ); + + services[i].status.type = 0x20; + services[i].status.controls_accepted = 0x0; + services[i].status.win32_exit_code = 0x0; + services[i].status.service_exit_code = 0x0; + services[i].status.check_point = 0x0; + services[i].status.wait_hint = 0x0; + if ( lp_servicenumber("NETLOGON") != -1 ) + services[i].status.state = SVCCTL_RUNNING; + else + services[i].status.state = SVCCTL_STOPPED; + + buffer_size = 0; + for (i=0; i q_u->buffer_size ) { + num_services = 0; + result = WERR_MORE_DATA; + } + + /* we have to set the outgoing buffer size to the same as the + incoming buffer size (even in the case of failure */ + + rpcbuf_init( &r_u->buffer, q_u->buffer_size, p->mem_ctx ); + + if ( W_ERROR_IS_OK(result) ) { + for ( i=0; ibuffer, 0 ); + } + + r_u->needed = (buffer_size > q_u->buffer_size) ? buffer_size : q_u->buffer_size; + r_u->returned = num_services; + + if ( !(r_u->resume = TALLOC_P( p->mem_ctx, uint32 )) ) + return WERR_NOMEM; + + *r_u->resume = 0x0; + + return result; +} + +/******************************************************************** +********************************************************************/ + +WERROR _svcctl_start_service(pipes_struct *p, SVCCTL_Q_START_SERVICE *q_u, SVCCTL_R_START_SERVICE *r_u) +{ + return WERR_ACCESS_DENIED; +} + +/******************************************************************** +********************************************************************/ + +WERROR _svcctl_control_service(pipes_struct *p, SVCCTL_Q_CONTROL_SERVICE *q_u, SVCCTL_R_CONTROL_SERVICE *r_u) +{ + return WERR_ACCESS_DENIED; +} + +/******************************************************************** +********************************************************************/ + +WERROR _svcctl_enum_dependent_services( pipes_struct *p, SVCCTL_Q_ENUM_DEPENDENT_SERVICES *q_u, SVCCTL_R_ENUM_DEPENDENT_SERVICES *r_u ) +{ + + /* we have to set the outgoing buffer size to the same as the + incoming buffer size (even in the case of failure */ + + rpcbuf_init( &r_u->buffer, q_u->buffer_size, p->mem_ctx ); + + r_u->needed = q_u->buffer_size; + + /* no dependent services...basically a stub function */ + r_u->returned = 0; + + return WERR_OK; +} + +/******************************************************************** +********************************************************************/ + +WERROR _svcctl_query_service_config( pipes_struct *p, SVCCTL_Q_QUERY_SERVICE_CONFIG *q_u, SVCCTL_R_QUERY_SERVICE_CONFIG *r_u ) +{ + + /* we have to set the outgoing buffer size to the same as the + incoming buffer size (even in the case of failure */ + + r_u->needed = q_u->buffer_size; + + /* no dependent services...basically a stub function */ + + return WERR_ACCESS_DENIED; +} + + diff --git a/source/rpc_server/srv_util.c b/source/rpc_server/srv_util.c index 802e7673a40..79d5d06d23a 100644 --- a/source/rpc_server/srv_util.c +++ b/source/rpc_server/srv_util.c @@ -42,6 +42,7 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_RPC_SRV +#if 0 /* these aren't used currently but are here if you need them */ /* * A list of the rids of well known BUILTIN and Domain users * and groups. @@ -78,7 +79,7 @@ static const rid_name domain_group_rids[] = { DOMAIN_GROUP_RID_GUESTS , "Domain Guests" }, { 0 , NULL } }; - +#endif /******************************************************************* gets a domain user's groups from their already-calculated NT_USER_TOKEN diff --git a/source/rpcclient/cmd_reg.c b/source/rpcclient/cmd_reg.c index 7b9bb9b39e5..fcc18cd9f52 100644 --- a/source/rpcclient/cmd_reg.c +++ b/source/rpcclient/cmd_reg.c @@ -57,6 +57,7 @@ static void cmd_reg_enum(struct client_info *info) POLICY_HND key_pol; fstring full_keyname; fstring key_name; + uint32 reg_type; /* * query key info @@ -87,6 +88,11 @@ static void cmd_reg_enum(struct client_info *info) return; } + if (!reg_split_key(full_keyname, ®_type, key_name)) { + fprintf(out_hnd, "Unknown registry hive '%s'\n", key_name); + return; + } + /* open WINREG session. */ res = res ? cli_nt_session_open(smb_cli, PI_WINREG) : False; @@ -130,7 +136,7 @@ static void cmd_reg_enum(struct client_info *info) time_t key_mod_time; /* unknown 1a it */ - res2 = res1 ? do_reg_unknown_1a(smb_cli, &key_pol, + res2 = res1 ? do_reg_getversion(smb_cli, &key_pol, &unk_1a_response) : False; if (res2 && unk_1a_response != 5) @@ -166,11 +172,11 @@ static void cmd_reg_enum(struct client_info *info) */ uint32 val_type; - BUFFER2 value; + REGVAL_BUFFER value; fstring val_name; /* unknown 1a it */ - res2 = res1 ? do_reg_unknown_1a(smb_cli, &key_pol, + res2 = res1 ? do_reg_getversion(smb_cli, &key_pol, &unk_1a_response) : False; if (res2 && unk_1a_response != 5) @@ -314,7 +320,7 @@ static void cmd_reg_query_key(struct client_info *info) /**************************************************************************** nt registry create value ****************************************************************************/ -static void cmd_reg_create_val(struct client_info *info) +static void cmd_reg_set_val(struct client_info *info) { BOOL res = True; BOOL res3 = True; @@ -327,7 +333,7 @@ static void cmd_reg_create_val(struct client_info *info) fstring val_name; fstring tmp; uint32 val_type; - BUFFER3 value; + RPC_DATA_BLOB value; #if 0 uint32 unk_0; @@ -337,7 +343,7 @@ static void cmd_reg_create_val(struct client_info *info) val_name, *val_type) : False; #endif - DEBUG(5, ("cmd_reg_create_val: smb_cli->fd:%d\n", smb_cli->fd)); + DEBUG(5, ("cmd_reg_set_val: smb_cli->fd:%d\n", smb_cli->fd)); if (!next_token_nr(NULL, full_keyname, NULL, sizeof(full_keyname))) { @@ -377,12 +383,12 @@ static void cmd_reg_create_val(struct client_info *info) { case 0x01: /* UNISTR */ { - init_buffer3_str(&value, tmp, strlen(tmp)+1); + init_rpc_blob_str(&value, tmp, strlen(tmp)+1); break; } case 0x03: /* BYTES */ { - init_buffer3_hex(&value, tmp); + init_rpc_blob_hex(&value, tmp); break; } case 0x04: /* DWORD */ @@ -396,7 +402,7 @@ static void cmd_reg_create_val(struct client_info *info) { tmp_val = strtol(tmp, (char**)NULL, 10); } - init_buffer3_uint32(&value, tmp_val); + init_rpc_blob_uint32(&value, tmp_val); break; } default: @@ -428,7 +434,7 @@ static void cmd_reg_create_val(struct client_info *info) } /* create an entry */ - res4 = res3 ? do_reg_create_val(smb_cli, &parent_pol, + res4 = res3 ? do_reg_set_val(smb_cli, &parent_pol, val_name, val_type, &value) : False; /* flush the modified key */ @@ -448,12 +454,12 @@ static void cmd_reg_create_val(struct client_info *info) if (res && res3 && res4) { - DEBUG(5,("cmd_reg_create_val: query succeeded\n")); + DEBUG(5,("cmd_reg_set_val: query succeeded\n")); fprintf(out_hnd,"OK\n"); } else { - DEBUG(5,("cmd_reg_create_val: query failed\n")); + DEBUG(5,("cmd_reg_set_val: query failed\n")); } } @@ -982,7 +988,7 @@ struct cmd_set reg_commands[] = { { "regqueryval", cmd_reg_query_info, "Registry Value Query", "" }, { "regquerykey", cmd_reg_query_key, "Registry Key Query", "" }, { "regdeleteval", cmd_reg_delete_val, "Registry Value Delete", "" }, - { "regcreateval", cmd_reg_create_val, "Registry Key Create", " " }, + { "regsetval", cmd_reg_set_val, "Registry Key Create", " " }, { "reggetsec", cmd_reg_get_key_sec, "Registry Key Security", "" }, { "regtestsec", cmd_reg_test_key_sec, "Test Registry Key Security", "" }, #endif diff --git a/source/rpcclient/cmd_samr.c b/source/rpcclient/cmd_samr.c index d3f89540502..53019dc1b23 100644 --- a/source/rpcclient/cmd_samr.c +++ b/source/rpcclient/cmd_samr.c @@ -568,25 +568,39 @@ static NTSTATUS cmd_samr_query_useraliases(struct cli_state *cli, { POLICY_HND connect_pol, domain_pol; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; - uint32 user_rid, num_aliases, *alias_rids; + DOM_SID *sids; + int num_sids; + uint32 num_aliases, *alias_rids; uint32 access_mask = MAXIMUM_ALLOWED_ACCESS; int i; fstring server; - DOM_SID tmp_sid; - DOM_SID2 sid; - DOM_SID global_sid_Builtin; + DOM_SID2 *sid2; - string_to_sid(&global_sid_Builtin, "S-1-5-32"); + if (argc < 3) { + printf("Usage: %s builtin|domain sid1 sid2 ...\n", argv[0]); + return NT_STATUS_INVALID_PARAMETER; + } - if ((argc < 3) || (argc > 4)) { - printf("Usage: %s builtin|domain rid [access mask]\n", argv[0]); - return NT_STATUS_OK; + sids = NULL; + num_sids = 0; + + for (i=2; i 3) - sscanf(argv[3], "%x", &access_mask); + sid2 = TALLOC_ARRAY(mem_ctx, DOM_SID2, num_sids); + if (sid2 == NULL) + return NT_STATUS_NO_MEMORY; + + for (i=0; idesthost); strupper_m(server); @@ -604,18 +618,19 @@ static NTSTATUS cmd_samr_query_useraliases(struct cli_state *cli, else if (StrCaseCmp(argv[1], "builtin")==0) result = cli_samr_open_domain(cli, mem_ctx, &connect_pol, access_mask, - &global_sid_Builtin, &domain_pol); - else - return NT_STATUS_OK; + &global_sid_Builtin, + &domain_pol); + else { + printf("Usage: %s builtin|domain sid1 sid2 ...\n", argv[0]); + return NT_STATUS_INVALID_PARAMETER; + } if (!NT_STATUS_IS_OK(result)) goto done; - sid_copy(&tmp_sid, &domain_sid); - sid_append_rid(&tmp_sid, user_rid); - init_dom_sid2(&sid, &tmp_sid); - - result = cli_samr_query_useraliases(cli, mem_ctx, &domain_pol, 1, &sid, &num_aliases, &alias_rids); + result = cli_samr_query_useraliases(cli, mem_ctx, &domain_pol, + num_sids, sid2, + &num_aliases, &alias_rids); if (!NT_STATUS_IS_OK(result)) goto done; @@ -851,11 +866,8 @@ static NTSTATUS cmd_samr_enum_als_groups(struct cli_state *cli, uint32 start_idx, size, num_als_groups, i; uint32 access_mask = MAXIMUM_ALLOWED_ACCESS; struct acct_info *als_groups; - DOM_SID global_sid_Builtin; BOOL got_connect_pol = False, got_domain_pol = False; - string_to_sid(&global_sid_Builtin, "S-1-5-32"); - if ((argc < 2) || (argc > 3)) { printf("Usage: %s builtin|domain [access mask]\n", argv[0]); return NT_STATUS_OK; @@ -933,9 +945,6 @@ static NTSTATUS cmd_samr_query_aliasmem(struct cli_state *cli, uint32 alias_rid, num_members, i; uint32 access_mask = MAXIMUM_ALLOWED_ACCESS; DOM_SID *alias_sids; - DOM_SID global_sid_Builtin; - - string_to_sid(&global_sid_Builtin, "S-1-5-32"); if ((argc < 3) || (argc > 4)) { printf("Usage: %s builtin|domain rid [access mask]\n", argv[0]); @@ -1261,6 +1270,15 @@ static NTSTATUS cmd_samr_create_dom_user(struct cli_state *cli, if (!NT_STATUS_IS_OK(result)) goto done; + result = cli_samr_close(cli, mem_ctx, &user_pol); + if (!NT_STATUS_IS_OK(result)) goto done; + + result = cli_samr_close(cli, mem_ctx, &domain_pol); + if (!NT_STATUS_IS_OK(result)) goto done; + + result = cli_samr_close(cli, mem_ctx, &connect_pol); + if (!NT_STATUS_IS_OK(result)) goto done; + done: return result; } @@ -1312,6 +1330,15 @@ static NTSTATUS cmd_samr_create_dom_group(struct cli_state *cli, if (!NT_STATUS_IS_OK(result)) goto done; + result = cli_samr_close(cli, mem_ctx, &group_pol); + if (!NT_STATUS_IS_OK(result)) goto done; + + result = cli_samr_close(cli, mem_ctx, &domain_pol); + if (!NT_STATUS_IS_OK(result)) goto done; + + result = cli_samr_close(cli, mem_ctx, &connect_pol); + if (!NT_STATUS_IS_OK(result)) goto done; + done: return result; } @@ -1328,9 +1355,6 @@ static NTSTATUS cmd_samr_lookup_names(struct cli_state *cli, uint32 num_rids, num_names, *name_types, *rids; const char **names; int i; - DOM_SID global_sid_Builtin; - - string_to_sid(&global_sid_Builtin, "S-1-5-32"); if (argc < 3) { printf("Usage: %s domain|builtin name1 [name2 [name3] [...]]\n", argv[0]); diff --git a/source/rpcclient/cmd_shutdown.c b/source/rpcclient/cmd_shutdown.c index e42ec30ac13..b0b92949c2a 100644 --- a/source/rpcclient/cmd_shutdown.c +++ b/source/rpcclient/cmd_shutdown.c @@ -24,6 +24,9 @@ #include "includes.h" #include "rpcclient.h" +#if 0 /* don't uncomment this unless you remove the getopt() calls */ + /* use net rpc shutdown instead */ + /**************************************************************************** nt shutdown init ****************************************************************************/ @@ -96,6 +99,7 @@ static NTSTATUS cmd_shutdown_abort(struct cli_state *cli, return result; } +#endif /* List of commands exported by this module */ @@ -103,10 +107,12 @@ struct cmd_set shutdown_commands[] = { { "SHUTDOWN" }, +#if 0 { "shutdowninit", RPC_RTYPE_NTSTATUS, cmd_shutdown_init, NULL, PI_SHUTDOWN, "Remote Shutdown (over shutdown pipe)", "syntax: shutdown [-m message] [-t timeout] [-r] [-h] [-f] (-r == reboot, -h == halt, -f == force)" }, { "shutdownabort", RPC_RTYPE_NTSTATUS, cmd_shutdown_abort, NULL, PI_SHUTDOWN, "Abort Shutdown (over shutdown pipe)", "syntax: shutdownabort" }, +#endif { NULL } }; diff --git a/source/rpcclient/cmd_spoolss.c b/source/rpcclient/cmd_spoolss.c index 49f22b36546..ec9d3048822 100644 --- a/source/rpcclient/cmd_spoolss.c +++ b/source/rpcclient/cmd_spoolss.c @@ -1283,7 +1283,7 @@ void set_drv_info_3_env (DRIVER_INFO_3 *info, const char *arch) wrapper for strtok to get the next parameter from a delimited list. Needed to handle the empty parameter string denoted by "NULL" *************************************************************************/ -static char* get_driver_3_param (const char* str, const char* delim, UNISTR* dest) +static char* get_driver_3_param (char* str, const char* delim, UNISTR* dest) { char *ptr; @@ -1310,11 +1310,8 @@ static char* get_driver_3_param (const char* str, const char* delim, UNISTR* des :::\ : *******************************************************************************/ -static BOOL init_drv_info_3_members ( - TALLOC_CTX *mem_ctx, - DRIVER_INFO_3 *info, - const char *args -) +static BOOL init_drv_info_3_members ( TALLOC_CTX *mem_ctx, DRIVER_INFO_3 *info, + char *args ) { char *str, *str2; uint32 len, i; @@ -1370,6 +1367,7 @@ static WERROR cmd_spoolss_addprinterdriver(struct cli_state *cli, DRIVER_INFO_3 info3; const char *arch; fstring driver_name; + char *driver_args; /* parse the command arguements */ if (argc != 3 && argc != 4) @@ -1393,7 +1391,8 @@ static WERROR cmd_spoolss_addprinterdriver(struct cli_state *cli, else set_drv_info_3_env(&info3, arch); - if (!init_drv_info_3_members(mem_ctx, &info3, argv[2])) + driver_args = talloc_strdup( mem_ctx, argv[2] ); + if (!init_drv_info_3_members(mem_ctx, &info3, driver_args )) { printf ("Error Invalid parameter list - %s.\n", argv[2]); return WERR_INVALID_PARAM; @@ -1813,6 +1812,38 @@ static WERROR cmd_spoolss_setform(struct cli_state *cli, TALLOC_CTX *mem_ctx, return werror; } +static const char *get_form_flag(int form_flag) +{ + switch (form_flag) { + case FORM_USER: + return "FORM_USER"; + case FORM_BUILTIN: + return "FORM_BUILTIN"; + case FORM_PRINTER: + return "FORM_PRINTER"; + default: + return "unknown"; + } +} + +static void display_form(FORM_1 *form) +{ + fstring form_name = ""; + + if (form->name.buffer) + rpcstr_pull(form_name, form->name.buffer, + sizeof(form_name), -1, STR_TERMINATE); + + printf("%s\n" \ + "\tflag: %s (%d)\n" \ + "\twidth: %d, length: %d\n" \ + "\tleft: %d, right: %d, top: %d, bottom: %d\n\n", + form_name, get_form_flag(form->flag), form->flag, + form->width, form->length, + form->left, form->right, + form->top, form->bottom); +} + /* Get a form */ static WERROR cmd_spoolss_getform(struct cli_state *cli, TALLOC_CTX *mem_ctx, @@ -1847,7 +1878,7 @@ static WERROR cmd_spoolss_getform(struct cli_state *cli, TALLOC_CTX *mem_ctx, got_handle = True; - /* Set the form */ + /* Get the form */ werror = cli_spoolss_getform(cli, mem_ctx, 0, &needed, &handle, argv[2], 1, &form); @@ -1859,12 +1890,7 @@ static WERROR cmd_spoolss_getform(struct cli_state *cli, TALLOC_CTX *mem_ctx, if (!W_ERROR_IS_OK(werror)) goto done; - printf("width: %d\n", form.width); - printf("length: %d\n", form.length); - printf("left: %d\n", form.left); - printf("top: %d\n", form.top); - printf("right: %d\n", form.right); - printf("bottom: %d\n", form.bottom); + display_form(&form); done: if (got_handle) @@ -1925,20 +1951,6 @@ static WERROR cmd_spoolss_deleteform(struct cli_state *cli, /* Enumerate forms */ -static const char *get_form_flag(int form_flag) -{ - switch (form_flag) { - case FORM_USER: - return "FORM_USER"; - case FORM_BUILTIN: - return "FORM_BUILTIN"; - case FORM_PRINTER: - return "FORM_PRINTER"; - default: - return "unknown"; - } -} - static WERROR cmd_spoolss_enum_forms(struct cli_state *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) @@ -1988,20 +2000,9 @@ static WERROR cmd_spoolss_enum_forms(struct cli_state *cli, /* Display output */ for (i = 0; i < num_forms; i++) { - fstring form_name; - - if (forms[i].name.buffer) - rpcstr_pull(form_name, forms[i].name.buffer, - sizeof(form_name), -1, STR_TERMINATE); - - printf("%s\n" \ - "\tflag: %s (%d)\n" \ - "\twidth: %d, length: %d\n" \ - "\tleft: %d, right: %d, top: %d, bottom: %d\n\n", - form_name, get_form_flag(forms[i].flag), forms[i].flag, - forms[i].width, forms[i].length, - forms[i].left, forms[i].right, - forms[i].top, forms[i].bottom); + + display_form(&forms[i]); + } done: diff --git a/source/rpcclient/rpcclient.c b/source/rpcclient/rpcclient.c index acb65b7f7ce..c02a279db9e 100644 --- a/source/rpcclient/rpcclient.c +++ b/source/rpcclient/rpcclient.c @@ -24,7 +24,6 @@ #include "rpcclient.h" DOM_SID domain_sid; -static int pipe_idx; /* List to hold groups of commands. @@ -559,7 +558,6 @@ static NTSTATUS do_cmd(struct cli_state *cli, /* Run command */ - pipe_idx = cmd_entry->pipe_idx; if ( cmd_entry->returntype == RPC_RTYPE_NTSTATUS ) { ntresult = cmd_entry->ntfn(cli, mem_ctx, argc, (const char **) argv); if (!NT_STATUS_IS_OK(ntresult)) { diff --git a/source/sam/idmap_util.c b/source/sam/idmap_util.c index f28e11cde74..41689f413b9 100644 --- a/source/sam/idmap_util.c +++ b/source/sam/idmap_util.c @@ -190,106 +190,3 @@ NTSTATUS idmap_sid_to_gid(const DOM_SID *sid, gid_t *gid, uint32 flags) return ret; } - - -/*************************************************************************** - Check first, call set_mapping if it doesn't already exist. -***************************************************************************/ - -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); - } - } - return NT_STATUS_OK; -} - -/*************************************************************************** - 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(); - struct passwd *pass; - GROUP_MAP *map=NULL; - int num_entries=0; - DOM_SID sid; - unid_t id; - fstring sid_string; - - if (!(guest_account && *guest_account)) { - DEBUG(1, ("NULL guest account!?!?\n")); - return False; - } - - pass = getpwnam_alloc(guest_account); - if (!pass) { - return False; - } - - /* 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_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)) { - int i; - - for (i = 0; i < num_entries; i++) { - id.gid = map[i].gid; - wellknown_id_init(&map[i].sid, id, ID_GROUPID); - } - SAFE_FREE(map); - } - - /* Fill in the SID for the administrator account. */ - id.uid = 0; - sid_copy(&sid, get_global_sam_sid()); - 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; - } - - return True; -} diff --git a/source/script/installman.sh b/source/script/installman.sh index c7a8f450951..d30429d50a0 100755 --- a/source/script/installman.sh +++ b/source/script/installman.sh @@ -15,7 +15,7 @@ fi for lang in $langs; do - if [ "X$lang" = Xen ]; then + if [ "X$lang" = XC ]; then echo Installing default man pages in $MANDIR/ lang=. else diff --git a/source/smbd/chgpasswd.c b/source/smbd/chgpasswd.c index 540acfc2250..d0e0f6e143a 100644 --- a/source/smbd/chgpasswd.c +++ b/source/smbd/chgpasswd.c @@ -747,8 +747,8 @@ static NTSTATUS check_oem_password(const char *user, static uchar null_pw[16]; static uchar null_ntpw[16]; SAM_ACCOUNT *sampass = NULL; - char *password_encrypted; - const char *encryption_key; + uint8 *password_encrypted; + const uint8 *encryption_key; const uint8 *lanman_pw, *nt_pw; uint16 acct_ctrl; uint32 new_pw_len; @@ -943,7 +943,8 @@ static BOOL check_passwd_history(SAM_ACCOUNT *sampass, const char *plaintext) const uint8 *nt_pw; const uint8 *pwhistory; BOOL found = False; - int i, pwHisLen, curr_pwHisLen; + int i; + uint32 pwHisLen, curr_pwHisLen; account_policy_get(AP_PASSWORD_HISTORY, &pwHisLen); if (pwHisLen == 0) { diff --git a/source/smbd/dir.c b/source/smbd/dir.c index 309f4adf478..0f32dddd2d7 100644 --- a/source/smbd/dir.c +++ b/source/smbd/dir.c @@ -24,6 +24,8 @@ This module implements directory related functions for Samba. */ +extern struct current_user current_user; + /* Make directory handle internals available. */ #define NAME_CACHE_SIZE 100 @@ -697,7 +699,7 @@ BOOL dir_check_ftype(connection_struct *conn,int mode,int dirtype) static BOOL mangle_mask_match(connection_struct *conn, fstring filename, char *mask) { mangle_map(filename,True,False,SNUM(conn)); - return mask_match(filename,mask,False); + return mask_match_search(filename,mask,False); } /**************************************************************************** @@ -712,16 +714,11 @@ BOOL get_dir_entry(connection_struct *conn,char *mask,int dirtype, pstring fname SMB_STRUCT_STAT sbuf; pstring path; pstring pathreal; - BOOL isrootdir; pstring filename; BOOL needslash; *path = *pathreal = *filename = 0; - isrootdir = (strequal(conn->dirpath,"./") || - strequal(conn->dirpath,".") || - strequal(conn->dirpath,"/")); - needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/'); if (!conn->dirptr) @@ -744,10 +741,8 @@ BOOL get_dir_entry(connection_struct *conn,char *mask,int dirtype, pstring fname see masktest for a demo */ if ((strcmp(mask,"*.*") == 0) || - mask_match(filename,mask,False) || + mask_match_search(filename,mask,False) || mangle_mask_match(conn,filename,mask)) { - if (isrootdir && (strequal(filename,"..") || strequal(filename,"."))) - continue; if (!mangle_is_8_3(filename, False)) mangle_map(filename,True,False,SNUM(conn)); @@ -792,7 +787,6 @@ BOOL get_dir_entry(connection_struct *conn,char *mask,int dirtype, pstring fname static BOOL user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst) { - extern struct current_user current_user; SEC_DESC *psd = NULL; size_t sd_size; files_struct *fsp; @@ -845,7 +839,6 @@ static BOOL user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_S static BOOL user_can_write_file(connection_struct *conn, char *name, SMB_STRUCT_STAT *pst) { - extern struct current_user current_user; SEC_DESC *psd = NULL; size_t sd_size; files_struct *fsp; diff --git a/source/smbd/dosmode.c b/source/smbd/dosmode.c index ff00b5dc6b1..3a0e81e5fef 100644 --- a/source/smbd/dosmode.c +++ b/source/smbd/dosmode.c @@ -431,7 +431,7 @@ int file_set_dosmode(connection_struct *conn, const char *fname, uint32 dosmode, than POSIX. *******************************************************************/ -int file_utime(connection_struct *conn, char *fname, struct utimbuf *times) +int file_utime(connection_struct *conn, const char *fname, struct utimbuf *times) { int ret = -1; @@ -467,7 +467,7 @@ int file_utime(connection_struct *conn, char *fname, struct utimbuf *times) Change a filetime - possibly allowing DOS semantics. *******************************************************************/ -BOOL set_filetime(connection_struct *conn, char *fname, time_t mtime) +BOOL set_filetime(connection_struct *conn, const char *fname, time_t mtime) { struct utimbuf times; diff --git a/source/smbd/error.c b/source/smbd/error.c index d611e0ef873..090a2f6d813 100644 --- a/source/smbd/error.c +++ b/source/smbd/error.c @@ -20,23 +20,44 @@ #include "includes.h" -/* these can be set by some functions to override the error codes */ -int unix_ERR_class=SMB_SUCCESS; -int unix_ERR_code=0; -NTSTATUS unix_ERR_ntstatus = NT_STATUS_OK; - /* From lib/error.c */ extern struct unix_error_map unix_dos_nt_errmap[]; +extern uint32 global_client_caps; +/* these can be set by some functions to override the error codes */ +static int override_ERR_class; +static int override_ERR_code; +static NTSTATUS override_ERR_ntstatus; + /**************************************************************************** - Ensure we don't have any errors cached. + Setting eclass and ecode only and status to NT_STATUS_INVALID forces DOS errors. + Setting status only and eclass and ecode to -1 forces NT errors. ****************************************************************************/ -void clear_cached_errors(void) +void set_saved_error_triple(int eclass, int ecode, NTSTATUS status) +{ + override_ERR_class = eclass; + override_ERR_code = ecode; + override_ERR_ntstatus = status; +} + +/**************************************************************************** + Return the current settings of the error triple. Return True if any are set. +****************************************************************************/ + +BOOL get_saved_error_triple(int *peclass, int *pecode, NTSTATUS *pstatus) { - unix_ERR_class = SMB_SUCCESS; - unix_ERR_code = 0; - unix_ERR_ntstatus = NT_STATUS_OK; + if (peclass) { + *peclass = override_ERR_class; + } + if (pecode) { + *pecode = override_ERR_code; + } + if (pstatus) { + *pstatus = override_ERR_ntstatus; + } + + return (override_ERR_class || !NT_STATUS_IS_OK(override_ERR_ntstatus)); } /**************************************************************************** @@ -46,36 +67,29 @@ void clear_cached_errors(void) int cached_error_packet(char *outbuf,files_struct *fsp,int line,const char *file) { write_bmpx_struct *wbmpx = fsp->wbmpx_ptr; - int32 eclass = wbmpx->wr_errclass; int32 err = wbmpx->wr_error; + NTSTATUS ntstatus = wbmpx->wr_status; /* We can now delete the auxiliary struct */ - free((char *)wbmpx); - fsp->wbmpx_ptr = NULL; - return error_packet(outbuf,NT_STATUS_OK,eclass,err,False,line,file); + SAFE_FREE(fsp->wbmpx_ptr); + return error_packet(outbuf,eclass,err,ntstatus,line,file); } /**************************************************************************** Create an error packet from errno. ****************************************************************************/ -int unix_error_packet(char *outbuf,int def_class,uint32 def_code, - int line, const char *file) +int unix_error_packet(char *outbuf,int def_class,uint32 def_code, NTSTATUS def_status, int line, const char *file) { int eclass=def_class; int ecode=def_code; - NTSTATUS ntstatus = NT_STATUS_OK; + NTSTATUS ntstatus = def_status; int i=0; - if (unix_ERR_class != SMB_SUCCESS) { - eclass = unix_ERR_class; - ecode = unix_ERR_code; - ntstatus = unix_ERR_ntstatus; - unix_ERR_class = SMB_SUCCESS; - unix_ERR_code = 0; - unix_ERR_ntstatus = NT_STATUS_OK; - } else { + if (errno != 0) { + DEBUG(3,("unix_error_packet: error string = %s\n",strerror(errno))); + while (unix_dos_nt_errmap[i].dos_class != 0) { if (unix_dos_nt_errmap[i].unix_error == errno) { eclass = unix_dos_nt_errmap[i].dos_class; @@ -87,39 +101,43 @@ int unix_error_packet(char *outbuf,int def_class,uint32 def_code, } } - return error_packet(outbuf,ntstatus,eclass,ecode,False,line,file); + return error_packet(outbuf,eclass,ecode,ntstatus,line,file); } /**************************************************************************** Create an error packet. Normally called using the ERROR() macro. + Setting eclass and ecode only and status to NT_STATUS_OK forces DOS errors. + Setting status only and eclass and ecode to zero forces NT errors. + If the override errors are set they take precedence over any passed in values. ****************************************************************************/ -int error_packet(char *outbuf,NTSTATUS ntstatus, - uint8 eclass,uint32 ecode,BOOL force_dos, int line, const char *file) +int error_packet(char *outbuf, uint8 eclass, uint32 ecode, NTSTATUS ntstatus, int line, const char *file) { int outsize = set_message(outbuf,0,0,True); - extern uint32 global_client_caps; + BOOL force_nt_status = False; + BOOL force_dos_status = False; + + if (override_ERR_class != SMB_SUCCESS || !NT_STATUS_IS_OK(override_ERR_ntstatus)) { + eclass = override_ERR_class; + ecode = override_ERR_code; + ntstatus = override_ERR_ntstatus; + override_ERR_class = SMB_SUCCESS; + override_ERR_code = 0; + override_ERR_ntstatus = NT_STATUS_OK; + } - if (errno != 0) - DEBUG(3,("error string = %s\n",strerror(errno))); - -#if defined(DEVELOPER) - if (unix_ERR_class != SMB_SUCCESS || unix_ERR_code != 0 || !NT_STATUS_IS_OK(unix_ERR_ntstatus)) - smb_panic("logic error in error processing"); -#endif - - /* - * We can explicitly force 32 bit error codes even when the - * parameter "nt status" is set to no by pre-setting the - * FLAGS2_32_BIT_ERROR_CODES bit in the smb_flg2 outbuf. - * This is to allow work arounds for client bugs that are needed - * when talking with clients that normally expect nt status codes. JRA. - */ - - if ((lp_nt_status_support() || (SVAL(outbuf,smb_flg2) & FLAGS2_32_BIT_ERROR_CODES)) && (global_client_caps & CAP_STATUS32) && (!force_dos)) { - if (NT_STATUS_V(ntstatus) == 0 && eclass) + if (eclass == (uint8)-1) { + force_nt_status = True; + } else if (NT_STATUS_IS_INVALID(ntstatus)) { + force_dos_status = True; + } + + if (force_nt_status || (!force_dos_status && lp_nt_status_support() && (global_client_caps & CAP_STATUS32))) { + /* We're returning an NT error. */ + if (NT_STATUS_V(ntstatus) == 0 && eclass) { ntstatus = dos_to_ntstatus(eclass, ecode); + } SIVAL(outbuf,smb_rcls,NT_STATUS_V(ntstatus)); SSVAL(outbuf,smb_flg2, SVAL(outbuf,smb_flg2)|FLAGS2_32_BIT_ERROR_CODES); DEBUG(3,("error packet at %s(%d) cmd=%d (%s) %s\n", @@ -127,22 +145,23 @@ int error_packet(char *outbuf,NTSTATUS ntstatus, (int)CVAL(outbuf,smb_com), smb_fn_name(CVAL(outbuf,smb_com)), nt_errstr(ntstatus))); - return outsize; - } - - if (eclass == 0 && NT_STATUS_V(ntstatus)) - ntstatus_to_dos(ntstatus, &eclass, &ecode); - - SSVAL(outbuf,smb_flg2, SVAL(outbuf,smb_flg2)&~FLAGS2_32_BIT_ERROR_CODES); - SSVAL(outbuf,smb_rcls,eclass); - SSVAL(outbuf,smb_err,ecode); - - DEBUG(3,("error packet at %s(%d) cmd=%d (%s) eclass=%d ecode=%d\n", - file, line, - (int)CVAL(outbuf,smb_com), - smb_fn_name(CVAL(outbuf,smb_com)), - eclass, - ecode)); + } else { + /* We're returning a DOS error only. */ + if (eclass == 0 && NT_STATUS_V(ntstatus)) { + ntstatus_to_dos(ntstatus, &eclass, &ecode); + } + + SSVAL(outbuf,smb_flg2, SVAL(outbuf,smb_flg2)&~FLAGS2_32_BIT_ERROR_CODES); + SSVAL(outbuf,smb_rcls,eclass); + SSVAL(outbuf,smb_err,ecode); + + DEBUG(3,("error packet at %s(%d) cmd=%d (%s) eclass=%d ecode=%d\n", + file, line, + (int)CVAL(outbuf,smb_com), + smb_fn_name(CVAL(outbuf,smb_com)), + eclass, + ecode)); + } return outsize; } diff --git a/source/smbd/fake_file.c b/source/smbd/fake_file.c index 53aac1e0364..ee510eb003f 100644 --- a/source/smbd/fake_file.c +++ b/source/smbd/fake_file.c @@ -20,6 +20,8 @@ #include "includes.h" +extern struct current_user current_user; + /**************************************************************************** Open a file with a share mode. ****************************************************************************/ @@ -29,7 +31,6 @@ files_struct *open_fake_file_shared1(enum FAKE_FILE_TYPE fake_file_type, connect int share_mode,int ofun, uint32 new_dos_attr, int oplock_request, int *Access,int *action) { - extern struct current_user current_user; int flags=0; files_struct *fsp = NULL; diff --git a/source/smbd/filename.c b/source/smbd/filename.c index 8c484dd232a..9ca2c0efae9 100644 --- a/source/smbd/filename.c +++ b/source/smbd/filename.c @@ -397,7 +397,7 @@ BOOL unix_convert(pstring name,connection_struct *conn,char *saved_last_componen a valid one for the user to access. ****************************************************************************/ -BOOL check_name(pstring name,connection_struct *conn) +BOOL check_name(const pstring name,connection_struct *conn) { BOOL ret = True; diff --git a/source/smbd/files.c b/source/smbd/files.c index 143c1196937..e893e9fefc1 100644 --- a/source/smbd/files.c +++ b/source/smbd/files.c @@ -95,15 +95,13 @@ files_struct *file_new(connection_struct *conn) } DEBUG(0,("ERROR! Out of file structures\n")); - unix_ERR_class = ERRSRV; - unix_ERR_code = ERRnofids; + set_saved_error_triple(ERRSRV, ERRnofids, NT_STATUS_TOO_MANY_OPENED_FILES); return NULL; } fsp = SMB_MALLOC_P(files_struct); if (!fsp) { - unix_ERR_class = ERRSRV; - unix_ERR_code = ERRnofids; + set_saved_error_triple(ERRDOS, ERRnomem, NT_STATUS_NO_MEMORY); return NULL; } diff --git a/source/smbd/lanman.c b/source/smbd/lanman.c index d8c5201ce67..127480f0b3d 100644 --- a/source/smbd/lanman.c +++ b/source/smbd/lanman.c @@ -27,6 +27,9 @@ #include "includes.h" +extern struct current_user current_user; +extern userdom_struct current_user_info; + #ifdef CHECK_TYPES #undef CHECK_TYPES #endif @@ -1652,9 +1655,10 @@ static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, char *param,c char *str1 = param+2; char *str2 = skip_string(str1,1); char *p = skip_string(str2,1); - BOOL ret; - GROUP_MAP *group_list; + struct pdb_search *search; + struct samr_displayentry *entries; + int num_entries; if (strcmp(str1,"WrLeh") != 0) @@ -1672,30 +1676,39 @@ static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, char *param,c /* get list of domain groups SID_DOMAIN_GRP=2 */ become_root(); - ret = pdb_enum_group_mapping(SID_NAME_DOM_GRP , &group_list, &num_entries, False); + search = pdb_search_groups(); unbecome_root(); - - if( !ret ) { - DEBUG(3,("api_RNetGroupEnum:failed to get group list")); + + if (search == NULL) { + DEBUG(3,("api_RNetGroupEnum:failed to get group list")); return False; } resume_context = SVAL(p,0); cli_buf_size=SVAL(p+2,0); - DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: %d\n", resume_context, cli_buf_size)); + DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: " + "%d\n", resume_context, cli_buf_size)); + + become_root(); + num_entries = pdb_search_entries(search, resume_context, 0xffffffff, + &entries); + unbecome_root(); *rdata_len = cli_buf_size; *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len); p = *rdata; - for(i=resume_context; i=resume_context) { - if( ((PTR_DIFF(p,*rdata)+21)<=*rdata_len)&&(strlen(name)<=21) ) { - pstrcpy(p,name); - DEBUG(10,("api_RNetUserEnum:adding entry %d username %s\n",count_sent,p)); - p += 21; - count_sent++; - } else { - /* set overflow error */ - DEBUG(10,("api_RNetUserEnum:overflow on entry %d username %s\n",count_sent,name)); - errflags=234; - break; - } - } - } - } ; - - pdb_endsampwent(); + become_root(); + num_users = pdb_search_entries(search, resume_context, 0xffffffff, + &users); unbecome_root(); - pdb_free_sam(&pwd); + errflags=NERR_Success; + + for (i=0; iservicename)); /* rest is reqpath */ - check_path_syntax(pdp->reqpath, p+1,True); + check_path_syntax(pdp->reqpath, p+1); DEBUG(10,("parse_dfs_path: rest of the path: %s\n",pdp->reqpath)); return True; @@ -75,7 +75,7 @@ static BOOL parse_dfs_path(char* pathname, struct dfs_path* pdp) into the dfs_path structure **********************************************************************/ -static BOOL parse_processed_dfs_path(char* pathname, struct dfs_path* pdp) +static BOOL parse_processed_dfs_path(char* pathname, struct dfs_path* pdp, BOOL allow_wcards) { pstring pathname_local; char* p,*temp; @@ -110,7 +110,11 @@ static BOOL parse_processed_dfs_path(char* pathname, struct dfs_path* pdp) DEBUG(10,("parse_processed_dfs_path: servicename: %s\n",pdp->servicename)); /* rest is reqpath */ - check_path_syntax(pdp->reqpath, p+1,True); + if (allow_wcards) { + check_path_syntax_wcard(pdp->reqpath, p+1); + } else { + check_path_syntax(pdp->reqpath, p+1); + } DEBUG(10,("parse_processed_dfs_path: rest of the path: %s\n",pdp->reqpath)); return True; @@ -278,8 +282,7 @@ should try the remaining path on the redirected server. *****************************************************************/ static BOOL resolve_dfs_path(pstring dfspath, struct dfs_path* dp, - connection_struct* conn, - BOOL findfirst_flag, + connection_struct* conn, BOOL search_flag, struct referral** reflistpp, int* refcntp, BOOL* self_referralp, int* consumedcntp) { @@ -311,18 +314,17 @@ static BOOL resolve_dfs_path(pstring dfspath, struct dfs_path* dp, /* check if need to redirect */ if (is_msdfs_link(conn, localpath, reflistpp, refcntp, NULL)) { - if (findfirst_flag) { + if ( search_flag ) { DEBUG(6,("resolve_dfs_path (FindFirst) No redirection " "for dfs link %s.\n", dfspath)); return False; - } else { - DEBUG(6,("resolve_dfs_path: %s resolves to a valid Dfs link.\n", - dfspath)); - if (consumedcntp) - *consumedcntp = strlen(dfspath); - return True; } - } + + DEBUG(6,("resolve_dfs_path: %s resolves to a valid Dfs link.\n", dfspath)); + if (consumedcntp) + *consumedcntp = strlen(dfspath); + return True; + } /* redirect if any component in the path is a link */ pstrcpy(reqpath, dp->reqpath); @@ -331,6 +333,7 @@ static BOOL resolve_dfs_path(pstring dfspath, struct dfs_path* dp, *p = '\0'; pstrcpy(localpath, reqpath); if (is_msdfs_link(conn, localpath, reflistpp, refcntp, NULL)) { + DEBUG(4, ("resolve_dfs_path: Redirecting %s because parent %s is dfs link\n", dfspath, localpath)); /* To find the path consumed, we truncate the original @@ -338,6 +341,7 @@ static BOOL resolve_dfs_path(pstring dfspath, struct dfs_path* dp, component. The length of the resulting string is the path consumed */ + if (consumedcntp) { char *q; pstring buf; @@ -364,17 +368,20 @@ static BOOL resolve_dfs_path(pstring dfspath, struct dfs_path* dp, /***************************************************************** Decides if a dfs pathname should be redirected or not. If not, the pathname is converted to a tcon-relative local unix path + + search_wcard_flag: this flag performs 2 functions bother related + to searches. See resolve_dfs_path() and parse_processed_dfs_path() + for details. *****************************************************************/ -BOOL dfs_redirect(pstring pathname, connection_struct* conn, - BOOL findfirst_flag) +BOOL dfs_redirect( pstring pathname, connection_struct* conn, BOOL search_wcard_flag ) { struct dfs_path dp; if (!conn || !pathname) return False; - parse_processed_dfs_path(pathname, &dp); + parse_processed_dfs_path(pathname, &dp, search_wcard_flag); /* if dfs pathname for a non-dfs share, convert to tcon-relative path and return false */ @@ -386,7 +393,7 @@ BOOL dfs_redirect(pstring pathname, connection_struct* conn, if (!strequal(dp.servicename, lp_servicename(SNUM(conn)) )) return False; - if (resolve_dfs_path(pathname, &dp, conn, findfirst_flag, + if (resolve_dfs_path(pathname, &dp, conn, search_wcard_flag, NULL, NULL, NULL, NULL)) { DEBUG(3,("dfs_redirect: Redirecting %s\n", pathname)); return True; @@ -802,6 +809,7 @@ int setup_dfs_referral(connection_struct *orig_conn, char *pathname, int max_ref /********************************************************************** Creates a junction structure from a Dfs pathname **********************************************************************/ + BOOL create_junction(char* pathname, struct junction_map* jucn) { struct dfs_path dp; diff --git a/source/smbd/negprot.c b/source/smbd/negprot.c index 9aaa818c62a..054afac683d 100644 --- a/source/smbd/negprot.c +++ b/source/smbd/negprot.c @@ -20,6 +20,7 @@ #include "includes.h" +extern fstring remote_proto; extern enum protocol_types Protocol; extern int max_recv; BOOL global_encrypted_passwords_negotiated = False; @@ -419,6 +420,7 @@ static const struct { {"NT LANMAN 1.0", "NT1", reply_nt1, PROTOCOL_NT1}, {"NT LM 0.12", "NT1", reply_nt1, PROTOCOL_NT1}, {"POSIX 2", "NT1", reply_nt1, PROTOCOL_NT1}, + {"LANMAN2.1", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2}, {"LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2}, {"Samba", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2}, {"DOS LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2}, @@ -548,7 +550,6 @@ int reply_negprot(connection_struct *conn, SSVAL(outbuf,smb_vwv0,choice); if(choice != -1) { - extern fstring remote_proto; fstrcpy(remote_proto,supported_protocols[protocol].short_name); reload_services(True); outsize = supported_protocols[protocol].proto_reply_fn(inbuf, outbuf); diff --git a/source/smbd/notify_kernel.c b/source/smbd/notify_kernel.c index 8fcc18a09f9..c368fd79a12 100644 --- a/source/smbd/notify_kernel.c +++ b/source/smbd/notify_kernel.c @@ -101,8 +101,9 @@ static BOOL kernel_check_notify(connection_struct *conn, uint16 vuid, char *path close((int)fd_pending_array[i]); fd_pending_array[i] = (SIG_ATOMIC_T)-1; if (signals_received - i - 1) { - memmove((void *)&fd_pending_array[i], (void *)&fd_pending_array[i+1], - sizeof(SIG_ATOMIC_T)*(signals_received-i-1)); + memmove(CONST_DISCARD(void *, &fd_pending_array[i]), + CONST_DISCARD(void *, &fd_pending_array[i+1]), + sizeof(SIG_ATOMIC_T)*(signals_received-i-1)); } data->directory_handle = -1; signals_received--; @@ -129,8 +130,9 @@ static void kernel_remove_notify(void *datap) if (fd == (int)fd_pending_array[i]) { fd_pending_array[i] = (SIG_ATOMIC_T)-1; if (signals_received - i - 1) { - memmove((void *)&fd_pending_array[i], (void *)&fd_pending_array[i+1], - sizeof(SIG_ATOMIC_T)*(signals_received-i-1)); + memmove(CONST_DISCARD(void *, &fd_pending_array[i]), + CONST_DISCARD(void *, &fd_pending_array[i+1]), + sizeof(SIG_ATOMIC_T)*(signals_received-i-1)); } data->directory_handle = -1; signals_received--; diff --git a/source/smbd/nttrans.c b/source/smbd/nttrans.c index fbb73640901..a3ffaad24ac 100644 --- a/source/smbd/nttrans.c +++ b/source/smbd/nttrans.c @@ -21,6 +21,7 @@ #include "includes.h" +extern int max_send; extern enum protocol_types Protocol; extern int smb_read_error; extern int global_oplock_break; @@ -40,6 +41,8 @@ static const char *known_nt_pipes[] = { "\\spoolss", "\\netdfs", "\\rpcecho", + "\\svcctl", + "\\eventlog", NULL }; @@ -81,7 +84,6 @@ static char *nttrans_realloc(char **ptr, size_t size) static int send_nt_replies(char *inbuf, char *outbuf, int bufsize, NTSTATUS nt_error, char *params, int paramsize, char *pdata, int datasize) { - extern int max_send; int data_to_send = datasize; int params_to_send = paramsize; int useable_space; @@ -353,6 +355,11 @@ static int map_share_mode( char *fname, uint32 create_options, int smb_open_mode = -1; uint32 original_desired_access = *desired_access; + /* This is a nasty hack - must fix... JRA. */ + if (*desired_access == MAXIMUM_ALLOWED_ACCESS) { + *desired_access = FILE_GENERIC_ALL; + } + /* * Convert GENERIC bits to specific bits. */ @@ -581,7 +588,6 @@ int reply_ntcreate_and_X(connection_struct *conn, uint32 create_disposition = IVAL(inbuf,smb_ntcreate_CreateDisposition); uint32 create_options = IVAL(inbuf,smb_ntcreate_CreateOptions); uint16 root_dir_fid = (uint16)IVAL(inbuf,smb_ntcreate_RootDirectoryFid); - SMB_BIG_UINT allocation_size = 0; int smb_ofun; int smb_open_mode; /* Breakout the oplock request bits so we can set the @@ -630,7 +636,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib if((smb_ofun = map_create_disposition( create_disposition )) == -1) { END_PROFILE(SMBntcreateX); - return(ERROR_DOS(ERRDOS,ERRnoaccess)); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } /* @@ -883,10 +889,8 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib if (create_options & FILE_NON_DIRECTORY_FILE) { restore_case_semantics(conn, file_attributes); - SSVAL(outbuf, smb_flg2, - SVAL(outbuf,smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); END_PROFILE(SMBntcreateX); - return ERROR_NT(NT_STATUS_FILE_IS_A_DIRECTORY); + return ERROR_FORCE_NT(NT_STATUS_FILE_IS_A_DIRECTORY); } oplock_request = 0; @@ -903,7 +907,6 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib END_PROFILE(SMBntcreateX); if (open_was_deferred(SVAL(inbuf,smb_mid))) { /* We have re-scheduled this call. */ - clear_cached_errors(); return -1; } return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess); @@ -915,8 +918,9 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib file_len = sbuf.st_size; fmode = dos_mode(conn,fname,&sbuf); - if(fmode == 0) + if(fmode == 0) { fmode = FILE_ATTRIBUTE_NORMAL; + } if (!fsp->is_directory && (fmode & aDIR)) { close_file(fsp,False); END_PROFILE(SMBntcreateX); @@ -924,25 +928,27 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib } /* Save the requested allocation size. */ - allocation_size = (SMB_BIG_UINT)IVAL(inbuf,smb_ntcreate_AllocationSize); + if ((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) { + SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)IVAL(inbuf,smb_ntcreate_AllocationSize); #ifdef LARGE_SMB_OFF_T - allocation_size |= (((SMB_BIG_UINT)IVAL(inbuf,smb_ntcreate_AllocationSize + 4)) << 32); + allocation_size |= (((SMB_BIG_UINT)IVAL(inbuf,smb_ntcreate_AllocationSize + 4)) << 32); #endif - if (allocation_size && (allocation_size > (SMB_BIG_UINT)file_len)) { - fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size); - if (fsp->is_directory) { - close_file(fsp,False); - END_PROFILE(SMBntcreateX); - /* Can't set allocation size on a directory. */ - return ERROR_NT(NT_STATUS_ACCESS_DENIED); - } - if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) { - close_file(fsp,False); - END_PROFILE(SMBntcreateX); - return ERROR_NT(NT_STATUS_DISK_FULL); + if (allocation_size && (allocation_size > (SMB_BIG_UINT)file_len)) { + fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size); + if (fsp->is_directory) { + close_file(fsp,False); + END_PROFILE(SMBntcreateX); + /* Can't set allocation size on a directory. */ + return ERROR_NT(NT_STATUS_ACCESS_DENIED); + } + if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) { + close_file(fsp,False); + END_PROFILE(SMBntcreateX); + return ERROR_NT(NT_STATUS_DISK_FULL); + } + } else { + fsp->initial_allocation_size = smb_roundup(fsp->conn,(SMB_BIG_UINT)file_len); } - } else { - fsp->initial_allocation_size = smb_roundup(fsp->conn,(SMB_BIG_UINT)file_len); } /* @@ -951,11 +957,13 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib * correct bit for extended oplock reply. */ - if (oplock_request && lp_fake_oplocks(SNUM(conn))) + if (oplock_request && lp_fake_oplocks(SNUM(conn))) { extended_oplock_granted = True; + } - if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) + if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) { extended_oplock_granted = True; + } #if 0 /* W2K sends back 42 words here ! If we do the same it breaks offline sync. Go figure... ? JRA. */ @@ -1158,6 +1166,34 @@ static NTSTATUS set_sd(files_struct *fsp, char *data, uint32 sd_len, uint32 secu return NT_STATUS_OK; } +/**************************************************************************** + Read a list of EA names and data from an incoming data buffer. Create an ea_list with them. +****************************************************************************/ + +static struct ea_list *read_nttrans_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size) +{ + struct ea_list *ea_list_head = NULL; + size_t offset = 0; + + if (data_size < 4) { + return NULL; + } + + while (offset + 4 <= data_size) { + size_t next_offset = IVAL(pdata,offset); + struct ea_list *tmp; + struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset + 4, data_size - offset - 4, NULL); + + DLIST_ADD_END(ea_list_head, eal, tmp); + if (next_offset == 0) { + break; + } + offset += next_offset; + } + + return ea_list_head; +} + /**************************************************************************** Reply to a NT_TRANSACT_CREATE call (needs to process SD's). ****************************************************************************/ @@ -1187,11 +1223,14 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o uint32 create_disposition; uint32 create_options; uint32 sd_len; + uint32 ea_len; uint16 root_dir_fid; - SMB_BIG_UINT allocation_size = 0; int smb_ofun; int smb_open_mode; time_t c_time; + struct ea_list *ea_list = NULL; + TALLOC_CTX *ctx = NULL; + char *pdata = NULL; NTSTATUS status; DEBUG(5,("call_nt_transact_create\n")); @@ -1217,7 +1256,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o if(parameter_count < 54) { DEBUG(0,("call_nt_transact_create - insufficient parameters (%u)\n", (unsigned int)parameter_count)); - return ERROR_DOS(ERRDOS,ERRnoaccess); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } flags = IVAL(params,0); @@ -1227,8 +1266,32 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o create_disposition = IVAL(params,28); create_options = IVAL(params,32); sd_len = IVAL(params,36); + ea_len = IVAL(params,40); root_dir_fid = (uint16)IVAL(params,4); + /* Ensure the data_len is correct for the sd and ea values given. */ + if ((ea_len + sd_len > data_count) || + (ea_len > data_count) || (sd_len > data_count) || + (ea_len + sd_len < ea_len) || (ea_len + sd_len < sd_len)) { + DEBUG(10,("call_nt_transact_create - ea_len = %u, sd_len = %u, data_count = %u\n", + (unsigned int)ea_len, (unsigned int)sd_len, (unsigned int)data_count )); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + + if (ea_len) { + if (!lp_ea_support(SNUM(conn))) { + DEBUG(10,("call_nt_transact_create - ea_len = %u but EA's not supported.\n", + (unsigned int)ea_len )); + return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED); + } + + if (ea_len < 10) { + DEBUG(10,("call_nt_transact_create - ea_len = %u - too small (should be more than 10)\n", + (unsigned int)ea_len )); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + } + if (create_options & FILE_OPEN_BY_FILE_ID) { return ERROR_NT(NT_STATUS_NOT_SUPPORTED); } @@ -1238,8 +1301,9 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o * NT values, as that's what our code is structured to accept. */ - if((smb_ofun = map_create_disposition( create_disposition )) == -1) - return ERROR_DOS(ERRDOS,ERRbadmem); + if((smb_ofun = map_create_disposition( create_disposition )) == -1) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } /* * Get the file name. @@ -1361,6 +1425,25 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o } } + if (ea_len) { + ctx = talloc_init("NTTRANS_CREATE_EA"); + if (!ctx) { + talloc_destroy(ctx); + restore_case_semantics(conn, file_attributes); + return ERROR_NT(NT_STATUS_NO_MEMORY); + } + + pdata = data + sd_len; + + /* We have already checked that ea_len <= data_count here. */ + ea_list = read_nttrans_ea_list(ctx, pdata, ea_len); + if (!ea_list ) { + talloc_destroy(ctx); + restore_case_semantics(conn, file_attributes); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + } + /* * If it's a request for a directory open, deal with it separately. */ @@ -1369,6 +1452,8 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o /* Can't open a temp directory. IFS kit test. */ if (file_attributes & FILE_ATTRIBUTE_TEMPORARY) { + talloc_destroy(ctx); + restore_case_semantics(conn, file_attributes); return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } @@ -1383,6 +1468,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, &smb_action); if(!fsp) { + talloc_destroy(ctx); restore_case_semantics(conn, file_attributes); return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess); } @@ -1398,7 +1484,6 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o oplock_request,&rmode,&smb_action); if (!fsp) { - if(errno == EISDIR) { /* @@ -1407,84 +1492,113 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o if (create_options & FILE_NON_DIRECTORY_FILE) { restore_case_semantics(conn, file_attributes); - SSVAL(outbuf, smb_flg2, SVAL(outbuf,smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); - return ERROR_NT(NT_STATUS_FILE_IS_A_DIRECTORY); + return ERROR_FORCE_NT(NT_STATUS_FILE_IS_A_DIRECTORY); } oplock_request = 0; fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, &smb_action); if(!fsp) { + talloc_destroy(ctx); restore_case_semantics(conn, file_attributes); return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess); } } else { + talloc_destroy(ctx); restore_case_semantics(conn, file_attributes); if (open_was_deferred(SVAL(inbuf,smb_mid))) { /* We have re-scheduled this call. */ - clear_cached_errors(); return -1; } return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess); } } - - file_len = sbuf.st_size; - fmode = dos_mode(conn,fname,&sbuf); - if(fmode == 0) - fmode = FILE_ATTRIBUTE_NORMAL; - - if (fmode & aDIR) { - close_file(fsp,False); - restore_case_semantics(conn, file_attributes); - return ERROR_DOS(ERRDOS,ERRnoaccess); - } - - /* - * If the caller set the extended oplock request bit - * and we granted one (by whatever means) - set the - * correct bit for extended oplock reply. - */ - - if (oplock_request && lp_fake_oplocks(SNUM(conn))) - extended_oplock_granted = True; - - if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) - extended_oplock_granted = True; } /* - * Now try and apply the desired SD. + * According to the MS documentation, the only time the security + * descriptor is applied to the opened file is iff we *created* the + * file; an existing file stays the same. + * + * Also, it seems (from observation) that you can open the file with + * any access mask but you can still write the sd. We need to override + * the granted access before we call set_sd + * Patch for bug #2242 from Tom Lackemann . */ - if (lp_nt_acl_support(SNUM(conn)) && sd_len && - !NT_STATUS_IS_OK(status = set_sd( fsp, data, sd_len, ALL_SECURITY_INFORMATION))) { - close_file(fsp,False); - restore_case_semantics(conn, file_attributes); - return ERROR_NT(status); - } + if (lp_nt_acl_support(SNUM(conn)) && sd_len && smb_action == FILE_WAS_CREATED) { + uint32 saved_access = fsp->desired_access; + + /* We have already checked that sd_len <= data_count here. */ + + fsp->desired_access = FILE_GENERIC_ALL; + + status = set_sd( fsp, data, sd_len, ALL_SECURITY_INFORMATION); + if (!NT_STATUS_IS_OK(status)) { + talloc_destroy(ctx); + close_file(fsp,False); + restore_case_semantics(conn, file_attributes); + return ERROR_NT(status); + } + fsp->desired_access = saved_access; + } + if (ea_len && (smb_action == FILE_WAS_CREATED)) { + status = set_ea(conn, fsp, fname, ea_list); + talloc_destroy(ctx); + if (!NT_STATUS_IS_OK(status)) { + close_file(fsp,False); + restore_case_semantics(conn, file_attributes); + return ERROR_NT(status); + } + } + restore_case_semantics(conn, file_attributes); + file_len = sbuf.st_size; + fmode = dos_mode(conn,fname,&sbuf); + if(fmode == 0) { + fmode = FILE_ATTRIBUTE_NORMAL; + } + if (!fsp->is_directory && (fmode & aDIR)) { + close_file(fsp,False); + return ERROR_DOS(ERRDOS,ERRnoaccess); + } + /* Save the requested allocation size. */ - allocation_size = (SMB_BIG_UINT)IVAL(params,12); + if ((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) { + SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)IVAL(params,12); #ifdef LARGE_SMB_OFF_T - allocation_size |= (((SMB_BIG_UINT)IVAL(params,16)) << 32); + allocation_size |= (((SMB_BIG_UINT)IVAL(params,16)) << 32); #endif - if (allocation_size && (allocation_size > file_len)) { - fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size); - if (fsp->is_directory) { - close_file(fsp,False); - END_PROFILE(SMBntcreateX); - /* Can't set allocation size on a directory. */ - return ERROR_NT(NT_STATUS_ACCESS_DENIED); - } - if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) { - close_file(fsp,False); - return ERROR_NT(NT_STATUS_DISK_FULL); + if (allocation_size && (allocation_size > file_len)) { + fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size); + if (fsp->is_directory) { + close_file(fsp,False); + /* Can't set allocation size on a directory. */ + return ERROR_NT(NT_STATUS_ACCESS_DENIED); + } + if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) { + close_file(fsp,False); + return ERROR_NT(NT_STATUS_DISK_FULL); + } + } else { + fsp->initial_allocation_size = smb_roundup(fsp->conn, (SMB_BIG_UINT)file_len); } - } else { - fsp->initial_allocation_size = smb_roundup(fsp->conn, (SMB_BIG_UINT)file_len); + } + + /* + * If the caller set the extended oplock request bit + * and we granted one (by whatever means) - set the + * correct bit for extended oplock reply. + */ + + if (oplock_request && lp_fake_oplocks(SNUM(conn))) { + extended_oplock_granted = True; + } + + if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) { + extended_oplock_granted = True; } /* Realloc the size of parameters and data we will return */ @@ -1662,12 +1776,11 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new &access_mode,&smb_action); if (!fsp1) { - status = NT_STATUS_ACCESS_DENIED; - if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare) - status = NT_STATUS_SHARING_VIOLATION; - unix_ERR_class = 0; - unix_ERR_code = 0; - unix_ERR_ntstatus = NT_STATUS_OK; + get_saved_error_triple(NULL, NULL, &status); + if (NT_STATUS_IS_OK(status)) { + status = NT_STATUS_ACCESS_DENIED; + } + set_saved_error_triple(0, 0, NT_STATUS_OK); return status; } @@ -1676,12 +1789,11 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new &access_mode,&smb_action); if (!fsp2) { - status = NT_STATUS_ACCESS_DENIED; - if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare) - status = NT_STATUS_SHARING_VIOLATION; - unix_ERR_class = 0; - unix_ERR_code = 0; - unix_ERR_ntstatus = NT_STATUS_OK; + get_saved_error_triple(NULL, NULL, &status); + if (NT_STATUS_IS_OK(status)) { + status = NT_STATUS_ACCESS_DENIED; + } + set_saved_error_triple(0, 0, NT_STATUS_OK); close_file(fsp1,False); return status; } @@ -1787,7 +1899,6 @@ int reply_ntrename(connection_struct *conn, END_PROFILE(SMBntrename); if (open_was_deferred(SVAL(inbuf,smb_mid))) { /* We have re-scheduled this call. */ - clear_cached_errors(); return -1; } return ERROR_NT(status); @@ -1909,7 +2020,6 @@ static int call_nt_transact_rename(connection_struct *conn, char *inbuf, char *o static size_t get_null_nt_acl(TALLOC_CTX *mem_ctx, SEC_DESC **ppsd) { - extern DOM_SID global_sid_World; size_t sd_size; *ppsd = make_standard_sec_desc( mem_ctx, &global_sid_World, &global_sid_World, NULL, &sd_size); @@ -2836,6 +2946,9 @@ due to being in oplock break state.\n", (unsigned int)function_code )); ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT); + /* We need to re-calcuate the new length after we've read the secondary packet. */ + length = smb_len(inbuf) + 4; + /* * The sequence number for the trans reply is always * based on the last secondary received. @@ -2883,7 +2996,7 @@ due to being in oplock break state.\n", (unsigned int)function_code )); goto bad_param; if (parameter_displacement > total_parameter_count) goto bad_param; - if ((smb_base(inbuf) + parameter_offset + parameter_count >= inbuf + bufsize) || + if ((smb_base(inbuf) + parameter_offset + parameter_count > inbuf + length) || (smb_base(inbuf) + parameter_offset + parameter_count < smb_base(inbuf))) goto bad_param; if (parameter_displacement + params < params) @@ -2900,7 +3013,7 @@ due to being in oplock break state.\n", (unsigned int)function_code )); goto bad_param; if (data_displacement > total_data_count) goto bad_param; - if ((smb_base(inbuf) + data_offset + data_count >= inbuf + bufsize) || + if ((smb_base(inbuf) + data_offset + data_count > inbuf + length) || (smb_base(inbuf) + data_offset + data_count < smb_base(inbuf))) goto bad_param; if (data_displacement + data < data) diff --git a/source/smbd/open.c b/source/smbd/open.c index 0a3903234dd..559994ca46c 100644 --- a/source/smbd/open.c +++ b/source/smbd/open.c @@ -21,6 +21,7 @@ #include "includes.h" +extern struct current_user current_user; extern userdom_struct current_user_info; extern uint16 global_oplock_port; extern uint16 global_smbpid; @@ -76,9 +77,92 @@ static void check_for_pipe(const char *fname) strlower_m(s); if (strstr(s,"pipe/")) { DEBUG(3,("Rejecting named pipe open for %s\n",fname)); - unix_ERR_class = ERRSRV; - unix_ERR_code = ERRaccess; - unix_ERR_ntstatus = NT_STATUS_ACCESS_DENIED; + set_saved_error_triple(ERRSRV, ERRaccess, NT_STATUS_ACCESS_DENIED); + } +} + +/**************************************************************************** + Change the ownership of a file to that of the parent directory. + Do this by fd if possible. +****************************************************************************/ + +void change_owner_to_parent(connection_struct *conn, files_struct *fsp, const char *fname, SMB_STRUCT_STAT *psbuf) +{ + const char *parent_path = parent_dirname(fname); + SMB_STRUCT_STAT parent_st; + int ret; + + ret = SMB_VFS_STAT(conn, parent_path, &parent_st); + if (ret == -1) { + DEBUG(0,("change_owner_to_parent: failed to stat parent directory %s. Error was %s\n", + parent_path, strerror(errno) )); + return; + } + + if (fsp && fsp->fd != -1) { + become_root(); + ret = SMB_VFS_FCHOWN(fsp, fsp->fd, parent_st.st_uid, (gid_t)-1); + unbecome_root(); + if (ret == -1) { + DEBUG(0,("change_owner_to_parent: failed to fchown file %s to parent directory uid %u. \ +Error was %s\n", + fname, (unsigned int)parent_st.st_uid, strerror(errno) )); + } + + DEBUG(10,("change_owner_to_parent: changed new file %s to parent directory uid %u.\n", + fname, (unsigned int)parent_st.st_uid )); + + } else { + /* We've already done an lstat into psbuf, and we know it's a directory. If + we can cd into the directory and the dev/ino are the same then we can safely + chown without races as we're locking the directory in place by being in it. + This should work on any UNIX (thanks tridge :-). JRA. + */ + + pstring saved_dir; + SMB_STRUCT_STAT sbuf; + + if (!vfs_GetWd(conn,saved_dir)) { + DEBUG(0,("change_owner_to_parent: failed to get current working directory\n")); + return; + } + + /* Chdir into the new path. */ + if (vfs_ChDir(conn, fname) == -1) { + DEBUG(0,("change_owner_to_parent: failed to change current working directory to %s. \ +Error was %s\n", fname, strerror(errno) )); + goto out; + } + + if (SMB_VFS_STAT(conn,".",&sbuf) == -1) { + DEBUG(0,("change_owner_to_parent: failed to stat directory '.' (%s) \ +Error was %s\n", fname, strerror(errno))); + goto out; + } + + /* Ensure we're pointing at the same place. */ + if (sbuf.st_dev != psbuf->st_dev || sbuf.st_ino != psbuf->st_ino || sbuf.st_mode != psbuf->st_mode ) { + DEBUG(0,("change_owner_to_parent: device/inode/mode on directory %s changed. Refusing to chown !\n", + fname )); + goto out; + } + + become_root(); + ret = SMB_VFS_CHOWN(conn, ".", parent_st.st_uid, (gid_t)-1); + unbecome_root(); + if (ret == -1) { + DEBUG(10,("change_owner_to_parent: failed to chown directory %s to parent directory uid %u. \ +Error was %s\n", + fname, (unsigned int)parent_st.st_uid, strerror(errno) )); + goto out; + } + + DEBUG(10,("change_owner_to_parent: changed ownership of new directory %s to parent directory uid %u.\n", + fname, (unsigned int)parent_st.st_uid )); + + out: + + vfs_ChDir(conn,saved_dir); } } @@ -89,7 +173,6 @@ static void check_for_pipe(const char *fname) static BOOL open_file(files_struct *fsp,connection_struct *conn, const char *fname,SMB_STRUCT_STAT *psbuf,int flags,mode_t mode, uint32 desired_access) { - extern struct current_user current_user; int accmode = (flags & O_ACCMODE); int local_flags = flags; @@ -165,9 +248,7 @@ static BOOL open_file(files_struct *fsp,connection_struct *conn, /* Don't create files with Microsoft wildcard characters. */ if ((local_flags & O_CREAT) && !VALID_STAT(*psbuf) && ms_has_wild(fname)) { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRinvalidname; - unix_ERR_ntstatus = NT_STATUS_OBJECT_NAME_INVALID; + set_saved_error_triple(ERRDOS, ERRinvalidname, NT_STATUS_OBJECT_NAME_INVALID); return False; } @@ -402,9 +483,7 @@ static BOOL check_share_mode(connection_struct *conn, share_mode_entry *share, i DEBUG(5,("check_share_mode: Failing open on file %s as delete on close flag is set.\n", fname )); /* Use errno to map to correct error. */ - unix_ERR_class = SMB_SUCCESS; - unix_ERR_code = 0; - unix_ERR_ntstatus = NT_STATUS_OK; + set_saved_error_triple(SMB_SUCCESS, 0, NT_STATUS_OK); return False; } @@ -444,10 +523,7 @@ static BOOL check_share_mode(connection_struct *conn, share_mode_entry *share, i (!GET_ALLOW_SHARE_DELETE(share->share_mode) || !GET_ALLOW_SHARE_DELETE(share_mode))) { DEBUG(5,("check_share_mode: Failing open on file %s as delete access requests conflict.\n", fname )); - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadshare; - unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION; - + set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION); return False; } @@ -472,10 +548,7 @@ existing desired access (0x%x).\n", fname, (unsigned int)desired_access, (unsign if ((desired_access & DELETE_ACCESS) && !GET_ALLOW_SHARE_DELETE(share->share_mode)) { DEBUG(5,("check_share_mode: Failing open on file %s as delete access requested and allow share delete not set.\n", fname )); - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadshare; - unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION; - + set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION); return False; } @@ -488,18 +561,14 @@ existing desired access (0x%x).\n", fname, (unsigned int)desired_access, (unsign if ((share->desired_access & DELETE_ACCESS) && !GET_ALLOW_SHARE_DELETE(share_mode)) { DEBUG(5,("check_share_mode: Failing open on file %s as delete access granted and allow share delete not requested.\n", fname )); - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadshare; - unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION; + set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION); return False; } #if 0 /* Bluarc test may need this ... needs further investigation. */ if (deny_mode == DENY_ALL || old_deny_mode == DENY_ALL) { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadshare; - unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION; + set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION); return False; } #endif @@ -529,10 +598,7 @@ existing desired access (0x%x).\n", fname, (unsigned int)desired_access, (unsign deny_mode,old_deny_mode,old_open_mode, (int)share->pid,fname, fcbopen, *flags, access_allowed)); - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadshare; - unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION; - + set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION); return False; } @@ -683,10 +749,7 @@ dev = %x, inode = %.0f\n", *p_oplock_request, share_entry->op_type, fname, (unsi DEBUG(0,("open_mode_check: FAILED when breaking oplock (%x) on file %s, \ dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (double)inode)); SAFE_FREE(old_shares); - errno = EACCES; - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadshare; - unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION; + set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION); return -1; } @@ -750,9 +813,7 @@ after break ! For file %s, dev = %x, inode = %.0f. Deleting it to continue...\n" if (del_share_entry(dev, inode, &broken_entry->entry, NULL) == -1) { free_broken_entry_list(broken_entry_list); errno = EACCES; - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadshare; - unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION; + set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION); return -1; } @@ -1019,9 +1080,7 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ delete_defered_open_entry_record(conn, dib.dev, dib.inode); unlock_share_entry(conn, dib.dev, dib.inode); - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadshare; - unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION; + set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION); return NULL; } /* Ensure we don't reprocess this message. */ @@ -1039,15 +1098,10 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ return print_fsp_open(conn, fname); } - fsp = file_new(conn); - if(!fsp) - return NULL; - DEBUG(10,("open_file_shared: fname = %s, dos_attrs = %x, share_mode = %x, ofun = %x, mode = %o, oplock request = %d\n", fname, new_dos_mode, share_mode, ofun, (int)mode, oplock_request )); if (!check_name(fname,conn)) { - file_free(fsp); return NULL; } @@ -1063,21 +1117,15 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ /* this is for OS/2 long file names - say we don't support them */ if (strstr(fname,".+,;=[].")) { - unix_ERR_class = ERRDOS; /* OS/2 Workplace shell fix may be main code stream in a later release. */ - unix_ERR_code = ERRcannotopen; - unix_ERR_ntstatus = NT_STATUS_OBJECT_NAME_NOT_FOUND; + set_saved_error_triple(ERRDOS, ERRcannotopen, NT_STATUS_OBJECT_NAME_NOT_FOUND); DEBUG(5,("open_file_shared: OS/2 long filenames are not supported.\n")); - /* need to reset errno or DEVELOPER will cause us to coredump */ - errno = 0; - file_free(fsp); return NULL; } if ((GET_FILE_OPEN_DISPOSITION(ofun) == FILE_EXISTS_FAIL) && file_existed) { DEBUG(5,("open_file_shared: create new requested for file %s and file already exists.\n", fname )); - file_free(fsp); if (S_ISDIR(psbuf->st_mode)) { errno = EISDIR; } else { @@ -1099,7 +1147,6 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ DEBUG(5,("open_file_shared: attributes missmatch for file %s (%x %x) (0%o, 0%o)\n", fname, existing_dos_mode, new_dos_mode, (int)psbuf->st_mode, (int)mode )); - file_free(fsp); errno = EACCES; return NULL; } @@ -1112,6 +1159,11 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ append does not mean the same thing under dos and unix */ switch (GET_OPEN_MODE(share_mode)) { + case DOS_OPEN_RDONLY: + flags = O_RDONLY; + if (desired_access == 0) + desired_access = FILE_READ_DATA; + break; case DOS_OPEN_WRONLY: flags = O_WRONLY; if (desired_access == 0) @@ -1124,15 +1176,15 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ desired_access = FILE_READ_DATA|FILE_WRITE_DATA; break; case DOS_OPEN_RDWR: + case DOS_OPEN_EXEC: flags = O_RDWR; if (desired_access == 0) desired_access = FILE_READ_DATA|FILE_WRITE_DATA; break; default: - flags = O_RDONLY; - if (desired_access == 0) - desired_access = FILE_READ_DATA; - break; + /* Force DOS error. */ + set_saved_error_triple(ERRDOS, ERRinvalidparam, NT_STATUS_INVALID); + return NULL; } #if defined(O_SYNC) @@ -1146,7 +1198,6 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ if (!fcbopen) { DEBUG(5,("open_file_shared: read/write access requested for file %s on read only %s\n", fname, !CAN_WRITE(conn) ? "share" : "file" )); - file_free(fsp); errno = EACCES; return NULL; } @@ -1155,7 +1206,6 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ if (deny_mode > DENY_NONE && deny_mode!=DENY_FCB) { DEBUG(2,("Invalid deny mode %d on file %s\n",deny_mode,fname)); - file_free(fsp); errno = EINVAL; return NULL; } @@ -1171,6 +1221,10 @@ files_struct *open_file_shared1(connection_struct *conn,char *fname, SMB_STRUCT_ } } + fsp = file_new(conn); + if(!fsp) + return NULL; + if (file_existed) { dev = psbuf->st_dev; @@ -1204,9 +1258,8 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", flags,(flags2&~(O_TRUNC|O_CREAT)),(int)mode,(int)fsp_open )); if (!fsp_open && errno) { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRnoaccess; - unix_ERR_ntstatus = NT_STATUS_ACCESS_DENIED; + /* Default error. */ + set_saved_error_triple(ERRDOS, ERRnoaccess, NT_STATUS_ACCESS_DENIED); } /* @@ -1214,9 +1267,13 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", * the braindead 1 second delay. */ - if (!internal_only_open && NT_STATUS_EQUAL(unix_ERR_ntstatus,NT_STATUS_SHARING_VIOLATION)) { - /* The fsp->open_time here represents the current time of day. */ - defer_open_sharing_error(conn, &fsp->open_time, fname, dev, inode); + if (!internal_only_open) { + NTSTATUS status; + get_saved_error_triple(NULL, NULL, &status); + if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION)) { + /* The fsp->open_time here represents the current time of day. */ + defer_open_sharing_error(conn, &fsp->open_time, fname, dev, inode); + } } unlock_share_entry(conn, dev, inode); @@ -1226,9 +1283,7 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", * We have detected a sharing violation here * so return the correct error code */ - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadshare; - unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION; + set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION); } file_free(fsp); return NULL; @@ -1300,7 +1355,9 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", * the braindead 1 second delay. */ - if (!internal_only_open && NT_STATUS_EQUAL(unix_ERR_ntstatus,NT_STATUS_SHARING_VIOLATION)) { + NTSTATUS status; + get_saved_error_triple(NULL, NULL, &status); + if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION)) { /* The fsp->open_time here represents the current time of day. */ defer_open_sharing_error(conn, &fsp->open_time, fname, dev, inode); } @@ -1312,9 +1369,7 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", * We have detected a sharing violation here, so * return the correct code. */ - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadshare; - unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION; + set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION); return NULL; } @@ -1380,7 +1435,7 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", DEBUG(10,("open_file_shared : share_mode = %x\n", fsp->share_mode )); if (Access) { - (*Access) = open_mode; + (*Access) = (SET_DENY_MODE(deny_mode) | SET_OPEN_MODE(open_mode)); } action = 0; @@ -1389,8 +1444,13 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", action = FILE_WAS_OPENED; if (file_existed && (flags2 & O_TRUNC)) action = FILE_WAS_OVERWRITTEN; - if (!file_existed) + if (!file_existed) { action = FILE_WAS_CREATED; + /* Change the owner if required. */ + if (lp_inherit_owner(SNUM(conn))) { + change_owner_to_parent(conn, fsp, fsp->fsp_name, psbuf); + } + } if (paction) { *paction = action; @@ -1437,9 +1497,7 @@ flags=0x%X flags2=0x%X mode=0%o returned %d\n", fd_close(conn,fsp); file_free(fsp); ntstatus_to_dos(result, &u_e_c, &u_e_code); - unix_ERR_ntstatus = result; - unix_ERR_class = u_e_c; - unix_ERR_code = u_e_code; + set_saved_error_triple(u_e_c, u_e_code, result); return NULL; } } @@ -1545,10 +1603,9 @@ int close_file_fchmod(files_struct *fsp) Open a directory from an NT SMB call. ****************************************************************************/ -files_struct *open_directory(connection_struct *conn, char *fname, SMB_STRUCT_STAT *psbuf, +files_struct *open_directory(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf, uint32 desired_access, int share_mode, int smb_ofun, int *action) { - extern struct current_user current_user; BOOL got_stat = False; files_struct *fsp = file_new(conn); BOOL delete_on_close = GET_DELETE_ON_CLOSE_FLAG(share_mode); @@ -1583,39 +1640,29 @@ files_struct *open_directory(connection_struct *conn, char *fname, SMB_STRUCT_ST * Try and create the directory. */ - if(!CAN_WRITE(conn)) { - DEBUG(2,("open_directory: failing create on read-only share\n")); - file_free(fsp); - errno = EACCES; - return NULL; - } + /* We know bad_path is false as it's caught earlier. */ - if (ms_has_wild(fname)) { - file_free(fsp); - DEBUG(5,("open_directory: failing create on filename %s with wildcards\n", fname)); - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRinvalidname; - unix_ERR_ntstatus = NT_STATUS_OBJECT_NAME_INVALID; - return NULL; - } + NTSTATUS status = mkdir_internal(conn, fname, False); - if( strchr_m(fname, ':')) { + if (!NT_STATUS_IS_OK(status)) { + DEBUG(2,("open_directory: unable to create %s. Error was %s\n", + fname, strerror(errno) )); file_free(fsp); - DEBUG(5,("open_directory: failing create on filename %s with colon in name\n", fname)); - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRinvalidname; - unix_ERR_ntstatus = NT_STATUS_NOT_A_DIRECTORY; + /* Ensure we return the correct NT status to the client. */ + set_saved_error_triple(0, 0, status); return NULL; } - if(vfs_MkDir(conn,fname, unix_mode(conn,aDIR, fname, True)) < 0) { - DEBUG(2,("open_directory: unable to create %s. Error was %s\n", - fname, strerror(errno) )); + /* Ensure we're checking for a symlink here.... */ + /* We don't want to get caught by a symlink racer. */ + + if(SMB_VFS_LSTAT(conn,fname, psbuf) != 0) { file_free(fsp); return NULL; } - if(SMB_VFS_STAT(conn,fname, psbuf) != 0) { + if(!S_ISDIR(psbuf->st_mode)) { + DEBUG(0,("open_directory: %s is not a directory !\n", fname )); file_free(fsp); return NULL; } @@ -1672,13 +1719,19 @@ files_struct *open_directory(connection_struct *conn, char *fname, SMB_STRUCT_ST string_set(&fsp->fsp_name,fname); if (delete_on_close) { - NTSTATUS result = set_delete_on_close_internal(fsp, delete_on_close, 0); + NTSTATUS status = set_delete_on_close_internal(fsp, delete_on_close, 0); - if (NT_STATUS_V(result) != NT_STATUS_V(NT_STATUS_OK)) { + if (!NT_STATUS_IS_OK(status)) { file_free(fsp); return NULL; } } + + /* Change the owner if required. */ + if ((*action == FILE_WAS_CREATED) && lp_inherit_owner(SNUM(conn))) { + change_owner_to_parent(conn, fsp, fsp->fsp_name, psbuf); + } + conn->num_files_open++; return fsp; @@ -1690,7 +1743,6 @@ files_struct *open_directory(connection_struct *conn, char *fname, SMB_STRUCT_ST files_struct *open_file_stat(connection_struct *conn, char *fname, SMB_STRUCT_STAT *psbuf) { - extern struct current_user current_user; files_struct *fsp = NULL; if (!VALID_STAT(*psbuf)) diff --git a/source/smbd/oplock.c b/source/smbd/oplock.c index b9e38e30fcc..9b8df98fd56 100644 --- a/source/smbd/oplock.c +++ b/source/smbd/oplock.c @@ -31,6 +31,9 @@ static int32 level_II_oplocks_open = 0; BOOL global_client_failed_oplock_break = False; BOOL global_oplock_break = False; +extern struct timeval smb_last_time; +extern uint32 global_client_caps; +extern struct current_user current_user; extern int smb_read_error; static struct kernel_oplocks *koplocks; @@ -518,8 +521,6 @@ static void prepare_break_message(char *outbuf, files_struct *fsp, BOOL level2) static void wait_before_sending_break(BOOL local_request) { - extern struct timeval smb_last_time; - if(local_request) { struct timeval cur_tv; long wait_left = (long)lp_oplock_break_wait_time(); @@ -603,7 +604,6 @@ static files_struct *initial_break_processing(SMB_DEV_T dev, SMB_INO_T inode, un static BOOL oplock_break_level2(files_struct *fsp, BOOL local_request) { - extern uint32 global_client_caps; char outbuf[128]; SMB_DEV_T dev = fsp->dev; SMB_INO_T inode = fsp->inode; @@ -676,8 +676,6 @@ static BOOL oplock_break_level2(files_struct *fsp, BOOL local_request) static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_id, BOOL local_request) { - extern uint32 global_client_caps; - extern struct current_user current_user; char *inbuf = NULL; char *outbuf = NULL; files_struct *fsp = NULL; @@ -807,7 +805,6 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_id, saved_user_conn = current_user.conn; saved_vuid = current_user.vuid; saved_fsp_conn = fsp->conn; - change_to_root_user(); /* * Initialize saved_dir to something sensible: vfs_GetWd may not work well * for root: the directory may be NFS-mounted and exported with root_squash @@ -818,6 +815,10 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_id, /* Save the chain fnum. */ file_chain_save(); + pstrcpy(file_name, fsp->fsp_name); + + change_to_root_user(); + /* * From Charles Hoch . If the break processing * code closes the file (as it often does), then the fsp pointer here @@ -825,8 +826,6 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_id, * around the loop. */ - pstrcpy(file_name, fsp->fsp_name); - while((fsp = initial_break_processing(dev, inode, file_id)) && OPEN_FSP(fsp) && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) { if(receive_smb(smbd_server_fd(),inbuf, timeout) == False) { @@ -940,6 +939,9 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_id, abort(); } + /* We know we have no saved errors here. */ + set_saved_error_triple(0, 0, NT_STATUS_OK); + if( DEBUGLVL( 3 ) ) { dbgtext( "oplock_break: returning success for " ); dbgtext( "dev = %x, inode = %.0f, file_id = %lu\n", (unsigned int)dev, (double)inode, file_id ); diff --git a/source/smbd/oplock_linux.c b/source/smbd/oplock_linux.c index 5de9dd56e68..5d6bdb98832 100644 --- a/source/smbd/oplock_linux.c +++ b/source/smbd/oplock_linux.c @@ -22,6 +22,22 @@ #if HAVE_KERNEL_OPLOCKS_LINUX +/* these can be removed when they are in glibc headers */ +struct cap_user_header { + uint32 version; + int pid; +} header; +struct cap_user_data { + uint32 effective; + uint32 permitted; + uint32 inheritable; +} data; + +extern int capget(struct cap_user_header * hdrp, + struct cap_user_data * datap); +extern int capset(struct cap_user_header * hdrp, + const struct cap_user_data * datap); + static SIG_ATOMIC_T signals_received; #define FD_PENDING_SIZE 100 static SIG_ATOMIC_T fd_pending_array[FD_PENDING_SIZE]; @@ -68,17 +84,6 @@ static void set_capability(unsigned capability) #ifndef _LINUX_CAPABILITY_VERSION #define _LINUX_CAPABILITY_VERSION 0x19980330 #endif - /* these can be removed when they are in glibc headers */ - struct { - uint32 version; - int pid; - } header; - struct { - uint32 effective; - uint32 permitted; - uint32 inheritable; - } data; - header.version = _LINUX_CAPABILITY_VERSION; header.pid = 0; @@ -133,7 +138,8 @@ static BOOL linux_oplock_receive_message(fd_set *fds, char *buffer, int buffer_l fsp = file_find_fd(fd); fd_pending_array[0] = (SIG_ATOMIC_T)-1; if (signals_received > 1) - memmove((void *)&fd_pending_array[0], (void *)&fd_pending_array[1], + memmove(CONST_DISCARD(void *, &fd_pending_array[0]), + CONST_DISCARD(void *, &fd_pending_array[1]), sizeof(SIG_ATOMIC_T)*(signals_received-1)); signals_received--; /* now we can receive more signals */ diff --git a/source/smbd/posix_acls.c b/source/smbd/posix_acls.c index 52ddf4cad6d..e0d98f4b897 100644 --- a/source/smbd/posix_acls.c +++ b/source/smbd/posix_acls.c @@ -21,6 +21,9 @@ #include "includes.h" +extern struct current_user current_user; +extern struct generic_mapping file_generic_mapping; + #undef DBGC_CLASS #define DBGC_CLASS DBGC_ACLS @@ -916,7 +919,6 @@ static BOOL unpack_nt_owners(int snum, SMB_STRUCT_STAT *psbuf, uid_t *puser, gid if (lp_force_unknown_acl_user(snum)) { /* this allows take ownership to work * reasonably */ - extern struct current_user current_user; *puser = current_user.uid; } else { DEBUG(3,("unpack_nt_owners: unable to validate" @@ -938,7 +940,6 @@ static BOOL unpack_nt_owners(int snum, SMB_STRUCT_STAT *psbuf, uid_t *puser, gid if (lp_force_unknown_acl_user(snum)) { /* this allows take group ownership to work * reasonably */ - extern struct current_user current_user; *pgrp = current_user.gid; } else { DEBUG(3,("unpack_nt_owners: unable to validate" @@ -1003,10 +1004,8 @@ static void apply_default_perms(files_struct *fsp, canon_ace *pace, mode_t type) static BOOL uid_entry_in_group( canon_ace *uid_ace, canon_ace *group_ace ) { - extern DOM_SID global_sid_World; fstring u_name; fstring g_name; - extern struct current_user current_user; /* "Everyone" always matches every uid. */ @@ -1041,12 +1040,11 @@ static BOOL uid_entry_in_group( canon_ace *uid_ace, canon_ace *group_ace ) static BOOL ensure_canon_entry_valid(canon_ace **pp_ace, files_struct *fsp, - DOM_SID *pfile_owner_sid, - DOM_SID *pfile_grp_sid, + const DOM_SID *pfile_owner_sid, + const DOM_SID *pfile_grp_sid, SMB_STRUCT_STAT *pst, BOOL setting_acl) { - extern DOM_SID global_sid_World; canon_ace *pace; BOOL got_user = False; BOOL got_grp = False; @@ -1220,10 +1218,6 @@ static BOOL create_canon_ace_lists(files_struct *fsp, SMB_STRUCT_STAT *pst, canon_ace **ppfile_ace, canon_ace **ppdir_ace, SEC_ACL *dacl) { - extern DOM_SID global_sid_Creator_Owner; - extern DOM_SID global_sid_Creator_Group; - extern DOM_SID global_sid_World; - extern struct generic_mapping file_generic_mapping; BOOL all_aces_are_inherit_only = (fsp->is_directory ? True : False); canon_ace *file_ace = NULL; canon_ace *dir_ace = NULL; @@ -1647,7 +1641,6 @@ Deny entry after Allow entry. Failing to set on file %s.\n", fsp->fsp_name )); static void process_deny_list( canon_ace **pp_ace_list ) { - extern DOM_SID global_sid_World; canon_ace *ace_list = *pp_ace_list; canon_ace *curr_ace = NULL; canon_ace *curr_ace_next = NULL; @@ -2065,9 +2058,8 @@ 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, struct pai_val *pal, SMB_ACL_TYPE_T the_acl_type) + const DOM_SID *powner, const 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; mode_t acl_mask = (S_IRUSR|S_IWUSR|S_IXUSR); canon_ace *list_head = NULL; @@ -2629,10 +2621,6 @@ static size_t merge_default_aces( SEC_ACE *nt_ace_list, size_t num_aces) 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; - extern DOM_SID global_sid_Creator_Owner; - extern DOM_SID global_sid_Creator_Group; connection_struct *conn = fsp->conn; SMB_STRUCT_STAT sbuf; SEC_ACE *nt_ace_list = NULL; @@ -2920,7 +2908,6 @@ size_t get_nt_acl(files_struct *fsp, uint32 security_info, SEC_DESC **ppdesc) static int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_t gid) { int ret; - extern struct current_user current_user; files_struct *fsp; SMB_STRUCT_STAT st; @@ -2976,7 +2963,6 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) uid_t orig_uid; gid_t orig_gid; BOOL need_chown = False; - extern struct current_user current_user; DEBUG(10,("set_nt_acl: called for file %s\n", fsp->fsp_name )); @@ -3067,7 +3053,7 @@ BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd) create_file_sids(&sbuf, &file_owner_sid, &file_grp_sid); acl_perms = unpack_canon_ace( fsp, &sbuf, &file_owner_sid, &file_grp_sid, - &file_ace_list, &dir_ace_list, security_info_sent, psd); + &file_ace_list, &dir_ace_list, security_info_sent, psd); /* Ignore W2K traverse DACL set. */ if (file_ace_list || dir_ace_list) { @@ -3760,7 +3746,6 @@ BOOL set_unix_posix_acl(connection_struct *conn, files_struct *fsp, const char * static int check_posix_acl_group_write(connection_struct *conn, const char *fname, SMB_STRUCT_STAT *psbuf) { - extern struct current_user current_user; SMB_ACL_T posix_acl = NULL; int entry_id = SMB_ACL_FIRST_ENTRY; SMB_ACL_ENTRY_T entry; @@ -3922,7 +3907,6 @@ failed to match on user or group in token.\n", fname )); BOOL can_delete_file_in_directory(connection_struct *conn, const char *fname) { - extern struct current_user current_user; SMB_STRUCT_STAT sbuf; pstring dname; int ret; @@ -3980,7 +3964,6 @@ BOOL can_delete_file_in_directory(connection_struct *conn, const char *fname) BOOL can_write_to_file(connection_struct *conn, const char *fname) { - extern struct current_user current_user; SMB_STRUCT_STAT sbuf; int ret; diff --git a/source/smbd/process.c b/source/smbd/process.c index 54837c3b9ae..1bf6f4f9d14 100644 --- a/source/smbd/process.c +++ b/source/smbd/process.c @@ -20,6 +20,11 @@ #include "includes.h" +extern uint16 global_smbpid; +extern int keepalive; +extern struct auth_context *negprot_global_auth_context; +extern int smb_echo_count; + struct timeval smb_last_time; static char *InBuffer = NULL; @@ -211,6 +216,7 @@ BOOL open_was_deferred(uint16 mid) for (pml = smb_sharing_violation_queue; pml; pml = pml->next) { if (SVAL(pml->buf.data,smb_mid) == mid) { + set_saved_error_triple(SMB_SUCCESS, 0, NT_STATUS_OK); return True; } } @@ -851,7 +857,6 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize { static pid_t pid= (pid_t)-1; int outsize = 0; - extern uint16 global_smbpid; type &= 0xff; @@ -859,6 +864,8 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize pid = sys_getpid(); errno = 0; + set_saved_error_triple(0, 0, NT_STATUS_OK); + last_message = type; /* Make sure this is an SMB packet. smb_size contains NetBIOS header so subtract 4 from it. */ @@ -1328,7 +1335,6 @@ static BOOL timeout_processing(int deadtime, int *select_timeout, time_t *last_t static time_t last_idle_closed_check = 0; time_t t; BOOL allidle = True; - extern int keepalive; if (smb_read_error == READ_EOF) { DEBUG(3,("timeout_processing: End of file from client (client has disconnected).\n")); @@ -1372,7 +1378,6 @@ static BOOL timeout_processing(int deadtime, int *select_timeout, time_t *last_t } if (keepalive && (t - last_keepalive_sent_time)>keepalive) { - extern struct auth_context *negprot_global_auth_context; if (!send_keepalive(smbd_server_fd())) { DEBUG( 2, ( "Keepalive failed - exiting.\n" ) ); return False; @@ -1490,7 +1495,6 @@ machine %s in domain %s.\n", global_myname(), lp_workgroup())); void smbd_process(void) { - extern int smb_echo_count; time_t last_timeout_processing_time = time(NULL); unsigned int num_smbs = 0; const size_t total_buffer_size = BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + SAFETY_MARGIN; diff --git a/source/smbd/quotas.c b/source/smbd/quotas.c index 1117461bc25..1a73fdf2223 100644 --- a/source/smbd/quotas.c +++ b/source/smbd/quotas.c @@ -882,8 +882,17 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB restore_re_uid(); if (r==-1) + { + DEBUG(5, ("quotactl for uid=%u: %s", euser_id, strerror(errno))); return(False); + } + /* No quota for this user. */ + if (F.d_blk_softlimit==0 && F.d_blk_hardlimit==0) + { + return(False); + } + /* Use softlimit to determine disk space, except when it has been exceeded */ if ( (F.d_blk_softlimit && F.d_bcount>=F.d_blk_softlimit) || @@ -895,14 +904,10 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB *dfree = 0; *dsize = F.d_bcount; } - else if (F.d_blk_softlimit==0 && F.d_blk_hardlimit==0) - { - return(False); - } else { *dfree = (F.d_blk_softlimit - F.d_bcount); - *dsize = F.d_blk_softlimit; + *dsize = F.d_blk_softlimit ? F.d_blk_softlimit : F.d_blk_hardlimit; } } diff --git a/source/smbd/reply.c b/source/smbd/reply.c index 5802720b7e9..c3cb81ddfc4 100644 --- a/source/smbd/reply.c +++ b/source/smbd/reply.c @@ -35,16 +35,17 @@ extern int global_oplock_break; unsigned int smb_echo_count = 0; extern uint32 global_client_caps; +extern struct current_user current_user; extern BOOL global_encrypted_passwords_negotiated; /**************************************************************************** - Ensure we check the path in *exactly* the same way as W2K. + Ensure we check the path in *exactly* the same way as W2K for regular pathnames. We're assuming here that '/' is not the second byte in any multibyte char set (a safe assumption). '\\' *may* be the second byte in a multibyte char set. ****************************************************************************/ -NTSTATUS check_path_syntax(pstring destname, const pstring srcname, BOOL allow_wcard_names) +NTSTATUS check_path_syntax(pstring destname, const pstring srcname) { char *d = destname; const char *s = srcname; @@ -118,20 +119,16 @@ NTSTATUS check_path_syntax(pstring destname, const pstring srcname, BOOL allow_w } if (!(*s & 0x80)) { - if (allow_wcard_names) { - *d++ = *s++; - } else { - switch (*s) { - case '*': - case '?': - case '<': - case '>': - case '"': - return NT_STATUS_OBJECT_NAME_INVALID; - default: - *d++ = *s++; - break; - } + switch (*s) { + case '*': + case '?': + case '<': + case '>': + case '"': + return NT_STATUS_OBJECT_NAME_INVALID; + default: + *d++ = *s++; + break; } } else { switch(next_mb_char_size(s)) { @@ -157,17 +154,127 @@ NTSTATUS check_path_syntax(pstring destname, const pstring srcname, BOOL allow_w } if (NT_STATUS_EQUAL(ret, NT_STATUS_OBJECT_NAME_INVALID)) { - /* For some strange reason being called from findfirst changes - the num_components number to cause the error return to change. JRA. */ - if (allow_wcard_names) { - if (num_bad_components > 2) { - ret = NT_STATUS_OBJECT_PATH_NOT_FOUND; + if (num_bad_components > 1) { + ret = NT_STATUS_OBJECT_PATH_NOT_FOUND; + } + } + + *d = '\0'; + return ret; +} + +/**************************************************************************** + Ensure we check the path in *exactly* the same way as W2K for a findfirst/findnext + path or anything including wildcards. + We're assuming here that '/' is not the second byte in any multibyte char + set (a safe assumption). '\\' *may* be the second byte in a multibyte char + set. +****************************************************************************/ + +NTSTATUS check_path_syntax_wcard(pstring destname, const pstring srcname) +{ + char *d = destname; + const char *s = srcname; + NTSTATUS ret = NT_STATUS_OK; + BOOL start_of_name_component = True; + unsigned int num_bad_components = 0; + + while (*s) { + if (IS_DIRECTORY_SEP(*s)) { + /* + * Safe to assume is not the second part of a mb char as this is handled below. + */ + /* Eat multiple '/' or '\\' */ + while (IS_DIRECTORY_SEP(*s)) { + s++; + } + if ((d != destname) && (*s != '\0')) { + /* We only care about non-leading or trailing '/' or '\\' */ + *d++ = '/'; } + + start_of_name_component = True; + continue; + } + + if (start_of_name_component) { + if ((s[0] == '.') && (s[1] == '.') && (IS_DIRECTORY_SEP(s[2]) || s[2] == '\0')) { + /* Uh oh - "/../" or "\\..\\" or "/..\0" or "\\..\0" ! */ + + /* + * No mb char starts with '.' so we're safe checking the directory separator here. + */ + + /* If we just added a '/' - delete it */ + if ((d > destname) && (*(d-1) == '/')) { + *(d-1) = '\0'; + d--; + } + + /* Are we at the start ? Can't go back further if so. */ + if (d <= destname) { + ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD; + break; + } + /* Go back one level... */ + /* We know this is safe as '/' cannot be part of a mb sequence. */ + /* NOTE - if this assumption is invalid we are not in good shape... */ + /* Decrement d first as d points to the *next* char to write into. */ + for (d--; d > destname; d--) { + if (*d == '/') + break; + } + s += 2; /* Else go past the .. */ + /* We're still at the start of a name component, just the previous one. */ + + if (num_bad_components) { + /* Hmmm. Should we only decrement the bad_components if + we're removing a bad component ? Need to check this. JRA. */ + num_bad_components--; + } + + continue; + + } else if ((s[0] == '.') && ((s[1] == '\0') || IS_DIRECTORY_SEP(s[1]))) { + /* Component of pathname can't be "." only. */ + ret = NT_STATUS_OBJECT_NAME_INVALID; + num_bad_components++; + *d++ = *s++; + continue; + } + } + + if (!(*s & 0x80)) { + *d++ = *s++; } else { - if (num_bad_components > 1) { - ret = NT_STATUS_OBJECT_PATH_NOT_FOUND; + switch(next_mb_char_size(s)) { + case 4: + *d++ = *s++; + case 3: + *d++ = *s++; + case 2: + *d++ = *s++; + case 1: + *d++ = *s++; + break; + default: + DEBUG(0,("check_path_syntax_wcard: character length assumptions invalid !\n")); + *d = '\0'; + return NT_STATUS_INVALID_PARAMETER; } } + if (start_of_name_component && num_bad_components) { + num_bad_components++; + } + start_of_name_component = False; + } + + if (NT_STATUS_EQUAL(ret, NT_STATUS_OBJECT_NAME_INVALID)) { + /* For some strange reason being called from findfirst changes + the num_components number to cause the error return to change. JRA. */ + if (num_bad_components > 2) { + ret = NT_STATUS_OBJECT_PATH_NOT_FOUND; + } } *d = '\0'; @@ -192,7 +299,11 @@ size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len } else { ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags); } - *err = check_path_syntax(dest, tmppath, allow_wcard_names); + if (allow_wcard_names) { + *err = check_path_syntax_wcard(dest, tmppath); + } else { + *err = check_path_syntax(dest, tmppath); + } return ret; } @@ -361,7 +472,6 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt int passlen = SVAL(inbuf,smb_vwv3); pstring path; char *p, *q; - extern BOOL global_encrypted_passwords_negotiated; START_PROFILE(SMBtconX); @@ -821,6 +931,8 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size BOOL can_open = True; BOOL bad_path = False; NTSTATUS nt_status; + BOOL allow_long_path_components = (SVAL(inbuf,smb_flg2) & FLAGS2_LONG_PATH_COMPONENTS) ? True : False; + START_PROFILE(SMBsearch); *mask = *directory = *fname = 0; @@ -839,7 +951,7 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size return ERROR_NT(nt_status); } - RESOLVE_DFSPATH(path, conn, inbuf, outbuf); + RESOLVE_DFSPATH_WCARD(path, conn, inbuf, outbuf); p++; status_len = SVAL(p, 0); @@ -920,7 +1032,8 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size if (ok) { if ((dirtype&0x1F) == aVOLID) { memcpy(p,status,21); - make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0); + make_dir_struct(p,"???????????",volume_label(SNUM(conn)), + 0,aVOLID,0,!allow_long_path_components); dptr_fill(p+12,dptr_num); if (dptr_zero(p+12) && (status_len==0)) numentries = 1; @@ -940,7 +1053,8 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend); if (!finished) { memcpy(p,status,21); - make_dir_struct(p,mask,fname,size,mode,date); + make_dir_struct(p,mask,fname,size, mode,date, + !allow_long_path_components); dptr_fill(p+12,dptr_num); numentries++; p += DIR_STRUCT_SIZE; @@ -978,8 +1092,11 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size SCVAL(smb_buf(outbuf),0,5); SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE); - if (Protocol >= PROTOCOL_NT1) - SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME); + /* The replies here are never long name. */ + SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_IS_LONG_NAME)); + if (!allow_long_path_components) { + SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) & (~FLAGS2_LONG_PATH_COMPONENTS)); + } /* This SMB *always* returns ASCII names. Remove the unicode bit in flags2. */ SSVAL(outbuf,smb_flg2, (SVAL(outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS))); @@ -1089,7 +1206,6 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, END_PROFILE(SMBopen); if (open_was_deferred(SVAL(inbuf,smb_mid))) { /* We have re-scheduled this call. */ - clear_cached_errors(); return -1; } return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess); @@ -1152,6 +1268,9 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt BOOL bad_path = False; files_struct *fsp; NTSTATUS status; + SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv9); + ssize_t retval = -1; + START_PROFILE(SMBopenX); /* If it's an IPC, pass off the pipe handler. */ @@ -1179,7 +1298,17 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt END_PROFILE(SMBopenX); return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); } - + + /* Strange open mode mapping. */ + if (smb_ofun == 0) { + if (GET_OPEN_MODE(smb_mode) == DOS_OPEN_EXEC) { + smb_ofun = FILE_EXISTS_FAIL | FILE_CREATE_IF_NOT_EXIST; + } else { + END_PROFILE(SMBopenX); + return ERROR_FORCE_DOS(ERRDOS, ERRbadaccess); + } + } + fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,(uint32)smb_attr, oplock_request, &rmode,&smb_action); @@ -1187,13 +1316,31 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt END_PROFILE(SMBopenX); if (open_was_deferred(SVAL(inbuf,smb_mid))) { /* We have re-scheduled this call. */ - clear_cached_errors(); return -1; } return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess); } size = sbuf.st_size; + + /* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size, + if the file is truncated or created. */ + if (((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) && allocation_size) { + fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size); + if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) { + close_file(fsp,False); + END_PROFILE(SMBntcreateX); + return ERROR_NT(NT_STATUS_DISK_FULL); + } + retval = vfs_set_filelen(fsp, (SMB_OFF_T)allocation_size); + if (retval < 0) { + close_file(fsp,False); + END_PROFILE(SMBwrite); + return ERROR_NT(NT_STATUS_DISK_FULL); + } + size = get_allocation_size(conn,fsp,&sbuf); + } + fmode = dos_mode(conn,fname,&sbuf); mtime = sbuf.st_mtime; if (fmode & aDIR) { @@ -1321,7 +1468,6 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, END_PROFILE(SMBcreate); if (open_was_deferred(SVAL(inbuf,smb_mid))) { /* We have re-scheduled this call. */ - clear_cached_errors(); return -1; } return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess); @@ -1405,7 +1551,6 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, END_PROFILE(SMBctemp); if (open_was_deferred(SVAL(inbuf,smb_mid))) { /* We have re-scheduled this call. */ - clear_cached_errors(); return -1; } return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess); @@ -1467,20 +1612,19 @@ static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype, return NT_STATUS_OK; /* We need a better way to return NT status codes from open... */ - unix_ERR_class = 0; - unix_ERR_code = 0; + set_saved_error_triple(0, 0, NT_STATUS_OK); fsp = open_file_shared1(conn, fname, pst, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL), (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action); if (!fsp) { - NTSTATUS ret = NT_STATUS_ACCESS_DENIED; - if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare) - ret = NT_STATUS_SHARING_VIOLATION; - unix_ERR_class = 0; - unix_ERR_code = 0; - unix_ERR_ntstatus = NT_STATUS_OK; - return ret; + NTSTATUS ret; + if (get_saved_error_triple(NULL, NULL, &ret)) { + set_saved_error_triple(0, 0, NT_STATUS_OK); + return ret; + } + set_saved_error_triple(0, 0, NT_STATUS_OK); + return NT_STATUS_ACCESS_DENIED; } close_file(fsp,False); return NT_STATUS_OK; @@ -1540,22 +1684,19 @@ NTSTATUS can_delete(connection_struct *conn, char *fname, int dirtype, BOOL bad_ don't do it here as we'll get it wrong. */ /* We need a better way to return NT status codes from open... */ - unix_ERR_class = 0; - unix_ERR_code = 0; + set_saved_error_triple(0, 0, NT_STATUS_OK); fsp = open_file_shared1(conn, fname, &sbuf, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL), (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), FILE_ATTRIBUTE_NORMAL, 0, &access_mode, &smb_action); if (!fsp) { - NTSTATUS ret = NT_STATUS_ACCESS_DENIED; - if (!NT_STATUS_IS_OK(unix_ERR_ntstatus)) - ret = unix_ERR_ntstatus; - else if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare) - ret = NT_STATUS_SHARING_VIOLATION; - unix_ERR_class = 0; - unix_ERR_code = 0; - unix_ERR_ntstatus = NT_STATUS_OK; - return ret; + NTSTATUS ret; + if (get_saved_error_triple(NULL, NULL, &ret)) { + set_saved_error_triple(0, 0, NT_STATUS_OK); + return ret; + } + set_saved_error_triple(0, 0, NT_STATUS_OK); + return NT_STATUS_ACCESS_DENIED; } close_file(fsp,False); } @@ -1716,7 +1857,7 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size return ERROR_NT(status); } - RESOLVE_DFSPATH(name, conn, inbuf, outbuf); + RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf); DEBUG(3,("reply_unlink : %s\n",name)); @@ -1724,7 +1865,6 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size if (!NT_STATUS_IS_OK(status)) { if (open_was_deferred(SVAL(inbuf,smb_mid))) { /* We have re-scheduled this call. */ - clear_cached_errors(); return -1; } return ERROR_NT(status); @@ -1870,7 +2010,6 @@ 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 out_buffsize) { - extern struct current_user current_user; ssize_t maxcount,mincount; size_t nread = 0; SMB_OFF_T startpos; @@ -2840,7 +2979,6 @@ 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; @@ -3314,29 +3452,32 @@ int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_ code. ****************************************************************************/ -NTSTATUS mkdir_internal(connection_struct *conn, pstring directory) +NTSTATUS mkdir_internal(connection_struct *conn, const pstring directory, BOOL bad_path) { - BOOL bad_path = False; - SMB_STRUCT_STAT sbuf; int ret= -1; - unix_convert(directory,conn,0,&bad_path,&sbuf); - - if( strchr_m(directory, ':')) { - return NT_STATUS_NOT_A_DIRECTORY; - } - - if (ms_has_wild(directory)) { - return NT_STATUS_OBJECT_NAME_INVALID; + if(!CAN_WRITE(conn)) { + DEBUG(5,("mkdir_internal: failing create on read-only share %s\n", lp_servicename(SNUM(conn)))); + errno = EACCES; + return map_nt_error_from_unix(errno); } if (bad_path) { return NT_STATUS_OBJECT_PATH_NOT_FOUND; } - if (check_name(directory, conn)) - ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True)); - + if (!check_name(directory, conn)) { + if(errno == ENOENT) { + if (bad_path) { + return NT_STATUS_OBJECT_PATH_NOT_FOUND; + } else { + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + } + return map_nt_error_from_unix(errno); + } + + ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True)); if (ret == -1) { if(errno == ENOENT) { return NT_STATUS_OBJECT_NAME_NOT_FOUND; @@ -3356,6 +3497,9 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, pstring directory; int outsize; NTSTATUS status; + BOOL bad_path = False; + SMB_STRUCT_STAT sbuf; + START_PROFILE(SMBmkdir); srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status, False); @@ -3366,12 +3510,38 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, RESOLVE_DFSPATH(directory, conn, inbuf, outbuf); - status = mkdir_internal(conn, directory); + unix_convert(directory,conn,0,&bad_path,&sbuf); + + if( strchr_m(directory, ':')) { + DEBUG(5,("reply_mkdir: failing create on filename %s with colon in name\n", directory)); + END_PROFILE(SMBmkdir); + return ERROR_FORCE_DOS(ERRDOS, ERRinvalidname); + } + + status = mkdir_internal(conn, directory,bad_path); if (!NT_STATUS_IS_OK(status)) { END_PROFILE(SMBmkdir); return ERROR_NT(status); } + if (lp_inherit_owner(SNUM(conn))) { + /* Ensure we're checking for a symlink here.... */ + /* We don't want to get caught by a symlink racer. */ + + if(SMB_VFS_LSTAT(conn,directory, &sbuf) != 0) { + END_PROFILE(SMBmkdir); + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } + + if(!S_ISDIR(sbuf.st_mode)) { + DEBUG(0,("reply_mkdir: %s is not a directory !\n", directory )); + END_PROFILE(SMBmkdir); + return(UNIXERROR(ERRDOS,ERRnoaccess)); + } + + change_owner_to_parent(conn, NULL, directory, &sbuf); + } + outsize = set_message(outbuf,0,0,True); DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) ); @@ -4145,8 +4315,8 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return ERROR_NT(status); } - RESOLVE_DFSPATH(name, conn, inbuf, outbuf); - RESOLVE_DFSPATH(newname, conn, inbuf, outbuf); + RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf); + RESOLVE_DFSPATH_WCARD(newname, conn, inbuf, outbuf); DEBUG(3,("reply_mv : %s -> %s\n",name,newname)); @@ -4155,7 +4325,6 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, END_PROFILE(SMBmv); if (open_was_deferred(SVAL(inbuf,smb_mid))) { /* We have re-scheduled this call. */ - clear_cached_errors(); return -1; } return ERROR_NT(status); @@ -4305,8 +4474,8 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return ERROR_DOS(ERRSRV,ERRinvdevice); } - RESOLVE_DFSPATH(name, conn, inbuf, outbuf); - RESOLVE_DFSPATH(newname, conn, inbuf, outbuf); + RESOLVE_DFSPATH_WCARD(name, conn, inbuf, outbuf); + RESOLVE_DFSPATH_WCARD(newname, conn, inbuf, outbuf); rc = unix_convert(name,conn,0,&bad_path1,&sbuf1); unix_convert(newname,conn,0,&bad_path2,&sbuf2); @@ -4419,8 +4588,7 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, return ERROR_DOS(ERRDOS,error); } else { if((errno == ENOENT) && (bad_path1 || bad_path2)) { - unix_ERR_class = ERRDOS; - unix_ERR_code = ERRbadpath; + set_saved_error_triple(ERRDOS, ERRbadpath, NT_STATUS_OK); } END_PROFILE(SMBcopy); return(UNIXERROR(ERRDOS,error)); @@ -4976,7 +5144,9 @@ int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, CHECK_FSP(fsp,conn); CHECK_WRITE(fsp); - CHECK_ERROR(fsp); + if (HAS_CACHED_ERROR(fsp)) { + return(CACHED_ERROR(fsp)); + } tcount = SVAL(inbuf,smb_vwv1); startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3); @@ -5119,8 +5289,12 @@ int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_siz END_PROFILE(SMBwriteBs); return(ERROR_DOS(ERRHRD,ERRdiskfull)); } + wbms->wr_errclass = ERRHRD; + wbms->wr_error = ERRdiskfull; + wbms->wr_status = NT_STATUS_DISK_FULL; + wbms->wr_discard = True; END_PROFILE(SMBwriteBs); - return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull)); + return -1; } /* Increment the total written, if this matches tcount diff --git a/source/smbd/server.c b/source/smbd/server.c index 7f7d55c7e3a..9d910cd14ad 100644 --- a/source/smbd/server.c +++ b/source/smbd/server.c @@ -30,6 +30,8 @@ int last_message = -1; /* a useful macro to debug the last message processed */ #define LAST_MESSAGE() smb_fn_name(last_message) +extern char *last_inbuf; +extern struct auth_context *negprot_global_auth_context; extern pstring user_socket_options; extern SIG_ATOMIC_T got_sig_term; extern SIG_ATOMIC_T reload_after_sighup; @@ -598,8 +600,6 @@ static BOOL dump_core(void) void exit_server(const char *reason) { static int firsttime=1; - extern char *last_inbuf; - extern struct auth_context *negprot_global_auth_context; if (!firsttime) exit(0); diff --git a/source/smbd/service.c b/source/smbd/service.c index 684d49c56ae..d39d3d3836c 100644 --- a/source/smbd/service.c +++ b/source/smbd/service.c @@ -20,6 +20,7 @@ #include "includes.h" +extern char magic_char; extern struct timeval smb_last_time; extern userdom_struct current_user_info; @@ -30,7 +31,6 @@ extern userdom_struct current_user_info; BOOL set_current_service(connection_struct *conn, uint16 flags, BOOL do_chdir) { - extern char magic_char; static connection_struct *last_conn; static uint16 last_flags; int snum; @@ -272,7 +272,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, struct passwd *pass = NULL; BOOL guest = False; connection_struct *conn; - struct stat st; + SMB_STRUCT_STAT st; fstring user; fstring dev; diff --git a/source/smbd/sesssetup.c b/source/smbd/sesssetup.c index 19acc4b1b08..9fbf0b1d51d 100644 --- a/source/smbd/sesssetup.c +++ b/source/smbd/sesssetup.c @@ -25,6 +25,12 @@ uint32 global_client_caps = 0; +extern BOOL global_encrypted_passwords_negotiated; +extern BOOL global_spnego_negotiated; +extern enum protocol_types Protocol; +extern int max_send; +extern struct auth_context *negprot_global_auth_context; + static struct auth_ntlmssp_state *global_ntlmssp_state; /* @@ -313,7 +319,9 @@ static int reply_spnego_kerberos(connection_struct *conn, /* wrap that up in a nice GSS-API wrapping */ if (NT_STATUS_IS_OK(ret)) { - ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep, TOK_ID_KRB_AP_REP); + ap_rep_wrapped = spnego_gen_krb5_wrap( + ap_rep, + CONST_ADD(const uint8 *, TOK_ID_KRB_AP_REP)); } else { ap_rep_wrapped = data_blob(NULL, 0); } @@ -417,7 +425,9 @@ static int reply_spnego_negotiate(connection_struct *conn, DATA_BLOB secblob; int i; DATA_BLOB chal; - BOOL got_kerberos = False; +#ifdef HAVE_KRB5 + BOOL got_kerberos_mechanism = False; +#endif NTSTATUS nt_status; /* parse out the OIDs and the first sec blob */ @@ -434,11 +444,13 @@ static int reply_spnego_negotiate(connection_struct *conn, server sent back krb5/mskrb5/ntlmssp as mechtypes, but the client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an NTLMSSP mechtoken. --jerry */ - + +#ifdef HAVE_KRB5 if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 || strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) { - got_kerberos = True; + got_kerberos_mechanism = True; } +#endif for (i=0;OIDs[i];i++) { DEBUG(3,("Got OID %s\n", OIDs[i])); @@ -447,7 +459,7 @@ static int reply_spnego_negotiate(connection_struct *conn, DEBUG(3,("Got secblob of size %lu\n", (unsigned long)secblob.length)); #ifdef HAVE_KRB5 - if (got_kerberos && (SEC_ADS == lp_security())) { + if (got_kerberos_mechanism && (SEC_ADS == lp_security())) { int ret = reply_spnego_kerberos(conn, inbuf, outbuf, length, bufsize, &secblob); data_blob_free(&secblob); @@ -631,13 +643,8 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, fstring native_lanman; fstring primary_domain; static BOOL done_sesssetup = False; - extern BOOL global_encrypted_passwords_negotiated; - extern BOOL global_spnego_negotiated; - extern enum protocol_types Protocol; - extern int max_send; auth_usersupplied_info *user_info = NULL; - extern struct auth_context *negprot_global_auth_context; auth_serversupplied_info *server_info = NULL; NTSTATUS nt_status; diff --git a/source/smbd/statcache.c b/source/smbd/statcache.c index cfc5286327b..8e22d9687b8 100644 --- a/source/smbd/statcache.c +++ b/source/smbd/statcache.c @@ -47,10 +47,15 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat TDB_DATA data_val; char *original_path; size_t original_path_length; + size_t sc_size = lp_max_stat_cache_size(); if (!lp_stat_cache()) return; + if (sc_size && (tdb_stat_cache->map_size > sc_size*1024)) { + reset_stat_cache(); + } + ZERO_STRUCT(data_val); /* diff --git a/source/smbd/trans2.c b/source/smbd/trans2.c index daa458f3a97..adc6322ac33 100644 --- a/source/smbd/trans2.c +++ b/source/smbd/trans2.c @@ -23,6 +23,7 @@ #include "includes.h" +extern int max_send; extern enum protocol_types Protocol; extern int smb_read_error; extern int global_oplock_break; @@ -58,14 +59,18 @@ SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, SMB { SMB_BIG_UINT ret; + if(S_ISDIR(sbuf->st_mode)) { + return 0; + } + #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE) ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks; #else ret = (SMB_BIG_UINT)get_file_size(*sbuf); #endif - if (!ret && fsp && fsp->initial_allocation_size) - ret = fsp->initial_allocation_size; + if (fsp && fsp->initial_allocation_size) + ret = MAX(ret,fsp->initial_allocation_size); return smb_roundup(conn, ret); } @@ -95,11 +100,6 @@ static BOOL samba_private_attr_name(const char *unix_ea_name) return False; } -struct ea_list { - struct ea_list *next, *prev; - struct ea_struct ea; -}; - /**************************************************************************** Get one EA value. Fill in a struct ea_struct. ****************************************************************************/ @@ -152,7 +152,8 @@ static BOOL get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_str Return a linked list of the total EA's. Plus the total size ****************************************************************************/ -static struct ea_list *get_ea_list(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp, const char *fname, size_t *pea_total_len) +static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp, + const char *fname, size_t *pea_total_len) { /* Get a list of all xattrs. Max namesize is 64k. */ size_t ea_namelist_size = 1024; @@ -186,7 +187,7 @@ static struct ea_list *get_ea_list(TALLOC_CTX *mem_ctx, connection_struct *conn, if (sizeret == -1) return NULL; - DEBUG(10,("get_ea_list: ea_namelist size = %d\n", sizeret )); + DEBUG(10,("get_ea_list_from_file: ea_namelist size = %d\n", sizeret )); if (sizeret) { for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p) + 1) { @@ -207,7 +208,7 @@ static struct ea_list *get_ea_list(TALLOC_CTX *mem_ctx, connection_struct *conn, fstring dos_ea_name; push_ascii_fstring(dos_ea_name, listp->ea.name); *pea_total_len += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length; - DEBUG(10,("get_ea_list: total_len = %u, %s, val len = %u\n", + DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len = %u\n", *pea_total_len, dos_ea_name, (unsigned int)listp->ea.value.length )); } @@ -219,7 +220,7 @@ static struct ea_list *get_ea_list(TALLOC_CTX *mem_ctx, connection_struct *conn, } } - DEBUG(10,("get_ea_list: total_len = %u\n", *pea_total_len)); + DEBUG(10,("get_ea_list_from_file: total_len = %u\n", *pea_total_len)); return ea_list_head; } @@ -228,34 +229,16 @@ static struct ea_list *get_ea_list(TALLOC_CTX *mem_ctx, connection_struct *conn, that was filled. ****************************************************************************/ -static unsigned int fill_ea_buffer(char *pdata, unsigned int total_data_size, - connection_struct *conn, files_struct *fsp, const char *fname) +static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size, + connection_struct *conn, struct ea_list *ea_list) { unsigned int ret_data_size = 4; char *p = pdata; - size_t total_ea_len; - TALLOC_CTX *mem_ctx; - struct ea_list *ea_list; SMB_ASSERT(total_data_size >= 4); - SIVAL(pdata,0,0); if (!lp_ea_support(SNUM(conn))) { - return 4; - } - mem_ctx = talloc_init("fill_ea_buffer"); - if (!mem_ctx) { - return 4; - } - - ea_list = get_ea_list(mem_ctx, conn, fsp, fname, &total_ea_len); - if (!ea_list) { - talloc_destroy(mem_ctx); - return 4; - } - - if (total_ea_len > total_data_size) { - talloc_destroy(mem_ctx); + SIVAL(pdata,4,0); return 4; } @@ -286,9 +269,7 @@ static unsigned int fill_ea_buffer(char *pdata, unsigned int total_data_size, } ret_data_size = PTR_DIFF(p, pdata); - DEBUG(10,("fill_ea_buffer: data_size = %u, total_ea_len = %u\n", - ret_data_size, total_ea_len )); - talloc_destroy(mem_ctx); + DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size )); SIVAL(pdata,0,ret_data_size); return ret_data_size; } @@ -302,7 +283,7 @@ static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, return 0; } mem_ctx = talloc_init("estimate_ea_size"); - (void)get_ea_list(mem_ctx, conn, fsp, fname, &total_ea_len); + (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len); talloc_destroy(mem_ctx); return total_ea_len; } @@ -315,7 +296,7 @@ static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, con { size_t total_ea_len; TALLOC_CTX *mem_ctx = talloc_init("canonicalize_ea_name"); - struct ea_list *ea_list = get_ea_list(mem_ctx, conn, fsp, fname, &total_ea_len); + struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len); for (; ea_list; ea_list = ea_list->next) { if (strequal(&unix_ea_name[5], ea_list->ea.name)) { @@ -332,99 +313,246 @@ static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, con Set or delete an extended attribute. ****************************************************************************/ -static NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, - char *pdata, int total_data) +NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list) { - unsigned int namelen; - unsigned int ealen; - int ret; - fstring unix_ea_name; - if (!lp_ea_support(SNUM(conn))) { return NT_STATUS_EAS_NOT_SUPPORTED; } - if (total_data < 8) { - return NT_STATUS_INVALID_PARAMETER; + for (;ea_list; ea_list = ea_list->next) { + int ret; + fstring unix_ea_name; + + fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */ + fstrcat(unix_ea_name, ea_list->ea.name); + + canonicalize_ea_name(conn, fsp, fname, unix_ea_name); + + DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, ea_list->ea.value.length)); + + if (samba_private_attr_name(unix_ea_name)) { + DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name)); + return NT_STATUS_ACCESS_DENIED; + } + + if (ea_list->ea.value.length == 0) { + /* Remove the attribute. */ + if (fsp && (fsp->fd != -1)) { + DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n", + unix_ea_name, fsp->fsp_name)); + ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fd, unix_ea_name); + } else { + DEBUG(10,("set_ea: deleting ea name %s on file %s.\n", + unix_ea_name, fname)); + ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name); + } +#ifdef ENOATTR + /* Removing a non existent attribute always succeeds. */ + if (ret == -1 && errno == ENOATTR) { + DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n", + unix_ea_name)); + ret = 0; + } +#endif + } else { + if (fsp && (fsp->fd != -1)) { + DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n", + unix_ea_name, fsp->fsp_name)); + ret = SMB_VFS_FSETXATTR(fsp, fsp->fd, unix_ea_name, + ea_list->ea.value.data, ea_list->ea.value.length, 0); + } else { + DEBUG(10,("set_ea: setting ea name %s on file %s.\n", + unix_ea_name, fname)); + ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name, + ea_list->ea.value.data, ea_list->ea.value.length, 0); + } + } + + if (ret == -1) { +#ifdef ENOTSUP + if (errno == ENOTSUP) { + return NT_STATUS_EAS_NOT_SUPPORTED; + } +#endif + return map_nt_error_from_unix(errno); + } + + } + return NT_STATUS_OK; +} +/**************************************************************************** + Read a list of EA names from an incoming data buffer. Create an ea_list with them. +****************************************************************************/ + +static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size) +{ + struct ea_list *ea_list_head = NULL; + size_t offset = 0; + + while (offset + 2 < data_size) { + struct ea_list *tmp; + struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list); + unsigned int namelen = CVAL(pdata,offset); + + offset++; /* Go past the namelen byte. */ + + /* integer wrap paranioa. */ + if ((offset + namelen < offset) || (offset + namelen < namelen) || + (offset > data_size) || (namelen > data_size) || + (offset + namelen >= data_size)) { + break; + } + /* Ensure the name is null terminated. */ + if (pdata[offset + namelen] != '\0') { + return NULL; + } + pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset]); + if (!eal->ea.name) { + return NULL; + } + + offset += (namelen + 1); /* Go past the name + terminating zero. */ + DLIST_ADD_END(ea_list_head, eal, tmp); + DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name)); + } + + return ea_list_head; +} + +/**************************************************************************** + Read one EA list entry from the buffer. +****************************************************************************/ + +struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used) +{ + struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list); + uint16 val_len; + unsigned int namelen; + + if (!eal) { + return NULL; } - if (IVAL(pdata,0) > total_data) { - DEBUG(10,("set_ea: bad total data size (%u) > %u\n", IVAL(pdata,0), (unsigned int)total_data)); - return NT_STATUS_INVALID_PARAMETER; + if (data_size < 6) { + return NULL; } - pdata += 4; + eal->ea.flags = CVAL(pdata,0); namelen = CVAL(pdata,1); - ealen = SVAL(pdata,2); - pdata += 4; - if (total_data < 8 + namelen + 1 + ealen) { - DEBUG(10,("set_ea: bad total data size (%u) < 8 + namelen (%u) + 1 + ealen (%u)\n", - (unsigned int)total_data, namelen, ealen)); - return NT_STATUS_INVALID_PARAMETER; + val_len = SVAL(pdata,2); + + if (4 + namelen + 1 + val_len > data_size) { + return NULL; } - if (pdata[namelen] != '\0') { - DEBUG(10,("set_ea: ea name not null terminated\n")); - return NT_STATUS_INVALID_PARAMETER; + /* Ensure the name is null terminated. */ + if (pdata[namelen + 4] != '\0') { + return NULL; + } + pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4); + if (!eal->ea.name) { + return NULL; } - fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */ - pull_ascii(&unix_ea_name[5], pdata, sizeof(fstring) - 5, -1, STR_TERMINATE); - pdata += (namelen + 1); + eal->ea.value = data_blob(NULL, (size_t)val_len + 1); + if (!eal->ea.value.data) { + return NULL; + } - canonicalize_ea_name(conn, fsp, fname, unix_ea_name); + memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len); - DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, ealen)); - if (ealen) { - DEBUG(10,("set_ea: data :\n")); - dump_data(10, pdata, ealen); - } + /* Ensure we're null terminated just in case we print the value. */ + eal->ea.value.data[val_len] = '\0'; + /* But don't count the null. */ + eal->ea.value.length--; - if (samba_private_attr_name(unix_ea_name)) { - DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name)); - return NT_STATUS_ACCESS_DENIED; + if (pbytes_used) { + *pbytes_used = 4 + namelen + 1 + val_len; } - if (ealen == 0) { - /* Remove the attribute. */ - if (fsp && (fsp->fd != -1)) { - DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n", - unix_ea_name, fsp->fsp_name)); - ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fd, unix_ea_name); - } else { - DEBUG(10,("set_ea: deleting ea name %s on file %s.\n", - unix_ea_name, fname)); - ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name); - } -#ifdef ENOATTR - /* Removing a non existent attribute always succeeds. */ - if (ret == -1 && errno == ENOATTR) { - DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n", unix_ea_name)); - ret = 0; - } -#endif - } else { - if (fsp && (fsp->fd != -1)) { - DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n", - unix_ea_name, fsp->fsp_name)); - ret = SMB_VFS_FSETXATTR(fsp, fsp->fd, unix_ea_name, pdata, ealen, 0); - } else { - DEBUG(10,("set_ea: setting ea name %s on file %s.\n", - unix_ea_name, fname)); - ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name, pdata, ealen, 0); + DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name)); + dump_data(10, eal->ea.value.data, eal->ea.value.length); + + return eal; +} + +/**************************************************************************** + Read a list of EA names and data from an incoming data buffer. Create an ea_list with them. +****************************************************************************/ + +static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size) +{ + struct ea_list *ea_list_head = NULL; + size_t offset = 0; + size_t bytes_used = 0; + + while (offset < data_size) { + struct ea_list *tmp; + struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used); + + if (!eal) { + return NULL; } + + DLIST_ADD_END(ea_list_head, eal, tmp); + offset += bytes_used; } - if (ret == -1) { -#ifdef ENOTSUP - if (errno == ENOTSUP) { - return NT_STATUS_EAS_NOT_SUPPORTED; + return ea_list_head; +} + +/**************************************************************************** + Count the total EA size needed. +****************************************************************************/ + +static size_t ea_list_size(struct ea_list *ealist) +{ + fstring dos_ea_name; + struct ea_list *listp; + size_t ret = 0; + + for (listp = ealist; listp; listp = listp->next) { + push_ascii_fstring(dos_ea_name, listp->ea.name); + ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length; + } + /* Add on 4 for total length. */ + if (ret) { + ret += 4; + } + + return ret; +} + +/**************************************************************************** + Return a union of EA's from a file list and a list of names. + The TALLOC context for the two lists *MUST* be identical as we steal + memory from one list to add to another. JRA. +****************************************************************************/ + +static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len) +{ + struct ea_list *nlistp, *flistp; + + for (nlistp = name_list; nlistp; nlistp = nlistp->next) { + for (flistp = file_list; flistp; flistp = flistp->next) { + if (strequal(nlistp->ea.name, flistp->ea.name)) { + break; + } + } + + if (flistp) { + /* Copy the data from this entry. */ + nlistp->ea.flags = flistp->ea.flags; + nlistp->ea.value = flistp->ea.value; + } else { + /* Null entry. */ + nlistp->ea.flags = 0; + ZERO_STRUCT(nlistp->ea.value); } -#endif - return map_nt_error_from_unix(errno); } - return NT_STATUS_OK; + *total_ea_len = ea_list_size(name_list); + return name_list; } /**************************************************************************** @@ -447,7 +575,6 @@ static int send_trans2_replies(char *outbuf, global struct. These different max_xmit variables should be merged as this is now too confusing */ - extern int max_send; int data_to_send = datasize; int params_to_send = paramsize; int useable_space; @@ -587,6 +714,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i unsigned int max_data_bytes) { char *params = *pparams; + char *pdata = *ppdata; int16 open_mode; int16 open_attr; BOOL oplock_request; @@ -606,18 +734,27 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i int smb_action = 0; BOOL bad_path = False; files_struct *fsp; + TALLOC_CTX *ctx = NULL; + struct ea_list *ea_list = NULL; + uint16 flags = 0; NTSTATUS status; /* * Ensure we have enough parameters to perform the operation. */ - if (total_params < 29) - return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + if (total_params < 29) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + flags = SVAL(params, 0); open_mode = SVAL(params, 2); open_attr = SVAL(params,6); - oplock_request = (((SVAL(params,0)|(1<<1))>>1) | ((SVAL(params,0)|(1<<2))>>1)); + oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0; + if (oplock_request) { + oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0; + } + #if 0 return_additional_info = BITSETW(params,0); open_sattr = SVAL(params, 4); @@ -635,7 +772,7 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i return ERROR_NT(status); } - DEBUG(3,("trans2open %s mode=%d attr=%d ofun=%d size=%d\n", + DEBUG(3,("call_trans2open %s mode=%d attr=%d ofun=%d size=%d\n", fname,open_mode, open_attr, open_ofun, open_size)); /* XXXX we need to handle passed times, sattr and flags */ @@ -649,13 +786,47 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess); } + /* Strange open mode mapping. */ + if (open_ofun == 0) { + if (GET_OPEN_MODE(open_mode) == DOS_OPEN_EXEC) { + open_ofun = FILE_EXISTS_FAIL | FILE_CREATE_IF_NOT_EXIST; + } + } + + /* Any data in this call is an EA list. */ + if (total_data && !lp_ea_support(SNUM(conn))) { + return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED); + } + + if (total_data) { + if (total_data < 10) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + + if (IVAL(pdata,0) > total_data) { + DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n", + IVAL(pdata,0), (unsigned int)total_data)); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + + ctx = talloc_init("TRANS2_OPEN_SET_EA"); + if (!ctx) { + return ERROR_NT(NT_STATUS_NO_MEMORY); + } + ea_list = read_ea_list(ctx, pdata + 4, total_data - 4); + if (!ea_list) { + talloc_destroy(ctx); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + } + fsp = open_file_shared(conn,fname,&sbuf,open_mode,open_ofun,(uint32)open_attr, oplock_request, &rmode,&smb_action); if (!fsp) { + talloc_destroy(ctx); if (open_was_deferred(SVAL(inbuf,smb_mid))) { /* We have re-scheduled this call. */ - clear_cached_errors(); return -1; } return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess); @@ -666,25 +837,37 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i mtime = sbuf.st_mtime; inode = sbuf.st_ino; if (fmode & aDIR) { + talloc_destroy(ctx); close_file(fsp,False); return(ERROR_DOS(ERRDOS,ERRnoaccess)); } + if (total_data && smb_action == FILE_WAS_CREATED) { + status = set_ea(conn, fsp, fname, ea_list); + talloc_destroy(ctx); + if (!NT_STATUS_IS_OK(status)) { + close_file(fsp,False); + return ERROR_NT(status); + } + } + /* Realloc the size of parameters and data we will return */ - params = SMB_REALLOC(*pparams, 28); - if( params == NULL ) - return(ERROR_DOS(ERRDOS,ERRnomem)); + params = SMB_REALLOC(*pparams, 30); + if( params == NULL ) { + return ERROR_NT(NT_STATUS_NO_MEMORY); + } *pparams = params; - memset((char *)params,'\0',28); + memset((char *)params,'\0',30); SSVAL(params,0,fsp->fnum); SSVAL(params,2,fmode); put_dos_date2(params,4, mtime); SIVAL(params,8, (uint32)size); SSVAL(params,12,rmode); - if (oplock_request && lp_fake_oplocks(SNUM(conn))) + if (oplock_request && lp_fake_oplocks(SNUM(conn))) { smb_action |= EXTENDED_OPLOCK_GRANTED; + } SSVAL(params,18,smb_action); @@ -692,9 +875,13 @@ static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, i * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes. */ SIVAL(params,20,inode); - + if (flags & 8) { + uint32 ea_size = estimate_ea_size(conn, fsp, fname); + SIVAL(params, 26, ea_size); + } + /* Send the required number of replies */ - send_trans2_replies(outbuf, bufsize, params, 28, *ppdata, 0); + send_trans2_replies(outbuf, bufsize, params, 30, *ppdata, 0); return -1; } @@ -811,7 +998,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, BOOL dont_descend,char **ppdata, char *base_data, int space_remaining, BOOL *out_of_space, BOOL *got_exact_match, - int *last_entry_off) + int *last_entry_off, struct ea_list *name_list, TALLOC_CTX *ea_ctx) { const char *dname; BOOL found = False; @@ -970,8 +1157,8 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL; switch (info_level) { - case SMB_INFO_STANDARD: - DEBUG(10,("get_lanman2_dir_entry: SMB_INFO_STANDARD\n")); + case SMB_FIND_INFO_STANDARD: + DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n")); if(requires_resume_key) { SIVAL(p,0,reskey); p += 4; @@ -1002,8 +1189,8 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, p += len; break; - case SMB_INFO_QUERY_EA_SIZE: - DEBUG(10,("get_lanman2_dir_entry: SMB_INFO_QUERY_EA_SIZE\n")); + case SMB_FIND_EA_SIZE: + DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n")); if(requires_resume_key) { SIVAL(p,0,reskey); p += 4; @@ -1039,6 +1226,63 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn, SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */ break; + case SMB_FIND_EA_LIST: + { + struct ea_list *file_list = NULL; + size_t ea_len = 0; + + DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n")); + if (!name_list) { + return False; + } + if(requires_resume_key) { + SIVAL(p,0,reskey); + p += 4; + } + put_dos_date2(p,l2_fdateCreation,cdate); + put_dos_date2(p,l2_fdateLastAccess,adate); + put_dos_date2(p,l2_fdateLastWrite,mdate); + SIVAL(p,l2_cbFile,(uint32)file_size); + SIVAL(p,l2_cbFileAlloc,(uint32)allocation_size); + SSVAL(p,l2_attrFile,mode); + p += l2_cbList; /* p now points to the EA area. */ + + file_list = get_ea_list_from_file(ea_ctx, conn, NULL, pathreal, &ea_len); + name_list = ea_list_union(name_list, file_list, &ea_len); + + /* We need to determine if this entry will fit in the space available. */ + /* Max string size is 255 bytes. */ + if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) { + /* Move the dirptr back to prev_dirpos */ + dptr_SeekDir(conn->dirptr, prev_dirpos); + *out_of_space = True; + DEBUG(9,("get_lanman2_dir_entry: out of space\n")); + return False; /* Not finished - just out of space */ + } + + /* Push the ea_data followed by the name. */ + p += fill_ea_buffer(ea_ctx, p, space_remaining, conn, name_list); + nameptr = p; + len = srvstr_push(outbuf, p + 1, fname, -1, STR_TERMINATE | STR_NOALIGN); + if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) { + if (len > 2) { + len -= 2; + } else { + len = 0; + } + } else { + if (len > 1) { + len -= 1; + } else { + len = 0; + } + } + SCVAL(nameptr,0,len); + p += len + 1; + SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */ + break; + } + case SMB_FIND_FILE_BOTH_DIRECTORY_INFO: DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n")); was_8_3 = mangle_is_8_3(fname, True); @@ -1338,10 +1582,13 @@ static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outb int space_remaining; BOOL bad_path = False; SMB_STRUCT_STAT sbuf; + TALLOC_CTX *ea_ctx = NULL; + struct ea_list *ea_list = NULL; NTSTATUS ntstatus = NT_STATUS_OK; - if (total_params < 12) - return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + if (total_params < 12) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } *directory = *mask = 0; @@ -1356,8 +1603,9 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", } switch (info_level) { - case SMB_INFO_STANDARD: - case SMB_INFO_QUERY_EA_SIZE: + case SMB_FIND_INFO_STANDARD: + case SMB_FIND_EA_SIZE: + case SMB_FIND_EA_LIST: case SMB_FIND_FILE_DIRECTORY_INFO: case SMB_FIND_FILE_FULL_DIRECTORY_INFO: case SMB_FIND_FILE_NAMES_INFO: @@ -1378,7 +1626,7 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", return ERROR_NT(ntstatus); } - RESOLVE_FINDFIRST_DFSPATH(directory, conn, inbuf, outbuf); + RESOLVE_DFSPATH_WCARD(directory, conn, inbuf, outbuf); unix_convert(directory,conn,0,&bad_path,&sbuf); if (bad_path) { @@ -1403,29 +1651,66 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", DEBUG(5,("dir=%s, mask = %s\n",directory, mask)); + if (info_level == SMB_FIND_EA_LIST) { + uint32 ea_size; + + if (total_data < 4) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + + ea_size = IVAL(pdata,0); + if (ea_size != total_data) { + DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \ +total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) )); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + + if (!lp_ea_support(SNUM(conn))) { + return ERROR_DOS(ERRDOS,ERReasnotsupported); + } + + if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) { + return ERROR_NT(NT_STATUS_NO_MEMORY); + } + + /* Pull out the list of names. */ + ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4); + if (!ea_list) { + talloc_destroy(ea_ctx); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + } + pdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN); - if( pdata == NULL ) - return(ERROR_DOS(ERRDOS,ERRnomem)); + if( pdata == NULL ) { + talloc_destroy(ea_ctx); + return ERROR_NT(NT_STATUS_NO_MEMORY); + } *ppdata = pdata; memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN); /* Realloc the params space */ params = SMB_REALLOC(*pparams, 10); - if (params == NULL) - return ERROR_DOS(ERRDOS,ERRnomem); + if (params == NULL) { + talloc_destroy(ea_ctx); + return ERROR_NT(NT_STATUS_NO_MEMORY); + } *pparams = params; dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid)); - if (dptr_num < 0) + if (dptr_num < 0) { + talloc_destroy(ea_ctx); return(UNIXERROR(ERRDOS,ERRbadfile)); + } /* Save the wildcard match and attribs we are using on this directory - needed as lanman2 assumes these are being saved between calls */ if (!dptr_set_wcard_and_attributes(dptr_num, mask, dirtype)) { dptr_close(&dptr_num); - return ERROR_DOS(ERRDOS,ERRnomem); + talloc_destroy(ea_ctx); + return ERROR_NT(NT_STATUS_NO_MEMORY); } DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, mask, dirtype)); @@ -1455,7 +1740,7 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", mask,dirtype,info_level, requires_resume_key,dont_descend, &p,pdata,space_remaining, &out_of_space, &got_exact_match, - &last_entry_off); + &last_entry_off, ea_list, ea_ctx); } if (finished && out_of_space) @@ -1477,6 +1762,8 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n", space_remaining = max_data_bytes - PTR_DIFF(p,pdata); } + talloc_destroy(ea_ctx); + /* Check if we can close the dirptr */ if(close_after_first || (finished && close_if_end)) { DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num)); @@ -1566,10 +1853,13 @@ static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbu BOOL dont_descend = False; BOOL out_of_space = False; int space_remaining; + TALLOC_CTX *ea_ctx = NULL; + struct ea_list *ea_list = NULL; NTSTATUS ntstatus = NT_STATUS_OK; - if (total_params < 12) - return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + if (total_params < 12) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } *mask = *directory = *resume_name = 0; @@ -1600,8 +1890,9 @@ resume_key = %d resume name = %s continue=%d level = %d\n", } switch (info_level) { - case SMB_INFO_STANDARD: - case SMB_INFO_QUERY_EA_SIZE: + case SMB_FIND_INFO_STANDARD: + case SMB_FIND_EA_SIZE: + case SMB_FIND_EA_LIST: case SMB_FIND_FILE_DIRECTORY_INFO: case SMB_FIND_FILE_FULL_DIRECTORY_INFO: case SMB_FIND_FILE_NAMES_INFO: @@ -1615,29 +1906,66 @@ resume_key = %d resume name = %s continue=%d level = %d\n", return ERROR_DOS(ERRDOS,ERRunknownlevel); } + if (info_level == SMB_FIND_EA_LIST) { + uint32 ea_size; + + if (total_data < 4) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + + ea_size = IVAL(pdata,0); + if (ea_size != total_data) { + DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \ +total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) )); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + + if (!lp_ea_support(SNUM(conn))) { + return ERROR_DOS(ERRDOS,ERReasnotsupported); + } + + if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) { + return ERROR_NT(NT_STATUS_NO_MEMORY); + } + + /* Pull out the list of names. */ + ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4); + if (!ea_list) { + talloc_destroy(ea_ctx); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + } + pdata = SMB_REALLOC( *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN); - if(pdata == NULL) - return ERROR_DOS(ERRDOS,ERRnomem); + if(pdata == NULL) { + talloc_destroy(ea_ctx); + return ERROR_NT(NT_STATUS_NO_MEMORY); + } *ppdata = pdata; memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN); /* Realloc the params space */ params = SMB_REALLOC(*pparams, 6*SIZEOFWORD); - if( params == NULL ) - return ERROR_DOS(ERRDOS,ERRnomem); + if( params == NULL ) { + talloc_destroy(ea_ctx); + return ERROR_NT(NT_STATUS_NO_MEMORY); + } *pparams = params; /* Check that the dptr is valid */ - if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) + if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) { + talloc_destroy(ea_ctx); return ERROR_DOS(ERRDOS,ERRnofiles); + } string_set(&conn->dirpath,dptr_path(dptr_num)); /* Get the wildcard mask from the dptr */ if((p = dptr_wcard(dptr_num))== NULL) { DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num)); + talloc_destroy(ea_ctx); return ERROR_DOS(ERRDOS,ERRnofiles); } @@ -1708,7 +2036,7 @@ resume_key = %d resume name = %s continue=%d level = %d\n", mask,dirtype,info_level, requires_resume_key,dont_descend, &p,pdata,space_remaining, &out_of_space, &got_exact_match, - &last_entry_off); + &last_entry_off, ea_list, ea_ctx); } if (finished && out_of_space) @@ -1730,6 +2058,8 @@ resume_key = %d resume name = %s continue=%d level = %d\n", space_remaining = max_data_bytes - PTR_DIFF(p,pdata); } + talloc_destroy(ea_ctx); + /* Check if we can close the dirptr */ if(close_after_request || (finished && close_if_end)) { DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num)); @@ -1780,8 +2110,9 @@ static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf } pdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN); - if ( pdata == NULL ) - return ERROR_DOS(ERRDOS,ERRnomem); + if ( pdata == NULL ) { + return ERROR_NT(NT_STATUS_NO_MEMORY); + } *ppdata = pdata; memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN); @@ -1830,7 +2161,13 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsi * the called hostname and the service name. */ SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) ); - len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN); + /* + * Win2k3 and previous mess this up by sending a name length + * one byte short. I believe only older clients (OS/2 Win9x) use + * this call so try fixing this by adding a terminating null to + * the pushed string. The change here was adding the STR_TERMINATE. JRA. + */ + len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN|STR_TERMINATE); SCVAL(pdata,l2_vol_cch,len); data_len = l2_vol_szVolLabel + len; DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n", @@ -2098,7 +2435,7 @@ static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outb if (total_params < 4) { DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n", total_params)); - return ERROR_DOS(ERRDOS,ERRinvalidparam); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } fsp = file_fsp(params,0); @@ -2333,7 +2670,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * int mode=0; SMB_OFF_T file_size=0; SMB_BIG_UINT allocation_size=0; - unsigned int data_size; + unsigned int data_size = 0; unsigned int param_size = 2; SMB_STRUCT_STAT sbuf; pstring fname, dos_fname; @@ -2346,6 +2683,8 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * int len; time_t c_time; files_struct *fsp = NULL; + TALLOC_CTX *ea_ctx = NULL; + struct ea_list *ea_list = NULL; uint32 desired_access = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */ if (!params) @@ -2354,8 +2693,9 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * ZERO_STRUCT(sbuf); if (tran_call == TRANSACT2_QFILEINFO) { - if (total_params < 4) - return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + if (total_params < 4) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } fsp = file_fsp(params,0); info_level = SVAL(params,2); @@ -2410,8 +2750,9 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * NTSTATUS status = NT_STATUS_OK; /* qpathinfo */ - if (total_params < 6) - return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + if (total_params < 6) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } info_level = SVAL(params,0); @@ -2463,7 +2804,6 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * fullpathname = fname; file_size = get_file_size(sbuf); - allocation_size = get_allocation_size(conn,fsp,&sbuf); if (mode & aDIR) { /* This is necessary, as otherwise the desktop.ini file in * this folder is ignored */ @@ -2471,27 +2811,58 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * file_size = 0; } + /* Pull any EA list from the data portion. */ + if (info_level == SMB_INFO_QUERY_EAS_FROM_LIST) { + uint32 ea_size; + + if (total_data < 4) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + ea_size = IVAL(pdata,0); + + if (total_data > 0 && ea_size != total_data) { + DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \ +total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) )); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + + if (!lp_ea_support(SNUM(conn))) { + return ERROR_DOS(ERRDOS,ERReasnotsupported); + } + + if ((ea_ctx = talloc_init("ea_list")) == NULL) { + return ERROR_NT(NT_STATUS_NO_MEMORY); + } + + /* Pull out the list of names. */ + ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4); + if (!ea_list) { + talloc_destroy(ea_ctx); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + } + params = SMB_REALLOC(*pparams,2); - if (params == NULL) - return ERROR_DOS(ERRDOS,ERRnomem); + if (params == NULL) { + talloc_destroy(ea_ctx); + return ERROR_NT(NT_STATUS_NO_MEMORY); + } *pparams = params; memset((char *)params,'\0',2); data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN; pdata = SMB_REALLOC(*ppdata, data_size); - if ( pdata == NULL ) - return ERROR_DOS(ERRDOS,ERRnomem); - *ppdata = pdata; - - if (total_data > 0 && IVAL(pdata,0) == total_data) { - /* uggh, EAs for OS2 */ - DEBUG(4,("Rejecting EA request with total_data=%d\n",total_data)); - return ERROR_DOS(ERRDOS,ERReasnotsupported); + if ( pdata == NULL ) { + talloc_destroy(ea_ctx); + return ERROR_NT(NT_STATUS_NO_MEMORY); } + *ppdata = pdata; memset((char *)pdata,'\0',data_size); c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))); + allocation_size = get_allocation_size(conn,fsp,&sbuf); + if (fsp) { if (fsp->pending_modtime) { /* the pending modtime overrides the current modtime */ @@ -2504,6 +2875,9 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * /* the pending modtime overrides the current modtime */ sbuf.st_mtime = fsp1->pending_modtime; } + if (fsp1 && fsp1->initial_allocation_size) { + allocation_size = get_allocation_size(conn, fsp1, &sbuf); + } } if (lp_dos_filetime_resolution(SNUM(conn))) { @@ -2560,21 +2934,51 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * break; case SMB_INFO_QUERY_EAS_FROM_LIST: + { + size_t total_ea_len = 0; + struct ea_list *ea_file_list = NULL; + DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n")); - data_size = 24; - put_dos_date2(pdata,0,c_time); - put_dos_date2(pdata,4,sbuf.st_atime); - put_dos_date2(pdata,8,sbuf.st_mtime); - SIVAL(pdata,12,(uint32)file_size); - SIVAL(pdata,16,(uint32)allocation_size); - SIVAL(pdata,20,mode); + + ea_file_list = get_ea_list_from_file(ea_ctx, conn, fsp, fname, &total_ea_len); + ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len); + + if (!ea_list || (total_ea_len > data_size)) { + talloc_destroy(ea_ctx); + data_size = 4; + SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */ + break; + } + + data_size = fill_ea_buffer(ea_ctx, pdata, data_size, conn, ea_list); + talloc_destroy(ea_ctx); break; + } case SMB_INFO_QUERY_ALL_EAS: - DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n")); + { /* We have data_size bytes to put EA's into. */ - data_size = fill_ea_buffer(pdata, data_size, conn, fsp, fname); + size_t total_ea_len = 0; + + DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n")); + + ea_ctx = talloc_init("ea_ctx"); + if (!ea_ctx) { + return ERROR_NT(NT_STATUS_NO_MEMORY); + } + + ea_list = get_ea_list_from_file(ea_ctx, conn, fsp, fname, &total_ea_len); + if (!ea_list || (total_ea_len > data_size)) { + talloc_destroy(ea_ctx); + data_size = 4; + SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */ + break; + } + + data_size = fill_ea_buffer(ea_ctx, pdata, data_size, conn, ea_list); + talloc_destroy(ea_ctx); break; + } case SMB_FILE_BASIC_INFORMATION: case SMB_QUERY_FILE_BASIC_INFO: @@ -3177,10 +3581,12 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char return ERROR_NT(NT_STATUS_INVALID_PARAMETER); ZERO_STRUCT(sbuf); + ZERO_STRUCT(tvs); if (tran_call == TRANSACT2_SETFILEINFO) { - if (total_params < 4) - return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + if (total_params < 4) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } fsp = file_fsp(params,0); info_level = SVAL(params,2); @@ -3226,8 +3632,9 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char } } else { /* set path info */ - if (total_params < 6) - return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + if (total_params < 6) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } info_level = SVAL(params,0); srvstr_get_path(inbuf, fname, ¶ms[6], sizeof(fname), -1, STR_TERMINATE, &status, False); @@ -3266,10 +3673,11 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n", tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data)); - /* Realloc the parameter and data sizes */ + /* Realloc the parameter size */ params = SMB_REALLOC(*pparams,2); - if(params == NULL) - return ERROR_DOS(ERRDOS,ERRnomem); + if(params == NULL) { + return ERROR_NT(NT_STATUS_NO_MEMORY); + } *pparams = params; SSVAL(params,0,0); @@ -3291,8 +3699,9 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char switch (info_level) { case SMB_INFO_STANDARD: { - if (total_data < 12) - return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + if (total_data < 12) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } /* access time */ tvs.actime = make_unix_date2(pdata+l1_fdateLastAccess); @@ -3302,17 +3711,50 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char } case SMB_INFO_SET_EA: - status = set_ea(conn, fsp, fname, pdata, total_data); - if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK)) + { + struct ea_list *ea_list = NULL; + TALLOC_CTX *ctx = NULL; + + if (total_data < 10) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + + if (IVAL(pdata,0) > total_data) { + DEBUG(10,("call_trans2setfilepathinfo: bad total data size (%u) > %u\n", + IVAL(pdata,0), (unsigned int)total_data)); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + + ctx = talloc_init("SMB_INFO_SET_EA"); + if (!ctx) { + return ERROR_NT(NT_STATUS_NO_MEMORY); + } + ea_list = read_ea_list(ctx, pdata + 4, total_data - 4); + if (!ea_list) { + talloc_destroy(ctx); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + status = set_ea(conn, fsp, fname, ea_list); + talloc_destroy(ctx); + + if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); - break; + } + /* We're done. We only get EA info in this call. */ + SSVAL(params,0,0); + send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); + return(-1); + } + +#if 0 + /* The following 2 info levels are only valid on query, not set. Remove them. JRA. */ /* XXXX um, i don't think this is right. it's also not in the cifs6.txt spec. */ case SMB_INFO_QUERY_EAS_FROM_LIST: if (total_data < 28) - return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); tvs.actime = make_unix_date2(pdata+8); tvs.modtime = make_unix_date2(pdata+12); @@ -3323,13 +3765,14 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char /* XXXX nor this. not in cifs6.txt, either. */ case SMB_INFO_QUERY_ALL_EAS: if (total_data < 28) - return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); tvs.actime = make_unix_date2(pdata+8); tvs.modtime = make_unix_date2(pdata+12); size = IVAL(pdata,16); dosmode = IVAL(pdata,24); break; +#endif case SMB_SET_FILE_BASIC_INFO: case SMB_FILE_BASIC_INFORMATION: @@ -3338,8 +3781,9 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char time_t write_time; time_t changed_time; - if (total_data < 36) - return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + if (total_data < 36) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } /* Ignore create time at offset pdata. */ @@ -3370,8 +3814,9 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char int ret = -1; SMB_BIG_UINT allocation_size; - if (total_data < 8) - return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + if (total_data < 8) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } allocation_size = (SMB_BIG_UINT)IVAL(pdata,0); #ifdef LARGE_SMB_OFF_T @@ -3444,8 +3889,9 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char case SMB_FILE_END_OF_FILE_INFORMATION: case SMB_SET_FILE_END_OF_FILE_INFO: { - if (total_data < 8) - return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + if (total_data < 8) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } size = IVAL(pdata,0); #ifdef LARGE_SMB_OFF_T @@ -3463,8 +3909,9 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char { BOOL delete_on_close; - if (total_data < 1) - return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + if (total_data < 1) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } delete_on_close = (CVAL(pdata,0) ? True : False); @@ -3477,23 +3924,28 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char status = set_delete_on_close_internal(fsp, delete_on_close, dosmode); - if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK)) + if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); + } /* The set is across all open files on this dev/inode pair. */ status =set_delete_on_close_over_all(fsp, delete_on_close); - if (NT_STATUS_V(status) != NT_STATUS_V(NT_STATUS_OK)) + if (!NT_STATUS_IS_OK(status)) { return ERROR_NT(status); + } - break; + SSVAL(params,0,0); + send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); + return(-1); } case SMB_FILE_POSITION_INFORMATION: { SMB_BIG_UINT position_information; - if (total_data < 8) - return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + if (total_data < 8) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } position_information = (SMB_BIG_UINT)IVAL(pdata,0); #ifdef LARGE_SMB_OFF_T @@ -3504,9 +3956,38 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char #endif /* LARGE_SMB_OFF_T */ DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n", fname, (double)position_information )); - if (fsp) + if (fsp) { fsp->position_information = position_information; - break; + } + + /* We're done. We only get position info in this call. */ + SSVAL(params,0,0); + send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); + return(-1); + } + + /* From tridge Samba4 : + * MODE_INFORMATION in setfileinfo (I have no + * idea what "mode information" on a file is - it takes a value of 0, + * 2, 4 or 6. What could it be?). + */ + + case SMB_FILE_MODE_INFORMATION: + { + uint32 mode; + + if (total_data < 4) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + mode = IVAL(pdata,0); + if (mode != 0 && mode != 2 && mode != 4 && mode != 6) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + + /* We're done. We only get mode info in this call. */ + SSVAL(params,0,0); + send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0); + return(-1); } /* @@ -3517,8 +3998,9 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char { uint32 raw_unixmode; - if (total_data < 100) - return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + if (total_data < 100) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO && IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) { @@ -3567,8 +4049,9 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", if (tran_call == TRANSACT2_SETFILEINFO) return(ERROR_DOS(ERRDOS,ERRnoaccess)); - if (raw_unixmode == SMB_MODE_NO_CHANGE) - return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + if (raw_unixmode == SMB_MODE_NO_CHANGE) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } #if defined(HAVE_MAKEDEV) dev = makedev(dev_major, dev_minor); @@ -3736,8 +4219,9 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", pstring base_name; char *p; - if (total_data < 12) - return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + if (total_data < 12) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } overwrite = (CVAL(pdata,0) ? True : False); root_fid = IVAL(pdata,4); @@ -3790,7 +4274,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", BOOL valid_def_acls = True; if (total_data < SMB_POSIX_ACL_HEADER_SIZE) { - return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } posix_acl_version = SVAL(pdata,0); num_file_acls = SVAL(pdata,2); @@ -3807,12 +4291,12 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", } if (posix_acl_version != SMB_POSIX_ACL_VERSION) { - return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } if (total_data < SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) { - return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls, @@ -3971,17 +4455,21 @@ static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, unsigned int max_data_bytes) { char *params = *pparams; + char *pdata = *ppdata; pstring directory; int ret = -1; SMB_STRUCT_STAT sbuf; BOOL bad_path = False; NTSTATUS status = NT_STATUS_OK; + TALLOC_CTX *ctx = NULL; + struct ea_list *ea_list = NULL; if (!CAN_WRITE(conn)) return ERROR_DOS(ERRSRV,ERRaccess); - if (total_params < 4) - return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + if (total_params < 4) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } srvstr_get_path(inbuf, directory, ¶ms[4], sizeof(directory), -1, STR_TERMINATE, &status, False); if (!NT_STATUS_IS_OK(status)) { @@ -3994,18 +4482,58 @@ static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, if (bad_path) { return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND); } - if (check_name(directory,conn)) + + /* Any data in this call is an EA list. */ + if (total_data && !lp_ea_support(SNUM(conn))) { + return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED); + } + + if (total_data) { + if (total_data < 10) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + + if (IVAL(pdata,0) > total_data) { + DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n", + IVAL(pdata,0), (unsigned int)total_data)); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + + ctx = talloc_init("TRANS2_MKDIR_SET_EA"); + if (!ctx) { + return ERROR_NT(NT_STATUS_NO_MEMORY); + } + ea_list = read_ea_list(ctx, pdata + 4, total_data - 4); + if (!ea_list) { + talloc_destroy(ctx); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } + } + + if (check_name(directory,conn)) { ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True)); + } if(ret < 0) { + talloc_destroy(ctx); DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno))); return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess); } + /* Try and set any given EA. */ + if (total_data) { + status = set_ea(conn, NULL, directory, ea_list); + talloc_destroy(ctx); + if (!NT_STATUS_IS_OK(status)) { + return ERROR_NT(status); + } + } + /* Realloc the parameter and data sizes */ params = SMB_REALLOC(*pparams,2); - if(params == NULL) - return ERROR_DOS(ERRDOS,ERRnomem); + if(params == NULL) { + return ERROR_NT(NT_STATUS_NO_MEMORY); + } *pparams = params; SSVAL(params,0,0); @@ -4028,8 +4556,9 @@ static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char char *params = *pparams; uint16 info_level; - if (total_params < 6) - return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + if (total_params < 6) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } info_level = SVAL(params,4); DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level)); @@ -4044,8 +4573,9 @@ static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char /* Realloc the parameter and data sizes */ params = SMB_REALLOC(*pparams,6); - if(params == NULL) - return ERROR_DOS(ERRDOS,ERRnomem); + if(params == NULL) { + return ERROR_NT(NT_STATUS_NO_MEMORY); + } *pparams = params; SSVAL(params,0,fnf_handle); @@ -4077,8 +4607,9 @@ static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char /* Realloc the parameter and data sizes */ params = SMB_REALLOC(*pparams,4); - if(params == NULL) - return ERROR_DOS(ERRDOS,ERRnomem); + if(params == NULL) { + return ERROR_NT(NT_STATUS_NO_MEMORY); + } *pparams = params; SSVAL(params,0,0); /* No changes */ @@ -4104,8 +4635,9 @@ static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* DEBUG(10,("call_trans2getdfsreferral\n")); - if (total_params < 2) - return(ERROR_DOS(ERRDOS,ERRinvalidparam)); + if (total_params < 2) { + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); + } max_referral_level = SVAL(params,0); @@ -4144,8 +4676,9 @@ static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) && (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) { pdata = SMB_REALLOC(*ppdata, 32); - if(pdata == NULL) - return ERROR_DOS(ERRDOS,ERRnomem); + if(pdata == NULL) { + return ERROR_NT(NT_STATUS_NO_MEMORY); + } *ppdata = pdata; /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2 @@ -4288,7 +4821,7 @@ int reply_trans2(connection_struct *conn, DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",suwcnt)); DEBUG(2,("Transaction is %d\n",tran_call)); END_PROFILE(SMBtrans2); - ERROR_DOS(ERRDOS,ERRinvalidparam); + return ERROR_NT(NT_STATUS_INVALID_PARAMETER); } } @@ -4303,7 +4836,7 @@ int reply_trans2(connection_struct *conn, SAFE_FREE(params); SAFE_FREE(data); END_PROFILE(SMBtrans2); - return ERROR_DOS(ERRDOS,ERRnomem); + return ERROR_NT(NT_STATUS_NO_MEMORY); } /* Copy the param and data bytes sent with this request into @@ -4352,6 +4885,9 @@ int reply_trans2(connection_struct *conn, unsigned int data_off; ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT); + + /* We need to re-calcuate the new length after we've read the secondary packet. */ + length = smb_len(inbuf) + 4; /* * The sequence number for the trans reply is always @@ -4399,7 +4935,7 @@ int reply_trans2(connection_struct *conn, goto bad_param; if (param_disp > total_params) goto bad_param; - if ((smb_base(inbuf) + param_off + num_params >= inbuf + bufsize) || + if ((smb_base(inbuf) + param_off + num_params > inbuf + length) || (smb_base(inbuf) + param_off + num_params < smb_base(inbuf))) goto bad_param; if (params + param_disp < params) @@ -4415,7 +4951,7 @@ int reply_trans2(connection_struct *conn, goto bad_param; if (data_disp > total_data) goto bad_param; - if ((smb_base(inbuf) + data_off + num_data >= inbuf + bufsize) || + if ((smb_base(inbuf) + data_off + num_data > inbuf + length) || (smb_base(inbuf) + data_off + num_data < smb_base(inbuf))) goto bad_param; if (data + data_disp < data) diff --git a/source/smbwrapper/smbw.c b/source/smbwrapper/smbw.c index bf60c2bc68c..edcc7a5c2f9 100644 --- a/source/smbwrapper/smbw.c +++ b/source/smbwrapper/smbw.c @@ -1224,7 +1224,7 @@ a wrapper for lseek() off_t smbw_lseek(int fd, off_t offset, int whence) { struct smbw_file *file; - size_t size; + SMB_OFF_T size; smbw_busy++; diff --git a/source/smbwrapper/smbw_stat.c b/source/smbwrapper/smbw_stat.c index bb76ef006a4..6effc9a71bc 100644 --- a/source/smbwrapper/smbw_stat.c +++ b/source/smbwrapper/smbw_stat.c @@ -69,17 +69,33 @@ BOOL smbw_getatr(struct smbw_server *srv, char *path, time_t *c_time, time_t *a_time, time_t *m_time, SMB_INO_T *ino) { + time_t c_a_m_time; + /* + * "size" (size_t) is only 32 bits. Rather than change the interface + * in this code as we change cli_qpathinfo2() and cli_getatr() to + * support 64-bit file sizes, we'll use a temporary variable and + * maintain the interface size_t. At some point, someone may want to + * change the interface as well. djl + */ + SMB_OFF_T fullsize; + DEBUG(4,("sending qpathinfo\n")); if (!srv->no_pathinfo2 && cli_qpathinfo2(&srv->cli, path, c_time, a_time, m_time, NULL, - size, mode, ino)) return True; + &fullsize, mode, ino)) { + if (size != NULL) *size = (size_t) fullsize; + return True; + } /* if this is NT then don't bother with the getatr */ if (srv->cli.capabilities & CAP_NT_SMBS) return False; - if (cli_getatr(&srv->cli, path, mode, size, m_time)) { - a_time = c_time = m_time; + if (cli_getatr(&srv->cli, path, mode, &fullsize, &c_a_m_time)) { + if (a_time != NULL) *a_time = c_a_m_time; + if (c_time != NULL) *a_time = c_a_m_time; + if (m_time != NULL) *a_time = c_a_m_time; + if (size != NULL) *size = (size_t) fullsize; srv->no_pathinfo2 = True; return True; } @@ -129,7 +145,7 @@ int smbw_fstat(int fd, struct stat *st) { struct smbw_file *file; time_t c_time, a_time, m_time; - size_t size; + SMB_OFF_T size; uint16 mode; SMB_INO_T ino = 0; diff --git a/source/tdb/tdb.c b/source/tdb/tdb.c index f66e50afe46..7159550c0c2 100644 --- a/source/tdb/tdb.c +++ b/source/tdb/tdb.c @@ -128,7 +128,7 @@ /* free memory if the pointer is valid and zero the pointer */ #ifndef SAFE_FREE -#define SAFE_FREE(x) do { if ((x) != NULL) {free((x)); (x)=NULL;} } while(0) +#define SAFE_FREE(x) do { if ((x) != NULL) {free(CONST_DISCARD(void *, (x))); (x)=NULL;} } while(0) #endif #define BUCKET(hash) ((hash) % tdb->header.hash_size) diff --git a/source/tdb/tdbbackup.c b/source/tdb/tdbbackup.c index 1a0e1c1588f..f49cd339c79 100644 --- a/source/tdb/tdbbackup.c +++ b/source/tdb/tdbbackup.c @@ -69,6 +69,9 @@ #include "tdb.h" #include "tdbback.h" +extern int optind; +extern char *optarg; + /* see if one file is newer than another */ @@ -100,8 +103,6 @@ static void usage(void) int c; int verify = 0; const char *suffix = ".bak"; - extern int optind; - extern char *optarg; while ((c = getopt(argc, argv, "vhs:")) != -1) { switch (c) { diff --git a/source/tdb/tdbtool.c b/source/tdb/tdbtool.c index 92009dcef48..2de3df961cf 100644 --- a/source/tdb/tdbtool.c +++ b/source/tdb/tdbtool.c @@ -131,7 +131,7 @@ static void help(void) "\n"); } -static void terror(char *why) +static void terror(const char *why) { printf("%s\n", why); } @@ -407,7 +407,7 @@ static void info_tdb(void) printf("%d records totalling %d bytes\n", count, total_bytes); } -static char *tdb_getline(char *prompt) +static char *tdb_getline(const char *prompt) { static char line[1024]; char *p; diff --git a/source/tdb/tdbutil.c b/source/tdb/tdbutil.c index 45ebdae3af0..4fcfb6185ae 100644 --- a/source/tdb/tdbutil.c +++ b/source/tdb/tdbutil.c @@ -40,14 +40,19 @@ static void gotalarm_sig(void) Make a TDB_DATA and keep the const warning in one place ****************************************************************/ -static TDB_DATA make_tdb_data(const char *dptr, size_t dsize) +TDB_DATA make_tdb_data(const char *dptr, size_t dsize) { TDB_DATA ret; - ret.dptr = dptr; + ret.dptr = CONST_DISCARD(char *, dptr); ret.dsize = dsize; return ret; } +TDB_DATA string_tdb_data(const char *string) +{ + return make_tdb_data(string, strlen(string)); +} + /**************************************************************************** Lock a chain with timeout (in seconds). ****************************************************************************/ @@ -57,7 +62,7 @@ static int tdb_chainlock_with_timeout_internal( TDB_CONTEXT *tdb, TDB_DATA key, /* Allow tdb_chainlock to be interrupted by an alarm. */ int ret; gotalarm = 0; - tdb_set_lock_alarm(&gotalarm); + tdb_set_lock_alarm(CONST_DISCARD(sig_atomic_t *, &gotalarm)); if (timeout) { CatchSignal(SIGALRM, SIGNAL_CAST gotalarm_sig); diff --git a/source/torture/torture.c b/source/torture/torture.c index b37a30cf2e3..8a4de57e7ff 100644 --- a/source/torture/torture.c +++ b/source/torture/torture.c @@ -590,7 +590,7 @@ static BOOL run_readwritelarge(int dummy) static struct cli_state *cli1; int fnum1; const char *lockfname = "\\large.dat"; - size_t fsize; + SMB_OFF_T fsize; char buf[126*1024]; BOOL correct = True; @@ -2360,7 +2360,7 @@ static BOOL run_trans2test(int dummy) { struct cli_state *cli; int fnum; - size_t size; + SMB_OFF_T size; time_t c_time, a_time, m_time, w_time, m_time2; const char *fname = "\\trans2.tst"; const char *dname = "\\trans2"; @@ -3591,7 +3591,7 @@ static BOOL run_opentest(int dummy) const char *fname = "\\readonly.file"; int fnum1, fnum2; char buf[20]; - size_t fsize; + SMB_OFF_T fsize; BOOL correct = True; char *tmp_path; diff --git a/source/torture/utable.c b/source/torture/utable.c index ba803a0da4f..c9b30f06e1c 100644 --- a/source/torture/utable.c +++ b/source/torture/utable.c @@ -137,7 +137,7 @@ BOOL torture_casetable(int dummy) } for (c=1; c < 0x10000; c++) { - size_t size; + SMB_OFF_T size; if (c == '.' || c == '\\') continue; diff --git a/source/utils/net.c b/source/utils/net.c index 9c05828357c..61c366710c6 100644 --- a/source/utils/net.c +++ b/source/utils/net.c @@ -87,6 +87,7 @@ const char *opt_destination = NULL; BOOL opt_have_ip = False; struct in_addr opt_dest_ip; +extern struct in_addr loopback_ip; extern BOOL AllowDebugChange; uint32 get_sec_channel_type(const char *param) @@ -321,7 +322,6 @@ BOOL net_find_server(unsigned flags, struct in_addr *server_ip, char **server_na } *server_name = SMB_STRDUP(inet_ntoa(opt_dest_ip)); } else if (!(flags & NET_FLAGS_LOCALHOST_DEFAULT_INSANE)) { - extern struct in_addr loopback_ip; *server_ip = loopback_ip; *server_name = SMB_STRDUP("127.0.0.1"); } @@ -632,62 +632,38 @@ static int net_afs(int argc, const char **argv) #endif /* WITH_FAKE_KASERVER */ -static uint32 get_maxrid(void) +static BOOL search_maxrid(struct pdb_search *search, const char *type, + uint32 *max_rid) { - SAM_ACCOUNT *pwd = NULL; - uint32 max_rid = 0; - GROUP_MAP *map = NULL; - int num_entries = 0; - int i; - - if (!pdb_setsampwent(False, 0)) { - DEBUG(0, ("get_maxrid: Unable to open passdb.\n")); - return 0; - } + struct samr_displayentry *entries; + uint32 i, num_entries; - for (; (NT_STATUS_IS_OK(pdb_init_sam(&pwd))) - && pdb_getsampwent(pwd) == True; pwd=NULL) { - uint32 rid; - - if (!sid_peek_rid(pdb_get_user_sid(pwd), &rid)) { - DEBUG(0, ("can't get RID for user '%s'\n", - pdb_get_username(pwd))); - pdb_free_sam(&pwd); - continue; - } - - if (rid > max_rid) - max_rid = rid; - - DEBUG(1,("%d is user '%s'\n", rid, pdb_get_username(pwd))); - pdb_free_sam(&pwd); + if (search == NULL) { + d_printf("get_maxrid: Could not search %s\n", type); + return False; } - pdb_endsampwent(); - pdb_free_sam(&pwd); - - if (!pdb_enum_group_mapping(SID_NAME_UNKNOWN, &map, &num_entries, - ENUM_ONLY_MAPPED)) - return max_rid; - - for (i = 0; i < num_entries; i++) { - uint32 rid; + num_entries = pdb_search_entries(search, 0, 0xffffffff, &entries); + for (i=0; i max_rid) - max_rid = rid; - } + if (!search_maxrid(pdb_search_users(0), "users", &max_rid)) + return 0; - SAFE_FREE(map); + if (!search_maxrid(pdb_search_groups(), "groups", &max_rid)) + return 0; + if (!search_maxrid(pdb_search_aliases(get_global_sam_sid()), + "aliases", &max_rid)) + return 0; + return max_rid; } diff --git a/source/utils/net_ads.c b/source/utils/net_ads.c index 9c00f05bfbb..34a357cd46d 100644 --- a/source/utils/net_ads.c +++ b/source/utils/net_ads.c @@ -81,7 +81,7 @@ static int net_ads_lookup(int argc, const char **argv) d_printf("Didn't find the cldap server!\n"); return -1; } if (!ads->config.realm) { - ads->config.realm = opt_target_workgroup; + ads->config.realm = CONST_DISCARD(char *, opt_target_workgroup); ads->ldap_port = 389; } @@ -1168,7 +1168,7 @@ static int net_ads_password(int argc, const char **argv) } if (argv[1]) { - new_password = (char *)argv[1]; + new_password = CONST_DISCARD(char *, argv[1]); } else { asprintf(&prompt, "Enter new password for %s:", user); new_password = getpass(prompt); diff --git a/source/utils/net_groupmap.c b/source/utils/net_groupmap.c index a63e8176f8a..b20a37c7267 100644 --- a/source/utils/net_groupmap.c +++ b/source/utils/net_groupmap.c @@ -693,12 +693,37 @@ static int net_groupmap_listmem(int argc, const char **argv) return 0; } +static BOOL print_alias_memberships(TALLOC_CTX *mem_ctx, + const DOM_SID *domain_sid, + const DOM_SID *member) +{ + uint32 *alias_rids; + int i, num_alias_rids; + + alias_rids = NULL; + num_alias_rids = 0; + + if (!pdb_enum_alias_memberships(mem_ctx, domain_sid, member, 1, + &alias_rids, &num_alias_rids)) { + d_printf("Could not list memberships for sid %s\n", + sid_string_static(member)); + return False; + } + + for (i = 0; i < num_alias_rids; i++) { + DOM_SID alias; + sid_copy(&alias, domain_sid); + sid_append_rid(&alias, alias_rids[i]); + printf("%s\n", sid_string_static(&alias)); + } + + return True; +} + static int net_groupmap_memberships(int argc, const char **argv) { - DOM_SID member; - DOM_SID *aliases; - int i, num; - NTSTATUS result; + TALLOC_CTX *mem_ctx; + DOM_SID *domain_sid, *builtin_sid, member; if ( (argc != 1) || !string_to_sid(&member, argv[0]) ) { @@ -706,17 +731,24 @@ static int net_groupmap_memberships(int argc, const char **argv) return -1; } - if (!pdb_enum_alias_memberships(&member, 1, &aliases, &num)) { - d_printf("Could not list memberships for sid %s: %s\n", - argv[0], nt_errstr(result)); + mem_ctx = talloc_init("net_groupmap_memberships"); + if (mem_ctx == NULL) { + d_printf("talloc_init failed\n"); return -1; } - for (i = 0; i < num; i++) { - printf("%s\n", sid_string_static(&(aliases[i]))); + domain_sid = get_global_sam_sid(); + builtin_sid = string_sid_talloc(mem_ctx, "S-1-5-32"); + if ((domain_sid == NULL) || (builtin_sid == NULL)) { + d_printf("Could not get domain sid\n"); + return -1; } - SAFE_FREE(aliases); + if (!print_alias_memberships(mem_ctx, domain_sid, &member) || + !print_alias_memberships(mem_ctx, builtin_sid, &member)) + return -1; + + talloc_destroy(mem_ctx); return 0; } diff --git a/source/utils/net_lookup.c b/source/utils/net_lookup.c index 7e5f12da454..9ddfe625081 100644 --- a/source/utils/net_lookup.c +++ b/source/utils/net_lookup.c @@ -193,7 +193,7 @@ static int net_lookup_kdc(int argc, const char **argv) } if (argc>0) { - realm.data = (krb5_pointer) argv[0]; + realm.data = CONST_DISCARD(krb5_pointer, argv[0]); realm.length = strlen(argv[0]); } else if (lp_realm() && *lp_realm()) { realm.data = (krb5_pointer) lp_realm(); @@ -209,7 +209,7 @@ static int net_lookup_kdc(int argc, const char **argv) realm.length = strlen(realm.data); } - rc = krb5_locate_kdc(ctx, &realm, &addrs, &num_kdcs, 0); + rc = krb5_locate_kdc(ctx, &realm, (struct sockaddr **) &addrs, &num_kdcs, 0); if (rc) { DEBUG(1, ("krb5_locate_kdc failed (%s)\n", error_message(rc))); return -1; diff --git a/source/utils/net_rap.c b/source/utils/net_rap.c index 6e8f0d088da..8205fe3fda9 100644 --- a/source/utils/net_rap.c +++ b/source/utils/net_rap.c @@ -589,9 +589,7 @@ static int net_rap_user_usage(int argc, const char **argv) return net_help_user(argc, argv); } -static void user_fn(const char *user_name, const char *comment, - const char * home_dir, const char * logon_script, - void *state) +static void user_fn(const char *user_name, void *state) { d_printf("%-21.21s\n", user_name); } @@ -696,7 +694,7 @@ int net_rap_user(int argc, const char **argv) cli_shutdown(cli); goto done; } - ret = cli_RNetUserEnum(cli, user_fn, NULL); + ret = cli_RNetUserEnum0(cli, user_fn, NULL); cli_shutdown(cli); goto done; } @@ -721,7 +719,7 @@ static void long_group_fn(const char *group_name, const char *comment, d_printf("%-21.21s %s\n", group_name, comment); } -static void group_fn(const char *group_name, const char *comment, void *state) +static void group_fn(const char *group_name, void *state) { d_printf("%-21.21s\n", group_name); } @@ -787,7 +785,7 @@ int net_rap_group(int argc, const char **argv) cli_shutdown(cli); return ret; } - ret = cli_RNetGroupEnum(cli, group_fn, NULL); + ret = cli_RNetGroupEnum0(cli, group_fn, NULL); cli_shutdown(cli); return ret; } @@ -912,6 +910,12 @@ static int rap_service_stop(int argc, const char **argv) return errmsg_not_implemented(); } +static void service_fn(const char *service_name, const char *dummy, + void *state) +{ + d_printf("%-21.21s\n", service_name); +} + int net_rap_service(int argc, const char **argv) { struct functable func[] = { @@ -931,7 +935,7 @@ int net_rap_service(int argc, const char **argv) d_printf("-----------------------------\n"); ret = cli_RNetServiceEnum(cli, long_group_fn, NULL); } - ret = cli_RNetServiceEnum(cli, group_fn, NULL); + ret = cli_RNetServiceEnum(cli, service_fn, NULL); cli_shutdown(cli); return ret; } diff --git a/source/utils/net_rpc.c b/source/utils/net_rpc.c index 27cc2a09186..6e884c24dfb 100644 --- a/source/utils/net_rpc.c +++ b/source/utils/net_rpc.c @@ -1909,7 +1909,6 @@ rpc_group_list_internals(const DOM_SID *domain_sid, const char *domain_name, NTSTATUS result = NT_STATUS_UNSUCCESSFUL; uint32 start_idx=0, max_entries=250, num_entries, i, loop_count = 0; struct acct_info *groups; - DOM_SID global_sid_Builtin; BOOL global = False; BOOL local = False; BOOL builtin = False; @@ -1931,8 +1930,6 @@ rpc_group_list_internals(const DOM_SID *domain_sid, const char *domain_name, builtin = True; } - string_to_sid(&global_sid_Builtin, "S-1-5-32"); - /* Get sam policy handle */ result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, @@ -2702,6 +2699,11 @@ rpc_share_migrate_shares_internals(const DOM_SID *domain_sid, const char *domain strequal(netname,"global")) continue; + if (opt_exclude && in_list(netname, opt_exclude, False)) { + printf("excluding [%s]\n", netname); + continue; + } + /* only work with file-shares */ if (!cli_send_tconX(cli, netname, "A:", "", 0)) { d_printf("skipping [%s]: not a file share.\n", netname); @@ -2971,7 +2973,7 @@ rpc_share_migrate_files_internals(const DOM_SID *domain_sid, const char *domain_ continue; } - if (opt_exclude && in_list(netname, (char *)opt_exclude, False)) { + if (opt_exclude && in_list(netname, opt_exclude, False)) { printf("excluding [%s]\n", netname); continue; } @@ -3273,7 +3275,6 @@ rpc_aliaslist_internals(const DOM_SID *domain_sid, const char *domain_name, { NTSTATUS result; POLICY_HND connect_pol; - DOM_SID global_sid_Builtin; result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, &connect_pol); @@ -3281,8 +3282,6 @@ rpc_aliaslist_internals(const DOM_SID *domain_sid, const char *domain_name, if (!NT_STATUS_IS_OK(result)) goto done; - string_to_sid(&global_sid_Builtin, "S-1-5-32"); - result = rpc_fetch_domain_aliases(cli, mem_ctx, &connect_pol, &global_sid_Builtin); @@ -3299,14 +3298,6 @@ rpc_aliaslist_internals(const DOM_SID *domain_sid, const char *domain_name, static void init_user_token(NT_USER_TOKEN *token, DOM_SID *user_sid) { - DOM_SID global_sid_World; - DOM_SID global_sid_Network; - DOM_SID global_sid_Authenticated_Users; - - string_to_sid(&global_sid_World, "S-1-1-0"); - string_to_sid(&global_sid_Network, "S-1-5-2"); - string_to_sid(&global_sid_Authenticated_Users, "S-1-5-11"); - token->num_sids = 4; token->user_sids = SMB_MALLOC_ARRAY(DOM_SID, 4); @@ -4472,6 +4463,7 @@ static NTSTATUS rpc_trustdom_del_internals(const DOM_SID *domain_sid, POLICY_HND connect_pol, domain_pol, user_pol; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; char *acct_name; + const char **names; DOM_SID trust_acct_sid; uint32 *user_rids, num_rids, *name_types; uint32 flags = 0x000003e8; /* Unknown */ @@ -4484,13 +4476,17 @@ static NTSTATUS rpc_trustdom_del_internals(const DOM_SID *domain_sid, /* * Make valid trusting domain account (ie. uppercased and with '$' appended) */ - - if (asprintf(&acct_name, "%s$", argv[0]) < 0) { + acct_name = talloc_asprintf(mem_ctx, "%s$", argv[0]); + + if (acct_name == NULL) return NT_STATUS_NO_MEMORY; - } strupper_m(acct_name); + names = TALLOC_ARRAY(mem_ctx, const char *, 1); + names[0] = acct_name; + + /* Get samr policy handle */ result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, &connect_pol); @@ -4507,8 +4503,8 @@ static NTSTATUS rpc_trustdom_del_internals(const DOM_SID *domain_sid, } result = cli_samr_lookup_names(cli, mem_ctx, &domain_pol, flags, 1, - &acct_name, &num_rids, &user_rids, - &name_types); + names, &num_rids, + &user_rids, &name_types); if (!NT_STATUS_IS_OK(result)) { goto done; @@ -4552,7 +4548,6 @@ static NTSTATUS rpc_trustdom_del_internals(const DOM_SID *domain_sid, } done: - SAFE_FREE(acct_name); return result; } @@ -4594,7 +4589,7 @@ static int rpc_trustdom_establish(int argc, const char **argv) TALLOC_CTX *mem_ctx; NTSTATUS nt_status; DOM_SID *domain_sid; - WKS_INFO_100 wks_info; + smb_ucs2_t *uni_domain_name; char* domain_name; char* domain_name_pol; @@ -4663,44 +4658,17 @@ static int rpc_trustdom_establish(int argc, const char **argv) for domain %s\n", domain_name)); } - /* - * Call WksQueryInfo to check remote server's capabilities - * note: It is now used only to get unicode domain name - */ - - if (!cli_nt_session_open(cli, PI_WKSSVC)) { - DEBUG(0, ("Couldn't not initialise wkssvc pipe\n")); - return -1; - } - - if (!(mem_ctx = talloc_init("establishing trust relationship to domain %s", - domain_name))) { + if (!(mem_ctx = talloc_init("establishing trust relationship to " + "domain %s", domain_name))) { DEBUG(0, ("talloc_init() failed\n")); cli_shutdown(cli); return -1; } - nt_status = cli_wks_query_info(cli, mem_ctx, &wks_info); - - if (NT_STATUS_IS_ERR(nt_status)) { - DEBUG(0, ("WksQueryInfo call failed.\n")); - return -1; - } - - if (cli->nt_pipe_fnum[cli->pipe_idx]) - cli_nt_session_close(cli); - - /* * Call LsaOpenPolicy and LsaQueryInfo */ - if (!(mem_ctx = talloc_init("rpc_trustdom_establish"))) { - DEBUG(0, ("talloc_init() failed\n")); - cli_shutdown(cli); - return -1; - } - if (!cli_nt_session_open(cli, PI_LSARPC)) { DEBUG(0, ("Could not initialise lsa pipe\n")); cli_shutdown(cli); @@ -4718,16 +4686,19 @@ static int rpc_trustdom_establish(int argc, const char **argv) /* Querying info level 5 */ nt_status = cli_lsa_query_info_policy(cli, mem_ctx, &connect_hnd, - 5 /* info level */, &domain_name_pol, - &domain_sid); + 5 /* info level */, + &domain_name_pol, &domain_sid); if (NT_STATUS_IS_ERR(nt_status)) { DEBUG(0, ("LSA Query Info failed. Returned error was %s\n", nt_errstr(nt_status))); return -1; } - - + if (push_ucs2_talloc(mem_ctx, &uni_domain_name, domain_name_pol) < 0) { + DEBUG(0, ("Could not convert domain name %s to unicode\n", + domain_name_pol)); + 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 */ @@ -4736,8 +4707,10 @@ static int rpc_trustdom_establish(int argc, const char **argv) * Store the password in secrets db */ - if (!secrets_store_trusted_domain_password(domain_name, wks_info.uni_lan_grp.buffer, - wks_info.uni_lan_grp.uni_str_len, opt_password, + if (!secrets_store_trusted_domain_password(domain_name, + uni_domain_name, + strlen_w(uni_domain_name)+1, + opt_password, *domain_sid)) { DEBUG(0, ("Storing password for trusted domain failed.\n")); return -1; @@ -4756,6 +4729,8 @@ static int rpc_trustdom_establish(int argc, const char **argv) if (cli->nt_pipe_fnum[cli->pipe_idx]) cli_nt_session_close(cli); + + cli_shutdown(cli); talloc_destroy(mem_ctx); @@ -5583,6 +5558,7 @@ int net_rpc(int argc, const char **argv) {"vampire", rpc_vampire}, {"getsid", net_rpc_getsid}, {"rights", net_rpc_rights}, + {"service", net_rpc_service}, {"help", net_rpc_help}, {NULL, NULL} }; diff --git a/source/utils/net_rpc_rights.c b/source/utils/net_rpc_rights.c index 32cb6a4650b..3a986ed2516 100644 --- a/source/utils/net_rpc_rights.c +++ b/source/utils/net_rpc_rights.c @@ -133,6 +133,36 @@ static NTSTATUS enum_privileges( TALLOC_CTX *ctx, struct cli_state *cli, /******************************************************************** ********************************************************************/ +static NTSTATUS check_privilege_for_user( TALLOC_CTX *ctx, struct cli_state *cli, + POLICY_HND *pol, DOM_SID *sid, const char *right) +{ + NTSTATUS result; + uint32 count; + char **rights; + int i; + + result = cli_lsa_enum_account_rights(cli, ctx, pol, sid, &count, &rights); + + if (!NT_STATUS_IS_OK(result)) { + return result; + } + + if (count == 0) { + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + + for (i = 0; i < count; i++) { + if (StrCaseCmp(rights[i], right) == 0) { + return NT_STATUS_OK; + } + } + + return NT_STATUS_OBJECT_NAME_NOT_FOUND; +} + +/******************************************************************** +********************************************************************/ + static NTSTATUS enum_privileges_for_user( TALLOC_CTX *ctx, struct cli_state *cli, POLICY_HND *pol, DOM_SID *sid ) { @@ -159,6 +189,52 @@ static NTSTATUS enum_privileges_for_user( TALLOC_CTX *ctx, struct cli_state *cli /******************************************************************** ********************************************************************/ +static NTSTATUS enum_accounts_for_privilege(TALLOC_CTX *ctx, struct cli_state *cli, + POLICY_HND *pol, const char *privilege) +{ + NTSTATUS result; + uint32 enum_context=0; + uint32 pref_max_length=0x1000; + DOM_SID *sids; + uint32 count=0; + int i; + fstring name; + + result = cli_lsa_enum_sids(cli, ctx, pol, &enum_context, + pref_max_length, &count, &sids); + + if (!NT_STATUS_IS_OK(result)) + return result; + + d_printf("%s:\n", privilege); + + for ( i=0; i 1 ) { - d_printf("Usage: net rpc rights list [name|SID]\n"); - result = NT_STATUS_OK; + result = enum_accounts_for_privilege(mem_ctx, cli, &pol, privname); + if (!NT_STATUS_IS_OK(result)) { + d_printf("Error enumerating accounts for privilege %s [%s].\n", + privname, nt_errstr(result)); + continue; + } } + goto done; } + /* special case to enumerate all privileged SIDs with associated rights */ + if (strequal( argv[0], "accounts")) { + int i = 1; + + if (argv[1] == NULL) { + result = enum_privileges_for_accounts(mem_ctx, cli, &pol); + goto done; + } + + while (argv[i] != NULL) { + result = name_to_sid(cli, mem_ctx, &sid, argv[i]); + if (!NT_STATUS_IS_OK(result)) { + goto done; + } + result = enum_privileges_for_user(mem_ctx, cli, &pol, &sid); + if (!NT_STATUS_IS_OK(result)) { + goto done; + } + i++; + } + goto done; + } + /* backward comaptibility: if no keyword provided, treat the key + as an account name */ + if (argc > 1) { + d_printf("Usage: net rpc rights list [[accounts|privileges] [name|SID]]\n"); + result = NT_STATUS_OK; + goto done; + } + + result = name_to_sid(cli, mem_ctx, &sid, argv[0]); + if (!NT_STATUS_IS_OK(result)) { + goto done; + } + result = enum_privileges_for_user( mem_ctx, cli, &pol, &sid ); done: cli_lsa_close(cli, mem_ctx, &pol); @@ -379,9 +511,9 @@ static int rpc_rights_revoke( int argc, const char **argv ) static int net_help_rights( int argc, const char **argv ) { - d_printf("net rpc rights list [accounts|username] View available or assigned privileges\n"); - d_printf("net rpc rights grant Assign privilege[s]\n"); - d_printf("net rpc rights revoke Revoke privilege[s]\n"); + d_printf("net rpc rights list [{accounts|privileges} [name|SID]] View available or assigned privileges\n"); + d_printf("net rpc rights grant Assign privilege[s]\n"); + d_printf("net rpc rights revoke Revoke privilege[s]\n"); d_printf("\nBoth 'grant' and 'revoke' require a SID and a list of privilege names.\n"); d_printf("For example\n"); diff --git a/source/utils/net_rpc_samsync.c b/source/utils/net_rpc_samsync.c index 49aef2a23cd..fa38004fe6f 100644 --- a/source/utils/net_rpc_samsync.c +++ b/source/utils/net_rpc_samsync.c @@ -24,8 +24,6 @@ #include "includes.h" #include "utils/net.h" -extern DOM_SID global_sid_Builtin; - static void display_group_mem_info(uint32 rid, SAM_GROUP_MEM_INFO *g) { int i; @@ -429,7 +427,7 @@ sam_account_from_delta(SAM_ACCOUNT *account, SAM_ACCOUNT_INFO *delta) if (delta->buf_logon_hrs.buffer) { pstring old, new; pdb_sethexhours(old, pdb_get_hours(account)); - pdb_sethexhours(new, (const char *)delta->buf_logon_hrs.buffer); + pdb_sethexhours(new, delta->buf_logon_hrs.buffer); if (!strequal(old, new)) pdb_set_hours(account, (const char *)delta->buf_logon_hrs.buffer, PDB_CHANGED); } diff --git a/source/utils/net_rpc_service.c b/source/utils/net_rpc_service.c new file mode 100644 index 00000000000..94644f8dcf4 --- /dev/null +++ b/source/utils/net_rpc_service.c @@ -0,0 +1,529 @@ +/* + Samba Unix/Linux SMB client library + Distributed SMB/CIFS Server Management Utility + Copyright (C) Gerald (Jerry) Carter 2005 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "includes.h" +#include "utils/net.h" + + +/******************************************************************** +********************************************************************/ + +static WERROR query_service_state( struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *hSCM, const char *service, uint32 *state ) +{ + POLICY_HND hService; + SERVICE_STATUS service_status; + WERROR result = WERR_GENERAL_FAILURE; + + /* now cycle until the status is actually 'watch_state' */ + + result = cli_svcctl_open_service( cli, mem_ctx, hSCM, &hService, + service, SC_RIGHT_SVC_QUERY_STATUS ); + + if ( !W_ERROR_IS_OK(result) ) { + d_printf("Failed to open service. [%s]\n", dos_errstr(result)); + return result; + } + + result = cli_svcctl_query_status( cli, mem_ctx, &hService, &service_status ); + if ( W_ERROR_IS_OK(result) ) { + *state = service_status.state; + } + + cli_svcctl_close_service( cli, mem_ctx, &hService ); + + return result; +} + +/******************************************************************** +********************************************************************/ + +static WERROR watch_service_state( struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *hSCM, const char *service, + uint32 watch_state, uint32 *final_state ) +{ + uint32 i; + uint32 state = 0; + WERROR result = WERR_GENERAL_FAILURE; + + + i = 0; + while ( (state != watch_state ) && i<30 ) { + /* get the status */ + + result = query_service_state( cli, mem_ctx, hSCM, service, &state ); + if ( !W_ERROR_IS_OK(result) ) { + break; + } + + d_printf("."); + i++; + usleep( 100 ); + } + d_printf("\n"); + + *final_state = state; + + return result; +} + +/******************************************************************** +********************************************************************/ + +static WERROR control_service( struct cli_state *cli, TALLOC_CTX *mem_ctx, + POLICY_HND *hSCM, const char *service, + uint32 control, uint32 watch_state ) +{ + POLICY_HND hService; + WERROR result = WERR_GENERAL_FAILURE; + SERVICE_STATUS service_status; + uint32 state = 0; + + /* Open the Service */ + + result = cli_svcctl_open_service( cli, mem_ctx, hSCM, &hService, + service, (SC_RIGHT_SVC_STOP|SC_RIGHT_SVC_PAUSE_CONTINUE) ); + + if ( !W_ERROR_IS_OK(result) ) { + d_printf("Failed to open service. [%s]\n", dos_errstr(result)); + goto done; + } + + /* get the status */ + + result = cli_svcctl_control_service( cli, mem_ctx, &hService, + control, &service_status ); + + if ( !W_ERROR_IS_OK(result) ) { + d_printf("Control service request failed. [%s]\n", dos_errstr(result)); + goto done; + } + + /* loop -- checking the state until we are where we want to be */ + + result = watch_service_state( cli, mem_ctx, hSCM, service, watch_state, &state ); + + d_printf("%s service is %s.\n", service, svc_status_string(state)); + +done: + cli_svcctl_close_service( cli, mem_ctx, &hService ); + + return result; +} + +/******************************************************************** +********************************************************************/ + +static NTSTATUS rpc_service_list_internal( const DOM_SID *domain_sid, const char *domain_name, + struct cli_state *cli, TALLOC_CTX *mem_ctx, + int argc, const char **argv ) +{ + POLICY_HND hSCM; + ENUM_SERVICES_STATUS *services; + WERROR result = WERR_GENERAL_FAILURE; + fstring servicename; + fstring displayname; + uint32 num_services = 0; + int i; + + if (argc != 0 ) { + d_printf("Usage: net rpc service list\n"); + return NT_STATUS_OK; + } + + result = cli_svcctl_open_scm( cli, mem_ctx, &hSCM, SC_RIGHT_MGR_ENUMERATE_SERVICE ); + if ( !W_ERROR_IS_OK(result) ) { + d_printf("Failed to open Service Control Manager. [%s]\n", dos_errstr(result)); + return werror_to_ntstatus(result); + } + + result = cli_svcctl_enumerate_services( cli, mem_ctx, &hSCM, SVCCTL_TYPE_WIN32, + SVCCTL_STATE_ALL, &num_services, &services ); + + if ( !W_ERROR_IS_OK(result) ) { + d_printf("Failed to enumerate services. [%s]\n", dos_errstr(result)); + goto done; + } + + if ( num_services == 0 ) + d_printf("No services returned\n"); + + for ( i=0; i\n"); + return NT_STATUS_OK; + } + + fstrcpy( servicename, argv[0] ); + + /* Open the Service Control Manager */ + + result = cli_svcctl_open_scm( cli, mem_ctx, &hSCM, SC_RIGHT_MGR_ENUMERATE_SERVICE ); + if ( !W_ERROR_IS_OK(result) ) { + d_printf("Failed to open Service Control Manager. [%s]\n", dos_errstr(result)); + return werror_to_ntstatus(result); + } + + /* Open the Service */ + + result = cli_svcctl_open_service( cli, mem_ctx, &hSCM, &hService, servicename, + (SC_RIGHT_SVC_QUERY_STATUS|SC_RIGHT_SVC_QUERY_CONFIG) ); + + if ( !W_ERROR_IS_OK(result) ) { + d_printf("Failed to open service. [%s]\n", dos_errstr(result)); + goto done; + } + + /* get the status */ + + result = cli_svcctl_query_status( cli, mem_ctx, &hService, &service_status ); + if ( !W_ERROR_IS_OK(result) ) { + d_printf("Query status request failed. [%s]\n", dos_errstr(result)); + goto done; + } + + d_printf("%s service is %s.\n", servicename, svc_status_string(service_status.state)); + + /* get the config */ + + result = cli_svcctl_query_config( cli, mem_ctx, &hService, &config ); + if ( !W_ERROR_IS_OK(result) ) { + d_printf("Query config request failed. [%s]\n", dos_errstr(result)); + goto done; + } + + /* print out the configuration information for the service */ + + d_printf("Configuration details:\n"); + d_printf("\tService Type = 0x%x\n", config.service_type); + d_printf("\tStart Type = 0x%x\n", config.start_type); + d_printf("\tError Control = 0x%x\n", config.error_control); + d_printf("\tTag ID = 0x%x\n", config.tag_id); + + if ( config.executablepath ) { + rpcstr_pull( ascii_string, config.executablepath->buffer, sizeof(ascii_string), -1, STR_TERMINATE ); + d_printf("\tExecutable Path = %s\n", ascii_string); + } + + if ( config.loadordergroup ) { + rpcstr_pull( ascii_string, config.loadordergroup->buffer, sizeof(ascii_string), -1, STR_TERMINATE ); + d_printf("\tLoad Order Group = %s\n", ascii_string); + } + + if ( config.dependencies ) { + rpcstr_pull( ascii_string, config.dependencies->buffer, sizeof(ascii_string), -1, STR_TERMINATE ); + d_printf("\tDependencies = %s\n", ascii_string); + } + + if ( config.startname ) { + rpcstr_pull( ascii_string, config.startname->buffer, sizeof(ascii_string), -1, STR_TERMINATE ); + d_printf("\tStart Name = %s\n", ascii_string); + } + + if ( config.displayname ) { + rpcstr_pull( ascii_string, config.displayname->buffer, sizeof(ascii_string), -1, STR_TERMINATE ); + d_printf("\tDisplay Name = %s\n", ascii_string); + } + +done: + cli_svcctl_close_service( cli, mem_ctx, &hService ); + cli_svcctl_close_service( cli, mem_ctx, &hSCM ); + + return werror_to_ntstatus(result); +} + + +/******************************************************************** +********************************************************************/ + +static NTSTATUS rpc_service_stop_internal( const DOM_SID *domain_sid, const char *domain_name, + struct cli_state *cli, TALLOC_CTX *mem_ctx, + int argc, const char **argv ) +{ + POLICY_HND hSCM; + WERROR result = WERR_GENERAL_FAILURE; + fstring servicename; + + if (argc != 1 ) { + d_printf("Usage: net rpc service status \n"); + return NT_STATUS_OK; + } + + fstrcpy( servicename, argv[0] ); + + /* Open the Service Control Manager */ + + result = cli_svcctl_open_scm( cli, mem_ctx, &hSCM, SC_RIGHT_MGR_ENUMERATE_SERVICE ); + if ( !W_ERROR_IS_OK(result) ) { + d_printf("Failed to open Service Control Manager. [%s]\n", dos_errstr(result)); + return werror_to_ntstatus(result); + } + + result = control_service( cli, mem_ctx, &hSCM, servicename, + SVCCTL_CONTROL_STOP, SVCCTL_STOPPED ); + + cli_svcctl_close_service( cli, mem_ctx, &hSCM ); + + return werror_to_ntstatus(result); +} + +/******************************************************************** +********************************************************************/ + +static NTSTATUS rpc_service_pause_internal( const DOM_SID *domain_sid, const char *domain_name, + struct cli_state *cli, TALLOC_CTX *mem_ctx, + int argc, const char **argv ) +{ + POLICY_HND hSCM; + WERROR result = WERR_GENERAL_FAILURE; + fstring servicename; + + if (argc != 1 ) { + d_printf("Usage: net rpc service status \n"); + return NT_STATUS_OK; + } + + fstrcpy( servicename, argv[0] ); + + /* Open the Service Control Manager */ + + result = cli_svcctl_open_scm( cli, mem_ctx, &hSCM, SC_RIGHT_MGR_ENUMERATE_SERVICE ); + if ( !W_ERROR_IS_OK(result) ) { + d_printf("Failed to open Service Control Manager. [%s]\n", dos_errstr(result)); + return werror_to_ntstatus(result); + } + + result = control_service( cli, mem_ctx, &hSCM, servicename, + SVCCTL_CONTROL_PAUSE, SVCCTL_PAUSED ); + + cli_svcctl_close_service( cli, mem_ctx, &hSCM ); + + return werror_to_ntstatus(result); +} + +/******************************************************************** +********************************************************************/ + +static NTSTATUS rpc_service_resume_internal( const DOM_SID *domain_sid, const char *domain_name, + struct cli_state *cli, TALLOC_CTX *mem_ctx, + int argc, const char **argv ) +{ + POLICY_HND hSCM; + WERROR result = WERR_GENERAL_FAILURE; + fstring servicename; + + if (argc != 1 ) { + d_printf("Usage: net rpc service status \n"); + return NT_STATUS_OK; + } + + fstrcpy( servicename, argv[0] ); + + /* Open the Service Control Manager */ + + result = cli_svcctl_open_scm( cli, mem_ctx, &hSCM, SC_RIGHT_MGR_ENUMERATE_SERVICE ); + if ( !W_ERROR_IS_OK(result) ) { + d_printf("Failed to open Service Control Manager. [%s]\n", dos_errstr(result)); + return werror_to_ntstatus(result); + } + + result = control_service( cli, mem_ctx, &hSCM, servicename, + SVCCTL_CONTROL_CONTINUE, SVCCTL_RUNNING ); + + cli_svcctl_close_service( cli, mem_ctx, &hSCM ); + + return werror_to_ntstatus(result); +} + +/******************************************************************** +********************************************************************/ + +static NTSTATUS rpc_service_start_internal( const DOM_SID *domain_sid, const char *domain_name, + struct cli_state *cli, TALLOC_CTX *mem_ctx, + int argc, const char **argv ) +{ + POLICY_HND hSCM, hService; + WERROR result = WERR_GENERAL_FAILURE; + fstring servicename; + uint32 state = 0; + + if (argc != 1 ) { + d_printf("Usage: net rpc service status \n"); + return NT_STATUS_OK; + } + + fstrcpy( servicename, argv[0] ); + + /* Open the Service Control Manager */ + + result = cli_svcctl_open_scm( cli, mem_ctx, &hSCM, SC_RIGHT_MGR_ENUMERATE_SERVICE ); + if ( !W_ERROR_IS_OK(result) ) { + d_printf("Failed to open Service Control Manager. [%s]\n", dos_errstr(result)); + return werror_to_ntstatus(result); + } + + /* Open the Service */ + + result = cli_svcctl_open_service( cli, mem_ctx, &hSCM, &hService, + servicename, SC_RIGHT_SVC_START ); + + if ( !W_ERROR_IS_OK(result) ) { + d_printf("Failed to open service. [%s]\n", dos_errstr(result)); + goto done; + } + + /* get the status */ + + result = cli_svcctl_start_service( cli, mem_ctx, &hService, NULL, 0 ); + if ( !W_ERROR_IS_OK(result) ) { + d_printf("Query status request failed. [%s]\n", dos_errstr(result)); + goto done; + } + + result = watch_service_state( cli, mem_ctx, &hSCM, servicename, SVCCTL_RUNNING, &state ); + + if ( W_ERROR_IS_OK(result) && (state == SVCCTL_RUNNING) ) + d_printf("Successfully started service: %s\n", servicename ); + else + d_printf("Failed to start service: %s [%s]\n", servicename, dos_errstr(result) ); + +done: + cli_svcctl_close_service( cli, mem_ctx, &hService ); + cli_svcctl_close_service( cli, mem_ctx, &hSCM ); + + return werror_to_ntstatus(result); +} + +/******************************************************************** +********************************************************************/ + +static int rpc_service_list( int argc, const char **argv ) +{ + return run_rpc_command( NULL, PI_SVCCTL, 0, + rpc_service_list_internal, argc, argv ); +} + +/******************************************************************** +********************************************************************/ + +static int rpc_service_start( int argc, const char **argv ) +{ + return run_rpc_command( NULL, PI_SVCCTL, 0, + rpc_service_start_internal, argc, argv ); +} + +/******************************************************************** +********************************************************************/ + +static int rpc_service_stop( int argc, const char **argv ) +{ + return run_rpc_command( NULL, PI_SVCCTL, 0, + rpc_service_stop_internal, argc, argv ); +} + +/******************************************************************** +********************************************************************/ + +static int rpc_service_resume( int argc, const char **argv ) +{ + return run_rpc_command( NULL, PI_SVCCTL, 0, + rpc_service_resume_internal, argc, argv ); +} + +/******************************************************************** +********************************************************************/ + +static int rpc_service_pause( int argc, const char **argv ) +{ + return run_rpc_command( NULL, PI_SVCCTL, 0, + rpc_service_pause_internal, argc, argv ); +} + +/******************************************************************** +********************************************************************/ + +static int rpc_service_status( int argc, const char **argv ) +{ + return run_rpc_command( NULL, PI_SVCCTL, 0, + rpc_service_status_internal, argc, argv ); +} + +/******************************************************************** +********************************************************************/ + +static int net_help_service( int argc, const char **argv ) +{ + d_printf("net rpc service list View configured Win32 services\n"); + d_printf("net rpc service start Start a service\n"); + d_printf("net rpc service stop Stop a service\n"); + d_printf("net rpc service pause Pause a service\n"); + d_printf("net rpc service resume Resume a paused a service\n"); + d_printf("net rpc service status View the current status of a service\n"); + + return -1; +} + +/******************************************************************** +********************************************************************/ + +int net_rpc_service(int argc, const char **argv) +{ + struct functable func[] = { + {"list", rpc_service_list}, + {"start", rpc_service_start}, + {"stop", rpc_service_stop}, + {"pause", rpc_service_pause}, + {"resume", rpc_service_resume}, + {"status", rpc_service_status}, + {NULL, NULL} + }; + + if ( argc ) + return net_run_function( argc, argv, func, net_help_service ); + + return net_help_service( argc, argv ); +} + + diff --git a/source/utils/pdbedit.c b/source/utils/pdbedit.c index c5ba59487cc..88ec6b1f4fa 100644 --- a/source/utils/pdbedit.c +++ b/source/utils/pdbedit.c @@ -175,7 +175,7 @@ static int print_sam_info (SAM_ACCOUNT *sam_pwent, BOOL verbosity, BOOL smbpwdst pdb_get_bad_password_count(sam_pwent)); hours = pdb_get_hours(sam_pwent); - pdb_sethexhours(temp, (const char *)hours); + pdb_sethexhours(temp, hours); printf ("Logon hours : %s\n", temp); } else if (smbpwdstyle) { @@ -911,7 +911,7 @@ int main (int argc, char **argv) if (!(checkparms & ~(BIT_MODIFY + BIT_USER))) { time_t pwd_can_change = -1; time_t pwd_must_change = -1; - char *errstr; + const char *errstr; if (pwd_can_change_time) { errstr = "can"; diff --git a/source/utils/smbcontrol.c b/source/utils/smbcontrol.c index 2eb661c8b68..5a7b6548c29 100644 --- a/source/utils/smbcontrol.c +++ b/source/utils/smbcontrol.c @@ -428,7 +428,8 @@ static BOOL do_printnotify(const pid_t pid, const int argc, const char **argv) return False; } - notify_printer_byname(argv[2], attribute, argv[4]); + notify_printer_byname(argv[2], attribute, + CONST_DISCARD(char *, argv[4])); goto send; } diff --git a/source/utils/smbpasswd.c b/source/utils/smbpasswd.c index 836a161021d..708d44df9f0 100644 --- a/source/utils/smbpasswd.c +++ b/source/utils/smbpasswd.c @@ -290,7 +290,7 @@ static BOOL password_change(const char *remote_mach, char *username, err_str, sizeof(err_str), msg_str, sizeof(msg_str)); if(*msg_str) - printf(msg_str); + printf("%s", msg_str); if(*err_str) fprintf(stderr, "%s", err_str); diff --git a/source/web/diagnose.c b/source/web/diagnose.c index 85e710cee8f..f4b022cf587 100644 --- a/source/web/diagnose.c +++ b/source/web/diagnose.c @@ -41,7 +41,6 @@ BOOL winbindd_running(void) response */ BOOL nmbd_running(void) { - extern struct in_addr loopback_ip; int fd, count, flags; struct in_addr *ip_list; @@ -66,7 +65,6 @@ BOOL nmbd_running(void) BOOL smbd_running(void) { static struct cli_state cli; - extern struct in_addr loopback_ip; if (!cli_initialise(&cli)) return False; diff --git a/source/web/neg_lang.c b/source/web/neg_lang.c index ca671822d87..cc2924afde6 100644 --- a/source/web/neg_lang.c +++ b/source/web/neg_lang.c @@ -54,8 +54,8 @@ struct pri_list { }; static int qsort_cmp_list(const void *x, const void *y) { - struct pri_list *a = (struct pri_list *)x; - struct pri_list *b = (struct pri_list *)y; + struct pri_list *a = CONST_DISCARD(struct pri_list *, x); + struct pri_list *b = CONST_DISCARD(struct pri_list *, y); if (a->pri > b->pri) return -1; if (a->pri == b->pri) return 0; return 1; -- cgit v1.2.1